📄 decoder.c
字号:
if (cbp & (1 << (5 - i))) { /* coded */ memset(block, 0, 64 * sizeof(int16_t)); /* clear */ start_timer(); get_inter_block(bs, block, direction); stop_coding_timer(); start_timer(); dequant(&data[i * 64], block, iQuant, dec->mpeg_quant_matrices); stop_iquant_timer(); start_timer(); idct(&data[i * 64]); stop_idct_timer(); } } if (dec->interlacing && pMB->field_dct) { next_block = stride; stride *= 2; } start_timer(); if (reduced_resolution) { if (cbp & 32) add_upsampled_8x8_16to8(pY_Cur, &data[0 * 64], stride); if (cbp & 16) add_upsampled_8x8_16to8(pY_Cur + 16, &data[1 * 64], stride); if (cbp & 8) add_upsampled_8x8_16to8(pY_Cur + next_block, &data[2 * 64], stride); if (cbp & 4) add_upsampled_8x8_16to8(pY_Cur + 16 + next_block, &data[3 * 64], stride); if (cbp & 2) add_upsampled_8x8_16to8(pU_Cur, &data[4 * 64], stride2); if (cbp & 1) add_upsampled_8x8_16to8(pV_Cur, &data[5 * 64], stride2); } else { if (cbp & 32) transfer_16to8add(pY_Cur, &data[0 * 64], stride); if (cbp & 16) transfer_16to8add(pY_Cur + 8, &data[1 * 64], stride); if (cbp & 8) transfer_16to8add(pY_Cur + next_block, &data[2 * 64], stride); 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();}static void __inlinevalidate_vector(VECTOR * mv, unsigned int x_pos, unsigned int y_pos, const DECODER * dec){ /* clip a vector to valid range prevents crashes if bitstream is broken */ int shift = 5 + dec->quarterpel; int xborder_high = (int)(dec->mb_width - x_pos) << shift; int xborder_low = (-(int)x_pos-1) << shift; int yborder_high = (int)(dec->mb_height - y_pos) << shift; int yborder_low = (-(int)y_pos-1) << shift;#define CHECK_MV(mv) \ do { \ if ((mv).x > xborder_high) { \ DPRINTF(XVID_DEBUG_MV, "mv.x > max -- %d > %d, MB %d, %d", (mv).x, xborder_high, x_pos, y_pos); \ (mv).x = xborder_high; \ } else if ((mv).x < xborder_low) { \ DPRINTF(XVID_DEBUG_MV, "mv.x < min -- %d < %d, MB %d, %d", (mv).x, xborder_low, x_pos, y_pos); \ (mv).x = xborder_low; \ } \ if ((mv).y > yborder_high) { \ DPRINTF(XVID_DEBUG_MV, "mv.y > max -- %d > %d, MB %d, %d", (mv).y, yborder_high, x_pos, y_pos); \ (mv).y = yborder_high; \ } else if ((mv).y < yborder_low) { \ DPRINTF(XVID_DEBUG_MV, "mv.y < min -- %d < %d, MB %d, %d", (mv).y, yborder_low, x_pos, y_pos); \ (mv).y = yborder_low; \ } \ } while (0) CHECK_MV(mv[0]); CHECK_MV(mv[1]); CHECK_MV(mv[2]); CHECK_MV(mv[3]);}/* decode an inter macroblock */static voiddecoder_mbinter(DECODER * dec, const MACROBLOCK * pMB, const uint32_t x_pos, const uint32_t y_pos, const uint32_t cbp, Bitstream * bs, const uint32_t rounding, const int reduced_resolution, const int ref){ uint32_t stride = dec->edged_width; uint32_t stride2 = stride / 2; uint32_t i; uint8_t *pY_Cur, *pU_Cur, *pV_Cur; int uv_dx, uv_dy; VECTOR mv[4]; /* local copy of mvs */ if (reduced_resolution) { pY_Cur = dec->cur.y + (y_pos << 5) * stride + (x_pos << 5); pU_Cur = dec->cur.u + (y_pos << 4) * stride2 + (x_pos << 4); pV_Cur = dec->cur.v + (y_pos << 4) * stride2 + (x_pos << 4); for (i = 0; i < 4; i++) { mv[i].x = RRV_MV_SCALEUP(pMB->mvs[i].x); mv[i].y = RRV_MV_SCALEUP(pMB->mvs[i].y); } } else { pY_Cur = dec->cur.y + (y_pos << 4) * stride + (x_pos << 4); pU_Cur = dec->cur.u + (y_pos << 3) * stride2 + (x_pos << 3); pV_Cur = dec->cur.v + (y_pos << 3) * stride2 + (x_pos << 3); for (i = 0; i < 4; i++) mv[i] = pMB->mvs[i]; } validate_vector(mv, x_pos, y_pos, dec); start_timer(); if (pMB->mode != MODE_INTER4V) { /* INTER, INTER_Q, NOT_CODED, FORWARD, BACKWARD */ uv_dx = mv[0].x; uv_dy = mv[0].y; if (dec->quarterpel) { uv_dx /= 2; uv_dy /= 2; } uv_dx = (uv_dx >> 1) + roundtab_79[uv_dx & 0x3]; uv_dy = (uv_dy >> 1) + roundtab_79[uv_dy & 0x3]; if (reduced_resolution) interpolate32x32_switch(dec->cur.y, dec->refn[0].y, 32*x_pos, 32*y_pos, mv[0].x, mv[0].y, stride, rounding); else if (dec->quarterpel) interpolate16x16_quarterpel(dec->cur.y, dec->refn[ref].y, dec->qtmp.y, dec->qtmp.y + 64, dec->qtmp.y + 128, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding); else interpolate16x16_switch(dec->cur.y, dec->refn[ref].y, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding); } else { /* MODE_INTER4V */ if(dec->quarterpel) { uv_dx = (mv[0].x / 2) + (mv[1].x / 2) + (mv[2].x / 2) + (mv[3].x / 2); uv_dy = (mv[0].y / 2) + (mv[1].y / 2) + (mv[2].y / 2) + (mv[3].y / 2); } else { uv_dx = mv[0].x + mv[1].x + mv[2].x + mv[3].x; uv_dy = mv[0].y + mv[1].y + mv[2].y + mv[3].y; } uv_dx = (uv_dx >> 3) + roundtab_76[uv_dx & 0xf]; uv_dy = (uv_dy >> 3) + roundtab_76[uv_dy & 0xf]; if (reduced_resolution) { interpolate16x16_switch(dec->cur.y, dec->refn[0].y, 32*x_pos, 32*y_pos, mv[0].x, mv[0].y, stride, rounding); interpolate16x16_switch(dec->cur.y, dec->refn[0].y , 32*x_pos + 16, 32*y_pos, mv[1].x, mv[1].y, stride, rounding); interpolate16x16_switch(dec->cur.y, dec->refn[0].y , 32*x_pos, 32*y_pos + 16, mv[2].x, mv[2].y, stride, rounding); interpolate16x16_switch(dec->cur.y, dec->refn[0].y , 32*x_pos + 16, 32*y_pos + 16, mv[3].x, mv[3].y, stride, rounding); interpolate16x16_switch(dec->cur.u, dec->refn[0].u , 16 * x_pos, 16 * y_pos, uv_dx, uv_dy, stride2, rounding); interpolate16x16_switch(dec->cur.v, dec->refn[0].v , 16 * x_pos, 16 * y_pos, uv_dx, uv_dy, stride2, rounding); } else if (dec->quarterpel) { interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y , dec->qtmp.y, dec->qtmp.y + 64, dec->qtmp.y + 128, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding); interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y , dec->qtmp.y, dec->qtmp.y + 64, dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos, mv[1].x, mv[1].y, stride, rounding); interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y , dec->qtmp.y, dec->qtmp.y + 64, dec->qtmp.y + 128, 16*x_pos, 16*y_pos + 8, mv[2].x, mv[2].y, stride, rounding); interpolate8x8_quarterpel(dec->cur.y, dec->refn[0].y , dec->qtmp.y, dec->qtmp.y + 64, dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8, mv[3].x, mv[3].y, stride, rounding); } else { interpolate8x8_switch(dec->cur.y, dec->refn[0].y , 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding); interpolate8x8_switch(dec->cur.y, dec->refn[0].y , 16*x_pos + 8, 16*y_pos, mv[1].x, mv[1].y, stride, rounding); interpolate8x8_switch(dec->cur.y, dec->refn[0].y , 16*x_pos, 16*y_pos + 8, mv[2].x, mv[2].y, stride, rounding); interpolate8x8_switch(dec->cur.y, dec->refn[0].y , 16*x_pos + 8, 16*y_pos + 8, mv[3].x, mv[3].y, stride, rounding); } } /* chroma */ if (reduced_resolution) { interpolate16x16_switch(dec->cur.u, dec->refn[0].u, 16 * x_pos, 16 * y_pos, uv_dx, uv_dy, stride2, rounding); interpolate16x16_switch(dec->cur.v, dec->refn[0].v, 16 * x_pos, 16 * y_pos, uv_dx, uv_dy, stride2, rounding); } else { interpolate8x8_switch(dec->cur.u, dec->refn[ref].u, 8 * x_pos, 8 * y_pos, uv_dx, uv_dy, stride2, rounding); interpolate8x8_switch(dec->cur.v, dec->refn[ref].v, 8 * x_pos, 8 * y_pos, uv_dx, uv_dy, stride2, rounding); } stop_comp_timer(); if (cbp) decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, reduced_resolution, pMB);}static voiddecoder_mbgmc(DECODER * dec, MACROBLOCK * const pMB, const uint32_t x_pos, const uint32_t y_pos, const uint32_t fcode, const uint32_t cbp, Bitstream * bs, const uint32_t rounding){ const uint32_t stride = dec->edged_width; const uint32_t stride2 = stride / 2; uint8_t *const pY_Cur=dec->cur.y + (y_pos << 4) * stride + (x_pos << 4); uint8_t *const pU_Cur=dec->cur.u + (y_pos << 3) * stride2 + (x_pos << 3); uint8_t *const pV_Cur=dec->cur.v + (y_pos << 3) * stride2 + (x_pos << 3); NEW_GMC_DATA * gmc_data = &dec->new_gmc_data; pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv; start_timer();/* this is where the calculations are done */ gmc_data->predict_16x16(gmc_data, dec->cur.y + y_pos*16*stride + x_pos*16, dec->refn[0].y, stride, stride, x_pos, y_pos, rounding); gmc_data->predict_8x8(gmc_data, dec->cur.u + y_pos*8*stride2 + x_pos*8, dec->refn[0].u, dec->cur.v + y_pos*8*stride2 + x_pos*8, dec->refn[0].v, stride2, stride2, x_pos, y_pos, rounding); gmc_data->get_average_mv(gmc_data, &pMB->amv, x_pos, y_pos, dec->quarterpel); pMB->amv.x = gmc_sanitize(pMB->amv.x, dec->quarterpel, fcode); pMB->amv.y = gmc_sanitize(pMB->amv.y, dec->quarterpel, fcode); pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv; stop_transfer_timer(); if (cbp) decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, 0, pMB);}static voiddecoder_iframe(DECODER * dec, Bitstream * bs, int reduced_resolution, int quant, int intra_dc_threshold){ uint32_t bound; uint32_t x, y; uint32_t mb_width = dec->mb_width; uint32_t mb_height = dec->mb_height; if (reduced_resolution) { mb_width = (dec->width + 31) / 32; mb_height = (dec->height + 31) / 32; } bound = 0; for (y = 0; y < mb_height; y++) { for (x = 0; x < 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, dec, 0, &quant, NULL, NULL, &intra_dc_threshold); x = bound % mb_width; y = bound / mb_width; } mb = &dec->mbs[y * dec->mb_width + x]; DPRINTF(XVID_DEBUG_MB, "macroblock (%i,%i) %08x\n", 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(XVID_DEBUG_MB,"deci: field_dct: %i\n", mb->field_dct); } decoder_mbintra(dec, mb, x, y, acpred_flag, cbp, bs, quant, intra_dc_threshold, bound, reduced_resolution); } if(dec->out_frm) output_slice(&dec->cur, dec->edged_width,dec->width,dec->out_frm,0,y,mb_width); }}static voidget_motion_vector(DECODER * dec, Bitstream * bs, int x, int y, int k, VECTOR * ret_mv, int fcode, const int bound){ const int scale_fac = 1 << (fcode - 1); const int high = (32 * scale_fac) - 1; const int low = ((-32) * scale_fac); const int range = (64 * scale_fac); const VECTOR pmv = get_pmv2(dec->mbs, dec->mb_width, bound, x, y, k); VECTOR mv; mv.x = get_mv(bs, fcode); mv.y = get_mv(bs, fcode); DPRINTF(XVID_DEBUG_MV,"mv_diff (%i,%i) pred (%i,%i) result (%i,%i)\n", mv.x, mv.y, pmv.x, pmv.y, mv.x+pmv.x, mv.y+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; } ret_mv->x = mv.x; ret_mv->y = mv.y;}/* for P_VOP set gmc_warp to NULL */static voiddecoder_pframe(DECODER * dec, Bitstream * bs, int rounding, int reduced_resolution, int quant, int fcode, int intra_dc_threshold, const WARPPOINTS *const gmc_warp)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -