• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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