• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023, 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 
13 #ifndef CLI_ENCODER_BASE_H_
14 #define CLI_ENCODER_BASE_H_
15 
16 #include <cstdint>
17 #include <list>
18 #include <memory>
19 #include <vector>
20 
21 #include "absl/base/thread_annotations.h"
22 #include "absl/status/status.h"
23 #include "absl/synchronization/mutex.h"
24 #include "iamf/cli/audio_frame_with_data.h"
25 #include "iamf/obu/codec_config.h"
26 
27 namespace iamf_tools {
28 
29 class EncoderBase {
30  public:
31   /*!\brief Constructor.
32    *
33    * After constructing `Initialize()` MUST be called and return successfully
34    * before using most functionality of the encoder.
35    *
36    * - Call `EncodeAudioFrame()` to encode an audio frame. The encoding may
37    *   happen asynchronously.
38    * - Call `FramesAvailable()` to see if there is any finished frame.
39    * - Call `Pop()` to retrieve finished frames one at a time, in the order
40    *   they were received by `EncodeAudioFrame()`.
41    * - Call `Finalize()` to close the encoder, telling it to finish encoding
42    *   any remaining frames, which can be retrieved via subsequent `Pop()`s.
43    *   After calling `Finalize()`, any subsequent call to `EncodeAudioFrame()`
44    *   will fail.
45    *
46    * \param codec_config Codec Config OBU for the encoder.
47    * \num_channels Number of channels for the encoder.
48    */
EncoderBase(const CodecConfigObu & codec_config,int num_channels)49   EncoderBase(const CodecConfigObu& codec_config, int num_channels)
50       : num_samples_per_frame_(codec_config.GetNumSamplesPerFrame()),
51         input_sample_rate_(codec_config.GetInputSampleRate()),
52         output_sample_rate_(codec_config.GetOutputSampleRate()),
53         input_pcm_bit_depth_(codec_config.GetBitDepthToMeasureLoudness()),
54         num_channels_(num_channels) {}
55 
56   /*!\brief Destructor. */
57   virtual ~EncoderBase() = 0;
58 
59   /*!\brief Initializes `EncoderBase`.
60    *
61    * \param validate_codec_delay If true, validates the Codec Config OBU fields
62    *        related to codec delay agree with the encoder.
63    * \return `absl::OkStatus()` on success. A specific status on failure.
64    */
65   absl::Status Initialize(bool validate_codec_delay);
66 
67   /*!\brief Encodes an audio frame.
68    *
69    * \param input_bit_depth Bit-depth of the input data.
70    * \param samples Samples arranged in (time x channel) axes. The samples are
71    *        left-justified and stored in the upper `input_bit_depth` bits.
72    * \param partial_audio_frame_with_data Unique pointer to take ownership of.
73    *        The underlying `audio_frame_` is modified. All other fields are
74    *        blindly passed along.
75    * \return `absl::OkStatus()` on success. Success does not necessarily mean
76    *         the frame was finished. A specific status on failure.
77    */
78   virtual absl::Status EncodeAudioFrame(
79       int input_bit_depth, const std::vector<std::vector<int32_t>>& samples,
80       std::unique_ptr<AudioFrameWithData> partial_audio_frame_with_data) = 0;
81 
82   /*!\brief Gets whether there are frames available.
83    *
84    * Available frames can be retrieved by `Pop()`.
85    *
86    * \return True if there is any finished audio frame.
87    */
FramesAvailable()88   bool FramesAvailable() const {
89     absl::MutexLock lock(&mutex_);
90     return !finalized_audio_frames_.empty();
91   }
92 
93   /*!\brief Pop the first finished audio frame (if any).
94    *
95    * \param audio_frames List to append the first finished frame to.
96    * \return `absl::OkStatus()` on success. A specific status on failure.
97    */
Pop(std::list<AudioFrameWithData> & audio_frames)98   absl::Status Pop(std::list<AudioFrameWithData>& audio_frames) {
99     absl::MutexLock lock(&mutex_);
100     if (!finalized_audio_frames_.empty()) {
101       audio_frames.splice(audio_frames.end(), finalized_audio_frames_,
102                           finalized_audio_frames_.begin());
103     }
104     return absl::OkStatus();
105   }
106 
107   /*!\brief Finalizes the encoder, signaling it to finish any remaining frames.
108    *
109    * This function MUST be called at most once before popping the last batch
110    * of encoded audio frames.
111    *
112    * \return `absl::OkStatus()` on success. A specific status on failure.
113    */
Finalize()114   virtual absl::Status Finalize() {
115     absl::MutexLock lock(&mutex_);
116     finished_ = true;
117     return absl::OkStatus();
118   }
119 
120   /*!\brief Gets whether the encoder has been closed.
121    *
122    * \return True if the encoder has been closed.
123    */
Finished()124   bool Finished() const {
125     absl::MutexLock lock(&mutex_);
126     return finished_ && finalized_audio_frames_.empty();
127   }
128 
129   /*!\brief Gets the required number of samples to delay at the start.
130    *
131    * Sometimes this is called "pre-skip". This represents the number of initial
132    * "junk" samples output from the encoder. In IAMF this represents the
133    * recommended amount of samples to trim at the start of a substream.
134    *
135    * \return Number of samples to delay at the start of the substream.
136    */
GetNumberOfSamplesToDelayAtStart()137   uint32_t GetNumberOfSamplesToDelayAtStart() const {
138     return required_samples_to_delay_at_start_;
139   }
140 
141   const uint32_t num_samples_per_frame_;
142   const uint32_t input_sample_rate_;
143   const uint32_t output_sample_rate_;
144   const uint8_t input_pcm_bit_depth_;
145   const int num_channels_;
146 
147  protected:
148   /*!\brief Initializes the child class.
149    *
150    * \return `absl::OkStatus()` on success. A specific status on failure.
151    */
152   virtual absl::Status InitializeEncoder() = 0;
153 
154   /*!\brief Initializes `required_samples_to_delay_at_start_`.
155    *
156    * \param validate_codec_delay If true, validates the Codec Config OBU fields
157    *        related to codec delay agree with the encoder.
158    * \return `absl::OkStatus()` on success. A specific status on failure.
159    */
SetNumberOfSamplesToDelayAtStart(bool)160   virtual absl::Status SetNumberOfSamplesToDelayAtStart(
161       bool /*validate_codec_delay*/) {
162     required_samples_to_delay_at_start_ = 0;
163     return absl::OkStatus();
164   }
165 
166   /*!\brief Validates `Finalize()` has not yet been called.
167    *
168    * \return `absl::OkStatus()` on success. A specific status on failure.
169    */
ValidateNotFinalized()170   absl::Status ValidateNotFinalized() {
171     if (Finished()) {
172       return absl::InvalidArgumentError(
173           "Encoding is disallowed after `Finalize()` has been called");
174     }
175     return absl::OkStatus();
176   }
177 
178   /*!\brief Validates `samples` has the correct number of ticks and channels.
179    *
180    * \return `absl::OkStatus()` on success. A specific status on failure.
181    */
182   absl::Status ValidateInputSamples(
183       const std::vector<std::vector<int32_t>>& samples) const;
184 
185   uint32_t required_samples_to_delay_at_start_ = 0;
186 
187   // Mutex to guard simultaneous access to data members.
188   mutable absl::Mutex mutex_;
189 
190   std::list<AudioFrameWithData> finalized_audio_frames_
191       ABSL_GUARDED_BY(mutex_) = {};
192 
193   // Whether the encoding has been closed.
194   bool finished_ ABSL_GUARDED_BY(mutex_) = false;
195 };
196 
197 }  // namespace iamf_tools
198 
199 #endif  // CLI_ENCODER_BASE_H_
200