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

📄 mp4_decode.cpp

📁 鼎鼎有名的手机mpeg4播放器smart movie-智能影院 解码内核
💻 CPP
📖 第 1 页 / 共 5 页
字号:
static const short move_vector_table_0[14] = {
   _M(3,4),_M(-3,4),_M(2,3),_M(2,3),_M(-2,3),_M(-2,3),_M(1,2),_M(1,2),
   _M(1,2),_M(1,2),_M(-1,2),_M(-1,2),_M(-1,2),_M(-1,2),
}, move_vector_table_1[96] = {
   _M(12,10),_M(-12,10),
   _M(11,10),_M(-11,10),_M(10,9),_M(10,9),_M(-10,9),_M(-10,9),_M(9,9),_M(9,9),
   _M(-9,9),_M(-9,9),_M(8,9),_M(8,9),_M(-8,9),_M(-8,9),_M(7,7),_M(7,7),
   _M(7,7),_M(7,7),_M(7,7),_M(7,7),_M(7,7),_M(7,7),_M(-7,7),_M(-7,7),
   _M(-7,7),_M(-7,7),_M(-7,7),_M(-7,7),_M(-7,7),_M(-7,7),_M(6,7),_M(6,7),
   _M(6,7),_M(6,7),_M(6,7),_M(6,7),_M(6,7),_M(6,7),_M(-6,7),_M(-6,7),
   _M(-6,7),_M(-6,7),_M(-6,7),_M(-6,7),_M(-6,7),_M(-6,7),_M(5,7),_M(5,7),
   _M(5,7),_M(5,7),_M(5,7),_M(5,7),_M(5,7),_M(5,7),_M(-5,7),_M(-5,7),
   _M(-5,7),_M(-5,7),_M(-5,7),_M(-5,7),_M(-5,7),_M(-5,7),_M(4,6),_M(4,6),
   _M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),
   _M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(4,6),_M(-4,6),_M(-4,6),
   _M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),
   _M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6),_M(-4,6)
}, move_vector_table_2[124] = {
   _M(32,12),_M(-32,12),
   _M(31,12),_M(-31,12),_M(30,11),_M(30,11),_M(-30,11),_M(-30,11),_M(29,11),_M(29,11),
   _M(-29,11),_M(-29,11),_M(28,11),_M(28,11),_M(-28,11),_M(-28,11),_M(27,11),_M(27,11),
   _M(-27,11),_M(-27,11),_M(26,11),_M(26,11),_M(-26,11),_M(-26,11),_M(25,11),_M(25,11),
   _M(-25,11),_M(-25,11),_M(24,10),_M(24,10),_M(24,10),_M(24,10),_M(-24,10),_M(-24,10),
   _M(-24,10),_M(-24,10),_M(23,10),_M(23,10),_M(23,10),_M(23,10),_M(-23,10),_M(-23,10),
   _M(-23,10),_M(-23,10),_M(22,10),_M(22,10),_M(22,10),_M(22,10),_M(-22,10),_M(-22,10),
   _M(-22,10),_M(-22,10),_M(21,10),_M(21,10),_M(21,10),_M(21,10),_M(-21,10),_M(-21,10),
   _M(-21,10),_M(-21,10),_M(20,10),_M(20,10),_M(20,10),_M(20,10),_M(-20,10),_M(-20,10),
   _M(-20,10),_M(-20,10),_M(19,10),_M(19,10),_M(19,10),_M(19,10),_M(-19,10),_M(-19,10),
   _M(-19,10),_M(-19,10),_M(18,10),_M(18,10),_M(18,10),_M(18,10),_M(-18,10),_M(-18,10),
   _M(-18,10),_M(-18,10),_M(17,10),_M(17,10),_M(17,10),_M(17,10),_M(-17,10),_M(-17,10),
   _M(-17,10),_M(-17,10),_M(16,10),_M(16,10),_M(16,10),_M(16,10),_M(-16,10),_M(-16,10),
   _M(-16,10),_M(-16,10),_M(15,10),_M(15,10),_M(15,10),_M(15,10),_M(-15,10),_M(-15,10),
   _M(-15,10),_M(-15,10),_M(14,10),_M(14,10),_M(14,10),_M(14,10),_M(-14,10),_M(-14,10),
   _M(-14,10),_M(-14,10),_M(13,10),_M(13,10),_M(13,10),_M(13,10),_M(-13,10),_M(-13,10),
   _M(-13,10),_M(-13,10)
};

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

int S_bit_reader::GetMoveData(int fcode){

   Load();
   if(Get1()){
                              //no movement (coded in 1 bit)
      return 0;
   }
   int code = Show(12);
   if(code >= 512) 
      code = move_vector_table_0[(code >> 8) - 2];
   else
   if(code >= 128)
      code = move_vector_table_1[(code >> 2) - 32];
   else
      code = move_vector_table_2[code-4]; 

   Flush(code & 255);
   code >>= 8;

   if(fcode){
      code <<= fcode;
      int res = Get(fcode);
      res -= (1 << fcode) - 1;
      if(code < 0)
         res = -res;
      code += res;
   }
   return code;
}

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

