编码器在整个HM解决方案中的工程名为TAppEncoder,入口点函数位于encmain.cpp文件中:
int main(int argc, char* argv[])
{
TAppEncTop cTAppEncTop; // print information
fprintf( stdout, "\n" );
fprintf( stdout, "HM software: Encoder Version [%s] (including RExt)", NV_VERSION );
fprintf( stdout, NVM_ONOS );
fprintf( stdout, NVM_COMPILEDBY );
fprintf( stdout, NVM_BITS );
fprintf( stdout, "\n\n" ); // create application encoder class
cTAppEncTop.create(); // parse configuration
try
{
if(!cTAppEncTop.parseCfg( argc, argv ))
{
cTAppEncTop.destroy();
#if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST
EnvVar::printEnvVar();
#endif
return ;
}
}
catch (df::program_options_lite::ParseFailure &e)
{
std::cerr << "Error parsing option \""<< e.arg <<"\" with argument \""<< e.val <<"\"." << std::endl;
return ;
} #if PRINT_MACRO_VALUES
printMacroSettings();
#endif #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST
EnvVar::printEnvVarInUse();
#endif // starting time
Double dResult;
clock_t lBefore = clock(); // call encoding function
cTAppEncTop.encode(); // ending time
dResult = (Double)(clock()-lBefore) / CLOCKS_PER_SEC;
printf("\n Total Time: %12.3f sec.\n", dResult); // destroy application encoder class
cTAppEncTop.destroy(); return ;
}
main
主要包括:
- 入口点函数main()【创建cTAppEncTop类,解析输入的配置函数,设定时间相关的参数】
- cTAppEncTop.encode()【对编码器所使用的几个对象进行初始化,分配YUV数据缓存,循环读取YUV文件】
- m_cTEncTop.encode(...)【调用m_cGOPEncoder.compressGOP()实现对一个GOP的实际编码】
- m_cGOPEncoder.compressGOP()【调用initGOP设置GOP的参数;调用m_pcSliceEncoder->initEncSlice(),利用SPS和PPS中的信息创建编码的slice对象;调用m_pcSliceEncoder->compressSlice ( pcPic )对一个slice进行编码。】
- m_pcSliceEncoder->compressSlice ( pcPic )【设置编码slice的参数,对slice的每一个cu进行处理】
- TEncCu::compressCU()【编码一个CU】
以上各个函数分别在前一个函数中调用,形成类似一个反向的call stack的结构。
函数调用关系如下:
main()——>cTAppEncTop.encode()——>m_cTEncTop.encode(...)——>m_cGOPEncoder.compressGOP()——>m_pcSliceEncoder->compressSlice()——>
xCheckRDCostInter()帧间
m_pcCuEncoder->compressCtu()——>xCompressCU()——>xCheckRDCostIntra()帧内
xCheckIntraPCM()PCM