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