/* * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "video/stream_synchronization.h" #include #include "system_wrappers/include/clock.h" #include "system_wrappers/include/ntp_time.h" #include "test/gtest.h" namespace webrtc { namespace { constexpr int kMaxChangeMs = 80; // From stream_synchronization.cc constexpr int kDefaultAudioFrequency = 8000; constexpr int kDefaultVideoFrequency = 90000; constexpr int kSmoothingFilter = 4 * 2; } // namespace class StreamSynchronizationTest : public ::testing::Test { public: StreamSynchronizationTest() : sync_(0, 0), clock_sender_(98765000), clock_receiver_(43210000) {} protected: // Generates the necessary RTCP measurements and RTP timestamps and computes // the audio and video delays needed to get the two streams in sync. // `audio_delay_ms` and `video_delay_ms` are the number of milliseconds after // capture which the frames are received. // `current_audio_delay_ms` is the number of milliseconds which audio is // currently being delayed by the receiver. bool DelayedStreams(int audio_delay_ms, int video_delay_ms, int current_audio_delay_ms, int* total_audio_delay_ms, int* total_video_delay_ms) { int audio_frequency = static_cast(kDefaultAudioFrequency * audio_clock_drift_ + 0.5); int video_frequency = static_cast(kDefaultVideoFrequency * video_clock_drift_ + 0.5); // Generate NTP/RTP timestamp pair for both streams corresponding to RTCP. StreamSynchronization::Measurements audio; StreamSynchronization::Measurements video; NtpTime ntp_time = clock_sender_.CurrentNtpTime(); uint32_t rtp_timestamp = clock_sender_.CurrentTime().ms() * audio_frequency / 1000; EXPECT_EQ(audio.rtp_to_ntp.UpdateMeasurements(ntp_time, rtp_timestamp), RtpToNtpEstimator::kNewMeasurement); clock_sender_.AdvanceTimeMilliseconds(100); clock_receiver_.AdvanceTimeMilliseconds(100); ntp_time = clock_sender_.CurrentNtpTime(); rtp_timestamp = clock_sender_.CurrentTime().ms() * video_frequency / 1000; EXPECT_EQ(video.rtp_to_ntp.UpdateMeasurements(ntp_time, rtp_timestamp), RtpToNtpEstimator::kNewMeasurement); clock_sender_.AdvanceTimeMilliseconds(900); clock_receiver_.AdvanceTimeMilliseconds(900); ntp_time = clock_sender_.CurrentNtpTime(); rtp_timestamp = clock_sender_.CurrentTime().ms() * audio_frequency / 1000; EXPECT_EQ(audio.rtp_to_ntp.UpdateMeasurements(ntp_time, rtp_timestamp), RtpToNtpEstimator::kNewMeasurement); clock_sender_.AdvanceTimeMilliseconds(100); clock_receiver_.AdvanceTimeMilliseconds(100); ntp_time = clock_sender_.CurrentNtpTime(); rtp_timestamp = clock_sender_.CurrentTime().ms() * video_frequency / 1000; EXPECT_EQ(video.rtp_to_ntp.UpdateMeasurements(ntp_time, rtp_timestamp), RtpToNtpEstimator::kNewMeasurement); clock_sender_.AdvanceTimeMilliseconds(900); clock_receiver_.AdvanceTimeMilliseconds(900); // Capture an audio and a video frame at the same time. audio.latest_timestamp = clock_sender_.CurrentTime().ms() * audio_frequency / 1000; video.latest_timestamp = clock_sender_.CurrentTime().ms() * video_frequency / 1000; if (audio_delay_ms > video_delay_ms) { // Audio later than video. clock_receiver_.AdvanceTimeMilliseconds(video_delay_ms); video.latest_receive_time_ms = clock_receiver_.CurrentTime().ms(); clock_receiver_.AdvanceTimeMilliseconds(audio_delay_ms - video_delay_ms); audio.latest_receive_time_ms = clock_receiver_.CurrentTime().ms(); } else { // Video later than audio. clock_receiver_.AdvanceTimeMilliseconds(audio_delay_ms); audio.latest_receive_time_ms = clock_receiver_.CurrentTime().ms(); clock_receiver_.AdvanceTimeMilliseconds(video_delay_ms - audio_delay_ms); video.latest_receive_time_ms = clock_receiver_.CurrentTime().ms(); } int relative_delay_ms; EXPECT_TRUE(StreamSynchronization::ComputeRelativeDelay( audio, video, &relative_delay_ms)); EXPECT_EQ(video_delay_ms - audio_delay_ms, relative_delay_ms); return sync_.ComputeDelays(relative_delay_ms, current_audio_delay_ms, total_audio_delay_ms, total_video_delay_ms); } // Simulate audio playback 300 ms after capture and video rendering 100 ms // after capture. Verify that the correct extra delays are calculated for // audio and video, and that they change correctly when we simulate that // NetEQ or the VCM adds more delay to the streams. void BothDelayedAudioLaterTest(int base_target_delay_ms) { const int kAudioDelayMs = base_target_delay_ms + 300; const int kVideoDelayMs = base_target_delay_ms + 100; int current_audio_delay_ms = base_target_delay_ms; int total_audio_delay_ms = 0; int total_video_delay_ms = base_target_delay_ms; int filtered_move = (kAudioDelayMs - kVideoDelayMs) / kSmoothingFilter; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms + filtered_move, total_video_delay_ms); EXPECT_EQ(base_target_delay_ms, total_audio_delay_ms); // Set new current delay. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds( 1000 - std::max(kAudioDelayMs, kVideoDelayMs)); // Simulate base_target_delay_ms minimum delay in the VCM. total_video_delay_ms = base_target_delay_ms; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms + 2 * filtered_move, total_video_delay_ms); EXPECT_EQ(base_target_delay_ms, total_audio_delay_ms); // Set new current delay. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds( 1000 - std::max(kAudioDelayMs, kVideoDelayMs)); // Simulate base_target_delay_ms minimum delay in the VCM. total_video_delay_ms = base_target_delay_ms; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms + 3 * filtered_move, total_video_delay_ms); EXPECT_EQ(base_target_delay_ms, total_audio_delay_ms); // Simulate that NetEQ introduces some audio delay. const int kNeteqDelayIncrease = 50; current_audio_delay_ms = base_target_delay_ms + kNeteqDelayIncrease; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds( 1000 - std::max(kAudioDelayMs, kVideoDelayMs)); // Simulate base_target_delay_ms minimum delay in the VCM. total_video_delay_ms = base_target_delay_ms; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); filtered_move = 3 * filtered_move + (kNeteqDelayIncrease + kAudioDelayMs - kVideoDelayMs) / kSmoothingFilter; EXPECT_EQ(base_target_delay_ms + filtered_move, total_video_delay_ms); EXPECT_EQ(base_target_delay_ms, total_audio_delay_ms); // Simulate that NetEQ reduces its delay. const int kNeteqDelayDecrease = 10; current_audio_delay_ms = base_target_delay_ms + kNeteqDelayDecrease; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds( 1000 - std::max(kAudioDelayMs, kVideoDelayMs)); // Simulate base_target_delay_ms minimum delay in the VCM. total_video_delay_ms = base_target_delay_ms; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); filtered_move = filtered_move + (kNeteqDelayDecrease + kAudioDelayMs - kVideoDelayMs) / kSmoothingFilter; EXPECT_EQ(base_target_delay_ms + filtered_move, total_video_delay_ms); EXPECT_EQ(base_target_delay_ms, total_audio_delay_ms); } void BothDelayedVideoLaterTest(int base_target_delay_ms) { const int kAudioDelayMs = base_target_delay_ms + 100; const int kVideoDelayMs = base_target_delay_ms + 300; int current_audio_delay_ms = base_target_delay_ms; int total_audio_delay_ms = 0; int total_video_delay_ms = base_target_delay_ms; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms, total_video_delay_ms); // The audio delay is not allowed to change more than this. EXPECT_GE(base_target_delay_ms + kMaxChangeMs, total_audio_delay_ms); int last_total_audio_delay_ms = total_audio_delay_ms; // Set new current audio delay. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs( current_audio_delay_ms, base_target_delay_ms + kVideoDelayMs - kAudioDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Set new current audio delay. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs( current_audio_delay_ms, base_target_delay_ms + kVideoDelayMs - kAudioDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Simulate that NetEQ for some reason reduced the delay. current_audio_delay_ms = base_target_delay_ms + 10; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs( current_audio_delay_ms, base_target_delay_ms + kVideoDelayMs - kAudioDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Simulate that NetEQ for some reason significantly increased the delay. current_audio_delay_ms = base_target_delay_ms + 350; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(kAudioDelayMs, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(base_target_delay_ms, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs( current_audio_delay_ms, base_target_delay_ms + kVideoDelayMs - kAudioDelayMs), total_audio_delay_ms); } int MaxAudioDelayChangeMs(int current_audio_delay_ms, int delay_ms) const { int diff_ms = (delay_ms - current_audio_delay_ms) / kSmoothingFilter; diff_ms = std::min(diff_ms, kMaxChangeMs); diff_ms = std::max(diff_ms, -kMaxChangeMs); return diff_ms; } StreamSynchronization sync_; SimulatedClock clock_sender_; SimulatedClock clock_receiver_; double audio_clock_drift_ = 1.0; double video_clock_drift_ = 1.0; }; TEST_F(StreamSynchronizationTest, NoDelay) { int total_audio_delay_ms = 0; int total_video_delay_ms = 0; EXPECT_FALSE(DelayedStreams(/*audio_delay_ms=*/0, /*video_delay_ms=*/0, /*current_audio_delay_ms=*/0, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_audio_delay_ms); EXPECT_EQ(0, total_video_delay_ms); } TEST_F(StreamSynchronizationTest, VideoDelayed) { const int kAudioDelayMs = 200; int total_audio_delay_ms = 0; int total_video_delay_ms = 0; EXPECT_TRUE(DelayedStreams(kAudioDelayMs, /*video_delay_ms=*/0, /*current_audio_delay_ms=*/0, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_audio_delay_ms); // The delay is not allowed to change more than this. EXPECT_EQ(kAudioDelayMs / kSmoothingFilter, total_video_delay_ms); // Simulate 0 minimum delay in the VCM. total_video_delay_ms = 0; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(kAudioDelayMs, /*video_delay_ms=*/0, /*current_audio_delay_ms=*/0, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_audio_delay_ms); EXPECT_EQ(2 * kAudioDelayMs / kSmoothingFilter, total_video_delay_ms); // Simulate 0 minimum delay in the VCM. total_video_delay_ms = 0; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(kAudioDelayMs, /*video_delay_ms=*/0, /*current_audio_delay_ms=*/0, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_audio_delay_ms); EXPECT_EQ(3 * kAudioDelayMs / kSmoothingFilter, total_video_delay_ms); } TEST_F(StreamSynchronizationTest, AudioDelayed) { const int kVideoDelayMs = 200; int current_audio_delay_ms = 0; int total_audio_delay_ms = 0; int total_video_delay_ms = 0; EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); // The delay is not allowed to change more than this. EXPECT_EQ(kVideoDelayMs / kSmoothingFilter, total_audio_delay_ms); int last_total_audio_delay_ms = total_audio_delay_ms; // Set new current audio delay. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs(current_audio_delay_ms, kVideoDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Set new current audio delay. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs(current_audio_delay_ms, kVideoDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Simulate that NetEQ for some reason reduced the delay. current_audio_delay_ms = 10; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs(current_audio_delay_ms, kVideoDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Simulate that NetEQ for some reason significantly increased the delay. current_audio_delay_ms = 350; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(800); EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs(current_audio_delay_ms, kVideoDelayMs), total_audio_delay_ms); } TEST_F(StreamSynchronizationTest, NoAudioIncomingUnboundedIncrease) { // Test how audio delay can grow unbounded when audio stops coming in. // This is handled in caller of RtpStreamsSynchronizer, for example in // RtpStreamsSynchronizer by not updating delays when audio samples stop // coming in. const int kVideoDelayMs = 300; const int kAudioDelayMs = 100; int current_audio_delay_ms = kAudioDelayMs; int total_audio_delay_ms = 0; int total_video_delay_ms = 0; EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); // The delay is not allowed to change more than this. EXPECT_EQ((kVideoDelayMs - kAudioDelayMs) / kSmoothingFilter, total_audio_delay_ms); int last_total_audio_delay_ms = total_audio_delay_ms; // Set new current audio delay: simulate audio samples are flowing in. current_audio_delay_ms = total_audio_delay_ms; clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(1000); EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); EXPECT_EQ(last_total_audio_delay_ms + MaxAudioDelayChangeMs(current_audio_delay_ms, kVideoDelayMs), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; // Simulate no incoming audio by not update audio delay. const int kSimulationSecs = 300; // 5min const int kMaxDeltaDelayMs = 10000; // max delay for audio in webrtc for (auto time_secs = 0; time_secs < kSimulationSecs; time_secs++) { clock_sender_.AdvanceTimeMilliseconds(1000); clock_receiver_.AdvanceTimeMilliseconds(1000); EXPECT_TRUE(DelayedStreams(/*audio_delay_ms=*/0, kVideoDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); EXPECT_EQ(0, total_video_delay_ms); // Audio delay does not go above kMaxDeltaDelayMs. EXPECT_EQ(std::min(kMaxDeltaDelayMs, last_total_audio_delay_ms + MaxAudioDelayChangeMs(current_audio_delay_ms, kVideoDelayMs)), total_audio_delay_ms); last_total_audio_delay_ms = total_audio_delay_ms; } // By now the audio delay has grown unbounded to kMaxDeltaDelayMs. EXPECT_EQ(kMaxDeltaDelayMs, last_total_audio_delay_ms); } TEST_F(StreamSynchronizationTest, BothDelayedVideoLater) { BothDelayedVideoLaterTest(0); } TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterAudioClockDrift) { audio_clock_drift_ = 1.05; BothDelayedVideoLaterTest(0); } TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterVideoClockDrift) { video_clock_drift_ = 1.05; BothDelayedVideoLaterTest(0); } TEST_F(StreamSynchronizationTest, BothDelayedAudioLater) { BothDelayedAudioLaterTest(0); } TEST_F(StreamSynchronizationTest, BothDelayedAudioClockDrift) { audio_clock_drift_ = 1.05; BothDelayedAudioLaterTest(0); } TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDrift) { video_clock_drift_ = 1.05; BothDelayedAudioLaterTest(0); } TEST_F(StreamSynchronizationTest, BothEquallyDelayed) { const int kDelayMs = 2000; int current_audio_delay_ms = kDelayMs; int total_audio_delay_ms = 0; int total_video_delay_ms = kDelayMs; // In sync, expect no change. EXPECT_FALSE(DelayedStreams(kDelayMs, kDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); // Trigger another call with the same values, delay should not be modified. total_video_delay_ms = kDelayMs; EXPECT_FALSE(DelayedStreams(kDelayMs, kDelayMs, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); // Change delay value, delay should not be modified. const int kDelayMs2 = 5000; current_audio_delay_ms = kDelayMs2; total_video_delay_ms = kDelayMs2; EXPECT_FALSE(DelayedStreams(kDelayMs2, kDelayMs2, current_audio_delay_ms, &total_audio_delay_ms, &total_video_delay_ms)); } TEST_F(StreamSynchronizationTest, BothDelayedAudioLaterWithBaseDelay) { const int kBaseTargetDelayMs = 3000; sync_.SetTargetBufferingDelay(kBaseTargetDelayMs); BothDelayedAudioLaterTest(kBaseTargetDelayMs); } TEST_F(StreamSynchronizationTest, BothDelayedAudioClockDriftWithBaseDelay) { const int kBaseTargetDelayMs = 3000; sync_.SetTargetBufferingDelay(kBaseTargetDelayMs); audio_clock_drift_ = 1.05; BothDelayedAudioLaterTest(kBaseTargetDelayMs); } TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDriftWithBaseDelay) { const int kBaseTargetDelayMs = 3000; sync_.SetTargetBufferingDelay(kBaseTargetDelayMs); video_clock_drift_ = 1.05; BothDelayedAudioLaterTest(kBaseTargetDelayMs); } TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterWithBaseDelay) { const int kBaseTargetDelayMs = 2000; sync_.SetTargetBufferingDelay(kBaseTargetDelayMs); BothDelayedVideoLaterTest(kBaseTargetDelayMs); } TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterAudioClockDriftWithBaseDelay) { const int kBaseTargetDelayMs = 2000; audio_clock_drift_ = 1.05; sync_.SetTargetBufferingDelay(kBaseTargetDelayMs); BothDelayedVideoLaterTest(kBaseTargetDelayMs); } TEST_F(StreamSynchronizationTest, BothDelayedVideoLaterVideoClockDriftWithBaseDelay) { const int kBaseTargetDelayMs = 2000; video_clock_drift_ = 1.05; sync_.SetTargetBufferingDelay(kBaseTargetDelayMs); BothDelayedVideoLaterTest(kBaseTargetDelayMs); } } // namespace webrtc