/*! *********************************************************************** * \file * block.c * * \brief * Block functions * * \author * Main contributors (see contributors.h for copyright, address and affiliation details) * - Inge Lille-Langoy * - Rickard Sjoberg *********************************************************************** */ #include "contributors.h" #include "global.h" #include "block.h" #include "image.h" #include "mb_access.h" #include "transform.h" #include "quant.h" #include "memalloc.h" #include "optim.h" /*! **************************************************************************** * \brief * Inverse 4x4 lossless_qpprime transformation, transforms cof to mb_rres **************************************************************************** */ void itrans4x4_ls(const h264_short_block_row_t *tblock, const h264_imgpel_macroblock_row_t *mb_pred, h264_imgpel_macroblock_row_t *mb_rec, int ioff, //!< index to 4x4 block int joff) //!< index to 4x4 block { int i,j; for (j = 0; j < BLOCK_SIZE; ++j) { for (i = 0; i < BLOCK_SIZE; ++i) { mb_rec[j+joff][i+ioff] = (imgpel) iClip1(255/*max_imgpel_value*/, mb_pred[j+joff][i+ioff] + tblock[j][i]); } } } /*! ************************************************************************ * \brief * Inverse residual DPCM for Intra lossless coding * ************************************************************************ */ void Inv_Residual_trans_4x4(Macroblock *currMB, //!< current macroblock ColorPlane pl, //!< used color plane int ioff, //!< index to 4x4 block int joff) //!< index to 4x4 block { int i,j; h264_short_block_t temp; Slice *currSlice = currMB->p_Slice; int subblock = cof4_pos_to_subblock[joff>>2][ioff>>2]; h264_short_block_row_t *tblock = currSlice->cof4[pl][subblock]; if(currMB->ipmode_DPCM == VERT_PRED) { for(i=0; i<4; ++i) { temp[0][i] = tblock[0][i]; temp[1][i] = tblock[1][i] + temp[0][i]; temp[2][i] = tblock[2][i] + temp[1][i]; temp[3][i] = tblock[3][i] + temp[2][i]; } } else if(currMB->ipmode_DPCM == HOR_PRED) { for(j=0; j<4; ++j) { temp[j][0] = tblock[j][0]; temp[j][1] = tblock[j][1] + temp[j][0]; temp[j][2] = tblock[j][2] + temp[j][1]; temp[j][3] = tblock[j][3] + temp[j][2]; } } else { for (j = 0; j < BLOCK_SIZE; ++j) for (i = 0; i < BLOCK_SIZE; ++i) temp[j][i] = tblock[j][i]; } for (j = 0; j < BLOCK_SIZE; ++j) { for (i = 0; i < BLOCK_SIZE; ++i) { currSlice->mb_rec[pl][j+joff][i+ioff] = (imgpel) (temp[j][i] + currSlice->mb_pred[pl][j+joff][i+ioff]); } } } /*! ************************************************************************ * \brief * Inverse residual DPCM for Intra lossless coding * * \par Input: * ioff_x,joff_y: Block position inside a macro block (0,8). ************************************************************************ */ //For residual DPCM void Inv_Residual_trans_8x8(Macroblock *currMB, ColorPlane pl, int ioff,int joff) { Slice *currSlice = currMB->p_Slice; int i, j; h264_short_8x8block_t temp; int block = (joff>>2) + (ioff>>3); if(currMB->ipmode_DPCM == VERT_PRED) { for(i=0; i<8; ++i) { temp[0][i] = currSlice->mb_rres8[pl][block][0][i]; temp[1][i] = currSlice->mb_rres8[pl][block][1][i] + temp[0][i]; temp[2][i] = currSlice->mb_rres8[pl][block][2][i] + temp[1][i]; temp[3][i] = currSlice->mb_rres8[pl][block][3][i] + temp[2][i]; temp[4][i] = currSlice->mb_rres8[pl][block][4][i] + temp[3][i]; temp[5][i] = currSlice->mb_rres8[pl][block][5][i] + temp[4][i]; temp[6][i] = currSlice->mb_rres8[pl][block][6][i] + temp[5][i]; temp[7][i] = currSlice->mb_rres8[pl][block][7][i] + temp[6][i]; } for(i=0; i<8; ++i) { currSlice->mb_rres8[pl][block][0][i]=temp[0][i]; currSlice->mb_rres8[pl][block][1][i]=temp[1][i]; currSlice->mb_rres8[pl][block][2][i]=temp[2][i]; currSlice->mb_rres8[pl][block][3][i]=temp[3][i]; currSlice->mb_rres8[pl][block][4][i]=temp[4][i]; currSlice->mb_rres8[pl][block][5][i]=temp[5][i]; currSlice->mb_rres8[pl][block][6][i]=temp[6][i]; currSlice->mb_rres8[pl][block][7][i]=temp[7][i]; } } else if(currMB->ipmode_DPCM == HOR_PRED)//HOR_PRED { for(i=0; i<8; ++i) { temp[i][0] = currSlice->mb_rres8[pl][block][i][0]; temp[i][1] = currSlice->mb_rres8[pl][block][i][1] + temp[i][0]; temp[i][2] = currSlice->mb_rres8[pl][block][i][2] + temp[i][1]; temp[i][3] = currSlice->mb_rres8[pl][block][i][3] + temp[i][2]; temp[i][4] = currSlice->mb_rres8[pl][block][i][4] + temp[i][3]; temp[i][5] = currSlice->mb_rres8[pl][block][i][5] + temp[i][4]; temp[i][6] = currSlice->mb_rres8[pl][block][i][6] + temp[i][5]; temp[i][7] = currSlice->mb_rres8[pl][block][i][7] + temp[i][6]; } for(i=0; i<8; ++i) { currSlice->mb_rres8[pl][block][i][0]=temp[i][0]; currSlice->mb_rres8[pl][block][i][1]=temp[i][1]; currSlice->mb_rres8[pl][block][i][2]=temp[i][2]; currSlice->mb_rres8[pl][block][i][3]=temp[i][3]; currSlice->mb_rres8[pl][block][i][4]=temp[i][4]; currSlice->mb_rres8[pl][block][i][5]=temp[i][5]; currSlice->mb_rres8[pl][block][i][6]=temp[i][6]; currSlice->mb_rres8[pl][block][i][7]=temp[i][7]; } } for (j = 0; j < BLOCK_SIZE_8x8; ++j) { for (i = 0; i < BLOCK_SIZE_8x8; ++i) { currSlice->mb_rec[pl][joff+j][ioff+i] = (imgpel) (currSlice->mb_rres8[pl][block][j][i] + currSlice->mb_pred[pl][joff+j][ioff+i]); } } } /*! *********************************************************************** * \brief * Luma DC inverse transform *********************************************************************** */ void itrans_2(Macroblock *currMB, ColorPlane pl) { Slice *currSlice = currMB->p_Slice; VideoParameters *p_Vid = currMB->p_Vid; int transform_pl = IS_INDEPENDENT(p_Vid) ? PLANE_Y /*p_Vid->colour_plane_id*/ : pl; h264_short_block_t *blocks = currSlice->cof4[transform_pl]; int qp_scaled = currMB->qp_scaled[pl]; int qp_per = p_Vid->qp_per_matrix[ qp_scaled ]; int qp_rem = p_Vid->qp_rem_matrix[ qp_scaled ]; int invLevelScale = currSlice->InvLevelScale4x4_Intra[pl][qp_rem][0][0]; h264_int_block_t M4; // horizontal M4[0][0]=blocks[0][0][0]; M4[0][1]=blocks[1][0][0]; M4[0][2]=blocks[4][0][0]; M4[0][3]=blocks[5][0][0]; M4[1][0]=blocks[2][0][0]; M4[1][1]=blocks[3][0][0]; M4[1][2]=blocks[6][0][0]; M4[1][3]=blocks[7][0][0]; M4[2][0]=blocks[8][0][0]; M4[2][1]=blocks[9][0][0]; M4[2][2]=blocks[12][0][0]; M4[2][3]=blocks[13][0][0]; M4[3][0]=blocks[10][0][0]; M4[3][1]=blocks[11][0][0]; M4[3][2]=blocks[14][0][0]; M4[3][3]=blocks[15][0][0]; ihadamard4x4(M4); // vertical blocks[0][0][0] = rshift_rnd((( M4[0][0] * invLevelScale) << qp_per), 6); blocks[1][0][0] = rshift_rnd((( M4[0][1] * invLevelScale) << qp_per), 6); blocks[4][0][0] = rshift_rnd((( M4[0][2] * invLevelScale) << qp_per), 6); blocks[5][0][0] = rshift_rnd((( M4[0][3] * invLevelScale) << qp_per), 6); blocks[2][0][0] = rshift_rnd((( M4[1][0] * invLevelScale) << qp_per), 6); blocks[3][0][0] = rshift_rnd((( M4[1][1] * invLevelScale) << qp_per), 6); blocks[6][0][0] = rshift_rnd((( M4[1][2] * invLevelScale) << qp_per), 6); blocks[7][0][0] = rshift_rnd((( M4[1][3] * invLevelScale) << qp_per), 6); blocks[8][0][0] = rshift_rnd((( M4[2][0] * invLevelScale) << qp_per), 6); blocks[9][0][0] = rshift_rnd((( M4[2][1] * invLevelScale) << qp_per), 6); blocks[12][0][0] = rshift_rnd((( M4[2][2] * invLevelScale) << qp_per), 6); blocks[13][0][0] = rshift_rnd((( M4[2][3] * invLevelScale) << qp_per), 6); blocks[10][0][0] = rshift_rnd((( M4[3][0] * invLevelScale) << qp_per), 6); blocks[11][0][0] = rshift_rnd((( M4[3][1] * invLevelScale) << qp_per), 6); blocks[14][0][0] = rshift_rnd((( M4[3][2] * invLevelScale) << qp_per), 6); blocks[15][0][0] = rshift_rnd((( M4[3][3] * invLevelScale) << qp_per), 6); } void itrans_sp(h264_short_block_row_t *tblock, const h264_imgpel_macroblock_row_t *mb_pred, Macroblock *currMB, ColorPlane pl, int ioff, int joff) { VideoParameters *p_Vid = currMB->p_Vid; Slice *currSlice = currMB->p_Slice; int i,j; int ilev, icof; int qp = (currSlice->slice_type == SI_SLICE) ? currSlice->qs : p_Vid->qp; int qp_per = p_Vid->qp_per_matrix[ qp ]; int qp_rem = p_Vid->qp_rem_matrix[ qp ]; int qp_per_sp = p_Vid->qp_per_matrix[ currSlice->qs ]; int qp_rem_sp = p_Vid->qp_rem_matrix[ currSlice->qs ]; int q_bits_sp = Q_BITS + qp_per_sp; int max_imgpel_value = p_Vid->max_pel_value_comp[pl]; const int (*InvLevelScale4x4) [4] = dequant_coef[qp_rem]; const int (*InvLevelScale4x4SP)[4] = dequant_coef[qp_rem_sp]; int **PBlock; get_mem2Dint(&PBlock, MB_BLOCK_SIZE, MB_BLOCK_SIZE); for (j=0; j< BLOCK_SIZE; ++j) for (i=0; i< BLOCK_SIZE; ++i) PBlock[j][i] = mb_pred[j+joff][i+ioff]; forward4x4(PBlock, PBlock, 0, 0); if(p_Vid->sp_switch || currSlice->slice_type==SI_SLICE) { for (j=0;j> qp_per) / InvLevelScale4x4[j][i]; ilev = rshift_rnd_sf(iabs(PBlock[j][i]) * quant_coef[qp_rem_sp][j][i], q_bits_sp); ilev = isignab(ilev, PBlock[j][i]) + icof; tblock[j][i] = ilev * InvLevelScale4x4SP[j][i] << qp_per_sp; } } } else { for (j=0;j> qp_per) / InvLevelScale4x4[j][i]; ilev = PBlock[j][i] + ((icof * InvLevelScale4x4[j][i] * A[j][i] << qp_per) >> 6); ilev = isign(ilev) * rshift_rnd_sf(iabs(ilev) * quant_coef[qp_rem_sp][j][i], q_bits_sp); tblock[j][i] = ilev * InvLevelScale4x4SP[j][i] << qp_per_sp; } } } { h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; opt_itrans4x4(tblock, mb_pred, mb_rec, ioff, joff); } free_mem2Dint(PBlock); } void itrans_sp_cr(Macroblock *currMB, int uv) { Slice *currSlice = currMB->p_Slice; VideoParameters *p_Vid = currMB->p_Vid; int i,j,ilev, icof, n2,n1; int mp1[BLOCK_SIZE]; int qp_per,qp_rem; int qp_per_sp,qp_rem_sp,q_bits_sp; int **PBlock; get_mem2Dint(&PBlock, MB_BLOCK_SIZE, MB_BLOCK_SIZE); qp_per = p_Vid->qp_per_matrix[ ((p_Vid->qp < 0 ? p_Vid->qp : QP_SCALE_CR[p_Vid->qp]))]; qp_rem = p_Vid->qp_rem_matrix[ ((p_Vid->qp < 0 ? p_Vid->qp : QP_SCALE_CR[p_Vid->qp]))]; qp_per_sp = p_Vid->qp_per_matrix[ ((currSlice->qs < 0 ? currSlice->qs : QP_SCALE_CR[currSlice->qs]))]; qp_rem_sp = p_Vid->qp_rem_matrix[ ((currSlice->qs < 0 ? currSlice->qs : QP_SCALE_CR[currSlice->qs]))]; q_bits_sp = Q_BITS + qp_per_sp; if (currSlice->slice_type == SI_SLICE) { qp_per = qp_per_sp; qp_rem = qp_rem_sp; } for (j=0; j < p_Vid->mb_cr_size_y; ++j) { for (i=0; i < p_Vid->mb_cr_size_x; ++i) { PBlock[j][i] = currSlice->mb_pred[uv + 1][j][i]; currSlice->mb_pred[uv + 1][j][i] = 0; } } for (n2=0; n2 < p_Vid->mb_cr_size_y; n2 += BLOCK_SIZE) { for (n1=0; n1 < p_Vid->mb_cr_size_x; n1 += BLOCK_SIZE) { forward4x4(PBlock, PBlock, n2, n1); } } // 2X2 transform of DC coeffs. mp1[0] = (PBlock[0][0] + PBlock[4][0] + PBlock[0][4] + PBlock[4][4]); mp1[1] = (PBlock[0][0] - PBlock[4][0] + PBlock[0][4] - PBlock[4][4]); mp1[2] = (PBlock[0][0] + PBlock[4][0] - PBlock[0][4] - PBlock[4][4]); mp1[3] = (PBlock[0][0] - PBlock[4][0] - PBlock[0][4] + PBlock[4][4]); if (p_Vid->sp_switch || currSlice->slice_type == SI_SLICE) { for (n2=0; n2 < 2; ++n2 ) { for (n1=0; n1 < 2; ++n1 ) { //quantization fo predicted block ilev = rshift_rnd_sf(iabs (mp1[n1+n2*2]) * quant_coef[qp_rem_sp][0][0], q_bits_sp + 1); //addition ilev = isignab(ilev, mp1[n1+n2*2]) + currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2][n1]][0][0]; //dequantization mp1[n1+n2*2] =ilev * dequant_coef[qp_rem_sp][0][0] << qp_per_sp; } } for (n2 = 0; n2 < p_Vid->mb_cr_size_y; n2 += BLOCK_SIZE) { for (n1 = 0; n1 < p_Vid->mb_cr_size_x; n1 += BLOCK_SIZE) { for (j = 0; j < BLOCK_SIZE; ++j) { for (i = 0; i < BLOCK_SIZE; ++i) { // recovering coefficient since they are already dequantized earlier currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2>>2][n1>>2]][j][i] = (currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2>>2][n1>>2]][j][i] >> qp_per) / dequant_coef[qp_rem][j][i]; //quantization of the predicted block ilev = rshift_rnd_sf(iabs(PBlock[n2 + j][n1 + i]) * quant_coef[qp_rem_sp][j][i], q_bits_sp); //addition of the residual ilev = isignab(ilev,PBlock[n2 + j][n1 + i]) + currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2>>2][n1>>2]][j][i] ; // Inverse quantization currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2>>2][n1>>2]][j][i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp; } } } } } else { for (n2=0; n2 < 2; ++n2 ) { for (n1=0; n1 < 2; ++n1 ) { ilev = mp1[n1+n2*2] + (((currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2][n1]][0][0] * dequant_coef[qp_rem][0][0] * A[0][0]) << qp_per) >> 5); ilev = isign(ilev) * rshift_rnd_sf(iabs(ilev) * quant_coef[qp_rem_sp][0][0], q_bits_sp + 1); //ilev = isignab(rshift_rnd_sf(iabs(ilev)* quant_coef[qp_rem_sp][0][0], q_bits_sp + 1), ilev); mp1[n1+n2*2] = ilev * dequant_coef[qp_rem_sp][0][0] << qp_per_sp; } } for (n2 = 0; n2 < p_Vid->mb_cr_size_y; n2 += BLOCK_SIZE) { for (n1 = 0; n1 < p_Vid->mb_cr_size_x; n1 += BLOCK_SIZE) { for (j = 0; j< BLOCK_SIZE; ++j) { for (i = 0; i< BLOCK_SIZE; ++i) { // recovering coefficient since they are already dequantized earlier icof = (currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2>>2][n1>>2]][j][i] >> qp_per) / dequant_coef[qp_rem][j][i]; //dequantization and addition of the predicted block ilev = PBlock[n2 + j][n1 + i] + ((icof * dequant_coef[qp_rem][j][i] * A[j][i] << qp_per) >> 6); //quantization and dequantization ilev = isign(ilev) * rshift_rnd_sf(iabs(ilev) * quant_coef[qp_rem_sp][j][i], q_bits_sp); currSlice->cof4[uv + 1][cof4_pos_to_subblock[n2>>2][n1>>2]][j][i] = ilev * dequant_coef[qp_rem_sp][j][i] << qp_per_sp; } } } } } currSlice->cof4[uv + 1][0][0][0] = (mp1[0] + mp1[1] + mp1[2] + mp1[3]) >> 1; currSlice->cof4[uv + 1][1][0][0] = (mp1[0] + mp1[1] - mp1[2] - mp1[3]) >> 1; currSlice->cof4[uv + 1][2][0][0] = (mp1[0] - mp1[1] + mp1[2] - mp1[3]) >> 1; currSlice->cof4[uv + 1][3][0][0] = (mp1[0] - mp1[1] - mp1[2] + mp1[3]) >> 1; free_mem2Dint(PBlock); } #if defined(_DEBUG) || !defined(_M_IX86) void iMBtrans4x4(Macroblock *currMB, ColorPlane pl, int smb) { Slice *currSlice = currMB->p_Slice; VideoParameters *p_Vid = currMB->p_Vid; StorablePicture *dec_picture = p_Vid->dec_picture; VideoImage *curr_img = pl ? dec_picture->imgUV[pl - 1]: dec_picture->imgY; // =============== 4x4 itrans ================ // ------------------------------------------- if (smb) { h264_short_block_t *blocks = currSlice->cof4[pl]; const h264_imgpel_macroblock_row_t *mb_pred=currSlice->mb_pred[pl]; itrans_sp(blocks[0], mb_pred, currMB, pl, 0, 0); itrans_sp(blocks[1], mb_pred, currMB, pl, 4, 0); itrans_sp(blocks[2], mb_pred, currMB, pl, 0, 4); itrans_sp(blocks[3], mb_pred, currMB, pl, 4, 4); itrans_sp(blocks[4], mb_pred, currMB, pl, 8, 0); itrans_sp(blocks[5], mb_pred, currMB, pl, 12, 0); itrans_sp(blocks[6], mb_pred, currMB, pl, 8, 4); itrans_sp(blocks[7], mb_pred, currMB, pl, 12, 4); itrans_sp(blocks[8], mb_pred, currMB, pl, 0, 8); itrans_sp(blocks[9], mb_pred, currMB, pl, 4, 8); itrans_sp(blocks[10], mb_pred, currMB, pl, 0, 12); itrans_sp(blocks[11], mb_pred, currMB, pl, 4, 12); itrans_sp(blocks[12], mb_pred, currMB, pl, 8, 8); itrans_sp(blocks[13], mb_pred, currMB, pl, 12, 8); itrans_sp(blocks[14], mb_pred, currMB, pl, 8, 12); itrans_sp(blocks[15], mb_pred, currMB, pl, 12, 12); } else if (currMB->is_lossless) { Inv_Residual_trans_4x4(currMB, pl, 0, 0); Inv_Residual_trans_4x4(currMB, pl, 4, 0); Inv_Residual_trans_4x4(currMB, pl, 0, 4); Inv_Residual_trans_4x4(currMB, pl, 4, 4); Inv_Residual_trans_4x4(currMB, pl, 8, 0); Inv_Residual_trans_4x4(currMB, pl, 12, 0); Inv_Residual_trans_4x4(currMB, pl, 8, 4); Inv_Residual_trans_4x4(currMB, pl, 12, 4); Inv_Residual_trans_4x4(currMB, pl, 0, 8); Inv_Residual_trans_4x4(currMB, pl, 4, 8); Inv_Residual_trans_4x4(currMB, pl, 0, 12); Inv_Residual_trans_4x4(currMB, pl, 4, 12); Inv_Residual_trans_4x4(currMB, pl, 8, 8); Inv_Residual_trans_4x4(currMB, pl, 12, 8); Inv_Residual_trans_4x4(currMB, pl, 8, 12); Inv_Residual_trans_4x4(currMB, pl, 12, 12); } else { const h264_short_block_t *blocks = currSlice->cof4[pl]; const h264_imgpel_macroblock_row_t *mb_pred=currSlice->mb_pred[pl]; h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; opt_itrans4x4(blocks[0], mb_pred, mb_rec, 0, 0); opt_itrans4x4(blocks[1], mb_pred, mb_rec, 4, 0); opt_itrans4x4(blocks[2], mb_pred, mb_rec, 0, 4); opt_itrans4x4(blocks[3], mb_pred, mb_rec, 4, 4); opt_itrans4x4(blocks[4], mb_pred, mb_rec, 8, 0); opt_itrans4x4(blocks[5], mb_pred, mb_rec, 12, 0); opt_itrans4x4(blocks[6], mb_pred, mb_rec, 8, 4); opt_itrans4x4(blocks[7], mb_pred, mb_rec, 12, 4); opt_itrans4x4(blocks[8], mb_pred, mb_rec, 0, 8); opt_itrans4x4(blocks[9], mb_pred, mb_rec, 4, 8); opt_itrans4x4(blocks[10], mb_pred, mb_rec, 0, 12); opt_itrans4x4(blocks[11], mb_pred, mb_rec, 4, 12); opt_itrans4x4(blocks[12], mb_pred, mb_rec, 8, 8); opt_itrans4x4(blocks[13], mb_pred, mb_rec, 12, 8); opt_itrans4x4(blocks[14], mb_pred, mb_rec, 8, 12); opt_itrans4x4(blocks[15], mb_pred, mb_rec, 12, 12); } // construct picture from 4x4 blocks opt_copy_image_data_16x16_stride(curr_img, currMB->pix_x, currMB->pix_y, currSlice->mb_rec[pl]); } #endif void iMBtrans8x8(Macroblock *currMB, ColorPlane pl) { Slice *currSlice = currMB->p_Slice; VideoParameters *p_Vid = currMB->p_Vid; StorablePicture *dec_picture = p_Vid->dec_picture; VideoImage *curr_img = pl ? dec_picture->imgUV[pl - 1] : dec_picture->imgY; h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; h264_imgpel_macroblock_row_t *mb_pred = currSlice->mb_pred[pl]; h264_short_8x8block_t *mb_rres8 = currSlice->mb_rres8[pl]; if (currMB->is_lossless == FALSE) { opt_itrans8x8(mb_rec, mb_pred, mb_rres8[0], 0); opt_itrans8x8(mb_rec, mb_pred, mb_rres8[1], 8); opt_itrans8x8(mb_rec+8, mb_pred+8, mb_rres8[2], 0); opt_itrans8x8(mb_rec+8, mb_pred+8, mb_rres8[3], 8); } else { itrans8x8_lossless(mb_rec, mb_pred, mb_rres8[0], 0); itrans8x8_lossless(mb_rec, mb_pred, mb_rres8[1], 8); itrans8x8_lossless(mb_rec+8, mb_pred+8, mb_rres8[2], 0); itrans8x8_lossless(mb_rec+8, mb_pred+8, mb_rres8[3], 8); } opt_copy_image_data_16x16_stride(curr_img, currMB->pix_x, currMB->pix_y, mb_rec); } void iTransform(Macroblock *currMB, ColorPlane pl, int smb) { Slice *currSlice = currMB->p_Slice; VideoParameters *p_Vid = currMB->p_Vid; StorablePicture *dec_picture = p_Vid->dec_picture; int uv = pl-1; if ((currMB->cbp & 15) != 0 || smb) { if(currMB->luma_transform_size_8x8_flag == 0) // 4x4 inverse transform { iMBtrans4x4(currMB, pl, smb); } else // 8x8 inverse transform { iMBtrans8x8(currMB, pl); } } else { VideoImage *curr_img = pl ? dec_picture->imgUV[uv] : dec_picture->imgY; opt_copy_image_data_16x16_stride(curr_img, currMB->pix_x, currMB->pix_y, currSlice->mb_pred[pl]); } // TODO: fix 4x4 lossless if (dec_picture->chroma_format_idc == YUV420) { VideoImage *curUV; for(uv=0;uv<2;++uv) { int pl = uv + 1; const h264_imgpel_macroblock_row_t *mb_pred=currSlice->mb_pred[pl]; // =============== 4x4 itrans ================ // ------------------------------------------- curUV = dec_picture->imgUV[uv]; if (!smb && (currMB->cbp>>4)) { if (currMB->is_lossless == FALSE) { const h264_short_block_t *blocks = currSlice->cof4[pl]; h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; opt_itrans4x4(blocks[0], mb_pred, mb_rec, 0, 0); opt_itrans4x4(blocks[1], mb_pred, mb_rec, 4, 0); opt_itrans4x4(blocks[2], mb_pred, mb_rec, 0, 4); opt_itrans4x4(blocks[3], mb_pred, mb_rec, 4, 4); copy_image_data_8x8_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_rec); } else { // lossless const h264_short_block_t *blocks = currSlice->cof4[pl]; h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; itrans4x4_ls(blocks[0], mb_pred, mb_rec, 0, 0); itrans4x4_ls(blocks[1], mb_pred, mb_rec, 4, 0); itrans4x4_ls(blocks[2], mb_pred, mb_rec, 0, 4); itrans4x4_ls(blocks[3], mb_pred, mb_rec, 4, 4); copy_image_data_8x8_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_rec); } } else if (smb) { const h264_short_block_t *blocks = currSlice->cof4[pl]; h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; itrans_sp_cr(currMB, uv); opt_itrans4x4(blocks[0], mb_pred, mb_rec, 0, 0); opt_itrans4x4(blocks[1], mb_pred, mb_rec, 4, 0); opt_itrans4x4(blocks[2], mb_pred, mb_rec, 0, 4); opt_itrans4x4(blocks[3], mb_pred, mb_rec, 4, 4); copy_image_data_8x8_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_rec); } else { copy_image_data_8x8_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_pred); } } } else if (dec_picture->chroma_format_idc == YUV422) { VideoImage *curUV; for(uv=0;uv<2;++uv) { // =============== 4x4 itrans ================ // ------------------------------------------- int pl = uv + 1; const h264_imgpel_macroblock_row_t *mb_pred=currSlice->mb_pred[pl]; curUV = dec_picture->imgUV[uv]; if (!smb && (currMB->cbp>>4)) { h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; const h264_short_block_t *blocks = currSlice->cof4[pl]; opt_itrans4x4(blocks[0], mb_pred, mb_rec, 0, 0); opt_itrans4x4(blocks[1], mb_pred, mb_rec, 4, 0); opt_itrans4x4(blocks[2], mb_pred, mb_rec, 0, 4); opt_itrans4x4(blocks[3], mb_pred, mb_rec, 4, 4); opt_itrans4x4(blocks[8], mb_pred, mb_rec, 0, 8); opt_itrans4x4(blocks[9], mb_pred, mb_rec, 4, 8); opt_itrans4x4(blocks[10], mb_pred, mb_rec, 0, 12); opt_itrans4x4(blocks[11], mb_pred, mb_rec, 4, 12); copy_image_data_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_rec, 8, 16); } else if (smb) { const h264_short_block_t *blocks = currSlice->cof4[pl]; h264_imgpel_macroblock_row_t *mb_rec = currSlice->mb_rec[pl]; itrans_sp_cr(currMB, uv); opt_itrans4x4(blocks[0], mb_pred, mb_rec, 0, 0); opt_itrans4x4(blocks[1], mb_pred, mb_rec, 4, 0); opt_itrans4x4(blocks[2], mb_pred, mb_rec, 0, 4); opt_itrans4x4(blocks[3], mb_pred, mb_rec, 4, 4); opt_itrans4x4(blocks[8], mb_pred, mb_rec, 0, 8); opt_itrans4x4(blocks[9], mb_pred, mb_rec, 4, 8); opt_itrans4x4(blocks[10], mb_pred, mb_rec, 0, 12); opt_itrans4x4(blocks[11], mb_pred, mb_rec, 4, 12); copy_image_data_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_rec, 8, 16); } else { copy_image_data_stride(curUV,currMB->pix_c_x, currMB->pix_c_y, mb_pred, 8, 16); } } } } /*! ************************************************************************************* * \brief * Copy ImgPel Data from one structure to another (16x16) ************************************************************************************* */ void copy_image_data_16x16(imgpel **imgBuf1, imgpel **imgBuf2, int dest_x, int src_x) { int j; for(j=0; jstride; // in case the compiler doesn't optimize this imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; _asm { mov eax, dest mov ecx, destination_stride mov edx, source; movaps xmm0, 0[edx] movaps xmm1, 16[edx] movaps xmm2, 32[edx] movaps xmm3, 64[edx] movups [eax], xmm0 // dest[0] movups [eax+ecx], xmm1 // dest[1] movups [eax+2*ecx], xmm2 // dest[2] movups [eax+4*ecx], xmm3 // dest[4] movaps xmm0, 48[edx] movaps xmm1, 96[edx] lea eax, [eax+2*ecx] // dest = &dest[2] movups [eax+ecx], xmm0 // dest[3] movups [eax+4*ecx], xmm1 // dest[6] movaps xmm0, 80[edx] movaps xmm1, 128[edx] lea eax, [eax+2*ecx] // dest = &dest[2] (dest[4] from start) movups [eax+ecx], xmm0 // dest[5] movups [eax+4*ecx], xmm1 // dest[8] movaps xmm0, 112[edx] movaps xmm1, 160[edx] lea eax, [eax+2*ecx] // dest = &dest[2] (dest[6] from start) movups [eax+ecx], xmm0 // dest[7] movups [eax+4*ecx], xmm1 // dest[10] movaps xmm0, 144[edx] movaps xmm1, 192[edx] lea eax, [eax+2*ecx] // dest = &dest[2] (dest[8] from start) movups [eax+ecx], xmm0 // dest[9] movups [eax+4*ecx], xmm1 // dest[12] movaps xmm0, 176[edx] movaps xmm1, 224[edx] lea eax, [eax+2*ecx] // dest = &dest[2] (dest[10] from start) movups [eax+ecx], xmm0 // dest[11] movups [eax+4*ecx], xmm1 // dest[14] movaps xmm0, 208[edx] movaps xmm1, 240[edx] lea eax, [eax+ecx] // dest = &dest[1] (dest[11] from start) movups [eax+2*ecx], xmm0 // dest[13] movups [eax+4*ecx], xmm1 // dest[15] } } #endif void copy_image_data_16x16_stride_c(VideoImage *destination, int dest_x, int dest_y, const h264_imgpel_macroblock_t source) { ptrdiff_t destination_stride = destination->stride; // in case the compiler doesn't optimize this imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; int j; for(j=0; jstride; imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; _asm { mov eax, src_y shl eax, 4 add eax, src_x add eax, imgBuf2 mov edx, dest mov ecx, destination_stride movq mm0, MMWORD PTR 0[eax] movq mm1, MMWORD PTR 16[eax] movq mm2, MMWORD PTR 32[eax] movq mm3, MMWORD PTR 48[eax] movq mm4, MMWORD PTR 64[eax] movq mm5, MMWORD PTR 80[eax] movq mm6, MMWORD PTR 96[eax] movq mm7, MMWORD PTR 112[eax] movntq [edx], mm0 movntq [edx+ecx], mm1 movntq [edx+2*ecx], mm2 movntq [edx+4*ecx], mm4 add edx, ecx movntq 0[edx+2*ecx], mm3 movntq 0[edx+4*ecx], mm5 add edx, ecx movntq 0[edx+4*ecx], mm6 add edx, ecx movntq 0[edx+4*ecx], mm7 } #else ptrdiff_t destination_stride = destination->stride; // in case the compiler doesn't optimize this imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; int j; for(j = 0; j < BLOCK_SIZE_8x8; ++j) { memcpy(dest, &imgBuf2[src_y+j][src_x], BLOCK_SIZE_8x8 * sizeof (imgpel)); dest+=destination_stride; } #endif } void copy_image_data_8x8_stride(VideoImage *destination, int dest_x, int dest_y, const h264_imgpel_macroblock_t imgBuf2) { #ifdef _M_IX86 ptrdiff_t destination_stride = destination->stride; imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; _asm { mov eax, imgBuf2 mov edx, dest mov ecx, destination_stride movq mm0, MMWORD PTR 0[eax] movq mm1, MMWORD PTR 16[eax] movq mm2, MMWORD PTR 32[eax] movq mm3, MMWORD PTR 48[eax] movq mm4, MMWORD PTR 64[eax] movq mm5, MMWORD PTR 80[eax] movq mm6, MMWORD PTR 96[eax] movq mm7, MMWORD PTR 112[eax] movntq [edx], mm0 movntq [edx+ecx], mm1 movntq [edx+2*ecx], mm2 movntq [edx+4*ecx], mm4 add edx, ecx movntq 0[edx+2*ecx], mm3 movntq 0[edx+4*ecx], mm5 add edx, ecx movntq 0[edx+4*ecx], mm6 add edx, ecx movntq 0[edx+4*ecx], mm7 } #else ptrdiff_t destination_stride = destination->stride; // in case the compiler doesn't optimize this imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; int j; for(j = 0; j < BLOCK_SIZE_8x8; ++j) { memcpy(dest, &imgBuf2[j][0], BLOCK_SIZE_8x8 * sizeof (imgpel)); dest+=destination_stride; } #endif } /*! ************************************************************************************* * \brief * Copy ImgPel Data from one structure to another (4x4) ************************************************************************************* */ void copy_image_data_4x4_stride(VideoImage *destination, int dest_x, int dest_y, const h264_imgpel_macroblock_t source, int src_x, int src_y) { ptrdiff_t destination_stride = destination->stride; // in case the compiler doesn't optimize this imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; h264_imgpel_macroblock_row_t *src = (h264_imgpel_macroblock_row_t *)source[src_y]; /* cast is for const */ int j; for(j = 0; j < BLOCK_SIZE; ++j) { memcpy(dest, &src[j][src_x], BLOCK_SIZE * sizeof (imgpel)); dest+=destination_stride; } } /*! ************************************************************************************* * \brief * Copy ImgPel Data from one structure to another (8x8) ************************************************************************************* */ void copy_image_data(imgpel **imgBuf1, imgpel **imgBuf2, int dest_x, int src_x, int width, int height) { int j; for(j = 0; j < height; ++j) { memcpy(&imgBuf1[j][dest_x], &imgBuf2[j][src_x], width * sizeof (imgpel)); } } void copy_image_data_stride(VideoImage *destination, int dest_x, int dest_y, const h264_imgpel_macroblock_t imgBuf2, int width, int height) { ptrdiff_t destination_stride = destination->stride; // in case the compiler doesn't optimize this imgpel *dest = destination->base_address + destination_stride * dest_y + dest_x; #ifdef H264_IPP IppiSize roi = {width,height}; ippiCopy_8u_C1R(imgBuf2[0], sizeof(imgBuf2[0]), dest, destination_stride, roi); #else int j; for(j = 0; j < height; ++j) { memcpy(dest, imgBuf2[j], width * sizeof (imgpel)); dest+=destination_stride; } #endif }