Commit 9197d647 authored by Frank Bossen's avatar Frank Bossen

Merge branch 'JVET-S0257-SwSupportOf360SEI' into 'master'

JVET-S0257: SW Support of dumping 360 SEI messages to config files

See merge request jvet/VVCSoftware_VTM!1731
parents 8fa2289b 7e2b096e
......@@ -371,6 +371,12 @@ void DecApp::xCreateDecLib()
std::ostream &os=m_seiMessageFileStream.is_open() ? m_seiMessageFileStream : std::cout;
m_cDecLib.setDecodedSEIMessageOutputStream(&os);
}
#if JVET_S0257_DUMP_360SEI_MESSAGE
if (!m_outputDecoded360SEIMessagesFilename.empty())
{
m_cDecLib.setDecoded360SEIMessageFileName(m_outputDecoded360SEIMessagesFilename);
}
#endif
m_cDecLib.m_targetSubPicIdx = this->m_targetSubPicIdx;
m_cDecLib.initScalingList();
}
......
......@@ -97,6 +97,9 @@ bool DecAppCfg::parseCfg( int argc, char* argv[] )
("TarDecLayerIdSetFile,l", cfg_TargetDecLayerIdSetFile, string(""), "targetDecLayerIdSet file name. The file should include white space separated LayerId values to be decoded. Omitting the option or a value of -1 in the file decodes all layers.")
("SEIColourRemappingInfoFilename", m_colourRemapSEIFileName, string(""), "Colour Remapping YUV output file name. If empty, no remapping is applied (ignore SEI message)\n")
("OutputDecodedSEIMessagesFilename", m_outputDecodedSEIMessagesFilename, string(""), "When non empty, output decoded SEI messages to the indicated file. If file is '-', then output to stdout\n")
#if JVET_S0257_DUMP_360SEI_MESSAGE
("360DumpFile", m_outputDecoded360SEIMessagesFilename, string(""), "When non empty, output decoded 360 SEI messages to the indicated file.\n")
#endif
("ClipOutputVideoToRec709Range", m_bClipOutputVideoToRec709Range, false, "If true then clip output video to the Rec. 709 Range on saving")
("PYUV", m_packedYUVMode, false, "If true then output 10-bit and 12-bit YUV data as 5-byte and 3-byte (respectively) packed YUV data. Ignored for interlaced output.")
#if ENABLE_TRACING
......@@ -235,6 +238,9 @@ DecAppCfg::DecAppCfg()
, m_colourRemapSEIFileName()
, m_targetDecLayerIdSet()
, m_outputDecodedSEIMessagesFilename()
#if JVET_S0257_DUMP_360SEI_MESSAGE
, m_outputDecoded360SEIMessagesFilename()
#endif
, m_bClipOutputVideoToRec709Range(false)
, m_packedYUVMode(false)
, m_statMode(0)
......
......@@ -72,6 +72,9 @@ protected:
std::string m_colourRemapSEIFileName; ///< output Colour Remapping file name
std::vector<int> m_targetDecLayerIdSet; ///< set of LayerIds to be included in the sub-bitstream extraction process.
std::string m_outputDecodedSEIMessagesFilename; ///< filename to output decoded SEI messages to. If '-', then use stdout. If empty, do not output details.
#if JVET_S0257_DUMP_360SEI_MESSAGE
std::string m_outputDecoded360SEIMessagesFilename; ///< filename to output decoded 360 SEI messages to.
#endif
bool m_bClipOutputVideoToRec709Range; ///< If true, clip the output video to the Rec 709 range on saving.
......
......@@ -50,7 +50,6 @@
#include <assert.h>
#include <cassert>
//########### place macros to be removed in next cycle below this line ###############
#define JVET_S0074_SPS_REORDER 1 // JVET-S0074: aspect 1, rearrange some syntax elements in SPS
......@@ -60,6 +59,8 @@
//########### place macros to be be kept below this line ###############
#define JVET_S0257_DUMP_360SEI_MESSAGE 1 // Software support of 360 SEI messages
#define JVET_R0351_HIGH_BIT_DEPTH_SUPPORT 1 // JVET-R0351: high bit depth coding support (syntax changes, no mathematical differences for CTCs)
#define JVET_R0351_HIGH_BIT_DEPTH_ENABLED 0 // JVET-R0351: high bit depth coding enabled (increases accuracies of some calculations, e.g. transforms)
......
......@@ -436,6 +436,9 @@ DecLib::DecLib()
, m_sliceLmcsApsId(-1)
, m_pDecodedSEIOutputStream(NULL)
, m_audIrapOrGdrAuFlag( false )
#if JVET_S0257_DUMP_360SEI_MESSAGE
, m_decoded360SeiDumpFileName()
#endif
, m_decodedPictureHashSEIEnabled(false)
, m_numberOfChecksumErrorsDetected(0)
, m_warningMessageSkipPicture(false)
......@@ -1780,6 +1783,9 @@ void DecLib::xParsePrefixSEImessages()
const SPS *sps = m_parameterSetManager.getActiveSPS();
const VPS *vps = m_parameterSetManager.getVPS(sps->getVPSId());
m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_SEIs, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream );
#if JVET_S0257_DUMP_360SEI_MESSAGE
m_seiCfgDump.write360SeiDump( m_decoded360SeiDumpFileName, m_SEIs, sps );
#endif
m_accessUnitSeiPayLoadTypes.push_back(std::tuple<NalUnitType, int, SEI::PayloadType>(nalu.m_nalUnitType, nalu.m_nuhLayerId, m_SEIs.back()->payloadType()));
delete m_prefixSEINALUs.front();
m_prefixSEINALUs.pop_front();
......@@ -2693,6 +2699,9 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay, i
const SPS *sps = m_parameterSetManager.getActiveSPS();
const VPS *vps = m_parameterSetManager.getVPS(sps->getVPSId());
m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_pcPic->SEIs, nalu.m_nalUnitType, nalu.m_nuhLayerId, nalu.m_temporalId, vps, sps, m_HRD, m_pDecodedSEIOutputStream );
#if JVET_S0257_DUMP_360SEI_MESSAGE
m_seiCfgDump.write360SeiDump(m_decoded360SeiDumpFileName, m_pcPic->SEIs, sps);
#endif
m_accessUnitSeiPayLoadTypes.push_back(std::tuple<NalUnitType, int, SEI::PayloadType>(nalu.m_nalUnitType, nalu.m_nuhLayerId, m_pcPic->SEIs.back()->payloadType()));
}
else
......
......@@ -105,6 +105,9 @@ private:
HLSyntaxReader m_HLSReader;
CABACDecoder m_CABACDecoder;
SEIReader m_seiReader;
#if JVET_S0257_DUMP_360SEI_MESSAGE
SeiCfgFileDump m_seiCfgDump;
#endif
LoopFilter m_cLoopFilter;
SampleAdaptiveOffset m_cSAO;
AdaptiveLoopFilter m_cALF;
......@@ -135,6 +138,9 @@ private:
int m_sliceLmcsApsId; //value of LmcsApsId, constraint is same id for all slices in one picture
std::ostream *m_pDecodedSEIOutputStream;
uint32_t m_audIrapOrGdrAuFlag;
#if JVET_S0257_DUMP_360SEI_MESSAGE
std::string m_decoded360SeiDumpFileName;
#endif
int m_decodedPictureHashSEIEnabled; ///< Checksum(3)/CRC(2)/MD5(1)/disable(0) acting on decoded picture hash SEI message
uint32_t m_numberOfChecksumErrorsDetected;
......@@ -222,6 +228,9 @@ public:
bool getFirstSliceInSequence(int layerId) const { return m_firstSliceInSequence[layerId]; }
void setFirstSliceInSequence(bool val, int layerId) { m_firstSliceInSequence[layerId] = val; }
void setDecodedSEIMessageOutputStream(std::ostream *pOpStream) { m_pDecodedSEIOutputStream = pOpStream; }
#if JVET_S0257_DUMP_360SEI_MESSAGE
void setDecoded360SEIMessageFileName(std::string &Dump360SeiFileName) { m_decoded360SeiDumpFileName = Dump360SeiFileName; }
#endif
uint32_t getNumberOfChecksumErrorsDetected() const { return m_numberOfChecksumErrorsDetected; }
int getDebugCTU( ) const { return m_debugCTU; }
......
......@@ -1390,6 +1390,146 @@ void SEIReader::xParseSEISampleAspectRatioInfo(SEISampleAspectRatioInfo& sei, ui
}
}
#if JVET_S0257_DUMP_360SEI_MESSAGE
void SeiCfgFileDump::write360SeiDump (std::string decoded360MessageFileName, SEIMessages& seis, const SPS* sps)
{
if (m_360SEIMessageDumped)
{
return;
}
SEIMessages equirectangularProjectionSEIs = getSeisByType(seis, SEI::EQUIRECTANGULAR_PROJECTION);
if (!equirectangularProjectionSEIs.empty())
{
SEIEquirectangularProjection* sei = (SEIEquirectangularProjection*)equirectangularProjectionSEIs.front();
xDumpSEIEquirectangularProjection(*sei, sps, decoded360MessageFileName);
m_360SEIMessageDumped = true;
}
else
{
SEIMessages generalizedCubemapProjectionSEIs = getSeisByType(seis, SEI::GENERALIZED_CUBEMAP_PROJECTION);
if (!generalizedCubemapProjectionSEIs.empty())
{
SEIGeneralizedCubemapProjection* sei = (SEIGeneralizedCubemapProjection*)generalizedCubemapProjectionSEIs.front();
xDumpSEIGeneralizedCubemapProjection(*sei, sps, decoded360MessageFileName);
m_360SEIMessageDumped = true;
}
}
}
void SeiCfgFileDump::xDumpSEIEquirectangularProjection (SEIEquirectangularProjection &sei, const SPS* sps, std::string decoded360MessageFileName)
{
if (!decoded360MessageFileName.empty())
{
FILE *fp = fopen(decoded360MessageFileName.c_str(), "w");
if (fp)
{
int chromaFormatTable[4] = {400, 420, 422, 444};
fprintf(fp, "InputBitDepth : %d # Input bitdepth\n", sps->getBitDepth(CHANNEL_TYPE_LUMA));
fprintf(fp, "InputChromaFormat : %d # Ratio of luminance to chrominance samples\n", chromaFormatTable[sps->getChromaFormatIdc()]);
fprintf(fp, "SourceWidth : %d # Input frame width\n", sps->getMaxPicWidthInLumaSamples());
fprintf(fp, "SourceHeight : %d # Input frame height\n\n", sps->getMaxPicHeightInLumaSamples());
fprintf(fp, "InputGeometryType : 0 # 0: equirectangular; 1: cubemap; 2: equalarea; this should be in the cfg of per sequence.\n");
if (sei.m_erpGuardBandFlag == 1)
{
fprintf(fp, "InputPERP : 1 # 0: original ERP input; 1: padded ERP input\n");
fprintf(fp, "CodingPERP : 0 # 0: coding with original ERP size; 1: coding with padded ERP\n");
}
fclose(fp);
m_360SEIMessageDumped = true;
}
else
{
msg( ERROR, "File %s could not be opened.\n", decoded360MessageFileName.c_str() );
}
}
}
void SeiCfgFileDump::xDumpSEIGeneralizedCubemapProjection (SEIGeneralizedCubemapProjection &sei, const SPS* sps, std::string decoded360MessageFileName)
{
if (!sei.m_gcmpCancelFlag)
{
int numFace = sei.m_gcmpPackingType == 4 || sei.m_gcmpPackingType == 5 ? 5 : 6;
int packingTypeTable[6][2] = {{6, 1}, {3, 2}, {2, 3}, {1, 6}, {1, 5}, {5, 1}};
int rotationTable[4] = {0, 90, 180, 270};
std::string packingTypeStr = "";
std::string gcmpsettingsStr = "";
std::ostringstream oss;
packingTypeStr += "SourceFPStructure : " + std::to_string(packingTypeTable[sei.m_gcmpPackingType][0]) + " " + std::to_string(packingTypeTable[sei.m_gcmpPackingType][1]);
gcmpsettingsStr += "InputGCMPSettings : ";
for (int i = 0; i < numFace; i++)
{
int rotation = rotationTable[sei.m_gcmpFaceRotation[i]];
if (sei.m_gcmpFaceIndex[i] == 1)
{
rotation = (rotation + 270) % 360 + 360;
}
else if (sei.m_gcmpFaceIndex[i] == 2)
{
rotation = (rotation + 180) % 360 + 360;
}
else
{
rotation += 360;
}
if (i % packingTypeTable[sei.m_gcmpPackingType][1] == 0)
{
packingTypeStr += " ";
}
packingTypeStr += std::to_string(sei.m_gcmpFaceIndex[i]) + " " + std::to_string(rotation) + " ";
if (sei.m_gcmpMappingFunctionType == 2)
{
double a = ((int)sei.m_gcmpFunctionCoeffU[i] + 1) / 128.0;
double b = ((int)sei.m_gcmpFunctionCoeffV[i] + 1) / 128.0;
oss.str("");
oss<<a;
std::string a_str = oss.str();
oss.str("");
oss<<b;
std::string b_str = oss.str();
gcmpsettingsStr += a_str + " " + std::to_string(sei.m_gcmpFunctionUAffectedByVFlag[i]) + " " + b_str + " " + std::to_string(sei.m_gcmpFunctionVAffectedByUFlag[i]) + " ";
}
}
if (!decoded360MessageFileName.empty())
{
FILE *fp = fopen(decoded360MessageFileName.c_str(), "w");
if (fp)
{
int chromaFormatTable[4] = {400, 420, 422, 444};
fprintf(fp, "InputBitDepth : %d # Input bitdepth\n", sps->getBitDepth(CHANNEL_TYPE_LUMA));
fprintf(fp, "InputChromaFormat : %d # Ratio of luminance to chrominance samples\n", chromaFormatTable[sps->getChromaFormatIdc()]);
fprintf(fp, "SourceWidth : %d # Input frame width\n", sps->getMaxPicWidthInLumaSamples());
fprintf(fp, "SourceHeight : %d # Input frame height\n\n", sps->getMaxPicHeightInLumaSamples());
fprintf(fp, "InputGeometryType : 15 # 0: equirectangular; 1: cubemap; 2: equalarea; this should be in the cfg of per sequence.\n");
packingTypeStr += " # frame packing order: numRows numCols Row0Idx0 ROT Row0Idx1 ROT ... Row1...";
gcmpsettingsStr += " # mapping function parameters for each face: u coefficient, u affected by v flag, v coefficient, v affected by u flag";
fprintf(fp, "%s\n", packingTypeStr.c_str());
fprintf(fp, "InputGCMPMappingType : %d # 0: CMP; 1: EAC; 2: parameterized CMP\n", (int)sei.m_gcmpMappingFunctionType);
if ((int)sei.m_gcmpMappingFunctionType == 2)
fprintf(fp, "%s\n", gcmpsettingsStr.c_str());
fprintf(fp, "InputGCMPPaddingFlag : %d # 0: input without guard bands; 1: input with guard bands\n", sei.m_gcmpGuardBandFlag);
if (sei.m_gcmpGuardBandFlag)
{
fprintf(fp, "InputGCMPPaddingType : %d # 0: unspecified(repetitive padding is used); 1: repetitive padding; 2: copy from neighboring face; 3: geometry padding\n", (int)sei.m_gcmpGuardBandType);
fprintf(fp, "InputGCMPPaddingExteriorFlag : %d # 0: guard bands only on discontinuous edges; 1: guard bands on both discontinuous edges and frame boundaries\n", sei.m_gcmpGuardBandBoundaryExteriorFlag);
fprintf(fp, "InputGCMPPaddingSize : %d # guard band size for input GCMP\n", (int)sei.m_gcmpGuardBandSamplesMinus1 + 1);
}
fclose(fp);
m_360SEIMessageDumped = true;
}
else
{
msg( ERROR, "File %s could not be opened.\n", decoded360MessageFileName.c_str() );
}
}
}
}
#endif
//! \}
......@@ -96,6 +96,27 @@ protected:
HRD m_nestedHrd;
};
#if JVET_S0257_DUMP_360SEI_MESSAGE
class SeiCfgFileDump
{
public:
SeiCfgFileDump()
: m_360SEIMessageDumped(false)
{};
virtual ~SeiCfgFileDump() {};
void write360SeiDump (std::string decoded360MessageFileName, SEIMessages& seis, const SPS* sps);
protected:
void xDumpSEIEquirectangularProjection (SEIEquirectangularProjection &sei, const SPS* sps, std::string decoded360MessageFileName);
void xDumpSEIGeneralizedCubemapProjection (SEIGeneralizedCubemapProjection &sei, const SPS* sps, std::string decoded360MessageFileName);
bool m_360SEIMessageDumped;
};
#endif
//! \}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment