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