decoder.cpp
来自「gaca源码」· C++ 代码 · 共 1,447 行 · 第 1/4 页
CPP
1,447 行
/*****************************************************************************
*
* XVID MPEG-4 VIDEO CODEC
* - Decoder Module -
*
* Copyright(C) 2002 MinChen <chenm001@163.com>
* 2002-2003 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.cpp,v 1.2 2005/09/16 14:28:47 jeanlf Exp $
*
****************************************************************************/
#include "quant.h"
#include "quant_matrix.h"
#include "interpolate8x8.h"
#include "reduced.h"
#include "mbprediction.h"
#include "gmc.h"
#include "mem_align.h"
#ifdef __SYMBIAN32__
#include <e32base.h>
#endif
//----------------------------
# define DECLARE_ALIGNED_MATRIX(name,sizex,sizey,type,alignment) \
type name##_storage[(sizex)*(sizey)+(alignment)-1]; \
type * name = (type *) (((int) name##_storage+(alignment - 1)) & ~((int)(alignment)-1))
//----------------------------
//----------------------------
/* K = 4 */
static const dword roundtab_76[16] = { 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1 };
/* K = 1 */
const dword roundtab_79[4] = { 0, 1, 0, 0 };
//----------------------------
int S_decoder::Resize(){
//free existing
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
image_destroy(&tmp, edged_width, edged_height);
image_destroy(&qtmp, edged_width, edged_height);
image_destroy(&gmc, edged_width, edged_height);
if(last_mbs)
xvid_free(last_mbs);
if(mbs)
xvid_free(mbs);
//realloc
mb_width = (width + 15) / 16;
mb_height = (height + 15) / 16;
edged_width = 16 * mb_width + 2 * EDGE_SIZE;
edged_height = 16 * mb_height + 2 * EDGE_SIZE;
if(image_create(&cur, edged_width, edged_height)){
xvid_free(this);
return XVID_ERR_MEMORY;
}
if(image_create(&refn[0], edged_width, edged_height)){
image_destroy(&cur, edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
//support B-frame to reference last 2 frame
if(image_create(&refn[1], edged_width, edged_height)){
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
if(image_create(&tmp, edged_width, edged_height)){
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
if(image_create(&qtmp, edged_width, edged_height)){
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
image_destroy(&tmp, edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
if(image_create(&gmc, edged_width, edged_height)){
image_destroy(&qtmp, edged_width, edged_height);
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
image_destroy(&tmp, edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
mbs = (MACROBLOCK*)xvid_malloc(sizeof(MACROBLOCK) * mb_width * mb_height, CACHE_LINE);
if(mbs == NULL){
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
image_destroy(&tmp, edged_width, edged_height);
image_destroy(&qtmp, edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
MemSet(mbs, 0, sizeof(MACROBLOCK) * mb_width * mb_height);
//for skip MB flag
last_mbs = (MACROBLOCK*)xvid_malloc(sizeof(MACROBLOCK) * mb_width * mb_height, CACHE_LINE);
if(!last_mbs){
xvid_free(mbs);
image_destroy(&cur, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
image_destroy(&tmp, edged_width, edged_height);
image_destroy(&qtmp, edged_width, edged_height);
xvid_free(this);
return XVID_ERR_MEMORY;
}
MemSet(last_mbs, 0, sizeof(MACROBLOCK) * mb_width * mb_height);
return 0;
}
//----------------------------
int decoder_create(xvid_dec_create_t *create){
if(XVID_VERSION_MAJOR(create->version) != 1) /* v1.x.x */
return XVID_ERR_VERSION;
//S_decoder *dec = (S_decoder*)xvid_malloc(sizeof(S_decoder), CACHE_LINE);
S_decoder *dec = new(ELeave) S_decoder(create);
if(!dec)
return XVID_ERR_MEMORY;
return dec->Init(create);
}
//----------------------------
S_decoder::S_decoder(xvid_dec_create_t *create):
#ifdef PROFILE
prof(*create->prof),
#endif
time_inc_resolution(0),
fixed_time_inc(0),
time_inc_bits(0),
shape(0),
quant_bits(0),
quant_type(0),
mpeg_quant_matrices(0),
quarterpel(0),
complexity_estimation_disable(0),
interlacing(false),
top_field_first(0),
alternate_vertical_scan(0),
aspect_ratio(0),
par_width(0),
par_height(0),
sprite_enable(0),
sprite_warping_points(0),
sprite_warping_accuracy(0),
sprite_brightness_change(0),
newpred_enable(0),
reduced_resolution_enable(false),
bs_version(0),
width(0),
height(0),
edged_width(0),
edged_height(0),
mb_width(0),
mb_height(0),
mbs(0),
last_mbs(0),
last_coding_type(0),
frames(0),
time(0),
time_base(0),
last_time_base(0),
last_non_b_time(0),
time_pp(0),
time_bp(0),
fixed_dimensions(false),
scalability(false),
low_delay(false),
low_delay_default(false),
last_reduced_resolution(false),
packed_mode(false)
{
MemSet(&p_fmv, 0, sizeof(p_fmv));
MemSet(&p_bmv, 0, sizeof(p_bmv));
}
//----------------------------
S_decoder::~S_decoder(){
xvid_free(last_mbs);
xvid_free(mbs);
//image based GMC
image_destroy(&gmc, edged_width, edged_height);
image_destroy(&refn[0], edged_width, edged_height);
image_destroy(&refn[1], edged_width, edged_height);
image_destroy(&tmp, edged_width, edged_height);
image_destroy(&qtmp, edged_width, edged_height);
image_destroy(&cur, edged_width, edged_height);
xvid_free(mpeg_quant_matrices);
}
//----------------------------
int S_decoder::Init(xvid_dec_create_t *create){
mpeg_quant_matrices = (dword*)xvid_malloc(sizeof(dword) * 64 * 8, CACHE_LINE);
if(!mpeg_quant_matrices){
delete this;
return XVID_ERR_MEMORY;
}
create->handle = this;
width = create->width;
height = create->height;
cur.Null();
refn[0].Null();
refn[1].Null();
tmp.Null();
qtmp.Null();
//image based GMC
gmc.Null();
mbs = NULL;
last_mbs = NULL;
init_mpeg_matrix(mpeg_quant_matrices);
//For B-frame support (used to save reference frame's time
frames = 0;
time = time_base = last_time_base = 0;
low_delay = false;
packed_mode = false;
fixed_dimensions = (width > 0 && height > 0);
init_vlc_tables();
idct_int32_init();
if(fixed_dimensions)
return Resize();
return 0;
}
//----------------------------
static const int dquant_table[4] = {
-1, -2, 1, 2
};
//----------------------------
static dword get_dc_scaler(dword quant, dword lum){
if(quant < 5)
return 8;
if(quant < 25 && !lum)
return (quant + 13) / 2;
if(quant < 9)
return 2 * quant;
if(quant < 25)
return quant + 8;
if(lum)
return 2 * quant - 16;
return quant - 6;
}
//---------------------------
#ifdef _ARM_
extern"C"
void XVID_ClearMatrix(void *dst);
#else
void XVID_ClearMatrix(void *dst);
#ifndef __MARM__
inline void XVID_ClearMatrix(void *dst){ MemSet(dst, 0, 64 * sizeof(int)); }
#endif
#endif
//--------------------------
/* decode an intra macroblock */
void S_decoder::MBIntra(MACROBLOCK *pMB, dword x_pos, dword y_pos, dword acpred_flag, dword cbp, Bitstream *bs,
dword quant, dword intra_dc_threshold, dword bound, bool reduced_resolution){
DECLARE_ALIGNED_MATRIX(block, 6, 64, int, CACHE_LINE);
DECLARE_ALIGNED_MATRIX(data, 6, 64, int, CACHE_LINE);
int i;
dword stride = edged_width;
const dword stride2 = stride / 2;
byte *pY_Cur, *pU_Cur, *pV_Cur;
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);
}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);
}
MemSet(block, 0, 6 * 64 * sizeof(int)); //clear
const dword iQuant = pMB->quant;
for(i = 0; i < 6; i++){
dword iDcScaler = get_dc_scaler(iQuant, i < 4);
int predictors[8];
int start_coeff;
predict_acdc(mbs, x_pos, y_pos, mb_width, i, &block[i * 64], iQuant, iDcScaler, predictors, bound);
if(!acpred_flag)
pMB->acpred_directions[i] = 0;
if(quant < intra_dc_threshold){
PROF_S(PROF_1);
int dc_size;
int dc_dif;
dc_size = i < 4 ? bs->get_dc_size_lum() : bs->get_dc_size_chrom();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?