diff --git a/third_party/libwebrtc/README.moz-ff-commit b/third_party/libwebrtc/README.moz-ff-commit index 687f3f4f921be..0020cc4389648 100644 --- a/third_party/libwebrtc/README.moz-ff-commit +++ b/third_party/libwebrtc/README.moz-ff-commit @@ -18753,3 +18753,6 @@ ffceb9b4ad # MOZ_LIBWEBRTC_SRC=/Users/danielbaker/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh # base of lastest vendoring 1cd97e2602 +# MOZ_LIBWEBRTC_SRC=/Users/danielbaker/moz-libwebrtc MOZ_LIBWEBRTC_BRANCH=mozpatches bash dom/media/webrtc/third_party_build/fast-forward-libwebrtc.sh +# base of lastest vendoring +93081d594f diff --git a/third_party/libwebrtc/README.mozilla b/third_party/libwebrtc/README.mozilla index 9f9a716c4381c..82da4ff33a67f 100644 --- a/third_party/libwebrtc/README.mozilla +++ b/third_party/libwebrtc/README.mozilla @@ -12524,3 +12524,5 @@ libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 202 libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 2023-02-06T15:22:04.298603. # ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/moz-libwebrtc --commit mozpatches libwebrtc libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 2023-02-06T15:23:21.330562. +# ./mach python dom/media/webrtc/third_party_build/vendor-libwebrtc.py --from-local /Users/danielbaker/moz-libwebrtc --commit mozpatches libwebrtc +libwebrtc updated from /Users/danielbaker/moz-libwebrtc commit mozpatches on 2023-02-06T15:32:35.264724. diff --git a/third_party/libwebrtc/video/task_queue_frame_decode_scheduler.cc b/third_party/libwebrtc/video/task_queue_frame_decode_scheduler.cc index c53a53073e5fb..cd109c2932ae9 100644 --- a/third_party/libwebrtc/video/task_queue_frame_decode_scheduler.cc +++ b/third_party/libwebrtc/video/task_queue_frame_decode_scheduler.cc @@ -49,8 +49,8 @@ void TaskQueueFrameDecodeScheduler::ScheduleFrame( SafeTask(task_safety_.flag(), [this, rtp, schedule, cb = std::move(cb)]() mutable { RTC_DCHECK_RUN_ON(bookkeeping_queue_); - // If the next frame rtp has changed since this task was - // this scheduled release should be skipped. + // If the next frame rtp has changed since this task was + // this scheduled release should be skipped. if (scheduled_rtp_ != rtp) return; scheduled_rtp_ = absl::nullopt; diff --git a/third_party/libwebrtc/video/video_stream_buffer_controller.cc b/third_party/libwebrtc/video/video_stream_buffer_controller.cc index 04560de4b44c4..c022dd6165889 100644 --- a/third_party/libwebrtc/video/video_stream_buffer_controller.cc +++ b/third_party/libwebrtc/video/video_stream_buffer_controller.cc @@ -199,7 +199,8 @@ void VideoStreamBufferController::OnFrameReady( absl::InlinedVector, 4> frames, Timestamp render_time) { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); - RTC_DCHECK(!frames.empty()); + RTC_CHECK(!frames.empty()) + << "Callers must ensure there is at least one frame to decode."; timeout_tracker_.OnEncodedFrameReleased(); @@ -284,11 +285,29 @@ void VideoStreamBufferController::OnTimeout(TimeDelta delay) { void VideoStreamBufferController::FrameReadyForDecode(uint32_t rtp_timestamp, Timestamp render_time) { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); - auto frames = buffer_->ExtractNextDecodableTemporalUnit(); - RTC_DCHECK(frames[0]->Timestamp() == rtp_timestamp) + // Check that the frame to decode is still valid before passing the frame for + // decoding. + auto decodable_tu_info = buffer_->DecodableTemporalUnitsInfo(); + if (!decodable_tu_info) { + RTC_LOG(LS_ERROR) + << "The frame buffer became undecodable during the wait " + "to decode frame with rtp-timestamp " + << rtp_timestamp + << ". Cancelling the decode of this frame, decoding " + "will resume when the frame buffers become decodable again."; + return; + } + RTC_DCHECK_EQ(rtp_timestamp, decodable_tu_info->next_rtp_timestamp) << "Frame buffer's next decodable frame was not the one sent for " - "extraction rtp=" - << rtp_timestamp << " extracted rtp=" << frames[0]->Timestamp(); + "extraction."; + auto frames = buffer_->ExtractNextDecodableTemporalUnit(); + if (frames.empty()) { + RTC_LOG(LS_ERROR) + << "The frame buffer should never return an empty temporal until list " + "when there is a decodable temporal unit."; + RTC_DCHECK_NOTREACHED(); + return; + } OnFrameReady(std::move(frames), render_time); } diff --git a/third_party/libwebrtc/video/video_stream_buffer_controller_unittest.cc b/third_party/libwebrtc/video/video_stream_buffer_controller_unittest.cc index ea9eaede2eb57..3e6c352fb1b67 100644 --- a/third_party/libwebrtc/video/video_stream_buffer_controller_unittest.cc +++ b/third_party/libwebrtc/video/video_stream_buffer_controller_unittest.cc @@ -754,6 +754,50 @@ TEST_P(VideoStreamBufferControllerTest, NextFrameWithOldTimestamp) { EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2))); } +TEST_P(VideoStreamBufferControllerTest, + FrameNotSetForDecodedIfFrameBufferBecomesNonDecodable) { + // This can happen if the frame buffer receives non-standard input. This test + // will simply clear the frame buffer to replicate this. + StartNextDecodeForceKeyframe(); + // Initial keyframe. + buffer_->InsertFrame(WithReceiveTimeFromRtpTimestamp( + test::FakeFrameBuilder().Id(0).Time(0).SpatialLayer(1).AsLast().Build())); + EXPECT_THAT(WaitForFrameOrTimeout(TimeDelta::Zero()), Frame(test::WithId(0))); + + // Insert a frame that will become non-decodable. + buffer_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder() + .Id(11) + .Time(kFps30Rtp) + .Refs({0}) + .SpatialLayer(1) + .AsLast() + .Build())); + StartNextDecode(); + // Second layer inserted after last layer for the same frame out-of-order. + // This second frame requires some older frame to be decoded and so now the + // super-frame is no longer decodable despite already being scheduled. + buffer_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder() + .Id(10) + .Time(kFps30Rtp) + .SpatialLayer(0) + .Refs({2}) + .Build())); + EXPECT_THAT(WaitForFrameOrTimeout(kMaxWaitForFrame), TimedOut()); + + // Ensure that this frame can be decoded later. + StartNextDecode(); + buffer_->InsertFrame(WithReceiveTimeFromRtpTimestamp(test::FakeFrameBuilder() + .Id(2) + .Time(kFps30Rtp / 2) + .SpatialLayer(0) + .Refs({0}) + .AsLast() + .Build())); + EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(2))); + StartNextDecode(); + EXPECT_THAT(WaitForFrameOrTimeout(kFps30Delay), Frame(test::WithId(10))); +} + INSTANTIATE_TEST_SUITE_P(VideoStreamBufferController, VideoStreamBufferControllerTest, ::testing::Combine(::testing::Bool(),