📄 decoder.c
字号:
/***************************************************************************** * * XVID MPEG-4 VIDEO CODEC * - Decoder Module - * * Copyright(C) 2002 MinChen <chenm001@163.com> * 2002-2004 Peter Ross <pross@xvid.org> * * This program is free software ; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation ; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY ; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program ; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * $Id: decoder.c,v 1.75.2.1 2005/12/30 14:26:46 Isibaar Exp $ * ****************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#ifdef BFRAMES_DEC_DEBUG#define BFRAMES_DEC#endif#include "xvid.h"#include "portab.h"#include "global.h"#include "decoder.h"#include "bitstream.h"#include "mbcoding.h"#include "quant.h"#include "quant_matrix.h"#include "idct.h"#include "mem_transfer.h"#include "interpolate8x8.h"//#include "font.h"#include "qpel.h"#include "mbcoding.h"#include "mbprediction.h"#include "gmc.h"#include "image.h"#include "colorspace.h"#include "postprocessing.h"#include "mem_align.h"#define DIV2ROUND(n) (((n)>>1)|((n)&1))#define DIV2(n) ((n)>>1)#define DIVUVMOV(n) (((n) >> 1) + roundtab_79[(n) & 0x3]) ///***************************************************************************** * Modified rounding tables * Original tables see ISO spec tables 7-6 -> 7-9 ****************************************************************************/const uint32_t roundtab[16] ={0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2 };/* K = 4 */const uint32_t roundtab_76[16] ={ 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };/* K = 2 */const uint32_t roundtab_78[8] ={ 0, 0, 1, 1, 0, 0, 0, 1 };/* K = 1 */const uint32_t roundtab_79[4] ={ 0, 1, 0, 0 };static intdecoder_resize(DECODER * dec){ /* free existing */ image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); image_destroy(&dec->gmc, dec->edged_width, dec->edged_height); image_null(&dec->cur); image_null(&dec->refn[0]); image_null(&dec->refn[1]); image_null(&dec->tmp); image_null(&dec->qtmp); image_null(&dec->gmc); xvid_free(dec->last_mbs); xvid_free(dec->mbs); xvid_free(dec->qscale); dec->last_mbs = NULL; dec->mbs = NULL; dec->qscale = NULL; /* realloc */ dec->mb_width = (dec->width + 15) / 16; dec->mb_height = (dec->height + 15) / 16; dec->edged_width = 16 * dec->mb_width + 2 * EDGE_SIZE; dec->edged_height = 16 * dec->mb_height + 2 * EDGE_SIZE; if ( image_create(&dec->cur, dec->edged_width, dec->edged_height) || image_create(&dec->refn[0], dec->edged_width, dec->edged_height) || image_create(&dec->refn[1], dec->edged_width, dec->edged_height) /* Support B-frame to reference last 2 frame */ || image_create(&dec->tmp, dec->edged_width, dec->edged_height) || image_create(&dec->qtmp, dec->edged_width, dec->edged_height) || image_create(&dec->gmc, dec->edged_width, dec->edged_height) ) goto memory_error; dec->mbs = xvid_malloc(sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height, CACHE_LINE); if (dec->mbs == NULL) goto memory_error; memset(dec->mbs, 0, sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height); /* For skip MB flag */ dec->last_mbs = xvid_malloc(sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height, CACHE_LINE); if (dec->last_mbs == NULL) goto memory_error; memset(dec->last_mbs, 0, sizeof(MACROBLOCK) * dec->mb_width * dec->mb_height); /* nothing happens if that fails */ dec->qscale = xvid_malloc(sizeof(int) * dec->mb_width * dec->mb_height, CACHE_LINE); if (dec->qscale) memset(dec->qscale, 0, sizeof(int) * dec->mb_width * dec->mb_height); return 0;memory_error: /* Most structures were deallocated / nullifieded, so it should be safe */ /* decoder_destroy(dec) minus the write_timer */ xvid_free(dec->mbs); image_destroy(&dec->cur, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); xvid_free(dec); return XVID_ERR_MEMORY;}intdecoder_create(xvid_dec_create_t * create){ DECODER *dec; if (XVID_VERSION_MAJOR(create->version) != 1) /* v1.x.x */ return XVID_ERR_VERSION; dec = xvid_malloc(sizeof(DECODER), CACHE_LINE); if (dec == NULL) { return XVID_ERR_MEMORY; } memset(dec, 0, sizeof(DECODER)); dec->mpeg_quant_matrices = xvid_malloc(sizeof(uint16_t) * 64 * 8, CACHE_LINE); if (dec->mpeg_quant_matrices == NULL) { xvid_free(dec); return XVID_ERR_MEMORY; } create->handle = dec; dec->width = create->width; dec->height = create->height; image_null(&dec->cur); image_null(&dec->refn[0]); image_null(&dec->refn[1]); image_null(&dec->tmp); image_null(&dec->qtmp); /* image based GMC */ image_null(&dec->gmc); dec->mbs = NULL; dec->last_mbs = NULL; dec->qscale = NULL; init_postproc(&dec->postproc); init_mpeg_matrix(dec->mpeg_quant_matrices); /* For B-frame support (used to save reference frame's time */ dec->frames = 0; dec->time = dec->time_base = dec->last_time_base = 0; dec->low_delay = 0; dec->packed_mode = 0; dec->time_inc_resolution = 1; /* until VOL header says otherwise */ dec->bs_version = 0xffff; /* Initialize to very high value -> assume bugfree stream */ dec->fixed_dimensions = (dec->width > 0 && dec->height > 0); if (dec->fixed_dimensions) return decoder_resize(dec); else return 0;}intdecoder_destroy(DECODER * dec){ xvid_free(dec->last_mbs); xvid_free(dec->mbs); xvid_free(dec->qscale); /* image based GMC */ image_destroy(&dec->gmc, dec->edged_width, dec->edged_height); image_destroy(&dec->refn[0], dec->edged_width, dec->edged_height); image_destroy(&dec->refn[1], dec->edged_width, dec->edged_height); image_destroy(&dec->tmp, dec->edged_width, dec->edged_height); image_destroy(&dec->qtmp, dec->edged_width, dec->edged_height); image_destroy(&dec->cur, dec->edged_width, dec->edged_height); xvid_free(dec->mpeg_quant_matrices); xvid_free(dec); return 0;}static const int32_t dquant_table[4] = { -1, -2, 1, 2};/* decode an intra macroblock */static voiddecoder_mbintra(DECODER * dec, MACROBLOCK * pMB, const uint32_t x_pos, const uint32_t y_pos, const uint32_t acpred_flag, const uint32_t cbp, Bitstream * bs, const uint32_t quant, const uint32_t intra_dc_threshold, const unsigned int bound){ DECLARE_ALIGNED_MATRIX(block, 6, 64, int16_t, CACHE_LINE); DECLARE_ALIGNED_MATRIX(data, 6, 64, int16_t, CACHE_LINE); uint32_t stride = dec->edged_width; uint32_t stride2 = stride / 2; uint32_t next_block = stride * 8; uint32_t i; uint32_t iQuant = pMB->quant; uint8_t *pY_Cur, *pU_Cur, *pV_Cur; 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); memset(block, 0, 6 * 64 * sizeof(int16_t)); /* clear */ for (i = 0; i < 6; i++) { uint32_t iDcScaler = get_dc_scaler(iQuant, i < 4); int16_t predictors[8]; int start_coeff; predict_acdc(dec->mbs, x_pos, y_pos, dec->mb_width, i, &block[i * 64], iQuant, iDcScaler, predictors, bound); if (!acpred_flag) { pMB->acpred_directions[i] = 0; } if (quant < intra_dc_threshold) { int dc_size; int dc_dif; dc_size = i < 4 ? get_dc_size_lum(bs) : get_dc_size_chrom(bs); dc_dif = dc_size ? get_dc_dif(bs, dc_size) : 0; if (dc_size > 8) { BitstreamSkip(bs, 1); /* marker */ } block[i * 64 + 0] = dc_dif; start_coeff = 1; DPRINTF(XVID_DEBUG_COEFF,"block[0] %i\n", dc_dif); } else { start_coeff = 0; } if (cbp & (1 << (5 - i))) /* coded */ { int direction = dec->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, dec->bs_version); if (dec->quant_type == 0) { dequant_h263_intra(&data[i * 64], &block[i * 64], iQuant, iDcScaler, dec->mpeg_quant_matrices); } else { dequant_mpeg_intra(&data[i * 64], &block[i * 64], iQuant, iDcScaler, dec->mpeg_quant_matrices); } idct_int32((short * const)&data[i * 64]); } if (dec->interlacing && pMB->field_dct) { next_block = stride; stride *= 2; } 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);}static voiddecoder_mb_decode(DECODER * dec, const uint32_t cbp, Bitstream * bs, uint8_t * pY_Cur, uint8_t * pU_Cur, uint8_t * pV_Cur, const MACROBLOCK * pMB){ DECLARE_ALIGNED_MATRIX(data, 1, 64, int16_t, CACHE_LINE); int stride = dec->edged_width; int i; const uint32_t iQuant = pMB->quant; const int direction = dec->alternate_vertical_scan ? 2 : 0; typedef void (*get_inter_block_function_t)( Bitstream * bs, int16_t * block, int direction, const int quant, const uint16_t *matrix); typedef void (*add_residual_function_t)( uint8_t *predicted_block, const int16_t *residual, int stride); const get_inter_block_function_t get_inter_block = (dec->quant_type == 0) ? (get_inter_block_function_t)get_inter_block_h263 : (get_inter_block_function_t)get_inter_block_mpeg; uint8_t *dst[6]; int strides[6]; if (dec->interlacing && pMB->field_dct) { dst[0] = pY_Cur; dst[1] = pY_Cur + 8; dst[2] = pY_Cur + stride; dst[3] = dst[2] + 8; dst[4] = pU_Cur; dst[5] = pV_Cur; strides[0] = strides[1] = strides[2] = strides[3] = stride*2; strides[4] = stride/2; strides[5] = stride/2; } else { dst[0] = pY_Cur; dst[1] = pY_Cur + 8; dst[2] = pY_Cur + 8*stride; dst[3] = dst[2] + 8; dst[4] = pU_Cur; dst[5] = pV_Cur; strides[0] = strides[1] = strides[2] = strides[3] = stride; strides[4] = stride/2; strides[5] = stride/2; } for (i = 0; i < 6; i++) { /* Process only coded blocks */ if (cbp & (1 << (5 - i))) { /* Clear the block */ memset(&data[0], 0, 64*sizeof(int16_t)); /* Decode coeffs and dequantize on the fly */ get_inter_block(bs, &data[0], direction, iQuant, get_inter_matrix(dec->mpeg_quant_matrices)); /* iDCT */ idct_int32((short * const)&data[0]); /* Add this residual to the predicted block */ transfer_16to8add(dst[i], &data[0], strides[i]); } }}static void __inlinevalidate_vector(VECTOR * mv, unsigned int x_pos, unsigned int y_pos, const DECODER * dec){ /* clip a vector to valid range
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -