• 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 CLI_OBU_SEQUENCER_BASE_H_
13 #define CLI_OBU_SEQUENCER_BASE_H_
14 
15 #include <cstdint>
16 #include <list>
17 #include <optional>
18 #include <vector>
19 
20 #include "absl/container/flat_hash_map.h"
21 #include "absl/status/status.h"
22 #include "absl/types/span.h"
23 #include "iamf/cli/audio_element_with_data.h"
24 #include "iamf/cli/audio_frame_with_data.h"
25 #include "iamf/cli/parameter_block_with_data.h"
26 #include "iamf/cli/temporal_unit_view.h"
27 #include "iamf/common/leb_generator.h"
28 #include "iamf/common/write_bit_buffer.h"
29 #include "iamf/obu/arbitrary_obu.h"
30 #include "iamf/obu/codec_config.h"
31 #include "iamf/obu/ia_sequence_header.h"
32 #include "iamf/obu/mix_presentation.h"
33 
34 namespace iamf_tools {
35 
36 /*!\brief Abstract base class for serializing and writing out OBUs.
37  *
38  * This class contains functions to serialize and write an IA Sequence. The
39  * concrete classes are responsible for packing and writing the output to some
40  * output stream.
41  *
42  * Usage pattern:
43  *   // Create a concrete sequencer. Interface is dependent on the conreate
44  *   // sequencer.
45  *   std::unique_ptr<ObuSequencerBase> sequencer = ...;
46  *
47  *  // Call the `PushDescriptorObus` method.
48  *  RETURN_IF_NOT_OK(sequencer->PushDescriptorObus(...));
49  *
50  *  while (more data is available) {
51  *    // Call the `PushTemporalUnit` method.
52  *    RETURN_IF_NOT_OK(sequencer->PushTemporalUnit(...));
53  *   }
54  *  // Signal that no more data is coming.
55  *  // Depending on the context, choose one of the closing functions. Either
56  *  // `UpdateDescriptorObusAndClose` (preferred) or `Close`.
57  *  RETURN_IF_NOT_OK(sequencer->UpdateDescriptorObusAndClose(...));
58  *  // Or:
59  *  RETURN_IF_NOT_OK(sequencer->Close());
60  *
61  * // Optionally. `Abort` may be called to clean up output. E.g. file-based
62  * // sequencers could delete their output file. `Abort` is most useful when
63  * // some component outside the class failes; failures in `PushDescriptorObus`,
64  * `PushTemporalUnit`, or `UpdateDescriptorObusAndClose` automatically call
65  * `Abort`.
66  */
67 class ObuSequencerBase {
68  public:
69   /*!\brief Serializes and writes out a temporal unit.
70    *
71    * Write out the OBUs contained within the input arguments to the output write
72    * buffer.
73    *
74    * \param include_temporal_delimiters Whether the serialized data should
75    *        include a temporal delimiter.
76    * \param temporal_unit Temporal unit to write out.
77    * \param wb Write buffer to write to.
78    * \param num_samples Number of samples written out.
79    * \return `absl::OkStatus()` on success. A specific status on failure.
80    */
81   [[deprecated("Use this class as per the class documentation instead.")]]
82   static absl::Status WriteTemporalUnit(bool include_temporal_delimiters,
83                                         const TemporalUnitView& temporal_unit,
84                                         WriteBitBuffer& wb, int& num_samples);
85 
86   /*!\brief Writes the input descriptor OBUs.
87    *
88    * Write out the OBUs contained within the input arguments to the output write
89    * buffer.
90    *
91    * \param ia_sequence_header_obu IA Sequence Header OBU to write.
92    * \param codec_config_obus Codec Config OBUs to write.
93    * \param audio_elements Audio Element OBUs with data to write.
94    * \param mix_presentation_obus Mix Presentation OBUs to write.
95    * \param arbitrary_obus Arbitrary OBUs to write.
96    * \param wb Write buffer to write to.
97    * \return `absl::OkStatus()` on success. A specific status on failure.
98    */
99   [[deprecated("Use this class as per the class documentation instead.")]]
100   static absl::Status WriteDescriptorObus(
101       const IASequenceHeaderObu& ia_sequence_header_obu,
102       const absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
103       const absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
104       const std::list<MixPresentationObu>& mix_presentation_obus,
105       const std::list<ArbitraryObu>& arbitrary_obus, WriteBitBuffer& wb);
106 
107   /*!\brief Constructor.
108    *
109    * \param leb_generator Leb generator to use when writing OBUs.
110    * \param include_temporal_delimiters Whether the serialized data should
111    *        include a temporal delimiter.
112    * \param delay_descriptors_until_first_untrimmed_sample When `true`,
113    *        `PushSerializedDescriptorObus` will be delayed until the first
114    *        untrimmed sample is pushed.
115    */
116   ObuSequencerBase(const LebGenerator& leb_generator,
117                    bool include_temporal_delimiters,
118                    bool delay_descriptors_until_first_untrimmed_sample);
119 
120   /*!\brief Destructor.*/
121   virtual ~ObuSequencerBase() = 0;
122 
123   /*!\brief Gathers statistics on and pushes the OBUs to some output.
124    *
125    * \param ia_sequence_header_obu IA Sequence Header OBU to write.
126    * \param codec_config_obus Codec Config OBUs to write.
127    * \param audio_elements Audio Element OBUs with data to write.
128    * \param mix_presentation_obus Mix Presentation OBUs to write.
129    * \param arbitrary_obus Arbitrary OBUs to write.
130    * \return `absl::OkStatus()` on success. A specific status on failure.
131    */
132   absl::Status PushDescriptorObus(
133       const IASequenceHeaderObu& ia_sequence_header_obu,
134       const absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
135       const absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
136       const std::list<MixPresentationObu>& mix_presentation_obus,
137       const std::list<ArbitraryObu>& arbitrary_obus);
138 
139   /*!\brief Gathers statistics on and pushes the temporal unit to some output.
140    *
141    * \param temporal_unit Temporal unit to push.
142    * \return `absl::OkStatus()` on success. A specific status on failure.
143    */
144   absl::Status PushTemporalUnit(const TemporalUnitView& temporal_unit);
145 
146   /*!\brief Finalizes the descriptor OBUs and closes the output.
147    *
148    * \param ia_sequence_header_obu IA Sequence Header OBU to write.
149    * \param codec_config_obus Codec Config OBUs to write.
150    * \param audio_elements Audio Element OBUs with data to write.
151    * \param mix_presentation_obus Mix Presentation OBUs to write.
152    * \param arbitrary_obus Arbitrary OBUs to write.
153    * \return `absl::OkStatus()` on success. A specific status on failure.
154    */
155   absl::Status UpdateDescriptorObusAndClose(
156       const IASequenceHeaderObu& ia_sequence_header_obu,
157       const absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
158       const absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
159       const std::list<MixPresentationObu>& mix_presentation_obus,
160       const std::list<ArbitraryObu>& arbitrary_obus);
161 
162   /*!\brief Signals that no more data is coming, and closes the output.
163    *
164    * \return `absl::OkStatus()` on success. A specific status on failure.
165    */
166   absl::Status Close();
167 
168   /*!\brief Aborts writing the output.
169    *
170    * Useful for sequencers which want to clean up their output. Such as to avoid
171    * leaving a stray file when encoding fails.
172    */
173   void Abort();
174 
175   /*!\brief Pick and places OBUs and write to some output.
176    *
177    * \param ia_sequence_header_obu IA Sequence Header OBU to write.
178    * \param codec_config_obus Codec Config OBUs to write.
179    * \param audio_elements Audio Element OBUs with data to write.
180    * \param mix_presentation_obus Mix Presentation OBUs to write.
181    * \param audio_frames Data about Audio Frame OBUs to write.
182    * \param parameter_blocks Data about Parameter Block OBUs to write.
183    * \param arbitrary_obus Arbitrary OBUs to write.
184    * \return `absl::OkStatus()` on success. A specific status on failure.
185    */
186   [[deprecated("Use this class as per the class documentation instead.")]]
187   absl::Status PickAndPlace(
188       const IASequenceHeaderObu& ia_sequence_header_obu,
189       const absl::flat_hash_map<uint32_t, CodecConfigObu>& codec_config_obus,
190       const absl::flat_hash_map<uint32_t, AudioElementWithData>& audio_elements,
191       const std::list<MixPresentationObu>& mix_presentation_obus,
192       const std::list<AudioFrameWithData>& audio_frames,
193       const std::list<ParameterBlockWithData>& parameter_blocks,
194       const std::list<ArbitraryObu>& arbitrary_obus);
195 
196  protected:
197   /*!\brief Pushes the descriptor OBUs and to some output.
198    *
199    * Various statistics are also signalled to the concrete class. For example,
200    * an MP4 sequencer may need the timing information to control the timebase in
201    * the output file. Concrete classes may ignore these statistics as they see
202    * fit.
203    *
204    * \param common_samples_per_frame Common number of samples per frame for the
205    *        IA Sequence.
206    * \param common_sample_rate Common sample rate for the IA Sequence.
207    * \param common_bit_depth Common bit depth for the IA Sequence.
208    * \param first_untrimmed_timestamp Timestamp for the first untrimmed sample
209    *        in the IA Sequence, or
210    *        `delay_descriptors_until_first_untrimmed_sample` is `false`. In some
211    *        contexts, this is known as the first Presentation Time Stamp (PTS).
212    * \param descriptor_obus Serialized descriptor OBUs to push.
213    * \return `absl::OkStatus()` on success. A specific status on failure.
214    */
215   virtual absl::Status PushSerializedDescriptorObus(
216       uint32_t common_samples_per_frame, uint32_t common_sample_rate,
217       uint8_t common_bit_depth,
218       std::optional<int64_t> first_untrimmed_timestamp, int num_channels,
219       absl::Span<const uint8_t> descriptor_obus) = 0;
220 
221   /*!\brief Pushes a single temporal unit to some output.
222    *
223    * \param timestamp Start timestamp of the temporal unit.
224    * \param num_samples Number of samples in the temporal unit.
225    * \param temporal_unit Temporal unit to push.
226    * \return `absl::OkStatus()` on success. A specific status on failure.
227    */
228   virtual absl::Status PushSerializedTemporalUnit(
229       int64_t timestamp, int num_samples,
230       absl::Span<const uint8_t> temporal_unit) = 0;
231 
232   /*!\brief Pushes the finalized descriptor OBUs to some output.
233    *
234    * \param descriptor_obus Serialized finalized descriptor OBUs to push.
235    * \return `absl::OkStatus()` on success. A specific status on failure.
236    */
237   virtual absl::Status PushFinalizedDescriptorObus(
238       absl::Span<const uint8_t> descriptor_obus) = 0;
239 
240   /*!\brief Signals that no more data is coming, and closes the output. */
241   virtual void CloseDerived() = 0;
242 
243   /*!\brief Aborts writing the output.
244    *
245    * Useful for sequencers which want to clean up their output. Such as to avoid
246    * leaving a stray file when encoding fails.
247    */
248   virtual void AbortDerived() = 0;
249 
250   // The `LebGenerator` to use when writing OBUs.
251   const LebGenerator leb_generator_;
252 
253  private:
254   /*!\brief Handles the initial temporal units.
255    *
256    * This function manages state to help process the initial temporal units up
257    * to and including the first one that has a real sample. In a typical IA
258    * Sequence, this would rarely be more few frames.
259    *
260    * \param temporal_unit Temporal unit to push.
261    * \param serialized_temporal_unit Serialized temporla unit.
262    * \return `absl::OkStatus()` on success. A specific status on failure.
263    */
264   absl::Status HandleInitialTemporalUnits(
265       const TemporalUnitView& temporal_unit,
266       absl::Span<const uint8_t> serialized_temporal_unit);
267 
268   enum State {
269     // Initial state.
270     kInitialized,
271     // `PushDescriptorObus` has been called, but it may have been delayed when
272     // `delay_descriptors_until_first_untrimmed_sample_` is `true`.
273     kPushDescriptorObusCalled,
274     // Descriptors have been pushed, in this state temporal units are no longer
275     // delayed.
276     kPushSerializedDescriptorsCalled,
277     // `Close` or `Abort` has been called.
278     kClosed
279   };
280   State state_ = kInitialized;
281 
282   const bool delay_descriptors_until_first_untrimmed_sample_;
283   const bool include_temporal_delimiters_;
284 
285   // Statistics for the current IA Sequence. Convenient to hold, in order to
286   // validate that the finalized OBUs are consistent with the initial ones.
287   struct DescriptorStatistics {
288     uint32_t common_samples_per_frame = 0;
289     uint32_t common_sample_rate = 0;
290     uint8_t common_bit_depth = 0;
291     int num_channels = 0;
292     std::optional<int64_t> first_untrimmed_timestamp;
293     std::vector<uint8_t> descriptor_obus;
294   };
295   std::optional<DescriptorStatistics> descriptor_statistics_;
296 
297   // Reusable scratch buffer.
298   WriteBitBuffer wb_;
299 
300   int64_t num_temporal_units_for_logging_ = 0;
301   int64_t cumulative_num_samples_for_logging_ = 0;
302 
303   // State for delayed OBUs. `delay_descriptors_until_first_untrimmed_sample_ ==
304   // true` implies we must cache and delayed OBUs until the first untrimmed
305   // sample is seen. In practical IA Sequences, this is rarely more than a few
306   // temporal units.
307   struct SerializedTemporalUnit {
308     int64_t start_timestamp;
309     uint32_t num_untrimmed_samples;
310     std::vector<uint8_t> data;
311   };
312   std::list<SerializedTemporalUnit> delayed_temporal_units_;
313 };
314 
315 }  // namespace iamf_tools
316 
317 #endif  // CLI_OBU_SEQUENCER_H_
318