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

📄 mp4_decode.cpp

📁 鼎鼎有名的手机mpeg4播放器smart movie-智能影院 解码内核
💻 CPP
📖 第 1 页 / 共 5 页
字号:
/*****************************************************************************
 *
 * 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
 *
 *****************************************************************************
 *
 * Authors:
 *
 *	Andrea	Graziani  (Ag): Original source code (Open Divx Decoder 0.4a).
 *	Marc	Dukette   (Md) and
 *	Pedro	Mateu     (Pm) and
 *	Gabor	Kovacs    (Kg) Heavily modified and optimized code
 * Michal Bacik    Porting into C++, optimizations
 *
 ****************************************************************************/

#include "Util.h"
#include "SoftIdct.h"
#include "profiling.h"
#include "VideoCodec.h"
#include "C_buffer.h"

//----------------------------

#define MPEG4_ERROR_QPEL      0x200
#define MPEG4_ERROR_INTERLACE 0x201
#define MPEG4_ERROR_GMC       0x202
#define MPEG4_ERROR_PARTITIONING 0x205

#define POSX(pos) ((pos) & (MAX_MACROBLOCKS_X-1))
#define POSY(pos) ((pos) >> MB_X2)

// maximun picture size in macroblocks (16x16)
// example MB_X2=6 -> 2^6=64 macroblocks -> 1024 pixels

#define MB_X2 6
#define MB_Y2 6
#define MAX_MACROBLOCKS_X (1<<MB_X2)
#define MAX_MACROBLOCKS_Y (1<<MB_Y2)

#define DC_LUM_MASK	((MAX_MACROBLOCKS_X*2)*4-1)
#define DC_CHR_MASK (MAX_MACROBLOCKS_X*2-1)

//----------------------------

#define MAKE_MOVEMENT_VECTOR_PAIR(x, y) (((y)<<16) | ((x)&0xffff))
#define MOVE_VECTOR_X(a) short(a)
#define MOVE_VECTOR_Y(a) ((a)>>16)

//----------------------------

                              //macros for fast bit-access in frequently-used locations
#define GetBits1() ((bits << bitpos++) < 0)
#define LoadBits() \
   if(bitpos >= 8){ \
      do{ \
         bits = (bits << 8) | *bit_ptr++; \
         bitpos -= 8; \
      }while(bitpos >= 8); \
   }

#define ShowBits(n) ((dword)(bits << bitpos) >> (32-(n)))
#define FlushBits(n) bitpos += n

//----------------------------

#if 0

static int Divide(int a, int b){
   return ((a>0) ? (a+(b>>1))/b : (a-(b>>1))/b);
}

#else

                              //optimized division for most common divisors
                              // (using multiplication by reciprocal in 12.20 fixed-point format)

#define RET_DIV(a, N) return (a*N+524288) >> 20;
#define RET_SHR(a, N, S) return (a+N) >> S;

static int Divide(int a, int b){
   switch(b){
   case 1: return a;
   case 2: RET_SHR(a, 1, 1);
   case 4: RET_SHR(a, 2, 2);
   case 8: RET_SHR(a, 4, 3);
   case 16: RET_SHR(a, 8, 4);
   case 32: RET_SHR(a, 16, 5);
   case 3: RET_DIV(a, 349525);
   case 5: RET_DIV(a, 209715);
   case 6: RET_DIV(a, 174763);
   case 7: RET_DIV(a, 149797);
   case 9: RET_DIV(a, 116509);
   case 10: RET_DIV(a, 104858);
   case 11: RET_DIV(a, 95325);
   case 12: RET_DIV(a, 87382);
   case 13: RET_DIV(a, 80660);
   case 14: RET_DIV(a, 74899);
   case 15: RET_DIV(a, 69905);
   case 17: RET_DIV(a, 61681);
   case 18: RET_DIV(a, 58255);
   case 19: RET_DIV(a, 55189);
   case 20: RET_DIV(a, 52429);
   case 21: RET_DIV(a, 49933);
   case 22: RET_DIV(a, 47663);
   case 23: RET_DIV(a, 45591);
   case 24: RET_DIV(a, 43691);
   case 25: RET_DIV(a, 41943);
   case 26: RET_DIV(a, 40330);
   case 27: RET_DIV(a, 38837);
   case 28: RET_DIV(a, 37450);
   case 29: RET_DIV(a, 36158);
   case 30: RET_DIV(a, 34953);
   case 31: RET_DIV(a, 33825);
   }
   if(a>0)                              
      a += b>>1;
   else
      a -= b>>1;
   return a/b;
}

