Skip to content

Commit

Permalink
fix dts calc. when frames are missing on input (#491)
Browse files Browse the repository at this point in the history
  • Loading branch information
lehmann-c authored Dec 19, 2024
1 parent 2dfd20c commit 81a3b6c
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 7 deletions.
7 changes: 7 additions & 0 deletions source/Lib/CommonLib/Picture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ Picture::Picture()
, sliceDataNumBins ( 0 )
, cts ( 0 )
, ctsValid ( false )
, picsInMissing ( 0 )
, picOutOffset ( 0 )
, isPreAnalysis ( false )
, m_picShared ( nullptr )
, gopAdaptedQP ( 0 )
Expand Down Expand Up @@ -246,6 +248,11 @@ void Picture::reset()
picApsGlobal = nullptr;
refApsGlobal = nullptr;

cts = 0;
ctsValid = false;
picsInMissing = 0;
picOutOffset = 0;

picVA.reset();

std::fill_n( m_sharedBufs, (int)NUM_PIC_TYPES, nullptr );
Expand Down
2 changes: 2 additions & 0 deletions source/Lib/CommonLib/Picture.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ struct Picture : public UnitArea
int sliceDataNumBins;
uint64_t cts;
bool ctsValid;
int64_t picsInMissing; // summed up missing frames on input
int64_t picOutOffset; // signalization of pic offset to re-calc dts
bool isPreAnalysis;

PicShared* m_picShared;
Expand Down
34 changes: 31 additions & 3 deletions source/Lib/EncoderLib/EncGOP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ EncGOP::EncGOP( MsgLog& logger )
, m_disableLMCSIP ( false )
, m_lastCodingNum ( -1 )
, m_numPicsCoded ( 0 )
, m_numPicsInMissing ( 0 )
, m_numPicsOutOffset ( 0 )
, m_lastCts ( 0 )
, m_pocRecOut ( 0 )
, m_ticksPerFrameMul4 ( 0 )
, m_lastIDR ( 0 )
Expand Down Expand Up @@ -244,6 +247,27 @@ void EncGOP::initPicture( Picture* pic )
pic->encTime.startTimer();

pic->TLayer = pic->gopEntry->m_temporalId;
if( pic->ctsValid )
{
if( m_lastCts )
{
int64_t ticksPerFrame = m_ticksPerFrameMul4/4;
int64_t expectedCtsDiff = (m_pcEncCfg->m_TicksPerSecond > 0 ) ? ticksPerFrame : 1;
int64_t ctsDiff = pic->cts - m_lastCts;

if( ctsDiff >= (expectedCtsDiff<<1) || ctsDiff < 0 )
{
// signalize that frames are missing at that particular picture
pic->picOutOffset = (m_pcEncCfg->m_TicksPerSecond > 0 ) ? (ctsDiff - ticksPerFrame)/ticksPerFrame : ctsDiff-1;
m_numPicsInMissing += pic->picOutOffset;
}
}
m_lastCts = pic->cts;
}
if( m_numPicsInMissing )
{
pic->picsInMissing = m_numPicsInMissing;
}

pic->setSccFlags( m_pcEncCfg );

Expand Down Expand Up @@ -2438,13 +2462,17 @@ void EncGOP::xWritePicture( Picture& pic, AccessUnitList& au, bool isEncodeLtRef

if( pic.ctsValid )
{
const int64_t iDiffFrames = m_numPicsCoded - pic.poc;
const int64_t iDiffFrames = m_numPicsCoded - pic.poc - pic.picsInMissing;
au.cts = pic.cts;
au.ctsValid = pic.ctsValid;
if ( pic.picOutOffset )
{
m_numPicsOutOffset += pic.picOutOffset;
}
if( m_pcEncCfg->m_TicksPerSecond > 0 )
au.dts = ( ( iDiffFrames - m_pcEncCfg->m_maxTLayer ) * m_ticksPerFrameMul4 ) / 4 + au.cts;
au.dts = ( ( iDiffFrames - m_pcEncCfg->m_maxTLayer + m_numPicsOutOffset ) * m_ticksPerFrameMul4 ) / 4 + au.cts;
else
au.dts = ( ( iDiffFrames - m_pcEncCfg->m_maxTLayer )) + au.cts;
au.dts = ( ( iDiffFrames - m_pcEncCfg->m_maxTLayer + m_numPicsOutOffset )) + au.cts;
au.dtsValid = pic.ctsValid;
}

Expand Down
3 changes: 3 additions & 0 deletions source/Lib/EncoderLib/EncGOP.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,9 @@ class EncGOP : public EncStage
bool m_disableLMCSIP;
int m_lastCodingNum;
int m_numPicsCoded;
int m_numPicsInMissing;
int m_numPicsOutOffset;
uint64_t m_lastCts;
int m_pocRecOut;
int m_ticksPerFrameMul4;
int m_lastIDR;
Expand Down
42 changes: 38 additions & 4 deletions test/vvenclibtest/vvenclibtest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ int checkSDKStringApiInvalid()
return ret;
}

static int runEncoder( vvenc_config& c, uint64_t framesToEncode )
static int runEncoder( vvenc_config& c, uint64_t framesToEncode, bool emulateMissingFrames = false )
{
uint64_t ctsDiff = (c.m_TicksPerSecond > 0) ? (uint64_t)c.m_TicksPerSecond * (uint64_t)c.m_FrameScale / (uint64_t)c.m_FrameRate : 1; // expected cts diff between frames
uint64_t ctsOffset = (c.m_TicksPerSecond > 0) ? (uint64_t)c.m_TicksPerSecond : (uint64_t)c.m_FrameRate/(uint64_t)c.m_FrameScale; // start with offset 1sec, to generate cts/dts > 0
Expand All @@ -922,6 +922,8 @@ static int runEncoder( vvenc_config& c, uint64_t framesToEncode )
bool eof = false;
bool encodeDone = false;
uint64_t framesRcvd = 0;
uint64_t numMissingFrames = emulateMissingFrames ? 10 : 0;

while( !eof || !encodeDone )
{
vvencYUVBuffer* inputPtr = nullptr;
Expand All @@ -931,6 +933,11 @@ static int runEncoder( vvenc_config& c, uint64_t framesToEncode )
yuvPicture->cts = (c.m_TicksPerSecond > 0) ? (ctsOffset + (framesRcvd * (uint64_t)c.m_TicksPerSecond * (uint64_t)c.m_FrameScale / (uint64_t)c.m_FrameRate)) : (ctsOffset + framesRcvd);
yuvPicture->ctsValid = true;
framesRcvd++;

if( emulateMissingFrames && framesRcvd == framesToEncode>>1 )
{
framesRcvd+=numMissingFrames; // emulate missing pictures
}
}

if( 0 != vvenc_encode( enc, inputPtr, AU, &encodeDone ))
Expand All @@ -950,10 +957,11 @@ static int runEncoder( vvenc_config& c, uint64_t framesToEncode )
{
if ( AU->dts <= lastDts ){
//std::cout << " AU dts " << AU->dts << " <= " << lastDts << " - dts must always increase" << std::endl;
}else{
goto fail;
}else if (!emulateMissingFrames){
//std::cout << " AU dts " << AU->dts << " but expecting " << lastDts + ctsDiff << " lastDts " << lastDts << std::endl;
goto fail;
}
goto fail;
}
lastDts = AU->dts;
}
Expand All @@ -964,7 +972,7 @@ static int runEncoder( vvenc_config& c, uint64_t framesToEncode )
goto fail;
}

