|
14.2.1 MPEG-4编/解码设计与剖析(10)
④ decoder_mbinter对Inter块实现解码
Inter块解码支持1/2像素精度,Inter块的decoder_mbinter()的流程如图14-10所示。
|
图14-10 decoder_mbinter () 流程图 | 根据该流程,代码实现如下。
void decoder_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 ref, const int bvop) { 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 */ /*获取指向图像空间的指针*/ 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); /*检查运动向量的合法性*/ /******************************运动补偿*****************************/ if ((pMB->mode != MODE_INTER4V)) { /* 编码模式是INTER、INTER_Q、NOT_CODED、FORWARD、BACKWARD */ uv_dx = mv[0].x; uv_dy = mv[0].y; uv_dx = (uv_dx >> 1) + roundtab_79[uv_dx & 0x3]; uv_dy = (uv_dy >> 1) + roundtab_79[uv_dy & 0x3]; /*亮度插值*/ interpolate16x16_switch(dec->cur.y,dec->refn[ref] .y,16*x_pos,16*y_pos,mv[0].x, mv[0].y, stride, rounding); } /*色度插值 */ 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); /******************************运动补偿*****************************/ /*根据cbp*/ if (cbp) decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, pMB); } |
上述代码实现Inter块的解码,首先作运动补偿,然后根据cbp编码模式决定是否做宏块解码。
⑥ decoder_mb_decode实现宏块的实际解码工作
首先VLD熵解码、反量化和IDCT变换,最后根据CBP编码模式决定块是否更新到当前解码帧图像。
Inter块的decoder_ mb_decode ()的流程如图14-11所示。
|
| 图14-11 decoder_mb_decode()流程图 |
根据该流程,代码实现如下。
void decoder_mb_decode(DECODER * dec, const uint32_t cbp, Bitstream * bs, uint8_t * pY_Cur, uint8_t * pU_Cur, uint8_t * pV_Cur, const int reduced_resolution,const MACROBLOCK * pMB) { DECLARE_ALIGNED_MATRIX(block, 1, 64, int16_t, CACHE_LINE); /*系数*/ DECLARE_ALIGNED_MATRIX(data, 6, 64, int16_t, CACHE_LINE); /*图像*/ int stride = dec->edged_width; /*图像边扩展后的宽度*/ int next_block = stride * 8; /*亮度的下一个块*/ const int stride2 = stride/2; /*色度的下一个快*/ int i; const uint32_t iQuant = pMB->quant; /*量化步长*/ const int direction = dec->alternate_vertical_scan 2 : 0; /*AC扫描方式*/ for (i = 0; i < 6; i++) { if (cbp & (1 << (5 - i))) { /*块做了编码*/ memset(block, 0, 64 * sizeof(int16_t)); /*清零*/ get_inter_block(bs, block, direction); /*VLD熵解码*/ dequant_h263_inter (&data[i * 64], block, iQuant, NULL);/*H263反量化*/ idct(&data[i * 64]); /*IDCT变换*/ } } /*根据CBP值决定是否加到当前图像*/ 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); } |
上述代码实现Inter块的解码工作,根据cbp值决定是否做解码。首先解码宏块空间block清零,VLD熵解码,然后反量化、反变换。最后根据cbp值决定是否更新当前解码帧图像。
为了提高解码器解码速度,解码器的最底层模块get_inter_block、dequant_h263_inter、idct、transfer_16to8add等,要使用平台的汇编来优化和设计。下一节将介绍这些核心模块的MMX/SSE/DM642汇编优化。
【责任编辑: 云霞 TEL:(010)68476606】
|