Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/media/BitReader.cpp
Line
Count
Source (jump to first uncovered line)
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 "BitReader.h"
8
9
namespace mozilla
10
{
11
12
BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer)
13
  : BitReader(aBuffer->Elements(), aBuffer->Length() * 8)
14
0
{
15
0
}
16
17
BitReader::BitReader(const mozilla::MediaByteBuffer* aBuffer, size_t aBits)
18
  : BitReader(aBuffer->Elements(), aBits)
19
0
{
20
0
}
21
22
BitReader::BitReader(const uint8_t* aBuffer, size_t aBits)
23
  : mData(aBuffer)
24
  , mOriginalBitSize(aBits)
25
  , mTotalBitsLeft(aBits)
26
  , mSize((aBits + 7) / 8)
27
  , mReservoir(0)
28
  , mNumBitsLeft(0)
29
0
{
30
0
}
31
32
0
BitReader::~BitReader() { }
33
34
uint32_t
35
BitReader::ReadBits(size_t aNum)
36
0
{
37
0
  MOZ_ASSERT(aNum <= 32);
38
0
  if (mTotalBitsLeft < aNum) {
39
0
    NS_ASSERTION(false, "Reading past end of buffer");
40
0
    return 0;
41
0
  }
42
0
  uint32_t result = 0;
43
0
  while (aNum > 0) {
44
0
    if (mNumBitsLeft == 0) {
45
0
      FillReservoir();
46
0
    }
47
0
48
0
    size_t m = aNum;
49
0
    if (m > mNumBitsLeft) {
50
0
      m = mNumBitsLeft;
51
0
    }
52
0
53
0
    result = (result << m) | (mReservoir >> (32 - m));
54
0
    mReservoir <<= m;
55
0
    mNumBitsLeft -= m;
56
0
    mTotalBitsLeft -= m;
57
0
58
0
    aNum -= m;
59
0
  }
60
0
61
0
  return result;
62
0
}
63
64
// Read unsigned integer Exp-Golomb-coded.
65
uint32_t
66
BitReader::ReadUE()
67
0
{
68
0
  uint32_t i = 0;
69
0
70
0
  while (ReadBit() == 0 && i < 32) {
71
0
    i++;
72
0
  }
73
0
  if (i == 32) {
74
0
    // This can happen if the data is invalid, or if it's
75
0
    // short, since ReadBit() will return 0 when it runs
76
0
    // off the end of the buffer.
77
0
    NS_WARNING("Invalid H.264 data");
78
0
    return 0;
79
0
  }
80
0
  uint32_t r = ReadBits(i);
81
0
  r += (1 << i) - 1;
82
0
  return r;
83
0
}
84
85
// Read signed integer Exp-Golomb-coded.
86
int32_t
87
BitReader::ReadSE()
88
0
{
89
0
  int32_t r = ReadUE();
90
0
  if (r & 1) {
91
0
    return (r+1) / 2;
92
0
  } else {
93
0
    return -r / 2;
94
0
  }
95
0
}
96
97
uint64_t
98
BitReader::ReadU64()
99
0
{
100
0
  uint64_t hi = ReadU32();
101
0
  uint32_t lo = ReadU32();
102
0
  return (hi << 32) | lo;
103
0
}
104
105
uint64_t
106
BitReader::ReadUTF8()
107
0
{
108
0
  int64_t val = ReadBits(8);
109
0
  uint32_t top = (val & 0x80) >> 1;
110
0
111
0
  if ((val & 0xc0) == 0x80 || val >= 0xFE) {
112
0
    // error.
113
0
    return -1;
114
0
  }
115
0
  while (val & top) {
116
0
    int tmp = ReadBits(8) - 128;
117
0
    if (tmp >> 6) {
118
0
      // error.
119
0
      return -1;
120
0
    }
121
0
    val = (val << 6) + tmp;
122
0
    top <<= 5;
123
0
  }
124
0
  val &= (top << 1) - 1;
125
0
  return val;
126
0
}
127
128
size_t
129
BitReader::BitCount() const
130
0
{
131
0
  return mOriginalBitSize - mTotalBitsLeft;
132
0
}
133
134
size_t
135
BitReader::BitsLeft() const
136
0
{
137
0
  return mTotalBitsLeft;
138
0
}
139
140
void
141
BitReader::FillReservoir()
142
0
{
143
0
  if (mSize == 0) {
144
0
    NS_ASSERTION(false, "Attempting to fill reservoir from past end of data");
145
0
    return;
146
0
  }
147
0
148
0
  mReservoir = 0;
149
0
  size_t i;
150
0
  for (i = 0; mSize > 0 && i < 4; i++) {
151
0
    mReservoir = (mReservoir << 8) | *mData;
152
0
    mData++;
153
0
    mSize--;
154
0
  }
155
0
156
0
  mNumBitsLeft = 8 * i;
157
0
  mReservoir <<= 32 - mNumBitsLeft;
158
0
}
159
160
/* static */ uint32_t
161
BitReader::GetBitLength(const mozilla::MediaByteBuffer* aNAL)
162
0
{
163
0
  size_t size = aNAL->Length();
164
0
165
0
  while (size > 0 && aNAL->ElementAt(size - 1) == 0) {
166
0
    size--;
167
0
  }
168
0
169
0
  if (!size) {
170
0
    return 0;
171
0
  }
172
0
173
0
  if (size > UINT32_MAX / 8) {
174
0
    // We can't represent it, we'll use as much as we can.
175
0
    return UINT32_MAX;
176
0
  }
177
0
178
0
  uint8_t v = aNAL->ElementAt(size - 1);
179
0
  size *= 8;
180
0
181
0
  // Remove the stop bit and following trailing zeros.
182
0
  if (v) {
183
0
    // Count the consecutive zero bits (trailing) on the right by binary search.
184
0
    // Adapted from Matt Whitlock algorithm to only bother with 8 bits integers.
185
0
    uint32_t c;
186
0
    if (v & 1) {
187
0
      // Special case for odd v (assumed to happen half of the time).
188
0
      c = 0;
189
0
    } else {
190
0
      c = 1;
191
0
      if ((v & 0xf) == 0) {
192
0
        v >>= 4;
193
0
        c += 4;
194
0
      }
195
0
      if ((v & 0x3) == 0) {
196
0
        v >>= 2;
197
0
        c += 2;
198
0
      }
199
0
      c -= v & 0x1;
200
0
    }
201
0
    size -= c + 1;
202
0
  }
203
0
  return size;
204
0
}
205
206
} // namespace mozilla