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_MIX_PRESENTATION_H_ 13 #define OBU_MIX_PRESENTATION_H_ 14 15 #include <cstdint> 16 #include <optional> 17 #include <string> 18 #include <utility> 19 #include <variant> 20 #include <vector> 21 22 #include "absl/status/status.h" 23 #include "absl/status/statusor.h" 24 #include "iamf/common/read_bit_buffer.h" 25 #include "iamf/common/write_bit_buffer.h" 26 #include "iamf/obu/obu_base.h" 27 #include "iamf/obu/obu_header.h" 28 #include "iamf/obu/param_definitions.h" 29 #include "iamf/obu/types.h" 30 31 namespace iamf_tools { 32 33 struct RenderingConfig { 34 /*!\brief A 2-bit enum describing how to render the content to headphones. */ 35 enum HeadphonesRenderingMode : uint8_t { 36 kHeadphonesRenderingModeStereo = 0, 37 kHeadphonesRenderingModeBinaural = 1, 38 kHeadphonesRenderingModeReserved2 = 2, 39 kHeadphonesRenderingModeReserved3 = 3, 40 }; 41 42 friend bool operator==(const RenderingConfig& lhs, 43 const RenderingConfig& rhs) = default; 44 HeadphonesRenderingMode headphones_rendering_mode; // 2 bits. 45 uint8_t reserved; // 6 bits. 46 DecodedUleb128 rendering_config_extension_size; 47 // Length `rendering_config_extension_size`. 48 std::vector<uint8_t> rendering_config_extension_bytes; 49 }; 50 51 /*!\brief One of the audio elements within a sub-mix. */ 52 struct SubMixAudioElement { 53 friend bool operator==(const SubMixAudioElement& lhs, 54 const SubMixAudioElement& rhs) = default; 55 56 /*!\brief Reads and validates the SubMixAudioElement from the buffer. 57 * 58 * \param rb Buffer to read from. 59 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 60 * write fails. 61 */ 62 absl::Status ReadAndValidate(const int32_t& count_label, ReadBitBuffer& rb); 63 64 // The ID of the associated Audio Element OBU. 65 DecodedUleb128 audio_element_id; 66 // Length `count_labels`. 67 std::vector<std::string> localized_element_annotations; 68 RenderingConfig rendering_config; 69 // The gain value to be applied to the rendered audio element signal. 70 MixGainParamDefinition element_mix_gain; 71 }; 72 73 struct AnchoredLoudnessElement { 74 /*!\brief A 8-bit enum for the associated loudness measurement. 75 * 76 * As defined in ISO-CICP. 77 */ 78 enum AnchorElement : uint8_t { 79 kAnchorElementUnknown = 0, 80 kAnchorElementDialogue = 1, 81 kAnchorElementAlbum = 2, 82 }; 83 84 friend bool operator==(const AnchoredLoudnessElement& lhs, 85 const AnchoredLoudnessElement& rhs) = default; 86 87 AnchorElement anchor_element; // 8 bits. 88 int16_t anchored_loudness; // Q7.8 format. 89 }; 90 91 struct AnchoredLoudness { 92 friend bool operator==(const AnchoredLoudness& lhs, 93 const AnchoredLoudness& rhs) = default; 94 95 // `num_anchored_loudness` is implicit based on the size of 96 // `anchor_elements`. 97 std::vector<AnchoredLoudnessElement> anchor_elements = {}; 98 }; 99 100 struct LayoutExtension { 101 friend bool operator==(const LayoutExtension& lhs, 102 const LayoutExtension& rhs) = default; 103 104 DecodedUleb128 info_type_size = 0; 105 // Length `info_type_size`. 106 std::vector<uint8_t> info_type_bytes; 107 }; 108 109 /*!\brief The loudness information for a given audio signal. */ 110 struct LoudnessInfo { 111 /*!\brief A 8-bit bitmask to determine the included optional loudness types. 112 */ 113 enum InfoTypeBitmask : uint8_t { 114 kTruePeak = 0x01, 115 kAnchoredLoudness = 0x02, 116 kInfoTypeBitMask4 = 0x04, 117 kInfoTypeBitMask8 = 0x08, 118 kInfoTypeBitMask16 = 0x10, 119 kInfoTypeBitMask32 = 0x20, 120 kInfoTypeBitMask64 = 0x40, 121 kInfoTypeBitMask128 = 0x80, 122 // For backwards compatibility several info types signal the need 123 // for a `layout_extension`. 124 kAnyLayoutExtension = 0xfc, 125 }; 126 127 friend bool operator==(const LoudnessInfo& lhs, 128 const LoudnessInfo& rhs) = default; 129 130 uint8_t info_type; // Apply `LoudnessInfoTypeBitmask` to identify what types 131 // of loudness information are included. 132 int16_t integrated_loudness = 0; // Q7.8 format. 133 int16_t digital_peak = 0; // Q7.8 format. 134 135 // Present if `(info_type & kTruePeak) != 0`. 136 int16_t true_peak = 0; // Q7.8 format. 137 138 // Present if `(info_type & kAnchoredLoudness) != 0`. 139 AnchoredLoudness anchored_loudness; 140 141 // Present if `(info_type & kAnyLayoutExtension) != 0`. 142 LayoutExtension layout_extension; 143 }; 144 145 /*!\brief Layout is defined using the sound system convention of ITU2051-3. 146 * 147 * Implements syntax and utility functions when the `Layout` defined in 148 * https://aomediacodec.github.io/iamf/v1.1.0.html#syntax-layout is 149 * `LOUDSPEAKERS_SS_CONVENTION`. 150 */ 151 struct LoudspeakersSsConventionLayout { 152 /*!\brief A 4-bit enum for loudspeaker layout. 153 * 154 * Sound systems A through J refer to ITU2051-3. 155 */ 156 enum SoundSystem : uint8_t { 157 kSoundSystemA_0_2_0 = 0, 158 kSoundSystemB_0_5_0 = 1, 159 kSoundSystemC_2_5_0 = 2, 160 kSoundSystemD_4_5_0 = 3, 161 kSoundSystemE_4_5_1 = 4, 162 kSoundSystemF_3_7_0 = 5, 163 kSoundSystemG_4_9_0 = 6, 164 kSoundSystemH_9_10_3 = 7, 165 kSoundSystemI_0_7_0 = 8, 166 kSoundSystemJ_4_7_0 = 9, 167 kSoundSystem10_2_7_0 = 10, 168 kSoundSystem11_2_3_0 = 11, 169 kSoundSystem12_0_1_0 = 12, 170 kSoundSystem13_6_9_0 = 13, 171 kSoundSystemBeginReserved = 14, 172 kSoundSystemEndReserved = 15, 173 }; 174 175 friend bool operator==(const LoudspeakersSsConventionLayout& lhs, 176 const LoudspeakersSsConventionLayout& rhs) = default; 177 178 /*!\brief Writes the layout to the buffer. 179 * 180 * \param wb Buffer to write to. 181 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 182 * write fails. 183 */ 184 absl::Status Write(bool& found_stereo_layout, WriteBitBuffer& wb) const; 185 186 /*!\brief Reads the layout from the buffer. 187 * 188 * \param rb Buffer to read from. 189 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 190 * read fails. 191 */ 192 absl::Status Read(ReadBitBuffer& rb); 193 194 /*!\brief Prints logging information about the layout. */ 195 void Print() const; 196 197 SoundSystem sound_system; 198 uint8_t reserved; // 2 bits. 199 }; 200 201 /*!\brief Layout is binaural or reserved. 202 * 203 * Implements syntax and utility functions when the `Layout` defined in 204 * https://aomediacodec.github.io/iamf/v1.1.0.html#syntax-layout is 205 * `BINAURAL` or `RESERVED`. 206 */ 207 struct LoudspeakersReservedOrBinauralLayout { 208 friend bool operator==(const LoudspeakersReservedOrBinauralLayout& lhs, 209 const LoudspeakersReservedOrBinauralLayout& rhs) = 210 default; 211 212 /*!\brief Writes the layout to the buffer. 213 * 214 * \param wb Buffer to write to. 215 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 216 * write fails. 217 */ 218 absl::Status Write(WriteBitBuffer& wb) const; 219 220 /*!\brief Reads the layout from the buffer. 221 * 222 * \param rb Buffer to read from. 223 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 224 * read fails. 225 */ 226 absl::Status Read(ReadBitBuffer& rb); 227 228 /*!\brief Prints logging information about the layout. */ 229 void Print() const; 230 231 uint8_t reserved; // 6 bits. 232 }; 233 234 /*!\brief Specifies either a binaural system or physical loudspeaker positions. 235 * 236 * Implements syntax and utility functions related to the `Layout` defined in 237 * https://aomediacodec.github.io/iamf/v1.1.0.html#syntax-layout. 238 */ 239 struct Layout { 240 /*!\brief A 2-bit enum for the type of layout. */ 241 enum LayoutType : uint8_t { 242 kLayoutTypeReserved0 = 0, 243 kLayoutTypeReserved1 = 1, 244 kLayoutTypeLoudspeakersSsConvention = 2, // Using convention of ITU2051-3. 245 kLayoutTypeBinaural = 3, // Layout is binaural. 246 }; 247 248 friend bool operator==(const Layout& lhs, const Layout& rhs) = default; 249 250 /*!\brief Reads and validates the Layout from the buffer. 251 * 252 * \param rb Buffer to read from. 253 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 254 * read fails. 255 */ 256 absl::Status ReadAndValidate(ReadBitBuffer& rb); 257 258 LayoutType layout_type; // 2 bits. 259 260 // The active field depends on `layout_type`. 261 std::variant<LoudspeakersSsConventionLayout, 262 LoudspeakersReservedOrBinauralLayout> 263 specific_layout; 264 }; 265 266 /*!\brief Identifies measured loudness information according to layout. */ 267 struct MixPresentationLayout { 268 friend bool operator==(const MixPresentationLayout& lhs, 269 const MixPresentationLayout& rhs) = default; 270 271 /*!\brief Reads and validates the MixPresentationLayout from the buffer. 272 * 273 * \param rb Buffer to read from. 274 * \return `absl::OkStatus()` if the layout is valid. A specific status if the 275 * read fails. 276 */ 277 absl::Status ReadAndValidate(ReadBitBuffer& rb); 278 279 Layout loudness_layout; 280 LoudnessInfo loudness; 281 }; 282 283 /*!\brief One of the sub-mixes within a Mix Presentation Obu. */ 284 struct MixPresentationSubMix { 285 friend bool operator==(const MixPresentationSubMix& lhs, 286 const MixPresentationSubMix& rhs) = default; 287 288 /*!\brief Reads and validates the MixPresentationSubMix from the buffer. 289 * 290 * \param rb Buffer to read from. 291 * \return `absl::OkStatus()` if the sub-mix is valid. A specific status if 292 * the read fails. 293 */ 294 absl::Status ReadAndValidate(const int32_t& count_label, ReadBitBuffer& rb); 295 296 // `num_audio_elements` is implicit based on the size of `audio_elements`. 297 std::vector<SubMixAudioElement> audio_elements; 298 299 // The gain value to be applied in post-processing the mixed audio signal to 300 // generate the audio signal for playback. 301 MixGainParamDefinition output_mix_gain; 302 303 // `num_layouts` is implicit based on the size of `layouts`. 304 std::vector<MixPresentationLayout> layouts; 305 }; 306 307 struct MixPresentationTags { 308 struct Tag { 309 friend bool operator==(const Tag& lhs, const Tag& rhs) = default; 310 311 std::string tag_name; 312 std::string tag_value; 313 }; 314 315 friend bool operator==(const MixPresentationTags& lhs, 316 const MixPresentationTags& rhs) = default; 317 318 /*!\brief Writes the MixPresentationTags to the buffer. 319 * 320 * \param wb Buffer to write to. 321 * \return `absl::OkStatus()` if the MixPresentationTags is valid. A specific 322 * status if the write fails. 323 */ 324 absl::Status ValidateAndWrite(WriteBitBuffer& wb) const; 325 326 // `num_tags` is implicit based on the size of `tags`. 327 std::vector<Tag> tags; 328 }; 329 330 /*!\brief Metadata required for post-processing the mixed audio signal. 331 * 332 * The metadata specifies how to render, process and mix one or more audio 333 * elements. 334 * 335 * A Mix Presentation MAY contain one or more sub-mixes. Common use cases MAY 336 * specify only one sub-mix, which includes all rendered and processed Audio 337 * Elements used in the Mix Presentation. The use-case for specifying more than 338 * one sub-mix arises if an IA multiplexer is merging two or more IA Sequences. 339 * In this case, it MAY choose to capture the loudness information from the 340 * original IA Sequences in multiple sub-mixes, instead of recomputing the 341 * loudness information for the final mix. 342 */ 343 class MixPresentationObu : public ObuBase { 344 public: 345 /*!\brief Writes the number of channels for a `Layout` to the output argument. 346 * 347 * \param loudness_layout `Layout` to process. 348 * \param num_channels Number of channels for this layout if successful. 349 * \return `absl::OkStatus()` if successful. `absl::InvalidArgumentError()` 350 * if the `layout_type` enum is a reserved or unknown value. 351 */ 352 static absl::Status GetNumChannelsFromLayout(const Layout& loudness_layout, 353 int32_t& num_channels); 354 355 /*!\brief Constructor. 356 * 357 * This class takes ownership of any allocated memory nested within 358 * `MixGainParamDefinition`s. 359 * 360 * \param header `ObuHeader` of the OBU. 361 * \param mix_presentation_id `mix_presentation_id` in the OBU. 362 * \param count_label `count_label` in the OBU. 363 * \param annotations_language Vector representing all of the 364 * `annotations_language`s in the OBU. 365 * \param localized_presentation_annotations Vector representing all of the 366 * `localized_presentation_annotations`s in the OBU. 367 * \param sub_mixes Vector representing all of the sub mixes in the OBU. 368 */ MixPresentationObu(const ObuHeader & header,DecodedUleb128 mix_presentation_id,DecodedUleb128 count_label,const std::vector<std::string> & annotations_language,const std::vector<std::string> & localized_presentation_annotations,std::vector<MixPresentationSubMix> & sub_mixes)369 MixPresentationObu( 370 const ObuHeader& header, DecodedUleb128 mix_presentation_id, 371 DecodedUleb128 count_label, 372 const std::vector<std::string>& annotations_language, 373 const std::vector<std::string>& localized_presentation_annotations, 374 std::vector<MixPresentationSubMix>& sub_mixes) 375 : ObuBase(header, kObuIaMixPresentation), 376 sub_mixes_(std::move(sub_mixes)), 377 mix_presentation_id_(mix_presentation_id), 378 count_label_(count_label), 379 annotations_language_(annotations_language), 380 localized_presentation_annotations_( 381 localized_presentation_annotations) {} 382 383 /*!\brief Creates a `MixPresentationObu` from a `ReadBitBuffer`. 384 * 385 * This function is designed to be used from the perspective of the decoder. 386 * It will call `ReadAndValidatePayload` in order to read from the buffer; 387 * therefore it can fail. 388 * 389 * \param header `ObuHeader` of the OBU. 390 * \param payload_size Size of the obu payload in bytes. 391 * \param rb `ReadBitBuffer` where the `MixPresentationObu` data is stored. 392 * Data read from the buffer is consumed. 393 * \return A `MixPresentationObu` on success. A specific status on failure. 394 */ 395 static absl::StatusOr<MixPresentationObu> CreateFromBuffer( 396 const ObuHeader& header, int64_t payload_size, ReadBitBuffer& rb); 397 398 /*!\brief Destructor. */ 399 ~MixPresentationObu() override = default; 400 401 friend bool operator==(const MixPresentationObu& lhs, 402 const MixPresentationObu& rhs) = default; 403 404 /*!\brief Prints logging information about the OBU. */ 405 void PrintObu() const override; 406 GetMixPresentationId()407 DecodedUleb128 GetMixPresentationId() const { return mix_presentation_id_; } 408 409 /*!\brief Gets a copy of the `annotations_language`. 410 * 411 * \return A copy of the `annotations_language` member variable. 412 */ GetAnnotationsLanguage()413 std::vector<std::string> GetAnnotationsLanguage() const { 414 return annotations_language_; 415 } 416 417 /*!\brief Gets a copy of the `localized_presentation_annotations`. 418 * 419 * \return A copy of the `localized_presentation_annotations` member variable. 420 */ GetLocalizedPresentationAnnotations()421 std::vector<std::string> GetLocalizedPresentationAnnotations() const { 422 return localized_presentation_annotations_; 423 } 424 GetNumSubMixes()425 DecodedUleb128 GetNumSubMixes() const { return sub_mixes_.size(); } 426 427 std::vector<MixPresentationSubMix> sub_mixes_; 428 429 // Implicitly included based on `obu_size` after writing the IAMF v1.1.0 430 // payload. 431 std::optional<MixPresentationTags> mix_presentation_tags_; 432 433 private: 434 DecodedUleb128 mix_presentation_id_; 435 DecodedUleb128 count_label_; 436 // Length `count_label`. 437 std::vector<std::string> annotations_language_; 438 // Length `count_label`. 439 std::vector<std::string> localized_presentation_annotations_; 440 441 // `num_sub_mixes_` is implicit based on the size of `sub_mixes_`. 442 443 // Used only by the factory create function. MixPresentationObu(const ObuHeader & header)444 explicit MixPresentationObu(const ObuHeader& header) 445 : ObuBase(header, kObuIaMixPresentation), 446 sub_mixes_({}), 447 mix_presentation_id_(DecodedUleb128()), 448 count_label_(DecodedUleb128()), 449 annotations_language_({}), 450 localized_presentation_annotations_({}) {} 451 /*!\brief Writes the OBU payload to the buffer. 452 * 453 * \param wb Buffer to write to. 454 * \return `absl::OkStatus()` if OBU is valid. A specific status on failure. 455 */ 456 absl::Status ValidateAndWritePayload(WriteBitBuffer& wb) const override; 457 458 /*!\brief Reads the OBU payload from the buffer. 459 * 460 * \param payload_size Size of the obu payload in bytes. 461 * \param rb Buffer to read from. 462 * \return `absl::OkStatus()` if the payload is valid. A specific status on 463 * failure. 464 */ 465 absl::Status ReadAndValidatePayloadDerived(int64_t payload_size, 466 ReadBitBuffer& rb) override; 467 }; 468 469 } // namespace iamf_tools 470 471 #endif // OBU_MIX_PRESENTATION_H_ 472