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

📄 tmp4.cpp

📁 mpeg4编解码器
💻 CPP
📖 第 1 页 / 共 3 页
字号:
  SKL_UINT32 Code = 0xDeadBeef;  do Code = (Code<<8) | fgetc(f);  while( Code!=Marker && !feof(f) );  return feof(f);}static long Parse_Input_File(SKL_BYTE *Buf, size_t Size, FILE *f){  int Ok = 0;  if (System_Stream==1)      // Ultra-Simplistic AVI Parser  {    static SKL_UINT32 Chunk_Size = 0;    static int Have_MOVI = 0;    if (!Have_MOVI) {      const SKL_UINT32 _movi_ = FourCC( "movi" );      if (Locate_Marker(_movi_, f))        return 0;      Have_MOVI = 1;    }    while(Size>0) {      while (Chunk_Size==0) {        SKL_UINT16 Nb = Get16b_LE(f);        SKL_UINT32 Id = Get16b_LE(f);        SKL_UINT32  S = Get32b_LE(f);        S += (S&1);        Nb = ((Nb>>8)-'0') + ((Nb&0xff)-'0')*10;        if ( Nb!=0 || Id!=TwoCC( "dc" ) )          fseek(f, S, SEEK_CUR);        else          Chunk_Size = S;      }      size_t Gotten = fread(Buf+Ok, 1, (Size>Chunk_Size) ? Chunk_Size : Size, f);      Ok         += Gotten;      Chunk_Size -= Gotten;      Size       -= Gotten;    }  }  else if (System_Stream==1)    // Ultra-Dumb MPG Parser  {    // not yet done...  }  else {    Ok = fread(Buf, 1, Size, f);  }  return Ok;}////////////////////////////////////////////////////////////// main decoding loop (very decorated!)////////////////////////////////////////////////////////////static int Decode_MPEG4(SKL_CST_STRING Name){    // create codec instance  MP4_New_Decoder = (SKL_MP4_NEW_DEC)SKL_LOAD_DYN_SYMBOL(SKL_MP4_DLL, Skl_MP4_New_Decoder);  MP4_Delete_Decoder = (SKL_MP4_DELETE_DEC)SKL_LOAD_DYN_SYMBOL(SKL_MP4_DLL, Skl_MP4_Delete_Decoder);  if (MP4_New_Decoder==0 || MP4_Delete_Decoder==0)  // problem with DLL    return -1;  SKL_MP4_DEC *Dec = MP4_New_Decoder();  if (Dec==0) return -2;  if (Trace_Mem)    Dec->Set_Memory_Manager(All_Mem);  Dec->Set_CPU( Cpu );  if (With_Slices) Dec->Set_Slicer(Display_Slice,0);      // Dec debug level: 1:show MVs  2:print scanlines 3-4: print infos   if (Debug>=4) Dec->Set_Debug_Level(Debug-3);    // Prepare a PSNR_INFOS for external PSNR comparison  PSNR_INFOS PSNR_Infos;       // open I/O files  FILE *f;  long Fullness, Left_To_Read, Size, Left;  SKL_BYTE *Buf, *mBuf = 0;  const int MAX_BUF = 400000;   // TODO: BAD  SKL_BYTE Buf0[MAX_BUF+4] = {0};     // +4 = sentinel (just in case)  int Err = 0;  SKL_PTIMER pTimer;  f = fopen( Name, "rb" );  if (f==0) {    fprintf( stderr, "Can't open file '%s' for reading.\n", Name );    return -1;  }  fseek(f, 0, SEEK_END);  Size = ftell(f);  rewind(f);  if (From_Mem) {    mBuf = (SKL_BYTE*)All_Mem->New(Size);    Buf = mBuf;    Fullness = Parse_Input_File(Buf, Size, f);    if (Fullness==0) {      Err = -1;      goto End;    }    Left_To_Read = 0;  }  else {    Buf = Buf0;    Left_To_Read = Size;    Fullness = 0;    if (Streaming && Jump_To>0) {      if (!Quiet) printf( "Jumping to offset %ld in file\n", Jump_To );      fseek(f, Jump_To, SEEK_SET); // wowowow!!    }  }      // main decoding loop  if (!Quiet)    printf( "Decoding MP4 bitstream '%s' (size:%ld).\n", Name, Size);  Left = Size;  pTimer.Reset();  while(Left>=0)  {    float Next_Tick = pTimer.Get_mSec();    if (!From_Mem && Fullness<MAX_BUF/2) {      if (Fullness>0)        memmove( Buf0, Buf, Fullness);      Buf = Buf0;      const int Free = MAX_BUF-Fullness;      size_t More = (Left_To_Read>Free) ? Free : Left_To_Read;      if (More>0) {        More = Parse_Input_File(Buf+Fullness, More, f);        Fullness += More;        Left_To_Read -= More;      }    }    int Read = MPEG12 ? Dec->Decode_MPEG12(Buf, Fullness)                      : Dec->Decode(Buf, Fullness);    if (Read>Fullness)      throw SKL_EXCEPTION( "Aieeee! Buffer read overflow" );    if (Debug==2)      printf( " Left:%ld consumed:%d fullness=%ld\n", Left, Read, Fullness );    else if (Debug==3)  // for gnuplot      printf( "%d %d %ld\n", Dec->Get_Frame_Number(), Read, Fullness );    if (Left==0 && Read==0) Left = -1;   // very last frame    else Left -= Read;    Buf       += Read;    Fullness  -= Read;    if (!Dec->Is_Frame_Ready() || Skip_Frames-->0)      continue;    if (Delay>0)          pTimer.Wait(1.0f*Delay);    else if (FPS>0.)    {      Next_Tick += 1000.f / FPS - pTimer.Get_mSec();      if (Next_Tick>0.)        pTimer.Wait(Next_Tick);      /* else: Hurry up! */    }          pTimer++;    SKL_MP4_PIC Pic;    if (VTrace==4) Dec->Get_All_Frames(&Pic);    else {      Dec->Consume_Frame(&Pic);      if (Debug==1)        printf( "Decoded frame #%d (Time stamp=%.3f s)   \r", Dec->Get_Frame_Number(), Pic.Time);      if (Show_PSNR)        Compare_PSNR_External(&Pic, &PSNR_Infos);    }    Deal_With_Pic( Pic, Dec->Get_Frame_Number() );    if (!Quiet && pTimer.Get_Count()==1)      printf( " - Frames size: %dx%d\n", Pic.Width, Pic.Height );    if (!Streaming && Jump_To>0 && !From_Mem && pTimer.Get_Count()==1) {      if (!Quiet) printf( "Jumping to offset %ld in file\n", Jump_To );      fseek(f, Jump_To, SEEK_SET); // wowowow!!      Fullness = 0;    }    if (!--Nb_Frames)      break;  }  if (Quiet!=1) pTimer.Elapsed_FPS(0,"\n");End:  if (f!=0) fclose(f);  if (From_Mem)    All_Mem->Delete(mBuf, Size);  MP4_Delete_Decoder(Dec);  return Err;}//////////////////////////////////////////////////////////////   Encoding////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// example of external "Slicer" hook //   => computes PSNR for each slice////////////////////////////////////////////////////////////static void Sliced_PSNR(const SKL_MP4_PIC *Pic, int yo, int Height, SKL_ANY Data){  PSNR_INFOS *I = (PSNR_INFOS*)Data;  if (Height==0)    // start/end of scan?  {    if (yo==0) {      // start of scan      I->Check(Pic->Width, Pic->Height, Pic->BpS);      I->Store(I->Y, Pic->Y, Pic->Width,   Pic->Height,   Pic->BpS);      I->Store(I->U, Pic->U, Pic->Width/2, Pic->Height/2, Pic->BpS);      I->Store(I->V, Pic->V, Pic->Width/2, Pic->Height/2, Pic->BpS);    }    else {            // end of scan      SKL_UINT32 SSE_Y = I->Get_SSE(I->Y, Pic->Y, Pic->Width,   Pic->Height,   Pic->BpS);      SKL_UINT32 SSE_U = I->Get_SSE(I->U, Pic->U, Pic->Width/2, Pic->Height/2, Pic->BpS);      SKL_UINT32 SSE_V = I->Get_SSE(I->V, Pic->V, Pic->Width/2, Pic->Height/2, Pic->BpS);      Img_Dsp.Switch_Off();      I->PSNR_Y += I->pY = I->Compute_PSNR(SSE_Y, Pic->Width*Pic->Height);      I->PSNR_U += I->pU = I->Compute_PSNR(SSE_U, Pic->Width*Pic->Height/4);      I->PSNR_V += I->pV = I->Compute_PSNR(SSE_V, Pic->Width*Pic->Height/4);      I->PSNR_A += I->pA = I->Compute_PSNR(SSE_Y+SSE_U+SSE_V, 3*Pic->Width*Pic->Height/2);      I->Cnt++;      if (I->Cnt==10000) {          // reset every ~10000 frames, to avoid overflow...          // (yeah, I know, we won't end up with the real PSNR :)        I->PSNR_Y /= I->Cnt;        I->PSNR_U /= I->Cnt;        I->PSNR_V /= I->Cnt;        I->PSNR_A /= I->Cnt;        I->Cnt = 1;      }    }  }  else { /* we're in a slice. */ }}////////////////////////////////////////////////////////////// Main encoding loop////////////////////////////////////////////////////////////static int Parse_Custom_Matrix_File(SKL_MP4_ENC *const Enc){  FILE *f = fopen(Custom_Matrix, "r");  if (f==0) {    fprintf( stderr, "Can't open custom matrix file [%s]\n", Custom_Matrix );    return 0;  }  SKL_BYTE M[2*64];  int i, k;  for(i=0; i<2*64; ++i)    if (fscanf(f, "%d", &k)!=1) return 0;    else M[i] = k;  fclose(f);  Enc->Set_Custom_Matrix(0, M+ 0);  Enc->Set_Custom_Matrix(1, M+64);  return 1;}static int Encode_MPEG4(SKL_CST_STRING Out_Name, SKL_CST_STRING In_Name){    // create an encoder instance  MP4_New_Encoder = (SKL_MP4_NEW_ENC)SKL_LOAD_DYN_SYMBOL(SKL_MP4_DLL, Skl_MP4_New_Encoder);  MP4_Delete_Encoder = (SKL_MP4_DELETE_ENC)SKL_LOAD_DYN_SYMBOL(SKL_MP4_DLL, Skl_MP4_Delete_Encoder);  if (MP4_New_Encoder==0 || MP4_Delete_Encoder==0)  // problem with DLL     return -1;  SKL_MP4_ENC *Enc = MP4_New_Encoder();  if (Enc==0) return -2;      /* Enc debug level: 1:show MVs  2:print scanlines 3-4: print infos  */  if (Debug>=4) Enc->Set_Debug_Level(Debug-3);  Enc->Set_CPU( Cpu );  Enc->Set_Memory_Manager(All_Mem);  Enc->Get_Analyzer()->Set_Memory_Manager(All_Mem);  if (Streaming) Enc->Ioctl( "emit-key-headers" );  if (Sequence_Codes) Enc->Ioctl( "emit-sequence-codes" );  if (Custom_Matrix)     if (!Parse_Custom_Matrix_File(Enc)) {      fprintf( stderr, "Custom matrix parsing failed!\n" );      return -2;    }    // warm up the analyzer  if (FPS==0) FPS = 29.970f;   // dflt value  Enc->Get_Analyzer()->Set_Param( "bitrate", Bit_Rate );  Enc->Get_Analyzer()->Set_Param( "framerate", FPS );  Enc->Get_Analyzer()->Set_Param( "base-quant", Global_Q );  Enc->Get_Analyzer()->Set_Param( "quant", Global_Q );  Enc->Get_Analyzer()->Set_Param( "quant-type", Quant_Type );  Enc->Get_Analyzer()->Set_Param( "intra-max-delay", Intra_Max );  Enc->Get_Analyzer()->Set_Param( "4v-probing", Inter4V_Probing );  Enc->Get_Analyzer()->Set_Param( "field-pred-probing", Field_Pred_Probing );  Enc->Get_Analyzer()->Set_Param( "gmc-mode", Use_GMC );  Enc->Get_Analyzer()->Set_Param( "gmc-pts", 3 );  Enc->Get_Analyzer()->Set_Param( "gmc-accuracy", GMC_Accuracy );  Enc->Get_Analyzer()->Set_Param( "reduced-frame", Use_Reduced );  Enc->Get_Analyzer()->Set_Param( "interlace-field", Interlace_Field );  Enc->Get_Analyzer()->Set_Param( "rounding", 0 );  Enc->Get_Analyzer()->Set_Param( "search-metric", Search_Metric );  Enc->Get_Analyzer()->Set_Param( "sad-skip-limit", SAD_Skip_Limit );  Enc->Get_Analyzer()->Set_Param( "sad-intra-limit", SAD_Intra_Limit );  Enc->Get_Analyzer()->Set_Param( "interlace-dct", Interlace_DCT );  Enc->Get_Analyzer()->Set_Param( "base-search-size", MV_Size );  Enc->Get_Analyzer()->Set_Param( "search-size", MV_Size );  Enc->Get_Analyzer()->Set_Param( "search-method", Search_Method );  Enc->Get_Analyzer()->Set_Param( "subpixel", Sub_Pixel );  Enc->Get_Analyzer()->Set_Param( "dquant-amp", dQuant_Amp );    Enc->Get_Analyzer()->Set_Param( "lambda", Lambda );  Enc->Get_Analyzer()->Set_Param( "intra-limit", Intra_Limit );  Enc->Get_Analyzer()->Set_Param( "inter-threshold", Inter_Thresh );  Enc->Get_Analyzer()->Set_Param( "use-trellis", Use_Trellis );  Enc->Get_Analyzer()->Set_Param( "hi-mem", Hi_Mem );  Enc->Get_Analyzer()->Set_Param( "buffer-size", Enc_Buf_Size );  Enc->Get_Analyzer()->Set_Param( "verbose", ADebug );  Enc->Get_Analyzer()->Set_Param( "pass", Pass_Nb);  Enc->Get_Analyzer()->Set_Param( "passfile", Pass_File);  Enc->Get_Analyzer()->Set_Param( "passrf", Pass_RF);    // plug PNSR slicer hook  PSNR_INFOS PSNR_Infos;  if (Show_PSNR&(1|2))    Enc->Set_Slicer(Sliced_PSNR, (SKL_ANY)&PSNR_Infos);    // open I/O files  int Err = 0;  FILE *In = 0, *Out = 0;    int Cnt = 0;  int W=0, H=0;  int Pos = 0;  SKL_PTIMER pTimer;  long Out_Size = 0;  if (In_Name) {    In = fopen(In_Name, "rb");    if (In==0) {      fprintf( stderr, "Can't open file '%s'!\n", In_Name );      Err = -1;      goto End;    }  }  else In = stdin;  if (Out_Name!=0) {    Out = fopen(Out_Name, "wb");    if (Out==0) {      fprintf( stderr, "Can't open file '%s' for writing.", Out_Name );      Err = -1;      goto End;    }    if (!Quiet)      printf( "Encoding MP4 bitstream '%s'.\n", Out_Name);  }  else SKL_ASSERT(Pass_Nb==1);      // Pass #1 doesn't require to output a bitstream (just stats)    // main loop  pTimer.Reset();  while( PGM_In(Enc, In, &W, &H, Cnt*1000./FPS) )  {    if (Skip_Frames-->0)      continue;    if (Use_Reduced>=0 && (((W/16)&1) || ((H*2/3/16)&1)) ) {      printf( "Reduced frames problem: Frame size %dx%d cannot be split into 32x32 blocks!!\n", W, H );      goto End;    }    ++Cnt;    if (!Quiet)      if (!(Cnt&0xf)) printf( "Encoding frame #%d   \r", Cnt );    Enc->Encode();    if (Enc->Get_Bits_Length())     {      if (Out!=0 && fwrite( Enc->Get_Bits(), Enc->Get_Bits_Length(), 1, Out )!=1) {        fprintf( stderr, "Write error!\n" );        Err = -1;        goto End;      }      Out_Size += Enc->Get_Bits_Length();// Example of key-frame detection://      const SKL_MP4_PIC *Last = Enc->Get_Last_Coded_Frame();//      if (Last->Coding==0) printf( "Key frame! (%ld)    ", Last->Time_Ticks );      if (Debug==2) {        printf( " Pos:%d Frame size:%d\n", Pos, Enc->Get_Bits_Length());        Pos += Enc->Get_Bits_Length();      }    }    pTimer++;    if (Show_PSNR&1)      PSNR_Infos.Print_Infos();    if (VTrace!=0) {      SKL_MP4_PIC Pic;      Enc->Get_All_Frames(&Pic);      Deal_With_Pic(Pic, pTimer.Get_Count());    }    if (!--Nb_Frames)      break;

⌨️ 快捷键说明

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