From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Sat, 29 May 2021 20:24:33 +0000 (+0100) Subject: Much better flushing. Delayed flushing only works for one delay. Noice artifacts... X-Git-Tag: 4.1-dev~106 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2ea28c06617040dbfc73e218d8b4c78206a65951;p=thirdparty%2Fshairport-sync.git Much better flushing. Delayed flushing only works for one delay. Noice artifacts removed when skipping. Pretty solid. --- diff --git a/player.h b/player.h index 2b5774a7..d3f4e63c 100644 --- a/player.h +++ b/player.h @@ -385,6 +385,8 @@ typedef struct { extern pthread_mutex_t playing_conn_lock; +void reset_buffer(rtsp_conn_info *conn); + void get_audio_buffer_size_and_occupancy(unsigned int *size, unsigned int *occupancy, rtsp_conn_info *conn); diff --git a/rtp.c b/rtp.c index 6e6b3995..b96bb5a4 100644 --- a/rtp.c +++ b/rtp.c @@ -2052,13 +2052,15 @@ void *rtp_buffered_audio_processor(void *arg) { int flush_requested = 0; int streaming_has_started = 0; - int flush_is_delayed; + int play_enabled = 0; uint32_t flush_from_timestamp; int dump_block_info = 0; + double requested_lead_time = 0.100; // normal lead time minimum do { - + int flush_is_delayed = 0; int flush_newly_requested = 0; int flush_newly_complete = 0; + int play_newly_stopped = 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_until_sequence_number; @@ -2105,7 +2107,7 @@ void *rtp_buffered_audio_processor(void *arg) { // blocks_read to ensure seq_no is valid if ((blocks_read != 0) && (seq_no >= flushUntilSeq)) { // we have reached or overshot the flushUntilSeq block - if (flushUntilSeq != seq_no) + // if (flushUntilSeq != seq_no) debug(1,"flushUntilSeq %u reached or overshot at %u.", flushUntilSeq, seq_no); conn->ap2_flush_requested = 0; flush_request_active = 0; @@ -2116,23 +2118,34 @@ void *rtp_buffered_audio_processor(void *arg) { flush_newly_complete = 1; flush_requested = flush_request_active; // flush_requested = conn->ap2_flush_requested; - int play_enabled = conn->ap2_play_enabled; + if ((play_enabled) && (conn->ap2_play_enabled == 0)) + play_newly_stopped = 1; + play_enabled = conn->ap2_play_enabled; debug_mutex_unlock(&conn->flush_mutex, 3); + // do this outside the flush mutex if (flush_newly_complete) { debug(1,"Flush Complete."); + blocks_read = 0; } + + if (play_newly_stopped != 0) + reset_buffer(conn); // stop play ASAP + if (flush_newly_requested) { + reset_buffer(conn); + if (flush_is_delayed == 0) { debug(1,"Immediate Buffered Audio Flush Started."); - player_full_flush(conn); + //player_full_flush(conn); streaming_has_started = 0; pcm_buffer_occupancy = 0; pcm_buffer_read_point = 0; dump_block_info = 0; } else { debug(1,"Delayed Buffered Audio Flush Started."); + streaming_has_started = 0; pcm_buffer_occupancy = 0; pcm_buffer_read_point = 0; } @@ -2145,9 +2158,8 @@ void *rtp_buffered_audio_processor(void *arg) { get_audio_buffer_size_and_occupancy(&player_buffer_size, &player_buffer_occupancy, conn); // debug(1,"player buffer size and occupancy: %u and %u", player_buffer_size, // player_buffer_occupancy); - double requested_lead_time = 0.10; // if (player_buffer_occupancy > - ((requested_lead_time + 0.20) * 44100.0 / 352)) { // must be greater than the lead time. + ((requested_lead_time + 0.10) * 44100.0 / 352)) { // must be greater than the lead time. // if there is enough stuff in the player's buffer, sleep for a while and try again // debug(1,"sleep for 20 ms"); usleep(20000); // wait for a while @@ -2170,22 +2182,23 @@ void *rtp_buffered_audio_processor(void *arg) { 0) { int64_t lead_time = buffer_should_be_time - get_absolute_time_in_ns(); // debug(1,"lead time in buffered_audio is %f milliseconds.", lead_time * 0.000001); + if (blocks_read > 1) { if ((lead_time >= (int64_t)(requested_lead_time * 1000000000)) || - (streaming_has_started == 1)) { + (streaming_has_started != 0)) { if (streaming_has_started == 0) debug(1, "Connection %d: buffered audio starting frame: %u, lead time: %f seconds.", conn->connection_number, pcm_buffer_read_point_rtptime, 0.000000001 * lead_time); - else { - if (expected_rtptime != pcm_buffer_read_point_rtptime) - debug(1,"actual rtptime is %u, expected rtptime is %u.", pcm_buffer_read_point_rtptime, expected_rtptime); - } - streaming_has_started = 1; + //else { + //if (expected_rtptime != pcm_buffer_read_point_rtptime) + // debug(1,"actual rtptime is %u, expected rtptime is %u.", pcm_buffer_read_point_rtptime, expected_rtptime); + //} expected_rtptime = pcm_buffer_read_point_rtptime + 352; - player_put_packet(0, 0, pcm_buffer_read_point_rtptime, - pcm_buffer + pcm_buffer_read_point, 352, conn); + pcm_buffer + pcm_buffer_read_point, 352, conn); + streaming_has_started++; usleep(2000); } + } pcm_buffer_read_point_rtptime += 352; pcm_buffer_read_point += 352 * 4; @@ -2299,10 +2312,17 @@ void *rtp_buffered_audio_processor(void *arg) { // debug(1,"seq_no %u, timestamp %u", seq_no, timestamp); if ((flush_requested) && (seq_no >= flushUntilSeq)) { + uint64_t should_be_time; + if ((frame_to_local_time(timestamp, &should_be_time, conn) == + 0) && (play_enabled)) { + // play enabled will be off when this is a full flush and the anchor information is not valid + int64_t lead_time = should_be_time - get_absolute_time_in_ns(); + debug(1,"flush completed to seq: %u with rtptime: %u, lead time: 0x%" PRIx64 " nanoseconds, i.e. %f sec.", seq_no, timestamp, lead_time, lead_time * 0.000000001); + } else { debug(1,"flush completed to seq: %u with rtptime: %u.", seq_no, timestamp); + } } - if (((flush_requested != 0) && (seq_no == flushUntilSeq)) || ((flush_requested == 0) && (new_buffer_needed))) { diff --git a/rtsp.c b/rtsp.c index 00bd3822..3ef47ba1 100644 --- a/rtsp.c +++ b/rtsp.c @@ -1350,6 +1350,7 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message // 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; @@ -1444,7 +1445,7 @@ void handle_setrateanchori(rtsp_conn_info *conn, rtsp_message *req, rtsp_message debug(1, "Connection %d: No timing peer list!", conn->connection_number); } } else { - player_full_flush(conn); + // player_full_flush(conn); // ptp_send_control_message_string("T"); // ensure an obsolete clock isn't picked up later. } }