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

📄 decoder.c

📁 xvid解码的精简版本.非常好的版本,节省了分离xvid源代码的过程
💻 C
📖 第 1 页 / 共 4 页
字号:
     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]);}/* Up to this version, chroma rounding was wrong with qpel.  * So we try to be backward compatible to avoid artifacts */#define BS_VERSION_BUGGY_CHROMA_ROUNDING 1/* 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 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) || (bvop)) { /* INTER, INTER_Q, NOT_CODED, FORWARD, BACKWARD */    uv_dx = mv[0].x;    uv_dy = mv[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);			}			else {        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 (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) {			if (dec->bs_version <= BS_VERSION_BUGGY_CHROMA_ROUNDING) {				int z;				uv_dx = 0; uv_dy = 0;				for (z = 0; z < 4; z++) {				  uv_dx += ((mv[z].x>>1) | (mv[z].x&1));				  uv_dy += ((mv[z].y>>1) | (mv[z].y&1));				}			}			else {        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 (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 */  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);  if (cbp)    decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, pMB);}/* decode an inter macroblock in field mode */static voiddecoder_mbinter_field(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;  uint8_t *pY_Cur, *pU_Cur, *pV_Cur;  int uvtop_dx, uvtop_dy;  int uvbot_dx, uvbot_dy;  VECTOR mv[4]; /* local copy of mvs */  /* Get pointer to memory areas */  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);    mv[0] = pMB->mvs[0];  mv[1] = pMB->mvs[1];  memset(&mv[2],0,2*sizeof(VECTOR));  validate_vector(mv, x_pos, y_pos, dec);  if((pMB->mode!=MODE_INTER4V) || (bvop))   /* INTER, INTER_Q, NOT_CODED, FORWARD, BACKWARD */  {     /* Prepare top field vector */    uvtop_dx = DIV2ROUND(mv[0].x);    uvtop_dy = DIV2ROUND(mv[0].y);    /* Prepare bottom field vector */    uvbot_dx = DIV2ROUND(mv[1].x);    uvbot_dy = DIV2ROUND(mv[1].y);    if(dec->quarterpel)    {      /* NOT supported */    }    else    {      /* Interpolate top field left part(we use double stride for every 2nd line) */      interpolate8x8_switch(dec->cur.y,dec->refn[ref].y+pMB->field_for_top*stride,                            16*x_pos,8*y_pos,mv[0].x, mv[0].y>>1,2*stride, rounding);      /* top field right part */      interpolate8x8_switch(dec->cur.y,dec->refn[ref].y+pMB->field_for_top*stride,                            16*x_pos+8,8*y_pos,mv[0].x, mv[0].y>>1,2*stride, rounding);      /* Interpolate bottom field left part(we use double stride for every 2nd line) */      interpolate8x8_switch(dec->cur.y+stride,dec->refn[ref].y+pMB->field_for_bot*stride,                            16*x_pos,8*y_pos,mv[1].x, mv[1].y>>1,2*stride, rounding);      /* Bottom field right part */      interpolate8x8_switch(dec->cur.y+stride,dec->refn[ref].y+pMB->field_for_bot*stride,                            16*x_pos+8,8*y_pos,mv[1].x, mv[1].y>>1,2*stride, rounding);      /* Interpolate field1 U */      interpolate8x4_switch(dec->cur.u,dec->refn[ref].u+pMB->field_for_top*stride2,                            8*x_pos,4*y_pos,uvtop_dx,DIV2ROUND(uvtop_dy),stride,rounding);            /* Interpolate field1 V */      interpolate8x4_switch(dec->cur.v,dec->refn[ref].v+pMB->field_for_top*stride2,                            8*x_pos,4*y_pos,uvtop_dx,DIV2ROUND(uvtop_dy),stride,rounding);          /* Interpolate field2 U */      interpolate8x4_switch(dec->cur.u+stride2,dec->refn[ref].u+pMB->field_for_bot*stride2,                            8*x_pos,4*y_pos,uvbot_dx,DIV2ROUND(uvbot_dy),stride,rounding);          /* Interpolate field2 V */      interpolate8x4_switch(dec->cur.v+stride2,dec->refn[ref].v+pMB->field_for_bot*stride2,                            8*x_pos,4*y_pos,uvbot_dx,DIV2ROUND(uvbot_dy),stride,rounding);    }  }   else   {    /* We don't expect 4 motion vectors in interlaced mode */  }  /* Must add error correction? */  if(cbp)   decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, 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;/* 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;  if (cbp)    decoder_mb_decode(dec, cbp, bs, pY_Cur, pU_Cur, pV_Cur, pMB);}static voiddecoder_iframe(DECODER * dec,        Bitstream * bs,        int quant,        int intra_dc_threshold){  uint32_t bound;  uint32_t x, y;  const uint32_t mb_width = dec->mb_width;  const uint32_t mb_height = dec->mb_height;  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);    }    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;}/* We use this when decoder runs interlaced -> different prediction */static void get_motion_vector_interlaced(DECODER * dec,        Bitstream * bs,        int x,        int y,        int k,        MACROBLOCK *pMB,        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);    /* Get interlaced prediction */  const VECTOR pmv=get_pmv2_interlaced(dec->mbs,dec->mb_width,bound,x,y,k);  VECTOR mv,mvf1,mvf2;  if(!pMB->field_pred)  {    mv.x = get_mv(bs,fcode);    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) {

⌨️ 快捷键说明

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