• 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_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