• 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 #ifndef OBU_CODEC_CONFIG_H_
13 #define OBU_CODEC_CONFIG_H_
14 
15 #include <cstdint>
16 #include <string>
17 #include <variant>
18 
19 #include "absl/status/status.h"
20 #include "absl/status/statusor.h"
21 #include "absl/strings/str_cat.h"
22 #include "iamf/common/read_bit_buffer.h"
23 #include "iamf/common/write_bit_buffer.h"
24 #include "iamf/obu/decoder_config/aac_decoder_config.h"
25 #include "iamf/obu/decoder_config/flac_decoder_config.h"
26 #include "iamf/obu/decoder_config/lpcm_decoder_config.h"
27 #include "iamf/obu/decoder_config/opus_decoder_config.h"
28 #include "iamf/obu/obu_base.h"
29 #include "iamf/obu/obu_header.h"
30 #include "iamf/obu/types.h"
31 
32 namespace iamf_tools {
33 
34 // TODO(b/305752871): Port this `std::variant` to a virtual class.
35 typedef std::variant<OpusDecoderConfig, AacDecoderConfig, FlacDecoderConfig,
36                      LpcmDecoderConfig>
37     DecoderConfig;
38 
39 struct CodecConfig {
40   enum CodecId : uint32_t {
41     kCodecIdOpus = 0x4f707573,   // "Opus"
42     kCodecIdFlac = 0x664c6143,   // "fLaC"
43     kCodecIdLpcm = 0x6970636d,   // "ipcm"
44     kCodecIdAacLc = 0x6d703461,  // "mp4a"
45   };
46 
47   template <typename Sink>
AbslStringifyCodecConfig48   friend void AbslStringify(Sink& sink, const CodecId& codec_id) {
49     std::string human_readable_codec_id;
50     switch (codec_id) {
51       case kCodecIdOpus:
52         human_readable_codec_id = "Opus";
53         break;
54       case kCodecIdFlac:
55         human_readable_codec_id = "FLAC";
56         break;
57       case kCodecIdLpcm:
58         human_readable_codec_id = "LPCM";
59         break;
60       case kCodecIdAacLc:
61         human_readable_codec_id = "AAC LC";
62         break;
63       default:
64         human_readable_codec_id = "Unknown";
65         break;
66     }
67 
68     sink.Append(absl::StrCat("0x", absl::Hex(codec_id, absl::kZeroPad8), " ( ",
69                              human_readable_codec_id, " )"));
70   }
71 
72   friend bool operator==(const CodecConfig& lhs,
73                          const CodecConfig& rhs) = default;
74 
75   CodecId codec_id;
76   DecodedUleb128 num_samples_per_frame;
77   int16_t audio_roll_distance;
78 
79   // Active field depends on `codec_id`.
80   DecoderConfig decoder_config;
81 };
82 
83 class CodecConfigObu : public ObuBase {
84  public:
85   /*!\brief Constructor.
86    *
87    * After constructing `Initialize` MUST be called and return successfully
88    * before using most functionality of the OBU.
89    *
90    * \param header `ObuHeader` of the OBU.
91    * \param codec_config_id `codec_config_id` in the OBU.
92    * \param codec_config `codec_config` in the OBU.
93    */
94   CodecConfigObu(const ObuHeader& header, DecodedUleb128 codec_config_id,
95                  const CodecConfig& codec_config);
96 
97   /*!\brief Creates a `CodecConfigObu` from a `ReadBitBuffer`.
98    *
99    * This function is designed to be used from the perspective of the decoder.
100    * It will call `ReadAndValidatePayload` in order to read from the buffer;
101    * therefore it can fail.
102    *
103    * \param header `ObuHeader` of the OBU.
104    * \param payload_size Size of the obu payload in bytes.
105    * \param rb `ReadBitBuffer` where the `CodecConfigObu` data is stored. Data
106    *        read from the buffer is consumed.
107    * \return a `CodecConfigObu` on success. A specific status on failure.
108    */
109   static absl::StatusOr<CodecConfigObu> CreateFromBuffer(
110       const ObuHeader& header, int64_t payload_size, ReadBitBuffer& rb);
111 
112   /*!\brief Destructor. */
113   ~CodecConfigObu() override = default;
114 
115   friend bool operator==(const CodecConfigObu& lhs,
116                          const CodecConfigObu& rhs) = default;
117 
118   /*!\brief Prints logging information about the OBU.*/
119   void PrintObu() const override;
120 
121   /*!\brief Initializes the OBU.
122    *
123    * `GetOutputSampleRate`, `GetInputSampleRate`, and
124    * `GetBitDepthToMeasureLoudness` may return inaccurate values if this
125    * function did not return `absl::OkStatus()`.
126    *
127    * \param automatically_override_roll_distance If true, the roll distance will
128    *        be overridden to value required by the IAMF spec.
129    * \return `absl::OkStatus()` on success. A specific status on failure.
130    */
131   absl::Status Initialize(bool automatically_override_roll_distance = true);
132 
133   /*!\brief Sets the codec delay in the underlying `decoder_config`.
134    *
135    * In some codecs, like Opus, the codec delay is called "pre-skip".
136    *
137    * \param codec_delay Codec delay to set in the underlying `decoder_config`.
138    * \return `absl::OkStatus()` on success. Succeed may be a no-op when the
139    *         underlying `decoder_config` does not have a field for codec delay.
140    *         A specific status on failure.
141    */
142   absl::Status SetCodecDelay(uint16_t codec_delay);
143 
144   /*!\brief Validates and writes the `DecoderConfig` portion of the OBU.
145    *
146    * \param wb Buffer to write to.
147    * \return `absl::OkStatus()` on success. A specific status on failure.
148    */
149   absl::Status ValidateAndWriteDecoderConfig(WriteBitBuffer& wb) const;
150 
151   /*!\brief Validates and reads the `DecoderConfig` portion of the OBU.
152    *
153    * \param rb Buffer to read from.
154    * \return `absl::OkStatus()` on success. A specific status on failure.
155    */
156   absl::Status ReadAndValidateDecoderConfig(ReadBitBuffer& rb);
157 
158   /*!\brief Gets the output sample rate associated with the OBU.
159    *
160    * This sample rate is used for timing and offset calculations as per
161    * section 3.11 of the IAMF spec.
162    *
163    *   - AAC, FLAC, LPCM: Based on the sample rate of the input stream.
164    *   - Opus: Always 48kHz ("The sample rate used for computing offsets SHALL
165    *           be 48 kHz.").
166    *
167    * \return Output sample rate in Hz if the OBU was initialized successfully.
168    */
GetOutputSampleRate()169   uint32_t GetOutputSampleRate() const { return output_sample_rate_; }
170 
171   /*!\brief Gets the input sample rate associated with the OBU.
172    *
173    * The sample rate of the data before being passed to the underlying codec
174    * libraries.
175    *
176    * \return Input sample rate in Hz if the OBU was initialized successfully.
177    */
GetInputSampleRate()178   uint32_t GetInputSampleRate() const { return input_sample_rate_; }
179 
180   /*!\brief Gets the bit-depth of the PCM to be used to measure loudness.
181    *
182    * This typically is the highest bit-depth associated substreams should be
183    * decoded to.
184    *
185    * \return Bit-depth of the PCM which will be used to measure loudness if the
186    *         OBU was initialized successfully.
187    */
GetBitDepthToMeasureLoudness()188   uint32_t GetBitDepthToMeasureLoudness() const {
189     return bit_depth_to_measure_loudness_;
190   }
191 
192   /*!\brief Gets the number of samples per frame of the OBU.
193    *
194    * \return Num samples per frame of the OBU.
195    */
GetNumSamplesPerFrame()196   uint32_t GetNumSamplesPerFrame() const {
197     return codec_config_.num_samples_per_frame;
198   }
199 
200   /*!\brief Gets the codec config id of the OBU.
201    *
202    * \return codec config id of the OBU.
203    */
GetCodecConfigId()204   DecodedUleb128 GetCodecConfigId() const { return codec_config_id_; }
205 
206   /*!\brief Gets the codec config of the OBU.
207    *
208    * \return codec config of the OBU.
209    */
GetCodecConfig()210   const CodecConfig& GetCodecConfig() const { return codec_config_; }
211 
212   bool IsLossless() const;
213 
214  private:
215   // Used only by the factory create function.
CodecConfigObu(const ObuHeader & header)216   explicit CodecConfigObu(const ObuHeader& header)
217       : ObuBase(header, kObuIaCodecConfig),
218         codec_config_id_(DecodedUleb128()),
219         codec_config_(CodecConfig()) {}
220 
221   // Fields in the OBU as per the IAMF specification.
222   DecodedUleb128 codec_config_id_;
223   CodecConfig codec_config_;
224 
225   // Metadata fields.
226   uint32_t input_sample_rate_ = 0;
227   uint32_t output_sample_rate_ = 0;
228   uint8_t bit_depth_to_measure_loudness_ = 0;
229 
230   // Tracks whether the OBU was initialized correctly.
231   absl::Status init_status_ =
232       absl::UnknownError("Codec Config OBU was not initialized correctly.");
233 
234   /*!\brief Writes the OBU payload to the buffer.
235    *
236    * \param wb Buffer to write to.
237    * \return `absl::OkStatus()` if the OBU is valid. A specific status on
238    *         failure.
239    */
240   absl::Status ValidateAndWritePayload(WriteBitBuffer& wb) const override;
241 
242   /*!\brief Reads the OBU payload from the buffer.
243    *
244    * \param payload_size Size of the obu payload in bytes.
245    * \param rb Buffer to read from.
246    * \return `absl::OkStatus()` if the payload is valid. A specific status on
247    *         failure.
248    */
249   absl::Status ReadAndValidatePayloadDerived(int64_t payload_size,
250                                              ReadBitBuffer& rb) override;
251 };
252 
253 }  // namespace iamf_tools
254 
255 #endif  // OBU_CODEC_CONFIG_H_
256