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 : #ifndef BYTE_READER_H_
6 : #define BYTE_READER_H_
7 :
8 : #include "mozilla/EndianUtils.h"
9 : #include "mozilla/Vector.h"
10 : #include "nsTArray.h"
11 : #include "MediaData.h"
12 :
13 : namespace mp4_demuxer {
14 :
15 : class MOZ_RAII ByteReader
16 : {
17 : public:
18 : ByteReader() : mPtr(nullptr), mRemaining(0) {}
19 : explicit ByteReader(const mozilla::Vector<uint8_t>& aData)
20 : : mPtr(aData.begin()), mRemaining(aData.length()), mLength(aData.length())
21 : {
22 : }
23 0 : ByteReader(const uint8_t* aData, size_t aSize)
24 0 : : mPtr(aData), mRemaining(aSize), mLength(aSize)
25 : {
26 0 : }
27 : template<size_t S>
28 0 : explicit ByteReader(const AutoTArray<uint8_t, S>& aData)
29 0 : : mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length())
30 : {
31 0 : }
32 0 : explicit ByteReader(const nsTArray<uint8_t>& aData)
33 0 : : mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length())
34 : {
35 0 : }
36 0 : explicit ByteReader(const mozilla::MediaByteBuffer* aData)
37 0 : : mPtr(aData->Elements()), mRemaining(aData->Length()), mLength(aData->Length())
38 : {
39 0 : }
40 :
41 : void SetData(const nsTArray<uint8_t>& aData)
42 : {
43 : MOZ_ASSERT(!mPtr && !mRemaining);
44 : mPtr = aData.Elements();
45 : mRemaining = aData.Length();
46 : mLength = mRemaining;
47 : }
48 :
49 0 : ~ByteReader()
50 0 : {
51 0 : }
52 :
53 0 : size_t Offset() const
54 : {
55 0 : return mLength - mRemaining;
56 : }
57 :
58 0 : size_t Remaining() const { return mRemaining; }
59 :
60 0 : bool CanRead8() const { return mRemaining >= 1; }
61 :
62 0 : uint8_t ReadU8()
63 : {
64 0 : auto ptr = Read(1);
65 0 : if (!ptr) {
66 0 : MOZ_ASSERT(false);
67 : return 0;
68 : }
69 0 : return *ptr;
70 : }
71 :
72 0 : bool CanRead16() { return mRemaining >= 2; }
73 :
74 0 : uint16_t ReadU16()
75 : {
76 0 : auto ptr = Read(2);
77 0 : if (!ptr) {
78 0 : MOZ_ASSERT(false);
79 : return 0;
80 : }
81 0 : return mozilla::BigEndian::readUint16(ptr);
82 : }
83 :
84 0 : int16_t ReadLE16()
85 : {
86 0 : auto ptr = Read(2);
87 0 : if (!ptr) {
88 0 : MOZ_ASSERT(false);
89 : return 0;
90 : }
91 0 : return mozilla::LittleEndian::readInt16(ptr);
92 : }
93 :
94 0 : uint32_t ReadU24()
95 : {
96 0 : auto ptr = Read(3);
97 0 : if (!ptr) {
98 0 : MOZ_ASSERT(false);
99 : return 0;
100 : }
101 0 : return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
102 : }
103 :
104 : uint32_t Read24()
105 : {
106 : return (uint32_t)ReadU24();
107 : }
108 :
109 0 : int32_t ReadLE24()
110 : {
111 0 : auto ptr = Read(3);
112 0 : if (!ptr) {
113 0 : MOZ_ASSERT(false);
114 : return 0;
115 : }
116 0 : int32_t result = int32_t(ptr[2] << 16 | ptr[1] << 8 | ptr[0]);
117 0 : if (result & 0x00800000u) {
118 0 : result -= 0x1000000;
119 : }
120 0 : return result;
121 : }
122 :
123 0 : bool CanRead32() { return mRemaining >= 4; }
124 :
125 0 : uint32_t ReadU32()
126 : {
127 0 : auto ptr = Read(4);
128 0 : if (!ptr) {
129 0 : MOZ_ASSERT(false);
130 : return 0;
131 : }
132 0 : return mozilla::BigEndian::readUint32(ptr);
133 : }
134 :
135 0 : int32_t Read32()
136 : {
137 0 : auto ptr = Read(4);
138 0 : if (!ptr) {
139 0 : MOZ_ASSERT(false);
140 : return 0;
141 : }
142 0 : return mozilla::BigEndian::readInt32(ptr);
143 : }
144 :
145 0 : uint64_t ReadU64()
146 : {
147 0 : auto ptr = Read(8);
148 0 : if (!ptr) {
149 0 : MOZ_ASSERT(false);
150 : return 0;
151 : }
152 0 : return mozilla::BigEndian::readUint64(ptr);
153 : }
154 :
155 0 : int64_t Read64()
156 : {
157 0 : auto ptr = Read(8);
158 0 : if (!ptr) {
159 0 : MOZ_ASSERT(false);
160 : return 0;
161 : }
162 0 : return mozilla::BigEndian::readInt64(ptr);
163 : }
164 :
165 0 : const uint8_t* Read(size_t aCount)
166 : {
167 0 : if (aCount > mRemaining) {
168 0 : mRemaining = 0;
169 0 : return nullptr;
170 : }
171 0 : mRemaining -= aCount;
172 :
173 0 : const uint8_t* result = mPtr;
174 0 : mPtr += aCount;
175 :
176 0 : return result;
177 : }
178 :
179 0 : const uint8_t* Rewind(size_t aCount)
180 : {
181 0 : MOZ_ASSERT(aCount <= Offset());
182 0 : size_t rewind = Offset();
183 0 : if (aCount < rewind) {
184 0 : rewind = aCount;
185 : }
186 0 : mRemaining += rewind;
187 0 : mPtr -= rewind;
188 0 : return mPtr;
189 : }
190 :
191 0 : uint8_t PeekU8() const
192 : {
193 0 : auto ptr = Peek(1);
194 0 : if (!ptr) {
195 0 : MOZ_ASSERT(false);
196 : return 0;
197 : }
198 0 : return *ptr;
199 : }
200 :
201 0 : uint16_t PeekU16() const
202 : {
203 0 : auto ptr = Peek(2);
204 0 : if (!ptr) {
205 0 : MOZ_ASSERT(false);
206 : return 0;
207 : }
208 0 : return mozilla::BigEndian::readUint16(ptr);
209 : }
210 :
211 0 : uint32_t PeekU24() const
212 : {
213 0 : auto ptr = Peek(3);
214 0 : if (!ptr) {
215 0 : MOZ_ASSERT(false);
216 : return 0;
217 : }
218 0 : return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
219 : }
220 :
221 : uint32_t Peek24() const
222 : {
223 : return (uint32_t)PeekU24();
224 : }
225 :
226 0 : uint32_t PeekU32() const
227 : {
228 0 : auto ptr = Peek(4);
229 0 : if (!ptr) {
230 0 : MOZ_ASSERT(false);
231 : return 0;
232 : }
233 0 : return mozilla::BigEndian::readUint32(ptr);
234 : }
235 :
236 : int32_t Peek32() const
237 : {
238 : auto ptr = Peek(4);
239 : if (!ptr) {
240 : MOZ_ASSERT(false);
241 : return 0;
242 : }
243 : return mozilla::BigEndian::readInt32(ptr);
244 : }
245 :
246 : uint64_t PeekU64() const
247 : {
248 : auto ptr = Peek(8);
249 : if (!ptr) {
250 : MOZ_ASSERT(false);
251 : return 0;
252 : }
253 : return mozilla::BigEndian::readUint64(ptr);
254 : }
255 :
256 : int64_t Peek64() const
257 : {
258 : auto ptr = Peek(8);
259 : if (!ptr) {
260 : MOZ_ASSERT(false);
261 : return 0;
262 : }
263 : return mozilla::BigEndian::readInt64(ptr);
264 : }
265 :
266 0 : const uint8_t* Peek(size_t aCount) const
267 : {
268 0 : if (aCount > mRemaining) {
269 0 : return nullptr;
270 : }
271 0 : return mPtr;
272 : }
273 :
274 0 : const uint8_t* Seek(size_t aOffset)
275 : {
276 0 : if (aOffset >= mLength) {
277 0 : MOZ_ASSERT(false);
278 : return nullptr;
279 : }
280 :
281 0 : mPtr = mPtr - Offset() + aOffset;
282 0 : mRemaining = mLength - aOffset;
283 0 : return mPtr;
284 : }
285 :
286 : const uint8_t* Reset()
287 : {
288 : mPtr -= Offset();
289 : mRemaining = mLength;
290 : return mPtr;
291 : }
292 :
293 0 : uint32_t Align() const
294 : {
295 0 : return 4 - ((intptr_t)mPtr & 3);
296 : }
297 :
298 0 : template <typename T> bool CanReadType() const { return mRemaining >= sizeof(T); }
299 :
300 0 : template <typename T> T ReadType()
301 : {
302 0 : auto ptr = Read(sizeof(T));
303 0 : if (!ptr) {
304 0 : MOZ_ASSERT(false);
305 : return 0;
306 : }
307 0 : return *reinterpret_cast<const T*>(ptr);
308 : }
309 :
310 : template <typename T>
311 0 : MOZ_MUST_USE bool ReadArray(nsTArray<T>& aDest, size_t aLength)
312 : {
313 0 : auto ptr = Read(aLength * sizeof(T));
314 0 : if (!ptr) {
315 0 : return false;
316 : }
317 :
318 0 : aDest.Clear();
319 0 : aDest.AppendElements(reinterpret_cast<const T*>(ptr), aLength);
320 0 : return true;
321 : }
322 :
323 : template <typename T>
324 0 : MOZ_MUST_USE bool ReadArray(FallibleTArray<T>& aDest, size_t aLength)
325 : {
326 0 : auto ptr = Read(aLength * sizeof(T));
327 0 : if (!ptr) {
328 0 : return false;
329 : }
330 :
331 0 : aDest.Clear();
332 0 : if (!aDest.SetCapacity(aLength, mozilla::fallible)) {
333 0 : return false;
334 : }
335 0 : MOZ_ALWAYS_TRUE(aDest.AppendElements(reinterpret_cast<const T*>(ptr),
336 : aLength,
337 : mozilla::fallible));
338 0 : return true;
339 : }
340 :
341 : private:
342 : const uint8_t* mPtr;
343 : size_t mRemaining;
344 : size_t mLength;
345 : };
346 :
347 : } // namespace mp4_demuxer
348 :
349 : #endif
|