1 /*
2 * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3 *
4 * This source code is subject to the terms of the BSD 3-Clause Clear License
5 * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6 * License was not distributed with this source code in the LICENSE file, you
7 * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8 * Alliance for Open Media Patent License 1.0 was not distributed with this
9 * source code in the PATENTS file, you can obtain it at
10 * www.aomedia.org/license/patent.
11 */
12 #include "iamf/obu/codec_config.h"
13
14 #include <sys/stat.h>
15
16 #include <cstdint>
17 #include <limits>
18 #include <memory>
19 #include <variant>
20 #include <vector>
21
22 #include "absl/status/status.h"
23 #include "absl/status/status_matchers.h"
24 #include "absl/status/statusor.h"
25 #include "absl/types/span.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include "iamf/common/leb_generator.h"
29 #include "iamf/common/read_bit_buffer.h"
30 #include "iamf/common/write_bit_buffer.h"
31 #include "iamf/obu/decoder_config/aac_decoder_config.h"
32 #include "iamf/obu/decoder_config/flac_decoder_config.h"
33 #include "iamf/obu/decoder_config/lpcm_decoder_config.h"
34 #include "iamf/obu/decoder_config/opus_decoder_config.h"
35 #include "iamf/obu/obu_header.h"
36 #include "iamf/obu/tests/obu_test_base.h"
37 #include "iamf/obu/types.h"
38
39 namespace iamf_tools {
40 namespace {
41
42 using ::absl_testing::IsOk;
43
44 constexpr bool kOverrideAudioRollDistance = true;
45 constexpr bool kDontOverrideAudioRollDistance = false;
46 constexpr int16_t kInvalidAudioRollDistance = 123;
47 constexpr int16_t kLpcmAudioRollDistance = 0;
48 constexpr DecodedUleb128 kCodecConfigId = 123;
49 constexpr int16_t kArbitraryCodecDelay = 999;
50
51 // Despite being represented in 4-bits the AAC Sampling Frequency Index 64000 is
52 // serialized across a byte boundary.
53 constexpr uint8_t kUpperByteSerializedSamplingFrequencyIndex64000 =
54 (static_cast<uint8_t>(AudioSpecificConfig::SampleFrequencyIndex::k64000) &
55 0x0e) >>
56 1;
57 constexpr uint8_t kLowerByteSerializedSamplingFrequencyIndex64000 =
58 (static_cast<uint8_t>(AudioSpecificConfig::SampleFrequencyIndex::k64000) &
59 0x01)
60 << 7;
61
62 class CodecConfigTestBase : public ObuTestBase {
63 public:
CodecConfigTestBase(CodecConfig::CodecId codec_id,DecoderConfig decoder_config)64 CodecConfigTestBase(CodecConfig::CodecId codec_id,
65 DecoderConfig decoder_config)
66 : ObuTestBase(
67 /*expected_header=*/{0, 14}, /*expected_payload=*/{}),
68 codec_config_id_(kCodecConfigId),
69 codec_config_({.codec_id = codec_id,
70 .num_samples_per_frame = 64,
71 .audio_roll_distance = 0,
72 .decoder_config = decoder_config}) {}
73
74 ~CodecConfigTestBase() override = default;
75
76 protected:
ConstructObu()77 void ConstructObu() {
78 obu_ = std::make_unique<CodecConfigObu>(header_, codec_config_id_,
79 codec_config_);
80 }
81
InitExpectOk()82 void InitExpectOk() override {
83 ConstructObu();
84 EXPECT_THAT(obu_->Initialize(), IsOk());
85 }
86
WriteObuExpectOk(WriteBitBuffer & wb)87 void WriteObuExpectOk(WriteBitBuffer& wb) override {
88 EXPECT_THAT(obu_->ValidateAndWriteObu(wb), IsOk());
89 }
90
TestInputSampleRate()91 void TestInputSampleRate() {
92 EXPECT_EQ(obu_->GetInputSampleRate(), expected_input_sample_rate_);
93 }
94
TestOutputSampleRate()95 void TestOutputSampleRate() {
96 EXPECT_EQ(obu_->GetOutputSampleRate(), expected_output_sample_rate_);
97 }
98
TestGetBitDepthToMeasureLoudness()99 void TestGetBitDepthToMeasureLoudness() {
100 EXPECT_EQ(obu_->GetBitDepthToMeasureLoudness(),
101 expected_output_pcm_bit_depth_);
102 }
103
104 uint32_t expected_input_sample_rate_;
105 uint32_t expected_output_sample_rate_;
106 uint8_t expected_output_pcm_bit_depth_;
107
108 std::unique_ptr<CodecConfigObu> obu_;
109
110 DecodedUleb128 codec_config_id_;
111 CodecConfig codec_config_;
112 };
113
114 struct SampleRateTestCase {
115 uint32_t sample_rate;
116 bool expect_ok;
117 };
118
119 class CodecConfigLpcmTestForSampleRate
120 : public CodecConfigTestBase,
121 public testing::TestWithParam<SampleRateTestCase> {
122 public:
CodecConfigLpcmTestForSampleRate()123 CodecConfigLpcmTestForSampleRate()
124 : CodecConfigTestBase(
125 CodecConfig::kCodecIdLpcm,
126 LpcmDecoderConfig{.sample_format_flags_bitmask_ =
127 LpcmDecoderConfig::kLpcmBigEndian,
128 .sample_size_ = 16,
129 .sample_rate_ = 48000}) {}
130 };
131
132 // Instantiate an LPCM `CodecConfigOBU` with the specified parameters. Verify
133 // the validation function returns the expected status.
TEST_P(CodecConfigLpcmTestForSampleRate,TestCodecConfigLpcm)134 TEST_P(CodecConfigLpcmTestForSampleRate, TestCodecConfigLpcm) {
135 // Replace the default sample rate and expected status codes.
136 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_rate_ =
137 GetParam().sample_rate;
138
139 obu_ = std::make_unique<CodecConfigObu>(header_, codec_config_id_,
140 codec_config_);
141
142 const bool expect_ok = GetParam().expect_ok;
143 EXPECT_EQ(obu_->Initialize().ok(), expect_ok);
144 WriteBitBuffer unused_wb(0);
145 EXPECT_EQ(obu_->ValidateAndWriteObu(unused_wb).ok(), expect_ok);
146
147 if (expect_ok) {
148 // Validate the functions to get the sample rate return the expected value.
149 expected_output_sample_rate_ = GetParam().sample_rate;
150 TestOutputSampleRate();
151
152 // The input sample rate function for LPCM should the output sample rate
153 // function.
154 expected_input_sample_rate_ = expected_output_sample_rate_;
155 TestInputSampleRate();
156 }
157 }
158
159 INSTANTIATE_TEST_SUITE_P(LegalSampleRates, CodecConfigLpcmTestForSampleRate,
160 testing::ValuesIn<SampleRateTestCase>({{48000, true},
161 {16000, true},
162 {32000, true},
163 {44100, true},
164 {48000, true},
165 {96000,
166 true}}));
167
168 INSTANTIATE_TEST_SUITE_P(
169 IllegalSampleRates, CodecConfigLpcmTestForSampleRate,
170 ::testing::ValuesIn<SampleRateTestCase>({{0, false},
171 {8000, false},
172 {22050, false},
173 {23000, false},
174 {196000, false}}));
175
176 class CodecConfigLpcmTest : public CodecConfigTestBase, public testing::Test {
177 public:
CodecConfigLpcmTest()178 CodecConfigLpcmTest()
179 : CodecConfigTestBase(
180 CodecConfig::kCodecIdLpcm,
181 LpcmDecoderConfig{.sample_format_flags_bitmask_ =
182 LpcmDecoderConfig::kLpcmBigEndian,
183 .sample_size_ = 16,
184 .sample_rate_ = 48000}) {
185 expected_payload_ = {// `codec_config_id`.
186 kCodecConfigId,
187 // `codec_id`.
188 'i', 'p', 'c', 'm',
189 // `num_samples_per_frame`.
190 64,
191 // `audio_roll_distance`.
192 0, 0,
193 // `sample_format_flags`.
194 0,
195 // `sample_size`.
196 16,
197 // `sample_rate`.
198 0, 0, 0xbb, 0x80};
199 }
200 };
201
TEST_F(CodecConfigLpcmTest,IsAlwaysLossless)202 TEST_F(CodecConfigLpcmTest, IsAlwaysLossless) {
203 InitExpectOk();
204
205 EXPECT_TRUE(obu_->IsLossless());
206 }
207
TEST_F(CodecConfigLpcmTest,SetCodecDelayIsNoOp)208 TEST_F(CodecConfigLpcmTest, SetCodecDelayIsNoOp) {
209 InitExpectOk();
210
211 EXPECT_THAT(obu_->SetCodecDelay(kArbitraryCodecDelay), IsOk());
212 }
213
TEST_F(CodecConfigLpcmTest,ConstructorSetsObuTyoe)214 TEST_F(CodecConfigLpcmTest, ConstructorSetsObuTyoe) {
215 InitExpectOk();
216
217 EXPECT_EQ(obu_->header_.obu_type, kObuIaCodecConfig);
218 }
219
TEST_F(CodecConfigLpcmTest,ConstructorSetsAudioRollDistance)220 TEST_F(CodecConfigLpcmTest, ConstructorSetsAudioRollDistance) {
221 codec_config_.audio_roll_distance = kInvalidAudioRollDistance;
222 ConstructObu();
223
224 EXPECT_EQ(obu_->GetCodecConfig().audio_roll_distance,
225 kInvalidAudioRollDistance);
226 }
227
TEST_F(CodecConfigLpcmTest,InitializeObeysInvalidAudioRollDistance)228 TEST_F(CodecConfigLpcmTest, InitializeObeysInvalidAudioRollDistance) {
229 codec_config_.audio_roll_distance = kInvalidAudioRollDistance;
230 ConstructObu();
231
232 EXPECT_THAT(obu_->Initialize(kDontOverrideAudioRollDistance), IsOk());
233
234 EXPECT_EQ(obu_->GetCodecConfig().audio_roll_distance,
235 kInvalidAudioRollDistance);
236 }
237
TEST_F(CodecConfigLpcmTest,InitializeMayOverrideAudioRollDistance)238 TEST_F(CodecConfigLpcmTest, InitializeMayOverrideAudioRollDistance) {
239 codec_config_.audio_roll_distance = kInvalidAudioRollDistance;
240 ConstructObu();
241
242 EXPECT_EQ(obu_->GetCodecConfig().audio_roll_distance,
243 kInvalidAudioRollDistance);
244 EXPECT_THAT(obu_->Initialize(kOverrideAudioRollDistance), IsOk());
245
246 EXPECT_EQ(obu_->GetCodecConfig().audio_roll_distance, kLpcmAudioRollDistance);
247 }
248
TEST_F(CodecConfigLpcmTest,NonMinimalLebGeneratorAffectsAllLeb128s)249 TEST_F(CodecConfigLpcmTest, NonMinimalLebGeneratorAffectsAllLeb128s) {
250 leb_generator_ =
251 LebGenerator::Create(LebGenerator::GenerationMode::kFixedSize, 2);
252 codec_config_id_ = 0;
253 codec_config_.num_samples_per_frame = 1;
254
255 expected_header_ = {0, 0x80 | 16, 0};
256 expected_payload_ = {// `codec_config_id`.
257 0x80, 0x00,
258 // `codec_id`.
259 'i', 'p', 'c', 'm',
260 // `num_samples_per_frame`.
261 0x81, 0x00,
262 // `audio_roll_distance`.
263 0, 0,
264 // `sample_format_flags`.
265 0,
266 // `sample_size`.
267 16,
268 // `sample_rate`.
269 0, 0, 0xbb, 0x80};
270
271 InitAndTestWrite();
272 }
273
TEST_F(CodecConfigLpcmTest,InitFailsWithIllegalCodecId)274 TEST_F(CodecConfigLpcmTest, InitFailsWithIllegalCodecId) {
275 codec_config_.codec_id = static_cast<CodecConfig::CodecId>(0);
276
277 obu_ = std::make_unique<CodecConfigObu>(header_, codec_config_id_,
278 codec_config_);
279 EXPECT_FALSE(obu_->Initialize().ok());
280 }
281
TEST_F(CodecConfigLpcmTest,InitializeFailsWithWriteIllegalSampleSize)282 TEST_F(CodecConfigLpcmTest, InitializeFailsWithWriteIllegalSampleSize) {
283 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_size_ = 33;
284
285 obu_ = std::make_unique<CodecConfigObu>(header_, codec_config_id_,
286 codec_config_);
287 EXPECT_FALSE(obu_->Initialize().ok());
288 }
289
TEST_F(CodecConfigLpcmTest,InitializeFailsWithGetIllegalSampleSize)290 TEST_F(CodecConfigLpcmTest, InitializeFailsWithGetIllegalSampleSize) {
291 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_size_ = 33;
292
293 obu_ = std::make_unique<CodecConfigObu>(header_, codec_config_id_,
294 codec_config_);
295 EXPECT_FALSE(obu_->Initialize().ok());
296 }
297
TEST_F(CodecConfigLpcmTest,ValidateAndWriteFailsWithIllegalNumSamplesPerFrame)298 TEST_F(CodecConfigLpcmTest,
299 ValidateAndWriteFailsWithIllegalNumSamplesPerFrame) {
300 codec_config_.num_samples_per_frame = 0;
301
302 InitExpectOk();
303 WriteBitBuffer unused_wb(0);
304 EXPECT_FALSE(obu_->ValidateAndWriteObu(unused_wb).ok());
305 }
306
TEST_F(CodecConfigLpcmTest,Default)307 TEST_F(CodecConfigLpcmTest, Default) { InitAndTestWrite(); }
308
TEST_F(CodecConfigLpcmTest,ExtensionHeader)309 TEST_F(CodecConfigLpcmTest, ExtensionHeader) {
310 header_.obu_extension_flag = true;
311 header_.extension_header_size = 5;
312 header_.extension_header_bytes = {'e', 'x', 't', 'r', 'a'};
313
314 expected_header_ = {kObuIaCodecConfig << 3 | kObuExtensionFlagBitMask,
315 // `obu_size`.
316 20,
317 // `extension_header_size`.
318 5,
319 // `extension_header_bytes`.
320 'e', 'x', 't', 'r', 'a'};
321 InitAndTestWrite();
322 }
323
TEST_F(CodecConfigLpcmTest,ConfigId)324 TEST_F(CodecConfigLpcmTest, ConfigId) {
325 codec_config_id_ = 100;
326 expected_payload_ = {// `codec_config_id`.
327 100,
328 // `codec_id`.
329 'i', 'p', 'c', 'm',
330 // `num_samples_per_frame`.
331 64,
332 // `audio_roll_distance`.
333 0, 0,
334 // `sample_format_flags`.
335 0,
336 // `sample_size`.
337 16,
338 // `sample_rate`.
339 0, 0, 0xbb, 0x80};
340 InitAndTestWrite();
341 }
342
TEST_F(CodecConfigLpcmTest,NumSamplesPerFrame)343 TEST_F(CodecConfigLpcmTest, NumSamplesPerFrame) {
344 codec_config_.num_samples_per_frame = 128;
345 expected_header_ = {0, 15};
346 expected_payload_ = {// `codec_config_id`.
347 kCodecConfigId,
348 // `codec_id`.
349 'i', 'p', 'c', 'm',
350 // `num_samples_per_frame`.
351 0x80, 0x01,
352 // `audio_roll_distance`.
353 0, 0,
354 // `sample_format_flags`.
355 0,
356 // `sample_size`.
357 16,
358 // `sample_rate`.
359 0, 0, 0xbb, 0x80};
360
361 InitAndTestWrite();
362 }
363
TEST_F(CodecConfigLpcmTest,SampleFormatFlags)364 TEST_F(CodecConfigLpcmTest, SampleFormatFlags) {
365 std::get<LpcmDecoderConfig>(codec_config_.decoder_config)
366 .sample_format_flags_bitmask_ = LpcmDecoderConfig::kLpcmLittleEndian;
367 expected_payload_ = {// `codec_config_id`.
368 kCodecConfigId,
369 // `codec_id`.
370 'i', 'p', 'c', 'm',
371 // `num_samples_per_frame`.
372 64,
373 // `audio_roll_distance`.
374 0, 0,
375 // `sample_format_flags`.
376 1,
377 // `sample_size`.
378 16,
379 // `sample_rate`.
380 0, 0, 0xbb, 0x80};
381
382 InitAndTestWrite();
383 }
384
TEST_F(CodecConfigLpcmTest,WriteSampleSize)385 TEST_F(CodecConfigLpcmTest, WriteSampleSize) {
386 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_size_ = 24;
387 expected_payload_ = {// `codec_config_id`.
388 kCodecConfigId,
389 // `codec_id`.
390 'i', 'p', 'c', 'm',
391 // `num_samples_per_frame`.
392 64,
393 // `audio_roll_distance`.
394 0, 0,
395 // `sample_format_flags`.
396 0,
397 // `sample_size`.
398 24,
399 // `sample_rate`.
400 0, 0, 0xbb, 0x80};
401
402 InitAndTestWrite();
403 }
404
TEST_F(CodecConfigLpcmTest,GetSampleSize)405 TEST_F(CodecConfigLpcmTest, GetSampleSize) {
406 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_size_ = 24;
407 expected_output_pcm_bit_depth_ = 24;
408 InitExpectOk();
409 TestGetBitDepthToMeasureLoudness();
410 }
411
TEST_F(CodecConfigLpcmTest,WriteSampleRate)412 TEST_F(CodecConfigLpcmTest, WriteSampleRate) {
413 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_rate_ =
414 16000;
415 expected_payload_ = {// `codec_config_id`.
416 kCodecConfigId,
417 // `codec_id`.
418 'i', 'p', 'c', 'm',
419 // `num_samples_per_frame`.
420 64,
421 // `audio_roll_distance`.
422 0, 0,
423 // `sample_format_flags`.
424 0,
425 // `sample_size`.
426 16,
427 // `sample_rate`.
428 0, 0, 0x3e, 0x80};
429
430 InitAndTestWrite();
431 }
432
TEST_F(CodecConfigLpcmTest,GetOutputSampleRate)433 TEST_F(CodecConfigLpcmTest, GetOutputSampleRate) {
434 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_rate_ =
435 16000;
436 expected_output_sample_rate_ = 16000;
437 InitExpectOk();
438 TestOutputSampleRate();
439 }
440
TEST_F(CodecConfigLpcmTest,GetInputSampleRate)441 TEST_F(CodecConfigLpcmTest, GetInputSampleRate) {
442 std::get<LpcmDecoderConfig>(codec_config_.decoder_config).sample_rate_ =
443 16000;
444 expected_input_sample_rate_ = 16000;
445 InitExpectOk();
446 TestInputSampleRate();
447 }
448
TEST_F(CodecConfigLpcmTest,RedundantCopy)449 TEST_F(CodecConfigLpcmTest, RedundantCopy) {
450 header_.obu_redundant_copy = true;
451
452 expected_header_ = {kObuIaCodecConfig << 3 | kObuRedundantCopyBitMask, 14};
453 InitAndTestWrite();
454 }
455
456 class CodecConfigOpusTest : public CodecConfigTestBase, public testing::Test {
457 public:
CodecConfigOpusTest()458 CodecConfigOpusTest()
459 : CodecConfigTestBase(
460 CodecConfig::kCodecIdOpus,
461 OpusDecoderConfig{
462 .version_ = 1, .pre_skip_ = 0, .input_sample_rate_ = 0}) {
463 // Overwrite some default values to be more reasonable for Opus.
464 codec_config_.num_samples_per_frame = 960;
465 codec_config_.audio_roll_distance = -4;
466 expected_header_ = {0, 20};
467 expected_payload_ = {kCodecConfigId, 'O', 'p', 'u', 's', 0xc0, 0x07, 0xff,
468 0xfc,
469 // Start `DecoderConfig`.
470 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0};
471 }
472 };
473
TEST_F(CodecConfigOpusTest,IsNeverLossless)474 TEST_F(CodecConfigOpusTest, IsNeverLossless) {
475 InitExpectOk();
476
477 EXPECT_FALSE(obu_->IsLossless());
478 }
479
TEST_F(CodecConfigOpusTest,ManyLargeValues)480 TEST_F(CodecConfigOpusTest, ManyLargeValues) {
481 leb_generator_ =
482 LebGenerator::Create(LebGenerator::GenerationMode::kFixedSize, 8);
483 codec_config_id_ = std::numeric_limits<DecodedUleb128>::max();
484 codec_config_.num_samples_per_frame =
485 std::numeric_limits<DecodedUleb128>::max();
486 codec_config_.audio_roll_distance = -1;
487 std::get<OpusDecoderConfig>(codec_config_.decoder_config).pre_skip_ = 0xffff;
488 std::get<OpusDecoderConfig>(codec_config_.decoder_config).input_sample_rate_ =
489 0xffffffff;
490
491 expected_header_ = {0, 0x80 | 33, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00};
492 expected_payload_ = {// `codec_config_id`.
493 0xff, 0xff, 0xff, 0xff, 0x8f, 0x80, 0x80, 0x00,
494 // `codec_id`.
495 'O', 'p', 'u', 's',
496 // `num_samples_per_frame`.
497 0xff, 0xff, 0xff, 0xff, 0x8f, 0x80, 0x80, 0x00,
498 // `audio_roll_distance`.
499 0xff, 0xff,
500 // Start `DecoderConfig`.
501 // `version`.
502 1,
503 // `output_channel_count`.
504 OpusDecoderConfig::kOutputChannelCount,
505 // `pre_skip`
506 0xff, 0xff,
507 //
508 // `input_sample_rate`.
509 0xff, 0xff, 0xff, 0xff,
510 // `output_gain`.
511 0, 0,
512 // `mapping_family`.
513 OpusDecoderConfig::kMappingFamily};
514
515 InitAndTestWrite();
516 }
517
TEST_F(CodecConfigOpusTest,InitializeFailsWithIllegalCodecId)518 TEST_F(CodecConfigOpusTest, InitializeFailsWithIllegalCodecId) {
519 codec_config_.codec_id = static_cast<CodecConfig::CodecId>(0);
520
521 obu_ = std::make_unique<CodecConfigObu>(header_, codec_config_id_,
522 codec_config_);
523 EXPECT_FALSE(obu_->Initialize().ok());
524 }
525
TEST_F(CodecConfigOpusTest,InitializeFailsWhenOverridingAudioRollDistanceFails)526 TEST_F(CodecConfigOpusTest,
527 InitializeFailsWhenOverridingAudioRollDistanceFails) {
528 constexpr uint32_t kNumSamplesPerFrameCausesDivideByZero = 0;
529 codec_config_.num_samples_per_frame = kNumSamplesPerFrameCausesDivideByZero;
530 ConstructObu();
531
532 // Underlying Opus roll distance calculation would fail.
533 EXPECT_FALSE(obu_->Initialize(kOverrideAudioRollDistance).ok());
534 }
535
TEST_F(CodecConfigOpusTest,ValidateAndWriteFailsWithIllegalNumSamplesPerFrame)536 TEST_F(CodecConfigOpusTest,
537 ValidateAndWriteFailsWithIllegalNumSamplesPerFrame) {
538 constexpr uint32_t kNumSamplesPerFrameCausesDivideByZero = 0;
539 codec_config_.num_samples_per_frame = kNumSamplesPerFrameCausesDivideByZero;
540 ConstructObu();
541 // User does not request to calculate the roll distance, so the invalid
542 // `num_samples_per_frame` is not detected at initialization time.
543 EXPECT_THAT(obu_->Initialize(kDontOverrideAudioRollDistance), IsOk());
544
545 // But later the write fails because `num_samples_per_frame` is invalid and/or
546 // the roll distance is undefined.
547 WriteBitBuffer undefined_wb(0);
548 EXPECT_FALSE(obu_->ValidateAndWriteObu(undefined_wb).ok());
549 }
550
TEST_F(CodecConfigOpusTest,Default)551 TEST_F(CodecConfigOpusTest, Default) { InitAndTestWrite(); }
552
TEST_F(CodecConfigOpusTest,SetCodecDelaySetsPreSkip)553 TEST_F(CodecConfigOpusTest, SetCodecDelaySetsPreSkip) {
554 InitExpectOk();
555 EXPECT_THAT(obu_->SetCodecDelay(kArbitraryCodecDelay), IsOk());
556
557 const auto decoder_config = obu_->GetCodecConfig().decoder_config;
558 ASSERT_TRUE(std::holds_alternative<OpusDecoderConfig>(decoder_config));
559 EXPECT_EQ(std::get<OpusDecoderConfig>(decoder_config).pre_skip_,
560 kArbitraryCodecDelay);
561 }
562
TEST_F(CodecConfigOpusTest,VarySeveralFields)563 TEST_F(CodecConfigOpusTest, VarySeveralFields) {
564 codec_config_id_ = 99;
565 std::get<OpusDecoderConfig>(codec_config_.decoder_config).version_ = 15;
566 std::get<OpusDecoderConfig>(codec_config_.decoder_config).pre_skip_ = 3;
567 std::get<OpusDecoderConfig>(codec_config_.decoder_config).input_sample_rate_ =
568 4;
569 expected_payload_ = {99, 'O', 'p', 'u', 's', 0xc0, 0x07, 0xff, 0xfc,
570 // Start `DecoderConfig`.
571 // `version`.
572 15,
573 // `output_channel_count`.
574 OpusDecoderConfig::kOutputChannelCount,
575 // `pre_skip`
576 0, 3,
577 //
578 // `input_sample_rate`.
579 0, 0, 0, 4,
580 // `output_gain`.
581 0, 0,
582 // `mapping_family`.
583 OpusDecoderConfig::kMappingFamily};
584 InitAndTestWrite();
585 }
586
TEST_F(CodecConfigOpusTest,RedundantCopy)587 TEST_F(CodecConfigOpusTest, RedundantCopy) {
588 header_.obu_redundant_copy = true;
589 expected_header_ = {4, 20};
590 InitAndTestWrite();
591 }
592
TEST(CreateFromBuffer,OpusDecoderConfig)593 TEST(CreateFromBuffer, OpusDecoderConfig) {
594 constexpr DecodedUleb128 kExpectedNumSamplesPerFrame = 960;
595 constexpr int16_t kExpectedAudioRollDistance = -4;
596 constexpr uint8_t kVersion = 15;
597 constexpr int16_t kExpectedPreSkip = 3;
598 constexpr int16_t kExpectedInputSampleRate = 4;
599 std::vector<uint8_t> source_data = {kCodecConfigId, 'O', 'p', 'u', 's',
600 // num_samples_per_frame
601 0xc0, 0x07,
602 // audio_roll_distance
603 0xff, 0xfc,
604 // Start `DecoderConfig`.
605 // `version`.
606 kVersion,
607 // `output_channel_count`.
608 OpusDecoderConfig::kOutputChannelCount,
609 // `pre_skip`
610 0, 3,
611 //
612 // `input_sample_rate`.
613 0, 0, 0, 4,
614 // `output_gain`.
615 0, 0,
616 // `mapping_family`.
617 OpusDecoderConfig::kMappingFamily};
618 const int64_t payload_size = source_data.size();
619 auto buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
620 1024, absl::MakeConstSpan(source_data));
621 ObuHeader header;
622
623 absl::StatusOr<CodecConfigObu> obu =
624 CodecConfigObu::CreateFromBuffer(header, payload_size, *buffer);
625 EXPECT_THAT(obu, IsOk());
626
627 EXPECT_EQ(obu->GetCodecConfigId(), kCodecConfigId);
628 EXPECT_EQ(obu->GetCodecConfig().codec_id, CodecConfig::kCodecIdOpus);
629 EXPECT_EQ(obu->GetNumSamplesPerFrame(), kExpectedNumSamplesPerFrame);
630 EXPECT_EQ(obu->GetCodecConfig().audio_roll_distance,
631 kExpectedAudioRollDistance);
632 ASSERT_TRUE(std::holds_alternative<OpusDecoderConfig>(
633 obu->GetCodecConfig().decoder_config));
634 const auto& opus_decoder_config =
635 std::get<OpusDecoderConfig>(obu->GetCodecConfig().decoder_config);
636 EXPECT_EQ(opus_decoder_config.version_, kVersion);
637 EXPECT_EQ(opus_decoder_config.output_channel_count_,
638 OpusDecoderConfig::kOutputChannelCount);
639 EXPECT_EQ(opus_decoder_config.pre_skip_, kExpectedPreSkip);
640 EXPECT_EQ(opus_decoder_config.input_sample_rate_, kExpectedInputSampleRate);
641 EXPECT_EQ(opus_decoder_config.output_gain_, OpusDecoderConfig::kOutputGain);
642 EXPECT_EQ(opus_decoder_config.mapping_family_,
643 OpusDecoderConfig::kMappingFamily);
644 EXPECT_FALSE(obu->IsLossless());
645 };
646
647 class CodecConfigAacTest : public CodecConfigTestBase, public testing::Test {
648 public:
CodecConfigAacTest()649 CodecConfigAacTest()
650 : CodecConfigTestBase(
651 CodecConfig::kCodecIdAacLc,
652 AacDecoderConfig{
653 .buffer_size_db_ = 0,
654 .max_bitrate_ = 0,
655 .average_bit_rate_ = 0,
656 .decoder_specific_info_ =
657 {.audio_specific_config =
658 {.sample_frequency_index_ = AudioSpecificConfig::
659 SampleFrequencyIndex::k64000}},
660 }) {
661 // Overwrite some default values to be more reasonable for AAC.
662 codec_config_.num_samples_per_frame = 1024;
663 codec_config_.audio_roll_distance = -1;
664 }
665 };
666
TEST_F(CodecConfigAacTest,IsNeverLossless)667 TEST_F(CodecConfigAacTest, IsNeverLossless) {
668 InitExpectOk();
669
670 EXPECT_FALSE(obu_->IsLossless());
671 }
672
TEST_F(CodecConfigAacTest,SetCodecDelayIsNoOp)673 TEST_F(CodecConfigAacTest, SetCodecDelayIsNoOp) {
674 InitExpectOk();
675
676 EXPECT_THAT(obu_->SetCodecDelay(kArbitraryCodecDelay), IsOk());
677 }
678
TEST(CreateFromBuffer,AacLcDecoderConfig)679 TEST(CreateFromBuffer, AacLcDecoderConfig) {
680 // A 7-bit mask representing `channel_configuration`, and all three fields in
681 // the GA specific config.
682 constexpr uint8_t kChannelConfigurationAndGaSpecificConfigMask =
683 AudioSpecificConfig::kChannelConfiguration << 3 | // 4 bits.
684 AudioSpecificConfig::GaSpecificConfig::kFrameLengthFlag << 2 | // 1 bit.
685 AudioSpecificConfig::GaSpecificConfig::kDependsOnCoreCoder
686 << 1 | // 1 bit.
687 AudioSpecificConfig::GaSpecificConfig::kExtensionFlag << 0; // 1 bit.
688 constexpr DecodedUleb128 kExpectedNumSamplesPerFrame = 1024;
689 constexpr int16_t kExpectedAudioRollDistance = -1;
690 std::vector<uint8_t> source_data = {
691 kCodecConfigId, 'm', 'p', '4', 'a',
692 // num_samples_per_frame
693 0x80, 0x08,
694 // audio_roll_distance
695 0xff, 0xff,
696 // Start `DecoderConfig`.
697 // `decoder_config_descriptor_tag`
698 AacDecoderConfig::kDecoderConfigDescriptorTag,
699 // ISO 14496:1 expandable size field.
700 17,
701 // `object_type_indication`.
702 AacDecoderConfig::kObjectTypeIndication,
703 // `stream_type`, `upstream`, `reserved`.
704 AacDecoderConfig::kStreamType << 2 | AacDecoderConfig::kUpstream << 1 |
705 AacDecoderConfig::kReserved << 0,
706 // `buffer_size_db`.
707 0, 0, 0,
708 // `max_bitrate`.
709 0, 0, 0, 0,
710 // `average_bit_rate`.
711 0, 0, 0, 0,
712 // `decoder_specific_info_tag`
713 AacDecoderConfig::DecoderSpecificInfo::kDecoderSpecificInfoTag,
714 // ISO 14496:1 expandable size field.
715 2,
716 // `audio_object_type`, upper 3 bits of `sample_frequency_index`.
717 AudioSpecificConfig::kAudioObjectType << 3 |
718 kUpperByteSerializedSamplingFrequencyIndex64000,
719 // lower bit of `sample_frequency_index`,
720 // `channel_configuration`, `frame_length_flag`,
721 // `depends_on_core_coder`, `extension_flag`.
722 kLowerByteSerializedSamplingFrequencyIndex64000 |
723 kChannelConfigurationAndGaSpecificConfigMask};
724 const int64_t payload_size = source_data.size();
725 auto buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
726 1024, absl::MakeConstSpan(source_data));
727 ObuHeader header;
728
729 absl::StatusOr<CodecConfigObu> obu =
730 CodecConfigObu::CreateFromBuffer(header, payload_size, *buffer);
731 EXPECT_THAT(obu, IsOk());
732
733 EXPECT_EQ(obu->GetCodecConfigId(), kCodecConfigId);
734 EXPECT_EQ(obu->GetCodecConfig().codec_id, CodecConfig::kCodecIdAacLc);
735 EXPECT_EQ(obu->GetNumSamplesPerFrame(), kExpectedNumSamplesPerFrame);
736 EXPECT_EQ(obu->GetCodecConfig().audio_roll_distance,
737 kExpectedAudioRollDistance);
738 ASSERT_TRUE(std::holds_alternative<AacDecoderConfig>(
739 obu->GetCodecConfig().decoder_config));
740 const auto& aac_decoder_config =
741 std::get<AacDecoderConfig>(obu->GetCodecConfig().decoder_config);
742 EXPECT_EQ(aac_decoder_config.decoder_config_descriptor_tag_,
743 AacDecoderConfig::kDecoderConfigDescriptorTag);
744 EXPECT_EQ(aac_decoder_config.object_type_indication_,
745 AacDecoderConfig::kObjectTypeIndication);
746 EXPECT_EQ(aac_decoder_config.stream_type_, AacDecoderConfig::kStreamType);
747 EXPECT_EQ(aac_decoder_config.upstream_, AacDecoderConfig::kUpstream);
748 EXPECT_EQ(aac_decoder_config.reserved_, AacDecoderConfig::kReserved);
749 EXPECT_EQ(aac_decoder_config.buffer_size_db_, 0);
750 EXPECT_EQ(aac_decoder_config.max_bitrate_, 0);
751 EXPECT_EQ(aac_decoder_config.average_bit_rate_, 0);
752 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.decoder_specific_info_tag,
753 AacDecoderConfig::DecoderSpecificInfo::kDecoderSpecificInfoTag);
754 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.audio_specific_config
755 .audio_object_type_,
756 AudioSpecificConfig::kAudioObjectType);
757 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.audio_specific_config
758 .sample_frequency_index_,
759 AudioSpecificConfig::SampleFrequencyIndex::k64000);
760 EXPECT_EQ(obu->GetOutputSampleRate(), 64000);
761 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.audio_specific_config
762 .channel_configuration_,
763 AudioSpecificConfig::kChannelConfiguration);
764 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.audio_specific_config
765 .ga_specific_config_.frame_length_flag,
766 AudioSpecificConfig::GaSpecificConfig::kFrameLengthFlag);
767 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.audio_specific_config
768 .ga_specific_config_.depends_on_core_coder,
769 AudioSpecificConfig::GaSpecificConfig::kDependsOnCoreCoder);
770 EXPECT_EQ(aac_decoder_config.decoder_specific_info_.audio_specific_config
771 .ga_specific_config_.extension_flag,
772 AudioSpecificConfig::GaSpecificConfig::kExtensionFlag);
773 EXPECT_FALSE(obu->IsLossless());
774 };
775
776 class CodecConfigFlacTest : public CodecConfigTestBase, public testing::Test {
777 public:
CodecConfigFlacTest()778 CodecConfigFlacTest()
779 : CodecConfigTestBase(
780 CodecConfig::kCodecIdFlac,
781 FlacDecoderConfig{
782 {{.header = {.last_metadata_block_flag = true,
783 .block_type = FlacMetaBlockHeader::kFlacStreamInfo,
784 .metadata_data_block_length = 34},
785 .payload = FlacMetaBlockStreamInfo{
786 .minimum_block_size = 16,
787 .maximum_block_size = 16,
788 .sample_rate = 48000,
789 .bits_per_sample = 15,
790 .total_samples_in_stream = 0}}}}) {}
791 };
792
TEST_F(CodecConfigFlacTest,IsAlwaysLossless)793 TEST_F(CodecConfigFlacTest, IsAlwaysLossless) {
794 InitExpectOk();
795
796 EXPECT_TRUE(obu_->IsLossless());
797 }
798
TEST_F(CodecConfigFlacTest,SetCodecDelayIsNoOp)799 TEST_F(CodecConfigFlacTest, SetCodecDelayIsNoOp) {
800 InitExpectOk();
801
802 EXPECT_THAT(obu_->SetCodecDelay(kArbitraryCodecDelay), IsOk());
803 }
804
TEST(CreateFromBuffer,ValidLpcmDecoderConfig)805 TEST(CreateFromBuffer, ValidLpcmDecoderConfig) {
806 constexpr DecodedUleb128 kNumSamplesPerFrame = 64;
807 constexpr int16_t kExpectedAudioRollDistance = 0;
808 constexpr uint8_t kSampleFormatFlagsAsUint8 = 0x00;
809 constexpr uint8_t kSampleSize = 16;
810 constexpr uint32_t kExpectedSampleRate = 48000;
811
812 std::vector<uint8_t> source_data = {// `codec_config_id`.
813 kCodecConfigId,
814 // `codec_id`.
815 'i', 'p', 'c', 'm',
816 // `num_samples_per_frame`.
817 kNumSamplesPerFrame,
818 // `audio_roll_distance`.
819 0, 0,
820 // `sample_format_flags`.
821 kSampleFormatFlagsAsUint8,
822 // `sample_size`.
823 kSampleSize,
824 // `sample_rate`.
825 0, 0, 0xbb, 0x80};
826 const int64_t payload_size = source_data.size();
827 auto buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
828 1024, absl::MakeConstSpan(source_data));
829 ObuHeader header;
830
831 absl::StatusOr<CodecConfigObu> obu =
832 CodecConfigObu::CreateFromBuffer(header, payload_size, *buffer);
833
834 EXPECT_THAT(obu, IsOk());
835 EXPECT_EQ(obu->GetCodecConfigId(), kCodecConfigId);
836 EXPECT_EQ(obu->GetCodecConfig().codec_id, CodecConfig::kCodecIdLpcm);
837 EXPECT_EQ(obu->GetNumSamplesPerFrame(), kNumSamplesPerFrame);
838 EXPECT_EQ(obu->GetCodecConfig().audio_roll_distance,
839 kExpectedAudioRollDistance);
840 ASSERT_TRUE(std::holds_alternative<LpcmDecoderConfig>(
841 obu->GetCodecConfig().decoder_config));
842 const auto& lpcm_decoder_config =
843 std::get<LpcmDecoderConfig>(obu->GetCodecConfig().decoder_config);
844 EXPECT_EQ(
845 static_cast<uint8_t>(lpcm_decoder_config.sample_format_flags_bitmask_),
846 kSampleFormatFlagsAsUint8);
847 EXPECT_EQ(lpcm_decoder_config.sample_size_, kSampleSize);
848 EXPECT_EQ(lpcm_decoder_config.sample_rate_, kExpectedSampleRate);
849 EXPECT_TRUE(obu->IsLossless());
850 }
851
TEST(CreateFromBuffer,ValidFlacDecoderConfig)852 TEST(CreateFromBuffer, ValidFlacDecoderConfig) {
853 constexpr DecodedUleb128 kNumSamplesPerFrame = 64;
854 constexpr int16_t kExpectedAudioRollDistance = 0;
855
856 std::vector<uint8_t> source_data = {
857 // `codec_config_id`.
858 kCodecConfigId,
859 // `codec_id`.
860 'f', 'L', 'a', 'C',
861 // `num_samples_per_frame`.
862 kNumSamplesPerFrame,
863 // `audio_roll_distance`.
864 0, 0,
865 // begin `FlacDecoderConfig`.
866 // `last_metadata_block_flag` and `block_type` fields.
867 1 << 7 | FlacMetaBlockHeader::kFlacStreamInfo,
868 // `metadata_data_block_length`.
869 0, 0, 34,
870 // `minimum_block_size`.
871 0, 64,
872 // `maximum_block_size`.
873 0, 64,
874 // `minimum_frame_size`.
875 0, 0, 0,
876 // `maximum_frame_size`.
877 0, 0, 0,
878 // `sample_rate` (20 bits)
879 0x0b, 0xb8,
880 (0 << 4) |
881 // `number_of_channels` (3 bits) and `bits_per_sample` (5 bits).
882 FlacStreamInfoConstraints::kNumberOfChannels << 1,
883 7 << 4 |
884 // `total_samples_in_stream` (36 bits).
885 0,
886 0x00, 0x00, 0x00, 100,
887 // MD5 sum.
888 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
889 0x00, 0x00, 0x00, 0x00};
890 const int64_t payload_size = source_data.size();
891 auto buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
892 1024, absl::MakeConstSpan(source_data));
893 ObuHeader header;
894
895 absl::StatusOr<CodecConfigObu> obu =
896 CodecConfigObu::CreateFromBuffer(header, payload_size, *buffer);
897
898 EXPECT_THAT(obu, IsOk());
899 EXPECT_EQ(obu->GetCodecConfigId(), kCodecConfigId);
900 EXPECT_EQ(obu->GetCodecConfig().codec_id, CodecConfig::kCodecIdFlac);
901 EXPECT_EQ(obu->GetNumSamplesPerFrame(), kNumSamplesPerFrame);
902 EXPECT_EQ(obu->GetCodecConfig().audio_roll_distance,
903 kExpectedAudioRollDistance);
904
905 ASSERT_TRUE(std::holds_alternative<FlacDecoderConfig>(
906 obu->GetCodecConfig().decoder_config));
907 const auto& flac_decoder_config =
908 std::get<FlacDecoderConfig>(obu->GetCodecConfig().decoder_config);
909 EXPECT_EQ(flac_decoder_config.metadata_blocks_.size(), 1);
910 FlacMetaBlockHeader flac_meta_block_header =
911 flac_decoder_config.metadata_blocks_[0].header;
912 EXPECT_EQ(flac_meta_block_header.block_type,
913 FlacMetaBlockHeader::kFlacStreamInfo);
914 EXPECT_EQ(flac_meta_block_header.metadata_data_block_length, 34);
915 FlacMetaBlockStreamInfo stream_info = std::get<FlacMetaBlockStreamInfo>(
916 flac_decoder_config.metadata_blocks_[0].payload);
917 EXPECT_EQ(stream_info.minimum_block_size, 64);
918 EXPECT_EQ(stream_info.maximum_block_size, 64);
919 EXPECT_EQ(stream_info.minimum_frame_size, 0);
920 EXPECT_EQ(stream_info.maximum_frame_size, 0);
921 EXPECT_EQ(stream_info.sample_rate, 48000);
922 EXPECT_EQ(stream_info.number_of_channels,
923 FlacStreamInfoConstraints::kNumberOfChannels);
924 EXPECT_EQ(stream_info.bits_per_sample, 7);
925 EXPECT_EQ(stream_info.total_samples_in_stream, 100);
926 EXPECT_EQ(stream_info.md5_signature,
927 FlacStreamInfoConstraints::kMd5Signature);
928 EXPECT_TRUE(obu->IsLossless());
929 }
930
931 } // namespace
932 } // namespace iamf_tools
933