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
13 #include "iamf/common/read_bit_buffer.h"
14
15 #include <algorithm>
16 #include <cstddef>
17 #include <cstdint>
18 #include <cstdio>
19 #include <filesystem>
20 #include <fstream>
21 #include <ios>
22 #include <limits>
23 #include <memory>
24 #include <string>
25 #include <utility>
26 #include <vector>
27
28 #include "absl/functional/any_invocable.h"
29 #include "absl/log/check.h"
30 #include "absl/log/log.h"
31 #include "absl/memory/memory.h"
32 #include "absl/status/status.h"
33 #include "absl/strings/str_cat.h"
34 #include "absl/types/span.h"
35 #include "iamf/common/utils/bit_buffer_util.h"
36 #include "iamf/common/utils/macros.h"
37 #include "iamf/obu/types.h"
38
39 namespace iamf_tools {
40
41 namespace {
42
CanReadByteAligned(const int64_t & buffer_bit_offset,const int64_t & num_bits)43 bool CanReadByteAligned(const int64_t& buffer_bit_offset,
44 const int64_t& num_bits) {
45 const bool buffer_bit_offset_is_aligned = (buffer_bit_offset % 8 == 0);
46 const bool num_bits_to_read_is_aligned = (num_bits % 8 == 0);
47 return buffer_bit_offset_is_aligned && num_bits_to_read_is_aligned;
48 }
49
50 // Reads one bit from source_data at position `offset`. Reads in order of most
51 // significant to least significant - that is, offset = 0 refers to the bit in
52 // position 2^7, offset = 1 refers to the bit in position 2^6, etc. Caller
53 // should ensure that offset/8 is < data.size().
GetUpperBit(const int64_t & offset,const std::vector<uint8_t> & source_data)54 uint8_t GetUpperBit(const int64_t& offset,
55 const std::vector<uint8_t>& source_data) {
56 int64_t byte_index = offset / 8;
57 uint8_t bit_index = 7 - (offset % 8);
58 return (source_data.at(byte_index) >> bit_index) & 0x01;
59 }
60
61 // Read unsigned literal bit by bit. Data is read into the lower
62 // `remaining_bits_to_read` of `output` from the upper `remaining_bits_to_read`
63 // of bit_offer[buffer_bit_offset].
64 //
65 // Ex: Input: bit_buffer = 10000111, buffer_bit_offset = 0,
66 // remaining_bits_to_read = 5, output = 0
67 // Output: output = {59 leading zeroes} + 10000, buffer_bit_offset = 5,
68 // remaining_bits_to_read = 0.
ReadUnsignedLiteralBits(const std::vector<uint8_t> & bit_buffer,const int64_t buffer_size,int64_t & buffer_bit_offset,int64_t & remaining_bits_to_read,uint64_t & output)69 void ReadUnsignedLiteralBits(const std::vector<uint8_t>& bit_buffer,
70 const int64_t buffer_size,
71 int64_t& buffer_bit_offset,
72 int64_t& remaining_bits_to_read,
73 uint64_t& output) {
74 while (((buffer_bit_offset / 8) < bit_buffer.size()) &&
75 remaining_bits_to_read > 0 && (buffer_bit_offset < buffer_size)) {
76 uint8_t upper_bit = GetUpperBit(buffer_bit_offset, bit_buffer);
77 output <<= 1;
78 output |= static_cast<uint64_t>(upper_bit);
79 remaining_bits_to_read--;
80 buffer_bit_offset++;
81 }
82 }
83
84 // Read unsigned literal byte by byte.
ReadUnsignedLiteralBytes(const std::vector<uint8_t> & bit_buffer,int64_t & buffer_bit_offset,int64_t & remaining_bits_to_read,uint64_t & output)85 void ReadUnsignedLiteralBytes(const std::vector<uint8_t>& bit_buffer,
86 int64_t& buffer_bit_offset,
87 int64_t& remaining_bits_to_read,
88 uint64_t& output) {
89 while (((buffer_bit_offset / 8) < bit_buffer.size()) &&
90 remaining_bits_to_read > 0) {
91 output <<= 8;
92 output |= static_cast<uint64_t>(bit_buffer.at(buffer_bit_offset / 8));
93 remaining_bits_to_read -= 8;
94 buffer_bit_offset += 8;
95 }
96 }
97
98 typedef absl::AnyInvocable<void(uint64_t, int, uint64_t&) const>
99 ByteAccumulator;
100
AccumulateUleb128Byte(const ByteAccumulator & accumulator,uint32_t max_output,const uint64_t & byte,const int index,bool & is_terminal_block,uint64_t & accumulated_value)101 absl::Status AccumulateUleb128Byte(const ByteAccumulator& accumulator,
102 uint32_t max_output, const uint64_t& byte,
103 const int index, bool& is_terminal_block,
104 uint64_t& accumulated_value) {
105 accumulator(byte, index, accumulated_value);
106 is_terminal_block = ((byte & 0x80) == 0);
107 if ((index == (kMaxLeb128Size - 1)) && !is_terminal_block) {
108 return absl::InvalidArgumentError(
109 "Have read the max allowable bytes for a uleb128, but bitstream "
110 "says to keep reading.");
111 }
112 if (accumulated_value > max_output) {
113 return absl::InvalidArgumentError(
114 absl::StrCat("Overflow - data is larger than max_output=", max_output));
115 }
116 return absl::OkStatus();
117 }
118
119 // Common internal function for reading uleb128 and iso14496_1 expanded. They
120 // have similar logic except the bytes are accumulated in different orders, and
121 // they have different max output values.
AccumulateUleb128OrIso14496_1Internal(const ByteAccumulator & accumulator,const uint32_t max_output,ReadBitBuffer & rb,uint32_t & output,int8_t & encoded_size)122 absl::Status AccumulateUleb128OrIso14496_1Internal(
123 const ByteAccumulator& accumulator, const uint32_t max_output,
124 ReadBitBuffer& rb, uint32_t& output, int8_t& encoded_size) {
125 uint64_t accumulated_value = 0;
126 uint64_t byte = 0;
127 bool terminal_block = false;
128 encoded_size = 0;
129 for (int i = 0; i < kMaxLeb128Size; ++i) {
130 RETURN_IF_NOT_OK(rb.ReadUnsignedLiteral(8, byte));
131 encoded_size++;
132 RETURN_IF_NOT_OK(AccumulateUleb128Byte(accumulator, max_output, byte, i,
133 terminal_block, accumulated_value));
134
135 if (terminal_block) {
136 break;
137 }
138 }
139 // Accumulated value is guaranteed to fit into a `uint32_t` at this
140 // stage.
141 output = static_cast<uint32_t>(accumulated_value);
142 return absl::OkStatus();
143 }
144
145 } // namespace
146
147 // Reads n = `num_bits` bits from the buffer. These are the upper n bits of
148 // `bit_buffer_`. n must be <= 64. The read data is consumed, meaning
149 // `buffer_bit_offset_` is incremented by n as a side effect of this fxn.
ReadUnsignedLiteral(const int num_bits,uint64_t & output)150 absl::Status ReadBitBuffer::ReadUnsignedLiteral(const int num_bits,
151 uint64_t& output) {
152 return ReadUnsignedLiteralInternal(num_bits, 64, output);
153 }
154
ReadUnsignedLiteral(const int num_bits,uint32_t & output)155 absl::Status ReadBitBuffer::ReadUnsignedLiteral(const int num_bits,
156 uint32_t& output) {
157 uint64_t value;
158 RETURN_IF_NOT_OK(ReadUnsignedLiteralInternal(num_bits, 32, value));
159 output = static_cast<uint32_t>(value);
160 return absl::OkStatus();
161 }
162
ReadUnsignedLiteral(const int num_bits,uint16_t & output)163 absl::Status ReadBitBuffer::ReadUnsignedLiteral(const int num_bits,
164 uint16_t& output) {
165 uint64_t value;
166 RETURN_IF_NOT_OK(ReadUnsignedLiteralInternal(num_bits, 16, value));
167 output = static_cast<uint16_t>(value);
168 return absl::OkStatus();
169 }
170
ReadUnsignedLiteral(const int num_bits,uint8_t & output)171 absl::Status ReadBitBuffer::ReadUnsignedLiteral(const int num_bits,
172 uint8_t& output) {
173 uint64_t value;
174 RETURN_IF_NOT_OK(ReadUnsignedLiteralInternal(num_bits, 8, value));
175 output = static_cast<uint8_t>(value);
176 return absl::OkStatus();
177 }
178
179 // Reads a standard int16_t in two's complement form from the read buffer.
ReadSigned16(int16_t & output)180 absl::Status ReadBitBuffer::ReadSigned16(int16_t& output) {
181 uint64_t value;
182 RETURN_IF_NOT_OK(ReadUnsignedLiteral(16, value));
183 output = static_cast<int16_t>(value) & 0xffff;
184 return absl::OkStatus();
185 }
186
187 // Reads a null terminated C-style string from the buffer.
ReadString(std::string & output)188 absl::Status ReadBitBuffer::ReadString(std::string& output) {
189 // Read up to the first `kIamfMaxStringSize` characters. Exit after seeing the
190 // null terminator. Override anything in `output`.
191 output = "";
192 for (int i = 0; i < kIamfMaxStringSize; i++) {
193 uint8_t byte;
194 RETURN_IF_NOT_OK(ReadUnsignedLiteral(8, byte));
195 if (byte == '\0') {
196 return absl::OkStatus();
197 }
198 output.push_back(byte);
199 }
200
201 // Failed to find the null terminator within `kIamfMaxStringSize` bytes.
202 return absl::InvalidArgumentError(
203 "Failed to find the null terminator for data= ");
204 }
205
ReadULeb128(DecodedUleb128 & uleb128)206 absl::Status ReadBitBuffer::ReadULeb128(DecodedUleb128& uleb128) {
207 int8_t unused_size;
208 return ReadULeb128(uleb128, unused_size);
209 }
210
ReadULeb128(DecodedUleb128 & uleb128,int8_t & encoded_uleb128_size)211 absl::Status ReadBitBuffer::ReadULeb128(DecodedUleb128& uleb128,
212 int8_t& encoded_uleb128_size) {
213 static const ByteAccumulator little_endian_accumulator =
214 [&](uint64_t byte, int index, uint64_t& accumulated_value) {
215 accumulated_value |= (byte & 0x7f) << (7 * index);
216 };
217 // IAMF requires all `leb128`s to decode to a value that fits in 32 bits.
218 const uint32_t kMaxUleb128 = std::numeric_limits<uint32_t>::max();
219 return AccumulateUleb128OrIso14496_1Internal(little_endian_accumulator,
220 kMaxUleb128, *this, uleb128,
221 encoded_uleb128_size);
222 }
223
ReadIso14496_1Expanded(uint32_t max_class_size,uint32_t & size_of_instance)224 absl::Status ReadBitBuffer::ReadIso14496_1Expanded(uint32_t max_class_size,
225 uint32_t& size_of_instance) {
226 static const ByteAccumulator big_endian_accumulator =
227 [](uint64_t byte, int /*index*/, uint64_t& accumulated_value) {
228 accumulated_value = accumulated_value << 7 | (byte & 0x7f);
229 };
230 int8_t unused_encoded_size = 0;
231 return AccumulateUleb128OrIso14496_1Internal(
232 big_endian_accumulator, max_class_size, *this, size_of_instance,
233 unused_encoded_size);
234 }
235
ReadUint8Span(absl::Span<uint8_t> output)236 absl::Status ReadBitBuffer::ReadUint8Span(absl::Span<uint8_t> output) {
237 for (auto& byte : output) {
238 RETURN_IF_NOT_OK(ReadUnsignedLiteral(8, byte));
239 }
240 return absl::OkStatus();
241 }
242
ReadBoolean(bool & output)243 absl::Status ReadBitBuffer::ReadBoolean(bool& output) {
244 uint64_t bit;
245 RETURN_IF_NOT_OK(ReadUnsignedLiteral(1, bit));
246 output = static_cast<bool>(bit);
247 return absl::OkStatus();
248 }
249
ReadBitBuffer(size_t capacity,int64_t source_size)250 ReadBitBuffer::ReadBitBuffer(size_t capacity, int64_t source_size)
251 : bit_buffer_(capacity),
252 buffer_bit_offset_(0),
253 buffer_size_(0),
254 source_size_(source_size),
255 source_bit_offset_(0) {}
256
IsDataAvailable() const257 bool ReadBitBuffer::IsDataAvailable() const {
258 const bool valid_data_in_buffer =
259 (buffer_bit_offset_ >= 0 && buffer_bit_offset_ < buffer_size_);
260 const bool valid_data_in_source =
261 (source_bit_offset_ >= 0 && source_bit_offset_ < source_size_);
262 return valid_data_in_buffer || valid_data_in_source;
263 }
264
CanReadBytes(int64_t num_bytes_requested) const265 bool ReadBitBuffer::CanReadBytes(int64_t num_bytes_requested) const {
266 CHECK_GE(num_bytes_requested, 0);
267 CHECK(source_bit_offset_ >= 0 && source_bit_offset_ <= source_size_);
268 const int64_t num_bytes_in_source = (source_size_ - source_bit_offset_) / 8;
269 CHECK(buffer_bit_offset_ >= 0 && buffer_bit_offset_ <= buffer_size_);
270 const int64_t num_bytes_in_buffer = (buffer_size_ - buffer_bit_offset_) / 8;
271 return (num_bytes_in_source + num_bytes_in_buffer) >= num_bytes_requested;
272 }
273
Tell()274 int64_t ReadBitBuffer::Tell() {
275 is_position_valid_ = true;
276 return source_bit_offset_ - buffer_size_ + buffer_bit_offset_;
277 }
278
Seek(const int64_t position)279 absl::Status ReadBitBuffer::Seek(const int64_t position) {
280 if (!is_position_valid_) {
281 return absl::FailedPreconditionError(
282 "Seeking to position has been disabled. This can happen if Flush() has "
283 "been called after Tell().");
284 }
285 if (position < 0) {
286 return absl::InvalidArgumentError(
287 absl::StrCat("Invalid source position: ", position));
288 }
289
290 if (position >= source_size_) {
291 return absl::ResourceExhaustedError(
292 absl::StrCat("Not enough bits in source: position= ", position,
293 " >= #(bits in source)= ", source_size_));
294 }
295
296 // Simply move the `buffer_bit_offset_` if the requested position lies within
297 // the current buffer.
298 if ((source_bit_offset_ - buffer_size_ <= position) &&
299 (position < source_bit_offset_)) {
300 buffer_bit_offset_ = position - (source_bit_offset_ - buffer_size_);
301 return absl::OkStatus();
302 }
303
304 // Load the data from the source, starting from the byte that the requested
305 // position is at.
306 const int64_t starting_byte = position / 8;
307 const int64_t num_bytes =
308 std::min(static_cast<int64_t>(bit_buffer_.capacity()),
309 source_size_ / 8 - starting_byte);
310
311 RETURN_IF_NOT_OK(LoadBytesToBuffer(starting_byte, num_bytes));
312
313 // Update other bookkeeping data.
314 buffer_bit_offset_ = position % 8;
315 source_bit_offset_ = (starting_byte + num_bytes) * 8;
316 buffer_size_ = num_bytes * 8;
317
318 return absl::OkStatus();
319 }
320
ReadUnsignedLiteralInternal(const int num_bits,const int max_num_bits,uint64_t & output)321 absl::Status ReadBitBuffer::ReadUnsignedLiteralInternal(const int num_bits,
322 const int max_num_bits,
323 uint64_t& output) {
324 if (num_bits > max_num_bits) {
325 return absl::InvalidArgumentError("num_bits must be <= max_num_bits.");
326 }
327 if (num_bits < 0) {
328 return absl::InvalidArgumentError("num_bits must be >= 0.");
329 }
330 if (buffer_bit_offset_ < 0) {
331 return absl::InvalidArgumentError("buffer_bit_offset_ must be >= 0.");
332 }
333 output = 0;
334
335 // Early return if 0 bit is requested to be read.
336 if (num_bits == 0) {
337 return absl::OkStatus();
338 }
339
340 // Now at least one bit is needed, make sure the buffer has some data in it.
341 RETURN_IF_NOT_OK(Seek(Tell()));
342 int64_t remaining_bits_to_read = num_bits;
343 const int64_t expected_final_position = Tell() + remaining_bits_to_read;
344
345 // If the final position and the current position lies within the same byte.
346 if (expected_final_position / 8 == Tell() / 8) {
347 ReadUnsignedLiteralBits(bit_buffer_, buffer_size_, buffer_bit_offset_,
348 remaining_bits_to_read, output);
349 CHECK_EQ(remaining_bits_to_read, 0) << remaining_bits_to_read;
350 return absl::OkStatus();
351 }
352
353 // Read the first several bits so that the `buffer_bit_offset_` is byte
354 // aligned.
355 if (buffer_bit_offset_ % 8 != 0) {
356 int64_t num_bits_to_byte_aligned = 8 - (buffer_bit_offset_ % 8);
357 remaining_bits_to_read -= num_bits_to_byte_aligned;
358 ReadUnsignedLiteralBits(bit_buffer_, buffer_size_, buffer_bit_offset_,
359 num_bits_to_byte_aligned, output);
360 }
361
362 // Read consecutive complete bytes.
363 while (remaining_bits_to_read >= 8) {
364 // Make sure the reading position has some buffer to read if possible.
365 RETURN_IF_NOT_OK(Seek(Tell()));
366
367 // Read as much as possible from the buffer.
368 int64_t num_bits_from_buffer = std::min(buffer_size_ - buffer_bit_offset_,
369 (remaining_bits_to_read / 8) * 8);
370
371 CHECK(CanReadByteAligned(buffer_bit_offset_, num_bits_from_buffer));
372 remaining_bits_to_read -= num_bits_from_buffer;
373 ReadUnsignedLiteralBytes(bit_buffer_, buffer_bit_offset_,
374 num_bits_from_buffer, output);
375 }
376
377 // Read the final several bits in the last byte.
378 int64_t num_bits_in_final_byte = expected_final_position % 8;
379 remaining_bits_to_read -= num_bits_in_final_byte;
380 ReadUnsignedLiteralBits(bit_buffer_, buffer_size_, buffer_bit_offset_,
381 num_bits_in_final_byte, output);
382 CHECK_EQ(remaining_bits_to_read, 0) << remaining_bits_to_read;
383 return absl::OkStatus();
384 }
385
386 // ----- MemoryBasedReadBitBuffer -----
387
388 std::unique_ptr<MemoryBasedReadBitBuffer>
CreateFromSpan(int64_t capacity,absl::Span<const uint8_t> source)389 MemoryBasedReadBitBuffer::CreateFromSpan(int64_t capacity,
390 absl::Span<const uint8_t> source) {
391 if (capacity < 0) {
392 LOG(ERROR) << "MemoryBasedReadBitBuffer capacity must be >= 0.";
393 return nullptr;
394 }
395 return absl::WrapUnique(new MemoryBasedReadBitBuffer(capacity, source));
396 }
397
LoadBytesToBuffer(int64_t starting_byte,int64_t num_bytes)398 absl::Status MemoryBasedReadBitBuffer::LoadBytesToBuffer(int64_t starting_byte,
399 int64_t num_bytes) {
400 if (starting_byte > source_vector_.size() ||
401 (starting_byte + num_bytes) > source_vector_.size()) {
402 return absl::InvalidArgumentError(
403 "Invalid starting or ending position to read from the vector");
404 }
405
406 std::copy(source_vector_.begin() + starting_byte,
407 source_vector_.begin() + starting_byte + num_bytes,
408 bit_buffer_.begin());
409 return absl::OkStatus();
410 }
411
MemoryBasedReadBitBuffer(size_t capacity,absl::Span<const uint8_t> source)412 MemoryBasedReadBitBuffer::MemoryBasedReadBitBuffer(
413 size_t capacity, absl::Span<const uint8_t> source)
414 : ReadBitBuffer(capacity, static_cast<int64_t>(source.size()) * 8),
415 source_vector_(source.begin(), source.end()) {}
416
417 // ----- FileBasedReadBitBuffer -----
418
419 std::unique_ptr<FileBasedReadBitBuffer>
CreateFromFilePath(const int64_t capacity,const std::filesystem::path & file_path)420 FileBasedReadBitBuffer::CreateFromFilePath(
421 const int64_t capacity, const std::filesystem::path& file_path) {
422 if (capacity < 0) {
423 LOG(ERROR) << "FileBasedReadBitBuffer capacity must be >= 0.";
424 return nullptr;
425 }
426 if (!std::filesystem::exists(file_path)) {
427 LOG(ERROR) << "File not found: " << file_path;
428 return nullptr;
429 }
430 std::ifstream ifs(file_path, std::ios::binary | std::ios::in);
431 ifs.seekg(0, ifs.end);
432 const auto file_size = static_cast<size_t>(ifs.tellg());
433 ifs.seekg(0, ifs.beg);
434 if (!ifs.good()) {
435 LOG(ERROR) << "Error accessing " << file_path;
436 return nullptr;
437 }
438
439 // File size is in bytes, `source_size` is in bits.
440 return absl::WrapUnique(
441 new FileBasedReadBitBuffer(capacity, file_size * 8, std::move(ifs)));
442 }
443
LoadBytesToBuffer(int64_t starting_byte,int64_t num_bytes)444 absl::Status FileBasedReadBitBuffer::LoadBytesToBuffer(int64_t starting_byte,
445 int64_t num_bytes) {
446 source_ifs_.seekg(starting_byte);
447 source_ifs_.read(reinterpret_cast<char*>(bit_buffer_.data()), num_bytes);
448 if (!source_ifs_.good()) {
449 return absl::InvalidArgumentError(
450 absl::StrCat("File reading failed. State= ", source_ifs_.rdstate()));
451 }
452
453 return absl::OkStatus();
454 }
455
FileBasedReadBitBuffer(size_t capacity,int64_t source_size,std::ifstream && ifs)456 FileBasedReadBitBuffer::FileBasedReadBitBuffer(size_t capacity,
457 int64_t source_size,
458 std::ifstream&& ifs)
459 : ReadBitBuffer(capacity, source_size), source_ifs_(std::move(ifs)) {}
460
461 // ----- StreamBasedReadBitBuffer -----
Create(int64_t capacity)462 std::unique_ptr<StreamBasedReadBitBuffer> StreamBasedReadBitBuffer::Create(
463 int64_t capacity) {
464 if (capacity < 0) {
465 LOG(ERROR) << "StreamBasedReadBitBuffer capacity must be >= 0.";
466 return nullptr;
467 }
468 // Since this is a stream based buffer, we do not initialize with any data,
469 // hence the source size is initially set to 0.
470 return absl::WrapUnique(
471 new StreamBasedReadBitBuffer(capacity, /*source_size=*/0));
472 }
473
PushBytes(absl::Span<const uint8_t> bytes)474 absl::Status StreamBasedReadBitBuffer::PushBytes(
475 absl::Span<const uint8_t> bytes) {
476 if (bytes.size() > ((max_source_size_ / 8) - source_vector_.size())) {
477 return absl::InvalidArgumentError(
478 "Cannot push more bytes than the available space in the source.");
479 }
480 // Copy the bytes to the source vector; this is added to the end in case there
481 // are already some bytes in the source.
482 source_vector_.insert(source_vector_.end(), bytes.begin(), bytes.end());
483 // The source grows as bytes are pushed.
484 source_size_ += bytes.size() * 8;
485 return absl::OkStatus();
486 }
487
488 // Flush should be called in a reasonable manner, i.e. not every time a read
489 // operation is performed, as the removal of elements from the source vector
490 // is an O(n) operation, where n is the number of elements in the source vector.
491 // In general, it is a trade-off: the more often it is called, the more
492 // space-efficient the buffer is (since it holds less data in the source vector)
493 // while simultaneously being less time-efficient (since it takes time to remove
494 // elements from the source vector).
Flush(int64_t num_bytes)495 absl::Status StreamBasedReadBitBuffer::Flush(int64_t num_bytes) {
496 if (num_bytes > source_vector_.size()) {
497 return absl::InvalidArgumentError(
498 "Cannot flush more bytes than are in the source.");
499 }
500 source_vector_.erase(source_vector_.begin(),
501 source_vector_.begin() + num_bytes);
502 // Offset needs to be moved back as erase moves the elements of a vector that
503 // are not removed to the beginning of the vector.
504 source_bit_offset_ -= num_bytes * 8;
505 source_size_ -= num_bytes * 8;
506 // Disable seeking as the position returned by a previous Tell() call is no
507 // longer valid.
508 is_position_valid_ = false;
509 return absl::OkStatus();
510 }
511
StreamBasedReadBitBuffer(size_t capacity,int64_t source_size)512 StreamBasedReadBitBuffer::StreamBasedReadBitBuffer(size_t capacity,
513 int64_t source_size)
514 : MemoryBasedReadBitBuffer(capacity, absl::Span<const uint8_t>()) {
515 max_source_size_ = kEntireObuSizeMaxTwoMegabytes * 2 * 8;
516 }
517
518 } // namespace iamf_tools
519