diff --git a/iamf/cli/renderer/BUILD b/iamf/cli/renderer/BUILD index 7bbaa7f..da0b424 100644 --- a/iamf/cli/renderer/BUILD +++ b/iamf/cli/renderer/BUILD @@ -16,11 +16,12 @@ cc_library( "//iamf/obu:audio_element", "//iamf/obu:mix_presentation", "//iamf/obu:types", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/log", "@com_google_absl//absl/memory", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", - "@com_google_absl//absl/synchronization", + "@com_google_absl//absl/types:span", ], ) @@ -59,6 +60,7 @@ cc_library( "//iamf/obu:audio_element", "//iamf/obu:mix_presentation", "//iamf/obu:types", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:no_destructor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/log", @@ -66,7 +68,7 @@ cc_library( "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", - "@com_google_absl//absl/synchronization", + "@com_google_absl//absl/types:span", ], ) @@ -84,6 +86,7 @@ cc_library( "//iamf/obu:audio_element", "//iamf/obu:mix_presentation", "//iamf/obu:types", + "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:no_destructor", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/functional:any_invocable", @@ -92,7 +95,6 @@ cc_library( "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", - "@com_google_absl//absl/synchronization", "@com_google_absl//absl/types:span", ], ) @@ -120,6 +122,7 @@ cc_library( "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:string_view", + "@com_google_absl//absl/types:span", ], ) diff --git a/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.cc b/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.cc index 7ffccc3..83e691e 100644 --- a/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.cc +++ b/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.cc @@ -22,7 +22,7 @@ #include "absl/memory/memory.h" #include "absl/status/status.h" #include "absl/strings/str_cat.h" -#include "absl/synchronization/mutex.h" +#include "absl/types/span.h" #include "iamf/cli/audio_element_with_data.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/proto/mix_presentation.pb.h" @@ -135,7 +135,7 @@ AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( const AmbisonicsConfig& ambisonics_config, const std::vector& audio_substream_ids, const SubstreamIdLabelsMap& substream_id_to_labels, - const Layout& playback_layout) { + const Layout& playback_layout, size_t num_samples_per_frame) { // Exclude unsupported modes first, and deal with only mono or projection // in the rest of the code. const auto mode = ambisonics_config.ambisonics_mode; @@ -194,15 +194,14 @@ AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( } return absl::WrapUnique(new AudioElementRendererAmbisonicsToChannel( - static_cast(num_output_channels), ambisonics_config, - channel_labels, *gains)); + static_cast(num_output_channels), num_samples_per_frame, + ambisonics_config, channel_labels, *gains)); } absl::Status AudioElementRendererAmbisonicsToChannel::RenderSamples( - const std::vector>& samples_to_render, + absl::Span> samples_to_render, std::vector& rendered_samples) { // Render the samples. - absl::MutexLock lock(&mutex_); RETURN_IF_NOT_OK(RenderAmbisonicsToLoudspeakers( samples_to_render, ambisonics_config_, gains_, rendered_samples)); diff --git a/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.h b/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.h index be3fa82..0a5c920 100644 --- a/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.h +++ b/iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.h @@ -15,7 +15,9 @@ #include #include +#include "absl/base/thread_annotations.h" #include "absl/status/status.h" +#include "absl/types/span.h" #include "iamf/cli/audio_element_with_data.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/renderer/audio_element_renderer_base.h" @@ -50,6 +52,7 @@ class AudioElementRendererAmbisonicsToChannel * \param audio_substream_ids Audio substream IDs. * \param substream_id_to_labels Mapping of substream IDs to labels. * \param playback_layout Layout of the audio element to be rendered. + * \param num_samples_per_frame Number of samples per frame. * \return Render to use or `nullptr` on failure. */ static std::unique_ptr @@ -57,7 +60,7 @@ class AudioElementRendererAmbisonicsToChannel const AmbisonicsConfig& ambisonics_config, const std::vector& audio_substream_ids, const SubstreamIdLabelsMap& substream_id_to_labels, - const Layout& playback_layout); + const Layout& playback_layout, size_t num_samples_per_frame); /*!\brief Destructor. */ ~AudioElementRendererAmbisonicsToChannel() override = default; @@ -73,10 +76,12 @@ class AudioElementRendererAmbisonicsToChannel * \param gains Gains matrix. */ AudioElementRendererAmbisonicsToChannel( - size_t num_output_channels, const AmbisonicsConfig& ambisonics_config, + size_t num_output_channels, size_t num_samples_per_frame, + const AmbisonicsConfig& ambisonics_config, const std::vector& ordered_labels, const std::vector>& gains) - : AudioElementRendererBase(ordered_labels, num_output_channels), + : AudioElementRendererBase(ordered_labels, num_samples_per_frame, + num_output_channels), ambisonics_config_(ambisonics_config), gains_(gains) {} @@ -87,8 +92,9 @@ class AudioElementRendererAmbisonicsToChannel * \return `absl::OkStatus()` on success. A specific status on failure. */ absl::Status RenderSamples( - const std::vector>& samples_to_render, - std::vector& rendered_samples) override; + absl::Span> samples_to_render, + std::vector& rendered_samples) + ABSL_SHARED_LOCKS_REQUIRED(mutex_) override; const AmbisonicsConfig ambisonics_config_; diff --git a/iamf/cli/renderer/audio_element_renderer_base.cc b/iamf/cli/renderer/audio_element_renderer_base.cc index 6fcaf32..7cab8fc 100644 --- a/iamf/cli/renderer/audio_element_renderer_base.cc +++ b/iamf/cli/renderer/audio_element_renderer_base.cc @@ -11,11 +11,13 @@ */ #include "iamf/cli/renderer/audio_element_renderer_base.h" +#include #include #include "absl/log/check.h" #include "absl/status/status.h" #include "absl/synchronization/mutex.h" +#include "absl/types/span.h" #include "iamf/cli/demixing_module.h" #include "iamf/cli/renderer/renderer_utils.h" #include "iamf/common/macros.h" @@ -25,35 +27,37 @@ namespace iamf_tools { AudioElementRendererBase::~AudioElementRendererBase() {} -absl::Status AudioElementRendererBase::Flush( - std::vector& rendered_samples) { +absl::StatusOr AudioElementRendererBase::RenderLabeledFrame( + const LabeledFrame& labeled_frame) { absl::MutexLock lock(&mutex_); - rendered_samples.insert(rendered_samples.end(), rendered_samples_.begin(), - rendered_samples_.end()); - rendered_samples_.clear(); - return absl::OkStatus(); -} -absl::StatusOr AudioElementRendererBase::RenderLabeledFrame( - const LabeledFrame& labeled_frame) { - std::vector> samples_to_render; + size_t num_valid_samples = 0; RETURN_IF_NOT_OK(iamf_tools::renderer_utils::ArrangeSamplesToRender( - labeled_frame, ordered_labels_, samples_to_render)); + labeled_frame, ordered_labels_, samples_to_render_, num_valid_samples)); // Render samples in concrete subclasses. - mutex_.Lock(); current_labeled_frame_ = &labeled_frame; - mutex_.Unlock(); + std::vector rendered_samples( - num_output_channels_ * samples_to_render.size(), 0); - RETURN_IF_NOT_OK(RenderSamples(samples_to_render, rendered_samples)); + num_output_channels_ * num_valid_samples, 0); + RETURN_IF_NOT_OK(RenderSamples( + absl::MakeConstSpan(samples_to_render_).first(num_valid_samples), + rendered_samples)); // Copy rendered samples to the output. - absl::MutexLock lock(&mutex_); rendered_samples_.insert(rendered_samples_.end(), rendered_samples.begin(), rendered_samples.end()); - return samples_to_render.size(); + return num_valid_samples; +} + +absl::Status AudioElementRendererBase::Flush( + std::vector& rendered_samples) { + absl::MutexLock lock(&mutex_); + rendered_samples.insert(rendered_samples.end(), rendered_samples_.begin(), + rendered_samples_.end()); + rendered_samples_.clear(); + return absl::OkStatus(); } } // namespace iamf_tools diff --git a/iamf/cli/renderer/audio_element_renderer_base.h b/iamf/cli/renderer/audio_element_renderer_base.h index 65d4c29..726d183 100644 --- a/iamf/cli/renderer/audio_element_renderer_base.h +++ b/iamf/cli/renderer/audio_element_renderer_base.h @@ -49,10 +49,10 @@ class AudioElementRendererBase { /*!\brief Renders samples stored in labeled frames. * * \param labeled_frame Labeled frame to render. - * \return Number of ticks which will be rendered. A specific status on + * \return Number of ticks that will be rendered. A specific status on * failure. */ - absl::StatusOr RenderLabeledFrame(const LabeledFrame& labeled_frame); + absl::StatusOr RenderLabeledFrame(const LabeledFrame& labeled_frame); /*!\brief Flushes finished audio frames. * @@ -87,12 +87,18 @@ class AudioElementRendererBase { /*!\brief Constructor. * * \param ordered_labels Ordered list of channel labels to render. + * \param num_samples_per_frame Number of samples per frame. * \param num_output_channels Number of output channels. */ AudioElementRendererBase(absl::Span ordered_labels, + const size_t num_samples_per_frame, const size_t num_output_channels) : ordered_labels_(ordered_labels.begin(), ordered_labels.end()), - num_output_channels_(num_output_channels) {} + num_samples_per_frame_(num_samples_per_frame), + num_output_channels_(num_output_channels), + samples_to_render_( + num_samples_per_frame_, + std::vector(ordered_labels_.size(), 0)) {} /*!\brief Renders samples. * @@ -101,14 +107,18 @@ class AudioElementRendererBase { * \return `absl::OkStatus()` on success. A specific status on failure. */ virtual absl::Status RenderSamples( - const std::vector>& samples_to_render, - std::vector& rendered_samples) = 0; + absl::Span> samples_to_render, + std::vector& rendered_samples) + ABSL_SHARED_LOCKS_REQUIRED(mutex_) = 0; const std::vector ordered_labels_; + const size_t num_samples_per_frame_ = 0; const size_t num_output_channels_; // Mutex to guard simultaneous access to data members. mutable absl::Mutex mutex_; + std::vector> samples_to_render_ + ABSL_GUARDED_BY(mutex_); std::vector rendered_samples_ ABSL_GUARDED_BY(mutex_); bool is_finalized_ ABSL_GUARDED_BY(mutex_) = false; const LabeledFrame* current_labeled_frame_ ABSL_GUARDED_BY(mutex_) = nullptr; diff --git a/iamf/cli/renderer/audio_element_renderer_channel_to_channel.cc b/iamf/cli/renderer/audio_element_renderer_channel_to_channel.cc index 315be82..1c6fc5f 100644 --- a/iamf/cli/renderer/audio_element_renderer_channel_to_channel.cc +++ b/iamf/cli/renderer/audio_element_renderer_channel_to_channel.cc @@ -26,7 +26,7 @@ #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" +#include "absl/types/span.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/proto/mix_presentation.pb.h" #include "iamf/cli/proto/test_vector_metadata.pb.h" @@ -117,7 +117,7 @@ absl::StatusOr LookupInputKeyFromLoudspeakerLayout( std::unique_ptr AudioElementRendererChannelToChannel::CreateFromScalableChannelLayoutConfig( const ScalableChannelLayoutConfig& scalable_channel_layout_config, - const Layout& playback_layout) { + const Layout& playback_layout, size_t num_samples_per_frame) { if (scalable_channel_layout_config.channel_audio_layer_configs.empty()) { LOG(ERROR) << "No channel audio layer configs provided."; return nullptr; @@ -162,14 +162,13 @@ AudioElementRendererChannelToChannel::CreateFromScalableChannelLayoutConfig( return absl::WrapUnique(new AudioElementRendererChannelToChannel( *input_key, *output_key, static_cast(num_output_channels), - *ordered_labels, *gains)); + num_samples_per_frame, *ordered_labels, *gains)); } absl::Status AudioElementRendererChannelToChannel::RenderSamples( - const std::vector>& samples_to_render, + absl::Span> samples_to_render, std::vector& rendered_samples) { // Render the samples. - absl::MutexLock lock(&mutex_); RETURN_IF_NOT_OK(RenderChannelLayoutToLoudspeakers( samples_to_render, current_labeled_frame_->demixing_params, ordered_labels_, input_key_, output_key_, gains_, rendered_samples)); diff --git a/iamf/cli/renderer/audio_element_renderer_channel_to_channel.h b/iamf/cli/renderer/audio_element_renderer_channel_to_channel.h index 96b1c93..fbff8a4 100644 --- a/iamf/cli/renderer/audio_element_renderer_channel_to_channel.h +++ b/iamf/cli/renderer/audio_element_renderer_channel_to_channel.h @@ -16,8 +16,10 @@ #include #include +#include "absl/base/thread_annotations.h" #include "absl/status/status.h" #include "absl/strings/string_view.h" +#include "absl/types/span.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/renderer/audio_element_renderer_base.h" #include "iamf/obu/audio_element.h" @@ -49,12 +51,13 @@ class AudioElementRendererChannelToChannel : public AudioElementRendererBase { * \param scalable_channel_layout_config Config for the scalable channel * layout. * \param playback_layout Layout of the audio element to be rendered. + * \param num_samples_per_frame Number of samples per frame. * \return Render to use or `nullptr` on failure. */ static std::unique_ptr CreateFromScalableChannelLayoutConfig( const ScalableChannelLayoutConfig& scalable_channel_layout_config, - const Layout& playback_layout); + const Layout& playback_layout, size_t num_samples_per_frame); /*!\brief Destructor. */ ~AudioElementRendererChannelToChannel() override = default; @@ -67,14 +70,16 @@ class AudioElementRendererChannelToChannel : public AudioElementRendererBase { * \param input_key Key representing the input loudspeaker layout. * \param output_key Key representing the output loudspeaker layout. * \param num_output_channels Number of output channels. + * \param num_samples_per_frame Number of samples per frame. * \param ordered_labels Ordered list of channel labels to render. */ AudioElementRendererChannelToChannel( absl::string_view input_key, absl::string_view output_key, - size_t num_output_channels, + size_t num_output_channels, size_t num_samples_per_frame, const std::vector& ordered_labels, const std::vector>& gains) - : AudioElementRendererBase(ordered_labels, num_output_channels), + : AudioElementRendererBase(ordered_labels, num_samples_per_frame, + num_output_channels), input_key_(input_key), output_key_(output_key), gains_(gains) {} @@ -86,8 +91,9 @@ class AudioElementRendererChannelToChannel : public AudioElementRendererBase { * \return `absl::OkStatus()` on success. A specific status on failure. */ absl::Status RenderSamples( - const std::vector>& samples_to_render, - std::vector& rendered_samples) override; + absl::Span> samples_to_render, + std::vector& rendered_samples) + ABSL_SHARED_LOCKS_REQUIRED(mutex_) override; const std::string input_key_; const std::string output_key_; diff --git a/iamf/cli/renderer/audio_element_renderer_passthrough.cc b/iamf/cli/renderer/audio_element_renderer_passthrough.cc index 418011b..9c504d1 100644 --- a/iamf/cli/renderer/audio_element_renderer_passthrough.cc +++ b/iamf/cli/renderer/audio_element_renderer_passthrough.cc @@ -13,6 +13,7 @@ #include "iamf/cli/renderer/audio_element_renderer_passthrough.h" +#include #include #include @@ -24,7 +25,6 @@ #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" -#include "absl/synchronization/mutex.h" #include "absl/types/span.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/proto/mix_presentation.pb.h" @@ -159,7 +159,7 @@ absl::StatusOr FindEquivalentLayer( std::unique_ptr AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( const ScalableChannelLayoutConfig& scalable_channel_layout_config, - const Layout& playback_layout) { + const Layout& playback_layout, size_t num_samples_per_frame) { const auto& equivalent_layer = FindEquivalentLayer(scalable_channel_layout_config, playback_layout); if (!equivalent_layer.ok()) { @@ -173,14 +173,14 @@ AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( return nullptr; } - return absl::WrapUnique(new AudioElementRendererPassThrough(*ordered_labels)); + return absl::WrapUnique(new AudioElementRendererPassThrough( + *ordered_labels, num_samples_per_frame)); } absl::Status AudioElementRendererPassThrough::RenderSamples( - const std::vector>& samples_to_render, + absl::Span> samples_to_render, std::vector& rendered_samples) { // Flatten the (time, channel) axes into interleaved samples. - absl::MutexLock lock(&mutex_); const absl::AnyInvocable kIdentityTransform = @@ -189,8 +189,8 @@ absl::Status AudioElementRendererPassThrough::RenderSamples( return absl::OkStatus(); }; - return ConvertTimeChannelToInterleaved(absl::MakeConstSpan(samples_to_render), - kIdentityTransform, rendered_samples); + return ConvertTimeChannelToInterleaved(samples_to_render, kIdentityTransform, + rendered_samples); } } // namespace iamf_tools diff --git a/iamf/cli/renderer/audio_element_renderer_passthrough.h b/iamf/cli/renderer/audio_element_renderer_passthrough.h index 8900364..d42952a 100644 --- a/iamf/cli/renderer/audio_element_renderer_passthrough.h +++ b/iamf/cli/renderer/audio_element_renderer_passthrough.h @@ -11,10 +11,13 @@ */ #ifndef CLI_RENDERER_AUDIO_ELEMENT_RENDERER_PASSTHROUGH_H_ #define CLI_RENDERER_AUDIO_ELEMENT_RENDERER_PASSTHROUGH_H_ +#include #include #include +#include "absl/base/thread_annotations.h" #include "absl/status/status.h" +#include "absl/types/span.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/renderer/audio_element_renderer_base.h" #include "iamf/obu/audio_element.h" @@ -51,13 +54,14 @@ class AudioElementRendererPassThrough : public AudioElementRendererBase { * * \param scalable_channel_layout_config Config for the scalable channel * layout. - * \param playback_layout Layout of the audio element to be rendered. + * \param playback_layout Layout of the audio element to be rendered + * \param num_samples_per_frame Number of samples per frame. * \return Render to use or `nullptr` if it would not be suitable for use. */ static std::unique_ptr CreateFromScalableChannelLayoutConfig( const ScalableChannelLayoutConfig& scalable_channel_layout_config, - const Layout& playback_layout); + const Layout& playback_layout, size_t num_samples_per_frame); /*!\brief Destructor. */ ~AudioElementRendererPassThrough() override = default; @@ -68,11 +72,13 @@ class AudioElementRendererPassThrough : public AudioElementRendererBase { * \param ordered_labels Ordered list of channel labels to render. */ AudioElementRendererPassThrough( - const std::vector& ordered_labels) + const std::vector& ordered_labels, + size_t num_samples_per_frame) : AudioElementRendererBase( ordered_labels, // For a passthrough renderer, (number of output channels) // is the same as (number of input channels). + num_samples_per_frame, /*num_output_channels=*/ordered_labels.size()) {} /*!\brief Renders samples. @@ -82,8 +88,9 @@ class AudioElementRendererPassThrough : public AudioElementRendererBase { * \return `absl::OkStatus()` on success. A specific status on failure. */ absl::Status RenderSamples( - const std::vector>& samples_to_render, - std::vector& rendered_samples) override; + absl::Span> samples_to_render, + std::vector& rendered_samples) + ABSL_SHARED_LOCKS_REQUIRED(mutex_) override; }; } // namespace iamf_tools diff --git a/iamf/cli/renderer/loudspeakers_renderer.cc b/iamf/cli/renderer/loudspeakers_renderer.cc index 1fe98de..040b3da 100644 --- a/iamf/cli/renderer/loudspeakers_renderer.cc +++ b/iamf/cli/renderer/loudspeakers_renderer.cc @@ -26,6 +26,7 @@ #include "absl/status/status.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" +#include "absl/types/span.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/renderer/precomputed_gains.h" #include "iamf/common/macros.h" @@ -162,7 +163,7 @@ double Q15ToSignedDouble(const int16_t input) { } std::vector> ProjectSamplesToRender( - const std::vector>& input_samples, + absl::Span>& input_samples, const int16_t* demixing_matrix, const int output_channel_count) { CHECK_NE(demixing_matrix, nullptr); std::vector> samples_to_render( @@ -188,15 +189,20 @@ std::vector> ProjectSamplesToRender( } void RenderSamplesUsingGains( - const std::vector>& input_samples, + absl::Span>& input_samples, const std::vector>& gains, const int16_t* demixing_matrix, std::vector& rendered_samples) { // Project with `demixing_matrix` when in projection mode. - const std::vector>& samples_to_render_double = - (demixing_matrix != nullptr) - ? ProjectSamplesToRender(input_samples, demixing_matrix, gains.size()) - : input_samples; + absl::Span> samples_to_render_double; + std::vector> projected_samples; + if (demixing_matrix != nullptr) { + projected_samples = + ProjectSamplesToRender(input_samples, demixing_matrix, gains.size()); + samples_to_render_double = absl::MakeConstSpan(projected_samples); + } else { + samples_to_render_double = input_samples; + } int rendered_samples_index = 0; std::fill(rendered_samples.begin(), rendered_samples.end(), 0); @@ -235,7 +241,7 @@ absl::StatusOr>> LookupPrecomputedGains( } absl::Status RenderChannelLayoutToLoudspeakers( - const std::vector>& input_samples, + absl::Span>& input_samples, const DownMixingParams& down_mixing_params, const std::vector& channel_labels, absl::string_view input_key, absl::string_view output_key, @@ -258,7 +264,7 @@ absl::Status RenderChannelLayoutToLoudspeakers( } absl::Status RenderAmbisonicsToLoudspeakers( - const std::vector>& input_samples, + absl::Span>& input_samples, const AmbisonicsConfig& ambisonics_config, const std::vector>& gains, std::vector& rendered_samples) { diff --git a/iamf/cli/renderer/loudspeakers_renderer.h b/iamf/cli/renderer/loudspeakers_renderer.h index 4414bb8..41bece9 100644 --- a/iamf/cli/renderer/loudspeakers_renderer.h +++ b/iamf/cli/renderer/loudspeakers_renderer.h @@ -17,6 +17,7 @@ #include "absl/status/status.h" #include "absl/status/statusor.h" #include "absl/strings/string_view.h" +#include "absl/types/span.h" #include "iamf/cli/channel_label.h" #include "iamf/obu/audio_element.h" #include "iamf/obu/demixing_info_parameter_data.h" @@ -45,7 +46,7 @@ absl::StatusOr>> LookupPrecomputedGains( * \return `absl::OkStatus()` on success. A specific status on failure. */ absl::Status RenderChannelLayoutToLoudspeakers( - const std::vector>& input_samples, + absl::Span>& input_samples, const DownMixingParams& down_mixing_params, const std::vector& channel_labels, absl::string_view input_key, absl::string_view output_key, @@ -61,7 +62,7 @@ absl::Status RenderChannelLayoutToLoudspeakers( * \return `absl::OkStatus()` on success. A specific status on failure. */ absl::Status RenderAmbisonicsToLoudspeakers( - const std::vector>& input_samples, + absl::Span>& input_samples, const AmbisonicsConfig& ambisonics_config, const std::vector>& gains, std::vector& rendered_samples); diff --git a/iamf/cli/renderer/renderer_utils.cc b/iamf/cli/renderer/renderer_utils.cc index c281425..2a5f114 100644 --- a/iamf/cli/renderer/renderer_utils.cc +++ b/iamf/cli/renderer/renderer_utils.cc @@ -9,6 +9,8 @@ * source code in the PATENTS file, you can obtain it at * www.aomedia.org/license/patent. */ +#include +#include #include #include @@ -34,11 +36,10 @@ namespace { // Returns the common number of time ticks to be rendered for the requested // labels or associated demixed label in `labeled_frame`. This represents the // number of time ticks in the rendered audio after trimming. -absl::StatusOr GetCommonNumTrimmedTimeTicks( +absl::StatusOr GetCommonNumTrimmedTimeTicks( const LabeledFrame& labeled_frame, const std::vector& ordered_labels) { - const int kUnknownNumTimeTicks = -1; - int num_raw_time_ticks = kUnknownNumTimeTicks; + std::optional num_raw_time_ticks; for (const auto& label : ordered_labels) { if (label == ChannelLabel::kOmitted) { continue; @@ -51,26 +52,25 @@ absl::StatusOr GetCommonNumTrimmedTimeTicks( if (samples_to_render == nullptr) { return absl::InvalidArgumentError( absl::StrCat("Label ", label, " or D_", label, " not found.")); - } else if (num_raw_time_ticks == kUnknownNumTimeTicks) { + } else if (!num_raw_time_ticks.has_value()) { num_raw_time_ticks = samples_to_render->size(); - } else if (num_raw_time_ticks != samples_to_render->size()) { + } else if (*num_raw_time_ticks != samples_to_render->size()) { return absl::InvalidArgumentError(absl::StrCat( "All labels must have the same number of samples ", label, " (", - samples_to_render->size(), " vs. ", num_raw_time_ticks, ")")); + samples_to_render->size(), " vs. ", *num_raw_time_ticks, ")")); } } - - const int num_trimmed_time_ticks = num_raw_time_ticks - - labeled_frame.samples_to_trim_at_start - - labeled_frame.samples_to_trim_at_end; - if (num_trimmed_time_ticks < 0) { + if (*num_raw_time_ticks < (labeled_frame.samples_to_trim_at_start + + labeled_frame.samples_to_trim_at_end)) { return absl::InvalidArgumentError(absl::StrCat( - "Not enough samples to render ", num_trimmed_time_ticks, - " samples. Raw samples: ", num_raw_time_ticks, + "Not enough samples to render samples", + ". #Raw samples: ", *num_raw_time_ticks, ", samples to trim at start: ", labeled_frame.samples_to_trim_at_start, ", samples to trim at end: ", labeled_frame.samples_to_trim_at_end)); } - return num_trimmed_time_ticks; + + return *num_raw_time_ticks - labeled_frame.samples_to_trim_at_start - + labeled_frame.samples_to_trim_at_end; } } // namespace @@ -78,21 +78,25 @@ absl::StatusOr GetCommonNumTrimmedTimeTicks( absl::Status ArrangeSamplesToRender( const LabeledFrame& labeled_frame, const std::vector& ordered_labels, - std::vector>& samples_to_render) { - samples_to_render.clear(); + std::vector>& samples_to_render, + size_t& num_valid_samples) { if (ordered_labels.empty()) { return absl::OkStatus(); } - const auto num_trimmed_time_ticks = + const auto common_num_trimmed_time_ticks = GetCommonNumTrimmedTimeTicks(labeled_frame, ordered_labels); - if (!num_trimmed_time_ticks.ok()) { - return num_trimmed_time_ticks.status(); + if (!common_num_trimmed_time_ticks.ok()) { + return common_num_trimmed_time_ticks.status(); } + num_valid_samples = *common_num_trimmed_time_ticks; const auto num_channels = ordered_labels.size(); - samples_to_render.resize(*num_trimmed_time_ticks, - std::vector(num_channels, 0)); + if (num_valid_samples > samples_to_render.size()) [[unlikely]] { + return absl::InvalidArgumentError(absl::StrCat( + "Number of time samples to render= ", num_valid_samples, + "does not fit into the output of size ", samples_to_render.size())); + } for (int channel = 0; channel < num_channels; ++channel) { const auto& channel_label = ordered_labels[channel]; @@ -111,7 +115,7 @@ absl::Status ArrangeSamplesToRender( // Grab the entire time axes for this label, Skip over any samples that // should be trimmed. - for (int time = 0; time < *num_trimmed_time_ticks; ++time) { + for (int time = 0; time < num_valid_samples; ++time) { samples_to_render[time][channel] = (*channel_samples)[time + labeled_frame.samples_to_trim_at_start]; } diff --git a/iamf/cli/renderer/renderer_utils.h b/iamf/cli/renderer/renderer_utils.h index c884b14..e2931e8 100644 --- a/iamf/cli/renderer/renderer_utils.h +++ b/iamf/cli/renderer/renderer_utils.h @@ -11,6 +11,7 @@ */ #ifndef CLI_RENDERER_RENDERER_UTILS_H_ #define CLI_RENDERER_RENDERER_UTILS_H_ +#include #include #include @@ -40,7 +41,8 @@ namespace renderer_utils { absl::Status ArrangeSamplesToRender( const LabeledFrame& labeled_frame, const std::vector& ordered_labels, - std::vector>& samples_to_render); + std::vector>& samples_to_render, + size_t& num_valid_samples); /*!\brief Gets a key associated with the playback layout. * diff --git a/iamf/cli/renderer/tests/BUILD b/iamf/cli/renderer/tests/BUILD index a3e2d46..691e64e 100644 --- a/iamf/cli/renderer/tests/BUILD +++ b/iamf/cli/renderer/tests/BUILD @@ -25,6 +25,7 @@ cc_test( "//iamf/obu:types", "@com_google_absl//absl/status", "@com_google_absl//absl/status:status_matchers", + "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) @@ -69,6 +70,7 @@ cc_test( "@com_google_absl//absl/status:status_matchers", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings:string_view", + "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) @@ -83,6 +85,7 @@ cc_test( "//iamf/obu:mix_presentation", "//iamf/obu:types", "@com_google_absl//absl/status:status_matchers", + "@com_google_absl//absl/types:span", "@com_google_googletest//:gtest_main", ], ) diff --git a/iamf/cli/renderer/tests/audio_element_renderer_ambisonics_to_channel_test.cc b/iamf/cli/renderer/tests/audio_element_renderer_ambisonics_to_channel_test.cc index 09e473a..6f2a854 100644 --- a/iamf/cli/renderer/tests/audio_element_renderer_ambisonics_to_channel_test.cc +++ b/iamf/cli/renderer/tests/audio_element_renderer_ambisonics_to_channel_test.cc @@ -12,6 +12,7 @@ #include "iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.h" +#include #include #include #include @@ -33,6 +34,7 @@ using enum ChannelLabel::Label; using enum LoudspeakersSsConventionLayout::SoundSystem; +constexpr size_t kOneSamplePerFrame = 1; const Layout kMonoLayout = { .layout_type = Layout::kLayoutTypeLoudspeakersSsConvention, .specific_layout = @@ -96,7 +98,7 @@ TEST(CreateFromAmbisonicsConfig, SupportsZerothOrderToMono) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullZerothOrderAmbisonicsConfig, kFullZerothOrderAudioSubstreamIds, - kZerothOrderSubstreamIdToLabels, kMonoLayout), + kZerothOrderSubstreamIdToLabels, kMonoLayout, kOneSamplePerFrame), nullptr); } @@ -106,7 +108,7 @@ TEST(CreateFromAmbisonicsConfig, SupportsZerothOrderToStereo) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullZerothOrderAmbisonicsConfig, kFullZerothOrderAudioSubstreamIds, - kZerothOrderSubstreamIdToLabels, kStereoLayout), + kZerothOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -116,7 +118,7 @@ TEST(CreateFromAmbisonicsConfig, SupportsZerothOrderTo9_1_6) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullZerothOrderAmbisonicsConfig, kFullZerothOrderAudioSubstreamIds, - kZerothOrderSubstreamIdToLabels, k9_1_6Layout), + kZerothOrderSubstreamIdToLabels, k9_1_6Layout, kOneSamplePerFrame), nullptr); } @@ -127,7 +129,7 @@ TEST(CreateFromAmbisonicsConfig, SupportsFirstOrderTo7_1_2) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullFirstOrderAmbisonicsConfig, kFullFirstOrderAudioSubstreamIds, - kFirstOrderSubstreamIdToLabels, k7_1_2Layout), + kFirstOrderSubstreamIdToLabels, k7_1_2Layout, kOneSamplePerFrame), nullptr); } @@ -141,7 +143,7 @@ TEST(CreateFromAmbisonicsConfig, SupportsThirdOrderToStereo) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullThirdOrderAmbisonicsConfig, kFullThirdOrderAudioSubstreamIds, - kThirdOrderSubstreamIdToLabels, kStereoLayout), + kThirdOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -156,7 +158,7 @@ TEST(CreateFromAmbisonicsConfig, SupportsFourthOrderAmbisonics) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullFourthOrderAmbisonicsConfig, kFullFourthOrderAudioSubstreamIds, - kFourthOrderSubstreamIdToLabels, kStereoLayout), + kFourthOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -166,7 +168,7 @@ TEST(CreateFromAmbisonicsConfig, DoesNotSupportBinauralOutput) { EXPECT_EQ( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullZerothOrderAmbisonicsConfig, kFullZerothOrderAudioSubstreamIds, - kZerothOrderSubstreamIdToLabels, kBinauralLayout), + kZerothOrderSubstreamIdToLabels, kBinauralLayout, kOneSamplePerFrame), nullptr); } @@ -187,7 +189,8 @@ TEST(CreateFromAmbisonicsConfig, SupportsMixedFirstOrderAmbisonics) { EXPECT_NE( AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kMixedFirstOrderAmbisonicsConfig, kMixedFirstOrderAudioSubstreamIds, - kMixedFirstOrderSubstreamIdToLabels, kStereoLayout), + kMixedFirstOrderSubstreamIdToLabels, kStereoLayout, + kOneSamplePerFrame), nullptr); } @@ -232,10 +235,11 @@ TEST(CreateFromAmbisonicsConfig, Projection) { const SubstreamIdLabelsMap kFirstOrderSubstreamIdToLabels = { {0, {kA0}}, {1, {kA1}}, {2, {kA2}}, {3, {kA3}}}; - EXPECT_NE(AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( - kAmbisonicsProjectionConfig, kFirstOrderAudioSubstreamIds, - kFirstOrderSubstreamIdToLabels, kStereoLayout), - nullptr); + EXPECT_NE( + AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( + kAmbisonicsProjectionConfig, kFirstOrderAudioSubstreamIds, + kFirstOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame), + nullptr); } TEST(CreateFromAmbisonicsConfig, @@ -251,10 +255,11 @@ TEST(CreateFromAmbisonicsConfig, const SubstreamIdLabelsMap kFirstOrderSubstreamIdToLabels = {{0, {kA0, kA1}}, {1, {kA2, kA3}}}; - EXPECT_NE(AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( - kAmbisonicsProjectionConfig, kFirstOrderAudioSubstreamIds, - kFirstOrderSubstreamIdToLabels, kStereoLayout), - nullptr); + EXPECT_NE( + AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( + kAmbisonicsProjectionConfig, kFirstOrderAudioSubstreamIds, + kFirstOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame), + nullptr); } // =========== Mixed-order ambisonics projection config =========== @@ -277,10 +282,11 @@ TEST(CreateFromAmbisonicsConfig, SupportedMixedOrderProjectionConfig) { const SubstreamIdLabelsMap kFirstOrderSubstreamIdToLabels = { {0, {kA0}}, {1, {kA1}}, {2, {kA3}}}; - EXPECT_NE(AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( - kAmbisonicsProjectionConfig, kFirstOrderAudioSubstreamIds, - kFirstOrderSubstreamIdToLabels, kStereoLayout), - nullptr); + EXPECT_NE( + AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( + kAmbisonicsProjectionConfig, kFirstOrderAudioSubstreamIds, + kFirstOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame), + nullptr); } TEST(RenderFrames, AcnZeroIsSymmetric) { @@ -290,7 +296,7 @@ TEST(RenderFrames, AcnZeroIsSymmetric) { auto renderer = AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kFullFirstOrderAmbisonicsConfig, kFullFirstOrderAudioSubstreamIds, - kFirstOrderSubstreamIdToLabels, kStereoLayout); + kFirstOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame); const LabeledFrame frame = { .label_to_samples = {{kA0, {10000}}, {kA1, {0}}, {kA2, {0}}, {kA3, {0}}}}; @@ -327,7 +333,7 @@ TEST(RenderFrames, UsesDemixingMatrix) { auto renderer_epsilon_identity = AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kAmbisonicsProjectionConfigIdentity, kFirstOrderAudioSubstreamIds, - kFirstOrderSubstreamIdToLabels, kStereoLayout); + kFirstOrderSubstreamIdToLabels, kStereoLayout, kOneSamplePerFrame); std::vector output_samples_epsilon_identity; RenderAndFlushExpectOk(frame, renderer_epsilon_identity.get(), output_samples_epsilon_identity); @@ -335,7 +341,7 @@ TEST(RenderFrames, UsesDemixingMatrix) { AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( kAmbisonicsProjectionConfigIdentityInverse, kFirstOrderAudioSubstreamIds, kFirstOrderSubstreamIdToLabels, - kStereoLayout); + kStereoLayout, kOneSamplePerFrame); std::vector output_samples_negative_epsilon_identity; RenderAndFlushExpectOk(frame, renderer_negative_epsilon_identity.get(), output_samples_negative_epsilon_identity); diff --git a/iamf/cli/renderer/tests/audio_element_renderer_base_test.cc b/iamf/cli/renderer/tests/audio_element_renderer_base_test.cc index a194de1..222a581 100644 --- a/iamf/cli/renderer/tests/audio_element_renderer_base_test.cc +++ b/iamf/cli/renderer/tests/audio_element_renderer_base_test.cc @@ -17,6 +17,7 @@ #include "absl/status/status.h" #include "absl/status/status_matchers.h" +#include "absl/types/span.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "iamf/obu/types.h" @@ -34,10 +35,10 @@ const std::vector kSamplesToRender = {0, 1, 2, 3}; // `RenderLabeledFrame`. class MockAudioElementRenderer : public AudioElementRendererBase { public: - MockAudioElementRenderer() : AudioElementRendererBase({}, 0) {}; + MockAudioElementRenderer() : AudioElementRendererBase({}, 0, 0) {}; absl::Status RenderSamples( - const std::vector>&, + absl::Span>, std::vector& rendered_samples) override { rendered_samples.insert(rendered_samples.end(), kSamplesToRender.begin(), kSamplesToRender.end()); diff --git a/iamf/cli/renderer/tests/audio_element_renderer_channel_to_channel_test.cc b/iamf/cli/renderer/tests/audio_element_renderer_channel_to_channel_test.cc index d7f7582..3cf11b0 100644 --- a/iamf/cli/renderer/tests/audio_element_renderer_channel_to_channel_test.cc +++ b/iamf/cli/renderer/tests/audio_element_renderer_channel_to_channel_test.cc @@ -12,6 +12,7 @@ #include "iamf/cli/renderer/audio_element_renderer_channel_to_channel.h" +#include #include #include "absl/status/status_matchers.h" @@ -47,6 +48,8 @@ constexpr int k3_1_2LFEChannelIndex = 3; constexpr int k5_1LFEChannelIndex = 3; constexpr int k9_1_6LFEChannelIndex = 3; +constexpr size_t kOneSamplePerFrame = 1; + const Layout kMonoLayout = { .layout_type = Layout::kLayoutTypeLoudspeakersSsConvention, .specific_layout = @@ -108,21 +111,24 @@ GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( TEST(CreateFromScalableChannelLayoutConfig, SupportsDownMixingStereoToMono) { EXPECT_NE(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kMonoLayout), + kStereoScalableChannelLayoutConfig, kMonoLayout, + kOneSamplePerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, SupportsDownMixing7_1_4To7_1_2) { EXPECT_NE(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - k7_1_4ScalableChannelLayoutConfig, k7_1_2Layout), + k7_1_4ScalableChannelLayoutConfig, k7_1_2Layout, + kOneSamplePerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, SupportsDownMixing7_1_4To3_1_2) { EXPECT_NE(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - k7_1_4ScalableChannelLayoutConfig, k3_1_2Layout), + k7_1_4ScalableChannelLayoutConfig, k3_1_2Layout, + kOneSamplePerFrame), nullptr); } @@ -132,7 +138,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutLFE), - kStereoLayout), + kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -142,7 +148,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutLFE), - k7_1_2Layout), + k7_1_2Layout, kOneSamplePerFrame), nullptr); } @@ -152,7 +158,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutLFE), - k7_1_4Layout), + k7_1_4Layout, kOneSamplePerFrame), nullptr); } @@ -162,7 +168,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoS), - kStereoLayout), + kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -172,7 +178,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoS), - k5_1_4Layout), + k5_1_4Layout, kOneSamplePerFrame), nullptr); } @@ -182,7 +188,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayout9_1_6_ch), - kStereoLayout), + kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -192,7 +198,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoSS), - kStereoLayout), + kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -202,7 +208,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoF), - k9_1_6Layout), + k9_1_6Layout, kOneSamplePerFrame), nullptr); } @@ -212,7 +218,7 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutReserved13), - kStereoLayout), + kStereoLayout, kOneSamplePerFrame), nullptr); } @@ -222,22 +228,25 @@ TEST(CreateFromScalableChannelLayoutConfig, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutReserved255), - kStereoLayout), + kStereoLayout, kOneSamplePerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportBinaural) { EXPECT_EQ(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - kBinauralScalableChannelLayoutConfig, kBinauralLayout), + kBinauralScalableChannelLayoutConfig, kBinauralLayout, + kOneSamplePerFrame), nullptr); EXPECT_EQ(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - kBinauralScalableChannelLayoutConfig, kStereoLayout), + kBinauralScalableChannelLayoutConfig, kStereoLayout, + kOneSamplePerFrame), nullptr); EXPECT_EQ(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kBinauralLayout), + kStereoScalableChannelLayoutConfig, kBinauralLayout, + kOneSamplePerFrame), nullptr); } @@ -248,14 +257,16 @@ TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportReservedLayout) { EXPECT_EQ(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kReservedLayout), + kStereoScalableChannelLayoutConfig, kReservedLayout, + kOneSamplePerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportPassThroughStereo) { EXPECT_EQ(AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kStereoLayout), + kStereoScalableChannelLayoutConfig, kStereoLayout, + kOneSamplePerFrame), nullptr); } @@ -263,7 +274,7 @@ TEST(CreateFromScalableChannelLayoutConfig, IsFinalizedImmediatelyAfterFinalizeCall) { auto renderer = AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig(kStereoScalableChannelLayoutConfig, - kMonoLayout); + kMonoLayout, kOneSamplePerFrame); ASSERT_NE(renderer, nullptr); EXPECT_THAT(renderer->RenderLabeledFrame( @@ -278,7 +289,7 @@ TEST(RenderLabeledFrame, ReturnsNumberOfTicks) { const int kNumTicks = 3; auto renderer = AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig(kStereoScalableChannelLayoutConfig, - kMonoLayout); + kMonoLayout, kNumTicks); ASSERT_NE(renderer, nullptr); const auto num_ticks = renderer->RenderLabeledFrame( @@ -298,7 +309,8 @@ TEST(RenderLabeledFrame, RendersStereoToMono) { auto renderer = AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig(kStereoScalableChannelLayoutConfig, - kMonoLayout); + kMonoLayout, + kExpectedMonoSamples.size()); std::vector rendered_samples; RenderAndFlushExpectOk( @@ -312,7 +324,7 @@ TEST(RenderLabeledFrame, StereoOutputIsSymmetricWhenInputIsLeftRightSymmetric7_1_4) { auto renderer = AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig(k7_1_4ScalableChannelLayoutConfig, - kStereoLayout); + kStereoLayout, kOneSamplePerFrame); constexpr InternalSampleType kSymmetricL7R7Input = kArbitrarySample1; constexpr InternalSampleType kSymmetricLss7Rss7Input = kArbitrarySample2; constexpr InternalSampleType kSymmetricLrs7Rss7Input = kArbitrarySample3; @@ -346,7 +358,7 @@ TEST(RenderLabeledFrame, PassThroughLFE) { CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutLFE), - k3_1_2Layout); + k3_1_2Layout, kOneSamplePerFrame); std::vector rendered_samples; RenderAndFlushExpectOk({.label_to_samples = {{kLFE, {kArbitrarySample1}}}}, @@ -361,7 +373,7 @@ TEST(RenderLabeledFrame, LFEPassesThroughFrom9_1_6) { CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayout9_1_6_ch), - k5_1_0Layout); + k5_1_0Layout, kOneSamplePerFrame); ASSERT_NE(renderer, nullptr); std::vector rendered_samples; @@ -391,7 +403,7 @@ TEST(RenderLabeledFrame, LFEPassesThroughTo9_1_6) { constexpr InternalSampleType kLFESample = 1234.0; auto renderer = AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig(k5_1_0ScalableChannelLayoutConfig, - k9_1_6Layout); + k9_1_6Layout, kOneSamplePerFrame); ASSERT_NE(renderer, nullptr); std::vector rendered_samples; @@ -417,7 +429,7 @@ TEST(RenderLabeledFrame, PassThroughStereoS) { CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoS), - k5_1_0Layout); + k5_1_0Layout, kOneSamplePerFrame); ASSERT_NE(renderer, nullptr); std::vector rendered_samples; @@ -445,12 +457,12 @@ TEST_P(ExpandedLayoutAndRelatedLoudspeakerLayoutTest, Equivalent) { CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( GetParam().expanded_layout), - GetParam().output_layout); + GetParam().output_layout, kOneSamplePerFrame); auto renderer_related_loudspeaker_layout = AudioElementRendererChannelToChannel:: CreateFromScalableChannelLayoutConfig( GetParam().related_scalable_layout_config, - GetParam().output_layout); + GetParam().output_layout, kOneSamplePerFrame); std::vector expanded_layout_rendered_samples; RenderAndFlushExpectOk( @@ -549,7 +561,7 @@ TEST(RenderLabeledFrame, CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayout9_1_6_ch), - kStereoLayout); + kStereoLayout, kOneSamplePerFrame); constexpr InternalSampleType kSymmetricFLFRInput = kArbitrarySample1; constexpr InternalSampleType kSymmetricBLBRInput = kArbitrarySample2; constexpr InternalSampleType kSymmetricFLcFRcInput = kArbitrarySample3; diff --git a/iamf/cli/renderer/tests/audio_element_renderer_passthrough_test.cc b/iamf/cli/renderer/tests/audio_element_renderer_passthrough_test.cc index 161c8f1..55eabb6 100644 --- a/iamf/cli/renderer/tests/audio_element_renderer_passthrough_test.cc +++ b/iamf/cli/renderer/tests/audio_element_renderer_passthrough_test.cc @@ -12,6 +12,7 @@ #include "iamf/cli/renderer/audio_element_renderer_passthrough.h" +#include #include #include #include @@ -82,17 +83,21 @@ const ScalableChannelLayoutConfig kMonoScalableChannelLayoutConfig = { .num_layers = 1, .channel_audio_layer_configs = {{.loudspeaker_layout = kLayoutMono}}}; +constexpr size_t kFourSamplesPerFrame = 4; + TEST(CreateFromScalableChannelLayoutConfig, SupportsPassThroughBinaural) { EXPECT_NE( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kBinauralScalableChannelLayoutConfig, kBinauralLayout), + kBinauralScalableChannelLayoutConfig, kBinauralLayout, + kFourSamplesPerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, SupportsPassThroughStereo) { EXPECT_NE( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kStereoLayout), + kStereoScalableChannelLayoutConfig, kStereoLayout, + kFourSamplesPerFrame), nullptr); } @@ -100,28 +105,32 @@ TEST(CreateFromScalableChannelLayoutConfig, SupportsPassThroughIfAnyLayerMatches) { EXPECT_NE( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kStereoLayout), + kStereoScalableChannelLayoutConfig, kStereoLayout, + kFourSamplesPerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportBinauralToStereo) { EXPECT_EQ( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kBinauralScalableChannelLayoutConfig, kStereoLayout), + kBinauralScalableChannelLayoutConfig, kStereoLayout, + kFourSamplesPerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportStereoToBinaural) { EXPECT_EQ( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kBinauralLayout), + kStereoScalableChannelLayoutConfig, kBinauralLayout, + kFourSamplesPerFrame), nullptr); } TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportIfNoLayerMatches) { EXPECT_EQ( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kMonoLayout), + kStereoScalableChannelLayoutConfig, kMonoLayout, + kFourSamplesPerFrame), nullptr); } @@ -132,7 +141,8 @@ TEST(CreateFromScalableChannelLayoutConfig, DoesNotSupportReservedLayout) { EXPECT_EQ( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kReservedLayout), + kStereoScalableChannelLayoutConfig, kReservedLayout, + kFourSamplesPerFrame), nullptr); } @@ -146,7 +156,7 @@ TEST(CreateFromScalableChannelLayoutConfig, EXPECT_EQ( AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( kStereoScalableChannelLayoutConfig, - kLayoutWithNoEquivalentSoundSystem), + kLayoutWithNoEquivalentSoundSystem, kFourSamplesPerFrame), nullptr); } @@ -156,7 +166,7 @@ TEST(CreateFromScalableChannelLayoutConfig, AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( kExpandedLayoutLFE), - k7_1_4Layout), + k7_1_4Layout, kFourSamplesPerFrame), nullptr); } @@ -166,7 +176,8 @@ TEST(CreateFromScalableChannelLayoutConfig, AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( kExpandedLayoutLFE), - GetScalableLayoutForSoundSystem(kSoundSystem10_2_7_0)), + GetScalableLayoutForSoundSystem(kSoundSystem10_2_7_0), + kFourSamplesPerFrame), nullptr); } @@ -176,7 +187,7 @@ TEST(CreateFromScalableChannelLayoutConfig, AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( kExpandedLayoutStereoS), - k5_1_4Layout), + k5_1_4Layout, kFourSamplesPerFrame), nullptr); } @@ -185,7 +196,8 @@ TEST(CreateFromScalableChannelLayoutConfig, SupportsPassThroughFor9_1_6) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( kExpandedLayout9_1_6_ch), - GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0)), + GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0), + kFourSamplesPerFrame), nullptr); } @@ -195,7 +207,8 @@ TEST(CreateFromScalableChannelLayoutConfig, AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( kExpandedLayoutTop6Ch), - GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0)), + GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0), + kFourSamplesPerFrame), nullptr); } @@ -205,7 +218,8 @@ const LabeledFrame kLabeledFrameWithL2AndR2 = { TEST(RenderLabeledFrame, RendersPassThroughStereo) { auto stereo_pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kStereoLayout); + kStereoScalableChannelLayoutConfig, kStereoLayout, + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(kLabeledFrameWithL2AndR2, @@ -219,7 +233,8 @@ TEST(RenderLabeledFrame, RendersPassThroughStereo) { TEST(RenderLabeledFrame, RendersPassThroughBinaural) { auto binaural_pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kBinauralScalableChannelLayoutConfig, kBinauralLayout); + kBinauralScalableChannelLayoutConfig, kBinauralLayout, + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(kLabeledFrameWithL2AndR2, @@ -248,7 +263,8 @@ TEST(RenderLabeledFrame, RendersPassThrough7_1_4) { }}; auto pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - k7_1_4ScalableChannelLayoutConfig, k7_1_4Layout); + k7_1_4ScalableChannelLayoutConfig, k7_1_4Layout, + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(k7_1_4LabeledFrame, pass_through_renderer.get(), @@ -267,7 +283,8 @@ TEST(RenderLabeledFrame, RendersPassThroughLFE) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutLFE), - GetScalableLayoutForSoundSystem(kSoundSystemJ_4_7_0)); + GetScalableLayoutForSoundSystem(kSoundSystemJ_4_7_0), + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(kLFELabeledFrame, pass_through_renderer.get(), @@ -288,7 +305,8 @@ TEST(RenderLabeledFrame, RendersPassThroughStereoS) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoS), - GetScalableLayoutForSoundSystem(kSoundSystemD_4_5_0)); + GetScalableLayoutForSoundSystem(kSoundSystemD_4_5_0), + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(kStereoSLabeledFrame, pass_through_renderer.get(), @@ -309,7 +327,8 @@ TEST(RenderLabeledFrame, RendersPassThrough3_0_Ch) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayout3_0_ch), - GetScalableLayoutForSoundSystem(kSoundSystemJ_4_7_0)); + GetScalableLayoutForSoundSystem(kSoundSystemJ_4_7_0), + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(k7_1_4LabeledFrame, pass_through_renderer.get(), @@ -344,7 +363,8 @@ TEST(RenderLabeledFrame, RendersPassThrough9_1_6) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayout9_1_6_ch), - GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0)); + GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0), + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(k9_1_6LabeledFrame, pass_through_renderer.get(), @@ -366,7 +386,8 @@ TEST(RenderLabeledFrame, RendersPassThroughStereoF) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutStereoF), - GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0)); + GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0), + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(kStreoFLabeledFrame, pass_through_renderer.get(), @@ -391,7 +412,8 @@ TEST(RenderLabeledFrame, RendersPassThroughTop6Ch) { AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( GetScalableChannelLayoutConfigForExpandedLayoutSoundSystem( ChannelAudioLayerConfig::kExpandedLayoutTop6Ch), - GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0)); + GetScalableLayoutForSoundSystem(kSoundSystem13_6_9_0), + kFourSamplesPerFrame); std::vector rendered_samples; RenderAndFlushExpectOk(kTop6ChLabeledFrame, pass_through_renderer.get(), @@ -409,7 +431,8 @@ TEST(RenderLabeledFrame, RendersDemixedSamples) { auto demixed_stereo_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoChannelConfigWithTwoLayers, kStereoLayout); + kStereoChannelConfigWithTwoLayers, kStereoLayout, + kFourSamplesPerFrame); EXPECT_NE(demixed_stereo_renderer, nullptr); EXPECT_THAT(demixed_stereo_renderer->RenderLabeledFrame(kTwoLayerStereo), @@ -430,7 +453,8 @@ TEST(RenderLabeledFrame, ReturnsNumberOfTicksToRender) { auto stereo_pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kStereoScalableChannelLayoutConfig, kStereoLayout); + kStereoScalableChannelLayoutConfig, kStereoLayout, + kFourSamplesPerFrame); const auto result = stereo_pass_through_renderer->RenderLabeledFrame( kStereoFrameWithTwoRenderedTicks); EXPECT_THAT(result, IsOk()); @@ -443,7 +467,7 @@ TEST(RenderLabeledFrame, EdgeCaseWithAllSamplesTrimmedReturnsZero) { auto mono_pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kMonoScalableChannelLayoutConfig, kMonoLayout); + kMonoScalableChannelLayoutConfig, kMonoLayout, kFourSamplesPerFrame); const auto result = mono_pass_through_renderer->RenderLabeledFrame(kMonoFrame); EXPECT_THAT(result, IsOk()); @@ -480,12 +504,12 @@ void CollectRenderedSamples(AudioElementRendererPassThrough& renderer, } TEST(RenderLabeledFrame, IsThreadSafe) { + constexpr int kSamplesPerFrame = 10; auto mono_pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - kMonoScalableChannelLayoutConfig, kMonoLayout); + kMonoScalableChannelLayoutConfig, kMonoLayout, kSamplesPerFrame); EXPECT_NE(mono_pass_through_renderer, nullptr); constexpr int kNumFrames = 1000; - constexpr int kSamplesPerFrame = 10; // Spawn a thread to render an increasing sequence. std::thread render_thread(&RenderMonoSequence, kNumFrames, kSamplesPerFrame, diff --git a/iamf/cli/renderer/tests/renderer_utils_test.cc b/iamf/cli/renderer/tests/renderer_utils_test.cc index dfe17cd..3566dca 100644 --- a/iamf/cli/renderer/tests/renderer_utils_test.cc +++ b/iamf/cli/renderer/tests/renderer_utils_test.cc @@ -12,9 +12,11 @@ #include "iamf/cli/renderer/renderer_utils.h" +#include #include #include "absl/status/status_matchers.h" +#include "absl/types/span.h" #include "gmock/gmock.h" #include "gtest/gtest.h" #include "iamf/cli/channel_label.h" @@ -31,10 +33,18 @@ using enum ChannelLabel::Label; using testing::DoubleEq; using testing::Pointwise; +constexpr size_t kNumSamplesPerFrame = 8; + TEST(ArrangeSamplesToRender, SucceedsOnEmptyFrame) { - std::vector> samples; - EXPECT_THAT(ArrangeSamplesToRender({}, {}, samples), IsOk()); - EXPECT_TRUE(samples.empty()); + std::vector> samples( + kNumSamplesPerFrame, std::vector(0)); + size_t num_valid_samples = 0; + EXPECT_THAT(ArrangeSamplesToRender({}, {}, samples, num_valid_samples), + IsOk()); + + // `samples` remains the same size, but `num_valid_samples` is zero. + EXPECT_EQ(samples.size(), kNumSamplesPerFrame); + EXPECT_EQ(num_valid_samples, 0); } TEST(ArrangeSamplesToRender, ArrangesSamplesInTimeChannelAxes) { @@ -42,11 +52,14 @@ TEST(ArrangeSamplesToRender, ArrangesSamplesInTimeChannelAxes) { .label_to_samples = {{kL2, {0, 1, 2}}, {kR2, {10, 11, 12}}}}; const std::vector kStereoArrangement = {kL2, kR2}; - std::vector> samples; - EXPECT_THAT( - ArrangeSamplesToRender(kStereoLabeledFrame, kStereoArrangement, samples), - IsOk()); - EXPECT_THAT(samples, + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kStereoArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT(ArrangeSamplesToRender(kStereoLabeledFrame, kStereoArrangement, + samples, num_valid_samples), + IsOk()); + EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples), testing::ElementsAreArray({Pointwise(DoubleEq(), {0.0, 10.0}), Pointwise(DoubleEq(), {1.0, 11.0}), Pointwise(DoubleEq(), {2.0, 12.0})})); @@ -57,12 +70,17 @@ TEST(ArrangeSamplesToRender, FindsDemixedLabels) { .label_to_samples = {{kMono, {75}}, {kL2, {50}}, {kDemixedR2, {100}}}}; const std::vector kStereoArrangement = {kL2, kR2}; - std::vector> samples; - EXPECT_THAT(ArrangeSamplesToRender(kDemixedTwoLayerStereoFrame, - kStereoArrangement, samples), - IsOk()); - EXPECT_THAT(samples, testing::ElementsAreArray( - {Pointwise(DoubleEq(), {50.0, 100.0})})); + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kStereoArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT( + ArrangeSamplesToRender(kDemixedTwoLayerStereoFrame, kStereoArrangement, + samples, num_valid_samples), + IsOk()); + EXPECT_THAT( + absl::MakeConstSpan(samples).first(num_valid_samples), + testing::ElementsAreArray({Pointwise(DoubleEq(), {50.0, 100.0})})); } TEST(ArrangeSamplesToRender, IgnoresExtraLabels) { @@ -70,11 +88,15 @@ TEST(ArrangeSamplesToRender, IgnoresExtraLabels) { .label_to_samples = {{kL2, {0}}, {kR2, {10}}, {kLFE, {999}}}}; const std::vector kStereoArrangement = {kL2, kR2}; - std::vector> samples; - EXPECT_THAT(ArrangeSamplesToRender(kStereoLabeledFrameWithExtraLabel, - kStereoArrangement, samples), - IsOk()); - EXPECT_THAT(samples, + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kStereoArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT( + ArrangeSamplesToRender(kStereoLabeledFrameWithExtraLabel, + kStereoArrangement, samples, num_valid_samples), + IsOk()); + EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples), testing::ElementsAreArray({Pointwise(DoubleEq(), {0.0, 10.0})})); } @@ -85,14 +107,18 @@ TEST(ArrangeSamplesToRender, LeavesOmittedLabelsZeroForMixedOrderAmbisonics) { const std::vector kMixedFirstOrderAmbisonicsArrangement = {kA0, kOmitted, kA2, kA3}; - std::vector> samples; - EXPECT_THAT( - ArrangeSamplesToRender(kMixedFirstOrderAmbisonicsFrame, - kMixedFirstOrderAmbisonicsArrangement, samples), - IsOk()); - EXPECT_THAT(samples, testing::ElementsAreArray( - {Pointwise(DoubleEq(), {1.0, 0.0, 201.0, 301.0}), - Pointwise(DoubleEq(), {2.0, 0.0, 202.0, 302.0})})); + std::vector> samples( + kNumSamplesPerFrame, std::vector( + kMixedFirstOrderAmbisonicsArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT(ArrangeSamplesToRender(kMixedFirstOrderAmbisonicsFrame, + kMixedFirstOrderAmbisonicsArrangement, + samples, num_valid_samples), + IsOk()); + EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples), + testing::ElementsAreArray( + {Pointwise(DoubleEq(), {1.0, 0.0, 201.0, 301.0}), + Pointwise(DoubleEq(), {2.0, 0.0, 202.0, 302.0})})); } TEST(ArrangeSamplesToRender, LeavesOmittedLabelsZeroForChannelBasedLayout) { @@ -100,13 +126,18 @@ TEST(ArrangeSamplesToRender, LeavesOmittedLabelsZeroForChannelBasedLayout) { const std::vector kLFEAsSecondChannelArrangement = { kOmitted, kOmitted, kLFE, kOmitted}; - std::vector> samples; - EXPECT_THAT(ArrangeSamplesToRender(kLFEOnlyFrame, - kLFEAsSecondChannelArrangement, samples), - IsOk()); - EXPECT_THAT(samples, testing::ElementsAreArray( - {Pointwise(DoubleEq(), {0.0, 0.0, 1.0, 0.0}), - Pointwise(DoubleEq(), {0.0, 0.0, 2.0, 0.0})})); + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kLFEAsSecondChannelArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT( + ArrangeSamplesToRender(kLFEOnlyFrame, kLFEAsSecondChannelArrangement, + samples, num_valid_samples), + IsOk()); + EXPECT_THAT( + absl::MakeConstSpan(samples).first(num_valid_samples), + testing::ElementsAreArray({Pointwise(DoubleEq(), {0.0, 0.0, 1.0, 0.0}), + Pointwise(DoubleEq(), {0.0, 0.0, 2.0, 0.0})})); } TEST(ArrangeSamplesToRender, ExcludesSamplesToBeTrimmed) { @@ -116,24 +147,29 @@ TEST(ArrangeSamplesToRender, ExcludesSamplesToBeTrimmed) { .label_to_samples = {{kMono, {999, 100, 999, 999}}}}; const std::vector kMonoArrangement = {kMono}; - std::vector> samples; - EXPECT_THAT(ArrangeSamplesToRender(kMonoLabeledFrameWithSamplesToTrim, - kMonoArrangement, samples), - IsOk()); - EXPECT_THAT(samples, + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kMonoArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT( + ArrangeSamplesToRender(kMonoLabeledFrameWithSamplesToTrim, + kMonoArrangement, samples, num_valid_samples), + IsOk()); + EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples), testing::ElementsAreArray({Pointwise(DoubleEq(), {100.0})})); } -TEST(ArrangeSamplesToRender, ClearsInputVector) { +TEST(ArrangeSamplesToRender, OverwritesInputVector) { const LabeledFrame kMonoLabeledFrame = { .label_to_samples = {{kMono, {1, 2}}}}; const std::vector kMonoArrangement = {kMono}; - std::vector> samples = {{999, 999}}; - EXPECT_THAT( - ArrangeSamplesToRender(kMonoLabeledFrame, kMonoArrangement, samples), - IsOk()); - EXPECT_THAT(samples, + std::vector> samples = {{999}, {999}}; + size_t num_valid_samples = 0; + EXPECT_THAT(ArrangeSamplesToRender(kMonoLabeledFrame, kMonoArrangement, + samples, num_valid_samples), + IsOk()); + EXPECT_THAT(absl::MakeConstSpan(samples).first(num_valid_samples), testing::ElementsAreArray({Pointwise(DoubleEq(), {1.0}), Pointwise(DoubleEq(), {2.0})})); } @@ -145,11 +181,15 @@ TEST(ArrangeSamplesToRender, TrimmingAllFramesFromStartIsResultsInEmptyOutput) { .label_to_samples = {{kMono, {999, 999, 999, 999}}}}; const std::vector kMonoArrangement = {kMono}; - std::vector> samples; - EXPECT_THAT(ArrangeSamplesToRender(kMonoLabeledFrameWithSamplesToTrim, - kMonoArrangement, samples), - IsOk()); - EXPECT_TRUE(samples.empty()); + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kMonoArrangement.size())); + size_t num_valid_samples = 0; + EXPECT_THAT( + ArrangeSamplesToRender(kMonoLabeledFrameWithSamplesToTrim, + kMonoArrangement, samples, num_valid_samples), + IsOk()); + EXPECT_TRUE(absl::MakeConstSpan(samples).first(num_valid_samples).empty()); } TEST(ArrangeSamplesToRender, @@ -158,9 +198,13 @@ TEST(ArrangeSamplesToRender, .label_to_samples = {{kL2, {0, 1}}, {kR2, {10}}}}; const std::vector kStereoArrangement = {kL2, kR2}; - std::vector> samples; + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kStereoArrangement.size())); + size_t num_valid_samples = 0; EXPECT_FALSE(ArrangeSamplesToRender(kStereoLabeledFrameWithMissingSample, - kStereoArrangement, samples) + kStereoArrangement, samples, + num_valid_samples) .ok()); } @@ -171,9 +215,13 @@ TEST(ArrangeSamplesToRender, InvalidWhenTrimIsImplausible) { .label_to_samples = {{kL2, {0, 1}}, {kR2, {10, 11}}}}; const std::vector kStereoArrangement = {kL2, kR2}; - std::vector> samples; + std::vector> samples( + kNumSamplesPerFrame, + std::vector(kStereoArrangement.size())); + size_t num_valid_samples = 0; EXPECT_FALSE(ArrangeSamplesToRender(kFrameWithExcessSamplesTrimmed, - kStereoArrangement, samples) + kStereoArrangement, samples, + num_valid_samples) .ok()); } @@ -182,9 +230,12 @@ TEST(ArrangeSamplesToRender, InvalidMissingLabel) { .label_to_samples = {{kL2, {0}}, {kR2, {10}}}}; const std::vector kMonoArrangement = {kMono}; - std::vector> unused_samples; + std::vector> unused_samples( + kNumSamplesPerFrame, + std::vector(kMonoArrangement.size())); + size_t num_valid_samples = 0; EXPECT_FALSE(ArrangeSamplesToRender(kStereoLabeledFrame, kMonoArrangement, - unused_samples) + unused_samples, num_valid_samples) .ok()); } diff --git a/iamf/cli/renderer_factory.cc b/iamf/cli/renderer_factory.cc index 80da878..1a4c892 100644 --- a/iamf/cli/renderer_factory.cc +++ b/iamf/cli/renderer_factory.cc @@ -11,6 +11,7 @@ */ #include "iamf/cli/renderer_factory.h" +#include #include #include #include @@ -43,7 +44,7 @@ std::unique_ptr MaybeCreateAmbisonicsRenderer( bool use_binaural, const std::vector& audio_substream_ids, const SubstreamIdLabelsMap& substream_id_to_labels, const AudioElementObu::AudioElementConfig& config, - const Layout& loudness_layout) { + const Layout& loudness_layout, size_t num_samples_per_frame) { const auto* ambisonics_config = std::get_if(&config); if (ambisonics_config == nullptr) { LOG(ERROR) << "Ambisonics config is inconsistent with audio element type."; @@ -59,12 +60,12 @@ std::unique_ptr MaybeCreateAmbisonicsRenderer( return AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig( *ambisonics_config, audio_substream_ids, substream_id_to_labels, - loudness_layout); + loudness_layout, num_samples_per_frame); } std::unique_ptr MaybeCreateChannelRenderer( bool use_binaural, const AudioElementObu::AudioElementConfig& config, - const Layout& loudness_layout) { + const Layout& loudness_layout, size_t num_samples_per_frame) { const auto* channel_config = std::get_if(&config); if (channel_config == nullptr) { @@ -74,7 +75,7 @@ std::unique_ptr MaybeCreateChannelRenderer( // Lazily try to make a pass-through renderer. auto pass_through_renderer = AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig( - *channel_config, loudness_layout); + *channel_config, loudness_layout, num_samples_per_frame); if (pass_through_renderer != nullptr) { return pass_through_renderer; } @@ -84,7 +85,8 @@ std::unique_ptr MaybeCreateChannelRenderer( return nullptr; } return AudioElementRendererChannelToChannel:: - CreateFromScalableChannelLayoutConfig(*channel_config, loudness_layout); + CreateFromScalableChannelLayoutConfig(*channel_config, loudness_layout, + num_samples_per_frame); } } // namespace @@ -97,8 +99,8 @@ RendererFactory::CreateRendererForLayout( const SubstreamIdLabelsMap& substream_id_to_labels, AudioElementObu::AudioElementType audio_element_type, const AudioElementObu::AudioElementConfig& audio_element_config, - const RenderingConfig& rendering_config, - const Layout& loudness_layout) const { + const RenderingConfig& rendering_config, const Layout& loudness_layout, + size_t num_samples_per_frame) const { const bool use_binaural = IsAudioElementRenderedBinaural( rendering_config.headphones_rendering_mode, loudness_layout.layout_type); @@ -106,10 +108,10 @@ RendererFactory::CreateRendererForLayout( case AudioElementObu::kAudioElementSceneBased: return MaybeCreateAmbisonicsRenderer( use_binaural, audio_substream_ids, substream_id_to_labels, - audio_element_config, loudness_layout); + audio_element_config, loudness_layout, num_samples_per_frame); case AudioElementObu::kAudioElementChannelBased: return MaybeCreateChannelRenderer(use_binaural, audio_element_config, - loudness_layout); + loudness_layout, num_samples_per_frame); case AudioElementObu::kAudioElementBeginReserved: case AudioElementObu::kAudioElementEndReserved: LOG(WARNING) << "Unsupported audio_element_type_= " << audio_element_type; diff --git a/iamf/cli/renderer_factory.h b/iamf/cli/renderer_factory.h index c48e462..4ed30ea 100644 --- a/iamf/cli/renderer_factory.h +++ b/iamf/cli/renderer_factory.h @@ -12,6 +12,7 @@ #ifndef CLI_RENDERER_FACTORY_H_ #define CLI_RENDERER_FACTORY_H_ +#include #include #include @@ -41,6 +42,7 @@ class RendererFactoryBase { * \param audio_element_config Configuration of the audio element. * \param rendering_config Configuration of the renderer. * \param loudness_layout Layout to render to. + * \param num_samples_per_frame Number of samples per frame. * \return Unique pointer to an audio element renderer or `nullptr` if it not * known how to render the audio element. */ @@ -49,8 +51,8 @@ class RendererFactoryBase { const SubstreamIdLabelsMap& substream_id_to_labels, AudioElementObu::AudioElementType audio_element_type, const AudioElementObu::AudioElementConfig& audio_element_config, - const RenderingConfig& rendering_config, - const Layout& loudness_layout) const = 0; + const RenderingConfig& rendering_config, const Layout& loudness_layout, + size_t num_samples_per_frame) const = 0; /*!\brief Destructor. */ virtual ~RendererFactoryBase() = 0; @@ -73,6 +75,7 @@ class RendererFactory : public RendererFactoryBase { * \param audio_element_config Configuration of the audio element. * \param rendering_config Configuration of the renderer. * \param loudness_layout Layout to render to. + * \param num_samples_per_frame Number of samples per frame. * \return Unique pointer to an audio element renderer or `nullptr` if it not * known how to render the audio element. */ @@ -81,8 +84,8 @@ class RendererFactory : public RendererFactoryBase { const SubstreamIdLabelsMap& substream_id_to_labels, AudioElementObu::AudioElementType audio_element_type, const AudioElementObu::AudioElementConfig& audio_element_config, - const RenderingConfig& rendering_config, - const Layout& loudness_layout) const override; + const RenderingConfig& rendering_config, const Layout& loudness_layout, + size_t num_samples_per_frame) const override; /*!\brief Destructor. */ ~RendererFactory() override = default; diff --git a/iamf/cli/rendering_mix_presentation_finalizer.cc b/iamf/cli/rendering_mix_presentation_finalizer.cc index 56c3a45..1afd944 100644 --- a/iamf/cli/rendering_mix_presentation_finalizer.cc +++ b/iamf/cli/rendering_mix_presentation_finalizer.cc @@ -117,7 +117,9 @@ absl::Status InitializeRenderingMetadata( sub_mix_audio_element.substream_id_to_labels, rendering_metadata.audio_element->GetAudioElementType(), sub_mix_audio_element.obu.config_, - sub_mix_audio_elements[i].rendering_config, loudness_layout); + sub_mix_audio_elements[i].rendering_config, loudness_layout, + static_cast( + rendering_metadata.codec_config->GetNumSamplesPerFrame())); if (rendering_metadata.renderer == nullptr) { return absl::UnknownError("Unable to create renderer."); diff --git a/iamf/cli/tests/renderer_factory_test.cc b/iamf/cli/tests/renderer_factory_test.cc index 78914f1..4215c5c 100644 --- a/iamf/cli/tests/renderer_factory_test.cc +++ b/iamf/cli/tests/renderer_factory_test.cc @@ -11,6 +11,8 @@ */ #include "iamf/cli/renderer_factory.h" +#include + #include "gtest/gtest.h" #include "iamf/cli/channel_label.h" #include "iamf/cli/proto/obu_header.pb.h" @@ -33,6 +35,8 @@ const Layout kMonoLayout = { LoudspeakersSsConventionLayout{.sound_system = kSoundSystem12_0_1_0}}; const Layout kBinauralLayout = {.layout_type = Layout::kLayoutTypeBinaural}; +constexpr size_t kNumSamplesPerFrame = 8; + const ScalableChannelLayoutConfig kBinauralChannelLayoutConfig = { .num_layers = 1, .channel_audio_layer_configs = {{.loudspeaker_layout = kLayoutBinaural}}}; @@ -65,11 +69,12 @@ const RenderingConfig kHeadphonesAsBinauralRenderingConfig = { TEST(CreateRendererForLayout, SupportsPassThroughRenderer) { const RendererFactory factory; - EXPECT_NE(factory.CreateRendererForLayout( - {0}, {{0, {kMono}}}, AudioElementObu::kAudioElementChannelBased, - kMonoScalableChannelLayoutConfig, - kHeadphonesAsStereoRenderingConfig, kMonoLayout), - nullptr); + EXPECT_NE( + factory.CreateRendererForLayout( + {0}, {{0, {kMono}}}, AudioElementObu::kAudioElementChannelBased, + kMonoScalableChannelLayoutConfig, kHeadphonesAsStereoRenderingConfig, + kMonoLayout, kNumSamplesPerFrame), + nullptr); } TEST(CreateRendererForLayout, SupportsPassThroughBinauralRenderer) { @@ -79,7 +84,7 @@ TEST(CreateRendererForLayout, SupportsPassThroughBinauralRenderer) { factory.CreateRendererForLayout( {0}, {{0, {kL2, kR2}}}, AudioElementObu::kAudioElementChannelBased, kBinauralChannelLayoutConfig, kHeadphonesAsBinauralRenderingConfig, - kBinauralLayout), + kBinauralLayout, kNumSamplesPerFrame), nullptr); } @@ -87,22 +92,24 @@ TEST(CreateRendererForLayout, ReturnsNullPtrWhenTypeIsSceneBasedButConfigIsChannelBased) { const RendererFactory factory; - EXPECT_EQ(factory.CreateRendererForLayout( - {0}, {{0, {kA0}}}, AudioElementObu::kAudioElementSceneBased, - kMonoScalableChannelLayoutConfig, - kHeadphonesAsStereoRenderingConfig, kMonoLayout), - nullptr); + EXPECT_EQ( + factory.CreateRendererForLayout( + {0}, {{0, {kA0}}}, AudioElementObu::kAudioElementSceneBased, + kMonoScalableChannelLayoutConfig, kHeadphonesAsStereoRenderingConfig, + kMonoLayout, kNumSamplesPerFrame), + nullptr); } TEST(CreateRendererForLayout, ReturnsNullPtrWhenTypeIsChannelBasedButConfigIsAmbisonics) { const RendererFactory factory; - EXPECT_EQ(factory.CreateRendererForLayout( - {0}, {{0, {kMono}}}, AudioElementObu::kAudioElementChannelBased, - kFullZerothOrderAmbisonicsConfig, - kHeadphonesAsStereoRenderingConfig, kMonoLayout), - nullptr); + EXPECT_EQ( + factory.CreateRendererForLayout( + {0}, {{0, {kMono}}}, AudioElementObu::kAudioElementChannelBased, + kFullZerothOrderAmbisonicsConfig, kHeadphonesAsStereoRenderingConfig, + kMonoLayout, kNumSamplesPerFrame), + nullptr); } // TODO(b/282877209): Support channel-based to binaural renderer. @@ -112,7 +119,8 @@ TEST(CreateRendererForLayout, ReturnsNullPtrForChannelToBinauralRenderer) { EXPECT_EQ(factory.CreateRendererForLayout( {0}, {{0, {kMono}}}, AudioElementObu::kAudioElementChannelBased, kMonoScalableChannelLayoutConfig, - kHeadphonesAsBinauralRenderingConfig, kBinauralLayout), + kHeadphonesAsBinauralRenderingConfig, kBinauralLayout, + kNumSamplesPerFrame), nullptr); } @@ -122,7 +130,7 @@ TEST(CreateRendererForLayout, ReturnsNullPtrForUnknownExtension) { EXPECT_EQ(factory.CreateRendererForLayout( {0}, {{0, {kMono}}}, AudioElementObu::kAudioElementEndReserved, kExtensionConfig, kHeadphonesAsStereoRenderingConfig, - kBinauralLayout), + kBinauralLayout, kNumSamplesPerFrame), nullptr); } @@ -133,18 +141,19 @@ TEST(CreateRendererForLayout, SupportsChannelToChannelRenderer) { factory.CreateRendererForLayout( {0}, {{0, {kL2, kR2}}}, AudioElementObu::kAudioElementChannelBased, kStereoScalableChannelLayoutConfig, - kHeadphonesAsStereoRenderingConfig, kMonoLayout), + kHeadphonesAsStereoRenderingConfig, kMonoLayout, kNumSamplesPerFrame), nullptr); } TEST(CreateRendererForLayout, SupportsAmbisonicsToChannelRenderer) { const RendererFactory factory; - EXPECT_NE(factory.CreateRendererForLayout( - {0}, {{0, {kA0}}}, AudioElementObu::kAudioElementSceneBased, - kFullZerothOrderAmbisonicsConfig, - kHeadphonesAsStereoRenderingConfig, kMonoLayout), - nullptr); + EXPECT_NE( + factory.CreateRendererForLayout( + {0}, {{0, {kA0}}}, AudioElementObu::kAudioElementSceneBased, + kFullZerothOrderAmbisonicsConfig, kHeadphonesAsStereoRenderingConfig, + kMonoLayout, kNumSamplesPerFrame), + nullptr); } // TODO(b/282877209): Support ambisonics to binaural renderer. @@ -154,7 +163,8 @@ TEST(CreateRendererForLayout, ReturnsNullPtrForAmbisonicsToBinauralRenderer) { EXPECT_EQ(factory.CreateRendererForLayout( {0}, {{0, {kA0}}}, AudioElementObu::kAudioElementSceneBased, kFullZerothOrderAmbisonicsConfig, - kHeadphonesAsBinauralRenderingConfig, kBinauralLayout), + kHeadphonesAsBinauralRenderingConfig, kBinauralLayout, + kNumSamplesPerFrame), nullptr); } diff --git a/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc b/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc index d6d0c1f..cebb7df 100644 --- a/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc +++ b/iamf/cli/tests/rendering_mix_presentation_finalizer_test.cc @@ -81,12 +81,14 @@ class MockRenderer : public AudioElementRendererBase { public: MockRenderer(absl::Span ordered_labels, size_t num_output_channels) - : AudioElementRendererBase(ordered_labels, num_output_channels) {} + : AudioElementRendererBase(ordered_labels, + static_cast(kNumSamplesPerFrame), + num_output_channels) {} MockRenderer() : MockRenderer({}, 0) {} MOCK_METHOD( absl::Status, RenderSamples, - (const std::vector>& samples_to_render, + (absl::Span> samples_to_render, std::vector& rendered_samples), (override)); }; @@ -102,7 +104,7 @@ class MockRendererFactory : public RendererFactoryBase { AudioElementObu::AudioElementType audio_element_type, const AudioElementObu::AudioElementConfig& audio_element_config, const RenderingConfig& rendering_config, - const Layout& /*loudness_layout*/), + const Layout& loudness_layout, size_t num_samples_per_frame), (const, override)); }; @@ -118,7 +120,8 @@ class AlwaysNullRendererFactory : public RendererFactoryBase { AudioElementObu::AudioElementType /*audio_element_type*/, const AudioElementObu::AudioElementConfig& /*audio_element_config*/, const RenderingConfig& /*rendering_config*/, - const Layout& /*loudness_layout*/) const override { + const Layout& /*loudness_layout*/, + size_t /*num_samples_per_frame*/) const override { return nullptr; } }; @@ -349,10 +352,12 @@ TEST_F(FinalizerTest, ForwardsAudioElementToRenderer) { const auto& forwarded_audio_element = audio_elements_.at(kAudioElementId); EXPECT_CALL( *mock_renderer_factory, - CreateRendererForLayout(forwarded_audio_element.obu.audio_substream_ids_, - forwarded_audio_element.substream_id_to_labels, - forwarded_audio_element.obu.GetAudioElementType(), - forwarded_audio_element.obu.config_, _, _)); + CreateRendererForLayout( + forwarded_audio_element.obu.audio_substream_ids_, + forwarded_audio_element.substream_id_to_labels, + forwarded_audio_element.obu.GetAudioElementType(), + forwarded_audio_element.obu.config_, _, _, + forwarded_audio_element.codec_config->GetNumSamplesPerFrame())); renderer_factory_ = std::move(mock_renderer_factory); RenderingMixPresentationFinalizer finalizer = GetFinalizer(); @@ -373,7 +378,7 @@ TEST_F(FinalizerTest, ForwardsRenderingConfigToRenderer) { forwarded_sub_mix.audio_elements[0].rendering_config; EXPECT_CALL( *mock_renderer_factory, - CreateRendererForLayout(_, _, _, _, forwarded_rendering_config, _)); + CreateRendererForLayout(_, _, _, _, forwarded_rendering_config, _, _)); renderer_factory_ = std::move(mock_renderer_factory); RenderingMixPresentationFinalizer finalizer = GetFinalizer(); @@ -392,7 +397,7 @@ TEST_F(FinalizerTest, ForwardsLayoutToRenderer) { const auto& forwarded_sub_mix = obus_to_finalize_.front().sub_mixes_[0]; const auto& forwarded_layout = forwarded_sub_mix.layouts[0].loudness_layout; EXPECT_CALL(*mock_renderer_factory, - CreateRendererForLayout(_, _, _, _, _, forwarded_layout)); + CreateRendererForLayout(_, _, _, _, _, forwarded_layout, _)); renderer_factory_ = std::move(mock_renderer_factory); RenderingMixPresentationFinalizer finalizer = GetFinalizer(); @@ -412,10 +417,12 @@ TEST_F(FinalizerTest, ForwardsOrderedSamplesToRenderer) { const std::vector> kExpectedTimeChannelOrderedSamples = {{0, 2}, {1, 3}}; EXPECT_CALL(*mock_renderer, - RenderSamples(kExpectedTimeChannelOrderedSamples, _)); + RenderSamples( + absl::MakeConstSpan(kExpectedTimeChannelOrderedSamples), _)); auto mock_renderer_factory = std::make_unique(); ASSERT_NE(mock_renderer_factory, nullptr); - EXPECT_CALL(*mock_renderer_factory, CreateRendererForLayout(_, _, _, _, _, _)) + EXPECT_CALL(*mock_renderer_factory, + CreateRendererForLayout(_, _, _, _, _, _, _)) .WillOnce(Return(std::move(mock_renderer))); renderer_factory_ = std::move(mock_renderer_factory); RenderingMixPresentationFinalizer finalizer = GetFinalizer(); @@ -434,7 +441,8 @@ TEST_F(FinalizerTest, CreatesWavFileWhenRenderingIsSupported) { auto mock_renderer = std::make_unique(); EXPECT_CALL(*mock_renderer, RenderSamples(_, _)); auto mock_renderer_factory = std::make_unique(); - EXPECT_CALL(*mock_renderer_factory, CreateRendererForLayout(_, _, _, _, _, _)) + EXPECT_CALL(*mock_renderer_factory, + CreateRendererForLayout(_, _, _, _, _, _, _)) .WillOnce(Return(std::move(mock_renderer))); renderer_factory_ = std::move(mock_renderer_factory); RenderingMixPresentationFinalizer finalizer = GetFinalizer();