From: Mike Brady Date: Mon, 7 May 2018 21:00:01 +0000 (+0100) Subject: Stop erroneously assuming that the buffer passed to the player is not changed --... X-Git-Tag: 3.2RC7~3^2~1^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6d66b2ed338741ee482ec5524ad02a81f8192433;p=thirdparty%2Fshairport-sync.git Stop erroneously assuming that the buffer passed to the player is not changed -- sometimes it is, it seems. Tidy up some typing. --- diff --git a/audio.h b/audio.h index e0defc55..dc7eb873 100644 --- 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 diff --git a/audio_alsa.c b/audio_alsa.c index 3310eeaa..d6bf73dd 100644 --- a/audio_alsa.c +++ b/audio_alsa.c @@ -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); diff --git a/player.c b/player.c index d3dcb0db..70d6f7a9 100644 --- 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 18bcc198..40c8bc8b 100644 --- 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;