/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2020, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ #include "CommonLib/CommonDef.h" #include "CommonLib/SEI.h" #include "EncGOP.h" #include "EncLib.h" uint32_t calcMD5(const CPelUnitBuf& pic, PictureHash &digest, const BitDepths &bitDepths); uint32_t calcCRC(const CPelUnitBuf& pic, PictureHash &digest, const BitDepths &bitDepths); uint32_t calcChecksum(const CPelUnitBuf& pic, PictureHash &digest, const BitDepths &bitDepths); std::string hashToString(const PictureHash &digest, int numChar); //! \ingroup EncoderLib //! \{ void SEIEncoder::initSEIFramePacking(SEIFramePacking *seiFramePacking, int currPicNum) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiFramePacking!=NULL), "Unspecified error"); seiFramePacking->m_arrangementId = m_pcCfg->getFramePackingArrangementSEIId(); seiFramePacking->m_arrangementCancelFlag = 0; seiFramePacking->m_arrangementType = m_pcCfg->getFramePackingArrangementSEIType(); CHECK(!((seiFramePacking->m_arrangementType > 2) && (seiFramePacking->m_arrangementType < 6) ), "Unspecified error"); seiFramePacking->m_quincunxSamplingFlag = m_pcCfg->getFramePackingArrangementSEIQuincunx(); seiFramePacking->m_contentInterpretationType = m_pcCfg->getFramePackingArrangementSEIInterpretation(); seiFramePacking->m_spatialFlippingFlag = 0; seiFramePacking->m_frame0FlippedFlag = 0; seiFramePacking->m_fieldViewsFlag = (seiFramePacking->m_arrangementType == 2); seiFramePacking->m_currentFrameIsFrame0Flag = ((seiFramePacking->m_arrangementType == 5) && (currPicNum&1) ); seiFramePacking->m_frame0SelfContainedFlag = 0; seiFramePacking->m_frame1SelfContainedFlag = 0; seiFramePacking->m_frame0GridPositionX = 0; seiFramePacking->m_frame0GridPositionY = 0; seiFramePacking->m_frame1GridPositionX = 0; seiFramePacking->m_frame1GridPositionY = 0; seiFramePacking->m_arrangementReservedByte = 0; seiFramePacking->m_arrangementPersistenceFlag = true; seiFramePacking->m_upsampledAspectRatio = 0; } void SEIEncoder::initSEIBufferingPeriod(SEIBufferingPeriod *bufferingPeriodSEI, bool noLeadingPictures) { CHECK(!(m_isInitialized), "bufferingPeriodSEI already initialized"); CHECK(!(bufferingPeriodSEI != nullptr), "Need a bufferingPeriodSEI for initialization (got nullptr)"); uint32_t uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec bufferingPeriodSEI->m_bpNalCpbParamsPresentFlag = true; bufferingPeriodSEI->m_bpVclCpbParamsPresentFlag = true; bufferingPeriodSEI->m_bpMaxSubLayers = m_pcCfg->getMaxTempLayer() ; bufferingPeriodSEI->m_bpCpbCnt = 1; for(int i=0; i < bufferingPeriodSEI->m_bpMaxSubLayers; i++) { for(int j=0; j < bufferingPeriodSEI->m_bpCpbCnt; j++) { bufferingPeriodSEI->m_initialCpbRemovalDelay[j][i][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalDelay[j][i][1] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalOffset[j][i][0] = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_initialCpbRemovalOffset[j][i][1] = uiInitialCpbRemovalDelay; } } // We don't set concatenation_flag here. max_initial_removal_delay_for_concatenation depends on the usage scenario. // The parameters could be added to config file, but as long as the initialisation of generic buffering parameters is // not controllable, it does not seem to make sense to provide settings for these. bufferingPeriodSEI->m_concatenationFlag = false; bufferingPeriodSEI->m_maxInitialRemovalDelayForConcatenation = uiInitialCpbRemovalDelay; bufferingPeriodSEI->m_bpDecodingUnitHrdParamsPresentFlag = m_pcCfg->getNoPicPartitionFlag() == false; bufferingPeriodSEI->m_decodingUnitCpbParamsInPicTimingSeiFlag = !m_pcCfg->getDecodingUnitInfoSEIEnabled(); bufferingPeriodSEI->m_initialCpbRemovalDelayLength = 16; // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit // Note: The following parameters require some knowledge about the GOP structure. // Using getIntraPeriod() should be avoided though, because it assumes certain GOP // properties, which are only valid in CTC. // Still copying this setting from HM for consistency, improvements welcome bool isRandomAccess = m_pcCfg->getIntraPeriod() > 0; if( isRandomAccess ) { bufferingPeriodSEI->m_cpbRemovalDelayLength = 6; // 32 = 2^5 (plus 1) bufferingPeriodSEI->m_dpbOutputDelayLength = 6; // 32 + 3 = 2^6 } else { bufferingPeriodSEI->m_cpbRemovalDelayLength = 9; // max. 2^10 bufferingPeriodSEI->m_dpbOutputDelayLength = 9; // max. 2^10 } bufferingPeriodSEI->m_duCpbRemovalDelayIncrementLength = 7; // ceil( log2( tick_divisor_minus2 + 2 ) ) bufferingPeriodSEI->m_dpbOutputDelayDuLength = bufferingPeriodSEI->m_dpbOutputDelayLength + bufferingPeriodSEI->m_duCpbRemovalDelayIncrementLength; //for the concatenation, it can be set to one during splicing. bufferingPeriodSEI->m_concatenationFlag = 0; //since the temporal layer HRDParameters is not ready, we assumed it is fixed bufferingPeriodSEI->m_auCpbRemovalDelayDelta = 1; bufferingPeriodSEI->m_cpbRemovalDelayDeltasPresentFlag = m_pcCfg->getBpDeltasGOPStructure() ; if (bufferingPeriodSEI->m_cpbRemovalDelayDeltasPresentFlag) { switch (m_pcCfg->getGOPSize()) { case 8: { if (noLeadingPictures) { bufferingPeriodSEI->m_numCpbRemovalDelayDeltas = 5; bufferingPeriodSEI->m_cpbRemovalDelayDelta[0] = 1; bufferingPeriodSEI->m_cpbRemovalDelayDelta[1] = 2; bufferingPeriodSEI->m_cpbRemovalDelayDelta[2] = 3; bufferingPeriodSEI->m_cpbRemovalDelayDelta[3] = 6; bufferingPeriodSEI->m_cpbRemovalDelayDelta[4] = 7; } else { bufferingPeriodSEI->m_numCpbRemovalDelayDeltas = 3; bufferingPeriodSEI->m_cpbRemovalDelayDelta[0] = 1; bufferingPeriodSEI->m_cpbRemovalDelayDelta[1] = 2; bufferingPeriodSEI->m_cpbRemovalDelayDelta[2] = 3; } } break; case 16: { if (noLeadingPictures) { bufferingPeriodSEI->m_numCpbRemovalDelayDeltas = 9; bufferingPeriodSEI->m_cpbRemovalDelayDelta[0] = 1; bufferingPeriodSEI->m_cpbRemovalDelayDelta[1] = 2; bufferingPeriodSEI->m_cpbRemovalDelayDelta[2] = 3; bufferingPeriodSEI->m_cpbRemovalDelayDelta[3] = 4; bufferingPeriodSEI->m_cpbRemovalDelayDelta[4] = 6; bufferingPeriodSEI->m_cpbRemovalDelayDelta[5] = 7; bufferingPeriodSEI->m_cpbRemovalDelayDelta[6] = 9; bufferingPeriodSEI->m_cpbRemovalDelayDelta[7] = 14; bufferingPeriodSEI->m_cpbRemovalDelayDelta[8] = 15; } else { bufferingPeriodSEI->m_numCpbRemovalDelayDeltas = 5; bufferingPeriodSEI->m_cpbRemovalDelayDelta[0] = 1; bufferingPeriodSEI->m_cpbRemovalDelayDelta[1] = 2; bufferingPeriodSEI->m_cpbRemovalDelayDelta[2] = 3; bufferingPeriodSEI->m_cpbRemovalDelayDelta[3] = 6; bufferingPeriodSEI->m_cpbRemovalDelayDelta[4] = 7; } } break; default: { THROW("m_cpbRemovalDelayDelta not applicable for the GOP size"); } break; } } // A commercial encoder should track the buffer state for all layers and sub-layers // to ensure CPB conformance. Such tracking is required for calculating alternative // CPB parameters. // Unfortunately VTM does not have such tracking. Thus we cannot encode alternative // CPB parameters here. bufferingPeriodSEI->m_altCpbParamsPresentFlag = false; bufferingPeriodSEI->m_useAltCpbParamsFlag = false; } void SEIEncoder::initSEIErp(SEIEquirectangularProjection* seiEquirectangularProjection) { CHECK(!(m_isInitialized), "seiEquirectangularProjection already initialized"); CHECK(!(seiEquirectangularProjection != nullptr), "Need a seiEquirectangularProjection for initialization (got nullptr)"); seiEquirectangularProjection->m_erpCancelFlag = m_pcCfg->getErpSEICancelFlag(); if (!seiEquirectangularProjection->m_erpCancelFlag) { seiEquirectangularProjection->m_erpPersistenceFlag = m_pcCfg->getErpSEIPersistenceFlag(); seiEquirectangularProjection->m_erpGuardBandFlag = m_pcCfg->getErpSEIGuardBandFlag(); if (seiEquirectangularProjection->m_erpGuardBandFlag == 1) { seiEquirectangularProjection->m_erpGuardBandType = m_pcCfg->getErpSEIGuardBandType(); seiEquirectangularProjection->m_erpLeftGuardBandWidth = m_pcCfg->getErpSEILeftGuardBandWidth(); seiEquirectangularProjection->m_erpRightGuardBandWidth = m_pcCfg->getErpSEIRightGuardBandWidth(); } } } void SEIEncoder::initSEISphereRotation(SEISphereRotation* seiSphereRotation) { CHECK(!(m_isInitialized), "seiSphereRotation already initialized"); CHECK(!(seiSphereRotation != nullptr), "Need a seiSphereRotation for initialization (got nullptr)"); seiSphereRotation->m_sphereRotationCancelFlag = m_pcCfg->getSphereRotationSEICancelFlag(); if ( !seiSphereRotation->m_sphereRotationCancelFlag ) { seiSphereRotation->m_sphereRotationPersistenceFlag = m_pcCfg->getSphereRotationSEIPersistenceFlag(); seiSphereRotation->m_sphereRotationYaw = m_pcCfg->getSphereRotationSEIYaw(); seiSphereRotation->m_sphereRotationPitch = m_pcCfg->getSphereRotationSEIPitch(); seiSphereRotation->m_sphereRotationRoll = m_pcCfg->getSphereRotationSEIRoll(); } } void SEIEncoder::initSEIOmniViewport(SEIOmniViewport* seiOmniViewport) { CHECK(!(m_isInitialized), "seiOmniViewport already initialized"); CHECK(!(seiOmniViewport != nullptr), "Need a seiOmniViewport for initialization (got nullptr)"); seiOmniViewport->m_omniViewportId = m_pcCfg->getOmniViewportSEIId(); seiOmniViewport->m_omniViewportCancelFlag = m_pcCfg->getOmniViewportSEICancelFlag(); if ( !seiOmniViewport->m_omniViewportCancelFlag ) { seiOmniViewport->m_omniViewportPersistenceFlag = m_pcCfg->getOmniViewportSEIPersistenceFlag(); seiOmniViewport->m_omniViewportCntMinus1 = m_pcCfg->getOmniViewportSEICntMinus1(); seiOmniViewport->m_omniViewportRegions.resize(seiOmniViewport->m_omniViewportCntMinus1+1); for (uint32_t i = 0; i <= seiOmniViewport->m_omniViewportCntMinus1; i++) { SEIOmniViewport::OmniViewport &viewport = seiOmniViewport->m_omniViewportRegions[i]; viewport.azimuthCentre = m_pcCfg->getOmniViewportSEIAzimuthCentre(i); viewport.elevationCentre = m_pcCfg->getOmniViewportSEIElevationCentre(i); viewport.tiltCentre = m_pcCfg->getOmniViewportSEITiltCentre(i); viewport.horRange = m_pcCfg->getOmniViewportSEIHorRange(i); viewport.verRange = m_pcCfg->getOmniViewportSEIVerRange(i); } } } void SEIEncoder::initSEIRegionWisePacking(SEIRegionWisePacking *seiRegionWisePacking) { CHECK(!(m_isInitialized), "seiRegionWisePacking already initialized"); CHECK(!(seiRegionWisePacking != nullptr), "Need a seiRegionWisePacking for initialization (got nullptr)"); seiRegionWisePacking->m_rwpCancelFlag = m_pcCfg->getRwpSEIRwpCancelFlag(); seiRegionWisePacking->m_rwpPersistenceFlag = m_pcCfg->getRwpSEIRwpPersistenceFlag(); seiRegionWisePacking->m_constituentPictureMatchingFlag = m_pcCfg->getRwpSEIConstituentPictureMatchingFlag(); seiRegionWisePacking->m_numPackedRegions = m_pcCfg->getRwpSEINumPackedRegions(); seiRegionWisePacking->m_projPictureWidth = m_pcCfg->getRwpSEIProjPictureWidth(); seiRegionWisePacking->m_projPictureHeight = m_pcCfg->getRwpSEIProjPictureHeight(); seiRegionWisePacking->m_packedPictureWidth = m_pcCfg->getRwpSEIPackedPictureWidth(); seiRegionWisePacking->m_packedPictureHeight = m_pcCfg->getRwpSEIPackedPictureHeight(); seiRegionWisePacking->m_rwpTransformType.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpGuardBandFlag.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_projRegionWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_projRegionHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpProjRegionTop.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_projRegionLeft.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionTop.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_packedRegionLeft.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpLeftGuardBandWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpRightGuardBandWidth.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpTopGuardBandHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpBottomGuardBandHeight.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpGuardBandNotUsedForPredFlag.resize(seiRegionWisePacking->m_numPackedRegions); seiRegionWisePacking->m_rwpGuardBandType.resize(4*seiRegionWisePacking->m_numPackedRegions); for( int i=0; i < seiRegionWisePacking->m_numPackedRegions; i++ ) { seiRegionWisePacking->m_rwpTransformType[i] = m_pcCfg->getRwpSEIRwpTransformType(i); seiRegionWisePacking->m_rwpGuardBandFlag[i] = m_pcCfg->getRwpSEIRwpGuardBandFlag(i); seiRegionWisePacking->m_projRegionWidth[i] = m_pcCfg->getRwpSEIProjRegionWidth(i); seiRegionWisePacking->m_projRegionHeight[i] = m_pcCfg->getRwpSEIProjRegionHeight(i); seiRegionWisePacking->m_rwpProjRegionTop[i] = m_pcCfg->getRwpSEIRwpSEIProjRegionTop(i); seiRegionWisePacking->m_projRegionLeft[i] = m_pcCfg->getRwpSEIProjRegionLeft(i); seiRegionWisePacking->m_packedRegionWidth[i] = m_pcCfg->getRwpSEIPackedRegionWidth(i); seiRegionWisePacking->m_packedRegionHeight[i] = m_pcCfg->getRwpSEIPackedRegionHeight(i); seiRegionWisePacking->m_packedRegionTop[i] = m_pcCfg->getRwpSEIPackedRegionTop(i); seiRegionWisePacking->m_packedRegionLeft[i] = m_pcCfg->getRwpSEIPackedRegionLeft(i); if( seiRegionWisePacking->m_rwpGuardBandFlag[i] ) { seiRegionWisePacking->m_rwpLeftGuardBandWidth[i] = m_pcCfg->getRwpSEIRwpLeftGuardBandWidth(i); seiRegionWisePacking->m_rwpRightGuardBandWidth[i] = m_pcCfg->getRwpSEIRwpRightGuardBandWidth(i); seiRegionWisePacking->m_rwpTopGuardBandHeight[i] = m_pcCfg->getRwpSEIRwpTopGuardBandHeight(i); seiRegionWisePacking->m_rwpBottomGuardBandHeight[i] = m_pcCfg->getRwpSEIRwpBottomGuardBandHeight(i); seiRegionWisePacking->m_rwpGuardBandNotUsedForPredFlag[i] = m_pcCfg->getRwpSEIRwpGuardBandNotUsedForPredFlag(i); for( int j=0; j < 4; j++ ) { seiRegionWisePacking->m_rwpGuardBandType[i*4 + j] = m_pcCfg->getRwpSEIRwpGuardBandType(i*4 + j); } } } } 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(); } } } void SEIEncoder::initSEISampleAspectRatioInfo(SEISampleAspectRatioInfo* seiSampleAspectRatioInfo) { CHECK(!(m_isInitialized), "seiSampleAspectRatioInfo already initialized"); CHECK(!(seiSampleAspectRatioInfo != nullptr), "Need a seiSampleAspectRatioInfo for initialization (got nullptr)"); seiSampleAspectRatioInfo->m_sariCancelFlag = m_pcCfg->getSariCancelFlag(); if (!seiSampleAspectRatioInfo->m_sariCancelFlag) { seiSampleAspectRatioInfo->m_sariPersistenceFlag = m_pcCfg->getSariPersistenceFlag(); seiSampleAspectRatioInfo->m_sariAspectRatioIdc = m_pcCfg->getSariAspectRatioIdc(); if (seiSampleAspectRatioInfo->m_sariAspectRatioIdc == 255) { seiSampleAspectRatioInfo->m_sariSarWidth = m_pcCfg->getSariSarWidth(); seiSampleAspectRatioInfo->m_sariSarHeight = m_pcCfg->getSariSarHeight(); } else { seiSampleAspectRatioInfo->m_sariSarWidth = 0; seiSampleAspectRatioInfo->m_sariSarHeight = 0; } } } #if JVET_P0190_SCALABLE_NESTING_SEI //! initialize scalable nesting SEI message. //! Note: The SEI message structures input into this function will become part of the scalable nesting SEI and will be //! automatically freed, when the nesting SEI is disposed. void SEIEncoder::initSEIScalableNesting(SEIScalableNesting *scalableNestingSEI, SEIMessages &nestedSEIs) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(scalableNestingSEI != NULL), "Unspecified error"); scalableNestingSEI->m_nestingOlsFlag = 1; // by If the nested SEI messages are picture buffering SEI messages, picture timing SEI messages or sub-picture timing SEI messages, nesting_ols_flag shall be equal to 1, by default case scalableNestingSEI->m_nestingNumOlssMinus1 = 1; // by default the nesting scalable SEI message applies to two OLSs. for (int i = 0; i <= scalableNestingSEI->m_nestingNumOlssMinus1; i++) { scalableNestingSEI->m_nestingOlsIdxDeltaMinus1[i] = 0; // first ols to which nesting SEI applies is } for (int i = 0; i <= scalableNestingSEI->m_nestingNumOlssMinus1; i++) { if (i == 0) { scalableNestingSEI->m_nestingOlsIdx[i] = scalableNestingSEI->m_nestingOlsIdxDeltaMinus1[i]; } else { scalableNestingSEI->m_nestingOlsIdx[i] = scalableNestingSEI->m_nestingOlsIdxDeltaMinus1[i] + scalableNestingSEI->m_nestingOlsIdxDeltaMinus1[i - 1] + 1; } } scalableNestingSEI->m_nestingAllLayersFlag = 1; // nesting is not applied to all layers scalableNestingSEI->m_nestingNumLayersMinus1 = 2 - 1; //nesting_num_layers_minus1 scalableNestingSEI->m_nestingLayerId[0] = 0; scalableNestingSEI->m_nestedSEIs.clear(); for (SEIMessages::iterator it = nestedSEIs.begin(); it != nestedSEIs.end(); it++) { scalableNestingSEI->m_nestedSEIs.push_back((*it)); } } #endif //! calculate hashes for entire reconstructed picture void SEIEncoder::initDecodedPictureHashSEI(SEIDecodedPictureHash *decodedPictureHashSEI, PelUnitBuf& pic, std::string &rHashString, const BitDepths &bitDepths) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(decodedPictureHashSEI!=NULL), "Unspecified error"); decodedPictureHashSEI->method = m_pcCfg->getDecodedPictureHashSEIType(); switch (m_pcCfg->getDecodedPictureHashSEIType()) { case HASHTYPE_MD5: { uint32_t numChar=calcMD5(pic, decodedPictureHashSEI->m_pictureHash, bitDepths); rHashString = hashToString(decodedPictureHashSEI->m_pictureHash, numChar); } break; case HASHTYPE_CRC: { uint32_t numChar=calcCRC(pic, decodedPictureHashSEI->m_pictureHash, bitDepths); rHashString = hashToString(decodedPictureHashSEI->m_pictureHash, numChar); } break; case HASHTYPE_CHECKSUM: default: { uint32_t numChar=calcChecksum(pic, decodedPictureHashSEI->m_pictureHash, bitDepths); rHashString = hashToString(decodedPictureHashSEI->m_pictureHash, numChar); } break; } } void SEIEncoder::initSEIDependentRAPIndication(SEIDependentRAPIndication *seiDependentRAPIndication) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiDependentRAPIndication!=NULL), "Unspecified error"); } template <typename T> static void readTokenValue(T &returnedValue, /// value returned bool &failed, /// used and updated std::istream &is, /// stream to read token from const char *pToken) /// token string { returnedValue=T(); if (failed) { return; } int c; // Ignore any whitespace while ((c=is.get())!=EOF && isspace(c)); // test for comment mark while (c=='#') { // Ignore to the end of the line while ((c=is.get())!=EOF && (c!=10 && c!=13)); // Ignore any white space at the start of the next line while ((c=is.get())!=EOF && isspace(c)); } // test first character of token failed=(c!=pToken[0]); // test remaining characters of token int pos; for(pos=1;!failed && pToken[pos]!=0 && is.get()==pToken[pos]; pos++); failed|=(pToken[pos]!=0); // Ignore any whitespace before the ':' while (!failed && (c=is.get())!=EOF && isspace(c)); failed|=(c!=':'); // Now read the value associated with the token: if (!failed) { is >> returnedValue; failed=!is.good(); if (!failed) { c=is.get(); failed=(c!=EOF && !isspace(c)); } } if (failed) { std::cerr << "Unable to read token '" << pToken << "'\n"; } } template <typename T> static void readTokenValueAndValidate(T &returnedValue, /// value returned bool &failed, /// used and updated std::istream &is, /// stream to read token from const char *pToken, /// token string const T &minInclusive, /// minimum value allowed, inclusive const T &maxInclusive) /// maximum value allowed, inclusive { readTokenValue(returnedValue, failed, is, pToken); if (!failed) { if (returnedValue<minInclusive || returnedValue>maxInclusive) { failed=true; std::cerr << "Value for token " << pToken << " must be in the range " << minInclusive << " to " << maxInclusive << " (inclusive); value read: " << returnedValue << std::endl; } } } #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI void SEIEncoder::initSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics *seiAltTransCharacteristics) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiAltTransCharacteristics!=NULL), "Unspecified error"); // Set SEI message parameters read from command line options seiAltTransCharacteristics->m_preferredTransferCharacteristics = m_pcCfg->getSEIPreferredTransferCharacteristics(); } #endif void SEIEncoder::initSEIFilmGrainCharacteristics(SEIFilmGrainCharacteristics *seiFilmGrain) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiFilmGrain != NULL), "Unspecified error"); // Set SEI message parameters read from command line options seiFilmGrain->m_filmGrainCharacteristicsCancelFlag = m_pcCfg->getFilmGrainCharactersticsSEICancelFlag(); seiFilmGrain->m_filmGrainCharacteristicsPersistenceFlag = m_pcCfg->getFilmGrainCharactersticsSEIPersistenceFlag(); seiFilmGrain->m_filmGrainModelId = m_pcCfg->getFilmGrainCharactersticsSEIModelID(); seiFilmGrain->m_separateColourDescriptionPresentFlag = m_pcCfg->getFilmGrainCharactersticsSEISepColourDescPresent(); seiFilmGrain->m_blendingModeId = m_pcCfg->getFilmGrainCharactersticsSEIBlendingModeID(); seiFilmGrain->m_log2ScaleFactor = m_pcCfg->getFilmGrainCharactersticsSEILog2ScaleFactor(); for (int i = 0; i < MAX_NUM_COMPONENT; i++) { seiFilmGrain->m_compModel[i].presentFlag = m_pcCfg->getFGCSEICompModelPresent(i); } } void SEIEncoder::initSEIMasteringDisplayColourVolume(SEIMasteringDisplayColourVolume *seiMDCV) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiMDCV != NULL), "Unspecified error"); // Set SEI message parameters read from command line options for (int j = 0; j <= 1; j++) { for (int i = 0; i <= 2; i++) { seiMDCV->values.primaries[i][j] = m_pcCfg->getMasteringDisplaySEI().primaries[i][j]; } seiMDCV->values.whitePoint[j] = m_pcCfg->getMasteringDisplaySEI().whitePoint[j]; } seiMDCV->values.maxLuminance = m_pcCfg->getMasteringDisplaySEI().maxLuminance; seiMDCV->values.minLuminance = m_pcCfg->getMasteringDisplaySEI().minLuminance; } void SEIEncoder::initSEIContentLightLevel(SEIContentLightLevelInfo *seiCLL) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiCLL != NULL), "Unspecified error"); // Set SEI message parameters read from command line options seiCLL->m_maxContentLightLevel = m_pcCfg->getCLLSEIMaxContentLightLevel(); seiCLL->m_maxPicAverageLightLevel = m_pcCfg->getCLLSEIMaxPicAvgLightLevel(); } void SEIEncoder::initSEIAmbientViewingEnvironment(SEIAmbientViewingEnvironment *seiAmbViewEnvironment) { CHECK(!(m_isInitialized), "Unspecified error"); CHECK(!(seiAmbViewEnvironment != NULL), "Unspecified error"); // Set SEI message parameters read from command line options seiAmbViewEnvironment->m_ambientIlluminance = m_pcCfg->getAmbientViewingEnvironmentSEIIlluminance(); seiAmbViewEnvironment->m_ambientLightX = m_pcCfg->getAmbientViewingEnvironmentSEIAmbientLightX(); seiAmbViewEnvironment->m_ambientLightY = m_pcCfg->getAmbientViewingEnvironmentSEIAmbientLightY(); } void SEIEncoder::initSEIContentColourVolume(SEIContentColourVolume *seiContentColourVolume) { assert(m_isInitialized); assert(seiContentColourVolume != NULL); seiContentColourVolume->m_ccvCancelFlag = m_pcCfg->getCcvSEICancelFlag(); seiContentColourVolume->m_ccvPersistenceFlag = m_pcCfg->getCcvSEIPersistenceFlag(); seiContentColourVolume->m_ccvPrimariesPresentFlag = m_pcCfg->getCcvSEIPrimariesPresentFlag(); seiContentColourVolume->m_ccvMinLuminanceValuePresentFlag = m_pcCfg->getCcvSEIMinLuminanceValuePresentFlag(); seiContentColourVolume->m_ccvMaxLuminanceValuePresentFlag = m_pcCfg->getCcvSEIMaxLuminanceValuePresentFlag(); seiContentColourVolume->m_ccvAvgLuminanceValuePresentFlag = m_pcCfg->getCcvSEIAvgLuminanceValuePresentFlag(); // Currently we are using a floor operation for setting up the "integer" values for this SEI. // This applies to both primaries and luminance limits. if (seiContentColourVolume->m_ccvPrimariesPresentFlag == true) { for (int i = 0; i < MAX_NUM_COMPONENT; i++) { seiContentColourVolume->m_ccvPrimariesX[i] = (int32_t)(50000.0 * m_pcCfg->getCcvSEIPrimariesX(i)); seiContentColourVolume->m_ccvPrimariesY[i] = (int32_t)(50000.0 * m_pcCfg->getCcvSEIPrimariesY(i)); } } if (seiContentColourVolume->m_ccvMinLuminanceValuePresentFlag == true) { seiContentColourVolume->m_ccvMinLuminanceValue = (uint32_t)(10000000 * m_pcCfg->getCcvSEIMinLuminanceValue()); } if (seiContentColourVolume->m_ccvMaxLuminanceValuePresentFlag == true) { seiContentColourVolume->m_ccvMaxLuminanceValue = (uint32_t)(10000000 * m_pcCfg->getCcvSEIMaxLuminanceValue()); } if (seiContentColourVolume->m_ccvAvgLuminanceValuePresentFlag == true) { seiContentColourVolume->m_ccvAvgLuminanceValue = (uint32_t)(10000000 * m_pcCfg->getCcvSEIAvgLuminanceValue()); } } void SEIEncoder::initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SPS *sps) { // subpicture level information should be specified via config file // unfortunately the implementation of subpictures is still not available // TODO: implement config file parameters and intialization fprintf(stderr, "SEISubpicureLevelInfo depends on subpictures! Initializing to dummy values!\n"); sei->m_sliSeqParameterSetId = sps->getSPSId(); sei->m_numRefLevels = 2; sei->m_refLevelIdc.resize(2); sei->m_refLevelIdc[0] = Level::LEVEL4; sei->m_refLevelIdc[1] = Level::LEVEL8_5; sei->m_explicitFractionPresentFlag = false; } //! \}