int S_bit_reader::GetMovementVectorPair(int fcode, int prev_vector_pair){

   --fcode;
   int mv_x = GetMoveData(fcode);
   int mv_y = GetMoveData(fcode); 
   int range = 1 << (fcode+6);
   int high = (range/2) - 1;
   int low = -(range/2);

   mv_x += MOVE_VECTOR_X(prev_vector_pair);
   if(mv_x < low)
      mv_x += range;
   if(mv_x > high)
      mv_x -= range;
   mv_y += MOVE_VECTOR_Y(prev_vector_pair);
   if(mv_y < low)
      mv_y += range;
   if(mv_y > high)
      mv_y -= range;
   return MAKE_MOVEMENT_VECTOR_PAIR(mv_x, mv_y);
}

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

int S_bit_reader::GetDCsizeLum(){

   int code = Show(11);

   for(int i=0; i<8; i++){
      if((code >> i)==1){
         Flush(11-i);
         return 12-i;
      }
   }
   code >>= 8;
   if(code == 1){
      Flush(3);
      return 4;
   }
   if(code == 2){
      Flush(3);
      return 3;
   }
   if(code == 3){
      Flush(3);
      return 0;
   }
   code >>=1;
   if(code == 2){
      Flush(2);
      return 2;
   }
   if(code == 3){
      Flush(2);
      return 1;
   }     
   return 0;
}

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

int S_bit_reader::GetDCsizeChr(){

   int i,code = Show(12);
   for (i=0;i<10;i++){
      if ((code >> i)==1) {
         Flush(12-i);
         return 12-i;
      }
   }
   return 3 - Get(2);
}

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

int S_bit_reader::GetDCdiff(int dct_dc_size){
   int code = Show(32); //we need only dct_dc_size bits (but in the higher bits)
   int adj = 0;
   Flush(dct_dc_size);
   if(code >= 0)
      adj = (-1 << dct_dc_size) + 1;
   return adj + ((dword)code >> (32-dct_dc_size));
}

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

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

class C_mp4_decode_imp: public C_mp4_decode{
   enum{ RESCUE = 0x80 };

   enum{ VOL_START_CODE_MASK = 0x0f };

   enum{
      VOL_START_CODE = 0x120,
      VOP_START_CODE = 0x1b6
   };

   enum{
      ASPECT_SQUARE = 1,
      ASPECT_625TYPE_43 = 2,
      ASPECT_525TYPE_43 =3,
      ASPECT_625TYPE_169 = 8,
      ASPECT_525TYPE_169 = 9,
      ASPECT_CUSTOM = 15,
   };

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

   enum E_FRAME_TYPE{
      I_VOP,
      P_VOP,
      B_VOP,
      S_VOP,
      N_VOP,
   };

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

   enum{
      INTER = 0,              //prediction
      INTER_Q = 1,
      INTER4V = 2,
      INTRA = 3,              //no prediction
      INTRA_Q = 4,
   };

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

   enum E_SPRITE_TYPE{
      SPRITE_NO,
      SPRITE_STATIC,
      SPRITE_GMC,
   };

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

   enum{
      DIRECT = 0,
      INTERPOLATE = 1,
      BACKWARD = 2,
      FORWARD = 3,
   };

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

#ifdef PROFILE
   C_profiler *prof;
#endif

   C_softidct soft_idct;
   S_bit_reader bit_reader;

   bool has_b_frames;

   int quant_precision;       //in how many bits is quantizier encoded

   dword video_sx, video_sy;

   bool valid_vol;            //VOL information was successfully read
   bool interlaced;
   bool ac_pred_flag;
   int frame_index;
   int last_ref_frame_index;  //index of last I or P frame

                              //frame index, when the last time particular macro-block changed
                              // (need to add 'block_update_base_indx' for getting actual index)
                              // also contains RESCUE flag
   byte block_update_data[MAX_MACROBLOCKS_X*MAX_MACROBLOCKS_Y];
   int mb_pos_end;            //index of end of macro-block table 'block_update_data'
   int block_update_base_indx;   //base frame index for above (typically set to last 'P' frame's index)
   int mb_xsize, mb_ysize;      //number of macroblocks for width/height

   E_SPRITE_TYPE sprite_type;
   int quantizer;

   int intra_dc_threshold;
	int fcode_forward, fcode_backward;
	int resync_marker_bits;

   short _block[64+16/sizeof(short)];
   short *block_8x8;          //16-byte aligned, used for 8x8 block computations (intra, inter)

   int time_increment_resolution;   //video framerate * 1000
   int last_ref_time;         //last time of reference frame (I or P, not B)

	// b-frame
	int time_pp, time_bp;
	int last_bframe;
   int trb, trb_trd;          //8.8 fixed-point

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

