看JMVC(joint multiview video coding)代码有一段时间了,现在虽然对代码中的一些数据结构和代码在H264的语法语义上的映射还不是很清楚,但也算对整个JMVC的编码框架有了一定的了解,希望能给还在迷茫中的朋友一些启发,也希望有人能指出我理解有问题的地方。
总体的框架如下:
1、主程序在H264AVCEncoderLibTest.cpp中,虽然只有区区几行代码,但要弄懂其是干什么的还是要按好几遍F11的。
RNOK( H264AVCEncoderTest::create( pcH264AVCEncoderTest ) );
创建个编码器的对象
RNOKS( pcH264AVCEncoderTest->init ( argc, argv ) );
初始化,主要是读入调用exe时后面的命令和配置文件
RNOK ( pcH264AVCEncoderTest->go () );
实施编码
RNOK ( pcH264AVCEncoderTest->destroy() );
销毁对象
2、实施编码的go()函数在H264AVCEncoderTest.cpp中,其中包含了大量的初始化信息,目前来说我看的还不是很清楚,希望大牛能解释下这些初始化的工作都做了些什么。实质性的编码工作就集中在一个函数中m_pcH264AVCEncoder->process( cOutExtBinDataAccessorList,apcOriginalPicBuffer,apcReconstructPicBuffer,acPicBufferOutputList,acPicBufferUnusedList )
这个函数后续又调用了一大堆处理函数,涉及很多的类和文件,就不费口舌说的那么细了,退一步说,目前我也说不出个所以然来,只能说下基本的框架,初始化和最后生成码流的部分就不提了,直接说下编码的部分。
PicEncoder.cpp:
process()
{
While(true) 每次循环编码完成一帧图像
{
if( ! pcInputAccessUnit ){break;} 终止条件
xEncodePicture(); 编码
}
}
在xEncodePicture中,会根据片头中的信息来选择m_pcSliceEncoder->encodeSliceMbAff()或m_pcSliceEncoder->encodeSlice()进行图像帧的片层编码。
SliceEncoder.cpp:
在encoderSlice()中,会对片层中的每个宏块进行编码
For(……)
{
m_pcMbEncoder->encodeMacroblock()
m_pcMbCoder->encode()
}
在encodeMacroblock()中,会根据帧的类型和编码模式来选择相应的预测方式,并选出最佳的预测方式。
if( rcMbDataAccess.getSH().isInterP() && bSkipModeAllowed )
{
RNOK( xEstimateMbSkip ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1 ) );
}
if( rcMbDataAccess.getSH().isInterB() )
{
RNOK( xEstimateMbDirect ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1, NULL, false,bSkipModeAllowed ) );
}
if( rcMbDataAccess.getSH().isInterP() || rcMbDataAccess.getSH().isInterB() )
{
RNOK( xEstimateMb16x16 ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1, false, uiNumMaxIter, uiIterSearchRange, false, NULL, false ) );
RNOK( xEstimateMb16x8 ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1, false, uiNumMaxIter, uiIterSearchRange, false, NULL, false ) );
RNOK( xEstimateMb8x16 ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1, false, uiNumMaxIter, uiIterSearchRange, false, NULL, false ) );
RNOK( xEstimateMb8x8 ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1, false, uiNumMaxIter, uiIterSearchRange, false, NULL, false ) );
RNOK( xEstimateMb8x8Frext ( m_pcIntMbTempData, m_pcIntMbBestData, rcList0, rcList1, false, uiNumMaxIter, uiIterSearchRange, false, NULL, false ) );
}
RNOK( xEstimateMbIntra16 ( m_pcIntMbTempData, m_pcIntMbBestData, rcMbDataAccess.getSH().isInterB() ) );
RNOK( xEstimateMbIntra8 ( m_pcIntMbTempData, m_pcIntMbBestData, rcMbDataAccess.getSH().isInterB() ) );
RNOK( xEstimateMbIntra4 ( m_pcIntMbTempData, m_pcIntMbBestData, rcMbDataAccess.getSH().isInterB() ) );
RNOK( xEstimateMbPCM ( m_pcIntMbTempData, m_pcIntMbBestData, rcMbDataAccess.getSH().isInterB() ) );
以上应该就是JMVC整个编码的流程,但其中我还是有很多不懂的地方,希望大家多和我交流,共同进步。