Files
UnrealEngine/Engine/Source/Runtime/AVEncoder/Private/Decoders/vdecmpeg4/M4VlcDecoder.h
2025-05-18 13:04:45 +08:00

261 lines
5.0 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "vdecmpeg4.h"
#include "M4Memory.h"
#include "M4Bitstream.h"
namespace vdecmpeg4
{
#define MK_VLC(a,b) \
( ((a)&0x1ffff) | ((b)<<17) )
#define VLC_CODE(a) \
((a)&0x1ffff)
#define VLC_LEN(a) \
((a)>>17)
#define VLC_ERROR MK_VLC(0x1ffff, 0)
#define VLC_ESCAPE 0x1BFF
typedef uint32 M4_VLC; //!< Definition of VLC data types
//! helper struct for passing some C++ tables to the ASM routines. Must be initialized only once.
struct M4BlockVlcCodeTab
{
M4_VLC* mVlcCodeTab[3];
void* mMaxLevel;
void* mMaxRun;
};
class M4VlcDecoder
{
public:
//! Default constructor
M4VlcDecoder()
{}
//! Destructor
~M4VlcDecoder()
{}
//! Init vlc tables
void init();
//!
int32 getCoeffIntraNoAsm(int32& run, int32& last, M4Bitstream& bs)
{
uint32 bits = bs.show(12);
M4CHECK(bits >= 8);
M4_VLC vlc = getIntraVlcTab(bits);
M4CHECK(vlc != VLC_ERROR);
bs.skip(VLC_LEN(vlc));
int32 level;
uint32 code = VLC_CODE(vlc);
if (code != VLC_ESCAPE)
{
run = (code >> 8) & 255;
level = code & 255;
last = (code >> 16) & 1;
int32 ret = bs.getBit() ? -level : level;
return ret;
}
uint32 escMode = bs.show(2);
if (escMode < 3)
{
bs.skip((escMode == 2) ? 2 : 1);
bits = bs.show(12);
M4CHECK(bits >= 8);
vlc = getIntraVlcTab(bits);
M4CHECK(vlc != VLC_ERROR);
bs.skip(VLC_LEN(vlc));
code = VLC_CODE(vlc);
run = (code >> 8) & 255;
level = code & 255;
last = (code >> 16) & 1;
if (escMode < 2) // first escape mode, level is offset
{
level += mMaxLevel[last][run]; // need to add back the max level
}
else if (escMode == 2) // second escape mode, run is offset
{
run += mMaxRun[last][level] + 1;
}
else
{
M4CHECK(0); //todo.... (needs a final verification)
}
int32 ret = bs.getBit() ? -level : level;
return ret;
}
// third escape mode - fixed length codes
bs.skip(2);
last = (int32) bs.getBits(1);
run = (int32) bs.getBits(6);
bs.skip(1); // marker
level = (int32) bs.getBits(12);
bs.skip(1); // marker
return (level & 0x800) ? (level | (-1 ^ 0xfff)) : level;
}
//!
int32 getCoeffInterNoAsm(int32& run, int32& last, M4Bitstream& bs)
{
// use ISO Table B-16, max 12 bit of VLC code
uint32 bits = bs.show(12);
M4CHECK(bits >= 8);
M4_VLC vlc = getInterVlcTab(bits);
M4CHECK(vlc != VLC_ERROR);
bs.skip(VLC_LEN(vlc));
int32 level;
uint32 code = VLC_CODE(vlc);
if (code != VLC_ESCAPE)
{
run = (code >> 4) & 255;
level = code & 15;
last = (code >> 12) & 1;
int32 ret = bs.getBit() ? -level : level;
return ret;
}
uint32 escMode = bs.show(2);
if (escMode < 3)
{
bs.skip((escMode == 2) ? 2 : 1);
bits = bs.show(12);
M4CHECK(bits >= 8);
vlc = getInterVlcTab(bits);
M4CHECK(vlc != VLC_ERROR);
bs.skip(VLC_LEN(vlc));
code = VLC_CODE(vlc);
run = (code >> 4) & 255;
level = code & 15;
last = (code >> 12) & 1;
if (escMode < 2) // first escape mode, level is offset
{
level += mMaxLevel[last + 2][run]; // need to add back the max level
}
else if (escMode == 2) // second escape mode, run is offset
{
run += mMaxRun[last + 2][level] + 1;
}
else
{
M4CHECK(0); //todo.... (needs a final verification)
}
int32 ret = bs.getBit() ? -level : level;
return ret;
}
// third escape mode - fixed length codes
bs.skip(2);
last = (int32) bs.getBits(1);
run = (int32) bs.getBits(6);
bs.skip(1); // marker
level = (int32) bs.getBits(12);
bs.skip(1); // marker
return (level & 0x800) ? (level | (-1 ^ 0xfff)) : level;
}
private:
//! Get vlc code for intra block
M4_VLC getIntraVlcTab(uint32 bits)
{
if (bits >=512)
{
return mIntraCodeTab.mVlcCodeTab[0][(bits >> 5) - 16];
}
else if (bits >= 128)
{
return mIntraCodeTab.mVlcCodeTab[1][(bits >> 2) - 32];
}
else
{
return mIntraCodeTab.mVlcCodeTab[2][bits - 8];
}
}
//! Get vlc code for inter block
M4_VLC getInterVlcTab(uint32 bits)
{
if (bits >=512)
{
return mInterCodeTab.mVlcCodeTab[0][(bits >> 5) - 16];
}
else if (bits >= 128)
{
return mInterCodeTab.mVlcCodeTab[1][(bits >> 2) - 32];
}
else
{
return mInterCodeTab.mVlcCodeTab[2][bits - 8];
}
}
//! Copy-constructor not implemented
M4VlcDecoder(const M4VlcDecoder &pObj);
//! Assignment operator not implemented
const M4VlcDecoder &operator=(const M4VlcDecoder &pObj);
M4BlockVlcCodeTab mIntraCodeTab;
M4BlockVlcCodeTab mInterCodeTab;
static uint8 mMaxLevel[4][64];
static uint8 mMaxRun[4][256];
static const M4_VLC mTabCbpCIntra[64];
static const M4_VLC mTabCbpCInter[257];
static const M4_VLC mTabCbpY[64];
static M4_VLC mTabTMNMV0[];
static M4_VLC mTabTMNMV1[];
static M4_VLC mTabTMNMV2[];
static M4_VLC mTabDCT3D0[];
static M4_VLC mTabDCT3D1[];
static M4_VLC mTabDCT3D2[];
static M4_VLC mTabDCT3D3[];
static M4_VLC mTabDCT3D4[];
static M4_VLC mTabDCT3D5[];
static const M4_VLC mDCLumTab[];
friend class M4BitstreamParser;
};
}