//给H264AVCEncoderTest* pcH264AVCEncoderTest分配空间,后面函数用它调用
//初始化pcH264AVCEncoderTest的成员,主要是编码器的参数配置
//给EncoderCodingParameter* m_pcEncoderCodingParameter分配空间
//它是H264AVCEncoderTest *pcH264AVCEncoderTest的成员
EncoderCodingParameter::create( m_pcEncoderCodingParameter ) //编码参数
//解析输入命令行,并把相应参数写入EncoderCodingParameter的基类CodingParameter的成员中
m_pcEncoderCodingParameter->init()
//读取配置文件
xReadFromFile( cFilename, rcBitstreamFile )
fopen( rcFilename.c_str(), "r"); encoder.cfg
//先创建每个参数
m_pEncoderLines[uiParLnCount++] = new EncoderConfigLineXXX
//从配置文件里读一行,重复直到文件末尾
xReadLine( f, acTags )
//查找读到的参数对应的m_pEncoderLines,更新值
fclose( f );
//从上面的配置文件读到的参数中得到有几层,和每层配置文件路径
//对每一层
setDependencyId(ui); //设置Did
//读取每一层的配置文件 读到如下类中
//EncoderCodingParameter::LayerParameters m_acLayerParameters[n]
xReadLayerFromFile( acLayerConfigName[ui], getLayerParameters(ui) )
//打开配置文件 layerX.cfg
//分配空间并初始化参数m_pLayerLines[] ,也是CodingParameter成员
//读取配置文件每行,并更新对应m_pLayerLines的值
//初始化ScalingList
xReadScalMat()
//设置输入输出文件路径
rcLayer.setInputFilename ( (Char*)cInputFilename.c_str() );
rcLayer.setOutputFilename ( (Char*)cOutputFilename.c_str() );
//初始化每个LayerParameters::ResizeParameters m_cResizeParameters
//读取SliceGroup的配置文件
xReadSliceGroupCfg( rcLayer)
//读取ROI配置文件
xReadROICfg( rcLayer)
//关闭配置文件
//设置CGS/MGS的Dependency_Id和Quality_id
//由BaseLayer更新当前Layer的ResizeParameter----------ESS
//对每一层 rcLayer = m_pcEncoderCodingParameter->getLayerParameters( uiLayer );
//创建并打开重建输出文件
WriteYuvToFile::create( m_apcWriteYuv[uiLayer] )
m_apcWriteYuv[uiLayer]->init( rcLayer.getOutputFilename() )
//创建并打开读入的视频文件
ReadYuvFile ::create( m_apcReadYuv [uiLayer] )
m_apcReadYuv[uiLayer]->init()
//创建并打开码流文件
WriteBitstreamToFile::create ( m_pcWriteBitstreamToFile )
m_pcWriteBitstreamToFile->init ( m_cEncoderIoParameter.cBitstreamFilename )
注意:
以上三个文件都是H264AVCEncoderTest类的成员
WriteBitstreamToFile* m_pcWriteBitstreamToFile;
WriteYuvToFile* m_apcWriteYuv [MAX_LAYERS];
ReadYuvFile* m_apcReadYuv [MAX_LAYERS];
也用到了辅助IO的成员
EncoderIoParameter m_cEncoderIoParameter;
//给编码器分配空间:它是H264AVCEncoderTest *pcH264AVCEncoderTest的成员
h264::CreaterH264AVCEncoder::create( m_pcH264AVCEncoder )
ParameterSetMng ::create( m_pcParameterSetMng )
BitWriteBuffer ::create( m_pcBitWriteBuffer )
BitCounter ::create( m_pcBitCounter )
NalUnitEncoder ::create( m_pcNalUnitEncoder)
SliceEncoder ::create( m_pcSliceEncoder )
UvlcWriter ::create( m_pcUvlcWriter )
UvlcWriter ::create( m_pcUvlcTester, false )
CabacWriter ::create( m_pcCabacWriter )
MbCoder ::create( m_pcMbCoder )
MbEncoder ::create( m_pcMbEncoder )
LoopFilter ::create( m_pcLoopFilter )
IntraPredictionSearch ::create( m_pcIntraPrediction )
MotionEstimationQuarterPel ::create( m_pcMotionEstimation )
H264AVCEncoder ::create( m_pcH264AVCEncoder )
ControlMngH264AVCEncoder ::create( m_pcControlMng )
ReconstructionBypass ::create( m_pcReconstructionBypass )
QuarterPelFilter ::create( m_pcQuarterPelFilter )
Transform ::create( m_pcTransform )
SampleWeighting ::create( m_pcSampleWeighting )
XDistortion ::create( m_pcXDistortion )
PicEncoder ::create( m_pcPicEncoder )
//每一层的编码器
for( UInt uiLayer = 0; uiLayer < MAX_LAYERS; uiLayer++ )
{
LayerEncoder ::create( m_apcLayerEncoder [uiLayer] )
PocCalculator ::create( m_apcPocCalculator [uiLayer] )
YuvBufferCtrl ::create( m_apcYuvFullPelBufferCtrl[uiLayer] )
YuvBufferCtrl ::create( m_apcYuvHalfPelBufferCtrl[uiLayer] )
}
//设置NAL UNIT起始码m_aucStartCodeBuffer[],绑定到H264AVCEncoderTest::BinData m_cBinDataStartCode;
//进行编码
//初始化编码器参数 h264::CreaterH264AVCEncoder* m_pcH264AVCEncoder; H264AVCEncoderTest成员
m_pcH264AVCEncoder->init( m_pcEncoderCodingParameter )
/*
几个参数关系
1. H264AVCEncoderTest的成员CreaterH264AVCEncoder* m_pcH264AVCEncoder调用init
2. 初始化H264AVCEncoderTest的成员EncoderCodingParameter * m_pcEncoderCodingParameter
3. 而CreaterH264AVCEncoder的成员CodingParameter* m_pcCodingParameter
被赋值传入的参数m_pcEncoderCodingParameter
*/
RateDistortion::create( m_pcRateDistortion ) //给率失真计算类分配空间 RateDistortion
m_pcBitWriteBuffer ->init() //初始化写Packet/比特流的类 BitWriteBuffer
m_pcBitCounter ->init() //初始化计算比特数类 BitCounter
m_pcXDistortion ->init() //初始化计算失真所需的参数 (块行数/列数/Dist计算函数指针)XDistortion
m_pcSampleWeighting ->init() //初始化加权函数 SampleWeighting
//初始化写NalUnit的类 NalUnitEncoder
m_pcNalUnitEncoder->init( m_pcBitWriteBuffer, m_pcUvlcWriter, m_pcUvlcTester )
m_pcUvlcWriter ->init( m_pcBitWriteBuffer ) //关联比特流缓存和写Uvlc的类 UvlcWriter
m_pcUvlcTester ->init( m_pcBitCounter ) //关联比特计数和写Uvlc的类 UvlcWriter
m_pcCabacWriter ->init( m_pcBitWriteBuffer ) //初始化Cabac的缓存 CabacWriter CabacEncoder
m_pcParameterSetMng ->init() //空函数
m_pcSliceEncoder->init() //关联MbEncoder、MbCoder、ControlMngH264AVCEncoder、CodingParameter、
PocCalculator和Transform 给Slice编码器 SliceEncoder
m_pcReconstructionBypass ->init() //空函数
m_pcLoopFilter->init( m_pcControlMng, m_pcReconstructionBypass, true ) //关联 ControlMngH264AVCEncoder和
ReconstructionBypass给去块滤波器 LoopFilter
m_pcQuarterPelFilter->init() //分配1/4像素插值滤波器 QuarterPelFilter
m_pcMbEncoder->init() //关联Transform、IntraPredictionSearch、MotionEstimation、CodingParameter、
RateDistortion和XDistortion给宏块编码器 MbEncoder
m_pcMotionEstimation ->init() MotionEstimation
MotionCompensation::init() //初始化MC相关—1/4插值滤波、变换、加权
//设置计算失真、MV搜索参数
MotionEstimationCost::xInit() //设置RD相关
//设置跟搜索范围搜索深度有关参数
// spiral search参数
m_pcControlMng->init() //分配上面所有的编码过程类到ControlMngH264AVCEncoder类中,集中管理
//包括每层的LayerEncoder、PocCalculator和YuvBufferCtrl
m_pcPicEncoder->init() //初始化AVC编码器
m_pcH264AVCEncoder ->init() //初始化SVC编码器 分配LayerEncoder、ParameterSetMng、PocCalculator、
// NalUnitEncoder、ControlMngIf和CodingParameter
//初始化LayerEncoder* m_apcLayerEncoder[MAX_LAYERS]
和AccessUnitDataList m_cAccessUnitDataList; H264AVCEncoder
//对每层
m_apcLayerEncoder[uiLayer]->init() //初始化每层编码所需的参数
//把配置文件读入的参数LayerParameter复制过来
xInitCodingOrder() // 初始化编码顺序和分层的对应关系
//初始化如ESS、LARDO等参数
//计算每层采用LARDO的情况
//Rate Control相关初始化,与GOP有关
//写SPS和PPS
参数:
UChar aucParameterSetBuffer[1000] 作为缓存
BinData cBinData 绑定上面的缓存
ExtBinDataAccessor cExtBinDataAccessor 操纵上面的cBinData
m_pcH264AVCEncoder->writeParameterSets( &cExtBinDataAccessor, pcAVCSPS, bMoreSets ) CreaterH264AVCEncoder
m_pcH264AVCEncoder->writeParameterSets( pcExtBinDataAccessor, rpcAVCSPS, rbMoreSets ) H264AVCEncoder
//如果是第一次调用
xInitParameterSets()
//对每一层
//设置基本参数
SequenceParameterSet::create( pcSPS ) // 分配SPS空间
PictureParameterSet ::create( pcPPS ) // 分配PPS空间
//设置SPS和PPS的ID和NalUnitType
ParameterSetMng* m_pcParameterSetMng有成员
StatBuf<SequenceParameterSet*,2*NUM_SPS_IDS> m_cSPSBuf; 当前对应SPS_ID的SPS
StatBuf<PictureParameterSet*,256> m_cPPSBuf; 当前对应PPS_ID的PPS
std::list<SequenceParameterSet*> m_cSPSList; 历史上的SPS存在此(和当前SPS_ID重合的)
std::list<PictureParameterSet*> m_cPPSList; 历史上的PPS存在此和当前PPS_ID重合的)
调用store()函数将(按ID)
PPS =>m_cPPSBuf 而从m_cPPSBuf取出的PPS => m_cPPSList
SPS =>m_cSPSBuf 而从m_cSPSBuf取出的SPS => m_cSPSList
m_pcParameterSetMng->store( pcPPS )
m_pcParameterSetMng->store( pcSPS )
设置m_auiActiveSPSId[uiDQId] = SPS_ID
每个QualityLayer都有一个m_auiActiveSPSId[uiDQId]
m_pcParameterSetMng->setActiveSPS( pcSPS->getSeqParameterSetId(), uiDQId + ui );
//设置SPS的内容
//设置subset SPS的内容
//设置PPS内容
// 初始化每层与帧分辨率有关的参数
m_pcControlMng->initParameterSets( *pcSPS, *pcPPS ) ControlMngH264AVCEncoder
m_apcYuvFullPelBufferCtrl[uiLayer]->initSPS( uiAllocY, uiAllocX, YUV_Y_MARGIN, YUV_X_MARGIN)
m_apcYuvHalfPelBufferCtrl[uiLayer]->initSPS( uiAllocY, uiAllocX, YUV_Y_MARGIN, YUV_X_MARGIN, 1 )
m_apcLayerEncoder [uiLayer]->initParameterSets( rcSPS, rcPPS )
//从ParameterSetMng类中的SPS和PPS缓存m_cSPSBuf和m_cPPSBuf读取并保存到
//std::list<SequenceParameterSet*> m_cUnWrittenSPS 和 std::list<PictureParameterSet*> m_cUnWrittenPPS;
m_pcParameterSetMng->setParamterSetList( m_cUnWrittenSPS, m_cUnWrittenPPS )
// 写SEI相关信息
//m_cUnWrittenSPS和m_cUnWrittenPPS非空,则
m_pcNalUnitEncoder->initNalUnit( pcExtBinDataAccessor ) //初始化写Nalunit的类
m_pcBitWriteBuffer->initPacket( (UInt*)(m_pucTempBuffer), m_uiPacketLength-1 ) //初始化写比特流的类
//读取SPS/PPS
m_pcNalUnitEncoder->write( rcSPS )
rcSPS.write( m_pcHeaderSymbolWriteIf ) //由m_pcHeaderSymbolWriteIf写NalUnit
m_pcNalUnitEncoder->closeNalUnit( uiBits )
xWriteTrailingBits() //写1000…补齐
m_pcBitWriteBuffer->flushBuffer() //把拖尾等最后的数据写入并计算bit
convertRBSPToPayload(…) //加上0x03
m_pcWriteBitstreamToFile->writePacket ( &m_cBinDataStartCode ) //先写starcode 0x00000001 区分NALUNIT
m_pcWriteBitstreamToFile->writePacket ( &cExtBinDataAccessor ) //再写实际NAL内容
//计算每层图像宽高、Crop信息和luma与chroma的Offset等
//对每个Frame ==============================START===============================
//对每一层 XXXXXXXXXXXXXXX START
本函数的重要参数:在H264AVCEndoderTest::go()函数里
PicBuffer* apcOriginalPicBuffer [MAX_LAYERS]; //原始图像list
PicBuffer* apcReconstructPicBuffer [MAX_LAYERS]; //重建图像list
PicBufferList acPicBufferOutputList [MAX_LAYERS]; //输出图像list
PicBufferList acPicBufferUnusedList [MAX_LAYERS];
ExtBinDataAccessorList cOutExtBinDataAccessorList; //输出NalUnit的list
//从PicBufferList m_acUnusedPicBufferList [MAX_LAYERS] 中弹出一个PicBuffer
//并存入PicBufferList m_acActivePicBufferList [MAX_LAYERS];
xGetNewPicBuffer( apcReconstructPicBuffer [uiLayer], uiLayer, auiPicSize[uiLayer] ) //重建帧
xGetNewPicBuffer( apcOriginalPicBuffer [uiLayer], uiLayer, auiPicSize[uiLayer] ) //原始帧
m_apcReadYuv[uiLayer]->readFrame(…) // 读取一帧到apcOriginalPicBuffer [uiLayer]
XXXXXXXXXXXXXXX END
//处理一帧,所有Layer都处理,数据写入cOutExtBinDataAccessorList CreaterH264AVCEncoder调用
m_pcH264AVCEncoder->process(cOutExtBinDataAccessorList,apcOriginalPicBuffer,
apcReconstructPicBuffer, acPicBufferOutputList, acPicBufferUnusedList )
àm_pcH264AVCEncoder->process( rcExtBinDataAccessorList, H264AVCEncoder调用
apcOriginalPicBuffer,
apcReconstructPicBuffer,
apcPicBufferOutputList,
apcPicBufferUnusedList )
xWrite ( cOutExtBinDataAccessorList, uiBytesUsed ) //把编码一帧后的NALUNIT写到比特流中
//重复,直到cOutExtBinDataAccessorList为空
m_pcWriteBitstreamToFile->writePacket( &m_cBinDataStartCode ) //写起始码
m_pcWriteBitstreamToFile->writePacket( rcList.front() ) //写NalUnit
//对每层
xWrite ( acPicBufferOutputList[uiLayer], uiLayer ) //把输出图像(重建文件)写到文件中
//从list中弹出一个图像
m_apcWriteYuv[uiLayer]->writeFrame()
m_cFile.write( pucSrc, uiWidth ) //重复调用此函数写重建图像
xRelease( acPicBufferUnusedList[uiLayer], uiLayer )
xRemovePicBuffer( rcPicBufferList, uiLayer ) //删除未使用的图像
//从m_acActivePicBufferList中找到acPicBufferUnusedList中每一帧
//从m_acActivePicBufferList中删除,添加到m_acUnusedPicBufferList中
==============================END===============================
m_pcH264AVCEncoder->finish(…)
m_pcH264AVCEncoder->finish(…)
//把不足GOP数量剩下的帧进行编码
xProcessGOP( apcPicBufferOutputList, apcPicBufferUnusedList )
//从AccessUnitDataList m_cAccessUnitDataList的成员std::list<AccessUnitData>m_cAccessUnitDataList
//取出编码后的NalUnit到cOutExtBinDataAccessorList
m_cAccessUnitDataList.emptyNALULists( rcExtBinDataAccessorList )
m_apcLayerEncoder[uiLayer]->finish() //输出每层的编码信息,如比特数和PSNR等
xWrite ( cOutExtBinDataAccessorList, uiWrittenBytes ) //把cOutExtBinDataAccessorList中的Nal写到比特流
//对每一层
xWrite ( acPicBufferOutputList[uiLayer], uiLayer ) //把输出图像(重建文件)写到文件中
xRelease( acPicBufferUnusedList[uiLayer], uiLayer ) //删除未使用的图像
//写SEI信息
m_pcH264AVCEncoder->writeParameterSets( &cExtBinDataAccessor, pcAVCSPS, bMoreSets )
m_pcWriteBitstreamToFile->writePacket ( &m_cBinDataStartCode )
m_pcWriteBitstreamToFile->writePacket ( &cExtBinDataAccessor )
m_pcWriteBitstreamToFile->uninit() //关闭比特流文件
m_pcWriteBitstreamToFile->destroy() //释放空间
ScalableDealing() //把临时的比特流文件转成Scalable比特流
//结束函数
//释放m_cBinDataStartCode、m_pcH264AVCEncoder、读写文件、m_pcEncoderCodingParameter和一些List的空间