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

📄 mp4_decode.cpp

📁 鼎鼎有名的手机mpeg4播放器smart movie-智能影院 解码内核
💻 CPP
📖 第 1 页 / 共 5 页
字号:
            vld_code;
            len += (code >> 5) & 127;
            code &= 31;
            level = code;
            if (code > 11) code = 11;
            if (len >= 64) code += 16; // add (last bit << 4)
            len += ((byte*)(table+TABLE_RMAX))[code]; // table_rmax[last][min(11,level)]
         }else{
                              //Type 3  - fixed length codes
            code = ShowBits(20);
            FlushBits(21);
            level = (code << 20) >> 20; //sign extend the lower 12 bits
            if (level < 0)
               level = -level;
            len   += code >> 13;  // last|run
            level *= q_scale;
            level += q_add;
            level *= q_matrix[scan[len & 63]];
            level >>= 4;

            if ((code << 20) < 0)
               level = -level;

            block_8x8[scan[len & 63]] = (short)level;
            continue;
         }
      }

      code = scan[len & 63];

      level *= q_scale;
      level += q_add;
      level *= q_matrix[code];
      level >>= 4;

      if(GetBits1()) 
         level = -level;

      block_8x8[code] = (short)level;
   }while(++len < 64);

   bit_reader.pos = bitpos;
   bit_reader.ptr = bit_ptr;
   bit_reader.bits = bits;
   return len - 64;
}

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

#define vld_write \
   block_8x8[scan[len & 63]] = (short)level; \
   if(++len < 64) continue; \
   bit_reader.pos = bitpos; \
   bit_reader.ptr = bit_ptr; \
   bit_reader.bits = bits; \
   return len - 64;

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

#define vld_quant \
   level *= q_scale; \
   level += q_add; \
   if(GetBits1()) \
      level = -level;

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

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

   int q_scale = quantizer << 1;
   int q_add = (quantizer-1) | 1;
   const byte *bit_ptr = bit_reader.ptr;
   int bitpos = bit_reader.pos, bits = bit_reader.bits;

   while(true){
                              //event vld
      int code;
      LoadBits();

      vld_code;
      int level = code&31; // 0x7FFF ESCAPE -> level = 31
      if(level != 31){
         code >>= 5;
         code &= 127;
         len += code; // last|run
         vld_quant
         vld_write
      }else{
                              //this value is escaped
         LoadBits();
         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]
            vld_quant
            vld_write
         }else
         if(!GetBits1()){
                              //Type 2
            vld_code;
            len += (code >> 5) & 127;
            code &= 31;
            level = code;
            if (code > 11) code = 11;
            if (len >= 64) code += 16; // add (last bit << 4)
            len += ((byte*)(table+TABLE_RMAX))[code]; // table_rmax[last][min(11,level)]
            vld_quant
            vld_write
         }else{
                              //Type 3  - fixed length codes
            code = ShowBits(21) >> 1;
            FlushBits(21);
            level = (code << 20) >> 20; //sign extend the lower 12 bits
            level *= q_scale;
            len   += code >> 13;  // last|run
            if(level > 0)
               level += q_add;
            else
               level -= q_add;

            vld_write;
         }
      }
   }
}

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

static const byte def_quant_inter[64] = {
   16, 17, 18, 19, 20, 21, 22, 23,
   17, 18, 19, 20, 21, 22, 23, 24,
   18, 19, 20, 21, 22, 23, 24, 25,
   19, 20, 21, 22, 23, 24, 26, 27,
   20, 21, 22, 23, 25, 26, 27, 28,
   21, 22, 23, 24, 26, 27, 28, 30,
   22, 23, 24, 26, 27, 28, 30, 31,
   23, 24, 25, 27, 28, 30, 31, 33
}, def_quant_intra[64] = {
    8, 17, 18, 19, 21, 23, 25, 27,
   17, 18, 19, 21, 23, 25, 27, 28,
   20, 21, 22, 23, 24, 26, 28, 30,
   21, 22, 23, 24, 26, 28, 30, 32,
   22, 23, 24, 26, 28, 30, 32, 35,
   23, 24, 26, 28, 30, 32, 35, 38,
   25, 26, 28, 30, 32, 35, 38, 41,
   27, 28, 30, 32, 35, 38, 41, 45
};

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

