]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Remember the original anchor information so that if the master clock become equal...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 1 Jun 2021 13:51:17 +0000 (14:51 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Tue, 1 Jun 2021 13:51:17 +0000 (14:51 +0100)
audio_alsa.c
player.c
player.h
rtp.c
rtsp.c

index c5794348e31370132f4836c37f6e009bb9665cf3..2d07c8f47cb1e6da8d4ce01bcfa7cd6b27e2f3df 100644 (file)
@@ -501,8 +501,8 @@ int actual_open_alsa_device(int do_auto_setup) {
     }
     ret = snd_pcm_hw_params_set_format(alsa_handle, alsa_params, sf);
     if (ret < 0) {
-      die("audio_alsa: Alsa sample format %d not available for device \"%s\": %s", sf,
-           alsa_out_dev, snd_strerror(ret));
+      die("audio_alsa: Alsa sample format %d not available for device \"%s\": %s", sf, alsa_out_dev,
+          snd_strerror(ret));
       return ret;
     }
   } else { // auto format
index a0e10d943472627ef54e138ee2e5bd8d400beff5..a9822d68c3a237b22b00943d3ea335cc30d2c109 100644 (file)
--- a/player.c
+++ b/player.c
@@ -384,11 +384,12 @@ static void terminate_decoders(rtsp_conn_info *conn) {
 }
 
 static void init_buffer(rtsp_conn_info *conn) {
-  debug(1,"input_bytes_per_frame: %d.", conn->input_bytes_per_frame);
-  debug(1,"input_bit_depth: %d.", conn->input_bit_depth);
+  // debug(1,"input_bytes_per_frame: %d.", conn->input_bytes_per_frame);
+  // debug(1,"input_bit_depth: %d.", conn->input_bit_depth);
   int i;
   for (i = 0; i < BUFFER_FRAMES; i++)
-//    conn->audio_buffer[i].data = malloc(conn->input_bytes_per_frame * conn->max_frames_per_packet);
+    //    conn->audio_buffer[i].data = malloc(conn->input_bytes_per_frame *
+    //    conn->max_frames_per_packet);
     conn->audio_buffer[i].data = malloc(8 * conn->max_frames_per_packet); // todo
 }
 
@@ -2121,7 +2122,7 @@ void *player_thread_func(void *arg) {
             int i, j;
             int32_t ls, rs;
             int32_t ll = 0, rl = 0;
-            int32_t *inps = (int32_t*) inbuf;
+            int32_t *inps = (int32_t *)inbuf;
             int32_t *outpl = (int32_t *)conn->tbuf;
             for (i = 0; i < inbuflength; i++) {
               ls = *inps++;
index a21deec6d0f6689e2e09631eedaa5d6977b4a789..c35e5726f8bf216304e8c96c424288e68981a5a2 100644 (file)
--- a/player.h
+++ b/player.h
@@ -273,10 +273,18 @@ typedef struct {
 
   int anchor_remote_info_is_valid;
   int anchor_clock_is_new;
+
+  // these can be modified if the master clock changes over time
   uint64_t anchor_clock;
   uint64_t anchor_time; // this is the time according to the clock
   uint32_t anchor_rtptime;
 
+  // these are used to identify when the master clock becomes equal to the
+  // actual anchor clock information, so it can be used to avoid accumulating errors
+  uint64_t actual_anchor_clock;
+  uint64_t actual_anchor_time;
+  uint32_t actual_anchor_rtptime;
+
   clock_status_t clock_status;
 
 #ifdef CONFIG_AIRPLAY_2
diff --git a/rtp.c b/rtp.c
index dc3ba0aa4c5a6018f00e910072c3bcdcd78dbe5f..9fb8481c8cf9148c8c99dcd54346845940e3633c 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -290,8 +290,8 @@ void *rtp_control_receiver(void *arg) {
                                                                 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
@@ -302,19 +302,19 @@ void *rtp_control_receiver(void *arg) {
                                                               // 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 packet 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 "
@@ -1220,22 +1220,45 @@ void set_ptp_anchor_info(rtsp_conn_info *conn, uint64_t clock_id, uint32_t rtpti
   // valid for some minimum time (and thus may not be reliable), we need to invalidate
   // last_anchor_info
 
+  if ((conn->airplay_stream_type == buffered_stream) &&
+      ((clock_id != conn->anchor_clock) || (conn->anchor_rtptime != rtptime) ||
+       (conn->anchor_time != networktime))) {
+    uint64_t master_clock_id = 0;
+    ptp_get_clock_info(&master_clock_id, NULL, NULL);
+    debug(1,
+          "Connection %d: Note: anchor parameters have changed. Old clock: %" PRIx64
+          ", rtptime: %u, networktime: %" PRIu64 ". New clock: %" PRIx64
+          ", rtptime: %u, networktime: %" PRIu64 ". Current master clock: %" PRIx64 ".",
+          conn->connection_number, conn->anchor_clock, conn->anchor_rtptime, conn->anchor_time,
+          clock_id, rtptime, networktime, master_clock_id);
+  }
+
   if ((clock_id == conn->anchor_clock) &&
       ((conn->anchor_rtptime != rtptime) || (conn->anchor_time != networktime))) {
     uint64_t time_now = get_absolute_time_in_ns();
     int64_t last_anchor_validity_duration = time_now - conn->last_anchor_validity_start_time;
     if (last_anchor_validity_duration < 5000000000) {
-      debug(1,
-            "Connection %d: Note: anchor parameters have changed before clock %" PRIx64
-            " has stabilised.",
-            conn->connection_number, clock_id);
+      if (conn->airplay_stream_type == buffered_stream)
+        debug(1,
+              "Connection %d: Note: anchor parameters have changed before clock %" PRIx64
+              " has stabilised.",
+              conn->connection_number, clock_id);
       conn->last_anchor_info_is_valid = 0;
     }
   }
+
   conn->anchor_remote_info_is_valid = 1;
+
+  // these can be modified if the master clock changes over time
   conn->anchor_rtptime = rtptime;
   conn->anchor_time = networktime;
   conn->anchor_clock = clock_id;
+
+  // these are used to identify when the master clock becomes equal to the
+  // actual anchor clock information, so it can be used to avoid accumulating errors
+  conn->actual_anchor_rtptime = rtptime;
+  conn->actual_anchor_time = networktime;
+  conn->actual_anchor_clock = clock_id;
 }
 
 void reset_ptp_anchor_info(rtsp_conn_info *conn) {
@@ -1303,8 +1326,18 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP,
             // here we adjust the time of the anchor rtptime
             // we know its local time, so we use the new clocks's offset to
             // calculate what time that must be on the new clock
-            conn->anchor_time = conn->last_anchor_local_time + actual_offset;
-            conn->anchor_clock = actual_clock_id;
+
+            // but if the master clock has become equal to the actual anchor clock
+            // then we can reinstate it all
+            if (actual_clock_id == conn->actual_anchor_clock) {
+              debug(1, "Master clock has become equal to the anchor clock");
+              conn->anchor_clock = conn->actual_anchor_clock;
+              conn->anchor_time = conn->actual_anchor_time;
+              conn->anchor_rtptime = conn->actual_anchor_rtptime;
+            } else {
+              conn->anchor_time = conn->last_anchor_local_time + actual_offset;
+              conn->anchor_clock = actual_clock_id;
+            }
           }
         } else {
           response = clock_not_valid; // no current clock information and no previous clock info
@@ -2087,37 +2120,38 @@ void *rtp_buffered_audio_processor(void *arg) {
 
   enum AVSampleFormat av_format;
   switch (config.output_format) {
-    case SPS_FORMAT_S32:
-    case SPS_FORMAT_S32_LE:
-    case SPS_FORMAT_S32_BE:
-    case SPS_FORMAT_S24:
-    case SPS_FORMAT_S24_LE:
-    case SPS_FORMAT_S24_BE:
-    case SPS_FORMAT_S24_3LE:
-    case SPS_FORMAT_S24_3BE:
-     av_format = AV_SAMPLE_FMT_S32;
-      conn->input_bytes_per_frame = 8; // the output from the decoder will be input to the player
-      conn->input_bit_depth = 32;
-       debug(1,"32-bit output format chosen");
-      break;
-    case SPS_FORMAT_S16:
-    case SPS_FORMAT_S16_LE:
-    case SPS_FORMAT_S16_BE:
-      av_format = AV_SAMPLE_FMT_S16;
-      conn->input_bytes_per_frame = 4;
-      conn->input_bit_depth = 16;
-      break;
-    case SPS_FORMAT_U8:
-      av_format = AV_SAMPLE_FMT_U8;
-      conn->input_bytes_per_frame = 2;
-      conn->input_bit_depth = 8;
-      break;
-    default:
-      debug(1,"Unsupported DAC output format %u. AV_SAMPLE_FMT_S16 decoding chosen. Good luck!", config.output_format);
-      av_format = AV_SAMPLE_FMT_S16;
-      conn->input_bytes_per_frame = 4; // the output from the decoder will be input to the player
-      conn->input_bit_depth = 16;
-      break;
+  case SPS_FORMAT_S32:
+  case SPS_FORMAT_S32_LE:
+  case SPS_FORMAT_S32_BE:
+  case SPS_FORMAT_S24:
+  case SPS_FORMAT_S24_LE:
+  case SPS_FORMAT_S24_BE:
+  case SPS_FORMAT_S24_3LE:
+  case SPS_FORMAT_S24_3BE:
+    av_format = AV_SAMPLE_FMT_S32;
+    conn->input_bytes_per_frame = 8; // the output from the decoder will be input to the player
+    conn->input_bit_depth = 32;
+    debug(1, "32-bit output format chosen");
+    break;
+  case SPS_FORMAT_S16:
+  case SPS_FORMAT_S16_LE:
+  case SPS_FORMAT_S16_BE:
+    av_format = AV_SAMPLE_FMT_S16;
+    conn->input_bytes_per_frame = 4;
+    conn->input_bit_depth = 16;
+    break;
+  case SPS_FORMAT_U8:
+    av_format = AV_SAMPLE_FMT_U8;
+    conn->input_bytes_per_frame = 2;
+    conn->input_bit_depth = 8;
+    break;
+  default:
+    debug(1, "Unsupported DAC output format %u. AV_SAMPLE_FMT_S16 decoding chosen. Good luck!",
+          config.output_format);
+    av_format = AV_SAMPLE_FMT_S16;
+    conn->input_bytes_per_frame = 4; // the output from the decoder will be input to the player
+    conn->input_bit_depth = 16;
+    break;
   };
 
   av_opt_set_sample_fmt(swr, "out_sample_fmt", av_format, 0);
@@ -2134,8 +2168,7 @@ void *rtp_buffered_audio_processor(void *arg) {
   ssize_t nread;
 
   int finished = 0;
-  int pcm_buffer_size =
-      (1024 + 352) * conn->input_bytes_per_frame;
+  int pcm_buffer_size = (1024 + 352) * conn->input_bytes_per_frame;
   uint8_t pcm_buffer[pcm_buffer_size];
 
   int pcm_buffer_occupancy = 0;
@@ -2307,8 +2340,9 @@ void *rtp_buffered_audio_processor(void *arg) {
           new_buffer_needed = 1;
           if (pcm_buffer_read_point != 0) {
             // debug(1,"pcm_buffer_read_point (frames): %u, pcm_buffer_occupancy (frames): %u",
-            // pcm_buffer_read_point/conn->input_bytes_per_frame, pcm_buffer_occupancy/conn->input_bytes_per_frame);
-            // if there is anything to move down to the front of the buffer, do it now;
+            // pcm_buffer_read_point/conn->input_bytes_per_frame,
+            // pcm_buffer_occupancy/conn->input_bytes_per_frame); if there is anything to move down
+            // to the front of the buffer, do it now;
             if ((pcm_buffer_occupancy - pcm_buffer_read_point) > 0) {
               // move the remaining frames down to the start of the buffer
               // debug(1,"move the remaining frames down to the start of the pcm_buffer");
@@ -2501,8 +2535,8 @@ void *rtp_buffered_audio_processor(void *arg) {
                               debug(2,
                                     "samples remaining before flush: %d, number of samples %d. "
                                     "flushFromTS: %u, pcm_buffer_read_point_rtptime: %u.",
-                                    samples_remaining, dst_bufsize / conn->input_bytes_per_frame, flush_from_timestamp,
-                                    pcm_buffer_read_point_rtptime);
+                                    samples_remaining, dst_bufsize / conn->input_bytes_per_frame,
+                                    flush_from_timestamp, pcm_buffer_read_point_rtptime);
                               dst_bufsize = samples_remaining * conn->input_bytes_per_frame;
                             }
                           }
@@ -2510,7 +2544,8 @@ void *rtp_buffered_audio_processor(void *arg) {
                             debug(1,
                                   "pcm_buffer_read_point (frames): %u, pcm_buffer_occupancy "
                                   "(frames): %u",
-                                  pcm_buffer_read_point / conn->input_bytes_per_frame, pcm_buffer_occupancy / conn->input_bytes_per_frame);
+                                  pcm_buffer_read_point / conn->input_bytes_per_frame,
+                                  pcm_buffer_occupancy / conn->input_bytes_per_frame);
                             pcm_buffer_size = dst_bufsize + pcm_buffer_occupancy;
                             debug(1, "fatal error! pcm buffer too small at %d bytes.",
                                   pcm_buffer_size);
diff --git a/rtsp.c b/rtsp.c
index c50b76793cbd4db16d6e128eb98acd559d649ad5..a808c96f92e8b095653f3746fa1ba31cf97741af 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -2077,7 +2077,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
       conn->input_bit_depth = 16;
       conn->input_bytes_per_frame = conn->input_num_channels * ((conn->input_bit_depth + 7) / 8);
 
-      player_prepare_to_play(conn); // get capabilities of DAC before creating the buffered audio thread
+      player_prepare_to_play(
+          conn); // get capabilities of DAC before creating the buffered audio thread
 
       pthread_create(&conn->rtp_buffered_audio_thread, NULL, &rtp_buffered_audio_processor,
                      (void *)conn);