diff --git a/YUViewLib/src/common/Typedef.h b/YUViewLib/src/common/Typedef.h index 23fbf0334..3abac89ed 100644 --- a/YUViewLib/src/common/Typedef.h +++ b/YUViewLib/src/common/Typedef.h @@ -218,6 +218,8 @@ typedef QPair QUIntPair; template using umap_1d = std::map; template using umap_2d = std::map>; template using umap_3d = std::map>; +template using umap_4d = std::map>; +template using umap_5d = std::map>; template using vector = std::vector; template using vector2d = std::vector>; @@ -226,6 +228,8 @@ template using vector4d = std::vector>; template using array = std::array; template using array2d = std::array, N1>; +template +using array3d = std::array, N2>, N1>; template int indexInVec(const std::vector &vec, const T &item) { diff --git a/YUViewLib/src/parser/AVC/ParserAnnexBAVC.cpp b/YUViewLib/src/parser/AVC/ParserAnnexBAVC.cpp index e7f2ed178..b7e9fd392 100644 --- a/YUViewLib/src/parser/AVC/ParserAnnexBAVC.cpp +++ b/YUViewLib/src/parser/AVC/ParserAnnexBAVC.cpp @@ -193,7 +193,8 @@ ParserAnnexBAVC::parseAndAddNALUnit(int // Save the info of the last frame if (!this->addFrameToList(*this->curFrameData->poc, this->curFrameData->fileStartEndPos, - this->curFrameData->isRandomAccess)) + this->curFrameData->isRandomAccess, + 0)) { if (parent) parent->createChildItem("Error - POC " + std::to_string(*this->curFrameData->poc) + @@ -481,7 +482,8 @@ ParserAnnexBAVC::parseAndAddNALUnit(int // Save the info of the last frame if (!this->addFrameToList(*this->curFrameData->poc, this->curFrameData->fileStartEndPos, - this->curFrameData->isRandomAccess)) + this->curFrameData->isRandomAccess, + 0)) { throw std::logic_error("Error - POC " + std::to_string(*this->curFrameData->poc) + " already in the POC list"); diff --git a/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.cpp b/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.cpp index 7783ff43d..40dacae80 100644 --- a/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.cpp +++ b/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.cpp @@ -283,7 +283,8 @@ ParserAnnexBHEVC::parseAndAddNALUnit(int if (curFramePOC != -1) { // Save the info of the last frame - if (!this->addFrameToList(curFramePOC, curFrameFileStartEndPos, curFrameIsRandomAccess)) + if (!this->addFrameToList( + curFramePOC, curFrameFileStartEndPos, curFrameIsRandomAccess, curFrameLayerID)) { throw std::logic_error("Error - POC " + std::to_string(curFramePOC) + " alread in the POC list."); @@ -291,10 +292,12 @@ ParserAnnexBHEVC::parseAndAddNALUnit(int if (curFrameFileStartEndPos) DEBUG_HEVC("ParserAnnexBHEVC::parseAndAddNALUnit Adding start/end " << curFrameFileStartEndPos->first << "/" << curFrameFileStartEndPos->second - << " - POC " << curFramePOC << (curFrameIsRandomAccess ? " - ra" : "")); + << " - POC " << curFramePOC << " layer " << curFrameLayerID + << (curFrameIsRandomAccess ? " - ra" : "")); else DEBUG_HEVC("ParserAnnexBHEVC::parseAndAddNALUnit Adding start/end NA/NA - POC " - << curFramePOC << (curFrameIsRandomAccess ? " - ra" : "")); + << curFramePOC << " layer " << curFrameLayerID + << (curFrameIsRandomAccess ? " - ra" : "")); } // The file ended return parseResult; @@ -445,7 +448,8 @@ ParserAnnexBHEVC::parseAndAddNALUnit(int if (curFramePOC != -1) { // Save the info of the last frame - if (!this->addFrameToList(curFramePOC, curFrameFileStartEndPos, curFrameIsRandomAccess)) + if (!this->addFrameToList( + curFramePOC, curFrameFileStartEndPos, curFrameIsRandomAccess, curFrameLayerID)) { throw std::logic_error("Error - POC " + std::to_string(curFramePOC) + " alread in the POC list."); @@ -453,14 +457,17 @@ ParserAnnexBHEVC::parseAndAddNALUnit(int if (curFrameFileStartEndPos) DEBUG_HEVC("ParserAnnexBHEVC::parseAndAddNALUnit Adding start/end " << curFrameFileStartEndPos->first << "/" << curFrameFileStartEndPos->second - << " - POC " << curFramePOC << (curFrameIsRandomAccess ? " - ra" : "")); + << " - POC " << curFramePOC << curFramePOC << " layer " + << (curFrameIsRandomAccess ? " - ra" : "")); else DEBUG_HEVC("ParserAnnexBHEVC::parseAndAddNALUnit Adding start/end NA/NA - POC " - << curFramePOC << (curFrameIsRandomAccess ? " - ra" : "")); + << curFramePOC << curFramePOC << " layer " + << (curFrameIsRandomAccess ? " - ra" : "")); } curFrameFileStartEndPos = nalStartEndPosFile; curFramePOC = newSlice->sliceSegmentHeader.globalPOC; curFrameIsRandomAccess = nalHEVC->header.isIRAP(); + curFrameLayerID = nalHEVC->header.nuh_layer_id; { std::shared_ptr refSPS; diff --git a/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.h b/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.h index 9206e592a..0c72dac73 100644 --- a/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.h +++ b/YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.h @@ -138,8 +138,9 @@ class ParserAnnexBHEVC : public ParserAnnexB // in case the frame has multiple NAL units // The POC of the current frame. We save this we encounter a NAL from the next POC; then we add // it. - int curFramePOC{-1}; - bool curFrameIsRandomAccess{false}; + int curFramePOC{-1}; + bool curFrameIsRandomAccess{false}; + unsigned curFrameLayerID{0}; hevc::AUDelimiterDetector auDelimiterDetector; diff --git a/YUViewLib/src/parser/HEVC/slice_segment_header.cpp b/YUViewLib/src/parser/HEVC/slice_segment_header.cpp index e2004855a..d42219be7 100644 --- a/YUViewLib/src/parser/HEVC/slice_segment_header.cpp +++ b/YUViewLib/src/parser/HEVC/slice_segment_header.cpp @@ -97,7 +97,18 @@ void slice_segment_header::parse(SubByteReaderLogging & reader, if (!dependent_slice_segment_flag) { - for (unsigned int i = 0; i < pps->num_extra_slice_header_bits; i++) + unsigned i = 0; + if (pps->num_extra_slice_header_bits > i) + { + i++; + this->discardable_flag = reader.readFlag("discardable_flag"); + } + if (pps->num_extra_slice_header_bits > i) + { + i++; + this->cross_layer_bla_flag = reader.readFlag("cross_layer_bla_flag"); + } + for (; i < pps->num_extra_slice_header_bits; i++) this->slice_reserved_flag.push_back(reader.readFlag(formatArray("slice_reserved_flag", i))); auto sliceTypeIdx = reader.readUEV( @@ -174,6 +185,12 @@ void slice_segment_header::parse(SubByteReaderLogging & reader, this->slice_temporal_mvp_enabled_flag = reader.readFlag("slice_temporal_mvp_enabled_flag"); } + // This is not 100% done yet. + // if (nalUnitHeader.nuh_layer_id > 0 && !default_ref_layers_active_flag && + // NumDirectRefLayers[nuh_layer_id] > 0) + // { + // } + if (sps->sample_adaptive_offset_enabled_flag) { this->slice_sao_luma_flag = reader.readFlag("slice_sao_luma_flag"); diff --git a/YUViewLib/src/parser/HEVC/slice_segment_header.h b/YUViewLib/src/parser/HEVC/slice_segment_header.h index 438ed15b7..0b301af60 100644 --- a/YUViewLib/src/parser/HEVC/slice_segment_header.h +++ b/YUViewLib/src/parser/HEVC/slice_segment_header.h @@ -75,6 +75,8 @@ class slice_segment_header bool dependent_slice_segment_flag{}; unsigned slice_pic_parameter_set_id{}; unsigned slice_segment_address{}; + bool discardable_flag{}; + bool cross_layer_bla_flag{}; vector slice_reserved_flag; SliceType slice_type{}; bool pic_output_flag{true}; diff --git a/YUViewLib/src/parser/ParserAnnexB.cpp b/YUViewLib/src/parser/ParserAnnexB.cpp index c02ebd74a..80b842dc7 100644 --- a/YUViewLib/src/parser/ParserAnnexB.cpp +++ b/YUViewLib/src/parser/ParserAnnexB.cpp @@ -62,10 +62,11 @@ std::string ParserAnnexB::getShortStreamDescription(const int) const bool ParserAnnexB::addFrameToList(int poc, std::optional fileStartEndPos, - bool randomAccessPoint) + bool randomAccessPoint, + unsigned layerID) { for (const auto &f : this->frameListCodingOrder) - if (f.poc == poc) + if (f.poc == poc && f.layerID == layerID) return false; if (!this->pocOfFirstRandomAccessFrame && randomAccessPoint) @@ -77,6 +78,7 @@ bool ParserAnnexB::addFrameToList(int poc, newFrame.poc = poc; newFrame.fileStartEndPos = fileStartEndPos; newFrame.randomAccessPoint = randomAccessPoint; + newFrame.layerID = layerID; this->frameListCodingOrder.push_back(newFrame); this->frameListDisplayOder.clear(); } diff --git a/YUViewLib/src/parser/ParserAnnexB.h b/YUViewLib/src/parser/ParserAnnexB.h index 8b0f092f5..2f0d45fbc 100644 --- a/YUViewLib/src/parser/ParserAnnexB.h +++ b/YUViewLib/src/parser/ParserAnnexB.h @@ -137,17 +137,20 @@ class ParserAnnexB : public Parser struct AnnexBFrame { AnnexBFrame() = default; - int poc{-1}; //< The poc of this frame - std::optional - fileStartEndPos; //< The start and end position of all slice NAL units (if known) - bool randomAccessPoint{false}; //< Can we start decoding here? + int poc{-1}; + std::optional fileStartEndPos; + bool randomAccessPoint{false}; + unsigned layerID{}; bool operator<(AnnexBFrame const &b) const { return (this->poc < b.poc); } bool operator==(AnnexBFrame const &b) const { return (this->poc == b.poc); } }; // Returns false if the POC was already present int the list - bool addFrameToList(int poc, std::optional fileStartEndPos, bool randomAccessPoint); + bool addFrameToList(int poc, + std::optional fileStartEndPos, + bool randomAccessPoint, + unsigned layerID); static void logNALSize(const ByteVector & data, std::shared_ptr root, diff --git a/YUViewLib/src/parser/VVC/ParserAnnexBVVC.cpp b/YUViewLib/src/parser/VVC/ParserAnnexBVVC.cpp index 5a10abec6..0a6b6a150 100644 --- a/YUViewLib/src/parser/VVC/ParserAnnexBVVC.cpp +++ b/YUViewLib/src/parser/VVC/ParserAnnexBVVC.cpp @@ -473,6 +473,7 @@ ParserAnnexBVVC::parseAndAddNALUnit(int nalVVC->rbsp = newSliceLayer; + updatedParsingState.currentAU.layerID = nalVVC->header.nuh_layer_id; updatedParsingState.currentAU.isKeyframe = (nalType == NalType::IDR_W_RADL || nalType == NalType::IDR_N_LP || nalType == NalType::CRA_NUT); @@ -596,22 +597,25 @@ int ParserAnnexBVVC::calculateAndUpdateGlobalPOC(bool isIRAP, unsigned PicOrderC bool ParserAnnexBVVC::handleNewAU(ParsingState &parsingState) { - DEBUG_VVC("Start of new AU. Adding bitrate " << parsingState.currentAU.sizeBytes << " POC " - << parsingState.currentAU.poc << " AU " - << parsingState.currentAU.counter); + DEBUG_VVC("Start of new AU. Adding bitrate " + << parsingState.currentAU.sizeBytes << " POC " << parsingState.currentAU.poc << " AU " + << parsingState.currentAU.counter << " Layer " << parsingState.currentAU.layerID); if (!this->addFrameToList(parsingState.currentAU.poc, parsingState.currentAU.fileStartEndPos, - parsingState.currentAU.isKeyframe)) + parsingState.currentAU.isKeyframe, + parsingState.currentAU.layerID)) return false; if (this->parsingState.currentAU.fileStartEndPos) DEBUG_VVC("Adding start/end " << parsingState.currentAU.fileStartEndPos->first << "/" << parsingState.currentAU.fileStartEndPos->second << " - AU " - << parsingState.currentAU.counter + << parsingState.currentAU.counter << " Layer " + << parsingState.currentAU.layerID << (parsingState.currentAU.isKeyframe ? " - ra" : "")); else - DEBUG_VVC("Adding start/end NA/NA - AU " << parsingState.currentAU.counter + DEBUG_VVC("Adding start/end NA/NA - AU " << parsingState.currentAU.counter << " Layer " + << parsingState.currentAU.layerID << (parsingState.currentAU.isKeyframe ? " - ra" : "")); return true; diff --git a/YUViewLib/src/parser/VVC/ParserAnnexBVVC.h b/YUViewLib/src/parser/VVC/ParserAnnexBVVC.h index 86eafe10a..43edf03ef 100644 --- a/YUViewLib/src/parser/VVC/ParserAnnexBVVC.h +++ b/YUViewLib/src/parser/VVC/ParserAnnexBVVC.h @@ -65,6 +65,7 @@ struct ParsingState size_t counter{}; size_t sizeBytes{}; int poc{-1}; + unsigned layerID{0}; bool isKeyframe{}; std::optional fileStartEndPos; };