Upload upstream chromium 108.0.5359.1
[platform/framework/web/chromium-efl.git] / media / filters / h264_bitstream_buffer.cc
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "media/filters/h264_bitstream_buffer.h"
6
7 #include "base/bits.h"
8 #include "base/sys_byteorder.h"
9
10 namespace media {
11
12 H264BitstreamBuffer::H264BitstreamBuffer() : data_(nullptr) {
13   Reset();
14 }
15
16 H264BitstreamBuffer::~H264BitstreamBuffer() {
17   free(data_);
18   data_ = nullptr;
19 }
20
21 void H264BitstreamBuffer::Reset() {
22   free(data_);
23   data_ = nullptr;
24
25   capacity_ = 0;
26   pos_ = 0;
27   bits_in_buffer_ = 0;
28   reg_ = 0;
29
30   Grow();
31
32   bits_left_in_reg_ = kRegBitSize;
33 }
34
35 void H264BitstreamBuffer::Grow() {
36   data_ = static_cast<uint8_t*>(realloc(data_, capacity_ + kGrowBytes));
37   CHECK(data_) << "Failed growing the buffer";
38   capacity_ += kGrowBytes;
39 }
40
41 void H264BitstreamBuffer::FlushReg() {
42   // Flush all bytes that have at least one bit cached, but not more
43   // (on Flush(), reg_ may not be full).
44   size_t bits_in_reg = kRegBitSize - bits_left_in_reg_;
45   if (bits_in_reg == 0)
46     return;
47
48   size_t bytes_in_reg = base::bits::AlignUp(bits_in_reg, size_t{8}) / 8;
49   reg_ <<= (kRegBitSize - bits_in_reg);
50
51   // Convert to MSB and append as such to the stream.
52   reg_ = base::HostToNet64(reg_);
53
54   // Make sure we have enough space. Grow() will CHECK() on allocation failure.
55   if (pos_ + bytes_in_reg > capacity_)
56     Grow();
57
58   memcpy(data_ + pos_, &reg_, bytes_in_reg);
59   bits_in_buffer_ = pos_ * 8 + bits_in_reg;
60   pos_ += bytes_in_reg;
61
62   reg_ = 0;
63   bits_left_in_reg_ = kRegBitSize;
64 }
65
66 void H264BitstreamBuffer::AppendU64(size_t num_bits, uint64_t val) {
67   CHECK_LE(num_bits, kRegBitSize);
68
69   while (num_bits > 0) {
70     if (bits_left_in_reg_ == 0)
71       FlushReg();
72
73     uint64_t bits_to_write =
74         num_bits > bits_left_in_reg_ ? bits_left_in_reg_ : num_bits;
75     uint64_t val_to_write = (val >> (num_bits - bits_to_write));
76     if (bits_to_write < 64)
77       val_to_write &= ((1ull << bits_to_write) - 1);
78     reg_ <<= bits_to_write;
79     reg_ |= val_to_write;
80     num_bits -= bits_to_write;
81     bits_left_in_reg_ -= bits_to_write;
82   }
83 }
84
85 void H264BitstreamBuffer::AppendBool(bool val) {
86   if (bits_left_in_reg_ == 0)
87     FlushReg();
88
89   reg_ <<= 1;
90   reg_ |= (static_cast<uint64_t>(val) & 1);
91   --bits_left_in_reg_;
92 }
93
94 void H264BitstreamBuffer::AppendSE(int val) {
95   if (val > 0)
96     AppendUE(val * 2 - 1);
97   else
98     AppendUE(-val * 2);
99 }
100
101 void H264BitstreamBuffer::AppendUE(unsigned int val) {
102   size_t num_zeros = 0;
103   unsigned int v = val + 1;
104
105   while (v > 1) {
106     v >>= 1;
107     ++num_zeros;
108   }
109
110   AppendBits(num_zeros, 0);
111   AppendBits(num_zeros + 1, val + 1);
112 }
113
114 #define DCHECK_FINISHED()                                                      \
115   DCHECK_EQ(bits_left_in_reg_, kRegBitSize) << "Pending bits not yet written " \
116                                                "to the buffer, call "          \
117                                                "FinishNALU() first."
118
119 void H264BitstreamBuffer::BeginNALU(H264NALU::Type nalu_type, int nal_ref_idc) {
120   DCHECK_FINISHED();
121
122   DCHECK_LE(nalu_type, H264NALU::kEOStream);
123   DCHECK_GE(nal_ref_idc, 0);
124   DCHECK_LE(nal_ref_idc, 3);
125
126   AppendBits(32, 0x00000001);
127   AppendBits(1, 0);  // forbidden_zero_bit
128   AppendBits(2, nal_ref_idc);
129   AppendBits(5, nalu_type);
130 }
131
132 void H264BitstreamBuffer::FinishNALU() {
133   // RBSP stop one bit.
134   AppendBits(1, 1);
135
136   // Byte-alignment zero bits.
137   AppendBits(bits_left_in_reg_ % 8, 0);
138
139   Flush();
140 }
141
142 void H264BitstreamBuffer::Flush() {
143   if (bits_left_in_reg_ != kRegBitSize)
144     FlushReg();
145 }
146
147 size_t H264BitstreamBuffer::BitsInBuffer() const {
148   return bits_in_buffer_;
149 }
150
151 size_t H264BitstreamBuffer::BytesInBuffer() const {
152   DCHECK_FINISHED();
153   return pos_;
154 }
155
156 const uint8_t* H264BitstreamBuffer::data() const {
157   DCHECK(data_);
158   DCHECK_FINISHED();
159
160   return data_;
161 }
162
163 }  // namespace media