From: Mike Brady Date: Mon, 2 Apr 2018 15:44:16 +0000 (+0100) Subject: Modify latency detection to use the second word of a sync packet to decide whether... X-Git-Tag: 3.2RC1~7^2~15 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d3e2cb5d92a339422a6c2ae42a4557fa9c130fba;p=thirdparty%2Fshairport-sync.git 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. --- diff --git a/dacp.c b/dacp.c index 799f719c..82c29329 100644 --- a/dacp.c +++ b/dacp.c @@ -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; diff --git a/player.c b/player.c index 2d2f0d0e..7560bfb4 100644 --- a/player.c +++ b/player.c @@ -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 diff --git a/player.h b/player.h index f04eee1a..4ceabf9c 100644 --- a/player.h +++ b/player.h @@ -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; diff --git a/rtp.c b/rtp.c index 7a9f8234..25d2198a 100644 --- a/rtp.c +++ b/rtp.c @@ -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;