📄 mp4_decode.cpp
字号:
0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,
0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,
0x4021,0x4021,0x4021,0x4021,0x4021,0x4021,0x4021,0x4021,
0x4003,0x4003,0x4003,0x4003,0x4003,0x4003,0x4003,0x4003,
0xa012,0xa011,0x99c1,0x99c1,0x99a1,0x99a1,0x9981,0x9981,
0x9961,0x9961,0x9941,0x9941,0x9822,0x9822,0x9804,0x9804,
0x9181,0x9181,0x9161,0x9161,0x90e2,0x90e2,0x90c2,0x90c2,
0x90a2,0x90a2,0x9063,0x9063,0x9043,0x9043,0x9026,0x9026,
0x9025,0x9025,0x9010,0x9010,0x9082,0x9082,0x900f,0x900f,
0x900e,0x900e,0x900d,0x900d,0x8901,0x8901,0x8901,0x8901,
0x88e1,0x88e1,0x88e1,0x88e1,0x88c1,0x88c1,0x88c1,0x88c1,
0x8803,0x8803,0x8803,0x8803,0x8141,0x8141,0x8141,0x8141,
0x8121,0x8121,0x8121,0x8121,0x8101,0x8101,0x8101,0x8101,
0x8921,0x8921,0x8921,0x8921,0x8062,0x8062,0x8062,0x8062,
0x8024,0x8024,0x8024,0x8024,0x800c,0x800c,0x800c,0x800c,
0x800b,0x800b,0x800b,0x800b,0x800a,0x800a,0x800a,0x800a,
0xb807,0xb807,0xb806,0xb806,0xb016,0xb016,0xb015,0xb015,
0xa842,0xa842,0xa842,0xa842,0xa823,0xa823,0xa823,0xa823,
0xa805,0xa805,0xa805,0xa805,0xa1a1,0xa1a1,0xa1a1,0xa1a1,
0xa0a3,0xa0a3,0xa0a3,0xa0a3,0xa102,0xa102,0xa102,0xa102,
0xa083,0xa083,0xa083,0xa083,0xa064,0xa064,0xa064,0xa064,
0xa044,0xa044,0xa044,0xa044,0xa027,0xa027,0xa027,0xa027,
0xa014,0xa014,0xa014,0xa014,0xa013,0xa013,0xa013,0xa013,
0xb017,0xb017,0xb018,0xb018,0xb028,0xb028,0xb122,0xb122,
0xb862,0xb862,0xb882,0xb882,0xb9e1,0xb9e1,0xba01,0xba01,
0xc019,0xc01a,0xc01b,0xc029,0xc0c3,0xc02a,0xc045,0xc0e3,
0xc1c1,0xc808,0xc8a2,0xc8c2,0xca21,0xca41,0xca61,0xca81,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x0a1b,0x0405,0x0303,0x0303,0x0202,0x0101,0x0101,0x0001,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0308,0x0202,0x0202,0x0102,0x0101,0x0101,0x0101,0x0101,
0x0101,0x0101,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0f02,0x080a,0x0304,0x0202,0x0202,0x0102,0x0101,0x0101,
0x1501,0x0207,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101
};
//----------------------------
//prediction
static const word vld_inter[112+96+120+64+16] = {
0x7901,0x78e1,0x78c1,0x78a1,0x7181,0x7161,0x7141,0x7004,
0x6881,0x6881,0x6861,0x6861,0x6841,0x6841,0x6821,0x6821,
0x6121,0x6121,0x6101,0x6101,0x60e1,0x60e1,0x60c1,0x60c1,
0x6022,0x6022,0x6003,0x6003,0x50a1,0x50a1,0x50a1,0x50a1,
0x5081,0x5081,0x5081,0x5081,0x5061,0x5061,0x5061,0x5061,
0x4801,0x4801,0x4801,0x4801,0x4801,0x4801,0x4801,0x4801,
0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,
0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,
0x4041,0x4041,0x4041,0x4041,0x4041,0x4041,0x4041,0x4041,
0x4002,0x4002,0x4002,0x4002,0x4002,0x4002,0x4002,0x4002,
0xa009,0xa008,0x9b01,0x9b01,0x9ae1,0x9ae1,0x9ac1,0x9ac1,
0x9aa1,0x9aa1,0x9a81,0x9a81,0x9a61,0x9a61,0x9a41,0x9a41,
0x9a21,0x9a21,0x9802,0x9802,0x92c1,0x92c1,0x92a1,0x92a1,
0x9281,0x9281,0x9261,0x9261,0x9241,0x9241,0x9221,0x9221,
0x9201,0x9201,0x91e1,0x91e1,0x9082,0x9082,0x9062,0x9062,
0x9007,0x9007,0x9006,0x9006,0x8a01,0x8a01,0x8a01,0x8a01,
0x89e1,0x89e1,0x89e1,0x89e1,0x89c1,0x89c1,0x89c1,0x89c1,
0x89a1,0x89a1,0x89a1,0x89a1,0x8981,0x8981,0x8981,0x8981,
0x8961,0x8961,0x8961,0x8961,0x8941,0x8941,0x8941,0x8941,
0x8921,0x8921,0x8921,0x8921,0x81c1,0x81c1,0x81c1,0x81c1,
0x81a1,0x81a1,0x81a1,0x81a1,0x8042,0x8042,0x8042,0x8042,
0x8023,0x8023,0x8023,0x8023,0x8005,0x8005,0x8005,0x8005,
0xb822,0xb822,0xb803,0xb803,0xb00b,0xb00b,0xb00a,0xb00a,
0xab81,0xab81,0xab81,0xab81,0xab61,0xab61,0xab61,0xab61,
0xab41,0xab41,0xab41,0xab41,0xab21,0xab21,0xab21,0xab21,
0xa122,0xa122,0xa122,0xa122,0xa102,0xa102,0xa102,0xa102,
0xa0e2,0xa0e2,0xa0e2,0xa0e2,0xa0c2,0xa0c2,0xa0c2,0xa0c2,
0xa0a2,0xa0a2,0xa0a2,0xa0a2,0xa063,0xa063,0xa063,0xa063,
0xa043,0xa043,0xa043,0xa043,0xa024,0xa024,0xa024,0xa024,
0xb00c,0xb00c,0xb025,0xb025,0xb2e1,0xb2e1,0xb301,0xb301,
0xbba1,0xbba1,0xbbc1,0xbbc1,0xbbe1,0xbbe1,0xbc01,0xbc01,
0xc026,0xc044,0xc083,0xc0a3,0xc0c3,0xc142,0xc321,0xc341,
0xcc21,0xcc41,0xcc61,0xcc81,0xcca1,0xccc1,0xcce1,0xcd01,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
0x060c,0x0304,0x0303,0x0203,0x0202,0x0102,0x0101,0x0101,
0x0101,0x0101,0x0101,0x0101,0x0101,0x0001,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x0203,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,
0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,
0x0101,0x0101,0x0101,0x0101,0x0001,0x0000,0x0000,0x0000,
0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
0x1b02,0x070b,0x0203,0x0102,0x0101,0x0101,0x0101,0x0101,
0x2901,0x0102,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101
};
//----------------------------
void C_mp4_decode_imp::RescuePredict(int pos){
int lumpos = 2*POSX(pos) + (POSY(pos) << (MB_X2+2));
if(pos>=MAX_MACROBLOCKS_X+1 && (block_update_data[pos-MAX_MACROBLOCKS_X-1]&RESCUE)){
//rescue -A- DC value
dc_lum[(lumpos-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
dc_chr[0][(pos-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
dc_chr[1][(pos-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
}
//left
if(pos>=1 && (block_update_data[pos-1]&RESCUE)){
// rescue -B- DC values
dc_lum[(lumpos) & DC_LUM_MASK] = 1024;
dc_lum[(lumpos+MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
dc_chr[0][pos & DC_CHR_MASK] = 1024;
dc_chr[1][pos & DC_CHR_MASK] = 1024;
if(ac_pred_flag){
//rescue -B- AC values
Clear32(ac_left_lum);
Clear32(ac_left_chr);
}
}
//top
if(pos>=MAX_MACROBLOCKS_X && (block_update_data[pos-MAX_MACROBLOCKS_X]&RESCUE)){
// rescue -C- DC values
dc_lum[(lumpos+1-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
dc_lum[(lumpos+2-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
dc_chr[0][(pos+1-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
dc_chr[1][(pos+1-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
if(ac_pred_flag){
//rescue -C- AC values
Clear32(ac_top_lum[lumpos & (MAX_MACROBLOCKS_X*2-1)]);
Clear32(ac_top_chr[pos & (MAX_MACROBLOCKS_X-1)]);
}
}
}
//----------------------------
bool C_mp4_decode_imp::UpdateCount(){
int *mv;
if(soft_idct.GetBufferCount() >= 3){
if(mv_bufmask != -1)
move_buf_invalid = 1;
mv_bufmask = -1; // full size mv buffer needed
if(!_mv_buf){
int size = 32 + 4*sizeof(int) * (mb_pos_end+1); // add one extra block for left border
_mv_buf = new int[size/4];
if(!_mv_buf)
return false;
MemSet(_mv_buf,0,size);
}
mv = _mv_buf;
}else{
move_buf_invalid = 1;
mv_bufmask = MAX_MACROBLOCKS_X-1; //only one row of mv buffer needed
mv = _mv_bufrow;
}
mv_buf = (int*)(((int)mv + 31 + 4*sizeof(int)) & ~31);
return true;
}
//----------------------------
bool C_mp4_decode_imp::Mp4_vop(const byte *strm, bool drop_b_frames, E_FRAME_TYPE frame_prediction_type){
resyncpos = 0;
switch(frame_prediction_type){
case N_VOP:
if(packed_b_size){
bit_reader.Init(packed_b_frame.Begin(), packed_b_size);
packed_b_size = 0;
if(ReadFrameHeaders(frame_prediction_type)){
bool ok = Mp4_vop(packed_b_frame.Begin(), drop_b_frames, frame_prediction_type);
if(ok)
return true;
}
}
return (frame_index > 0);
case P_VOP:
//P (predicted) frames are predicted from the most recently reconstructed I or P frame
//each macroblock in a P frame can either come with a vector and difference DCT coefficients for a close match in the last I or P,
// or it can just be "intra" coded if there was no good match
if(frame_index < 1)
return false;
//flow...
case I_VOP:
//I (intra) frames are coded as individual still images (JPG)
//I/P-frames are the "reference" frames
// they are decode into refframe
// P-frames depend on last refenrence frame: refframe^1
refframe ^= 1;
if(has_b_frames)
++last_bframe;
int frame_to_show;
if(!has_b_frames || frame_index==0)
frame_to_show = refframe; // show this refframe
else
frame_to_show = refframe ^ 1; // show last refframe
if(frame_prediction_type == I_VOP) {
soft_idct.FrameStart(frame_index, refframe, -1, -1, frame_to_show);
IVOP();
}else{
soft_idct.FrameStart(frame_index, refframe, refframe ^ 1, -1, frame_to_show);
PVOP();
}
break;
case B_VOP:
//B (bidirectional) frames are predicted from the closest two I or P frames, one in the past and one in the future
if(frame_index < 2 || move_buf_invalid)
return false;
last_bframe = 0;
if(drop_b_frames){
//ignore b-frames
return false;
}
if(move_buf_invalid == 2){
move_buf_invalid = 0;
MemSet(mv_buf, 0, 4*sizeof(int)*mb_pos_end);
}
assert(has_b_frames);
/*
if(soft_idct.GetBufferCount()<3){
SetIDCTBufferCount(3);
if(move_buf_invalid)
return false;
}
*/
/*
//save this b-frame if there was already a packed one
if(frame_to_show >= 0){
//rewind
bit_reader.Rewind(strm);
return true;
}
*/
soft_idct.FrameStart(-frame_index, 2, refframe,refframe ^ 1, 2);
if(time_pp){
int TRB = time_pp - time_bp;
trb = (TRB<<8) / time_pp;
trb_trd = ((TRB - time_pp)<<8) / time_pp;
}else{
trb = 0;
trb_trd = 0;
}
BVOP();
break;
default:
return false;
}
frame_index++;
//make sure that data in block_update_data don't overflow
const int MAX_D = 128;
if((frame_index - block_update_base_indx) >= MAX_D){
for(int pos=0; pos<mb_pos_end; pos+=MAX_MACROBLOCKS_X-mb_xsize){
for(; POSX(pos)<mb_xsize; ++pos){
byte i = block_update_data[pos];
byte r = i&RESCUE;
i &= 0x7f;
if(i >= (MAX_D-8))
i -= (MAX_D-8);
else
i = 0;
block_update_data[pos] = i|r;
}
}
block_update_base_indx += MAX_D-8;
}
return true;
}
//----------------------------
bool C_mp4_decode_imp::Frame(const byte* ptr, int len, bool drop_b_frames){
E_FRAME_TYPE frame_prediction_type;
if(!len){
//null frame, return last rendered frame
return true;
}
PROF_S(PROF_DECODE);
bit_reader.Init(ptr, len);
if(!ReadFrameHeaders(frame_prediction_type) || !valid_vol)
return false; //invalid header or no vol information
bool ok = Mp4_vop(ptr, drop_b_frames, frame_prediction_type);
PROF_E(PROF_DECODE);
#if defined _DEBUG && 0
//mark frame type
if(ok){
byte *y, *u, *v;
if(soft_idct.GetBuffer(y, u, v)){
dword pi = soft_idct.GetBufferPitch();
for(int i=0; i<3; i++){
byte *d = !i ? y : i==1 ? u : v;
dword p = pi;
dword s = 16;
if(i){
p /= 2;
s /= 2;
d += p*4*4;
}else
d += p*8*4;
byte val;
switch(frame_prediction_type){
case I_VOP: val = !i ? 0x00 : i==1 ? 0x00 : 0xff; break;
case P_VOP: val = !i ? 0x80 : i==1 ? 0x80 : 0x80; break;
case B_VOP: val = !i ? 0x80 : i==1 ? 0xff : 0x00; break;
default: val = !i ? 0x0 : i==1 ? 0x80 : 0x80;
}
for(int y=s; y--; ){
for(int x=s; x--; ){
d[x] = val;
}
d += p;
}
}
}
}
#endif
if(ok){
//check for packed b-frame
const byte *pos = bit_reader.ptr - 4 + ((bit_reader.pos+7) >> 3);
len -= (pos - ptr);
if(len > 4){
if(!has_b_frames){
has_b_frames = true;
SetIDCTBufferCount(3);
}
//save packed b-frame
if(packed_b_frame.Size() < len)
packed_b_frame.Resize((len+8+0x1fff) & ~0x1fff);
packed_b_size = len;
MemCpy(packed_b_frame.Begin(), pos, len);
}
}
return ok;
}
//----------------------------
void C_mp4_decode_imp::Ac_recon(int block_num, int pos, int predict_dir){
int i;
short *ac_top;
short *ac_left;
if(block_num < 4){
//Y
ac_top = ac_top_lum[pos & (MAX_MACROBLOCKS_X*2-1)];
ac_left = ac_left_lum[(pos >> (MB_X2+1)) & 1];
i = MAX_MACROBLOCKS_X*2-1; //stride-1
}else{
//UV
ac_top = ac_top_chr[pos & (MAX_MACROBLOCKS_X-1)][block_num & 1];
ac_left = ac_left_chr[block_num & 1];
i = MAX_MACROBLOCKS_X-1; //stride-1
}
if(ac_pred_flag){
if(predict_dir == 1){
//TOP
if(pos > i){
for(i = 1; i < 8; i++)
block_8x8[i] = (short)(block_8x8[i] + ac_top[i]);
}
}else{
//LEFT
if(pos & i){
for(i = 1; i < 8; i++)
block_8x8[i<<3] = (short)(block_8x8[i<<3] + ac_left[i]);
}
}
}
for(i = 1; i < 8; i++){
ac_top[i] = block_8x8[i];
ac_left[i] = block_8x8[i<<3];
}
}
//----------------------------
short *C_mp4_decode_imp::Dc_recon(int block_num, int pos, int dc_scaler, int &predict_dir){
short *dc;
int Fb = 1024;
int Fc = 1024;
if(block_num < 4){
//Y
dc = dc_lum;
if(pos >= MAX_MACROBLOCKS_X*2){
Fb = dc[(pos-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK];
Fc = dc[(pos+1-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK];
}
dc += pos & DC_LUM_MASK;
}else{
//UV
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -