Modify latency detection to use the second word of a sync packet to decide whether to add an extra delay or not. Use all sync packets, not just one with the exception flag. Use 1024 buffers -- a bit profligate, but hey.
This commit is contained in:
@@ -223,7 +223,8 @@ int dacp_send_command(const char *command, char **body, ssize_t *bodysize) {
|
||||
int ndata = recv(sockfd, buffer, sizeof(buffer), 0);
|
||||
// debug(1,"Received %d bytes: \"%s\".",ndata,buffer);
|
||||
if (ndata <= 0) {
|
||||
debug(2, "dacp_send_command -- error receiving response for command \"%s\".",command);
|
||||
debug(2, "dacp_send_command -- error receiving response for command \"%s\".",
|
||||
command);
|
||||
free(response.body);
|
||||
response.body = NULL;
|
||||
response.malloced_size = 0;
|
||||
|
||||
@@ -833,7 +833,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
|
||||
// supposed to start playing this
|
||||
have_sent_prefiller_silence = 0;
|
||||
|
||||
// debug(1, "First packet timestamp is %" PRId64 ".", conn->first_packet_timestamp);
|
||||
// debug(1, "First packet timestamp is %" PRId64 ".", conn->first_packet_timestamp);
|
||||
|
||||
// say we have started playing here
|
||||
#ifdef CONFIG_METADATA
|
||||
|
||||
@@ -141,7 +141,7 @@ typedef struct {
|
||||
int control_socket; // our local [server] control socket
|
||||
int timing_socket; // local timing socket
|
||||
|
||||
int64_t latency_delayed_timestamp; // this is for debugging only...
|
||||
int64_t latency_delayed_timestamp; // this is for debugging only...
|
||||
int64_t reference_timestamp;
|
||||
uint64_t reference_timestamp_time;
|
||||
uint64_t remote_reference_timestamp_time;
|
||||
|
||||
@@ -56,7 +56,6 @@ void rtp_initialise(rtsp_conn_info *conn) {
|
||||
int rc = pthread_mutex_init(&conn->reference_time_mutex, NULL);
|
||||
if (rc)
|
||||
debug(1, "Error initialising reference_time_mutex.");
|
||||
|
||||
}
|
||||
|
||||
void rtp_terminate(rtsp_conn_info *conn) {
|
||||
@@ -209,39 +208,45 @@ void *rtp_control_receiver(void *arg) {
|
||||
break;
|
||||
|
||||
ssize_t plen = nread;
|
||||
if (packet[1] == 0xd4) { // sync data
|
||||
/*
|
||||
// the following stanza is for debugging only -- normally commented out.
|
||||
{
|
||||
char obf[4096];
|
||||
char *obfp = obf;
|
||||
int obfc;
|
||||
for (obfc = 0; obfc < plen; obfc++) {
|
||||
sprintf(obfp, "%02X", packet[obfc]);
|
||||
obfp += 2;
|
||||
};
|
||||
*obfp = 0;
|
||||
|
||||
|
||||
// get raw timestamp information
|
||||
// I think that a good way to understand these timestamps is that
|
||||
// (1) the rtlt below is the timestamp of the frame that should be playing at the client-time specified in the packet if there was no delay
|
||||
// and (2) that the rt below is the timestamp of the frame that should be playing at the client-time specified in the packet on this device taking account of the delay
|
||||
// Thus, (3) the latency can be calculated by subtracting the second from the first.
|
||||
// There must be more to it -- there something missing.
|
||||
|
||||
// In addition, it seems that if the value of the short represented by the second pair of bytes in the packe is 7
|
||||
// then an extra time lag is expected to be added, presumably by the AirPort Express. Best guess is that this delay is 11,025 frames.
|
||||
|
||||
uint32_t rtlt = nctohl(&packet[4]); // raw timestamp less latency
|
||||
uint32_t rt = nctohl(&packet[16]); // raw timestamp
|
||||
|
||||
uint32_t fl = nctohs(&packet[2]); //
|
||||
|
||||
// debug(1,"Sync Packet of %d bytes received: \"%s\", flags: %d, timestamps %u and %u, giving a latency of %d frames.",plen,obf,fl,rt,rtlt,rt-rtlt);
|
||||
// debug(1,"Monotonic timestamps are: %" PRId64 " and %" PRId64 " respectively.",monotonic_timestamp(rt, conn),monotonic_timestamp(rtlt, conn));
|
||||
}
|
||||
*/
|
||||
if (packet[1] == 0xd4) { // sync data
|
||||
/*
|
||||
// the following stanza is for debugging only -- normally commented out.
|
||||
{
|
||||
char obf[4096];
|
||||
char *obfp = obf;
|
||||
int obfc;
|
||||
for (obfc = 0; obfc < plen; obfc++) {
|
||||
sprintf(obfp, "%02X", packet[obfc]);
|
||||
obfp += 2;
|
||||
};
|
||||
*obfp = 0;
|
||||
|
||||
|
||||
// get raw timestamp information
|
||||
// I think that a good way to understand these timestamps is that
|
||||
// (1) the rtlt below is the timestamp of the frame that should be playing at the
|
||||
client-time specified in the packet if there was no delay
|
||||
// and (2) that the rt below is the timestamp of the frame that should be playing at
|
||||
the client-time specified in the packet on this device taking account of the delay
|
||||
// Thus, (3) the latency can be calculated by subtracting the second from the first.
|
||||
// There must be more to it -- there something missing.
|
||||
|
||||
// In addition, it seems that if the value of the short represented by the second pair
|
||||
of bytes in the packe is 7
|
||||
// then an extra time lag is expected to be added, presumably by the AirPort Express.
|
||||
Best guess is that this delay is 11,025 frames.
|
||||
|
||||
uint32_t rtlt = nctohl(&packet[4]); // raw timestamp less latency
|
||||
uint32_t rt = nctohl(&packet[16]); // raw timestamp
|
||||
|
||||
uint32_t fl = nctohs(&packet[2]); //
|
||||
|
||||
// debug(1,"Sync Packet of %d bytes received: \"%s\", flags: %d, timestamps %u and %u,
|
||||
giving a latency of %d frames.",plen,obf,fl,rt,rtlt,rt-rtlt);
|
||||
// debug(1,"Monotonic timestamps are: %" PRId64 " and %" PRId64 "
|
||||
respectively.",monotonic_timestamp(rt, conn),monotonic_timestamp(rtlt, conn));
|
||||
}
|
||||
*/
|
||||
if (conn->local_to_remote_time_difference) { // need a time packet to be interchanged first...
|
||||
|
||||
remote_time_of_sync = (uint64_t)nctohl(&packet[8]) << 32;
|
||||
@@ -279,15 +284,14 @@ void *rtp_control_receiver(void *arg) {
|
||||
la = conn->maximum_latency;
|
||||
if ((conn->minimum_latency) && (conn->minimum_latency > la))
|
||||
la = conn->minimum_latency;
|
||||
|
||||
|
||||
const int max_frames = ((3 * BUFFER_FRAMES * 352)/4)-11025;
|
||||
|
||||
const int max_frames = ((3 * BUFFER_FRAMES * 352) / 4) - 11025;
|
||||
|
||||
if ((la < 0) || (la > max_frames)) {
|
||||
warn("An out-of-range latency request of %" PRId64
|
||||
" frames was ignored. Must be %d frames or less (44,100 frames per second). Latency remains at %" PRId64
|
||||
" frames.",
|
||||
la,max_frames,conn->latency);
|
||||
" frames was ignored. Must be %d frames or less (44,100 frames per second). "
|
||||
"Latency remains at %" PRId64 " frames.",
|
||||
la, max_frames, conn->latency);
|
||||
} else {
|
||||
|
||||
if (la != conn->latency) {
|
||||
@@ -302,31 +306,33 @@ void *rtp_control_receiver(void *arg) {
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&conn->reference_time_mutex);
|
||||
|
||||
//this is for debugging
|
||||
//uint64_t old_remote_reference_time = conn->remote_reference_timestamp_time;
|
||||
//int64_t old_reference_timestamp = conn->reference_timestamp;
|
||||
//int64_t old_latency_delayed_timestamp = conn->latency_delayed_timestamp;
|
||||
|
||||
// this is for debugging
|
||||
// uint64_t old_remote_reference_time = conn->remote_reference_timestamp_time;
|
||||
// int64_t old_reference_timestamp = conn->reference_timestamp;
|
||||
// int64_t old_latency_delayed_timestamp = conn->latency_delayed_timestamp;
|
||||
conn->remote_reference_timestamp_time = remote_time_of_sync;
|
||||
conn->reference_timestamp_time =
|
||||
remote_time_of_sync - conn->local_to_remote_time_difference;
|
||||
conn->reference_timestamp = sync_rtp_timestamp;
|
||||
conn->latency_delayed_timestamp = rtp_timestamp_less_latency;
|
||||
pthread_mutex_unlock(&conn->reference_time_mutex);
|
||||
|
||||
|
||||
// this is for debugging
|
||||
/*
|
||||
uint64_t time_difference = remote_time_of_sync - old_remote_reference_time;
|
||||
int64_t reference_frame_difference = sync_rtp_timestamp - old_reference_timestamp;
|
||||
int64_t delayed_frame_difference = rtp_timestamp_less_latency - old_latency_delayed_timestamp;
|
||||
|
||||
int64_t delayed_frame_difference = rtp_timestamp_less_latency -
|
||||
old_latency_delayed_timestamp;
|
||||
|
||||
if (old_remote_reference_time)
|
||||
debug(1,"Time difference: %" PRIu64 " reference and delayed frame differences: %" PRId64 " and %" PRId64 ", giving rates of %f and %f respectively.",
|
||||
debug(1,"Time difference: %" PRIu64 " reference and delayed frame differences: %" PRId64 "
|
||||
and %" PRId64 ", giving rates of %f and %f respectively.",
|
||||
(time_difference*1000000)>>32,reference_frame_difference,delayed_frame_difference,(1.0*(reference_frame_difference*10000000))/((time_difference*10000000)>>32),(1.0*(delayed_frame_difference*10000000))/((time_difference*10000000)>>32));
|
||||
else
|
||||
debug(1,"First sync received");
|
||||
*/
|
||||
|
||||
|
||||
// debug(1,"New Reference timestamp and timestamp time...");
|
||||
// get estimated remote time now
|
||||
// remote_time_now = local_time_now + local_to_remote_time_difference;
|
||||
|
||||
Reference in New Issue
Block a user