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