• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear
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/rendering_mix_presentation_finalizer.h"
13 
14 #include <array>
15 #include <cstddef>
16 #include <cstdint>
17 #include <filesystem>
18 #include <limits>
19 #include <list>
20 #include <memory>
21 #include <optional>
22 #include <string>
23 #include <utility>
24 #include <vector>
25 
26 #include "absl/container/flat_hash_map.h"
27 #include "absl/log/check.h"
28 #include "absl/status/status.h"
29 #include "absl/status/status_matchers.h"
30 #include "absl/strings/str_cat.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/types/span.h"
33 #include "gmock/gmock.h"
34 #include "gtest/gtest.h"
35 #include "iamf/cli/audio_element_with_data.h"
36 #include "iamf/cli/channel_label.h"
37 #include "iamf/cli/demixing_module.h"
38 #include "iamf/cli/loudness_calculator_base.h"
39 #include "iamf/cli/loudness_calculator_factory_base.h"
40 #include "iamf/cli/parameter_block_with_data.h"
41 #include "iamf/cli/proto/codec_config.pb.h"
42 #include "iamf/cli/proto_conversion/proto_to_obu/codec_config_generator.h"
43 #include "iamf/cli/renderer/audio_element_renderer_base.h"
44 #include "iamf/cli/renderer_factory.h"
45 #include "iamf/cli/tests/cli_test_utils.h"
46 #include "iamf/cli/user_metadata_builder/codec_config_obu_metadata_builder.h"
47 #include "iamf/cli/user_metadata_builder/iamf_input_layout.h"
48 #include "iamf/cli/wav_reader.h"
49 #include "iamf/cli/wav_writer.h"
50 #include "iamf/obu/audio_element.h"
51 #include "iamf/obu/codec_config.h"
52 #include "iamf/obu/mix_presentation.h"
53 #include "iamf/obu/types.h"
54 #include "src/google/protobuf/repeated_ptr_field.h"
55 
56 namespace iamf_tools {
57 namespace {
58 
59 using ::absl_testing::IsOk;
60 using ::absl_testing::IsOkAndHolds;
61 using ::absl_testing::StatusIs;
62 using ::testing::_;
63 using ::testing::Eq;
64 using ::testing::IsEmpty;
65 using ::testing::Not;
66 using testing::Return;
67 using enum ChannelLabel::Label;
68 
69 using absl::StatusCode::kFailedPrecondition;
70 
71 constexpr int64_t kStartTime = 0;
72 constexpr int32_t kEndTime = 10;
73 constexpr bool kValidateLoudness = true;
74 constexpr bool kDontValidateLoudness = false;
75 const std::optional<uint8_t> kNoOverrideBitDepth = std::nullopt;
76 constexpr absl::string_view kSuffixAfterMixPresentationId =
77     "_first_submix_first_layout.wav";
78 
79 constexpr uint32_t kMixPresentationId = 42;
80 constexpr uint32_t kCodecConfigId = 42;
81 constexpr uint32_t kAudioElementId = 42;
82 constexpr int kNumchannelsForMono = 1;
83 constexpr uint32_t kBitDepth = 16;
84 constexpr uint32_t kSampleRate = 48000;
85 constexpr uint32_t kCommonParameterRate = kSampleRate;
86 constexpr uint32_t kNumSamplesPerFrame = 8;
87 constexpr uint8_t kCodecConfigBitDepth = 16;
88 constexpr uint8_t kNoTrimFromEnd = 0;
89 constexpr std::array<DecodedUleb128, 1> kMonoSubstreamIds = {0};
90 constexpr std::array<DecodedUleb128, 1> kStereoSubstreamIds = {1};
91 
92 constexpr std::array<ChannelLabel::Label, 2> kStereoLabels = {kL2, kR2};
93 
94 constexpr size_t kFirstSubmixIndex = 0;
95 constexpr size_t kFirstLayoutIndex = 0;
96 
97 typedef ::google::protobuf::RepeatedPtrField<
98     iamf_tools_cli_proto::CodecConfigObuMetadata>
99     CodecConfigObuMetadatas;
100 
101 class MockRenderer : public AudioElementRendererBase {
102  public:
MockRenderer(absl::Span<const ChannelLabel::Label> ordered_labels,size_t num_output_channels)103   MockRenderer(absl::Span<const ChannelLabel::Label> ordered_labels,
104                size_t num_output_channels)
105       : AudioElementRendererBase(ordered_labels,
106                                  static_cast<size_t>(kNumSamplesPerFrame),
107                                  num_output_channels) {}
MockRenderer()108   MockRenderer() : MockRenderer({}, 0) {}
109 
110   MOCK_METHOD(
111       absl::Status, RenderSamples,
112       (absl::Span<const std::vector<InternalSampleType>> samples_to_render,
113        std::vector<InternalSampleType>& rendered_samples),
114       (override));
115 };
116 
117 class MockRendererFactory : public RendererFactoryBase {
118  public:
MockRendererFactory()119   MockRendererFactory() : RendererFactoryBase() {}
120 
121   MOCK_METHOD(std::unique_ptr<AudioElementRendererBase>,
122               CreateRendererForLayout,
123               (const std::vector<DecodedUleb128>& audio_substream_ids,
124                const SubstreamIdLabelsMap& substream_id_to_labels,
125                AudioElementObu::AudioElementType audio_element_type,
126                const AudioElementObu::AudioElementConfig& audio_element_config,
127                const RenderingConfig& rendering_config,
128                const Layout& loudness_layout, size_t num_samples_per_frame),
129               (const, override));
130 };
131 
132 /*!\brief A simple factory which always returns `nullptr`. */
133 class AlwaysNullRendererFactory : public RendererFactoryBase {
134  public:
135   /*!\brief Destructor. */
136   ~AlwaysNullRendererFactory() override = default;
137 
CreateRendererForLayout(const std::vector<DecodedUleb128> &,const SubstreamIdLabelsMap &,AudioElementObu::AudioElementType,const AudioElementObu::AudioElementConfig &,const RenderingConfig &,const Layout &,size_t) const138   std::unique_ptr<AudioElementRendererBase> CreateRendererForLayout(
139       const std::vector<DecodedUleb128>& /*audio_substream_ids*/,
140       const SubstreamIdLabelsMap& /*substream_id_to_labels*/,
141       AudioElementObu::AudioElementType /*audio_element_type*/,
142       const AudioElementObu::AudioElementConfig& /*audio_element_config*/,
143       const RenderingConfig& /*rendering_config*/,
144       const Layout& /*loudness_layout*/,
145       size_t /*num_samples_per_frame*/) const override {
146     return nullptr;
147   }
148 };
149 
150 /*!\brief A simple factory which always returns `nullptr`. */
151 class AlwaysNullLoudnessCalculatorFactory
152     : public LoudnessCalculatorFactoryBase {
153  public:
154   /*!\brief Destructor. */
155   ~AlwaysNullLoudnessCalculatorFactory() override = default;
156 
CreateLoudnessCalculator(const MixPresentationLayout &,uint32_t,int32_t,int32_t) const157   std::unique_ptr<LoudnessCalculatorBase> CreateLoudnessCalculator(
158       const MixPresentationLayout& /*layout*/,
159       uint32_t /*num_samples_per_frame*/, int32_t /*rendered_sample_rate*/,
160       int32_t /*rendered_bit_depth*/) const override {
161     return nullptr;
162   }
163 };
164 
GetFirstSubmixFirstLayoutExpectedPath()165 std::string GetFirstSubmixFirstLayoutExpectedPath() {
166   return absl::StrCat(GetAndCreateOutputDirectory(""), "_id_",
167                       kMixPresentationId, kSuffixAfterMixPresentationId);
168 }
169 
170 class FinalizerTest : public ::testing::Test {
171  public:
InitPrerequisiteObusForMonoInput(DecodedUleb128 audio_element_id)172   void InitPrerequisiteObusForMonoInput(DecodedUleb128 audio_element_id) {
173     AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
174                                           codec_configs_);
175     AddScalableAudioElementWithSubstreamIds(
176         IamfInputLayout::kMono, audio_element_id, kCodecConfigId,
177         kMonoSubstreamIds, codec_configs_, audio_elements_);
178   }
179 
InitPrerequisiteObusForStereoInput(DecodedUleb128 audio_element_id)180   void InitPrerequisiteObusForStereoInput(DecodedUleb128 audio_element_id) {
181     AddLpcmCodecConfigWithIdAndSampleRate(kCodecConfigId, kSampleRate,
182                                           codec_configs_);
183     AddScalableAudioElementWithSubstreamIds(
184         IamfInputLayout::kStereo, audio_element_id, kCodecConfigId,
185         kStereoSubstreamIds, codec_configs_, audio_elements_);
186   }
187 
AddMixPresentationObuForMonoOutput(DecodedUleb128 mix_presentation_id)188   void AddMixPresentationObuForMonoOutput(DecodedUleb128 mix_presentation_id) {
189     AddMixPresentationObuWithAudioElementIds(
190         mix_presentation_id, {kAudioElementId},
191         /*common_parameter_id=*/999, kCommonParameterRate, obus_to_finalize_);
192     obus_to_finalize_.back().sub_mixes_[0].layouts[0].loudness_layout = {
193         .layout_type = Layout::kLayoutTypeLoudspeakersSsConvention,
194         .specific_layout = LoudspeakersSsConventionLayout{
195             .sound_system =
196                 LoudspeakersSsConventionLayout::kSoundSystem12_0_1_0}};
197   }
198 
AddMixPresentationObuForStereoOutput(DecodedUleb128 mix_presentation_id)199   void AddMixPresentationObuForStereoOutput(
200       DecodedUleb128 mix_presentation_id) {
201     AddMixPresentationObuWithAudioElementIds(
202         mix_presentation_id, {kAudioElementId},
203         /*common_parameter_id=*/999, kCommonParameterRate, obus_to_finalize_);
204   }
205 
AddLabeledFrame(DecodedUleb128 audio_element_id,const LabelSamplesMap & label_to_samples,int32_t end_timestamp,uint32_t samples_to_trim_at_end=0,uint32_t samples_to_trim_at_start=0)206   void AddLabeledFrame(DecodedUleb128 audio_element_id,
207                        const LabelSamplesMap& label_to_samples,
208                        int32_t end_timestamp,
209                        uint32_t samples_to_trim_at_end = 0,
210                        uint32_t samples_to_trim_at_start = 0) {
211     IdLabeledFrameMap id_to_labeled_frame;
212     id_to_labeled_frame[audio_element_id] = {
213         .end_timestamp = end_timestamp,
214         .samples_to_trim_at_end = samples_to_trim_at_end,
215         .samples_to_trim_at_start = samples_to_trim_at_start,
216         .label_to_samples = label_to_samples};
217     ordered_labeled_frames_.push_back(id_to_labeled_frame);
218   }
219 
PrepareObusForOneSamplePassThroughMono()220   void PrepareObusForOneSamplePassThroughMono() {
221     InitPrerequisiteObusForMonoInput(kAudioElementId);
222     AddMixPresentationObuForMonoOutput(kMixPresentationId);
223     const LabelSamplesMap kLabelToSamples = {{kMono, {0, 1}}};
224     AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
225   }
226 
CreateFinalizerExpectOk()227   RenderingMixPresentationFinalizer CreateFinalizerExpectOk() {
228     auto finalizer = RenderingMixPresentationFinalizer::Create(
229         renderer_factory_.get(), loudness_calculator_factory_.get(),
230         audio_elements_, sample_processor_factory_, obus_to_finalize_);
231     EXPECT_THAT(finalizer, IsOk());
232     return *std::move(finalizer);
233   }
234 
ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout()235   void ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout() {
236     sample_processor_factory_ =
237         [output_directory = output_directory_,
238          output_wav_file_bit_depth_override =
239              output_wav_file_bit_depth_override_](
240             DecodedUleb128 mix_presentation_id, int sub_mix_index,
241             int layout_index, const Layout&, int num_channels, int sample_rate,
242             int bit_depth,
243             size_t num_samples_per_frame) -> std::unique_ptr<WavWriter> {
244       if (sub_mix_index != 0 || layout_index != 0) {
245         return nullptr;
246       }
247       // Obey the override bit depth. But if it is not set, just match the input
248       // audio.
249       const uint8_t wav_file_bit_depth =
250           output_wav_file_bit_depth_override.value_or(bit_depth);
251       const auto wav_path =
252           absl::StrCat(output_directory.string(), "_id_", mix_presentation_id,
253                        kSuffixAfterMixPresentationId);
254       return WavWriter::Create(wav_path, num_channels, sample_rate,
255                                wav_file_bit_depth, num_samples_per_frame);
256     };
257   }
258 
IterativeRenderingExpectOk(RenderingMixPresentationFinalizer & finalizer,const std::list<ParameterBlockWithData> & parameter_blocks)259   void IterativeRenderingExpectOk(
260       RenderingMixPresentationFinalizer& finalizer,
261       const std::list<ParameterBlockWithData>& parameter_blocks) {
262     int64_t start_timestamp = 0;
263     for (const auto& id_to_labeled_frame : ordered_labeled_frames_) {
264       ASSERT_TRUE(id_to_labeled_frame.contains(kAudioElementId));
265       EXPECT_THAT(finalizer.PushTemporalUnit(
266                       id_to_labeled_frame, start_timestamp,
267                       id_to_labeled_frame.at(kAudioElementId).end_timestamp,
268                       parameter_blocks),
269                   IsOk());
270     }
271 
272     EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
273     auto finalized_obus =
274         finalizer.GetFinalizedMixPresentationObus(validate_loudness_);
275     ASSERT_THAT(finalized_obus, IsOk());
276     finalized_obus_ = *std::move(finalized_obus);
277   }
278 
279  protected:
280   // Prerequisite OBUs.
281   absl::flat_hash_map<DecodedUleb128, CodecConfigObu> codec_configs_;
282   absl::flat_hash_map<DecodedUleb128, AudioElementWithData> audio_elements_;
283   std::list<MixPresentationObu> obus_to_finalize_;
284   std::list<ParameterBlockWithData> parameter_blocks_;
285 
286   // Finalizer create settings. Default to simplistic inputs that disable
287   // most features.
288   std::filesystem::path output_directory_ = GetAndCreateOutputDirectory("");
289   std::optional<uint8_t> output_wav_file_bit_depth_override_ =
290       kNoOverrideBitDepth;
291   bool validate_loudness_ = kDontValidateLoudness;
292   std::unique_ptr<RendererFactoryBase> renderer_factory_;
293   std::unique_ptr<LoudnessCalculatorFactoryBase> loudness_calculator_factory_;
294   // Custom `Finalize` arguments.
295   RenderingMixPresentationFinalizer::SampleProcessorFactory
296       sample_processor_factory_ =
297           RenderingMixPresentationFinalizer::ProduceNoSampleProcessors;
298 
299   std::vector<IdLabeledFrameMap> ordered_labeled_frames_;
300 
301   std::list<MixPresentationObu> finalized_obus_;
302 };
303 
304 // =Tests that the create function does not crash with various modes disabled.=
305 
TEST_F(FinalizerTest,CreateDoesNotCrashWithMockFactories)306 TEST_F(FinalizerTest, CreateDoesNotCrashWithMockFactories) {
307   renderer_factory_ = std::make_unique<MockRendererFactory>();
308   loudness_calculator_factory_ =
309       std::make_unique<MockLoudnessCalculatorFactory>();
310 
311   CreateFinalizerExpectOk();
312 }
313 
TEST_F(FinalizerTest,CreateDoesNotCrashWhenRendererFactoryIsNullptr)314 TEST_F(FinalizerTest, CreateDoesNotCrashWhenRendererFactoryIsNullptr) {
315   renderer_factory_ = nullptr;
316 
317   CreateFinalizerExpectOk();
318 }
319 
TEST_F(FinalizerTest,CreateDoesNotCrashWhenLoudnessCalculatorFactoryIsNullptr)320 TEST_F(FinalizerTest,
321        CreateDoesNotCrashWhenLoudnessCalculatorFactoryIsNullptr) {
322   renderer_factory_ = std::make_unique<AlwaysNullRendererFactory>();
323   loudness_calculator_factory_ = nullptr;
324 
325   CreateFinalizerExpectOk();
326 }
327 
TEST_F(FinalizerTest,CreateFailsWitMismatchingNumSamplesPerFrame)328 TEST_F(FinalizerTest, CreateFailsWitMismatchingNumSamplesPerFrame) {
329   // The first audio element references an LPCM codec config.
330   renderer_factory_ = std::make_unique<AlwaysNullRendererFactory>();
331   CodecConfigObuMetadatas metadata;
332   metadata.Add(CodecConfigObuMetadataBuilder::GetOpusCodecConfigObuMetadata(
333       kCodecConfigId, 960));
334   constexpr uint32_t kSecondCodecConfigId = kCodecConfigId + 1;
335   metadata.Add(CodecConfigObuMetadataBuilder::GetOpusCodecConfigObuMetadata(
336       kSecondCodecConfigId, 1920));
337   CodecConfigGenerator generator(metadata);
338   ASSERT_THAT(generator.Generate(codec_configs_), IsOk());
339 
340   AddScalableAudioElementWithSubstreamIds(
341       IamfInputLayout::kMono, kAudioElementId, kCodecConfigId,
342       kMonoSubstreamIds, codec_configs_, audio_elements_);
343   // The second audio element references a codec Config with a different
344   // number of samples per frame.
345   constexpr DecodedUleb128 kStereoAudioElementId = kAudioElementId + 1;
346   AddScalableAudioElementWithSubstreamIds(
347       IamfInputLayout::kStereo, kStereoAudioElementId, kSecondCodecConfigId,
348       kStereoSubstreamIds, codec_configs_, audio_elements_);
349   // Mixing these is invalid because there must be only one codec config in IAMF
350   // v1.1.0.
351   AddMixPresentationObuWithAudioElementIds(
352       kMixPresentationId, {kAudioElementId, kStereoAudioElementId},
353       /*common_parameter_id=*/999, kCommonParameterRate, obus_to_finalize_);
354 
355   EXPECT_FALSE(RenderingMixPresentationFinalizer::Create(
356                    renderer_factory_.get(), loudness_calculator_factory_.get(),
357                    audio_elements_, sample_processor_factory_,
358                    obus_to_finalize_)
359                    .ok());
360 }
361 
362 // =========== Tests that work is delegated to the renderer factory. ===========
TEST_F(FinalizerTest,ForwardsAudioElementToRenderer)363 TEST_F(FinalizerTest, ForwardsAudioElementToRenderer) {
364   InitPrerequisiteObusForStereoInput(kAudioElementId);
365   AddMixPresentationObuForStereoOutput(kMixPresentationId);
366   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
367   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
368 
369   // We expect audio-element related arguments to be forwarded from the OBUs to
370   // the renderer factory.
371   auto mock_renderer_factory = std::make_unique<MockRendererFactory>();
372   const auto& forwarded_audio_element = audio_elements_.at(kAudioElementId);
373   EXPECT_CALL(
374       *mock_renderer_factory,
375       CreateRendererForLayout(
376           forwarded_audio_element.obu.audio_substream_ids_,
377           forwarded_audio_element.substream_id_to_labels,
378           forwarded_audio_element.obu.GetAudioElementType(),
379           forwarded_audio_element.obu.config_, _, _,
380           forwarded_audio_element.codec_config->GetNumSamplesPerFrame()));
381   renderer_factory_ = std::move(mock_renderer_factory);
382 
383   auto finalizer = CreateFinalizerExpectOk();
384 }
385 
TEST_F(FinalizerTest,ForwardsRenderingConfigToRenderer)386 TEST_F(FinalizerTest, ForwardsRenderingConfigToRenderer) {
387   InitPrerequisiteObusForStereoInput(kAudioElementId);
388   AddMixPresentationObuForStereoOutput(kMixPresentationId);
389   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
390   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
391 
392   // We expect arguments to be forwarded from the OBUs to the renderer factory.
393   auto mock_renderer_factory = std::make_unique<MockRendererFactory>();
394   const auto& forwarded_sub_mix = obus_to_finalize_.front().sub_mixes_[0];
395   const auto& forwarded_rendering_config =
396       forwarded_sub_mix.audio_elements[0].rendering_config;
397   EXPECT_CALL(
398       *mock_renderer_factory,
399       CreateRendererForLayout(_, _, _, _, forwarded_rendering_config, _, _));
400   renderer_factory_ = std::move(mock_renderer_factory);
401 
402   CreateFinalizerExpectOk();
403 }
404 
TEST_F(FinalizerTest,ForwardsLayoutToRenderer)405 TEST_F(FinalizerTest, ForwardsLayoutToRenderer) {
406   InitPrerequisiteObusForStereoInput(kAudioElementId);
407   AddMixPresentationObuForStereoOutput(kMixPresentationId);
408   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
409   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
410 
411   // We expect arguments to be forwarded from the OBUs to the renderer factory.
412   auto mock_renderer_factory = std::make_unique<MockRendererFactory>();
413   const auto& forwarded_sub_mix = obus_to_finalize_.front().sub_mixes_[0];
414   const auto& forwarded_layout = forwarded_sub_mix.layouts[0].loudness_layout;
415   EXPECT_CALL(*mock_renderer_factory,
416               CreateRendererForLayout(_, _, _, _, _, forwarded_layout, _));
417   renderer_factory_ = std::move(mock_renderer_factory);
418 
419   CreateFinalizerExpectOk();
420 }
421 
TEST_F(FinalizerTest,ForwardsOrderedSamplesToRenderer)422 TEST_F(FinalizerTest, ForwardsOrderedSamplesToRenderer) {
423   InitPrerequisiteObusForStereoInput(kAudioElementId);
424   AddMixPresentationObuForStereoOutput(kMixPresentationId);
425   const LabelSamplesMap kLabelToSamples = {{kL2, {0, 1}}, {kR2, {2, 3}}};
426   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
427 
428   // We expect arguments to be forwarded from the OBUs to the renderer.
429   auto mock_renderer = std::make_unique<MockRenderer>(kStereoLabels, 2);
430   std::vector<InternalSampleType> rendered_samples;
431   const std::vector<std::vector<InternalSampleType>>
432       kExpectedTimeChannelOrderedSamples = {{0, 2}, {1, 3}};
433   EXPECT_CALL(*mock_renderer,
434               RenderSamples(
435                   absl::MakeConstSpan(kExpectedTimeChannelOrderedSamples), _));
436   auto mock_renderer_factory = std::make_unique<MockRendererFactory>();
437   ASSERT_NE(mock_renderer_factory, nullptr);
438   EXPECT_CALL(*mock_renderer_factory,
439               CreateRendererForLayout(_, _, _, _, _, _, _))
440       .WillOnce(Return(std::move(mock_renderer)));
441   renderer_factory_ = std::move(mock_renderer_factory);
442   std::list<ParameterBlockWithData> parameter_blocks;
443 
444   auto finalizer = CreateFinalizerExpectOk();
445   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
446 }
447 
TEST_F(FinalizerTest,CreatesWavFileWhenRenderingIsSupported)448 TEST_F(FinalizerTest, CreatesWavFileWhenRenderingIsSupported) {
449   InitPrerequisiteObusForStereoInput(kAudioElementId);
450   AddMixPresentationObuForStereoOutput(kMixPresentationId);
451   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
452   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
453   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
454   auto mock_renderer = std::make_unique<MockRenderer>();
455   EXPECT_CALL(*mock_renderer, RenderSamples(_, _));
456   auto mock_renderer_factory = std::make_unique<MockRendererFactory>();
457   EXPECT_CALL(*mock_renderer_factory,
458               CreateRendererForLayout(_, _, _, _, _, _, _))
459       .WillOnce(Return(std::move(mock_renderer)));
460   renderer_factory_ = std::move(mock_renderer_factory);
461   std::list<ParameterBlockWithData> parameter_blocks;
462 
463   auto finalizer = CreateFinalizerExpectOk();
464   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
465 
466   EXPECT_TRUE(std::filesystem::exists(GetFirstSubmixFirstLayoutExpectedPath()));
467 }
468 
TEST_F(FinalizerTest,DoesNotCreateFilesWhenRenderingFactoryIsNullptr)469 TEST_F(FinalizerTest, DoesNotCreateFilesWhenRenderingFactoryIsNullptr) {
470   InitPrerequisiteObusForStereoInput(kAudioElementId);
471   AddMixPresentationObuForStereoOutput(kMixPresentationId);
472   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
473   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
474   const std::filesystem::path output_directory =
475       GetAndCreateOutputDirectory("");
476   renderer_factory_ = nullptr;
477   std::list<ParameterBlockWithData> parameter_blocks;
478 
479   auto finalizer = CreateFinalizerExpectOk();
480   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
481 
482   EXPECT_TRUE(std::filesystem::is_empty(output_directory));
483 }
484 
TEST_F(FinalizerTest,DoesNotCreateFilesWhenRenderingFactoryReturnsNullptr)485 TEST_F(FinalizerTest, DoesNotCreateFilesWhenRenderingFactoryReturnsNullptr) {
486   InitPrerequisiteObusForStereoInput(kAudioElementId);
487   AddMixPresentationObuForStereoOutput(kMixPresentationId);
488   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
489   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
490   const std::filesystem::path output_directory =
491       GetAndCreateOutputDirectory("");
492   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
493   renderer_factory_ = std::make_unique<AlwaysNullRendererFactory>();
494   std::list<ParameterBlockWithData> parameter_blocks;
495 
496   auto finalizer = CreateFinalizerExpectOk();
497   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
498 
499   EXPECT_TRUE(std::filesystem::is_empty(output_directory));
500 }
501 
502 // =========== Tests on output rendered wav file properties ===========
503 
TEST_F(FinalizerTest,UsesCodecConfigBitDepthWhenOverrideIsNotSet)504 TEST_F(FinalizerTest, UsesCodecConfigBitDepthWhenOverrideIsNotSet) {
505   InitPrerequisiteObusForMonoInput(kAudioElementId);
506   AddMixPresentationObuForMonoOutput(kMixPresentationId);
507   const LabelSamplesMap kLabelToSamples = {{kMono, {0, 1}}};
508   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
509   renderer_factory_ = std::make_unique<RendererFactory>();
510   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
511   std::list<ParameterBlockWithData> parameter_blocks;
512   auto finalizer = CreateFinalizerExpectOk();
513 
514   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
515 
516   const auto wav_reader =
517       CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath());
518   EXPECT_EQ(wav_reader.bit_depth(), kCodecConfigBitDepth);
519 }
520 
TEST_F(FinalizerTest,OverridesBitDepthWhenRequested)521 TEST_F(FinalizerTest, OverridesBitDepthWhenRequested) {
522   InitPrerequisiteObusForMonoInput(kAudioElementId);
523   AddMixPresentationObuForMonoOutput(kMixPresentationId);
524   const LabelSamplesMap kLabelToSamples = {{kMono, {0, 1}}};
525   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
526   renderer_factory_ = std::make_unique<RendererFactory>();
527   output_wav_file_bit_depth_override_ = 32;
528   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
529   std::list<ParameterBlockWithData> parameter_blocks;
530   auto finalizer = CreateFinalizerExpectOk();
531 
532   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
533 
534   const auto wav_reader =
535       CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath());
536 
537   EXPECT_EQ(wav_reader.bit_depth(), 32);
538 }
539 
TEST_F(FinalizerTest,InvalidWhenFrameIsLargerThanNumSamplesPerFrame)540 TEST_F(FinalizerTest, InvalidWhenFrameIsLargerThanNumSamplesPerFrame) {
541   const LabelSamplesMap kInvalidLabelToSamplesWithTooManySamples = {
542       {kMono, std::vector<InternalSampleType>(kNumSamplesPerFrame + 1, 0)}};
543   InitPrerequisiteObusForMonoInput(kAudioElementId);
544   AddMixPresentationObuForMonoOutput(kMixPresentationId);
545   AddLabeledFrame(kAudioElementId, kInvalidLabelToSamplesWithTooManySamples,
546                   kEndTime);
547   renderer_factory_ = std::make_unique<RendererFactory>();
548   std::list<ParameterBlockWithData> parameter_blocks;
549   auto finalizer = CreateFinalizerExpectOk();
550 
551   EXPECT_FALSE(
552       finalizer
553           .PushTemporalUnit(
554               ordered_labeled_frames_[0], kStartTime,
555               ordered_labeled_frames_[0].at(kAudioElementId).end_timestamp,
556               parameter_blocks)
557           .ok());
558 }
559 
TEST_F(FinalizerTest,WavFileHasExpectedProperties)560 TEST_F(FinalizerTest, WavFileHasExpectedProperties) {
561   const std::vector<InternalSampleType> kFourSamples = {1, 2, 3, 4};
562   InitPrerequisiteObusForMonoInput(kAudioElementId);
563   AddMixPresentationObuForMonoOutput(kMixPresentationId);
564   const LabelSamplesMap kLabelToSamples = {{kMono, kFourSamples}};
565   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
566   renderer_factory_ = std::make_unique<RendererFactory>();
567   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
568   std::list<ParameterBlockWithData> parameter_blocks;
569   auto finalizer = CreateFinalizerExpectOk();
570 
571   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
572 
573   const auto wav_reader =
574       CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath());
575   EXPECT_EQ(wav_reader.remaining_samples(), kFourSamples.size());
576   EXPECT_EQ(wav_reader.sample_rate_hz(), kSampleRate);
577   EXPECT_EQ(wav_reader.num_channels(), 1);
578   EXPECT_EQ(wav_reader.bit_depth(), kBitDepth);
579 }
580 
TEST_F(FinalizerTest,SamplesAreTrimmedFromWavFile)581 TEST_F(FinalizerTest, SamplesAreTrimmedFromWavFile) {
582   constexpr int kNumSamplesToTrimFromStart = 2;
583   constexpr int kNumSamplesToTrimFromEnd = 1;
584   constexpr int kExpectedNumSamples = 1;
585   const std::vector<InternalSampleType> kFourSamples = {1, 2, 3, 4};
586   InitPrerequisiteObusForMonoInput(kAudioElementId);
587   AddMixPresentationObuForMonoOutput(kMixPresentationId);
588   const LabelSamplesMap kLabelToSamples = {{kMono, kFourSamples}};
589   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime,
590                   kNumSamplesToTrimFromStart, kNumSamplesToTrimFromEnd);
591   renderer_factory_ = std::make_unique<RendererFactory>();
592   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
593   std::list<ParameterBlockWithData> parameter_blocks;
594   auto finalizer = CreateFinalizerExpectOk();
595 
596   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
597 
598   const auto wav_reader =
599       CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath());
600   EXPECT_EQ(wav_reader.remaining_samples(), kExpectedNumSamples);
601 }
602 
TEST_F(FinalizerTest,SupportsFullyTrimmedFrames)603 TEST_F(FinalizerTest, SupportsFullyTrimmedFrames) {
604   // Sometimes at the start of a stream frames could be fully trimmed due to
605   // codec delay.
606   constexpr int kNumSamplesToTrimFromStart = 4;
607   constexpr int kExpectedZeroSamplesAfterTrimming = 0;
608   const std::vector<InternalSampleType> kFourSamples = {1, 2, 3, 4};
609   InitPrerequisiteObusForMonoInput(kAudioElementId);
610   AddMixPresentationObuForMonoOutput(kMixPresentationId);
611   const LabelSamplesMap kLabelToSamples = {{kMono, kFourSamples}};
612   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime,
613                   kNumSamplesToTrimFromStart, kNoTrimFromEnd);
614   renderer_factory_ = std::make_unique<RendererFactory>();
615   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
616   std::list<ParameterBlockWithData> parameter_blocks;
617   auto finalizer = CreateFinalizerExpectOk();
618 
619   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
620 
621   const auto wav_reader =
622       CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath());
623   EXPECT_EQ(wav_reader.remaining_samples(), kExpectedZeroSamplesAfterTrimming);
624 }
625 
626 // =========== Tests for finalized OBUs ===========
627 
628 const LoudnessInfo kExpectedMinimumLoudnessInfo = {
629     .info_type = 0,
630     .integrated_loudness = std::numeric_limits<int16_t>::min(),
631     .digital_peak = std::numeric_limits<int16_t>::min(),
632 };
633 
634 const LoudnessInfo kArbitraryLoudnessInfo = {
635     .info_type = LoudnessInfo::kTruePeak,
636     .integrated_loudness = 123,
637     .digital_peak = 456,
638     .true_peak = 789,
639 };
640 
TEST_F(FinalizerTest,CreatesWavFilesBasedOnFactoryFunction)641 TEST_F(FinalizerTest, CreatesWavFilesBasedOnFactoryFunction) {
642   PrepareObusForOneSamplePassThroughMono();
643 
644   // A factory can be used to omit generating wav files.
645   renderer_factory_ = std::make_unique<RendererFactory>();
646   sample_processor_factory_ =
647       RenderingMixPresentationFinalizer::ProduceNoSampleProcessors;
648   auto finalizer_without_post_processors = CreateFinalizerExpectOk();
649   EXPECT_THAT(finalizer_without_post_processors.FinalizePushingTemporalUnits(),
650               IsOk());
651   EXPECT_FALSE(
652       std::filesystem::exists(GetFirstSubmixFirstLayoutExpectedPath()));
653 
654   // Or a factory can be used to create wav files.
655   renderer_factory_ = std::make_unique<RendererFactory>();
656   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
657   auto finalizer_with_wav_writers = CreateFinalizerExpectOk();
658   EXPECT_THAT(finalizer_with_wav_writers.FinalizePushingTemporalUnits(),
659               IsOk());
660   EXPECT_TRUE(std::filesystem::exists(GetFirstSubmixFirstLayoutExpectedPath()));
661 }
662 
TEST_F(FinalizerTest,ForwardsArgumentsToSampleProcessorFactory)663 TEST_F(FinalizerTest, ForwardsArgumentsToSampleProcessorFactory) {
664   PrepareObusForOneSamplePassThroughMono();
665   // Rendering needs to be initialized to create wav files.
666   renderer_factory_ = std::make_unique<RendererFactory>();
667   // We expect arguments to be forwarded from the OBUs to the wav writer
668   // factory.
669   constexpr int kFirstSubmixIndex = 0;
670   constexpr int kFirstLayoutIndex = 0;
671   const auto& forwarded_layout =
672       obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness_layout;
673   const int32_t forwarded_sample_rate = static_cast<int32_t>(
674       codec_configs_.at(kCodecConfigId).GetOutputSampleRate());
675   const int32_t forwarded_bit_depth = static_cast<int32_t>(
676       codec_configs_.at(kCodecConfigId).GetBitDepthToMeasureLoudness());
677   const uint32_t forwarded_num_samples_per_frame =
678       codec_configs_.at(kCodecConfigId).GetNumSamplesPerFrame();
679 
680   MockSampleProcessorFactory mock_sample_processor_factory;
681   EXPECT_CALL(mock_sample_processor_factory,
682               Call(kMixPresentationId, kFirstSubmixIndex, kFirstLayoutIndex,
683                    forwarded_layout, kNumchannelsForMono, forwarded_sample_rate,
684                    forwarded_bit_depth, forwarded_num_samples_per_frame));
685   sample_processor_factory_ = mock_sample_processor_factory.AsStdFunction();
686 
687   auto finalizer = CreateFinalizerExpectOk();
688 }
689 
TEST_F(FinalizerTest,PushTemporalUnitDelegatesToSampleProcessor)690 TEST_F(FinalizerTest, PushTemporalUnitDelegatesToSampleProcessor) {
691   // Post-processing is only possible if rendering is enabled.
692   renderer_factory_ = std::make_unique<RendererFactory>();
693   const std::vector<std::vector<int32_t>> kExpectedPassthroughSamples = {
694       {0}, {std::numeric_limits<int32_t>::max()}};
695   const std::vector<InternalSampleType> kInputSamples = {0, 1.0};
696   InitPrerequisiteObusForMonoInput(kAudioElementId);
697   AddMixPresentationObuForMonoOutput(kMixPresentationId);
698   const LabelSamplesMap kLabelToSamples = {{kMono, {0, 1}}};
699   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
700   constexpr auto kNoOutputSamples = 0;
701   auto mock_sample_processor = std::make_unique<MockSampleProcessor>(
702       codec_configs_.at(kCodecConfigId).GetNumSamplesPerFrame(),
703       kNumchannelsForMono, kNoOutputSamples);
704   // We expect the post-processor to be called with the rendered samples.
705   EXPECT_CALL(
706       *mock_sample_processor,
707       PushFrameDerived(absl::MakeConstSpan(kExpectedPassthroughSamples)));
708   MockSampleProcessorFactory mock_sample_processor_factory;
709   EXPECT_CALL(mock_sample_processor_factory, Call(_, _, _, _, _, _, _, _))
710       .WillOnce(Return(std::move(mock_sample_processor)));
711   sample_processor_factory_ = mock_sample_processor_factory.AsStdFunction();
712 
713   auto finalizer = CreateFinalizerExpectOk();
714 
715   EXPECT_THAT(
716       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
717                                  /*start_timestamp=*/0,
718                                  /*end_timestamp=*/10, parameter_blocks_),
719       IsOk());
720 }
721 
TEST_F(FinalizerTest,FinalizePushingTemporalUnitsDelegatesToSampleProcessorFlush)722 TEST_F(FinalizerTest,
723        FinalizePushingTemporalUnitsDelegatesToSampleProcessorFlush) {
724   // Post-processing is only possible if rendering is enabled.
725   renderer_factory_ = std::make_unique<RendererFactory>();
726   InitPrerequisiteObusForMonoInput(kAudioElementId);
727   AddMixPresentationObuForMonoOutput(kMixPresentationId);
728   constexpr auto kNoOutputSamples = 0;
729   auto mock_sample_processor = std::make_unique<MockSampleProcessor>(
730       codec_configs_.at(kCodecConfigId).GetNumSamplesPerFrame(),
731       kNumchannelsForMono, kNoOutputSamples);
732   // We expect sample processors to be flushed when FinalizePushingTemporalUnits
733   // is called.
734   MockSampleProcessorFactory mock_sample_processor_factory;
735   EXPECT_CALL(*mock_sample_processor, FlushDerived());
736   EXPECT_CALL(mock_sample_processor_factory, Call(_, _, _, _, _, _, _, _))
737       .WillOnce(Return(std::move(mock_sample_processor)));
738   sample_processor_factory_ = mock_sample_processor_factory.AsStdFunction();
739 
740   auto finalizer = CreateFinalizerExpectOk();
741 
742   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
743 }
744 
TEST_F(FinalizerTest,ForwardsArgumentsToLoudnessCalculatorFactory)745 TEST_F(FinalizerTest, ForwardsArgumentsToLoudnessCalculatorFactory) {
746   PrepareObusForOneSamplePassThroughMono();
747   // We expect arguments to be forwarded from the OBUs to the loudness
748   // calculator factory.
749   auto mock_loudness_calculator_factory =
750       std::make_unique<MockLoudnessCalculatorFactory>();
751   const auto& forwarded_layout =
752       obus_to_finalize_.front().sub_mixes_[0].layouts[0];
753   const uint32_t forwarded_num_samples_per_frame =
754       codec_configs_.at(kCodecConfigId).GetNumSamplesPerFrame();
755   const int32_t forwarded_sample_rate = static_cast<int32_t>(
756       codec_configs_.at(kCodecConfigId).GetOutputSampleRate());
757   const int32_t forwarded_bit_depth_to_measure_loudness = static_cast<int32_t>(
758       codec_configs_.at(kCodecConfigId).GetBitDepthToMeasureLoudness());
759   EXPECT_CALL(
760       *mock_loudness_calculator_factory,
761       CreateLoudnessCalculator(
762           forwarded_layout, forwarded_num_samples_per_frame,
763           forwarded_sample_rate, forwarded_bit_depth_to_measure_loudness));
764   renderer_factory_ = std::make_unique<RendererFactory>();
765   loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory);
766 
767   auto finalizer = CreateFinalizerExpectOk();
768 }
769 
TEST_F(FinalizerTest,DelegatestoLoudnessCalculator)770 TEST_F(FinalizerTest, DelegatestoLoudnessCalculator) {
771   const LoudnessInfo kMockCalculatedLoudness = kArbitraryLoudnessInfo;
772   const LoudnessInfo kMismatchingUserLoudness = kExpectedMinimumLoudnessInfo;
773   const std::vector<std::vector<int32_t>> kExpectedPassthroughSamples = {
774       {0}, {std::numeric_limits<int32_t>::max()}};
775   const std::vector<InternalSampleType> kInputSamples = {0, 1.0};
776   InitPrerequisiteObusForMonoInput(kAudioElementId);
777   AddMixPresentationObuForMonoOutput(kMixPresentationId);
778   const LabelSamplesMap kLabelToSamples = {{kMono, {0, 1}}};
779   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
780   // We expect arguments to be forwarded from the OBUs to the loudness
781   // calculator factory.
782   auto mock_loudness_calculator_factory =
783       std::make_unique<MockLoudnessCalculatorFactory>();
784   auto mock_loudness_calculator = std::make_unique<MockLoudnessCalculator>();
785   // We expect the loudness calculator to be called with the rendered samples.
786   EXPECT_CALL(*mock_loudness_calculator,
787               AccumulateLoudnessForSamples(
788                   absl::MakeConstSpan(kExpectedPassthroughSamples)))
789       .WillOnce(Return(absl::OkStatus()));
790   ON_CALL(*mock_loudness_calculator, QueryLoudness())
791       .WillByDefault(Return(kArbitraryLoudnessInfo));
792   EXPECT_CALL(*mock_loudness_calculator_factory,
793               CreateLoudnessCalculator(_, _, _, _))
794       .WillOnce(Return(std::move(mock_loudness_calculator)));
795   renderer_factory_ = std::make_unique<RendererFactory>();
796   loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory);
797   auto finalizer = CreateFinalizerExpectOk();
798 
799   obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness =
800       kMismatchingUserLoudness;
801   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
802 
803   // Data was copied based on `QueryLoudness()`.
804   EXPECT_EQ(finalized_obus_.front().sub_mixes_[0].layouts[0].loudness,
805             kArbitraryLoudnessInfo);
806 }
807 
TEST_F(FinalizerTest,ValidatesUserLoudnessWhenRequested)808 TEST_F(FinalizerTest, ValidatesUserLoudnessWhenRequested) {
809   const LoudnessInfo kMockCalculatedLoudness = kArbitraryLoudnessInfo;
810   const LoudnessInfo kMismatchingUserLoudness = kExpectedMinimumLoudnessInfo;
811   PrepareObusForOneSamplePassThroughMono();
812 
813   auto mock_loudness_calculator_factory =
814       std::make_unique<MockLoudnessCalculatorFactory>();
815   auto mock_loudness_calculator = std::make_unique<MockLoudnessCalculator>();
816   EXPECT_CALL(*mock_loudness_calculator, AccumulateLoudnessForSamples(_))
817       .WillOnce(Return(absl::OkStatus()));
818   ON_CALL(*mock_loudness_calculator, QueryLoudness())
819       .WillByDefault(Return(kMockCalculatedLoudness));
820   EXPECT_CALL(*mock_loudness_calculator_factory,
821               CreateLoudnessCalculator(_, _, _, _))
822       .WillOnce(Return(std::move(mock_loudness_calculator)));
823 
824   // The user provided loudness does not match what the mock "measured".
825   obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness =
826       kMismatchingUserLoudness;
827   validate_loudness_ = kValidateLoudness;
828   renderer_factory_ = std::make_unique<RendererFactory>();
829   loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory);
830   std::list<ParameterBlockWithData> parameter_blocks;
831   auto finalizer = CreateFinalizerExpectOk();
832 
833   EXPECT_THAT(
834       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
835                                  /*start_timestamp=*/0,
836                                  /*end_timestamp=*/10, parameter_blocks),
837       IsOk());
838 
839   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
840   EXPECT_FALSE(
841       finalizer.GetFinalizedMixPresentationObus(validate_loudness_).ok());
842 }
843 
844 //============== Various modes fallback to preserving loudness. ==============
845 
FinalizeOneFrameAndExpectUserLoudnessIsPreserved(const std::vector<IdLabeledFrameMap> & ordered_labeled_frames_,const LoudnessInfo & kExpectedLoudness,RenderingMixPresentationFinalizer & finalizer)846 void FinalizeOneFrameAndExpectUserLoudnessIsPreserved(
847     const std::vector<IdLabeledFrameMap>& ordered_labeled_frames_,
848     const LoudnessInfo& kExpectedLoudness,
849     RenderingMixPresentationFinalizer& finalizer) {
850   std::list<ParameterBlockWithData> parameter_blocks;
851   int64_t start_timestamp = 0;
852   for (const auto& id_to_labeled_frame : ordered_labeled_frames_) {
853     ASSERT_TRUE(id_to_labeled_frame.contains(kAudioElementId));
854     EXPECT_THAT(finalizer.PushTemporalUnit(
855                     id_to_labeled_frame, start_timestamp,
856                     id_to_labeled_frame.at(kAudioElementId).end_timestamp,
857                     parameter_blocks),
858                 IsOk());
859   }
860   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
861 
862   const auto finalized_obus =
863       finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness);
864   ASSERT_THAT(finalized_obus, IsOkAndHolds(Not(IsEmpty())));
865 
866   EXPECT_EQ(finalized_obus->front().sub_mixes_[0].layouts[0].loudness,
867             kExpectedLoudness);
868 }
869 
TEST_F(FinalizerTest,PreservesUserLoudnessWhenRenderFactoryIsNullptr)870 TEST_F(FinalizerTest, PreservesUserLoudnessWhenRenderFactoryIsNullptr) {
871   PrepareObusForOneSamplePassThroughMono();
872   obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness =
873       kArbitraryLoudnessInfo;
874   renderer_factory_ = nullptr;
875   auto finalizer = CreateFinalizerExpectOk();
876 
877   FinalizeOneFrameAndExpectUserLoudnessIsPreserved(
878       ordered_labeled_frames_, kArbitraryLoudnessInfo, finalizer);
879 }
880 
TEST_F(FinalizerTest,PreservesUserLoudnessWhenRenderingIsNotSupported)881 TEST_F(FinalizerTest, PreservesUserLoudnessWhenRenderingIsNotSupported) {
882   PrepareObusForOneSamplePassThroughMono();
883   obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness =
884       kArbitraryLoudnessInfo;
885   renderer_factory_ = std::make_unique<AlwaysNullRendererFactory>();
886   loudness_calculator_factory_ =
887       std::make_unique<AlwaysNullLoudnessCalculatorFactory>();
888   auto finalizer = CreateFinalizerExpectOk();
889 
890   FinalizeOneFrameAndExpectUserLoudnessIsPreserved(
891       ordered_labeled_frames_, kArbitraryLoudnessInfo, finalizer);
892 }
893 
TEST_F(FinalizerTest,PreservesUserLoudnessWhenLoudnessFactoryIsNullPtr)894 TEST_F(FinalizerTest, PreservesUserLoudnessWhenLoudnessFactoryIsNullPtr) {
895   PrepareObusForOneSamplePassThroughMono();
896   obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness =
897       kArbitraryLoudnessInfo;
898   renderer_factory_ = std::make_unique<RendererFactory>();
899   loudness_calculator_factory_ = nullptr;
900   auto finalizer = CreateFinalizerExpectOk();
901 
902   FinalizeOneFrameAndExpectUserLoudnessIsPreserved(
903       ordered_labeled_frames_, kArbitraryLoudnessInfo, finalizer);
904 }
905 
TEST_F(FinalizerTest,PreservesUserLoudnessWhenLoudnessFactoryReturnsNullPtr)906 TEST_F(FinalizerTest, PreservesUserLoudnessWhenLoudnessFactoryReturnsNullPtr) {
907   PrepareObusForOneSamplePassThroughMono();
908   obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness =
909       kArbitraryLoudnessInfo;
910   renderer_factory_ = std::make_unique<RendererFactory>();
911   loudness_calculator_factory_ =
912       std::make_unique<AlwaysNullLoudnessCalculatorFactory>();
913   auto finalizer = CreateFinalizerExpectOk();
914 
915   FinalizeOneFrameAndExpectUserLoudnessIsPreserved(
916       ordered_labeled_frames_, kArbitraryLoudnessInfo, finalizer);
917 }
918 
TEST_F(FinalizerTest,CreateSucceedsWithValidInput)919 TEST_F(FinalizerTest, CreateSucceedsWithValidInput) {
920   InitPrerequisiteObusForStereoInput(kAudioElementId);
921   AddMixPresentationObuForStereoOutput(kMixPresentationId);
922   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
923   renderer_factory_ = std::make_unique<RendererFactory>();
924 
925   auto finalizer = CreateFinalizerExpectOk();
926 }
927 
TEST_F(FinalizerTest,FinalizePushingTemporalUnitsReturnsFailedPreconditionAfterFirstCall)928 TEST_F(FinalizerTest,
929        FinalizePushingTemporalUnitsReturnsFailedPreconditionAfterFirstCall) {
930   auto finalizer = CreateFinalizerExpectOk();
931   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
932 
933   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(),
934               StatusIs(kFailedPrecondition));
935 }
936 
TEST_F(FinalizerTest,GetFinalizedMixPresentationObusFailsBeforeFinalizePushingTemporalUnits)937 TEST_F(FinalizerTest,
938        GetFinalizedMixPresentationObusFailsBeforeFinalizePushingTemporalUnits) {
939   auto finalizer = CreateFinalizerExpectOk();
940 
941   EXPECT_FALSE(
942       finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness).ok());
943 }
944 
TEST_F(FinalizerTest,PushingIsNotAllowedAnyTimeAfterFinalizePushingTemporalUnits)945 TEST_F(FinalizerTest,
946        PushingIsNotAllowedAnyTimeAfterFinalizePushingTemporalUnits) {
947   InitPrerequisiteObusForMonoInput(kAudioElementId);
948   AddMixPresentationObuForMonoOutput(kMixPresentationId);
949   const LabelSamplesMap kLabelToSamples = {
950       {kMono, Int32ToInternalSampleType({100, 900})}};
951   const std::vector<std::vector<int32_t>> kExpectedSamples = {{100}, {900}};
952   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
953   auto finalizer = CreateFinalizerExpectOk();
954   EXPECT_THAT(
955       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
956                                  /*start_timestamp=*/0,
957                                  /*end_timestamp=*/10, parameter_blocks_),
958       IsOk());
959   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
960 
961   // Any time after `FinalizePushingTemporalUnits()` has been called pushing is
962   // not allowed. Even if later functions such as
963   // `GetFinalizedMixPresentationObus` are called.
964   EXPECT_THAT(
965       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
966                                  /*start_timestamp=*/10,
967                                  /*end_timestamp=*/20, parameter_blocks_),
968       Not(IsOk()));
969   EXPECT_THAT(finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness),
970               IsOk());
971   EXPECT_THAT(
972       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
973                                  /*start_timestamp=*/10,
974                                  /*end_timestamp=*/20, parameter_blocks_),
975       Not(IsOk()));
976 }
977 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanCanBeUsedBeforeOrAfterGetFinalizedMixPresentationObus)978 TEST_F(
979     FinalizerTest,
980     GetPostProcessedSamplesAsSpanCanBeUsedBeforeOrAfterGetFinalizedMixPresentationObus) {
981   InitPrerequisiteObusForStereoInput(kAudioElementId);
982   AddMixPresentationObuForStereoOutput(kMixPresentationId);
983   renderer_factory_ = std::make_unique<RendererFactory>();
984   auto finalizer = CreateFinalizerExpectOk();
985   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
986 
987   // It's acceptable to retrieve the post-processed samples either before or
988   // after retrieving the finalized mix presentation OBUs.
989   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
990                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
991               IsOk());
992   EXPECT_THAT(finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness),
993               IsOk());
994   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
995                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
996               IsOk());
997 }
998 
TEST_F(FinalizerTest,GetFinalizedMixPresentationObusMayNotBeCalledTwice)999 TEST_F(FinalizerTest, GetFinalizedMixPresentationObusMayNotBeCalledTwice) {
1000   InitPrerequisiteObusForStereoInput(kAudioElementId);
1001   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1002   auto finalizer = CreateFinalizerExpectOk();
1003   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
1004 
1005   EXPECT_THAT(finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness),
1006               IsOk());
1007 
1008   // The finalized OBUs have already been flushed out and cannot be retrieved
1009   // again.
1010   EXPECT_THAT(finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness),
1011               Not(IsOk()));
1012 }
1013 
TEST_F(FinalizerTest,GetFinalizedMixPresentationObusReturnsObusInSameorder)1014 TEST_F(FinalizerTest, GetFinalizedMixPresentationObusReturnsObusInSameorder) {
1015   InitPrerequisiteObusForStereoInput(kAudioElementId);
1016   constexpr DecodedUleb128 kFirstMixPresentationId = 100;
1017   constexpr DecodedUleb128 kSecondMixPresentationId = 99;
1018   constexpr DecodedUleb128 kThirdMixPresentationId = 101;
1019   AddMixPresentationObuForStereoOutput(kFirstMixPresentationId);
1020   AddMixPresentationObuForStereoOutput(kSecondMixPresentationId);
1021   AddMixPresentationObuForStereoOutput(kThirdMixPresentationId);
1022   auto finalizer = CreateFinalizerExpectOk();
1023   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
1024 
1025   // We expect the entire list to come back in the same order. List order
1026   // may affect the priority downstream when selecting the default mix to
1027   // playback.
1028   ASSERT_THAT(finalizer.GetFinalizedMixPresentationObus(kDontValidateLoudness),
1029               IsOkAndHolds(Eq(obus_to_finalize_)));
1030 }
1031 
1032 // =========== Tests for PushTemporalUnit ===========
1033 // TODO(b/380110994): Add more tests for PushTemporalUnit. Check that rendered
1034 // output is written to wav file appropriately.
TEST_F(FinalizerTest,PushTemporalUnitSucceedsWithValidInput)1035 TEST_F(FinalizerTest, PushTemporalUnitSucceedsWithValidInput) {
1036   InitPrerequisiteObusForStereoInput(kAudioElementId);
1037   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1038   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
1039   AddLabeledFrame(kAudioElementId, kLabelToSamples, /*end_timestamp=*/10);
1040 
1041   ASSERT_EQ(ordered_labeled_frames_.size(), 1);
1042   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
1043   renderer_factory_ = std::make_unique<RendererFactory>();
1044   auto finalizer = CreateFinalizerExpectOk();
1045   EXPECT_THAT(finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
1046                                          /*start_timestamp=*/0,
1047                                          /*end_timestamp=*/10,
1048                                          /*parameter_blocks=*/{}),
1049               IsOk());
1050 }
1051 
TEST_F(FinalizerTest,FullIterativeRenderingSucceedsWithValidInput)1052 TEST_F(FinalizerTest, FullIterativeRenderingSucceedsWithValidInput) {
1053   InitPrerequisiteObusForStereoInput(kAudioElementId);
1054   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1055   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
1056   AddLabeledFrame(kAudioElementId, kLabelToSamples, /*end_timestamp=*/10);
1057 
1058   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
1059   renderer_factory_ = std::make_unique<RendererFactory>();
1060 
1061   // Prepare a mock loudness calculator that will return arbitrary loudness
1062   // information.
1063   auto mock_loudness_calculator_factory =
1064       std::make_unique<MockLoudnessCalculatorFactory>();
1065   auto mock_loudness_calculator = std::make_unique<MockLoudnessCalculator>();
1066   ON_CALL(*mock_loudness_calculator, QueryLoudness())
1067       .WillByDefault(Return(kArbitraryLoudnessInfo));
1068   EXPECT_CALL(*mock_loudness_calculator_factory,
1069               CreateLoudnessCalculator(_, _, _, _))
1070       .WillOnce(Return(std::move(mock_loudness_calculator)));
1071   loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory);
1072   validate_loudness_ = false;
1073   auto finalizer = CreateFinalizerExpectOk();
1074 
1075   IterativeRenderingExpectOk(finalizer, parameter_blocks_);
1076 
1077   // Then we expect the loudness to be populated with the computed loudness.
1078   EXPECT_EQ(finalized_obus_.front().sub_mixes_[0].layouts[0].loudness,
1079             kArbitraryLoudnessInfo);
1080 }
1081 
TEST_F(FinalizerTest,InvalidComputedLoudnessFails)1082 TEST_F(FinalizerTest, InvalidComputedLoudnessFails) {
1083   InitPrerequisiteObusForStereoInput(kAudioElementId);
1084   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1085   const LabelSamplesMap kLabelToSamples = {{kL2, {0}}, {kR2, {2}}};
1086   AddLabeledFrame(kAudioElementId, kLabelToSamples, /*end_timestamp=*/10);
1087 
1088   ConfigureWavWriterFactoryToProduceFirstSubMixFirstLayout();
1089   renderer_factory_ = std::make_unique<RendererFactory>();
1090 
1091   // Prepare a mock loudness calculator that will return arbitrary loudness
1092   // information.
1093   auto mock_loudness_calculator_factory =
1094       std::make_unique<MockLoudnessCalculatorFactory>();
1095   auto mock_loudness_calculator = std::make_unique<MockLoudnessCalculator>();
1096   ON_CALL(*mock_loudness_calculator, QueryLoudness())
1097       .WillByDefault(Return(kArbitraryLoudnessInfo));
1098   EXPECT_CALL(*mock_loudness_calculator_factory,
1099               CreateLoudnessCalculator(_, _, _, _))
1100       .WillOnce(Return(std::move(mock_loudness_calculator)));
1101   loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory);
1102 
1103   auto finalizer = CreateFinalizerExpectOk();
1104   EXPECT_THAT(finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
1105                                          /*start_timestamp=*/0,
1106                                          /*end_timestamp=*/10,
1107                                          /*parameter_blocks=*/{}),
1108               IsOk());
1109   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
1110   // Do validate that computed loudness matches the user provided loudness -
1111   // since kArbitraryLoudnessInfo is the `computed` loudness, it won't.
1112   validate_loudness_ = true;
1113   EXPECT_FALSE(
1114       finalizer.GetFinalizedMixPresentationObus(validate_loudness_).ok());
1115 }
1116 
1117 // =========== Tests for GetPostProcessedSamplesAsSpan ===========
1118 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsEmptySpanAfterCreate)1119 TEST_F(FinalizerTest,
1120        GetPostProcessedSamplesAsSpanReturnsEmptySpanAfterCreate) {
1121   InitPrerequisiteObusForStereoInput(kAudioElementId);
1122   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1123   renderer_factory_ = std::make_unique<RendererFactory>();
1124 
1125   auto finalizer = CreateFinalizerExpectOk();
1126 
1127   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1128                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
1129               IsOkAndHolds(IsEmpty()));
1130 }
1131 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsErrorWithRenderingDisabled)1132 TEST_F(FinalizerTest,
1133        GetPostProcessedSamplesAsSpanReturnsErrorWithRenderingDisabled) {
1134   InitPrerequisiteObusForStereoInput(kAudioElementId);
1135   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1136   // Disable rendering.
1137   renderer_factory_ = nullptr;
1138 
1139   auto finalizer = CreateFinalizerExpectOk();
1140 
1141   // Post-processed samples are only available if rendering was enabled.
1142   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1143                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
1144               Not(IsOk()));
1145 }
1146 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsErrorWithUnknownMixPresentationId)1147 TEST_F(FinalizerTest,
1148        GetPostProcessedSamplesAsSpanReturnsErrorWithUnknownMixPresentationId) {
1149   InitPrerequisiteObusForStereoInput(kAudioElementId);
1150   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1151   const DecodedUleb128 kUnknownMixPresentationId = kMixPresentationId + 1;
1152   renderer_factory_ = std::make_unique<RendererFactory>();
1153 
1154   auto finalizer = CreateFinalizerExpectOk();
1155 
1156   EXPECT_THAT(
1157       finalizer.GetPostProcessedSamplesAsSpan(
1158           kUnknownMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
1159       Not(IsOk()));
1160 }
1161 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsErrorWithUnknownLayoutIndex)1162 TEST_F(FinalizerTest,
1163        GetPostProcessedSamplesAsSpanReturnsErrorWithUnknownLayoutIndex) {
1164   InitPrerequisiteObusForStereoInput(kAudioElementId);
1165   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1166   const int kUnknownLayoutIndex = kFirstLayoutIndex + 1;
1167   renderer_factory_ = std::make_unique<RendererFactory>();
1168 
1169   auto finalizer = CreateFinalizerExpectOk();
1170 
1171   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1172                   kMixPresentationId, kUnknownLayoutIndex, kFirstSubmixIndex),
1173               Not(IsOk()));
1174 }
1175 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsErrorWithUnknownSubmixIndex)1176 TEST_F(FinalizerTest,
1177        GetPostProcessedSamplesAsSpanReturnsErrorWithUnknownSubmixIndex) {
1178   InitPrerequisiteObusForStereoInput(kAudioElementId);
1179   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1180   const int kUnknownSubmixIndex = kFirstSubmixIndex + 1;
1181   renderer_factory_ = std::make_unique<RendererFactory>();
1182 
1183   auto finalizer = CreateFinalizerExpectOk();
1184 
1185   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1186                   kMixPresentationId, kFirstLayoutIndex, kUnknownSubmixIndex),
1187               Not(IsOk()));
1188 }
1189 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsEmptySpanWhenFinalizedWithNoPostProcessor)1190 TEST_F(
1191     FinalizerTest,
1192     GetPostProcessedSamplesAsSpanReturnsEmptySpanWhenFinalizedWithNoPostProcessor) {
1193   InitPrerequisiteObusForStereoInput(kAudioElementId);
1194   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1195   renderer_factory_ = std::make_unique<RendererFactory>();
1196   sample_processor_factory_ =
1197       RenderingMixPresentationFinalizer::ProduceNoSampleProcessors;
1198 
1199   auto finalizer = CreateFinalizerExpectOk();
1200   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
1201 
1202   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1203                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
1204               IsOkAndHolds(IsEmpty()));
1205 }
1206 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanPrioritizesPostProcessedSamples)1207 TEST_F(FinalizerTest,
1208        GetPostProcessedSamplesAsSpanPrioritizesPostProcessedSamples) {
1209   InitPrerequisiteObusForStereoInput(kAudioElementId);
1210   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1211   const LabelSamplesMap kLabelToSamples = {
1212       {kL2, Int32ToInternalSampleType({0, 1})},
1213       {kR2, Int32ToInternalSampleType({2, 3})}};
1214   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
1215   renderer_factory_ = std::make_unique<RendererFactory>();
1216   const std::vector<std::vector<int32_t>> kExpectedSamples = {{1, 3}};
1217   // We expect the post-processor to be called with the rendered samples.
1218   sample_processor_factory_ =
1219       [](DecodedUleb128 /*mix_presentation_id*/, int /*sub_mix_index*/,
1220          int /*layout_index*/, const Layout& /*layout*/, int num_channels,
1221          int /*sample_rate*/, int /*bit_depth*/, size_t num_samples_per_frame) {
1222         return std::make_unique<EverySecondTickResampler>(num_samples_per_frame,
1223                                                           num_channels);
1224       };
1225   auto finalizer = CreateFinalizerExpectOk();
1226 
1227   // Push a temporal unit.
1228   EXPECT_THAT(
1229       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
1230                                  /*start_timestamp=*/0,
1231                                  /*end_timestamp=*/10, parameter_blocks_),
1232       IsOk());
1233 
1234   // We expect the post-processed samples, i.e. every other tick.
1235   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1236                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
1237               IsOkAndHolds(absl::MakeConstSpan(kExpectedSamples)));
1238 }
1239 
TEST_F(FinalizerTest,GetPostProcessedSamplesAsSpanReturnsFallsBackToRenderedSamples)1240 TEST_F(FinalizerTest,
1241        GetPostProcessedSamplesAsSpanReturnsFallsBackToRenderedSamples) {
1242   InitPrerequisiteObusForStereoInput(kAudioElementId);
1243   AddMixPresentationObuForStereoOutput(kMixPresentationId);
1244   const LabelSamplesMap kLabelToSamples = {
1245       {kL2, Int32ToInternalSampleType({0, 1})},
1246       {kR2, Int32ToInternalSampleType({2, 3})}};
1247   const std::vector<std::vector<int32_t>> kExpectedSamples = {{0, 2}, {1, 3}};
1248   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
1249   renderer_factory_ = std::make_unique<RendererFactory>();
1250   sample_processor_factory_ =
1251       RenderingMixPresentationFinalizer::ProduceNoSampleProcessors;
1252   auto finalizer = CreateFinalizerExpectOk();
1253 
1254   // Push a temporal unit.
1255   EXPECT_THAT(
1256       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
1257                                  /*start_timestamp=*/0,
1258                                  /*end_timestamp=*/10, parameter_blocks_),
1259       IsOk());
1260 
1261   // There is no post-processor, but it safely falls back to the pass-through
1262   // rendered samples.
1263   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1264                   kMixPresentationId, kFirstLayoutIndex, kFirstSubmixIndex),
1265               IsOkAndHolds(absl::MakeConstSpan(kExpectedSamples)));
1266 }
1267 
TEST_F(FinalizerTest,DelayedSamplesAreAvailableAfterFinalizePushingTemporalUnits)1268 TEST_F(FinalizerTest,
1269        DelayedSamplesAreAvailableAfterFinalizePushingTemporalUnits) {
1270   InitPrerequisiteObusForMonoInput(kAudioElementId);
1271   AddMixPresentationObuForMonoOutput(kMixPresentationId);
1272   renderer_factory_ = std::make_unique<RendererFactory>();
1273   sample_processor_factory_ =
1274       [](DecodedUleb128 /*mix_presentation_id*/, int /*sub_mix_index*/,
1275          int /*layout_index*/, const Layout& /*layout*/, int num_channels,
1276          int /*sample_rate*/, int /*bit_depth*/, size_t num_samples_per_frame) {
1277         return std::make_unique<OneFrameDelayer>(num_samples_per_frame,
1278                                                  num_channels);
1279       };
1280   const LabelSamplesMap kLabelToSamples = {
1281       {kMono, Int32ToInternalSampleType({100, 900})}};
1282   const std::vector<std::vector<int32_t>> kExpectedSamples = {{100}, {900}};
1283   AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime);
1284   auto finalizer = CreateFinalizerExpectOk();
1285 
1286   // The post-processor has delay. So samples are not available immediately.
1287   EXPECT_THAT(
1288       finalizer.PushTemporalUnit(ordered_labeled_frames_[0],
1289                                  /*start_timestamp=*/0,
1290                                  /*end_timestamp=*/10, parameter_blocks_),
1291       IsOk());
1292   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1293                   kMixPresentationId, kFirstSubmixIndex, kFirstLayoutIndex),
1294               IsOkAndHolds(IsEmpty()));
1295 
1296   // But finally after flushing, samples are available.
1297   EXPECT_THAT(finalizer.FinalizePushingTemporalUnits(), IsOk());
1298   EXPECT_THAT(finalizer.GetPostProcessedSamplesAsSpan(
1299                   kMixPresentationId, kFirstSubmixIndex, kFirstLayoutIndex),
1300               IsOkAndHolds(absl::MakeConstSpan(kExpectedSamples)));
1301 }
1302 
1303 }  // namespace
1304 }  // namespace iamf_tools
1305