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