From 5dd493b3daa06091c0f85829f32d0629b31fe447 Mon Sep 17 00:00:00 2001 From: Sergey Silkin Date: Fri, 3 Feb 2023 16:23:41 +0100 Subject: [PATCH] Do not use PostDelayedTask in video codec tester's pacer PostDelayedTask doesn't guarantee task execution order. For example, if you post two tasks, A and B, back-to-back using the same delay there is no guarantee that A will be executed before B. Re-implemented pacing using sleep(). Changed pacer to compute task scheduled time instead of delay. Sleep time is calculated right before task start. This provides better accuracy by accounting for any delays that may happen after pacing time is computed and before task queue is ready to run the task. It is tricky to implement pacer tests using simulated clocks. The test use system time which make them flacky on low performance bots. Keep the test disabled by default. Bug: b/261160916, webrtc:14852 Change-Id: I88e1a2001e6d33cf3bb7fe16730ec28abf90acc8 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291804 Reviewed-by: Rasmus Brandt Commit-Queue: Sergey Silkin Cr-Commit-Position: refs/heads/main@{#39302} --- .../codecs/test/video_codec_analyzer.cc | 5 +- .../codecs/test/video_codec_analyzer.h | 6 +- .../test/video_codec_analyzer_unittest.cc | 15 +- .../codecs/test/video_codec_tester_impl.cc | 118 ++++------- .../codecs/test/video_codec_tester_impl.h | 8 - .../test/video_codec_tester_impl_unittest.cc | 190 +++++++----------- 6 files changed, 129 insertions(+), 213 deletions(-) diff --git a/modules/video_coding/codecs/test/video_codec_analyzer.cc b/modules/video_coding/codecs/test/video_codec_analyzer.cc index 6521112bbc..e2e7384bbd 100644 --- a/modules/video_coding/codecs/test/video_codec_analyzer.cc +++ b/modules/video_coding/codecs/test/video_codec_analyzer.cc @@ -56,11 +56,8 @@ Psnr CalcPsnr(const I420BufferInterface& ref_buffer, } // namespace VideoCodecAnalyzer::VideoCodecAnalyzer( - rtc::TaskQueue& task_queue, ReferenceVideoSource* reference_video_source) - : task_queue_(task_queue), - reference_video_source_(reference_video_source), - num_frames_(0) { + : reference_video_source_(reference_video_source), num_frames_(0) { sequence_checker_.Detach(); } diff --git a/modules/video_coding/codecs/test/video_codec_analyzer.h b/modules/video_coding/codecs/test/video_codec_analyzer.h index 8cb1b542d6..8b5089136b 100644 --- a/modules/video_coding/codecs/test/video_codec_analyzer.h +++ b/modules/video_coding/codecs/test/video_codec_analyzer.h @@ -41,8 +41,8 @@ class VideoCodecAnalyzer { Resolution resolution) = 0; }; - VideoCodecAnalyzer(rtc::TaskQueue& task_queue, - ReferenceVideoSource* reference_video_source = nullptr); + explicit VideoCodecAnalyzer( + ReferenceVideoSource* reference_video_source = nullptr); void StartEncode(const VideoFrame& frame); @@ -55,7 +55,7 @@ class VideoCodecAnalyzer { std::unique_ptr GetStats(); protected: - rtc::TaskQueue& task_queue_; + TaskQueueForTest task_queue_; ReferenceVideoSource* const reference_video_source_; diff --git a/modules/video_coding/codecs/test/video_codec_analyzer_unittest.cc b/modules/video_coding/codecs/test/video_codec_analyzer_unittest.cc index 133a60ff36..d7c5fe28a4 100644 --- a/modules/video_coding/codecs/test/video_codec_analyzer_unittest.cc +++ b/modules/video_coding/codecs/test/video_codec_analyzer_unittest.cc @@ -59,8 +59,7 @@ EncodedImage CreateEncodedImage(uint32_t timestamp_rtp, int spatial_idx = 0) { } // namespace TEST(VideoCodecAnalyzerTest, StartEncode) { - TaskQueueForTest task_queue; - VideoCodecAnalyzer analyzer(task_queue); + VideoCodecAnalyzer analyzer; analyzer.StartEncode(CreateVideoFrame(kTimestamp)); auto fs = analyzer.GetStats()->Slice(); @@ -69,8 +68,7 @@ TEST(VideoCodecAnalyzerTest, StartEncode) { } TEST(VideoCodecAnalyzerTest, FinishEncode) { - TaskQueueForTest task_queue; - VideoCodecAnalyzer analyzer(task_queue); + VideoCodecAnalyzer analyzer; analyzer.StartEncode(CreateVideoFrame(kTimestamp)); EncodedImage encoded_frame = CreateEncodedImage(kTimestamp, kSpatialIdx); @@ -82,8 +80,7 @@ TEST(VideoCodecAnalyzerTest, FinishEncode) { } TEST(VideoCodecAnalyzerTest, StartDecode) { - TaskQueueForTest task_queue; - VideoCodecAnalyzer analyzer(task_queue); + VideoCodecAnalyzer analyzer; analyzer.StartDecode(CreateEncodedImage(kTimestamp, kSpatialIdx)); auto fs = analyzer.GetStats()->Slice(); @@ -92,8 +89,7 @@ TEST(VideoCodecAnalyzerTest, StartDecode) { } TEST(VideoCodecAnalyzerTest, FinishDecode) { - TaskQueueForTest task_queue; - VideoCodecAnalyzer analyzer(task_queue); + VideoCodecAnalyzer analyzer; analyzer.StartDecode(CreateEncodedImage(kTimestamp, kSpatialIdx)); VideoFrame decoded_frame = CreateVideoFrame(kTimestamp); analyzer.FinishDecode(decoded_frame, kSpatialIdx); @@ -105,9 +101,8 @@ TEST(VideoCodecAnalyzerTest, FinishDecode) { } TEST(VideoCodecAnalyzerTest, ReferenceVideoSource) { - TaskQueueForTest task_queue; MockReferenceVideoSource reference_video_source; - VideoCodecAnalyzer analyzer(task_queue, &reference_video_source); + VideoCodecAnalyzer analyzer(&reference_video_source); analyzer.StartDecode(CreateEncodedImage(kTimestamp, kSpatialIdx)); EXPECT_CALL(reference_video_source, GetFrame) diff --git a/modules/video_coding/codecs/test/video_codec_tester_impl.cc b/modules/video_coding/codecs/test/video_codec_tester_impl.cc index 3655c3061d..9445cf7fbb 100644 --- a/modules/video_coding/codecs/test/video_codec_tester_impl.cc +++ b/modules/video_coding/codecs/test/video_codec_tester_impl.cc @@ -71,37 +71,37 @@ class Pacer { public: explicit Pacer(PacingSettings settings) : settings_(settings), delay_(TimeDelta::Zero()) {} - TimeDelta Delay(Timestamp beat) { + Timestamp Schedule(Timestamp timestamp) { + Timestamp now = Timestamp::Micros(rtc::TimeMicros()); if (settings_.mode == PacingMode::kNoPacing) { - return TimeDelta::Zero(); + return now; } - Timestamp now = Timestamp::Micros(rtc::TimeMicros()); - if (prev_time_.has_value()) { - delay_ += PacingTime(beat); - delay_ -= (now - *prev_time_); - if (delay_.ns() < 0) { - delay_ = TimeDelta::Zero(); + Timestamp scheduled = now; + if (prev_scheduled_) { + scheduled = *prev_scheduled_ + PacingTime(timestamp); + if (scheduled < now) { + scheduled = now; } } - prev_beat_ = beat; - prev_time_ = now; - return delay_; + prev_timestamp_ = timestamp; + prev_scheduled_ = scheduled; + return scheduled; } private: - TimeDelta PacingTime(Timestamp beat) { + TimeDelta PacingTime(Timestamp timestamp) { if (settings_.mode == PacingMode::kRealTime) { - return beat - *prev_beat_; + return timestamp - *prev_timestamp_; } RTC_CHECK_EQ(PacingMode::kConstantRate, settings_.mode); return 1 / settings_.constant_rate; } PacingSettings settings_; - absl::optional prev_beat_; - absl::optional prev_time_; + absl::optional prev_timestamp_; + absl::optional prev_scheduled_; TimeDelta delay_; }; @@ -119,18 +119,20 @@ class LimitedTaskQueue { // task starts. static constexpr int kMaxTaskQueueSize = 3; - explicit LimitedTaskQueue(rtc::TaskQueue& task_queue) - : task_queue_(task_queue), queue_size_(0) {} + LimitedTaskQueue() : queue_size_(0) {} - void PostDelayedTask(absl::AnyInvocable task, TimeDelta delay) { + void PostScheduledTask(absl::AnyInvocable task, Timestamp start) { ++queue_size_; - task_queue_.PostDelayedTask( - [this, task = std::move(task)]() mutable { - std::move(task)(); - --queue_size_; - task_executed_.Set(); - }, - delay); + task_queue_.PostTask([this, task = std::move(task), start]() mutable { + int wait_ms = static_cast(start.ms() - rtc::TimeMillis()); + if (wait_ms > 0) { + SleepMs(wait_ms); + } + + std::move(task)(); + --queue_size_; + task_executed_.Set(); + }); task_executed_.Reset(); if (queue_size_ > kMaxTaskQueueSize) { @@ -146,7 +148,7 @@ class LimitedTaskQueue { } } - rtc::TaskQueue& task_queue_; + TaskQueueForTest task_queue_; std::atomic_int queue_size_; rtc::Event task_executed_; }; @@ -155,20 +157,18 @@ class TesterDecoder { public: TesterDecoder(Decoder* decoder, VideoCodecAnalyzer* analyzer, - const DecoderSettings& settings, - rtc::TaskQueue& task_queue) + const DecoderSettings& settings) : decoder_(decoder), analyzer_(analyzer), settings_(settings), - pacer_(settings.pacing), - task_queue_(task_queue) { + pacer_(settings.pacing) { RTC_CHECK(analyzer_) << "Analyzer must be provided"; } void Decode(const EncodedImage& frame) { Timestamp timestamp = Timestamp::Micros((frame.Timestamp() / k90kHz).us()); - task_queue_.PostDelayedTask( + task_queue_.PostScheduledTask( [this, frame] { analyzer_->StartDecode(frame); decoder_->Decode( @@ -177,7 +177,7 @@ class TesterDecoder { this->analyzer_->FinishDecode(decoded_frame, spatial_idx); }); }, - pacer_.Delay(timestamp)); + pacer_.Schedule(timestamp)); } void Flush() { task_queue_.WaitForPreviouslyPostedTasks(); } @@ -195,21 +195,19 @@ class TesterEncoder { TesterEncoder(Encoder* encoder, TesterDecoder* decoder, VideoCodecAnalyzer* analyzer, - const EncoderSettings& settings, - rtc::TaskQueue& task_queue) + const EncoderSettings& settings) : encoder_(encoder), decoder_(decoder), analyzer_(analyzer), settings_(settings), - pacer_(settings.pacing), - task_queue_(task_queue) { + pacer_(settings.pacing) { RTC_CHECK(analyzer_) << "Analyzer must be provided"; } void Encode(const VideoFrame& frame) { Timestamp timestamp = Timestamp::Micros((frame.timestamp() / k90kHz).us()); - task_queue_.PostDelayedTask( + task_queue_.PostScheduledTask( [this, frame] { analyzer_->StartEncode(frame); encoder_->Encode(frame, [this](const EncodedImage& encoded_frame) { @@ -219,7 +217,7 @@ class TesterEncoder { } }); }, - pacer_.Delay(timestamp)); + pacer_.Schedule(timestamp)); } void Flush() { task_queue_.WaitForPreviouslyPostedTasks(); } @@ -235,29 +233,12 @@ class TesterEncoder { } // namespace -VideoCodecTesterImpl::VideoCodecTesterImpl() - : VideoCodecTesterImpl(/*task_queue_factory=*/nullptr) {} - -VideoCodecTesterImpl::VideoCodecTesterImpl(TaskQueueFactory* task_queue_factory) - : task_queue_factory_(task_queue_factory) { - if (task_queue_factory_ == nullptr) { - owned_task_queue_factory_ = CreateDefaultTaskQueueFactory(); - task_queue_factory_ = owned_task_queue_factory_.get(); - } -} - std::unique_ptr VideoCodecTesterImpl::RunDecodeTest( CodedVideoSource* video_source, Decoder* decoder, const DecoderSettings& decoder_settings) { - rtc::TaskQueue analyser_task_queue(task_queue_factory_->CreateTaskQueue( - "Analyzer", TaskQueueFactory::Priority::NORMAL)); - rtc::TaskQueue decoder_task_queue(task_queue_factory_->CreateTaskQueue( - "Decoder", TaskQueueFactory::Priority::NORMAL)); - - VideoCodecAnalyzer perf_analyzer(analyser_task_queue); - TesterDecoder tester_decoder(decoder, &perf_analyzer, decoder_settings, - decoder_task_queue); + VideoCodecAnalyzer perf_analyzer; + TesterDecoder tester_decoder(decoder, &perf_analyzer, decoder_settings); while (auto frame = video_source->PullFrame()) { tester_decoder.Decode(*frame); @@ -272,15 +253,10 @@ std::unique_ptr VideoCodecTesterImpl::RunEncodeTest( RawVideoSource* video_source, Encoder* encoder, const EncoderSettings& encoder_settings) { - rtc::TaskQueue analyser_task_queue(task_queue_factory_->CreateTaskQueue( - "Analyzer", TaskQueueFactory::Priority::NORMAL)); - rtc::TaskQueue encoder_task_queue(task_queue_factory_->CreateTaskQueue( - "Encoder", TaskQueueFactory::Priority::NORMAL)); - SyncRawVideoSource sync_source(video_source); - VideoCodecAnalyzer perf_analyzer(analyser_task_queue); + VideoCodecAnalyzer perf_analyzer; TesterEncoder tester_encoder(encoder, /*decoder=*/nullptr, &perf_analyzer, - encoder_settings, encoder_task_queue); + encoder_settings); while (auto frame = sync_source.PullFrame()) { tester_encoder.Encode(*frame); @@ -297,19 +273,11 @@ std::unique_ptr VideoCodecTesterImpl::RunEncodeDecodeTest( Decoder* decoder, const EncoderSettings& encoder_settings, const DecoderSettings& decoder_settings) { - rtc::TaskQueue analyser_task_queue(task_queue_factory_->CreateTaskQueue( - "Analyzer", TaskQueueFactory::Priority::NORMAL)); - rtc::TaskQueue decoder_task_queue(task_queue_factory_->CreateTaskQueue( - "Decoder", TaskQueueFactory::Priority::NORMAL)); - rtc::TaskQueue encoder_task_queue(task_queue_factory_->CreateTaskQueue( - "Encoder", TaskQueueFactory::Priority::NORMAL)); - SyncRawVideoSource sync_source(video_source); - VideoCodecAnalyzer perf_analyzer(analyser_task_queue, &sync_source); - TesterDecoder tester_decoder(decoder, &perf_analyzer, decoder_settings, - decoder_task_queue); + VideoCodecAnalyzer perf_analyzer(&sync_source); + TesterDecoder tester_decoder(decoder, &perf_analyzer, decoder_settings); TesterEncoder tester_encoder(encoder, &tester_decoder, &perf_analyzer, - encoder_settings, encoder_task_queue); + encoder_settings); while (auto frame = sync_source.PullFrame()) { tester_encoder.Encode(*frame); diff --git a/modules/video_coding/codecs/test/video_codec_tester_impl.h b/modules/video_coding/codecs/test/video_codec_tester_impl.h index bb8ee72502..32191b5a98 100644 --- a/modules/video_coding/codecs/test/video_codec_tester_impl.h +++ b/modules/video_coding/codecs/test/video_codec_tester_impl.h @@ -13,7 +13,6 @@ #include -#include "api/task_queue/task_queue_factory.h" #include "api/test/video_codec_tester.h" namespace webrtc { @@ -22,9 +21,6 @@ namespace test { // A stateless implementation of `VideoCodecTester`. This class is thread safe. class VideoCodecTesterImpl : public VideoCodecTester { public: - VideoCodecTesterImpl(); - explicit VideoCodecTesterImpl(TaskQueueFactory* task_queue_factory); - std::unique_ptr RunDecodeTest( CodedVideoSource* video_source, Decoder* decoder, @@ -41,10 +37,6 @@ class VideoCodecTesterImpl : public VideoCodecTester { Decoder* decoder, const EncoderSettings& encoder_settings, const DecoderSettings& decoder_settings) override; - - protected: - std::unique_ptr owned_task_queue_factory_; - TaskQueueFactory* task_queue_factory_; }; } // namespace test diff --git a/modules/video_coding/codecs/test/video_codec_tester_impl_unittest.cc b/modules/video_coding/codecs/test/video_codec_tester_impl_unittest.cc index c1195a7f3d..8874f26df6 100644 --- a/modules/video_coding/codecs/test/video_codec_tester_impl_unittest.cc +++ b/modules/video_coding/codecs/test/video_codec_tester_impl_unittest.cc @@ -49,6 +49,13 @@ using PacingMode = PacingSettings::PacingMode; constexpr Frequency k90kHz = Frequency::Hertz(90000); +struct PacingTestParams { + PacingSettings pacing_settings; + Frequency framerate; + int num_frames; + std::vector expected_delta_ms; +}; + VideoFrame CreateVideoFrame(uint32_t timestamp_rtp) { rtc::scoped_refptr buffer(I420Buffer::Create(2, 2)); return VideoFrame::Builder() @@ -65,16 +72,47 @@ EncodedImage CreateEncodedImage(uint32_t timestamp_rtp) { class MockRawVideoSource : public RawVideoSource { public: - MOCK_METHOD(absl::optional, PullFrame, (), (override)); + MockRawVideoSource(int num_frames, Frequency framerate) + : num_frames_(num_frames), frame_num_(0), framerate_(framerate) {} + + absl::optional PullFrame() override { + if (frame_num_ >= num_frames_) { + return absl::nullopt; + } + uint32_t timestamp_rtp = frame_num_ * k90kHz / framerate_; + ++frame_num_; + return CreateVideoFrame(timestamp_rtp); + } + MOCK_METHOD(VideoFrame, GetFrame, (uint32_t timestamp_rtp, Resolution), (override)); + + private: + int num_frames_; + int frame_num_; + Frequency framerate_; }; class MockCodedVideoSource : public CodedVideoSource { public: - MOCK_METHOD(absl::optional, PullFrame, (), (override)); + MockCodedVideoSource(int num_frames, Frequency framerate) + : num_frames_(num_frames), frame_num_(0), framerate_(framerate) {} + + absl::optional PullFrame() override { + if (frame_num_ >= num_frames_) { + return absl::nullopt; + } + uint32_t timestamp_rtp = frame_num_ * k90kHz / framerate_; + ++frame_num_; + return CreateEncodedImage(timestamp_rtp); + } + + private: + int num_frames_; + int frame_num_; + Frequency framerate_; }; class MockDecoder : public Decoder { @@ -110,144 +148,70 @@ class MockTaskQueueFactory : public TaskQueueFactory { } // namespace class VideoCodecTesterImplPacingTest - : public ::testing::TestWithParam, - std::vector, - std::vector>> { + : public ::testing::TestWithParam { public: - VideoCodecTesterImplPacingTest() - : pacing_settings_(std::get<0>(GetParam())), - frame_timestamp_ms_(std::get<1>(GetParam())), - frame_capture_delay_ms_(std::get<2>(GetParam())), - expected_frame_start_ms_(std::get<3>(GetParam())), - num_frames_(frame_timestamp_ms_.size()), - task_queue_factory_(task_queue_) {} - - void SetUp() override { - ON_CALL(task_queue_, PostTask) - .WillByDefault(Invoke( - [](absl::AnyInvocable task) { std::move(task)(); })); - - ON_CALL(task_queue_, PostDelayedTask) - .WillByDefault( - Invoke([&](absl::AnyInvocable task, TimeDelta delay) { - clock_.AdvanceTime(delay); - std::move(task)(); - })); - } + VideoCodecTesterImplPacingTest() : test_params_(GetParam()) {} protected: - PacingSettings pacing_settings_; - std::vector frame_timestamp_ms_; - std::vector frame_capture_delay_ms_; - std::vector expected_frame_start_ms_; - size_t num_frames_; - - rtc::ScopedFakeClock clock_; - MockTaskQueueBase task_queue_; - MockTaskQueueFactory task_queue_factory_; + PacingTestParams test_params_; }; TEST_P(VideoCodecTesterImplPacingTest, PaceEncode) { - MockRawVideoSource video_source; - - size_t frame_num = 0; - EXPECT_CALL(video_source, PullFrame).WillRepeatedly(Invoke([&]() mutable { - if (frame_num >= num_frames_) { - return absl::optional(); - } - clock_.AdvanceTime(TimeDelta::Millis(frame_capture_delay_ms_[frame_num])); - - uint32_t timestamp_rtp = frame_timestamp_ms_[frame_num] * k90kHz.hertz() / - rtc::kNumMillisecsPerSec; - ++frame_num; - return absl::optional(CreateVideoFrame(timestamp_rtp)); - })); - + MockRawVideoSource video_source(test_params_.num_frames, + test_params_.framerate); MockEncoder encoder; EncoderSettings encoder_settings; - encoder_settings.pacing = pacing_settings_; + encoder_settings.pacing = test_params_.pacing_settings; - VideoCodecTesterImpl tester(&task_queue_factory_); + VideoCodecTesterImpl tester; auto fs = tester.RunEncodeTest(&video_source, &encoder, encoder_settings)->Slice(); - ASSERT_EQ(fs.size(), num_frames_); + ASSERT_EQ(static_cast(fs.size()), test_params_.num_frames); - for (size_t i = 0; i < fs.size(); ++i) { - int encode_start_ms = (fs[i].encode_start - fs[0].encode_start).ms(); - EXPECT_NEAR(encode_start_ms, expected_frame_start_ms_[i], 10); + for (size_t i = 1; i < fs.size(); ++i) { + int delta_ms = (fs[i].encode_start - fs[i - 1].encode_start).ms(); + EXPECT_NEAR(delta_ms, test_params_.expected_delta_ms[i - 1], 10); } } TEST_P(VideoCodecTesterImplPacingTest, PaceDecode) { - MockCodedVideoSource video_source; - - size_t frame_num = 0; - EXPECT_CALL(video_source, PullFrame).WillRepeatedly(Invoke([&]() mutable { - if (frame_num >= num_frames_) { - return absl::optional(); - } - clock_.AdvanceTime(TimeDelta::Millis(frame_capture_delay_ms_[frame_num])); - - uint32_t timestamp_rtp = frame_timestamp_ms_[frame_num] * k90kHz.hertz() / - rtc::kNumMillisecsPerSec; - ++frame_num; - return absl::optional(CreateEncodedImage(timestamp_rtp)); - })); - + MockCodedVideoSource video_source(test_params_.num_frames, + test_params_.framerate); MockDecoder decoder; DecoderSettings decoder_settings; - decoder_settings.pacing = pacing_settings_; + decoder_settings.pacing = test_params_.pacing_settings; - VideoCodecTesterImpl tester(&task_queue_factory_); + VideoCodecTesterImpl tester; auto fs = tester.RunDecodeTest(&video_source, &decoder, decoder_settings)->Slice(); - ASSERT_EQ(fs.size(), num_frames_); + ASSERT_EQ(static_cast(fs.size()), test_params_.num_frames); - for (size_t i = 0; i < fs.size(); ++i) { - int decode_start_ms = (fs[i].decode_start - fs[0].decode_start).ms(); - EXPECT_NEAR(decode_start_ms, expected_frame_start_ms_[i], 10); + for (size_t i = 1; i < fs.size(); ++i) { + int delta_ms = (fs[i].decode_start - fs[i - 1].decode_start).ms(); + EXPECT_NEAR(delta_ms, test_params_.expected_delta_ms[i - 1], 20); } } INSTANTIATE_TEST_SUITE_P( - All, + DISABLED_All, VideoCodecTesterImplPacingTest, ::testing::ValuesIn( - {std::make_tuple(PacingSettings({.mode = PacingMode::kNoPacing}), - /*frame_timestamp_ms=*/std::vector{0, 100}, - /*frame_capture_delay_ms=*/std::vector{0, 0}, - /*expected_frame_start_ms=*/std::vector{0, 0}), - // Pace with rate equal to the source frame rate. Frames are captured - // instantly. Verify that frames are paced with the source frame rate. - std::make_tuple(PacingSettings({.mode = PacingMode::kRealTime}), - /*frame_timestamp_ms=*/std::vector{0, 100}, - /*frame_capture_delay_ms=*/std::vector{0, 0}, - /*expected_frame_start_ms=*/std::vector{0, 100}), - // Pace with rate equal to the source frame rate. Frame capture is - // delayed by more than pacing time. Verify that no extra delay is - // added. - std::make_tuple(PacingSettings({.mode = PacingMode::kRealTime}), - /*frame_timestamp_ms=*/std::vector{0, 100}, - /*frame_capture_delay_ms=*/std::vector{0, 200}, - /*expected_frame_start_ms=*/std::vector{0, 200}), - // Pace with constant rate less then source frame rate. Frames are - // captured instantly. Verify that frames are paced with the requested - // constant rate. - std::make_tuple( - PacingSettings({.mode = PacingMode::kConstantRate, - .constant_rate = Frequency::Hertz(20)}), - /*frame_timestamp_ms=*/std::vector{0, 100}, - /*frame_capture_delay_ms=*/std::vector{0, 0}, - /*expected_frame_start_ms=*/std::vector{0, 50}), - // Pace with constant rate less then source frame rate. Frame capture - // is delayed by more than the pacing time. Verify that no extra delay - // is added. - std::make_tuple( - PacingSettings({.mode = PacingMode::kConstantRate, - .constant_rate = Frequency::Hertz(20)}), - /*frame_timestamp_ms=*/std::vector{0, 100}, - /*frame_capture_delay_ms=*/std::vector{0, 200}, - /*expected_frame_start_ms=*/std::vector{0, 200})})); + {// No pacing. + PacingTestParams({.pacing_settings = {.mode = PacingMode::kNoPacing}, + .framerate = Frequency::Hertz(10), + .num_frames = 3, + .expected_delta_ms = {0, 0}}), + // Real-time pacing. + PacingTestParams({.pacing_settings = {.mode = PacingMode::kRealTime}, + .framerate = Frequency::Hertz(10), + .num_frames = 3, + .expected_delta_ms = {100, 100}}), + // Pace with specified constant rate. + PacingTestParams( + {.pacing_settings = {.mode = PacingMode::kConstantRate, + .constant_rate = Frequency::Hertz(20)}, + .framerate = Frequency::Hertz(10), + .num_frames = 3, + .expected_delta_ms = {50, 50}})})); } // namespace test } // namespace webrtc