]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
recognise two types of flush -- one with from and until information, the other with...
authorMike Brady <4265913+mikebrady@users.noreply.github.com>
Fri, 28 May 2021 18:16:37 +0000 (19:16 +0100)
committerMike Brady <4265913+mikebrady@users.noreply.github.com>
Fri, 28 May 2021 18:16:37 +0000 (19:16 +0100)
player.h
rtp.c
rtsp.c

index 35a3db6e5bfe2fd0030bda232a59e33052150f1b..2b5774a7407d6d8b83ce56ed3b357f67d5510103 100644 (file)
--- a/player.h
+++ b/player.h
@@ -295,8 +295,11 @@ typedef struct {
 
   ssize_t ap2_audio_buffer_size;
   int ap2_flush_requested;
-  uint32_t ap2_flush_rtp_timestamp;
-  uint32_t ap2_flush_sequence_number;
+  int ap2_flush_from_valid;
+  uint32_t ap2_flush_from_rtp_timestamp;
+  uint32_t ap2_flush_from_sequence_number;
+  uint32_t ap2_flush_until_rtp_timestamp;
+  uint32_t ap2_flush_until_sequence_number;
   int ap2_rate;         // protect with flush mutex, 0 means don't play, 1 means play
   int ap2_play_enabled; // protect with flush mutex
 
diff --git a/rtp.c b/rtp.c
index d7ad5472582fbf3c05ecae20436c555e2e89b5b4..3e1be921a93e5070bd39a6342ca41ea7991d4ee1 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -1213,6 +1213,7 @@ void set_ptp_anchor_info(rtsp_conn_info *conn, uint64_t clock_id, uint32_t rtpti
     debug(2, "Connection %d: Set Anchor Clock: %" PRIx64 ".", conn->connection_number, clock_id);
     conn->anchor_clock_is_new = 1;
   }
+  debug(1,"set anchor info clock: %" PRIx64", rtptime: %u, networktime: %" PRIx64 ".", clock_id, rtptime, networktime);
   conn->anchor_remote_info_is_valid = 1;
   conn->anchor_rtptime = rtptime;
   conn->anchor_time = networktime;
@@ -2056,18 +2057,41 @@ void *rtp_buffered_audio_processor(void *arg) {
     int flush_newly_requested = 0;
     // are we in in flush mode, or just about to leave it?
     debug_mutex_lock(&conn->flush_mutex, 10000, 1); // 10ms is a long time to wait!
-    uint32_t flushUntilSeq = conn->ap2_flush_sequence_number;
-    uint32_t flushUntilTS = conn->ap2_flush_rtp_timestamp;
-    // if we are in flush mode
+    uint32_t flushUntilSeq = conn->ap2_flush_until_sequence_number;
+    uint32_t flushUntilTS = conn->ap2_flush_until_rtp_timestamp;
+
+    int flush_request_active = 0;
     if (conn->ap2_flush_requested) {
+      if (conn->ap2_flush_from_valid == 0) {// i.e. a flush from right now
+        flush_request_active = 1;
+      } else {
+        int32_t blocks_to_start_of_flush = conn->ap2_flush_from_sequence_number - seq_no;
+        if (blocks_to_start_of_flush <= 0) {
+          flush_request_active = 1;
+          // debug(1, "delayed flush request going active");
+        }
+      }
+    }
+    // if we are in flush mode
+    if (flush_request_active) {
       if (flush_requested == 0) {
         // here, a flush has been newly requested
-        debug(1,
-              "flush requested. flushUntilSeq = %u, flushUntilTS = %u, seq_no: %u, "
-              "pcm_buffer_read_point_rtptime = "
-              "%u, buffer_size: %u.",
-              flushUntilSeq, flushUntilTS, seq_no, pcm_buffer_read_point_rtptime,
-              buffered_audio->buffer_occupancy);
+        debug(1,"Flush requested:");
+        if (conn->ap2_flush_from_valid) {
+          debug(1,"  fromTS:          %u", conn->ap2_flush_from_rtp_timestamp);
+          debug(1,"  fromSeq:         %u", conn->ap2_flush_from_sequence_number);
+          debug(1,"--");
+        }
+          debug(1,"  untilTS:         %u", conn->ap2_flush_until_rtp_timestamp);
+          debug(1,"  untilSeq:        %u", conn->ap2_flush_until_sequence_number);
+          debug(1,"--");
+          debug(1,"  currentTS_Start: %u", pcm_buffer_read_point_rtptime);
+          uint32_t fib = (pcm_buffer_occupancy - pcm_buffer_read_point) / 4;
+          debug(1,"  framesInBuffer:  %u", fib);
+          uint32_t endTS = fib + pcm_buffer_read_point_rtptime;
+          debug(1,"  currentTS_End:   %u", endTS); // a frame occupies 4 bytes
+          debug(1,"  currentSeq:      %u", seq_no);
+
         last_block_flushed_rtp_time = pcm_buffer_read_point_rtptime;
         last_block_flushed_seq_no = seq_no;
         flush_newly_requested = 1;
@@ -2096,22 +2120,19 @@ void *rtp_buffered_audio_processor(void *arg) {
           pcm_buffer_read_point_rtptime = flushUntilTS;
         }
         conn->ap2_flush_requested = 0;
+        flush_request_active = 0;
       } else {
         if (seq_no > flushUntilSeq) {
           debug(1,
                 "we have overshot the flush ending block. flushUntilSeq is %u, this block is: %u.",
                 flushUntilSeq, seq_no);
           conn->ap2_flush_requested = 0; // but conn->ap2_play_enabled will remain at zero
+          flush_request_active = 0;
         }
       }
     }
-    flush_requested = conn->ap2_flush_requested;
-
-    // this isn't always the case, i.e. that play is re-enabled after a flush
-    // if (flush_requested)
-    //  conn->ap2_play_enabled = 0;
-    // play is disabled until an anchor time is sent and play is restarted
-
+    flush_requested = flush_request_active;
+    // flush_requested = conn->ap2_flush_requested;
     int play_enabled = conn->ap2_play_enabled;
     debug_mutex_unlock(&conn->flush_mutex, 3);
 
@@ -2237,6 +2258,7 @@ void *rtp_buffered_audio_processor(void *arg) {
         */
         seq_no = packet[1] * (1 << 16) + packet[2] * (1 << 8) + packet[3];
         uint32_t timestamp = nctohl(&packet[4]);
+        // debug(1, "immediately: block %u, rtptime %u", seq_no, timestamp);
         // uint32_t ssrc = nctohl(&packet[8]);
         // uint8_t marker = 0;
         // uint8_t payload_type = 0;
@@ -2266,13 +2288,14 @@ void *rtp_buffered_audio_processor(void *arg) {
         if ((flush_requested) && (seq_no < flushUntilSeq)) {
           last_block_flushed_seq_no = seq_no;
           last_block_flushed_rtp_time = timestamp;
-          // debug(1, "flushing block %u, rtptime %u up to block %u, rtptime %u.", seq_no,
-          // timestamp, flushUntilSeq, flushUntilTS);
+          debug(1, "flush block %u, rtptime %u", seq_no, timestamp);
         }
 
         if (((flush_requested) && (seq_no == flushUntilSeq)) || (new_buffer_needed)) {
 
           if ((flush_requested) && (seq_no == flushUntilSeq)) {
+         if (conn->ap2_flush_from_valid != 0)
+            debug(1, "also flush block %u, rtptime %u", seq_no, timestamp);
             int32_t timestamp_difference = timestamp - flushUntilTS;
             debug(1,
                   "end of flush reached. flushUntilSeq = %u, flushUntilTS = %u, last block flushed "
diff --git a/rtsp.c b/rtsp.c
index 7ae9fc7bfedbd0d592205fe7dca89506b6089731..24d8ea14b7e49d2dc61e57643e93dc8ef246ac9d 100644 (file)
--- a/rtsp.c
+++ b/rtsp.c
@@ -1300,11 +1300,35 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message
         req->path, req->contentlength);
   debug_log_rtsp_message(1, "FLUSHBUFFERED request", req);
 
+  uint64_t flushFromSeq = 0;
+  uint64_t flushFromTS = 0;
   uint64_t flushUntilSeq = 0;
   uint64_t flushUntilTS = 0;
+  int flushFromValid = 0;
   plist_t messagePlist = plist_from_rtsp_content(req);
+  plist_t item = plist_dict_get_item(messagePlist, "flushFromSeq");
+  if (item == NULL) {
+    debug(2, "Can't find a flushFromSeq");
+  } else {
+    flushFromValid = 1;
+    plist_get_uint_val(item, &flushFromSeq);
+    debug(2, "flushFromSeq is %" PRId64 ".", flushFromSeq);
+  }
+
+  item = plist_dict_get_item(messagePlist, "flushFromTS");
+  if (item == NULL) {
+    if (conn->ap2_flush_from_valid != 0)
+      debug(1, "flushFromSeq without flushFromTS!");
+    else
+      debug(2, "Can't find a flushFromTS");
+  } else {
+    plist_get_uint_val(item, &flushFromTS);
+    if (flushFromValid == 0)
+      debug(1,"flushFromTS without flushFromSeq!");
+    debug(2, "flushFromTS is %" PRId64 ".", flushFromTS);
+  }
 
-  plist_t item = plist_dict_get_item(messagePlist, "flushUntilSeq");
+  item = plist_dict_get_item(messagePlist, "flushUntilSeq");
   if (item == NULL) {
     debug(1, "Can't find the flushUntilSeq");
   } else {
@@ -1321,8 +1345,15 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message
   }
 
   debug_mutex_lock(&conn->flush_mutex, 1000, 1);
-  conn->ap2_flush_sequence_number = flushUntilSeq;
-  conn->ap2_flush_rtp_timestamp = flushUntilTS;
+  conn->ap2_flush_from_valid = flushFromValid;
+  // a flush with from... components will not be followed by a setanchoe (i.e. a play)
+  // if it's a flush that will be followed by a setanchor (i.e. a play) then stop play now.
+  if (flushFromValid == 0)
+    conn->ap2_play_enabled = 0;
+  conn->ap2_flush_from_sequence_number = flushFromSeq;
+  conn->ap2_flush_from_rtp_timestamp = flushFromTS;
+  conn->ap2_flush_until_sequence_number = flushUntilSeq;
+  conn->ap2_flush_until_rtp_timestamp = flushUntilTS;
   conn->ap2_flush_requested = 1;
   debug_mutex_unlock(&conn->flush_mutex, 3);
 
@@ -3788,7 +3819,7 @@ static void *rtsp_conversation_thread_func(void *pconn) {
   rtsp_message *req, *resp;
 
 #ifdef CONFIG_AIRPLAY_2
-  conn->ap2_audio_buffer_size = 1024 * 1024 * 8;
+  conn->ap2_audio_buffer_size = 1024 * 1024 * 128;
 #endif
 
   while (conn->stop == 0) {