Commit ca106408 authored by Karsten Suehring's avatar Karsten Suehring
Browse files

Regional Nesting SEI



(initial commit, requires some more work)
Patch-by: Adarsh Krishnan Ramasubramonian's avatarAdarsh Krishnan Ramasubramonian <aramasub@qti.qualcomm.com>
parent e58096f9
num_seis: 2
num_regions: 2
0 10 10 10 20
1 20 20 30 40
payloadType: 142
colour_remap_id: 0
colour_remap_cancel_flag: 0
colour_remap_persistence_flag: 1
colour_remap_video_signal_info_present_flag: 1
colour_remap_full_range_flag: 0
colour_remap_primaries: 9
colour_remap_transfer_function: 16
colour_remap_matrix_coefficients: 9
colour_remap_input_bit_depth: 10
colour_remap_bit_depth: 10
pre_lut_num_val_minus1[c]: 1
pre_lut_coded_value[c][i]: 64 pre_lut_target_value[c][i]: 64
pre_lut_coded_value[c][i]: 940 pre_lut_target_value[c][i]: 500
pre_lut_num_val_minus1[c]: 1
pre_lut_coded_value[c][i]: 64 pre_lut_target_value[c][i]: 128
pre_lut_coded_value[c][i]: 960 pre_lut_target_value[c][i]: 896
pre_lut_num_val_minus1[c]: 1
pre_lut_coded_value[c][i]: 64 pre_lut_target_value[c][i]: 192
pre_lut_coded_value[c][i]: 960 pre_lut_target_value[c][i]: 832
colour_remap_matrix_present_flag: 0
post_lut_num_val_minus1[c]: 1
post_lut_coded_value[c][i]: 64 post_lut_target_value[c][i]: 64
post_lut_coded_value[c][i]: 500 post_lut_target_value[c][i]: 940
post_lut_num_val_minus1[c]: 1
post_lut_coded_value[c][i]: 128 post_lut_target_value[c][i]: 64
post_lut_coded_value[c][i]: 896 post_lut_target_value[c][i]: 960
post_lut_num_val_minus1[c]: 1
post_lut_coded_value[c][i]: 192 post_lut_target_value[c][i]: 64
post_lut_coded_value[c][i]: 832 post_lut_target_value[c][i]: 960
num_regions: 2
3 10 10 30 20
1 20 20 30 40
payloadType: 149
SEICCVCancelFlag : 0
SEICCVPersistenceFlag : 1
SEICCVPrimariesPresent : 1
m_ccvSEIPrimariesX0 : 0.300
m_ccvSEIPrimariesY0 : 0.600
m_ccvSEIPrimariesX1 : 0.150
m_ccvSEIPrimariesY1 : 0.060
m_ccvSEIPrimariesX2 : 0.640
m_ccvSEIPrimariesY2 : 0.330
SEICCVMinLuminanceValuePresent : 1
SEICCVMinLuminanceValue : 0.0
SEICCVMaxLuminanceValuePresent : 1
SEICCVMaxLuminanceValue : 0.1
SEICCVAvgLuminanceValuePresent : 1
SEICCVAvgLuminanceValue : 0.01
num_seis: 3
num_regions: 2
0 10 10 10 20
1 20 20 30 40
payloadType: 140
SEIChromaResamplingHorizontalFilterType: 0
SEIChromaResamplingVerticalFilterType: 2
num_regions: 2
4 10 10 30 20
1 20 20 30 40
payloadType: 149
SEICCVCancelFlag : 0
SEICCVPersistenceFlag : 1
SEICCVPrimariesPresent : 1
m_ccvSEIPrimariesX0 : 0.300
m_ccvSEIPrimariesY0 : 0.600
m_ccvSEIPrimariesX1 : 0.150
m_ccvSEIPrimariesY1 : 0.060
m_ccvSEIPrimariesX2 : 0.640
m_ccvSEIPrimariesY2 : 0.330
SEICCVMinLuminanceValuePresent : 1
SEICCVMinLuminanceValue : 0.0
SEICCVMaxLuminanceValuePresent : 1
SEICCVMaxLuminanceValue : 0.1
SEICCVAvgLuminanceValuePresent : 1
SEICCVAvgLuminanceValue : 0.01
num_regions: 2
5 10 10 10 20
6 20 20 30 40
payloadType: 140
SEIChromaResamplingHorizontalFilterType: 2
SEIChromaResamplingVerticalFilterType: 2
No preview for this file type
......@@ -1213,6 +1213,9 @@ Bool TAppEncCfg::parseCfg( Int argc, TChar* argv[] )
("SEIRwpBottomGuardBandHeight", cfg_rwpSEIRwpBottomGuardBandHeight, cfg_rwpSEIRwpBottomGuardBandHeight, "specifies the height of the guard band below the i-th packed region.")
("SEIRwpGuardBandNotUsedForPredFlag", cfg_rwpSEIRwpGuardBandNotUsedForPredFlag, cfg_rwpSEIRwpGuardBandNotUsedForPredFlag, "Specifies if the guard bands is used in the inter prediction process.")
("SEIRwpGuardBandType", cfg_rwpSEIRwpGuardBandType, cfg_rwpSEIRwpGuardBandType, "Specifies the type of the guard bands for the i-th packed region.")
#endif
#if RNSEI
("SEIRegionalNestingFileRoot,-rns", m_regionalNestingSEIFileRoot, string(""), "Regional nesting SEI parameters root file name (wo num ext)")
#endif
;
......
......@@ -414,6 +414,9 @@ protected:
std::vector<Bool> m_rwpSEIRwpGuardBandNotUsedForPredFlag;
std::vector<UChar> m_rwpSEIRwpGuardBandType;
#endif
#if RNSEI
Bool m_rnSEIEnabled;
#endif
// weighted prediction
Bool m_useWeightedPred; ///< Use of weighted prediction in P slices
Bool m_useWeightedBiPred; ///< Use of bi-directional weighted prediction in B slices
......@@ -480,6 +483,9 @@ protected:
Int m_log2MaxMvLengthHorizontal; ///< Indicate the maximum absolute value of a decoded horizontal MV component in quarter-pel luma units
Int m_log2MaxMvLengthVertical; ///< Indicate the maximum absolute value of a decoded vertical MV component in quarter-pel luma units
std::string m_colourRemapSEIFileRoot;
#if RNSEI
std::string m_regionalNestingSEIFileRoot;
#endif
std::string m_summaryOutFilename; ///< filename to use for producing summary output file.
std::string m_summaryPicFilenameBase; ///< Base filename to use for producing summary picture output files. The actual filenames used will have I.txt, P.txt and B.txt appended.
......
......@@ -428,7 +428,9 @@ Void TAppEncTop::xInitLibCfg()
m_cTEncTop.setSEIGreenMetadataInfoSEIEnable ( m_greenMetadataType > 0 );
m_cTEncTop.setSEIGreenMetadataType ( UChar(m_greenMetadataType) );
m_cTEncTop.setSEIXSDMetricType ( UChar(m_xsdMetricType) );
#if RNSEI
m_cTEncTop.setRegionalNestingSEIFileRoot ( m_regionalNestingSEIFileRoot );
#endif
m_cTEncTop.setTileUniformSpacingFlag ( m_tileUniformSpacingFlag );
m_cTEncTop.setNumColumnsMinus1 ( m_numTileColumnsMinus1 );
m_cTEncTop.setNumRowsMinus1 ( m_numTileRowsMinus1 );
......
......@@ -37,6 +37,7 @@
#include "CommonDef.h"
#include "SEI.h"
#include <iostream>
SEIMessages getSeisByType(SEIMessages &seiList, SEI::PayloadType seiType)
{
......@@ -112,6 +113,70 @@ void SEIPictureTiming::copyTo (SEIPictureTiming& target)
target.m_numNalusInDuMinus1 = m_numNalusInDuMinus1;
target.m_duCpbRemovalDelayMinus1 = m_duCpbRemovalDelayMinus1;
}
#if RNSEI
std::ostream& operator<<(std::ostream &os, RNSEIWindow const &region)
{
os << region.getRegionId() << " " << region.getWindowLeftOffset() <<
region.getWindowRightOffset() << " " << region.getWindowTopOffset() << " " <<
region.getWindowBottomOffset() << "\n";
return os;
}
SEIRegionalNesting::~SEIRegionalNesting()
{
// Delete SEI messages
for(Int i = 0; i < m_rnSeiMessages.size(); i++)
{
delete m_rnSeiMessages[i].second;
}
}
Void SEIRegionalNesting::addRegionalSEI(RegionalSEI *regSEI)
{
// Check if no conflict with region IDs of regions
const RNSEIWindowVec newRegions = regSEI->getRegions();
RNSEIWindowVec regionsToAdd;
std::vector<UInt> listOfIndices;
// Loop through regions to add
for(RNSEIWindowVec::const_iterator iterNew = newRegions.begin();
iterNew != newRegions.end(); iterNew++)
{
Bool addNewRegion = m_regions.empty() ? true : false;
Bool foundRegion = false;
// Loop through regions already present
for(RNSEIWindowVec::const_iterator iterRef = m_regions.begin();
!foundRegion && iterRef != m_regions.end(); iterRef++)
{
if( (*iterNew) == (*iterRef) ) // Check if same region present
{
listOfIndices.push_back(iterRef - m_regions.begin()); // Add index
foundRegion = true;
}
else if( iterRef->checkSameID(*iterNew) ) // Check if there is a region ID class
{
// Two regions are different yet have same ID value; violates constraint
std::cout << "Two different regions have the same ID; please check.\n";
std::cout << "Region:" << (*iterNew) << "\n";
std::cout << "Region:" << (*iterRef) << "\n";
exit(1);
}
}
addNewRegion = !foundRegion;
if(addNewRegion)
{
// Index is current size of the m_regions;
listOfIndices.push_back(m_regions.size());
m_regions.push_back((*iterNew));
}
}
if(listOfIndices.empty())
{
std::cout << "Unable to add regions to the regional nesting SEI.\n";
exit(1);
}
addRegionalSEI(listOfIndices, regSEI->getSEI());
}
#endif
// Static member
const TChar *SEI::getSEIMessageString(SEI::PayloadType payloadType)
......@@ -169,6 +234,9 @@ const TChar *SEI::getSEIMessageString(SEI::PayloadType payloadType)
#endif
#if RWP_SEI_MESSAGE
case SEI::REGION_WISE_PACKING: return "Region wise packing information";
#endif
#if RNSEI
case SEI::REGIONAL_NESTING: return "Regional nesting";
#endif
default: return "Unknown";
}
......
......@@ -105,6 +105,9 @@ public:
#endif
#if RWP_SEI_MESSAGE
REGION_WISE_PACKING = 155,
#endif
#if RNSEI
REGIONAL_NESTING = 157,
#endif
};
......@@ -129,7 +132,6 @@ SEIMessages extractSeisByType(SEIMessages &seiList, SEI::PayloadType seiType);
Void deleteSEIs (SEIMessages &seiList);
class SEIBufferingPeriod : public SEI
{
public:
......@@ -1001,5 +1003,75 @@ public:
};
#endif
#if RNSEI
// Class that associates an SEI with one more regions
class RegionalSEI
{
public:
RegionalSEI(): m_seiMessage(NULL) {}
RegionalSEI(SEI *sei, RNSEIWindowVec &regions)
{
if( checkRegionalNestedSEIPayloadType(sei->payloadType()) )
{
m_seiMessage = sei;
m_regions = regions;
}
else
{
m_seiMessage = sei;
}
}
~RegionalSEI()
{
// m_seiMessage not deleted here; pointer should be passed to another object
}
SEI *getSEI() { return m_seiMessage; } // TBD - const?
UInt getNumRegions() const { return m_regions.size(); }
const RNSEIWindowVec& getRegions() { return m_regions; }
Void addRegions(RNSEIWindowVec const &regions) { m_regions.insert(m_regions.end(), regions.begin(), regions.end()); }
static Bool checkRegionalNestedSEIPayloadType(SEI::PayloadType const payloadType)
{
switch(payloadType)
{
case SEI::USER_DATA_REGISTERED_ITU_T_T35:
case SEI::USER_DATA_UNREGISTERED:
case SEI::FILM_GRAIN_CHARACTERISTICS:
case SEI::POST_FILTER_HINT:
case SEI::TONE_MAPPING_INFO:
case SEI::CHROMA_RESAMPLING_FILTER_HINT:
case SEI::KNEE_FUNCTION_INFO:
case SEI::COLOUR_REMAPPING_INFO:
case SEI::CONTENT_COLOUR_VOLUME:
return true;
default:
return false;
}
}
private:
SEI *m_seiMessage;
RNSEIWindowVec m_regions;
};
class SEIRegionalNesting : public SEI
{
public:
SEIRegionalNesting(): m_rnId(0) {}
~SEIRegionalNesting();
PayloadType payloadType() const { return REGIONAL_NESTING; }
UInt getNumRnSEIMessage() const { return m_rnSeiMessages.size(); }
UInt getNumRectRegions() const { return m_regions.size(); }
UInt getRNId() const { return m_rnId; }
Void addRegion(RNSEIWindow *regn) { m_regions.push_back(*regn); }
Void clearRegions() { m_regions.clear(); }
Void addRegionalSEI(std::vector<UInt> listInd, SEI *sei) {m_rnSeiMessages.push_back(std::pair<std::vector<UInt>, SEI *>(listInd,sei));}
Void addRegionalSEI(RegionalSEI *regSEI);
const std::vector< std::pair< std::vector<UInt>, SEI* > >& getRnSEIMessages() const { return m_rnSeiMessages; }
const std::vector<RNSEIWindow> &getRegions() const { return m_regions; }
private:
UInt m_rnId;
RNSEIWindowVec m_regions;
std::vector< std::pair< std::vector<UInt>, SEI* > > m_rnSeiMessages;
};
#endif
//! \}
......@@ -512,44 +512,6 @@ public:
const TimingInfo* getTimingInfo() const { return &m_timingInfo; }
};
class Window
{
private:
Bool m_enabledFlag;
Int m_winLeftOffset;
Int m_winRightOffset;
Int m_winTopOffset;
Int m_winBottomOffset;
public:
Window()
: m_enabledFlag (false)
, m_winLeftOffset (0)
, m_winRightOffset (0)
, m_winTopOffset (0)
, m_winBottomOffset(0)
{ }
Bool getWindowEnabledFlag() const { return m_enabledFlag; }
Int getWindowLeftOffset() const { return m_enabledFlag ? m_winLeftOffset : 0; }
Void setWindowLeftOffset(Int val) { m_winLeftOffset = val; m_enabledFlag = true; }
Int getWindowRightOffset() const { return m_enabledFlag ? m_winRightOffset : 0; }
Void setWindowRightOffset(Int val) { m_winRightOffset = val; m_enabledFlag = true; }
Int getWindowTopOffset() const { return m_enabledFlag ? m_winTopOffset : 0; }
Void setWindowTopOffset(Int val) { m_winTopOffset = val; m_enabledFlag = true; }
Int getWindowBottomOffset() const { return m_enabledFlag ? m_winBottomOffset: 0; }
Void setWindowBottomOffset(Int val) { m_winBottomOffset = val; m_enabledFlag = true; }
Void setWindow(Int offsetLeft, Int offsetLRight, Int offsetLTop, Int offsetLBottom)
{
m_enabledFlag = true;
m_winLeftOffset = offsetLeft;
m_winRightOffset = offsetLRight;
m_winTopOffset = offsetLTop;
m_winBottomOffset = offsetLBottom;
}
};
class TComVUI
{
private:
......
......@@ -44,6 +44,7 @@
#include <vector>
#include <utility>
#include <iostream>
//! \ingroup TLibCommon
//! \{
......@@ -99,6 +100,7 @@
#define CMP_SEI_MESSAGE 1 // cubemap projection SEI message
#define ERP_SR_OV_SEI_MESSAGE 1 // equirectangular projection, sphere rotation, and omni viewport SEI message
#define RNSEI 1 ///< Support for signalling regional nesting SEI message
// ====================================================================================================================
// Tool Switches
// ====================================================================================================================
......@@ -902,6 +904,80 @@ struct WCGChromaQPControl
Double chromaQpOffset; ///< Chroma QP Offset (0.0:default)
};
class Window
{
private:
Bool m_enabledFlag;
Int m_winLeftOffset;
Int m_winRightOffset;
Int m_winTopOffset;
Int m_winBottomOffset;
public:
Window()
: m_enabledFlag (false)
, m_winLeftOffset (0)
, m_winRightOffset (0)
, m_winTopOffset (0)
, m_winBottomOffset(0)
{ }
Bool getWindowEnabledFlag() const { return m_enabledFlag; }
Int getWindowLeftOffset() const { return m_enabledFlag ? m_winLeftOffset : 0; }
Void setWindowLeftOffset(Int val) { m_winLeftOffset = val; m_enabledFlag = true; }
Int getWindowRightOffset() const { return m_enabledFlag ? m_winRightOffset : 0; }
Void setWindowRightOffset(Int val) { m_winRightOffset = val; m_enabledFlag = true; }
Int getWindowTopOffset() const { return m_enabledFlag ? m_winTopOffset : 0; }
Void setWindowTopOffset(Int val) { m_winTopOffset = val; m_enabledFlag = true; }
Int getWindowBottomOffset() const { return m_enabledFlag ? m_winBottomOffset: 0; }
Void setWindowBottomOffset(Int val) { m_winBottomOffset = val; m_enabledFlag = true; }
Void setWindow(Int offsetLeft, Int offsetLRight, Int offsetLTop, Int offsetLBottom)
{
m_enabledFlag = true;
m_winLeftOffset = offsetLeft;
m_winRightOffset = offsetLRight;
m_winTopOffset = offsetLTop;
m_winBottomOffset = offsetLBottom;
}
Bool operator == (const Window &rhs) const
{
return ( m_enabledFlag && rhs.m_enabledFlag &&
m_winLeftOffset == rhs.m_winLeftOffset &&
m_winRightOffset == rhs.m_winRightOffset &&
m_winTopOffset == rhs.m_winTopOffset &&
m_winBottomOffset == rhs.m_winBottomOffset
);
}
};
#if RNSEI
class RNSEIWindow : public Window
{
private:
UInt m_regionId;
public:
RNSEIWindow() : Window(), m_regionId(0) {}
Int getRegionId() const { return getWindowEnabledFlag() ? m_regionId : 0; }
Void setRegionId(UInt const val) { m_regionId = val; }
// Check two RNSEIWindows are identical
Bool operator == (RNSEIWindow const &rhs) const
{
return ( (m_regionId == rhs.m_regionId) &&
Window(*this) == Window(rhs) );
}
// Check if two windows are identical, even though regions may be different
Bool checkSameRegion(RNSEIWindow const &rhs) const
{
return ( Window(*this) == Window(rhs) );
}
Bool checkSameID(RNSEIWindow const &rhs) const
{
return ( m_regionId == rhs.m_regionId );
}
friend std::ostream& operator<<(std::ostream &os, RNSEIWindow const &region);
};
typedef std::vector<RNSEIWindow> RNSEIWindowVec;
#endif
//! \}
#endif
......
......@@ -391,6 +391,12 @@ Void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
sei = new SEIRegionWisePacking;
xParseSEIRegionWisePacking((SEIRegionWisePacking&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
#endif
#if RNSEI
case SEI::REGIONAL_NESTING:
sei = new SEIRegionalNesting;
xParseSEIRegionalNesting((SEIRegionalNesting&) *sei, payloadSize, sps, pDecodedMessageOutputStream);
break;
#endif
default:
for (UInt i = 0; i < payloadSize; i++)
......@@ -509,6 +515,149 @@ Void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
setBitstream(bs);
}
#if RNSEI
Void SEIReader::xReadSEImessageHdrPayload(SEI* &sei, const TComSPS *sps, std::ostream *pDecodedMessageOutputStream)
{
#if ENC_DEC_TRACE
xTraceSEIHeader();
#endif
Int payloadType = 0;
UInt val = 0;
do
{
sei_read_code(NULL, 8, val, "payload_type");
payloadType += val;
} while (val==0xFF);
UInt payloadSize = 0;
do
{
sei_read_code(NULL, 8, val, "payload_size");
payloadSize += val;
} while (val==0xFF);
#if ENC_DEC_TRACE
xTraceSEIMessageType((SEI::PayloadType)payloadType);
#endif
/* extract the payload for this single SEI message.
* This allows greater safety in erroneous parsing of an SEI message
* from affecting subsequent messages.
* After parsing the payload, bs needs to be restored as the primary
* bitstream.
*/
TComInputBitstream *bs = getBitstream();
setBitstream(bs->extractSubstream(payloadSize * 8));
{
switch (payloadType)
{
case SEI::USER_DATA_REGISTERED_ITU_T_T35:
sei = new SEIUserDataRegistered;
xParseSEIUserDataRegistered((SEIUserDataRegistered&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::USER_DATA_UNREGISTERED:
sei = new SEIUserDataUnregistered;
xParseSEIUserDataUnregistered((SEIUserDataUnregistered&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::FILM_GRAIN_CHARACTERISTICS:
sei = new SEIFilmGrainCharacteristics;
xParseSEIFilmGrainCharacteristics((SEIFilmGrainCharacteristics&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::POST_FILTER_HINT:
if (!sps)
{
printf ("Warning: post filter hint SEI message, but no active SPS is available. Ignoring.");
}
else
{
sei = new SEIPostFilterHint;
xParseSEIPostFilterHint((SEIPostFilterHint&) *sei, payloadSize, sps, pDecodedMessageOutputStream);
}
break;
case SEI::TONE_MAPPING_INFO:
sei = new SEIToneMappingInfo;
xParseSEIToneMappingInfo((SEIToneMappingInfo&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::CHROMA_RESAMPLING_FILTER_HINT:
sei = new SEIChromaResamplingFilterHint;
xParseSEIChromaResamplingFilterHint((SEIChromaResamplingFilterHint&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::KNEE_FUNCTION_INFO:
sei = new SEIKneeFunctionInfo;
xParseSEIKneeFunctionInfo((SEIKneeFunctionInfo&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::COLOUR_REMAPPING_INFO:
sei = new SEIColourRemappingInfo;
xParseSEIColourRemappingInfo((SEIColourRemappingInfo&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
case SEI::CONTENT_COLOUR_VOLUME:
sei = new SEIContentColourVolume;
xParseSEIContentColourVolume((SEIContentColourVolume&) *sei, payloadSize, pDecodedMessageOutputStream);
break;
default:
for (UInt i = 0; i < payloadSize; i++)
{
UInt seiByte;
sei_read_code (NULL, 8, seiByte, "unknown prefix SEI payload byte");
}
printf ("Unknown prefix SEI message (payloadType = %d) was found!\n", payloadType);
if (pDecodedMessageOutputStream)
{
(*pDecodedMessageOutputStream) << "Unknown prefix SEI message (payloadType = " << payloadType << ") was found!\n";
}
break;
}
}
/* By definition the underlying bitstream terminates in a byte-aligned manner.
* 1. Extract all bar the last MIN(bitsremaining,nine) bits as reserved_payload_extension_data
* 2. Examine the final 8 bits to determine the payload_bit_equal_to_one marker
* 3. Extract the remainingreserved_payload_extension_data bits.
*
* If there are fewer than 9 bits available, extract them.
*/
Int payloadBitsRemaining = getBitstream()->getNumBitsLeft();
if (payloadBitsRemaining) /* more_data_in_payload() */
{
for (; payloadBitsRemaining > 9; payloadBitsRemaining--)
{
UInt reservedPayloadExtensionData;
sei_read_code ( pDecodedMessageOutputStream, 1, reservedPayloadExtensionData, "reserved_payload_extension_data");
}
/* 2 */
Int finalBits = getBitstream()->peekBits(payloadBitsRemaining);
Int finalPayloadBits = 0;
for (Int mask = 0xff; finalBits & (mask >> finalPayloadBits); finalPayloadBits++)
{
continue;
}
/* 3 */