From 28afb1fbb8964f7dc6e85a1419bce32b4766ada3 Mon Sep 17 00:00:00 2001 From: "F. Duncanh" Date: Fri, 10 Feb 2023 14:05:08 -0500 Subject: [PATCH] export both local and remote ntp times with audio and video frames --- lib/raop_rtp.c | 28 ++++++++++++++-------------- lib/raop_rtp_mirror.c | 15 ++++++++------- lib/stream.h | 7 +++++-- uxplay.cpp | 4 ++-- 4 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lib/raop_rtp.c b/lib/raop_rtp.c index 6ee0e1d..e4f9b4a 100644 --- a/lib/raop_rtp.c +++ b/lib/raop_rtp.c @@ -542,7 +542,6 @@ raop_rtp_thread_udp(void *arg) uint64_t ntp_time = 0; if (have_synced) { ntp_time = (uint64_t) (raop_rtp->rtp_sync_offset + (int64_t) (raop_rtp->rtp_clock_rate * rtp_time)); - ntp_time = raop_ntp_convert_remote_time(raop_rtp->ntp, ntp_time); } logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp resent audio packet: seqnum=%u", seqnum); int result = raop_buffer_enqueue(raop_rtp->buffer, resent_packet, resent_packetlen, &ntp_time, &rtp_time, 1); @@ -653,7 +652,6 @@ raop_rtp_thread_udp(void *arg) seqnum1 = seqnum; } else { ntp_time = (uint64_t) (raop_rtp->rtp_sync_offset + (int64_t) (raop_rtp->rtp_clock_rate * rtp_time)); - ntp_time = raop_ntp_convert_remote_time(raop_rtp->ntp, ntp_time); } int result = raop_buffer_enqueue(raop_rtp->buffer, packet, packetlen, &ntp_time, &rtp_time, 1); assert(result >= 0); @@ -669,23 +667,25 @@ raop_rtp_thread_udp(void *arg) audio_data.seqnum = seqnum; audio_data.data_len = payload_size; audio_data.data = payload; - if (ntp_timestamp) { - audio_data.ntp_time = ntp_timestamp; - } else { - if (have_synced) { - uint64_t ntp_remote = (uint64_t) (raop_rtp->rtp_sync_offset + (int64_t) (raop_rtp->rtp_clock_rate * rtp64_timestamp)); - audio_data.ntp_time = raop_ntp_convert_remote_time(raop_rtp->ntp, ntp_remote); - } else { - audio_data.ntp_time = raop_rtp->ntp_start_time + delay + - (uint64_t) (sync_adjustment + raop_rtp->rtp_clock_rate * (rtp64_timestamp - raop_rtp->rtp_start_time)); - } + if (have_synced) { + if (ntp_timestamp == 0) { + ntp_timestamp = (uint64_t) (raop_rtp->rtp_sync_offset + (int64_t) (raop_rtp->rtp_clock_rate * rtp64_timestamp)); + } + audio_data.ntp_time_remote = ntp_timestamp; + audio_data.ntp_time_local = raop_ntp_convert_remote_time(raop_rtp->ntp, audio_data.ntp_time_remote); + audio_data.sync_status = 1; + } else { + double elapsed_time = sync_adjustment + raop_rtp->rtp_clock_rate * (rtp64_timestamp - raop_rtp->rtp_start_time); + audio_data.ntp_time_local = raop_rtp->ntp_start_time + delay + (uint64_t) elapsed_time; + audio_data.ntp_time_remote = raop_ntp_convert_local_time(raop_rtp->ntp, audio_data.ntp_time_local); + audio_data.sync_status = 0; } raop_rtp->callbacks.audio_process(raop_rtp->callbacks.cls, raop_rtp->ntp, &audio_data); free(payload); uint64_t ntp_now = raop_ntp_get_local_time(raop_rtp->ntp); - int64_t latency = ((int64_t) ntp_now) - ((int64_t) audio_data.ntp_time); + int64_t latency = ((int64_t) ntp_now) - ((int64_t) audio_data.ntp_time_local); logger_log(raop_rtp->logger, LOGGER_DEBUG, "raop_rtp audio: now = %8.6f, ntp = %8.6f, latency = %8.6f, rtp_time=%u seqnum = %u", - ((double) ntp_now ) / SEC, ((double) audio_data.ntp_time) / SEC, ((double) latency) / SEC, (uint32_t) rtp64_timestamp, + (double) ntp_now / SEC, (double) audio_data.ntp_time_local / SEC, (double) latency / SEC, (uint32_t) rtp64_timestamp, seqnum); } diff --git a/lib/raop_rtp_mirror.c b/lib/raop_rtp_mirror.c index 3a7d223..4ddfda1 100644 --- a/lib/raop_rtp_mirror.c +++ b/lib/raop_rtp_mirror.c @@ -203,7 +203,7 @@ raop_rtp_mirror_thread(void *arg) uint64_t ntp_timestamp_nal = 0; uint64_t ntp_timestamp_raw = 0; uint64_t ntp_timestamp_remote = 0; - uint64_t ntp_timestamp; + uint64_t ntp_timestamp_local = 0; unsigned char nal_start_code[4] = { 0x00, 0x00, 0x00, 0x01 }; #ifdef DUMP_H264 @@ -375,11 +375,11 @@ raop_rtp_mirror_thread(void *arg) // ntp time stamps don't include the SECONDS_FROM_1900_TO_1970, so it's really just // counting nano seconds since last boot. - ntp_timestamp = raop_ntp_convert_remote_time(raop_rtp_mirror->ntp, ntp_timestamp_remote); + ntp_timestamp_local = raop_ntp_convert_remote_time(raop_rtp_mirror->ntp, ntp_timestamp_remote); uint64_t ntp_now = raop_ntp_get_local_time(raop_rtp_mirror->ntp); - int64_t latency = ((int64_t) ntp_now) - ((int64_t) ntp_timestamp); + int64_t latency = ((int64_t) ntp_now) - ((int64_t) ntp_timestamp_local); logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp video: now = %8.6f, ntp = %8.6f, latency = %8.6f, ts = %8.6f, %s", - (double) ntp_now / SEC, (double) ntp_timestamp / SEC, (double) latency / SEC, (double) ntp_timestamp_remote / SEC, packet_description); + (double) ntp_now / SEC, (double) ntp_timestamp_local / SEC, (double) latency / SEC, (double) ntp_timestamp_remote / SEC, packet_description); #ifdef DUMP_H264 fwrite(payload, payload_size, 1, file_source); @@ -448,14 +448,15 @@ raop_rtp_mirror_thread(void *arg) #endif payload_decrypted = NULL; h264_decode_struct h264_data; - h264_data.ntp_time = ntp_timestamp; + h264_data.ntp_time_local = ntp_timestamp_local; + h264_data.ntp_time_remote = ntp_timestamp_remote; h264_data.nal_count = nalus_count; /*nal_count will be the number of nal units in the packet */ h264_data.data_len = payload_size; h264_data.data = payload_out; if (prepend_sps_pps) { h264_data.data_len += raop_rtp_mirror->sps_pps_len; h264_data.nal_count += 2; - if (ntp_timestamp_remote != ntp_timestamp_nal) { + if (ntp_timestamp_raw != ntp_timestamp_nal) { logger_log(raop_rtp_mirror->logger, LOGGER_WARNING, "raop_rtp_mirror: prepended sps_pps timestamp does not match that of video payload"); } } @@ -471,7 +472,7 @@ raop_rtp_mirror_thread(void *arg) logger_log(raop_rtp_mirror->logger, LOGGER_DEBUG, "raop_rtp_mirror, discard type 0x01 packet with no payload"); break; } - ntp_timestamp_nal = ntp_timestamp_remote; + ntp_timestamp_nal = ntp_timestamp_raw; float width = byteutils_get_float(packet, 16); float height = byteutils_get_float(packet, 20); float width_source = byteutils_get_float(packet, 40); diff --git a/lib/stream.h b/lib/stream.h index be5c5ed..ceec89d 100644 --- a/lib/stream.h +++ b/lib/stream.h @@ -25,13 +25,16 @@ typedef struct { int nal_count; unsigned char *data; int data_len; - uint64_t ntp_time; + uint64_t ntp_time_local; + uint64_t ntp_time_remote; } h264_decode_struct; typedef struct { unsigned char *data; int data_len; - uint64_t ntp_time; + int sync_status; + uint64_t ntp_time_local; + uint64_t ntp_time_remote; uint64_t rtp_time; unsigned short seqnum; } audio_decode_struct; diff --git a/uxplay.cpp b/uxplay.cpp index 082751e..c713895 100644 --- a/uxplay.cpp +++ b/uxplay.cpp @@ -994,7 +994,7 @@ extern "C" void audio_process (void *cls, raop_ntp_t *ntp, audio_decode_struct * dump_audio_to_file(data->data, data->data_len, (data->data)[0] & 0xf0); } if (use_audio) { - audio_renderer_render_buffer(data->data, &(data->data_len), &(data->seqnum), &(data->ntp_time)); + audio_renderer_render_buffer(data->data, &(data->data_len), &(data->seqnum), &(data->ntp_time_local)); } } @@ -1003,7 +1003,7 @@ extern "C" void video_process (void *cls, raop_ntp_t *ntp, h264_decode_struct *d dump_video_to_file(data->data, data->data_len); } if (use_video) { - video_renderer_render_buffer(data->data, &(data->data_len), &(data->nal_count), &(data->ntp_time)); + video_renderer_render_buffer(data->data, &(data->data_len), &(data->nal_count), &(data->ntp_time_local)); } }