⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 decoder.c

📁 xvid解码的精简版本.非常好的版本,节省了分离xvid源代码的过程
💻 C
📖 第 1 页 / 共 4 页
字号:
      mv.x-=range;    }    if (mv.y < low) {      mv.y += range;    } else if (mv.y > high) {      mv.y -= range;    }        pMB->mvs[0]=pMB->mvs[1]=pMB->mvs[2]=pMB->mvs[3]=mv;  }  else  {    mvf1.x = get_mv(bs, fcode);    mvf1.y = get_mv(bs, fcode);    mvf1.x += pmv.x;    mvf1.y = 2*(mvf1.y+pmv.y/2); /* It's multiple of 2 */    if (mvf1.x < low) {      mvf1.x += range;    } else if (mvf1.x > high) {      mvf1.x -= range;    }    if (mvf1.y < low) {      mvf1.y += range;    } else if (mvf1.y > high) {      mvf1.y -= range;    }    mvf2.x = get_mv(bs, fcode);    mvf2.y = get_mv(bs, fcode);    mvf2.x += pmv.x;    mvf2.y = 2*(mvf2.y+pmv.y/2); /* It's multiple of 2 */    if (mvf2.x < low) {      mvf2.x += range;    } else if (mvf2.x > high) {      mvf2.x -= range;    }    if (mvf2.y < low) {      mvf2.y += range;    } else if (mvf2.y > high) {      mvf2.y -= range;    }    pMB->mvs[0]=mvf1;    pMB->mvs[1]=mvf2;    pMB->mvs[2].x=pMB->mvs[3].x=0;    pMB->mvs[2].y=pMB->mvs[3].y=0;      /* Calculate average for as it is field predicted */    pMB->mvs_avg.x=DIV2ROUND(pMB->mvs[0].x+pMB->mvs[1].x);    pMB->mvs_avg.y=DIV2ROUND(pMB->mvs[0].y+pMB->mvs[1].y);  }}/* for P_VOP set gmc_warp to NULL */static voiddecoder_pframe(DECODER * dec,        Bitstream * bs,        int rounding,        int quant,        int fcode,        int intra_dc_threshold,        const WARPPOINTS *const gmc_warp){  uint32_t x, y;  uint32_t bound;  int cp_mb, st_mb;  const uint32_t mb_width = dec->mb_width;  const uint32_t mb_height = dec->mb_height;  if (!dec->is_edged[0]) {    image_setedges(&dec->refn[0], dec->edged_width, dec->edged_height,            dec->width, dec->height, dec->bs_version);    dec->is_edged[0] = 1;     }  if (gmc_warp) {    /* accuracy: 0==1/2, 1=1/4, 2=1/8, 3=1/16 */    generate_GMCparameters( dec->sprite_warping_points,        dec->sprite_warping_accuracy, gmc_warp,        dec->width, dec->height, &dec->new_gmc_data);    /* image warping is done block-based in decoder_mbgmc(), now */  }  bound = 0;  for (y = 0; y < mb_height; y++) {    cp_mb = st_mb = 0;    for (x = 0; x < 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, dec, fcode - 1,          &quant, &fcode, 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));      if (!(BitstreamGetBit(bs))) { /* block _is_ coded */        uint32_t mcbpc, cbpc, cbpy, cbp;        uint32_t intra, acpred_flag = 0;        int mcsel = 0;    /* mcsel: '0'=local motion, '1'=GMC */        cp_mb++;        mcbpc = get_mcbpc_inter(bs);        mb->mode = mcbpc & 7;        cbpc = (mcbpc >> 4);        DPRINTF(XVID_DEBUG_MB, "mode %i\n", mb->mode);        DPRINTF(XVID_DEBUG_MB, "cbpc %i\n", cbpc);        intra = (mb->mode == MODE_INTRA || mb->mode == MODE_INTRA_Q);        if (gmc_warp && (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q))          mcsel = BitstreamGetBit(bs);        else if (intra)          acpred_flag = BitstreamGetBit(bs);        cbpy = get_cbpy(bs, intra);        DPRINTF(XVID_DEBUG_MB, "cbpy %i mcsel %i \n", cbpy,mcsel);        cbp = (cbpy << 2) | cbpc;        if (mb->mode == MODE_INTER_Q || mb->mode == MODE_INTRA_Q) {          int dquant = dquant_table[BitstreamGetBits(bs, 2)];          DPRINTF(XVID_DEBUG_MB, "dquant %i\n", dquant);          quant += dquant;          if (quant > 31) {            quant = 31;          } else if (quant < 1) {            quant = 1;          }          DPRINTF(XVID_DEBUG_MB, "quant %i\n", quant);        }        mb->quant = quant;         mb->field_pred=0;        if (dec->interlacing) {          if (cbp || intra) {            mb->field_dct = BitstreamGetBit(bs);            DPRINTF(XVID_DEBUG_MB,"decp: field_dct: %i\n", mb->field_dct);          }          if ((mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) && !mcsel) {            mb->field_pred = BitstreamGetBit(bs);            DPRINTF(XVID_DEBUG_MB, "decp: field_pred: %i\n", mb->field_pred);            if (mb->field_pred) {              mb->field_for_top = BitstreamGetBit(bs);              DPRINTF(XVID_DEBUG_MB,"decp: field_for_top: %i\n", mb->field_for_top);              mb->field_for_bot = BitstreamGetBit(bs);              DPRINTF(XVID_DEBUG_MB,"decp: field_for_bot: %i\n", mb->field_for_bot);            }          }        }        if (mcsel) {          decoder_mbgmc(dec, mb, x, y, fcode, cbp, bs, rounding);          continue;        } else if (mb->mode == MODE_INTER || mb->mode == MODE_INTER_Q) {          if(dec->interlacing) {            /* Get motion vectors interlaced, field_pred is handled there */            get_motion_vector_interlaced(dec, bs, x, y, 0, mb, fcode, bound);          } else {            get_motion_vector(dec, bs, x, y, 0, &mb->mvs[0], fcode, bound);            mb->mvs[1] = mb->mvs[2] = mb->mvs[3] = mb->mvs[0];          }        } else if (mb->mode == MODE_INTER4V ) {          /* interlaced missing here */          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;        }        /* See how to decode */        if(!mb->field_pred)         decoder_mbinter(dec, mb, x, y, cbp, bs, rounding, 0, 0);        else          decoder_mbinter_field(dec, mb, x, y, cbp, bs, rounding, 0, 0);      } else if (gmc_warp) {  /* a not coded S(GMC)-VOP macroblock */        mb->mode = MODE_NOT_CODED_GMC;        mb->quant = quant;        decoder_mbgmc(dec, mb, x, y, fcode, 0x00, bs, rounding);        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;      } else { /* not coded P_VOP macroblock */        mb->mode = MODE_NOT_CODED;        mb->quant = quant;        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;        mb->field_pred=0; /* (!) */        decoder_mbinter(dec, mb, x, y, 0, bs,                                 rounding, 0, 0);        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);  }}/* decode B-frame motion vector */static voidget_b_motion_vector(Bitstream * bs,          VECTOR * mv,          int fcode,          const VECTOR pmv,          const DECODER * const dec,          const int x, const int y){  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);  int mv_x = get_mv(bs, fcode);  int mv_y = get_mv(bs, fcode);  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;}/* decode an B-frame direct & interpolate macroblock */static voiddecoder_bf_interpolate_mbinter(DECODER * dec,                IMAGE forward,                IMAGE backward,                MACROBLOCK * pMB,                const uint32_t x_pos,                const uint32_t y_pos,                Bitstream * bs,                const int direct){  uint32_t stride = dec->edged_width;  uint32_t stride2 = stride / 2;  int uv_dx, uv_dy;  int b_uv_dx, b_uv_dy;  uint8_t *pY_Cur, *pU_Cur, *pV_Cur;  const uint32_t cbp = pMB->cbp;  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);  validate_vector(pMB->mvs, x_pos, y_pos, dec);  validate_vector(pMB->b_mvs, x_pos, y_pos, dec);  if (!direct) {    uv_dx = pMB->mvs[0].x;    uv_dy = pMB->mvs[0].y;    b_uv_dx = pMB->b_mvs[0].x;    b_uv_dy = pMB->b_mvs[0].y;    if (dec->quarterpel) {			if (dec->bs_version <= BS_VERSION_BUGGY_CHROMA_ROUNDING) {				uv_dx = (uv_dx>>1) | (uv_dx&1);				uv_dy = (uv_dy>>1) | (uv_dy&1);				b_uv_dx = (b_uv_dx>>1) | (b_uv_dx&1);				b_uv_dy = (b_uv_dy>>1) | (b_uv_dy&1);			}			else {        uv_dx /= 2;        uv_dy /= 2;        b_uv_dx /= 2;        b_uv_dy /= 2;      }    }    uv_dx = (uv_dx >> 1) + roundtab_79[uv_dx & 0x3];    uv_dy = (uv_dy >> 1) + roundtab_79[uv_dy & 0x3];    b_uv_dx = (b_uv_dx >> 1) + roundtab_79[b_uv_dx & 0x3];    b_uv_dy = (b_uv_dy >> 1) + roundtab_79[b_uv_dy & 0x3];  } else {	  if (dec->quarterpel) { /* for qpel the /2 shall be done before summation. We've done it right in the encoder in the past. */							 /* TODO: figure out if we ever did it wrong on the encoder side. If yes, add some workaround */		if (dec->bs_version <= BS_VERSION_BUGGY_CHROMA_ROUNDING) {			int z;			uv_dx = 0; uv_dy = 0;			b_uv_dx = 0; b_uv_dy = 0;			for (z = 0; z < 4; z++) {			  uv_dx += ((pMB->mvs[z].x>>1) | (pMB->mvs[z].x&1));			  uv_dy += ((pMB->mvs[z].y>>1) | (pMB->mvs[z].y&1));			  b_uv_dx += ((pMB->b_mvs[z].x>>1) | (pMB->b_mvs[z].x&1));			  b_uv_dy += ((pMB->b_mvs[z].y>>1) | (pMB->b_mvs[z].y&1));			}		}		else {			uv_dx = (pMB->mvs[0].x / 2) + (pMB->mvs[1].x / 2) + (pMB->mvs[2].x / 2) + (pMB->mvs[3].x / 2);			uv_dy = (pMB->mvs[0].y / 2) + (pMB->mvs[1].y / 2) + (pMB->mvs[2].y / 2) + (pMB->mvs[3].y / 2);			b_uv_dx = (pMB->b_mvs[0].x / 2) + (pMB->b_mvs[1].x / 2) + (pMB->b_mvs[2].x / 2) + (pMB->b_mvs[3].x / 2);			b_uv_dy = (pMB->b_mvs[0].y / 2) + (pMB->b_mvs[1].y / 2) + (pMB->b_mvs[2].y / 2) + (pMB->b_mvs[3].y / 2);		} 	} else {      uv_dx = pMB->mvs[0].x + pMB->mvs[1].x + pMB->mvs[2].x + pMB->mvs[3].x;      uv_dy = pMB->mvs[0].y + pMB->mvs[1].y + pMB->mvs[2].y + pMB->mvs[3].y;      b_uv_dx = pMB->b_mvs[0].x + pMB->b_mvs[1].x + pMB->b_mvs[2].x + pMB->b_mvs[3].x;      b_uv_dy = pMB->b_mvs[0].y + pMB->b_mvs[1].y + pMB->b_mvs[2].y + pMB->b_mvs[3].y;    }    uv_dx = (uv_dx >> 3) + roundtab_76[uv_dx & 0xf];    uv_dy = (uv_dy >> 3) + roundtab_76[uv_dy & 0xf];    b_uv_dx = (b_uv_dx >> 3) + roundtab_76[b_uv_dx & 0xf];    b_uv_dy = (b_uv_dy >> 3) + roundtab_76[b_uv_dy & 0xf];  }  if(dec->quarterpel) {    if(!direct) {      interpolate16x16_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,                    dec->qtmp.y + 128, 16*x_pos, 16*y_pos,                    pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);    } else {      interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,                    dec->qtmp.y + 128, 16*x_pos, 16*y_pos,                    pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);      interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,                    dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos,                    pMB->mvs[1].x, pMB->mvs[1].y, stride, 0);      interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,                    dec->qtmp.y + 128, 16*x_pos, 16*y_pos + 8,                    pMB->mvs[2].x, pMB->mvs[2].y, stride, 0);      interpolate8x8_quarterpel(dec->cur.y, forward.y, dec->qtmp.y, dec->qtmp.y + 64,                    dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8,                    pMB->mvs[3].x, pMB->mvs[3].y, stride, 0);    }  } else {    interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos, 16 * y_pos,              pMB->mvs[0].x, pMB->mvs[0].y, stride, 0);    interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos + 8, 16 * y_pos,              pMB->mvs[1].x, pMB->mvs[1].y, stride, 0);    interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos, 16 * y_pos + 8,              pMB->mvs[2].x, pMB->mvs[2].y, stride, 0);    interpolate8x8_switch(dec->cur.y, forward.y, 16 * x_pos + 8, 16 * y_pos + 8,              pMB->mvs[3].x, pMB->mvs[3].y, stride, 0);  }  interpolate8x8_switch(dec->cur.u, forward.u, 8 * x_pos, 8 * y_pos, uv_dx,            uv_dy, stride2, 0);  interpolate8x8_switch(dec->cur.v, forward.v, 8 * x_pos, 8 * y_pos, uv_dx,            uv_dy, stride2, 0);  if(dec->quarterpel) {    if(!direct) {      interpolate16x16_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,          dec->qtmp.y + 128, 16*x_pos, 16*y_pos,          pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);    } else {      interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,          dec->qtmp.y + 128, 16*x_pos, 16*y_pos,          pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);      interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,          dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos,          pMB->b_mvs[1].x, pMB->b_mvs[1].y, stride, 0);      interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,          dec->qtmp.y + 128, 16*x_pos, 16*y_pos + 8,          pMB->b_mvs[2].x, pMB->b_mvs[2].y, stride, 0);      interpolate8x8_add_quarterpel(dec->cur.y, backward.y, dec->qtmp.y, dec->qtmp.y + 64,          dec->qtmp.y + 128, 16*x_pos + 8, 16*y_pos + 8,          pMB->b_mvs[3].x, pMB->b_mvs[3].y, stride, 0);    }  } else {    interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos, 16 * y_pos,        pMB->b_mvs[0].x, pMB->b_mvs[0].y, stride, 0);    interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos + 8,        16 * y_pos, pMB->b_mvs[1].x, pMB->b_mvs[1].y, stride, 0);    interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos,        16 * y_pos + 8, pMB->b_mvs[2].x, pMB->b_mvs[2].y, stride, 0);    interpolate8x8_add_switch(dec->cur.y, backward.y, 16 * x_pos + 8,        16 * y_pos + 8, pMB->b_mvs[3].x, pMB->b_mvs[3].y, stride, 0);  }  interpolate8x8_add_switch(dec->cur.u, backward.u, 8 * x_pos, 8 * y_pos,      b_uv_dx, b_uv_dy, stride2, 0);  interpolate8x8_add_switch(dec->cur.v, backward.v, 8 * x_pos, 8 * y_pos,      b_uv_dx, b_uv_dy, stride2, 0);  if (cbp)    decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, pMB);}/* for decode B-frame dbquant */static __inline int32_tget_dbquant(Bitstream * bs){  if (!BitstreamGetBit(bs))   /*  '0' */    return (0);  else if (!BitstreamGetBit(bs))  /* '10' */

⌨️ 快捷键说明

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