void C_mp4_decode_imp::ReadHeader_vol(){

   bit_reader.Flush(32+1+8); // start_code + random_accessible_vol + video_object_type_indication
   bit_reader.Load();
    
   int visual_object_layer_verid;
   if(bit_reader.Get1()){
                              //object layer identifier
      visual_object_layer_verid = bit_reader.Get(4);
      bit_reader.Flush(3); // video_object_layer_priority
   }else{
      visual_object_layer_verid = 1;
   }

   int aspect = bit_reader.Get(4); // aspect ratio
   if(aspect == ASPECT_CUSTOM) {
      bit_reader.Load();
      bit_reader.Get(8); //aspect_width
      bit_reader.Get(8); //aspect_height
   }

   if(bit_reader.Get1()){ // vol control parameters
      bit_reader.Flush(2); // chroma_format
      has_b_frames = !bit_reader.Get1();
      if(has_b_frames) // b-frames
         SetIDCTBufferCount(3);
      if(bit_reader.Get1()) // vbv parameters
         bit_reader.Flush(15+1+15+1+15+1+3+11+1+15+1);
   }

   bit_reader.Flush(2+1); // shape + marker
   bit_reader.Load();

   time_increment_resolution = bit_reader.Get(16);
   if(time_increment_resolution <= 0)
      time_increment_resolution = 1;
   time_increment_bits = FindHighestBit(time_increment_resolution-1)+1;

   bit_reader.Flush(1); // marker
   if(bit_reader.Get1()) //fixed_vop_rate
      bit_reader.Flush(time_increment_bits);

   bit_reader.Flush(1); // marker
   bit_reader.Load();
   int width = bit_reader.Get(13); //width
   bit_reader.Flush(1);
   bit_reader.Load();
   int height = bit_reader.Get(13); //height
   bit_reader.Flush(1); // marker
   interlaced = bit_reader.Get1();
   /*
   if (interlaced && showerror && NotSupported(MPEG4_ERROR_INTERLACE)) // interlace
      return;
      */

   bit_reader.Flush(1); // obmc_disable

   if(width!=video_sx || height!=video_sy){
      valid_vol = false;
      return;
   }

   bit_reader.Load();
   sprite_type = (E_SPRITE_TYPE)bit_reader.Get((visual_object_layer_verid==1) ? 1 : 2);
   if(sprite_type == SPRITE_STATIC || sprite_type == SPRITE_GMC){
      //assert(0);
      //if(showerror && NotSupported(MPEG4_ERROR_GMC))
         //return;

      if(sprite_type != SPRITE_GMC) {
         bit_reader.Flush(13+1+13+1+13+1+13+1); //width+marker+height+marker+left+marker+top+marker
         bit_reader.Load();
      }
                              //sprite warping points
      bit_reader.Get(6);
                              //sprite warping accuracy
      bit_reader.Get(2);
      bit_reader.Get1(); // brightness change not supported

      if(sprite_type != SPRITE_GMC)
         bit_reader.Flush(1); // low_latency_sprite_enable
   }
      
   bit_reader.Load();
   if(bit_reader.Get1()){  // not 8 bit
      quant_precision = bit_reader.Get(4);
      bit_reader.Flush(4); // bit per pixel
   }else 
      quant_precision = 5;

   bool quant_type = bit_reader.Get1();
   if(quant_type){ // quant type
      if(bit_reader.Get1())  // load intra
         bit_reader.GetQuantMatrix(quant_matrix[0]);
      else
         MemCpy(quant_matrix[0], def_quant_intra, sizeof(def_quant_intra));

      if(bit_reader.Get1())  // load inter
         bit_reader.GetQuantMatrix(quant_matrix[1]);
      else
         MemCpy(quant_matrix[1], def_quant_inter, sizeof(def_quant_inter));
   }

   bit_reader.Load();
   if(visual_object_layer_verid != 1) {
      if(bit_reader.Get1()){// && showerror)// && NotSupported(MPEG4_ERROR_QPEL))
                              //quarter-pel
         assert(0);
         //return;
      }
   } 

   bit_reader.Flush(1); // complexity estimation
   bit_reader.Flush(1); // resync marker disabled (?)

   if(bit_reader.Get1()){
                              //partitioning
      bit_reader.Flush(1);
      assert(0);
      //if(showerror)// && NotSupported(MPEG4_ERROR_PARTITIONING))
         //return;
      //return;
   }

   if(visual_object_layer_verid != 1) {
      if(bit_reader.Get1()) //new pred not supported
         bit_reader.Flush(2+1); // req msg type, seg type
      bit_reader.Flush(1); //reduced res not supported
   }

   if(bit_reader.Get1()) // scalability
      bit_reader.Flush(1+4+1+5+5+5+5+1); // not supported

   valid_vol = true;
   //showerror = 0;
}

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

