• 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_DECODER_CONFIG_FLAC_DECODER_CONFIG_H_
13 #define OBU_DECODER_CONFIG_FLAC_DECODER_CONFIG_H_
14 
15 #include <array>
16 #include <cstdint>
17 #include <variant>
18 #include <vector>
19 
20 #include "absl/status/status.h"
21 #include "iamf/common/read_bit_buffer.h"
22 #include "iamf/common/write_bit_buffer.h"
23 
24 namespace iamf_tools {
25 
26 struct FlacStreamInfoConstraints {
27   // Required 0 audio_roll_distance as per IAMF spec.
28   static constexpr int16_t kAudioRollDistance = 0;
29 
30   // Block size must be equal to num_samples_per_frame and at least 16, as per
31   // FLAC spec.
32   static constexpr uint16_t kMinMinAndMaxBlockSize = 16;
33 
34   // IAMF requires frame_size fields to have fixed values.
35   static constexpr uint32_t kMinFrameSize = 0;
36   static constexpr uint32_t kMaxFrameSize = 0;
37 
38   // In IAMF the number_of_channels is fixed to `1`, but can be ignored when
39   // reading / decoding. The actual number of channels is determined on a
40   // per-substream basis based on the audio element.
41   static constexpr uint8_t kNumberOfChannels = 1;
42 
43   // Required signature, as per IAMF spec.
44   static constexpr std::array<uint8_t, 16> kMd5Signature = {0};
45 
46   // Acceptable ranges for sample_rate, bits_per_sample, and
47   // totals_samples_in_stream from the FLAC documentation.
48   static constexpr uint32_t kMinSampleRate = 1;
49   static constexpr uint32_t kMaxSampleRate = 655350;
50   static constexpr uint8_t kMinBitsPerSample = 3;
51   static constexpr uint8_t kMaxBitsPerSample = 31;
52   // FLAC allows a value of 0 to represent an unknown total number of samples.
53   static constexpr uint64_t kMinTotalSamplesInStream = 0;
54   static constexpr uint64_t kMaxTotalSamplesInStream = 0xfffffffff;
55 };
56 
57 struct FlacMetaBlockStreamInfo {
58   friend bool operator==(const FlacMetaBlockStreamInfo& lhs,
59                          const FlacMetaBlockStreamInfo& rhs) = default;
60 
61   uint16_t minimum_block_size;
62   uint16_t maximum_block_size;
63   uint32_t minimum_frame_size =
64       FlacStreamInfoConstraints::kMinFrameSize;  // 24 bits.
65   uint32_t maximum_frame_size =
66       FlacStreamInfoConstraints::kMaxFrameSize;  // 24 bits.
67   uint32_t sample_rate;                          // 20 bits.
68   uint8_t number_of_channels =
69       FlacStreamInfoConstraints::kNumberOfChannels;  // 3 bits.
70   uint8_t bits_per_sample;                           // 5 bits.
71   uint64_t total_samples_in_stream;                  // 36 bits.
72   std::array<uint8_t, 16> md5_signature =
73       FlacStreamInfoConstraints::kMd5Signature;
74 };
75 
76 /*!\brief The header portion of a metadata block described in the FLAC spec. */
77 struct FlacMetaBlockHeader {
78   /*!\brief An 8-bit enum for the type of FLAC block.
79    *
80    * See `BLOCK_TYPE` in the FLAC spec.
81    */
82   enum FlacBlockType : uint8_t {
83     kFlacStreamInfo = 0,
84     kFlacPadding = 1,
85     kFlacApplication = 2,
86     kFlacSeektable = 3,
87     kFlacVorbisComment = 4,
88     kFlacCuesheet = 5,
89     kFlacPicture = 6,
90     // 7 - 126 are reserved.
91     kFlacInvalid = 127,
92   };
93 
94   friend bool operator==(const FlacMetaBlockHeader& lhs,
95                          const FlacMetaBlockHeader& rhs) = default;
96 
97   bool last_metadata_block_flag;
98   FlacBlockType block_type;             // 7 bits.
99   uint32_t metadata_data_block_length;  // 24 bits.
100 };
101 
102 struct FlacMetadataBlock {
103   friend bool operator==(const FlacMetadataBlock& lhs,
104                          const FlacMetadataBlock& rhs) = default;
105 
106   FlacMetaBlockHeader header;
107 
108   // When `header.block_type == kFlacStreamInfo` this is
109   // `FlacMetaBlockStreamInfo`. Otherwise IAMF just passes along the data.
110   std::variant<FlacMetaBlockStreamInfo, std::vector<uint8_t> > payload;
111 };
112 /*!\brief The `CodecConfig` `decoder_config` field for FLAC.*/
113 class FlacDecoderConfig {
114  public:
115   friend bool operator==(const FlacDecoderConfig& lhs,
116                          const FlacDecoderConfig& rhs) = default;
117 
118   /*!\brief Returns the required audio roll distance.
119    *
120    * \return Audio roll distance required by the IAMF spec.
121    */
GetRequiredAudioRollDistance()122   static int16_t GetRequiredAudioRollDistance() {
123     return FlacStreamInfoConstraints::kAudioRollDistance;
124   }
125 
126   /*!\brief Validates and writes the `FlacDecoderConfig` to a buffer.
127    *
128    * \param num_samples_per_frame `num_samples_per_frame` in the associated
129    *        Codec Config OBU.
130    * \param audio_roll_distance `audio_roll_distance` in the associated Codec
131    *        Config OBU.
132    * \param wb Buffer to write to.
133    * \return `absl::OkStatus()` if the decoder config is valid. A specific
134    *         status on failure.
135    */
136   absl::Status ValidateAndWrite(uint32_t num_samples_per_frame,
137                                 int16_t audio_roll_distance,
138                                 WriteBitBuffer& wb) const;
139 
140   /*!\brief Reads and validates the `FlacDecoderConfig` from a buffer.
141    *
142    * \param num_samples_per_frame `num_samples_per_frame` in the associated
143    *        Codec Config OBU.
144    * \param audio_roll_distance `audio_roll_distance` in the associated Codec
145    *        Config OBU.
146    * \param rb Buffer to read from.
147    * \return `absl::OkStatus()` if the decoder config is valid. A specific error
148    *         code on failure.
149    */
150   absl::Status ReadAndValidate(uint32_t num_samples_per_frame,
151                                int16_t audio_roll_distance, ReadBitBuffer& rb);
152 
153   /*!\brief Gets the output sample rate represented within the decoder config.
154    *
155    * This sample rate is used for timing and offset calculations.
156    *
157    * IAMF v1.1.0 section 3.11.3 specifies:
158    *  > "The sample rate used for computing offsets SHALL be the sampling rate
159    *     indicated in the METADATA_BLOCK."
160    *
161    * \param output_sample_rate Output sample rate.
162    * \return `absl::OkStatus()` if successful.  `absl::InvalidArgumentError()`
163    *         if the `FlacMetaBlockStreamInfo` cannot be found or if the
164    *         retrieved value is invalid.
165    */
166   absl::Status GetOutputSampleRate(uint32_t& output_sample_rate) const;
167 
168   /*!\brief Gets the bit-depth of the PCM to be used to measure loudness.
169    *
170    * This typically is the highest bit-depth the user should decode the signal
171    * to.
172    *
173    * \param bit_depth_to_measure_loudness Bit-depth of the PCM which will be
174    *        used to measure loudness.
175    * \return `absl::OkStatus()` if successful. `absl::InvalidArgumentError()`
176    *         if the `FlacMetaBlockStreamInfo`  cannot be found or if the
177    *         retrieved value is invalid.
178    */
179   absl::Status GetBitDepthToMeasureLoudness(
180       uint8_t& bit_depth_to_measure_loudness) const;
181 
182   /*!\brief Gets the `total_samples_in_stream` from a `FlacDecoderConfig`.
183    *
184    * \param total_samples_in_stream Total samples in stream.
185    * \return `absl::OkStatus()` if successful. `absl::InvalidArgumentError()`
186    *         if the `FlacMetaBlockStreamInfo`  cannot be found or if the
187    *         retrieved value is invalid.
188    */
189   absl::Status GetTotalSamplesInStream(uint64_t& total_samples_in_stream) const;
190 
191   /*!\brief Prints logging information about the decoder config.
192    */
193   void Print() const;
194 
195   std::vector<FlacMetadataBlock> metadata_blocks_;
196 };
197 
198 }  // namespace iamf_tools
199 
200 #endif  // OBU_DECODER_CONFIG_FLAC_DECODER_CONFIG_H_
201