Prefer use of time controller main thread to run loop

Bug: None
Change-Id: I1f3802ad720b585a44e8e4cba1aad0c48a1473a5
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/266499
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#37791}
This commit is contained in:
Evan Shrubsole
2022-08-16 08:08:53 +00:00
committed by WebRTC LUCI CQ
parent c3cfa5f123
commit 7cbd8dee7b
2 changed files with 45 additions and 46 deletions

View File

@ -19,7 +19,6 @@
#include "api/units/time_delta.h"
#include "test/gmock.h"
#include "test/gtest.h"
#include "test/run_loop.h"
#include "test/time_controller/simulated_time_controller.h"
#include "video/frame_decode_scheduler.h"
#include "video/frame_decode_timing.h"
@ -37,12 +36,13 @@ class DecodeSynchronizerTest : public ::testing::Test {
: time_controller_(Timestamp::Millis(1337)),
clock_(time_controller_.GetClock()),
metronome_(kTickPeriod),
decode_synchronizer_(clock_, &metronome_, run_loop_.task_queue()) {}
decode_synchronizer_(clock_,
&metronome_,
time_controller_.GetMainThread()) {}
protected:
GlobalSimulatedTimeController time_controller_;
Clock* clock_;
test::RunLoop run_loop_;
test::ForcedTickMetronome metronome_;
DecodeSynchronizer decode_synchronizer_;
};
@ -77,7 +77,7 @@ TEST_F(DecodeSynchronizerTest, AllFramesReadyBeforeNextTickDecoded) {
Call(Eq(frame_rtp), Eq(frame_sched.render_time)));
}
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// Cleanup
scheduler1->Stop();
@ -98,7 +98,7 @@ TEST_F(DecodeSynchronizerTest, FramesNotDecodedIfDecodeTimeIsInNextInterval) {
mock_callback.AsStdFunction());
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// No decodes should have happened in this tick.
::testing::Mock::VerifyAndClearExpectations(&mock_callback);
@ -106,7 +106,7 @@ TEST_F(DecodeSynchronizerTest, FramesNotDecodedIfDecodeTimeIsInNextInterval) {
EXPECT_CALL(mock_callback, Call(Eq(frame_rtp), Eq(frame_sched.render_time)));
time_controller_.AdvanceTime(kTickPeriod);
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// Cleanup
scheduler->Stop();
@ -124,13 +124,13 @@ TEST_F(DecodeSynchronizerTest, FrameDecodedOnce) {
mock_callback.AsStdFunction());
EXPECT_CALL(mock_callback, Call(_, _)).Times(1);
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
::testing::Mock::VerifyAndClearExpectations(&mock_callback);
// Trigger tick again. No frame should be decoded now.
time_controller_.AdvanceTime(kTickPeriod);
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// Cleanup
scheduler->Stop();
@ -151,7 +151,7 @@ TEST_F(DecodeSynchronizerTest, FrameWithDecodeTimeInPastDecodedImmediately) {
::testing::Mock::VerifyAndClearExpectations(&mock_callback);
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// Cleanup
scheduler->Stop();
@ -176,7 +176,7 @@ TEST_F(DecodeSynchronizerTest,
time_controller_.AdvanceTime(kTickPeriod);
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// A frame that would be behind by exactly kMaxAllowedFrameDelay after next
// tick should decode at the next tick.
@ -191,7 +191,7 @@ TEST_F(DecodeSynchronizerTest,
EXPECT_CALL(mock_callback, Call(Eq(180000u), _)).Times(1);
time_controller_.AdvanceTime(kTickPeriod);
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
// Cleanup
scheduler->Stop();
@ -212,7 +212,7 @@ TEST_F(DecodeSynchronizerTest, FramesNotReleasedAfterStop) {
// No callback should occur on this tick since Stop() was called before.
metronome_.Tick();
run_loop_.Flush();
time_controller_.AdvanceTime(TimeDelta::Zero());
}
TEST_F(DecodeSynchronizerTest, MetronomeNotListenedWhenNoStreamsAreActive) {

View File

@ -12,9 +12,11 @@
#include <algorithm>
#include <cstddef>
#include <deque>
#include <limits>
#include <memory>
#include <ostream>
#include <queue>
#include <tuple>
#include <utility>
#include <vector>
@ -49,7 +51,6 @@
#include "test/gtest.h"
#include "test/mock_transport.h"
#include "test/rtcp_packet_parser.h"
#include "test/run_loop.h"
#include "test/time_controller/simulated_time_controller.h"
#include "test/video_decoder_proxy_factory.h"
#include "video/call_stats2.h"
@ -118,37 +119,33 @@ constexpr uint32_t kFirstRtpTimestamp = 90000;
class FakeVideoRenderer : public rtc::VideoSinkInterface<VideoFrame> {
public:
explicit FakeVideoRenderer(TimeController* time_controller,
test::RunLoop* loop)
: time_controller_(time_controller), loop_(loop) {}
explicit FakeVideoRenderer(TimeController* time_controller)
: time_controller_(time_controller) {}
~FakeVideoRenderer() override = default;
void OnFrame(const VideoFrame& frame) override {
RTC_LOG(LS_VERBOSE) << "Received frame with timestamp="
<< frame.timestamp();
if (last_frame_) {
RTC_LOG(LS_VERBOSE) << "Already had frame queue with timestamp="
<< last_frame_->timestamp();
if (!last_frame_.empty()) {
RTC_LOG(LS_INFO) << "Already had frame queue with timestamp="
<< last_frame_.back().timestamp();
}
last_frame_ = frame;
last_frame_.push_back(frame);
}
// If `advance_time`, then the clock will always advance by `timeout`.
absl::optional<VideoFrame> WaitForFrame(TimeDelta timeout,
bool advance_time = false) {
auto start = time_controller_->GetClock()->CurrentTime();
if (!last_frame_) {
loop_->Flush();
if (last_frame_.empty()) {
time_controller_->AdvanceTime(TimeDelta::Zero());
time_controller_->Wait(
[this] {
loop_->Flush();
return last_frame_.has_value();
},
timeout);
time_controller_->Wait([this] { return !last_frame_.empty(); }, timeout);
}
absl::optional<VideoFrame> ret;
if (!last_frame_.empty()) {
ret = last_frame_.front();
last_frame_.pop_front();
}
absl::optional<VideoFrame> ret = std::move(last_frame_);
last_frame_.reset();
if (advance_time) {
time_controller_->AdvanceTime(
timeout - (time_controller_->GetClock()->CurrentTime() - start));
@ -157,9 +154,8 @@ class FakeVideoRenderer : public rtc::VideoSinkInterface<VideoFrame> {
}
private:
absl::optional<VideoFrame> last_frame_;
std::deque<VideoFrame> last_frame_;
TimeController* const time_controller_;
test::RunLoop* const loop_;
};
MATCHER_P2(Resolution, w, h, "") {
@ -167,7 +163,12 @@ MATCHER_P2(Resolution, w, h, "") {
}
MATCHER_P(RtpTimestamp, timestamp, "") {
return arg.timestamp() == timestamp;
if (arg.timestamp() != timestamp) {
*result_listener->stream()
<< "rtp timestamp was " << arg.timestamp() << " != " << timestamp;
return false;
}
return true;
}
// Rtp timestamp for in order frame at 30fps.
@ -194,11 +195,13 @@ class VideoReceiveStream2Test : public ::testing::TestWithParam<bool> {
: time_controller_(kStartTime),
clock_(time_controller_.GetClock()),
config_(&mock_transport_, &mock_h264_decoder_factory_),
call_stats_(clock_, loop_.task_queue()),
fake_renderer_(&time_controller_, &loop_),
call_stats_(clock_, time_controller_.GetMainThread()),
fake_renderer_(&time_controller_),
fake_metronome_(time_controller_.GetTaskQueueFactory(),
TimeDelta::Millis(16)),
decode_sync_(clock_, &fake_metronome_, loop_.task_queue()),
decode_sync_(clock_,
&fake_metronome_,
time_controller_.GetMainThread()),
h264_decoder_factory_(&mock_decoder_) {
if (UseMetronome()) {
fake_call_.SetFieldTrial("WebRTC-FrameBuffer3/arm:SyncDecoding/");
@ -226,6 +229,7 @@ class VideoReceiveStream2Test : public ::testing::TestWithParam<bool> {
.WillByDefault(
Invoke(&rtcp_packet_parser_, &test::RtcpPacketParser::Parse));
}
~VideoReceiveStream2Test() override {
if (video_receive_stream_) {
video_receive_stream_->Stop();
@ -276,8 +280,6 @@ class VideoReceiveStream2Test : public ::testing::TestWithParam<bool> {
protected:
GlobalSimulatedTimeController time_controller_;
Clock* const clock_;
// Tasks on the main thread can be controlled with the run loop.
test::RunLoop loop_;
NackPeriodicProcessor nack_periodic_processor_;
testing::NiceMock<MockVideoDecoderFactory> mock_h264_decoder_factory_;
VideoReceiveStreamInterface::Config config_;
@ -432,7 +434,6 @@ TEST_P(VideoReceiveStream2Test, MaxCompositionDelaySetFromMaxPlayoutDelay) {
EXPECT_THAT(timing_->RenderParameters().max_composition_delay_in_frames,
Eq(absl::nullopt));
time_controller_.AdvanceTime(k30FpsDelay);
loop_.Flush();
// Max composition delay not set for playout delay 0,0.
std::unique_ptr<test::FakeEncodedFrame> test_frame1 =
@ -447,7 +448,6 @@ TEST_P(VideoReceiveStream2Test, MaxCompositionDelaySetFromMaxPlayoutDelay) {
EXPECT_THAT(timing_->RenderParameters().max_composition_delay_in_frames,
Eq(absl::nullopt));
time_controller_.AdvanceTime(k30FpsDelay);
loop_.Flush();
// Max composition delay not set for playout delay X,Y, where X,Y>0.
std::unique_ptr<test::FakeEncodedFrame> test_frame2 =
@ -463,7 +463,6 @@ TEST_P(VideoReceiveStream2Test, MaxCompositionDelaySetFromMaxPlayoutDelay) {
Eq(absl::nullopt));
time_controller_.AdvanceTime(k30FpsDelay);
loop_.Flush();
// Max composition delay set if playout delay X,Y, where X=0,Y>0.
const int kExpectedMaxCompositionDelayInFrames = 3; // ~50 ms at 60 fps.
@ -711,7 +710,6 @@ TEST_P(VideoReceiveStream2Test, RequestsKeyFramesUntilKeyFrameReceived) {
MakeFrame(VideoFrameType::kVideoFrameDelta, 0));
fake_renderer_.WaitForFrame(kDefaultTimeOut);
time_controller_.AdvanceTime(tick);
loop_.Flush();
video_receive_stream_->OnCompleteFrame(
MakeFrame(VideoFrameType::kVideoFrameDelta, 1));
fake_renderer_.WaitForFrame(kDefaultTimeOut);
@ -726,7 +724,6 @@ TEST_P(VideoReceiveStream2Test, RequestsKeyFramesUntilKeyFrameReceived) {
video_receive_stream_->OnCompleteFrame(
MakeFrame(VideoFrameType::kVideoFrameDelta, 2));
EXPECT_THAT(fake_renderer_.WaitForFrame(kDefaultTimeOut), RenderedFrame());
loop_.Flush();
testing::Mock::VerifyAndClearExpectations(&mock_transport_);
EXPECT_THAT(rtcp_packet_parser_.pli()->num_packets(), Eq(2));
@ -740,7 +737,6 @@ TEST_P(VideoReceiveStream2Test, RequestsKeyFramesUntilKeyFrameReceived) {
video_receive_stream_->OnCompleteFrame(
MakeFrame(VideoFrameType::kVideoFrameDelta, 4));
EXPECT_THAT(fake_renderer_.WaitForFrame(kDefaultTimeOut), RenderedFrame());
loop_.Flush();
EXPECT_THAT(rtcp_packet_parser_.pli()->num_packets(), Eq(2));
}
@ -962,8 +958,10 @@ TEST_P(VideoReceiveStream2Test, FramesFastForwardOnSystemHalt) {
video_receive_stream_->OnCompleteFrame(std::move(key_frame));
video_receive_stream_->OnCompleteFrame(std::move(ffwd_frame));
video_receive_stream_->OnCompleteFrame(std::move(rendered_frame));
EXPECT_THAT(fake_renderer_.WaitForFrame(TimeDelta::Zero()), RenderedFrame());
EXPECT_THAT(fake_renderer_.WaitForFrame(TimeDelta::Zero()), RenderedFrame());
EXPECT_THAT(fake_renderer_.WaitForFrame(TimeDelta::Zero()),
RenderedFrameWith(RtpTimestamp(RtpTimestampForFrame(0))));
EXPECT_THAT(fake_renderer_.WaitForFrame(TimeDelta::Zero()),
RenderedFrameWith(RtpTimestamp(RtpTimestampForFrame(2))));
// Check stats show correct dropped frames.
auto stats = video_receive_stream_->GetStats();
@ -1024,6 +1022,7 @@ TEST_P(VideoReceiveStream2Test, BetterFrameInsertedWhileWaitingToDecodeFrame) {
// fake delay of around 6.5 hours. Even though time is simulated, this will be
// around 1,500,000 metronome tick invocations.
TEST_P(VideoReceiveStream2Test, RtpTimestampWrapAround) {
EXPECT_CALL(mock_transport_, SendRtcp).Times(AnyNumber());
video_receive_stream_->Start();
constexpr uint32_t kBaseRtp = std::numeric_limits<uint32_t>::max() / 2;