]> git.ipfire.org Git - thirdparty/shairport-sync.git/commitdiff
Stop erroneously assuming that the buffer passed to the player is not changed --...
authorMike Brady <mikebrady@eircom.net>
Mon, 7 May 2018 21:00:01 +0000 (22:00 +0100)
committerMike Brady <mikebrady@eircom.net>
Mon, 7 May 2018 21:00:01 +0000 (22:00 +0100)
audio.h
audio_alsa.c
player.c
rtp.c

diff --git a/audio.h b/audio.h
index e0defc55480ddf6384106566e67986a165ab9cdf..dc7eb873f7dcd984a019c25a7ae47a2209c1d5ed 100644 (file)
--- a/audio.h
+++ b/audio.h
@@ -22,7 +22,7 @@ typedef struct {
   void (*start)(int sample_rate, int sample_format);
 
   // block of samples
-  void (*play)(short buf[], int samples);
+  void (*play)(void *buf, int samples);
   void (*stop)(void);
 
   // may be null if not implemented
index 3310eeaaca16a2ef01f292a0c88554f3da67d285..d6bf73dd69c67ea3848a16be99662e418639bd42 100644 (file)
@@ -40,7 +40,7 @@ static void help(void);
 static int init(int argc, char **argv);
 static void deinit(void);
 static void start(int i_sample_rate, int i_sample_format);
-static void play(short buf[], int samples);
+static void play(void *buf, int samples);
 static void stop(void);
 static void flush(void);
 int delay(long *the_delay);
@@ -836,7 +836,7 @@ int delay(long *the_delay) {
   }
 }
 
