• 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 #ifndef CLI_RENDERER_AUDIO_ELEMENT_RENDERER_BASE_H_
13 #define CLI_RENDERER_AUDIO_ELEMENT_RENDERER_BASE_H_
14 #include <cstddef>
15 #include <vector>
16 
17 #include "absl/base/thread_annotations.h"
18 #include "absl/status/status.h"
19 #include "absl/status/statusor.h"
20 #include "absl/synchronization/mutex.h"
21 #include "absl/types/span.h"
22 #include "iamf/cli/channel_label.h"
23 #include "iamf/cli/demixing_module.h"
24 #include "iamf/obu/types.h"
25 
26 namespace iamf_tools {
27 /*!\brief Abstract class to render a demixed audio element to a playback layout.
28  *
29  * This class represents an abstract interface to render a single audio element
30  * to a single layout according to IAMF Spec 7.3.2
31  * (https://aomediacodec.github.io/iamf/#processing-mixpresentation-rendering).
32  *
33  * - Call `RenderAudioFrame()` to render a labeled frame. The rendering may
34  *   happen asynchronously.
35  * - Call `Flush()` to retrieve finished frames, in the order they were
36  *   received by `RenderLabeledFrame()`.
37  * - Call `Finalize()` to close the renderer, telling it to finish rendering
38  *   any remaining frames. Afterwards `IsFinalized()` should be called until it
39  *   returns true, then audio frames should be  retrieved one last time via
40  *   `Flush()`. After calling `Finalize()`, any subsequent call to
41  *   `RenderAudioFrame()` may fail.
42  * - Call `IsFinalized()` to ensure the renderer is Finalized.
43  */
44 class AudioElementRendererBase {
45  public:
46   /*!\brief Destructor. */
47   virtual ~AudioElementRendererBase() = 0;
48 
49   /*!\brief Renders samples stored in labeled frames.
50    *
51    * \param labeled_frame Labeled frame to render.
52    * \return Number of ticks that will be rendered. A specific status on
53    *         failure.
54    */
55   absl::StatusOr<size_t> RenderLabeledFrame(const LabeledFrame& labeled_frame);
56 
57   /*!\brief Flushes finished audio frames.
58    *
59    * \param rendered_samples Vector to append rendered samples to.
60    * \return `absl::OkStatus()` on success. A specific status on failure.
61    */
62   absl::Status Flush(std::vector<InternalSampleType>& rendered_samples);
63 
64   /*!\brief Finalizes the renderer. Waits for it to finish any remaining frames.
65    *
66    * \return `absl::OkStatus()` on success. A specific status on failure.
67    */
Finalize()68   virtual absl::Status Finalize() {
69     absl::MutexLock lock(&mutex_);
70     is_finalized_ = true;
71     return absl::OkStatus();
72   }
73 
74   /*!\brief Checks if the renderer is finalized.
75    *
76    * Sub-classes should override this if the renderer is not finalized directly
77    * in the body of `Finalize()`.
78    *
79    * \return `true` if the render is finalized. `false` otherwise.
80    */
IsFinalized()81   virtual bool IsFinalized() const {
82     absl::MutexLock lock(&mutex_);
83     return is_finalized_;
84   }
85 
86  protected:
87   /*!\brief Constructor.
88    *
89    * \param ordered_labels Ordered list of channel labels to render.
90    * \param num_samples_per_frame Number of samples per frame.
91    * \param num_output_channels Number of output channels.
92    */
AudioElementRendererBase(absl::Span<const ChannelLabel::Label> ordered_labels,const size_t num_samples_per_frame,const size_t num_output_channels)93   AudioElementRendererBase(absl::Span<const ChannelLabel::Label> ordered_labels,
94                            const size_t num_samples_per_frame,
95                            const size_t num_output_channels)
96       : ordered_labels_(ordered_labels.begin(), ordered_labels.end()),
97         num_samples_per_frame_(num_samples_per_frame),
98         num_output_channels_(num_output_channels),
99         samples_to_render_(
100             num_samples_per_frame_,
101             std::vector<InternalSampleType>(ordered_labels_.size(), 0)) {}
102 
103   /*!\brief Renders samples.
104    *
105    * \param samples_to_render Samples to render arranged in (time, channel).
106    * \param rendered_samples Output rendered samples.
107    * \return `absl::OkStatus()` on success. A specific status on failure.
108    */
109   virtual absl::Status RenderSamples(
110       absl::Span<const std::vector<InternalSampleType>> samples_to_render,
111       std::vector<InternalSampleType>& rendered_samples)
112       ABSL_SHARED_LOCKS_REQUIRED(mutex_) = 0;
113 
114   const std::vector<ChannelLabel::Label> ordered_labels_;
115   const size_t num_samples_per_frame_ = 0;
116   const size_t num_output_channels_;
117 
118   // Mutex to guard simultaneous access to data members.
119   mutable absl::Mutex mutex_;
120   std::vector<std::vector<InternalSampleType>> samples_to_render_
121       ABSL_GUARDED_BY(mutex_);
122   std::vector<InternalSampleType> rendered_samples_ ABSL_GUARDED_BY(mutex_);
123   bool is_finalized_ ABSL_GUARDED_BY(mutex_) = false;
124   const LabeledFrame* current_labeled_frame_ ABSL_GUARDED_BY(mutex_) = nullptr;
125 };
126 
127 }  // namespace iamf_tools
128 #endif  // CLI_RENDERER_AUDIO_ELEMENT_RENDERER_BASE_H_
129