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:
Mike Brady
2018-04-02 16:44:16 +01:00
parent d34e707e0c
commit d3e2cb5d92
4 changed files with 60 additions and 53 deletions
+2 -1
View File
@@ -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;
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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 -50
View File
@@ -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;