JM8.6编码器中的Configure函数究竟做了什么?(编程思想:抽象,间接)

来源:互联网 发布:档案管理系统软件源码 编辑:程序博客网 时间:2024/04/27 16:55

        从字面意思来看,configure就是配置的意思,顾名思义,Configure函数就是配置函数了。配置函数的作用是给程序配置(设定)一些初始的值,这些值在很大程度上相当于一个开关.

 

        在用别人写的软件的时候,我们经常在软件的界面的某一个对话框里面输入一个参数,然后软件里的程序就会捕捉到这个对话框里面的参数,这样就把用户设定的参数传到了程序里面。细想一下,在JM8.6编码器中就是这样的,这里的“对话框”实际上是一个配置文件,比如:encoder_baseline.cfg. 那为什么需要这样一个配置文件呢?原因很简单,为了抽象,为了间接. 抽象是为了更好地重用. 间接又可以实现职责的分离,即用户可以通过配置文件来设定自己想用的参数,而不需要去改软件的程序.

        

        先来简要地看一个结构体类型InputParameters, 在编码器的global.h中,是这么定义的:

typedef struct{  //档次  int ProfileIDC;               //!< profile idc    //级别  int LevelIDC;                 //!< level idc    //编码的帧数  int no_frames;                //!< number of frames to be encoded    //第一帧QP  int qp0;                      //!< QP of first frame    //剩余帧QP  int qpN;                      //!< QP of remaining frames    //隔n帧编码  int jumpd;                    //!< number of frames to skip in input sequence (e.g 2 takes frame 0,3,6,9...)    int hadamard;                 /*!< 0: 'normal' SAD in 1/3 pixel search.  1: use 4x4 Haphazard transform and '                                     Sum of absolute transform difference' in 1/3 pixel search                   */    //搜索范围  int search_range;             /*!< search range - integer pel search and 16x16 blocks.  The search window is                                     generally around the predicted vector. Max vector is 2xmcrange.  For 8x8                                     and 4x4 block sizes the search range is 1/2 of that for 16x16 blocks.       */    //参考帧数  int num_reference_frames;     //!< number of reference frames to be used    int P_List0_refs;  int B_List0_refs;  int B_List1_refs;  //图像宽度和高度必须是整MB的  int img_width;                //!< image width  (must be a multiple of 16 pels)  int img_height;               //!< image height (must be a multiple of 16 pels)    //目前只支持4 : 2 : 0  int yuv_format;               //!< GH: YUV format (0=4:0:0, 1=4:2:0, 2=4:2:2, 3=4:4:4,currently only 4:2:0 is supported)    //目前只支持8位色深  int color_depth;              //!< GH: YUV color depth per component in bit/pel (currently only 8 bit/pel is supported)  int intra_upd;                /*!< For error robustness. 0: no special action. 1: One GOB/frame is intra coded                                     as regular 'update'. 2: One GOB every 2 frames is intra coded etc.                                     In connection with this intra update, restrictions is put on motion vectors                                     to prevent errors to propagate from the past                                */  int blc_size[8][2];           //!< array for different block sizes  int slice_mode;               //!< Indicate what algorithm to use for setting slices  int slice_argument;           //!< Argument to the specified slice algorithm    //帧间宏块是否可用作帧内预测  int UseConstrainedIntraPred;  //!< 0: Inter MB pixels are allowed for intra prediction 1: Not allowed  int  infile_header;           //!< If input file has a header set this to the length of the header    //输入,输出,重建,跟踪. (4个文件名)  char infile[100];             //!< YUV 4:2:0 input format  char outfile[100];            //!< H.264 compressed output bitstream  char ReconFile[100];          //!< Reconstructed Pictures  char TraceFile[100];          //!< Trace Outputs      int intra_period;             //!< Random Access period though intra    // IDR片  int idr_enable;//!< Encode intra slices as IDR    //编码帧的开始位置  int start_frame;//!< Encode sequence starting from Frame start_frame  // B pictures  int successive_Bframe;        //!< number of B frames that will be used  int qpB;                      //!< QP of B frames  int direct_type;              //!< Direct Mode type to be used (0: Temporal, 1: Spatial)  int directInferenceFlag;      //!< Direct Inference Flag  // SP Pictures  int sp_periodicity;           //!< The periodicity of SP-pictures  int qpsp;                     //!< SP Picture QP for prediction error  int qpsp_pred;                //!< SP Picture QP for predicted block  int WeightedPrediction;        //!< Weighted prediciton for P frames (0: not used, 1: explicit)  int WeightedBiprediction;      //!< Weighted prediciton for B frames (0: not used, 1: explicit, 2: implicit)  int StoredBPictures;           //!< Stored (Reference) B pictures replace P pictures (0: not used, 1: used)  //熵编码方式  int symbol_mode;              //!< Specifies the mode the symbols are mapped on bits    //输出文件方式(output file mode)即0:Annex B, 1:RTP  int of_mode;                  //!< Specifies the mode of the output file    //分割方式  int partition_mode;           //!< Specifies the mode of data partitioning  //帧间搜索方式  int InterSearch16x16;  int InterSearch16x8;  int InterSearch8x16;  int InterSearch8x8;  int InterSearch8x4;  int InterSearch4x8;  int InterSearch4x4;  char PictureTypeSequence[MAXPICTURETYPESEQUENCELEN];  int FrameRate;  int chroma_qp_index_offset;#ifdef _FULL_SEARCH_RANGE_  int full_search;#endif#ifdef _ADAPT_LAST_GROUP_  int last_frame;#endif#ifdef _CHANGE_QP_  int qpN2, qpB2, qp2start;  int qp02;#endif  int rdopt;#ifdef _LEAKYBUCKET_  int NumberLeakyBuckets;  char LeakyBucketRateFile[100];  char LeakyBucketParamFile[100];#endif  int PicInterlace;           //!< picture adaptive frame/field  int MbInterlace;            //!< macroblock adaptive frame/field  int IntraBottom;            //!< Force Intra Bottom at GOP periods.  int LossRateA;              //!< assumed loss probablility of partition A (or full slice), in per cent, used for loss-aware R/D optimization  int LossRateB;              //!< assumed loss probablility of partition B, in per cent, used for loss-aware R/D   int LossRateC;              //!< assumed loss probablility of partition C, in per cent, used for loss-aware R/D   int NoOfDecoders;  int RestrictRef;  int NumFramesInELSubSeq;  int NumFrameIn2ndIGOP;  int RandomIntraMBRefresh;     //!< Number of pseudo-random intra-MBs per picture  int LFSendParameters;  int LFDisableIdc;  int LFAlphaC0Offset;  int LFBetaOffset;  int SparePictureOption;  int SPDetectionThreshold;  int SPPercentageThreshold;  // FMO  char SliceGroupConfigFileName[100];    //!< Filename for config info fot type 0, 2, 6  int num_slice_groups_minus1;           //!< "FmoNumSliceGroups" in encoder.cfg, same as FmoNumSliceGroups, which should be erased later  int slice_group_map_type;   int *top_left;                         //!< top_left and bottom_right store values indicating foregrounds  int *bottom_right;   int *slice_group_id;                   //!< slice_group_id is for slice group type being 6    int *run_length_minus1;                //!< run_length_minus1 is for slice group type being 0  int slice_group_change_direction_flag;  int slice_group_change_rate_minus1;  int slice_group_change_cycle;  int redundant_slice_flag; //! whether redundant slices exist,  JVT-D101  int pic_order_cnt_type;   // POC200301  int context_init_method;  int model_number;  //! Rate Control on JVT standard   int RCEnable;      int bit_rate;  int SeinitialQP;  int basicunit;  int channel_type;  // FastME enable(快速运动估计)  int FMEnable;} InputParameters;


        可以看出, InputParameters结构体类型实际上就是对各种输入参数的一个打包. 在lencod.c中有下面的全局变量定义:

InputParameters inputs, *input = &inputs;


         最终配置文件的信息都会导入到input->...里面,那么究竟怎么导入呢?这就要看Configure函数了,在main中, Configure函数是这样被调用的:

Configure (argc, argv);


         在典型的正常配置下(可以在VC6.0中配置), argc = 3,  argv[0]指向"...lencod.exe",  argv[1]指向"-d",  argv[2]指向 "encoder_baseline.cfg",  也就是说,有了argc和argv,就有了配置文件的名字. 下面进入Configure函数看看:(说明,只给出程序正常进入的部分,只为示意)

 

void Configure(int ac, char *av[]){  char *content, *filename;  //configinput 在configfile.h中定义为:InputParameters configinput;  //下面语句将configinput中的数据项全部置为0  memset (&configinput, 0, sizeof (InputParameters));    configinput.LevelIDC   = LEVEL_IDC;  configinput.ProfileIDC = PROFILE_IDC;    filename = av[2]; //获得了正确的"encoder_baseline.cfg"     //content指向了堆内存,堆内存中的内容串是配置文件的内容串,很长  content = GetConfigFileContent (filename);  //下面对content指向的内容串进行分析  //以便让lencod.c中的全局变量input->...从配置文件中获取足够信息  ParseContent (content, strlen(content));    free (content);  PatchInp();//对input->...的合法性进行检验}


        原来, Configure函数就是专门干这个的.