mirror of
https://github.com/morgan9e/UxPlay
synced 2026-04-14 00:04:13 +09:00
v1.63: fix audio sync with client video in Audio-only mode
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user