• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear
5  * License and the Alliance for Open Media Patent License 1.0. If the BSD
6  * 3-Clause Clear License was not distributed with this source code in the
7  * LICENSE file, you can obtain it at
8  * www.aomedia.org/license/software-license/bsd-3-c-c. If the Alliance for
9  * Open Media Patent License 1.0 was not distributed with this source code
10  * in the PATENTS file, you can obtain it at www.aomedia.org/license/patent.
11  */
12 #include "iamf/cli/obu_sequencer_base.h"
13 
14 #include <cstdint>
15 #include <list>
16 #include <memory>
17 #include <optional>
18 #include <utility>
19 #include <vector>
20 
21 #include "absl/container/flat_hash_map.h"
22 #include "absl/status/status.h"
23 #include "absl/status/status_matchers.h"
24 #include "absl/types/span.h"
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "iamf/cli/audio_element_with_data.h"
28 #include "iamf/cli/audio_frame_with_data.h"
29 #include "iamf/cli/parameter_block_with_data.h"
30 #include "iamf/cli/temporal_unit_view.h"
31 #include "iamf/cli/tests/cli_test_utils.h"
32 #include "iamf/common/leb_generator.h"
33 #include "iamf/common/write_bit_buffer.h"
34 #include "iamf/obu/arbitrary_obu.h"
35 #include "iamf/obu/audio_frame.h"
36 #include "iamf/obu/codec_config.h"
37 #include "iamf/obu/demixing_info_parameter_data.h"
38 #include "iamf/obu/demixing_param_definition.h"
39 #include "iamf/obu/ia_sequence_header.h"
40 #include "iamf/obu/mix_presentation.h"
41 #include "iamf/obu/obu_base.h"
42 #include "iamf/obu/obu_header.h"
43 #include "iamf/obu/parameter_block.h"
44 #include "iamf/obu/temporal_delimiter.h"
45 #include "iamf/obu/types.h"
46 
47 namespace iamf_tools {
48 namespace {
49 
50 using ::absl_testing::IsOk;
51 using ::testing::_;
52 using ::testing::Not;
53 using ::testing::Return;
54 
55 using absl::MakeConstSpan;
56 
57 constexpr DecodedUleb128 kCodecConfigId = 1;
58 constexpr uint32_t kNumSamplesPerFrame = 8;
59 constexpr uint32_t kSampleRate = 48000;
60 // Some timestamps consistent with the number of samples per frame.
61 constexpr InternalTimestamp kFirstTimestamp = kNumSamplesPerFrame * 0;
62 constexpr InternalTimestamp kSecondTimestamp = kNumSamplesPerFrame * 1;
63 constexpr InternalTimestamp kThirdTimestamp = kNumSamplesPerFrame * 2;
64 constexpr DecodedUleb128 kFirstAudioElementId = 1;
65 constexpr DecodedUleb128 kSecondAudioElementId = 2;
66 constexpr DecodedUleb128 kFirstSubstreamId = 1;
67 constexpr DecodedUleb128 kSecondSubstreamId = 2;
68 constexpr DecodedUleb128 kFirstMixPresentationId = 100;
69 constexpr DecodedUleb128 kFirstDemixingParameterId = 998;
70 constexpr DecodedUleb128 kCommonMixGainParameterId = 999;
71 constexpr uint32_t kCommonMixGainParameterRate = kSampleRate;
72 
73 constexpr bool kIncludeTemporalDelimiters = true;
74 constexpr bool kDoNotIncludeTemporalDelimiters = false;
75 
76 constexpr bool kDelayDescriptorsUntilTrimAtStartIsKnown = true;
77 constexpr bool kDoNotDelayDescriptorsUntilTrimAtStartIsKnown = false;
78 
79 constexpr std::nullopt_t kOriginalSamplesAreIrrelevant = std::nullopt;
80 
81 constexpr absl::Span<ParameterBlockWithData> kNoParameterBlocks = {};
82 constexpr absl::Span<ArbitraryObu> kNoArbitraryObus = {};
83 
InitializeDescriptorObusForOneMonoAmbisonicsAudioElement(absl::flat_hash_map<DecodedUleb128,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<uint32_t,AudioElementWithData> & audio_elements,std::list<MixPresentationObu> & mix_presentation_obus)84 void InitializeDescriptorObusForOneMonoAmbisonicsAudioElement(
85     absl::flat_hash_map<DecodedUleb128, CodecConfigObu>& codec_config_obus,
86     absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
87     std::list<MixPresentationObu>& mix_presentation_obus) {
88   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
89                                         codec_config_obus);
90   AddAmbisonicsMonoAudioElementWithSubstreamIds(
91       kFirstAudioElementId, kCodecConfigId, {kFirstSubstreamId},
92       codec_config_obus, audio_elements);
93   AddMixPresentationObuWithAudioElementIds(
94       kFirstMixPresentationId, {kFirstAudioElementId},
95       kCommonMixGainParameterId, kCommonMixGainParameterRate,
96       mix_presentation_obus);
97 }
98 
AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(uint32_t audio_element_id,uint32_t substream_id,InternalTimestamp start_timestamp,InternalTimestamp end_timestamp,const absl::flat_hash_map<uint32_t,AudioElementWithData> & audio_elements,std::list<AudioFrameWithData> & audio_frames)99 void AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
100     uint32_t audio_element_id, uint32_t substream_id,
101     InternalTimestamp start_timestamp, InternalTimestamp end_timestamp,
102     const absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
103     std::list<AudioFrameWithData>& audio_frames) {
104   ASSERT_TRUE(audio_elements.contains(audio_element_id));
105 
106   audio_frames.emplace_back(AudioFrameWithData{
107       .obu = AudioFrameObu(ObuHeader(), substream_id, {}),
108       .start_timestamp = start_timestamp,
109       .end_timestamp = end_timestamp,
110       .pcm_samples = kOriginalSamplesAreIrrelevant,
111       .down_mixing_params = {.in_bitstream = false},
112       .audio_element_with_data = &audio_elements.at(audio_element_id)});
113 }
114 
InitializeOneFrameIaSequence(absl::flat_hash_map<uint32_t,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<uint32_t,AudioElementWithData> & audio_elements,std::list<AudioFrameWithData> & audio_frames)115 void InitializeOneFrameIaSequence(
116     absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
117     absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
118     std::list<AudioFrameWithData>& audio_frames) {
119   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
120                                         codec_config_obus);
121   AddAmbisonicsMonoAudioElementWithSubstreamIds(
122       kFirstAudioElementId, kCodecConfigId, {kFirstSubstreamId},
123       codec_config_obus, audio_elements);
124   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
125       kFirstAudioElementId, kFirstSubstreamId, kFirstTimestamp,
126       kSecondTimestamp, audio_elements, audio_frames);
127 }
128 
InitializeOneFrameIaSequenceWithMixPresentation(absl::flat_hash_map<DecodedUleb128,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<uint32_t,AudioElementWithData> & audio_elements,std::list<MixPresentationObu> & mix_presentation_obus,std::list<AudioFrameWithData> & audio_frames)129 void InitializeOneFrameIaSequenceWithMixPresentation(
130     absl::flat_hash_map<DecodedUleb128, CodecConfigObu>& codec_config_obus,
131     absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
132     std::list<MixPresentationObu>& mix_presentation_obus,
133     std::list<AudioFrameWithData>& audio_frames) {
134   InitializeDescriptorObusForOneMonoAmbisonicsAudioElement(
135       codec_config_obus, audio_elements, mix_presentation_obus);
136 
137   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
138       kFirstAudioElementId, kFirstSubstreamId, 0, 8, audio_elements,
139       audio_frames);
140 }
141 
InitializeOneParameterBlockAndOneAudioFrame(DemixingParamDefinition & param_definition,std::list<ParameterBlockWithData> & parameter_blocks,std::list<AudioFrameWithData> & audio_frames,absl::flat_hash_map<uint32_t,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<uint32_t,AudioElementWithData> & audio_elements)142 void InitializeOneParameterBlockAndOneAudioFrame(
143     DemixingParamDefinition& param_definition,
144     std::list<ParameterBlockWithData>& parameter_blocks,
145     std::list<AudioFrameWithData>& audio_frames,
146     absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
147     absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements) {
148   InitializeOneFrameIaSequence(codec_config_obus, audio_elements, audio_frames);
149   auto data = std::make_unique<DemixingInfoParameterData>();
150   data->dmixp_mode = DemixingInfoParameterData::kDMixPMode1;
151   data->reserved = 0;
152   auto parameter_block = std::make_unique<ParameterBlockObu>(
153       ObuHeader(), param_definition.parameter_id_, param_definition);
154   ASSERT_THAT(parameter_block->InitializeSubblocks(), IsOk());
155   parameter_block->subblocks_[0].param_data = std::move(data);
156   parameter_blocks.emplace_back(ParameterBlockWithData{
157       .obu = std::move(parameter_block),
158       .start_timestamp = kFirstTimestamp,
159       .end_timestamp = kSecondTimestamp,
160   });
161 }
InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(absl::flat_hash_map<DecodedUleb128,CodecConfigObu> & codec_config_obus,absl::flat_hash_map<uint32_t,AudioElementWithData> & audio_elements,std::list<MixPresentationObu> & mix_presentation_obus)162 void InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
163     absl::flat_hash_map<DecodedUleb128, CodecConfigObu>& codec_config_obus,
164     absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
165     std::list<MixPresentationObu>& mix_presentation_obus) {
166   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
167                                         codec_config_obus);
168   AddAmbisonicsMonoAudioElementWithSubstreamIds(
169       kFirstAudioElementId, kCodecConfigId, {kFirstSubstreamId},
170       codec_config_obus, audio_elements);
171   AddAmbisonicsMonoAudioElementWithSubstreamIds(
172       kSecondAudioElementId, kCodecConfigId, {kSecondSubstreamId},
173       codec_config_obus, audio_elements);
174   AddMixPresentationObuWithAudioElementIds(
175       kFirstMixPresentationId, {kFirstAudioElementId, kSecondAudioElementId},
176       kCommonMixGainParameterId, kCommonMixGainParameterRate,
177       mix_presentation_obus);
178 }
179 
CreateDemixingParamDefinition(const DecodedUleb128 parameter_id)180 DemixingParamDefinition CreateDemixingParamDefinition(
181     const DecodedUleb128 parameter_id) {
182   DemixingParamDefinition demixing_param_definition;
183   demixing_param_definition.parameter_id_ = parameter_id;
184   demixing_param_definition.parameter_rate_ = 48000;
185   demixing_param_definition.param_definition_mode_ = 0;
186   demixing_param_definition.duration_ = 8;
187   demixing_param_definition.constant_subblock_duration_ = 8;
188   demixing_param_definition.reserved_ = 10;
189 
190   return demixing_param_definition;
191 }
192 
ValidateWriteTemporalUnitSequence(bool include_temporal_delimiters,const TemporalUnitView & temporal_unit,const std::list<const ObuBase * > & expected_sequence)193 void ValidateWriteTemporalUnitSequence(
194     bool include_temporal_delimiters, const TemporalUnitView& temporal_unit,
195     const std::list<const ObuBase*>& expected_sequence) {
196   WriteBitBuffer result_wb(128);
197   int unused_num_samples;
198   EXPECT_THAT(ObuSequencerBase::WriteTemporalUnit(include_temporal_delimiters,
199                                                   temporal_unit, result_wb,
200                                                   unused_num_samples),
201               IsOk());
202 
203   EXPECT_EQ(result_wb.bit_buffer(), SerializeObusExpectOk(expected_sequence));
204 }
205 
TEST(WriteTemporalUnit,WritesArbitraryObuBeforeParameterBlocksAtTime)206 TEST(WriteTemporalUnit, WritesArbitraryObuBeforeParameterBlocksAtTime) {
207   std::list<ParameterBlockWithData> parameter_blocks;
208   std::list<AudioFrameWithData> audio_frames;
209   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
210   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
211   DemixingParamDefinition param_definition =
212       CreateDemixingParamDefinition(kFirstDemixingParameterId);
213   InitializeOneParameterBlockAndOneAudioFrame(
214       param_definition, parameter_blocks, audio_frames, codec_config_obus,
215       audio_elements);
216   const std::list<ArbitraryObu> kArbitraryObuBeforeParameterBlocks(
217       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
218                     ArbitraryObu::kInsertionHookBeforeParameterBlocksAtTick,
219                     kFirstTimestamp)});
220   const auto temporal_unit = TemporalUnitView::Create(
221       parameter_blocks, audio_frames, kArbitraryObuBeforeParameterBlocks);
222   ASSERT_THAT(temporal_unit, IsOk());
223 
224   const TemporalDelimiterObu temporal_delimiter_obu(ObuHeader{});
225 
226   const std::list<const ObuBase*>
227       expected_arbitrary_obu_between_temporal_delimiter_and_parameter_block = {
228           &temporal_delimiter_obu, &kArbitraryObuBeforeParameterBlocks.front(),
229           parameter_blocks.front().obu.get(), &audio_frames.front().obu};
230 
231   ValidateWriteTemporalUnitSequence(
232       kIncludeTemporalDelimiters, *temporal_unit,
233       expected_arbitrary_obu_between_temporal_delimiter_and_parameter_block);
234 }
235 
TEST(WriteTemporalUnit,WritesArbitraryObuAfterParameterBlocksAtTime)236 TEST(WriteTemporalUnit, WritesArbitraryObuAfterParameterBlocksAtTime) {
237   std::list<ParameterBlockWithData> parameter_blocks;
238   std::list<AudioFrameWithData> audio_frames;
239   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
240   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
241   DemixingParamDefinition param_definition =
242       CreateDemixingParamDefinition(kFirstDemixingParameterId);
243   InitializeOneParameterBlockAndOneAudioFrame(
244       param_definition, parameter_blocks, audio_frames, codec_config_obus,
245       audio_elements);
246   const std::list<ArbitraryObu> kArbitraryObuAfterParameterBlocks(
247       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
248                     ArbitraryObu::kInsertionHookAfterParameterBlocksAtTick,
249                     kFirstTimestamp)});
250   const auto temporal_unit = TemporalUnitView::Create(
251       parameter_blocks, audio_frames, kArbitraryObuAfterParameterBlocks);
252   ASSERT_THAT(temporal_unit, IsOk());
253 
254   const std::list<const ObuBase*>
255       expected_arbitrary_obu_between_parameter_block_and_audio_frame = {
256           parameter_blocks.front().obu.get(),
257           &kArbitraryObuAfterParameterBlocks.front(),
258           &audio_frames.front().obu,
259       };
260 
261   ValidateWriteTemporalUnitSequence(
262       kDoNotIncludeTemporalDelimiters, *temporal_unit,
263       expected_arbitrary_obu_between_parameter_block_and_audio_frame);
264 }
265 
TEST(WriteTemporalUnit,WritesArbitraryObuAfterAudioFramesAtTime)266 TEST(WriteTemporalUnit, WritesArbitraryObuAfterAudioFramesAtTime) {
267   std::list<ParameterBlockWithData> parameter_blocks;
268   std::list<AudioFrameWithData> audio_frames;
269   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
270   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
271   DemixingParamDefinition param_definition =
272       CreateDemixingParamDefinition(kFirstDemixingParameterId);
273   InitializeOneParameterBlockAndOneAudioFrame(
274       param_definition, parameter_blocks, audio_frames, codec_config_obus,
275       audio_elements);
276   const std::list<ArbitraryObu> kArbitraryObuAfterAudioFrames({ArbitraryObu(
277       kObuIaReserved25, ObuHeader(), {},
278       ArbitraryObu::kInsertionHookAfterAudioFramesAtTick, kFirstTimestamp)});
279   const auto temporal_unit = TemporalUnitView::Create(
280       parameter_blocks, audio_frames, kArbitraryObuAfterAudioFrames);
281   ASSERT_THAT(temporal_unit, IsOk());
282 
283   const std::list<const ObuBase*> expected_arbitrary_obu_after_audio_frame = {
284       parameter_blocks.front().obu.get(),
285       &audio_frames.front().obu,
286       &kArbitraryObuAfterAudioFrames.front(),
287   };
288 
289   ValidateWriteTemporalUnitSequence(kDoNotIncludeTemporalDelimiters,
290                                     *temporal_unit,
291                                     expected_arbitrary_obu_after_audio_frame);
292 }
293 
TEST(WriteTemporalUnit,AccumulatesZeroSamplesForFullyTrimmedAudioFrame)294 TEST(WriteTemporalUnit, AccumulatesZeroSamplesForFullyTrimmedAudioFrame) {
295   std::list<AudioFrameWithData> audio_frames;
296   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
297   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
298   InitializeOneFrameIaSequence(codec_config_obus, audio_elements, audio_frames);
299   audio_frames.front().obu.header_.num_samples_to_trim_at_end = 0;
300   audio_frames.front().obu.header_.num_samples_to_trim_at_start = 8;
301   constexpr uint32_t kNumUntrimmedSamples = 0;
302   const auto temporal_unit = TemporalUnitView::Create(
303       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
304   ASSERT_THAT(temporal_unit, IsOk());
305 
306   WriteBitBuffer wb(128);
307   int num_samples = 0;
308   EXPECT_THAT(
309       ObuSequencerBase::WriteTemporalUnit(kDoNotIncludeTemporalDelimiters,
310                                           *temporal_unit, wb, num_samples),
311       IsOk());
312 
313   EXPECT_EQ(num_samples, kNumUntrimmedSamples);
314 }
315 
TEST(WriteTemporalUnit,AddsNumberOfUntrimmedSamplesToNumSamples)316 TEST(WriteTemporalUnit, AddsNumberOfUntrimmedSamplesToNumSamples) {
317   std::list<AudioFrameWithData> audio_frames;
318   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
319   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
320   InitializeOneFrameIaSequence(codec_config_obus, audio_elements, audio_frames);
321   audio_frames.front().obu.header_.num_samples_to_trim_at_end = 2;
322   audio_frames.front().obu.header_.num_samples_to_trim_at_start = 1;
323   constexpr uint32_t kNumUntrimmedSamples = kNumSamplesPerFrame - 1 - 2;
324   const auto temporal_unit = TemporalUnitView::Create(
325       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
326   ASSERT_THAT(temporal_unit, IsOk());
327 
328   WriteBitBuffer undefined_wb(128);
329   int num_samples = 0;
330   EXPECT_THAT(ObuSequencerBase::WriteTemporalUnit(
331                   kDoNotIncludeTemporalDelimiters, *temporal_unit, undefined_wb,
332                   num_samples),
333               IsOk());
334   EXPECT_EQ(num_samples, kNumUntrimmedSamples);
335   // Another write keeps adding to the number of samples.
336   EXPECT_THAT(ObuSequencerBase::WriteTemporalUnit(
337                   kDoNotIncludeTemporalDelimiters, *temporal_unit, undefined_wb,
338                   num_samples),
339               IsOk());
340   EXPECT_EQ(num_samples, kNumUntrimmedSamples * 2);
341 }
342 
TEST(WriteTemporalUnit,WritesTemporalDelimiterObuWhenEnabled)343 TEST(WriteTemporalUnit, WritesTemporalDelimiterObuWhenEnabled) {
344   std::list<ParameterBlockWithData> parameter_blocks;
345   std::list<AudioFrameWithData> audio_frames;
346   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
347   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
348   DemixingParamDefinition param_definition =
349       CreateDemixingParamDefinition(kFirstDemixingParameterId);
350   InitializeOneParameterBlockAndOneAudioFrame(
351       param_definition, parameter_blocks, audio_frames, codec_config_obus,
352       audio_elements);
353   const auto temporal_unit = TemporalUnitView::Create(
354       parameter_blocks, audio_frames, kNoArbitraryObus);
355   ASSERT_THAT(temporal_unit, IsOk());
356 
357   const TemporalDelimiterObu kTemporalDelimiterObu(ObuHeader{});
358   const std::list<const ObuBase*> expected_sequence = {
359       &kTemporalDelimiterObu,
360       parameter_blocks.front().obu.get(),
361       &audio_frames.front().obu,
362   };
363 
364   ValidateWriteTemporalUnitSequence(kIncludeTemporalDelimiters, *temporal_unit,
365                                     expected_sequence);
366 }
367 
TEST(WriteTemporalUnit,OmitsTemporalDelimiterObuWhenDisabled)368 TEST(WriteTemporalUnit, OmitsTemporalDelimiterObuWhenDisabled) {
369   std::list<ParameterBlockWithData> parameter_blocks;
370   std::list<AudioFrameWithData> audio_frames;
371   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus;
372   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
373   DemixingParamDefinition param_definition =
374       CreateDemixingParamDefinition(kFirstDemixingParameterId);
375   InitializeOneParameterBlockAndOneAudioFrame(
376       param_definition, parameter_blocks, audio_frames, codec_config_obus,
377       audio_elements);
378   const auto temporal_unit = TemporalUnitView::Create(
379       parameter_blocks, audio_frames, kNoArbitraryObus);
380   ASSERT_THAT(temporal_unit, IsOk());
381 
382   const std::list<const ObuBase*> expected_sequence = {
383       parameter_blocks.front().obu.get(),
384       &audio_frames.front().obu,
385   };
386 
387   ValidateWriteTemporalUnitSequence(kDoNotIncludeTemporalDelimiters,
388                                     *temporal_unit, expected_sequence);
389 }
390 
391 class ObuSequencerTest : public ::testing::Test {
392  public:
InitializeDescriptorObus()393   void InitializeDescriptorObus() {
394     ia_sequence_header_obu_.emplace(ObuHeader(), IASequenceHeaderObu::kIaCode,
395                                     ProfileVersion::kIamfSimpleProfile,
396                                     ProfileVersion::kIamfSimpleProfile);
397     AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
398                                           codec_config_obus_);
399     AddAmbisonicsMonoAudioElementWithSubstreamIds(
400         kFirstAudioElementId, kCodecConfigId, {kFirstSubstreamId},
401         codec_config_obus_, audio_elements_);
402     AddMixPresentationObuWithAudioElementIds(
403         kFirstMixPresentationId, {kFirstAudioElementId},
404         kCommonMixGainParameterId, kCommonMixGainParameterRate,
405         mix_presentation_obus_);
406 
407     ASSERT_TRUE(ia_sequence_header_obu_.has_value());
408     ASSERT_TRUE(codec_config_obus_.contains(kCodecConfigId));
409     ASSERT_TRUE(audio_elements_.contains(kFirstAudioElementId));
410     ASSERT_FALSE(mix_presentation_obus_.empty());
411   }
412 
InitObusForOneFrameIaSequence()413   void InitObusForOneFrameIaSequence() {
414     ia_sequence_header_obu_.emplace(ObuHeader(), IASequenceHeaderObu::kIaCode,
415                                     ProfileVersion::kIamfSimpleProfile,
416                                     ProfileVersion::kIamfSimpleProfile);
417     param_definition_ =
418         CreateDemixingParamDefinition(kFirstDemixingParameterId);
419     InitializeOneParameterBlockAndOneAudioFrame(
420         param_definition_, parameter_blocks_, audio_frames_, codec_config_obus_,
421         audio_elements_);
422     AddMixPresentationObuWithAudioElementIds(
423         kFirstMixPresentationId, {audio_elements_.begin()->first},
424         kCommonMixGainParameterId, kCommonMixGainParameterRate,
425         mix_presentation_obus_);
426   }
427 
ValidateWriteDescriptorObuSequence(const std::list<const ObuBase * > & expected_sequence)428   void ValidateWriteDescriptorObuSequence(
429       const std::list<const ObuBase*>& expected_sequence) {
430     WriteBitBuffer expected_wb(128);
431     for (const auto* expected_obu : expected_sequence) {
432       ASSERT_NE(expected_obu, nullptr);
433       EXPECT_THAT(expected_obu->ValidateAndWriteObu(expected_wb), IsOk());
434     }
435 
436     WriteBitBuffer result_wb(128);
437     EXPECT_THAT(ObuSequencerBase::WriteDescriptorObus(
438                     ia_sequence_header_obu_.value(), codec_config_obus_,
439                     audio_elements_, mix_presentation_obus_, arbitrary_obus_,
440                     result_wb),
441                 IsOk());
442 
443     EXPECT_EQ(result_wb.bit_buffer(), expected_wb.bit_buffer());
444   }
445 
446  protected:
447   std::optional<IASequenceHeaderObu> ia_sequence_header_obu_;
448   absl::flat_hash_map<uint32_t, CodecConfigObu> codec_config_obus_;
449   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements_;
450   std::list<MixPresentationObu> mix_presentation_obus_;
451 
452   DemixingParamDefinition param_definition_;
453   std::list<ParameterBlockWithData> parameter_blocks_;
454   std::list<AudioFrameWithData> audio_frames_;
455 
456   std::list<ArbitraryObu> arbitrary_obus_;
457 };
458 
TEST_F(ObuSequencerTest,OrdersByAParticularObuType)459 TEST_F(ObuSequencerTest, OrdersByAParticularObuType) {
460   InitializeDescriptorObus();
461   // The IAMF spec REQUIRES descriptor OBUs to be ordered by `obu_type` in a
462   // particular order (i.e. IA Sequence Header, Codec Config Audio Element, Mix
463   // Presentation).
464   const std::list<const ObuBase*> expected_sequence = {
465       &ia_sequence_header_obu_.value(), &codec_config_obus_.at(kCodecConfigId),
466       &audio_elements_.at(kFirstAudioElementId).obu,
467       &mix_presentation_obus_.back()};
468 
469   ValidateWriteDescriptorObuSequence(expected_sequence);
470 }
471 
TEST_F(ObuSequencerTest,ArbitraryObuAfterIaSequenceHeader)472 TEST_F(ObuSequencerTest, ArbitraryObuAfterIaSequenceHeader) {
473   InitializeDescriptorObus();
474 
475   arbitrary_obus_.emplace_back(
476       ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
477                    ArbitraryObu::kInsertionHookAfterIaSequenceHeader));
478 
479   const std::list<const ObuBase*> expected_sequence = {
480       &ia_sequence_header_obu_.value(),
481       &arbitrary_obus_.back(),
482       &codec_config_obus_.at(kCodecConfigId),
483       &audio_elements_.at(kFirstAudioElementId).obu,
484       &mix_presentation_obus_.back(),
485   };
486 
487   ValidateWriteDescriptorObuSequence(expected_sequence);
488 }
489 
TEST_F(ObuSequencerTest,ArbitraryObuAfterCodecConfigs)490 TEST_F(ObuSequencerTest, ArbitraryObuAfterCodecConfigs) {
491   InitializeDescriptorObus();
492 
493   arbitrary_obus_.emplace_back(
494       ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
495                    ArbitraryObu::kInsertionHookAfterCodecConfigs));
496 
497   const std::list<const ObuBase*> expected_sequence = {
498       &ia_sequence_header_obu_.value(),
499       &codec_config_obus_.at(kCodecConfigId),
500       &arbitrary_obus_.back(),
501       &audio_elements_.at(kFirstAudioElementId).obu,
502       &mix_presentation_obus_.back(),
503   };
504 
505   ValidateWriteDescriptorObuSequence(expected_sequence);
506 }
507 
TEST_F(ObuSequencerTest,ArbitraryObuAfterAudioElements)508 TEST_F(ObuSequencerTest, ArbitraryObuAfterAudioElements) {
509   InitializeDescriptorObus();
510 
511   arbitrary_obus_.emplace_back(
512       ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
513                    ArbitraryObu::kInsertionHookAfterAudioElements));
514 
515   const std::list<const ObuBase*> expected_sequence = {
516       &ia_sequence_header_obu_.value(),
517       &codec_config_obus_.at(kCodecConfigId),
518       &audio_elements_.at(kFirstAudioElementId).obu,
519       &arbitrary_obus_.back(),
520       &mix_presentation_obus_.back(),
521   };
522 
523   ValidateWriteDescriptorObuSequence(expected_sequence);
524 }
525 
TEST_F(ObuSequencerTest,ArbitraryObuAfterMixPresentations)526 TEST_F(ObuSequencerTest, ArbitraryObuAfterMixPresentations) {
527   InitializeDescriptorObus();
528 
529   arbitrary_obus_.emplace_back(
530       ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
531                    ArbitraryObu::kInsertionHookAfterMixPresentations));
532 
533   const std::list<const ObuBase*> expected_sequence = {
534       &ia_sequence_header_obu_.value(),
535       &codec_config_obus_.at(kCodecConfigId),
536       &audio_elements_.at(kFirstAudioElementId).obu,
537       &mix_presentation_obus_.back(),
538       &arbitrary_obus_.back(),
539   };
540 
541   ValidateWriteDescriptorObuSequence(expected_sequence);
542 }
543 
544 // This behavior helps ensure that "after descriptors" are not written in the
545 // "IACB" box in MP4.
TEST_F(ObuSequencerTest,DoesNotWriteArbitraryObuAfterDescriptors)546 TEST_F(ObuSequencerTest, DoesNotWriteArbitraryObuAfterDescriptors) {
547   InitializeDescriptorObus();
548 
549   arbitrary_obus_.emplace_back(
550       ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
551                    ArbitraryObu::kInsertionHookAfterDescriptors));
552 
553   const std::list<const ObuBase*> expected_sequence = {
554       &ia_sequence_header_obu_.value(), &codec_config_obus_.at(kCodecConfigId),
555       &audio_elements_.at(kFirstAudioElementId).obu,
556       &mix_presentation_obus_.back(),
557       // &arbitrary_obus_.back(),
558   };
559 
560   ValidateWriteDescriptorObuSequence(expected_sequence);
561 }
562 
TEST_F(ObuSequencerTest,CodecConfigAreAscendingOrderByDefault)563 TEST_F(ObuSequencerTest, CodecConfigAreAscendingOrderByDefault) {
564   InitializeDescriptorObus();
565 
566   // Initialize a second Codec Config OBU.
567   const DecodedUleb128 kSecondCodecConfigId = 101;
568   AddLpcmCodecConfigWithIdAndSampleRate(kSecondCodecConfigId, kSampleRate,
569                                         codec_config_obus_);
570 
571   // IAMF makes no recommendation for the ordering between multiple descriptor
572   // OBUs of the same type. By default `WriteDescriptorObus` orders them in
573   // ascending order.
574   ASSERT_LT(kCodecConfigId, kSecondCodecConfigId);
575   const std::list<const ObuBase*> expected_sequence = {
576       &ia_sequence_header_obu_.value(), &codec_config_obus_.at(kCodecConfigId),
577       &codec_config_obus_.at(kSecondCodecConfigId),
578       &audio_elements_.at(kFirstAudioElementId).obu,
579       &mix_presentation_obus_.back()};
580 
581   ValidateWriteDescriptorObuSequence(expected_sequence);
582 }
583 
TEST_F(ObuSequencerTest,AudioElementAreAscendingOrderByDefault)584 TEST_F(ObuSequencerTest, AudioElementAreAscendingOrderByDefault) {
585   InitializeDescriptorObus();
586 
587   // Initialize a second Audio Element OBU.
588   const DecodedUleb128 kSecondAudioElementId = 101;
589   AddAmbisonicsMonoAudioElementWithSubstreamIds(
590       kSecondAudioElementId, kCodecConfigId, {kFirstSubstreamId},
591       codec_config_obus_, audio_elements_);
592 
593   // IAMF makes no recommendation for the ordering between multiple descriptor
594   // OBUs of the same type. By default `WriteDescriptorObus` orders them in
595   // ascending order.
596   ASSERT_LT(kFirstAudioElementId, kSecondAudioElementId);
597   const std::list<const ObuBase*> expected_sequence = {
598       &ia_sequence_header_obu_.value(), &codec_config_obus_.at(kCodecConfigId),
599       &audio_elements_.at(kFirstAudioElementId).obu,
600       &audio_elements_.at(kSecondAudioElementId).obu,
601       &mix_presentation_obus_.back()};
602 
603   ValidateWriteDescriptorObuSequence(expected_sequence);
604 }
605 
TEST_F(ObuSequencerTest,MixPresentationsMaintainOriginalOrder)606 TEST_F(ObuSequencerTest, MixPresentationsMaintainOriginalOrder) {
607   InitializeDescriptorObus();
608   mix_presentation_obus_.clear();
609 
610   // Prefix descriptor OBUs.
611   std::list<const ObuBase*> expected_sequence = {
612       &ia_sequence_header_obu_.value(),
613       &codec_config_obus_.at(kCodecConfigId),
614       &audio_elements_.at(kFirstAudioElementId).obu,
615   };
616   // Initialize three Mix Presentation OBUs, regardless of their IDs we
617   // expect them to be serialized in the same order as the input list.
618   constexpr DecodedUleb128 kFirstMixPresentationId = 100;
619   constexpr DecodedUleb128 kSecondMixPresentationId = 99;
620   constexpr DecodedUleb128 kThirdMixPresentationId = 101;
621   AddMixPresentationObuWithAudioElementIds(
622       kFirstMixPresentationId, {kFirstAudioElementId},
623       kCommonMixGainParameterId, kCommonMixGainParameterRate,
624       mix_presentation_obus_);
625   expected_sequence.push_back(&mix_presentation_obus_.back());
626   AddMixPresentationObuWithAudioElementIds(
627       kSecondMixPresentationId, {kFirstAudioElementId},
628       kCommonMixGainParameterId, kCommonMixGainParameterRate,
629       mix_presentation_obus_);
630   expected_sequence.push_back(&mix_presentation_obus_.back());
631   AddMixPresentationObuWithAudioElementIds(
632       kThirdMixPresentationId, {kFirstAudioElementId},
633       kCommonMixGainParameterId, kCommonMixGainParameterRate,
634       mix_presentation_obus_);
635   expected_sequence.push_back(&mix_presentation_obus_.back());
636 
637   ValidateWriteDescriptorObuSequence(expected_sequence);
638 }
639 
TEST(WriteDescriptorObus,InvalidWhenMixPresentationDoesNotComplyWithIaSequenceHeader)640 TEST(WriteDescriptorObus,
641      InvalidWhenMixPresentationDoesNotComplyWithIaSequenceHeader) {
642   IASequenceHeaderObu ia_sequence_header_obu(
643       ObuHeader(), IASequenceHeaderObu::kIaCode,
644       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfSimpleProfile);
645   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
646   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
647   std::list<MixPresentationObu> mix_presentation_obus;
648   InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
649       codec_config_obus, audio_elements, mix_presentation_obus);
650 
651   WriteBitBuffer unused_wb(0);
652   EXPECT_FALSE(ObuSequencerBase::WriteDescriptorObus(
653                    ia_sequence_header_obu, codec_config_obus, audio_elements,
654                    mix_presentation_obus, /*arbitrary_obus=*/{}, unused_wb)
655                    .ok());
656 }
657 
TEST(WriteDescriptorObus,ValidWhenMixPresentationCompliesWithIaSequenceHeader)658 TEST(WriteDescriptorObus,
659      ValidWhenMixPresentationCompliesWithIaSequenceHeader) {
660   IASequenceHeaderObu ia_sequence_header_obu(
661       ObuHeader(), IASequenceHeaderObu::kIaCode,
662       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
663   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
664   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
665   std::list<MixPresentationObu> mix_presentation_obus;
666   InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
667       codec_config_obus, audio_elements, mix_presentation_obus);
668 
669   WriteBitBuffer unused_wb(0);
670   EXPECT_THAT(ObuSequencerBase::WriteDescriptorObus(
671                   ia_sequence_header_obu, codec_config_obus, audio_elements,
672                   mix_presentation_obus, /*arbitrary_obus=*/{}, unused_wb),
673               IsOk());
674 }
675 
TEST(PushDescriptorObus,SucceedsWithIaSequenceHeaderOnly)676 TEST(PushDescriptorObus, SucceedsWithIaSequenceHeaderOnly) {
677   const IASequenceHeaderObu kIaSequenceHeader(
678       ObuHeader(), IASequenceHeaderObu::kIaCode,
679       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
680   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
681   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
682   const std::list<MixPresentationObu> kNoMixPresentationObus;
683   const std::list<ArbitraryObu> kNoArbitraryObus;
684   MockObuSequencer mock_obu_sequencer(
685       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
686       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
687 
688   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
689                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
690                   kNoMixPresentationObus, kNoArbitraryObus),
691               IsOk());
692 }
693 
TEST(PickAndPlace,SucceedsWithIaSequenceHeaderOnly)694 TEST(PickAndPlace, SucceedsWithIaSequenceHeaderOnly) {
695   const IASequenceHeaderObu kIaSequenceHeader(
696       ObuHeader(), IASequenceHeaderObu::kIaCode,
697       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
698   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
699   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
700   const std::list<MixPresentationObu> kNoMixPresentationObus;
701   const std::list<AudioFrameWithData> kNoAudioFrames;
702   const std::list<ParameterBlockWithData> kNoParameterBlocks;
703   const std::list<ArbitraryObu> kNoArbitraryObus;
704   MockObuSequencer mock_obu_sequencer(
705       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
706       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
707 
708   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
709                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
710                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
711                   kNoArbitraryObus),
712               IsOk());
713 }
714 
TEST(PushDescriptorObus,FailsWhenCalledTwice)715 TEST(PushDescriptorObus, FailsWhenCalledTwice) {
716   const IASequenceHeaderObu kIaSequenceHeader(
717       ObuHeader(), IASequenceHeaderObu::kIaCode,
718       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
719   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
720   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
721   const std::list<MixPresentationObu> kNoMixPresentationObus;
722   const std::list<ArbitraryObu> kNoArbitraryObus;
723   MockObuSequencer mock_obu_sequencer(
724       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
725       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
726   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
727                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
728                   kNoMixPresentationObus, kNoArbitraryObus),
729               IsOk());
730 
731   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
732                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
733                   kNoMixPresentationObus, kNoArbitraryObus),
734               Not(IsOk()));
735 }
736 
TEST(PickAndPlace,FailsWhenCalledTwice)737 TEST(PickAndPlace, FailsWhenCalledTwice) {
738   const IASequenceHeaderObu kIaSequenceHeader(
739       ObuHeader(), IASequenceHeaderObu::kIaCode,
740       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
741   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
742   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
743   const std::list<MixPresentationObu> kNoMixPresentationObus;
744   const std::list<AudioFrameWithData> kNoAudioFrames;
745   const std::list<ParameterBlockWithData> kNoParameterBlocks;
746   const std::list<ArbitraryObu> kNoArbitraryObus;
747   MockObuSequencer mock_obu_sequencer(
748       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
749       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
750   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
751                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
752                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
753                   kNoArbitraryObus),
754               IsOk());
755 
756   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
757                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
758                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
759                   kNoArbitraryObus),
760               Not(IsOk()));
761 }
762 
TEST(PushDescriptorObus,ForwardsPropertiesToPushSerializedDescriptorObus)763 TEST(PushDescriptorObus, ForwardsPropertiesToPushSerializedDescriptorObus) {
764   const IASequenceHeaderObu kIaSequenceHeader(
765       ObuHeader(), IASequenceHeaderObu::kIaCode,
766       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
767   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
768   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
769   std::list<MixPresentationObu> mix_presentation_obus;
770   const std::list<ArbitraryObu> kNoArbitraryObus;
771   InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
772       codec_config_obus, audio_elements, mix_presentation_obus);
773   MockObuSequencer mock_obu_sequencer(
774       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
775       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
776 
777   // Several properties should match values derived from the descriptor OBUs.
778   const auto& codec_config_obu = codec_config_obus.begin()->second;
779   const uint32_t kExpectedCommonSamplesPerFrame =
780       codec_config_obu.GetNumSamplesPerFrame();
781   const uint32_t kExpectedCommonSampleRate =
782       codec_config_obu.GetOutputSampleRate();
783   const uint8_t kExpectedCommonBitDepth =
784       codec_config_obu.GetBitDepthToMeasureLoudness();
785   const std::optional<int64_t> kOmitFirstPts = std::nullopt;
786   const int kExpectedNumChannels = 2;
787   const std::vector<uint8_t> descriptor_obus = {1, 2, 3};
788   EXPECT_CALL(
789       mock_obu_sequencer,
790       PushSerializedDescriptorObus(
791           kExpectedCommonSamplesPerFrame, kExpectedCommonSampleRate,
792           kExpectedCommonBitDepth, kOmitFirstPts, kExpectedNumChannels, _));
793 
794   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
795                   kIaSequenceHeader, codec_config_obus, audio_elements,
796                   mix_presentation_obus, kNoArbitraryObus),
797               IsOk());
798 }
799 
TEST(PickAndPlace,ForwardsPropertiesToPushSerializedDescriptorObus)800 TEST(PickAndPlace, ForwardsPropertiesToPushSerializedDescriptorObus) {
801   const IASequenceHeaderObu kIaSequenceHeader(
802       ObuHeader(), IASequenceHeaderObu::kIaCode,
803       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
804   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
805   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
806   std::list<MixPresentationObu> mix_presentation_obus;
807   const std::list<AudioFrameWithData> kNoAudioFrames;
808   const std::list<ParameterBlockWithData> kNoParameterBlocks;
809   const std::list<ArbitraryObu> kNoArbitraryObus;
810   InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
811       codec_config_obus, audio_elements, mix_presentation_obus);
812   MockObuSequencer mock_obu_sequencer(
813       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
814       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
815 
816   // Several properties should match values derived from the descriptor OBUs.
817   const auto& codec_config_obu = codec_config_obus.begin()->second;
818   const uint32_t kExpectedCommonSamplesPerFrame =
819       codec_config_obu.GetNumSamplesPerFrame();
820   const uint32_t kExpectedCommonSampleRate =
821       codec_config_obu.GetOutputSampleRate();
822   const uint8_t kExpectedCommonBitDepth =
823       codec_config_obu.GetBitDepthToMeasureLoudness();
824   const std::optional<int64_t> kOmitFirstPts = std::nullopt;
825   const int kExpectedNumChannels = 2;
826   const std::vector<uint8_t> descriptor_obus = {1, 2, 3};
827   EXPECT_CALL(
828       mock_obu_sequencer,
829       PushSerializedDescriptorObus(
830           kExpectedCommonSamplesPerFrame, kExpectedCommonSampleRate,
831           kExpectedCommonBitDepth, kOmitFirstPts, kExpectedNumChannels, _));
832 
833   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
834                   kIaSequenceHeader, codec_config_obus, audio_elements,
835                   mix_presentation_obus, kNoAudioFrames, kNoParameterBlocks,
836                   kNoArbitraryObus),
837               IsOk());
838 }
839 
TEST(PushDescriptorObus,WhenDescriptorsAreNotDelayedDescriptorsAreForwardedImmediately)840 TEST(PushDescriptorObus,
841      WhenDescriptorsAreNotDelayedDescriptorsAreForwardedImmediately) {
842   // Configure the OBU sequencer to not delay descriptors. This means the
843   // properties can be forwarded right away.
844   const IASequenceHeaderObu kIaSequenceHeader(
845       ObuHeader(), IASequenceHeaderObu::kIaCode,
846       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
847   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
848   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
849   const std::list<MixPresentationObu> kNoMixPresentationObus;
850   const std::list<ArbitraryObu> kNoArbitraryObus;
851   MockObuSequencer mock_obu_sequencer(
852       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
853       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
854 
855   // The properties themselves are arbitrary, but "reasonable" defaults. This is
856   // to ensure certain OBU sequencers can have a file with reasonable
857   // properties, even if the IA Sequence is trivial.
858   const uint32_t kExpectedCommonSamplesPerFrame = 1024;
859   const uint32_t kExpectedCommonSampleRate = 48000;
860   const uint8_t kExpectedCommonBitDepth = 16;
861   const std::optional<int64_t> kFirstUntrimmedTimestamp = std::nullopt;
862   const int kExpectedNumChannels = 2;
863   EXPECT_CALL(mock_obu_sequencer,
864               PushSerializedDescriptorObus(
865                   kExpectedCommonSamplesPerFrame, kExpectedCommonSampleRate,
866                   kExpectedCommonBitDepth, kFirstUntrimmedTimestamp,
867                   kExpectedNumChannels, _));
868 
869   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
870                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
871                   kNoMixPresentationObus, kNoArbitraryObus),
872               IsOk());
873 }
874 
TEST(PushDescriptorObus,WhenDescriptorsAreDelayedPropertiesAreForwardedAfterCloseForTrivialIaSequences)875 TEST(
876     PushDescriptorObus,
877     WhenDescriptorsAreDelayedPropertiesAreForwardedAfterCloseForTrivialIaSequences) {
878   // Configure the OBU sequencer to delay descriptors until the first untrimmed
879   // sample is known. We can't detect it is a trivial IA Sequence, until the
880   // sequencer is closed.
881   const IASequenceHeaderObu kIaSequenceHeader(
882       ObuHeader(), IASequenceHeaderObu::kIaCode,
883       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
884   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
885   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
886   const std::list<MixPresentationObu> kNoMixPresentationObus;
887   const std::list<ArbitraryObu> kNoArbitraryObus;
888   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
889                                       kDoNotIncludeTemporalDelimiters,
890                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
891   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
892                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
893                   kNoMixPresentationObus, kNoArbitraryObus),
894               IsOk());
895 
896   // The properties themselves are arbitrary, but "reasonable" defaults. This is
897   // to ensure certain OBU sequencers can have a file with reasonable
898   // properties, even if the IA Sequence is trivial.
899   const uint32_t kExpectedCommonSamplesPerFrame = 1024;
900   const uint32_t kExpectedCommonSampleRate = 48000;
901   const uint8_t kExpectedCommonBitDepth = 16;
902   const std::optional<int64_t> kFirstUntrimmedTimestamp = 0;
903   const int kExpectedNumChannels = 2;
904   EXPECT_CALL(mock_obu_sequencer,
905               PushSerializedDescriptorObus(
906                   kExpectedCommonSamplesPerFrame, kExpectedCommonSampleRate,
907                   kExpectedCommonBitDepth, kFirstUntrimmedTimestamp,
908                   kExpectedNumChannels, _));
909   // Finally at close time, we detect that there are no audio frames. Therefore
910   // we can make up a fake first timestamp.
911   EXPECT_THAT(mock_obu_sequencer.Close(), IsOk());
912 }
913 
TEST(PickAndPlace,ForwardsDefaultPropertiesForTrivialIaSequences)914 TEST(PickAndPlace, ForwardsDefaultPropertiesForTrivialIaSequences) {
915   const IASequenceHeaderObu kIaSequenceHeader(
916       ObuHeader(), IASequenceHeaderObu::kIaCode,
917       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
918   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
919   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
920   const std::list<MixPresentationObu> kNoMixPresentationObus;
921   const std::list<AudioFrameWithData> kNoAudioFrames;
922   const std::list<ParameterBlockWithData> kNoParameterBlocks;
923   const std::list<ArbitraryObu> kNoArbitraryObus;
924   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
925                                       kDoNotIncludeTemporalDelimiters,
926                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
927 
928   // The properties themselves are arbitrary, but "reasonable" defaults. This is
929   // to ensure certain OBU sequencers can have a file with reasonable
930   // properties, even if the IA Sequence is trivial.
931   const uint32_t kExpectedCommonSamplesPerFrame = 1024;
932   const uint32_t kExpectedCommonSampleRate = 48000;
933   const uint8_t kExpectedCommonBitDepth = 16;
934   const std::optional<int64_t> kFirstUntrimmedTimestamp = 0;
935   const int kExpectedNumChannels = 2;
936   EXPECT_CALL(mock_obu_sequencer,
937               PushSerializedDescriptorObus(
938                   kExpectedCommonSamplesPerFrame, kExpectedCommonSampleRate,
939                   kExpectedCommonBitDepth, kFirstUntrimmedTimestamp,
940                   kExpectedNumChannels, _));
941 
942   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
943                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
944                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
945                   kNoArbitraryObus),
946               IsOk());
947 }
948 
TEST(PushDescriptorObus,ForwardsSerializedDescriptorObusToPushDescriptorObus)949 TEST(PushDescriptorObus, ForwardsSerializedDescriptorObusToPushDescriptorObus) {
950   const IASequenceHeaderObu kIaSequenceHeader(
951       ObuHeader(), IASequenceHeaderObu::kIaCode,
952       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
953   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
954   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
955   std::list<MixPresentationObu> mix_presentation_obus;
956   const std::list<ArbitraryObu> kNoArbitraryObus;
957   InitializeDescriptorObusForOneMonoAmbisonicsAudioElement(
958       codec_config_obus, audio_elements, mix_presentation_obus);
959   MockObuSequencer mock_obu_sequencer(
960       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
961       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
962 
963   // The spec prescribes an order among different types of descriptor OBUs.
964   const auto descriptor_obus = SerializeObusExpectOk(std::list<const ObuBase*>{
965       &kIaSequenceHeader, &codec_config_obus.begin()->second,
966       &audio_elements.begin()->second.obu, &mix_presentation_obus.front()});
967   EXPECT_CALL(mock_obu_sequencer,
968               PushSerializedDescriptorObus(_, _, _, _, _,
969                                            MakeConstSpan(descriptor_obus)));
970 
971   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
972                   kIaSequenceHeader, codec_config_obus, audio_elements,
973                   mix_presentation_obus, kNoArbitraryObus),
974               IsOk());
975 }
976 
TEST(PickAndPlace,ForwardsSerializedDescriptorObusToPushDescriptorObus)977 TEST(PickAndPlace, ForwardsSerializedDescriptorObusToPushDescriptorObus) {
978   const IASequenceHeaderObu kIaSequenceHeader(
979       ObuHeader(), IASequenceHeaderObu::kIaCode,
980       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
981   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
982   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
983   std::list<MixPresentationObu> mix_presentation_obus;
984   const std::list<AudioFrameWithData> kNoAudioFrames;
985   const std::list<ParameterBlockWithData> kNoParameterBlocks;
986   const std::list<ArbitraryObu> kNoArbitraryObus;
987   InitializeDescriptorObusForOneMonoAmbisonicsAudioElement(
988       codec_config_obus, audio_elements, mix_presentation_obus);
989   MockObuSequencer mock_obu_sequencer(
990       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
991       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
992 
993   // The spec prescribes an order among different types of descriptor OBUs.
994   const auto descriptor_obus = SerializeObusExpectOk(std::list<const ObuBase*>{
995       &kIaSequenceHeader, &codec_config_obus.begin()->second,
996       &audio_elements.begin()->second.obu, &mix_presentation_obus.front()});
997   EXPECT_CALL(mock_obu_sequencer,
998               PushSerializedDescriptorObus(_, _, _, _, _,
999                                            MakeConstSpan(descriptor_obus)));
1000 
1001   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1002                   kIaSequenceHeader, codec_config_obus, audio_elements,
1003                   mix_presentation_obus, kNoAudioFrames, kNoParameterBlocks,
1004                   kNoArbitraryObus),
1005               IsOk());
1006 }
1007 
TEST(PushDescriptorObus,ForwardsArbitraryObusToPushSerializedDescriptorObus)1008 TEST(PushDescriptorObus, ForwardsArbitraryObusToPushSerializedDescriptorObus) {
1009   const IASequenceHeaderObu kIaSequenceHeader(
1010       ObuHeader(), IASequenceHeaderObu::kIaCode,
1011       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1012   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1013   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1014   const std::list<MixPresentationObu> kNoMixPresentationObus;
1015   const std::list<ArbitraryObu> kArbitraryObuAfterIaSequenceHeader(
1016       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
1017                     ArbitraryObu::kInsertionHookAfterIaSequenceHeader)});
1018   MockObuSequencer mock_obu_sequencer(
1019       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1020       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1021 
1022   // Custom arbitrary OBUs can be placed according to their hook.
1023   const auto descriptor_obus = SerializeObusExpectOk(std::list<const ObuBase*>{
1024       &kIaSequenceHeader, &kArbitraryObuAfterIaSequenceHeader.front()});
1025   EXPECT_CALL(mock_obu_sequencer,
1026               PushSerializedDescriptorObus(_, _, _, _, _,
1027                                            MakeConstSpan(descriptor_obus)));
1028 
1029   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1030                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
1031                   kNoMixPresentationObus, kArbitraryObuAfterIaSequenceHeader),
1032               IsOk());
1033 }
1034 
TEST(PickAndPlace,ForwardsArbitraryObusToPushSerializedDescriptorObus)1035 TEST(PickAndPlace, ForwardsArbitraryObusToPushSerializedDescriptorObus) {
1036   const IASequenceHeaderObu kIaSequenceHeader(
1037       ObuHeader(), IASequenceHeaderObu::kIaCode,
1038       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1039   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1040   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1041   const std::list<MixPresentationObu> kNoMixPresentationObus;
1042   const std::list<AudioFrameWithData> kNoAudioFrames;
1043   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1044   const std::list<ArbitraryObu> kArbitraryObuAfterIaSequenceHeader(
1045       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
1046                     ArbitraryObu::kInsertionHookAfterIaSequenceHeader)});
1047   MockObuSequencer mock_obu_sequencer(
1048       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1049       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1050 
1051   // Custom arbitrary OBUs can be placed according to their hook.
1052   const auto descriptor_obus = SerializeObusExpectOk(std::list<const ObuBase*>{
1053       &kIaSequenceHeader, &kArbitraryObuAfterIaSequenceHeader.front()});
1054   EXPECT_CALL(mock_obu_sequencer,
1055               PushSerializedDescriptorObus(_, _, _, _, _,
1056                                            MakeConstSpan(descriptor_obus)));
1057 
1058   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1059                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
1060                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
1061                   kArbitraryObuAfterIaSequenceHeader),
1062               IsOk());
1063 }
1064 
TEST(PushTemporalUnit,ForwardsPropertiesToPushAllTemporalUnits)1065 TEST(PushTemporalUnit, ForwardsPropertiesToPushAllTemporalUnits) {
1066   const IASequenceHeaderObu kIaSequenceHeader(
1067       ObuHeader(), IASequenceHeaderObu::kIaCode,
1068       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1069   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1070   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1071   std::list<MixPresentationObu> mix_presentation_obus;
1072   std::list<AudioFrameWithData> audio_frames;
1073   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1074   const std::list<ArbitraryObu> kNoArbitraryObus;
1075   InitializeOneFrameIaSequenceWithMixPresentation(
1076       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1077   audio_frames.front().obu.header_.num_samples_to_trim_at_start = 2;
1078   audio_frames.front().obu.header_.num_samples_to_trim_at_end = 1;
1079   const auto temporal_unit = TemporalUnitView::Create(
1080       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
1081   ASSERT_THAT(temporal_unit, IsOk());
1082   // We expect eight samples per frame, less the trimmed samples.
1083   constexpr int kExpectedTimestamp = 0;
1084   constexpr int kExpectedNumSamples = 5;
1085   MockObuSequencer mock_obu_sequencer(
1086       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1087       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1088   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1089                   kIaSequenceHeader, codec_config_obus, audio_elements,
1090                   mix_presentation_obus, kNoArbitraryObus),
1091               IsOk());
1092 
1093   EXPECT_CALL(
1094       mock_obu_sequencer,
1095       PushSerializedTemporalUnit(kExpectedTimestamp, kExpectedNumSamples, _));
1096 
1097   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*temporal_unit), IsOk());
1098 }
1099 
TEST(PickAndPlace,ForwardsPropertiesToPushAllTemporalUnits)1100 TEST(PickAndPlace, ForwardsPropertiesToPushAllTemporalUnits) {
1101   const IASequenceHeaderObu kIaSequenceHeader(
1102       ObuHeader(), IASequenceHeaderObu::kIaCode,
1103       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1104   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1105   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1106   std::list<MixPresentationObu> mix_presentation_obus;
1107   std::list<AudioFrameWithData> audio_frames;
1108   InitializeOneFrameIaSequenceWithMixPresentation(
1109       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1110   audio_frames.front().obu.header_.num_samples_to_trim_at_start = 2;
1111   audio_frames.front().obu.header_.num_samples_to_trim_at_end = 1;
1112   // We expect eight samples per frame, less the trimmed samples.
1113   constexpr int kExpectedTimestamp = 0;
1114   constexpr int kExpectedNumSamples = 5;
1115   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1116   const std::list<ArbitraryObu> kNoArbitraryObus;
1117   MockObuSequencer mock_obu_sequencer(
1118       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1119       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1120 
1121   EXPECT_CALL(
1122       mock_obu_sequencer,
1123       PushSerializedTemporalUnit(kExpectedTimestamp, kExpectedNumSamples, _));
1124 
1125   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1126                   kIaSequenceHeader, codec_config_obus, audio_elements,
1127                   mix_presentation_obus, audio_frames, kNoParameterBlocks,
1128                   kNoArbitraryObus),
1129               IsOk());
1130 }
1131 
TEST(PickAndPlace,OrdersTemporalUnitsByTimestamp)1132 TEST(PickAndPlace, OrdersTemporalUnitsByTimestamp) {
1133   const IASequenceHeaderObu kIaSequenceHeader(
1134       ObuHeader(), IASequenceHeaderObu::kIaCode,
1135       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1136   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1137   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1138   std::list<MixPresentationObu> mix_presentation_obus;
1139   std::list<AudioFrameWithData> two_audio_frames;
1140   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1141   const std::list<ArbitraryObu> kNoArbitraryObus;
1142   InitializeOneFrameIaSequenceWithMixPresentation(
1143       codec_config_obus, audio_elements, mix_presentation_obus,
1144       two_audio_frames);
1145   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
1146       kFirstAudioElementId, kFirstSubstreamId, kSecondTimestamp,
1147       kThirdTimestamp, audio_elements, two_audio_frames);
1148   // Ok, it is strange, to have audio frames in the wrong order. But the
1149   // sequencer handles this and arranges as per the timestamp.
1150   std::swap(two_audio_frames.front(), two_audio_frames.back());
1151   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1152                                       kDoNotIncludeTemporalDelimiters,
1153                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1154 
1155   // The cumulative number of samples to trim at the start of the IA Sequence
1156   // for the initial audio frane(s).
1157   EXPECT_CALL(mock_obu_sequencer,
1158               PushSerializedTemporalUnit(kFirstTimestamp, _, _));
1159   EXPECT_CALL(mock_obu_sequencer,
1160               PushSerializedTemporalUnit(kSecondTimestamp, _, _));
1161 
1162   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1163                   kIaSequenceHeader, codec_config_obus, audio_elements,
1164                   mix_presentation_obus, two_audio_frames, kNoParameterBlocks,
1165                   kNoArbitraryObus),
1166               IsOk());
1167 }
1168 
TEST(PushTemporalUnit,ForwardsNumUntrimmedSamplesToPushSerializedTemporalUnitWhenConfigured)1169 TEST(PushTemporalUnit,
1170      ForwardsNumUntrimmedSamplesToPushSerializedTemporalUnitWhenConfigured) {
1171   const IASequenceHeaderObu kIaSequenceHeader(
1172       ObuHeader(), IASequenceHeaderObu::kIaCode,
1173       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1174   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1175   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1176   std::list<MixPresentationObu> mix_presentation_obus;
1177   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1178   const std::list<ArbitraryObu> kNoArbitraryObus;
1179   std::list<AudioFrameWithData> first_audio_frame;
1180   InitializeOneFrameIaSequenceWithMixPresentation(
1181       codec_config_obus, audio_elements, mix_presentation_obus,
1182       first_audio_frame);
1183   first_audio_frame.back().obu.header_.num_samples_to_trim_at_start = 8;
1184   const auto first_temporal_unit = TemporalUnitView::Create(
1185       kNoParameterBlocks, first_audio_frame, kNoArbitraryObus);
1186   ASSERT_THAT(first_temporal_unit, IsOk());
1187   std::list<AudioFrameWithData> second_audio_frame;
1188   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
1189       kFirstAudioElementId, kFirstSubstreamId, kSecondTimestamp,
1190       kThirdTimestamp, audio_elements, second_audio_frame);
1191   second_audio_frame.back().obu.header_.num_samples_to_trim_at_start = 3;
1192   const auto second_temporal_unit = TemporalUnitView::Create(
1193       kNoParameterBlocks, second_audio_frame, kNoArbitraryObus);
1194   ASSERT_THAT(second_temporal_unit, IsOk());
1195   // The first frame is fully trimmed. The second frame is partially trimmed.
1196   constexpr std::optional<int64_t> kExpectedFirstUntrimmedTimestamp = 11;
1197   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1198                                       kDoNotIncludeTemporalDelimiters,
1199                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1200   // Neither the initial descriptors, nor the first temporal unit have enough
1201   // information to determine the first untrimmed timestamp.
1202   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1203                   kIaSequenceHeader, codec_config_obus, audio_elements,
1204                   mix_presentation_obus, kNoArbitraryObus),
1205               IsOk());
1206   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*first_temporal_unit),
1207               IsOk());
1208 
1209   // But by the second temporal unit, we can see the cumulative number of
1210   // samples to trim at the start for this IA Sequence.
1211   EXPECT_CALL(mock_obu_sequencer,
1212               PushSerializedDescriptorObus(
1213                   _, _, _, kExpectedFirstUntrimmedTimestamp, _, _));
1214   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*second_temporal_unit),
1215               IsOk());
1216 }
1217 
TEST(PickAndPlace,ForwardsNumUntrimmedSamplesToPushAllTemporalUnitsWhenConfigured)1218 TEST(PickAndPlace,
1219      ForwardsNumUntrimmedSamplesToPushAllTemporalUnitsWhenConfigured) {
1220   const IASequenceHeaderObu kIaSequenceHeader(
1221       ObuHeader(), IASequenceHeaderObu::kIaCode,
1222       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1223   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1224   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1225   std::list<MixPresentationObu> mix_presentation_obus;
1226   std::list<AudioFrameWithData> audio_frames;
1227   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1228   const std::list<ArbitraryObu> kNoArbitraryObus;
1229   InitializeOneFrameIaSequenceWithMixPresentation(
1230       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1231   audio_frames.back().obu.header_.num_samples_to_trim_at_start = 8;
1232   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
1233       kFirstAudioElementId, kFirstSubstreamId, kSecondTimestamp,
1234       kThirdTimestamp, audio_elements, audio_frames);
1235   audio_frames.back().obu.header_.num_samples_to_trim_at_start = 3;
1236   // The first frame is fully trimmed. The second frame is partially trimmed.
1237   constexpr std::optional<int64_t> kExpectedFirstUntrimmedTimestamp = 11;
1238   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1239                                       kDoNotIncludeTemporalDelimiters,
1240                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1241 
1242   // The cumulative number of samples to trim at the start of the IA Sequence
1243   // for the initial audio frane(s).
1244   EXPECT_CALL(mock_obu_sequencer,
1245               PushSerializedDescriptorObus(
1246                   _, _, _, kExpectedFirstUntrimmedTimestamp, _, _));
1247 
1248   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1249                   kIaSequenceHeader, codec_config_obus, audio_elements,
1250                   mix_presentation_obus, audio_frames, kNoParameterBlocks,
1251                   kNoArbitraryObus),
1252               IsOk());
1253 }
1254 
TEST(PushDescriptorObus,ReturnsErrorWhenResamplingWouldBeRequired)1255 TEST(PushDescriptorObus, ReturnsErrorWhenResamplingWouldBeRequired) {
1256   const IASequenceHeaderObu kIaSequenceHeader(
1257       ObuHeader(), IASequenceHeaderObu::kIaCode,
1258       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1259   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1260   // Theoretically, a future profile may support multiple codec config OBUs with
1261   // different sample rates. The underlying code is written to only support IAMF
1262   // v1.1.0 profiles, which all only support a single codec config OBU.
1263   constexpr uint32_t kCodecConfigId = 1;
1264   constexpr uint32_t kSecondCodecConfigId = 2;
1265   constexpr uint32_t kSampleRate = 48000;
1266   constexpr uint32_t kSecondSampleRate = 44100;
1267   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
1268                                         codec_config_obus);
1269   AddLpcmCodecConfigWithIdAndSampleRate(kSecondCodecConfigId, kSecondSampleRate,
1270                                         codec_config_obus);
1271   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1272   const std::list<MixPresentationObu> kNoMixPresentationObus;
1273   const std::list<ArbitraryObu> kNoArbitraryObus;
1274   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1275                                       kDoNotIncludeTemporalDelimiters,
1276                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1277 
1278   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1279                   kIaSequenceHeader, codec_config_obus, kNoAudioElements,
1280                   kNoMixPresentationObus, kNoArbitraryObus),
1281               Not(IsOk()));
1282 }
1283 
TEST(PickAndPlace,ReturnsErrorWhenResamplingWouldBeRequired)1284 TEST(PickAndPlace, ReturnsErrorWhenResamplingWouldBeRequired) {
1285   const IASequenceHeaderObu kIaSequenceHeader(
1286       ObuHeader(), IASequenceHeaderObu::kIaCode,
1287       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1288   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1289   // Theoretically, a future profile may support multiple codec config OBUs with
1290   // different sample rates. The underlying code is written to only support IAMF
1291   // v1.1.0 profiles, which all only support a single codec config OBU.
1292   constexpr uint32_t kCodecConfigId = 1;
1293   constexpr uint32_t kSecondCodecConfigId = 2;
1294   constexpr uint32_t kSampleRate = 48000;
1295   constexpr uint32_t kSecondSampleRate = 44100;
1296   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
1297                                         codec_config_obus);
1298   AddLpcmCodecConfigWithIdAndSampleRate(kSecondCodecConfigId, kSecondSampleRate,
1299                                         codec_config_obus);
1300   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1301   const std::list<MixPresentationObu> kNoMixPresentationObus;
1302   const std::list<AudioFrameWithData> kNoAudioFrames;
1303   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1304   const std::list<ArbitraryObu> kNoArbitraryObus;
1305   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1306                                       kDoNotIncludeTemporalDelimiters,
1307                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1308 
1309   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1310                   kIaSequenceHeader, codec_config_obus, kNoAudioElements,
1311                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
1312                   kNoArbitraryObus),
1313               Not(IsOk()));
1314 }
1315 
TEST(PushTemporalUnit,ReturnsErrorWhenSamplesAreTrimmedFromStartAfterFirstUntrimmedSample)1316 TEST(PushTemporalUnit,
1317      ReturnsErrorWhenSamplesAreTrimmedFromStartAfterFirstUntrimmedSample) {
1318   const IASequenceHeaderObu kIaSequenceHeader(
1319       ObuHeader(), IASequenceHeaderObu::kIaCode,
1320       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1321   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1322   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1323   std::list<MixPresentationObu> mix_presentation_obus;
1324   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1325   const std::list<ArbitraryObu> kNoArbitraryObus;
1326   std::list<AudioFrameWithData> first_audio_frame;
1327   InitializeOneFrameIaSequenceWithMixPresentation(
1328       codec_config_obus, audio_elements, mix_presentation_obus,
1329       first_audio_frame);
1330   first_audio_frame.back().obu.header_.num_samples_to_trim_at_start = 0;
1331   const auto first_temporal_unit = TemporalUnitView::Create(
1332       kNoParameterBlocks, first_audio_frame, kNoArbitraryObus);
1333   ASSERT_THAT(first_temporal_unit, IsOk());
1334   // Corrupt the data by adding a second frame with samples trimmed from the
1335   // start, after the first frame had no trimmed samples.
1336   std::list<AudioFrameWithData> second_audio_frame;
1337   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
1338       kFirstAudioElementId, kFirstSubstreamId, kSecondTimestamp,
1339       kThirdTimestamp, audio_elements, second_audio_frame);
1340   second_audio_frame.back().obu.header_.num_samples_to_trim_at_start = 1;
1341   const auto second_temporal_unit = TemporalUnitView::Create(
1342       kNoParameterBlocks, second_audio_frame, kNoArbitraryObus);
1343   ASSERT_THAT(second_temporal_unit, IsOk());
1344   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1345                                       kDoNotIncludeTemporalDelimiters,
1346                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1347   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1348                   kIaSequenceHeader, codec_config_obus, audio_elements,
1349                   mix_presentation_obus, kNoArbitraryObus),
1350               IsOk());
1351   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*first_temporal_unit),
1352               IsOk());
1353 
1354   // The second temporal unit is corrupt, because it has samples trimmed from
1355   // the start after the first temporal unit had no trimmed samples.
1356   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*second_temporal_unit),
1357               Not(IsOk()));
1358 }
1359 
TEST(PickAndPlace,ReturnsErrorWhenSamplesAreTrimmedFromStartAfterFirstUntrimmedSample)1360 TEST(PickAndPlace,
1361      ReturnsErrorWhenSamplesAreTrimmedFromStartAfterFirstUntrimmedSample) {
1362   const IASequenceHeaderObu kIaSequenceHeader(
1363       ObuHeader(), IASequenceHeaderObu::kIaCode,
1364       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1365   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1366   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1367   std::list<MixPresentationObu> mix_presentation_obus;
1368   std::list<AudioFrameWithData> audio_frames;
1369   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1370   const std::list<ArbitraryObu> kNoArbitraryObus;
1371   InitializeOneFrameIaSequenceWithMixPresentation(
1372       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1373   audio_frames.back().obu.header_.num_samples_to_trim_at_start = 0;
1374   // Corrupt the data by adding a second frame with samples trimmed from the
1375   // start, after the first frame had no trimmed samples.
1376   AddEmptyAudioFrameWithAudioElementIdSubstreamIdAndTimestamps(
1377       kFirstAudioElementId, kFirstSubstreamId, kSecondTimestamp,
1378       kThirdTimestamp, audio_elements, audio_frames);
1379   audio_frames.back().obu.header_.num_samples_to_trim_at_start = 1;
1380   MockObuSequencer mock_obu_sequencer(*LebGenerator::Create(),
1381                                       kDoNotIncludeTemporalDelimiters,
1382                                       kDelayDescriptorsUntilTrimAtStartIsKnown);
1383 
1384   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1385                   kIaSequenceHeader, codec_config_obus, audio_elements,
1386                   mix_presentation_obus, audio_frames, kNoParameterBlocks,
1387                   kNoArbitraryObus),
1388               Not(IsOk()));
1389 }
1390 
TEST(PushTemporalUnit,ForwardsObusToPushSerializedTemporalUnit)1391 TEST(PushTemporalUnit, ForwardsObusToPushSerializedTemporalUnit) {
1392   const IASequenceHeaderObu kIaSequenceHeader(
1393       ObuHeader(), IASequenceHeaderObu::kIaCode,
1394       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1395   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1396   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1397   std::list<MixPresentationObu> mix_presentation_obus;
1398   std::list<AudioFrameWithData> audio_frames;
1399   DemixingParamDefinition param_definition =
1400       CreateDemixingParamDefinition(kFirstDemixingParameterId);
1401   std::list<ParameterBlockWithData> parameter_blocks;
1402   InitializeOneParameterBlockAndOneAudioFrame(
1403       param_definition, parameter_blocks, audio_frames, codec_config_obus,
1404       audio_elements);
1405   const std::list<ArbitraryObu> kNoArbitraryObus;
1406   const auto temporal_unit = TemporalUnitView::Create(
1407       parameter_blocks, audio_frames, kNoArbitraryObus);
1408   ASSERT_THAT(temporal_unit, IsOk());
1409   MockObuSequencer mock_obu_sequencer(
1410       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1411       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1412   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1413                   kIaSequenceHeader, codec_config_obus, audio_elements,
1414                   mix_presentation_obus, kNoArbitraryObus),
1415               IsOk());
1416 
1417   // The spec prescribes an order among different types of OBUs.
1418   const std::vector<uint8_t> serialized_temporal_unit =
1419       SerializeObusExpectOk(std::list<const ObuBase*>{
1420           parameter_blocks.front().obu.get(), &audio_frames.front().obu});
1421   EXPECT_CALL(mock_obu_sequencer,
1422               PushSerializedTemporalUnit(
1423                   _, _, MakeConstSpan(serialized_temporal_unit)));
1424 
1425   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*temporal_unit), IsOk());
1426 }
1427 
TEST(PickAndPlace,ForwardsObusToPushSerializedTemporalUnit)1428 TEST(PickAndPlace, ForwardsObusToPushSerializedTemporalUnit) {
1429   const IASequenceHeaderObu kIaSequenceHeader(
1430       ObuHeader(), IASequenceHeaderObu::kIaCode,
1431       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1432   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1433   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1434   std::list<MixPresentationObu> mix_presentation_obus;
1435   std::list<AudioFrameWithData> audio_frames;
1436   DemixingParamDefinition param_definition =
1437       CreateDemixingParamDefinition(kFirstDemixingParameterId);
1438   std::list<ParameterBlockWithData> parameter_blocks;
1439   InitializeOneParameterBlockAndOneAudioFrame(
1440       param_definition, parameter_blocks, audio_frames, codec_config_obus,
1441       audio_elements);
1442   const std::list<ArbitraryObu> kNoArbitraryObus;
1443   MockObuSequencer mock_obu_sequencer(
1444       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1445       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1446 
1447   // The spec prescribes an order among different types of OBUs.
1448   const std::vector<uint8_t> serialized_temporal_unit =
1449       SerializeObusExpectOk(std::list<const ObuBase*>{
1450           parameter_blocks.front().obu.get(), &audio_frames.front().obu});
1451   EXPECT_CALL(mock_obu_sequencer,
1452               PushSerializedTemporalUnit(
1453                   _, _, MakeConstSpan(serialized_temporal_unit)));
1454 
1455   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1456                   kIaSequenceHeader, codec_config_obus, audio_elements,
1457                   mix_presentation_obus, audio_frames, parameter_blocks,
1458                   kNoArbitraryObus),
1459               IsOk());
1460 }
1461 
TEST(PushTemporalUnit,ForwardsArbitraryObusToPushSerializedTemporalUnit)1462 TEST(PushTemporalUnit, ForwardsArbitraryObusToPushSerializedTemporalUnit) {
1463   const IASequenceHeaderObu kIaSequenceHeader(
1464       ObuHeader(), IASequenceHeaderObu::kIaCode,
1465       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1466   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1467   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1468   std::list<MixPresentationObu> mix_presentation_obus;
1469   std::list<AudioFrameWithData> audio_frames;
1470   InitializeOneFrameIaSequenceWithMixPresentation(
1471       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1472   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1473   const std::list<ArbitraryObu> kArbitraryObuBeforeFirstAudioFrame(
1474       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
1475                     ArbitraryObu::kInsertionHookAfterAudioFramesAtTick,
1476                     kFirstTimestamp)});
1477   const auto first_temporal_unit = TemporalUnitView::Create(
1478       kNoParameterBlocks, audio_frames, kArbitraryObuBeforeFirstAudioFrame);
1479   ASSERT_THAT(first_temporal_unit, IsOk());
1480   MockObuSequencer mock_obu_sequencer(
1481       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1482       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1483   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1484                   kIaSequenceHeader, codec_config_obus, audio_elements,
1485                   mix_presentation_obus, kArbitraryObuBeforeFirstAudioFrame),
1486               IsOk());
1487 
1488   // Custom arbitrary OBUs can be placed according to their hook.
1489   const std::vector<uint8_t> serialized_audio_frame = SerializeObusExpectOk(
1490       std::list<const ObuBase*>{&audio_frames.front().obu,
1491                                 &kArbitraryObuBeforeFirstAudioFrame.front()});
1492   EXPECT_CALL(
1493       mock_obu_sequencer,
1494       PushSerializedTemporalUnit(_, _, MakeConstSpan(serialized_audio_frame)));
1495 
1496   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*first_temporal_unit),
1497               IsOk());
1498 }
1499 
TEST(PickAndPlace,ForwardsArbitraryObusToPushSerializedTemporalUnit)1500 TEST(PickAndPlace, ForwardsArbitraryObusToPushSerializedTemporalUnit) {
1501   const IASequenceHeaderObu kIaSequenceHeader(
1502       ObuHeader(), IASequenceHeaderObu::kIaCode,
1503       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1504   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1505   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1506   std::list<MixPresentationObu> mix_presentation_obus;
1507   std::list<AudioFrameWithData> audio_frames;
1508   InitializeOneFrameIaSequenceWithMixPresentation(
1509       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1510   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1511   const std::list<ArbitraryObu> kArbitraryObuBeforeFirstAudioFrame(
1512       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
1513                     ArbitraryObu::kInsertionHookAfterAudioFramesAtTick,
1514                     kFirstTimestamp)});
1515   MockObuSequencer mock_obu_sequencer(
1516       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1517       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1518 
1519   // Custom arbitrary OBUs can be placed according to their hook.
1520   const std::vector<uint8_t> serialized_audio_frame = SerializeObusExpectOk(
1521       std::list<const ObuBase*>{&audio_frames.front().obu,
1522                                 &kArbitraryObuBeforeFirstAudioFrame.front()});
1523   EXPECT_CALL(
1524       mock_obu_sequencer,
1525       PushSerializedTemporalUnit(_, _, MakeConstSpan(serialized_audio_frame)));
1526 
1527   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1528                   kIaSequenceHeader, codec_config_obus, audio_elements,
1529                   mix_presentation_obus, audio_frames, kNoParameterBlocks,
1530                   kArbitraryObuBeforeFirstAudioFrame),
1531               IsOk());
1532 }
1533 
TEST(Close,CallsCloseDerived)1534 TEST(Close, CallsCloseDerived) {
1535   MockObuSequencer mock_obu_sequencer(
1536       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1537       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1538 
1539   // `CloseDerived` is called when done, which allows concrete implementation to
1540   // finalize and optionally close their output streams.
1541   EXPECT_CALL(mock_obu_sequencer, CloseDerived());
1542 
1543   EXPECT_THAT(mock_obu_sequencer.Close(), IsOk());
1544 }
1545 
TEST(Close,FailsWhenCalledTwice)1546 TEST(Close, FailsWhenCalledTwice) {
1547   MockObuSequencer mock_obu_sequencer(
1548       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1549       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1550   EXPECT_THAT(mock_obu_sequencer.Close(), IsOk());
1551 
1552   EXPECT_THAT(mock_obu_sequencer.Close(), Not(IsOk()));
1553 }
1554 
TEST(PickAndPlace,CallsCloseDerivedWhenDone)1555 TEST(PickAndPlace, CallsCloseDerivedWhenDone) {
1556   const IASequenceHeaderObu kIaSequenceHeader(
1557       ObuHeader(), IASequenceHeaderObu::kIaCode,
1558       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1559   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1560   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1561   const std::list<MixPresentationObu> kNoMixPresentationObus;
1562   const std::list<AudioFrameWithData> kNoAudioFrames;
1563   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1564   const std::list<ArbitraryObu> kArbitraryObuAfterIaSequenceHeader(
1565       {ArbitraryObu(kObuIaReserved25, ObuHeader(), {},
1566                     ArbitraryObu::kInsertionHookAfterIaSequenceHeader)});
1567   MockObuSequencer mock_obu_sequencer(
1568       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1569       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1570 
1571   // `CloseDerived` is called when done, which allows concrete implementation to
1572   // finalize and optionally close their output streams.
1573   EXPECT_CALL(mock_obu_sequencer, CloseDerived());
1574 
1575   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1576                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
1577                   kNoMixPresentationObus, kNoAudioFrames, kNoParameterBlocks,
1578                   kArbitraryObuAfterIaSequenceHeader),
1579               IsOk());
1580 }
1581 
TEST(Abort,CallsAbortDerived)1582 TEST(Abort, CallsAbortDerived) {
1583   MockObuSequencer mock_obu_sequencer(
1584       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1585       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1586 
1587   // `CloseDerived` is called when done, which allows concrete implementation to
1588   // finalize and optionally close their output streams.
1589   EXPECT_CALL(mock_obu_sequencer, AbortDerived());
1590 
1591   mock_obu_sequencer.Abort();
1592 }
1593 
TEST(PushDescriptorObus,CallsAbortDerivedWhenPushDescriptorObusFails)1594 TEST(PushDescriptorObus, CallsAbortDerivedWhenPushDescriptorObusFails) {
1595   const IASequenceHeaderObu kIaSequenceHeader(
1596       ObuHeader(), IASequenceHeaderObu::kIaCode,
1597       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1598   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1599   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1600   std::list<MixPresentationObu> mix_presentation_obus;
1601   InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
1602       codec_config_obus, audio_elements, mix_presentation_obus);
1603   const std::list<ArbitraryObu> kNoArbitraryObus;
1604   MockObuSequencer mock_obu_sequencer(
1605       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1606       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1607 
1608   // If `PushSerializedDescriptorObus` fails, `Abort` is called. This allows
1609   // concrete implementation to clean up and remove the file in one place.
1610   EXPECT_CALL(mock_obu_sequencer,
1611               PushSerializedDescriptorObus(_, _, _, _, _, _))
1612       .WillOnce(Return(absl::InternalError("")));
1613   EXPECT_CALL(mock_obu_sequencer, AbortDerived()).Times(1);
1614 
1615   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1616                   kIaSequenceHeader, codec_config_obus, audio_elements,
1617                   mix_presentation_obus, kNoArbitraryObus),
1618               Not(IsOk()));
1619 }
1620 
TEST(PickAndPlace,CallsAbortDerivedWhenPushDescriptorObusFails)1621 TEST(PickAndPlace, CallsAbortDerivedWhenPushDescriptorObusFails) {
1622   const IASequenceHeaderObu kIaSequenceHeader(
1623       ObuHeader(), IASequenceHeaderObu::kIaCode,
1624       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1625   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1626   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1627   std::list<MixPresentationObu> mix_presentation_obus;
1628   InitializeDescriptorObusForTwoMonoAmbisonicsAudioElement(
1629       codec_config_obus, audio_elements, mix_presentation_obus);
1630   const std::list<AudioFrameWithData> kNoAudioFrames;
1631   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1632   const std::list<ArbitraryObu> kNoArbitraryObus;
1633   MockObuSequencer mock_obu_sequencer(
1634       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1635       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1636 
1637   // If `PushSerializedDescriptorObus` fails, `Abort` is called. This allows
1638   // concrete implementation to clean up and remove the file in one place.
1639   EXPECT_CALL(mock_obu_sequencer,
1640               PushSerializedDescriptorObus(_, _, _, _, _, _))
1641       .WillOnce(Return(absl::InternalError("")));
1642   EXPECT_CALL(mock_obu_sequencer, AbortDerived()).Times(1);
1643 
1644   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1645                   kIaSequenceHeader, codec_config_obus, audio_elements,
1646                   mix_presentation_obus, kNoAudioFrames, kNoParameterBlocks,
1647                   kNoArbitraryObus),
1648               Not(IsOk()));
1649 }
1650 
TEST(PushTemporalUnit,CallsAbortDerivedWhenPushAllTemporalUnitsFails)1651 TEST(PushTemporalUnit, CallsAbortDerivedWhenPushAllTemporalUnitsFails) {
1652   const IASequenceHeaderObu kIaSequenceHeader(
1653       ObuHeader(), IASequenceHeaderObu::kIaCode,
1654       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1655   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1656   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1657   std::list<MixPresentationObu> mix_presentation_obus;
1658   std::list<AudioFrameWithData> audio_frames;
1659   InitializeOneFrameIaSequenceWithMixPresentation(
1660       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1661   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1662   const std::list<ArbitraryObu> kNoArbitraryObus;
1663   const auto temporal_unit = TemporalUnitView::Create(
1664       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
1665   ASSERT_THAT(temporal_unit, IsOk());
1666   MockObuSequencer mock_obu_sequencer(
1667       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1668       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1669   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1670                   kIaSequenceHeader, codec_config_obus, audio_elements,
1671                   mix_presentation_obus, kNoArbitraryObus),
1672               IsOk());
1673 
1674   // If `PushSerializedTemporalUnit` fails, `AbortDerived` is called. This
1675   // allows concrete implementation to clean up and remove the file in one
1676   // place.
1677   EXPECT_CALL(mock_obu_sequencer, PushSerializedTemporalUnit(_, _, _))
1678       .WillOnce(Return(absl::InternalError("")));
1679   EXPECT_CALL(mock_obu_sequencer, AbortDerived()).Times(1);
1680 
1681   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*temporal_unit), Not(IsOk()));
1682 }
1683 
TEST(PickAndPlace,CallsAbortDerivedWhenPushAllTemporalUnitsFails)1684 TEST(PickAndPlace, CallsAbortDerivedWhenPushAllTemporalUnitsFails) {
1685   const IASequenceHeaderObu kIaSequenceHeader(
1686       ObuHeader(), IASequenceHeaderObu::kIaCode,
1687       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1688   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1689   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1690   std::list<MixPresentationObu> mix_presentation_obus;
1691   std::list<AudioFrameWithData> audio_frames;
1692   InitializeOneFrameIaSequenceWithMixPresentation(
1693       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1694   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1695   const std::list<ArbitraryObu> kNoArbitraryObus;
1696   MockObuSequencer mock_obu_sequencer(
1697       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1698       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1699 
1700   // If `PushSerializedTemporalUnit` fails, `AbortDerived` is called. This
1701   // allows concrete implementation to clean up and remove the file in one
1702   // place.
1703   EXPECT_CALL(mock_obu_sequencer, PushSerializedTemporalUnit(_, _, _))
1704       .WillOnce(Return(absl::InternalError("")));
1705   EXPECT_CALL(mock_obu_sequencer, AbortDerived()).Times(1);
1706 
1707   EXPECT_THAT(mock_obu_sequencer.PickAndPlace(
1708                   kIaSequenceHeader, codec_config_obus, audio_elements,
1709                   mix_presentation_obus, audio_frames, kNoParameterBlocks,
1710                   kNoArbitraryObus),
1711               Not(IsOk()));
1712 }
1713 
TEST(PushTemporalUnit,FailsWhenBeforePushDescriptorObus)1714 TEST(PushTemporalUnit, FailsWhenBeforePushDescriptorObus) {
1715   const IASequenceHeaderObu kIaSequenceHeader(
1716       ObuHeader(), IASequenceHeaderObu::kIaCode,
1717       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1718   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1719   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1720   std::list<MixPresentationObu> mix_presentation_obus;
1721   std::list<AudioFrameWithData> audio_frames;
1722   InitializeOneFrameIaSequenceWithMixPresentation(
1723       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1724   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1725   const std::list<ArbitraryObu> kNoArbitraryObus;
1726   const auto temporal_unit = TemporalUnitView::Create(
1727       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
1728   ASSERT_THAT(temporal_unit, IsOk());
1729   MockObuSequencer mock_obu_sequencer(
1730       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1731       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1732   // Omitted call to `PushDescriptorObus`. We can't accept temporal units yet.
1733 
1734   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*temporal_unit), Not(IsOk()));
1735 }
1736 
TEST(PushTemporalUnit,FailsWhenCalledAfterClose)1737 TEST(PushTemporalUnit, FailsWhenCalledAfterClose) {
1738   const IASequenceHeaderObu kIaSequenceHeader(
1739       ObuHeader(), IASequenceHeaderObu::kIaCode,
1740       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1741   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1742   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1743   std::list<MixPresentationObu> mix_presentation_obus;
1744   std::list<AudioFrameWithData> audio_frames;
1745   InitializeOneFrameIaSequenceWithMixPresentation(
1746       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1747   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1748   const std::list<ArbitraryObu> kNoArbitraryObus;
1749   const auto temporal_unit = TemporalUnitView::Create(
1750       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
1751   ASSERT_THAT(temporal_unit, IsOk());
1752   MockObuSequencer mock_obu_sequencer(
1753       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1754       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1755   EXPECT_THAT(mock_obu_sequencer.Close(), IsOk());
1756 
1757   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*temporal_unit), Not(IsOk()));
1758 }
1759 
TEST(PushTemporalUnit,FailsWhenCalledAfterAbort)1760 TEST(PushTemporalUnit, FailsWhenCalledAfterAbort) {
1761   const IASequenceHeaderObu kIaSequenceHeader(
1762       ObuHeader(), IASequenceHeaderObu::kIaCode,
1763       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1764   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_config_obus;
1765   absl::flat_hash_map<uint32_t, AudioElementWithData> audio_elements;
1766   std::list<MixPresentationObu> mix_presentation_obus;
1767   std::list<AudioFrameWithData> audio_frames;
1768   InitializeOneFrameIaSequenceWithMixPresentation(
1769       codec_config_obus, audio_elements, mix_presentation_obus, audio_frames);
1770   const std::list<ParameterBlockWithData> kNoParameterBlocks;
1771   const std::list<ArbitraryObu> kNoArbitraryObus;
1772   const auto temporal_unit = TemporalUnitView::Create(
1773       kNoParameterBlocks, audio_frames, kNoArbitraryObus);
1774   ASSERT_THAT(temporal_unit, IsOk());
1775   MockObuSequencer mock_obu_sequencer(
1776       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1777       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1778   mock_obu_sequencer.Abort();
1779 
1780   EXPECT_THAT(mock_obu_sequencer.PushTemporalUnit(*temporal_unit), Not(IsOk()));
1781 }
1782 
TEST(UpdateDescriptorObusAndClose,ForwardsDescriptorObusToPushFinalizedDescriptorObus)1783 TEST(UpdateDescriptorObusAndClose,
1784      ForwardsDescriptorObusToPushFinalizedDescriptorObus) {
1785   const IASequenceHeaderObu kOriginalIaSequenceHeader(
1786       ObuHeader(), IASequenceHeaderObu::kIaCode,
1787       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1788   const IASequenceHeaderObu kUpdatedIaSequenceHeader(
1789       ObuHeader(), IASequenceHeaderObu::kIaCode,
1790       ProfileVersion::kIamfBaseProfile, ProfileVersion::kIamfBaseProfile);
1791   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1792   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1793   const std::list<MixPresentationObu> kNoMixPresentationObus;
1794   const std::list<ArbitraryObu> kNoArbitraryObus;
1795   MockObuSequencer mock_obu_sequencer(
1796       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1797       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1798   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1799                   kOriginalIaSequenceHeader, kNoCodecConfigObus,
1800                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1801               IsOk());
1802   const auto expected_finalized_descriptor_obus = SerializeObusExpectOk(
1803       std::list<const ObuBase*>{&kUpdatedIaSequenceHeader});
1804 
1805   // Several properties should match values derived from the descriptor
1806   // OBUs.
1807   EXPECT_CALL(mock_obu_sequencer, PushFinalizedDescriptorObus(MakeConstSpan(
1808                                       expected_finalized_descriptor_obus)));
1809 
1810   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1811                   kUpdatedIaSequenceHeader, kNoCodecConfigObus,
1812                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1813               IsOk());
1814 }
1815 
TEST(UpdateDescriptorObusAndClose,FailsBeforePushDescriptorObus)1816 TEST(UpdateDescriptorObusAndClose, FailsBeforePushDescriptorObus) {
1817   const IASequenceHeaderObu kIaSequenceHeader(
1818       ObuHeader(), IASequenceHeaderObu::kIaCode,
1819       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1820   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1821   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1822   const std::list<MixPresentationObu> kNoMixPresentationObus;
1823   const std::list<ArbitraryObu> kNoArbitraryObus;
1824   MockObuSequencer mock_obu_sequencer(
1825       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1826       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1827 
1828   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1829                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
1830                   kNoMixPresentationObus, kNoArbitraryObus),
1831               Not(IsOk()));
1832 }
1833 
TEST(UpdateDescriptorObusAndClose,SubsequentCloseCallsFails)1834 TEST(UpdateDescriptorObusAndClose, SubsequentCloseCallsFails) {
1835   const IASequenceHeaderObu kIaSequenceHeader(
1836       ObuHeader(), IASequenceHeaderObu::kIaCode,
1837       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1838   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1839   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1840   const std::list<MixPresentationObu> kNoMixPresentationObus;
1841   const std::list<ArbitraryObu> kNoArbitraryObus;
1842   MockObuSequencer mock_obu_sequencer(
1843       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1844       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1845   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1846                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
1847                   kNoMixPresentationObus, kNoArbitraryObus),
1848               IsOk());
1849   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1850                   kIaSequenceHeader, kNoCodecConfigObus, kNoAudioElements,
1851                   kNoMixPresentationObus, kNoArbitraryObus),
1852               IsOk());
1853 
1854   EXPECT_THAT(mock_obu_sequencer.Close(), Not(IsOk()));
1855 }
1856 
TEST(UpdateDescriptorObusAndClose,CallsCloseDerived)1857 TEST(UpdateDescriptorObusAndClose, CallsCloseDerived) {
1858   const IASequenceHeaderObu kOriginalIaSequenceHeader(
1859       ObuHeader(), IASequenceHeaderObu::kIaCode,
1860       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1861   const IASequenceHeaderObu kUpdatedIaSequenceHeader(
1862       ObuHeader(), IASequenceHeaderObu::kIaCode,
1863       ProfileVersion::kIamfBaseProfile, ProfileVersion::kIamfBaseProfile);
1864   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1865   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1866   const std::list<MixPresentationObu> kNoMixPresentationObus;
1867   const std::list<ArbitraryObu> kNoArbitraryObus;
1868   MockObuSequencer mock_obu_sequencer(
1869       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1870       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1871   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1872                   kOriginalIaSequenceHeader, kNoCodecConfigObus,
1873                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1874               IsOk());
1875   EXPECT_CALL(mock_obu_sequencer, CloseDerived()).Times(1);
1876 
1877   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1878                   kUpdatedIaSequenceHeader, kNoCodecConfigObus,
1879                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1880               IsOk());
1881 }
1882 
TEST(UpdateDescriptorObusAndClose,CallsAbortDerivedWhenPushFinalizedDescriptorObusFails)1883 TEST(UpdateDescriptorObusAndClose,
1884      CallsAbortDerivedWhenPushFinalizedDescriptorObusFails) {
1885   const IASequenceHeaderObu kOriginalIaSequenceHeader(
1886       ObuHeader(), IASequenceHeaderObu::kIaCode,
1887       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1888   const IASequenceHeaderObu kUpdatedIaSequenceHeader(
1889       ObuHeader(), IASequenceHeaderObu::kIaCode,
1890       ProfileVersion::kIamfBaseProfile, ProfileVersion::kIamfBaseProfile);
1891   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1892   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1893   const std::list<MixPresentationObu> kNoMixPresentationObus;
1894   const std::list<ArbitraryObu> kNoArbitraryObus;
1895   MockObuSequencer mock_obu_sequencer(
1896       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1897       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1898   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1899                   kOriginalIaSequenceHeader, kNoCodecConfigObus,
1900                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1901               IsOk());
1902   ON_CALL(mock_obu_sequencer, PushFinalizedDescriptorObus(_))
1903       .WillByDefault(Return(absl::InternalError("")));
1904   EXPECT_CALL(mock_obu_sequencer, AbortDerived()).Times(1);
1905 
1906   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1907                   kUpdatedIaSequenceHeader, kNoCodecConfigObus,
1908                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1909               Not(IsOk()));
1910 }
1911 
TEST(UpdateDescriptorObusAndClose,FailsWhenSerializedSizeChanges)1912 TEST(UpdateDescriptorObusAndClose, FailsWhenSerializedSizeChanges) {
1913   const IASequenceHeaderObu kOriginalIaSequenceHeader(
1914       ObuHeader(), IASequenceHeaderObu::kIaCode,
1915       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1916   const IASequenceHeaderObu kResizedIaSequenceHeader(
1917       ObuHeader{.obu_extension_flag = true, .extension_header_size = 0},
1918       IASequenceHeaderObu::kIaCode, ProfileVersion::kIamfBaseProfile,
1919       ProfileVersion::kIamfBaseProfile);
1920   const absl::flat_hash_map<DecodedUleb128, CodecConfigObu> kNoCodecConfigObus;
1921   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1922   const std::list<MixPresentationObu> kNoMixPresentationObus;
1923   const std::list<ArbitraryObu> kNoArbitraryObus;
1924   MockObuSequencer mock_obu_sequencer(
1925       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1926       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1927   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1928                   kOriginalIaSequenceHeader, kNoCodecConfigObus,
1929                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1930               IsOk());
1931 
1932   // Derived classes may assume the descriptor OBUs are the same size, to
1933   // permit writes in place. We could lift this restriction, but it's not
1934   // clear it's worth the effort.
1935   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1936                   kResizedIaSequenceHeader, kNoCodecConfigObus,
1937                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1938               Not(IsOk()));
1939 }
1940 
TEST(UpdateDescriptorObusAndClose,FailsWhenCodecConfigPropertiesChange)1941 TEST(UpdateDescriptorObusAndClose, FailsWhenCodecConfigPropertiesChange) {
1942   const IASequenceHeaderObu kIaSequenceHeader(
1943       ObuHeader(), IASequenceHeaderObu::kIaCode,
1944       ProfileVersion::kIamfSimpleProfile, ProfileVersion::kIamfBaseProfile);
1945   absl::flat_hash_map<DecodedUleb128, CodecConfigObu>
1946       original_codec_config_obus;
1947   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, 48000,
1948                                         original_codec_config_obus);
1949   absl::flat_hash_map<DecodedUleb128, CodecConfigObu>
1950       modified_codec_config_obus;
1951   AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, 44100,
1952                                         modified_codec_config_obus);
1953   const absl::flat_hash_map<uint32_t, AudioElementWithData> kNoAudioElements;
1954   const std::list<MixPresentationObu> kNoMixPresentationObus;
1955   const std::list<ArbitraryObu> kNoArbitraryObus;
1956   MockObuSequencer mock_obu_sequencer(
1957       *LebGenerator::Create(), kDoNotIncludeTemporalDelimiters,
1958       kDoNotDelayDescriptorsUntilTrimAtStartIsKnown);
1959   EXPECT_THAT(mock_obu_sequencer.PushDescriptorObus(
1960                   kIaSequenceHeader, original_codec_config_obus,
1961                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1962               IsOk());
1963 
1964   EXPECT_THAT(mock_obu_sequencer.UpdateDescriptorObusAndClose(
1965                   kIaSequenceHeader, modified_codec_config_obus,
1966                   kNoAudioElements, kNoMixPresentationObus, kNoArbitraryObus),
1967               Not(IsOk()));
1968 }
1969 
1970 }  // namespace
1971 }  // namespace iamf_tools
1972