From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Fri, 28 May 2021 18:16:37 +0000 (+0100) Subject: recognise two types of flush -- one with from and until information, the other with... X-Git-Tag: 4.1-dev~110 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e258cca33aed5ed2699d77bce1c0285bfc572dce;p=thirdparty%2Fshairport-sync.git recognise two types of flush -- one with from and until information, the other with just until information. A flush with "with" information is not followed by a new set anchor, whereas a flush without the " with" information is alwasy followed by a new setanchor. --- diff --git a/player.h b/player.h index 35a3db6e..2b5774a7 100644 --- 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 d7ad5472..3e1be921 100644 --- 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 7ae9fc7b..24d8ea14 100644 --- 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) {