]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Add a cancellation stack to get_buffer_frame.
authorMike Brady <mikebrady@eircom.net>
Sun, 15 Jul 2018 12:11:51 +0000 (13:11 +0100)
committerMike Brady <mikebrady@eircom.net>
Sun, 15 Jul 2018 12:11:51 +0000 (13:11 +0100)
player.c

index 07716b769b133e1142d426509894f0c4f48a00a7..4ba93f8f085612b02c61de4089a20b191c4e9726 100644 (file)
--- a/player.c
+++ b/player.c
@@ -771,6 +771,11 @@ static inline void process_sample(int32_t sample, char **outp, enum sps_format_t
   *outp += result;
 }
 
+void buffer_get_frame_cleanup_handler(void *arg) {
+  rtsp_conn_info *conn = (rtsp_conn_info *)arg;
+  debug_mutex_unlock(&conn->ab_mutex, 3);
+}
+
 // get the next frame, when available. return 0 if underrun/stream reset.
 static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
   // int16_t buf_fill;
@@ -780,8 +785,12 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
   int notified_buffer_empty = 0; // diagnostic only
 
   debug_mutex_lock(&conn->ab_mutex, 30000, 1);
+  
+  
   int wait;
   long dac_delay = 0; // long because alsa returns a long
+  
+  pthread_cleanup_push(buffer_get_frame_cleanup_handler, (void *)conn); // undo what's been done so far
   do {
     // get the time
     local_time_now = get_absolute_time_in_fp(); // type okay
@@ -820,8 +829,8 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
     debug_mutex_lock(&conn->flush_mutex, 1000, 1);
     if (conn->flush_requested == 1) {
       if (config.output->flush)
-        config.output->flush();
-      ab_resync(conn);
+        config.output->flush(); // no cancellation points
+      ab_resync(conn); // no cancellation points
       conn->first_packet_timestamp = 0;
       conn->first_packet_time_to_play = 0;
       conn->time_since_play_started = 0;
@@ -1207,7 +1216,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
       time_of_wakeup.tv_sec = sec;
       time_of_wakeup.tv_nsec = nsec;
       //      pthread_cond_timedwait(&conn->flowcontrol, &conn->ab_mutex, &time_of_wakeup);
-      int rc = pthread_cond_timedwait(&conn->flowcontrol, &conn->ab_mutex, &time_of_wakeup);
+      int rc = pthread_cond_timedwait(&conn->flowcontrol, &conn->ab_mutex, &time_of_wakeup);  // this is a pthread cancellation point
       if (rc != 0)
         debug(3, "pthread_cond_timedwait returned error code %d.", rc);
 #endif
@@ -1222,24 +1231,24 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
     }
   } while (wait);
 
-  if (conn->player_thread_please_stop) {
-    debug(3, "buffer_get_frame exiting due to thread stop request.");
-    debug_mutex_unlock(&conn->ab_mutex, 3);
-    return 0;
-  }
-
   // seq_t read = conn->ab_read;
-
-  if (!curframe->ready) {
-    // debug(1, "Supplying a silent frame for frame %u", read);
-    conn->missing_packets++;
-    curframe->timestamp = 0; // indicate a silent frame should be substituted
+  if (conn->player_thread_please_stop==0) {
+    if (!curframe->ready) {
+      // debug(1, "Supplying a silent frame for frame %u", read);
+      conn->missing_packets++;
+      curframe->timestamp = 0; // indicate a silent frame should be substituted
+    }
+    curframe->ready = 0;
+    curframe->resend_level = 0;
+    conn->ab_read = SUCCESSOR(conn->ab_read);
   }
-  curframe->ready = 0;
-  curframe->resend_level = 0;
-  conn->ab_read = SUCCESSOR(conn->ab_read);
-  debug_mutex_unlock(&conn->ab_mutex, 3);
-  return curframe;
+  
+  pthread_cleanup_pop(1);
+
+  if (conn->player_thread_please_stop)
+    return 0;
+  else
+    return curframe;
 }
 
 static inline short shortmean(short a, short b) {
@@ -1743,7 +1752,7 @@ void *player_thread_func(void *arg) {
 
   // debug(1, "Play begin");
   while (!conn->player_thread_please_stop) {
-    abuf_t *inframe = buffer_get_frame(conn);
+    abuf_t *inframe = buffer_get_frame(conn); // this has cancellation point(s)
     if (inframe) {
       inbuf = inframe->data;
       inbuflength = inframe->length;