• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024, 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 COMMON_READ_BIT_BUFFER_H_
13 #define COMMON_READ_BIT_BUFFER_H_
14 
15 #include <cstddef>
16 #include <cstdint>
17 #include <filesystem>
18 #include <fstream>
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/status/status.h"
24 #include "absl/types/span.h"
25 #include "iamf/obu/types.h"
26 
27 namespace iamf_tools {
28 
29 /*!\brief Abstract class representing a buffer to read bit from.
30  *
31  * Concrete subclasses should hold the actual storage of the data and
32  * implement `LoadBytesToBuffer()` to handle how data are loaded from the
33  * storage to the internal buffer.
34  */
35 class ReadBitBuffer {
36  public:
37   /*!\brief Destructor.*/
38   virtual ~ReadBitBuffer() = default;
39 
40   /*!\brief Reads upper `num_bits` from buffer to lower `num_bits` of `output`.
41    *
42    * \param num_bits Number of upper bits to read from buffer. Maximum value of
43    *        64.
44    * \param output Unsigned literal from buffer will be written here.
45    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
46    *         `num_bits > 64` or the buffer's bit offset is negative.
47    *         `absl::ResourceExhaustedError()` if the buffer
48    *         runs out of data and cannot get more from source before the desired
49    *         `num_bits` are read.
50    */
51   absl::Status ReadUnsignedLiteral(int num_bits, uint64_t& output);
52 
53   /*!\brief Reads upper `num_bits` from buffer to lower `num_bits` of `output`.
54    *
55    * \param num_bits Number of upper bits to read from buffer. Maximum value of
56    *        32.
57    * \param output Unsigned literal from buffer will be written here.
58    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
59    *         `num_bits > 32` or the buffer's bit offset is negative.
60    *         `absl::ResourceExhaustedError()` if the buffer
61    *         runs out of data and cannot get more from source before the desired
62    *         `num_bits` are read.
63    */
64   absl::Status ReadUnsignedLiteral(int num_bits, uint32_t& output);
65 
66   /*!\brief Reads upper `num_bits` from buffer to lower `num_bits` of `output`.
67    *
68    * \param num_bits Number of upper bits to read from buffer. Maximum value of
69    *        16.
70    * \param output Unsigned literal from buffer will be written here.
71    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
72    *         `num_bits > 16` or the buffer's bit offset is negative.
73    *         `absl::ResourceExhaustedError()` if the buffer runs out of data
74    *         and cannot get more from source before the desired `num_bits` are
75    *         read.
76    */
77   absl::Status ReadUnsignedLiteral(int num_bits, uint16_t& output);
78 
79   /*!\brief Reads upper `num_bits` from buffer to lower `num_bits` of `output`.
80    *
81    * \param num_bits Number of upper bits to read from buffer. Maximum value of
82    *        8.
83    * \param output Unsigned literal from buffer will be written here.
84    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
85    *         `num_bits > 8` or the buffer's bit offset is negative.
86    *         `absl::ResourceExhaustedError()` if the buffer runs
87    *         out of data and cannot get more from source before the desired
88    *         `num_bits` are read.
89    */
90   absl::Status ReadUnsignedLiteral(int num_bits, uint8_t& output);
91 
92   /*!\brief Reads the signed 16 bit integer from the read buffer.
93    *
94    * \param output Signed 16 bit integer will be written here.
95    * \return `absl::OkStatus()` on success.  `absl::ResourceExhaustedError()` if
96    *         the buffer is exhausted before the signed 16 is fully read and
97    *         source does not have the requisite data to complete the signed 16.
98    *         `absl::InvalidArgumentError()` if the buffer's bit offset is
99    *         negative.
100    */
101   absl::Status ReadSigned16(int16_t& output);
102 
103   /*!\brief Reads a null terminated string from the read buffer.
104    *
105    * \param output String will be written here.
106    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
107    *         the string is not terminated within `kIamfMaxStringSize` bytes.
108    *         `absl::Status::kResourceExhausted` if the buffer is exhausted
109    *         before the string is terminated and source does not have the
110    *         requisite data to complete the string. Other specific statuses on
111    *         failure.
112    */
113   absl::Status ReadString(std::string& output);
114 
115   /*!\brief Reads an unsigned leb128 from buffer into `uleb128`.
116    *
117    * This version is useful when the caller does not care about the number of
118    * bytes used to encode the data in the bitstream.
119    *
120    * \param uleb128 Decoded unsigned leb128 from buffer will be written here.
121    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
122    *         the consumed data from the buffer does not fit into the 32 bits of
123    *         uleb128, or if the data in the buffer requires that we read more
124    *         than `kMaxLeb128Size` bytes, or the buffer's bit offset is
125    *         negative. `absl::ResourceExhaustedError()` if the buffer is
126    *         exhausted before the uleb128 is fully read and source does not
127    *         have the requisite data to complete the uleb128.
128    */
129   absl::Status ReadULeb128(DecodedUleb128& uleb128);
130 
131   /*!\brief Reads an unsigned leb128 from buffer into `uleb128`.
132    *
133    * This version also records the number of bytes used to store the encoded
134    * uleb128 in the bitstream.
135    *
136    * \param uleb128 Decoded unsigned leb128 from buffer will be written here.
137    * \param encoded_uleb128_size Number of bytes used to store the encoded
138    *        uleb128 in the bitstream.
139    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
140    *         the consumed data from the buffer does not fit into the 32 bits of
141    *         uleb128, or if the data in the buffer requires that we read more
142    *         than `kMaxLeb128Size` bytes, the buffer's bit offset is negative.
143    *         `absl::ResourceExhaustedError()` if
144    *         the buffer is exhausted before the uleb128 is fully read and
145    *         source does not have the requisite data to complete the uleb128.
146    */
147   absl::Status ReadULeb128(DecodedUleb128& uleb128,
148                            int8_t& encoded_uleb128_size);
149 
150   /*!\brief Reads the expandable size according to ISO 14496-1.
151    *
152    * \param max_class_size Maximum class size in bits.
153    * \param size_of_instance Size of instance according to the expandable size.
154    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
155    *         the consumed data from the buffer does not fit into the 32 bit
156    *         output, or if the data encoded is larger than the `max_class_size`
157    *         bits, the buffer's bit offset is negative.
158    *         `absl::ResourceExhaustedError()` if the buffer is exhausted
159    *         before the expanded field is fully read and source does not have
160    *         the requisite data to complete the expanded field.
161    */
162   absl::Status ReadIso14496_1Expanded(uint32_t max_class_size,
163                                       uint32_t& size_of_instance);
164 
165   /*!\brief Reads `uint8_t`s into the output span.
166    *
167    * \param output Span of `uint8_t`s to write to.
168    * \return `absl::OkStatus()` on success. `absl::ResourceExhaustedError()` if
169    *         the buffer runs out of data and cannot get more from source before
170    *         filling the span. `absl::InvalidArgumentError()` if the
171    *         buffer's bit offset is negative.
172    */
173   absl::Status ReadUint8Span(absl::Span<uint8_t> output);
174 
175   /*!\brief Reads a boolean from buffer into `output`.
176    *
177    * \param output Boolean bit from buffer will be written here.
178    * \return `absl::OkStatus()` on success. `absl::ResourceExhaustedError()` if
179    *         the buffer runs out of data and cannot get more from source before
180    *         the desired boolean is read. `absl::InvalidArgumentError()` if the
181    *         buffer's bit offset is negative.
182    */
183   absl::Status ReadBoolean(bool& output);
184 
185   /*!\brief Checks whether there is any data left in the buffer or source.
186    *
187    * \return `true` if there is some data left in the buffer or source that has
188    *         not been consumed yet. `false` otherwise.
189    */
190   bool IsDataAvailable() const;
191 
192   /*!\brief Checks whether num_bytes_requested can be read.
193    *
194    * \param num_bytes_requested Desired number of bytes to read.
195    * \return `true` if the buffer has enough data to read the requested bytes.
196    *         `false` otherwise.
197    */
198   bool CanReadBytes(int64_t num_bytes_requested) const;
199 
200   /*!\brief Returns the next reading position of the source in bits.
201    *
202    * \return Next reading position of the source in bits.
203    */
204   int64_t Tell();
205 
206   /*!\brief Moves the next reading position in bits of the source.
207    *
208    * \param position Requested position in bits to move to.
209    * \return `absl::OkStatus()` on success. `absl::ResourceExhaustedError()` if
210    *         the buffer runs out of data. `absl::InvalidArgumentError()` if
211    *         the requested position is negative.
212    */
213   absl::Status Seek(int64_t position);
214 
215  protected:
216   /*!\brief Constructor.
217    *
218    * \param capacity Capacity of the internal buffer in bytes.
219    * \param source_size Size of the source data in bits.
220    */
221   ReadBitBuffer(size_t capacity, int64_t source_size);
222 
223   /*!\brief Internal reading function that reads `num_bits` from buffer.
224    *
225    * As a side effect buffer loading might happen.
226    *
227    * \param num_bits Number of upper bits to read from buffer.
228    * \param max_num_bits Maximum number of upper bits to read from buffer.
229    * \param output Output unsigned literal read from buffer.
230    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
231    *         `num_bits > max_num_bits` or the buffer's bit offset is negative.
232    *         `absl::ResourceExhaustedError()` if the buffer runs out of data
233    *         and cannot get more from source before the desired `num_bits`
234    *         are read.
235    */
236   absl::Status ReadUnsignedLiteralInternal(int num_bits, int max_num_bits,
237                                            uint64_t& output);
238   /*!\brief Load bytes from source to the buffer.
239    *
240    * Subclasses of this class should implement the actual loading logic.
241    *
242    * \param starting_byte Starting byte to load from source.
243    * \param num_bytes Number of bytes to load.
244    * \return `absl::OkStatus()` on success. Other specific statuses (depending
245    *         on the subclass) on failure.
246    */
247   virtual absl::Status LoadBytesToBuffer(int64_t starting_byte,
248                                          int64_t num_bytes) = 0;
249 
250   // Read buffer.
251   std::vector<uint8_t> bit_buffer_;
252 
253   // Specifies the next bit to consume in the `bit_buffer_`.
254   int64_t buffer_bit_offset_ = 0;
255 
256   // Size of the valid data in the buffer in bits.
257   int64_t buffer_size_ = 0;
258 
259   // Size of the source data in bits. It may refer to the total file size
260   // for a file-based buffer, or the total memory size for a memory-based
261   // buffer. For a stream-based buffer, it is the current size of the source
262   // data, which is updated as bytes are pushed or flushed.
263   int64_t source_size_;
264 
265   // Specifies the next bit to consume from the source data (the actual storage
266   // type is subclass-specific).
267   int64_t source_bit_offset_ = 0;
268 
269   // Specifies whether a position returned by Tell() is valid.
270   bool is_position_valid_;
271 };
272 
273 /*!\brief Memory-based read bit buffer.
274  *
275  * The entire content of the source data is held as a vector inside the class.
276  *
277  * NOTICE: This is mostly useful for testing and processing small files,
278  * because it will hold the entire content in memory during its lifetime.
279  * For processing large (e.g. 2 GB) files, use the `FileBasedReadBitBuffer`
280  * for example.
281  */
282 class MemoryBasedReadBitBuffer : public ReadBitBuffer {
283  public:
284   /*!\brief Creates an instance of a memory-based read bit buffer.
285    *
286    * \param capacity Capacity of the internal buffer in bytes.
287    * \param source Source span from which the buffer will load data. The
288    *        entire contents will be copied into the constructed instance.
289    * \return Unique pointer of the created instance. `nullptr` if the creation
290    *         fails.
291    */
292   static std::unique_ptr<MemoryBasedReadBitBuffer> CreateFromSpan(
293       int64_t capacity, absl::Span<const uint8_t> source);
294 
295   /*!\brief Destructor.*/
296   ~MemoryBasedReadBitBuffer() override = default;
297 
298  protected:
299   /*!\brief Protected constructor. Called by the factory method or subclasses.
300    *
301    * \param capacity Capacity of the internal buffer in bytes.
302    * \param source Source span from which the buffer will load data. The
303    *        entire contents will be copied into the constructed instance.
304    */
305   MemoryBasedReadBitBuffer(size_t capacity, absl::Span<const uint8_t> source);
306   /*!\brief Load bytes from the source vector to the buffer.
307    *
308    * \param starting_byte Starting byte to load from source.
309    * \param num_bytes Number of bytes to load.
310    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
311    *         the start/ending position is invalid.
312    */
313   absl::Status LoadBytesToBuffer(int64_t starting_byte,
314                                  int64_t num_bytes) override;
315 
316   // Source data stored in a vector.
317   std::vector<uint8_t> source_vector_;
318 };
319 
320 /*!\brief File-based read bit buffer.
321  *
322  * The file is read and buffer loaded only when necessary.
323  */
324 class FileBasedReadBitBuffer : public ReadBitBuffer {
325  public:
326   /*!\brief Creates an instance of a file-based read bit buffer.
327    *
328    * \param capacity Capacity of the internal buffer in bytes.
329    * \param file_path Path to the file to load the buffer from.
330    * \return Unique pointer of the created instance. `nullptr` if the creation
331    *         fails.
332    */
333   static std::unique_ptr<FileBasedReadBitBuffer> CreateFromFilePath(
334       int64_t capacity, const std::filesystem::path& file_path);
335 
336   /*!\brief Destructor.*/
337   ~FileBasedReadBitBuffer() override = default;
338 
339  private:
340   /*!\brief Private constructor. Called by the factory method only.
341    *
342    * \param capacity Capacity of the internal buffer in bytes.
343    * \param source_size Total size of the file in bits.
344    * \param ifs Input file stream from which the buffer will load data. At most
345    *        a buffer full of data will be read at a given time.
346    *
347    */
348   FileBasedReadBitBuffer(size_t capacity, int64_t source_size,
349                          std::ifstream&& ifs);
350 
351   /*!\brief Load bytes from the source file to the buffer.
352    *
353    * \param starting_byte Starting byte to load from source.
354    * \param num_bytes Number of bytes to load.
355    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
356    *         the file reading fails.
357    */
358   absl::Status LoadBytesToBuffer(int64_t starting_byte,
359                                  int64_t num_bytes) override;
360 
361   // Source data stored in a file stream.
362   std::ifstream source_ifs_;
363 };
364 
365 /*!\brief Stream-based read bit buffer.
366  *
367  * The buffer is loaded from a stream. The user should Create() the stream
368  * and push data to the buffer using PushBytes() as needed; calls to Read*()
369  * methods will read data from the stream and provide it to the caller, or else
370  * will instruct the caller to push more data if necessary.
371  */
372 class StreamBasedReadBitBuffer : public MemoryBasedReadBitBuffer {
373  public:
374   /*!\brief Creates an instance of a stream-based read bit buffer.
375    *
376    * \param capacity Capacity of the internal buffer in bytes.
377    * \return Unique pointer of the created instance. `nullptr` if the creation
378    *         fails.
379    */
380   static std::unique_ptr<StreamBasedReadBitBuffer> Create(int64_t capacity);
381 
382   /*!\brief Adds some chunk of data to StreamBasedReadBitBuffer.
383    *
384    * \param bytes Bytes to push.
385    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
386    *         the stream push fails.
387    */
388   absl::Status PushBytes(absl::Span<const uint8_t> bytes);
389 
390   /*!\brief Flush already processed data from StreamBasedReadBitBuffer.
391    *
392    * Should be called whenever the caller no longer needs the first `num_bytes`
393    * of data.
394    *
395    * \param num_bytes Bytes to flush from StreamBasedReadBitBuffer
396    * \return `absl::OkStatus()` on success. Specific statuses on failure.
397    */
398   absl::Status Flush(int64_t num_bytes);
399 
400   /*!\brief Destructor.*/
401   ~StreamBasedReadBitBuffer() override = default;
402 
403  private:
404   /*!\brief Private constructor.
405    *
406    * \param capacity Capacity of the internal buffer in bytes.
407    * \param source_size Size of the source data in bits.
408    *
409    */
410   StreamBasedReadBitBuffer(size_t capacity, int64_t source_size);
411 
412   // Specifies the maximum size of the source data in bits.
413   int64_t max_source_size_;
414 };
415 
416 }  // namespace iamf_tools
417 
418 #endif  // COMMON_READ_BIT_BUFFER_H_
419