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

📄 mp4_decode.cpp

📁 鼎鼎有名的手机mpeg4播放器smart movie-智能影院 解码内核
💻 CPP
📖 第 1 页 / 共 5 页
字号:
   0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
   0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,
   0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,0x3002,
   0x4021,0x4021,0x4021,0x4021,0x4021,0x4021,0x4021,0x4021,
   0x4003,0x4003,0x4003,0x4003,0x4003,0x4003,0x4003,0x4003,
   0xa012,0xa011,0x99c1,0x99c1,0x99a1,0x99a1,0x9981,0x9981,
   0x9961,0x9961,0x9941,0x9941,0x9822,0x9822,0x9804,0x9804,
   0x9181,0x9181,0x9161,0x9161,0x90e2,0x90e2,0x90c2,0x90c2,
   0x90a2,0x90a2,0x9063,0x9063,0x9043,0x9043,0x9026,0x9026,
   0x9025,0x9025,0x9010,0x9010,0x9082,0x9082,0x900f,0x900f,
   0x900e,0x900e,0x900d,0x900d,0x8901,0x8901,0x8901,0x8901,
   0x88e1,0x88e1,0x88e1,0x88e1,0x88c1,0x88c1,0x88c1,0x88c1,
   0x8803,0x8803,0x8803,0x8803,0x8141,0x8141,0x8141,0x8141,
   0x8121,0x8121,0x8121,0x8121,0x8101,0x8101,0x8101,0x8101,
   0x8921,0x8921,0x8921,0x8921,0x8062,0x8062,0x8062,0x8062,
   0x8024,0x8024,0x8024,0x8024,0x800c,0x800c,0x800c,0x800c,
   0x800b,0x800b,0x800b,0x800b,0x800a,0x800a,0x800a,0x800a,
   0xb807,0xb807,0xb806,0xb806,0xb016,0xb016,0xb015,0xb015,
   0xa842,0xa842,0xa842,0xa842,0xa823,0xa823,0xa823,0xa823,
   0xa805,0xa805,0xa805,0xa805,0xa1a1,0xa1a1,0xa1a1,0xa1a1,
   0xa0a3,0xa0a3,0xa0a3,0xa0a3,0xa102,0xa102,0xa102,0xa102,
   0xa083,0xa083,0xa083,0xa083,0xa064,0xa064,0xa064,0xa064,
   0xa044,0xa044,0xa044,0xa044,0xa027,0xa027,0xa027,0xa027,
   0xa014,0xa014,0xa014,0xa014,0xa013,0xa013,0xa013,0xa013,
   0xb017,0xb017,0xb018,0xb018,0xb028,0xb028,0xb122,0xb122,
   0xb862,0xb862,0xb882,0xb882,0xb9e1,0xb9e1,0xba01,0xba01,
   0xc019,0xc01a,0xc01b,0xc029,0xc0c3,0xc02a,0xc045,0xc0e3,
   0xc1c1,0xc808,0xc8a2,0xc8c2,0xca21,0xca41,0xca61,0xca81,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   
   0x0a1b,0x0405,0x0303,0x0303,0x0202,0x0101,0x0101,0x0001,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0308,0x0202,0x0202,0x0102,0x0101,0x0101,0x0101,0x0101,
   0x0101,0x0101,0x0001,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0f02,0x080a,0x0304,0x0202,0x0202,0x0102,0x0101,0x0101,
   0x1501,0x0207,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101
};

//----------------------------
                              //prediction
static const word vld_inter[112+96+120+64+16] = {
   0x7901,0x78e1,0x78c1,0x78a1,0x7181,0x7161,0x7141,0x7004,
   0x6881,0x6881,0x6861,0x6861,0x6841,0x6841,0x6821,0x6821,
   0x6121,0x6121,0x6101,0x6101,0x60e1,0x60e1,0x60c1,0x60c1,
   0x6022,0x6022,0x6003,0x6003,0x50a1,0x50a1,0x50a1,0x50a1,
   0x5081,0x5081,0x5081,0x5081,0x5061,0x5061,0x5061,0x5061,
   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,
   0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,0x2001,
   0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,
   0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,0x3021,
   0x4041,0x4041,0x4041,0x4041,0x4041,0x4041,0x4041,0x4041,
   0x4002,0x4002,0x4002,0x4002,0x4002,0x4002,0x4002,0x4002,
   0xa009,0xa008,0x9b01,0x9b01,0x9ae1,0x9ae1,0x9ac1,0x9ac1,
   0x9aa1,0x9aa1,0x9a81,0x9a81,0x9a61,0x9a61,0x9a41,0x9a41,
   0x9a21,0x9a21,0x9802,0x9802,0x92c1,0x92c1,0x92a1,0x92a1,
   0x9281,0x9281,0x9261,0x9261,0x9241,0x9241,0x9221,0x9221,
   0x9201,0x9201,0x91e1,0x91e1,0x9082,0x9082,0x9062,0x9062,
   0x9007,0x9007,0x9006,0x9006,0x8a01,0x8a01,0x8a01,0x8a01,
   0x89e1,0x89e1,0x89e1,0x89e1,0x89c1,0x89c1,0x89c1,0x89c1,
   0x89a1,0x89a1,0x89a1,0x89a1,0x8981,0x8981,0x8981,0x8981,
   0x8961,0x8961,0x8961,0x8961,0x8941,0x8941,0x8941,0x8941,
   0x8921,0x8921,0x8921,0x8921,0x81c1,0x81c1,0x81c1,0x81c1,
   0x81a1,0x81a1,0x81a1,0x81a1,0x8042,0x8042,0x8042,0x8042,
   0x8023,0x8023,0x8023,0x8023,0x8005,0x8005,0x8005,0x8005,
   0xb822,0xb822,0xb803,0xb803,0xb00b,0xb00b,0xb00a,0xb00a,
   0xab81,0xab81,0xab81,0xab81,0xab61,0xab61,0xab61,0xab61,
   0xab41,0xab41,0xab41,0xab41,0xab21,0xab21,0xab21,0xab21,
   0xa122,0xa122,0xa122,0xa122,0xa102,0xa102,0xa102,0xa102,
   0xa0e2,0xa0e2,0xa0e2,0xa0e2,0xa0c2,0xa0c2,0xa0c2,0xa0c2,
   0xa0a2,0xa0a2,0xa0a2,0xa0a2,0xa063,0xa063,0xa063,0xa063,
   0xa043,0xa043,0xa043,0xa043,0xa024,0xa024,0xa024,0xa024,
   0xb00c,0xb00c,0xb025,0xb025,0xb2e1,0xb2e1,0xb301,0xb301,
   0xbba1,0xbba1,0xbbc1,0xbbc1,0xbbe1,0xbbe1,0xbc01,0xbc01,
   0xc026,0xc044,0xc083,0xc0a3,0xc0c3,0xc142,0xc321,0xc341,
   0xcc21,0xcc41,0xcc61,0xcc81,0xcca1,0xccc1,0xcce1,0xcd01,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,
   0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,0x7fff,

   0x060c,0x0304,0x0303,0x0203,0x0202,0x0102,0x0101,0x0101,
   0x0101,0x0101,0x0101,0x0101,0x0101,0x0001,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x0203,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,
   0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101,
   0x0101,0x0101,0x0101,0x0101,0x0001,0x0000,0x0000,0x0000,
   0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
   0x1b02,0x070b,0x0203,0x0102,0x0101,0x0101,0x0101,0x0101,
   0x2901,0x0102,0x0101,0x0101,0x0101,0x0101,0x0101,0x0101
};

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

void C_mp4_decode_imp::RescuePredict(int pos){

   int lumpos = 2*POSX(pos) + (POSY(pos) << (MB_X2+2));

   if(pos>=MAX_MACROBLOCKS_X+1 && (block_update_data[pos-MAX_MACROBLOCKS_X-1]&RESCUE)){
                              //rescue -A- DC value
      dc_lum[(lumpos-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
      dc_chr[0][(pos-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
      dc_chr[1][(pos-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
   }

                              //left
   if(pos>=1 && (block_update_data[pos-1]&RESCUE)){
      // rescue -B- DC values
      dc_lum[(lumpos) & DC_LUM_MASK] = 1024;
      dc_lum[(lumpos+MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
      dc_chr[0][pos & DC_CHR_MASK] = 1024;
      dc_chr[1][pos & DC_CHR_MASK] = 1024;
      
      if(ac_pred_flag){
                              //rescue -B- AC values
         Clear32(ac_left_lum);
         Clear32(ac_left_chr);
      }
   }
                              //top
   if(pos>=MAX_MACROBLOCKS_X && (block_update_data[pos-MAX_MACROBLOCKS_X]&RESCUE)){
      
      // rescue -C- DC values
      dc_lum[(lumpos+1-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
      dc_lum[(lumpos+2-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK] = 1024;
      dc_chr[0][(pos+1-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
      dc_chr[1][(pos+1-MAX_MACROBLOCKS_X) & DC_CHR_MASK] = 1024;
      
      if(ac_pred_flag){
                              //rescue -C- AC values
         Clear32(ac_top_lum[lumpos & (MAX_MACROBLOCKS_X*2-1)]);
         Clear32(ac_top_chr[pos & (MAX_MACROBLOCKS_X-1)]);
      }
   }
}

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

bool C_mp4_decode_imp::UpdateCount(){

   int *mv;
   if(soft_idct.GetBufferCount() >= 3){
      if(mv_bufmask != -1)
         move_buf_invalid = 1;
      mv_bufmask = -1; // full size mv buffer needed
      if(!_mv_buf){
         int size = 32 + 4*sizeof(int) * (mb_pos_end+1); // add one extra block for left border
         _mv_buf = new int[size/4];
         if(!_mv_buf)
            return false;
         MemSet(_mv_buf,0,size);
      }
      mv = _mv_buf;
   }else{
      move_buf_invalid = 1;
      mv_bufmask = MAX_MACROBLOCKS_X-1; //only one row of mv buffer needed
      mv = _mv_bufrow;
   }
   mv_buf = (int*)(((int)mv + 31 + 4*sizeof(int)) & ~31);
   return true;
}

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

bool C_mp4_decode_imp::Mp4_vop(const byte *strm, bool drop_b_frames, E_FRAME_TYPE frame_prediction_type){

   resyncpos = 0;

   switch(frame_prediction_type){
   case N_VOP:
      if(packed_b_size){
         bit_reader.Init(packed_b_frame.Begin(), packed_b_size);
         packed_b_size = 0;
         if(ReadFrameHeaders(frame_prediction_type)){
            bool ok = Mp4_vop(packed_b_frame.Begin(), drop_b_frames, frame_prediction_type);
            if(ok)
               return true;
         }
      }
      return (frame_index > 0);
   case P_VOP:
                              //P (predicted) frames are predicted from the most recently reconstructed I or P frame
                              //each macroblock in a P frame can either come with a vector and difference DCT coefficients for a close match in the last I or P,
                              // or it can just be "intra" coded if there was no good match
      if(frame_index < 1)
         return false;
                              //flow...
   case I_VOP:
                              //I (intra) frames are coded as individual still images (JPG)

                              //I/P-frames are the "reference" frames
                              // they are decode into refframe 
                              // P-frames depend on last refenrence frame: refframe^1

      refframe ^= 1;

      if(has_b_frames)
         ++last_bframe;

      int frame_to_show;
      if(!has_b_frames || frame_index==0)
         frame_to_show = refframe; // show this refframe
      else
         frame_to_show = refframe ^ 1; // show last refframe 

      if(frame_prediction_type == I_VOP) {
         soft_idct.FrameStart(frame_index, refframe, -1, -1, frame_to_show);
         IVOP();
      }else{
         soft_idct.FrameStart(frame_index, refframe, refframe ^ 1, -1, frame_to_show);
         PVOP();
      }
      break;

   case B_VOP:
                              //B (bidirectional) frames are predicted from the closest two I or P frames, one in the past and one in the future
      if(frame_index < 2 || move_buf_invalid)
         return false;

      last_bframe = 0;

      if(drop_b_frames){
                              //ignore b-frames
         return false;
      }

      if(move_buf_invalid == 2){
         move_buf_invalid = 0;
         MemSet(mv_buf, 0, 4*sizeof(int)*mb_pos_end);
      }

      assert(has_b_frames);
      /*
      if(soft_idct.GetBufferCount()<3){
         SetIDCTBufferCount(3);
         if(move_buf_invalid)
            return false;
      }
      */
      /*
                              //save this b-frame if there was already a packed one
      if(frame_to_show >= 0){
                              //rewind
         bit_reader.Rewind(strm);
         return true;
      }
      */
      soft_idct.FrameStart(-frame_index, 2, refframe,refframe ^ 1, 2);
      
      if(time_pp){
         int TRB = time_pp - time_bp;
         trb = (TRB<<8) / time_pp;
         trb_trd = ((TRB - time_pp)<<8) / time_pp;
      }else{
         trb = 0;
         trb_trd = 0;
      }
      BVOP();
      break;

   default:
      return false;
   }

   frame_index++;

                              //make sure that data in block_update_data don't overflow
   const int MAX_D = 128;
   if((frame_index - block_update_base_indx) >= MAX_D){
      for(int pos=0; pos<mb_pos_end; pos+=MAX_MACROBLOCKS_X-mb_xsize){
         for(; POSX(pos)<mb_xsize; ++pos){
            byte i = block_update_data[pos];
            byte r = i&RESCUE;
            i &= 0x7f;
            if(i >= (MAX_D-8))
               i -= (MAX_D-8);
            else
               i = 0;
            block_update_data[pos] = i|r;
         }
      }
      block_update_base_indx += MAX_D-8;
   }
   return true;
}

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

bool C_mp4_decode_imp::Frame(const byte* ptr, int len, bool drop_b_frames){

   E_FRAME_TYPE frame_prediction_type;
   if(!len){
                              //null frame, return last rendered frame
      return true;
   }

   PROF_S(PROF_DECODE);

   bit_reader.Init(ptr, len);

   if(!ReadFrameHeaders(frame_prediction_type) || !valid_vol)
      return false; //invalid header or no vol information

   bool ok = Mp4_vop(ptr, drop_b_frames, frame_prediction_type);
   PROF_E(PROF_DECODE);

#if defined _DEBUG && 0
                              //mark frame type
   if(ok){
      byte *y, *u, *v;
      if(soft_idct.GetBuffer(y, u, v)){
         dword pi = soft_idct.GetBufferPitch();
         for(int i=0; i<3; i++){
            byte *d = !i ? y : i==1 ? u : v;
            dword p = pi;
            dword s = 16;
            if(i){
               p /= 2;
               s /= 2;
               d += p*4*4;
            }else
               d += p*8*4;
            byte val;
            switch(frame_prediction_type){
            case I_VOP: val = !i ? 0x00 : i==1 ? 0x00 : 0xff; break;
            case P_VOP: val = !i ? 0x80 : i==1 ? 0x80 : 0x80; break;
            case B_VOP: val = !i ? 0x80 : i==1 ? 0xff : 0x00; break;
            default: val = !i ? 0x0 : i==1 ? 0x80 : 0x80;
            }
            for(int y=s; y--; ){
               for(int x=s; x--; ){
                  d[x] = val;
               }
               d += p;
            }
         }
      }
   }
#endif
   if(ok){
                              //check for packed b-frame
      const byte *pos = bit_reader.ptr - 4 + ((bit_reader.pos+7) >> 3);

      len -= (pos - ptr);
      if(len > 4){
         if(!has_b_frames){
            has_b_frames = true;
            SetIDCTBufferCount(3);
         }
                              //save packed b-frame
         if(packed_b_frame.Size() < len)
            packed_b_frame.Resize((len+8+0x1fff) & ~0x1fff);
         packed_b_size = len;
         MemCpy(packed_b_frame.Begin(), pos, len);
      }
   }
   return ok;
}

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

void C_mp4_decode_imp::Ac_recon(int block_num, int pos, int predict_dir){

   int i;
   short *ac_top;
   short *ac_left;
   if(block_num < 4){
                              //Y
      ac_top = ac_top_lum[pos & (MAX_MACROBLOCKS_X*2-1)];
      ac_left = ac_left_lum[(pos >> (MB_X2+1)) & 1];
      i = MAX_MACROBLOCKS_X*2-1; //stride-1
   }else{
                              //UV
      ac_top = ac_top_chr[pos & (MAX_MACROBLOCKS_X-1)][block_num & 1];
      ac_left = ac_left_chr[block_num & 1];
      i = MAX_MACROBLOCKS_X-1; //stride-1
   }
   if(ac_pred_flag){
      if(predict_dir == 1){
                              //TOP
         if(pos > i){
            for(i = 1; i < 8; i++)
               block_8x8[i] = (short)(block_8x8[i] + ac_top[i]);
         }
      }else{
                              //LEFT
         if(pos & i){
            for(i = 1; i < 8; i++)
               block_8x8[i<<3] = (short)(block_8x8[i<<3] + ac_left[i]);
         }
      }
   }
   for(i = 1; i < 8; i++){
      ac_top[i] = block_8x8[i];
      ac_left[i] = block_8x8[i<<3];
   }
}

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

short *C_mp4_decode_imp::Dc_recon(int block_num, int pos, int dc_scaler, int &predict_dir){

   short *dc;

   int Fb = 1024;
   int Fc = 1024;

   if(block_num < 4){
                              //Y
      dc = dc_lum;
      if(pos >= MAX_MACROBLOCKS_X*2){
         Fb = dc[(pos-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK];
         Fc = dc[(pos+1-MAX_MACROBLOCKS_X*2) & DC_LUM_MASK];
      }
      dc += pos & DC_LUM_MASK;
   }else{
                              //UV

⌨️ 快捷键说明

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