📄 qualitylevelassigner.cpp
字号:
if( uiLevel == MSYS_UINT_MAX )
printf( "determine distortion (layer %d - FGS %d - base layer ) ...", uiLayer, uiFGSLayer );
else
printf( "determine distortion (layer %d - FGS %d - lev%2d - %s ) ...", uiLayer, uiFGSLayer, uiLevel, bIndependent?"ind":"dep" );
#if WIN32
Char tmp_file_name[] = "decout.tmp";
#endif
UInt uiFrame = 0;
UInt uiMbX = 0;
UInt uiMbY = 0;
UInt uiSize = 0;
UInt auiCropping[4];
UInt uiLumOffset = 0;
UInt uiCbOffset = 0;
UInt uiCrOffset = 0;
UInt uiLumWidth = 0;
UInt uiLumHeight = 0;
UInt uiLumStride = 0;
PicBuffer* pcPicBuffer = 0;
PicBuffer* pcPicBufferOrig = 0;
WriteYuvToFile* pcWriteYuv = 0;
PicBufferList cPicBufferOutputList;
PicBufferList cPicBufferUnusedList;
UInt auiFrameNumAnalysis[MAX_LAYERS] = { MSYS_UINT_MAX, MSYS_UINT_MAX, MSYS_UINT_MAX, MSYS_UINT_MAX, MSYS_UINT_MAX, MSYS_UINT_MAX, MSYS_UINT_MAX, MSYS_UINT_MAX };
//===== init =====
RNOK( m_pcH264AVCPacketAnalyzer->init() );
RNOK( m_pcH264AVCDecoder ->init( true ) );
ReadBitstreamFile* pcReadBitStream = 0;
ReadYuvFile* pcReadYuv = 0;
RNOK( ReadBitstreamFile ::create( pcReadBitStream ) );
RNOK( ReadYuvFile ::create( pcReadYuv ) );
RNOK( pcReadBitStream ->init( m_pcParameter->getInputBitStreamName() ) );
RNOK( pcReadYuv ->init( m_pcParameter->getOriginalFileName ( uiTopLayer ), m_auiFrameHeight[uiTopLayer], m_auiFrameWidth[uiTopLayer] ) );
if( m_bOutputReconstructions )
{
Char acName[1024];
sprintf( acName, "rec_Layer%d_FGS%d_Level%d_Mode%d", uiLayer, uiFGSLayer, uiLevel, (bIndependent?0:1) );
RNOK( WriteYuvToFile::create( pcWriteYuv ) );
RNOK( pcWriteYuv->init( std::string( acName ) ) );
}
//-----------------------------------------------------------
//===== =====
//===== L O O P O V E R A C C E S S U N I T S =====
//===== =====
//-----------------------------------------------------------
Bool bFirstAccessUnit = true;
h264::AccessUnit cAccessUnit;
while( ! cAccessUnit.isEndOfStream() )
{
//===== read next access unit =====
while( ! cAccessUnit.isComplete() )
{
BinData* pcBinData = 0;
Bool bEOS = false; // dummy
RNOK( xGetNextValidPacket( pcBinData, pcReadBitStream, uiTopLayer, uiLayer, uiFGSLayer, uiLevel, bIndependent, bEOS, auiFrameNumAnalysis ) );
RNOK( m_pcH264AVCDecoder->initNALUnit ( pcBinData, cAccessUnit ) );
RNOK( pcReadBitStream->releasePacket ( pcBinData ) );
}
//===== set dimensions =====
if( bFirstAccessUnit )
{
const h264::SliceDataNALUnit* pcSliceDataNalUnit = cAccessUnit.getLastVCLNalUnit();
ROF( pcSliceDataNalUnit );
uiMbX = pcSliceDataNalUnit->getFrameWidthInMb ();
uiMbY = pcSliceDataNalUnit->getFrameHeightInMb ();
UInt uiChromaSize = ( ( uiMbX << 3 ) + YUV_X_MARGIN ) * ( ( uiMbY << 3 ) + YUV_Y_MARGIN );
uiLumOffset = ( ( uiMbX << 4 ) + YUV_X_MARGIN * 2 ) * YUV_Y_MARGIN + YUV_X_MARGIN;
uiCbOffset = ( ( uiMbX << 3 ) + YUV_X_MARGIN ) * YUV_Y_MARGIN / 2 + YUV_X_MARGIN / 2 + uiChromaSize * 4;
uiCrOffset = ( ( uiMbX << 3 ) + YUV_X_MARGIN ) * YUV_Y_MARGIN / 2 + YUV_X_MARGIN / 2 + uiChromaSize * 5;
uiLumHeight = ( uiMbY << 4 );
uiLumWidth = ( uiMbX << 4 );
uiLumStride = ( uiMbX << 4 ) + YUV_X_MARGIN * 2;
uiSize = 6 * uiChromaSize;
auiCropping[0] = pcSliceDataNalUnit->getCroppingRectangle ()[0];
auiCropping[1] = pcSliceDataNalUnit->getCroppingRectangle ()[1];
auiCropping[2] = pcSliceDataNalUnit->getCroppingRectangle ()[2];
auiCropping[3] = pcSliceDataNalUnit->getCroppingRectangle ()[3];
bFirstAccessUnit = false;
RNOK( xGetNewPicBuffer( pcPicBufferOrig, uiSize ) );
}
//===== process access unit =====
while( cAccessUnit.isComplete() )
{
//----- decode NAL unit -----
BinDataList cBinDataList; // dummy
h264::NALUnit* pcNalUnit = 0;
pcPicBuffer = 0;
RNOK( cAccessUnit.getAndRemoveNextNalUnit( pcNalUnit ) );
RNOK( xGetNewPicBuffer( pcPicBuffer, uiSize ) );
#if WIN32 // for linux, this has to be slightly re-formulated
// re-direct stdout
Int orig_stdout = _dup(1);
FILE* stdout_copy = freopen( tmp_file_name, "wt", stdout );
#endif
RNOK( m_pcH264AVCDecoder->processNALUnit( pcPicBuffer, cPicBufferOutputList, cPicBufferUnusedList, cBinDataList, *pcNalUnit ) );
#if WIN32 // for linux, this have to be slightly re-formulated
// restore stdout
fclose( stdout );
_dup2( orig_stdout, 1 );
_iob[1] = *fdopen( 1, "wt" );
fclose( fdopen( orig_stdout, "w" ) );
#endif
//----- determine distortion (and output for debugging) -----
while( ! cPicBufferOutputList.empty() )
{
PicBuffer* pcPicBufferTmp = cPicBufferOutputList.popFront();
if( pcPicBufferTmp )
{
//----- output (for debugging) -----
if( pcWriteYuv )
{
RNOK( pcWriteYuv->writeFrame( *pcPicBufferTmp + uiLumOffset,
*pcPicBufferTmp + uiCbOffset,
*pcPicBufferTmp + uiCrOffset,
uiLumHeight, uiLumWidth, uiLumStride, auiCropping ) );
}
//----- read in reference picture ------
RNOK( pcReadYuv->readFrame ( *pcPicBufferOrig + uiLumOffset,
*pcPicBufferOrig + uiCbOffset,
*pcPicBufferOrig + uiCrOffset,
uiLumHeight, uiLumWidth, uiLumStride ) );
//----- get distortion -----
RNOK( xGetDistortion ( auiDistortion[uiFrame],
*pcPicBufferTmp + uiLumOffset,
*pcPicBufferOrig + uiLumOffset,
uiLumHeight, uiLumWidth, uiLumStride ) );
//----- increment output picture number -----
uiFrame++;
if( uiLevel == MSYS_UINT_MAX )
printf( "\rdetermine distortion (layer %d - FGS %d - base layer ) --> frame %d completed", uiLayer, uiFGSLayer, uiFrame );
else
printf( "\rdetermine distortion (layer %d - FGS %d - lev%2d - %s ) --> frame %d completed", uiLayer, uiFGSLayer, uiLevel, bIndependent?"ind":"dep", uiFrame );
}
}
//----- free buffers and delete slice data NAL units -----
RNOK( xRemovePicBuffer( cPicBufferUnusedList ) );
delete pcNalUnit;
}
}
//----- remove original pic buffer -----
PicBufferList cPicBufferListOrig; cPicBufferListOrig.push_back( pcPicBufferOrig );
RNOK( xRemovePicBuffer( cPicBufferListOrig ) );
#if WIN32
remove( tmp_file_name );
#endif
//===== uninit =====
RNOK( m_pcH264AVCPacketAnalyzer ->uninit () );
RNOK( m_pcH264AVCDecoder ->uninit ( true ) );
RNOK( pcReadBitStream ->uninit () );
RNOK( pcReadYuv ->uninit () );
RNOK( pcReadBitStream ->destroy () );
RNOK( pcReadYuv ->destroy () );
if( pcWriteYuv )
{
RNOK( pcWriteYuv->destroy() );
}
//---- re-create decoder (there's something wrong) -----
RNOK( m_pcH264AVCDecoder->destroy() );
RNOK( CreaterH264AVCDecoder::create( m_pcH264AVCDecoder ) );
printf("\n");
return Err::m_nOK;
}
ErrVal
QualityLevelAssigner::xWriteDataFile( const std::string& cFileName )
{
printf( "write data to file \"%s\" ...", cFileName.c_str() );
FILE* pFile = fopen( cFileName.c_str(), "wt" );
if( !pFile )
{
fprintf( stderr, "\nERROR: Cannot open file \"%s\" for writing!\n\n", cFileName.c_str() );
return Err::m_nERR;
}
for( UInt uiLayer = 0; uiLayer < m_uiNumLayers; uiLayer ++ )
for( UInt uiFGS = 0; uiFGS <= m_auiNumFGSLayers[uiLayer]; uiFGS ++ )
for( UInt uiFrame = 0; uiFrame < m_auiNumFrames [uiLayer]; uiFrame ++ )
{
fprintf( pFile,
"%d %d %5d %6d %lf\n",
uiLayer, uiFGS, uiFrame,
m_aaauiPacketSize [uiLayer][uiFGS][uiFrame],
m_aaadDeltaDist [uiLayer][uiFGS][uiFrame] );
}
fclose( pFile );
printf("\n");
return Err::m_nOK;
}
ErrVal
QualityLevelAssigner::xReadDataFile( const std::string& cFileName )
{
printf( "read data from file \"%s\" ...", cFileName.c_str() );
FILE* pFile = fopen( cFileName.c_str(), "rt" );
if( !pFile )
{
fprintf( stderr, "\nERROR: Cannot open file \"%s\" for reading!\n\n", cFileName.c_str() );
return Err::m_nERR;
}
Bool bEOS = false;
UInt uiLayer, uiFGS, uiFrame, uiPacketSize, uiNumPackets;
Double dDeltaDist;
for( uiNumPackets = 0; !bEOS; uiNumPackets++ )
{
Int iNumRead = fscanf( pFile,
" %d %d %d %d %lf",
&uiLayer, &uiFGS, &uiFrame, &uiPacketSize, &dDeltaDist );
if( iNumRead == 5 )
{
ROF( uiLayer < m_uiNumLayers );
ROF( uiFGS <= m_auiNumFGSLayers[uiLayer] );
ROF( uiFrame < m_auiNumFrames [uiLayer] );
m_aaauiPacketSize [uiLayer][uiFGS][uiFrame] = uiPacketSize;
m_aaadDeltaDist [uiLayer][uiFGS][uiFrame] = dDeltaDist;
}
else
{
bEOS = true;
uiNumPackets--;
}
}
//----- check number of elements -----
UInt uiTargetPackets = 0;
for( uiLayer = 0; uiLayer < m_uiNumLayers; uiLayer++ )
{
uiTargetPackets += ( 1 + m_auiNumFGSLayers[uiLayer] ) * m_auiNumFrames[uiLayer];
}
if( uiTargetPackets != uiNumPackets )
{
fprintf( stderr, "\nERROR: File \"%s\" contains incomplete data!\n\n", cFileName.c_str() );
return Err::m_nERR;
}
fclose( pFile );
printf("\n");
return Err::m_nOK;
}
ErrVal
QualityLevelAssigner::xDetermineQualityIDs()
{
printf( "determine quality levels ..." );
//===== determine minimum and maximum quality level id's =====
UInt auiMinQualityLevel[MAX_LAYERS];
UInt auiMaxQualityLevel[MAX_LAYERS];
{
for( Int iLayer = (Int)m_uiNumLayers-1; iLayer >= 0; iLayer-- )
{
UInt uiMinQLLayer = ( iLayer == (Int)m_uiNumLayers-1 ? 0 : auiMaxQualityLevel[iLayer+1]+1 );
UInt uiNumQLInLayer = ( 63 - uiMinQLLayer ) / ( iLayer + 1 );
auiMinQualityLevel[iLayer] = uiMinQLLayer;
auiMaxQualityLevel[iLayer] = uiMinQLLayer + uiNumQLInLayer - 1;
}
}
//===== determine optimized quality levels per layer =====
for( UInt uiLayer = 0; uiLayer < m_uiNumLayers; uiLayer++ )
{
//----- create quality estimation object -----
QualityLevelEstimation cQualityLevelEstimation;
RNOK( cQualityLevelEstimation.init( m_uiNumLayers, m_auiNumFGSLayers, m_auiNumFrames ) );
//----- initialize with packets -----
{
for( UInt uiFGSLayer = 1; uiFGSLayer <= m_auiNumFGSLayers[uiLayer]; uiFGSLayer++ )
for( UInt uiFrame = 0; uiFrame < m_auiNumFrames [uiLayer]; uiFrame ++ )
{
RNOK( cQualityLevelEstimation.addPacket( uiLayer, uiFGSLayer, uiFrame,
m_aaauiPacketSize [uiLayer][uiFGSLayer][uiFrame],
m_aaadDeltaDist [uiLayer][uiFGSLayer][uiFrame] ) );
}
}
//----- determine quality levels -----
RNOK( cQualityLevelEstimation.optimizeQualityLevel( uiLayer, uiLayer, auiMinQualityLevel[uiLayer], auiMaxQualityLevel[uiLayer] ) );
//----- assign quality levels -----
{
for( UInt uiFGSLayer = 0; uiFGSLayer <= m_auiNumFGSLayers[uiLayer]; uiFGSLayer++ )
for( UInt uiFrame = 0; uiFrame < m_auiNumFrames [uiLayer]; uiFrame ++ )
{
m_aaauiQualityID[uiLayer][uiFGSLayer][uiFrame] = ( uiFGSLayer ? cQualityLevelEstimation.getQualityId( uiLayer, uiFGSLayer, uiFrame ) : 63 );
}
}
}
printf("\n");
return Err::m_nOK;
}
//JVT-S043
ErrVal
QualityLevelAssigner::xDetermineMultiLayerQualityIDs()
{
printf( "determine ML quality levels ..." );
//===== determine minimum and maximum quality level id's =====
UInt uiMinQualityLevel = 0;
UInt uiMaxQualityLevel = 62;
UInt uiLayer;
//----- create quality estimation object -----
QualityLevelEstimation cQualityLevelEstimation;
RNOK( cQualityLevelEstimation.init( m_uiNumLayers, m_auiNumFGSLayers, m_auiNumFrames ) );
//===== determine optimized quality levels per layer =====
for( uiLayer = 0; uiLayer < m_uiNumLayers; uiLayer++ )
{
//----- initialize with packets -----
{
for( UInt uiFGSLayer = 1; uiFGSLayer <= m_auiNumFGSLayers[uiLayer]; uiFGSLayer++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -