• 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 COMMON_WRITE_BIT_BUFFER_H_
13 #define COMMON_WRITE_BIT_BUFFER_H_
14 
15 #include <cstdint>
16 #include <fstream>
17 #include <optional>
18 #include <string>
19 #include <vector>
20 
21 #include "absl/status/status.h"
22 #include "absl/types/span.h"
23 #include "iamf/common/leb_generator.h"
24 #include "iamf/obu/types.h"
25 
26 namespace iamf_tools {
27 
28 /*!\brief Holds a buffer and tracks the next bit to be written to. */
29 class WriteBitBuffer {
30  public:
31   /*!\brief Constructor.
32    *
33    * \param initial_capacity Initial capacity of the internal buffer in bytes.
34    * \param leb_generator `LebGenerator` to use.
35    */
36   WriteBitBuffer(int64_t initial_capacity,
37                  const LebGenerator& leb_generator = *LebGenerator::Create());
38 
39   /*!\brief Destructor.*/
40   ~WriteBitBuffer() = default;
41 
42   /*!\brief Writes the lower `num_bits` of data to the write buffer.
43    *
44    * \param data Data to write.
45    * \param num_bits Number of lower bits of the data to write. Maximum value of
46    *        32.
47    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
48    *         `num_bits > 32` or if `data >= 2^(num_bits)`.
49    *         `absl::UnknownError()` if the `wb->bit_offset` is negative.
50    */
51   absl::Status WriteUnsignedLiteral(uint32_t data, int num_bits);
52 
53   /*!\brief Writes the specified number of lower bits of data to the buffer.
54    *
55    * \param data Data to write.
56    * \param num_bits Number of lower bits of the data to write. Maximum value of
57    *        64.
58    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
59    *         `num_bits > 64` or if `data >= 2^(num_bits)`.
60    *         `absl::UnknownError()` if the `wb->bit_offset` is
61    *         negative.
62    */
63   absl::Status WriteUnsignedLiteral64(uint64_t data, int num_bits);
64 
65   /*!\brief Writes specified signed 8 bit integer to the write buffer.
66    *
67    * \param data Data to write in standard two's complement form.
68    * \return `absl::OkStatus()` on success. `absl::UnknownError()` if the
69    *         `wb->bit_offset` is negative.
70    */
71   absl::Status WriteSigned8(int8_t data);
72 
73   /*!\brief Writes the signed 16 bit integer to the write buffer.
74    *
75    * \param data Data to write in standard two's complement form.
76    * \return `absl::OkStatus()` on success. `absl::UnknownError()` if the
77    *         `wb->bit_offset` is negative.
78    */
79   absl::Status WriteSigned16(int16_t data);
80 
81   /*!\brief Writes a null terminated string to the write buffer.
82    *
83    * \param data Data to write.
84    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
85    *         the string is not terminated within `kIamfMaxStringSize` bytes.
86    *         Other specific statuses on failure.
87    */
88   absl::Status WriteString(const std::string& data);
89 
90   /*!\brief Writes a `absl::Span<const uint8_t>` to the write buffer.
91    *
92    * \param data Data to write.
93    * \return `absl::OkStatus()` on success. `absl::UnknownError()` if the
94    *         `wb->bit_offset` is negative.
95    */
96   absl::Status WriteUint8Span(absl::Span<const uint8_t> data);
97 
98   /*!\brief Writes a ULEB128 to the buffer using an implicit generator.
99    *
100    * \param data Data to write using the member `leb_generator_`.
101    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
102    *         the generation fails. Other specific statuses on failure.
103    */
104   absl::Status WriteUleb128(DecodedUleb128 data);
105 
106   /*!\brief Writes the expandable size according to ISO 14496-1.
107    *
108    * \param size_of_instance Size of the instance.
109    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
110    *         the generation fails. Other specific statuses on failure.
111    */
112   absl::Status WriteIso14496_1Expanded(uint32_t size_of_instance);
113 
114   /*!\brief Flushes and writes a byte-aligned buffer to a file.
115    *
116    * \param output_file File to write to. Or `std::nullopt` to omit writing.
117    * \return `absl::OkStatus()` on success. `absl::InvalidArgumentError()` if
118    *         the buffer is not byte-aligned. `absl::UnknownError()` if the write
119    *         failed.
120    */
121   absl::Status FlushAndWriteToFile(std::optional<std::fstream>& output_file);
122 
123   /*!\brief May flush the buffer to a file if it is getting full.
124    *
125    * Intended to be used to avoid storing the entire buffer in memory if it will
126    * later be flushed to a file anyway.
127    *
128    * \param output_file File to write to. Or `std::nullopt` to omit writing.
129    * \return `absl::OkStatus()` on success. Success does not guarantee the
130    *         buffer was flushed or written to the file.
131    *         `absl::InvalidArgumentError()` if the buffer is not byte-aligned
132    *         when writing to a file. `absl::UnknownError()` if the write failed.
133    */
134   absl::Status MaybeFlushIfCloseToCapacity(
135       std::optional<std::fstream>& output_file);
136 
137   /*!\brief Gets the offset in bits of the buffer.
138    * \return Offset in bits of the write buffer.
139    */
bit_offset()140   int64_t bit_offset() const { return bit_offset_; }
141 
142   /*!\brief Returns a `const` pointer to the underlying buffer.
143    *
144    * If the buffer is not byte-aligned the last byte will be padded with zeroes.
145    *
146    * \return A `const` pointer to the underlying buffer.
147    */
bit_buffer()148   const std::vector<uint8_t>& bit_buffer() const { return bit_buffer_; }
149 
150   /*!\brief Checks whether the current data in the buffer is byte-aligned.
151    *
152    * \return `true` when the current data in the buffer is byte-aligned.
153    */
IsByteAligned()154   bool IsByteAligned() const { return bit_offset_ % 8 == 0; }
155 
156   /*!\brief Resets the underlying buffer. */
157   void Reset();
158 
159   LebGenerator leb_generator_;
160 
161  private:
162   std::vector<uint8_t> bit_buffer_;
163   int64_t bit_offset_;
164 };
165 
166 }  // namespace iamf_tools
167 
168 #endif  // COMMON_WRITE_BIT_BUFFER_H_
169