UDocumentation UE5.7 10.02.2026 (Source)
API documentation for Unreal Engine 5.7
M4Bitstream.h
Go to the documentation of this file.
1// Copyright Epic Games, Inc. All Rights Reserved.
2#pragma once
3
4#include "vdecmpeg4.h"
5#include "vdecmpeg4_Stream.h"
6#include "M4Memory.h"
7
8namespace vdecmpeg4
9{
10
11#if 1 // Little endian platform
12inline uint32 XSWAP(uint32 value)
13{
14 return (value << 24) | ((value & 0xff00) << 8) | ((value >> 8) & 0xff00) | (value >> 24);
15}
16#else
17#define XSWAP(a) (a)
18#endif
19
20
22{
23public:
26
29
32
34 void init(const uint8* bitstream, uint32 length);
35
38
40 uint32 show(const uint32 bits);
41
43 void skip(const uint32 bits);
44
46 void align();
47
49 void nextStartCode();
50 void nextResyncMarker();
51 void skipResyncMarker();
52
55
56 bool validStuffingBits();
57
59 uint32 getBits(const uint32 bits);
60
62 uint32 getBit();
63
65 bool isEof();
66
68 void totalBitsClear();
69
71 uint32 totalBitsGet() const;
72
74 const uint32* getBaseAddr() const;
75
76private:
78 VIDError ReadStreamBuffered(uint32& value);
79
82
84 const M4Bitstream& operator=(const M4Bitstream& pObj);
85
86 uint32 mAWord;
87 uint32 mBWord;
88
89 uint32 mPos;
90 uint32* mTail;
91
92 uint32 mLength;
93 uint32* mStart;
94
95 VIDStreamIO* mpStreamIO;
96
97 uint8* mpInternalBuffer;
98 uint32 mInternalBufferBytes;
99 uint32 mInternalBufferCurrentBytes;
100 uint32 mInternalBufferIndex;
101
102 M4MemHandler* mpMemSys;
103
104 uint32 mTotalBits;
105
106};
107
108/******************************************************************************
109 * INLINE FUNCTIONS
110 ******************************************************************************/
111
112// ----------------------------------------------------------------------------
119{
120 mTotalBits = 0;
121}
122
123
124
125
126// ----------------------------------------------------------------------------
131 : mTail(nullptr)
132 , mLength(0)
133 , mStart(nullptr)
134 , mpStreamIO(nullptr)
135 , mpInternalBuffer(nullptr)
136 , mInternalBufferBytes(0)
137 , mInternalBufferCurrentBytes(0)
138 , mInternalBufferIndex(0)
139 , mpMemSys(nullptr)
140 , mTotalBits(0)
141{
142}
143
144
145// ----------------------------------------------------------------------------
150{
151 if (mpInternalBuffer && mpMemSys)
152 {
153 mpMemSys->free(mpInternalBuffer);
154 }
155}
156
157
158// ----------------------------------------------------------------------------
167{
168 mpMemSys = &memSys;
169}
170
171
180inline void M4Bitstream::init(const uint8* bitstream, uint32 length)
181{
182 mStart = mTail = (uint32*)bitstream;
183 // initialize 'working' words with 1st 64 bits from stream
184 mAWord = XSWAP(mStart[0]);
185 mBWord = XSWAP(mStart[1]);
186 mPos = 0;
187
188 mLength = length;
189
190 mpStreamIO = nullptr;
191 if (mpInternalBuffer)
192 {
193 mpMemSys->free(mpInternalBuffer);
194 }
195 mpInternalBuffer = nullptr;
197}
198
199
200// ----------------------------------------------------------------------------
206inline VIDError M4Bitstream::ReadStreamBuffered(uint32& value)
207{
208 if (mInternalBufferIndex >= mInternalBufferCurrentBytes)
209 {
210 mInternalBufferIndex = 0;
211 VIDStreamResult result = mpStreamIO->Read(mpInternalBuffer, mInternalBufferBytes, mInternalBufferCurrentBytes);
212 if (result != VID_STREAM_OK)
213 {
214 value = 0;
215 mInternalBufferCurrentBytes = 0;
216 return result == VID_STREAM_EOF ? VID_ERROR_STREAM_EOF : VID_ERROR_STREAM_ERROR;
217 }
218 else
219 {
220 // Check returned data is multiple of 4bytes
221 M4CHECK((mInternalBufferCurrentBytes & 0x3) == 0 );
222 // Check if returned ANY result
223 M4CHECK( mInternalBufferCurrentBytes > 0 );
224 }
225 }
226 value = *((uint32*)(mpInternalBuffer + mInternalBufferIndex));
227 mInternalBufferIndex += 4;
228 return VID_OK;
229}
230
231
232// ----------------------------------------------------------------------------
240{
242
243 mpStreamIO = pStreamIO;
244
245 if (mpInternalBuffer)
246 {
247 mpMemSys->free(mpInternalBuffer);
248 }
249 mInternalBufferBytes = streamBufferBytes;
250 mpInternalBuffer = (uint8*)mpMemSys->malloc(mInternalBufferBytes);
251 mInternalBufferCurrentBytes = 0;
252 mInternalBufferIndex = 0;
253
254 // Read initial chunk of data
255 uint32 value;
256 ReadStreamBuffered(value);
257 mAWord = XSWAP(value);
258
259 ReadStreamBuffered(value);
260 mBWord = XSWAP(value);
261
262 // initialize 'working' words with 1st 64 bits from stream
263 mPos = 0;
264 mLength = 0;
265
266 mStart = mTail = nullptr;
268}
269
280{
281 M4CHECK(bits>0 && bits<=32);
282 uint32 res2;
283 int32 nbit = (int32)bits + int32(mPos - 32);
284 if (nbit > 0)
285 {
286 res2 = ((mAWord & (0xffffffff >> mPos)) << nbit) | (mBWord >> (32 - nbit));
287 }
288 else
289 {
290 res2 = (mAWord & (0xffffffff >> mPos)) >> (32 - mPos - bits);
291 }
292 return res2;
293}
294
302inline void M4Bitstream::skip(uint32 bits)
303{
304 M4CHECK(bits>0 && bits<=32);
305 mPos += bits; // advance bit position pointer
306 mTotalBits += bits;
307 if (mPos >= 32)
308 {
309 mAWord = mBWord;
310 if (mpStreamIO)
311 {
312 uint32 value;
313 ReadStreamBuffered(value);
314 mBWord = XSWAP(value);
315 }
316 else
317 {
318 mBWord = XSWAP(*(mTail+2));
319 mTail++;
320 }
321 mPos -= 32;
322 }
323}
324
325
326// ----------------------------------------------------------------------------
333{
334 return mpStreamIO ? mpStreamIO->IsEof() : ((8 * 4 * (mTail - mStart) + mPos)>>3) >= mLength;
335}
336
343{
344 uint32 remainder = mPos & 7;
345 if (remainder)
346 {
347 skip(8 - remainder);
348 }
349}
350
351
352// ----------------------------------------------------------------------------
357{
359 (void)zeroBit;
360 M4CHECK(zeroBit == 0);
361 while((mPos & 7) != 0)
362 {
363 uint32 oneBit = getBit();
364 (void)oneBit;
365 M4CHECK(oneBit == 1);
366 }
367}
368
370{
371 // This is the same as nextStartCode(), actually...
373}
374
376{
377 // Resync marker is at least 16 zero bits followed by a one.
378 // The number of zero bits varies depending on the VOP type, but syntactically it is always the same
379 // so we can simply skip over zero bits and one 1 bit.
380 while(getBit() == 0)
381 {
382 }
383}
384
385
386// ----------------------------------------------------------------------------
395{
396 M4CHECK(bits>0 && bits<=23);
397
398 uint32 rem = mPos & 7;
399 if (rem == 0)
400 {
401 // Are the next 8 bits an end marker?
402 if (show(8) == 0x7f)
403 {
404 // Yes. This must be skipped and the next n bits returned.
405 uint32 v = show(8 + bits);
406 return v & (0xffffffff >> (32 - bits));
407 }
408 else
409 {
410 return show(bits);
411 }
412 }
413 else
414 {
415 uint32 v = show(8 - (mPos & 7) + bits);
416 return v & (0xffffffff >> (32 - bits));
417 }
418}
419
420// ----------------------------------------------------------------------------
427{
428 static const uint8 stuffing[8] = { 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00 };
429 uint32 rb = mPos & 7;
430 if (rb == 0)
431 {
432 return show(8) == 0x7f;
433 }
434 else
435 {
436 uint32 rem = show(8 - rb);
437 return rem == stuffing[rb];
438 }
439}
440
441
452{
453 uint32 ret = show(bits);
454 skip(bits);
455 return ret;
456}
457
464{
465 return getBits(1);
466}
467
468// ----------------------------------------------------------------------------
475{
476 return mTotalBits;
477}
478
479// ----------------------------------------------------------------------------
483inline const uint32* M4Bitstream::getBaseAddr() const
484{
485 return (const uint32*)mStart;
486}
487
488
489}
490
491
OODEFFUNC typedef void(OODLE_CALLBACK t_fp_OodleCore_Plugin_Free)(void *ptr)
FPlatformTypes::int32 int32
A 32-bit signed integer.
Definition Platform.h:1125
UE_FORCEINLINE_HINT TSharedRef< CastToType, Mode > StaticCastSharedRef(TSharedRef< CastFromType, Mode > const &InSharedRef)
Definition SharedPointer.h:127
uint8_t uint8
Definition binka_ue_file_header.h:8
uint32_t uint32
Definition binka_ue_file_header.h:6
Definition M4Bitstream.h:22
bool validStuffingBits()
Definition M4Bitstream.h:426
uint32 show(const uint32 bits)
Show indicated bit from stream without moving file position.
Definition M4Bitstream.h:279
void skipResyncMarker()
Definition M4Bitstream.h:375
uint32 getBits(const uint32 bits)
Return indicated # of bits from stream.
Definition M4Bitstream.h:451
void setMemoryHook(M4MemHandler &memSys)
Set memory allocator.
Definition M4Bitstream.h:166
void nextStartCode()
implements next_start_code()
Definition M4Bitstream.h:356
const uint32 * getBaseAddr() const
Return memory base addres of stream.
Definition M4Bitstream.h:483
void nextResyncMarker()
Definition M4Bitstream.h:369
uint32 totalBitsGet() const
Read the byte counter.
Definition M4Bitstream.h:474
void align()
Align bitstream to next byte boundary.
Definition M4Bitstream.h:342
bool isEof()
Check eof.
Definition M4Bitstream.h:332
uint32 showBitsByteAligned(const uint32 bits)
implements nextbits_bytealigned()
Definition M4Bitstream.h:394
~M4Bitstream()
Destructor.
Definition M4Bitstream.h:149
M4Bitstream()
Construction of bitstream object.
Definition M4Bitstream.h:130
uint32 getBit()
Return 1 bit from stream.
Definition M4Bitstream.h:463
void skip(const uint32 bits)
Skip indicated bits in stream.
Definition M4Bitstream.h:302
void totalBitsClear()
Clear the byte counter.
Definition M4Bitstream.h:118
void init(const uint8 *bitstream, uint32 length)
Link bitstream to provided byte sequence.
Definition M4Bitstream.h:180
Definition M4Memory.h:34
void free(void *ptr)
Memory release.
Definition M4Memory.h:52
void * malloc(size_t size, size_t alignment=32)
Memory allocation with possible alignment.
Definition M4Memory.h:44
Definition vdecmpeg4_Stream.h:22
virtual VIDStreamResult Read(uint8 *pRequestedDataBuffer, uint32 requestedDataBytes, uint32 &actualDataBytes)=0
virtual bool IsEof()=0
Definition M4Bitstream.h:9
uint32 XSWAP(uint32 value)
Definition M4Bitstream.h:12
int32 VIDError
Generic error type.
Definition vdecmpeg4_ErrorCodes.h:10
VIDStreamResult
Possible resuls for VIDStream methods.
Definition vdecmpeg4_Stream.h:11
@ VID_STREAM_EOF
Definition vdecmpeg4_Stream.h:13
@ VID_STREAM_OK
Definition vdecmpeg4_Stream.h:12
float v
Definition radaudio_mdct.cpp:62
#define M4CHECK
Definition vdecmpeg4_Types.h:8