if( framesRcvd >= framesToEncode )
if( framesRcvd >= (framesToEncode+numMissingFrames) )
{
eof = true;
}
Expand Down Expand Up @@ -1089,6 +1097,31 @@ int checkTimestampsInvalid()
return 0;
}

int checkDtsDefault()
{
std::vector <int> tickspersecVec;
tickspersecVec.push_back(90000);
tickspersecVec.push_back(-1);

for( auto & tickspersec : tickspersecVec )
{
vvenc_config c;
vvenc_init_default( &c, 176,144, 60, VVENC_RC_OFF, 55, vvencPresetMode::VVENC_FASTER );
c.m_internChromaFormat = VVENC_CHROMA_420;

c.m_FrameRate = 50;
c.m_FrameScale = 1;
c.m_TicksPerSecond = tickspersec;
uint64_t frames= c.m_FrameRate/c.m_FrameScale * 2;

if( 0 != runEncoder(c,frames, true) )
{
return -1;
}
}
return 0;
}

int testLibCallingOrder()
{
testfunc( "callingOrderInvalidUninit", &callingOrderInvalidUninit, true );
Expand Down Expand Up @@ -1123,6 +1156,7 @@ int testTimestamps()
{
testfunc( "checkTimestampsDefault", &checkTimestampsDefault, false );
testfunc( "checkTimestampsDefaultInvalid", &checkTimestampsInvalid, true );
testfunc( "checkDtsDefault", &checkDtsDefault, false );

return 0;
}
Expand Down

0 comments on commit 81a3b6c

Please sign in to comment.