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 + -
显示快捷键?