diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-06-12 05:35:29 +0000 |
commit | 59203c63bb777a3bacec32fb8830fba33540e809 (patch) | |
tree | 58298e711c0ff0575818c30485b44a2f21bf28a0 /dom/media/driftcontrol/gtest | |
parent | Adding upstream version 126.0.1. (diff) | |
download | firefox-59203c63bb777a3bacec32fb8830fba33540e809.tar.xz firefox-59203c63bb777a3bacec32fb8830fba33540e809.zip |
Adding upstream version 127.0.upstream/127.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/media/driftcontrol/gtest')
4 files changed, 162 insertions, 121 deletions
diff --git a/dom/media/driftcontrol/gtest/TestAudioDriftCorrection.cpp b/dom/media/driftcontrol/gtest/TestAudioDriftCorrection.cpp index c13f443d37..9d3f0f091a 100644 --- a/dom/media/driftcontrol/gtest/TestAudioDriftCorrection.cpp +++ b/dom/media/driftcontrol/gtest/TestAudioDriftCorrection.cpp @@ -260,10 +260,10 @@ TEST(TestAudioDriftCorrection, LargerTransmitterBlockSizeThanDesiredBuffering) // Input is stable so no corrections should occur. EXPECT_EQ(ad.NumCorrectionChanges(), 0U); - // The drift correction buffer size had to be larger than the desired (the - // buffer size is twice the initial buffering level), to accomodate the large - // input block size. - EXPECT_EQ(ad.BufferSize(), 9600U); + // The desired buffering and pre-buffering level was + // transmitterBlockSize * 11 / 10 to accomodate the large input block size. + // The buffer size was twice the pre-buffering level. + EXPECT_EQ(ad.BufferSize(), transmitterBlockSize * 11 / 10 * 2); } TEST(TestAudioDriftCorrection, LargerReceiverBlockSizeThanDesiredBuffering) @@ -275,9 +275,9 @@ TEST(TestAudioDriftCorrection, LargerReceiverBlockSizeThanDesiredBuffering) MakePrincipalHandle(nsContentUtils::GetSystemPrincipal()); AudioDriftCorrection ad(sampleRate, sampleRate, testPrincipal); + AudioSegment inSegment; for (uint32_t i = 0; i < (sampleRate / 1000) * 500; i += transmitterBlockSize) { - AudioSegment inSegment; AudioChunk chunk = CreateAudioChunk<float>(transmitterBlockSize, 1, AUDIO_FORMAT_FLOAT32); inSegment.AppendAndConsumeChunk(std::move(chunk)); @@ -285,6 +285,7 @@ TEST(TestAudioDriftCorrection, LargerReceiverBlockSizeThanDesiredBuffering) if (i % receiverBlockSize == 0) { AudioSegment outSegment = ad.RequestFrames(inSegment, receiverBlockSize); EXPECT_EQ(outSegment.GetDuration(), receiverBlockSize); + inSegment.Clear(); } if (i >= receiverBlockSize) { @@ -294,11 +295,12 @@ TEST(TestAudioDriftCorrection, LargerReceiverBlockSizeThanDesiredBuffering) // Input is stable so no corrections should occur. EXPECT_EQ(ad.NumCorrectionChanges(), 0U); + EXPECT_EQ(ad.NumUnderruns(), 0U); // The drift correction buffer size had to be larger than the desired (the // buffer size is twice the initial buffering level), to accomodate the large // input block size that gets buffered in the resampler only when processing // output. - EXPECT_EQ(ad.BufferSize(), 19200U); + EXPECT_EQ(ad.BufferSize(), 9600U); } TEST(TestAudioDriftCorrection, DynamicInputBufferSizeChanges) @@ -329,9 +331,9 @@ TEST(TestAudioDriftCorrection, DynamicInputBufferSizeChanges) if (((receivedFramesStart - transmittedFramesStart + i) / aTransmitterBlockSize) > numBlocksTransmitted) { tone.Generate(inSegment, aTransmitterBlockSize); - MOZ_ASSERT(!inSegment.IsNull()); + MOZ_RELEASE_ASSERT(!inSegment.IsNull()); inToneVerifier.AppendData(inSegment); - MOZ_ASSERT(!inSegment.IsNull()); + MOZ_RELEASE_ASSERT(!inSegment.IsNull()); ++numBlocksTransmitted; totalFramesTransmitted += aTransmitterBlockSize; } @@ -459,29 +461,50 @@ TEST(TestAudioDriftCorrection, DriftStepResponseUnderrunHighLatencyInput) constexpr uint32_t iterations = 200; const PrincipalHandle testPrincipal = MakePrincipalHandle(nsContentUtils::GetSystemPrincipal()); - uint32_t inputRate = nominalRate * 1005 / 1000; // 0.5% drift - uint32_t inputInterval = inputRate; + uint32_t inputRate1 = nominalRate * 1005 / 1000; // 0.5% drift + uint32_t inputInterval1 = inputRate1; AudioGenerator<AudioDataValue> tone(1, nominalRate, 440); AudioDriftCorrection ad(nominalRate, nominalRate, testPrincipal); for (uint32_t i = 0; i < interval * iterations; i += interval / 100) { AudioSegment inSegment; if (i > 0 && i % interval == 0) { - tone.Generate(inSegment, inputInterval); + tone.Generate(inSegment, inputInterval1); } ad.RequestFrames(inSegment, interval / 100); } - inputRate = nominalRate * 995 / 1000; // -0.5% drift - inputInterval = inputRate; + uint32_t inputRate2 = nominalRate * 995 / 1000; // -0.5% drift + uint32_t inputInterval2 = inputRate2; for (uint32_t i = 0; i < interval * iterations; i += interval / 100) { AudioSegment inSegment; + // The first segment is skipped to cause an underrun. if (i > 0 && i % interval == 0) { - tone.Generate(inSegment, inputInterval); + tone.Generate(inSegment, inputInterval2); } ad.RequestFrames(inSegment, interval / 100); + if (i >= interval / 10 && i < interval) { + // While the DynamicResampler has not set its pre-buffer after the + // underrun, InFramesBuffered() reports the pre-buffer size. + // The initial desired buffer and pre-buffer size was + // inputInterval1 * 11 / 10 to accomodate the large input block size. + // This was doubled when the underrun occurred. + EXPECT_EQ(ad.CurrentBuffering(), inputInterval1 * 11 / 10 * 2) + << "for i=" << i; + } else if (i == interval) { + // After the pre-buffer was set and used to generate the first output + // block, the actual number of frames buffered almost matches the + // pre-buffer size, with some rounding from output to input frame count + // conversion. + EXPECT_EQ(ad.CurrentBuffering(), inputInterval1 * 11 / 10 * 2 - 1) + << "after first input after underrun"; + } } - EXPECT_EQ(ad.BufferSize(), 220800U); + // The initial desired buffering and pre-buffering level was + // inputInterval1 * 11 / 10 to accomodate the large input block size. + // The buffer size was initially twice the pre-buffering level, and then + // doubled when the underrun occurred. + EXPECT_EQ(ad.BufferSize(), inputInterval1 * 11 / 10 * 2 * 2); EXPECT_EQ(ad.NumUnderruns(), 1u); } @@ -511,7 +534,7 @@ TEST(TestAudioDriftCorrection, DriftStepResponseOverrun) ad.RequestFrames(inSegment, interval / 100); } - // Change input callbacks to 2000ms (+0.5% drift) = 48200 frames, which will + // Change input callbacks to 1000ms (+0.5% drift) = 48200 frames, which will // overrun the ring buffer. for (uint32_t i = 0; i < interval * iterations; i += interval / 100) { AudioSegment inSegment; @@ -524,6 +547,9 @@ TEST(TestAudioDriftCorrection, DriftStepResponseOverrun) ad.RequestFrames(inSegment, interval / 100); } - EXPECT_EQ(ad.BufferSize(), 105600U); + // The desired buffering and pre-buffering levels were increased to + // inputInterval * 11 / 10 to accomodate the large input block size. + // The buffer size was increased to twice the pre-buffering level. + EXPECT_EQ(ad.BufferSize(), inputInterval * 11 / 10 * 2); EXPECT_EQ(ad.NumUnderruns(), 1u); } diff --git a/dom/media/driftcontrol/gtest/TestAudioResampler.cpp b/dom/media/driftcontrol/gtest/TestAudioResampler.cpp index f04bc87314..7122b60a1a 100644 --- a/dom/media/driftcontrol/gtest/TestAudioResampler.cpp +++ b/dom/media/driftcontrol/gtest/TestAudioResampler.cpp @@ -64,8 +64,7 @@ TEST(TestAudioResampler, OutAudioSegment_Float) uint32_t pre_buffer = 21; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioSegment inSegment = CreateAudioSegment<float>(in_frames, channels, AUDIO_FORMAT_FLOAT32); @@ -91,9 +90,9 @@ TEST(TestAudioResampler, OutAudioSegment_Float) } } - // Update out rate - out_rate = 44100; - dr.UpdateOutRate(out_rate); + // Update in rate + in_rate = 26122; + dr.UpdateInRate(in_rate); out_frames = in_frames * out_rate / in_rate; EXPECT_EQ(out_frames, 18u); // Even if we provide no input if we have enough buffered input, we can create @@ -121,8 +120,7 @@ TEST(TestAudioResampler, OutAudioSegment_Short) uint32_t pre_buffer = 21; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioSegment inSegment = CreateAudioSegment<short>(in_frames, channels, AUDIO_FORMAT_S16); @@ -148,9 +146,9 @@ TEST(TestAudioResampler, OutAudioSegment_Short) } } - // Update out rate - out_rate = 44100; - dr.UpdateOutRate(out_rate); + // Update in rate + in_rate = 26122; + dr.UpdateInRate(out_rate); out_frames = in_frames * out_rate / in_rate; EXPECT_EQ(out_frames, 18u); // Even if we provide no input if we have enough buffered input, we can create @@ -175,8 +173,7 @@ TEST(TestAudioResampler, OutAudioSegmentLargerThanResampledInput_Float) uint32_t pre_buffer = 5; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - PRINCIPAL_HANDLE_NONE); + AudioResampler dr(in_rate, out_rate, pre_buffer, PRINCIPAL_HANDLE_NONE); AudioSegment inSegment = CreateAudioSegment<float>(in_frames, channels, AUDIO_FORMAT_FLOAT32); @@ -209,8 +206,7 @@ TEST(TestAudioResampler, InAudioSegment_Float) uint32_t out_rate = 48000; uint32_t pre_buffer = 10; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioSegment inSegment; @@ -275,8 +271,7 @@ TEST(TestAudioResampler, InAudioSegment_Short) uint32_t out_rate = 48000; uint32_t pre_buffer = 10; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioSegment inSegment; @@ -342,8 +337,7 @@ TEST(TestAudioResampler, ChannelChange_MonoToStereo) uint32_t pre_buffer = 0; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioChunk monoChunk = CreateAudioChunk<float>(in_frames, 1, AUDIO_FORMAT_FLOAT32); @@ -378,8 +372,7 @@ TEST(TestAudioResampler, ChannelChange_StereoToMono) uint32_t pre_buffer = 0; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioChunk monoChunk = CreateAudioChunk<float>(in_frames, 1, AUDIO_FORMAT_FLOAT32); @@ -414,8 +407,7 @@ TEST(TestAudioResampler, ChannelChange_StereoToQuad) uint32_t pre_buffer = 0; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, pre_buffer, testPrincipal); AudioChunk stereoChunk = CreateAudioChunk<float>(in_frames, 2, AUDIO_FORMAT_FLOAT32); @@ -452,7 +444,7 @@ TEST(TestAudioResampler, ChannelChange_QuadToStereo) uint32_t in_rate = 24000; uint32_t out_rate = 48000; - AudioResampler dr(in_rate, out_rate, media::TimeUnit::Zero(), testPrincipal); + AudioResampler dr(in_rate, out_rate, 0, testPrincipal); AudioChunk stereoChunk = CreateAudioChunk<float>(in_frames, 2, AUDIO_FORMAT_FLOAT32); @@ -497,7 +489,7 @@ TEST(TestAudioResampler, ChannelChange_Discontinuity) uint32_t in_frames = in_rate / 100; uint32_t out_frames = out_rate / 100; - AudioResampler dr(in_rate, out_rate, media::TimeUnit::Zero(), testPrincipal); + AudioResampler dr(in_rate, out_rate, 0, testPrincipal); AudioChunk monoChunk = CreateAudioChunk<float>(in_frames, 1, AUDIO_FORMAT_FLOAT32); @@ -560,8 +552,7 @@ TEST(TestAudioResampler, ChannelChange_Discontinuity2) uint32_t in_frames = in_rate / 100; uint32_t out_frames = out_rate / 100; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(10, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, 10, testPrincipal); AudioChunk monoChunk = CreateAudioChunk<float>(in_frames / 2, 1, AUDIO_FORMAT_FLOAT32); @@ -630,8 +621,7 @@ TEST(TestAudioResampler, ChannelChange_Discontinuity3) uint32_t in_frames = in_rate / 100; uint32_t out_frames = out_rate / 100; - AudioResampler dr(in_rate, out_rate, media::TimeUnit(10, in_rate), - testPrincipal); + AudioResampler dr(in_rate, out_rate, 10, testPrincipal); AudioChunk stereoChunk = CreateAudioChunk<float>(in_frames, 2, AUDIO_FORMAT_FLOAT32); @@ -660,9 +650,9 @@ TEST(TestAudioResampler, ChannelChange_Discontinuity3) // The resampler here is updated due to the rate change. This is because the // in and out rate was the same so a pass through logic was used. By updating - // the out rate to something different than the in rate, the resampler will + // the in rate to something different than the out rate, the resampler will // start being used and discontinuity will exist. - dr.UpdateOutRate(out_rate + 400); + dr.UpdateInRate(in_rate - 400); dr.AppendInput(inSegment); AudioSegment s2 = dr.Resample(out_frames, &hasUnderrun); EXPECT_FALSE(hasUnderrun); diff --git a/dom/media/driftcontrol/gtest/TestDriftController.cpp b/dom/media/driftcontrol/gtest/TestDriftController.cpp index 33486f945f..132577e44a 100644 --- a/dom/media/driftcontrol/gtest/TestDriftController.cpp +++ b/dom/media/driftcontrol/gtest/TestDriftController.cpp @@ -18,50 +18,50 @@ TEST(TestDriftController, Basic) constexpr uint32_t bufferedHigh = 7 * 480; DriftController c(48000, 48000, media::TimeUnit::FromSeconds(0.05)); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000U); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000U); // The adjustment interval is 1s. const auto oneSec = media::TimeUnit(48000, 48000); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedLow, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48048u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 47952u); c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 47952u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48048u); } TEST(TestDriftController, BasicResampler) { // The buffer level is the only input to the controller logic. - constexpr uint32_t buffered = 5 * 240; - constexpr uint32_t bufferedLow = 3 * 240; - constexpr uint32_t bufferedHigh = 7 * 240; + constexpr uint32_t buffered = 5 * 480; + constexpr uint32_t bufferedLow = 3 * 480; + constexpr uint32_t bufferedHigh = 7 * 480; - DriftController c(24000, 48000, media::TimeUnit::FromSeconds(0.05)); + DriftController c(48000, 24000, media::TimeUnit::FromSeconds(0.05)); // The adjustment interval is 1s. const auto oneSec = media::TimeUnit(48000, 48000); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // low c.UpdateClock(oneSec, oneSec, bufferedLow, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48048u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 47952u); // high c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // high c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 47964u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48048u); } TEST(TestDriftController, BufferedInput) @@ -72,56 +72,56 @@ TEST(TestDriftController, BufferedInput) constexpr uint32_t bufferedHigh = 7 * 480; DriftController c(48000, 48000, media::TimeUnit::FromSeconds(0.05)); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // The adjustment interval is 1s. const auto oneSec = media::TimeUnit(48000, 48000); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // 0 buffered when updating correction c.UpdateClock(oneSec, oneSec, 0, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48048u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 47952u); c.UpdateClock(oneSec, oneSec, bufferedLow, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 47952u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48048u); } TEST(TestDriftController, BufferedInputWithResampling) { // The buffer level is the only input to the controller logic. - constexpr uint32_t buffered = 5 * 240; - constexpr uint32_t bufferedLow = 3 * 240; - constexpr uint32_t bufferedHigh = 7 * 240; + constexpr uint32_t buffered = 5 * 480; + constexpr uint32_t bufferedLow = 3 * 480; + constexpr uint32_t bufferedHigh = 7 * 480; - DriftController c(24000, 48000, media::TimeUnit::FromSeconds(0.05)); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + DriftController c(48000, 24000, media::TimeUnit::FromSeconds(0.05)); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // The adjustment interval is 1s. const auto oneSec = media::TimeUnit(24000, 24000); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // 0 buffered when updating correction c.UpdateClock(oneSec, oneSec, 0, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48048u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 47952u); c.UpdateClock(oneSec, oneSec, bufferedLow, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 47952u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48048u); } TEST(TestDriftController, SmallError) @@ -132,21 +132,21 @@ TEST(TestDriftController, SmallError) constexpr uint32_t bufferedHigh = buffered + 48; DriftController c(48000, 48000, media::TimeUnit::FromSeconds(0.05)); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); // The adjustment interval is 1s. const auto oneSec = media::TimeUnit(48000, 48000); c.UpdateClock(oneSec, oneSec, buffered, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedLow, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); c.UpdateClock(oneSec, oneSec, bufferedHigh, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000u); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000u); } TEST(TestDriftController, SmallBufferedFrames) @@ -158,11 +158,34 @@ TEST(TestDriftController, SmallBufferedFrames) media::TimeUnit oneSec = media::TimeUnit::FromSeconds(1); media::TimeUnit hundredMillis = oneSec / 10; - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000U); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000U); for (uint32_t i = 0; i < 9; ++i) { c.UpdateClock(hundredMillis, hundredMillis, bufferedLow, 0); } - EXPECT_EQ(c.GetCorrectedTargetRate(), 48000U); + EXPECT_EQ(c.GetCorrectedSourceRate(), 48000U); c.UpdateClock(hundredMillis, hundredMillis, bufferedLow, 0); - EXPECT_EQ(c.GetCorrectedTargetRate(), 48048U); + EXPECT_EQ(c.GetCorrectedSourceRate(), 47952U); +} + +TEST(TestDriftController, VerySmallBufferedFrames) +{ + // The buffer level is the only input to the controller logic. + uint32_t bufferedLow = 1; + uint32_t nominalRate = 48000; + + DriftController c(nominalRate, nominalRate, media::TimeUnit::FromSeconds(1)); + media::TimeUnit oneSec = media::TimeUnit::FromSeconds(1); + media::TimeUnit sourceDuration(1, nominalRate); + + EXPECT_EQ(c.GetCorrectedSourceRate(), nominalRate); + uint32_t previousCorrected = nominalRate; + // Steps are limited to nominalRate/1000. + // Perform 1001 steps to check the corrected rate does not underflow zero. + for (uint32_t i = 0; i < 1001; ++i) { + c.UpdateClock(sourceDuration, oneSec, bufferedLow, 0); + uint32_t correctedRate = c.GetCorrectedSourceRate(); + EXPECT_LE(correctedRate, previousCorrected) << "for i=" << i; + EXPECT_GT(correctedRate, 0u) << "for i=" << i; + previousCorrected = correctedRate; + } } diff --git a/dom/media/driftcontrol/gtest/TestDynamicResampler.cpp b/dom/media/driftcontrol/gtest/TestDynamicResampler.cpp index fb8ac52ae4..539dfbfbea 100644 --- a/dom/media/driftcontrol/gtest/TestDynamicResampler.cpp +++ b/dom/media/driftcontrol/gtest/TestDynamicResampler.cpp @@ -19,7 +19,7 @@ TEST(TestDynamicResampler, SameRates_Float1) DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32); - EXPECT_EQ(dr.GetOutRate(), out_rate); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); // float in_ch1[] = {.1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0}; @@ -76,7 +76,7 @@ TEST(TestDynamicResampler, SameRates_Short1) DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_S16); - EXPECT_EQ(dr.GetOutRate(), out_rate); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); short in_ch1[] = {1, 2, 3}; @@ -298,9 +298,9 @@ TEST(TestDynamicResampler, UpdateOutRate_Float) uint32_t pre_buffer = 20; - DynamicResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate)); + DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32); - EXPECT_EQ(dr.GetOutRate(), out_rate); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); float in_ch1[10] = {}; @@ -329,10 +329,10 @@ TEST(TestDynamicResampler, UpdateOutRate_Float) EXPECT_FLOAT_EQ(out_ch2[i], 0.0); } - // Update out rate - out_rate = 44100; - dr.UpdateResampler(out_rate, channels); - EXPECT_EQ(dr.GetOutRate(), out_rate); + // Update in rate + in_rate = 26122; + dr.UpdateResampler(in_rate, channels); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); out_frames = in_frames * out_rate / in_rate; EXPECT_EQ(out_frames, 18u); @@ -354,9 +354,9 @@ TEST(TestDynamicResampler, UpdateOutRate_Short) uint32_t pre_buffer = 20; - DynamicResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate)); + DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_S16); - EXPECT_EQ(dr.GetOutRate(), out_rate); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); short in_ch1[10] = {}; @@ -385,10 +385,10 @@ TEST(TestDynamicResampler, UpdateOutRate_Short) EXPECT_EQ(out_ch2[i], 0.0); } - // Update out rate - out_rate = 44100; - dr.UpdateResampler(out_rate, channels); - EXPECT_EQ(dr.GetOutRate(), out_rate); + // Update in rate + in_rate = 26122; + dr.UpdateResampler(in_rate, channels); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); out_frames = in_frames * out_rate / in_rate; EXPECT_EQ(out_frames, 18u); @@ -400,16 +400,15 @@ TEST(TestDynamicResampler, UpdateOutRate_Short) EXPECT_FALSE(hasUnderrun); } -TEST(TestDynamicResampler, BigRangeOutRates_Float) +TEST(TestDynamicResampler, BigRangeInRates_Float) { uint32_t in_frames = 10; uint32_t out_frames = 10; uint32_t channels = 2; uint32_t in_rate = 44100; uint32_t out_rate = 44100; - uint32_t pre_buffer = 20; - DynamicResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate)); + DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32); const uint32_t in_capacity = 40; @@ -427,10 +426,14 @@ TEST(TestDynamicResampler, BigRangeOutRates_Float) float out_ch1[out_capacity] = {}; float out_ch2[out_capacity] = {}; - for (uint32_t rate = 10000; rate < 90000; ++rate) { - out_rate = rate; - dr.UpdateResampler(out_rate, channels); - EXPECT_EQ(dr.GetOutRate(), out_rate); + // Downsampling at a high enough ratio happens to have enough excess + // in_frames from rounding in the out_frames calculation to cover the + // skipped input latency when switching from zero-latency 44100->44100 to a + // non-1:1 ratio. + for (uint32_t rate = 100000; rate >= 10000; rate -= 2) { + in_rate = rate; + dr.UpdateResampler(in_rate, channels); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); in_frames = 20; // more than we need out_frames = in_frames * out_rate / in_rate; @@ -444,16 +447,15 @@ TEST(TestDynamicResampler, BigRangeOutRates_Float) } } -TEST(TestDynamicResampler, BigRangeOutRates_Short) +TEST(TestDynamicResampler, BigRangeInRates_Short) { uint32_t in_frames = 10; uint32_t out_frames = 10; uint32_t channels = 2; uint32_t in_rate = 44100; uint32_t out_rate = 44100; - uint32_t pre_buffer = 20; - DynamicResampler dr(in_rate, out_rate, media::TimeUnit(pre_buffer, in_rate)); + DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_S16); const uint32_t in_capacity = 40; @@ -471,9 +473,9 @@ TEST(TestDynamicResampler, BigRangeOutRates_Short) short out_ch1[out_capacity] = {}; short out_ch2[out_capacity] = {}; - for (uint32_t rate = 10000; rate < 90000; ++rate) { - out_rate = rate; - dr.UpdateResampler(out_rate, channels); + for (uint32_t rate = 100000; rate >= 10000; rate -= 2) { + in_rate = rate; + dr.UpdateResampler(in_rate, channels); in_frames = 20; // more than we need out_frames = in_frames * out_rate / in_rate; for (uint32_t y = 0; y < 2; ++y) { @@ -517,8 +519,8 @@ TEST(TestDynamicResampler, UpdateChannels_Float) EXPECT_FALSE(hasUnderrun); // Add 3rd channel - dr.UpdateResampler(out_rate, 3); - EXPECT_EQ(dr.GetOutRate(), out_rate); + dr.UpdateResampler(in_rate, 3); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), 3u); float in_ch3[10] = {}; @@ -546,8 +548,8 @@ TEST(TestDynamicResampler, UpdateChannels_Float) in_buffer[3] = in_ch4; float out_ch4[10] = {}; - dr.UpdateResampler(out_rate, 4); - EXPECT_EQ(dr.GetOutRate(), out_rate); + dr.UpdateResampler(in_rate, 4); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), 4u); dr.AppendInput(in_buffer, in_frames); @@ -592,8 +594,8 @@ TEST(TestDynamicResampler, UpdateChannels_Short) EXPECT_FALSE(hasUnderrun); // Add 3rd channel - dr.UpdateResampler(out_rate, 3); - EXPECT_EQ(dr.GetOutRate(), out_rate); + dr.UpdateResampler(in_rate, 3); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), 3u); short in_ch3[10] = {}; @@ -622,8 +624,8 @@ TEST(TestDynamicResampler, UpdateChannels_Short) in_buffer[3] = in_ch4; short out_ch4[10] = {}; - dr.UpdateResampler(out_rate, 4); - EXPECT_EQ(dr.GetOutRate(), out_rate); + dr.UpdateResampler(in_rate, 4); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), 4u); dr.AppendInput(in_buffer, in_frames); @@ -647,7 +649,7 @@ TEST(TestDynamicResampler, Underrun) DynamicResampler dr(in_rate, out_rate); dr.SetSampleFormat(AUDIO_FORMAT_FLOAT32); - EXPECT_EQ(dr.GetOutRate(), out_rate); + EXPECT_EQ(dr.GetInRate(), in_rate); EXPECT_EQ(dr.GetChannels(), channels); float in_ch1[in_frames] = {}; @@ -689,7 +691,7 @@ TEST(TestDynamicResampler, Underrun) } // Now try with resampling. - dr.UpdateResampler(out_rate / 2, channels); + dr.UpdateResampler(in_rate * 2, channels); dr.AppendInput(in_buffer, in_frames); hasUnderrun = dr.Resample(out_ch1, out_frames, 0); EXPECT_TRUE(hasUnderrun); |