v1.63: fix audio sync with client video in Audio-only mode

This commit is contained in:
F. Duncanh
2023-02-06 14:15:52 -05:00
parent f6a18a5a37
commit c8025be711
11 changed files with 98 additions and 98 deletions

View File

@@ -60,6 +60,7 @@ struct raop_s {
uint8_t overscanned;
uint8_t clientFPSdata;
int audio_delay_micros;
int max_ntp_timeouts;
};
@@ -461,6 +462,7 @@ raop_init(int max_clients, raop_callbacks_t *callbacks) {
raop->clientFPSdata = 0;
raop->max_ntp_timeouts = 0;
raop->audio_delay_micros = 250000;
return raop;
}
@@ -519,6 +521,11 @@ int raop_set_plist(raop_t *raop, const char *plist_item, const int value) {
} else if (strcmp(plist_item, "max_ntp_timeouts") == 0) {
raop->max_ntp_timeouts = (value > 0 ? value : 0);
if (raop->max_ntp_timeouts != value) retval = 1;
} else if (strcmp(plist_item, "audio_delay_micros") == 0) {
if (value >= 0 && value <= 10 * SECOND_IN_USECS) {
raop->audio_delay_micros = value;
}
if (raop->audio_delay_micros != value) retval = 1;
} else {
retval = -1;
}

View File

@@ -20,6 +20,8 @@
#include <ctype.h>
#include <stdlib.h>
#include <plist/plist.h>
#define AUDIO_SAMPLE_RATE 44100 /* all supported AirPlay audio format use this sample rate */
#define SECOND_IN_USECS 1000000
typedef void (*raop_handler_t)(raop_conn_t *, http_request_t *,
http_response_t *, char **, int *);
@@ -500,7 +502,9 @@ raop_handler_setup(raop_conn_t *conn,
unsigned short cport = conn->raop->control_lport, dport = conn->raop->data_lport;
unsigned short remote_cport = 0;
unsigned char ct;
unsigned int sr = 44100; /* all AirPlay audio formats supported so far have sample rate 44.1kHz */
unsigned int sr = AUDIO_SAMPLE_RATE; /* all AirPlay audio formats supported so far have sample rate 44.1kHz */
unsigned int ad = (unsigned int) (((uint64_t) conn->raop->audio_delay_micros) * AUDIO_SAMPLE_RATE / SECOND_IN_USECS);
uint64_t uint_val = 0;
plist_t req_stream_control_port_node = plist_dict_get_item(req_stream_node, "controlPort");
plist_get_uint_val(req_stream_control_port_node, &uint_val);
@@ -545,7 +549,7 @@ raop_handler_setup(raop_conn_t *conn,
}
if (conn->raop_rtp) {
raop_rtp_start_audio(conn->raop_rtp, use_udp, &remote_cport, &cport, &dport, &ct, &sr);
raop_rtp_start_audio(conn->raop_rtp, use_udp, &remote_cport, &cport, &dport, &ct, &sr, &ad);
logger_log(conn->raop->logger, LOGGER_DEBUG, "RAOP initialized success");
} else {
logger_log(conn->raop->logger, LOGGER_ERR, "RAOP not initialized at SETUP, playing will fail!");
@@ -686,7 +690,10 @@ raop_handler_record(raop_conn_t *conn,
http_request_t *request, http_response_t *response,
char **response_data, int *response_datalen)
{
char audio_latency[12];
unsigned int ad = (unsigned int) (((uint64_t) conn->raop->audio_delay_micros) * AUDIO_SAMPLE_RATE / SECOND_IN_USECS);
sprintf(audio_latency, "%u", ad);
logger_log(conn->raop->logger, LOGGER_DEBUG, "raop_handler_record");
http_response_add_header(response, "Audio-Latency", "11025");
http_response_add_header(response, "Audio-Latency", audio_latency);
http_response_add_header(response, "Audio-Jack-Status", "connected; type=analog");
}

View File

@@ -54,6 +54,7 @@ struct raop_rtp_s {
// Time and sync
raop_ntp_t *ntp;
double rtp_clock_rate;
unsigned int audio_delay_rtp;
int64_t rtp_sync_offset;
raop_rtp_sync_data_t sync_data[RAOP_RTP_SYNC_DATA_COUNT];
int sync_data_index;
@@ -551,14 +552,12 @@ raop_rtp_thread_udp(void *arg)
uint64_t sync_ntp_raw = byteutils_get_long_be(packet, 8);
uint64_t sync_ntp_remote = raop_ntp_timestamp_to_nano_seconds(sync_ntp_raw, true);
uint64_t sync_ntp_local = raop_ntp_convert_remote_time(raop_rtp->ntp, sync_ntp_remote);
int64_t shift;
int64_t shift = 0;
switch (raop_rtp->ct) {
case 0x08: /*AAC-ELD */
shift = -11025; /* 44100/4 */
case 0x02: /* ALAC audio-only mode */
break;
case 0x02:
default:
shift = 0; /* not needed for ALAC (audio only) */
shift -= (int64_t) raop_rtp->audio_delay_rtp; /* remove delay in Mirror mode */
break;
}
char *str = utils_data_to_string(packet, packetlen, 20);
@@ -710,8 +709,8 @@ raop_rtp_thread_udp(void *arg)
// Start rtp service, three udp ports
void
raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short *control_rport,
unsigned short *control_lport, unsigned short *data_lport, unsigned char *ct, unsigned int *sr)
raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short *control_rport, unsigned short *control_lport,
unsigned short *data_lport, unsigned char *ct, unsigned int *sr, unsigned int *ad)
{
logger_log(raop_rtp->logger, LOGGER_INFO, "raop_rtp starting audio");
int use_ipv6 = 0;
@@ -726,6 +725,7 @@ raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short *control_
raop_rtp->ct = *ct;
raop_rtp->rtp_clock_rate = SECOND_IN_NSECS / *sr;
raop_rtp->audio_delay_rtp = *ad;
/* Initialize ports and sockets */
raop_rtp->control_lport = *control_lport;

View File

@@ -29,8 +29,8 @@ typedef struct raop_rtp_s raop_rtp_t;
raop_rtp_t *raop_rtp_init(logger_t *logger, raop_callbacks_t *callbacks, raop_ntp_t *ntp, const unsigned char *remote,
int remotelen, const unsigned char *aeskey, const unsigned char *aesiv);
void raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short *control_rport,
unsigned short *control_lport, unsigned short *data_lport, unsigned char *ct, unsigned int *sr);
void raop_rtp_start_audio(raop_rtp_t *raop_rtp, int use_udp, unsigned short *control_rport, unsigned short *control_lport,
unsigned short *data_lport, unsigned char *ct, unsigned int *sr, unsigned int *ad);
void raop_rtp_set_volume(raop_rtp_t *raop_rtp, float volume);
void raop_rtp_set_metadata(raop_rtp_t *raop_rtp, const char *data, int datalen);