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 <ilnik@webrtc.org> Commit-Queue: Evan Shrubsole <eshr@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37237}
This commit is contained in:
parent
6e4d7e606c
commit
a1d3ada96b
@ -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",
|
||||
]
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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<void()>;
|
||||
using TimeoutCallback = std::function<void(TimeDelta wait)>;
|
||||
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_;
|
||||
};
|
||||
|
||||
@ -11,9 +11,9 @@
|
||||
#include "video/video_receive_stream_timeout_tracker.h"
|
||||
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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 <class Task>
|
||||
void OnQueue(Task&& t) {
|
||||
task_queue_.PostTask(std::forward<Task>(t));
|
||||
time_controller_.AdvanceTime(TimeDelta::Zero());
|
||||
}
|
||||
|
||||
GlobalSimulatedTimeController time_controller_;
|
||||
rtc::TaskQueue task_queue_;
|
||||
VideoReceiveStreamTimeoutTracker timeout_tracker_;
|
||||
int timeouts_ = 0;
|
||||
std::vector<TimeDelta> 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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user