decoder.cpp
来自「gaca源码」· C++ 代码 · 共 1,447 行 · 第 1/4 页
CPP
1,447 行
MACROBLOCK *mb = &mbs[y * mb_width + x];
MACROBLOCK *last_mb = &last_mbs[y * mb_width + x];
const int fcode_max = (fcode_forward>fcode_backward) ? fcode_forward : fcode_backward;
if(bs->check_resync_marker(fcode_max - 1)){
dword intra_dc_threshold; /* fake variable */
int bound = read_video_packet_header(bs, fcode_max - 1, &quant, &fcode_forward, &fcode_backward, (int*)&intra_dc_threshold);
x = bound % mb_width;
y = bound / mb_width;
//reset predicted macroblocks
p_fmv = p_bmv = zeromv;
}
mv = mb->b_mvs[0] = mb->b_mvs[1] = mb->b_mvs[2] = mb->b_mvs[3] = mb->mvs[0] = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = zeromv;
mb->quant = quant;
/*
* skip if the co-located P_VOP macroblock is not coded
* if not codec in co-located S_VOP macroblock is _not_
* automatically skipped
*/
if(last_mb->mode == MODE_NOT_CODED){
mb->cbp = 0;
mb->mode = MODE_FORWARD;
DecodeInterMacroBlock(mb, x, y, mb->cbp, bs, 0, 0, 1);
continue;
}
if(!bs->GetBit()){
//modb=='0'
const byte modb2 = bs->GetBit();
mb->mode = get_mbtype(bs);
if (!modb2) /* modb=='00' */
mb->cbp = bs->GetBits(6);
else
mb->cbp = 0;
if (mb->mode && mb->cbp) {
quant += get_dbquant(bs);
if (quant > 31)
quant = 31;
else if (quant < 1)
quant = 1;
}
mb->quant = quant;
if(interlacing){
if (mb->cbp) {
mb->field_dct = bs->GetBit();
DPRINTF(XVID_DEBUG_MB,"decp: field_dct: %i\n", mb->field_dct);
}
if (mb->mode) {
mb->field_pred = bs->GetBit();
DPRINTF(XVID_DEBUG_MB, "decp: field_pred: %i\n", mb->field_pred);
if (mb->field_pred) {
mb->field_for_top = bs->GetBit();
DPRINTF(XVID_DEBUG_MB,"decp: field_for_top: %i\n", mb->field_for_top);
mb->field_for_bot = bs->GetBit();
DPRINTF(XVID_DEBUG_MB,"decp: field_for_bot: %i\n", mb->field_for_bot);
}
}
}
}else{
mb->mode = MODE_DIRECT_NONE_MV;
mb->cbp = 0;
}
switch(mb->mode){
case MODE_DIRECT:
get_b_motion_vector(bs, &mv, 1, zeromv);
//flow...
case MODE_DIRECT_NONE_MV:
for(i=0; i<4; i++){
mb->mvs[i].x = (int)((int(TRB) * last_mb->mvs[i].x) / (int)TRD + mv.x);
mb->b_mvs[i].x = (int) ((mv.x == 0) ?
(int(TRB - TRD) * last_mb->mvs[i].x) / (int)TRD :
mb->mvs[i].x - last_mb->mvs[i].x);
mb->mvs[i].y = (int) ((int(TRB) * last_mb->mvs[i].y) / (int)TRD + mv.y);
mb->b_mvs[i].y = (int) ((mv.y == 0) ?
(int(TRB - TRD) * last_mb->mvs[i].y) / int(TRD) :
int(mb->mvs[i].y - last_mb->mvs[i].y));
}
BFrameInterpolateMBInter(refn[1], refn[0], mb, x, y, bs, 1);
break;
case MODE_INTERPOLATE:
get_b_motion_vector(bs, &mb->mvs[0], fcode_forward, p_fmv);
p_fmv = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0];
get_b_motion_vector(bs, &mb->b_mvs[0], fcode_backward, p_bmv);
p_bmv = mb->b_mvs[1] = mb->b_mvs[2] = mb->b_mvs[3] = mb->b_mvs[0];
BFrameInterpolateMBInter(refn[1], refn[0], mb, x, y, bs, 0);
break;
case MODE_BACKWARD:
get_b_motion_vector(bs, &mb->mvs[0], fcode_backward, p_bmv);
p_bmv = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0];
DecodeInterMacroBlock(mb, x, y, mb->cbp, bs, 0, 0, 0);
break;
case MODE_FORWARD:
get_b_motion_vector(bs, &mb->mvs[0], fcode_forward, p_fmv);
p_fmv = mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0];
DecodeInterMacroBlock(mb, x, y, mb->cbp, bs, 0, 0, 1);
break;
default:
DPRINTF(XVID_DEBUG_ERROR,"Not supported B-frame mb_type = %i\n", mb->mode);
}
}
}
PROF_E(PROF_FRM_B);
}
//----------------------------
/* perform post processing if necessary, and output the image */
/*
void S_decoder::Output(IMAGE *img, xvid_dec_frame_t *frame, xvid_dec_stats_t *stats, int coding_type){
//image_output(img, width, height, edged_width, (byte**)frame->output.plane, (unsigned int*)frame->output.stride, frame->output.csp, interlacing);
yv12_to_bgr((byte*)frame->output.plane, frame->output.stride, img->y, img->u, img->v, edged_width, edged_width/2, width, height, false);
if(stats){
stats->type = coding2type(coding_type);
stats->data.vop.time_base = (int)time_base;
stats->data.vop.time_increment = 0; //XXX: todo
}
}
*/
//----------------------------
int S_decoder::Decode(xvid_dec_frame_t *frame, xvid_dec_stats_t *stats){
PROF_S(PROF_DECODE);
Bitstream bs;
bool rounding;
bool reduced_resolution;
dword quant;
dword fcode_forward;
dword fcode_backward;
dword intra_dc_threshold;
WARPPOINTS gmc_warp;
int coding_type;
frame->img_out = NULL;
if(XVID_VERSION_MAJOR(frame->version) != 1 || (stats && XVID_VERSION_MAJOR(stats->version) != 1)){ //v1.x.x
PROF_E(PROF_DECODE);
return XVID_ERR_VERSION;
}
//start_global_timer();
low_delay_default = (frame->general & XVID_LOWDELAY);
if((frame->general & XVID_DISCONTINUITY))
frames = 0;
/*
#ifdef XVID_CSP_SLICE
out_frm = (frame->output.csp == XVID_CSP_SLICE) ? &frame->output : NULL;
#endif
*/
if(frame->length < 0){
//decoder flush
int ret;
//if not decoding "low_delay/packed", and this isn't low_delay and
// we have a reference frame, then outout the reference frame
if(!(low_delay_default && packed_mode) && !low_delay && frames>0){
//Output(&refn[0], frame, stats, last_coding_type);
frame->img_out = &refn[0];
frames = 0;
ret = 0;
} else {
if (stats) stats->type = XVID_TYPE_NOTHING;
ret = XVID_ERR_END;
}
//stop_global_timer();
PROF_E(PROF_DECODE);
return ret;
}
bs.Init(frame->bitstream, frame->length);
//XXX: 0x7f is only valid whilst decoding vfw xvid/divx5 avi's
if(low_delay_default && frame->length == 1 && bs.ShowBits(8) == 0x7f){
//image_output(&refn[0], width, height, edged_width, (byte**)frame->output.plane, (unsigned int*)frame->output.stride, frame->output.csp, interlacing);
if(stats)
stats->type = XVID_TYPE_NOTHING;
PROF_E(PROF_DECODE);
return 1; //one byte consumed
}
bool success = false;
bool output = false;
bool seen_something = false;
/*
cur.Clear(width, height, edged_width, 0, 0, 0);
refn[0].Clear(width, height, edged_width, 0, 0, 0);
refn[1].Clear(width, height, edged_width, 0, 0, 0);
*/
repeat:
coding_type = BitstreamReadHeaders(&bs, rounding, &reduced_resolution, &quant, &fcode_forward, &fcode_backward, &intra_dc_threshold, &gmc_warp);
//DPRINTF(XVID_DEBUG_HEADER, "coding_type=%i, packed=%i, time=%lli, time_pp=%i, time_bp=%i\n", coding_type, packed_mode, time, time_pp, time_bp);
if(coding_type == -1){
//nothing
if(success)
goto done;
if(stats)
stats->type = XVID_TYPE_NOTHING;
PROF_E(PROF_DECODE);
return bs.Pos()/8;
}
if(coding_type == -2 || coding_type == -3){
//vol and/or resize
if(coding_type == -3)
Resize();
/*
if(stats){
stats->type = XVID_TYPE_VOL;
stats->data.vol.general = 0;
//XXX: if (interlacing) stats->data.vol.general |= ++INTERLACING;
stats->data.vol.width = width;
stats->data.vol.height = height;
stats->data.vol.par = aspect_ratio;
stats->data.vol.par_width = par_width;
stats->data.vol.par_height = par_height;
return bs.Pos()/8; //number of bytes consumed
}
*/
goto repeat;
}
p_bmv.x = p_bmv.y = p_fmv.y = p_fmv.y = 0;
//packed_mode: special-N_VOP treament
if(packed_mode && coding_type == N_VOP){
if(low_delay_default && frames > 0){
//Output(&refn[0], frame, stats, last_coding_type);
frame->img_out = &refn[0];
output = true;
}
//ignore otherwise
}else
if(coding_type != B_VOP){
switch(coding_type){
case I_VOP:
PROF_S(PROF_FRM_I);
I_Frame(&bs, reduced_resolution, quant, intra_dc_threshold);
PROF_E(PROF_FRM_I);
break;
case P_VOP:
P_Frame(&bs, rounding, reduced_resolution, quant, fcode_forward, intra_dc_threshold, NULL);
break;
case S_VOP:
//not called (or very rare)
P_Frame(&bs, rounding, reduced_resolution, quant, fcode_forward, intra_dc_threshold, &gmc_warp);
break;
case N_VOP:
//XXX: not_coded vops are not used for forward prediction we should not swap(last_mbs,mbs)
cur.Copy(&refn[0], edged_width, height);
break;
}
if(reduced_resolution)
cur.deblock_rrv(edged_width, mbs, (width + 31) / 32, (height + 31) / 32, mb_width, 16, 0);
//note: for packed_mode, output is performed when the special-N_VOP is decoded
if(!(low_delay_default && packed_mode)){
if(low_delay){
//Output(&cur, frame, stats, coding_type);
frame->img_out = &cur;
output = true;
}else
if(frames > 0){
//is the reference frame valid?
// output the reference frame
//Output(&refn[0], frame, stats, last_coding_type);
frame->img_out = &refn[1];
output = true;
}
}
refn[0].Swap(&refn[1]);
cur.Swap(&refn[0]);
Swap(mbs, last_mbs);
last_reduced_resolution = reduced_resolution;
last_coding_type = coding_type;
frames++;
seen_something = true;
}else{
//B_VOP
if(low_delay){
DPRINTF(XVID_DEBUG_ERROR, "warning: bvop found in low_delay==1 stream\n");
low_delay = true;
}
if(frames < 2){
/* attemping to decode a bvop without atleast 2 reference frames */
cur.Print(edged_width, height, 16, 16, "broken b-frame, mising ref frames");
}else
if(time_pp <= time_bp){
//this occurs when dx50_bvop_compatibility==0 sequences are decoded in vfw
cur.Print(edged_width, height, 16, 16, "broken b-frame");
}else{
B_Frame(&bs, quant, fcode_forward, fcode_backward);
}
//Output(&cur, frame, stats, coding_type);
frame->img_out = &cur;
output = true;
frames++;
}
bs.ByteAlign();
//low_delay_default mode: repeat in packed_mode
if(low_delay_default && packed_mode && !output && !success){
success = true;
goto repeat;
}
done:
//low_delay_default mode: if we've gotten here without outputting anything,
// then output the recently decoded frame, or print an error message
if(low_delay_default && !output){
if(packed_mode && seen_something){
//output the recently decoded frame
//Output(&refn[0], frame, stats, last_coding_type);
frame->img_out = &refn[0];
}else{
cur.Clear(width, height, edged_width, 0, 128, 128);
cur.Print(edged_width, height, 16, 16, "warning: nothing to output");
cur.Print(edged_width, height, 16, 64, "bframe decoder lag");
//Output(&cur, frame, stats, P_VOP);
frame->img_out = &cur;
if(stats)
stats->type = XVID_TYPE_NOTHING;
}
}
PROF_E(PROF_DECODE);
//number of bytes consumed
return bs.Pos() / 8;
}
//----------------------------
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?