-static void play(short buf[], int samples) {
+static void play(void *buf, int samples) {
   // debug(3,"audio_alsa play called.");
   int ret = 0;
   if (alsa_handle == NULL) {
@@ -867,7 +867,7 @@ static void play(short buf[], int samples) {
       if (samples == 0)
         debug(1, "empty buffer being passed to pcm_writei -- skipping it");
       if ((samples != 0) && (buf != NULL)) {
-        err = alsa_pcm_write(alsa_handle, (char *)buf, samples);
+        err = alsa_pcm_write(alsa_handle, buf, samples);
         if (err < 0) {
           debug(1, "Error %d writing %d samples in play(): \"%s\".", err, samples,
                 snd_strerror(err));
@@ -893,10 +893,8 @@ static void flush(void) {
   do_mute(1);
   if (alsa_handle) {
 
-    debug(1,"Start drain.");
-    if ((derr = snd_pcm_drain(alsa_handle)))
-      debug(1, "Error %d (\"%s\") draining output device.", derr, snd_strerror(derr));
-    debug(1,"Finish drain.");
+    if ((derr = snd_pcm_drop(alsa_handle)))
+      debug(1, "Error %d (\"%s\") dropping output device.", derr, snd_strerror(derr));
 
     if ((derr = snd_pcm_hw_free(alsa_handle)))
       debug(1, "Error %d (\"%s\") freeing the output device hardware.", derr, snd_strerror(derr));
@@ -904,6 +902,7 @@ static void flush(void) {
     // flush also closes the device
     if ((derr = snd_pcm_close(alsa_handle)))
       debug(1, "Error %d (\"%s\") closing the output device.", derr, snd_strerror(derr));
+
     alsa_handle = NULL;
   }
   pthread_mutex_unlock(&alsa_mutex);
index d3dcb0db4ff5a10e8c3e505c03f829ddeb5a3fe9..70d6f7a992aeac8b69c61f1f76855e9e93f8c3de 100644 (file)
--- a/player.c
+++ b/player.c
@@ -452,8 +452,7 @@ static void terminate_decoders(rtsp_conn_info *conn) {
 static void init_buffer(rtsp_conn_info *conn) {
   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->max_frame_size_change));
+    conn->audio_buffer[i].data = malloc(conn->input_bytes_per_frame * conn->max_frames_per_packet);
   ab_resync(conn);
 }
 
@@ -1036,13 +1035,13 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
                       // ab_write),ab_read,ab_write);
                       conn->ab_buffering = 0;
                     }
-                    signed short *silence;
+                    void *silence;
                     // if (fs==0)
                     //  debug(2,"Zero length silence buffer needed with gross_frame_gap of %lld and
                     //  dac_delay of %lld.",gross_frame_gap,dac_delay);
                     // the fs (number of frames of silence to play) can be zero in the DAC doesn't
                     // start
-                    // ouotputting frames for a while -- it could get loaded up but not start
+                    // outputting frames for a while -- it could get loaded up but not start
                     // responding
                     // for many milliseconds.
                     if (fs > 0) {
@@ -1066,7 +1065,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
                   // debug(1,"Back end has no delay function.");
                   // send the appropriate prefiller here...
 
-                  signed short *silence;
+                  void *silence;
                   if (lead_time != 0) {
                     int64_t frame_gap = (lead_time * config.output_rate) >> 32;
                     // debug(1,"%d frames needed.",frame_gap);
@@ -1079,7 +1078,7 @@ static abuf_t *buffer_get_frame(rtsp_conn_info *conn) {
                       if (silence == NULL)
                         debug(1, "Failed to allocate %d frame silence buffer.", fs);
                       else {
-                        // debug(1, "Outputting %d frames of silence.", fs);
+                        // debug(1, "No delay function -- outputting %d frames of silence.", fs);
                         memset(silence, 0, conn->output_bytes_per_frame * fs);
                         config.output->play(silence, fs);
                         free(silence);
@@ -1546,7 +1545,7 @@ static void *player_thread_func(void *arg) {
   static char rnstate[256];
   initstate(time(NULL), rnstate, 256);
 
-  signed short *inbuf, *tbuf, *silence;
+  signed short *inbuf, *tbuf;
 
   int32_t *sbuf;
 
@@ -1597,13 +1596,12 @@ static void *player_thread_func(void *arg) {
     die("Failed to allocate memory for the transition buffer.");
   sbuf = 0;
   // initialise this, because soxr stuffing might be chosen later
-  // if (config.packet_stuffing == ST_soxr) { // needed for stuffing
+
   sbuf = malloc(sizeof(int32_t) * 2 * (conn->max_frames_per_packet * conn->output_sample_ratio +
                                        conn->max_frame_size_change));
   if (sbuf == NULL)
     debug(1, "Failed to allocate memory for the sbuf buffer.");
-  // }
-  // We might need an output buffer and a buffer of silence.
+
   // The size of these dependents on the number of frames, the size of each frame and the maximum
   // size change
   outbuf = malloc(
@@ -1611,12 +1609,6 @@ static void *player_thread_func(void *arg) {
       (conn->max_frames_per_packet * conn->output_sample_ratio + conn->max_frame_size_change));
   if (outbuf == NULL)
     die("Failed to allocate memory for an output buffer.");
-  silence = malloc(conn->output_bytes_per_frame * conn->max_frames_per_packet *
-                   conn->output_sample_ratio);
-  if (silence == NULL)
-    die("Failed to allocate memory for a silence buffer.");
-  memset(silence, 0,
-         conn->output_bytes_per_frame * conn->max_frames_per_packet * conn->output_sample_ratio);
   conn->first_packet_timestamp = 0;
   conn->missing_packets = conn->late_packets = conn->too_late_packets = conn->resend_requests = 0;
   conn->flush_rtp_timestamp =
@@ -1695,10 +1687,22 @@ static void *player_thread_func(void *arg) {
         conn->play_number_after_flush++;
         if (inframe->timestamp == 0) {
           debug(3, "Player has supplied a silent frame, (possibly frame %u) for play number %d.",
-                SUCCESSOR(conn->last_seqno_read),play_number);
+                SUCCESSOR(conn->last_seqno_read), play_number);
           conn->last_seqno_read = (SUCCESSOR(conn->last_seqno_read) &
                                    0xffff); // manage the packet out of sequence minder
-          config.output->play(silence, conn->max_frames_per_packet * conn->output_sample_ratio);
+
+          void *silence = malloc(conn->output_bytes_per_frame * conn->max_frames_per_packet *
+                                 conn->output_sample_ratio);
+          if (silence == NULL) {
+            debug(1, "Failed to allocate memory for a silent frame silence buffer.");
+          } else {
+            // the player may change the contents of the buffer, so it has to be zeroed each time;
+            // might as well malloc and freee it locally
+            memset(silence, 0, conn->output_bytes_per_frame * conn->max_frames_per_packet *
+                                   conn->output_sample_ratio);
+            config.output->play(silence, conn->max_frames_per_packet * conn->output_sample_ratio);
+            free(silence);
+          }
         } else if (conn->play_number_after_flush < 10) {
           /*
           int64_t difference = 0;
@@ -1708,7 +1712,18 @@ static void *player_thread_func(void *arg) {
           debug(1, "Play number %d, monotonic timestamp %llx, difference
           %lld.",conn->play_number_after_flush,inframe->timestamp,difference);
           */
-          config.output->play(silence, conn->max_frames_per_packet * conn->output_sample_ratio);
+          void *silence = malloc(conn->output_bytes_per_frame * conn->max_frames_per_packet *
+                                 conn->output_sample_ratio);
+          if (silence == NULL) {
+            debug(1, "Failed to allocate memory for a flush silence buffer.");
+          } else {
+            // the player may change the contents of the buffer, so it has to be zeroed each time;
+            // might as well malloc and freee it locally
+            memset(silence, 0, conn->output_bytes_per_frame * conn->max_frames_per_packet *
+                                   conn->output_sample_ratio);
+            config.output->play(silence, conn->max_frames_per_packet * conn->output_sample_ratio);
+            free(silence);
+          }
         } else if (frames_to_drop) {
           if (frames_to_drop > 3 * config.output_rate)
             warn("Very large number of frames to drop: %" PRId64 ".", frames_to_drop);
@@ -1948,7 +1963,7 @@ static void *player_thread_func(void *arg) {
                   die("Failed to allocate memory for a long_silence buffer of %d frames.",
                       silence_length);
                 memset(long_silence, 0, conn->output_bytes_per_frame * silence_length);
-                config.output->play((short *)long_silence, silence_length);
+                config.output->play(long_silence, silence_length);
                 free(long_silence);
               }
             } else {
@@ -2085,7 +2100,7 @@ static void *player_thread_func(void *arg) {
                 if (play_samples == 0)
                   debug(1, "play_samples==0 skipping it (1).");
                 else
-                  config.output->play((short *)outbuf, play_samples); // remove the (short*)!
+                  config.output->play(outbuf, play_samples);
               }
 
               // check for loss of sync
@@ -2119,7 +2134,7 @@ static void *player_thread_func(void *arg) {
             if (outbuf == NULL)
               debug(1, "NULL outbuf to play -- skipping it.");
             else
-              config.output->play((short *)outbuf, play_samples); // remove the (short*)!
+              config.output->play(outbuf, play_samples); // remove the (short*)!
           }
 
           // mark the frame as finished
@@ -2314,8 +2329,6 @@ static void *player_thread_func(void *arg) {
   }
   if (outbuf)
     free(outbuf);
-  if (silence)
-    free(silence);
   if (tbuf)
     free(tbuf);
   if (sbuf)
diff --git a/rtp.c b/rtp.c
index 18bcc1981c8cafb56478e9f8c5f81443edba03cf..40c8bc8b7e11cc0099969a84ebc1c687007cec61 100644 (file)
--- a/rtp.c
+++ b/rtp.c
@@ -302,13 +302,15 @@ void *rtp_control_receiver(void *arg) {
 
               uint16_t flags = nctohs(&packet[2]);
               int64_t la = sync_rtp_timestamp - rtp_timestamp_less_latency;
-              debug(3, "Latency derived just from the sync packet is %" PRId64 " frames.", la);
+              // debug(3, "Latency derived just from the sync packet is %" PRId64 " frames.", la);
               if ((flags == 7) || ((conn->AirPlayVersion > 0) && (conn->AirPlayVersion <= 353))) {
                 la += config.fixedLatencyOffset;
-                debug(3, "A fixed latency offset of %d frames has been added, giving a latency of "
-                         "%" PRId64
-                         " frames with flags: %d and AirPlay version %d (triggers if 353 or less).",
-                      config.fixedLatencyOffset, la, flags, conn->AirPlayVersion);
+                // debug(3, "A fixed latency offset of %d frames has been added, giving a latency of
+                // "
+                //         "%" PRId64
+                //         " frames with flags: %d and AirPlay version %d (triggers if 353 or
+                //         less).",
+                //      config.fixedLatencyOffset, la, flags, conn->AirPlayVersion);
               }
               if ((conn->maximum_latency) && (conn->maximum_latency < la))
                 la = conn->maximum_latency;