• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, 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 
13 #include "iamf/api/decoder/iamf_decoder.h"
14 
15 #include <array>
16 #include <cstddef>
17 #include <cstdint>
18 #include <list>
19 #include <vector>
20 
21 #include "absl/container/flat_hash_map.h"
22 #include "absl/status/status_matchers.h"
23 #include "absl/types/span.h"
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "iamf/api/types.h"
27 #include "iamf/cli/audio_element_with_data.h"
28 #include "iamf/cli/audio_frame_with_data.h"
29 #include "iamf/cli/parameter_block_with_data.h"
30 #include "iamf/cli/tests/cli_test_utils.h"
31 #include "iamf/obu/audio_frame.h"
32 #include "iamf/obu/codec_config.h"
33 #include "iamf/obu/ia_sequence_header.h"
34 #include "iamf/obu/mix_presentation.h"
35 #include "iamf/obu/obu_base.h"
36 #include "iamf/obu/obu_header.h"
37 #include "iamf/obu/temporal_delimiter.h"
38 #include "iamf/obu/types.h"
39 
40 namespace iamf_tools {
41 namespace {
42 
43 using ::absl_testing::IsOk;
44 using ::absl_testing::IsOkAndHolds;
45 using ::testing::Not;
46 
47 using api::OutputLayout;
48 using ::testing::Not;
49 
50 constexpr DecodedUleb128 kFirstCodecConfigId = 1;
51 constexpr uint32_t kNumSamplesPerFrame = 8;
52 constexpr uint32_t kBitDepth = 16;
53 constexpr DecodedUleb128 kSampleRate = 48000;
54 constexpr DecodedUleb128 kFirstAudioElementId = 2;
55 constexpr DecodedUleb128 kFirstSubstreamId = 18;
56 constexpr DecodedUleb128 kFirstMixPresentationId = 3;
57 constexpr DecodedUleb128 kCommonMixGainParameterId = 999;
58 constexpr DecodedUleb128 kCommonParameterRate = kSampleRate;
59 constexpr std::array<uint8_t, 16> kEightSampleAudioFrame = {
60     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
61 
GenerateBasicDescriptorObus()62 std::vector<uint8_t> GenerateBasicDescriptorObus() {
63   const IASequenceHeaderObu ia_sequence_header(
64       ObuHeader(), IASequenceHeaderObu::kIaCode,
65       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
66   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_configs;
67   AddLpcmCodecConfig(kFirstCodecConfigId, kNumSamplesPerFrame, kBitDepth,
68                      kSampleRate, codec_configs);
69   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
70   AddAmbisonicsMonoAudioElementWithSubstreamIds(
71       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
72       codec_configs, audio_elements);
73   std::list<MixPresentationObu> mix_presentation_obus;
74   AddMixPresentationObuWithAudioElementIds(
75       kFirstMixPresentationId, {kFirstAudioElementId},
76       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
77   return SerializeObusExpectOk({&ia_sequence_header,
78                                 &codec_configs.at(kFirstCodecConfigId),
79                                 &audio_elements.at(kFirstAudioElementId).obu,
80                                 &mix_presentation_obus.front()});
81 }
82 
TEST(IsDescriptorProcessingComplete,ReturnsFalseBeforeDescriptorObusAreProcessed)83 TEST(IsDescriptorProcessingComplete,
84      ReturnsFalseBeforeDescriptorObusAreProcessed) {
85   auto decoder =
86       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
87 
88   EXPECT_FALSE(decoder->IsDescriptorProcessingComplete());
89 }
90 
TEST(IamfDecoder,MethodsDependingOnDescriptorsFailBeforeDescriptorObusAreProcessed)91 TEST(IamfDecoder,
92      MethodsDependingOnDescriptorsFailBeforeDescriptorObusAreProcessed) {
93   auto decoder =
94       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
95 
96   EXPECT_THAT(decoder->GetOutputLayout(), Not(IsOk()));
97   EXPECT_THAT(decoder->GetNumberOfOutputChannels(), Not(IsOk()));
98   EXPECT_THAT(decoder->GetSampleRate(), Not(IsOk()));
99   EXPECT_THAT(decoder->GetFrameSize(), Not(IsOk()));
100   std::vector<api::MixPresentationMetadata> output_mix_presentation_metadatas;
101   EXPECT_THAT(decoder->GetMixPresentations(output_mix_presentation_metadatas),
102               Not(IsOk()));
103 }
104 
TEST(GetOutputLayout,ReturnsOutputLayoutAfterDescriptorObusAreProcessed)105 TEST(GetOutputLayout, ReturnsOutputLayoutAfterDescriptorObusAreProcessed) {
106   auto decoder = api::IamfDecoder::CreateFromDescriptors(
107       OutputLayout::kItu2051_SoundSystemA_0_2_0, GenerateBasicDescriptorObus());
108 
109   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
110   auto output_layout = decoder->GetOutputLayout();
111   EXPECT_THAT(output_layout.status(), IsOk());
112   EXPECT_EQ(*output_layout, OutputLayout::kItu2051_SoundSystemA_0_2_0);
113   auto number_of_output_channels = decoder->GetNumberOfOutputChannels();
114   EXPECT_THAT(number_of_output_channels.status(), IsOk());
115   EXPECT_EQ(*number_of_output_channels, 2);
116 }
117 
TEST(GetOutputLayout,ReturnsDefaultStereoLayoutIfNoMatchingLayoutExists)118 TEST(GetOutputLayout, ReturnsDefaultStereoLayoutIfNoMatchingLayoutExists) {
119   auto decoder = api::IamfDecoder::CreateFromDescriptors(
120       OutputLayout::kItu2051_SoundSystemE_4_5_1, GenerateBasicDescriptorObus());
121 
122   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
123   auto output_layout = decoder->GetOutputLayout();
124   EXPECT_THAT(output_layout.status(), IsOk());
125   EXPECT_EQ(*output_layout, OutputLayout::kItu2051_SoundSystemA_0_2_0);
126   auto number_of_output_channels = decoder->GetNumberOfOutputChannels();
127   EXPECT_THAT(number_of_output_channels.status(), IsOk());
128   EXPECT_EQ(*number_of_output_channels, 2);
129 }
130 
TEST(GetOutputLayout,ReturnsDefaultStereoLayoutIfNoMatchingLayoutExistsUsingDecode)131 TEST(GetOutputLayout,
132      ReturnsDefaultStereoLayoutIfNoMatchingLayoutExistsUsingDecode) {
133   auto decoder =
134       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemE_4_5_1);
135   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
136   TemporalDelimiterObu temporal_delimiter_obu =
137       TemporalDelimiterObu(ObuHeader());
138   auto temporal_delimiter_bytes =
139       SerializeObusExpectOk({&temporal_delimiter_obu});
140   source_data.insert(source_data.end(), temporal_delimiter_bytes.begin(),
141                      temporal_delimiter_bytes.end());
142 
143   EXPECT_THAT(decoder->Decode(source_data), IsOk());
144 
145   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
146   auto output_layout = decoder->GetOutputLayout();
147   EXPECT_THAT(output_layout.status(), IsOk());
148   EXPECT_EQ(*output_layout, OutputLayout::kItu2051_SoundSystemA_0_2_0);
149   auto number_of_output_channels = decoder->GetNumberOfOutputChannels();
150   EXPECT_THAT(number_of_output_channels.status(), IsOk());
151   EXPECT_EQ(*number_of_output_channels, 2);
152 }
153 
TEST(GetOutputLayout,ReturnsNonStereoLayoutWhenPresentInDescriptorObus)154 TEST(GetOutputLayout, ReturnsNonStereoLayoutWhenPresentInDescriptorObus) {
155   // Add a mix presentation with a non-stereo layout.
156   const IASequenceHeaderObu ia_sequence_header(
157       ObuHeader(), IASequenceHeaderObu::kIaCode,
158       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
159   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_configs;
160   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
161                                         codec_configs);
162   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
163   AddAmbisonicsMonoAudioElementWithSubstreamIds(
164       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
165       codec_configs, audio_elements);
166   std::vector<LoudspeakersSsConventionLayout::SoundSystem>
167       mix_presentation_layouts = {
168           LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0,
169           LoudspeakersSsConventionLayout::kSoundSystemB_0_5_0};
170   std::list<MixPresentationObu> mix_presentation_obus;
171   AddMixPresentationObuWithConfigurableLayouts(
172       kFirstMixPresentationId, {kFirstAudioElementId},
173       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_layouts,
174       mix_presentation_obus);
175   std::vector<uint8_t> descriptor_obus = SerializeObusExpectOk(
176       {&ia_sequence_header, &codec_configs.at(kFirstCodecConfigId),
177        &audio_elements.at(kFirstAudioElementId).obu,
178        &mix_presentation_obus.front()});
179 
180   auto decoder = api::IamfDecoder::CreateFromDescriptors(
181       OutputLayout::kItu2051_SoundSystemB_0_5_0, descriptor_obus);
182 
183   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
184   auto output_layout = decoder->GetOutputLayout();
185   EXPECT_THAT(output_layout.status(), IsOk());
186   EXPECT_EQ(*output_layout, OutputLayout::kItu2051_SoundSystemB_0_5_0);
187   auto number_of_output_channels = decoder->GetNumberOfOutputChannels();
188   EXPECT_THAT(number_of_output_channels.status(), IsOk());
189   EXPECT_EQ(*number_of_output_channels, 6);
190 }
191 
TEST(Create,SucceedsAndDecodeSucceedsWithPartialData)192 TEST(Create, SucceedsAndDecodeSucceedsWithPartialData) {
193   auto decoder =
194       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
195   EXPECT_THAT(decoder, IsOk());
196 
197   std::vector<uint8_t> source_data = {0x01, 0x23, 0x45};
198   EXPECT_TRUE(decoder->Decode(source_data).ok());
199   EXPECT_FALSE(decoder->IsDescriptorProcessingComplete());
200 }
201 
TEST(Create,SucceedsWithNonStereoLayout)202 TEST(Create, SucceedsWithNonStereoLayout) {
203   auto decoder =
204       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemB_0_5_0);
205   EXPECT_THAT(decoder, IsOk());
206 }
207 
TEST(CreateFromDescriptors,Succeeds)208 TEST(CreateFromDescriptors, Succeeds) {
209   auto decoder = api::IamfDecoder::CreateFromDescriptors(
210       OutputLayout::kItu2051_SoundSystemA_0_2_0, GenerateBasicDescriptorObus());
211 
212   EXPECT_THAT(decoder, IsOk());
213   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
214 }
215 
TEST(CreateFromDescriptors,SucceedsWithNonStereoLayout)216 TEST(CreateFromDescriptors, SucceedsWithNonStereoLayout) {
217   auto decoder = api::IamfDecoder::CreateFromDescriptors(
218       OutputLayout::kItu2051_SoundSystemB_0_5_0, GenerateBasicDescriptorObus());
219 
220   EXPECT_THAT(decoder, IsOk());
221   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
222 }
223 
TEST(CreateFromDescriptors,FailsWithIncompleteDescriptorObus)224 TEST(CreateFromDescriptors, FailsWithIncompleteDescriptorObus) {
225   auto descriptors = GenerateBasicDescriptorObus();
226   // remove the last byte to make the descriptor OBUs incomplete.
227   descriptors.pop_back();
228 
229   auto decoder = api::IamfDecoder::CreateFromDescriptors(
230       OutputLayout::kItu2051_SoundSystemA_0_2_0, descriptors);
231 
232   EXPECT_FALSE(decoder.ok());
233 }
234 
TEST(CreateFromDescriptors,FailsWithDescriptorObuInSubsequentDecode)235 TEST(CreateFromDescriptors, FailsWithDescriptorObuInSubsequentDecode) {
236   auto decoder = api::IamfDecoder::CreateFromDescriptors(
237       OutputLayout::kItu2051_SoundSystemA_0_2_0, GenerateBasicDescriptorObus());
238   EXPECT_THAT(decoder, IsOk());
239   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
240 
241   std::list<MixPresentationObu> mix_presentation_obus;
242   AddMixPresentationObuWithAudioElementIds(
243       kFirstMixPresentationId + 1, {kFirstAudioElementId},
244       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
245   auto second_chunk = SerializeObusExpectOk({&mix_presentation_obus.front()});
246 
247   EXPECT_FALSE(decoder->Decode(second_chunk).ok());
248 }
249 
TEST(Decode,SucceedsAndProcessesDescriptorsWithTemporalDelimiterAtEnd)250 TEST(Decode, SucceedsAndProcessesDescriptorsWithTemporalDelimiterAtEnd) {
251   auto decoder =
252       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
253   ASSERT_THAT(decoder, IsOk());
254   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
255   TemporalDelimiterObu temporal_delimiter_obu =
256       TemporalDelimiterObu(ObuHeader());
257   auto temporal_delimiter_bytes =
258       SerializeObusExpectOk({&temporal_delimiter_obu});
259   source_data.insert(source_data.end(), temporal_delimiter_bytes.begin(),
260                      temporal_delimiter_bytes.end());
261 
262   EXPECT_THAT(decoder->Decode(source_data), IsOk());
263   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
264 }
265 
TEST(Decode,SucceedsWithMultiplePushesOfDescriptorObus)266 TEST(Decode, SucceedsWithMultiplePushesOfDescriptorObus) {
267   auto decoder =
268       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
269   ASSERT_THAT(decoder, IsOk());
270   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
271   TemporalDelimiterObu temporal_delimiter_obu =
272       TemporalDelimiterObu(ObuHeader());
273   auto temporal_delimiter_bytes =
274       SerializeObusExpectOk({&temporal_delimiter_obu});
275   source_data.insert(source_data.end(), temporal_delimiter_bytes.begin(),
276                      temporal_delimiter_bytes.end());
277   auto first_chunk = absl::MakeConstSpan(source_data).first(2);
278   auto second_chunk =
279       absl::MakeConstSpan(source_data).last(source_data.size() - 2);
280 
281   EXPECT_THAT(decoder->Decode(first_chunk), IsOk());
282   EXPECT_FALSE(decoder->IsDescriptorProcessingComplete());
283   EXPECT_THAT(decoder->Decode(second_chunk), IsOk());
284   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
285 }
286 
TEST(Decode,SucceedsWithSeparatePushesOfDescriptorAndTemporalUnits)287 TEST(Decode, SucceedsWithSeparatePushesOfDescriptorAndTemporalUnits) {
288   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
289   auto decoder = api::IamfDecoder::CreateFromDescriptors(
290       OutputLayout::kItu2051_SoundSystemA_0_2_0, source_data);
291   ASSERT_THAT(decoder, IsOk());
292   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
293   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
294                             kEightSampleAudioFrame);
295   auto temporal_unit = SerializeObusExpectOk({&audio_frame});
296 
297   EXPECT_THAT(decoder->Decode(temporal_unit), IsOk());
298 }
299 
TEST(Decode,SucceedsWithOneTemporalUnit)300 TEST(Decode, SucceedsWithOneTemporalUnit) {
301   auto decoder =
302       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
303   ASSERT_THAT(decoder, IsOk());
304   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
305   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
306                             kEightSampleAudioFrame);
307   auto temporal_unit = SerializeObusExpectOk({&audio_frame});
308   source_data.insert(source_data.end(), temporal_unit.begin(),
309                      temporal_unit.end());
310 
311   EXPECT_THAT(decoder->Decode(source_data), IsOk());
312 }
313 
TEST(Decode,SucceedsWithMultipleTemporalUnits)314 TEST(Decode, SucceedsWithMultipleTemporalUnits) {
315   auto decoder =
316       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
317   ASSERT_THAT(decoder, IsOk());
318   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
319   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
320                             kEightSampleAudioFrame);
321   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
322   source_data.insert(source_data.end(), temporal_units.begin(),
323                      temporal_units.end());
324 
325   EXPECT_THAT(decoder->Decode(source_data), IsOk());
326 }
327 
TEST(Decode,SucceedsWithMultipleTemporalUnitsForNonStereoLayout)328 TEST(Decode, SucceedsWithMultipleTemporalUnitsForNonStereoLayout) {
329   auto decoder =
330       api::IamfDecoder::Create(OutputLayout::kIAMF_SoundSystemExtension_0_1_0);
331   ASSERT_THAT(decoder, IsOk());
332 
333   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
334   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
335                                         codec_config_obus);
336   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
337       audio_elements_with_data;
338   AddAmbisonicsMonoAudioElementWithSubstreamIds(
339       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
340       codec_config_obus, audio_elements_with_data);
341   std::list<MixPresentationObu> mix_presentation_obus;
342   std::vector<LoudspeakersSsConventionLayout::SoundSystem>
343       sound_system_layouts = {
344           LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0,
345           LoudspeakersSsConventionLayout::kSoundSystem12_0_1_0};
346   AddMixPresentationObuWithConfigurableLayouts(
347       kFirstMixPresentationId, {kFirstAudioElementId},
348       kCommonMixGainParameterId, kCommonParameterRate, sound_system_layouts,
349       mix_presentation_obus);
350 
351   const std::list<AudioFrameWithData> empty_audio_frames_with_data = {};
352   const std::list<ParameterBlockWithData> empty_parameter_blocks_with_data = {};
353 
354   const IASequenceHeaderObu ia_sequence_header(
355       ObuHeader(), IASequenceHeaderObu::kIaCode,
356       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
357   std::list<const ObuBase*> input_ia_sequence(
358       {&codec_config_obus.at(kFirstCodecConfigId),
359        &audio_elements_with_data.at(kFirstAudioElementId).obu,
360        &mix_presentation_obus.front()});
361   input_ia_sequence.push_front(&ia_sequence_header);
362 
363   std::vector<uint8_t> source_data = SerializeObusExpectOk(input_ia_sequence);
364   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
365                             kEightSampleAudioFrame);
366   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
367   source_data.insert(source_data.end(), temporal_units.begin(),
368                      temporal_units.end());
369 
370   EXPECT_THAT(decoder->Decode(source_data), IsOk());
371   // Calling with empty due to forced exit after descriptor processing, so that
372   // we can get the output temporal unit.
373   EXPECT_THAT(decoder->Decode({}), IsOk());
374 
375   const size_t expected_output_size = 8 * 4;  // 8 samples, 32-bit ints, mono.
376   std::vector<uint8_t> output_data(expected_output_size);
377   size_t bytes_written;
378   EXPECT_THAT(decoder->GetOutputTemporalUnit(absl::MakeSpan(output_data),
379                                              bytes_written),
380               IsOk());
381   EXPECT_EQ(bytes_written, expected_output_size);
382 }
383 
TEST(Decode,FailsWhenCalledAfterFlush)384 TEST(Decode, FailsWhenCalledAfterFlush) {
385   auto decoder =
386       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
387   ASSERT_THAT(decoder, IsOk());
388   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
389   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
390                             kEightSampleAudioFrame);
391   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
392   source_data.insert(source_data.end(), temporal_units.begin(),
393                      temporal_units.end());
394   ASSERT_THAT(decoder->Decode(source_data), IsOk());
395   ASSERT_FALSE(decoder->IsTemporalUnitAvailable());
396   ASSERT_THAT(decoder->Decode({}), IsOk());
397   ASSERT_TRUE(decoder->IsTemporalUnitAvailable());
398 
399   size_t expected_size = 2 * 8 * 4;  // Stereo * 8 samples * int32.
400   std::vector<uint8_t> output_data(expected_size);
401   size_t bytes_written;
402   bool output_is_done;
403   EXPECT_THAT(decoder->Flush(absl::MakeSpan(output_data), bytes_written,
404                              output_is_done),
405               IsOk());
406   EXPECT_TRUE(output_is_done);
407   EXPECT_EQ(bytes_written, expected_size);
408   EXPECT_FALSE(decoder->Decode(source_data).ok());
409 }
410 
TEST(IsTemporalUnitAvailable,ReturnsFalseAfterCreateFromDescriptorObus)411 TEST(IsTemporalUnitAvailable, ReturnsFalseAfterCreateFromDescriptorObus) {
412   auto decoder = api::IamfDecoder::CreateFromDescriptors(
413       OutputLayout::kItu2051_SoundSystemA_0_2_0, GenerateBasicDescriptorObus());
414   ASSERT_THAT(decoder, IsOk());
415   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
416 }
417 
TEST(IsTemporalUnitAvailable,TemporalUnitIsNotAvailableAfterDecodeWithNoTemporalDelimiterAtEnd)418 TEST(IsTemporalUnitAvailable,
419      TemporalUnitIsNotAvailableAfterDecodeWithNoTemporalDelimiterAtEnd) {
420   auto decoder =
421       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
422   ASSERT_THAT(decoder, IsOk());
423   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
424   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
425                             kEightSampleAudioFrame);
426   auto temporal_unit = SerializeObusExpectOk({&audio_frame});
427   source_data.insert(source_data.end(), temporal_unit.begin(),
428                      temporal_unit.end());
429 
430   ASSERT_THAT(decoder->Decode(source_data), IsOk());
431   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
432 }
433 
TEST(IsTemporalUnitAvailable,ReturnsTrueAfterDecodingOneTemporalUnitWithTemporalDelimiterAtEnd)434 TEST(IsTemporalUnitAvailable,
435      ReturnsTrueAfterDecodingOneTemporalUnitWithTemporalDelimiterAtEnd) {
436   auto decoder =
437       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
438   ASSERT_THAT(decoder, IsOk());
439   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
440   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
441                             kEightSampleAudioFrame);
442   auto temporal_delimiter_obu = TemporalDelimiterObu(ObuHeader());
443   auto temporal_unit =
444       SerializeObusExpectOk({&audio_frame, &temporal_delimiter_obu});
445   source_data.insert(source_data.end(), temporal_unit.begin(),
446                      temporal_unit.end());
447 
448   ASSERT_THAT(decoder->Decode(source_data), IsOk());
449   EXPECT_TRUE(decoder->IsDescriptorProcessingComplete());
450   // Even though a temporal unit was provided, it has not been decoded yet. This
451   // is because Decode() returns after processing the descriptor OBUs, even if
452   // there is more data available. This is done to give the user a chance to do
453   // any configurations based on the descriptors before beginning to decode the
454   // temporal units.
455   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
456   // The user can call Decode() again to process the temporal unit still
457   // available in the buffer.
458   EXPECT_THAT(decoder->Decode({}), IsOk());
459   // Now, the temporal unit has been decoded and is available for output.
460   EXPECT_TRUE(decoder->IsTemporalUnitAvailable());
461 }
462 
TEST(IsTemporalUnitAvailable,ReturnsTrueAfterDecodingMultipleTemporalUnits)463 TEST(IsTemporalUnitAvailable, ReturnsTrueAfterDecodingMultipleTemporalUnits) {
464   auto decoder =
465       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
466   ASSERT_THAT(decoder, IsOk());
467   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
468   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
469                             kEightSampleAudioFrame);
470   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
471   source_data.insert(source_data.end(), temporal_units.begin(),
472                      temporal_units.end());
473 
474   ASSERT_THAT(decoder->Decode(source_data), IsOk());
475   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
476   EXPECT_THAT(decoder->Decode({}), IsOk());
477   EXPECT_TRUE(decoder->IsTemporalUnitAvailable());
478 }
479 
TEST(GetOutputTemporalUnit,FillsOutputVectorWithLastTemporalUnit)480 TEST(GetOutputTemporalUnit, FillsOutputVectorWithLastTemporalUnit) {
481   auto decoder =
482       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
483   ASSERT_THAT(decoder, IsOk());
484   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
485   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
486                             kEightSampleAudioFrame);
487   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
488   source_data.insert(source_data.end(), temporal_units.begin(),
489                      temporal_units.end());
490   ASSERT_THAT(decoder->Decode(source_data), IsOk());
491   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
492   EXPECT_THAT(decoder->Decode({}), IsOk());
493   EXPECT_TRUE(decoder->IsTemporalUnitAvailable());
494 
495   size_t expected_size = 2 * 8 * 4;
496   std::vector<uint8_t> output_data(expected_size);
497   size_t bytes_written;
498   EXPECT_THAT(decoder->GetOutputTemporalUnit(absl::MakeSpan(output_data),
499                                              bytes_written),
500               IsOk());
501 
502   EXPECT_EQ(bytes_written, expected_size);
503   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
504 }
505 
TEST(GetOutputTemporalUnit,FillsOutputVectorWithInt16)506 TEST(GetOutputTemporalUnit, FillsOutputVectorWithInt16) {
507   auto decoder =
508       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
509   decoder->ConfigureOutputSampleType(api::OutputSampleType::kInt16LittleEndian);
510   ASSERT_THAT(decoder, IsOk());
511   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
512   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
513                             kEightSampleAudioFrame);
514   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
515   source_data.insert(source_data.end(), temporal_units.begin(),
516                      temporal_units.end());
517 
518   ASSERT_THAT(decoder->Decode(source_data), IsOk());
519   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
520   EXPECT_THAT(decoder->Decode({}), IsOk());
521   EXPECT_TRUE(decoder->IsTemporalUnitAvailable());
522 
523   size_t expected_size = 2 * 8 * 2;  // Stereo * 8 samples * 2 bytes (int16).
524   std::vector<uint8_t> output_data(expected_size);
525   size_t bytes_written;
526   EXPECT_THAT(decoder->GetOutputTemporalUnit(absl::MakeSpan(output_data),
527                                              bytes_written),
528               IsOk());
529 
530   EXPECT_EQ(bytes_written, expected_size);
531 }
532 
TEST(GetOutputTemporalUnit,FailsWhenBufferTooSmall)533 TEST(GetOutputTemporalUnit, FailsWhenBufferTooSmall) {
534   auto decoder =
535       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
536   decoder->ConfigureOutputSampleType(api::OutputSampleType::kInt16LittleEndian);
537   ASSERT_THAT(decoder, IsOk());
538   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
539   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
540                             kEightSampleAudioFrame);
541   auto temporal_units = SerializeObusExpectOk({&audio_frame, &audio_frame});
542   source_data.insert(source_data.end(), temporal_units.begin(),
543                      temporal_units.end());
544 
545   ASSERT_THAT(decoder->Decode(source_data), IsOk());
546   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
547   EXPECT_THAT(decoder->Decode({}), IsOk());
548   EXPECT_TRUE(decoder->IsTemporalUnitAvailable());
549 
550   size_t needed_size = 2 * 8 * 2;  // Stereo * 8 samples * 2 bytes (int16).
551   std::vector<uint8_t> output_data(needed_size - 1);  // Buffer too small.
552   size_t bytes_written;
553   EXPECT_THAT(decoder->GetOutputTemporalUnit(absl::MakeSpan(output_data),
554                                              bytes_written),
555               Not(IsOk()));
556   EXPECT_EQ(bytes_written, 0);
557 }
558 
TEST(GetOutputTemporalUnit,DoesNotFillOutputVectorWhenNoTemporalUnitIsAvailable)559 TEST(GetOutputTemporalUnit,
560      DoesNotFillOutputVectorWhenNoTemporalUnitIsAvailable) {
561   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
562   auto decoder = api::IamfDecoder::CreateFromDescriptors(
563       OutputLayout::kItu2051_SoundSystemA_0_2_0, source_data);
564   ASSERT_THAT(decoder, IsOk());
565 
566   std::vector<uint8_t> output_data;
567   size_t bytes_written;
568   EXPECT_THAT(decoder->GetOutputTemporalUnit(absl::MakeSpan(output_data),
569                                              bytes_written),
570               IsOk());
571 
572   EXPECT_EQ(bytes_written, 0);
573 }
574 
TEST(Flush,SucceedsWithMultipleTemporalUnits)575 TEST(Flush, SucceedsWithMultipleTemporalUnits) {
576   auto decoder =
577       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
578   ASSERT_THAT(decoder, IsOk());
579   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
580   AudioFrameObu audio_frame(ObuHeader(), kFirstSubstreamId,
581                             kEightSampleAudioFrame);
582   auto temporal_delimiter_obu = TemporalDelimiterObu(ObuHeader());
583   auto temporal_units =
584       SerializeObusExpectOk({&audio_frame, &temporal_delimiter_obu,
585                              &audio_frame, &temporal_delimiter_obu});
586   source_data.insert(source_data.end(), temporal_units.begin(),
587                      temporal_units.end());
588   ASSERT_THAT(decoder->Decode(source_data), IsOk());
589   EXPECT_FALSE(decoder->IsTemporalUnitAvailable());
590   EXPECT_THAT(decoder->Decode({}), IsOk());
591   EXPECT_TRUE(decoder->IsTemporalUnitAvailable());
592 
593   // Stereo * 8 samples * 4 bytes per sample
594   const size_t expected_size_per_temp_unit = 2 * 8 * 4;
595   std::vector<uint8_t> output_data(expected_size_per_temp_unit);
596   size_t bytes_written;
597   bool output_is_done;
598   EXPECT_THAT(decoder->Flush(absl::MakeSpan(output_data), bytes_written,
599                              output_is_done),
600               IsOk());
601   EXPECT_EQ(bytes_written, expected_size_per_temp_unit);
602   EXPECT_FALSE(output_is_done);
603   EXPECT_THAT(decoder->Flush(absl::MakeSpan(output_data), bytes_written,
604                              output_is_done),
605               IsOk());
606   EXPECT_EQ(bytes_written, expected_size_per_temp_unit);
607   EXPECT_TRUE(output_is_done);
608 }
609 
TEST(Flush,SucceedsWithNoTemporalUnits)610 TEST(Flush, SucceedsWithNoTemporalUnits) {
611   auto decoder =
612       api::IamfDecoder::Create(OutputLayout::kItu2051_SoundSystemA_0_2_0);
613   ASSERT_THAT(decoder, IsOk());
614 
615   std::vector<std::vector<int32_t>> output_decoded_temporal_unit;
616   std::vector<uint8_t> output_data;
617   size_t bytes_written;
618   bool output_is_done;
619   EXPECT_THAT(decoder->Flush(absl::MakeSpan(output_data), bytes_written,
620                              output_is_done),
621               IsOk());
622 
623   EXPECT_EQ(bytes_written, 0);
624   EXPECT_TRUE(output_is_done);
625 }
626 
TEST(GetSampleRate,ReturnsSampleRateBasedOnCodecConfigObu)627 TEST(GetSampleRate, ReturnsSampleRateBasedOnCodecConfigObu) {
628   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
629   auto decoder = api::IamfDecoder::CreateFromDescriptors(
630       api::OutputLayout::kItu2051_SoundSystemA_0_2_0, source_data);
631   ASSERT_THAT(decoder, IsOk());
632 
633   EXPECT_THAT(decoder->GetSampleRate(), IsOkAndHolds(kSampleRate));
634 }
635 
TEST(GetFrameSize,ReturnsFrameSizeBasedOnCodecConfigObu)636 TEST(GetFrameSize, ReturnsFrameSizeBasedOnCodecConfigObu) {
637   std::vector<uint8_t> source_data = GenerateBasicDescriptorObus();
638   auto decoder = api::IamfDecoder::CreateFromDescriptors(
639       api::OutputLayout::kItu2051_SoundSystemA_0_2_0, source_data);
640   ASSERT_THAT(decoder, IsOk());
641 
642   EXPECT_THAT(decoder->GetFrameSize(), IsOkAndHolds(kNumSamplesPerFrame));
643 }
644 
645 }  // namespace
646 }  // namespace iamf_tools
647