#endif

//----------------------------

static dword FindHighestBit(dword mask){

   int base = 0;
   if(mask&0xffff0000){
      base = 16;
      mask >>= 16;
   }
   if(mask&0x0000ff00){
      base += 8;
      mask >>= 8;
   }
   if(mask&0x000000f0){
      base += 4;
      mask >>= 4;
   }
   static const int lut[] = {-1, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3};
   return base + lut[mask];
}

//----------------------------

static void Clear32(void* p){
   int *i = (int*)p;
   i[0] = 0; i[1] = 0;  i[2] = 0; i[3] = 0;
   i[4] = 0; i[5] = 0;  i[6] = 0; i[7] = 0;
}

//----------------------------
//----------------------------

struct S_bit_reader{
   int bits, pos;
   const byte *ptr, *bitend;

   void Init(const byte *stream, int len){
      bits = 0;
      pos = 32;
      ptr = stream;
      bitend = stream+len+6; //adding more just to be safe
      Flush(0);
   }

   inline void Flush(int n){
      pos += n;
   }

//----------------------------
// n=1..24 (or ..32 after bytealign)
   inline dword Show(int n) const{
      return (dword)(bits << pos) >> (32-n);
   }
//----------------------------
   inline int Get(int n){
      int i = Show(n);
      Flush(n);
      return i;
   }

//----------------------------
   inline bool Get1(){
      return Get(1);
   }

   inline int BitsToNextByte() const{
      return 8-(pos & 7);
   }
   inline bool Eof() const{
      return (ptr >= bitend);
   }

   inline int ShowLarge(int n){
      int i = Show(n);
      i |= *ptr >> (40-n-pos);
      return i;
   }
   inline void Rewind(const byte *p){
      pos = 32;
      ptr = p;
   }
   inline void ByteAlign(){
      pos = (pos + 7) & ~7;
   }
   void Load();

//----------------------------

   int GetCodedBlockPatternLuminance();

   int GetMCodedBlockPatternChrominance_i();

   int GetMCodedBlockPatternChrominance_p();

   void GetQuantMatrix(byte m[2*8*8]);

//----------------------------
// Get single move value from bitstream.
   int GetMoveData(int fcode);

//----------------------------
// Get movement vector from stream. The vector is stored in stream as delta, so pass in previous value, which is added to read values.
   int GetMovementVectorPair(int fcode, int prev_vector_pair);

   int GetDCsizeLum();
   int GetDCsizeChr();
   int GetDCdiff(int dct_dc_size);
};

//----------------------------

void S_bit_reader::Load(){
   
   if(pos >= 8){
      do{
         bits = (bits << 8) | *ptr++;
         pos -= 8;
      }while(pos >= 8);
   }                                
}

//----------------------------
// Meaning of CBPY (Coded Block Pattern-luminance), indicates which blocks within a macroblock contain coded coefficients.
// First byte encodes bits 0-3 associated with 2x2 luminance (Y) blocks in one 16x16 maxroblock.
// Second byte encodes number of bits representing this information in the bitstream.
static const byte tab_coded_block_pattern_luminance[] = { 
   0, 0,  0, 0,  6, 6,   9,6,   8,5,   8,5,   4,5,   4,5,
   2, 5,  2, 5,  1, 5,   1,5,   0,4,   0,4,   0,4,   0,4, 
   12,4,  12,4,  12,4,  12,4,  10,4,  10,4,  10,4,  10,4,
   14,4,  14,4,  14,4,  14,4,   5,4,   5,4,   5,4,   5,4,
   13,4,  13,4,  13,4,  13,4,   3,4,   3,4,   3,4,   3,4, 
   11,4,  11,4,  11,4,  11,4,   7,4,   7,4,   7,4,   7,4 
};

//----------------------------

int S_bit_reader::GetCodedBlockPatternLuminance(){
                              //max 6 bits
   int code = Show(6);
   if(code < 2)
      return -1;
   if(code >= 0x30){
      Flush(2);
      return 0xf;
   }
   code *= 2;
   Flush(tab_coded_block_pattern_luminance[code+1]);
   return tab_coded_block_pattern_luminance[code];
}

//----------------------------

