TestAudioTrackEncoder.cpp (10399B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "AudioGenerator.h" 8 #include "AudioSampleFormat.h" 9 #include "OpusTrackEncoder.h" 10 #include "gtest/gtest.h" 11 12 using namespace mozilla; 13 14 class TestOpusTrackEncoder : public OpusTrackEncoder { 15 public: 16 TestOpusTrackEncoder(TrackRate aTrackRate, 17 MediaQueue<EncodedFrame>& aEncodedDataQueue) 18 : OpusTrackEncoder(aTrackRate, aEncodedDataQueue) {} 19 20 // Return true if it has successfully initialized the Opus encoder. 21 bool TestOpusRawCreation(int aChannels) { 22 if (Init(aChannels) == NS_OK) { 23 if (IsInitialized()) { 24 return true; 25 } 26 } 27 return false; 28 } 29 }; 30 31 static bool TestOpusInit(int aChannels, TrackRate aSamplingRate) { 32 MediaQueue<EncodedFrame> frames; 33 TestOpusTrackEncoder encoder(aSamplingRate, frames); 34 return encoder.TestOpusRawCreation(aChannels); 35 } 36 37 TEST(OpusAudioTrackEncoder, InitRaw) 38 { 39 // Expect false with 0 or negative channels of input signal. 40 EXPECT_FALSE(TestOpusInit(0, 16000)); 41 EXPECT_FALSE(TestOpusInit(-1, 16000)); 42 43 // The Opus format supports up to 8 channels, and supports multitrack audio up 44 // to 255 channels, but the current implementation supports only mono and 45 // stereo, and downmixes any more than that. 46 // Expect false with channels of input signal exceed the max supported number. 47 EXPECT_FALSE(TestOpusInit(8 + 1, 16000)); 48 49 // Should accept channels within valid range. 50 for (int i = 1; i <= 8; i++) { 51 EXPECT_TRUE(TestOpusInit(i, 16000)); 52 } 53 54 // Expect false with 0 or negative sampling rate of input signal. 55 EXPECT_FALSE(TestOpusInit(1, 0)); 56 EXPECT_FALSE(TestOpusInit(1, -1)); 57 58 // Verify sample rate bounds checking. 59 EXPECT_FALSE(TestOpusInit(2, 2000)); 60 EXPECT_FALSE(TestOpusInit(2, 4000)); 61 EXPECT_FALSE(TestOpusInit(2, 7999)); 62 EXPECT_TRUE(TestOpusInit(2, 8000)); 63 EXPECT_TRUE(TestOpusInit(2, 192000)); 64 EXPECT_FALSE(TestOpusInit(2, 192001)); 65 EXPECT_FALSE(TestOpusInit(2, 200000)); 66 } 67 68 TEST(OpusAudioTrackEncoder, Init) 69 { 70 { 71 // The encoder does not normally recieve enough info from null data to 72 // init. However, multiple attempts to do so, with sufficiently long 73 // duration segments, should result in a default-init. The first attempt 74 // should never do this though, even if the duration is long: 75 MediaQueue<EncodedFrame> frames; 76 OpusTrackEncoder encoder(48000, frames); 77 AudioSegment segment; 78 segment.AppendNullData(48000 * 100); 79 encoder.TryInit(segment, segment.GetDuration()); 80 EXPECT_FALSE(encoder.IsInitialized()); 81 82 // Multiple init attempts should result in best effort init: 83 encoder.TryInit(segment, segment.GetDuration()); 84 EXPECT_TRUE(encoder.IsInitialized()); 85 } 86 87 { 88 // For non-null segments we should init immediately 89 MediaQueue<EncodedFrame> frames; 90 OpusTrackEncoder encoder(48000, frames); 91 AudioSegment segment; 92 AudioGenerator<AudioDataValue> generator(2, 48000); 93 generator.Generate(segment, 1); 94 encoder.TryInit(segment, segment.GetDuration()); 95 EXPECT_TRUE(encoder.IsInitialized()); 96 } 97 98 { 99 // Test low sample rate bound 100 MediaQueue<EncodedFrame> frames; 101 OpusTrackEncoder encoder(7999, frames); 102 AudioSegment segment; 103 AudioGenerator<AudioDataValue> generator(2, 7999); 104 generator.Generate(segment, 1); 105 encoder.TryInit(segment, segment.GetDuration()); 106 EXPECT_FALSE(encoder.IsInitialized()); 107 } 108 109 { 110 // Test low sample rate bound 111 MediaQueue<EncodedFrame> frames; 112 OpusTrackEncoder encoder(8000, frames); 113 AudioSegment segment; 114 AudioGenerator<AudioDataValue> generator(2, 8000); 115 generator.Generate(segment, 1); 116 encoder.TryInit(segment, segment.GetDuration()); 117 EXPECT_TRUE(encoder.IsInitialized()); 118 } 119 120 { 121 // Test high sample rate bound 122 MediaQueue<EncodedFrame> frames; 123 OpusTrackEncoder encoder(192001, frames); 124 AudioSegment segment; 125 AudioGenerator<AudioDataValue> generator(2, 192001); 126 generator.Generate(segment, 1); 127 encoder.TryInit(segment, segment.GetDuration()); 128 EXPECT_FALSE(encoder.IsInitialized()); 129 } 130 131 { 132 // Test high sample rate bound 133 MediaQueue<EncodedFrame> frames; 134 OpusTrackEncoder encoder(192000, frames); 135 AudioSegment segment; 136 AudioGenerator<AudioDataValue> generator(2, 192000); 137 generator.Generate(segment, 1); 138 encoder.TryInit(segment, segment.GetDuration()); 139 EXPECT_TRUE(encoder.IsInitialized()); 140 } 141 142 { 143 // Test that it takes 10s to trigger default-init. 144 MediaQueue<EncodedFrame> frames; 145 OpusTrackEncoder encoder(48000, frames); 146 AudioSegment longSegment; 147 longSegment.AppendNullData(48000 * 10 - 1); 148 AudioSegment shortSegment; 149 shortSegment.AppendNullData(1); 150 encoder.TryInit(longSegment, longSegment.GetDuration()); 151 EXPECT_FALSE(encoder.IsInitialized()); 152 encoder.TryInit(shortSegment, shortSegment.GetDuration()); 153 EXPECT_FALSE(encoder.IsInitialized()); 154 encoder.TryInit(shortSegment, shortSegment.GetDuration()); 155 EXPECT_TRUE(encoder.IsInitialized()); 156 } 157 } 158 159 static int TestOpusResampler(TrackRate aSamplingRate) { 160 MediaQueue<EncodedFrame> frames; 161 OpusTrackEncoder encoder(aSamplingRate, frames); 162 return encoder.mOutputSampleRate; 163 } 164 165 TEST(OpusAudioTrackEncoder, Resample) 166 { 167 // Sampling rates of data to be fed to Opus encoder, should remain unchanged 168 // if it is one of Opus supported rates (8000, 12000, 16000, 24000 and 48000 169 // (kHz)) at initialization. 170 EXPECT_TRUE(TestOpusResampler(8000) == 8000); 171 EXPECT_TRUE(TestOpusResampler(12000) == 12000); 172 EXPECT_TRUE(TestOpusResampler(16000) == 16000); 173 EXPECT_TRUE(TestOpusResampler(24000) == 24000); 174 EXPECT_TRUE(TestOpusResampler(48000) == 48000); 175 176 // Otherwise, it should be resampled to 48kHz by resampler. 177 EXPECT_TRUE(TestOpusResampler(9600) == 48000); 178 EXPECT_TRUE(TestOpusResampler(44100) == 48000); 179 } 180 181 TEST(OpusAudioTrackEncoder, FetchMetadata) 182 { 183 const int32_t channels = 1; 184 const TrackRate sampleRate = 44100; 185 MediaQueue<EncodedFrame> frames; 186 TestOpusTrackEncoder encoder(sampleRate, frames); 187 EXPECT_TRUE(encoder.TestOpusRawCreation(channels)); 188 189 RefPtr<TrackMetadataBase> metadata = encoder.GetMetadata(); 190 ASSERT_EQ(TrackMetadataBase::METADATA_OPUS, metadata->GetKind()); 191 192 RefPtr<OpusMetadata> opusMeta = static_cast<OpusMetadata*>(metadata.get()); 193 EXPECT_EQ(channels, opusMeta->mChannels); 194 EXPECT_EQ(sampleRate, opusMeta->mSamplingFrequency); 195 } 196 197 TEST(OpusAudioTrackEncoder, FrameEncode) 198 { 199 const int32_t channels = 1; 200 const TrackRate sampleRate = 44100; 201 MediaQueue<EncodedFrame> frames; 202 TestOpusTrackEncoder encoder(sampleRate, frames); 203 EXPECT_TRUE(encoder.TestOpusRawCreation(channels)); 204 205 // Generate five seconds of raw audio data. 206 AudioGenerator<AudioDataValue> generator(channels, sampleRate); 207 AudioSegment segment; 208 const int32_t samples = sampleRate * 5; 209 generator.Generate(segment, samples); 210 211 encoder.AppendAudioSegment(std::move(segment)); 212 encoder.NotifyEndOfStream(); 213 214 EXPECT_TRUE(encoder.IsEncodingComplete()); 215 EXPECT_TRUE(frames.IsFinished()); 216 217 // Verify that encoded data is 5 seconds long. 218 uint64_t totalDuration = 0; 219 while (RefPtr<EncodedFrame> frame = frames.PopFront()) { 220 totalDuration += frame->mDuration; 221 } 222 // 44100 as used above gets resampled to 48000 for opus. 223 const uint64_t five = 48000 * 5; 224 EXPECT_EQ(five + encoder.GetLookahead(), totalDuration); 225 } 226 227 TEST(OpusAudioTrackEncoder, DefaultInitDuration) 228 { 229 const TrackRate rate = 44100; 230 MediaQueue<EncodedFrame> frames; 231 OpusTrackEncoder encoder(rate, frames); 232 AudioGenerator<AudioDataValue> generator(2, rate); 233 AudioSegment segment; 234 // 15 seconds should trigger the default-init rate. 235 // The default-init timeout is evaluated once per chunk, so keep chunks 236 // reasonably short. 237 for (int i = 0; i < 150; ++i) { 238 generator.Generate(segment, rate / 10); 239 } 240 encoder.AppendAudioSegment(std::move(segment)); 241 encoder.NotifyEndOfStream(); 242 243 EXPECT_TRUE(encoder.IsEncodingComplete()); 244 EXPECT_TRUE(frames.IsFinished()); 245 246 // Verify that encoded data is 15 seconds long. 247 uint64_t totalDuration = 0; 248 while (RefPtr<EncodedFrame> frame = frames.PopFront()) { 249 totalDuration += frame->mDuration; 250 } 251 // 44100 as used above gets resampled to 48000 for opus. 252 const uint64_t fifteen = 48000 * 15; 253 EXPECT_EQ(totalDuration, fifteen + encoder.GetLookahead()); 254 } 255 256 uint64_t TestSampleRate(TrackRate aSampleRate, uint64_t aInputFrames) { 257 MediaQueue<EncodedFrame> frames; 258 OpusTrackEncoder encoder(aSampleRate, frames); 259 AudioGenerator<AudioDataValue> generator(2, aSampleRate); 260 AudioSegment segment; 261 const uint64_t chunkSize = aSampleRate / 10; 262 const uint64_t chunks = aInputFrames / chunkSize; 263 // 15 seconds should trigger the default-init rate. 264 // The default-init timeout is evaluated once per chunk, so keep chunks 265 // reasonably short. 266 for (size_t i = 0; i < chunks; ++i) { 267 generator.Generate(segment, chunkSize); 268 } 269 generator.Generate(segment, aInputFrames % chunks); 270 encoder.AppendAudioSegment(std::move(segment)); 271 encoder.NotifyEndOfStream(); 272 273 EXPECT_TRUE(encoder.IsEncodingComplete()); 274 EXPECT_TRUE(frames.IsFinished()); 275 276 // Verify that encoded data is 15 seconds long. 277 uint64_t totalDuration = 0; 278 while (RefPtr<EncodedFrame> frame = frames.PopFront()) { 279 totalDuration += frame->mDuration; 280 } 281 return totalDuration - encoder.GetLookahead(); 282 } 283 284 TEST(OpusAudioTrackEncoder, DurationSampleRates) 285 { 286 // Factors of 48k 287 EXPECT_EQ(TestSampleRate(48000, 48000 * 3 / 2), 48000U * 3 / 2); 288 EXPECT_EQ(TestSampleRate(24000, 24000 * 3 / 2), 48000U * 3 / 2); 289 EXPECT_EQ(TestSampleRate(16000, 16000 * 3 / 2), 48000U * 3 / 2); 290 EXPECT_EQ(TestSampleRate(12000, 12000 * 3 / 2), 48000U * 3 / 2); 291 EXPECT_EQ(TestSampleRate(8000, 8000 * 3 / 2), 48000U * 3 / 2); 292 293 // Non-factors of 48k, resampled 294 EXPECT_EQ(TestSampleRate(44100, 44100 * 3 / 2), 48000U * 3 / 2); 295 EXPECT_EQ(TestSampleRate(32000, 32000 * 3 / 2), 48000U * 3 / 2); 296 EXPECT_EQ(TestSampleRate(96000, 96000 * 3 / 2), 48000U * 3 / 2); 297 EXPECT_EQ(TestSampleRate(33330, 33330 * 3 / 2), 48000U * 3 / 2); 298 }