diff --git a/cfg/sei/generalized_cubemap_projection.cfg b/cfg/sei/generalized_cubemap_projection.cfg new file mode 100644 index 0000000000000000000000000000000000000000..82cd6d8a491d7df90875bf3cd40bd1b74cce9a83 --- /dev/null +++ b/cfg/sei/generalized_cubemap_projection.cfg @@ -0,0 +1,16 @@ +#======== Generalized Cubemap Projection SEI message ===================== +SEIGcmpEnabled : 1 +SEIGcmpCancelFlag : 0 +SEIGcmpPersistenceFlag : 1 +SEIGcmpPackingType : 2 +SEIGcmpMappingFunctionType : 2 +SEIGcmpFaceIndex : 5 0 4 3 1 2 +SEIGcmpFaceRotation : 2 2 2 2 2 2 +SEIGcmpFunctionCoeffU : 0.28 0.28 0.28 0.28 0.28 0.28 +SEIGcmpFunctionUAffectedByVFlag : 0 0 0 0 0 0 +SEIGcmpFunctionCoeffV : 0.4 0.4 0.4 0.28 0.4 0.28 +SEIGcmpFunctionVAffectedByUFlag : 1 1 1 0 1 0 +SEIGcmpGuardBandFlag : 1 +SEIGcmpGuardBandBoundaryType : 1 +SEIGcmpGuardBandSamplesMinus1 : 15 + diff --git a/doc/software-manual.tex b/doc/software-manual.tex index c6f7c693ffa617d8564d41e59ec94af841350544..718b22377a0d3085ee02150dc9d4c4c9433a7cb0 100755 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -2684,6 +2684,7 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension 148 & Ambient viewing environment & Table \ref{tab:sei-ambient-viewing-environment}\\ 149 & Content colour volume & Table \ref{tab:sei-content-colour-volume}\\ 150 & Equirectangular projection & Table \ref{tab:sei-erp} \\ + 153 & Generalized cubemap projection & Table \ref{tab:sei-gcmp} \\ 154 & Sphere rotation & Table \ref{tab:sei-sphere-rotation} \\ 155 & Region-wise packing & Table \ref{tab:sei-rwp} \\ 156 & Omni viewport & Table \ref{tab:sei-omni-viewport} \\ @@ -3378,6 +3379,96 @@ Inicates the width of the guard band on the right side of the onstituent picture \\ \end{OptionTableNoShorthand} +\begin{OptionTableNoShorthand}{Generalized Cubemap Projection SEI message encoder parameters}{tab:sei-gcmp} +\Option{SEIGcmpEnabled} & +\Default{false} & +Enables (true) or disables (false) the insertion of generalized cubemap projection SEI message. +\\ +\Option{SEIGcmpCancelFlag} & +\Default{true} & +Indicates that generalized cubemap projection SEI message cancels the persistence (true) or follows (false). +\\ +\Option{SEIGcmpPersistenceFlag} & +\Default{false} & +Specifies the persistence of the generalized cubemap projection SEI message. +\\ +\Option{SEIGcmpPackingType} & +\Default{0} & +Specifies the packing type. +\par +\begin{tabular}{cp{0.35\textwidth}} + 0 & 6 rows and 1 columns \\ + 1 & 3 rows and 2 columns \\ + 2 & 2 rows and 3 columns \\ + 3 & 1 rows and 6 columns \\ + 4 & 1 rows and 5 columns (hemisphere cubemap) \\ + 5 & 5 rows and 1 columns (hemisphere cubemap) \\ +\end{tabular} +\\ +\Option{SEIGcmpMappingFunctionType} & +\Default{0} & +Specifies the mapping function used to adjust the sample locations. +\par +\begin{tabular}{cp{0.35\textwidth}} + 0 & Disabled (conventional cubemap projection) \\ + 1 & Equi-angular mapping function \\ + 2 & Defined by SEIGcmpFunctionCoeffU, SEIGcmpFunctionUAffectedByVFlag, SEIGcmpFunctionCoeffV, and SEIGcmpFunctionVAffectedByUFlag \\ +\end{tabular} +\\ +\Option{SEIGcmpFaceIndex} & +\Default{} & +An array that specifies the face index for the faces packed in the cubemap projected picture. +\par +\begin{tabular}{cp{0.35\textwidth}} + 0 & Front face \\ + 1 & Back face \\ + 2 & Top face \\ + 3 & Bottom face \\ + 4 & Right face \\ + 5 & Left face \\ +\end{tabular} +\\ +\Option{SEIGcmpFaceRotation} & +\Default{} & +An array that specifies the rotation to be applied to the faces. +\par +\begin{tabular}{cp{0.35\textwidth}} + 0 & No rotation \\ + 1 & 90 degree anticlockwise \\ + 2 & 180 degree anticlockwise \\ + 3 & 270 degree anticlockwise \\ +\end{tabular} +\\ +\Option{SEIGcmpFunctionCoeffU} & +\Default{} & +An array that specifies the coefficients used in the cubemap mapping function of the u-axis for the faces when SEIGcmpMappingFunctionType is set to 2. +\\ +\Option{SEIGcmpFunctionUAffectedByVFlag} & +\Default{} & +An array that specifies whether the cubemap mapping function of the u-axis refers to the v position of the sample location for the faces when SEIGcmpMappingFunctionType is set to 2. +\\ +\Option{SEIGcmpFunctionCoeffV} & +\Default{} & +An array that specifies the coefficients used in the cubemap mapping function of the v-axis for the faces when SEIGcmpMappingFunctionType is set to 2. +\\ +\Option{SEIGcmpFunctionVAffectedByUFlag} & +\Default{} & +An array that specifies whether the cubemap mapping function of the v-axis refers to the u position of the sample location for the faces when SEIGcmpMappingFunctionType is set to 2. +\\ +\Option{SEIGcmpGuardBandFlag} & +\Default{false} & +Indicates the existence of guard band areas in the picture. +\\ +\Option{SEIGcmpGuardBandBoundaryType} & +\Default{false} & +Enables (true) or disables (false) the boundary guard bands. +\\ +\Option{SEIGcmpGuardBandSamplesMinus1} & +\Default{0} & +Specifies the number of guard band samples minus 1 used in the cubemap projected picture. +\\ +\end{OptionTableNoShorthand} + \begin{OptionTableNoShorthand}{Sphere Rotation SEI message encoder parameters}{tab:sei-sphere-rotation} \Option{SEISphereRotationEnabled} & \Default{false} & diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index c5b0eced7feeb87248bb0ebd53c4dc8cb15edab5..baf182c6bae220d1c4627111fe1a071bd951f1a6 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -737,6 +737,22 @@ void EncApp::xInitLibCfg() m_cEncLib.setRwpSEIRwpGuardBandNotUsedForPredFlag (m_rwpSEIRwpGuardBandNotUsedForPredFlag); m_cEncLib.setRwpSEIRwpGuardBandType (m_rwpSEIRwpGuardBandType); #endif +#if JVET_P0597_GCMP_SEI + m_cEncLib.setGcmpSEIEnabled ( m_gcmpSEIEnabled ); + m_cEncLib.setGcmpSEICancelFlag ( m_gcmpSEICancelFlag ); + m_cEncLib.setGcmpSEIPersistenceFlag ( m_gcmpSEIPersistenceFlag ); + m_cEncLib.setGcmpSEIPackingType ( (uint8_t)m_gcmpSEIPackingType ); + m_cEncLib.setGcmpSEIMappingFunctionType ( (uint8_t)m_gcmpSEIMappingFunctionType ); + m_cEncLib.setGcmpSEIFaceIndex ( m_gcmpSEIFaceIndex ); + m_cEncLib.setGcmpSEIFaceRotation ( m_gcmpSEIFaceRotation ); + m_cEncLib.setGcmpSEIFunctionCoeffU ( m_gcmpSEIFunctionCoeffU ); + m_cEncLib.setGcmpSEIFunctionUAffectedByVFlag ( m_gcmpSEIFunctionUAffectedByVFlag ); + m_cEncLib.setGcmpSEIFunctionCoeffV ( m_gcmpSEIFunctionCoeffV ); + m_cEncLib.setGcmpSEIFunctionVAffectedByUFlag ( m_gcmpSEIFunctionVAffectedByUFlag ); + m_cEncLib.setGcmpSEIGuardBandFlag ( m_gcmpSEIGuardBandFlag ); + m_cEncLib.setGcmpSEIGuardBandBoundaryType ( m_gcmpSEIGuardBandBoundaryType ); + m_cEncLib.setGcmpSEIGuardBandSamplesMinus1 ( (uint8_t)m_gcmpSEIGuardBandSamplesMinus1 ); +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL m_cEncLib.setSubpicureLevelInfoSEIEnabled (m_subpicureLevelInfoSEIEnabled); #endif diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 30e1bb073338abdf307d7f00d324749fa6747466..0a9f80b9ad722c4b2af3803d980c2725fa292ce2 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -913,6 +913,14 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) SMultiValueInput<bool> cfg_rwpSEIRwpGuardBandNotUsedForPredFlag (0, 1, 0, std::numeric_limits<uint8_t>::max()); SMultiValueInput<uint32_t> cfg_rwpSEIRwpGuardBandType (0, 7, 0, 4*std::numeric_limits<uint8_t>::max()); #endif +#if JVET_P0597_GCMP_SEI + SMultiValueInput<uint32_t> cfg_gcmpSEIFaceIndex (0, 5, 5, 6); + SMultiValueInput<uint32_t> cfg_gcmpSEIFaceRotation (0, 3, 5, 6); + SMultiValueInput<double> cfg_gcmpSEIFunctionCoeffU (0.0, 1.0, 5, 6); + SMultiValueInput<uint32_t> cfg_gcmpSEIFunctionUAffectedByVFlag (0, 1, 5, 6); + SMultiValueInput<double> cfg_gcmpSEIFunctionCoeffV (0.0, 1.0, 5, 6); + SMultiValueInput<uint32_t> cfg_gcmpSEIFunctionVAffectedByUFlag (0, 1, 5, 6); +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET const int defaultLadfQpOffset[3] = { 1, 0, 1 }; const int defaultLadfIntervalLowerBound[2] = { 350, 833 }; @@ -1633,6 +1641,22 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("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 JVET_P0597_GCMP_SEI + ("SEIGcmpEnabled", m_gcmpSEIEnabled, false, "Control generation of generalized cubemap projection SEI messages") + ("SEIGcmpCancelFlag", m_gcmpSEICancelFlag, true, "Indicate that generalized cubemap projection SEI message cancels the persistence or follows") + ("SEIGcmpPersistenceFlag", m_gcmpSEIPersistenceFlag, false, "Specifies the persistence of the generalized cubemap projection SEI messages") + ("SEIGcmpPackingType", m_gcmpSEIPackingType, 0u, "Specifies the packing type") + ("SEIGcmpMappingFunctionType", m_gcmpSEIMappingFunctionType, 0u, "Specifies the mapping function used to adjust the sample locations of the cubemap projection") + ("SEIGcmpFaceIndex", cfg_gcmpSEIFaceIndex, cfg_gcmpSEIFaceIndex, "Specifies the face index for the i-th face") + ("SEIGcmpFaceRotation", cfg_gcmpSEIFaceRotation, cfg_gcmpSEIFaceRotation, "Specifies the rotation to be applied to the i-th face") + ("SEIGcmpFunctionCoeffU", cfg_gcmpSEIFunctionCoeffU, cfg_gcmpSEIFunctionCoeffU, "Specifies the coefficient used in the cubemap mapping function of the u-axis of the i-th face") + ("SEIGcmpFunctionUAffectedByVFlag", cfg_gcmpSEIFunctionUAffectedByVFlag, cfg_gcmpSEIFunctionUAffectedByVFlag, "Specifies whether the cubemap mapping function of the u-axis refers to the v position of the sample location") + ("SEIGcmpFunctionCoeffV", cfg_gcmpSEIFunctionCoeffV, cfg_gcmpSEIFunctionCoeffV, "Specifies the coefficient used in the cubemap mapping function of the v-axis of the i-th face") + ("SEIGcmpFunctionVAffectedByUFlag", cfg_gcmpSEIFunctionVAffectedByUFlag, cfg_gcmpSEIFunctionVAffectedByUFlag, "Specifies whether the cubemap mapping function of the v-axis refers to the u position of the sample location") + ("SEIGcmpGuardBandFlag", m_gcmpSEIGuardBandFlag, false, "Indicate the existence of guard band areas in the picture") + ("SEIGcmpGuardBandBoundaryType", m_gcmpSEIGuardBandBoundaryType, false, "Indicate which face boundaries contain guard bands") + ("SEIGcmpGuardBandSamplesMinus1", m_gcmpSEIGuardBandSamplesMinus1, 0u, "Specifies the number of guard band samples minus1 used in the cubemap projected picture") +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL ("SEISubpicureLevelInfo", m_subpicureLevelInfoSEIEnabled, false, "Control generation of Subpicture Level Information SEI messages") #endif @@ -2836,6 +2860,39 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } } +#endif +#if JVET_P0597_GCMP_SEI + if (m_gcmpSEIEnabled && !m_gcmpSEICancelFlag) + { + int numFace = m_gcmpSEIPackingType == 4 || m_gcmpSEIPackingType == 5 ? 5 : 6; + CHECK (!(cfg_gcmpSEIFaceIndex.values.size() == numFace), "Number of SEIGcmpFaceIndex must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6"); + CHECK (!(cfg_gcmpSEIFaceRotation.values.size() == numFace), "Number of SEIGcmpFaceRotation must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6"); + m_gcmpSEIFaceIndex.resize(numFace); + m_gcmpSEIFaceRotation.resize(numFace); + if (m_gcmpSEIMappingFunctionType == 2) + { + CHECK (!(cfg_gcmpSEIFunctionCoeffU.values.size() == numFace), "Number of SEIGcmpFunctionCoeffU must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6"); + CHECK (!(cfg_gcmpSEIFunctionUAffectedByVFlag.values.size() == numFace), "Number of SEIGcmpFunctionUAffectedByVFlag must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6"); + CHECK (!(cfg_gcmpSEIFunctionCoeffV.values.size() == numFace), "Number of SEIGcmpFunctionCoeffV must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6"); + CHECK (!(cfg_gcmpSEIFunctionVAffectedByUFlag.values.size() == numFace), "Number of SEIGcmpFunctionVAffectedByUFlag must be equal to 5 when SEIGcmpPackingType is equal to 4 or 5, otherwise, it must be equal to 6"); + m_gcmpSEIFunctionCoeffU.resize(numFace); + m_gcmpSEIFunctionUAffectedByVFlag.resize(numFace); + m_gcmpSEIFunctionCoeffV.resize(numFace); + m_gcmpSEIFunctionVAffectedByUFlag.resize(numFace); + } + for (int i = 0; i < numFace; i++) + { + m_gcmpSEIFaceIndex[i] = cfg_gcmpSEIFaceIndex.values[i]; + m_gcmpSEIFaceRotation[i] = cfg_gcmpSEIFaceRotation.values[i]; + if (m_gcmpSEIMappingFunctionType == 2) + { + m_gcmpSEIFunctionCoeffU[i] = cfg_gcmpSEIFunctionCoeffU.values[i]; + m_gcmpSEIFunctionUAffectedByVFlag[i] = cfg_gcmpSEIFunctionUAffectedByVFlag.values[i]; + m_gcmpSEIFunctionCoeffV[i] = cfg_gcmpSEIFunctionCoeffV.values[i]; + m_gcmpSEIFunctionVAffectedByUFlag[i] = cfg_gcmpSEIFunctionVAffectedByUFlag.values[i]; + } + } + } #endif m_reshapeCW.binCW.resize(3); m_reshapeCW.rspFps = m_iFrameRate; @@ -4273,6 +4330,27 @@ bool EncAppCfg::xCheckParameter() } #endif +#if JVET_P0597_GCMP_SEI + if (m_gcmpSEIEnabled && !m_gcmpSEICancelFlag) + { + xConfirmPara( m_gcmpSEIMappingFunctionType < 0 || m_gcmpSEIMappingFunctionType > 2, "SEIGcmpMappingFunctionType must be in the range of 0 to 2"); + int numFace = m_gcmpSEIPackingType == 4 || m_gcmpSEIPackingType == 5 ? 5 : 6; + for ( int i = 0; i < numFace; i++ ) + { + xConfirmPara( m_gcmpSEIFaceIndex[i] < 0 || m_gcmpSEIFaceIndex[i] > 5, "SEIGcmpFaceIndex must be in the range of 0 to 5"); + xConfirmPara( m_gcmpSEIFaceRotation[i] < 0 || m_gcmpSEIFaceRotation[i] > 3, "SEIGcmpFaceRotation must be in the range of 0 to 3"); + if (m_gcmpSEIMappingFunctionType == 2) + { + xConfirmPara( m_gcmpSEIFunctionCoeffU[i] <= 0.0 || m_gcmpSEIFunctionCoeffU[i] > 1.0, "SEIGcmpFunctionCoeffU must be in the range (0, 1]"); + xConfirmPara( m_gcmpSEIFunctionCoeffV[i] <= 0.0 || m_gcmpSEIFunctionCoeffV[i] > 1.0, "SEIGcmpFunctionCoeffV must be in the range (0, 1]"); + } + } + if (m_gcmpSEIGuardBandFlag) + { + xConfirmPara( m_gcmpSEIGuardBandSamplesMinus1 < 0 || m_gcmpSEIGuardBandSamplesMinus1 > 15, "SEIGcmpGuardBandSamplesMinus1 must be in the range of 0 to 15"); + } + } +#endif #if HEVC_SEI || JVET_P0337_PORTING_SEI #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 8f227d1d99144dc5d1198b6f28ddc12c5c23233f..10c9ab465b4fd5c5d0ebe74f6c03b4272f413f4d 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -681,6 +681,23 @@ protected: std::vector<uint8_t> m_rwpSEIRwpGuardBandType; #endif +#if JVET_P0597_GCMP_SEI + bool m_gcmpSEIEnabled; + bool m_gcmpSEICancelFlag; + bool m_gcmpSEIPersistenceFlag; + uint32_t m_gcmpSEIPackingType; + uint32_t m_gcmpSEIMappingFunctionType; + std::vector<uint8_t> m_gcmpSEIFaceIndex; + std::vector<uint8_t> m_gcmpSEIFaceRotation; + std::vector<double> m_gcmpSEIFunctionCoeffU; + std::vector<bool> m_gcmpSEIFunctionUAffectedByVFlag; + std::vector<double> m_gcmpSEIFunctionCoeffV; + std::vector<bool> m_gcmpSEIFunctionVAffectedByUFlag; + bool m_gcmpSEIGuardBandFlag; + bool m_gcmpSEIGuardBandBoundaryType; + uint32_t m_gcmpSEIGuardBandSamplesMinus1; +#endif + #if JVET_P0984_SEI_SUBPIC_LEVEL bool m_subpicureLevelInfoSEIEnabled; #endif diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 85959f02e67df5fe79cc1f29fc0261480346ba39..078c00a9cde68d06165b05c4bf9340fc6f1bbd57 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -237,6 +237,9 @@ const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) case SEI::REGION_WISE_PACKING: return "Region wise packing information"; case SEI::OMNI_VIEWPORT: return "Omni viewport"; #endif +#if JVET_P0597_GCMP_SEI + case SEI::GENERALIZED_CUBEMAP_PROJECTION: return "Generalized cubemap projection"; +#endif #if JVET_P0450_SEI_SARI case SEI::SAMPLE_ASPECT_RATIO_INFO: return "Sample aspect ratio information"; #endif diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 6bb76936944967ac366652eef1edc90a4c5dc9dc..f48890f0202105a59c67b4af4c11273875af4ea1 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -111,6 +111,9 @@ public: REGION_WISE_PACKING = 155, OMNI_VIEWPORT = 156, #endif +#if JVET_P0597_GCMP_SEI + GENERALIZED_CUBEMAP_PROJECTION = 153, +#endif #if HEVC_SEI && !JVET_P0337_PORTING_SEI #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI ALTERNATIVE_TRANSFER_CHARACTERISTICS = 182, @@ -229,6 +232,31 @@ public: }; #endif +#if JVET_P0597_GCMP_SEI +class SEIGeneralizedCubemapProjection : public SEI +{ +public: + PayloadType payloadType() const { return GENERALIZED_CUBEMAP_PROJECTION; } + + SEIGeneralizedCubemapProjection() {} + virtual ~SEIGeneralizedCubemapProjection() {} + + bool m_gcmpCancelFlag; + bool m_gcmpPersistenceFlag; + uint8_t m_gcmpPackingType; + uint8_t m_gcmpMappingFunctionType; + std::vector<uint8_t> m_gcmpFaceIndex; + std::vector<uint8_t> m_gcmpFaceRotation; + std::vector<uint8_t> m_gcmpFunctionCoeffU; + std::vector<bool> m_gcmpFunctionUAffectedByVFlag; + std::vector<uint8_t> m_gcmpFunctionCoeffV; + std::vector<bool> m_gcmpFunctionVAffectedByUFlag; + bool m_gcmpGuardBandFlag; + bool m_gcmpGuardBandBoundaryType; + uint8_t m_gcmpGuardBandSamplesMinus1; +}; +#endif + #if JVET_P0450_SEI_SARI class SEISampleAspectRatioInfo : public SEI { diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 5340737b9e542166660364a638ee0c913c7cee22..1936308a0b54d47bce1c126b0423fdc20239cf67 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -291,6 +291,8 @@ #define JVET_P0184 1 //JVET-P0184: Decoding process for generating unavailable reference pictures +#define JVET_P0597_GCMP_SEI 1 // JVET-P0597: generalized cubemap projection SEI message + #define HEVC_SEI 0 // SEI messages that are defined in HEVC, but not in VVC typedef std::pair<int, bool> TrMode; diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index f8e813497a727385b1d7f68451adcdca12ae0ae1..cc556d2a0a207a8823deb732ee69d689032cd8f4 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -350,6 +350,12 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType xParseSEIRegionWisePacking((SEIRegionWisePacking&) *sei, payloadSize, pDecodedMessageOutputStream); break; #endif +#if JVET_P0597_GCMP_SEI + case SEI::GENERALIZED_CUBEMAP_PROJECTION: + sei = new SEIGeneralizedCubemapProjection; + xParseSEIGeneralizedCubemapProjection((SEIGeneralizedCubemapProjection&) *sei, payloadSize, pDecodedMessageOutputStream); + break; +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL case SEI::SUBPICTURE_LEVEL_INFO: sei = new SEISubpicureLevelInfo; @@ -1857,6 +1863,52 @@ void SEIReader::xParseSEIRegionWisePacking(SEIRegionWisePacking& sei, uint32_t p } #endif +#if JVET_P0597_GCMP_SEI +void SEIReader::xParseSEIGeneralizedCubemapProjection(SEIGeneralizedCubemapProjection& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) +{ + uint32_t val; + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + + sei_read_flag( pDecodedMessageOutputStream, val, "gcmp_cancel_flag" ); sei.m_gcmpCancelFlag = val; + if (!sei.m_gcmpCancelFlag) + { + sei_read_flag( pDecodedMessageOutputStream, val, "gcmp_persistence_flag" ); sei.m_gcmpPersistenceFlag = val; + sei_read_code( pDecodedMessageOutputStream, 3, val, "gcmp_packing_type" ); sei.m_gcmpPackingType = val; + sei_read_code( pDecodedMessageOutputStream, 2, val, "gcmp_mapping_function_type" ); sei.m_gcmpMappingFunctionType = val; + + int numFace = sei.m_gcmpPackingType == 4 || sei.m_gcmpPackingType == 5 ? 5 : 6; + sei.m_gcmpFaceIndex.resize(numFace); + sei.m_gcmpFaceRotation.resize(numFace); + if (sei.m_gcmpMappingFunctionType == 2) + { + sei.m_gcmpFunctionCoeffU.resize(numFace); + sei.m_gcmpFunctionUAffectedByVFlag.resize(numFace); + sei.m_gcmpFunctionCoeffV.resize(numFace); + sei.m_gcmpFunctionVAffectedByUFlag.resize(numFace); + } + + for (int i = 0; i < numFace; i++) + { + sei_read_code( pDecodedMessageOutputStream, 3, val, "gcmp_face_index" ); sei.m_gcmpFaceIndex[i] = val; + sei_read_code( pDecodedMessageOutputStream, 2, val, "gcmp_face_rotation" ); sei.m_gcmpFaceRotation[i] = val; + if (sei.m_gcmpMappingFunctionType == 2) + { + sei_read_code( pDecodedMessageOutputStream, 7, val, "gcmp_function_coeff_u" ); sei.m_gcmpFunctionCoeffU[i] = val; + sei_read_flag( pDecodedMessageOutputStream, val, "gcmp_function_u_affected_by_v_flag" ); sei.m_gcmpFunctionUAffectedByVFlag[i] = val; + sei_read_code( pDecodedMessageOutputStream, 7, val, "gcmp_function_coeff_v" ); sei.m_gcmpFunctionCoeffV[i] = val; + sei_read_flag( pDecodedMessageOutputStream, val, "gcmp_function_v_affected_by_u_flag" ); sei.m_gcmpFunctionVAffectedByUFlag[i] = val; + } + } + sei_read_flag( pDecodedMessageOutputStream, val, "gcmp_guard_band_flag" ); sei.m_gcmpGuardBandFlag = val; + if (sei.m_gcmpGuardBandFlag) + { + sei_read_flag( pDecodedMessageOutputStream, val, "gcmp_guard_band_boundary_type" ); sei.m_gcmpGuardBandBoundaryType = val; + sei_read_code( pDecodedMessageOutputStream, 4, val, "gcmp_guard_band_samples_minus1" ); sei.m_gcmpGuardBandSamplesMinus1 = val; + } + } +} +#endif + #if JVET_P0984_SEI_SUBPIC_LEVEL void SEIReader::xParseSEISubpictureLevelInfo(SEISubpicureLevelInfo& sei, const SPS *sps, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) { diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index b6de66c701dfb111c8b271f45a9a6ce87081b590..a5d95bf9056bb99a74bf7d77e7a1505127e0fda9 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -116,6 +116,9 @@ protected: void xParseSEIOmniViewport (SEIOmniViewport& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); void xParseSEIRegionWisePacking (SEIRegionWisePacking& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); #endif +#if JVET_P0597_GCMP_SEI + void xParseSEIGeneralizedCubemapProjection (SEIGeneralizedCubemapProjection &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL void xParseSEISubpictureLevelInfo (SEISubpicureLevelInfo& sei, const SPS *sps, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); #endif diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 03b9f5397c3ab938925ea634fbfd55b04d5000f4..47f5b79d55cbe2fe09e1238b15114c082da25193 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -663,6 +663,22 @@ protected: std::vector<bool> m_rwpSEIRwpGuardBandNotUsedForPredFlag; std::vector<uint8_t> m_rwpSEIRwpGuardBandType; #endif +#if JVET_P0597_GCMP_SEI + bool m_gcmpSEIEnabled; + bool m_gcmpSEICancelFlag; + bool m_gcmpSEIPersistenceFlag; + uint8_t m_gcmpSEIPackingType; + uint8_t m_gcmpSEIMappingFunctionType; + std::vector<uint8_t> m_gcmpSEIFaceIndex; + std::vector<uint8_t> m_gcmpSEIFaceRotation; + std::vector<double> m_gcmpSEIFunctionCoeffU; + std::vector<bool> m_gcmpSEIFunctionUAffectedByVFlag; + std::vector<double> m_gcmpSEIFunctionCoeffV; + std::vector<bool> m_gcmpSEIFunctionVAffectedByUFlag; + bool m_gcmpSEIGuardBandFlag; + bool m_gcmpSEIGuardBandBoundaryType; + uint8_t m_gcmpSEIGuardBandSamplesMinus1; +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL bool m_subpicureLevelInfoSEIEnabled; #endif @@ -1815,6 +1831,36 @@ public: void setRwpSEIRwpGuardBandType(const std::vector<uint8_t>& rwpGuardBandType) { m_rwpSEIRwpGuardBandType = rwpGuardBandType; } uint8_t getRwpSEIRwpGuardBandType(uint32_t idx) const { return m_rwpSEIRwpGuardBandType[idx]; } #endif +#if JVET_P0597_GCMP_SEI + void setGcmpSEIEnabled(bool b) { m_gcmpSEIEnabled = b; } + bool getGcmpSEIEnabled() { return m_gcmpSEIEnabled; } + void setGcmpSEICancelFlag(bool b) { m_gcmpSEICancelFlag = b; } + bool getGcmpSEICancelFlag() { return m_gcmpSEICancelFlag; } + void setGcmpSEIPersistenceFlag(bool b) { m_gcmpSEIPersistenceFlag = b; } + bool getGcmpSEIPersistenceFlag() { return m_gcmpSEIPersistenceFlag; } + void setGcmpSEIPackingType(uint8_t u) { m_gcmpSEIPackingType = u; } + uint8_t getGcmpSEIPackingType() { return m_gcmpSEIPackingType; } + void setGcmpSEIMappingFunctionType(uint8_t u) { m_gcmpSEIMappingFunctionType = u; } + uint8_t getGcmpSEIMappingFunctionType() { return m_gcmpSEIMappingFunctionType; } + void setGcmpSEIFaceIndex(const std::vector<uint8_t>& gcmpFaceIndex) { m_gcmpSEIFaceIndex = gcmpFaceIndex; } + uint8_t getGcmpSEIFaceIndex(int idx) const { return m_gcmpSEIFaceIndex[idx]; } + void setGcmpSEIFaceRotation(const std::vector<uint8_t>& gcmpFaceRotation) { m_gcmpSEIFaceRotation = gcmpFaceRotation; } + uint8_t getGcmpSEIFaceRotation(int idx) const { return m_gcmpSEIFaceRotation[idx]; } + void setGcmpSEIFunctionCoeffU(const std::vector<double>& gcmpFunctionCoeffU) { m_gcmpSEIFunctionCoeffU = gcmpFunctionCoeffU; } + double getGcmpSEIFunctionCoeffU(int idx) const { return m_gcmpSEIFunctionCoeffU[idx]; } + void setGcmpSEIFunctionUAffectedByVFlag(const std::vector<bool>& gcmpFunctionUAffectedByVFlag) { m_gcmpSEIFunctionUAffectedByVFlag = gcmpFunctionUAffectedByVFlag; } + bool getGcmpSEIFunctionUAffectedByVFlag(int idx) const { return m_gcmpSEIFunctionUAffectedByVFlag[idx]; } + void setGcmpSEIFunctionCoeffV(const std::vector<double>& gcmpFunctionCoeffV) { m_gcmpSEIFunctionCoeffV = gcmpFunctionCoeffV; } + double getGcmpSEIFunctionCoeffV(int idx) const { return m_gcmpSEIFunctionCoeffV[idx]; } + void setGcmpSEIFunctionVAffectedByUFlag(const std::vector<bool>& gcmpFunctionVAffectedByUFlag) { m_gcmpSEIFunctionVAffectedByUFlag = gcmpFunctionVAffectedByUFlag; } + bool getGcmpSEIFunctionVAffectedByUFlag(int idx) const { return m_gcmpSEIFunctionVAffectedByUFlag[idx]; } + void setGcmpSEIGuardBandFlag(bool b) { m_gcmpSEIGuardBandFlag = b; } + bool getGcmpSEIGuardBandFlag() { return m_gcmpSEIGuardBandFlag; } + void setGcmpSEIGuardBandBoundaryType(bool b) { m_gcmpSEIGuardBandBoundaryType = b; } + bool getGcmpSEIGuardBandBoundaryType() { return m_gcmpSEIGuardBandBoundaryType; } + void setGcmpSEIGuardBandSamplesMinus1( uint8_t u ) { m_gcmpSEIGuardBandSamplesMinus1 = u; } + uint8_t getGcmpSEIGuardBandSamplesMinus1() { return m_gcmpSEIGuardBandSamplesMinus1; } +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL bool getSubpicureLevelInfoSEIEnabled() const { return m_subpicureLevelInfoSEIEnabled; } void setSubpicureLevelInfoSEIEnabled(bool val) { m_subpicureLevelInfoSEIEnabled = val; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index a631486e03c1cf98bfadbc8dd6b3c4b74029659d..c33a5042eaac498e5d190ce3d2cdc2d5ceee1038 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -806,6 +806,14 @@ void EncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const SPS seiMessages.push_back(seiRegionWisePacking); } #endif +#if JVET_P0597_GCMP_SEI + if (m_pcCfg->getGcmpSEIEnabled()) + { + SEIGeneralizedCubemapProjection *sei = new SEIGeneralizedCubemapProjection; + m_seiEncoder.initSEIGcmp(sei); + seiMessages.push_back(sei); + } +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL if (m_pcCfg->getSubpicureLevelInfoSEIEnabled()) { diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 973f83e18808d5d2fb96c40b4e51bb9a01e8ed06..f88eb966e0134c63e7447315f6aae4ae0698f1d4 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -454,6 +454,52 @@ void SEIEncoder::initSEIRegionWisePacking(SEIRegionWisePacking *seiRegionWisePac } #endif +#if JVET_P0597_GCMP_SEI +void SEIEncoder::initSEIGcmp(SEIGeneralizedCubemapProjection* seiGeneralizedCubemapProjection) +{ + CHECK(!(m_isInitialized), "seiGeneralizedCubemapProjection already initialized"); + CHECK(!(seiGeneralizedCubemapProjection != nullptr), "Need a seiGeneralizedCubemapProjection for initialization (got nullptr)"); + + seiGeneralizedCubemapProjection->m_gcmpCancelFlag = m_pcCfg->getGcmpSEICancelFlag(); + if (!seiGeneralizedCubemapProjection->m_gcmpCancelFlag) + { + seiGeneralizedCubemapProjection->m_gcmpPersistenceFlag = m_pcCfg->getGcmpSEIPersistenceFlag(); + seiGeneralizedCubemapProjection->m_gcmpPackingType = m_pcCfg->getGcmpSEIPackingType(); + seiGeneralizedCubemapProjection->m_gcmpMappingFunctionType = m_pcCfg->getGcmpSEIMappingFunctionType(); + + int numFace = seiGeneralizedCubemapProjection->m_gcmpPackingType == 4 || seiGeneralizedCubemapProjection->m_gcmpPackingType == 5 ? 5 : 6; + seiGeneralizedCubemapProjection->m_gcmpFaceIndex.resize(numFace); + seiGeneralizedCubemapProjection->m_gcmpFaceRotation.resize(numFace); + if (seiGeneralizedCubemapProjection->m_gcmpMappingFunctionType == 2) + { + seiGeneralizedCubemapProjection->m_gcmpFunctionCoeffU.resize(numFace); + seiGeneralizedCubemapProjection->m_gcmpFunctionUAffectedByVFlag.resize(numFace); + seiGeneralizedCubemapProjection->m_gcmpFunctionCoeffV.resize(numFace); + seiGeneralizedCubemapProjection->m_gcmpFunctionVAffectedByUFlag.resize(numFace); + } + for (int i = 0; i < numFace; i++) + { + seiGeneralizedCubemapProjection->m_gcmpFaceIndex[i] = m_pcCfg->getGcmpSEIFaceIndex(i); + seiGeneralizedCubemapProjection->m_gcmpFaceRotation[i] = m_pcCfg->getGcmpSEIFaceRotation(i); + if (seiGeneralizedCubemapProjection->m_gcmpMappingFunctionType == 2) + { + seiGeneralizedCubemapProjection->m_gcmpFunctionCoeffU[i] = std::max<uint8_t>(1, (uint8_t)(128.0 * m_pcCfg->getGcmpSEIFunctionCoeffU(i) + 0.5)) - 1; + seiGeneralizedCubemapProjection->m_gcmpFunctionUAffectedByVFlag[i] = m_pcCfg->getGcmpSEIFunctionUAffectedByVFlag(i); + seiGeneralizedCubemapProjection->m_gcmpFunctionCoeffV[i] = std::max<uint8_t>(1, (uint8_t)(128.0 * m_pcCfg->getGcmpSEIFunctionCoeffV(i) + 0.5)) - 1; + seiGeneralizedCubemapProjection->m_gcmpFunctionVAffectedByUFlag[i] = m_pcCfg->getGcmpSEIFunctionVAffectedByUFlag(i); + } + } + + seiGeneralizedCubemapProjection->m_gcmpGuardBandFlag = m_pcCfg->getGcmpSEIGuardBandFlag(); + if (seiGeneralizedCubemapProjection->m_gcmpGuardBandFlag) + { + seiGeneralizedCubemapProjection->m_gcmpGuardBandBoundaryType = m_pcCfg->getGcmpSEIGuardBandBoundaryType(); + seiGeneralizedCubemapProjection->m_gcmpGuardBandSamplesMinus1 = m_pcCfg->getGcmpSEIGuardBandSamplesMinus1(); + } + } +} +#endif + #if JVET_P0450_SEI_SARI void SEIEncoder::initSEISampleAspectRatioInfo(SEISampleAspectRatioInfo* seiSampleAspectRatioInfo) { diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index b7e283ce89fe024a361fc1848c9873cf970b1cab..f6c29face2728f708c57d2f31b0d45ca578a573f 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -109,6 +109,9 @@ public: void initSEIOmniViewport(SEIOmniViewport *sei); void initSEIRegionWisePacking(SEIRegionWisePacking *sei); #endif +#if JVET_P0597_GCMP_SEI + void initSEIGcmp(SEIGeneralizedCubemapProjection *sei); +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL void initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SPS *sps); #endif diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 5a300a5dd8435d093a383d5ae08ba785489d1de5..bcb5c04e0c6892da91e3be3dd143cf2e7e4fe6d0 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -177,6 +177,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream& bs, const SEI& sei, const xWriteSEIRegionWisePacking(*static_cast<const SEIRegionWisePacking*>(&sei)); break; #endif +#if JVET_P0597_GCMP_SEI + case SEI::GENERALIZED_CUBEMAP_PROJECTION: + xWriteSEIGeneralizedCubemapProjection(*static_cast<const SEIGeneralizedCubemapProjection*>(&sei)); + break; +#endif #if JVET_P0337_PORTING_SEI case SEI::USER_DATA_REGISTERED_ITU_T_T35: xWriteSEIUserDataRegistered(*static_cast<const SEIUserDataRegistered*>(&sei)); @@ -1247,6 +1252,38 @@ void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei) } #endif +#if JVET_P0597_GCMP_SEI +void SEIWriter::xWriteSEIGeneralizedCubemapProjection(const SEIGeneralizedCubemapProjection &sei) +{ + WRITE_FLAG( sei.m_gcmpCancelFlag, "gcmp_cancel_flag" ); + if (!sei.m_gcmpCancelFlag) + { + WRITE_FLAG( sei.m_gcmpPersistenceFlag, "gcmp_persistence_flag" ); + WRITE_CODE( sei.m_gcmpPackingType, 3, "gcmp_packing_type" ); + WRITE_CODE( sei.m_gcmpMappingFunctionType, 2, "gcmp_mapping_function_type" ); + int numFace = sei.m_gcmpPackingType == 4 || sei.m_gcmpPackingType == 5 ? 5 : 6; + for (int i = 0; i < numFace; i++) + { + WRITE_CODE( sei.m_gcmpFaceIndex[i], 3, "gcmp_face_index" ); + WRITE_CODE( sei.m_gcmpFaceRotation[i], 2, "gcmp_face_rotation" ); + if (sei.m_gcmpMappingFunctionType == 2) + { + WRITE_CODE( sei.m_gcmpFunctionCoeffU[i], 7, "gcmp_function_coeff_u" ); + WRITE_FLAG( sei.m_gcmpFunctionUAffectedByVFlag[i], "gcmp_function_u_affected_by_v_flag" ); + WRITE_CODE( sei.m_gcmpFunctionCoeffV[i], 7, "gcmp_function_coeff_v" ); + WRITE_FLAG( sei.m_gcmpFunctionVAffectedByUFlag[i], "gcmp_function_v_affected_by_u_flag" ); + } + } + WRITE_FLAG( sei.m_gcmpGuardBandFlag, "gcmp_guard_band_flag" ); + if (sei.m_gcmpGuardBandFlag) + { + WRITE_FLAG( sei.m_gcmpGuardBandBoundaryType, "gcmp_guard_band_boundary_type" ); + WRITE_CODE( sei.m_gcmpGuardBandSamplesMinus1, 4, "gcmp_guard_band_samples_minus1" ); + } + } +} +#endif + #if JVET_P0984_SEI_SUBPIC_LEVEL void SEIWriter::xWriteSEISubpictureLevelInfo(const SEISubpicureLevelInfo &sei, const SPS* sps) { diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index 960b6198b82c628bbfc1a65274c277a56fd4639f..d15e91754363666d99c965a5f75370368c20bf47 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -107,6 +107,9 @@ protected: void xWriteSEIOmniViewport (const SEIOmniViewport& sei); void xWriteSEIRegionWisePacking (const SEIRegionWisePacking &sei); #endif +#if JVET_P0597_GCMP_SEI + void xWriteSEIGeneralizedCubemapProjection (const SEIGeneralizedCubemapProjection &sei); +#endif #if JVET_P0984_SEI_SUBPIC_LEVEL void xWriteSEISubpictureLevelInfo (const SEISubpicureLevelInfo &sei, const SPS* sps); #endif