📄 decoder.c
字号:
if (cbp & 4) transfer_16to8add(pY_Cur + 8 + next_block, &data[3 * 64], stride); if (cbp & 2) transfer_16to8add(pU_Cur, &data[4 * 64], stride2); if (cbp & 1) transfer_16to8add(pV_Cur, &data[5 * 64], stride2); stop_transfer_timer();}voiddecoder_iframe(DECODER * dec, Bitstream * bs, int quant, int intra_dc_threshold){ uint32_t bound; uint32_t x, y; bound = 0; for (y = 0; y < dec->mb_height; y++) { for (x = 0; x < dec->mb_width; x++) { MACROBLOCK *mb; uint32_t mcbpc; uint32_t cbpc; uint32_t acpred_flag; uint32_t cbpy; uint32_t cbp; while (BitstreamShowBits(bs, 9) == 1) BitstreamSkip(bs, 9); if (check_resync_marker(bs, 0)) { bound = read_video_packet_header(bs, 0, &quant); x = bound % dec->mb_width; y = bound / dec->mb_width; } mb = &dec->mbs[y * dec->mb_width + x]; DPRINTF(DPRINTF_MB, "macroblock (%i,%i) %08x", x, y, BitstreamShowBits(bs, 32)); mcbpc = get_mcbpc_intra(bs); mb->mode = mcbpc & 7; cbpc = (mcbpc >> 4); acpred_flag = BitstreamGetBit(bs); cbpy = get_cbpy(bs, 1); cbp = (cbpy << 2) | cbpc; if (mb->mode == MODE_INTRA_Q) { quant += dquant_table[BitstreamGetBits(bs, 2)]; if (quant > 31) { quant = 31; } else if (quant < 1) { quant = 1; } } mb->quant = quant; mb->mvs[0].x = mb->mvs[0].y = mb->mvs[1].x = mb->mvs[1].y = mb->mvs[2].x = mb->mvs[2].y = mb->mvs[3].x = mb->mvs[3].y =0; if (dec->interlacing) { mb->field_dct = BitstreamGetBit(bs); DPRINTF(DPRINTF_DEBUG, "deci: field_dct: %d", mb->field_dct); } decoder_mbintra(dec, mb, x, y, acpred_flag, cbp, bs, quant, intra_dc_threshold, bound); } if(dec->out_frm) output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,0,y,dec->mb_width); }}voidget_motion_vector(DECODER * dec, Bitstream * bs, int x, int y, int k, VECTOR * mv, int fcode, const int bound){ int scale_fac = 1 << (fcode - 1); int high = (32 * scale_fac) - 1; int low = ((-32) * scale_fac); int range = (64 * scale_fac); VECTOR pmv; int mv_x, mv_y; pmv = get_pmv2(dec->mbs, dec->mb_width, bound, x, y, k); mv_x = get_mv(bs, fcode); mv_y = get_mv(bs, fcode); DPRINTF(DPRINTF_MV,"mv_diff (%i,%i) pred (%i,%i)", mv_x, mv_y, pmv.x, pmv.y); mv_x += pmv.x; mv_y += pmv.y; if (mv_x < low) { mv_x += range; } else if (mv_x > high) { mv_x -= range; } if (mv_y < low) { mv_y += range; } else if (mv_y > high) { mv_y -= range; } mv->x = mv_x; mv->y = mv_y;}voiddecoder_pframe(DECODER * dec, Bitstream * bs, int rounding, int quant, int fcode, int intra_dc_threshold){ uint32_t x, y; uint32_t bound; int cp_mb, st_mb; start_timer(); image_setedges(&dec->refn[0], dec->edged_width, dec->edged_height, dec->width, dec->height); stop_edges_timer(); bound = 0; for (y = 0; y < dec->mb_height; y++) { cp_mb = st_mb = 0; for (x = 0; x < dec->mb_width; x++) { MACROBLOCK *mb; /* skip stuffing */ while (BitstreamShowBits(bs, 10) == 1) BitstreamSkip(bs, 10); if (check_resync_marker(bs, fcode - 1)) { bound = read_video_packet_header(bs, fcode - 1, &quant); x = bound % dec->mb_width; y = bound / dec->mb_width; } mb = &dec->mbs[y * dec->mb_width + x]; DPRINTF(DPRINTF_MB, "macroblock (%i,%i) %08x", x, y, BitstreamShowBits(bs, 32)); /*if (!(dec->mb_skip[y*dec->mb_width + x]=BitstreamGetBit(bs))) not_coded */ if (!(BitstreamGetBit(bs))) /* not_coded */ { uint32_t mcbpc; uint32_t cbpc; uint32_t acpred_flag; uint32_t cbpy; uint32_t cbp; uint32_t intra; cp_mb++; mcbpc = get_mcbpc_inter(bs); mb->mode = mcbpc & 7; cbpc = (mcbpc >> 4); DPRINTF(DPRINTF_MB, "mode %i", mb->mode); DPRINTF(DPRINTF_MB, "cbpc %i", cbpc); acpred_flag = 0; intra = (mb->mode == MODE_INTRA || mb->mode == MODE_INTRA_Q); if (intra) { acpred_flag = BitstreamGetBit(bs); } cbpy = get_cbpy(bs, intra); DPRINTF(DPRINTF_MB, "cbpy %i", cbpy); cbp = (cbpy << 2) | cbpc; if (mb->mode == MODE_INTER_Q || mb->mode == MODE_INTRA_Q) { int dquant = dquant_table[BitstreamGetBits(bs, 2)]; DPRINTF(DPRINTF_MB, "dquant %i", dquant); quant += dquant; if (quant > 31) { quant = 31; } else if (quant < 1) { quant = 1; } DPRINTF(DPRINTF_MB, "quant %i", quant); } mb->quant = quant; if (dec->interlacing) { if (cbp || intra) { mb->field_dct = BitstreamGetBit(bs); DPRINTF(DPRINTF_DEBUG, "decp: field_dct: %d", mb->field_dct); } if (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) { mb->field_pred = BitstreamGetBit(bs); DPRINTF(DPRINTF_DEBUG, "decp: field_pred: %d", mb->field_pred); if (mb->field_pred) { mb->field_for_top = BitstreamGetBit(bs); DPRINTF(DPRINTF_DEBUG, "decp: field_for_top: %d", mb->field_for_top); mb->field_for_bot = BitstreamGetBit(bs); DPRINTF(DPRINTF_DEBUG, "decp: field_for_bot: %d", mb->field_for_bot); } } } if (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) { if (dec->interlacing && mb->field_pred) { get_motion_vector(dec, bs, x, y, 0, &mb->mvs[0], fcode, bound); get_motion_vector(dec, bs, x, y, 0, &mb->mvs[1], fcode, bound); } else { get_motion_vector(dec, bs, x, y, 0, &mb->mvs[0], fcode, bound); mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = mb->mvs[0].x; mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = mb->mvs[0].y; } } else if (mb->mode == MODE_INTER4V ) { get_motion_vector(dec, bs, x, y, 0, &mb->mvs[0], fcode, bound); get_motion_vector(dec, bs, x, y, 1, &mb->mvs[1], fcode, bound); get_motion_vector(dec, bs, x, y, 2, &mb->mvs[2], fcode, bound); get_motion_vector(dec, bs, x, y, 3, &mb->mvs[3], fcode, bound); } else /* MODE_INTRA, MODE_INTRA_Q */ { mb->mvs[0].x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = 0; mb->mvs[0].y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = 0; decoder_mbintra(dec, mb, x, y, acpred_flag, cbp, bs, quant, intra_dc_threshold, bound); continue; } decoder_mbinter(dec, mb, x, y, acpred_flag, cbp, bs, quant, rounding); } else /* not coded */ { DPRINTF(DPRINTF_DEBUG, "P-frame MB at (X,Y)=(%d,%d)", x, y); mb->mode = MODE_NOT_CODED; mb->mvs[0].x = mb->mvs[1].x = mb->mvs[2].x = mb->mvs[3].x = 0; mb->mvs[0].y = mb->mvs[1].y = mb->mvs[2].y = mb->mvs[3].y = 0; /* copy macroblock directly from ref to cur */ start_timer(); transfer8x8_copy(dec->cur.y + (16 * y) * dec->edged_width + (16 * x), dec->refn[0].y + (16 * y) * dec->edged_width + (16 * x), dec->edged_width); transfer8x8_copy(dec->cur.y + (16 * y) * dec->edged_width + (16 * x + 8), dec->refn[0].y + (16 * y) * dec->edged_width + (16 * x + 8), dec->edged_width); transfer8x8_copy(dec->cur.y + (16 * y + 8) * dec->edged_width + (16 * x), dec->refn[0].y + (16 * y + 8) * dec->edged_width + (16 * x), dec->edged_width); transfer8x8_copy(dec->cur.y + (16 * y + 8) * dec->edged_width + (16 * x + 8), dec->refn[0].y + (16 * y + 8) * dec->edged_width + (16 * x + 8), dec->edged_width); transfer8x8_copy(dec->cur.u + (8 * y) * dec->edged_width / 2 + (8 * x), dec->refn[0].u + (8 * y) * dec->edged_width / 2 + (8 * x), dec->edged_width / 2); transfer8x8_copy(dec->cur.v + (8 * y) * dec->edged_width / 2 + (8 * x), dec->refn[0].v + (8 * y) * dec->edged_width / 2 + (8 * x), dec->edged_width / 2); stop_transfer_timer(); if(dec->out_frm && cp_mb > 0) { output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,st_mb,y,cp_mb); cp_mb = 0; } st_mb = x+1; } } if(dec->out_frm && cp_mb > 0) output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,st_mb,y,cp_mb); }}/* swap two MACROBLOCK array */voidmb_swap(MACROBLOCK ** mb1, MACROBLOCK ** mb2){ MACROBLOCK *temp = *mb1; *mb1 = *mb2; *mb2 = temp;}intdecoder_decode(DECODER * dec, XVID_DEC_FRAME * frame){ Bitstream bs; uint32_t rounding; uint32_t quant; uint32_t fcode_forward; uint32_t fcode_backward; uint32_t intra_dc_threshold; uint32_t vop_type; start_global_timer(); dec->out_frm = (frame->colorspace == XVID_CSP_EXTERN) ? frame->image : NULL; BitstreamInit(&bs, frame->bitstream, frame->length); /* add by chenm001 <chenm001@163.com> */ /* for support B-frame to reference last 2 frame */ dec->frames++; vop_type = BitstreamReadHeaders(&bs, dec, &rounding, &quant, &fcode_forward, &fcode_backward, &intra_dc_threshold); dec->p_bmv.x = dec->p_bmv.y = dec->p_fmv.y = dec->p_fmv.y = 0; /* init pred vector to 0 */ switch (vop_type) { case P_VOP: decoder_pframe(dec, &bs, rounding, quant, fcode_forward, intra_dc_threshold); break; case I_VOP: decoder_iframe(dec, &bs, quant, intra_dc_threshold); break; case B_VOP: image_copy(&dec->cur, &dec->refn[0], dec->edged_width, dec->height); break; case N_VOP: /* when low_delay==0, N_VOP's should interpolate between the past and future frames */ image_copy(&dec->cur, &dec->refn[0], dec->edged_width, dec->height); break; default: return XVID_ERR_FAIL; } frame->length = BitstreamPos(&bs) / 8; image_output(&dec->cur, dec->width, dec->height, dec->edged_width, frame->image, frame->stride, frame->colorspace); if (vop_type == I_VOP || vop_type == P_VOP) { image_swap(&dec->refn[0], &dec->refn[1]); image_swap(&dec->cur, &dec->refn[0]); /* swap MACROBLOCK */ /* the Divx will not set the low_delay flage some times */ /* so follow code will wrong to not swap at that time */ /* this will broken bitstream! so I'm change it, */ /* But that is not the best way! can anyone tell me how */ /* to do another way? */ /* 18-07-2002 MinChen<chenm001@163.com> */ /*if (!dec->low_delay && vop_type == P_VOP) */ if (vop_type == P_VOP) mb_swap(&dec->mbs, &dec->last_mbs); } emms(); stop_global_timer(); return XVID_ERR_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -