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

📄 mp4_decode.cpp

📁 鼎鼎有名的手机mpeg4播放器smart movie-智能影院 解码内核
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      dc = dc_chr[block_num & 1];
      if(pos >= MAX_MACROBLOCKS_X){
         Fb=dc[(pos-MAX_MACROBLOCKS_X) & DC_CHR_MASK];
         Fc=dc[(pos+1-MAX_MACROBLOCKS_X) & DC_CHR_MASK];
      }
      dc += pos & DC_CHR_MASK;
   }
   int Fa = dc[0];
   if(Abs(Fb - Fa) < Abs(Fb - Fc)){
                              //TOP
      predict_dir = 1;
      Fa = Fc;
   }else{
                              //LEFT
      predict_dir = 0;
   }
   /*
   if(Fa>0)
      Fa += dc_scaler>>1;
   else
      Fa -= dc_scaler>>1;
   Fa /= dc_scaler;
      /**/
   //assert(Divide(Fa, dc_scaler) == ( ((Fa>0)?(Fa+(dc_scaler>>1)):(Fa-(dc_scaler>>1)))/dc_scaler ));
   Fa = Divide(Fa, dc_scaler);

   ++dc;
   Fa *= dc_scaler;
   *dc = (short)Fa;
   return dc;
}

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

static void ClearBlock(short *block){

   int *i = (int*)block;
   const int *ie = i+32;
   do {
      i[3] = i[2] = i[1] = i[0] = 0;
      i[7] = i[6] = i[5] = i[4] = 0;
      i += 8;
   }while(i!=ie);
}

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

void C_mp4_decode_imp::BlockIntra(int pos, int coded_block_pattern){

   soft_idct.BeginBlock(POSX(pos), POSY(pos));

   PROF_S(PROF_BLOCK_INTRA);
   short *block = block_8x8;
                              //macroblock consists of four luminance blocks and the two spatially corresponding color difference blocks
   for(int i=0; i<6; ++i){
      int subpos;
      int dc_scaler = quantizer;

      ClearBlock(block);
      bit_reader.Load();
                              //stream: 24bit available
      if(i < 4){
                              //Y
         if(dc_scaler >24)
            dc_scaler = dc_scaler*2 - 16;
         else
         if(dc_scaler>8)
            dc_scaler = (dc_scaler + 8);
         else
         if(dc_scaler>4)
            dc_scaler <<= 1;
         else
            dc_scaler = 8;

                              //convert 1x1 -> 2x2 (accodring to block number)
         subpos = 2*POSX(pos) + (POSY(pos) << (MB_X2+2));
         subpos += (i & 1) + ((i & 2) << MB_X2);
      }else{
                              //UV
         if(dc_scaler > 24)
            dc_scaler = (dc_scaler - 6);
         else
         if(dc_scaler > 4)
            dc_scaler = (dc_scaler + 13)>>1;
         else
            dc_scaler = 8;

         subpos = pos;
      }
      int len;
      if(quantizer < intra_dc_threshold){
         int dct_dc_size, dct_dc_diff;

         dct_dc_diff = 0;
         dct_dc_size = i<4 ? bit_reader.GetDCsizeLum() : bit_reader.GetDCsizeChr(); //max11bit : max12bit

         if(dct_dc_size){
            dct_dc_diff = bit_reader.GetDCdiff(dct_dc_size);
            if(dct_dc_size > 8)          
               bit_reader.Flush(1); // marker bit  
         }
         *block = (short)(dct_dc_diff * dc_scaler);
         len = 1;
      }else
         len = 0;
                              //dc reconstruction, prediction direction
      int predict_dir;
      short *dc_addr = Dc_recon(i, subpos, dc_scaler, predict_dir);
      int scantype;
      if(ac_pred_flag){
         if(predict_dir == 1)   //TOP
            scantype = IDCTSCAN_ALT_HORI;
         else
            scantype = IDCTSCAN_ALT_VERT;
      }else
         scantype = IDCTSCAN_ZIGZAG;

      if((coded_block_pattern << (26+i)) < 0){
                              //coded block
         if(quant_type)
            len = Vld_block_mpeg(vld_intra, scan_table[scantype], len);
         else
            len = Vld_block_mpeg4(vld_intra, scan_table[scantype], len);
      }
                              //dc add 
      if(quantizer >= intra_dc_threshold){
         if(quant_type)
            *block = (short)(Divide(*block*8, quant_matrix[0][0] * quantizer) * dc_scaler);
         else
            *block = (short)(Divide(*block, quantizer*2) * dc_scaler);
      }
      *block = *dc_addr = (short)(*block + *dc_addr);
      
                              //ac reconstruction
      Ac_recon(i, subpos, predict_dir);
      soft_idct.Intra8x8(block, Max(len, 14), scantype);
   }
   PROF_E(PROF_BLOCK_INTRA);
}

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

void C_mp4_decode_imp::BlockInter(int coded_block_pattern){

                              //texture decoding add
                              //macroblock consists of four luminance blocks and the two spatially corresponding color difference blocks
   for(int i = 0; i < 6; i++){
      int len = 0;
      if((coded_block_pattern << (26+i)) < 0){
                              //coded
         ClearBlock(block_8x8);
         if(quant_type)
            len = Vld_block_mpeg(vld_inter, scan_table[IDCTSCAN_ZIGZAG], len);
         else
            len = Vld_block_mpeg4(vld_inter, scan_table[IDCTSCAN_ZIGZAG], len);
      }
      soft_idct.Inter8x8(block_8x8, len);
   }
}

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

static const signed char DQtab[4] = {
   -1, -2, 1, 2
};

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

void C_mp4_decode_imp::IVOP(){

   PROF_S(PROF_I_VOP);

   move_buf_invalid = 2; // invalid, but can be cleared to make it valid
   last_ref_frame_index = frame_index;
   block_update_base_indx = frame_index;
   MemSet(block_update_data, 0, mb_pos_end); // set all block to current frame (and clear rescue flag)

   resync_marker_bits = 17;

   for(int pos=0; pos<mb_pos_end; pos+=MAX_MACROBLOCKS_X-mb_xsize){
      for( ; POSX(pos)<mb_xsize; ++pos){
         bit_reader.Load();
                              //skip stuffing
         while(bit_reader.Show(9) == 1){
            bit_reader.Flush(9);
            bit_reader.Load();
            if(bit_reader.Eof())
               return;
         }
         if(bit_reader.Eof())
            return;

         if(ResyncMarker()){
            pos = ReSync();
            if(pos>=mb_pos_end)
               return;
         }
                              //stream: 24bits available
         int mcbpc = bit_reader.GetMCodedBlockPatternChrominance_i();
                              //stream: 15bits available
         ac_pred_flag = bit_reader.Get1();
         int coded_block_pattern = (bit_reader.GetCodedBlockPatternLuminance() << 2) | ((mcbpc >> 4) & 3);
            
         if((mcbpc & 7) == INTRA_Q){
                              //mb_type
            int q = quantizer + DQtab[bit_reader.Get(2)];
            quantizer = q<1 ? 1: q>31 ? 31 : q;
         }
         BlockIntra(pos, coded_block_pattern);
      }
   }
   PROF_E(PROF_I_VOP);
}

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

static int MvChroma(int v){
   v |= ((v & 0x3)!=0) << 1;     //adjust dx
   v |= ((v & 0x30000)!=0) << 17;   //adjust dy

   v >>= 1; //shift

   //replace dx sign bit with old signed bit
   v &= ~0x8000;        
   v |= (v & 0x4000) << 1;

   return v;
}

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

static const byte roundtab[16] = {
   0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2
};

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

#define sign(x) ((x)<0?-1:1)

static int MvChroma4(const int* mv){
   int dx = MOVE_VECTOR_X(mv[0]) + MOVE_VECTOR_X(mv[1]) + MOVE_VECTOR_X(mv[2]) + MOVE_VECTOR_X(mv[3]);
   int dy = MOVE_VECTOR_Y(mv[0]) + MOVE_VECTOR_Y(mv[1]) + MOVE_VECTOR_Y(mv[2]) + MOVE_VECTOR_Y(mv[3]);

   if (dx)
      dx = sign(dx) * (roundtab[Abs(dx) & 0xF] + ((Abs(dx) >> 4) <<1));
   
   if (dy)
      dy = sign(dy) * (roundtab[Abs(dy) & 0xF] + ((Abs(dy) >> 4) <<1));

   return MAKE_MOVEMENT_VECTOR_PAIR(dx, dy);
}

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