static const byte MCBPCtabIntra[] = {
   0, 0, //-1,0
   20,6,  36, 6,  52,6,  4,4,    4, 4,   4, 4, 
   4, 4,  19, 3,  19,3,  19,3,  19, 3,  19, 3, 
   19,3,  19, 3,  19,3,  35,3,  35, 3,  35, 3, 
   35,3,  35, 3,  35,3,  35,3,  35, 3,  51, 3, 
   51,3,  51, 3,  51,3,  51,3,  51, 3,  51, 3, 
   51,3
};

//----------------------------

int S_bit_reader::GetMCodedBlockPatternChrominance_i(){
                              //max 9bits
   int code = Show(9);
   if(code == 1){
      Flush(9); // stuffing
      return 0;
   }
   if(code < 8)
      return -1;
   code >>= 3;
   if(code >= 32){
      Flush(1);
      return 3;
   }
   code *= 2;
   Flush(MCBPCtabIntra[code+1]);
   return MCBPCtabIntra[code];
}

//----------------------------

static const byte MCBPCtabInter[] = {
   0,0, //-1,0
   0,9, 52,9, 36,9, 20,9, 49,9, 35,8, 35,8, 19,8, 19,8,
   50,8, 50,8, 51,7, 51,7, 51,7, 51,7, 34,7, 34,7, 34,7,
   34,7, 18,7, 18,7, 18,7, 18,7, 33,7, 33,7, 33,7, 33,7, 
   17,7, 17,7, 17,7, 17,7, 4,6, 4,6, 4,6, 4,6, 4,6, 
   4,6, 4,6, 4,6, 48,6, 48,6, 48,6, 48,6, 48,6, 48,6, 
   48,6, 48,6, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 
   3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 3,5, 
   32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 
   32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 
   32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 32,4, 
   32,4, 32,4, 32,4, 32,4, 32,4, 16,4, 16,4, 16,4, 16,4, 
   16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 
   16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 
   16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 16,4, 
   16,4, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 2,3, 
   2,3, 2,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 1,3, 
   1,3, 1,3, 1,3
};

//----------------------------

int S_bit_reader::GetMCodedBlockPatternChrominance_p(){
                              //max 9bits
   int code = Show(9);

   if(code == 0)
      return -1;
   if(code >= 256){
      Flush(1);
      return 0;
   }
   code *= 2;
   Flush(MCBPCtabInter[code+1]);
   return MCBPCtabInter[code];
}

//----------------------------

static const byte scan_table[3][64] = {
   {
       0,  1,  8, 16,  9,  2,  3, 10, 
      17, 24, 32, 25, 18, 11,  4,  5,
      12, 19, 26, 33, 40, 48, 41, 34, 
      27, 20, 13,  6,  7, 14, 21, 28, 
      35, 42, 49, 56, 57, 50, 43, 36, 
      29, 22, 15, 23, 30, 37, 44, 51, 
      58, 59, 52, 45, 38, 31, 39, 46, 
      53, 60, 61, 54, 47, 55, 62, 63
   },
   {
       0,  1,  2,  3,  8,  9, 16, 17, 
      10, 11,  4,  5,  6,  7, 15, 14,
      13, 12, 19, 18, 24, 25, 32, 33, 
      26, 27, 20, 21, 22, 23, 28, 29,
      30, 31, 34, 35, 40, 41, 48, 49, 
      42, 43, 36, 37, 38, 39, 44, 45,
      46, 47, 50, 51, 56, 57, 58, 59, 
      52, 53, 54, 55, 60, 61, 62, 63
   },
   {
       0,  8, 16, 24,  1,  9,  2, 10, 
      17, 25, 32, 40, 48, 56, 57, 49,
      41, 33, 26, 18,  3, 11,  4, 12, 
      19, 27, 34, 42, 50, 58, 35, 43,
      51, 59, 20, 28,  5, 13,  6, 14, 
      21, 29, 36, 44, 52, 60, 37, 45,
      53, 61, 22, 30,  7, 15, 23, 31, 
      38, 46, 54, 62, 39, 47, 55, 63
   }
};

//----------------------------

void S_bit_reader::GetQuantMatrix(byte* m){

   int i = 0;
   int last, value = 0;
   do{
      last = value;
      Load();
      value = Get(8);
      m[scan_table[0][i++]] = (byte)value;
   }while(value!=0 && i<64);
   i--;
   while(i < 64) 
      m[scan_table[0][i++]] = (byte)last;
}

//----------------------------

#define _M(mv, bits) (mv<<8) | (bits)

⌨️ 快捷键说明

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