📄 mp4_decode.cpp
字号:
vld_code;
len += (code >> 5) & 127;
code &= 31;
level = code;
if (code > 11) code = 11;
if (len >= 64) code += 16; // add (last bit << 4)
len += ((byte*)(table+TABLE_RMAX))[code]; // table_rmax[last][min(11,level)]
}else{
//Type 3 - fixed length codes
code = ShowBits(20);
FlushBits(21);
level = (code << 20) >> 20; //sign extend the lower 12 bits
if (level < 0)
level = -level;
len += code >> 13; // last|run
level *= q_scale;
level += q_add;
level *= q_matrix[scan[len & 63]];
level >>= 4;
if ((code << 20) < 0)
level = -level;
block_8x8[scan[len & 63]] = (short)level;
continue;
}
}
code = scan[len & 63];
level *= q_scale;
level += q_add;
level *= q_matrix[code];
level >>= 4;
if(GetBits1())
level = -level;
block_8x8[code] = (short)level;
}while(++len < 64);
bit_reader.pos = bitpos;
bit_reader.ptr = bit_ptr;
bit_reader.bits = bits;
return len - 64;
}
//----------------------------
#define vld_write \
block_8x8[scan[len & 63]] = (short)level; \
if(++len < 64) continue; \
bit_reader.pos = bitpos; \
bit_reader.ptr = bit_ptr; \
bit_reader.bits = bits; \
return len - 64;
//----------------------------
#define vld_quant \
level *= q_scale; \
level += q_add; \
if(GetBits1()) \
level = -level;
//----------------------------
int C_mp4_decode_imp::Vld_block_mpeg4(const word *table, const byte *scan, int len){
int q_scale = quantizer << 1;
int q_add = (quantizer-1) | 1;
const byte *bit_ptr = bit_reader.ptr;
int bitpos = bit_reader.pos, bits = bit_reader.bits;
while(true){
//event vld
int code;
LoadBits();
vld_code;
int level = code&31; // 0x7FFF ESCAPE -> level = 31
if(level != 31){
code >>= 5;
code &= 127;
len += code; // last|run
vld_quant
vld_write
}else{
//this value is escaped
LoadBits();
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]
vld_quant
vld_write
}else
if(!GetBits1()){
//Type 2
vld_code;
len += (code >> 5) & 127;
code &= 31;
level = code;
if (code > 11) code = 11;
if (len >= 64) code += 16; // add (last bit << 4)
len += ((byte*)(table+TABLE_RMAX))[code]; // table_rmax[last][min(11,level)]
vld_quant
vld_write
}else{
//Type 3 - fixed length codes
code = ShowBits(21) >> 1;
FlushBits(21);
level = (code << 20) >> 20; //sign extend the lower 12 bits
level *= q_scale;
len += code >> 13; // last|run
if(level > 0)
level += q_add;
else
level -= q_add;
vld_write;
}
}
}
}
//----------------------------
static const byte def_quant_inter[64] = {
16, 17, 18, 19, 20, 21, 22, 23,
17, 18, 19, 20, 21, 22, 23, 24,
18, 19, 20, 21, 22, 23, 24, 25,
19, 20, 21, 22, 23, 24, 26, 27,
20, 21, 22, 23, 25, 26, 27, 28,
21, 22, 23, 24, 26, 27, 28, 30,
22, 23, 24, 26, 27, 28, 30, 31,
23, 24, 25, 27, 28, 30, 31, 33
}, def_quant_intra[64] = {
8, 17, 18, 19, 21, 23, 25, 27,
17, 18, 19, 21, 23, 25, 27, 28,
20, 21, 22, 23, 24, 26, 28, 30,
21, 22, 23, 24, 26, 28, 30, 32,
22, 23, 24, 26, 28, 30, 32, 35,
23, 24, 26, 28, 30, 32, 35, 38,
25, 26, 28, 30, 32, 35, 38, 41,
27, 28, 30, 32, 35, 38, 41, 45
};
//----------------------------
void C_mp4_decode_imp::ReadHeader_vol(){
bit_reader.Flush(32+1+8); // start_code + random_accessible_vol + video_object_type_indication
bit_reader.Load();
int visual_object_layer_verid;
if(bit_reader.Get1()){
//object layer identifier
visual_object_layer_verid = bit_reader.Get(4);
bit_reader.Flush(3); // video_object_layer_priority
}else{
visual_object_layer_verid = 1;
}
int aspect = bit_reader.Get(4); // aspect ratio
if(aspect == ASPECT_CUSTOM) {
bit_reader.Load();
bit_reader.Get(8); //aspect_width
bit_reader.Get(8); //aspect_height
}
if(bit_reader.Get1()){ // vol control parameters
bit_reader.Flush(2); // chroma_format
has_b_frames = !bit_reader.Get1();
if(has_b_frames) // b-frames
SetIDCTBufferCount(3);
if(bit_reader.Get1()) // vbv parameters
bit_reader.Flush(15+1+15+1+15+1+3+11+1+15+1);
}
bit_reader.Flush(2+1); // shape + marker
bit_reader.Load();
time_increment_resolution = bit_reader.Get(16);
if(time_increment_resolution <= 0)
time_increment_resolution = 1;
time_increment_bits = FindHighestBit(time_increment_resolution-1)+1;
bit_reader.Flush(1); // marker
if(bit_reader.Get1()) //fixed_vop_rate
bit_reader.Flush(time_increment_bits);
bit_reader.Flush(1); // marker
bit_reader.Load();
int width = bit_reader.Get(13); //width
bit_reader.Flush(1);
bit_reader.Load();
int height = bit_reader.Get(13); //height
bit_reader.Flush(1); // marker
interlaced = bit_reader.Get1();
/*
if (interlaced && showerror && NotSupported(MPEG4_ERROR_INTERLACE)) // interlace
return;
*/
bit_reader.Flush(1); // obmc_disable
if(width!=video_sx || height!=video_sy){
valid_vol = false;
return;
}
bit_reader.Load();
sprite_type = (E_SPRITE_TYPE)bit_reader.Get((visual_object_layer_verid==1) ? 1 : 2);
if(sprite_type == SPRITE_STATIC || sprite_type == SPRITE_GMC){
//assert(0);
//if(showerror && NotSupported(MPEG4_ERROR_GMC))
//return;
if(sprite_type != SPRITE_GMC) {
bit_reader.Flush(13+1+13+1+13+1+13+1); //width+marker+height+marker+left+marker+top+marker
bit_reader.Load();
}
//sprite warping points
bit_reader.Get(6);
//sprite warping accuracy
bit_reader.Get(2);
bit_reader.Get1(); // brightness change not supported
if(sprite_type != SPRITE_GMC)
bit_reader.Flush(1); // low_latency_sprite_enable
}
bit_reader.Load();
if(bit_reader.Get1()){ // not 8 bit
quant_precision = bit_reader.Get(4);
bit_reader.Flush(4); // bit per pixel
}else
quant_precision = 5;
bool quant_type = bit_reader.Get1();
if(quant_type){ // quant type
if(bit_reader.Get1()) // load intra
bit_reader.GetQuantMatrix(quant_matrix[0]);
else
MemCpy(quant_matrix[0], def_quant_intra, sizeof(def_quant_intra));
if(bit_reader.Get1()) // load inter
bit_reader.GetQuantMatrix(quant_matrix[1]);
else
MemCpy(quant_matrix[1], def_quant_inter, sizeof(def_quant_inter));
}
bit_reader.Load();
if(visual_object_layer_verid != 1) {
if(bit_reader.Get1()){// && showerror)// && NotSupported(MPEG4_ERROR_QPEL))
//quarter-pel
assert(0);
//return;
}
}
bit_reader.Flush(1); // complexity estimation
bit_reader.Flush(1); // resync marker disabled (?)
if(bit_reader.Get1()){
//partitioning
bit_reader.Flush(1);
assert(0);
//if(showerror)// && NotSupported(MPEG4_ERROR_PARTITIONING))
//return;
//return;
}
if(visual_object_layer_verid != 1) {
if(bit_reader.Get1()) //new pred not supported
bit_reader.Flush(2+1); // req msg type, seg type
bit_reader.Flush(1); //reduced res not supported
}
if(bit_reader.Get1()) // scalability
bit_reader.Flush(1+4+1+5+5+5+5+1); // not supported
valid_vol = true;
//showerror = 0;
}
//----------------------------
static const byte tab_intra_dc_threshold[] = {
32,
13,
15,
17,
19,
21,
23,
1,
};
//----------------------------
void C_mp4_decode_imp::ReadHeader_vop(E_FRAME_TYPE &frame_prediction_type){
bit_reader.Flush(32);
bit_reader.Load();
frame_prediction_type = (E_FRAME_TYPE)bit_reader.Get(2);
while(bit_reader.Get1())
bit_reader.Load();
bit_reader.Flush(1); //marker
bit_reader.Load();
int time_increment = bit_reader.Get(time_increment_bits);
if(time_increment_resolution){
if(frame_prediction_type != B_VOP){
time_pp = (time_increment_resolution + time_increment - last_ref_time) % time_increment_resolution;
last_ref_time = time_increment;
}else{
time_bp = (time_increment_resolution + last_ref_time - time_increment) % time_increment_resolution;
}
}
bit_reader.Flush(1); //marker
bit_reader.Load();
if(!bit_reader.Get1()){
frame_prediction_type = N_VOP;
return;
}
bool rounding = false;
if(frame_prediction_type == P_VOP || frame_prediction_type == S_VOP)
rounding = bit_reader.Get1();
soft_idct.SetRounding(rounding);
intra_dc_threshold = tab_intra_dc_threshold[bit_reader.Get(3)];
if(interlaced)
bit_reader.Flush(2); //top_field_first, alternate_scan
//if (frame_prediction_type == S_VOP && (sprite_type == SPRITE_STATIC || sprite_type == SPRITE_GMC))
//spritetrajectory(this);
quantizer = bit_reader.Get(quant_precision); // vop quant
bit_reader.Load();
if(frame_prediction_type != I_VOP)
fcode_forward = bit_reader.Get(3);
if(frame_prediction_type == B_VOP)
fcode_backward = bit_reader.Get(3);
}
//----------------------------
bool C_mp4_decode_imp::ReadFrameHeaders(E_FRAME_TYPE &frame_prediction_type){
while(true){
bit_reader.ByteAlign();
bit_reader.Load();
if(bit_reader.Eof())
return false;
int code = bit_reader.Show(32);
if((code & ~VOL_START_CODE_MASK) == VOL_START_CODE){
ReadHeader_vol();
}else
if(code == VOP_START_CODE){
ReadHeader_vop(frame_prediction_type);
return true;
}else
bit_reader.Flush(8);
}
}
//----------------------------
void C_mp4_decode_imp::BlockDirect(int pos, int dmv, int coded_block_pattern){
int fmv[6];
int bmv[6];
int *mv = &mv_buf[pos*4];
for(int j=0; j<4; ++j,++mv){
int dx, dy, v;
v = trb * MOVE_VECTOR_X(*mv);
if(v<0) //best code for (v<0)
--v;
dx = v >> 8;
if(dx<0) ++dx;
v = trb * MOVE_VECTOR_Y(*mv);
if(v<0) //best code for (v<0)
--v;
dy = v >> 8;
if(dy<0) ++dy;
dx += MOVE_VECTOR_X(dmv);
dy += MOVE_VECTOR_Y(dmv);
fmv[j] = MAKE_MOVEMENT_VECTOR_PAIR(dx, dy);
if(dmv & 0xffff)
dx -= MOVE_VECTOR_X(*mv);
else{
v = trb_trd * MOVE_VECTOR_X(*mv);
if(v<0) //best code for (v<0)
--v;
dx = v >> 8;
if(dx<0) ++dx;
}
if(dmv & 0xffff0000)
dy -= MOVE_VECTOR_Y(*mv);
else{
v = trb_trd * MOVE_VECTOR_Y(*mv);
if(v
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -