decoder.cpp

来自「gaca源码」· C++ 代码 · 共 1,447 行 · 第 1/4 页

CPP
1,447
字号
         dc_dif = dc_size ? bs->get_dc_dif(dc_size) : 0;

         if (dc_size > 8) {
            bs->Skip(1);   /* marker */
         }

         block[i * 64 + 0] = dc_dif;
         start_coeff = 1;

         DPRINTF(XVID_DEBUG_COEFF,"block[0] %i\n", dc_dif);
         PROF_E(PROF_1);
      }else{
         start_coeff = 0;
      }
      if(cbp & (1 << (5 - i))){
                              //coded
         int direction = alternate_vertical_scan ? 2 : pMB->acpred_directions[i];
         get_intra_block(bs, &block[i * 64], direction, start_coeff);
      }
      add_acdc(pMB, i, &block[i * 64], iDcScaler, predictors);
      if(quant_type == 0){
         dequant_h263_intra(&data[i * 64], &block[i * 64], iQuant, iDcScaler, mpeg_quant_matrices);
      }else{
         dequant_mpeg_intra(&data[i * 64], &block[i * 64], iQuant, iDcScaler, mpeg_quant_matrices);
      }
      InverseDiscreteCosineTransform(&data[i * 64]);
   }

   dword next_block = stride * 8;
   if(interlacing && pMB->field_dct){
      next_block = stride;
      stride *= 2;
   }
   if(reduced_resolution){
      next_block*=2;
      copy_upsampled_8x8_16to8(pY_Cur, &data[0 * 64], stride);
      copy_upsampled_8x8_16to8(pY_Cur + 16, &data[1 * 64], stride);
      copy_upsampled_8x8_16to8(pY_Cur + next_block, &data[2 * 64], stride);
      copy_upsampled_8x8_16to8(pY_Cur + 16 + next_block, &data[3 * 64], stride);
      copy_upsampled_8x8_16to8(pU_Cur, &data[4 * 64], stride2);
      copy_upsampled_8x8_16to8(pV_Cur, &data[5 * 64], stride2);
   }else{
      transfer_16to8copy(pY_Cur, &data[0 * 64], stride);
      transfer_16to8copy(pY_Cur + 8, &data[1 * 64], stride);
      transfer_16to8copy(pY_Cur + next_block, &data[2 * 64], stride);
      transfer_16to8copy(pY_Cur + 8 + next_block, &data[3 * 64], stride);
      transfer_16to8copy(pU_Cur, &data[4 * 64], stride2);
      transfer_16to8copy(pV_Cur, &data[5 * 64], stride2);
   }
}

//----------------------------

void S_decoder::mb_decode(const dword cbp, Bitstream * bs, byte * pY_Cur, byte * pU_Cur, byte * pV_Cur, bool reduced_resolution, const MACROBLOCK *pMB){

   DECLARE_ALIGNED_MATRIX(block, 1, 64, int, CACHE_LINE);
   DECLARE_ALIGNED_MATRIX(data, 6, 64, int, CACHE_LINE);

   int i;
   int stride = edged_width;
   const int stride2 = stride/2;

   const dword iQuant = pMB->quant;
   const int direction = alternate_vertical_scan ? 2 : 0;
   const quant_interFuncPtr dequant = quant_type == 0 ? dequant_h263_inter : dequant_mpeg_inter;
   for(i = 0; i < 6; i++){
      if(cbp & (1 << (5 - i))){
                              //coded
         XVID_ClearMatrix(block);
         get_inter_block(bs, block, direction);
         dequant(&data[i * 64], block, iQuant, mpeg_quant_matrices);
         InverseDiscreteCosineTransform(&data[i * 64]);
      }
   }

   int next_block = stride * (reduced_resolution ? 16 : 8);
   if(interlacing && pMB->field_dct){
      next_block = stride;
      stride *= 2;
   }

   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);
   }
}

//----------------------------

void S_decoder::DecodeInterMacroBlock(const MACROBLOCK * pMB, dword x_pos, dword y_pos, dword cbp, Bitstream *bs,
   bool rounding, bool reduced_resolution, int ref){

   dword stride = edged_width;
   dword stride2 = stride / 2;
   dword i;

   byte *pY_Cur, *pU_Cur, *pV_Cur;

   int uv_dx, uv_dy;
   VECTOR mv[4];              //local copy of mvs

   if(reduced_resolution){
      pY_Cur = cur.y + (y_pos << 5) * stride + (x_pos << 5);
      pU_Cur = cur.u + (y_pos << 4) * stride2 + (x_pos << 4);
      pV_Cur = 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 = cur.y + (y_pos << 4) * stride + (x_pos << 4);
      pU_Cur = cur.u + (y_pos << 3) * stride2 + (x_pos << 3);
      pV_Cur = cur.v + (y_pos << 3) * stride2 + (x_pos << 3);
      for(i = 0; i < 4; i++)
         mv[i] = pMB->mvs[i];
   }

   if(pMB->mode != MODE_INTER4V){
                              //INTER, INTER_Q, NOT_CODED, FORWARD, BACKWARD

      uv_dx = mv[0].x;
      uv_dy = mv[0].y;
      if (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(cur.y, refn[0].y, 32*x_pos, 32*y_pos, mv[0].x, mv[0].y, stride, rounding);
      else
      if(quarterpel)
         interpolate16x16_quarterpel(cur.y, refn[ref].y, qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding);
      else
         interpolate16x16_switch(cur.y, refn[ref].y, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding);
   }else{
                              //MODE_INTER4V

      if(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(cur.y, refn[0].y, 32*x_pos,      32*y_pos,      mv[0].x, mv[0].y, stride, rounding);
         interpolate16x16_switch(cur.y, refn[0].y, 32*x_pos + 16, 32*y_pos,      mv[1].x, mv[1].y, stride, rounding);
         interpolate16x16_switch(cur.y, refn[0].y, 32*x_pos,      32*y_pos + 16, mv[2].x, mv[2].y, stride, rounding);
         interpolate16x16_switch(cur.y, refn[0].y, 32*x_pos + 16, 32*y_pos + 16, mv[3].x, mv[3].y, stride, rounding);
         interpolate16x16_switch(cur.u, refn[0].u, 16*x_pos,      16*y_pos,      uv_dx,   uv_dy,   stride2, rounding);
         interpolate16x16_switch(cur.v, refn[0].v, 16*x_pos,      16*y_pos,      uv_dx,   uv_dy,   stride2, rounding);
      }else
      if(quarterpel){
         interpolate8x8_quarterpel(cur.y, refn[0].y , qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding);
         interpolate8x8_quarterpel(cur.y, refn[0].y , qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos + 8, 16*y_pos, mv[1].x, mv[1].y, stride, rounding);
         interpolate8x8_quarterpel(cur.y, refn[0].y , qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos, 16*y_pos + 8, mv[2].x, mv[2].y, stride, rounding);
         interpolate8x8_quarterpel(cur.y, refn[0].y , qtmp.y, qtmp.y + 64, qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8, mv[3].x, mv[3].y, stride, rounding);
      } else {
         interpolate8x8_switch(cur.y, refn[0].y , 16*x_pos, 16*y_pos, mv[0].x, mv[0].y, stride, rounding);
         interpolate8x8_switch(cur.y, refn[0].y , 16*x_pos + 8, 16*y_pos, mv[1].x, mv[1].y, stride, rounding);
         interpolate8x8_switch(cur.y, refn[0].y , 16*x_pos, 16*y_pos + 8, mv[2].x, mv[2].y, stride, rounding);
         interpolate8x8_switch(cur.y, 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(cur.u, refn[0].u, 16*x_pos, 16*y_pos, uv_dx, uv_dy, stride2, rounding);
      interpolate16x16_switch(cur.v, refn[0].v, 16*x_pos, 16*y_pos, uv_dx, uv_dy, stride2, rounding);
   }else{
      interpolate8x8_switch(cur.u, refn[ref].u,  8*x_pos,  8*y_pos, uv_dx, uv_dy, stride2, rounding);
      interpolate8x8_switch(cur.v, refn[ref].v,  8*x_pos,  8*y_pos, uv_dx, uv_dy, stride2, rounding);
   }
   if(cbp)
      mb_decode(cbp, bs, pY_Cur, pU_Cur, pV_Cur, reduced_resolution, pMB);
}

//----------------------------

inline int gmc_sanitize(int value, int quarterpel, int fcode){

   int length = 1 << (fcode+4);

#if 0
   if (quarterpel) value *= 2;
#endif

   if (value < -length)
      return -length;
   else if (value >= length)
      return length-1;
   else return value;
}

//----------------------------

void S_decoder::mbgmc(MACROBLOCK *pMB, dword x_pos, dword y_pos, dword fcode, dword cbp, Bitstream * bs, bool rounding){

   const dword stride = edged_width;
   const dword stride2 = stride / 2;

   byte *const pY_Cur=cur.y + (y_pos << 4) * stride + (x_pos << 4);
   byte *const pU_Cur=cur.u + (y_pos << 3) * stride2 + (x_pos << 3);
   byte *const pV_Cur=cur.v + (y_pos << 3) * stride2 + (x_pos << 3);

   NEW_GMC_DATA *gmc_data = &new_gmc_data;

   pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv;

                              //this is where the calculations are done
   gmc_data->predict_16x16(gmc_data, cur.y + y_pos*16*stride + x_pos*16, refn[0].y, stride, stride, x_pos, y_pos, rounding);
   gmc_data->predict_8x8(gmc_data, cur.u + y_pos*8*stride2 + x_pos*8, refn[0].u, cur.v + y_pos*8*stride2 + x_pos*8, refn[0].v, stride2, stride2, x_pos, y_pos, rounding);
   gmc_data->get_average_mv(gmc_data, &pMB->amv, x_pos, y_pos, quarterpel);

   pMB->amv.x = gmc_sanitize(pMB->amv.x, quarterpel, fcode);
   pMB->amv.y = gmc_sanitize(pMB->amv.y, quarterpel, fcode);

   pMB->mvs[0] = pMB->mvs[1] = pMB->mvs[2] = pMB->mvs[3] = pMB->amv;

   if(cbp)
      mb_decode(cbp, bs, pY_Cur, pU_Cur, pV_Cur, 0, pMB);
}

//----------------------------

void S_decoder::I_Frame(Bitstream * bs, bool reduced_resolution, int quant, int intra_dc_threshold){

   dword bound;
   dword x, y;
   //dword mb_width = mb_width;
   //dword mb_height = mb_height;

   if (reduced_resolution) {
      mb_width = (width + 31) / 32;
      mb_height = (height + 31) / 32;
   }

   bound = 0;

   for (y = 0; y < mb_height; y++) {
      for (x = 0; x < mb_width; x++) {
         dword mcbpc;
         dword cbpc;
         dword acpred_flag;
         dword cbpy;
         dword cbp;

         while(bs->ShowBits(9) == 1)
            bs->Skip(9);

         if(bs->check_resync_marker(0)){
            bound = read_video_packet_header(bs, 0, &quant, NULL, NULL, &intra_dc_threshold);
            x = bound % mb_width;
            y = bound / mb_width;
         }
         MACROBLOCK *mb = &mbs[y * mb_width + x];

         //DPRINTF(XVID_DEBUG_MB, "macroblock (%i,%i) %08x\n", x, y, bs->ShowBits(32));

         mcbpc = bs->get_mcbpc_intra();
         mb->mode = mcbpc & 7;
         cbpc = (mcbpc >> 4);

         acpred_flag = bs->GetBit();

         cbpy = bs->GetCbpy(1);
         cbp = (cbpy << 2) | cbpc;

         if (mb->mode == MODE_INTRA_Q) {
            quant += dquant_table[bs->GetBits(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(interlacing){
            mb->field_dct = bs->GetBit();
            DPRINTF(XVID_DEBUG_MB,"deci: field_dct: %i\n", mb->field_dct);
         }
         MBIntra(mb, x, y, acpred_flag, cbp, bs, quant, intra_dc_threshold, bound, reduced_resolution);
      }
      /*
#ifdef XVID_CSP_SLICE
      if(out_frm)
         output_slice(&cur, edged_width,width,out_frm,0,y,mb_width);
#endif
         */
   }
}

//----------------------------

void S_decoder::GetMotionVector(Bitstream * bs, int x, int y, int k, VECTOR *ret_mv, int fcode, 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(mbs, mb_width, bound, x, y, k);
   VECTOR mv;

   mv.x = bs->GetMoveVector(fcode);
   mv.y = bs->GetMoveVector(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;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?