diff --git a/YUViewLib/src/parser/parserAnnexBAVC.cpp b/YUViewLib/src/parser/parserAnnexBAVC.cpp index a6fd7aa28..953864b59 100644 --- a/YUViewLib/src/parser/parserAnnexBAVC.cpp +++ b/YUViewLib/src/parser/parserAnnexBAVC.cpp @@ -211,8 +211,6 @@ parserAnnexB::ParseResult parserAnnexBAVC::parseAndAddNALUnit(int nalID, QByteAr bool parsingSuccess = true; bool currentSliceIntra = false; QString currentSliceType; - QSharedPointer currentBufferingPeriodSEI; - QSharedPointer currentPicTimingSEI; if (nal_avc.nal_unit_type == SPS) { // A sequence parameter set @@ -347,15 +345,21 @@ parserAnnexB::ParseResult parserAnnexBAVC::parseAndAddNALUnit(int nalID, QByteAr auto new_buffering_period_sei = QSharedPointer(new buffering_period_sei(new_sei)); result = new_buffering_period_sei->parse_buffering_period_sei(sub_sei_data, this->active_SPS_list, message_tree); reparse = new_buffering_period_sei; - currentBufferingPeriodSEI = new_buffering_period_sei; - this->hrd.isFirstAUInBufferingPeriod = true; + if (this->lastBufferingPeriodSEI.isNull()) + this->lastBufferingPeriodSEI = new_buffering_period_sei; + else + this->newBufferingPeriodSEI = new_buffering_period_sei; + this->nextAUIsFirstAUInBufferingPeriod = true; } else if (new_sei->payloadType == 1) { auto new_pic_timing_sei = QSharedPointer(new pic_timing_sei(new_sei)); result = new_pic_timing_sei->parse_pic_timing_sei(sub_sei_data, this->active_SPS_list, CpbDpbDelaysPresentFlag, message_tree); reparse = new_pic_timing_sei; - currentPicTimingSEI = new_pic_timing_sei; + if (this->lastPicTimingSEI.isNull()) + this->lastPicTimingSEI = new_pic_timing_sei; + else + this->newPicTimingSEI = new_pic_timing_sei; } else if (new_sei->payloadType == 4) { @@ -428,6 +432,11 @@ parserAnnexB::ParseResult parserAnnexBAVC::parseAndAddNALUnit(int nalID, QByteAr parseResult.bitrateEntry = entry; this->hrd.addAU(this->sizeCurrentAU * 8, curFramePOC, this->active_SPS_list[0], this->lastBufferingPeriodSEI, this->lastPicTimingSEI, this->getHRDPlotModel()); + + if (this->newBufferingPeriodSEI) + this->lastBufferingPeriodSEI = this->newBufferingPeriodSEI; + if (this->newPicTimingSEI) + this->lastPicTimingSEI = this->newPicTimingSEI; } this->sizeCurrentAU = 0; this->counterAU++; @@ -438,6 +447,13 @@ parserAnnexB::ParseResult parserAnnexBAVC::parseAndAddNALUnit(int nalID, QByteAr this->lastFramePOC = curFramePOC; this->sizeCurrentAU += data.size(); + if (this->nextAUIsFirstAUInBufferingPeriod) + { + if (this->counterAU > 0) + this->hrd.isFirstAUInBufferingPeriod = true; + this->nextAUIsFirstAUInBufferingPeriod = false; + } + if (nal_avc.isSlice()) { if (!currentSliceIntra) @@ -445,11 +461,6 @@ parserAnnexB::ParseResult parserAnnexBAVC::parseAndAddNALUnit(int nalID, QByteAr this->currentAUSliceTypes[currentSliceType]++; } - if (currentBufferingPeriodSEI) - this->lastBufferingPeriodSEI = currentBufferingPeriodSEI; - if (currentPicTimingSEI) - this->lastPicTimingSEI = currentPicTimingSEI; - if (nalRoot) { // Set a useful name of the TreeItem (the root for this NAL) @@ -2256,7 +2267,7 @@ void parserAnnexBAVC::HRD::addAU(unsigned auBits, unsigned poc, QSharedPointerau_n == 0) // { - // auBits += 47 * 8; + // auBits += 49 * 8; // } /* Some notation: @@ -2370,7 +2381,8 @@ void parserAnnexBAVC::HRD::addAU(unsigned auBits, unsigned poc, QSharedPointeraddConstantBufferLine(poc, lastFrameTime, (*it).t_r, plotModel); this->removeFromBufferAndCheck((*it), poc, (*it).t_r, plotModel); it = this->framesToRemove.erase(it); - lastFrameTime = (*it).t_r; + if (it != this->framesToRemove.end()) + lastFrameTime = (*it).t_r; } else break; @@ -2409,7 +2421,7 @@ void parserAnnexBAVC::HRD::addAU(unsigned auBits, unsigned poc, QSharedPointer parserAnnexBAVC::HRD::popRemoveFra { QList l; auto it = this->framesToRemove.begin(); + double t_r_previous = 0; while (it != this->framesToRemove.end()) { + if ((*it).t_r < from) + { + DEBUG_AVC("Warning: Frame " << (*it).poc << " was not removed at the time (" << double((*it).t_r) << ") it should have been. Dropping it now."); + it = this->framesToRemove.erase(it); + continue; + } + if ((*it).t_r < t_r_previous) + { + DEBUG_AVC("Warning: Frame " << (*it).poc << " has a removal time (" << double((*it).t_r) << ") before the previous frame (" << t_r_previous << "). Dropping it now."); + it = this->framesToRemove.erase(it); + continue; + } if ((*it).t_r >= from && (*it).t_r < to) { + t_r_previous = (*it).t_r; l.push_back((*it)); it = this->framesToRemove.erase(it); continue; diff --git a/YUViewLib/src/parser/parserAnnexBAVC.h b/YUViewLib/src/parser/parserAnnexBAVC.h index 40de197ed..e6333d45a 100644 --- a/YUViewLib/src/parser/parserAnnexBAVC.h +++ b/YUViewLib/src/parser/parserAnnexBAVC.h @@ -543,8 +543,12 @@ class parserAnnexBAVC : public parserAnnexB // parameter sets. Here we keep a list of seis that need to be parsed after the parameter sets were recieved. QList> reparse_sei; + // When new SEIs come in and they don't initialize the HRD, they are not accessed until the current AU is processed by the HRD. QSharedPointer lastBufferingPeriodSEI; QSharedPointer lastPicTimingSEI; + QSharedPointer newBufferingPeriodSEI; + QSharedPointer newPicTimingSEI; + bool nextAUIsFirstAUInBufferingPeriod {false}; // In an SEI, the number of bytes indicated do not consider the emulation prevention. This function // can determine the real number of bytes that we need to read from the input considering the emulation prevention diff --git a/YUViewLib/src/ui/views/plotViewWidget.cpp b/YUViewLib/src/ui/views/plotViewWidget.cpp index 6e7c68e59..7c18f1222 100644 --- a/YUViewLib/src/ui/views/plotViewWidget.cpp +++ b/YUViewLib/src/ui/views/plotViewWidget.cpp @@ -679,6 +679,8 @@ void PlotViewWidget::drawPlot(QPainter &painter) const { unsigned intervalLeft = 0; unsigned intervalRight = nrpoints; + if (nrpoints == 0) + return intervalLeft; while (true) { unsigned pointToCheck = intervalLeft + (intervalRight - intervalLeft) / 2;