• 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/cli/obu_processor.h"
14 
15 #include <array>
16 #include <cstddef>
17 #include <cstdint>
18 #include <filesystem>
19 #include <iterator>
20 #include <list>
21 #include <memory>
22 #include <optional>
23 #include <string>
24 #include <system_error>
25 #include <utility>
26 #include <vector>
27 
28 #include "absl/container/flat_hash_map.h"
29 #include "absl/status/status_matchers.h"
30 #include "absl/strings/string_view.h"
31 #include "absl/types/span.h"
32 #include "gmock/gmock.h"
33 #include "gtest/gtest.h"
34 #include "iamf/cli/audio_element_with_data.h"
35 #include "iamf/cli/audio_frame_with_data.h"
36 #include "iamf/cli/global_timing_module.h"
37 #include "iamf/cli/parameter_block_with_data.h"
38 #include "iamf/cli/parameters_manager.h"
39 #include "iamf/cli/rendering_mix_presentation_finalizer.h"
40 #include "iamf/cli/sample_processor_base.h"
41 #include "iamf/cli/tests/cli_test_utils.h"
42 #include "iamf/cli/user_metadata_builder/iamf_input_layout.h"
43 #include "iamf/cli/wav_reader.h"
44 #include "iamf/cli/wav_writer.h"
45 #include "iamf/common/read_bit_buffer.h"
46 #include "iamf/obu/arbitrary_obu.h"
47 #include "iamf/obu/audio_frame.h"
48 #include "iamf/obu/codec_config.h"
49 #include "iamf/obu/ia_sequence_header.h"
50 #include "iamf/obu/mix_gain_parameter_data.h"
51 #include "iamf/obu/mix_presentation.h"
52 #include "iamf/obu/obu_base.h"
53 #include "iamf/obu/obu_header.h"
54 #include "iamf/obu/param_definition_variant.h"
55 #include "iamf/obu/param_definitions.h"
56 #include "iamf/obu/parameter_block.h"
57 #include "iamf/obu/temporal_delimiter.h"
58 #include "iamf/obu/types.h"
59 
60 namespace iamf_tools {
61 namespace {
62 
63 using ::absl_testing::IsOk;
64 using ::absl_testing::IsOkAndHolds;
65 using ::testing::IsNull;
66 using ::testing::Not;
67 using ::testing::NotNull;
68 
69 constexpr DecodedUleb128 kFirstCodecConfigId = 1;
70 constexpr DecodedUleb128 kSecondCodecConfigId = 2;
71 constexpr DecodedUleb128 kFirstAudioElementId = 2;
72 constexpr DecodedUleb128 kSecondAudioElementId = 3;
73 constexpr DecodedUleb128 kThirdAudioElementId = 4;
74 constexpr DecodedUleb128 kFirstSubstreamId = 18;
75 constexpr DecodedUleb128 kSecondSubstreamId = 19;
76 constexpr DecodedUleb128 kThirdSubstreamId = 20;
77 constexpr DecodedUleb128 kFourthSubstreamId = 21;
78 constexpr DecodedUleb128 kFirstMixPresentationId = 3;
79 constexpr DecodedUleb128 kSecondMixPresentationId = 4;
80 constexpr DecodedUleb128 kThirdMixPresentationId = 5;
81 constexpr DecodedUleb128 kCommonMixGainParameterId = 999;
82 constexpr uint32_t kFrameSize = 1024;
83 constexpr uint32_t kBitDepth = 16;
84 constexpr DecodedUleb128 kSampleRate = 48000;
85 constexpr DecodedUleb128 kCommonParameterRate = kSampleRate;
86 
87 constexpr DecodedUleb128 kImplicitSubstreamId = 0;
88 
89 constexpr int kObuTypeBitShift = 3;
90 constexpr int64_t kBufferCapacity = 1024;
91 
92 constexpr std::optional<uint8_t> kNoOutputFileBitDepthOverride = std::nullopt;
93 constexpr std::array<uint8_t, 16> kArbitraryAudioFrame = {
94     1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
95 
AddSequenceHeaderAndSerializeObusExpectOk(const std::list<const ObuBase * > & input_ia_sequence_without_header)96 std::vector<uint8_t> AddSequenceHeaderAndSerializeObusExpectOk(
97     const std::list<const ObuBase*>& input_ia_sequence_without_header) {
98   const IASequenceHeaderObu ia_sequence_header(
99       ObuHeader(), IASequenceHeaderObu::kIaCode,
100       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
101   std::list<const ObuBase*> input_ia_sequence(input_ia_sequence_without_header);
102   input_ia_sequence.push_front(&ia_sequence_header);
103   return SerializeObusExpectOk(input_ia_sequence);
104 }
105 
CreateAllWavWriters(const std::string output_filename_string,bool write_wav_header)106 auto CreateAllWavWriters(const std::string output_filename_string,
107                          bool write_wav_header) {
108   return [output_filename_string, write_wav_header](
109              DecodedUleb128 /*mix_presentation_id*/, int /*sub_mix_index*/,
110              int /*layout_index*/, const Layout& /*layout*/, int num_channels,
111              int sample_rate, int bit_depth, size_t max_input_samples_per_frame)
112              -> std::unique_ptr<SampleProcessorBase> {
113     return WavWriter::Create(output_filename_string, num_channels, sample_rate,
114                              bit_depth, max_input_samples_per_frame,
115                              write_wav_header);
116   };
117 }
118 
TEST(ProcessDescriptorObus,FailsWithEmptyBitstream)119 TEST(ProcessDescriptorObus, FailsWithEmptyBitstream) {
120   const std::vector<uint8_t> bitstream_without_ia_sequence_header =
121       SerializeObusExpectOk({});
122   IASequenceHeaderObu ia_sequence_header;
123   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obu;
124   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
125       audio_elements_with_data;
126   std::list<MixPresentationObu> mix_presentation_obus;
127 
128   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
129       kBufferCapacity,
130       absl::MakeConstSpan(bitstream_without_ia_sequence_header));
131   bool insufficient_data;
132   EXPECT_FALSE(ObuProcessor::ProcessDescriptorObus(
133                    /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
134                    ia_sequence_header, codec_config_obu,
135                    audio_elements_with_data, mix_presentation_obus,
136                    insufficient_data)
137                    .ok());
138   // There's no data (and `is_exhaustive_and_exact` is false), so we need more
139   // data to proceed.
140   EXPECT_TRUE(insufficient_data);
141 }
142 
TEST(ProcessDescriptorObus,CollectsCodecConfigsBeforeATemporalUnit)143 TEST(ProcessDescriptorObus, CollectsCodecConfigsBeforeATemporalUnit) {
144   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> input_codec_configs;
145   AddOpusCodecConfigWithId(kFirstCodecConfigId, input_codec_configs);
146   AddOpusCodecConfigWithId(kSecondCodecConfigId, input_codec_configs);
147   AudioFrameObu input_audio_frame(
148       ObuHeader(), kFirstSubstreamId, /*audio_frame=*/
149       {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
150   const auto two_codec_configs_and_audio_frame =
151       AddSequenceHeaderAndSerializeObusExpectOk(
152           {&input_codec_configs.at(kFirstCodecConfigId),
153            &input_codec_configs.at(kSecondCodecConfigId), &input_audio_frame});
154   IASequenceHeaderObu unused_ia_sequence_header;
155   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> output_codec_config_obus;
156   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
157       audio_elements_with_data;
158   std::list<MixPresentationObu> mix_presentation_obus;
159 
160   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
161       kBufferCapacity, absl::MakeConstSpan(two_codec_configs_and_audio_frame));
162   bool insufficient_data;
163   EXPECT_THAT(
164       ObuProcessor::ProcessDescriptorObus(
165           /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
166           unused_ia_sequence_header, output_codec_config_obus,
167           audio_elements_with_data, mix_presentation_obus, insufficient_data),
168       IsOk());
169 
170   EXPECT_EQ(output_codec_config_obus.size(), 2);
171   EXPECT_TRUE(output_codec_config_obus.contains(kFirstCodecConfigId));
172   EXPECT_TRUE(output_codec_config_obus.contains(kSecondCodecConfigId));
173   // `insufficient_data` is false because we have successfully read all provided
174   // descriptor obus AND `is_exhaustive_and_exact` is true, meaning that the
175   // caller has indicated that there are no future Descriptor OBUs coming.
176   EXPECT_FALSE(insufficient_data);
177 }
178 
TEST(ProcessDescriptorObus,CollectsCodecConfigsAtEndOfBitstream)179 TEST(ProcessDescriptorObus, CollectsCodecConfigsAtEndOfBitstream) {
180   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> input_codec_configs;
181   AddOpusCodecConfigWithId(kFirstCodecConfigId, input_codec_configs);
182   AddOpusCodecConfigWithId(kSecondCodecConfigId, input_codec_configs);
183   const auto two_codec_configs_at_end_of_bitstream =
184       AddSequenceHeaderAndSerializeObusExpectOk(
185           {&input_codec_configs.at(kFirstCodecConfigId),
186            &input_codec_configs.at(kSecondCodecConfigId)});
187   IASequenceHeaderObu ia_sequence_header;
188   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
189   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
190       audio_elements_with_data;
191   std::list<MixPresentationObu> mix_presentation_obus;
192 
193   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
194       kBufferCapacity,
195       absl::MakeConstSpan(two_codec_configs_at_end_of_bitstream));
196   bool insufficient_data;
197   EXPECT_THAT(
198       ObuProcessor::ProcessDescriptorObus(
199           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
200           ia_sequence_header, codec_config_obus, audio_elements_with_data,
201           mix_presentation_obus, insufficient_data),
202       IsOk());
203   // `is_exhaustive_and_exact` is true so it could not be a more-data situation.
204   EXPECT_FALSE(insufficient_data);
205 
206   EXPECT_EQ(codec_config_obus.size(), 2);
207   EXPECT_TRUE(codec_config_obus.contains(kFirstCodecConfigId));
208   EXPECT_TRUE(codec_config_obus.contains(kSecondCodecConfigId));
209 }
210 
TEST(ProcessDescriptorObus,DoesNotCollectCodecConfigsAtEndOfBitstreamWithoutIsExhaustiveAndExact)211 TEST(ProcessDescriptorObus,
212      DoesNotCollectCodecConfigsAtEndOfBitstreamWithoutIsExhaustiveAndExact) {
213   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> input_codec_configs;
214   AddOpusCodecConfigWithId(kFirstCodecConfigId, input_codec_configs);
215   AddOpusCodecConfigWithId(kSecondCodecConfigId, input_codec_configs);
216   const auto two_codec_configs_at_end_of_bitstream =
217       AddSequenceHeaderAndSerializeObusExpectOk(
218           {&input_codec_configs.at(kFirstCodecConfigId),
219            &input_codec_configs.at(kSecondCodecConfigId)});
220   IASequenceHeaderObu ia_sequence_header;
221   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
222   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
223       audio_elements_with_data;
224   std::list<MixPresentationObu> mix_presentation_obus;
225 
226   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
227       kBufferCapacity,
228       absl::MakeConstSpan(two_codec_configs_at_end_of_bitstream));
229   auto start_position = read_bit_buffer->Tell();
230   bool insufficient_data;
231   EXPECT_THAT(
232       ObuProcessor::ProcessDescriptorObus(
233           /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
234           ia_sequence_header, codec_config_obus, audio_elements_with_data,
235           mix_presentation_obus, insufficient_data),
236       Not(IsOk()));
237   // `is_exhaustive_and_exact` is false so we won't know it's the end of the
238   // bitstream until we see a temporal unit.  Need more data to know we're done.
239   EXPECT_TRUE(insufficient_data);
240   EXPECT_EQ(codec_config_obus.size(), 0);
241   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
242 }
243 
TEST(ProcessDescriptorObus,CollectsIaSequenceHeaderWithoutOtherObus)244 TEST(ProcessDescriptorObus, CollectsIaSequenceHeaderWithoutOtherObus) {
245   const auto only_ia_sequence_header =
246       AddSequenceHeaderAndSerializeObusExpectOk({});
247   IASequenceHeaderObu ia_sequence_header;
248   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
249   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
250       audio_elements_with_data;
251   std::list<MixPresentationObu> mix_presentation_obus;
252 
253   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
254       kBufferCapacity, absl::MakeConstSpan(only_ia_sequence_header));
255   bool insufficient_data;
256   EXPECT_THAT(
257       ObuProcessor::ProcessDescriptorObus(
258           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
259           ia_sequence_header, codec_config_obus, audio_elements_with_data,
260           mix_presentation_obus, insufficient_data),
261       IsOk());
262 
263   EXPECT_EQ(ia_sequence_header.GetPrimaryProfile(),
264             ProfileVersion::kIamfSimpleProfile);
265   EXPECT_EQ(ia_sequence_header.GetAdditionalProfile(),
266             ProfileVersion::kIamfBaseProfile);
267   EXPECT_FALSE(insufficient_data);
268 }
269 
TEST(ProcessDescriptorObus,DescriptorObusMustStartWithIaSequenceHeader)270 TEST(ProcessDescriptorObus, DescriptorObusMustStartWithIaSequenceHeader) {
271   const IASequenceHeaderObu input_ia_sequence_header(
272       ObuHeader(), IASequenceHeaderObu::kIaCode,
273       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
274   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> input_codec_configs;
275   AddOpusCodecConfigWithId(kFirstCodecConfigId, input_codec_configs);
276 
277   IASequenceHeaderObu unused_ia_sequence_header;
278   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> unused_codec_config_obus;
279   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
280       unused_audio_elements_with_data;
281   std::list<MixPresentationObu> unused_mix_presentation_obus;
282 
283   // Descriptor OBUs must start with IA Sequence Header.
284   const auto ia_sequence_header_then_codec_config =
285       SerializeObusExpectOk({&input_ia_sequence_header,
286                              &input_codec_configs.at(kFirstCodecConfigId)});
287 
288   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
289       kBufferCapacity,
290       absl::MakeConstSpan(ia_sequence_header_then_codec_config));
291   bool insufficient_data;
292   EXPECT_THAT(ObuProcessor::ProcessDescriptorObus(
293                   /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
294                   unused_ia_sequence_header, unused_codec_config_obus,
295                   unused_audio_elements_with_data, unused_mix_presentation_obus,
296                   insufficient_data),
297               IsOk());
298   EXPECT_FALSE(insufficient_data);
299   // The reverse order is not valid according to
300   // https://aomediacodec.github.io/iamf/#standalone-descriptor-obus
301   const auto codec_config_then_ia_sequence_header =
302       SerializeObusExpectOk({&input_codec_configs.at(kFirstCodecConfigId),
303                              &input_ia_sequence_header});
304 
305   read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
306       kBufferCapacity,
307       absl::MakeConstSpan(codec_config_then_ia_sequence_header));
308   EXPECT_FALSE(ObuProcessor::ProcessDescriptorObus(
309                    /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
310                    unused_ia_sequence_header, unused_codec_config_obus,
311                    unused_audio_elements_with_data,
312                    unused_mix_presentation_obus, insufficient_data)
313                    .ok());
314   // `insufficient_data` is false as the error was due to an invalid ordering of
315   // OBUs, rather than not having enough data.
316   EXPECT_FALSE(insufficient_data);
317 }
318 
TEST(ProcessDescriptorObus,SucceedsWithSuccessiveRedundantSequenceHeaders)319 TEST(ProcessDescriptorObus, SucceedsWithSuccessiveRedundantSequenceHeaders) {
320   const IASequenceHeaderObu input_redundant_ia_sequence_header(
321       ObuHeader{.obu_redundant_copy = true}, IASequenceHeaderObu::kIaCode,
322       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
323   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
324       {&input_redundant_ia_sequence_header});
325   IASequenceHeaderObu ia_sequence_header;
326   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
327   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
328       audio_elements_with_data;
329   std::list<MixPresentationObu> mix_presentation_obus;
330 
331   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
332       kBufferCapacity, absl::MakeConstSpan(bitstream));
333   bool insufficient_data;
334   EXPECT_THAT(
335       ObuProcessor::ProcessDescriptorObus(
336           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
337           ia_sequence_header, codec_config_obus, audio_elements_with_data,
338           mix_presentation_obus, insufficient_data),
339       IsOk());
340   EXPECT_FALSE(insufficient_data);
341 }
342 
TEST(ProcessDescriptorObus,ConsumesUpToNextNonRedundantSequenceHeader)343 TEST(ProcessDescriptorObus, ConsumesUpToNextNonRedundantSequenceHeader) {
344   const IASequenceHeaderObu input_non_redundant_ia_sequence_header(
345       ObuHeader(), IASequenceHeaderObu::kIaCode,
346       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
347   auto buffer =
348       SerializeObusExpectOk({&input_non_redundant_ia_sequence_header});
349   const int64_t first_ia_sequence_size = buffer.size();
350 
351   // Add a second non-redundant sequence header.
352   const auto second_non_redundant_ia_sequence =
353       SerializeObusExpectOk({&input_non_redundant_ia_sequence_header});
354   buffer.insert(buffer.end(), second_non_redundant_ia_sequence.begin(),
355                 second_non_redundant_ia_sequence.end());
356 
357   IASequenceHeaderObu ia_sequence_header;
358   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
359   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
360       audio_elements_with_data;
361   std::list<MixPresentationObu> mix_presentation_obus;
362 
363   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
364       kBufferCapacity, absl::MakeConstSpan(buffer));
365   bool insufficient_data;
366   EXPECT_THAT(
367       ObuProcessor::ProcessDescriptorObus(
368           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
369           ia_sequence_header, codec_config_obus, audio_elements_with_data,
370           mix_presentation_obus, insufficient_data),
371       IsOk());
372   EXPECT_FALSE(insufficient_data);
373 
374   // Expect the reader position to be right next to the end of the first IA
375   // sequence.
376   EXPECT_EQ(read_bit_buffer->Tell(), first_ia_sequence_size * 8);
377 }
378 
TEST(ProcessDescriptorObus,CollectsIaSequenceHeaderWithCodecConfigs)379 TEST(ProcessDescriptorObus, CollectsIaSequenceHeaderWithCodecConfigs) {
380   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> input_codec_configs;
381   const DecodedUleb128 kFirstCodecConfigId = 123;
382   AddOpusCodecConfigWithId(kFirstCodecConfigId, input_codec_configs);
383   const DecodedUleb128 kSecondCodecConfigId = 124;
384   AddOpusCodecConfigWithId(kSecondCodecConfigId, input_codec_configs);
385   const auto ia_sequence_header_with_codec_configs =
386       AddSequenceHeaderAndSerializeObusExpectOk(
387           {&input_codec_configs.at(kFirstCodecConfigId),
388            &input_codec_configs.at(kSecondCodecConfigId)});
389   IASequenceHeaderObu ia_sequence_header;
390   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
391   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
392       audio_elements_with_data;
393   std::list<MixPresentationObu> mix_presentation_obus;
394 
395   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
396       kBufferCapacity,
397       absl::MakeConstSpan(ia_sequence_header_with_codec_configs));
398   bool insufficient_data;
399   EXPECT_THAT(
400       ObuProcessor::ProcessDescriptorObus(
401           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
402           ia_sequence_header, codec_config_obus, audio_elements_with_data,
403           mix_presentation_obus, insufficient_data),
404       IsOk());
405 
406   EXPECT_FALSE(insufficient_data);
407   EXPECT_EQ(ia_sequence_header.GetPrimaryProfile(),
408             ProfileVersion::kIamfSimpleProfile);
409   EXPECT_EQ(codec_config_obus.size(), 2);
410   EXPECT_TRUE(codec_config_obus.contains(kFirstCodecConfigId));
411   EXPECT_TRUE(codec_config_obus.contains(kSecondCodecConfigId));
412 }
413 
414 // Returns a bitstream with all the descriptor obus for a zeroth order
415 // ambisonics stream.
InitAllDescriptorsForZerothOrderAmbisonics()416 std::vector<uint8_t> InitAllDescriptorsForZerothOrderAmbisonics() {
417   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> input_codec_configs;
418   AddOpusCodecConfigWithId(kFirstCodecConfigId, input_codec_configs);
419   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
420       audio_elements_with_data;
421   AddAmbisonicsMonoAudioElementWithSubstreamIds(
422       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
423       input_codec_configs, audio_elements_with_data);
424   std::list<MixPresentationObu> mix_presentation_obus;
425   AddMixPresentationObuWithAudioElementIds(
426       kFirstMixPresentationId, {kFirstAudioElementId},
427       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
428 
429   return AddSequenceHeaderAndSerializeObusExpectOk(
430       {&input_codec_configs.at(kFirstCodecConfigId),
431        &audio_elements_with_data.at(kFirstAudioElementId).obu,
432        &mix_presentation_obus.front()});
433 }
434 
435 // Descriptor obus only, is_exhaustive_and_exact = true.
TEST(ProcessDescriptorObus,SucceedsWithoutTemporalUnitFollowing)436 TEST(ProcessDescriptorObus, SucceedsWithoutTemporalUnitFollowing) {
437   auto zeroth_order_ambisonics_descriptor_obus =
438       InitAllDescriptorsForZerothOrderAmbisonics();
439 
440   IASequenceHeaderObu ia_sequence_header;
441   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
442   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
443       audio_elements_with_data;
444   std::list<MixPresentationObu> mix_presentation_obus;
445 
446   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
447       kBufferCapacity,
448       absl::MakeConstSpan(zeroth_order_ambisonics_descriptor_obus));
449   bool insufficient_data;
450 
451   EXPECT_THAT(
452       ObuProcessor::ProcessDescriptorObus(
453           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
454           ia_sequence_header, codec_config_obus, audio_elements_with_data,
455           mix_presentation_obus, insufficient_data),
456       IsOk());
457 
458   EXPECT_FALSE(insufficient_data);
459   EXPECT_EQ(ia_sequence_header.GetPrimaryProfile(),
460             ProfileVersion::kIamfSimpleProfile);
461   EXPECT_EQ(codec_config_obus.size(), 1);
462   EXPECT_TRUE(codec_config_obus.contains(kFirstCodecConfigId));
463   EXPECT_EQ(audio_elements_with_data.size(), 1);
464   EXPECT_TRUE(audio_elements_with_data.contains(kFirstAudioElementId));
465   EXPECT_EQ(mix_presentation_obus.size(), 1);
466   EXPECT_EQ(mix_presentation_obus.front().GetMixPresentationId(),
467             kFirstMixPresentationId);
468 }
469 
470 // Descriptor obus only, is_exhaustive_and_exact = false.
TEST(ProcessDescriptorObus,RejectsWithoutTemporalUnitFollowingAndNotExhaustive)471 TEST(ProcessDescriptorObus,
472      RejectsWithoutTemporalUnitFollowingAndNotExhaustive) {
473   auto zeroth_order_ambisonics_descriptor_obus =
474       InitAllDescriptorsForZerothOrderAmbisonics();
475 
476   IASequenceHeaderObu ia_sequence_header;
477   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
478   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
479       audio_elements_with_data;
480   std::list<MixPresentationObu> mix_presentation_obus;
481 
482   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
483       kBufferCapacity,
484       absl::MakeConstSpan(zeroth_order_ambisonics_descriptor_obus));
485   auto start_position = read_bit_buffer->Tell();
486   bool insufficient_data;
487 
488   EXPECT_THAT(
489       ObuProcessor::ProcessDescriptorObus(
490           /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
491           ia_sequence_header, codec_config_obus, audio_elements_with_data,
492           mix_presentation_obus, insufficient_data),
493       Not(IsOk()));
494 
495   // We've received a valid bitstream so far but not complete.
496   EXPECT_TRUE(insufficient_data);
497   EXPECT_EQ(codec_config_obus.size(), 0);
498   EXPECT_EQ(audio_elements_with_data.size(), 0);
499   EXPECT_EQ(mix_presentation_obus.size(), 0);
500   // Expect the reader position to be unchanged since we returned an error.
501   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
502 }
503 
504 // Descriptor obus + temporal unit header following, is_exhaustive_and_exact =
505 // true
TEST(ProcessDescriptorObusTest,RejectDescriptorObusWithTemporalUnitFollowingAndIsExhaustiveAndExact)506 TEST(ProcessDescriptorObusTest,
507      RejectDescriptorObusWithTemporalUnitFollowingAndIsExhaustiveAndExact) {
508   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
509 
510   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
511                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
512   const auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
513   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
514                    temporal_unit_obus.end());
515 
516   IASequenceHeaderObu ia_sequence_header;
517   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
518   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
519       audio_elements_with_data;
520   std::list<MixPresentationObu> mix_presentation_obus;
521 
522   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
523       kBufferCapacity, absl::MakeConstSpan(bitstream));
524   auto start_position = read_bit_buffer->Tell();
525   bool insufficient_data;
526 
527   EXPECT_THAT(
528       ObuProcessor::ProcessDescriptorObus(
529           /*is_exhaustive_and_exact=*/true, *read_bit_buffer,
530           ia_sequence_header, codec_config_obus, audio_elements_with_data,
531           mix_presentation_obus, insufficient_data),
532       Not(IsOk()));
533 
534   // We failed with sufficient data.
535   EXPECT_FALSE(insufficient_data);
536 
537   // Expect the reader position to be unchanged since we returned an error.
538   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
539 }
540 
541 // Descriptor obus + temporal unit header following, is_exhaustive_and_exact =
542 // false.
TEST(ProcessDescriptorObusTest,SucceedsWithTemporalUnitFollowing)543 TEST(ProcessDescriptorObusTest, SucceedsWithTemporalUnitFollowing) {
544   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
545   const int64_t descriptors_size = bitstream.size();
546 
547   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
548                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
549   const auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
550   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
551                    temporal_unit_obus.end());
552 
553   IASequenceHeaderObu ia_sequence_header;
554   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
555   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
556       audio_elements_with_data;
557   std::list<MixPresentationObu> mix_presentation_obus;
558 
559   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
560       kBufferCapacity, absl::MakeConstSpan(bitstream));
561   bool insufficient_data;
562 
563   EXPECT_THAT(
564       ObuProcessor::ProcessDescriptorObus(
565           /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
566           ia_sequence_header, codec_config_obus, audio_elements_with_data,
567           mix_presentation_obus, insufficient_data),
568       IsOk());
569 
570   EXPECT_FALSE(insufficient_data);
571   EXPECT_EQ(ia_sequence_header.GetPrimaryProfile(),
572             ProfileVersion::kIamfSimpleProfile);
573   EXPECT_EQ(codec_config_obus.size(), 1);
574   EXPECT_TRUE(codec_config_obus.contains(kFirstCodecConfigId));
575   EXPECT_EQ(audio_elements_with_data.size(), 1);
576   EXPECT_TRUE(audio_elements_with_data.contains(kFirstAudioElementId));
577   EXPECT_EQ(mix_presentation_obus.size(), 1);
578   EXPECT_EQ(mix_presentation_obus.front().GetMixPresentationId(),
579             kFirstMixPresentationId);
580 
581   // Expect the reader position to be right next to the end of the descriptors.
582   // sequence.
583   EXPECT_EQ(read_bit_buffer->Tell(), descriptors_size * 8);
584 }
585 
586 // Descriptor obus + non_temporal_unit_header following but not enough data to
587 // read last obu.
TEST(ProcessDescriptorObusTest,RejectDescriptorObusWithNonTemporalUnitHeaderFollowingAndNotEnoughData)588 TEST(ProcessDescriptorObusTest,
589      RejectDescriptorObusWithNonTemporalUnitHeaderFollowingAndNotEnoughData) {
590   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
591 
592   std::vector<uint8_t> extra_descriptor_obu_header_bytes = {
593       kObuIaCodecConfig << kObuTypeBitShift,
594       // `obu_size`. -> Non-zero size, but we have no bytes following.
595       0x7f};
596 
597   bitstream.insert(bitstream.end(), extra_descriptor_obu_header_bytes.begin(),
598                    extra_descriptor_obu_header_bytes.end());
599 
600   IASequenceHeaderObu ia_sequence_header;
601   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
602   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
603       audio_elements_with_data;
604   std::list<MixPresentationObu> mix_presentation_obus;
605 
606   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
607       kBufferCapacity, absl::MakeConstSpan(bitstream));
608   auto start_position = read_bit_buffer->Tell();
609   bool insufficient_data;
610 
611   EXPECT_THAT(
612       ObuProcessor::ProcessDescriptorObus(
613           /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
614           ia_sequence_header, codec_config_obus, audio_elements_with_data,
615           mix_presentation_obus, insufficient_data),
616       Not(IsOk()));
617 
618   // We've received a valid bitstream so far but not complete.
619   EXPECT_TRUE(insufficient_data);
620   // Expect the reader position to be unchanged since we returned an error.
621   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
622 }
623 
624 // Descriptor obus + partial header following.
TEST(ProcessDescriptorObus,RejectsDescriptorObusWithPartialHeaderFollowing)625 TEST(ProcessDescriptorObus, RejectsDescriptorObusWithPartialHeaderFollowing) {
626   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
627 
628   std::vector<uint8_t> partial_header_obu = {0x80};
629   bitstream.insert(bitstream.end(), partial_header_obu.begin(),
630                    partial_header_obu.end());
631 
632   IASequenceHeaderObu ia_sequence_header;
633   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
634   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
635       audio_elements_with_data;
636   std::list<MixPresentationObu> mix_presentation_obus;
637 
638   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
639       kBufferCapacity, absl::MakeConstSpan(bitstream));
640   auto start_position = read_bit_buffer->Tell();
641   bool insufficient_data;
642 
643   EXPECT_THAT(
644       ObuProcessor::ProcessDescriptorObus(
645           /*is_exhaustive_and_exact=*/false, *read_bit_buffer,
646           ia_sequence_header, codec_config_obus, audio_elements_with_data,
647           mix_presentation_obus, insufficient_data),
648       Not(IsOk()));
649 
650   // We've received a valid bitstream so far but not complete.
651   EXPECT_TRUE(insufficient_data);
652   EXPECT_EQ(codec_config_obus.size(), 0);
653   EXPECT_EQ(audio_elements_with_data.size(), 0);
654   EXPECT_EQ(mix_presentation_obus.size(), 0);
655   // Expect the reader position to be unchanged since we returned an error.
656   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
657 }
658 
TEST(ProcessTemporalUnitObus,OkAndProducesNoObusIfEmpty)659 TEST(ProcessTemporalUnitObus, OkAndProducesNoObusIfEmpty) {
660   const auto empty_temporal_unit = SerializeObusExpectOk({});
661   auto empty_read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
662       kBufferCapacity, absl::MakeConstSpan(empty_temporal_unit));
663   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigs =
664       {};
665   const absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
666       kNoAudioElementsWithData = {};
667   auto global_timing_module =
668       GlobalTimingModule::Create(kNoAudioElementsWithData,
669                                  /*param_definitions=*/{});
670   ASSERT_THAT(global_timing_module, NotNull());
671   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
672 
673   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
674       substream_id_to_audio_element = {};
675   ParametersManager parameters_manager(kNoAudioElementsWithData);
676   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
677   bool continue_processing = true;
678   std::optional<AudioFrameWithData> audio_frame_with_data;
679   std::optional<ParameterBlockWithData> parameter_block_with_data;
680   std::optional<TemporalDelimiterObu> temporal_delimiter;
681   EXPECT_THAT(
682       ObuProcessor::ProcessTemporalUnitObu(
683           kNoAudioElementsWithData, kNoCodecConfigs,
684           substream_id_to_audio_element, param_definitions, parameters_manager,
685           *empty_read_bit_buffer, *global_timing_module, audio_frame_with_data,
686           parameter_block_with_data, temporal_delimiter, continue_processing),
687       IsOk());
688 
689   EXPECT_FALSE(audio_frame_with_data.has_value());
690   EXPECT_FALSE(parameter_block_with_data.has_value());
691   EXPECT_FALSE(temporal_delimiter.has_value());
692   EXPECT_FALSE(continue_processing);
693 }
694 
TEST(ProcessTemporalUnitObus,ConsumesAllTemporalUnits)695 TEST(ProcessTemporalUnitObus, ConsumesAllTemporalUnits) {
696   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
697                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
698 
699   const auto one_temporal_unit = SerializeObusExpectOk({&audio_frame_obu});
700 
701   // Set up inputs.
702   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
703   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
704   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
705       audio_elements_with_data;
706   AddAmbisonicsMonoAudioElementWithSubstreamIds(
707       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
708       codec_config_obus, audio_elements_with_data);
709   auto global_timing_module =
710       GlobalTimingModule::Create(audio_elements_with_data,
711                                  /*param_definitions=*/{});
712   ASSERT_THAT(global_timing_module, NotNull());
713 
714   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
715       substream_id_to_audio_element = {
716           {kFirstSubstreamId,
717            &audio_elements_with_data.at(kFirstAudioElementId)}};
718   ParametersManager parameters_manager(audio_elements_with_data);
719   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
720   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
721   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
722       kBufferCapacity, absl::MakeConstSpan(one_temporal_unit));
723 
724   bool continue_processing = true;
725   std::optional<AudioFrameWithData> audio_frame_with_data;
726   std::optional<ParameterBlockWithData> parameter_block_with_data;
727   std::optional<TemporalDelimiterObu> temporal_delimiter;
728   EXPECT_THAT(
729       ObuProcessor::ProcessTemporalUnitObu(
730           audio_elements_with_data, codec_config_obus,
731           substream_id_to_audio_element, param_definitions, parameters_manager,
732           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
733           parameter_block_with_data, temporal_delimiter, continue_processing),
734       IsOk());
735   EXPECT_TRUE(audio_frame_with_data.has_value());
736   EXPECT_FALSE(parameter_block_with_data.has_value());
737   EXPECT_FALSE(temporal_delimiter.has_value());
738 
739   // Reaching the end of the stream.
740   EXPECT_FALSE(read_bit_buffer->IsDataAvailable());
741 }
742 
TEST(ProcessTemporalUnitObus,ReadsAllTemporalUnitsBeforeNewIaSequence)743 TEST(ProcessTemporalUnitObus, ReadsAllTemporalUnitsBeforeNewIaSequence) {
744   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
745                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
746   const IASequenceHeaderObu non_redundant_ia_sequence_header(
747       ObuHeader{.obu_redundant_copy = false}, IASequenceHeaderObu::kIaCode,
748       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
749 
750   const auto one_temporal_unit_before_non_redundant_descriptor_obu =
751       SerializeObusExpectOk(
752           {&audio_frame_obu, &non_redundant_ia_sequence_header});
753 
754   // Set up inputs.
755   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
756   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
757   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
758       audio_elements_with_data;
759   AddAmbisonicsMonoAudioElementWithSubstreamIds(
760       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
761       codec_config_obus, audio_elements_with_data);
762   auto global_timing_module =
763       GlobalTimingModule::Create(audio_elements_with_data,
764                                  /*param_definitions=*/{});
765   ASSERT_THAT(global_timing_module, NotNull());
766 
767   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
768       substream_id_to_audio_element = {
769           {kFirstSubstreamId,
770            &audio_elements_with_data.at(kFirstAudioElementId)}};
771   ParametersManager parameters_manager(audio_elements_with_data);
772   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
773   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
774   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
775       kBufferCapacity,
776       absl::MakeConstSpan(
777           one_temporal_unit_before_non_redundant_descriptor_obu));
778 
779   bool continue_processing = true;
780   std::optional<AudioFrameWithData> audio_frame_with_data;
781   std::optional<ParameterBlockWithData> parameter_block_with_data;
782   std::optional<TemporalDelimiterObu> temporal_delimiter;
783   EXPECT_THAT(
784       ObuProcessor::ProcessTemporalUnitObu(
785           audio_elements_with_data, codec_config_obus,
786           substream_id_to_audio_element, param_definitions, parameters_manager,
787           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
788           parameter_block_with_data, temporal_delimiter, continue_processing),
789       IsOk());
790   EXPECT_TRUE(audio_frame_with_data.has_value());
791   EXPECT_FALSE(parameter_block_with_data.has_value());
792   EXPECT_FALSE(temporal_delimiter.has_value());
793   EXPECT_TRUE(continue_processing);
794 
795   // Process again, this time a new IA sequence is encountred, empty OBUs
796   // are returned, and `continue_processing` is set to false.
797   EXPECT_THAT(
798       ObuProcessor::ProcessTemporalUnitObu(
799           audio_elements_with_data, codec_config_obus,
800           substream_id_to_audio_element, param_definitions, parameters_manager,
801           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
802           parameter_block_with_data, temporal_delimiter, continue_processing),
803       IsOk());
804   EXPECT_FALSE(audio_frame_with_data.has_value());
805   EXPECT_FALSE(parameter_block_with_data.has_value());
806   EXPECT_FALSE(temporal_delimiter.has_value());
807   EXPECT_FALSE(continue_processing);
808 
809   // NOT reaching the end of the stream because we haven't consumed the
810   // next IA sequence header.
811   EXPECT_TRUE(read_bit_buffer->IsDataAvailable());
812 }
813 
TEST(ProcessTemporalUnitObus,ConsumesAllTemporalUnitsAndRedundantDescriptorObus)814 TEST(ProcessTemporalUnitObus,
815      ConsumesAllTemporalUnitsAndRedundantDescriptorObus) {
816   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
817                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
818   const IASequenceHeaderObu redundant_ia_sequence_header(
819       ObuHeader{.obu_redundant_copy = true}, IASequenceHeaderObu::kIaCode,
820       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
821   // Set up inputs.
822   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
823   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
824   auto& redundant_codec_config = codec_config_obus.at(kFirstCodecConfigId);
825   redundant_codec_config.header_.obu_redundant_copy = true;
826 
827   const auto one_temporal_unit_before_redundant_descriptor_obu =
828       SerializeObusExpectOk({&audio_frame_obu, &redundant_ia_sequence_header,
829                              &redundant_codec_config});
830 
831   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
832       audio_elements_with_data;
833   AddAmbisonicsMonoAudioElementWithSubstreamIds(
834       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
835       codec_config_obus, audio_elements_with_data);
836   auto global_timing_module =
837       GlobalTimingModule::Create(audio_elements_with_data,
838                                  /*param_definitions=*/{});
839   ASSERT_THAT(global_timing_module, NotNull());
840   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
841       substream_id_to_audio_element = {
842           {kFirstSubstreamId,
843            &audio_elements_with_data.at(kFirstAudioElementId)}};
844   ParametersManager parameters_manager(audio_elements_with_data);
845   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
846   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
847   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
848       kBufferCapacity,
849       absl::MakeConstSpan(one_temporal_unit_before_redundant_descriptor_obu));
850 
851   bool continue_processing = true;
852   std::optional<AudioFrameWithData> audio_frame_with_data;
853   std::optional<ParameterBlockWithData> parameter_block_with_data;
854   std::optional<TemporalDelimiterObu> temporal_delimiter;
855   EXPECT_THAT(
856       ObuProcessor::ProcessTemporalUnitObu(
857           audio_elements_with_data, codec_config_obus,
858           substream_id_to_audio_element, param_definitions, parameters_manager,
859           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
860           parameter_block_with_data, temporal_delimiter, continue_processing),
861       IsOk());
862   EXPECT_TRUE(audio_frame_with_data.has_value());
863   EXPECT_FALSE(parameter_block_with_data.has_value());
864   EXPECT_FALSE(temporal_delimiter.has_value());
865   EXPECT_TRUE(continue_processing);
866 
867   // Process again, this time the redundant IA sequence header is read and
868   // outputs are empty.
869   EXPECT_THAT(
870       ObuProcessor::ProcessTemporalUnitObu(
871           audio_elements_with_data, codec_config_obus,
872           substream_id_to_audio_element, param_definitions, parameters_manager,
873           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
874           parameter_block_with_data, temporal_delimiter, continue_processing),
875       IsOk());
876   EXPECT_FALSE(audio_frame_with_data.has_value());
877   EXPECT_FALSE(parameter_block_with_data.has_value());
878   EXPECT_FALSE(temporal_delimiter.has_value());
879   EXPECT_TRUE(continue_processing);
880 
881   // Process again, this time the redundant Codec Config is read and outputs
882   // are empty.
883   EXPECT_THAT(
884       ObuProcessor::ProcessTemporalUnitObu(
885           audio_elements_with_data, codec_config_obus,
886           substream_id_to_audio_element, param_definitions, parameters_manager,
887           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
888           parameter_block_with_data, temporal_delimiter, continue_processing),
889       IsOk());
890   EXPECT_FALSE(audio_frame_with_data.has_value());
891   EXPECT_FALSE(parameter_block_with_data.has_value());
892   EXPECT_FALSE(temporal_delimiter.has_value());
893 
894   // Reaching the end of the stream.
895   EXPECT_FALSE(read_bit_buffer->IsDataAvailable());
896 }
897 
TEST(ProcessTemporalUnitObus,FailsOnNonRedundantAndNonIaSequenceHeaderDescriptorObu)898 TEST(ProcessTemporalUnitObus,
899      FailsOnNonRedundantAndNonIaSequenceHeaderDescriptorObu) {
900   // Set up inputs.
901   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
902   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
903   auto& non_redundant_codec_config = codec_config_obus.at(kFirstCodecConfigId);
904   non_redundant_codec_config.header_.obu_redundant_copy = false;
905 
906   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
907                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
908 
909   const auto temporal_unit_with_non_redundant_codec_config_obu =
910       SerializeObusExpectOk({&audio_frame_obu, &non_redundant_codec_config});
911 
912   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
913       audio_elements_with_data;
914   AddAmbisonicsMonoAudioElementWithSubstreamIds(
915       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
916       codec_config_obus, audio_elements_with_data);
917   auto global_timing_module =
918       GlobalTimingModule::Create(audio_elements_with_data,
919                                  /*param_definitions=*/{});
920   ASSERT_THAT(global_timing_module, NotNull());
921   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
922       substream_id_to_audio_element = {
923           {kFirstSubstreamId,
924            &audio_elements_with_data.at(kFirstAudioElementId)}};
925   ParametersManager parameters_manager(audio_elements_with_data);
926   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
927   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
928   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
929       kBufferCapacity,
930       absl::MakeConstSpan(temporal_unit_with_non_redundant_codec_config_obu));
931 
932   bool continue_processing = true;
933   std::optional<AudioFrameWithData> audio_frame_with_data;
934   std::optional<ParameterBlockWithData> parameter_block_with_data;
935   std::optional<TemporalDelimiterObu> temporal_delimiter;
936   EXPECT_THAT(
937       ObuProcessor::ProcessTemporalUnitObu(
938           audio_elements_with_data, codec_config_obus,
939           substream_id_to_audio_element, param_definitions, parameters_manager,
940           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
941           parameter_block_with_data, temporal_delimiter, continue_processing),
942       IsOk());
943   EXPECT_TRUE(audio_frame_with_data.has_value());
944   EXPECT_FALSE(parameter_block_with_data.has_value());
945   EXPECT_FALSE(temporal_delimiter.has_value());
946   EXPECT_TRUE(continue_processing);
947 
948   // Process again, this time the non-redundant Codec Config OBU is read and
949   // the function fails.
950   EXPECT_FALSE(ObuProcessor::ProcessTemporalUnitObu(
951                    audio_elements_with_data, codec_config_obus,
952                    substream_id_to_audio_element, param_definitions,
953                    parameters_manager, *read_bit_buffer, *global_timing_module,
954                    audio_frame_with_data, parameter_block_with_data,
955                    temporal_delimiter, continue_processing)
956                    .ok());
957 }
958 
TEST(ProcessTemporalUnitObus,ConsumesAllTemporalUnitsAndReservedObus)959 TEST(ProcessTemporalUnitObus, ConsumesAllTemporalUnitsAndReservedObus) {
960   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
961                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
962   ArbitraryObu reserved_obu_before_audio_frame(
963       kObuIaReserved25, ObuHeader(), /*payload=*/{0, 99},
964       ArbitraryObu::kInsertionHookAfterDescriptors);
965   ArbitraryObu reserved_obu_after_audio_frame(
966       kObuIaReserved29, ObuHeader{.obu_redundant_copy = true},
967       /*payload=*/{0, 99}, ArbitraryObu::kInsertionHookAfterDescriptors);
968 
969   const auto temporal_unit_with_reserved_obus =
970       SerializeObusExpectOk({&reserved_obu_before_audio_frame, &audio_frame_obu,
971                              &reserved_obu_after_audio_frame});
972   // Set up inputs.
973   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
974   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
975   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
976       audio_elements_with_data;
977   AddAmbisonicsMonoAudioElementWithSubstreamIds(
978       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
979       codec_config_obus, audio_elements_with_data);
980   auto global_timing_module =
981       GlobalTimingModule::Create(audio_elements_with_data,
982                                  /*param_definitions=*/{});
983   ASSERT_THAT(global_timing_module, NotNull());
984   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
985       substream_id_to_audio_element = {
986           {kFirstSubstreamId,
987            &audio_elements_with_data.at(kFirstAudioElementId)}};
988   ParametersManager parameters_manager(audio_elements_with_data);
989   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
990   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
991   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
992       kBufferCapacity, absl::MakeConstSpan(temporal_unit_with_reserved_obus));
993 
994   bool continue_processing = true;
995   std::optional<AudioFrameWithData> audio_frame_with_data;
996   std::optional<ParameterBlockWithData> parameter_block_with_data;
997   std::optional<TemporalDelimiterObu> temporal_delimiter;
998 
999   // First call: reading and discarding the reserved OBU.
1000   EXPECT_THAT(
1001       ObuProcessor::ProcessTemporalUnitObu(
1002           audio_elements_with_data, codec_config_obus,
1003           substream_id_to_audio_element, param_definitions, parameters_manager,
1004           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1005           parameter_block_with_data, temporal_delimiter, continue_processing),
1006       IsOk());
1007   EXPECT_FALSE(audio_frame_with_data.has_value());
1008   EXPECT_FALSE(parameter_block_with_data.has_value());
1009   EXPECT_FALSE(temporal_delimiter.has_value());
1010   EXPECT_TRUE(continue_processing);
1011 
1012   // Second call: reading the Audio Frame OBU.
1013   EXPECT_THAT(
1014       ObuProcessor::ProcessTemporalUnitObu(
1015           audio_elements_with_data, codec_config_obus,
1016           substream_id_to_audio_element, param_definitions, parameters_manager,
1017           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1018           parameter_block_with_data, temporal_delimiter, continue_processing),
1019       IsOk());
1020   EXPECT_TRUE(audio_frame_with_data.has_value());
1021   EXPECT_FALSE(parameter_block_with_data.has_value());
1022   EXPECT_FALSE(temporal_delimiter.has_value());
1023   EXPECT_TRUE(continue_processing);
1024 
1025   // Third call: reading and discarding the reserved OBU.
1026   EXPECT_THAT(
1027       ObuProcessor::ProcessTemporalUnitObu(
1028           audio_elements_with_data, codec_config_obus,
1029           substream_id_to_audio_element, param_definitions, parameters_manager,
1030           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1031           parameter_block_with_data, temporal_delimiter, continue_processing),
1032       IsOk());
1033   EXPECT_FALSE(audio_frame_with_data.has_value());
1034   EXPECT_FALSE(parameter_block_with_data.has_value());
1035   EXPECT_FALSE(temporal_delimiter.has_value());
1036   EXPECT_TRUE(continue_processing);
1037 
1038   // Reaching the end of the stream.
1039   EXPECT_FALSE(read_bit_buffer->IsDataAvailable());
1040 }
1041 
TEST(ProcessTemporalUnitObusTest,ProcessMultipleAudioSubstreams)1042 TEST(ProcessTemporalUnitObusTest, ProcessMultipleAudioSubstreams) {
1043   std::vector<AudioFrameObu> audio_frame_obus;
1044   audio_frame_obus.push_back(AudioFrameObu(
1045       ObuHeader(), kFirstSubstreamId, /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1046   audio_frame_obus.push_back(
1047       AudioFrameObu(ObuHeader(), kSecondSubstreamId,
1048                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}));
1049   audio_frame_obus.push_back(
1050       AudioFrameObu(ObuHeader(), kImplicitSubstreamId,
1051                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8, 9}));
1052   const auto multiple_audio_substreams = SerializeObusExpectOk(
1053       {&audio_frame_obus[0], &audio_frame_obus[1], &audio_frame_obus[2]});
1054   // Set up inputs.
1055   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1056   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
1057   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
1058       audio_elements_with_data;
1059   AddAmbisonicsMonoAudioElementWithSubstreamIds(
1060       kFirstAudioElementId, kFirstCodecConfigId,
1061       {kFirstSubstreamId, kSecondSubstreamId, kImplicitSubstreamId},
1062       codec_config_obus, audio_elements_with_data);
1063   auto global_timing_module =
1064       GlobalTimingModule::Create(audio_elements_with_data,
1065                                  /*param_definitions=*/{});
1066   ASSERT_THAT(global_timing_module, NotNull());
1067   const auto* first_audio_element =
1068       &audio_elements_with_data.at(kFirstAudioElementId);
1069   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
1070       substream_id_to_audio_element = {
1071           {kFirstSubstreamId, first_audio_element},
1072           {kSecondSubstreamId, first_audio_element},
1073           {kImplicitSubstreamId, first_audio_element}};
1074   ParametersManager parameters_manager(audio_elements_with_data);
1075   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
1076   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
1077   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1078       kBufferCapacity, absl::MakeConstSpan(multiple_audio_substreams));
1079 
1080   bool continue_processing = true;
1081   std::optional<AudioFrameWithData> audio_frame_with_data;
1082   std::optional<ParameterBlockWithData> parameter_block_with_data;
1083   std::optional<TemporalDelimiterObu> temporal_delimiter;
1084 
1085   // Call three times, each outputing an audio frame.
1086   for (int i = 0; i < 3; i++) {
1087     EXPECT_THAT(ObuProcessor::ProcessTemporalUnitObu(
1088                     audio_elements_with_data, codec_config_obus,
1089                     substream_id_to_audio_element, param_definitions,
1090                     parameters_manager, *read_bit_buffer, *global_timing_module,
1091                     audio_frame_with_data, parameter_block_with_data,
1092                     temporal_delimiter, continue_processing),
1093                 IsOk());
1094     EXPECT_TRUE(audio_frame_with_data.has_value());
1095     EXPECT_FALSE(parameter_block_with_data.has_value());
1096     EXPECT_FALSE(temporal_delimiter.has_value());
1097     EXPECT_TRUE(continue_processing);
1098   }
1099 }
1100 
TEST(ProcessTemporalUnitObusTest,ProcessesSubstreamWithMultipleFrames)1101 TEST(ProcessTemporalUnitObusTest, ProcessesSubstreamWithMultipleFrames) {
1102   std::vector<AudioFrameObu> audio_frame_obus;
1103   audio_frame_obus.push_back(AudioFrameObu(
1104       ObuHeader(), kFirstSubstreamId, /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1105   audio_frame_obus.push_back(
1106       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1107                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}));
1108   const auto audio_substream_with_two_frames =
1109       SerializeObusExpectOk({&audio_frame_obus[0], &audio_frame_obus[1]});
1110   // Set up inputs.
1111   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1112   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
1113   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
1114       audio_elements_with_data;
1115   AddAmbisonicsMonoAudioElementWithSubstreamIds(
1116       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
1117       codec_config_obus, audio_elements_with_data);
1118   auto global_timing_module =
1119       GlobalTimingModule::Create(audio_elements_with_data,
1120                                  /*param_definitions=*/{});
1121   ASSERT_THAT(global_timing_module, NotNull());
1122   const auto* first_audio_element =
1123       &audio_elements_with_data.at(kFirstAudioElementId);
1124   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
1125       substream_id_to_audio_element = {
1126           {kFirstSubstreamId, first_audio_element}};
1127   ParametersManager parameters_manager(audio_elements_with_data);
1128   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
1129   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
1130   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1131       kBufferCapacity, absl::MakeConstSpan(audio_substream_with_two_frames));
1132 
1133   bool continue_processing = true;
1134   std::optional<AudioFrameWithData> audio_frame_with_data;
1135   std::optional<ParameterBlockWithData> parameter_block_with_data;
1136   std::optional<TemporalDelimiterObu> temporal_delimiter;
1137 
1138   // Call two times, each outputing an audio frame.
1139   for (int i = 0; i < 2; i++) {
1140     EXPECT_THAT(ObuProcessor::ProcessTemporalUnitObu(
1141                     audio_elements_with_data, codec_config_obus,
1142                     substream_id_to_audio_element, param_definitions,
1143                     parameters_manager, *read_bit_buffer, *global_timing_module,
1144                     audio_frame_with_data, parameter_block_with_data,
1145                     temporal_delimiter, continue_processing),
1146                 IsOk());
1147     EXPECT_TRUE(audio_frame_with_data.has_value());
1148     EXPECT_FALSE(parameter_block_with_data.has_value());
1149     EXPECT_FALSE(temporal_delimiter.has_value());
1150     EXPECT_TRUE(continue_processing);
1151   }
1152 }
1153 
TEST(ProcessTemporalUnitObusTest,ProcessesTemporalDelimiterObu)1154 TEST(ProcessTemporalUnitObusTest, ProcessesTemporalDelimiterObu) {
1155   auto temporal_delimiter_obu = TemporalDelimiterObu(ObuHeader());
1156   std::vector<AudioFrameObu> audio_frame_obus;
1157   audio_frame_obus.push_back(
1158       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1159                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1160   audio_frame_obus.push_back(
1161       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1162                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1163 
1164   const auto two_temporal_units_with_delimiter_obu =
1165       SerializeObusExpectOk({&audio_frame_obus[0], &temporal_delimiter_obu,
1166                              &audio_frame_obus[1], &temporal_delimiter_obu});
1167   // Set up inputs.
1168   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1169   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
1170   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
1171       audio_elements_with_data;
1172   AddAmbisonicsMonoAudioElementWithSubstreamIds(
1173       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
1174       codec_config_obus, audio_elements_with_data);
1175   auto global_timing_module =
1176       GlobalTimingModule::Create(audio_elements_with_data,
1177                                  /*param_definitions=*/{});
1178   ASSERT_THAT(global_timing_module, NotNull());
1179   const auto* first_audio_element =
1180       &audio_elements_with_data.at(kFirstAudioElementId);
1181   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
1182       substream_id_to_audio_element = {
1183           {kFirstSubstreamId, first_audio_element}};
1184   ParametersManager parameters_manager(audio_elements_with_data);
1185   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
1186   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
1187   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1188       kBufferCapacity,
1189       absl::MakeConstSpan(two_temporal_units_with_delimiter_obu));
1190 
1191   bool continue_processing = true;
1192   std::optional<AudioFrameWithData> audio_frame_with_data;
1193   std::optional<ParameterBlockWithData> parameter_block_with_data;
1194   std::optional<TemporalDelimiterObu> temporal_delimiter;
1195 
1196   // Call four times, outputing two audio frames and two temporal delimiters.
1197   const std::vector<bool> expecting_audio_frame = {true, false, true, false};
1198   const std::vector<bool> expecting_temporal_delimiter = {false, true, false,
1199                                                           true};
1200   for (int i = 0; i < 4; i++) {
1201     EXPECT_THAT(ObuProcessor::ProcessTemporalUnitObu(
1202                     audio_elements_with_data, codec_config_obus,
1203                     substream_id_to_audio_element, param_definitions,
1204                     parameters_manager, *read_bit_buffer, *global_timing_module,
1205                     audio_frame_with_data, parameter_block_with_data,
1206                     temporal_delimiter, continue_processing),
1207                 IsOk());
1208     EXPECT_EQ(audio_frame_with_data.has_value(), expecting_audio_frame[i]);
1209     EXPECT_FALSE(parameter_block_with_data.has_value());
1210     EXPECT_EQ(temporal_delimiter.has_value(), expecting_temporal_delimiter[i]);
1211     EXPECT_TRUE(continue_processing);
1212   }
1213 }
1214 
TEST(ProcessTemporalUnitObusTest,FillsMetadataAndTimestampsForParameterBlocks)1215 TEST(ProcessTemporalUnitObusTest,
1216      FillsMetadataAndTimestampsForParameterBlocks) {
1217   constexpr DecodedUleb128 kParameterBlockId = 1;
1218   constexpr DecodedUleb128 kParameterBlockDuration = 10;
1219   // Set up inputs.
1220   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1221   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
1222   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
1223       audio_elements_with_data;
1224   AddAmbisonicsMonoAudioElementWithSubstreamIds(
1225       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
1226       codec_config_obus, audio_elements_with_data);
1227 
1228   // Param definition.
1229   MixGainParamDefinition param_definition;
1230   param_definition.parameter_id_ = kParameterBlockId;
1231   param_definition.parameter_rate_ = 1;
1232   param_definition.param_definition_mode_ = 0;
1233   param_definition.duration_ = kParameterBlockDuration;
1234   param_definition.constant_subblock_duration_ = kParameterBlockDuration;
1235   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
1236   param_definitions.emplace(kParameterBlockId, param_definition);
1237   ParameterBlockObu parameter_block_obu(ObuHeader(), kParameterBlockId,
1238                                         param_definition);
1239   EXPECT_THAT(parameter_block_obu.InitializeSubblocks(), IsOk());
1240   parameter_block_obu.subblocks_[0].param_data =
1241       std::make_unique<MixGainParameterData>(
1242           MixGainParameterData::kAnimateStep,
1243           AnimationStepInt16{.start_point_value = 99});
1244 
1245   // Initialize the sequence with a single parameter block.
1246   const auto one_parameter_block_obu =
1247       SerializeObusExpectOk({&parameter_block_obu});
1248   auto global_timing_module =
1249       GlobalTimingModule::Create(audio_elements_with_data, param_definitions);
1250   ASSERT_THAT(global_timing_module, NotNull());
1251   const auto* first_audio_element =
1252       &audio_elements_with_data.at(kFirstAudioElementId);
1253   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
1254       substream_id_to_audio_element = {
1255           {kFirstSubstreamId, first_audio_element}};
1256   ParametersManager parameters_manager(audio_elements_with_data);
1257   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
1258   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1259       kBufferCapacity, absl::MakeConstSpan(one_parameter_block_obu));
1260 
1261   bool continue_processing = true;
1262   std::optional<AudioFrameWithData> audio_frame_with_data;
1263   std::optional<ParameterBlockWithData> parameter_block_with_data;
1264   std::optional<TemporalDelimiterObu> temporal_delimiter;
1265   EXPECT_THAT(
1266       ObuProcessor::ProcessTemporalUnitObu(
1267           audio_elements_with_data, codec_config_obus,
1268           substream_id_to_audio_element, param_definitions, parameters_manager,
1269           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1270           parameter_block_with_data, temporal_delimiter, continue_processing),
1271       IsOk());
1272   EXPECT_FALSE(audio_frame_with_data.has_value());
1273   EXPECT_TRUE(parameter_block_with_data.has_value());
1274   EXPECT_FALSE(temporal_delimiter.has_value());
1275   EXPECT_TRUE(continue_processing);
1276 
1277   const int32_t kObuRelativeTime = 0;
1278   float unused_mix_gain;
1279   EXPECT_THAT(parameter_block_with_data->obu->GetLinearMixGain(kObuRelativeTime,
1280                                                                unused_mix_gain),
1281               IsOk());
1282   EXPECT_EQ(parameter_block_with_data->start_timestamp, 0);
1283   EXPECT_EQ(parameter_block_with_data->end_timestamp, kParameterBlockDuration);
1284 }
1285 
TEST(ProcessTemporalUnitObus,ConsumesAllTemporalUnitsWithAnIncompleteHeaderAtEnd)1286 TEST(ProcessTemporalUnitObus,
1287      ConsumesAllTemporalUnitsWithAnIncompleteHeaderAtEnd) {
1288   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1289                                 kArbitraryAudioFrame);
1290 
1291   auto one_temporal_unit = SerializeObusExpectOk({&audio_frame_obu});
1292 
1293   // Set up inputs with descriptors, one audio frame, and one incomplete header.
1294   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1295   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
1296   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
1297       audio_elements_with_data;
1298   AddAmbisonicsMonoAudioElementWithSubstreamIds(
1299       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
1300       codec_config_obus, audio_elements_with_data);
1301   auto global_timing_module =
1302       GlobalTimingModule::Create(audio_elements_with_data,
1303                                  /*param_definitions=*/{});
1304   ASSERT_THAT(global_timing_module, NotNull());
1305 
1306   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
1307       substream_id_to_audio_element = {
1308           {kFirstSubstreamId,
1309            &audio_elements_with_data.at(kFirstAudioElementId)}};
1310   ParametersManager parameters_manager(audio_elements_with_data);
1311   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
1312   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
1313   // Add a single byte to the end of the temporal unit to represent an
1314   // incomplete header (A header requires at least 2 bytes).
1315   one_temporal_unit.push_back(0);
1316   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1317       kBufferCapacity, absl::MakeConstSpan(one_temporal_unit));
1318 
1319   // Confirm that the first temporal unit is processed successfully.
1320   bool continue_processing = true;
1321   std::optional<AudioFrameWithData> audio_frame_with_data;
1322   std::optional<ParameterBlockWithData> parameter_block_with_data;
1323   std::optional<TemporalDelimiterObu> temporal_delimiter;
1324   EXPECT_THAT(
1325       ObuProcessor::ProcessTemporalUnitObu(
1326           audio_elements_with_data, codec_config_obus,
1327           substream_id_to_audio_element, param_definitions, parameters_manager,
1328           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1329           parameter_block_with_data, temporal_delimiter, continue_processing),
1330       IsOk());
1331   EXPECT_TRUE(audio_frame_with_data.has_value());
1332 
1333   // Confirm that the second temporal unit it is incomplete.
1334   auto start_position = read_bit_buffer->Tell();
1335   EXPECT_THAT(
1336       ObuProcessor::ProcessTemporalUnitObu(
1337           audio_elements_with_data, codec_config_obus,
1338           substream_id_to_audio_element, param_definitions, parameters_manager,
1339           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1340           parameter_block_with_data, temporal_delimiter, continue_processing),
1341       IsOk());
1342   EXPECT_FALSE(audio_frame_with_data.has_value());
1343   EXPECT_FALSE(parameter_block_with_data.has_value());
1344   EXPECT_FALSE(temporal_delimiter.has_value());
1345   EXPECT_FALSE(continue_processing);
1346   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
1347 }
1348 
TEST(ProcessTemporalUnitObus,ConsumesAllTemporalUnitsWithAnIncompleteObuAtEnd)1349 TEST(ProcessTemporalUnitObus,
1350      ConsumesAllTemporalUnitsWithAnIncompleteObuAtEnd) {
1351   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1352                                 kArbitraryAudioFrame);
1353 
1354   auto ia_sequence = SerializeObusExpectOk({&audio_frame_obu});
1355 
1356   // Set up inputs with descriptors, one audio frame, and one incomplete obu
1357   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1358   AddOpusCodecConfigWithId(kFirstCodecConfigId, codec_config_obus);
1359   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
1360       audio_elements_with_data;
1361   AddAmbisonicsMonoAudioElementWithSubstreamIds(
1362       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
1363       codec_config_obus, audio_elements_with_data);
1364   auto global_timing_module =
1365       GlobalTimingModule::Create(audio_elements_with_data,
1366                                  /*param_definitions=*/{});
1367   ASSERT_THAT(global_timing_module, NotNull());
1368 
1369   const absl::flat_hash_map<DecodedUleb128, const AudioElementWithData*>
1370       substream_id_to_audio_element = {
1371           {kFirstSubstreamId,
1372            &audio_elements_with_data.at(kFirstAudioElementId)}};
1373   ParametersManager parameters_manager(audio_elements_with_data);
1374   ASSERT_THAT(parameters_manager.Initialize(), IsOk());
1375   absl::flat_hash_map<DecodedUleb128, ParamDefinitionVariant> param_definitions;
1376   std::vector<uint8_t> extra_audio_frame_obu_header_bytes = {
1377       kObuIaAudioFrameId0 << kObuTypeBitShift,
1378       // `obu_size`. -> Non-zero size, but we have no bytes following.
1379       0x7f};
1380   ia_sequence.insert(ia_sequence.end(),
1381                      extra_audio_frame_obu_header_bytes.begin(),
1382                      extra_audio_frame_obu_header_bytes.end());
1383   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1384       kBufferCapacity, absl::MakeConstSpan(ia_sequence));
1385 
1386   // Confirm that the first temporal unit is processed successfully.
1387   bool continue_processing = true;
1388   std::optional<AudioFrameWithData> audio_frame_with_data;
1389   std::optional<ParameterBlockWithData> parameter_block_with_data;
1390   std::optional<TemporalDelimiterObu> temporal_delimiter;
1391   EXPECT_THAT(
1392       ObuProcessor::ProcessTemporalUnitObu(
1393           audio_elements_with_data, codec_config_obus,
1394           substream_id_to_audio_element, param_definitions, parameters_manager,
1395           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1396           parameter_block_with_data, temporal_delimiter, continue_processing),
1397       IsOk());
1398   EXPECT_TRUE(audio_frame_with_data.has_value());
1399 
1400   // Confirm that the second temporal unit it is incomplete.
1401   auto start_position = read_bit_buffer->Tell();
1402   EXPECT_THAT(
1403       ObuProcessor::ProcessTemporalUnitObu(
1404           audio_elements_with_data, codec_config_obus,
1405           substream_id_to_audio_element, param_definitions, parameters_manager,
1406           *read_bit_buffer, *global_timing_module, audio_frame_with_data,
1407           parameter_block_with_data, temporal_delimiter, continue_processing),
1408       IsOk());
1409   EXPECT_FALSE(audio_frame_with_data.has_value());
1410   EXPECT_FALSE(parameter_block_with_data.has_value());
1411   EXPECT_FALSE(temporal_delimiter.has_value());
1412   EXPECT_FALSE(continue_processing);
1413   EXPECT_EQ(read_bit_buffer->Tell(), start_position);
1414 }
1415 
1416 using OutputTemporalUnit = ObuProcessor::OutputTemporalUnit;
1417 
TEST(ProcessTemporalUnit,ConsumesOneAudioFrameAsTemporalUnit)1418 TEST(ProcessTemporalUnit, ConsumesOneAudioFrameAsTemporalUnit) {
1419   // Set up inputs with a single audio frame.
1420   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1421   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1422                                 kArbitraryAudioFrame);
1423   auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
1424   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
1425                    temporal_unit_obus.end());
1426   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1427       kBufferCapacity, absl::MakeConstSpan(bitstream));
1428   bool insufficient_data;
1429   auto obu_processor =
1430       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1431                            read_bit_buffer.get(), insufficient_data);
1432   ASSERT_THAT(obu_processor, NotNull());
1433   ASSERT_FALSE(insufficient_data);
1434 
1435   // Call `ProcessTemporalUnit()` with `eos_is_end_of_sequence` set to true.
1436   // This means that we can assume that the end of the stream implies the end of
1437   // the temporal unit.
1438   std::optional<OutputTemporalUnit> output_temporal_unit;
1439   bool continue_processing = true;
1440   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1441                   /*eos_is_end_of_sequence=*/true, output_temporal_unit,
1442                   continue_processing),
1443               IsOk());
1444 
1445   EXPECT_FALSE(continue_processing);
1446   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1447 }
1448 
TEST(ProcessTemporalUnit,DoesNotConsumeOneAudioFrameAsTemporalUnit)1449 TEST(ProcessTemporalUnit, DoesNotConsumeOneAudioFrameAsTemporalUnit) {
1450   // Set up inputs with a single audio frame.
1451   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1452   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1453                                 /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8});
1454   auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
1455   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
1456                    temporal_unit_obus.end());
1457   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1458       kBufferCapacity, absl::MakeConstSpan(bitstream));
1459   bool insufficient_data;
1460   auto obu_processor =
1461       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1462                            read_bit_buffer.get(), insufficient_data);
1463   ASSERT_THAT(obu_processor, NotNull());
1464   ASSERT_FALSE(insufficient_data);
1465 
1466   std::optional<OutputTemporalUnit> output_temporal_unit;
1467   bool continue_processing = true;
1468   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1469                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1470                   continue_processing),
1471               IsOk());
1472 
1473   EXPECT_FALSE(continue_processing);
1474   EXPECT_FALSE(output_temporal_unit.has_value());
1475 }
1476 
TEST(ProcessTemporalUnit,ConsumesMultipleTemporalUnitsWithTemporalDelimiters)1477 TEST(ProcessTemporalUnit, ConsumesMultipleTemporalUnitsWithTemporalDelimiters) {
1478   // Set up inputs with two audio frames and temporal delimiters.
1479   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1480   auto temporal_delimiter_obu = TemporalDelimiterObu(ObuHeader());
1481   std::vector<AudioFrameObu> audio_frame_obus;
1482   audio_frame_obus.push_back(
1483       AudioFrameObu(ObuHeader(), kFirstSubstreamId, kArbitraryAudioFrame));
1484   audio_frame_obus.push_back(
1485       AudioFrameObu(ObuHeader(), kFirstSubstreamId, kArbitraryAudioFrame));
1486   const auto two_temporal_units_with_delimiter_obu =
1487       SerializeObusExpectOk({&audio_frame_obus[0], &temporal_delimiter_obu,
1488                              &audio_frame_obus[1], &temporal_delimiter_obu});
1489   bitstream.insert(bitstream.end(),
1490                    two_temporal_units_with_delimiter_obu.begin(),
1491                    two_temporal_units_with_delimiter_obu.end());
1492   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1493       kBufferCapacity, absl::MakeConstSpan(bitstream));
1494   bool insufficient_data;
1495   auto obu_processor =
1496       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1497                            read_bit_buffer.get(), insufficient_data);
1498   ASSERT_THAT(obu_processor, NotNull());
1499   ASSERT_FALSE(insufficient_data);
1500 
1501   std::optional<OutputTemporalUnit> output_temporal_unit;
1502   bool continue_processing = true;
1503   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1504                   /*eos_is_end_of_sequence=*/true, output_temporal_unit,
1505                   continue_processing),
1506               IsOk());
1507 
1508   // The first temporal unit is consumed; it should only contain the first
1509   // audio frame.
1510   EXPECT_TRUE(continue_processing);
1511   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1512 
1513   output_temporal_unit.reset();
1514   continue_processing = true;
1515   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1516                   /*eos_is_end_of_sequence=*/true, output_temporal_unit,
1517                   continue_processing),
1518               IsOk());
1519   // Seeing a temporal delimiter at the end of the stream implies that the
1520   // stream is incomplete.
1521   EXPECT_TRUE(continue_processing);
1522   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1523 }
1524 
TEST(ProcessTemporalUnit,ConsumesMultipleTemporalUnitsWithoutTemporalDelimiters)1525 TEST(ProcessTemporalUnit,
1526      ConsumesMultipleTemporalUnitsWithoutTemporalDelimiters) {
1527   // Set up inputs with two audio frames. Two audio frames are known to be in a
1528   // separate temporal unit if they have the same substream ID. Their underlying
1529   // timestamps are different.
1530   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1531   std::vector<AudioFrameObu> audio_frame_obus;
1532   audio_frame_obus.push_back(
1533       AudioFrameObu(ObuHeader(), kFirstSubstreamId, kArbitraryAudioFrame));
1534   audio_frame_obus.push_back(
1535       AudioFrameObu(ObuHeader(), kFirstSubstreamId, kArbitraryAudioFrame));
1536   const auto two_temporal_units =
1537       SerializeObusExpectOk({&audio_frame_obus[0], &audio_frame_obus[1]});
1538   bitstream.insert(bitstream.end(), two_temporal_units.begin(),
1539                    two_temporal_units.end());
1540   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1541       kBufferCapacity, absl::MakeConstSpan(bitstream));
1542   bool insufficient_data;
1543   auto obu_processor =
1544       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1545                            read_bit_buffer.get(), insufficient_data);
1546   ASSERT_THAT(obu_processor, NotNull());
1547   ASSERT_FALSE(insufficient_data);
1548 
1549   std::optional<OutputTemporalUnit> output_temporal_unit;
1550   bool continue_processing = true;
1551   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1552                   /*eos_is_end_of_sequence=*/true, output_temporal_unit,
1553                   continue_processing),
1554               IsOk());
1555 
1556   // The first temporal unit is consumed; it should only contain the first
1557   // audio frame.
1558   EXPECT_TRUE(continue_processing);
1559   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1560 
1561   output_temporal_unit.reset();
1562   continue_processing = true;
1563   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1564                   /*eos_is_end_of_sequence=*/true, output_temporal_unit,
1565                   continue_processing),
1566               IsOk());
1567 
1568   EXPECT_FALSE(continue_processing);
1569   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1570 }
1571 
TEST(ProcessTemporalUnit,ConsumesOnlyOneTemporalUnitFromTwoAudioFrames)1572 TEST(ProcessTemporalUnit, ConsumesOnlyOneTemporalUnitFromTwoAudioFrames) {
1573   // eos_is_end_of_sequence is false. Only one temporal unit is consumed because
1574   // we don't know that the second temporal unit is finished.
1575 
1576   // Set up inputs with two audio frames. Two audio
1577   // frames are known to be in a separate temporal unit if they have the same
1578   // substream ID. Their underlying timestamps are different.
1579   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1580   std::vector<AudioFrameObu> audio_frame_obus;
1581   audio_frame_obus.push_back(
1582       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1583                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1584   audio_frame_obus.push_back(
1585       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1586                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1587   const auto two_temporal_units =
1588       SerializeObusExpectOk({&audio_frame_obus[0], &audio_frame_obus[1]});
1589   bitstream.insert(bitstream.end(), two_temporal_units.begin(),
1590                    two_temporal_units.end());
1591   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1592       kBufferCapacity, absl::MakeConstSpan(bitstream));
1593   bool insufficient_data;
1594   auto obu_processor =
1595       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1596                            read_bit_buffer.get(), insufficient_data);
1597   ASSERT_THAT(obu_processor, NotNull());
1598   ASSERT_FALSE(insufficient_data);
1599 
1600   std::optional<OutputTemporalUnit> output_temporal_unit;
1601   bool continue_processing = true;
1602   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1603                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1604                   continue_processing),
1605               IsOk());
1606 
1607   // The first temporal unit is consumed; it should only contain the first
1608   // audio frame.
1609   EXPECT_TRUE(continue_processing);
1610   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1611 
1612   output_temporal_unit.reset();
1613   continue_processing = true;
1614   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1615                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1616                   continue_processing),
1617               IsOk());
1618 
1619   EXPECT_FALSE(continue_processing);
1620   EXPECT_FALSE(output_temporal_unit.has_value());
1621 }
1622 
TEST(ProcessTemporalUnit,ConsumesOnlyOneTemporalUnitFromTwoAudioFramesAndIncompleteObuAtEnd)1623 TEST(ProcessTemporalUnit,
1624      ConsumesOnlyOneTemporalUnitFromTwoAudioFramesAndIncompleteObuAtEnd) {
1625   // eos_is_end_of_sequence is false. Only one temporal unit is consumed because
1626   // we don't know that the second temporal unit is finished.
1627 
1628   // Set up inputs with two audio frames. Two audio
1629   // frames are known to be in a separate temporal unit if they have the same
1630   // substream ID. Their underlying timestamps are different.
1631   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1632   std::vector<AudioFrameObu> audio_frame_obus;
1633   audio_frame_obus.push_back(
1634       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1635                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1636   audio_frame_obus.push_back(
1637       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1638                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1639   auto two_temporal_units =
1640       SerializeObusExpectOk({&audio_frame_obus[0], &audio_frame_obus[1]});
1641   std::vector<uint8_t> extra_audio_frame_obu_header_bytes = {
1642       kObuIaAudioFrameId0 << kObuTypeBitShift,
1643       // `obu_size`. -> Non-zero size, but we have no bytes following.
1644       0x7f};
1645   two_temporal_units.insert(two_temporal_units.end(),
1646                             extra_audio_frame_obu_header_bytes.begin(),
1647                             extra_audio_frame_obu_header_bytes.end());
1648   bitstream.insert(bitstream.end(), two_temporal_units.begin(),
1649                    two_temporal_units.end());
1650   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1651       kBufferCapacity, absl::MakeConstSpan(bitstream));
1652   bool insufficient_data;
1653   auto obu_processor =
1654       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1655                            read_bit_buffer.get(), insufficient_data);
1656   ASSERT_THAT(obu_processor, NotNull());
1657   ASSERT_FALSE(insufficient_data);
1658 
1659   std::optional<OutputTemporalUnit> output_temporal_unit;
1660   bool continue_processing = false;
1661   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1662                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1663                   continue_processing),
1664               IsOk());
1665 
1666   // The first temporal unit is consumed; it should only contain the first
1667   // audio frame.
1668   EXPECT_TRUE(continue_processing);
1669   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1670 
1671   output_temporal_unit.reset();
1672   continue_processing = true;
1673   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1674                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1675                   continue_processing),
1676               IsOk());
1677 
1678   // The second temporal unit is not consumed since we don't know that it is
1679   // complete.
1680   EXPECT_FALSE(continue_processing);
1681   EXPECT_FALSE(output_temporal_unit.has_value());
1682 }
1683 
TEST(ProcessTemporalUnit,ConsumesMultipleTemporalUnitsChunkedArbitrarily)1684 TEST(ProcessTemporalUnit, ConsumesMultipleTemporalUnitsChunkedArbitrarily) {
1685   // Set up inputs with two audio frames. Two audio frames are known to be in a
1686   // separate temporal unit if they have the same substream ID. Their underlying
1687   // timestamps are different.
1688   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1689   auto read_bit_buffer = StreamBasedReadBitBuffer::Create(kBufferCapacity);
1690   // Push descriptors.
1691   ASSERT_THAT(read_bit_buffer->PushBytes(bitstream), IsOk());
1692   bool insufficient_data;
1693   auto obu_processor =
1694       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
1695                            read_bit_buffer.get(), insufficient_data);
1696   ASSERT_THAT(obu_processor, NotNull());
1697   ASSERT_FALSE(insufficient_data);
1698 
1699   std::vector<AudioFrameObu> audio_frame_obus;
1700   audio_frame_obus.push_back(
1701       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1702                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1703   audio_frame_obus.push_back(
1704       AudioFrameObu(ObuHeader(), kFirstSubstreamId,
1705                     /*audio_frame=*/{2, 3, 4, 5, 6, 7, 8}));
1706   const auto two_temporal_units =
1707       SerializeObusExpectOk({&audio_frame_obus[0], &audio_frame_obus[1]});
1708 
1709   // Split the temporal units into three chunks.
1710   const int64_t chunk_size = two_temporal_units.size() / 3;
1711   std::vector<uint8_t> chunk_1(two_temporal_units.begin(),
1712                                two_temporal_units.begin() + chunk_size);
1713   std::vector<uint8_t> chunk_2(two_temporal_units.begin() + chunk_size,
1714                                two_temporal_units.begin() + 2 * chunk_size);
1715   std::vector<uint8_t> chunk_3(two_temporal_units.begin() + 2 * chunk_size,
1716                                two_temporal_units.end());
1717 
1718   // Chunk 1.
1719   ASSERT_THAT(read_bit_buffer->PushBytes(chunk_1), IsOk());
1720   std::optional<OutputTemporalUnit> output_temporal_unit;
1721   bool continue_processing = true;
1722   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1723                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1724                   continue_processing),
1725               IsOk());
1726 
1727   // Chunk 1 is not enough to finish reading the first audio frame, so the
1728   // first temporal unit is not finished.
1729   EXPECT_FALSE(continue_processing);
1730   EXPECT_FALSE(output_temporal_unit.has_value());
1731 
1732   // Chunk 2.
1733   ASSERT_THAT(read_bit_buffer->PushBytes(chunk_2), IsOk());
1734   continue_processing = true;
1735   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1736                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1737                   continue_processing),
1738               IsOk());
1739 
1740   // Chunk 2 is enough to finish reading the first audio frame, but not the
1741   // second. Since we haven't finished reading the second audio frame, we cannot
1742   // know that the first temporal unit is complete. Therefore we still do not
1743   // have a temporal unit.
1744   EXPECT_FALSE(continue_processing);
1745   EXPECT_FALSE(output_temporal_unit.has_value());
1746 
1747   // Chunk 3.
1748   ASSERT_THAT(read_bit_buffer->PushBytes(chunk_3), IsOk());
1749   continue_processing = true;
1750   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1751                   /*eos_is_end_of_sequence=*/false, output_temporal_unit,
1752                   continue_processing),
1753               IsOk());
1754 
1755   // Chunk 3 is enough to finish reading the second audio frame, so the first
1756   // temporal unit is now complete. But we don't know that the second temporal
1757   // unit is complete since more data could be coming behind it.
1758   EXPECT_TRUE(continue_processing);
1759   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1760 
1761   // To get the second temporal unit, we make one final call with
1762   // `eos_is_end_of_sequence` set to true. At this point, the bitstream is
1763   // exhausted, but we can get the second temporal unit that we previously
1764   // processed since we now know that the sequence is complete.
1765   continue_processing = true;
1766   output_temporal_unit.reset();
1767   EXPECT_THAT(obu_processor->ProcessTemporalUnit(
1768                   /*eos_is_end_of_sequence=*/true, output_temporal_unit,
1769                   continue_processing),
1770               IsOk());
1771 
1772   EXPECT_FALSE(continue_processing);
1773   EXPECT_EQ(output_temporal_unit->output_audio_frames.size(), 1);
1774 }
1775 
1776 // TODO(b/377772983): Test rejecting processing temporal units with mismatching
1777 //                    durations from parameter blocks and audio frames.
1778 // TODO(b/377772983): Test rejecting processing temporal units where the
1779 //                    required descriptors (audio elements, codec configs, etc.)
1780 //                    are not present.
1781 
1782 constexpr bool kWriteWavHeader = true;
1783 constexpr bool kDontWriteWavHeader = false;
1784 constexpr Layout kStereoLayout = {
1785     .layout_type = Layout::kLayoutTypeLoudspeakersSsConvention,
1786     .specific_layout = LoudspeakersSsConventionLayout{
1787         .sound_system = LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0}};
1788 
TEST(CollectObusFromIaSequence,ConsumesIaSequenceAndCollectsAllObus)1789 TEST(CollectObusFromIaSequence, ConsumesIaSequenceAndCollectsAllObus) {
1790   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1791   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1792                                 kArbitraryAudioFrame);
1793   const auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
1794   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
1795                    temporal_unit_obus.end());
1796   const int64_t ia_sequence_size = bitstream.size();
1797 
1798   IASequenceHeaderObu ia_sequence_header;
1799   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1800   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
1801   std::list<MixPresentationObu> mix_presentation_obus;
1802   std::list<AudioFrameWithData> audio_frames;
1803   std::list<ParameterBlockWithData> parameter_blocks;
1804   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1805       kBufferCapacity, absl::MakeConstSpan(bitstream));
1806   EXPECT_THAT(CollectObusFromIaSequence(*read_bit_buffer, ia_sequence_header,
1807                                         codec_config_obus, audio_elements,
1808                                         mix_presentation_obus, audio_frames,
1809                                         parameter_blocks),
1810               IsOk());
1811   EXPECT_EQ(read_bit_buffer->Tell(), ia_sequence_size * 8);
1812 
1813   // Reaching the end of the stream.
1814   EXPECT_FALSE(read_bit_buffer->IsDataAvailable());
1815   EXPECT_TRUE(codec_config_obus.contains(kFirstCodecConfigId));
1816   EXPECT_TRUE(audio_elements.contains(kFirstAudioElementId));
1817   EXPECT_FALSE(mix_presentation_obus.empty());
1818   EXPECT_EQ(mix_presentation_obus.front().GetMixPresentationId(),
1819             kFirstMixPresentationId);
1820   EXPECT_FALSE(audio_frames.empty());
1821   EXPECT_EQ(audio_frames.front().obu.GetSubstreamId(), kFirstSubstreamId);
1822   EXPECT_TRUE(parameter_blocks.empty());
1823 }
1824 
TEST(CollectObusFromIaSequence,ConsumesTrivialIaSequence)1825 TEST(CollectObusFromIaSequence, ConsumesTrivialIaSequence) {
1826   const IASequenceHeaderObu input_non_redundant_ia_sequence_header(
1827       ObuHeader(), IASequenceHeaderObu::kIaCode,
1828       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1829   const auto trivial_ia_sequence =
1830       SerializeObusExpectOk({&input_non_redundant_ia_sequence_header});
1831   auto non_trivial_ia_sequence = InitAllDescriptorsForZerothOrderAmbisonics();
1832   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1833                                 kArbitraryAudioFrame);
1834   const auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
1835   non_trivial_ia_sequence.insert(non_trivial_ia_sequence.end(),
1836                                  temporal_unit_obus.begin(),
1837                                  temporal_unit_obus.end());
1838   std::vector<uint8_t> two_ia_sequences(trivial_ia_sequence);
1839   const int64_t trivial_ia_sequence_size = trivial_ia_sequence.size();
1840 
1841   two_ia_sequences.insert(two_ia_sequences.end(),
1842                           non_trivial_ia_sequence.begin(),
1843                           non_trivial_ia_sequence.end());
1844   const int64_t two_ia_sequences_size = two_ia_sequences.size();
1845 
1846   IASequenceHeaderObu ia_sequence_header;
1847   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1848   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
1849   std::list<MixPresentationObu> mix_presentation_obus;
1850   std::list<AudioFrameWithData> audio_frames;
1851   std::list<ParameterBlockWithData> parameter_blocks;
1852   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1853       kBufferCapacity, absl::MakeConstSpan(two_ia_sequences));
1854   EXPECT_THAT(CollectObusFromIaSequence(*read_bit_buffer, ia_sequence_header,
1855                                         codec_config_obus, audio_elements,
1856                                         mix_presentation_obus, audio_frames,
1857                                         parameter_blocks),
1858               IsOk());
1859   EXPECT_EQ(read_bit_buffer->Tell(), trivial_ia_sequence_size * 8);
1860 
1861   // The first IA sequence is trivial and should be consumed.
1862   EXPECT_TRUE(codec_config_obus.empty());
1863   EXPECT_TRUE(audio_elements.empty());
1864   EXPECT_TRUE(mix_presentation_obus.empty());
1865   EXPECT_TRUE(audio_frames.empty());
1866   EXPECT_TRUE(parameter_blocks.empty());
1867 
1868   // A second call retrieves the next IA sequence, which has an audio frame.
1869   EXPECT_THAT(CollectObusFromIaSequence(*read_bit_buffer, ia_sequence_header,
1870                                         codec_config_obus, audio_elements,
1871                                         mix_presentation_obus, audio_frames,
1872                                         parameter_blocks),
1873               IsOk());
1874   EXPECT_FALSE(audio_frames.empty());
1875   EXPECT_EQ(read_bit_buffer->Tell(), two_ia_sequences_size * 8);
1876 }
1877 
TEST(CollectObusFromIaSequence,ConsumesUpToNextIaSequence)1878 TEST(CollectObusFromIaSequence, ConsumesUpToNextIaSequence) {
1879   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1880   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
1881                                 kArbitraryAudioFrame);
1882   const auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
1883   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
1884                    temporal_unit_obus.end());
1885   const int64_t first_ia_sequence_size = bitstream.size();
1886   const IASequenceHeaderObu non_redundant_ia_sequence_header(
1887       ObuHeader{.obu_redundant_copy = false}, IASequenceHeaderObu::kIaCode,
1888       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1889   const auto start_of_second_ia_sequence =
1890       SerializeObusExpectOk({&non_redundant_ia_sequence_header});
1891   bitstream.insert(bitstream.end(), start_of_second_ia_sequence.begin(),
1892                    start_of_second_ia_sequence.end());
1893 
1894   IASequenceHeaderObu ia_sequence_header;
1895   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1896   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements;
1897   std::list<MixPresentationObu> mix_presentation_obus;
1898   std::list<AudioFrameWithData> audio_frames;
1899   std::list<ParameterBlockWithData> parameter_blocks;
1900   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1901       kBufferCapacity, absl::MakeConstSpan(bitstream));
1902   EXPECT_THAT(CollectObusFromIaSequence(*read_bit_buffer, ia_sequence_header,
1903                                         codec_config_obus, audio_elements,
1904                                         mix_presentation_obus, audio_frames,
1905                                         parameter_blocks),
1906               IsOk());
1907 
1908   // Expect the reader position to be right next to the end of the first IA
1909   // sequence.
1910   EXPECT_EQ(read_bit_buffer->Tell(), first_ia_sequence_size * 8);
1911 }
1912 
TEST(Create,Succeeds)1913 TEST(Create, Succeeds) {
1914   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1915   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1916       kBufferCapacity, absl::MakeConstSpan(bitstream));
1917   bool insufficient_data;
1918 
1919   auto obu_processor =
1920       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
1921                            read_bit_buffer.get(), insufficient_data);
1922 
1923   EXPECT_THAT(obu_processor, NotNull());
1924   EXPECT_FALSE(insufficient_data);
1925   EXPECT_EQ(obu_processor->audio_elements_.size(), 1);
1926   EXPECT_EQ(obu_processor->codec_config_obus_.size(), 1);
1927   EXPECT_EQ(obu_processor->mix_presentations_.size(), 1);
1928 }
1929 
TEST(Create,SucceedsForTrivialIaSequence)1930 TEST(Create, SucceedsForTrivialIaSequence) {
1931   const IASequenceHeaderObu kIaSequenceHeader(
1932       ObuHeader(), IASequenceHeaderObu::kIaCode,
1933       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1934   auto buffer = SerializeObusExpectOk({&kIaSequenceHeader});
1935   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1936       kBufferCapacity, absl::MakeConstSpan(buffer));
1937   bool insufficient_data;
1938   auto obu_processor =
1939       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
1940                            read_bit_buffer.get(), insufficient_data);
1941 
1942   EXPECT_THAT(obu_processor, NotNull());
1943   EXPECT_FALSE(insufficient_data);
1944 }
1945 
TEST(Create,FailsOnNullReadBitBuffer)1946 TEST(Create, FailsOnNullReadBitBuffer) {
1947   bool insufficient_data;
1948 
1949   auto obu_processor = ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1950                                             nullptr, insufficient_data);
1951 
1952   EXPECT_THAT(obu_processor, IsNull());
1953   EXPECT_FALSE(insufficient_data);
1954 }
1955 
TEST(Create,FailsOnInsufficientData)1956 TEST(Create, FailsOnInsufficientData) {
1957   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
1958   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1959       kBufferCapacity, absl::MakeConstSpan(bitstream));
1960   bool insufficient_data;
1961 
1962   auto obu_processor =
1963       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
1964                            read_bit_buffer.get(), insufficient_data);
1965 
1966   EXPECT_THAT(obu_processor, IsNull());
1967   // We've received a valid bitstream so far but not complete.
1968   EXPECT_TRUE(insufficient_data);
1969 }
1970 
TEST(GetOutputSampleRate,ReturnsSampleRateBasedOnCodecConfigObu)1971 TEST(GetOutputSampleRate, ReturnsSampleRateBasedOnCodecConfigObu) {
1972   const IASequenceHeaderObu kIaSequenceHeader(
1973       ObuHeader(), IASequenceHeaderObu::kIaCode,
1974       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1975   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1976   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
1977                                         codec_config_obus);
1978   const auto buffer = SerializeObusExpectOk(
1979       {&kIaSequenceHeader, &codec_config_obus.at(kFirstCodecConfigId)});
1980   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1981       kBufferCapacity, absl::MakeConstSpan(buffer));
1982   bool insufficient_data;
1983   auto obu_processor =
1984       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
1985                            read_bit_buffer.get(), insufficient_data);
1986   ASSERT_THAT(obu_processor, NotNull());
1987 
1988   EXPECT_THAT(obu_processor->GetOutputSampleRate(), IsOkAndHolds(kSampleRate));
1989 }
1990 
TEST(GetOutputSampleRate,FailsForTrivialIaSequence)1991 TEST(GetOutputSampleRate, FailsForTrivialIaSequence) {
1992   const IASequenceHeaderObu kIaSequenceHeader(
1993       ObuHeader(), IASequenceHeaderObu::kIaCode,
1994       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1995   const auto buffer = SerializeObusExpectOk({&kIaSequenceHeader});
1996   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
1997       kBufferCapacity, absl::MakeConstSpan(buffer));
1998   bool insufficient_data;
1999   auto obu_processor =
2000       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
2001                            read_bit_buffer.get(), insufficient_data);
2002   ASSERT_THAT(obu_processor, NotNull());
2003 
2004   EXPECT_THAT(obu_processor->GetOutputSampleRate(), Not(IsOk()));
2005 }
2006 
TEST(GetOutputSampleRate,FailsForMultipleCodecConfigObus)2007 TEST(GetOutputSampleRate, FailsForMultipleCodecConfigObus) {
2008   const IASequenceHeaderObu kIaSequenceHeader(
2009       ObuHeader(), IASequenceHeaderObu::kIaCode,
2010       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
2011   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2012   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2013                                         codec_config_obus);
2014   AddLpcmCodecConfigWithIdAndSampleRate(kSecondCodecConfigId, kSampleRate,
2015                                         codec_config_obus);
2016   const auto buffer = SerializeObusExpectOk(
2017       {&kIaSequenceHeader, &codec_config_obus.at(kFirstCodecConfigId),
2018        &codec_config_obus.at(kSecondCodecConfigId)});
2019   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2020       kBufferCapacity, absl::MakeConstSpan(buffer));
2021   bool insufficient_data;
2022   auto obu_processor =
2023       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
2024                            read_bit_buffer.get(), insufficient_data);
2025   ASSERT_THAT(obu_processor, NotNull());
2026 
2027   EXPECT_THAT(obu_processor->GetOutputSampleRate(), Not(IsOk()));
2028 }
2029 
TEST(GetOutputFrameSize,ReturnsSampleRateBasedOnCodecConfigObu)2030 TEST(GetOutputFrameSize, ReturnsSampleRateBasedOnCodecConfigObu) {
2031   const IASequenceHeaderObu kIaSequenceHeader(
2032       ObuHeader(), IASequenceHeaderObu::kIaCode,
2033       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
2034   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2035   AddLpcmCodecConfig(kFirstCodecConfigId, kFrameSize, kBitDepth, kSampleRate,
2036                      codec_config_obus);
2037   const auto buffer = SerializeObusExpectOk(
2038       {&kIaSequenceHeader, &codec_config_obus.at(kFirstCodecConfigId)});
2039   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2040       kBufferCapacity, absl::MakeConstSpan(buffer));
2041   bool insufficient_data;
2042   auto obu_processor =
2043       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
2044                            read_bit_buffer.get(), insufficient_data);
2045   ASSERT_THAT(obu_processor, NotNull());
2046 
2047   EXPECT_THAT(obu_processor->GetOutputSampleRate(), IsOkAndHolds(kSampleRate));
2048 }
2049 
TEST(GetOutputFrameSize,FailsForTrivialIaSequence)2050 TEST(GetOutputFrameSize, FailsForTrivialIaSequence) {
2051   const IASequenceHeaderObu kIaSequenceHeader(
2052       ObuHeader(), IASequenceHeaderObu::kIaCode,
2053       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
2054   const auto buffer = SerializeObusExpectOk({&kIaSequenceHeader});
2055   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2056       kBufferCapacity, absl::MakeConstSpan(buffer));
2057   bool insufficient_data;
2058   auto obu_processor =
2059       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
2060                            read_bit_buffer.get(), insufficient_data);
2061   ASSERT_THAT(obu_processor, NotNull());
2062 
2063   EXPECT_THAT(obu_processor->GetOutputFrameSize(), Not(IsOk()));
2064 }
2065 
TEST(GetOutputFrameSize,FailsForMultipleCodecConfigObus)2066 TEST(GetOutputFrameSize, FailsForMultipleCodecConfigObus) {
2067   const IASequenceHeaderObu kIaSequenceHeader(
2068       ObuHeader(), IASequenceHeaderObu::kIaCode,
2069       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
2070   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2071   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2072                                         codec_config_obus);
2073   AddLpcmCodecConfigWithIdAndSampleRate(kSecondCodecConfigId, kSampleRate,
2074                                         codec_config_obus);
2075   const auto buffer = SerializeObusExpectOk(
2076       {&kIaSequenceHeader, &codec_config_obus.at(kFirstCodecConfigId),
2077        &codec_config_obus.at(kSecondCodecConfigId)});
2078   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2079       kBufferCapacity, absl::MakeConstSpan(buffer));
2080   bool insufficient_data;
2081   auto obu_processor =
2082       ObuProcessor::Create(/*is_exhaustive_and_exact=*/true,
2083                            read_bit_buffer.get(), insufficient_data);
2084   ASSERT_THAT(obu_processor, NotNull());
2085 
2086   EXPECT_THAT(obu_processor->GetOutputFrameSize(), Not(IsOk()));
2087 }
2088 
TEST(NonStatic,ProcessTemporalUnitObu)2089 TEST(NonStatic, ProcessTemporalUnitObu) {
2090   auto bitstream = InitAllDescriptorsForZerothOrderAmbisonics();
2091   AudioFrameObu audio_frame_obu(ObuHeader(), kFirstSubstreamId,
2092                                 kArbitraryAudioFrame);
2093   const auto temporal_unit_obus = SerializeObusExpectOk({&audio_frame_obu});
2094   bitstream.insert(bitstream.end(), temporal_unit_obus.begin(),
2095                    temporal_unit_obus.end());
2096 
2097   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2098       kBufferCapacity, absl::MakeConstSpan(bitstream));
2099   bool insufficient_data;
2100 
2101   auto obu_processor =
2102       ObuProcessor::Create(/*is_exhaustive_and_exact=*/false,
2103                            read_bit_buffer.get(), insufficient_data);
2104   ASSERT_THAT(obu_processor, NotNull());
2105   ASSERT_FALSE(insufficient_data);
2106 
2107   std::optional<AudioFrameWithData> audio_frame_with_data;
2108   std::optional<ParameterBlockWithData> parameter_block_with_data;
2109   std::optional<TemporalDelimiterObu> temporal_delimiter;
2110   bool continue_processing = true;
2111   EXPECT_THAT(obu_processor->ProcessTemporalUnitObu(
2112                   audio_frame_with_data, parameter_block_with_data,
2113                   temporal_delimiter, continue_processing),
2114               IsOk());
2115 
2116   EXPECT_TRUE(audio_frame_with_data.has_value());
2117   EXPECT_FALSE(parameter_block_with_data.has_value());
2118   EXPECT_FALSE(temporal_delimiter.has_value());
2119   EXPECT_TRUE(continue_processing);
2120 }
2121 
2122 // TODO(b/381068413): Add more tests for the new iterative API.
RenderUsingObuProcessorExpectOk(absl::string_view output_filename,bool write_wav_header,const std::optional<uint8_t> output_file_bit_depth_override,const std::list<AudioFrameWithData> & audio_frames,const std::list<ParameterBlockWithData> & parameter_blocks,const std::vector<uint8_t> & bitstream_of_descriptors)2123 void RenderUsingObuProcessorExpectOk(
2124     absl::string_view output_filename, bool write_wav_header,
2125     const std::optional<uint8_t> output_file_bit_depth_override,
2126     const std::list<AudioFrameWithData>& audio_frames,
2127     const std::list<ParameterBlockWithData>& parameter_blocks,
2128     const std::vector<uint8_t>& bitstream_of_descriptors) {
2129   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2130       kBufferCapacity, absl::MakeConstSpan(bitstream_of_descriptors));
2131   bool insufficient_data;
2132 
2133   const std::string output_filename_string(output_filename);
2134   Layout unused_output_layout;
2135   auto obu_processor = ObuProcessor::CreateForRendering(
2136       kStereoLayout,
2137       CreateAllWavWriters(output_filename_string, write_wav_header),
2138       /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2139       unused_output_layout, insufficient_data);
2140   ASSERT_THAT(obu_processor, NotNull());
2141   ASSERT_FALSE(insufficient_data);
2142   absl::Span<const std::vector<int32_t>> output_rendered_pcm_samples;
2143   EXPECT_THAT(obu_processor->RenderTemporalUnitAndMeasureLoudness(
2144                   /*timestamp=*/0, audio_frames, parameter_blocks,
2145                   output_rendered_pcm_samples),
2146               IsOk());
2147   EXPECT_TRUE(output_rendered_pcm_samples.empty());
2148 }
2149 
RenderOneSampleFoaToStereoWavExpectOk(absl::string_view output_filename,bool write_wav_header,std::optional<uint8_t> output_file_bit_depth_override)2150 void RenderOneSampleFoaToStereoWavExpectOk(
2151     absl::string_view output_filename, bool write_wav_header,
2152     std::optional<uint8_t> output_file_bit_depth_override) {
2153   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2154   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2155                                         codec_config_obus);
2156   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2157       audio_elements_with_data;
2158   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2159       kFirstAudioElementId, kFirstCodecConfigId, {kFirstSubstreamId},
2160       codec_config_obus, audio_elements_with_data);
2161   std::list<MixPresentationObu> mix_presentation_obus;
2162   AddMixPresentationObuWithAudioElementIds(
2163       kFirstMixPresentationId, {kFirstAudioElementId},
2164       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2165   std::list<AudioFrameWithData> audio_frames_with_data;
2166   const auto* common_audio_element_with_data =
2167       &audio_elements_with_data.at(kFirstAudioElementId);
2168   audio_frames_with_data.push_back(AudioFrameWithData{
2169       .obu =
2170           AudioFrameObu(ObuHeader(), kFirstSubstreamId, /*audio_frame=*/{0, 0}),
2171       .start_timestamp = 0,
2172       .end_timestamp = 1,
2173       .audio_element_with_data = common_audio_element_with_data,
2174   });
2175   // Create a single parameter block consistent with the mix presentation OBU.
2176   std::list<ParameterBlockWithData> parameter_blocks_with_data = {};
2177   auto parameter_block = std::make_unique<ParameterBlockObu>(
2178       ObuHeader(), kCommonMixGainParameterId,
2179       mix_presentation_obus.front().sub_mixes_[0].output_mix_gain);
2180   EXPECT_THAT(parameter_block->InitializeSubblocks(1, 1, 1), IsOk());
2181   parameter_block->subblocks_[0].param_data =
2182       std::make_unique<MixGainParameterData>(
2183           MixGainParameterData::kAnimateStep,
2184           AnimationStepInt16{.start_point_value = 99});
2185   parameter_blocks_with_data.push_back(ParameterBlockWithData{
2186       .obu = std::move(parameter_block),
2187       .start_timestamp = 0,
2188       .end_timestamp = 1,
2189   });
2190 
2191   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2192       {&codec_config_obus.at(kFirstCodecConfigId),
2193        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2194        &mix_presentation_obus.front()});
2195   RenderUsingObuProcessorExpectOk(
2196       output_filename, write_wav_header, output_file_bit_depth_override,
2197       audio_frames_with_data, parameter_blocks_with_data, bitstream);
2198 }
TEST(RenderAudioFramesWithDataAndMeasureLoudness,RenderingNothingReturnsOk)2199 TEST(RenderAudioFramesWithDataAndMeasureLoudness, RenderingNothingReturnsOk) {
2200   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2201   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2202                                         codec_config_obus);
2203   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2204       audio_elements_with_data;
2205   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2206       kFirstAudioElementId, kFirstCodecConfigId,
2207       {kFirstSubstreamId, kSecondSubstreamId, kThirdSubstreamId,
2208        kFourthSubstreamId},
2209       codec_config_obus, audio_elements_with_data);
2210   std::list<MixPresentationObu> mix_presentation_obus;
2211   AddMixPresentationObuWithAudioElementIds(
2212       kFirstMixPresentationId, {kFirstAudioElementId},
2213       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2214 
2215   const std::list<AudioFrameWithData> empty_audio_frames_with_data = {};
2216   const std::list<ParameterBlockWithData> empty_parameter_blocks_with_data = {};
2217   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2218       {&codec_config_obus.at(kFirstCodecConfigId),
2219        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2220        &mix_presentation_obus.front()});
2221   RenderUsingObuProcessorExpectOk("unused_filename", kDontWriteWavHeader,
2222                                   kNoOutputFileBitDepthOverride,
2223                                   empty_audio_frames_with_data,
2224                                   empty_parameter_blocks_with_data, bitstream);
2225 }
2226 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,RendersFoaToStereoWav)2227 TEST(RenderAudioFramesWithDataAndMeasureLoudness, RendersFoaToStereoWav) {
2228   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2229   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2230   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2231                                         codec_config_obus);
2232   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2233       audio_elements_with_data;
2234   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2235       kFirstAudioElementId, kFirstCodecConfigId,
2236       {kFirstSubstreamId, kSecondSubstreamId, kThirdSubstreamId,
2237        kFourthSubstreamId},
2238       codec_config_obus, audio_elements_with_data);
2239   std::list<MixPresentationObu> mix_presentation_obus;
2240   AddMixPresentationObuWithAudioElementIds(
2241       kFirstMixPresentationId, {kFirstAudioElementId},
2242       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2243   std::list<AudioFrameWithData> audio_frames_with_data;
2244   const std::list<ParameterBlockWithData> parameter_blocks_with_data = {};
2245   const auto* common_audio_element_with_data =
2246       &audio_elements_with_data.at(kFirstAudioElementId);
2247   audio_frames_with_data.push_back(AudioFrameWithData{
2248       .obu =
2249           AudioFrameObu(ObuHeader(), kFirstSubstreamId, /*audio_frame=*/{0, 0}),
2250       .start_timestamp = 0,
2251       .end_timestamp = 1,
2252       .audio_element_with_data = common_audio_element_with_data,
2253   });
2254   audio_frames_with_data.push_back(AudioFrameWithData{
2255       .obu = AudioFrameObu(ObuHeader(), kSecondSubstreamId,
2256                            /*audio_frame=*/{0, 0}),
2257       .start_timestamp = 0,
2258       .end_timestamp = 1,
2259       .audio_element_with_data = common_audio_element_with_data,
2260   });
2261   audio_frames_with_data.push_back(AudioFrameWithData{
2262       .obu =
2263           AudioFrameObu(ObuHeader(), kThirdSubstreamId, /*audio_frame=*/{0, 0}),
2264       .start_timestamp = 0,
2265       .end_timestamp = 1,
2266       .audio_element_with_data = common_audio_element_with_data,
2267   });
2268   audio_frames_with_data.push_back(AudioFrameWithData{
2269       .obu = AudioFrameObu(ObuHeader(), kFourthSubstreamId,
2270                            /*audio_frame=*/{0, 0}),
2271       .start_timestamp = 0,
2272       .end_timestamp = 1,
2273       .audio_element_with_data = common_audio_element_with_data,
2274   });
2275 
2276   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2277       {&codec_config_obus.at(kFirstCodecConfigId),
2278        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2279        &mix_presentation_obus.front()});
2280   RenderUsingObuProcessorExpectOk(
2281       output_filename, kWriteWavHeader, kNoOutputFileBitDepthOverride,
2282       audio_frames_with_data, parameter_blocks_with_data, bitstream);
2283 
2284   const auto wav_reader = CreateWavReaderExpectOk(output_filename);
2285   EXPECT_EQ(wav_reader.num_channels(), 2);
2286 }
2287 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,SupportsMixGainParameterBlocks)2288 TEST(RenderAudioFramesWithDataAndMeasureLoudness,
2289      SupportsMixGainParameterBlocks) {
2290   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2291 
2292   RenderOneSampleFoaToStereoWavExpectOk(output_filename, kWriteWavHeader,
2293                                         kNoOutputFileBitDepthOverride);
2294 
2295   const auto wav_reader = CreateWavReaderExpectOk(output_filename);
2296   EXPECT_EQ(wav_reader.num_channels(), 2);
2297 }
2298 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,CanWritePcmOrWav)2299 TEST(RenderAudioFramesWithDataAndMeasureLoudness, CanWritePcmOrWav) {
2300   const auto output_wav_filename = GetAndCleanupOutputFileName(".wav");
2301   RenderOneSampleFoaToStereoWavExpectOk(output_wav_filename, kWriteWavHeader,
2302                                         kNoOutputFileBitDepthOverride);
2303 
2304   const auto wav_reader = CreateWavReaderExpectOk(output_wav_filename);
2305   EXPECT_EQ(wav_reader.remaining_samples(), 2);
2306 
2307   const auto output_pcm_filename = GetAndCleanupOutputFileName(".pcm");
2308   RenderOneSampleFoaToStereoWavExpectOk(
2309       output_pcm_filename, kDontWriteWavHeader, kNoOutputFileBitDepthOverride);
2310 
2311   EXPECT_TRUE(std::filesystem::exists(output_pcm_filename));
2312   // PCM file size excludes the header. We expect each sample to be 2 bytes.
2313   std::error_code error_code;
2314   EXPECT_EQ(std::filesystem::file_size(output_pcm_filename, error_code), 4);
2315   EXPECT_FALSE(error_code);
2316 }
2317 
AddOneLayerStereoAudioElement(DecodedUleb128 codec_config_id,DecodedUleb128 audio_element_id,uint32_t substream_id,const absl::flat_hash_map<DecodedUleb128,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<DecodedUleb128,AudioElementWithData> & audio_elements)2318 void AddOneLayerStereoAudioElement(
2319     DecodedUleb128 codec_config_id, DecodedUleb128 audio_element_id,
2320     uint32_t substream_id,
2321     const absl::flat_hash_map<DecodedUleb128, CodecConfigObu>&
2322         codec_config_obus,
2323     absl::flat_hash_map<DecodedUleb128, AudioElementWithData>& audio_elements) {
2324   AddScalableAudioElementWithSubstreamIds(
2325       IamfInputLayout::kStereo, audio_element_id, codec_config_id,
2326       {substream_id}, codec_config_obus, audio_elements);
2327 }
2328 
TEST(RenderTemporalUnitAndMeasureLoudness,RendersPassthroughStereoToPcm)2329 TEST(RenderTemporalUnitAndMeasureLoudness, RendersPassthroughStereoToPcm) {
2330   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2331   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2332                                         codec_config_obus);
2333   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2334       audio_elements_with_data;
2335   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kFirstAudioElementId,
2336                                 kFirstSubstreamId, codec_config_obus,
2337                                 audio_elements_with_data);
2338   std::list<MixPresentationObu> mix_presentation_obus;
2339   AddMixPresentationObuWithAudioElementIds(
2340       kFirstMixPresentationId, {kFirstAudioElementId},
2341       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2342   std::list<AudioFrameWithData> audio_frames_with_data;
2343   const std::list<ParameterBlockWithData> kNoParameterBlocks = {};
2344 
2345   audio_frames_with_data.push_back(AudioFrameWithData{
2346       .obu = AudioFrameObu(ObuHeader(), kFirstSubstreamId,
2347                            /*audio_frame=*/
2348                            {// First left sample.
2349                             0x11, 0x33,
2350                             // First right sample.
2351                             0x22, 0x44,
2352                             // Second left sample.
2353                             0x55, 0x77,
2354                             // Second right sample.
2355                             0x66, 0x08,
2356                             // Third left sample.
2357                             0x99, 0x0a,
2358                             // Third right sample.
2359                             0xbb, 0x0d}),
2360       .start_timestamp = 0,
2361       .end_timestamp = 1,
2362       .audio_element_with_data =
2363           &audio_elements_with_data.at(kFirstAudioElementId),
2364   });
2365 
2366   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2367       {&codec_config_obus.at(kFirstCodecConfigId),
2368        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2369        &mix_presentation_obus.front()});
2370   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2371       kBufferCapacity, absl::MakeConstSpan(bitstream));
2372 
2373   Layout unused_output_layout;
2374   bool insufficient_data;
2375   auto obu_processor = ObuProcessor::CreateForRendering(
2376       kStereoLayout,
2377       RenderingMixPresentationFinalizer::ProduceNoSampleProcessors,
2378       /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2379       unused_output_layout, insufficient_data);
2380   ASSERT_THAT(obu_processor, NotNull());
2381   ASSERT_FALSE(insufficient_data);
2382   absl::Span<const std::vector<int32_t>> output_rendered_pcm_samples;
2383   EXPECT_THAT(obu_processor->RenderTemporalUnitAndMeasureLoudness(
2384                   /*timestamp=*/0, audio_frames_with_data, kNoParameterBlocks,
2385                   output_rendered_pcm_samples),
2386               IsOk());
2387 
2388   // Outer vector is for each tick, inner vector is for each channel.
2389   std::vector<std::vector<int32_t>> expected_pcm_samples = {
2390       {0x33110000, 0x44220000},
2391       {0x77550000, 0x08660000},
2392       {0x0a990000, 0x0dbb0000},
2393   };
2394   EXPECT_EQ(output_rendered_pcm_samples, expected_pcm_samples);
2395 }
2396 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,RendersPassthroughStereoToWav)2397 TEST(RenderAudioFramesWithDataAndMeasureLoudness,
2398      RendersPassthroughStereoToWav) {
2399   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2400   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2401   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2402                                         codec_config_obus);
2403   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2404       audio_elements_with_data;
2405   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kFirstAudioElementId,
2406                                 kFirstSubstreamId, codec_config_obus,
2407                                 audio_elements_with_data);
2408   std::list<MixPresentationObu> mix_presentation_obus;
2409   AddMixPresentationObuWithAudioElementIds(
2410       kFirstMixPresentationId, {kFirstAudioElementId},
2411       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2412   std::list<AudioFrameWithData> audio_frames_with_data;
2413   const std::list<ParameterBlockWithData> kNoParameterBlocks = {};
2414 
2415   audio_frames_with_data.push_back(AudioFrameWithData{
2416       .obu = AudioFrameObu(ObuHeader(), kFirstSubstreamId,
2417                            /*audio_frame=*/
2418                            {// First left sample.
2419                             0x11, 0x33,
2420                             // First right sample.
2421                             0x22, 0x44,
2422                             // Second left sample.
2423                             0x55, 0x77,
2424                             // Second right sample.
2425                             0x66, 0x08,
2426                             // Third left sample.
2427                             0x99, 0x0a,
2428                             // Third right sample.
2429                             0xbb, 0x0d}),
2430       .start_timestamp = 0,
2431       .end_timestamp = 1,
2432       .audio_element_with_data =
2433           &audio_elements_with_data.at(kFirstAudioElementId),
2434   });
2435 
2436   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2437       {&codec_config_obus.at(kFirstCodecConfigId),
2438        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2439        &mix_presentation_obus.front()});
2440 
2441   RenderUsingObuProcessorExpectOk(
2442       output_filename, kWriteWavHeader, kNoOutputFileBitDepthOverride,
2443       audio_frames_with_data, kNoParameterBlocks, bitstream);
2444 
2445   auto wav_reader = CreateWavReaderExpectOk(output_filename, 4);
2446   EXPECT_EQ(wav_reader.num_channels(), 2);
2447   EXPECT_EQ(wav_reader.ReadFrame(), 6);
2448   // Validate left channel.
2449   EXPECT_EQ(wav_reader.buffers_[0][0], int32_t{0x33110000});
2450   EXPECT_EQ(wav_reader.buffers_[1][0], int32_t{0x77550000});
2451   EXPECT_EQ(wav_reader.buffers_[2][0], int32_t{0x0a990000});
2452   // Validate right channel.
2453   EXPECT_EQ(wav_reader.buffers_[0][1], int32_t{0x44220000});
2454   EXPECT_EQ(wav_reader.buffers_[1][1], int32_t{0x08660000});
2455   EXPECT_EQ(wav_reader.buffers_[2][1], int32_t{0x0dbb0000});
2456 }
2457 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,RendersPassthroughStereoToWav_2)2458 TEST(RenderAudioFramesWithDataAndMeasureLoudness,
2459      RendersPassthroughStereoToWav_2) {
2460   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2461   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2462   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2463                                         codec_config_obus);
2464   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2465       audio_elements_with_data;
2466   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kFirstAudioElementId,
2467                                 kFirstSubstreamId, codec_config_obus,
2468                                 audio_elements_with_data);
2469   std::list<MixPresentationObu> mix_presentation_obus;
2470   AddMixPresentationObuWithAudioElementIds(
2471       kFirstMixPresentationId, {kFirstAudioElementId},
2472       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2473   const std::list<ParameterBlockWithData> kNoParameterBlocks = {};
2474 
2475   // Render using `ObuProcessor`, which closes the output WAV file upon
2476   // going out of scope.
2477   {
2478     const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2479         {&codec_config_obus.at(kFirstCodecConfigId),
2480          &audio_elements_with_data.at(kFirstAudioElementId).obu,
2481          &mix_presentation_obus.front()});
2482     auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2483         kBufferCapacity, absl::MakeConstSpan(bitstream));
2484 
2485     Layout unused_output_layout;
2486     bool insufficient_data;
2487     const std::string output_filename_string(output_filename);
2488     auto obu_processor = ObuProcessor::CreateForRendering(
2489         kStereoLayout,
2490         CreateAllWavWriters(output_filename_string, kWriteWavHeader),
2491         /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2492         unused_output_layout, insufficient_data);
2493     ASSERT_THAT(obu_processor, NotNull());
2494     ASSERT_FALSE(insufficient_data);
2495 
2496     for (int i = 0; i < 100; ++i) {
2497       std::list<AudioFrameWithData> audio_frames_with_data;
2498       audio_frames_with_data.push_back(AudioFrameWithData{
2499           .obu = AudioFrameObu(ObuHeader(), kFirstSubstreamId,
2500                                /*audio_frame=*/
2501                                std::vector<uint8_t>(8, i)),
2502           .start_timestamp = i,
2503           .end_timestamp = i + 1,
2504           .audio_element_with_data =
2505               &audio_elements_with_data.at(kFirstAudioElementId),
2506       });
2507       absl::Span<const std::vector<int32_t>> unused_output_rendered_pcm_samples;
2508       EXPECT_THAT(obu_processor->RenderTemporalUnitAndMeasureLoudness(
2509                       /*timestamp=*/i, audio_frames_with_data,
2510                       kNoParameterBlocks, unused_output_rendered_pcm_samples),
2511                   IsOk());
2512     }
2513   }
2514 
2515   auto wav_reader = CreateWavReaderExpectOk(output_filename, 2);
2516   EXPECT_EQ(wav_reader.num_channels(), 2);
2517 
2518   for (int i = 0; i < 100; ++i) {
2519     EXPECT_EQ(wav_reader.ReadFrame(), 4);
2520     const int32_t expected_sample = (i << 16) | (i << 24);
2521     EXPECT_THAT(wav_reader.buffers_[0],
2522                 std::vector<int32_t>(2, expected_sample));
2523     EXPECT_THAT(wav_reader.buffers_[1],
2524                 std::vector<int32_t>(2, expected_sample));
2525   }
2526 }
2527 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,SelectsFirstMixPresentationWhenSupported)2528 TEST(RenderAudioFramesWithDataAndMeasureLoudness,
2529      SelectsFirstMixPresentationWhenSupported) {
2530   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2531   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2532   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2533                                         codec_config_obus);
2534   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2535       audio_elements_with_data;
2536   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kFirstAudioElementId,
2537                                 kFirstSubstreamId, codec_config_obus,
2538                                 audio_elements_with_data);
2539   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kSecondAudioElementId,
2540                                 kSecondSubstreamId, codec_config_obus,
2541                                 audio_elements_with_data);
2542   std::list<AudioFrameWithData> audio_frames_with_data;
2543   const std::list<ParameterBlockWithData> kNoParameterBlocks;
2544   audio_frames_with_data.push_back(AudioFrameWithData{
2545       .obu = AudioFrameObu(ObuHeader(), kFirstSubstreamId,
2546                            /*audio_frame=*/{1, 0, 0, 0}),
2547       .start_timestamp = 0,
2548       .end_timestamp = 1,
2549       .audio_element_with_data =
2550           &audio_elements_with_data.at(kFirstAudioElementId),
2551   });
2552   audio_frames_with_data.push_back(AudioFrameWithData{
2553       .obu = AudioFrameObu(ObuHeader(), kSecondSubstreamId,
2554                            /*audio_frame=*/{7, 0, 0, 0}),
2555       .start_timestamp = 0,
2556       .end_timestamp = 1,
2557       .audio_element_with_data =
2558           &audio_elements_with_data.at(kSecondAudioElementId),
2559   });
2560 
2561   std::list<MixPresentationObu> mix_presentation_obus;
2562   constexpr int32_t kExpectedFirstSampleForFirstMixPresentation = 1 << 16;
2563   AddMixPresentationObuWithAudioElementIds(
2564       kFirstMixPresentationId, {kFirstAudioElementId},
2565       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2566   AddMixPresentationObuWithAudioElementIds(
2567       kSecondMixPresentationId, {kSecondAudioElementId},
2568       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2569 
2570   auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2571       {&codec_config_obus.at(kFirstCodecConfigId),
2572        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2573        &audio_elements_with_data.at(kSecondAudioElementId).obu,
2574        &mix_presentation_obus.front(), &mix_presentation_obus.back()});
2575   RenderUsingObuProcessorExpectOk(
2576       output_filename, kWriteWavHeader, kNoOutputFileBitDepthOverride,
2577       audio_frames_with_data, kNoParameterBlocks, bitstream);
2578 
2579   auto wav_reader = CreateWavReaderExpectOk(output_filename);
2580   EXPECT_EQ(wav_reader.ReadFrame(), 2);
2581   EXPECT_EQ(wav_reader.buffers_[0][0],
2582             kExpectedFirstSampleForFirstMixPresentation);
2583 }
2584 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,DoesNotSupportBaseEnhancedProfile)2585 TEST(RenderAudioFramesWithDataAndMeasureLoudness,
2586      DoesNotSupportBaseEnhancedProfile) {
2587   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2588   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2589   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2590                                         codec_config_obus);
2591   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2592       audio_elements_with_data;
2593   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kFirstAudioElementId,
2594                                 kFirstSubstreamId, codec_config_obus,
2595                                 audio_elements_with_data);
2596   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kSecondAudioElementId,
2597                                 kSecondSubstreamId, codec_config_obus,
2598                                 audio_elements_with_data);
2599   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kThirdAudioElementId,
2600                                 kThirdSubstreamId, codec_config_obus,
2601                                 audio_elements_with_data);
2602   std::list<AudioFrameWithData> audio_frames_with_data;
2603   const std::list<ParameterBlockWithData> kNoParameterBlocks;
2604   audio_frames_with_data.push_back(AudioFrameWithData{
2605       .obu = AudioFrameObu(ObuHeader(), kFirstSubstreamId,
2606                            /*audio_frame=*/{0, 0, 0, 0}),
2607       .start_timestamp = 0,
2608       .end_timestamp = 1,
2609       .audio_element_with_data =
2610           &audio_elements_with_data.at(kFirstAudioElementId),
2611   });
2612   audio_frames_with_data.push_back(AudioFrameWithData{
2613       .obu = AudioFrameObu(ObuHeader(), kSecondSubstreamId,
2614                            /*audio_frame=*/{0, 0, 0, 0}),
2615       .start_timestamp = 0,
2616       .end_timestamp = 1,
2617       .audio_element_with_data =
2618           &audio_elements_with_data.at(kSecondAudioElementId),
2619   });
2620   audio_frames_with_data.push_back(AudioFrameWithData{
2621       .obu = AudioFrameObu(ObuHeader(), kThirdSubstreamId,
2622                            /*audio_frame=*/{0, 0, 0, 0}),
2623       .start_timestamp = 0,
2624       .end_timestamp = 1,
2625       .audio_element_with_data =
2626           &audio_elements_with_data.at(kThirdAudioElementId),
2627   });
2628 
2629   // The only mix presentation is not suitable for simple or base profile.
2630   std::list<MixPresentationObu> mix_presentation_obus;
2631   AddMixPresentationObuWithAudioElementIds(
2632       kFirstMixPresentationId,
2633       {kFirstAudioElementId, kSecondAudioElementId, kThirdAudioElementId},
2634       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2635 
2636   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2637       {&codec_config_obus.at(kFirstCodecConfigId),
2638        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2639        &audio_elements_with_data.at(kSecondAudioElementId).obu,
2640        &audio_elements_with_data.at(kThirdAudioElementId).obu,
2641        &mix_presentation_obus.front()});
2642 
2643   // Expect that the `ObuProcessor` rejects the rendering request.
2644   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2645       kBufferCapacity, absl::MakeConstSpan(bitstream));
2646   Layout unused_output_layout;
2647   bool insufficient_data;
2648   auto obu_processor = ObuProcessor::CreateForRendering(
2649       kStereoLayout,
2650       RenderingMixPresentationFinalizer::ProduceNoSampleProcessors,
2651       /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2652       unused_output_layout, insufficient_data);
2653   EXPECT_FALSE(insufficient_data);
2654   EXPECT_THAT(obu_processor, IsNull());
2655 }
2656 
TEST(RenderAudioFramesWithDataAndMeasureLoudness,SelectsFirstSupportedMixPresentation)2657 TEST(RenderAudioFramesWithDataAndMeasureLoudness,
2658      SelectsFirstSupportedMixPresentation) {
2659   const auto output_filename = GetAndCleanupOutputFileName(".wav");
2660   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2661   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2662                                         codec_config_obus);
2663   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2664       audio_elements_with_data;
2665   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kFirstAudioElementId,
2666                                 kFirstSubstreamId, codec_config_obus,
2667                                 audio_elements_with_data);
2668   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kSecondAudioElementId,
2669                                 kSecondSubstreamId, codec_config_obus,
2670                                 audio_elements_with_data);
2671   AddOneLayerStereoAudioElement(kFirstCodecConfigId, kThirdAudioElementId,
2672                                 kThirdSubstreamId, codec_config_obus,
2673                                 audio_elements_with_data);
2674   std::list<AudioFrameWithData> audio_frames_with_data;
2675   const std::list<ParameterBlockWithData> kNoParameterBlocks;
2676   audio_frames_with_data.push_back(AudioFrameWithData{
2677       .obu = AudioFrameObu(ObuHeader(), kFirstSubstreamId,
2678                            /*audio_frame=*/{10, 0, 0, 0}),
2679       .start_timestamp = 0,
2680       .end_timestamp = 1,
2681       .audio_element_with_data =
2682           &audio_elements_with_data.at(kFirstAudioElementId),
2683   });
2684   audio_frames_with_data.push_back(AudioFrameWithData{
2685       .obu = AudioFrameObu(ObuHeader(), kSecondSubstreamId,
2686                            /*audio_frame=*/{20, 0, 0, 0}),
2687       .start_timestamp = 0,
2688       .end_timestamp = 1,
2689       .audio_element_with_data =
2690           &audio_elements_with_data.at(kSecondAudioElementId),
2691   });
2692   audio_frames_with_data.push_back(AudioFrameWithData{
2693       .obu = AudioFrameObu(ObuHeader(), kThirdSubstreamId,
2694                            /*audio_frame=*/{40, 0, 0, 0}),
2695       .start_timestamp = 0,
2696       .end_timestamp = 1,
2697       .audio_element_with_data =
2698           &audio_elements_with_data.at(kThirdAudioElementId),
2699   });
2700   // The first mix presentation is not suitable for simple or base profile.
2701   std::list<MixPresentationObu> mix_presentation_obus;
2702   AddMixPresentationObuWithAudioElementIds(
2703       kFirstMixPresentationId,
2704       {kFirstAudioElementId, kSecondAudioElementId, kThirdAudioElementId},
2705       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2706   // The second is suitable.
2707   constexpr int32_t kExpectedFirstSampleForFirstSupportedMixPresentation =
2708       30 << 16;
2709   AddMixPresentationObuWithAudioElementIds(
2710       kSecondMixPresentationId, {kFirstAudioElementId, kSecondAudioElementId},
2711       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2712   // The third is also suitable, but the will not be selected.
2713   AddMixPresentationObuWithAudioElementIds(
2714       kThirdMixPresentationId, {kFirstAudioElementId, kThirdAudioElementId},
2715       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2716 
2717   auto mix_presentation_obus_iter = mix_presentation_obus.begin();
2718   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2719       {&codec_config_obus.at(kFirstCodecConfigId),
2720        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2721        &audio_elements_with_data.at(kSecondAudioElementId).obu,
2722        &audio_elements_with_data.at(kThirdAudioElementId).obu,
2723        &(*mix_presentation_obus_iter++), &(*mix_presentation_obus_iter++),
2724        &(*mix_presentation_obus_iter++)});
2725   RenderUsingObuProcessorExpectOk(
2726       output_filename, kWriteWavHeader, kNoOutputFileBitDepthOverride,
2727       audio_frames_with_data, kNoParameterBlocks, bitstream);
2728 
2729   auto wav_reader = CreateWavReaderExpectOk(output_filename);
2730   EXPECT_EQ(wav_reader.ReadFrame(), 2);
2731   EXPECT_EQ(wav_reader.buffers_[0][0],
2732             kExpectedFirstSampleForFirstSupportedMixPresentation);
2733 }
2734 
TEST(CreateForRendering,ForwardsArgumentsToSampleProcessorFactory)2735 TEST(CreateForRendering, ForwardsArgumentsToSampleProcessorFactory) {
2736   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2737   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2738                                         codec_config_obus);
2739   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2740       audio_elements_with_data;
2741   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2742       kFirstAudioElementId, kFirstCodecConfigId,
2743       {kFirstSubstreamId, kSecondSubstreamId, kThirdSubstreamId,
2744        kFourthSubstreamId},
2745       codec_config_obus, audio_elements_with_data);
2746   std::list<MixPresentationObu> mix_presentation_obus;
2747   AddMixPresentationObuWithAudioElementIds(
2748       kFirstMixPresentationId, {kFirstAudioElementId},
2749       kCommonMixGainParameterId, kCommonParameterRate, mix_presentation_obus);
2750 
2751   const std::list<AudioFrameWithData> empty_audio_frames_with_data = {};
2752   const std::list<ParameterBlockWithData> empty_parameter_blocks_with_data = {};
2753 
2754   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2755       {&codec_config_obus.at(kFirstCodecConfigId),
2756        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2757        &mix_presentation_obus.front()});
2758   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2759       kBufferCapacity, absl::MakeConstSpan(bitstream));
2760   bool insufficient_data;
2761 
2762   // We expect arguments to be forwarded from the OBUs to the sample processor
2763   // factory.
2764   constexpr int kFirstSubmixIndex = 0;
2765   constexpr int kFirstLayoutIndex = 0;
2766   const auto& forwarded_layout =
2767       mix_presentation_obus.front().sub_mixes_[0].layouts[0].loudness_layout;
2768   const int32_t forwarded_sample_rate = static_cast<int32_t>(
2769       codec_config_obus.at(kFirstCodecConfigId).GetOutputSampleRate());
2770   const int32_t forwarded_bit_depth = static_cast<int32_t>(
2771       codec_config_obus.at(kFirstCodecConfigId).GetBitDepthToMeasureLoudness());
2772   const uint32_t forwarded_num_samples_per_frame =
2773       codec_config_obus.at(kFirstCodecConfigId).GetNumSamplesPerFrame();
2774 
2775   MockSampleProcessorFactory mock_sample_processor_factory;
2776   EXPECT_CALL(
2777       mock_sample_processor_factory,
2778       Call(kFirstMixPresentationId, kFirstSubmixIndex, kFirstLayoutIndex,
2779            forwarded_layout, /*num_channels=*/2, forwarded_sample_rate,
2780            forwarded_bit_depth, forwarded_num_samples_per_frame));
2781   RenderingMixPresentationFinalizer::SampleProcessorFactory
2782       sample_processor_factory = mock_sample_processor_factory.AsStdFunction();
2783 
2784   Layout unused_output_layout;
2785   EXPECT_THAT(ObuProcessor::CreateForRendering(
2786                   kStereoLayout, sample_processor_factory,
2787                   /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2788                   unused_output_layout, insufficient_data),
2789               NotNull());
2790 }
2791 
2792 using testing::_;
2793 
2794 constexpr Layout k5_1_Layout = {
2795     .layout_type = Layout::kLayoutTypeLoudspeakersSsConvention,
2796     .specific_layout = LoudspeakersSsConventionLayout{
2797         .sound_system = LoudspeakersSsConventionLayout::kSoundSystemB_0_5_0}};
2798 
TEST(CreateForRendering,ForwardsChosenLayoutToSampleProcessorFactory)2799 TEST(CreateForRendering, ForwardsChosenLayoutToSampleProcessorFactory) {
2800   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2801   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2802                                         codec_config_obus);
2803   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2804       audio_elements_with_data;
2805   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2806       kFirstAudioElementId, kFirstCodecConfigId,
2807       {kFirstSubstreamId, kSecondSubstreamId, kThirdSubstreamId,
2808        kFourthSubstreamId},
2809       codec_config_obus, audio_elements_with_data);
2810   std::list<MixPresentationObu> mix_presentation_obus;
2811   std::vector<LoudspeakersSsConventionLayout::SoundSystem>
2812       sound_system_layouts = {
2813           LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0,
2814           LoudspeakersSsConventionLayout::kSoundSystemB_0_5_0};
2815   AddMixPresentationObuWithConfigurableLayouts(
2816       kFirstMixPresentationId, {kFirstAudioElementId},
2817       kCommonMixGainParameterId, kCommonParameterRate, sound_system_layouts,
2818       mix_presentation_obus);
2819 
2820   const std::list<AudioFrameWithData> empty_audio_frames_with_data = {};
2821   const std::list<ParameterBlockWithData> empty_parameter_blocks_with_data = {};
2822 
2823   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2824       {&codec_config_obus.at(kFirstCodecConfigId),
2825        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2826        &mix_presentation_obus.front()});
2827   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2828       kBufferCapacity, absl::MakeConstSpan(bitstream));
2829   bool insufficient_data;
2830 
2831   // We expect to use the second layout, since this is the only one that matches
2832   // the desired layout.
2833   constexpr int kSubmixIndex = 0;
2834   constexpr int kLayoutIndex = 1;
2835   const auto& forwarded_layout =
2836       mix_presentation_obus.front().sub_mixes_[0].layouts[1].loudness_layout;
2837 
2838   MockSampleProcessorFactory mock_sample_processor_factory;
2839   EXPECT_CALL(mock_sample_processor_factory,
2840               Call(kFirstMixPresentationId, kSubmixIndex, kLayoutIndex,
2841                    forwarded_layout, /*num_channels=*/6, _, _, _));
2842   RenderingMixPresentationFinalizer::SampleProcessorFactory
2843       sample_processor_factory = mock_sample_processor_factory.AsStdFunction();
2844 
2845   Layout output_layout;
2846   EXPECT_THAT(ObuProcessor::CreateForRendering(
2847                   k5_1_Layout, sample_processor_factory,
2848                   /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2849                   output_layout, insufficient_data),
2850               NotNull());
2851   EXPECT_EQ(output_layout, k5_1_Layout);
2852 }
2853 
TEST(CreateForRendering,ForwardsDefaultLayoutToSampleProcessorFactory)2854 TEST(CreateForRendering, ForwardsDefaultLayoutToSampleProcessorFactory) {
2855   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2856   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2857                                         codec_config_obus);
2858   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2859       audio_elements_with_data;
2860   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2861       kFirstAudioElementId, kFirstCodecConfigId,
2862       {kFirstSubstreamId, kSecondSubstreamId, kThirdSubstreamId,
2863        kFourthSubstreamId},
2864       codec_config_obus, audio_elements_with_data);
2865   std::list<MixPresentationObu> mix_presentation_obus;
2866   std::vector<LoudspeakersSsConventionLayout::SoundSystem>
2867       sound_system_layouts = {
2868           LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0,
2869           LoudspeakersSsConventionLayout::kSoundSystemJ_4_7_0};
2870   AddMixPresentationObuWithConfigurableLayouts(
2871       kFirstMixPresentationId, {kFirstAudioElementId},
2872       kCommonMixGainParameterId, kCommonParameterRate, sound_system_layouts,
2873       mix_presentation_obus);
2874 
2875   const std::list<AudioFrameWithData> empty_audio_frames_with_data = {};
2876   const std::list<ParameterBlockWithData> empty_parameter_blocks_with_data = {};
2877 
2878   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2879       {&codec_config_obus.at(kFirstCodecConfigId),
2880        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2881        &mix_presentation_obus.front()});
2882   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2883       kBufferCapacity, absl::MakeConstSpan(bitstream));
2884   bool insufficient_data;
2885 
2886   // We expect to use the first layout as default, since the desired layout is
2887   // not available in the mix presentation.
2888   constexpr int kSubmixIndex = 0;
2889   constexpr int kLayoutIndex = 0;
2890   const auto& forwarded_layout =
2891       mix_presentation_obus.front().sub_mixes_[0].layouts[0].loudness_layout;
2892 
2893   MockSampleProcessorFactory mock_sample_processor_factory;
2894   EXPECT_CALL(mock_sample_processor_factory,
2895               Call(kFirstMixPresentationId, kSubmixIndex, kLayoutIndex,
2896                    forwarded_layout, /*num_channels=*/2, _, _, _));
2897   RenderingMixPresentationFinalizer::SampleProcessorFactory
2898       sample_processor_factory = mock_sample_processor_factory.AsStdFunction();
2899 
2900   Layout unused_output_layout;
2901   EXPECT_THAT(ObuProcessor::CreateForRendering(
2902                   k5_1_Layout, sample_processor_factory,
2903                   /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2904                   unused_output_layout, insufficient_data),
2905               NotNull());
2906 }
2907 
TEST(CreateForRendering,ForwardsChosenLayoutToSampleProcessorFactoryWithMultipleMixPresentations)2908 TEST(CreateForRendering,
2909      ForwardsChosenLayoutToSampleProcessorFactoryWithMultipleMixPresentations) {
2910   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
2911   AddLpcmCodecConfigWithIdAndSampleRate(kFirstCodecConfigId, kSampleRate,
2912                                         codec_config_obus);
2913   absl::flat_hash_map<DecodedUleb128, AudioElementWithData>
2914       audio_elements_with_data;
2915   AddAmbisonicsMonoAudioElementWithSubstreamIds(
2916       kFirstAudioElementId, kFirstCodecConfigId,
2917       {kFirstSubstreamId, kSecondSubstreamId, kThirdSubstreamId,
2918        kFourthSubstreamId},
2919       codec_config_obus, audio_elements_with_data);
2920   std::list<MixPresentationObu> mix_presentation_obus;
2921   std::vector<LoudspeakersSsConventionLayout::SoundSystem>
2922       sound_system_layouts_first_mix_presentation = {
2923           LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0,
2924           LoudspeakersSsConventionLayout::kSoundSystem10_2_7_0};
2925   AddMixPresentationObuWithConfigurableLayouts(
2926       kFirstMixPresentationId, {kFirstAudioElementId},
2927       kCommonMixGainParameterId, kCommonParameterRate,
2928       sound_system_layouts_first_mix_presentation, mix_presentation_obus);
2929   std::vector<LoudspeakersSsConventionLayout::SoundSystem>
2930       sound_system_layouts_second_mix_presentation = {
2931           LoudspeakersSsConventionLayout::kSoundSystemA_0_2_0,
2932           LoudspeakersSsConventionLayout::kSoundSystemB_0_5_0};
2933   AddMixPresentationObuWithConfigurableLayouts(
2934       kSecondMixPresentationId, {kFirstAudioElementId},
2935       kCommonMixGainParameterId, kCommonParameterRate,
2936       sound_system_layouts_second_mix_presentation, mix_presentation_obus);
2937 
2938   const std::list<AudioFrameWithData> empty_audio_frames_with_data = {};
2939   const std::list<ParameterBlockWithData> empty_parameter_blocks_with_data = {};
2940 
2941   const auto bitstream = AddSequenceHeaderAndSerializeObusExpectOk(
2942       {&codec_config_obus.at(kFirstCodecConfigId),
2943        &audio_elements_with_data.at(kFirstAudioElementId).obu,
2944        &mix_presentation_obus.front(),
2945        &*(std::next(mix_presentation_obus.begin()))});
2946   auto read_bit_buffer = MemoryBasedReadBitBuffer::CreateFromSpan(
2947       kBufferCapacity, absl::MakeConstSpan(bitstream));
2948   bool insufficient_data;
2949 
2950   // We expect to use the second layout in the second mix presentation, since
2951   // this is the only one that matches the desired layout.
2952   constexpr int kSubmixIndex = 0;
2953   constexpr int kLayoutIndex = 1;
2954   const auto& forwarded_layout = (std::next(mix_presentation_obus.begin()))
2955                                      ->sub_mixes_[0]
2956                                      .layouts[1]
2957                                      .loudness_layout;
2958 
2959   MockSampleProcessorFactory mock_sample_processor_factory;
2960   EXPECT_CALL(mock_sample_processor_factory,
2961               Call(kSecondMixPresentationId, kSubmixIndex, kLayoutIndex,
2962                    forwarded_layout, /*num_channels=*/6, _, _, _));
2963   RenderingMixPresentationFinalizer::SampleProcessorFactory
2964       sample_processor_factory = mock_sample_processor_factory.AsStdFunction();
2965 
2966   Layout output_layout;
2967   EXPECT_THAT(ObuProcessor::CreateForRendering(
2968                   k5_1_Layout, sample_processor_factory,
2969                   /*is_exhaustive_and_exact=*/true, read_bit_buffer.get(),
2970                   output_layout, insufficient_data),
2971               NotNull());
2972   EXPECT_EQ(output_layout, k5_1_Layout);
2973 }
2974 
TEST(CreateForRendering,NullReadBitBufferRejected)2975 TEST(CreateForRendering, NullReadBitBufferRejected) {
2976   MockSampleProcessorFactory mock_sample_processor_factory;
2977   auto sample_processor_factory = mock_sample_processor_factory.AsStdFunction();
2978   ReadBitBuffer* read_bit_buffer_nullptr = nullptr;
2979   bool insufficient_data;
2980 
2981   Layout unused_output_layout;
2982   EXPECT_THAT(ObuProcessor::CreateForRendering(
2983                   kStereoLayout, sample_processor_factory,
2984                   /*is_exhaustive_and_exact=*/true, read_bit_buffer_nullptr,
2985                   unused_output_layout, insufficient_data),
2986               IsNull());
2987   EXPECT_FALSE(insufficient_data);
2988 }
2989 
2990 }  // namespace
2991 }  // namespace iamf_tools
2992