static const byte tab_intra_dc_threshold[] = {
   32,
   13,
   15,
   17,
   19,
   21,
   23,
   1,
};

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

void C_mp4_decode_imp::ReadHeader_vop(E_FRAME_TYPE &frame_prediction_type){

   bit_reader.Flush(32);
   bit_reader.Load();

   frame_prediction_type = (E_FRAME_TYPE)bit_reader.Get(2);

   while(bit_reader.Get1())
      bit_reader.Load();

   bit_reader.Flush(1); //marker
   bit_reader.Load();

   int time_increment = bit_reader.Get(time_increment_bits);
   if(time_increment_resolution){
      if(frame_prediction_type != B_VOP){
         time_pp = (time_increment_resolution + time_increment - last_ref_time) % time_increment_resolution;
         last_ref_time = time_increment;
      }else{
         time_bp = (time_increment_resolution + last_ref_time - time_increment) % time_increment_resolution;
      }
   }

   bit_reader.Flush(1); //marker
   bit_reader.Load();

   if(!bit_reader.Get1()){
      frame_prediction_type = N_VOP;
      return;
   }  

   bool rounding = false;
   if(frame_prediction_type == P_VOP || frame_prediction_type == S_VOP)
      rounding = bit_reader.Get1();
   soft_idct.SetRounding(rounding);

   intra_dc_threshold = tab_intra_dc_threshold[bit_reader.Get(3)];

   if(interlaced)
      bit_reader.Flush(2); //top_field_first, alternate_scan

   //if (frame_prediction_type == S_VOP && (sprite_type == SPRITE_STATIC || sprite_type == SPRITE_GMC))
      //spritetrajectory(this);
   quantizer = bit_reader.Get(quant_precision); // vop quant

   bit_reader.Load();
   if(frame_prediction_type != I_VOP) 
      fcode_forward = bit_reader.Get(3); 

   if(frame_prediction_type == B_VOP) 
      fcode_backward = bit_reader.Get(3); 
}

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

bool C_mp4_decode_imp::ReadFrameHeaders(E_FRAME_TYPE &frame_prediction_type){

   while(true){
      bit_reader.ByteAlign();
      bit_reader.Load();

      if(bit_reader.Eof())
         return false;
      int code = bit_reader.Show(32);

      if((code & ~VOL_START_CODE_MASK) == VOL_START_CODE){
         ReadHeader_vol();
      }else
      if(code == VOP_START_CODE){
         ReadHeader_vop(frame_prediction_type);
         return true;
      }else
         bit_reader.Flush(8);
   }
}

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

void C_mp4_decode_imp::BlockDirect(int pos, int dmv, int coded_block_pattern){

   int fmv[6];
   int bmv[6];

   int *mv = &mv_buf[pos*4];
   
   for(int j=0; j<4; ++j,++mv){
      int dx, dy, v;

      v = trb * MOVE_VECTOR_X(*mv);
      if(v<0) //best code for (v<0)
         --v;
      dx = v >> 8;
      if(dx<0) ++dx;

      v = trb * MOVE_VECTOR_Y(*mv);
      if(v<0) //best code for (v<0)
         --v;
      dy = v >> 8;
      if(dy<0) ++dy;

      dx += MOVE_VECTOR_X(dmv);
      dy += MOVE_VECTOR_Y(dmv);

      fmv[j] = MAKE_MOVEMENT_VECTOR_PAIR(dx, dy);
      
      if(dmv & 0xffff)
         dx -= MOVE_VECTOR_X(*mv);
      else{
         v = trb_trd * MOVE_VECTOR_X(*mv);
         if(v<0) //best code for (v<0)
            --v;
         dx = v >> 8;
         if(dx<0) ++dx;
      }
      if(dmv & 0xffff0000)
         dy -= MOVE_VECTOR_Y(*mv);
      else{
         v = trb_trd * MOVE_VECTOR_Y(*mv);
         if(v

⌨️ 快捷键说明

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