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

📄 passreg.cpp

📁 mpeg4编解码器
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************** * Some code. Copyright (C) 2003 by Pascal Massimino.   * * All Rights Reserved.      (http://skal.planet-d.net) * * For Educational/Academic use ONLY. See 'LICENSE.TXT'.* ********************************************************//* * two-pass log file regularizer * *********************************************************//* *   This program can be used to generate, from a 1rst-pass *   log file, a "roadmap" for the final encoding (2nd-pass). *  *   Usually, two-pass encoding amounts to the following three steps: *  *   a)  'tmp4 input.ppm -pass 1 -passfile pass1.log -q 2' *  *   This will generate a log file 'pass1.log' during the 1rst pass. *   The input source (input.ppm) is analyzed only, using a fixed  *   quantizer (Note: no bitstream is generated). *  *   b) 'passreg pass1.log -o pass2.log -tp 50 -v' *  *   This will generate a road map file 'pass2.log' that aims at *   reducing the original size by 50%. Various other options are *   available for 'passreg'. For instance: '-ts' to specify a *   target size, '-la'/'-ha/ for asymmetric bit distribution, etc... *  *   c) tmp4 input.ppm -pass 2 -passfile pass2.log -o output.mp4 -trellis -4v 60 *  *   This is the final encoding, using 'pass2.log' to drive the *   quality and control the size of the bitstream..  *   Any additional encoding option can be used (trellis, ...): *   they needn't be exactly the same than the first pass. *  *  *   Note: all of these are rather experimental, and you're encouraged *   to play with options/code, since it's all an external application *   from the core codec point of view. *  *  ********************************************************/#include <stdio.h>#include <math.h>#include <stdlib.h>#include <string.h>#include <assert.h>#ifdef _WINDOWS#include <io.h>#include <fcntl.h>#endifstruct PASS_PARAM{  struct PASS_FRAME {    int Pic_Type;    float Q, FCode, mMV, dMV;    int Bytes, Txt_Bytes, MV_Bytes;    int Avrg;    float Avrg_mMV, Avrg_dMV;    int New_Bytes, New_Txt_Bytes;    void Accumulate(int nMin, int nMax, const PASS_FRAME Frames[]);  };  struct PASS_SCENE {    int Start, Len;    int Bytes;    float Q_Avrg;  };  const char *In_File, *Out_File;  int Verbose;  int Target_Size;  float Target_Percent;  float FPS, Bit_Rate;  int Hi_Amp_Percent;  int Low_Amp_Percent;  int Min_Frame, Max_Frame, Nb_Frames;  int All_Frames, All_Key_Frames;  int All_Bytes, All_Txt_Bytes, All_MV_Bytes;  int Win_Size;  int Log_Type;   // 0: MPEG4, 1:H264  int Pic_W, Pic_H, Nb_MBs;  int Pic_Min_Sizes[3];  int KBoost_Percent;  int Reg_Method;       // 0: assymetric scale    1: use average  2: scene activity  float Act_Limit;  PASS_FRAME *Frames;  PASS_SCENE *Scenes;  void Reset();   // default values  void Cleanup();  void Compute_Windowed_Average();  void Regularize_Frames();  void Setup_New_Quantizers();  void Parse_In_File();  void Write_Out_File();  void Help( char **argv, const char *S=0 );  void Missing( const char *S );  int Parse_Int_Value(const int argc, const char * const *argv, int &k,                      const int Min=-0x7fffff, const int Max=0x7ffffff);  float Parse_Float_Value(const int argc, const char * const *argv, int &k,                          const float Min=-1.e30f, const float Max=1.e30f);  void Parse_Options( int argc, char **argv );  int Process(int argc, char *argv[]);   // main entry call};#define ERROR for( ; 1; throw this )//////////////////////////////////////////////////////////void PASS_PARAM::Reset(){  Out_File        = 0;  In_File         = 0;  Verbose         = 1;  Target_Size     = 0;  Target_Percent  = 0.;  FPS             = 25.f;  Bit_Rate        = 0;  Hi_Amp_Percent  = 30;  Low_Amp_Percent = 10;  Min_Frame       = 0;  Max_Frame       =-1;  Nb_Frames       = 0;  Win_Size        = 20;  Log_Type        =-1;  KBoost_Percent  = 5;  Reg_Method      = 0;  Act_Limit       = 0.5f;  Frames          = 0;  Scenes          = 0;}void PASS_PARAM::Cleanup(){  if (Frames) free(Frames);  if (Scenes) free(Scenes);  Reset();}//////////////////////////////////////////////////////////// The main workvoid PASS_PARAM::PASS_FRAME::Accumulate(int nMin, int nMax, const PASS_FRAME Frames[]){  Bytes = 0;  mMV = 0.;  dMV = 0.;  for(int n=nMin; n<nMax; ++n)  {    Bytes += Frames[n].Bytes;    mMV   += Frames[n].mMV;    dMV   += Frames[n].dMV;  }}void PASS_PARAM::Compute_Windowed_Average(){  int n, nMin, nMax;  PASS_FRAME Avrg;  n = Min_Frame;  for(nMin=n; nMin>=0 && nMin>=n-Win_Size; --nMin)    if (Frames[nMin].Pic_Type==0)      break;  for(nMax=n+1; nMax<=Max_Frame && nMax<=n+Win_Size; ++nMax)    if (Frames[nMax].Pic_Type==0)      break;  Avrg.Accumulate(nMin, nMax, Frames);  while(1)  {    const int Nb_Samples = nMax - nMin;    Frames[n].Avrg     = Avrg.Bytes / Nb_Samples;    Frames[n].Avrg_mMV = Avrg.mMV   / Nb_Samples;    Frames[n].Avrg_dMV = Avrg.dMV   / Nb_Samples;//    printf( "%d %d %d %d %d\n", n, nMin, nMax, Frames[n].Bytes, Frames[n].Avrg );    if (n==Max_Frame) break;    if (n-Win_Size==nMin) {      Avrg.Bytes -= Frames[nMin].Bytes;      Avrg.mMV   -= Frames[nMin].mMV;      Avrg.dMV   -= Frames[nMin].dMV;      nMin++;    }    n++;    if (n+Win_Size==nMax)    {      if (nMax<=Max_Frame && Frames[nMax].Pic_Type!=0) {        Avrg.Bytes += Frames[nMax].Bytes;        Avrg.mMV   += Frames[nMax].mMV;        Avrg.dMV   += Frames[nMax].dMV;        nMax++;      }    }    else if (n==nMax) {      nMin = nMax;      for(nMax=nMax+1; nMax<=Max_Frame && nMax<=n+Win_Size; ++nMax)        if (Frames[nMax].Pic_Type==0)          break;      Avrg.Accumulate(nMin, nMax, Frames);    }      }}void PASS_PARAM::Regularize_Frames(){  int n;  int Locked_Size = 0, Rest_Size = 0;  float Scale = Target_Percent/100.f;  for(n=Min_Frame; n<=Max_Frame; ++n)  {    const int Type = Frames[n].Pic_Type;    double s;    if (Type==0) {      s = 1. + KBoost_Percent/100.;    }    else {      if (Reg_Method==0) {        const int Delta = Frames[n].Bytes - Frames[n].Avrg;        if (Delta>=0) s = 1. + Hi_Amp_Percent/100.;        else          s = 1. + Low_Amp_Percent/100.;      }      else if (Reg_Method==1) {        s = 1.;      }      else {        double Activity;        double mMV = Frames[n].Avrg_mMV + .01;        double dMV = Frames[n].Avrg_dMV + .01;        Activity = log(mMV) - Act_Limit*log(dMV);        if (Activity>0.)        {          s = 1. + Activity*Low_Amp_Percent/100.;        }        else {//          Activity = 1. - (Act_Limit*dMV)/mMV;          s = 1. - Activity*Hi_Amp_Percent/100.;        }        if (Verbose>2)          printf( "%d %f %f %f %f %f %f\n", n, Activity, (float)s,            Frames[n].Avrg_mMV, Frames[n].mMV,            Frames[n].Avrg_dMV, Frames[n].dMV );      }    }    int New_Bytes = (Type==0) ? Frames[n].Bytes : Frames[n].Avrg;    New_Bytes = (int)( s*Scale * New_Bytes );    if (New_Bytes<Pic_Min_Sizes[Type])    {      New_Bytes = Pic_Min_Sizes[Type];      Frames[n].New_Bytes = New_Bytes;      Locked_Size += New_Bytes;    }    else {      Frames[n].New_Bytes = -New_Bytes;   // negative value indicates "TODO later"      Rest_Size += New_Bytes;    }  }  Scale = 1.f * (Target_Size - Locked_Size) / Rest_Size;  Locked_Size = 0;  for(n=Min_Frame; n<=Max_Frame; ++n)  {    if (Frames[n].New_Bytes<0)      Frames[n].New_Bytes = (int)( -Frames[n].New_Bytes*Scale );    Frames[n].New_Txt_Bytes = (int)( Frames[n].Txt_Bytes * 1.*Frames[n].New_Bytes / Frames[n].Bytes );    Locked_Size += Frames[n].New_Bytes;  }  if (Verbose>0) {    printf( "Final size:     %d bytes  [underflow:%.4f%%]\n", Locked_Size, 100.f*Locked_Size/Target_Size-100.f );    printf( "Final Bitrate:  %.2f kbps\n", FPS*Locked_Size*8.f/1000.f / Nb_Frames );    printf( "\n" );  }}void PASS_PARAM::Setup_New_Quantizers(){  int n;  for(n=Min_Frame; n<=Max_Frame; ++n)  {    float New_Q = 0.;    double Amp = 1. * Frames[n].Bytes / Frames[n].New_Bytes;    if (Log_Type==0) {      New_Q = (float)( Frames[n].Q * Amp );      New_Q = (New_Q<1.1f) ? 1.1f : (New_Q>31.5f) ? 31.5f : New_Q;    }    else {      New_Q = (float)( Frames[n].Q * ( 1.0 + 0.112*log( Amp ) ) );      New_Q = (New_Q<0.1f) ? 0.1f : (New_Q>51.0f) ? 51.0f : New_Q;    }    Frames[n].Q = New_Q;  }}//////////////////////////////////////////////////////////// Read in-filevoid PASS_PARAM::Parse_In_File(){  int i, n, Nb, s;  PASS_FRAME F = {0};  PASS_SCENE *Scene;  FILE *f;  char *Mem, *Start;  f = In_File ? fopen(In_File, "r") : stdin;  if (f==0) ERROR fprintf( stderr, "Can't open in-file %s\n", In_File );  fseek(f, 0, SEEK_END);  const int Size = (int)ftell(f);  fseek(f, 0, SEEK_SET);    Mem = (char*)malloc(Size+1);  if (Mem==0) ERROR fprintf( stderr, "Malloc error for reading file (size=%d)\n", Size+1);  if (fread(Mem, Size, 1, f)!=1) {    free(Mem);    ERROR fprintf( stderr, "Error reading in-file!\n" );  }

⌨️ 快捷键说明

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