(1)HM代码入口:main函数 encmain。找到main函数中调用的函数。再继续走下去
// call encoding function
<span style="color:#ff0000;">cTAppEncTop.encode()</span>;//cTAppEncTop时TAppEncTop的对象,该语句的含义是调用成员函数。。encode是类TAppEncTop的成员函数
// 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 0;
}
这里调用了TAppEncTop.cpp中定义的一个函数
cTAppEncTop.encode()
(2)转到TAppEncTop.cpp中,查看函数encode的定义
Void TAppEncTop::encode()
{
fstream bitstreamFile(m_pchBitstreamFile, fstream::binary | fstream::out);
if (!bitstreamFile)
{
fprintf(stderr, "\nfailed to open bitstream file `%s' for writing\n", m_pchBitstreamFile);//
exit(EXIT_FAILURE);
}
TComPicYuv* pcPicYuvOrg = new TComPicYuv;
TComPicYuv* pcPicYuvRec = NULL;
// initialize internal class & member variables
xInitLibCfg();//都是类中函数调用类中的函数
xCreateLib();//TAppEncTop的成员函数
xInitLib(m_isField);
printChromaFormat();
// main encoder loop主编码函数环路
Int iNumEncoded = 0;
Bool bEos = false;
const InputColourSpaceConversion ipCSC = m_inputColourSpaceConvert;
const InputColourSpaceConversion snrCSC = (!m_snrInternalColourSpace) ? m_inputColourSpaceConvert : IPCOLOURSPACE_UNCHANGED;
list<AccessUnit> outputAccessUnits; ///< list of access units to write out. is populated by the encoding process
TComPicYuv cPicYuvTrueOrg;
// allocate original YUV buffer分配原始YUV缓冲器
if( m_isField )
{
pcPicYuvOrg->create( m_iSourceWidth, m_iSourceHeightOrg, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth );
cPicYuvTrueOrg.create(m_iSourceWidth, m_iSourceHeightOrg, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth);
}
else
{
pcPicYuvOrg->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth );
cPicYuvTrueOrg.create(m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth);
}
while ( !bEos )
{
// get buffers
xGetBuffer(pcPicYuvRec);
// read input YUV file
m_cTVideoIOYuvInputFile.read( pcPicYuvOrg, &cPicYuvTrueOrg, ipCSC, m_aiPad, m_InputChromaFormatIDC );
// increase number of received frames
m_iFrameRcvd++;//总的帧数增加
bEos = (m_isField && (m_iFrameRcvd == (m_framesToBeEncoded >> 1) )) || ( !m_isField && (m_iFrameRcvd == m_framesToBeEncoded) );
Bool flush = 0;
// if end of file (which is only detected on a read failure) flush the encoder of any queued pictures
if (m_cTVideoIOYuvInputFile.isEof())
{
flush = true;
bEos = true;
m_iFrameRcvd--;
m_cTEncTop.setFramesToBeEncoded(m_iFrameRcvd);
}
// call encoding function for one frame
<span style="color:#ff0000;">if ( m_isField ) m_cTEncTop.encode</span>( bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded, m_isTopFieldFirst );
<span style="color:#ff0000;">else m_cTEncTop.encode(</span> bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded );
// write bistream to file if necessary
if ( iNumEncoded > 0 )
{
xWriteOutput(bitstreamFile, iNumEncoded, outputAccessUnits);
outputAccessUnits.clear();
}
}
m_cTEncTop.printSummary(m_isField);
// delete original YUV buffer
pcPicYuvOrg->destroy();
delete pcPicYuvOrg;
pcPicYuvOrg = NULL;
// delete used buffers in encoder class
m_cTEncTop.deletePicBuffer();
cPicYuvTrueOrg.destroy();
// delete buffers & classes
xDeleteBuffer();
xDestroyLib();
printRateSummary();
return;
}
(3)这里面调用了函数m_cTEncTop.encode(这样说不知道对不对),这函数是类TEncTop中的类函数,在TEncTop.cpp中定义了。
Void <span style="color:#cc0000;">TEncTop::encode</span>( Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded )
{
if (pcPicYuvOrg != NULL)
{
// get original YUV
TComPic* pcPicCurr = NULL;
xGetNewPicBuffer( pcPicCurr );
pcPicYuvOrg->copyToPic( pcPicCurr->getPicYuvOrg() );
pcPicYuvTrueOrg->copyToPic( pcPicCurr->getPicYuvTrueOrg() );
// compute image characteristics
if ( getUseAdaptiveQP() )
{
m_cPreanalyzer.xPreanalyze( dynamic_cast<TEncPic*>( pcPicCurr ) );
}
}
if ((m_iNumPicRcvd == 0) || (!flush && (m_iPOCLast != 0) && (m_iNumPicRcvd != m_iGOPSize) && (m_iGOPSize != 0)))
{
iNumEncoded = 0;
return;
}
if (<span style="color:#ff0000;"> m_RCEnableRateControl</span> )//在GOP层初始化
{
m_cRateCtrl.<span style="color:#ff0000;">initRCGOP</span>( m_iNumPicRcvd );//调用TENCRatectrl.cpp中的initRCGOP函数
}
// compress GOP
<span style="color:#ff0000;">m_cGOPEncoder.compressGOP</span>(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, false, false, snrCSC, m_printFrameMSE);
if ( m_RCEnableRateControl )
{
<span style="color:#ff0000;"> m_cRateCtrl.destroy</span>RCGOP();
}
iNumEncoded = m_iNumPicRcvd;
m_iNumPicRcvd = 0;
m_uiNumAllPicCoded += iNumEncoded;
}
这个函数的定义中有调用后面TEncGOP类中的函数
<span style="color:#ff0000;">GOPEncoder.compressGOP</span>
和码率控制模块的初始化函数 m_cRateCtrl.initRCGOP( m_iNumPicRcvd ),这里是码率控制函数第一次(???不确定)被调用。。下面就有两条路线了,一条直接进入码率控制模块,一条继续进入GOP>>slice>>cu。。下面先进入GOP层。。。
(4)
<span style="color: rgb(255, 0, 0);">GOPEncoder.compressGOP</span>
GOPEncoder声明为类TencGOP的对象函数,所以GOPEncoder.compressGOP就是调用类TencGOP的类函数compressGOP函数。
Void <span style="color:#cc0000;">TEncGOP::compressGOP</span>( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,
TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsInGOP,
Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE )
{
TComPic* pcPic;
TComPicYuv* pcPicYuvRecOut;
TComSlice* pcSlice;
TComOutputBitstream *pcBitstreamRedirect;
pcBitstreamRedirect = new TComOutputBitstream;
AccessUnit::iterator itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted
UInt uiOneBitstreamPerSliceLength = 0;
TEncSbac* pcSbacCoders = NULL;
TComOutputBitstream* pcSubstreamsOut = NULL;
xInitGOP( iPOCLast, iNumPicRcvd, rcListPic, rcListPicYuvRecOut, isField );
m_iNumPicCoded = 0;
SEIPictureTiming pictureTimingSEI;
Bool writeSOP = m_pcCfg->getSOPDescriptionSEIEnabled();
while(nextCUAddr<uiRealEndAddress) // determine slice boundaries
{
pcSlice->setNextSlice ( false );
pcSlice->setNextSliceSegment( false );
assert(pcPic->getNumAllocatedSlice() == startCUAddrSliceIdx);
m_pcSliceEncoder-><span style="color:#ff0000;">precompressSlice</span>( pcPic );
m_pcSliceEncoder-><span style="color:#cc0000;">compressSlice</span> ( pcPic );
这两个调用的函数是定义在TEncSlice.cpp中的,转到定义处,进入TEncSlice.cpp
(5)
Void TEncSlice::<span style="color:#ff0000;">compressSlice</span>( TComPic*& rpcPic )
{
UInt uiStartCUAddr;
UInt uiBoundingCUAddr;
rpcPic->getSlice(getSliceIdx())->setSliceSegmentBits(0);
TEncBinCABAC* pppcRDSbacCoder = NULL;
TComSlice* pcSlice = rpcPic->getSlice(getSliceIdx());
xDetermineStartAndBoundingCUAddr ( uiStartCUAddr, uiBoundingCUAddr, rpcPic, false );
// initialize cost values
m_uiPicTotalBits = 0;
m_dPicRdCost = 0;
m_uiPicDist = 0;
// set entropy coder
// run CU encoder
m_pcCuEncoder-><span style="color:#ff0000;">compressCU</span>( pcCU );
// restore entropy coder to an initial stage
compressCU被调用,函数进入TEncCu.cpp中
(6)
Void <span style="color:#ff0000;">TEncCu::compressCU</span>( TComDataCU*& rpcCU )
{
// initialize CU data
m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
// analysis of CU
DEBUG_STRING_NEW(sDebug)
xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 DEBUG_STRING_PASS_INTO(sDebug) );
DEBUG_STRING_OUTPUT(std::cout, sDebug)
这就走到最底层了吧?我是这么想的。。哈哈。。。还有就是在GOP<<slice<<cu每层都有调用RDcost ratecontrol类中的函数。。也就是这些控制在过程都有用到。现在还不知道怎么弄得,接下来就是分析这些了,那里调用了,为什么调用,为什么在哪里调用??对应的原理是什么,把代码翻译成理论。。。。。。