• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 3-Clause Clear License
5  * and the Alliance for Open Media Patent License 1.0. If the BSD 3-Clause Clear
6  * License was not distributed with this source code in the LICENSE file, you
7  * can obtain it at www.aomedia.org/license/software-license/bsd-3-c-c. If the
8  * Alliance for Open Media Patent License 1.0 was not distributed with this
9  * source code in the PATENTS file, you can obtain it at
10  * www.aomedia.org/license/patent.
11  */
12 #include "iamf/cli/renderer_factory.h"
13 
14 #include <cstddef>
15 #include <memory>
16 #include <variant>
17 #include <vector>
18 
19 #include "absl/log/log.h"
20 #include "iamf/cli/audio_element_with_data.h"
21 #include "iamf/cli/renderer/audio_element_renderer_ambisonics_to_channel.h"
22 #include "iamf/cli/renderer/audio_element_renderer_base.h"
23 #include "iamf/cli/renderer/audio_element_renderer_channel_to_channel.h"
24 #include "iamf/cli/renderer/audio_element_renderer_passthrough.h"
25 #include "iamf/obu/audio_element.h"
26 #include "iamf/obu/mix_presentation.h"
27 #include "iamf/obu/types.h"
28 
29 namespace iamf_tools {
30 
31 namespace {
32 
IsAudioElementRenderedBinaural(RenderingConfig::HeadphonesRenderingMode headphones_rendering_mode,Layout::LayoutType layout_type)33 bool IsAudioElementRenderedBinaural(
34     RenderingConfig::HeadphonesRenderingMode headphones_rendering_mode,
35     Layout::LayoutType layout_type) {
36   {
37     return headphones_rendering_mode ==
38                RenderingConfig::kHeadphonesRenderingModeBinaural &&
39            layout_type == Layout::kLayoutTypeBinaural;
40   }
41 }
42 
MaybeCreateAmbisonicsRenderer(bool use_binaural,const std::vector<DecodedUleb128> & audio_substream_ids,const SubstreamIdLabelsMap & substream_id_to_labels,const AudioElementObu::AudioElementConfig & config,const Layout & loudness_layout,size_t num_samples_per_frame)43 std::unique_ptr<AudioElementRendererBase> MaybeCreateAmbisonicsRenderer(
44     bool use_binaural, const std::vector<DecodedUleb128>& audio_substream_ids,
45     const SubstreamIdLabelsMap& substream_id_to_labels,
46     const AudioElementObu::AudioElementConfig& config,
47     const Layout& loudness_layout, size_t num_samples_per_frame) {
48   const auto* ambisonics_config = std::get_if<AmbisonicsConfig>(&config);
49   if (ambisonics_config == nullptr) {
50     LOG(ERROR) << "Ambisonics config is inconsistent with audio element type.";
51     return nullptr;
52   }
53 
54   if (use_binaural) {
55     LOG(WARNING) << "Skipping creating an Ambisonics to binaural-based "
56                     "renderer. Binaural rendering is not yet supported for "
57                     "ambisonics.";
58     return nullptr;
59   }
60 
61   return AudioElementRendererAmbisonicsToChannel::CreateFromAmbisonicsConfig(
62       *ambisonics_config, audio_substream_ids, substream_id_to_labels,
63       loudness_layout, num_samples_per_frame);
64 }
65 
MaybeCreateChannelRenderer(bool use_binaural,const AudioElementObu::AudioElementConfig & config,const Layout & loudness_layout,size_t num_samples_per_frame)66 std::unique_ptr<AudioElementRendererBase> MaybeCreateChannelRenderer(
67     bool use_binaural, const AudioElementObu::AudioElementConfig& config,
68     const Layout& loudness_layout, size_t num_samples_per_frame) {
69   const auto* channel_config =
70       std::get_if<ScalableChannelLayoutConfig>(&config);
71   if (channel_config == nullptr) {
72     LOG(ERROR) << "Channel config is inconsistent with audio element type.";
73     return nullptr;
74   }
75   // Lazily try to make a pass-through renderer.
76   auto pass_through_renderer =
77       AudioElementRendererPassThrough::CreateFromScalableChannelLayoutConfig(
78           *channel_config, loudness_layout, num_samples_per_frame);
79   if (pass_through_renderer != nullptr) {
80     return pass_through_renderer;
81   }
82 
83   if (use_binaural) {
84     LOG(WARNING) << "Skipping creating a channel to binaural-based renderer.";
85     return nullptr;
86   }
87   return AudioElementRendererChannelToChannel::
88       CreateFromScalableChannelLayoutConfig(*channel_config, loudness_layout,
89                                             num_samples_per_frame);
90 }
91 
92 }  // namespace
93 
~RendererFactoryBase()94 RendererFactoryBase::~RendererFactoryBase() {}
95 
96 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 & audio_element_config,const RenderingConfig & rendering_config,const Layout & loudness_layout,size_t num_samples_per_frame) const97 RendererFactory::CreateRendererForLayout(
98     const std::vector<DecodedUleb128>& audio_substream_ids,
99     const SubstreamIdLabelsMap& substream_id_to_labels,
100     AudioElementObu::AudioElementType audio_element_type,
101     const AudioElementObu::AudioElementConfig& audio_element_config,
102     const RenderingConfig& rendering_config, const Layout& loudness_layout,
103     size_t num_samples_per_frame) const {
104   const bool use_binaural = IsAudioElementRenderedBinaural(
105       rendering_config.headphones_rendering_mode, loudness_layout.layout_type);
106 
107   switch (audio_element_type) {
108     case AudioElementObu::kAudioElementSceneBased:
109       return MaybeCreateAmbisonicsRenderer(
110           use_binaural, audio_substream_ids, substream_id_to_labels,
111           audio_element_config, loudness_layout, num_samples_per_frame);
112     case AudioElementObu::kAudioElementChannelBased:
113       return MaybeCreateChannelRenderer(use_binaural, audio_element_config,
114                                         loudness_layout, num_samples_per_frame);
115     case AudioElementObu::kAudioElementBeginReserved:
116     case AudioElementObu::kAudioElementEndReserved:
117       LOG(WARNING) << "Unsupported audio_element_type_= " << audio_element_type;
118       return nullptr;
119   }
120   // The above switch is exhaustive.
121   LOG(FATAL) << "Unsupported audio_element_type_= " << audio_element_type;
122 }
123 
124 }  // namespace iamf_tools
125