Skip to content

Commit

Permalink
Create an abstract RendererFactory.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 628081076
  • Loading branch information
jwcullen committed Apr 25, 2024
1 parent 362cb87 commit cb4cff4
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 3 deletions.
13 changes: 13 additions & 0 deletions iamf/cli/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,19 @@ cc_library(
],
)

cc_library(
name = "renderer_factory",
srcs = ["renderer_factory.cc"],
hdrs = ["renderer_factory.h"],
deps = [
":audio_element_with_data",
"//iamf/cli/renderer:audio_element_renderer_base",
"//iamf/obu:audio_element",
"//iamf/obu:leb128",
"//iamf/obu:mix_presentation",
],
)

cc_library(
name = "wav_reader",
srcs = ["wav_reader.cc"],
Expand Down
2 changes: 1 addition & 1 deletion iamf/cli/mix_presentation_finalizer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ MeasureLoudnessOrFallbackToUserLoudnessMixPresentationFinalizer::Finalize(
LOG(INFO) << " Loudness information may be copied from user "
<< "provided values.";

// TODO(b/332567539): Render and measure loudness for certain layouts.
// TODO(b/332567539): Use `RendererFactory` to render certain layouts.
int metadata_index = 0;
for (auto& mix_presentation_obu : mix_presentation_obus) {
for (int sub_mix_index = 0;
Expand Down
40 changes: 40 additions & 0 deletions iamf/cli/renderer_factory.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright (c) 2024, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* www.aomedia.org/license/patent.
*/
#include "iamf/cli/renderer_factory.h"

#include <memory>
#include <vector>

#include "iamf/cli/audio_element_with_data.h"
#include "iamf/cli/renderer/audio_element_renderer_base.h"
#include "iamf/obu/audio_element.h"
#include "iamf/obu/leb128.h"
#include "iamf/obu/mix_presentation.h"

namespace iamf_tools {

RendererFactoryBase::~RendererFactoryBase() {}

std::unique_ptr<AudioElementRendererBase>
RendererFactory::CreateRendererForLayout(
const std::vector<DecodedUleb128>& audio_substream_ids,
const SubstreamIdLabelsMap& substream_id_to_labels,
AudioElementObu::AudioElementType audio_element_type,
const AudioElementObu::AudioElementConfig& config,
const Layout& loudness_layout) const {
// TODO(b/332567539): Implement and return renderers depending on the input
// audio element and output layout.

return nullptr;
}

} // namespace iamf_tools
89 changes: 89 additions & 0 deletions iamf/cli/renderer_factory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (c) 2024, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* www.aomedia.org/license/patent.
*/
#ifndef CLI_RENDERER_FACTORY_H_
#define CLI_RENDERER_FACTORY_H_

#include <memory>
#include <vector>

#include "iamf/cli/audio_element_with_data.h"
#include "iamf/cli/renderer/audio_element_renderer_base.h"
#include "iamf/obu/audio_element.h"
#include "iamf/obu/leb128.h"
#include "iamf/obu/mix_presentation.h"

namespace iamf_tools {

/*\!brief Abstract class to create renderers.
*
* This class will be used when rendering the loudness of a mix presentation
* layout. The mix presentation finalizer will take in a factory and use them to
* create a renderers. By taking in a factory the finalizer can be agnostic to
* the collection of renderers that are being used and it what circumstances
* they are used.
*/
class RendererFactoryBase {
public:
/*\!brief Creates a renderer based on the audio element and layout.
*
* \param audio_substream_ids Audio susbtream IDs.
* \param substream_id_to_labels Mapping of substream IDs to labels.
* \param audio_element_type Type of the audio element.
* \param config Configuration of the audio element.
* \param loudness_layout Layout to render to.
* \return Unique pointer to an audio element renderer or `nullptr` if it not
* known how to render the audio element.
*/
virtual std::unique_ptr<AudioElementRendererBase> CreateRendererForLayout(
const std::vector<DecodedUleb128>& audio_substream_ids,
const SubstreamIdLabelsMap& substream_id_to_labels,
AudioElementObu::AudioElementType audio_element_type,
const AudioElementObu::AudioElementConfig& config,
const Layout& loudness_layout) const = 0;

/*\!brief Destructor. */
virtual ~RendererFactoryBase() = 0;
};

/*\!brief Factory which creates a renderers.
*
* This factory provides renderers in a best-effort manner according to the
* recommendations in the IAMF specification. When a recommended renderer is not
* implemented by `iamf-tools` the factory will fallback to returning a
* `nullptr`.
*/
class RendererFactory : public RendererFactoryBase {
public:
/*\!brief Creates a renderer based on the audio element and layout.
*
* \param audio_substream_ids Audio susbtream IDs.
* \param substream_id_to_labels Mapping of substream IDs to labels.
* \param audio_element_type Type of the audio element.
* \param config Configuration of the audio element.
* \param loudness_layout Layout to render to.
* \return Unique pointer to an audio element renderer or `nullptr` if it not
* known how to render the audio element.
*/
std::unique_ptr<AudioElementRendererBase> CreateRendererForLayout(
const std::vector<DecodedUleb128>& audio_substream_ids,
const SubstreamIdLabelsMap& substream_id_to_labels,
AudioElementObu::AudioElementType audio_element_type,
const AudioElementObu::AudioElementConfig& config,
const Layout& loudness_layout) const override;

/*\!brief Destructor. */
~RendererFactory() override = default;
};

} // namespace iamf_tools

#endif // CLI_LOUDNESS_CALCULATOR_H_
15 changes: 15 additions & 0 deletions iamf/cli/tests/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,21 @@ cc_test(
],
)

cc_test(
name = "renderer_factory_test",
srcs = ["renderer_factory_test.cc"],
deps = [
"//iamf/cli:renderer_factory",
"//iamf/cli/proto:obu_header_cc_proto",
"//iamf/cli/proto:parameter_data_cc_proto",
"//iamf/cli/proto:temporal_delimiter_cc_proto",
"//iamf/cli/proto:user_metadata_cc_proto",
"//iamf/obu:audio_element",
"//iamf/obu:mix_presentation",
"@com_google_googletest//:gtest_main",
],
)

cc_test(
name = "wav_reader_test",
srcs = ["wav_reader_test.cc"],
Expand Down
95 changes: 95 additions & 0 deletions iamf/cli/tests/renderer_factory_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
* Copyright (c) 2024, Alliance for Open Media. All rights reserved
*
* This source code is subject to the terms of the BSD 3-Clause Clear License
* and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
* License was not distributed with this source code in the LICENSE file, you
* can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
* Alliance for Open Media Patent License 1.0 was not distributed with this
* source code in the PATENTS file, you can obtain it at
* www.aomedia.org/license/patent.
*/
#include "iamf/cli/renderer_factory.h"

#include "gtest/gtest.h"
#include "iamf/cli/proto/obu_header.pb.h"
#include "iamf/cli/proto/parameter_data.pb.h"
#include "iamf/cli/proto/temporal_delimiter.pb.h"
#include "iamf/cli/proto/user_metadata.pb.h"
#include "iamf/obu/audio_element.h"
#include "iamf/obu/mix_presentation.h"

namespace iamf_tools {
namespace {

using enum LoudspeakersSsConventionLayout::SoundSystem;
using enum ChannelAudioLayerConfig::LoudspeakerLayout;

const Layout kMonoLayout = {
.layout_type = Layout::kLayoutTypeLoudspeakersSsConvention,
.specific_layout =
LoudspeakersSsConventionLayout{.sound_system = kSoundSystem12_0_1_0}};
const Layout kBinauralLayout = {.layout_type = Layout::kLayoutTypeBinaural};

const ScalableChannelLayoutConfig kMonoScalableChannelLayoutConfig = {
.num_layers = 1,
.channel_audio_layer_configs = {{.loudspeaker_layout = kLayoutMono}}};

const ScalableChannelLayoutConfig kStereoScalableChannelLayoutConfig = {
.num_layers = 1,
.channel_audio_layer_configs = {{.loudspeaker_layout = kLayoutStereo}}};

const AmbisonicsConfig kFullZerothOrderAmbisonicsConfig = {
.ambisonics_mode = AmbisonicsConfig::kAmbisonicsModeMono,
.ambisonics_config = AmbisonicsMonoConfig{.output_channel_count = 1,
.substream_count = 1,
.channel_mapping = {0}}};

TEST(CreateRendererForLayout, ReturnsNullPtrForPassThroughRenderer) {
const RendererFactory factory;

EXPECT_EQ(factory.CreateRendererForLayout(
{0}, {{0, {"M"}}}, AudioElementObu::kAudioElementChannelBased,
kMonoScalableChannelLayoutConfig, kMonoLayout),
nullptr);
}

TEST(CreateRendererForLayout, ReturnsNullPtrForChannelToBinauralRenderer) {
const RendererFactory factory;

EXPECT_EQ(factory.CreateRendererForLayout(
{0}, {{0, {"M"}}}, AudioElementObu::kAudioElementChannelBased,
kMonoScalableChannelLayoutConfig, kBinauralLayout),
nullptr);
}

TEST(CreateRendererForLayout, ReturnsNullPtrForChannelToChannelRenderer) {
const RendererFactory factory;

EXPECT_EQ(
factory.CreateRendererForLayout(
{0}, {{0, {"L2", "R2"}}}, AudioElementObu::kAudioElementChannelBased,
kStereoScalableChannelLayoutConfig, kMonoLayout),
nullptr);
}

TEST(CreateRendererForLayout, ReturnsNullPtrForAmbisonicsToChannelRenderer) {
const RendererFactory factory;

EXPECT_EQ(factory.CreateRendererForLayout(
{0}, {{0, {"A0"}}}, AudioElementObu::kAudioElementSceneBased,
kFullZerothOrderAmbisonicsConfig, kMonoLayout),
nullptr);
}

TEST(CreateRendererForLayout, ReturnsNullPtrForAmbisonicsToBinauralRenderer) {
const RendererFactory factory;

EXPECT_EQ(factory.CreateRendererForLayout(
{0}, {{0, {"A0"}}}, AudioElementObu::kAudioElementSceneBased,
kFullZerothOrderAmbisonicsConfig, kBinauralLayout),
nullptr);
}

} // namespace
} // namespace iamf_tools
7 changes: 5 additions & 2 deletions iamf/obu/audio_element.h
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,10 @@ class AudioElementObu : public ObuBase {
kAudioElementEndReserved = 7,
};

typedef std::variant<ScalableChannelLayoutConfig, AmbisonicsConfig,
ExtensionConfig>
AudioElementConfig;

/*!\brief Constructor.
*
* \param header `ObuHeader` of the OBU.
Expand Down Expand Up @@ -332,8 +336,7 @@ class AudioElementObu : public ObuBase {
std::vector<AudioElementParam> audio_element_params_;

// Active field depends on `audio_element_type_`.
std::variant<ScalableChannelLayoutConfig, AmbisonicsConfig, ExtensionConfig>
config_;
AudioElementConfig config_;

private:
DecodedUleb128 audio_element_id_;
Expand Down

0 comments on commit cb4cff4

Please sign in to comment.