📄 mp4_decode.cpp
字号:
static const short move_vector_table_0[14] = {
_M(3,4),_M(-3,4),_M(2,3),_M(2,3),_M(-2,3),_M(-2,3),_M(1,2),_M(1,2),
_M(1,2),_M(1,2),_M(-1,2),_M(-1,2),_M(-1,2),_M(-1,2),
}, move_vector_table_1[96] = {
_M(12,10),_M(-12,10),
_M(11,10),_M(-11,10),_M(10,9),_M(10,9),_M(-10,9),_M(-10,9),_M(9,9),_M(9,9),
_M(-9,9),_M(-9,9),_M(8,9),_M(8,9),_M(-8,9),_M(-8,9),_M(7,7),_M(7,7),
_M(7,7),_M(7,7),_M(7,7),_M(7,7),_M(7,7),_M(7,7),_M(-7,7),_M(-7,7),
_M(-7,7),_M(-7,7),_M(-7,7),_M(-7,7),_M(-7,7),_M(-7,7),_M(6,7),_M(6,7),
_M(6,7),_M(6,7),_M(6,7),_M(6,7),_M(6,7),_M(6,7),_M(-6,7),_M(-6,7),
_M(-6,7),_M(-6,7),_M(-6,7),_M(-6,7),_M(-6,7),_M(-6,7),_M(5,7),_M(5,7),
_M(5,7),_M(5,7),_M(5,7),_M(5,7),_M(5,7),_M(5,7),_M(-5,7),_M(-5,7),
_M(-5,7),_M(-5,7),_M(-5,7),_M(-5,7),_M(-5,7),_M(-5,7),_M(4,6),_M(4,6),
_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),
_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(-4,6),_M(-4,6),
_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),
_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6)
}, move_vector_table_2[124] = {
_M(32,12),_M(-32,12),
_M(31,12),_M(-31,12),_M(30,11),_M(30,11),_M(-30,11),_M(-30,11),_M(29,11),_M(29,11),
_M(-29,11),_M(-29,11),_M(28,11),_M(28,11),_M(-28,11),_M(-28,11),_M(27,11),_M(27,11),
_M(-27,11),_M(-27,11),_M(26,11),_M(26,11),_M(-26,11),_M(-26,11),_M(25,11),_M(25,11),
_M(-25,11),_M(-25,11),_M(24,10),_M(24,10),_M(24,10),_M(24,10),_M(-24,10),_M(-24,10),
_M(-24,10),_M(-24,10),_M(23,10),_M(23,10),_M(23,10),_M(23,10),_M(-23,10),_M(-23,10),
_M(-23,10),_M(-23,10),_M(22,10),_M(22,10),_M(22,10),_M(22,10),_M(-22,10),_M(-22,10),
_M(-22,10),_M(-22,10),_M(21,10),_M(21,10),_M(21,10),_M(21,10),_M(-21,10),_M(-21,10),
_M(-21,10),_M(-21,10),_M(20,10),_M(20,10),_M(20,10),_M(20,10),_M(-20,10),_M(-20,10),
_M(-20,10),_M(-20,10),_M(19,10),_M(19,10),_M(19,10),_M(19,10),_M(-19,10),_M(-19,10),
_M(-19,10),_M(-19,10),_M(18,10),_M(18,10),_M(18,10),_M(18,10),_M(-18,10),_M(-18,10),
_M(-18,10),_M(-18,10),_M(17,10),_M(17,10),_M(17,10),_M(17,10),_M(-17,10),_M(-17,10),
_M(-17,10),_M(-17,10),_M(16,10),_M(16,10),_M(16,10),_M(16,10),_M(-16,10),_M(-16,10),
_M(-16,10),_M(-16,10),_M(15,10),_M(15,10),_M(15,10),_M(15,10),_M(-15,10),_M(-15,10),
_M(-15,10),_M(-15,10),_M(14,10),_M(14,10),_M(14,10),_M(14,10),_M(-14,10),_M(-14,10),
_M(-14,10),_M(-14,10),_M(13,10),_M(13,10),_M(13,10),_M(13,10),_M(-13,10),_M(-13,10),
_M(-13,10),_M(-13,10)
};
//----------------------------
int S_bit_reader::GetMoveData(int fcode){
Load();
if(Get1()){
//no movement (coded in 1 bit)
return 0;
}
int code = Show(12);
if(code >= 512)
code = move_vector_table_0[(code >> 8) - 2];
else
if(code >= 128)
code = move_vector_table_1[(code >> 2) - 32];
else
code = move_vector_table_2[code-4];
Flush(code & 255);
code >>= 8;
if(fcode){
code <<= fcode;
int res = Get(fcode);
res -= (1 << fcode) - 1;
if(code < 0)
res = -res;
code += res;
}
return code;
}
//----------------------------
int S_bit_reader::GetMovementVectorPair(int fcode, int prev_vector_pair){
--fcode;
int mv_x = GetMoveData(fcode);
int mv_y = GetMoveData(fcode);
int range = 1 << (fcode+6);
int high = (range/2) - 1;
int low = -(range/2);
mv_x += MOVE_VECTOR_X(prev_vector_pair);
if(mv_x < low)
mv_x += range;
if(mv_x > high)
mv_x -= range;
mv_y += MOVE_VECTOR_Y(prev_vector_pair);
if(mv_y < low)
mv_y += range;
if(mv_y > high)
mv_y -= range;
return MAKE_MOVEMENT_VECTOR_PAIR(mv_x, mv_y);
}
//----------------------------
int S_bit_reader::GetDCsizeLum(){
int code = Show(11);
for(int i=0; i<8; i++){
if((code >> i)==1){
Flush(11-i);
return 12-i;
}
}
code >>= 8;
if(code == 1){
Flush(3);
return 4;
}
if(code == 2){
Flush(3);
return 3;
}
if(code == 3){
Flush(3);
return 0;
}
code >>=1;
if(code == 2){
Flush(2);
return 2;
}
if(code == 3){
Flush(2);
return 1;
}
return 0;
}
//----------------------------
int S_bit_reader::GetDCsizeChr(){
int i,code = Show(12);
for (i=0;i<10;i++){
if ((code >> i)==1) {
Flush(12-i);
return 12-i;
}
}
return 3 - Get(2);
}
//----------------------------
int S_bit_reader::GetDCdiff(int dct_dc_size){
int code = Show(32); //we need only dct_dc_size bits (but in the higher bits)
int adj = 0;
Flush(dct_dc_size);
if(code >= 0)
adj = (-1 << dct_dc_size) + 1;
return adj + ((dword)code >> (32-dct_dc_size));
}
//----------------------------
//----------------------------
//----------------------------
class C_mp4_decode_imp: public C_mp4_decode{
enum{ RESCUE = 0x80 };
enum{ VOL_START_CODE_MASK = 0x0f };
enum{
VOL_START_CODE = 0x120,
VOP_START_CODE = 0x1b6
};
enum{
ASPECT_SQUARE = 1,
ASPECT_625TYPE_43 = 2,
ASPECT_525TYPE_43 =3,
ASPECT_625TYPE_169 = 8,
ASPECT_525TYPE_169 = 9,
ASPECT_CUSTOM = 15,
};
//----------------------------
enum E_FRAME_TYPE{
I_VOP,
P_VOP,
B_VOP,
S_VOP,
N_VOP,
};
//----------------------------
enum{
INTER = 0, //prediction
INTER_Q = 1,
INTER4V = 2,
INTRA = 3, //no prediction
INTRA_Q = 4,
};
//----------------------------
enum E_SPRITE_TYPE{
SPRITE_NO,
SPRITE_STATIC,
SPRITE_GMC,
};
//----------------------------
enum{
DIRECT = 0,
INTERPOLATE = 1,
BACKWARD = 2,
FORWARD = 3,
};
//----------------------------
#ifdef PROFILE
C_profiler *prof;
#endif
C_softidct soft_idct;
S_bit_reader bit_reader;
bool has_b_frames;
int quant_precision; //in how many bits is quantizier encoded
dword video_sx, video_sy;
bool valid_vol; //VOL information was successfully read
bool interlaced;
bool ac_pred_flag;
int frame_index;
int last_ref_frame_index; //index of last I or P frame
//frame index, when the last time particular macro-block changed
// (need to add 'block_update_base_indx' for getting actual index)
// also contains RESCUE flag
byte block_update_data[MAX_MACROBLOCKS_X*MAX_MACROBLOCKS_Y];
int mb_pos_end; //index of end of macro-block table 'block_update_data'
int block_update_base_indx; //base frame index for above (typically set to last 'P' frame's index)
int mb_xsize, mb_ysize; //number of macroblocks for width/height
E_SPRITE_TYPE sprite_type;
int quantizer;
int intra_dc_threshold;
int fcode_forward, fcode_backward;
int resync_marker_bits;
short _block[64+16/sizeof(short)];
short *block_8x8; //16-byte aligned, used for 8x8 block computations (intra, inter)
int time_increment_resolution; //video framerate * 1000
int last_ref_time; //last time of reference frame (I or P, not B)
// b-frame
int time_pp, time_bp;
int last_bframe;
int trb, trb_trd; //8.8 fixed-point
//----------------------------
int resyncpos;
int time_increment_bits;
bool quant_type; //type of quantizied - mpeg (true) or mpeg4 (false)
// motion compensation buffer
int *mv_buf; //32bytes aligned
int* _mv_buf;
int mv_bufmask;
int move_buf_invalid;
//packed B frame
C_buffer<byte> packed_b_frame;
dword packed_b_size;
int refframe;
byte quant_matrix[2][8*8]; // [intra / inter]
short dc_lum[4*MAX_MACROBLOCKS_X*2]; //[4][double width row]
short ac_left_lum[2][8]; //[lower/upper][8]
short ac_top_lum[2*MAX_MACROBLOCKS_X][8]; //[double witdh row][8]
short dc_chr[2][2*MAX_MACROBLOCKS_X]; //[U/V][2][normal width row]
short ac_left_chr[2][8]; //[U/V][8]
short ac_top_chr[MAX_MACROBLOCKS_X][2][8];//[normal width row][U/V][8]
int _mv_bufrow[4*(MAX_MACROBLOCKS_X+1)+32/sizeof(int)]; // add one extra block for left border + 32align
//----------------------------
void RescuePredict(int pos);
//----------------------------
// Read all frame's headers (VOL, VOP). Return true if VOP was found and read.
bool ReadFrameHeaders(E_FRAME_TYPE &frame_prediction_type);
//----------------------------
// Read volume header.
void ReadHeader_vol();
//----------------------------
// Read picture header.
void ReadHeader_vop(E_FRAME_TYPE &frame_prediction_type);
//----------------------------
int ReSync();
//----------------------------
bool ResyncMarker();
//----------------------------
int GetPreviousMoveVector(int block_num, int pos);
//----------------------------
int Vld_block_mpeg(const word *table, const byte *scan, int len);
int Vld_block_mpeg4(const word *table, const byte *scan, int len);
//----------------------------
short *Dc_recon(int block_num, int pos, int dc_scaler, int &predict_dir);
void Ac_recon(int block_num, int pos, int predict_dir);
//----------------------------
// Decode block with no prediction.
void BlockIntra(int pos, int coded_block_pattern);
//----------------------------
// Decode block with prediction.
void BlockInter(int coded_block_pattern);
//----------------------------
void BlockDirect(int pos, int dmv, int coded_block_pattern);
//----------------------------
void IVOP();
void PVOP();
void BVOP();
//----------------------------
bool Frame(const byte *strm, int len, bool drop_b_frames);
public:
//----------------------------
bool SetIDCTBufferCount(int count);
bool UpdateCount();
bool Init();
bool Mp4_vop(const byte *strm, bool drop_b_frames, E_FRAME_TYPE frame_prediction_type);
virtual bool Process(const byte *packet, dword len, bool drop_b_frames, S_yuv_image &out);
//----------------------------
C_mp4_decode_imp(dword sx, dword sy, void *profiler);
~C_mp4_decode_imp(){
delete[] _mv_buf;
}
};
//----------------------------
bool C_mp4_decode_imp::Process(const byte *packet, dword len, bool drop_b_frames, S_yuv_image &out){
out.type = 0;
#ifdef PROFILE
if(frame_index==10)
prof->ResetAverage();
#endif
/*
if(frame_to_show!=-1){ // pending frame?
SendData(out);
frame_to_show = -1;
assert(out.type);
return true;
}
*/
// if(has_b_frames && FrameTime>0 && RefTime >= FrameTime)
// RefTime -= FrameTime;
if(!Frame(packet, len, drop_b_frames))
return false;
//send to display
if(!soft_idct.GetBuffer(out.y, out.u, out.v)){
assert(0);
return false;
}
out.pitch = soft_idct.GetBufferPitch();
out.type = 1;
return true;
}
//----------------------------
bool C_mp4_decode_imp::SetIDCTBufferCount(int c){
if(!soft_idct.SetBufferCount(c))
return false;
return UpdateCount();
}
//----------------------------
// msb..lsb
// 4bit flushbits, 1bit last, 6bit run, 5bit level
//no prediction
static const word vld_intra[112+96+120+64+16] = {
0x7881,0x7861,0x70c1,0x78a1,0x70e1,0x7042,0x7023,0x7009,
0x6802,0x6802,0x60a1,0x60a1,0x6841,0x6841,0x6821,0x6821,
0x6081,0x6081,0x6061,0x6061,0x6008,0x6008,0x6007,0x6007,
0x6022,0x6022,0x6006,0x6006,0x5041,0x5041,0x5041,0x5041,
0x5005,0x5005,0x5005,0x5005,0x5004,0x5004,0x5004,0x5004,
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,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -