From: Mike Brady <4265913+mikebrady@users.noreply.github.com> Date: Mon, 6 Dec 2021 18:13:20 +0000 (+0000) Subject: Skip some invalid AAC packets, don't decode outdated frames, wait for timing informat... X-Git-Tag: 4.1-rc1~24^2~366^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0b21373c0e5ba8e565bf420ed2ad8eb79f23d491;p=thirdparty%2Fshairport-sync.git Skip some invalid AAC packets, don't decode outdated frames, wait for timing information to be valid. --- diff --git a/rtp.c b/rtp.c index 5b79ff4b..d3bf06c4 100644 --- a/rtp.c +++ b/rtp.c @@ -1310,7 +1310,7 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, // if the master clock and the anchor clock are the same // wait at least this time before using the new master clock // note that mastershipo may be backdated - if (duration_of_mastership < 1500000000) { + if (duration_of_mastership < 100000000) { debug(3, "master not old enough yet: %f ms", 0.000001 * duration_of_mastership); response = clock_not_ready; } else if ((duration_of_mastership > 5000000000) || @@ -1400,6 +1400,7 @@ int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, } } } else { + // debug(1, "anchor_remote_info_is_valid not valid"); response = clock_no_anchor_info; // no anchor information } } @@ -2253,7 +2254,14 @@ void *rtp_buffered_audio_processor(void *arg) { int streaming_has_started = 0; int play_enabled = 0; uint32_t flush_from_timestamp; - double requested_lead_time = 0.3; // normal lead time minimum + double requested_lead_time = 0.0; // normal lead time minimum -- maybe it should be about 0.1 + + // wait until our timing information is valid + + // debug(1,"rtp_buffered_audio_processor ready."); + while (have_ptp_timing_information(conn) == 0) + usleep(1000); + reset_buffer(conn); // in case there is any garbage in the player // int not_first_time_out = 0; @@ -2519,28 +2527,42 @@ void *rtp_buffered_audio_processor(void *arg) { // to decipher it first // debug(1,"seq_no %u, timestamp %u", seq_no, timestamp); + uint64_t local_should_be_time = 0; + int have_time_information = frame_to_local_time(timestamp, &local_should_be_time, conn); + int64_t local_lead_time = 0; + int64_t requested_lead_time_ns = (int64_t)(requested_lead_time * 1000000000); + requested_lead_time_ns = (int64_t)(-300000000); + int outdated = 0; + if (have_time_information == 0) { + local_lead_time = local_should_be_time - get_absolute_time_in_ns(); + outdated = (local_lead_time < requested_lead_time_ns); + // if (outdated != 0) + // debug(1,"Frame is outdated %d if lead_time %" PRId64 " is less than requested lead time %" PRId64 " ns.", outdated, local_lead_time, requested_lead_time_ns); + } else { + debug(1,"Timing information not valid"); + // outdated = 1; + } + + if ((flush_requested) && (seq_no >= flushUntilSeq)) { - uint64_t should_be_time; - if ((frame_to_local_time(timestamp, &should_be_time, conn) == 0) && (play_enabled)) { + if ((have_time_information == 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, + debug(2, "flush completed to seq: %u, flushUntilTS; %u with rtptime: %u, lead time: " "0x%" PRIx64 " nanoseconds, i.e. %f sec.", - seq_no, flushUntilTS, timestamp, lead_time, lead_time * 0.000000001); + seq_no, flushUntilTS, timestamp, local_lead_time, local_lead_time * 0.000000001); } else { debug(2, "flush completed to seq: %u with rtptime: %u.", seq_no, timestamp); } } - - if (((flush_requested != 0) && (seq_no == flushUntilSeq)) || - ((flush_requested == 0) && (new_buffer_needed))) { - + // if we are here because of a flush request, it must be the case that // flushing the pcm buffer wasn't enough, as the request would have been turned off by now // so we better indicate that the pcm buffer is empty and its contents invalid - if (flush_requested) { + + // also, if the incomgin frame is outdated, set pcm_buffer_occupancy to 0; + if ((flush_requested) || (outdated)){ pcm_buffer_occupancy = 0; } @@ -2556,6 +2578,11 @@ void *rtp_buffered_audio_processor(void *arg) { //} } + + if (((flush_requested != 0) && (seq_no == flushUntilSeq)) || + ((flush_requested == 0) && (new_buffer_needed))) { + + unsigned char nonce[12]; memset(nonce, 0, sizeof(nonce)); memcpy(nonce + 4, packet + nread - 8, @@ -2596,6 +2623,7 @@ void *rtp_buffered_audio_processor(void *arg) { data_remaining = aac_packet_length; int ret = 0; // there can be more than one av packet (? terminology) in a block + int frame_within_block = 0; while (data_remaining > 0) { if (decoded_frame == NULL) { decoded_frame = av_frame_alloc(); @@ -2608,14 +2636,20 @@ void *rtp_buffered_audio_processor(void *arg) { if (ret < 0) { debug(1, "error while parsing deciphered audio packet."); } else { + frame_within_block++; data_to_process += ret; data_remaining -= ret; // debug(1, "frame found"); // now pass each packet to be decoded if (pkt->size) { + //if (0) { + if (pkt->size <= 7) { // no idea about this... + debug(1,"malformed AAC packet skipped."); + } else { ret = avcodec_send_packet(codec_context, pkt); + if (ret < 0) { - debug(1, "error sending packet to decoder"); + debug(1, "error sending frame %d of size %d to decoder, blocks_read: %u, blocks_read_since_flush: %u.", frame_within_block, pkt->size, blocks_read, blocks_read_since_flush); } else { while (ret >= 0) { ret = avcodec_receive_frame(codec_context, decoded_frame); @@ -2672,6 +2706,7 @@ void *rtp_buffered_audio_processor(void *arg) { } } } + } } if (decoded_frame == NULL) debug(1, "decoded_frame is NULL");