📄 qualitylevelassigner.cpp
字号:
//----- 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 );
}
}
} // if( bToDecode )
//----- free buffers -----
RNOK( xRemovePicBuffer( cPicBufferReleaseList ) );
RNOK( xRemovePicBuffer( cPicBufferUnusedList ) );
//----- delete bin data -----
if( pcBinData )
{
RNOK( pcReadBitStream->releasePacket( pcBinData ) );
pcBinData = 0;
}
}
//----- 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.getQualityLevel( uiLayer, uiFGSLayer, uiFrame ) : 63 );
}
if( m_bMGS )
{
m_aaauiQualityID[uiLayer][1][0] = 62; // first frame must be presents (when any other MGS refinement is present)
}
}
}
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++ )
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( m_uiNumLayers-1, 0, uiMinQualityLevel, uiMaxQualityLevel ) );
for( uiLayer = 0; uiLayer < m_uiNumLayers; 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.getQualityLevel( uiLayer, uiFGSLayer, uiFrame ) : 63 );
}
}
}
printf("\n");
return Err::m_nOK;
}
ErrVal
QualityLevelAssigner::xWriteQualityLayerStreamPID()
{
printf( "write stream with quality layer (PID) \"%s\" ...", m_pcParameter->getOutputBitStreamName().c_str() );
BinData* pcBinData = 0;
SEI::SEIMessage* pcScalableSEI = 0;
PacketDescription cPacketDescription;
static Bool bAVCComaptible = false; //bug-fix suffix
UInt auiFrameNum[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 };
UInt uiLevel_prefix = 0;//prefix unit
//===== init =====
RNOK( m_pcH264AVCPacketAnalyzer->init() );
ReadBitstreamFile* pcReadBitStream = 0;
WriteBitstreamToFile* pcWriteBitStream = 0;
RNOK( ReadBitstreamFile ::create( pcReadBitStream ) );
RNOK( WriteBitstreamToFile::create( pcWriteBitStream ) );
RNOK( pcReadBitStream ->init( m_pcParameter->getInputBitStreamName () ) );
RNOK( pcWriteBitStream->init( m_pcParameter->getOutputBitStreamName () ) );
//===== loop over packets =====
while( true )
{
//----- read packet -----
Bool bEOS = false;
RNOK( pcReadBitStream->extractPacket( pcBinData, bEOS ) );
if( bEOS )
{
//manu.mathew@samsung : memory leak fix
RNOK( pcReadBitStream ->releasePacket ( pcBinData ) );
pcBinData = NULL;
//--
break;
}
//----- get packet description -----
RNOK( m_pcH264AVCPacketAnalyzer->process( pcBinData, cPacketDescription, pcScalableSEI ) );
//{suffix TL read
if(cPacketDescription.NalUnitType== NAL_UNIT_CODED_SLICE ||
cPacketDescription.NalUnitType== NAL_UNIT_CODED_SLICE_IDR )
{
cPacketDescription.Level = uiLevel_prefix;//prefix unit
h264::PacketDescription cPacketDescriptionTemp;
h264::SEI::SEIMessage* pcScalableSeiTemp = 0;
Int iFilePos = 0;
RNOK( pcReadBitStream->getPosition( iFilePos ) );
BinData *pcNextBinData;
Bool bEos;
RNOK( pcReadBitStream->extractPacket( pcNextBinData, bEos ) );
m_pcH264AVCPacketAnalyzer->process( pcNextBinData, cPacketDescriptionTemp, pcScalableSeiTemp );
if( (cPacketDescription.NalUnitType == NAL_UNIT_CODED_SLICE_SCALABLE || cPacketDescription.NalUnitType == NAL_UNIT_CODED_SLICE_IDR_SCALABLE) //prefix unit
&& cPacketDescriptionTemp.Layer == 0 && cPacketDescriptionTemp.FGSLayer == 0 ) //AVC suffix
cPacketDescription.Level = cPacketDescriptionTemp.Level;
RNOK( pcReadBitStream->setPosition(iFilePos ) );
}
//}suffix TL read
delete pcScalableSEI; pcScalableSEI = 0;
//----- set packet size -----
while( pcBinData->data()[ pcBinData->size() - 1 ] == 0x00 )
{
RNOK( pcBinData->decreaseEndPos( 1 ) ); // remove trailing zeros
}
//----- analyse packets -----
if( cPacketDescription.FGSLayer )
{
// JVT-T083: modify the Position of SimplePriorityId
// clear previous value
pcBinData->data()[1] &= 0xC0;
// write new value of priority ID
pcBinData->data()[1] |= m_aaauiQualityID[cPacketDescription.Layer][cPacketDescription.FGSLayer][auiFrameNum[cPacketDescription.Layer]];
}
else
{
//bug-fix suffix{{
if(cPacketDescription.NalUnitType == NAL_UNIT_CODED_SLICE_IDR || cPacketDescription.NalUnitType == NAL_UNIT_CODED_SLICE)
{
bAVCComaptible = true;
}
if((cPacketDescription.NalUnitType == 20 || cPacketDescription.NalUnitType == 21) && cPacketDescription.Layer == 0 && cPacketDescription.FGSLayer == 0 && bAVCComaptible)
{
RNOK( pcWriteBitStream->writePacket ( &m_cBinDataStartCode ) );
RNOK( pcWriteBitStream->writePacket ( pcBinData ) );
RNOK( pcReadBitStream ->releasePacket ( pcBinData ) );
continue;
}
//bug-fix suffix}}
if( ! cPacketDescription.ParameterSet && cPacketDescription.NalUnitType != NAL_UNIT_SEI &&
! cPacketDescription.FGSLayer && cPacketDescription.NalUnitType != NAL_UNIT_PREFIX)//prefix unit
{
auiFrameNum[cPacketDescription.Layer]++;
}
}
//prefix unit{{
if(cPacketDescription.NalUnitType == 14)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -