• 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 #include "iamf/common/utils/bit_buffer_util.h"
13 
14 #include <cstdint>
15 #include <vector>
16 
17 #include "absl/status/status.h"
18 
19 namespace iamf_tools {
20 
21 // Checks to see if `bit_buffer` is writeable. If not, will resize the buffer
22 // accordingly, so long as `allow_resizing` is set to true.
CanWriteBits(const bool allow_resizing,const int num_bits,const int64_t bit_offset,std::vector<uint8_t> & bit_buffer)23 absl::Status CanWriteBits(const bool allow_resizing, const int num_bits,
24                           const int64_t bit_offset,
25                           std::vector<uint8_t>& bit_buffer) {
26   const int64_t size = static_cast<int64_t>(bit_buffer.size());
27   if (bit_offset + num_bits <= size * 8) {
28     return absl::OkStatus();
29   }
30 
31   if (!allow_resizing) {
32     return absl::ResourceExhaustedError(
33         "The buffer does not have enough capacity to write and cannot be "
34         "resized.");
35   }
36 
37   const int64_t required_bytes = ((bit_offset + num_bits) / 8) +
38                                  ((bit_offset + num_bits) % 8 == 0 ? 0 : 1);
39 
40   // Adjust the size of the buffer.
41   bit_buffer.resize(required_bytes, 0);
42 
43   return absl::OkStatus();
44 }
45 
CanWriteBytes(const bool allow_resizing,const int num_bytes,const int64_t bit_offset,std::vector<uint8_t> & bit_buffer)46 absl::Status CanWriteBytes(const bool allow_resizing, const int num_bytes,
47                            const int64_t bit_offset,
48                            std::vector<uint8_t>& bit_buffer) {
49   return CanWriteBits(allow_resizing, num_bytes * 8, bit_offset, bit_buffer);
50 }
51 
52 // Write one bit `bit` to `bit_buffer` using an AND or OR mask. All unwritten
53 // bits are unchanged. This function is designed to work even if the buffer has
54 // uninitialized data - this is done by calling CanWriteBit first. Has the side
55 // effect of incrementing bit_offset if successful.
WriteBit(int bit,int64_t & bit_offset,std::vector<uint8_t> & bit_buffer)56 absl::Status WriteBit(int bit, int64_t& bit_offset,
57                       std::vector<uint8_t>& bit_buffer) {
58   if (bit_offset < 0) {
59     return absl::InvalidArgumentError("The bit offset should not be negative.");
60   }
61   const int64_t off = bit_offset;
62   const int64_t p = off >> 3;
63   const int q = 7 - static_cast<int>(off & 0x7);
64 
65   if (bit == 0) {
66     // AND mask to set the target bit to 0 and leave others unchanged.
67     bit_buffer[p] &= ~(1 << q);
68   } else {
69     // OR mask to set the target bit to 1 and leave others unchanged.
70     bit_buffer[p] |= (1 << q);
71   }
72   bit_offset = off + 1;
73 
74   return absl::OkStatus();
75 }
76 }  // namespace iamf_tools
77