void C_mp4_decode_imp::PVOP(){

   PROF_S(PROF_P_VOP);
                              //if no b-frames, we need only one row of mv vectors
   int j;

   move_buf_invalid = 0;
   byte currframemap = byte(frame_index - block_update_base_indx);
   last_ref_frame_index = frame_index;
   resync_marker_bits = 16 + fcode_forward;

   int last_frame_index = soft_idct.GetPreviousDstFrameIndex();

   for(int pos=0; pos<mb_pos_end; pos+=MAX_MACROBLOCKS_X-mb_xsize){

      int *mv = &mv_buf[(pos & mv_bufmask)*4];

      for(;POSX(pos)<mb_xsize;++pos,mv+=4){
         bit_reader.Load();
                              //skip stuffing
         while(bit_reader.Show(10) == 1){
            bit_reader.Flush( 10);
            bit_reader.Load();
            if(bit_reader.Eof())
               return;
         }
         if(bit_reader.Eof())
            return;

         if(ResyncMarker()){
            pos = ReSync();
            if(pos>=mb_pos_end)
               return;

         }
                              //stream: 24bits available
         if(!bit_reader.Get1()){
            
                              //coded
            int mcbpc = bit_reader.GetMCodedBlockPatternChrominance_p();
            int mb_type = mcbpc & 7;
            mcbpc = (mcbpc >> 4) & 3;

            //stream: 14bits available

            block_update_data[pos] = (byte)currframemap;
            if(mb_type >= INTRA){

               ac_pred_flag = bit_reader.Get1();
               int coded_block_pattern = (bit_reader.GetCodedBlockPatternLuminance() << 2) | mcbpc;

                              //stream: 7bits available
               if(mb_type == INTRA_Q){
                  int q = quantizer + DQtab[bit_reader.Get(2)]; //DQtab[dquant]
                  quantizer = q<1 ? 1: (q>31 ? 31:q);
               }

               //stream: 5bits available

               mv[3] = mv[2] = mv[1] = mv[0] = 0;

               RescuePredict(pos);  //Restore AC_DC values
               BlockIntra(pos, coded_block_pattern);
            }else{
               //return;
               soft_idct.BeginBlock(POSX(pos), POSY(pos));

               block_update_data[pos] |= RESCUE; // set rescue needed flag

               int coded_block_pattern = ((15-bit_reader.GetCodedBlockPatternLuminance()) << 2) | mcbpc;

               //stream: 8bits available

               // we will use mv[4],mv[5] for temporary purposes
               // in the next macroblock it will be overwrite (mv incremented by 4)

               switch(mb_type){
               case INTER4V:
                  for(j = 0; j<4; j++)
                     mv[j] = bit_reader.GetMovementVectorPair(fcode_forward, GetPreviousMoveVector(j, pos));
                  mv[5] = mv[4] = MvChroma4(mv);
                  soft_idct.SetMotionCompensationData(mv, NULL);
                  break;

               case INTER_Q:
                  {
                     int q = quantizer + DQtab[bit_reader.Get(2)];
                     quantizer = q<1 ? 1: (q>31 ? 31:q);
                  }

               default: //INTER
                  mv[3] = mv[2] = mv[1] = mv[0] = bit_reader.GetMovementVectorPair(fcode_forward, GetPreviousMoveVector(0, pos));
                  mv[5] = mv[4] = MvChroma(mv[0]);

                  soft_idct.SetMotionCompensationData(mv, NULL);
                  break;
               }
               BlockInter(coded_block_pattern);
            }
         }else{
                              //not coded macroblock
            int n = block_update_base_indx + (block_update_data[pos]&0x7f);
            block_update_data[pos] |= RESCUE;

                              //copy needed or the buffer already has this block?
            if(last_frame_index < n)
               soft_idct.Copy16x16(POSX(pos), POSY(pos), 0);

            mv[3] = mv[2] = mv[1] = mv[0] = 0;
         }
      }
   }
   PROF_E(PROF_P_VOP);
}

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

#define vld_code \
   code = ShowBits(12); \
   if(code >> 9) \
      code = (code >> 5) - 16 + TABLE_1; \
   else if (code >> 7) \
      code = (code >> 2) - 32 + TABLE_2; \
   else /* if (code >= 8)  but we don't care about invalid huffman codes */ \
      code = code - 8 + TABLE_3;          \
   code = table[code];                    \
   FlushBits(code >> 12);

#define TABLE_1         0
#define TABLE_2         112
#define TABLE_3         112+96
#define TABLE_LMAX      112+96+120
#define TABLE_RMAX      112+96+120+64

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

int C_mp4_decode_imp::Vld_block_mpeg(const word *table, const byte *scan, int len){

   int q_add = 0;
   int q_scale = quantizer << 1;
   byte *q_matrix = quant_matrix[0];
   const byte *bit_ptr = bit_reader.ptr;
   int bitpos = bit_reader.pos, bits = bit_reader.bits;

   if(table == vld_inter){
      q_add = quantizer;
      q_matrix += 8*8;
   }

   do {// event vld
      int code,level;

      LoadBits();
      vld_code;
      level = code & 31; // 0x7FFF ESCAPE -> level = 31
      if(level != 31){
         code >>= 5;
         code &= 127;
         len += code; // last|run
      }else{
         LoadBits();
                              //this value is escaped
         if(!GetBits1()){
                              //Type 1
            vld_code;
            level = code & 31;
            code >>= 5;
            code &= 127;
            len   += code; // last|run
            level += ((byte*)(table+TABLE_LMAX))[code]; // table_lmax[last][run]
         }else
         if(!GetBits1()){
                              //Type 2   

⌨️ 快捷键说明

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