Skip to content

Commit

Permalink
Parse Slice headers for multiple layers in HEVC and VVC
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianFeldmann committed Feb 20, 2024
1 parent 35ff669 commit 0bad52e
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 24 deletions.
4 changes: 4 additions & 0 deletions YUViewLib/src/common/Typedef.h
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ typedef QPair<unsigned int, unsigned int> QUIntPair;
template <typename T> using umap_1d = std::map<unsigned, T>;
template <typename T> using umap_2d = std::map<unsigned, umap_1d<T>>;
template <typename T> using umap_3d = std::map<unsigned, umap_2d<T>>;
template <typename T> using umap_4d = std::map<unsigned, umap_3d<T>>;
template <typename T> using umap_5d = std::map<unsigned, umap_4d<T>>;

template <typename T> using vector = std::vector<T>;
template <typename T> using vector2d = std::vector<vector<T>>;
Expand All @@ -226,6 +228,8 @@ template <typename T> using vector4d = std::vector<vector3d<T>>;

template <typename T, size_t N> using array = std::array<T, N>;
template <typename T, size_t N1, size_t N2> using array2d = std::array<std::array<T, N2>, N1>;
template <typename T, size_t N1, size_t N2, size_t N3>
using array3d = std::array<std::array<std::array<T, N3>, N2>, N1>;

template <typename T> int indexInVec(const std::vector<T> &vec, const T &item)
{
Expand Down
6 changes: 4 additions & 2 deletions YUViewLib/src/parser/AVC/ParserAnnexBAVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) +
Expand Down Expand Up @@ -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");
Expand Down
19 changes: 13 additions & 6 deletions YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -283,18 +283,21 @@ 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.");
}
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;
Expand Down Expand Up @@ -445,22 +448,26 @@ 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.");
}
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<seq_parameter_set_rbsp> refSPS;
Expand Down
5 changes: 3 additions & 2 deletions YUViewLib/src/parser/HEVC/ParserAnnexBHEVC.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
19 changes: 18 additions & 1 deletion YUViewLib/src/parser/HEVC/slice_segment_header.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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");
Expand Down
2 changes: 2 additions & 0 deletions YUViewLib/src/parser/HEVC/slice_segment_header.h
Original file line number Diff line number Diff line change
Expand Up @@ -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<bool> slice_reserved_flag;
SliceType slice_type{};
bool pic_output_flag{true};
Expand Down
6 changes: 4 additions & 2 deletions YUViewLib/src/parser/ParserAnnexB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,11 @@ std::string ParserAnnexB::getShortStreamDescription(const int) const

bool ParserAnnexB::addFrameToList(int poc,
std::optional<pairUint64> 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)
Expand All @@ -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();
}
Expand Down
13 changes: 8 additions & 5 deletions YUViewLib/src/parser/ParserAnnexB.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,17 +137,20 @@ class ParserAnnexB : public Parser
struct AnnexBFrame
{
AnnexBFrame() = default;
int poc{-1}; //< The poc of this frame
std::optional<pairUint64>
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<pairUint64> 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<pairUint64> fileStartEndPos, bool randomAccessPoint);
bool addFrameToList(int poc,
std::optional<pairUint64> fileStartEndPos,
bool randomAccessPoint,
unsigned layerID);

static void logNALSize(const ByteVector & data,
std::shared_ptr<TreeItem> root,
Expand Down
16 changes: 10 additions & 6 deletions YUViewLib/src/parser/VVC/ParserAnnexBVVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions YUViewLib/src/parser/VVC/ParserAnnexBVVC.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ struct ParsingState
size_t counter{};
size_t sizeBytes{};
int poc{-1};
unsigned layerID{0};
bool isKeyframe{};
std::optional<pairUint64> fileStartEndPos;
};
Expand Down

0 comments on commit 0bad52e

Please sign in to comment.