	int resyncpos;

	int time_increment_bits;
	bool quant_type;             //type of quantizied - mpeg (true) or mpeg4 (false)

	// motion compensation buffer
	int *mv_buf; //32bytes aligned
	int* _mv_buf;
	int mv_bufmask;
	int move_buf_invalid;

                              //packed B frame
   C_buffer<byte> packed_b_frame;
   dword packed_b_size;

	int refframe;

	byte quant_matrix[2][8*8]; // [intra / inter]

	short dc_lum[4*MAX_MACROBLOCKS_X*2];		//[4][double width row]
	short ac_left_lum[2][8];		//[lower/upper][8]
	short ac_top_lum[2*MAX_MACROBLOCKS_X][8]; //[double witdh row][8]

	short dc_chr[2][2*MAX_MACROBLOCKS_X];		//[U/V][2][normal width row]
	short ac_left_chr[2][8];		//[U/V][8]
	short ac_top_chr[MAX_MACROBLOCKS_X][2][8];//[normal width row][U/V][8]

   int _mv_bufrow[4*(MAX_MACROBLOCKS_X+1)+32/sizeof(int)]; // add one extra block for left border + 32align

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

   void RescuePredict(int pos);

//----------------------------
// Read all frame's headers (VOL, VOP). Return true if VOP was found and read.
   bool ReadFrameHeaders(E_FRAME_TYPE &frame_prediction_type);

//----------------------------
// Read volume header.
   void ReadHeader_vol();

//----------------------------
// Read picture header.
   void ReadHeader_vop(E_FRAME_TYPE &frame_prediction_type);

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

   int ReSync();

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

   bool ResyncMarker();

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

   int GetPreviousMoveVector(int block_num, int pos);

//----------------------------
   int Vld_block_mpeg(const word *table, const byte *scan, int len);
   int Vld_block_mpeg4(const word *table, const byte *scan, int len);

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

   short *Dc_recon(int block_num, int pos, int dc_scaler, int &predict_dir);
   void Ac_recon(int block_num, int pos, int predict_dir);

//----------------------------
// Decode block with no prediction.
   void BlockIntra(int pos, int coded_block_pattern);

//----------------------------
// Decode block with prediction.
   void BlockInter(int coded_block_pattern);

//----------------------------
   void BlockDirect(int pos, int dmv, int coded_block_pattern);

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

   void IVOP();
   void PVOP();
   void BVOP();

//----------------------------
   bool Frame(const byte *strm, int len, bool drop_b_frames);

public:

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

   bool SetIDCTBufferCount(int count);

   bool UpdateCount();
   bool Init();

   bool Mp4_vop(const byte *strm, bool drop_b_frames, E_FRAME_TYPE frame_prediction_type);

   virtual bool Process(const byte *packet, dword len, bool drop_b_frames, S_yuv_image &out);

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

   C_mp4_decode_imp(dword sx, dword sy, void *profiler);
   ~C_mp4_decode_imp(){
      delete[] _mv_buf;
   }
};

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

bool C_mp4_decode_imp::Process(const byte *packet, dword len, bool drop_b_frames, S_yuv_image &out){

   out.type = 0;
#ifdef PROFILE
   if(frame_index==10)
      prof->ResetAverage();
#endif
   /*
   if(frame_to_show!=-1){ // pending frame?
      SendData(out);
      frame_to_show = -1;
      assert(out.type);
      return true;
   }
      */
//       if(has_b_frames && FrameTime>0 && RefTime >= FrameTime)
//          RefTime -= FrameTime;
   if(!Frame(packet, len, drop_b_frames))
      return false;
                              //send to display
   if(!soft_idct.GetBuffer(out.y, out.u, out.v)){
      assert(0);
      return false;
   }
   out.pitch = soft_idct.GetBufferPitch();
   out.type = 1;
   return true;
}

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

bool C_mp4_decode_imp::SetIDCTBufferCount(int c){

   if(!soft_idct.SetBufferCount(c))
      return false;
   return UpdateCount();
}

//----------------------------
// msb..lsb
// 4bit flushbits, 1bit last, 6bit run, 5bit level

                              //no prediction
static const word vld_intra[112+96+120+64+16] = {
   0x7881,0x7861,0x70c1,0x78a1,0x70e1,0x7042,0x7023,0x7009,
   0x6802,0x6802,0x60a1,0x60a1,0x6841,0x6841,0x6821,0x6821,
   0x6081,0x6081,0x6061,0x6061,0x6008,0x6008,0x6007,0x6007,
   0x6022,0x6022,0x6006,0x6006,0x5041,0x5041,0x5041,0x5041,
   0x5005,0x5005,0x5005,0x5005,0x5004,0x5004,0x5004,0x5004,
   0x4801,0x4801,0x4801,0x4801,0x4801,0x4801,0x4801,0x4801,
   0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
   0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
   0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,

⌨️ 快捷键说明

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