📄 mp4_decode.cpp
字号:
dc = dc_chr[block_num & 1];
if(pos >= MAX_MACROBLOCKS_X){
Fb=dc[(pos-MAX_MACROBLOCKS_X) & DC_CHR_MASK];
Fc=dc[(pos+1-MAX_MACROBLOCKS_X) & DC_CHR_MASK];
}
dc += pos & DC_CHR_MASK;
}
int Fa = dc[0];
if(Abs(Fb - Fa) < Abs(Fb - Fc)){
//TOP
predict_dir = 1;
Fa = Fc;
}else{
//LEFT
predict_dir = 0;
}
/*
if(Fa>0)
Fa += dc_scaler>>1;
else
Fa -= dc_scaler>>1;
Fa /= dc_scaler;
/**/
//assert(Divide(Fa, dc_scaler) == ( ((Fa>0)?(Fa+(dc_scaler>>1)):(Fa-(dc_scaler>>1)))/dc_scaler ));
Fa = Divide(Fa, dc_scaler);
++dc;
Fa *= dc_scaler;
*dc = (short)Fa;
return dc;
}
//----------------------------
static void ClearBlock(short *block){
int *i = (int*)block;
const int *ie = i+32;
do {
i[3] = i[2] = i[1] = i[0] = 0;
i[7] = i[6] = i[5] = i[4] = 0;
i += 8;
}while(i!=ie);
}
//----------------------------
void C_mp4_decode_imp::BlockIntra(int pos, int coded_block_pattern){
soft_idct.BeginBlock(POSX(pos), POSY(pos));
PROF_S(PROF_BLOCK_INTRA);
short *block = block_8x8;
//macroblock consists of four luminance blocks and the two spatially corresponding color difference blocks
for(int i=0; i<6; ++i){
int subpos;
int dc_scaler = quantizer;
ClearBlock(block);
bit_reader.Load();
//stream: 24bit available
if(i < 4){
//Y
if(dc_scaler >24)
dc_scaler = dc_scaler*2 - 16;
else
if(dc_scaler>8)
dc_scaler = (dc_scaler + 8);
else
if(dc_scaler>4)
dc_scaler <<= 1;
else
dc_scaler = 8;
//convert 1x1 -> 2x2 (accodring to block number)
subpos = 2*POSX(pos) + (POSY(pos) << (MB_X2+2));
subpos += (i & 1) + ((i & 2) << MB_X2);
}else{
//UV
if(dc_scaler > 24)
dc_scaler = (dc_scaler - 6);
else
if(dc_scaler > 4)
dc_scaler = (dc_scaler + 13)>>1;
else
dc_scaler = 8;
subpos = pos;
}
int len;
if(quantizer < intra_dc_threshold){
int dct_dc_size, dct_dc_diff;
dct_dc_diff = 0;
dct_dc_size = i<4 ? bit_reader.GetDCsizeLum() : bit_reader.GetDCsizeChr(); //max11bit : max12bit
if(dct_dc_size){
dct_dc_diff = bit_reader.GetDCdiff(dct_dc_size);
if(dct_dc_size > 8)
bit_reader.Flush(1); // marker bit
}
*block = (short)(dct_dc_diff * dc_scaler);
len = 1;
}else
len = 0;
//dc reconstruction, prediction direction
int predict_dir;
short *dc_addr = Dc_recon(i, subpos, dc_scaler, predict_dir);
int scantype;
if(ac_pred_flag){
if(predict_dir == 1) //TOP
scantype = IDCTSCAN_ALT_HORI;
else
scantype = IDCTSCAN_ALT_VERT;
}else
scantype = IDCTSCAN_ZIGZAG;
if((coded_block_pattern << (26+i)) < 0){
//coded block
if(quant_type)
len = Vld_block_mpeg(vld_intra, scan_table[scantype], len);
else
len = Vld_block_mpeg4(vld_intra, scan_table[scantype], len);
}
//dc add
if(quantizer >= intra_dc_threshold){
if(quant_type)
*block = (short)(Divide(*block*8, quant_matrix[0][0] * quantizer) * dc_scaler);
else
*block = (short)(Divide(*block, quantizer*2) * dc_scaler);
}
*block = *dc_addr = (short)(*block + *dc_addr);
//ac reconstruction
Ac_recon(i, subpos, predict_dir);
soft_idct.Intra8x8(block, Max(len, 14), scantype);
}
PROF_E(PROF_BLOCK_INTRA);
}
//----------------------------
void C_mp4_decode_imp::BlockInter(int coded_block_pattern){
//texture decoding add
//macroblock consists of four luminance blocks and the two spatially corresponding color difference blocks
for(int i = 0; i < 6; i++){
int len = 0;
if((coded_block_pattern << (26+i)) < 0){
//coded
ClearBlock(block_8x8);
if(quant_type)
len = Vld_block_mpeg(vld_inter, scan_table[IDCTSCAN_ZIGZAG], len);
else
len = Vld_block_mpeg4(vld_inter, scan_table[IDCTSCAN_ZIGZAG], len);
}
soft_idct.Inter8x8(block_8x8, len);
}
}
//----------------------------
static const signed char DQtab[4] = {
-1, -2, 1, 2
};
//----------------------------
void C_mp4_decode_imp::IVOP(){
PROF_S(PROF_I_VOP);
move_buf_invalid = 2; // invalid, but can be cleared to make it valid
last_ref_frame_index = frame_index;
block_update_base_indx = frame_index;
MemSet(block_update_data, 0, mb_pos_end); // set all block to current frame (and clear rescue flag)
resync_marker_bits = 17;
for(int pos=0; pos<mb_pos_end; pos+=MAX_MACROBLOCKS_X-mb_xsize){
for( ; POSX(pos)<mb_xsize; ++pos){
bit_reader.Load();
//skip stuffing
while(bit_reader.Show(9) == 1){
bit_reader.Flush(9);
bit_reader.Load();
if(bit_reader.Eof())
return;
}
if(bit_reader.Eof())
return;
if(ResyncMarker()){
pos = ReSync();
if(pos>=mb_pos_end)
return;
}
//stream: 24bits available
int mcbpc = bit_reader.GetMCodedBlockPatternChrominance_i();
//stream: 15bits available
ac_pred_flag = bit_reader.Get1();
int coded_block_pattern = (bit_reader.GetCodedBlockPatternLuminance() << 2) | ((mcbpc >> 4) & 3);
if((mcbpc & 7) == INTRA_Q){
//mb_type
int q = quantizer + DQtab[bit_reader.Get(2)];
quantizer = q<1 ? 1: q>31 ? 31 : q;
}
BlockIntra(pos, coded_block_pattern);
}
}
PROF_E(PROF_I_VOP);
}
//----------------------------
static int MvChroma(int v){
v |= ((v & 0x3)!=0) << 1; //adjust dx
v |= ((v & 0x30000)!=0) << 17; //adjust dy
v >>= 1; //shift
//replace dx sign bit with old signed bit
v &= ~0x8000;
v |= (v & 0x4000) << 1;
return v;
}
//----------------------------
static const byte roundtab[16] = {
0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2
};
//----------------------------
#define sign(x) ((x)<0?-1:1)
static int MvChroma4(const int* mv){
int dx = MOVE_VECTOR_X(mv[0]) + MOVE_VECTOR_X(mv[1]) + MOVE_VECTOR_X(mv[2]) + MOVE_VECTOR_X(mv[3]);
int dy = MOVE_VECTOR_Y(mv[0]) + MOVE_VECTOR_Y(mv[1]) + MOVE_VECTOR_Y(mv[2]) + MOVE_VECTOR_Y(mv[3]);
if (dx)
dx = sign(dx) * (roundtab[Abs(dx) & 0xF] + ((Abs(dx) >> 4) <<1));
if (dy)
dy = sign(dy) * (roundtab[Abs(dy) & 0xF] + ((Abs(dy) >> 4) <<1));
return MAKE_MOVEMENT_VECTOR_PAIR(dx, dy);
}
//----------------------------
void C_mp4_decode_imp::PVOP(){
PROF_S(PROF_P_VOP);
//if no b-frames, we need only one row of mv vectors
int j;
move_buf_invalid = 0;
byte currframemap = byte(frame_index - block_update_base_indx);
last_ref_frame_index = frame_index;
resync_marker_bits = 16 + fcode_forward;
int last_frame_index = soft_idct.GetPreviousDstFrameIndex();
for(int pos=0; pos<mb_pos_end; pos+=MAX_MACROBLOCKS_X-mb_xsize){
int *mv = &mv_buf[(pos & mv_bufmask)*4];
for(;POSX(pos)<mb_xsize;++pos,mv+=4){
bit_reader.Load();
//skip stuffing
while(bit_reader.Show(10) == 1){
bit_reader.Flush( 10);
bit_reader.Load();
if(bit_reader.Eof())
return;
}
if(bit_reader.Eof())
return;
if(ResyncMarker()){
pos = ReSync();
if(pos>=mb_pos_end)
return;
}
//stream: 24bits available
if(!bit_reader.Get1()){
//coded
int mcbpc = bit_reader.GetMCodedBlockPatternChrominance_p();
int mb_type = mcbpc & 7;
mcbpc = (mcbpc >> 4) & 3;
//stream: 14bits available
block_update_data[pos] = (byte)currframemap;
if(mb_type >= INTRA){
ac_pred_flag = bit_reader.Get1();
int coded_block_pattern = (bit_reader.GetCodedBlockPatternLuminance() << 2) | mcbpc;
//stream: 7bits available
if(mb_type == INTRA_Q){
int q = quantizer + DQtab[bit_reader.Get(2)]; //DQtab[dquant]
quantizer = q<1 ? 1: (q>31 ? 31:q);
}
//stream: 5bits available
mv[3] = mv[2] = mv[1] = mv[0] = 0;
RescuePredict(pos); //Restore AC_DC values
BlockIntra(pos, coded_block_pattern);
}else{
//return;
soft_idct.BeginBlock(POSX(pos), POSY(pos));
block_update_data[pos] |= RESCUE; // set rescue needed flag
int coded_block_pattern = ((15-bit_reader.GetCodedBlockPatternLuminance()) << 2) | mcbpc;
//stream: 8bits available
// we will use mv[4],mv[5] for temporary purposes
// in the next macroblock it will be overwrite (mv incremented by 4)
switch(mb_type){
case INTER4V:
for(j = 0; j<4; j++)
mv[j] = bit_reader.GetMovementVectorPair(fcode_forward, GetPreviousMoveVector(j, pos));
mv[5] = mv[4] = MvChroma4(mv);
soft_idct.SetMotionCompensationData(mv, NULL);
break;
case INTER_Q:
{
int q = quantizer + DQtab[bit_reader.Get(2)];
quantizer = q<1 ? 1: (q>31 ? 31:q);
}
default: //INTER
mv[3] = mv[2] = mv[1] = mv[0] = bit_reader.GetMovementVectorPair(fcode_forward, GetPreviousMoveVector(0, pos));
mv[5] = mv[4] = MvChroma(mv[0]);
soft_idct.SetMotionCompensationData(mv, NULL);
break;
}
BlockInter(coded_block_pattern);
}
}else{
//not coded macroblock
int n = block_update_base_indx + (block_update_data[pos]&0x7f);
block_update_data[pos] |= RESCUE;
//copy needed or the buffer already has this block?
if(last_frame_index < n)
soft_idct.Copy16x16(POSX(pos), POSY(pos), 0);
mv[3] = mv[2] = mv[1] = mv[0] = 0;
}
}
}
PROF_E(PROF_P_VOP);
}
//----------------------------
#define vld_code \
code = ShowBits(12); \
if(code >> 9) \
code = (code >> 5) - 16 + TABLE_1; \
else if (code >> 7) \
code = (code >> 2) - 32 + TABLE_2; \
else /* if (code >= 8) but we don't care about invalid huffman codes */ \
code = code - 8 + TABLE_3; \
code = table[code]; \
FlushBits(code >> 12);
#define TABLE_1 0
#define TABLE_2 112
#define TABLE_3 112+96
#define TABLE_LMAX 112+96+120
#define TABLE_RMAX 112+96+120+64
//----------------------------
int C_mp4_decode_imp::Vld_block_mpeg(const word *table, const byte *scan, int len){
int q_add = 0;
int q_scale = quantizer << 1;
byte *q_matrix = quant_matrix[0];
const byte *bit_ptr = bit_reader.ptr;
int bitpos = bit_reader.pos, bits = bit_reader.bits;
if(table == vld_inter){
q_add = quantizer;
q_matrix += 8*8;
}
do {// event vld
int code,level;
LoadBits();
vld_code;
level = code & 31; // 0x7FFF ESCAPE -> level = 31
if(level != 31){
code >>= 5;
code &= 127;
len += code; // last|run
}else{
LoadBits();
//this value is escaped
if(!GetBits1()){
//Type 1
vld_code;
level = code & 31;
code >>= 5;
code &= 127;
len += code; // last|run
level += ((byte*)(table+TABLE_LMAX))[code]; // table_lmax[last][run]
}else
if(!GetBits1()){
//Type 2
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -