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