From b7a747346b73db47cf97ba80a3bf9777040a4f96 Mon Sep 17 00:00:00 2001 From: jwcullen Date: Wed, 8 Jan 2025 17:28:46 -0500 Subject: [PATCH] Apply cleanups to `RenderingMixPresentationFinalizer`. - Replace constructor and `Initialize` with a factory function (`Create`): - Protects from misuse as it can never be an in an uninitialized state. - Class can hold fewer variables, since they are only needed at initialize. - Pass in `absl::Nullable`-annotated pointer for factories that are safe to disable. Ownership transfer via unique_ptr is not needed because the factory is no longer held. - `Finalize`: Remove duplicate use of `validate_loudness`. It was previously duplicated at the constructor (now factory function). - `PushTemporalUnit`: Remove unused OBU argument. - `PushTemporalUnit`: Simplify to directly take a reference to a list of parameter blocks. Now we no longer need to deal with iterators since the callsite code always holds one temporal unit at a time. - Move some structs in the interface to private where feasible. PiperOrigin-RevId: 713417852 --- iamf/cli/BUILD | 2 + iamf/cli/encoder_main_lib.cc | 18 +- .../rendering_mix_presentation_finalizer.cc | 107 ++++---- .../rendering_mix_presentation_finalizer.h | 97 ++++---- ...ndering_mix_presentation_finalizer_test.cc | 232 +++++++----------- 5 files changed, 194 insertions(+), 262 deletions(-) diff --git a/iamf/cli/BUILD b/iamf/cli/BUILD index 523904e..8c54647 100644 --- a/iamf/cli/BUILD +++ b/iamf/cli/BUILD @@ -459,12 +459,14 @@ cc_library( "//iamf/obu:param_definitions", "//iamf/obu:parameter_block", "//iamf/obu:types", + "@com_google_absl//absl/base:nullability", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/container:flat_hash_set", "@com_google_absl//absl/functional:any_invocable", "@com_google_absl//absl/log", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", + "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/time", ], diff --git a/iamf/cli/encoder_main_lib.cc b/iamf/cli/encoder_main_lib.cc index 2a7018f..8a3ecb3 100644 --- a/iamf/cli/encoder_main_lib.cc +++ b/iamf/cli/encoder_main_lib.cc @@ -210,12 +210,13 @@ absl::Status GenerateObus( return wav_sample_provider.status(); } - RenderingMixPresentationFinalizer mix_presentation_finalizer( + auto mix_presentation_finalizer = RenderingMixPresentationFinalizer::Create( output_wav_file_prefix, output_wav_file_bit_depth_override, - user_metadata.test_vector_metadata().validate_user_loudness(), - CreateRendererFactory(), CreateLoudnessCalculatorFactory()); - RETURN_IF_NOT_OK(mix_presentation_finalizer.Initialize( - audio_elements, ProduceAllWavWriters, mix_presentation_obus)); + CreateRendererFactory().get(), CreateLoudnessCalculatorFactory().get(), + audio_elements, ProduceAllWavWriters, mix_presentation_obus); + if (!mix_presentation_finalizer.ok()) { + return mix_presentation_finalizer.status(); + } // Parameter blocks. TimeParameterBlockMetadataMap time_parameter_block_metadata; @@ -279,10 +280,9 @@ absl::Status GenerateObus( LOG(INFO) << "No audio frame generated in this iteration; continue."; continue; } - RETURN_IF_NOT_OK(mix_presentation_finalizer.PushTemporalUnit( + RETURN_IF_NOT_OK(mix_presentation_finalizer->PushTemporalUnit( id_to_labeled_frame, temp_audio_frames.front().start_timestamp, - temp_audio_frames.front().end_timestamp, temp_parameter_blocks.begin(), - temp_parameter_blocks.end(), mix_presentation_obus)); + temp_audio_frames.front().end_timestamp, temp_parameter_blocks)); audio_frames.splice(audio_frames.end(), temp_audio_frames); parameter_blocks.splice(parameter_blocks.end(), temp_parameter_blocks); @@ -290,7 +290,7 @@ absl::Status GenerateObus( LOG(INFO) << "\n============================= END of Generating Data OBUs" << " =============================\n\n"; PrintAudioFrames(audio_frames); - RETURN_IF_NOT_OK(mix_presentation_finalizer.Finalize( + RETURN_IF_NOT_OK(mix_presentation_finalizer->Finalize( user_metadata.test_vector_metadata().validate_user_loudness(), mix_presentation_obus)); diff --git a/iamf/cli/rendering_mix_presentation_finalizer.cc b/iamf/cli/rendering_mix_presentation_finalizer.cc index cc577a4..a45f818 100644 --- a/iamf/cli/rendering_mix_presentation_finalizer.cc +++ b/iamf/cli/rendering_mix_presentation_finalizer.cc @@ -24,6 +24,7 @@ #include #include +#include "absl/base/nullability.h" #include "absl/container/flat_hash_map.h" #include "absl/container/flat_hash_set.h" #include "absl/functional/any_invocable.h" @@ -211,10 +212,7 @@ absl::Status GetParameterBlockLinearMixGainsPerTick( // `GetParameterBlockLinearMixGainsPerTick()` is in use. absl::Status GetParameterBlockLinearMixGainsPerTick( uint32_t common_sample_rate, int32_t start_timestamp, int32_t end_timestamp, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end, + const std::list& parameter_blocks, const MixGainParamDefinition& mix_gain, std::vector& linear_mix_gain_per_tick) { if (mix_gain.parameter_rate_ != common_sample_rate) { @@ -238,13 +236,13 @@ absl::Status GetParameterBlockLinearMixGainsPerTick( (cur_tick - start_timestamp) < linear_mix_gain_per_tick.size()) { // Find the parameter block that this tick occurs during. const auto parameter_block_iter = std::find_if( - parameter_blocks_start, parameter_blocks_end, + parameter_blocks.begin(), parameter_blocks.end(), [cur_tick, parameter_id](const auto& parameter_block) { return parameter_block.obu->parameter_id_ == parameter_id && parameter_block.start_timestamp <= cur_tick && cur_tick < parameter_block.end_timestamp; }); - if (parameter_block_iter == parameter_blocks_end) { + if (parameter_block_iter == parameter_blocks.end()) { // Default mix gain will be used for this frame. Logic elsewhere validates // the rest of the audio frames have consistent coverage. break; @@ -302,10 +300,7 @@ absl::Status GetAndApplyMixGain( // NOLINT // TODO(b/379961928): Remove once the new GetAndApplyMixGain is in use. absl::Status GetAndApplyMixGain( uint32_t common_sample_rate, int32_t start_timestamp, int32_t end_timestamp, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end, + const std::list& parameter_blocks, const MixGainParamDefinition& mix_gain, int32_t num_channels, std::vector& linear_mix_gain_per_tick, std::vector& rendered_samples) { @@ -319,9 +314,8 @@ absl::Status GetAndApplyMixGain( // Get the mix gain on a per tick basis from the parameter block. linear_mix_gain_per_tick.resize(rendered_samples.size() / num_channels, 0.0f); RETURN_IF_NOT_OK(GetParameterBlockLinearMixGainsPerTick( - common_sample_rate, start_timestamp, end_timestamp, - parameter_blocks_start, parameter_blocks_end, mix_gain, - linear_mix_gain_per_tick)); + common_sample_rate, start_timestamp, end_timestamp, parameter_blocks, + mix_gain, linear_mix_gain_per_tick)); if (!linear_mix_gain_per_tick.empty()) { LOG_FIRST_N(INFO, 6) << " First tick in this frame has gain: " @@ -375,10 +369,7 @@ absl::Status RenderAllFramesForLayout( const IdLabeledFrameMap& id_to_labeled_frame, const std::vector& rendering_metadata_array, const int32_t start_timestamp, const int32_t end_timestamp, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end, + const std::list& parameter_blocks, const uint32_t common_sample_rate, std::vector& rendered_samples) { rendered_samples.clear(); @@ -400,8 +391,7 @@ absl::Status RenderAllFramesForLayout( labeled_frame, rendering_metadata, rendered_audio_elements[i])); } RETURN_IF_NOT_OK(GetAndApplyMixGain( - common_sample_rate, start_timestamp, end_timestamp, - parameter_blocks_start, parameter_blocks_end, + common_sample_rate, start_timestamp, end_timestamp, parameter_blocks, sub_mix_audio_element.element_mix_gain, num_channels, linear_mix_gain_per_tick, rendered_audio_elements[i])); } @@ -414,10 +404,10 @@ absl::Status RenderAllFramesForLayout( LOG_FIRST_N(INFO, 1) << " Applying output_mix_gain.default_mix_gain= " << output_mix_gain.default_mix_gain_; - RETURN_IF_NOT_OK(GetAndApplyMixGain( - common_sample_rate, start_timestamp, end_timestamp, - parameter_blocks_start, parameter_blocks_end, output_mix_gain, - num_channels, linear_mix_gain_per_tick, rendered_samples_internal)); + RETURN_IF_NOT_OK( + GetAndApplyMixGain(common_sample_rate, start_timestamp, end_timestamp, + parameter_blocks, output_mix_gain, num_channels, + linear_mix_gain_per_tick, rendered_samples_internal)); // Convert the rendered samples to int32, clipping if needed. rendered_samples.reserve(rendered_samples_internal.size()); @@ -583,9 +573,10 @@ absl::Status GenerateRenderingMetadataForLayouts( // elements and layouts that need to be rendered as well. Not all of these // need to be rendered; only the ones that either have a wav writer or a // loudness calculator. -absl::Status GenerateRenderingMetadataForSubmixes( // NOLINT +absl::Status GenerateRenderingMetadataForSubmixes( const RendererFactoryBase& renderer_factory, - const LoudnessCalculatorFactoryBase* loudness_calculator_factory, + absl::Nullable + loudness_calculator_factory, const RenderingMixPresentationFinalizer::WavWriterFactory& wav_writer_factory, const std::filesystem::path& file_path_prefix, @@ -697,10 +688,7 @@ bool CanRenderAnyLayout( absl::Status RenderWriteAndCalculateLoudnessForTemporalUnit( const IdLabeledFrameMap& id_to_labeled_frame, const int32_t start_timestamp, const int32_t end_timestamp, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end, + const std::list& parameter_blocks, std::vector& rendering_metadata) { for (auto& submix_rendering_metadata : rendering_metadata) { for (auto& layout_rendering_metadata : @@ -717,9 +705,8 @@ absl::Status RenderWriteAndCalculateLoudnessForTemporalUnit( submix_rendering_metadata.audio_elements_in_sub_mix, *submix_rendering_metadata.mix_gain, id_to_labeled_frame, layout_rendering_metadata.audio_element_rendering_metadata, - start_timestamp, end_timestamp, parameter_blocks_start, - parameter_blocks_end, submix_rendering_metadata.common_sample_rate, - rendered_samples)); + start_timestamp, end_timestamp, parameter_blocks, + submix_rendering_metadata.common_sample_rate, rendered_samples)); if (layout_rendering_metadata.wav_writer != nullptr) { RETURN_IF_NOT_OK(WriteRenderedSamples( rendered_samples, submix_rendering_metadata.wav_file_bit_depth, @@ -736,44 +723,47 @@ absl::Status RenderWriteAndCalculateLoudnessForTemporalUnit( } // namespace -absl::Status RenderingMixPresentationFinalizer::Initialize( +absl::StatusOr +RenderingMixPresentationFinalizer::Create( + const std::filesystem::path& file_path_prefix, + std::optional output_wav_file_bit_depth_override, + absl::Nullable renderer_factory, + absl::Nullable + loudness_calculator_factory, const absl::flat_hash_map& audio_elements, const WavWriterFactory& wav_writer_factory, std::list& mix_presentation_obus) { - if (renderer_factory_ == nullptr) { - LOG(INFO) << "Renderer factory is null; so rendering is safely aborted."; - return absl::OkStatus(); + if (renderer_factory == nullptr) { + LOG(INFO) << "Rendering is safely disabled."; + return RenderingMixPresentationFinalizer( + std::vector()); } - if (loudness_calculator_factory_ == nullptr) { + if (loudness_calculator_factory == nullptr) { LOG(INFO) << "Loudness calculator factory is null so loudness will not be " "calculated."; } + std::vector rendering_metadata; + rendering_metadata.reserve(mix_presentation_obus.size()); for (auto& mix_presentation_obu : mix_presentation_obus) { - std::vector rendering_metadata; + std::vector sub_mix_rendering_metadata; RETURN_IF_NOT_OK(GenerateRenderingMetadataForSubmixes( - *renderer_factory_, loudness_calculator_factory_.get(), - wav_writer_factory, file_path_prefix_, audio_elements, - output_wav_file_bit_depth_override_, mix_presentation_obu, - rendering_metadata)); - MixPresentationRenderingMetadata mix_presentation_rendering_metadata; - mix_presentation_rendering_metadata.mix_presentation_id = - mix_presentation_obu.GetMixPresentationId(); - mix_presentation_rendering_metadata.submix_rendering_metadata = - std::move(rendering_metadata); - rendering_metadata_.push_back( - std::move(mix_presentation_rendering_metadata)); + *renderer_factory, loudness_calculator_factory, wav_writer_factory, + file_path_prefix, audio_elements, output_wav_file_bit_depth_override, + mix_presentation_obu, sub_mix_rendering_metadata)); + + rendering_metadata.push_back(MixPresentationRenderingMetadata{ + .mix_presentation_id = mix_presentation_obu.GetMixPresentationId(), + .submix_rendering_metadata = std::move(sub_mix_rendering_metadata), + }); } - return absl::OkStatus(); + + return RenderingMixPresentationFinalizer(std::move(rendering_metadata)); } absl::Status RenderingMixPresentationFinalizer::PushTemporalUnit( const IdLabeledFrameMap& id_to_labeled_frame, const int32_t start_timestamp, const int32_t end_timestamp, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end, - std::list& mix_presentation_obus) { + const std::list& parameter_blocks) { for (auto& mix_presentation_rendering_metadata : rendering_metadata_) { if (!CanRenderAnyLayout( mix_presentation_rendering_metadata.submix_rendering_metadata)) { @@ -781,8 +771,7 @@ absl::Status RenderingMixPresentationFinalizer::PushTemporalUnit( continue; } RETURN_IF_NOT_OK(RenderWriteAndCalculateLoudnessForTemporalUnit( - id_to_labeled_frame, start_timestamp, end_timestamp, - parameter_blocks_start, parameter_blocks_end, + id_to_labeled_frame, start_timestamp, end_timestamp, parameter_blocks, mix_presentation_rendering_metadata.submix_rendering_metadata)); } return absl::OkStatus(); @@ -791,8 +780,8 @@ absl::Status RenderingMixPresentationFinalizer::PushTemporalUnit( absl::Status RenderingMixPresentationFinalizer::Finalize( bool validate_loudness, std::list& mix_presentation_obus) { - if (renderer_factory_ == nullptr) { - LOG(INFO) << "Renderer factory is null; so rendering is safely aborted."; + if (rendering_is_disabled_) { + LOG(INFO) << "Renderer is disabled; so rendering is safely aborted."; return absl::OkStatus(); } if (rendering_metadata_.size() != mix_presentation_obus.size()) { diff --git a/iamf/cli/rendering_mix_presentation_finalizer.h b/iamf/cli/rendering_mix_presentation_finalizer.h index d34a014..49d3cc2 100644 --- a/iamf/cli/rendering_mix_presentation_finalizer.h +++ b/iamf/cli/rendering_mix_presentation_finalizer.h @@ -21,9 +21,11 @@ #include #include +#include "absl/base/nullability.h" #include "absl/container/flat_hash_map.h" #include "absl/functional/any_invocable.h" #include "absl/status/status.h" +#include "absl/status/statusor.h" #include "iamf/cli/audio_element_with_data.h" #include "iamf/cli/demixing_module.h" #include "iamf/cli/loudness_calculator_base.h" @@ -90,12 +92,6 @@ class RenderingMixPresentationFinalizer { std::vector layout_rendering_metadata; }; - // Contains rendering metadata for all submixes in a given mix presentation. - struct MixPresentationRenderingMetadata { - DecodedUleb128 mix_presentation_id; - std::vector submix_rendering_metadata; - }; - /*!\brief Factory for a wav writer. * * Used to control whether or not wav writers are created and control their @@ -121,45 +117,43 @@ class RenderingMixPresentationFinalizer { int num_channels, int sample_rate, int bit_depth) const> WavWriterFactory; - /*!\brief Constructor. + /*!\brief Creates a rendering mix presentation finalizer. + * + * Rendering metadata is extracted from the mix presentation OBUs, which will + * be used to render the mix presentations in PushTemporalUnit. * - * \param mix_presentation_metadata Input mix presentation metadata. Only the - * `loudness_metadata` fields are used. + * \param mix_presentation_metadata Input mix presentation metadata. Only + * the `loudness_metadata` fields are used. * \param file_path_prefix Prefix for the output WAV file names. * \param output_wav_file_bit_depth_override If present, overrides the output * WAV file bit depth. - * \param validate_loudness If true, validate the loudness against the user - * provided loudness. - * \param renderer_factory Factory to take control of for creating renderers. - * \param renderer_factory Factory to take control of for creating loudness - * calculators. - */ - RenderingMixPresentationFinalizer( - const std::filesystem::path& file_path_prefix, - std::optional output_wav_file_bit_depth_override, - bool validate_loudness, - std::unique_ptr renderer_factory, - std::unique_ptr - loudness_calculator_factory) - : file_path_prefix_(file_path_prefix), - output_wav_file_bit_depth_override_(output_wav_file_bit_depth_override), - validate_loudness_(validate_loudness), - renderer_factory_(std::move(renderer_factory)), - loudness_calculator_factory_(std::move(loudness_calculator_factory)) {} - - /*!\brief Initializes the rendering mix presentation finalizer. - * - * Rendering metadata is extracted from the mix presentation OBUs, which will - * be used to render the mix presentations in PushTemporalUnit. This must be - * called before PushTemporalUnit or Finalize. + * \param renderer_factory Factory to create renderers, or `nullptr` to + * disable rendering. + * \param loudness_calculator_factory Factory to create loudness calculators + * or `nullptr` to disable loudness calculation. + * \param audio_elements Audio elements with data. + * \param wav_writer_factory Factory to create wav writers. + * \param mix_presentation_obus Output list of OBUs to finalize with initial + * user-provided loudness information. * * \return `absl::OkStatus()` on success. A specific status on failure. */ - absl::Status Initialize( + static absl::StatusOr Create( + const std::filesystem::path& file_path_prefix, + std::optional output_wav_file_bit_depth_override, + absl::Nullable renderer_factory, + absl::Nullable + loudness_calculator_factory, const absl::flat_hash_map& audio_elements, const WavWriterFactory& wav_writer_factory, std::list& mix_presentation_obus); + /*!\brief Move constructor. */ + RenderingMixPresentationFinalizer(RenderingMixPresentationFinalizer&&) = + default; + /*!\brief Destructor. */ + ~RenderingMixPresentationFinalizer() = default; + /*!\brief Renders and writes a single temporal unit. * * Renders a single temporal unit for all mix presentations. It also computes @@ -170,10 +164,8 @@ class RenderingMixPresentationFinalizer { * keyed by audio element ID and channel label. * \param start_timestamp Start timestamp of this temporal unit. * \param end_timestamp End timestamp of this temporal unit. - * \param parameter_blocks_start Start of the Input Parameter Block OBUs - * associated with this temporal unit. - * \param parameter_blocks_end End of the Input Parameter Block OBUs - * associated with this temporal unit. + * \param parameter_blocks Parameter Block OBUs associated with this temporal + * unit. * \param mix_presentation_obus Output list of OBUs to finalize with initial * user-provided loudness information. * \return `absl::OkStatus()` on success. A specific status on failure. @@ -181,11 +173,7 @@ class RenderingMixPresentationFinalizer { absl::Status PushTemporalUnit( const IdLabeledFrameMap& id_to_labeled_frame, int32_t start_timestamp, int32_t end_timestamp, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end, - std::list& mix_presentation_obus); + const std::list& parameter_blocks); /*!\brief Validates and updates loudness for all mix presentations. * @@ -202,13 +190,24 @@ class RenderingMixPresentationFinalizer { std::list& mix_presentation_obus); private: - const std::filesystem::path file_path_prefix_; - const std::optional output_wav_file_bit_depth_override_; - const bool validate_loudness_; + /*!\brief Metadata for all sub mixes within a single mix presentation. */ + struct MixPresentationRenderingMetadata { + DecodedUleb128 mix_presentation_id; + std::vector submix_rendering_metadata; + }; + + /*!\brief Private constructor. + * + * Used only by the factory method. + * + * \param rendering_metadata Mix presentation metadata. + */ + RenderingMixPresentationFinalizer( + std::vector&& rendering_metadata) + : rendering_is_disabled_(rendering_metadata.empty()), + rendering_metadata_(std::move(rendering_metadata)) {} - const std::unique_ptr renderer_factory_; - const std::unique_ptr - loudness_calculator_factory_; + const bool rendering_is_disabled_; std::vector rendering_metadata_; }; diff --git a/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc b/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc index 943bdd4..8023b9b 100644 --- a/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc +++ b/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc @@ -249,31 +249,26 @@ class FinalizerTest : public ::testing::Test { AddLabeledFrame(kAudioElementId, kLabelToSamples, kEndTime); } - RenderingMixPresentationFinalizer GetFinalizer() { - return RenderingMixPresentationFinalizer( + RenderingMixPresentationFinalizer CreateFinalizerExpectOk() { + auto finalizer = RenderingMixPresentationFinalizer::Create( output_directory_, output_wav_file_bit_depth_override_, - validate_loudness_, std::move(renderer_factory_), - std::move(loudness_calculator_factory_)); + renderer_factory_.get(), loudness_calculator_factory_.get(), + audio_elements_, wav_writer_factory_, obus_to_finalize_); + EXPECT_THAT(finalizer, IsOk()); + return *std::move(finalizer); } void IterativeRenderingExpectOk( RenderingMixPresentationFinalizer& finalizer, - const std::list::const_iterator& - parameter_blocks_start, - const std::list::const_iterator& - parameter_blocks_end) { - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + const std::list& parameter_blocks) { int64_t start_timestamp = 0; for (const auto& id_to_labeled_frame : ordered_labeled_frames_) { ASSERT_TRUE(id_to_labeled_frame.contains(kAudioElementId)); - EXPECT_THAT( - finalizer.PushTemporalUnit( - id_to_labeled_frame, start_timestamp, - id_to_labeled_frame.at(kAudioElementId).end_timestamp, - parameter_blocks_start, parameter_blocks_end, obus_to_finalize_), - IsOk()); + EXPECT_THAT(finalizer.PushTemporalUnit( + id_to_labeled_frame, start_timestamp, + id_to_labeled_frame.at(kAudioElementId).end_timestamp, + parameter_blocks), + IsOk()); } EXPECT_THAT(finalizer.Finalize(validate_loudness_, obus_to_finalize_), @@ -287,7 +282,7 @@ class FinalizerTest : public ::testing::Test { std::list obus_to_finalize_; std::list parameter_blocks_; - // Finalizer constructor settings. Default to simplistic inputs that disable + // Finalizer create settings. Default to simplistic inputs that disable // most features. std::filesystem::path output_directory_ = GetAndCreateOutputDirectory(""); std::optional output_wav_file_bit_depth_override_ = @@ -302,28 +297,28 @@ class FinalizerTest : public ::testing::Test { std::vector ordered_labeled_frames_; }; -// === Tests that the constructor does not crash with various modes disabled === +// =Tests that the create function does not crash with various modes disabled.= -TEST_F(FinalizerTest, ConstructorDoesNotCrashWithMockFactories) { +TEST_F(FinalizerTest, CreateDoesNotCrashWithMockFactories) { renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = std::make_unique(); - GetFinalizer(); + CreateFinalizerExpectOk(); } -TEST_F(FinalizerTest, ConstructorDoesNotCrashWhenRendererFactoryIsNullptr) { +TEST_F(FinalizerTest, CreateDoesNotCrashWhenRendererFactoryIsNullptr) { renderer_factory_ = nullptr; - GetFinalizer(); + CreateFinalizerExpectOk(); } TEST_F(FinalizerTest, - ConstructorDoesNotCrashWhenLoudnessCalculatorFactoryIsNullptr) { + CreateDoesNotCrashWhenLoudnessCalculatorFactoryIsNullptr) { renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = nullptr; - GetFinalizer(); + CreateFinalizerExpectOk(); } // =========== Tests that work is delegated to the renderer factory. =========== @@ -346,11 +341,8 @@ TEST_F(FinalizerTest, ForwardsAudioElementToRenderer) { forwarded_audio_element.obu.config_, _, _, forwarded_audio_element.codec_config->GetNumSamplesPerFrame())); renderer_factory_ = std::move(mock_renderer_factory); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + auto finalizer = CreateFinalizerExpectOk(); } TEST_F(FinalizerTest, ForwardsRenderingConfigToRenderer) { @@ -368,11 +360,8 @@ TEST_F(FinalizerTest, ForwardsRenderingConfigToRenderer) { *mock_renderer_factory, CreateRendererForLayout(_, _, _, _, forwarded_rendering_config, _, _)); renderer_factory_ = std::move(mock_renderer_factory); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + CreateFinalizerExpectOk(); } TEST_F(FinalizerTest, ForwardsLayoutToRenderer) { @@ -388,11 +377,8 @@ TEST_F(FinalizerTest, ForwardsLayoutToRenderer) { EXPECT_CALL(*mock_renderer_factory, CreateRendererForLayout(_, _, _, _, _, forwarded_layout, _)); renderer_factory_ = std::move(mock_renderer_factory); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + CreateFinalizerExpectOk(); } TEST_F(FinalizerTest, ForwardsOrderedSamplesToRenderer) { @@ -417,10 +403,8 @@ TEST_F(FinalizerTest, ForwardsOrderedSamplesToRenderer) { renderer_factory_ = std::move(mock_renderer_factory); std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + auto finalizer = CreateFinalizerExpectOk(); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); } TEST_F(FinalizerTest, CreatesWavFileWhenRenderingIsSupported) { @@ -438,9 +422,9 @@ TEST_F(FinalizerTest, CreatesWavFileWhenRenderingIsSupported) { .WillOnce(Return(std::move(mock_renderer))); renderer_factory_ = std::move(mock_renderer_factory); std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + + auto finalizer = CreateFinalizerExpectOk(); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); EXPECT_TRUE(std::filesystem::exists(GetFirstSubmixFirstLayoutExpectedPath())); } @@ -454,10 +438,9 @@ TEST_F(FinalizerTest, DoesNotCreateFilesWhenRenderingFactoryIsNullptr) { GetAndCreateOutputDirectory(""); renderer_factory_ = nullptr; std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + auto finalizer = CreateFinalizerExpectOk(); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); EXPECT_TRUE(std::filesystem::is_empty(output_directory)); } @@ -472,10 +455,9 @@ TEST_F(FinalizerTest, DoesNotCreateFilesWhenRenderingFactoryReturnsNullptr) { wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; renderer_factory_ = std::make_unique(); std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + auto finalizer = CreateFinalizerExpectOk(); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); EXPECT_TRUE(std::filesystem::is_empty(output_directory)); } @@ -490,10 +472,9 @@ TEST_F(FinalizerTest, UsesCodecConfigBitDepthWhenOverrideIsNotSet) { renderer_factory_ = std::make_unique(); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); const auto wav_reader = CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath()); @@ -509,10 +490,9 @@ TEST_F(FinalizerTest, OverridesBitDepthWhenRequested) { wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; output_wav_file_bit_depth_override_ = 32; std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); const auto wav_reader = CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath()); @@ -529,18 +509,14 @@ TEST_F(FinalizerTest, InvalidWhenFrameIsLargerThanNumSamplesPerFrame) { kEndTime); renderer_factory_ = std::make_unique(); std::list parameter_blocks; + auto finalizer = CreateFinalizerExpectOk(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); EXPECT_FALSE( finalizer .PushTemporalUnit( ordered_labeled_frames_[0], kStartTime, ordered_labeled_frames_[0].at(kAudioElementId).end_timestamp, - parameter_blocks.begin(), parameter_blocks.end(), - obus_to_finalize_) + parameter_blocks) .ok()); } @@ -553,10 +529,9 @@ TEST_F(FinalizerTest, WavFileHasExpectedProperties) { renderer_factory_ = std::make_unique(); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); const auto wav_reader = CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath()); @@ -579,10 +554,9 @@ TEST_F(FinalizerTest, SamplesAreTrimmedFromWavFile) { renderer_factory_ = std::make_unique(); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); const auto wav_reader = CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath()); @@ -603,10 +577,9 @@ TEST_F(FinalizerTest, SupportsFullyTrimmedFrames) { renderer_factory_ = std::make_unique(); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); - IterativeRenderingExpectOk(finalizer, parameter_blocks_.begin(), - parameter_blocks_.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); const auto wav_reader = CreateWavReaderExpectOk(GetFirstSubmixFirstLayoutExpectedPath()); @@ -630,20 +603,23 @@ const LoudnessInfo kArbitraryLoudnessInfo = { TEST_F(FinalizerTest, CreatesWavFilesBasedOnFactoryFunction) { PrepareObusForOneSamplePassThroughMono(); - renderer_factory_ = std::make_unique(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); // A factory can be used to omit generating the wav file. + renderer_factory_ = std::make_unique(); wav_writer_factory_ = ProduceNoWavWriters; - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), + auto finalizer_without_wav_writers = CreateFinalizerExpectOk(); + EXPECT_THAT(finalizer_without_wav_writers.Finalize(validate_loudness_, + obus_to_finalize_), IsOk()); EXPECT_FALSE( std::filesystem::exists(GetFirstSubmixFirstLayoutExpectedPath())); + // Or a factory can be used to create it. + renderer_factory_ = std::make_unique(); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), + auto finalizer_with_wav_writers = CreateFinalizerExpectOk(); + EXPECT_THAT(finalizer_with_wav_writers.Finalize(validate_loudness_, + obus_to_finalize_), IsOk()); EXPECT_TRUE(std::filesystem::exists(GetFirstSubmixFirstLayoutExpectedPath())); } @@ -666,11 +642,8 @@ TEST_F(FinalizerTest, ForwardsArgumentsToLoudnessCalculatorFactory) { forwarded_bit_depth_to_measure_loudness)); renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + auto finalizer = CreateFinalizerExpectOk(); } TEST_F(FinalizerTest, DelegatestoLoudnessCalculator) { @@ -700,12 +673,11 @@ TEST_F(FinalizerTest, DelegatestoLoudnessCalculator) { renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory); std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness = kMismatchingUserLoudness; - IterativeRenderingExpectOk(finalizer, parameter_blocks.begin(), - parameter_blocks.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); // Data was copied based on `QueryLoudness()`. EXPECT_EQ(obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness, @@ -735,16 +707,12 @@ TEST_F(FinalizerTest, ValidatesUserLoudnessWhenRequested) { renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory); std::list parameter_blocks; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); EXPECT_THAT( finalizer.PushTemporalUnit(ordered_labeled_frames_[0], /*start_timestamp=*/0, - /*end_timestamp=*/10, parameter_blocks.begin(), - parameter_blocks.end(), obus_to_finalize_), + /*end_timestamp=*/10, parameter_blocks), IsOk()); EXPECT_FALSE(finalizer.Finalize(validate_loudness_, obus_to_finalize_).ok()); @@ -753,29 +721,23 @@ TEST_F(FinalizerTest, ValidatesUserLoudnessWhenRequested) { //============== Various modes fallback to preserving loudness. ============== void FinalizeOneFrameAndExpectUserLoudnessIsPreserved( - const absl::flat_hash_map& - audio_elements, const std::vector& ordered_labeled_frames_, RenderingMixPresentationFinalizer& finalizer, std::list& obus_to_finalize) { obus_to_finalize.front().sub_mixes_[0].layouts[0].loudness = kArbitraryLoudnessInfo; std::list parameter_blocks; - EXPECT_THAT(finalizer.Initialize(audio_elements, ProduceNoWavWriters, - obus_to_finalize), - IsOk()); int64_t start_timestamp = 0; for (const auto& id_to_labeled_frame : ordered_labeled_frames_) { ASSERT_TRUE(id_to_labeled_frame.contains(kAudioElementId)); - EXPECT_THAT( - finalizer.PushTemporalUnit( - id_to_labeled_frame, start_timestamp, - id_to_labeled_frame.at(kAudioElementId).end_timestamp, - parameter_blocks.begin(), parameter_blocks.end(), obus_to_finalize), - IsOk()); + EXPECT_THAT(finalizer.PushTemporalUnit( + id_to_labeled_frame, start_timestamp, + id_to_labeled_frame.at(kAudioElementId).end_timestamp, + parameter_blocks), + IsOk()); } - EXPECT_THAT(finalizer.Finalize(/*validate_loudness=*/true, obus_to_finalize), + EXPECT_THAT(finalizer.Finalize(kDontValidateLoudness, obus_to_finalize), IsOk()); const auto& loudness = @@ -786,10 +748,10 @@ void FinalizeOneFrameAndExpectUserLoudnessIsPreserved( TEST_F(FinalizerTest, PreservesUserLoudnessWhenRenderFactoryIsNullptr) { PrepareObusForOneSamplePassThroughMono(); renderer_factory_ = nullptr; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); FinalizeOneFrameAndExpectUserLoudnessIsPreserved( - audio_elements_, ordered_labeled_frames_, finalizer, obus_to_finalize_); + ordered_labeled_frames_, finalizer, obus_to_finalize_); } TEST_F(FinalizerTest, PreservesUserLoudnessWhenRenderingIsNotSupported) { @@ -797,20 +759,20 @@ TEST_F(FinalizerTest, PreservesUserLoudnessWhenRenderingIsNotSupported) { renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = std::make_unique(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); FinalizeOneFrameAndExpectUserLoudnessIsPreserved( - audio_elements_, ordered_labeled_frames_, finalizer, obus_to_finalize_); + ordered_labeled_frames_, finalizer, obus_to_finalize_); } TEST_F(FinalizerTest, PreservesUserLoudnessWhenLoudnessFactoryIsNullPtr) { PrepareObusForOneSamplePassThroughMono(); renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = nullptr; - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); FinalizeOneFrameAndExpectUserLoudnessIsPreserved( - audio_elements_, ordered_labeled_frames_, finalizer, obus_to_finalize_); + ordered_labeled_frames_, finalizer, obus_to_finalize_); } TEST_F(FinalizerTest, PreservesUserLoudnessWhenLoudnessFactoryReturnsNullPtr) { @@ -818,22 +780,19 @@ TEST_F(FinalizerTest, PreservesUserLoudnessWhenLoudnessFactoryReturnsNullPtr) { renderer_factory_ = std::make_unique(); loudness_calculator_factory_ = std::make_unique(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); + auto finalizer = CreateFinalizerExpectOk(); FinalizeOneFrameAndExpectUserLoudnessIsPreserved( - audio_elements_, ordered_labeled_frames_, finalizer, obus_to_finalize_); + ordered_labeled_frames_, finalizer, obus_to_finalize_); } -TEST_F(FinalizerTest, InitializeSucceedsWithValidInput) { +TEST_F(FinalizerTest, CreateSucceedsWithValidInput) { InitPrerequisiteObusForStereoInput(kAudioElementId); AddMixPresentationObuForStereoOutput(kMixPresentationId); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; renderer_factory_ = std::make_unique(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + auto finalizer = CreateFinalizerExpectOk(); } TEST_F(FinalizerTest, FinalizeFailsIfCalledTwice) { @@ -842,10 +801,7 @@ TEST_F(FinalizerTest, FinalizeFailsIfCalledTwice) { wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; renderer_factory_ = std::make_unique(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + auto finalizer = CreateFinalizerExpectOk(); EXPECT_THAT(finalizer.Finalize(validate_loudness_, obus_to_finalize_), IsOk()); EXPECT_FALSE(finalizer.Finalize(validate_loudness_, obus_to_finalize_).ok()); @@ -869,15 +825,11 @@ TEST_F(FinalizerTest, PushTemporalUnitSucceedsWithValidInput) { ASSERT_EQ(ordered_labeled_frames_.size(), 1); wav_writer_factory_ = ProduceFirstSubMixFirstLayoutWavWriter; renderer_factory_ = std::make_unique(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + auto finalizer = CreateFinalizerExpectOk(); EXPECT_THAT( finalizer.PushTemporalUnit(ordered_labeled_frames_[0], /*start_timestamp=*/0, - /*end_timestamp=*/10, parameter_blocks.begin(), - parameter_blocks.end(), obus_to_finalize_), + /*end_timestamp=*/10, parameter_blocks), IsOk()); } @@ -908,11 +860,9 @@ TEST_F(FinalizerTest, FullIterativeRenderingSucceedsWithValidInput) { .WillOnce(Return(std::move(mock_loudness_calculator))); loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory); validate_loudness_ = false; + auto finalizer = CreateFinalizerExpectOk(); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - - IterativeRenderingExpectOk(finalizer, parameter_blocks.begin(), - parameter_blocks.end()); + IterativeRenderingExpectOk(finalizer, parameter_blocks_); // Then we expect the loudness to be populated with the computed loudness. EXPECT_EQ(obus_to_finalize_.front().sub_mixes_[0].layouts[0].loudness, @@ -946,20 +896,16 @@ TEST_F(FinalizerTest, InvalidComputedLoudnessFails) { .WillOnce(Return(std::move(mock_loudness_calculator))); loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + auto finalizer = CreateFinalizerExpectOk(); EXPECT_THAT( finalizer.PushTemporalUnit(ordered_labeled_frames_[0], /*start_timestamp=*/0, - /*end_timestamp=*/10, parameter_blocks.begin(), - parameter_blocks.end(), obus_to_finalize_), + /*end_timestamp=*/10, parameter_blocks), IsOk()); // Do validate that computed loudness matches the user provided loudness - // since kArbitraryLoudnessInfo is the `computed` loudness, it won't. - EXPECT_FALSE( - finalizer.Finalize(/*validate_loudness=*/true, obus_to_finalize_).ok()); + validate_loudness_ = true; + EXPECT_FALSE(finalizer.Finalize(validate_loudness_, obus_to_finalize_).ok()); } TEST_F(FinalizerTest, OutofOrderMixPresentationObusFailOnFinalize) { @@ -985,21 +931,17 @@ TEST_F(FinalizerTest, OutofOrderMixPresentationObusFailOnFinalize) { auto mock_loudness_calculator = std::make_unique(); loudness_calculator_factory_ = std::move(mock_loudness_calculator_factory); - RenderingMixPresentationFinalizer finalizer = GetFinalizer(); - EXPECT_THAT(finalizer.Initialize(audio_elements_, wav_writer_factory_, - obus_to_finalize_), - IsOk()); + validate_loudness_ = false; + auto finalizer = CreateFinalizerExpectOk(); EXPECT_THAT( finalizer.PushTemporalUnit(ordered_labeled_frames_[0], /*start_timestamp=*/0, - /*end_timestamp=*/10, parameter_blocks.begin(), - parameter_blocks.end(), obus_to_finalize_), + /*end_timestamp=*/10, parameter_blocks), IsOk()); // Reverse the list of OBUs to finalize. This will cause the mix presentation // ID to be out of order with respect to the rendering metadata. std::reverse(obus_to_finalize_.begin(), obus_to_finalize_.end()); - EXPECT_FALSE( - finalizer.Finalize(/*validate_loudness=*/false, obus_to_finalize_).ok()); + EXPECT_FALSE(finalizer.Finalize(validate_loudness_, obus_to_finalize_).ok()); } } // namespace