Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this
3 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : // Derived from Stagefright's ABitReader.
6 :
7 : #include "mp4_demuxer/BitReader.h"
8 :
9 : using namespace mozilla;
10 :
11 : namespace mp4_demuxer
12 : {
13 :
14 0 : BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer)
15 0 : : BitReader(aBuffer->Elements(), aBuffer->Length() * 8)
16 : {
17 0 : }
18 :
19 0 : BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer, size_t aBits)
20 0 : : BitReader(aBuffer->Elements(), aBits)
21 : {
22 0 : }
23 :
24 0 : BitReader::BitReader(const uint8_t* aBuffer, size_t aBits)
25 : : mData(aBuffer)
26 : , mOriginalBitSize(aBits)
27 : , mTotalBitsLeft(aBits)
28 0 : , mSize((aBits + 7) / 8)
29 : , mReservoir(0)
30 0 : , mNumBitsLeft(0)
31 : {
32 0 : }
33 :
34 0 : BitReader::~BitReader() { }
35 :
36 : uint32_t
37 0 : BitReader::ReadBits(size_t aNum)
38 : {
39 0 : MOZ_ASSERT(aNum <= 32);
40 0 : if (mTotalBitsLeft < aNum) {
41 0 : NS_ASSERTION(false, "Reading past end of buffer");
42 0 : return 0;
43 : }
44 0 : uint32_t result = 0;
45 0 : while (aNum > 0) {
46 0 : if (mNumBitsLeft == 0) {
47 0 : FillReservoir();
48 : }
49 :
50 0 : size_t m = aNum;
51 0 : if (m > mNumBitsLeft) {
52 0 : m = mNumBitsLeft;
53 : }
54 :
55 0 : result = (result << m) | (mReservoir >> (32 - m));
56 0 : mReservoir <<= m;
57 0 : mNumBitsLeft -= m;
58 0 : mTotalBitsLeft -= m;
59 :
60 0 : aNum -= m;
61 : }
62 :
63 0 : return result;
64 : }
65 :
66 : // Read unsigned integer Exp-Golomb-coded.
67 : uint32_t
68 0 : BitReader::ReadUE()
69 : {
70 0 : uint32_t i = 0;
71 :
72 0 : while (ReadBit() == 0 && i < 32) {
73 0 : i++;
74 : }
75 0 : if (i == 32) {
76 : // This can happen if the data is invalid, or if it's
77 : // short, since ReadBit() will return 0 when it runs
78 : // off the end of the buffer.
79 0 : NS_WARNING("Invalid H.264 data");
80 0 : return 0;
81 : }
82 0 : uint32_t r = ReadBits(i);
83 0 : r += (1 << i) - 1;
84 0 : return r;
85 : }
86 :
87 : // Read signed integer Exp-Golomb-coded.
88 : int32_t
89 0 : BitReader::ReadSE()
90 : {
91 0 : int32_t r = ReadUE();
92 0 : if (r & 1) {
93 0 : return (r+1) / 2;
94 : } else {
95 0 : return -r / 2;
96 : }
97 : }
98 :
99 : uint64_t
100 0 : BitReader::ReadU64()
101 : {
102 0 : uint64_t hi = ReadU32();
103 0 : uint32_t lo = ReadU32();
104 0 : return (hi << 32) | lo;
105 : }
106 :
107 : uint64_t
108 0 : BitReader::ReadUTF8()
109 : {
110 0 : int64_t val = ReadBits(8);
111 0 : uint32_t top = (val & 0x80) >> 1;
112 :
113 0 : if ((val & 0xc0) == 0x80 || val >= 0xFE) {
114 : // error.
115 0 : return -1;
116 : }
117 0 : while (val & top) {
118 0 : int tmp = ReadBits(8) - 128;
119 0 : if (tmp >> 6) {
120 : // error.
121 0 : return -1;
122 : }
123 0 : val = (val << 6) + tmp;
124 0 : top <<= 5;
125 : }
126 0 : val &= (top << 1) - 1;
127 0 : return val;
128 : }
129 :
130 : size_t
131 0 : BitReader::BitCount() const
132 : {
133 0 : return mOriginalBitSize - mTotalBitsLeft;
134 : }
135 :
136 : size_t
137 0 : BitReader::BitsLeft() const
138 : {
139 0 : return mTotalBitsLeft;
140 : }
141 :
142 : void
143 0 : BitReader::FillReservoir()
144 : {
145 0 : if (mSize == 0) {
146 0 : NS_ASSERTION(false, "Attempting to fill reservoir from past end of data");
147 0 : return;
148 : }
149 :
150 0 : mReservoir = 0;
151 : size_t i;
152 0 : for (i = 0; mSize > 0 && i < 4; i++) {
153 0 : mReservoir = (mReservoir << 8) | *mData;
154 0 : mData++;
155 0 : mSize--;
156 : }
157 :
158 0 : mNumBitsLeft = 8 * i;
159 0 : mReservoir <<= 32 - mNumBitsLeft;
160 : }
161 :
162 : } // namespace mp4_demuxer
|