From a1d3ada96b3a8e14f338d149554ddea2cc2f7565 Mon Sep 17 00:00:00 2001 From: Evan Shrubsole Date: Thu, 16 Jun 2022 11:52:09 +0000 Subject: [PATCH] Video stream timeout tracker returns the total delay This will later be used when merging FrameBuffer3Proxy into VideoReceiveStream2. Bug: webrtc:14003 Change-Id: Ieb97767c40f494510873abe775fc339125036dc0 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/265923 Reviewed-by: Ilya Nikolaevskiy Commit-Queue: Evan Shrubsole Cr-Commit-Position: refs/heads/main@{#37237} --- video/BUILD.gn | 1 + video/frame_buffer_proxy.cc | 4 +- video/video_receive_stream_timeout_tracker.cc | 18 +++--- video/video_receive_stream_timeout_tracker.h | 6 +- ...receive_stream_timeout_tracker_unittest.cc | 61 +++++++++---------- 5 files changed, 46 insertions(+), 44 deletions(-) diff --git a/video/BUILD.gn b/video/BUILD.gn index 737e02853b..381cad0b76 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -416,6 +416,7 @@ rtc_library("video_receive_stream_timeout_tracker") { deps = [ "../api/task_queue", "../api/units:time_delta", + "../api/units:timestamp", "../rtc_base/task_utils:repeating_task", "../system_wrappers", ] diff --git a/video/frame_buffer_proxy.cc b/video/frame_buffer_proxy.cc index 3657fba36c..f69d9da124 100644 --- a/video/frame_buffer_proxy.cc +++ b/video/frame_buffer_proxy.cc @@ -369,14 +369,14 @@ class FrameBuffer3Proxy : public FrameBufferProxy { })); } - void OnTimeout() { + void OnTimeout(TimeDelta delay) { RTC_DCHECK_RUN_ON(&worker_sequence_checker_); // If the stream is paused then ignore the timeout. if (!decoder_ready_for_new_frame_) { timeout_tracker_.Stop(); return; } - receiver_->OnDecodableFrameTimeout(MaxWait()); + receiver_->OnDecodableFrameTimeout(delay); // Stop sending timeouts until receive starts waiting for a new frame. timeout_tracker_.Stop(); decoder_ready_for_new_frame_ = false; diff --git a/video/video_receive_stream_timeout_tracker.cc b/video/video_receive_stream_timeout_tracker.cc index 79e0e2cfc8..c0c8087b24 100644 --- a/video/video_receive_stream_timeout_tracker.cc +++ b/video/video_receive_stream_timeout_tracker.cc @@ -22,7 +22,7 @@ VideoReceiveStreamTimeoutTracker::VideoReceiveStreamTimeoutTracker( : clock_(clock), bookkeeping_queue_(bookkeeping_queue), timeouts_(timeouts), - callback_(std::move(callback)) {} + timeout_cb_(std::move(callback)) {} VideoReceiveStreamTimeoutTracker::~VideoReceiveStreamTimeoutTracker() { RTC_DCHECK(!timeout_task_.Running()); @@ -36,12 +36,11 @@ void VideoReceiveStreamTimeoutTracker::Start(bool waiting_for_keyframe) { RTC_DCHECK(!timeout_task_.Running()); waiting_for_keyframe_ = waiting_for_keyframe; TimeDelta timeout_delay = TimeoutForNextFrame(); - timeout_ = clock_->CurrentTime() + timeout_delay; - timeout_task_ = RepeatingTaskHandle::DelayedStart( - bookkeeping_queue_, timeout_delay, [this] { - RTC_DCHECK_RUN_ON(bookkeeping_queue_); - return HandleTimeoutTask(); - }); + last_frame_ = clock_->CurrentTime(); + timeout_ = last_frame_ + timeout_delay; + timeout_task_ = + RepeatingTaskHandle::DelayedStart(bookkeeping_queue_, timeout_delay, + [this] { return HandleTimeoutTask(); }); } void VideoReceiveStreamTimeoutTracker::Stop() { @@ -60,7 +59,8 @@ void VideoReceiveStreamTimeoutTracker::SetWaitingForKeyframe() { void VideoReceiveStreamTimeoutTracker::OnEncodedFrameReleased() { // If we were waiting for a keyframe, then it has just been released. waiting_for_keyframe_ = false; - timeout_ = clock_->CurrentTime() + TimeoutForNextFrame(); + last_frame_ = clock_->CurrentTime(); + timeout_ = last_frame_ + TimeoutForNextFrame(); } TimeDelta VideoReceiveStreamTimeoutTracker::HandleTimeoutTask() { @@ -70,7 +70,7 @@ TimeDelta VideoReceiveStreamTimeoutTracker::HandleTimeoutTask() { if (now >= timeout_) { TimeDelta timeout_delay = TimeoutForNextFrame(); timeout_ = now + timeout_delay; - callback_(); + timeout_cb_(now - last_frame_); return timeout_delay; } // Otherwise, `timeout_` changed since we scheduled a timeout. Reschedule diff --git a/video/video_receive_stream_timeout_tracker.h b/video/video_receive_stream_timeout_tracker.h index 6993e13ad4..d555ac8cd6 100644 --- a/video/video_receive_stream_timeout_tracker.h +++ b/video/video_receive_stream_timeout_tracker.h @@ -15,6 +15,7 @@ #include "api/task_queue/task_queue_base.h" #include "api/units/time_delta.h" +#include "api/units/timestamp.h" #include "rtc_base/task_utils/repeating_task.h" #include "system_wrappers/include/clock.h" @@ -27,7 +28,7 @@ class VideoReceiveStreamTimeoutTracker { TimeDelta max_wait_for_frame; }; - using TimeoutCallback = std::function; + using TimeoutCallback = std::function; VideoReceiveStreamTimeoutTracker(Clock* clock, TaskQueueBase* const bookkeeping_queue, const Timeouts& timeouts, @@ -54,9 +55,10 @@ class VideoReceiveStreamTimeoutTracker { Clock* const clock_; TaskQueueBase* const bookkeeping_queue_; const Timeouts timeouts_; - const TimeoutCallback callback_; + const TimeoutCallback timeout_cb_; RepeatingTaskHandle timeout_task_; + Timestamp last_frame_ = Timestamp::MinusInfinity(); Timestamp timeout_ = Timestamp::MinusInfinity(); bool waiting_for_keyframe_; }; diff --git a/video/video_receive_stream_timeout_tracker_unittest.cc b/video/video_receive_stream_timeout_tracker_unittest.cc index 4aec4d332b..ea3bf896b8 100644 --- a/video/video_receive_stream_timeout_tracker_unittest.cc +++ b/video/video_receive_stream_timeout_tracker_unittest.cc @@ -11,9 +11,9 @@ #include "video/video_receive_stream_timeout_tracker.h" #include +#include #include "api/task_queue/task_queue_base.h" -#include "rtc_base/task_queue.h" #include "test/gmock.h" #include "test/gtest.h" #include "test/time_controller/simulated_time_controller.h" @@ -32,64 +32,63 @@ class VideoReceiveStreamTimeoutTrackerTest : public ::testing::Test { public: VideoReceiveStreamTimeoutTrackerTest() : time_controller_(Timestamp::Millis(2000)), - task_queue_(time_controller_.GetTaskQueueFactory()->CreateTaskQueue( - "scheduler", - TaskQueueFactory::Priority::NORMAL)), timeout_tracker_(time_controller_.GetClock(), - task_queue_.Get(), + time_controller_.GetMainThread(), config, - [this] { OnTimeout(); }) {} + [this](TimeDelta delay) { OnTimeout(delay); }) {} protected: - template - void OnQueue(Task&& t) { - task_queue_.PostTask(std::forward(t)); - time_controller_.AdvanceTime(TimeDelta::Zero()); - } - GlobalSimulatedTimeController time_controller_; - rtc::TaskQueue task_queue_; VideoReceiveStreamTimeoutTracker timeout_tracker_; - int timeouts_ = 0; + std::vector timeouts_; private: - void OnTimeout() { ++timeouts_; } + void OnTimeout(TimeDelta delay) { timeouts_.push_back(delay); } }; TEST_F(VideoReceiveStreamTimeoutTrackerTest, TimeoutAfterInitialPeriod) { - OnQueue([&] { timeout_tracker_.Start(true); }); + timeout_tracker_.Start(true); time_controller_.AdvanceTime(kMaxWaitForKeyframe); - EXPECT_EQ(1, timeouts_); - OnQueue([&] { timeout_tracker_.Stop(); }); + EXPECT_THAT(timeouts_, testing::ElementsAre(kMaxWaitForKeyframe)); + timeout_tracker_.Stop(); } TEST_F(VideoReceiveStreamTimeoutTrackerTest, NoTimeoutAfterStop) { - OnQueue([&] { timeout_tracker_.Start(true); }); + timeout_tracker_.Start(true); time_controller_.AdvanceTime(kMaxWaitForKeyframe / 2); - OnQueue([&] { timeout_tracker_.Stop(); }); + timeout_tracker_.Stop(); time_controller_.AdvanceTime(kMaxWaitForKeyframe); - EXPECT_EQ(0, timeouts_); + EXPECT_THAT(timeouts_, testing::IsEmpty()); } TEST_F(VideoReceiveStreamTimeoutTrackerTest, TimeoutForDeltaFrame) { - OnQueue([&] { timeout_tracker_.Start(true); }); + timeout_tracker_.Start(true); time_controller_.AdvanceTime(TimeDelta::Millis(5)); - OnQueue([&] { timeout_tracker_.OnEncodedFrameReleased(); }); + timeout_tracker_.OnEncodedFrameReleased(); time_controller_.AdvanceTime(kMaxWaitForFrame); - EXPECT_EQ(1, timeouts_); - - OnQueue([&] { timeout_tracker_.Stop(); }); + EXPECT_THAT(timeouts_, testing::ElementsAre(kMaxWaitForFrame)); + timeout_tracker_.Stop(); } TEST_F(VideoReceiveStreamTimeoutTrackerTest, TimeoutForKeyframeWhenForced) { - OnQueue([&] { timeout_tracker_.Start(true); }); + timeout_tracker_.Start(true); time_controller_.AdvanceTime(TimeDelta::Millis(5)); - OnQueue([&] { timeout_tracker_.OnEncodedFrameReleased(); }); - OnQueue([&] { timeout_tracker_.SetWaitingForKeyframe(); }); + timeout_tracker_.OnEncodedFrameReleased(); + timeout_tracker_.SetWaitingForKeyframe(); time_controller_.AdvanceTime(kMaxWaitForKeyframe); - EXPECT_EQ(1, timeouts_); + EXPECT_THAT(timeouts_, testing::ElementsAre(kMaxWaitForKeyframe)); + timeout_tracker_.Stop(); +} - OnQueue([&] { timeout_tracker_.Stop(); }); +TEST_F(VideoReceiveStreamTimeoutTrackerTest, TotalTimeoutUsedInCallback) { + timeout_tracker_.Start(true); + time_controller_.AdvanceTime(kMaxWaitForKeyframe * 2); + timeout_tracker_.OnEncodedFrameReleased(); + time_controller_.AdvanceTime(kMaxWaitForFrame * 2); + EXPECT_THAT(timeouts_, + testing::ElementsAre(kMaxWaitForKeyframe, kMaxWaitForKeyframe * 2, + kMaxWaitForFrame, kMaxWaitForFrame * 2)); + timeout_tracker_.Stop(); } } // namespace webrtc