/* 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-2015, 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. */ /** \file TEncGOP.cpp \brief GOP encoder class */ #include #include #include #include "TEncTop.h" #include "TEncGOP.h" #include "TEncAnalyze.h" #include "libmd5/MD5.h" #include "TLibCommon/SEI.h" #include "TLibCommon/NAL.h" #include "NALwrite.h" #include #include #if SVC_EXTENSION #include #endif using namespace std; #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST Bool g_bFinalEncode = false; #endif //! \ingroup TLibEncoder //! \{ // ==================================================================================================================== // Constructor / destructor / initialization / destroy // ==================================================================================================================== Int getLSB(Int poc, Int maxLSB) { if (poc >= 0) { return poc % maxLSB; } else { return (maxLSB - ((-poc) % maxLSB)) % maxLSB; } } TEncGOP::TEncGOP() { m_iLastIDR = 0; m_iGopSize = 0; m_iNumPicCoded = 0; //Niko m_bFirst = true; #if ALLOW_RECOVERY_POINT_AS_RAP m_iLastRecoveryPicPOC = 0; #endif m_pcCfg = NULL; m_pcSliceEncoder = NULL; m_pcListPic = NULL; m_pcEntropyCoder = NULL; m_pcCavlcCoder = NULL; m_pcSbacCoder = NULL; m_pcBinCABAC = NULL; m_bSeqFirst = true; m_bRefreshPending = 0; m_pocCRA = 0; m_numLongTermRefPicSPS = 0; ::memset(m_ltRefPicPocLsbSps, 0, sizeof(m_ltRefPicPocLsbSps)); ::memset(m_ltRefPicUsedByCurrPicFlag, 0, sizeof(m_ltRefPicUsedByCurrPicFlag)); m_cpbRemovalDelay = 0; m_lastBPSEI = 0; xResetNonNestedSEIPresentFlags(); xResetNestedSEIPresentFlags(); m_associatedIRAPType = NAL_UNIT_CODED_SLICE_IDR_N_LP; m_associatedIRAPPOC = 0; #if SVC_EXTENSION m_pocCraWithoutReset = 0; m_associatedIrapPocBeforeReset = 0; m_pcPredSearch = NULL; #if CGS_3D_ASYMLUT m_temp = NULL; m_pColorMappedPic = NULL; #endif m_lastPocPeriodId = -1; m_noRaslOutputFlag = false; m_prevPicHasEos = false; #endif //SVC_EXTENSION #if Q0074_COLOUR_REMAPPING_SEI for( Int c=0 ; c<3 ; c++) { m_colourRemapSEIPreLutCodedValue[c] = NULL; m_colourRemapSEIPreLutTargetValue[c] = NULL; m_colourRemapSEIPostLutCodedValue[c] = NULL; m_colourRemapSEIPostLutTargetValue[c] = NULL; } #endif return; } TEncGOP::~TEncGOP() { #if CGS_3D_ASYMLUT if(m_pColorMappedPic) { m_pColorMappedPic->destroy(); delete m_pColorMappedPic; m_pColorMappedPic = NULL; } if(m_temp) { free_mem2DintWithPad(m_temp, m_iTap>>1, 0); m_temp = NULL; } #endif } /** Create list to contain pointers to CTU start addresses of slice. */ #if SVC_EXTENSION Void TEncGOP::create( UInt layerId ) { m_bLongtermTestPictureHasBeenCoded = 0; m_bLongtermTestPictureHasBeenCoded2 = 0; m_layerId = layerId; } #else Void TEncGOP::create() { m_bLongtermTestPictureHasBeenCoded = 0; m_bLongtermTestPictureHasBeenCoded2 = 0; } #endif Void TEncGOP::destroy() { } Void TEncGOP::init ( TEncTop* pcTEncTop ) { m_pcEncTop = pcTEncTop; m_pcCfg = pcTEncTop; m_pcSliceEncoder = pcTEncTop->getSliceEncoder(); m_pcListPic = pcTEncTop->getListPic(); m_pcEntropyCoder = pcTEncTop->getEntropyCoder(); m_pcCavlcCoder = pcTEncTop->getCavlcCoder(); m_pcSbacCoder = pcTEncTop->getSbacCoder(); m_pcBinCABAC = pcTEncTop->getBinCABAC(); m_pcLoopFilter = pcTEncTop->getLoopFilter(); m_pcSAO = pcTEncTop->getSAO(); m_pcRateCtrl = pcTEncTop->getRateCtrl(); m_lastBPSEI = 0; m_totalCoded = 0; #if SVC_EXTENSION m_ppcTEncTop = pcTEncTop->getLayerEnc(); m_pcPredSearch = pcTEncTop->getPredSearch(); ///< encoder search class #if CGS_3D_ASYMLUT if( pcTEncTop->getLayerId() ) { UInt prevLayerIdx = 0; UInt prevLayerId = 0; if (pcTEncTop->getNumActiveRefLayers() > 0) { prevLayerIdx = pcTEncTop->getPredLayerIdx( pcTEncTop->getNumActiveRefLayers() - 1); prevLayerId = pcTEncTop->getRefLayerId(prevLayerIdx); } m_Enc3DAsymLUTPicUpdate.create( m_pcCfg->getCGSMaxOctantDepth() , g_bitDepthLayer[CHANNEL_TYPE_LUMA][prevLayerId] , g_bitDepthLayer[CHANNEL_TYPE_CHROMA][prevLayerId] , g_bitDepthLayer[CHANNEL_TYPE_LUMA][pcTEncTop->getLayerId()] , g_bitDepthLayer[CHANNEL_TYPE_CHROMA][pcTEncTop->getLayerId()] , m_pcCfg->getCGSMaxYPartNumLog2() /*, m_pcCfg->getCGSPhaseAlignment()*/ ); m_Enc3DAsymLUTPPS.create( m_pcCfg->getCGSMaxOctantDepth() , g_bitDepthLayer[CHANNEL_TYPE_LUMA][prevLayerId] , g_bitDepthLayer[CHANNEL_TYPE_CHROMA][prevLayerId] , g_bitDepthLayer[CHANNEL_TYPE_LUMA][pcTEncTop->getLayerId()] , g_bitDepthLayer[CHANNEL_TYPE_CHROMA][pcTEncTop->getLayerId()] , m_pcCfg->getCGSMaxYPartNumLog2() /*, m_pcCfg->getCGSPhaseAlignment()*/ ); if(!m_pColorMappedPic) { m_pColorMappedPic = new TComPicYuv; m_pColorMappedPic->create( m_ppcTEncTop[0]->getSourceWidth(), m_ppcTEncTop[0]->getSourceHeight(), m_ppcTEncTop[0]->getChromaFormatIDC(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, NULL ); } } #endif #endif //SVC_EXTENSION } SEIActiveParameterSets* TEncGOP::xCreateSEIActiveParameterSets (const TComSPS *sps) { SEIActiveParameterSets *seiActiveParameterSets = new SEIActiveParameterSets(); seiActiveParameterSets->activeVPSId = m_pcCfg->getVPS()->getVPSId(); seiActiveParameterSets->m_selfContainedCvsFlag = false; seiActiveParameterSets->m_noParameterSetUpdateFlag = false; #if R0247_SEI_ACTIVE seiActiveParameterSets->numSpsIdsMinus1 = m_pcCfg->getNumLayer()-1; seiActiveParameterSets->activeSeqParameterSetId.resize(seiActiveParameterSets->numSpsIdsMinus1 + 1); seiActiveParameterSets->layerSpsIdx.resize(seiActiveParameterSets->numSpsIdsMinus1+ 1); for (Int c=0; c <= seiActiveParameterSets->numSpsIdsMinus1; c++) { seiActiveParameterSets->activeSeqParameterSetId[c] = c; } for (Int c=1; c <= seiActiveParameterSets->numSpsIdsMinus1; c++) { seiActiveParameterSets->layerSpsIdx[c] = c; } #else seiActiveParameterSets->numSpsIdsMinus1 = 0; seiActiveParameterSets->activeSeqParameterSetId.resize(seiActiveParameterSets->numSpsIdsMinus1 + 1); seiActiveParameterSets->activeSeqParameterSetId[0] = sps->getSPSId(); #endif return seiActiveParameterSets; } SEIFramePacking* TEncGOP::xCreateSEIFramePacking() { SEIFramePacking *seiFramePacking = new SEIFramePacking(); seiFramePacking->m_arrangementId = m_pcCfg->getFramePackingArrangementSEIId(); seiFramePacking->m_arrangementCancelFlag = 0; seiFramePacking->m_arrangementType = m_pcCfg->getFramePackingArrangementSEIType(); assert((seiFramePacking->m_arrangementType > 2) && (seiFramePacking->m_arrangementType < 6) ); 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) && (m_iNumPicCoded&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; return seiFramePacking; } SEISegmentedRectFramePacking* TEncGOP::xCreateSEISegmentedRectFramePacking() { SEISegmentedRectFramePacking *seiSegmentedRectFramePacking = new SEISegmentedRectFramePacking(); seiSegmentedRectFramePacking->m_arrangementCancelFlag = m_pcCfg->getSegmentedRectFramePackingArrangementSEICancel(); seiSegmentedRectFramePacking->m_contentInterpretationType = m_pcCfg->getSegmentedRectFramePackingArrangementSEIType(); seiSegmentedRectFramePacking->m_arrangementPersistenceFlag = m_pcCfg->getSegmentedRectFramePackingArrangementSEIPersistence(); return seiSegmentedRectFramePacking; } SEIDisplayOrientation* TEncGOP::xCreateSEIDisplayOrientation() { SEIDisplayOrientation *seiDisplayOrientation = new SEIDisplayOrientation(); seiDisplayOrientation->cancelFlag = false; seiDisplayOrientation->horFlip = false; seiDisplayOrientation->verFlip = false; seiDisplayOrientation->anticlockwiseRotation = m_pcCfg->getDisplayOrientationSEIAngle(); return seiDisplayOrientation; } SEIToneMappingInfo* TEncGOP::xCreateSEIToneMappingInfo() { SEIToneMappingInfo *seiToneMappingInfo = new SEIToneMappingInfo(); seiToneMappingInfo->m_toneMapId = m_pcCfg->getTMISEIToneMapId(); seiToneMappingInfo->m_toneMapCancelFlag = m_pcCfg->getTMISEIToneMapCancelFlag(); seiToneMappingInfo->m_toneMapPersistenceFlag = m_pcCfg->getTMISEIToneMapPersistenceFlag(); seiToneMappingInfo->m_codedDataBitDepth = m_pcCfg->getTMISEICodedDataBitDepth(); assert(seiToneMappingInfo->m_codedDataBitDepth >= 8 && seiToneMappingInfo->m_codedDataBitDepth <= 14); seiToneMappingInfo->m_targetBitDepth = m_pcCfg->getTMISEITargetBitDepth(); assert(seiToneMappingInfo->m_targetBitDepth >= 1 && seiToneMappingInfo->m_targetBitDepth <= 17); seiToneMappingInfo->m_modelId = m_pcCfg->getTMISEIModelID(); assert(seiToneMappingInfo->m_modelId >=0 &&seiToneMappingInfo->m_modelId<=4); switch( seiToneMappingInfo->m_modelId) { case 0: { seiToneMappingInfo->m_minValue = m_pcCfg->getTMISEIMinValue(); seiToneMappingInfo->m_maxValue = m_pcCfg->getTMISEIMaxValue(); break; } case 1: { seiToneMappingInfo->m_sigmoidMidpoint = m_pcCfg->getTMISEISigmoidMidpoint(); seiToneMappingInfo->m_sigmoidWidth = m_pcCfg->getTMISEISigmoidWidth(); break; } case 2: { UInt num = 1u<<(seiToneMappingInfo->m_targetBitDepth); seiToneMappingInfo->m_startOfCodedInterval.resize(num); Int* ptmp = m_pcCfg->getTMISEIStartOfCodedInterva(); if(ptmp) { for(Int i=0; im_startOfCodedInterval[i] = ptmp[i]; } } break; } case 3: { seiToneMappingInfo->m_numPivots = m_pcCfg->getTMISEINumPivots(); seiToneMappingInfo->m_codedPivotValue.resize(seiToneMappingInfo->m_numPivots); seiToneMappingInfo->m_targetPivotValue.resize(seiToneMappingInfo->m_numPivots); Int* ptmpcoded = m_pcCfg->getTMISEICodedPivotValue(); Int* ptmptarget = m_pcCfg->getTMISEITargetPivotValue(); if(ptmpcoded&&ptmptarget) { for(Int i=0; i<(seiToneMappingInfo->m_numPivots);i++) { seiToneMappingInfo->m_codedPivotValue[i]=ptmpcoded[i]; seiToneMappingInfo->m_targetPivotValue[i]=ptmptarget[i]; } } break; } case 4: { seiToneMappingInfo->m_cameraIsoSpeedIdc = m_pcCfg->getTMISEICameraIsoSpeedIdc(); seiToneMappingInfo->m_cameraIsoSpeedValue = m_pcCfg->getTMISEICameraIsoSpeedValue(); assert( seiToneMappingInfo->m_cameraIsoSpeedValue !=0 ); seiToneMappingInfo->m_exposureIndexIdc = m_pcCfg->getTMISEIExposurIndexIdc(); seiToneMappingInfo->m_exposureIndexValue = m_pcCfg->getTMISEIExposurIndexValue(); assert( seiToneMappingInfo->m_exposureIndexValue !=0 ); seiToneMappingInfo->m_exposureCompensationValueSignFlag = m_pcCfg->getTMISEIExposureCompensationValueSignFlag(); seiToneMappingInfo->m_exposureCompensationValueNumerator = m_pcCfg->getTMISEIExposureCompensationValueNumerator(); seiToneMappingInfo->m_exposureCompensationValueDenomIdc = m_pcCfg->getTMISEIExposureCompensationValueDenomIdc(); seiToneMappingInfo->m_refScreenLuminanceWhite = m_pcCfg->getTMISEIRefScreenLuminanceWhite(); seiToneMappingInfo->m_extendedRangeWhiteLevel = m_pcCfg->getTMISEIExtendedRangeWhiteLevel(); assert( seiToneMappingInfo->m_extendedRangeWhiteLevel >= 100 ); seiToneMappingInfo->m_nominalBlackLevelLumaCodeValue = m_pcCfg->getTMISEINominalBlackLevelLumaCodeValue(); seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue = m_pcCfg->getTMISEINominalWhiteLevelLumaCodeValue(); assert( seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue > seiToneMappingInfo->m_nominalBlackLevelLumaCodeValue ); seiToneMappingInfo->m_extendedWhiteLevelLumaCodeValue = m_pcCfg->getTMISEIExtendedWhiteLevelLumaCodeValue(); assert( seiToneMappingInfo->m_extendedWhiteLevelLumaCodeValue >= seiToneMappingInfo->m_nominalWhiteLevelLumaCodeValue ); break; } default: { assert(!"Undefined SEIToneMapModelId"); break; } } return seiToneMappingInfo; } SEITempMotionConstrainedTileSets* TEncGOP::xCreateSEITempMotionConstrainedTileSets (const TComPPS *pps) { SEITempMotionConstrainedTileSets *sei = new SEITempMotionConstrainedTileSets(); if(pps->getTilesEnabledFlag()) { sei->m_mc_all_tiles_exact_sample_value_match_flag = false; sei->m_each_tile_one_tile_set_flag = false; sei->m_limited_tile_set_display_flag = false; sei->setNumberOfTileSets((pps->getNumTileColumnsMinus1() + 1) * (pps->getNumTileRowsMinus1() + 1)); for(Int i=0; i < sei->getNumberOfTileSets(); i++) { sei->tileSetData(i).m_mcts_id = i; //depends the application; sei->tileSetData(i).setNumberOfTileRects(1); for(Int j=0; jtileSetData(i).getNumberOfTileRects(); j++) { sei->tileSetData(i).topLeftTileIndex(j) = i+j; sei->tileSetData(i).bottomRightTileIndex(j) = i+j; } sei->tileSetData(i).m_exact_sample_value_match_flag = false; sei->tileSetData(i).m_mcts_tier_level_idc_present_flag = false; } } else { assert(!"Tile is not enabled"); } return sei; } SEIKneeFunctionInfo* TEncGOP::xCreateSEIKneeFunctionInfo() { SEIKneeFunctionInfo *seiKneeFunctionInfo = new SEIKneeFunctionInfo(); seiKneeFunctionInfo->m_kneeId = m_pcCfg->getKneeSEIId(); seiKneeFunctionInfo->m_kneeCancelFlag = m_pcCfg->getKneeSEICancelFlag(); if ( !seiKneeFunctionInfo->m_kneeCancelFlag ) { seiKneeFunctionInfo->m_kneePersistenceFlag = m_pcCfg->getKneeSEIPersistenceFlag(); seiKneeFunctionInfo->m_kneeInputDrange = m_pcCfg->getKneeSEIInputDrange(); seiKneeFunctionInfo->m_kneeInputDispLuminance = m_pcCfg->getKneeSEIInputDispLuminance(); seiKneeFunctionInfo->m_kneeOutputDrange = m_pcCfg->getKneeSEIOutputDrange(); seiKneeFunctionInfo->m_kneeOutputDispLuminance = m_pcCfg->getKneeSEIOutputDispLuminance(); seiKneeFunctionInfo->m_kneeNumKneePointsMinus1 = m_pcCfg->getKneeSEINumKneePointsMinus1(); Int* piInputKneePoint = m_pcCfg->getKneeSEIInputKneePoint(); Int* piOutputKneePoint = m_pcCfg->getKneeSEIOutputKneePoint(); if(piInputKneePoint&&piOutputKneePoint) { seiKneeFunctionInfo->m_kneeInputKneePoint.resize(seiKneeFunctionInfo->m_kneeNumKneePointsMinus1+1); seiKneeFunctionInfo->m_kneeOutputKneePoint.resize(seiKneeFunctionInfo->m_kneeNumKneePointsMinus1+1); for(Int i=0; i<=seiKneeFunctionInfo->m_kneeNumKneePointsMinus1; i++) { seiKneeFunctionInfo->m_kneeInputKneePoint[i] = piInputKneePoint[i]; seiKneeFunctionInfo->m_kneeOutputKneePoint[i] = piOutputKneePoint[i]; } } } return seiKneeFunctionInfo; } SEIChromaSamplingFilterHint* TEncGOP::xCreateSEIChromaSamplingFilterHint(Bool bChromaLocInfoPresent, Int iHorFilterIndex, Int iVerFilterIndex) { SEIChromaSamplingFilterHint *seiChromaSamplingFilterHint = new SEIChromaSamplingFilterHint(); seiChromaSamplingFilterHint->m_verChromaFilterIdc = iVerFilterIndex; seiChromaSamplingFilterHint->m_horChromaFilterIdc = iHorFilterIndex; seiChromaSamplingFilterHint->m_verFilteringProcessFlag = 1; seiChromaSamplingFilterHint->m_targetFormatIdc = 3; seiChromaSamplingFilterHint->m_perfectReconstructionFlag = false; if(seiChromaSamplingFilterHint->m_verChromaFilterIdc == 1) { seiChromaSamplingFilterHint->m_numVerticalFilters = 1; seiChromaSamplingFilterHint->m_verTapLengthMinus1 = (Int*)malloc(seiChromaSamplingFilterHint->m_numVerticalFilters * sizeof(Int)); seiChromaSamplingFilterHint->m_verFilterCoeff = (Int**)malloc(seiChromaSamplingFilterHint->m_numVerticalFilters * sizeof(Int*)); for(Int i = 0; i < seiChromaSamplingFilterHint->m_numVerticalFilters; i ++) { seiChromaSamplingFilterHint->m_verTapLengthMinus1[i] = 0; seiChromaSamplingFilterHint->m_verFilterCoeff[i] = (Int*)malloc(seiChromaSamplingFilterHint->m_verTapLengthMinus1[i] * sizeof(Int)); for(Int j = 0; j < seiChromaSamplingFilterHint->m_verTapLengthMinus1[i]; j ++) { seiChromaSamplingFilterHint->m_verFilterCoeff[i][j] = 0; } } } else { seiChromaSamplingFilterHint->m_numVerticalFilters = 0; seiChromaSamplingFilterHint->m_verTapLengthMinus1 = NULL; seiChromaSamplingFilterHint->m_verFilterCoeff = NULL; } if(seiChromaSamplingFilterHint->m_horChromaFilterIdc == 1) { seiChromaSamplingFilterHint->m_numHorizontalFilters = 1; seiChromaSamplingFilterHint->m_horTapLengthMinus1 = (Int*)malloc(seiChromaSamplingFilterHint->m_numHorizontalFilters * sizeof(Int)); seiChromaSamplingFilterHint->m_horFilterCoeff = (Int**)malloc(seiChromaSamplingFilterHint->m_numHorizontalFilters * sizeof(Int*)); for(Int i = 0; i < seiChromaSamplingFilterHint->m_numHorizontalFilters; i ++) { seiChromaSamplingFilterHint->m_horTapLengthMinus1[i] = 0; seiChromaSamplingFilterHint->m_horFilterCoeff[i] = (Int*)malloc(seiChromaSamplingFilterHint->m_horTapLengthMinus1[i] * sizeof(Int)); for(Int j = 0; j < seiChromaSamplingFilterHint->m_horTapLengthMinus1[i]; j ++) { seiChromaSamplingFilterHint->m_horFilterCoeff[i][j] = 0; } } } else { seiChromaSamplingFilterHint->m_numHorizontalFilters = 0; seiChromaSamplingFilterHint->m_horTapLengthMinus1 = NULL; seiChromaSamplingFilterHint->m_horFilterCoeff = NULL; } return seiChromaSamplingFilterHint; } Void TEncGOP::xCreateLeadingSEIMessages (/*SEIMessages seiMessages,*/ AccessUnit &accessUnit, const TComSPS *sps, const TComPPS *pps) { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); if(m_pcCfg->getActiveParameterSetsSEIEnabled() #if R0247_SEI_ACTIVE && m_layerId == 0 #endif ) { SEIActiveParameterSets *sei = xCreateSEIActiveParameterSets (sps); //nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; m_activeParameterSetSEIPresentInAU = true; } if(m_pcCfg->getFramePackingArrangementSEIEnabled()) { SEIFramePacking *sei = xCreateSEIFramePacking (); nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } if(m_pcCfg->getSegmentedRectFramePackingArrangementSEIEnabled()) { SEISegmentedRectFramePacking *sei = xCreateSEISegmentedRectFramePacking (); nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } if (m_pcCfg->getDisplayOrientationSEIAngle()) { SEIDisplayOrientation *sei = xCreateSEIDisplayOrientation(); nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } if(m_pcCfg->getToneMappingInfoSEIEnabled()) { SEIToneMappingInfo *sei = xCreateSEIToneMappingInfo (); nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } if(m_pcCfg->getTMCTSSEIEnabled()) { SEITempMotionConstrainedTileSets *sei_tmcts = xCreateSEITempMotionConstrainedTileSets (pps); nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei_tmcts, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei_tmcts, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei_tmcts; } if(m_pcCfg->getTimeCodeSEIEnabled()) { SEITimeCode sei_time_code; // Set data as per command line options sei_time_code.numClockTs = m_pcCfg->getNumberOfTimesets(); for(Int i = 0; i < sei_time_code.numClockTs; i++) { sei_time_code.timeSetArray[i] = m_pcCfg->getTimeSet(i); } nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_time_code, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_time_code, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } if(m_pcCfg->getKneeSEIEnabled()) { SEIKneeFunctionInfo *sei = xCreateSEIKneeFunctionInfo(); nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } if(m_pcCfg->getMasteringDisplaySEI().colourVolumeSEIEnabled) { const TComSEIMasteringDisplay &seiCfg=m_pcCfg->getMasteringDisplaySEI(); SEIMasteringDisplayColourVolume mdcv; mdcv.values = seiCfg; nalu = NALUnit(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, mdcv, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, mdcv, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } #if SVC_EXTENSION #if LAYERS_NOT_PRESENT_SEI if(m_pcCfg->getLayersNotPresentSEIEnabled()) { SEILayersNotPresent *sei = xCreateSEILayersNotPresent (); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } #endif #if N0383_IL_CONSTRAINED_TILE_SETS_SEI if(m_pcCfg->getInterLayerConstrainedTileSetsSEIEnabled()) { SEIInterLayerConstrainedTileSets *sei = xCreateSEIInterLayerConstrainedTileSets (); nalu = NALUnit(NAL_UNIT_PREFIX_SEI, 0, m_pcCfg->getNumLayer()-1); // For highest layer m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } #endif #if P0123_ALPHA_CHANNEL_SEI if( m_pcCfg->getAlphaSEIEnabled() && m_pcEncTop->getVPS()->getScalabilityId(m_layerId, AUX_ID) && m_pcEncTop->getVPS()->getDimensionId(m_pcEncTop->getVPS()->getLayerIdxInVps(m_layerId), m_pcEncTop->getVPS()->getNumScalabilityTypes() - 1) == AUX_ALPHA ) { SEIAlphaChannelInfo *sei = xCreateSEIAlphaChannelInfo(); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } #endif #if Q0096_OVERLAY_SEI if(m_pcCfg->getOverlaySEIEnabled()) { SEIOverlayInfo *sei = xCreateSEIOverlayInfo(); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), sps); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, sps); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } #endif #endif //SVC_EXTENSION } #if Q0074_COLOUR_REMAPPING_SEI Void TEncGOP::freeColourCRI() { for( Int c=0 ; c<3 ; c++) { if ( m_colourRemapSEIPreLutCodedValue[c] != NULL) { delete[] m_colourRemapSEIPreLutCodedValue[c]; m_colourRemapSEIPreLutCodedValue[c] = NULL; } if ( m_colourRemapSEIPreLutTargetValue[c] != NULL) { delete[] m_colourRemapSEIPreLutTargetValue[c]; m_colourRemapSEIPreLutTargetValue[c] = NULL; } if ( m_colourRemapSEIPostLutCodedValue[c] != NULL) { delete[] m_colourRemapSEIPostLutCodedValue[c]; m_colourRemapSEIPostLutCodedValue[c] = NULL; } if ( m_colourRemapSEIPostLutTargetValue[c] != NULL) { delete[] m_colourRemapSEIPostLutTargetValue[c]; m_colourRemapSEIPostLutTargetValue[c] = NULL; } } } Int TEncGOP::readingCRIparameters(){ // reading external Colour Remapping Information SEI message parameters from file if( m_colourRemapSEIFile.c_str() ) { FILE* fic; Int retval; if((fic = fopen(m_colourRemapSEIFile.c_str(),"r")) == (FILE*)NULL) { //fprintf(stderr, "Can't open Colour Remapping Information SEI parameters file %s\n", m_colourRemapSEIFile.c_str()); //exit(EXIT_FAILURE); return (-1); } Int tempCode; retval = fscanf( fic, "%d", &m_colourRemapSEIId ); retval = fscanf( fic, "%d", &tempCode );m_colourRemapSEICancelFlag = tempCode ? 1 : 0; if( !m_colourRemapSEICancelFlag ) { retval = fscanf( fic, "%d", &tempCode ); m_colourRemapSEIPersistenceFlag= tempCode ? 1 : 0; retval = fscanf( fic, "%d", &tempCode); m_colourRemapSEIVideoSignalInfoPresentFlag = tempCode ? 1 : 0; if( m_colourRemapSEIVideoSignalInfoPresentFlag ) { retval = fscanf( fic, "%d", &tempCode ); m_colourRemapSEIFullRangeFlag = tempCode ? 1 : 0; retval = fscanf( fic, "%d", &m_colourRemapSEIPrimaries ); retval = fscanf( fic, "%d", &m_colourRemapSEITransferFunction ); retval = fscanf( fic, "%d", &m_colourRemapSEIMatrixCoefficients ); } retval = fscanf( fic, "%d", &m_colourRemapSEIInputBitDepth ); retval = fscanf( fic, "%d", &m_colourRemapSEIBitDepth ); for( Int c=0 ; c<3 ; c++ ) { retval = fscanf( fic, "%d", &m_colourRemapSEIPreLutNumValMinus1[c] ); if( m_colourRemapSEIPreLutNumValMinus1[c]>0 ) { m_colourRemapSEIPreLutCodedValue[c] = new Int[m_colourRemapSEIPreLutNumValMinus1[c]+1]; m_colourRemapSEIPreLutTargetValue[c] = new Int[m_colourRemapSEIPreLutNumValMinus1[c]+1]; for( Int i=0 ; i<=m_colourRemapSEIPreLutNumValMinus1[c] ; i++ ) { retval = fscanf( fic, "%d", &m_colourRemapSEIPreLutCodedValue[c][i] ); retval = fscanf( fic, "%d", &m_colourRemapSEIPreLutTargetValue[c][i] ); } } } retval = fscanf( fic, "%d", &tempCode ); m_colourRemapSEIMatrixPresentFlag = tempCode ? 1 : 0; if( m_colourRemapSEIMatrixPresentFlag ) { retval = fscanf( fic, "%d", &m_colourRemapSEILog2MatrixDenom ); for( Int c=0 ; c<3 ; c++ ) for( Int i=0 ; i<3 ; i++ ) retval = fscanf( fic, "%d", &m_colourRemapSEICoeffs[c][i] ); } for( Int c=0 ; c<3 ; c++ ) { retval = fscanf( fic, "%d", &m_colourRemapSEIPostLutNumValMinus1[c] ); if( m_colourRemapSEIPostLutNumValMinus1[c]>0 ) { m_colourRemapSEIPostLutCodedValue[c] = new Int[m_colourRemapSEIPostLutNumValMinus1[c]+1]; m_colourRemapSEIPostLutTargetValue[c] = new Int[m_colourRemapSEIPostLutNumValMinus1[c]+1]; for( Int i=0 ; i<=m_colourRemapSEIPostLutNumValMinus1[c] ; i++ ) { retval = fscanf( fic, "%d", &m_colourRemapSEIPostLutCodedValue[c][i] ); retval = fscanf( fic, "%d", &m_colourRemapSEIPostLutTargetValue[c][i] ); } } } } fclose( fic ); if( retval != 1 ) { fprintf(stderr, "Error while reading Colour Remapping Information SEI parameters file\n"); exit(EXIT_FAILURE); } } return 1; } Bool confirmParameter(Bool bflag, const Char* message); // ==================================================================================================================== // Private member functions // ==================================================================================================================== Void TEncGOP::xCheckParameter() { Bool check_failed = false; /* abort if there is a fatal configuration problem */ #define xConfirmParameter(a,b) check_failed |= confirmParameter(a,b) if ( m_colourRemapSEIFile.c_str() && !m_colourRemapSEICancelFlag ) { xConfirmParameter( m_colourRemapSEIInputBitDepth < 8 || m_colourRemapSEIInputBitDepth > 16 , "colour_remap_coded_data_bit_depth shall be in the range of 8 to 16, inclusive"); xConfirmParameter( m_colourRemapSEIBitDepth < 8 || (m_colourRemapSEIBitDepth > 16 && m_colourRemapSEIBitDepth < 255) , "colour_remap_target_bit_depth shall be in the range of 8 to 16, inclusive"); for( Int c=0 ; c<3 ; c++) { xConfirmParameter( m_colourRemapSEIPreLutNumValMinus1[c] < 0 || m_colourRemapSEIPreLutNumValMinus1[c] > 32, "pre_lut_num_val_minus1[c] shall be in the range of 0 to 32, inclusive"); if( m_colourRemapSEIPreLutNumValMinus1[c]>0 ) for( Int i=0 ; i<=m_colourRemapSEIPreLutNumValMinus1[c] ; i++) { xConfirmParameter( m_colourRemapSEIPreLutCodedValue[c][i] < 0 || m_colourRemapSEIPreLutCodedValue[c][i] > ((1< ((1< 32, "post_lut_num_val_minus1[c] shall be in the range of 0 to 32, inclusive"); if( m_colourRemapSEIPostLutNumValMinus1[c]>0 ) for( Int i=0 ; i<=m_colourRemapSEIPostLutNumValMinus1[c] ; i++) { xConfirmParameter( m_colourRemapSEIPostLutCodedValue[c][i] < 0 || m_colourRemapSEIPostLutCodedValue[c][i] > ((1< ((1< 15, "log2_matrix_denom shall be in the range of 0 to 15, inclusive"); for( Int c=0 ; c<3 ; c++) for( Int i=0 ; i<3 ; i++) xConfirmParameter( m_colourRemapSEICoeffs[c][i] < -32768 || m_colourRemapSEICoeffs[c][i] > 32767, "colour_remap_coeffs[c][i] shall be in the range of -32768 and 32767, inclusive"); } } } #endif // ==================================================================================================================== // Public member functions // ==================================================================================================================== #if SVC_EXTENSION Void TEncGOP::compressGOP( Int iPicIdInGOP, Int iPOCLast, Int iNumPicRcvd, TComList& rcListPic, TComList& rcListPicYuvRecOut, std::list& accessUnitsInGOP, Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE ) #else Void TEncGOP::compressGOP( Int iPOCLast, Int iNumPicRcvd, TComList& rcListPic, TComList& rcListPicYuvRecOut, std::list& accessUnitsInGOP, Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE ) #endif { // TODO: Split this function up. TComPic* pcPic = NULL; TComPicYuv* pcPicYuvRecOut; TComSlice* pcSlice; TComOutputBitstream *pcBitstreamRedirect; pcBitstreamRedirect = new TComOutputBitstream; AccessUnit::iterator itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted xInitGOP( iPOCLast, iNumPicRcvd, rcListPic, rcListPicYuvRecOut, isField ); m_iNumPicCoded = 0; SEIPictureTiming pictureTimingSEI; Bool writeSOP = m_pcCfg->getSOPDescriptionSEIEnabled(); // Initialize Scalable Nesting SEI with single layer values SEIScalableNesting scalableNestingSEI; scalableNestingSEI.m_bitStreamSubsetFlag = 1; // If the nested SEI messages are picture buffereing SEI mesages, picure timing SEI messages or sub-picture timing SEI messages, bitstream_subset_flag shall be equal to 1 scalableNestingSEI.m_nestingOpFlag = 0; scalableNestingSEI.m_nestingNumOpsMinus1 = 0; //nesting_num_ops_minus1 scalableNestingSEI.m_allLayersFlag = 0; scalableNestingSEI.m_nestingNoOpMaxTemporalIdPlus1 = 6 + 1; //nesting_no_op_max_temporal_id_plus1 scalableNestingSEI.m_nestingNumLayersMinus1 = 1 - 1; //nesting_num_layers_minus1 scalableNestingSEI.m_nestingLayerId[0] = 0; scalableNestingSEI.m_callerOwnsSEIs = true; Int picSptDpbOutputDuDelay = 0; UInt *accumBitsDU = NULL; UInt *accumNalsDU = NULL; SEIDecodingUnitInfo decodingUnitInfoSEI; #if EFFICIENT_FIELD_IRAP Int IRAPGOPid = -1; Bool IRAPtoReorder = false; Bool swapIRAPForward = false; if(isField) { Int pocCurr; #if SVC_EXTENSION for ( Int iGOPid=iPicIdInGOP; iGOPid < iPicIdInGOP+1; iGOPid++ ) #else for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ ) #endif { // determine actual POC if(iPOCLast == 0) //case first frame or first top field { pocCurr=0; } else if(iPOCLast == 1 && isField) //case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value { pocCurr = 1; } else { pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC - isField; } // check if POC corresponds to IRAP NalUnitType tmpUnitType = getNalUnitType(pocCurr, m_iLastIDR, isField); if(tmpUnitType >= NAL_UNIT_CODED_SLICE_BLA_W_LP && tmpUnitType <= NAL_UNIT_CODED_SLICE_CRA) // if picture is an IRAP { if(pocCurr%2 == 0 && iGOPid < m_iGopSize-1 && m_pcCfg->getGOPEntry(iGOPid).m_POC == m_pcCfg->getGOPEntry(iGOPid+1).m_POC-1) { // if top field and following picture in enc order is associated bottom field IRAPGOPid = iGOPid; IRAPtoReorder = true; swapIRAPForward = true; break; } if(pocCurr%2 != 0 && iGOPid > 0 && m_pcCfg->getGOPEntry(iGOPid).m_POC == m_pcCfg->getGOPEntry(iGOPid-1).m_POC+1) { // if picture is an IRAP remember to process it first IRAPGOPid = iGOPid; IRAPtoReorder = true; swapIRAPForward = false; break; } } } } #endif // reset flag indicating whether pictures have been encoded for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ ) { m_pcCfg->setEncodedFlag(iGOPid, false); } #if SVC_EXTENSION for ( Int iGOPid=iPicIdInGOP; iGOPid < iPicIdInGOP+1; iGOPid++ ) #else for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ ) #endif { #if EFFICIENT_FIELD_IRAP if(IRAPtoReorder) { if(swapIRAPForward) { if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid +1; } else if(iGOPid == IRAPGOPid +1) { iGOPid = IRAPGOPid; } } else { if(iGOPid == IRAPGOPid -1) { iGOPid = IRAPGOPid; } else if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid -1; } } } #endif UInt uiColDir = 1; //-- For time output for each slice clock_t iBeforeTime = clock(); //select uiColDir Int iCloseLeft=1, iCloseRight=-1; for(Int i = 0; igetGOPEntry(iGOPid).m_numRefPics; i++) { Int iRef = m_pcCfg->getGOPEntry(iGOPid).m_referencePics[i]; if(iRef>0&&(iRefiCloseLeft||iCloseLeft==1)) { iCloseLeft=iRef; } } if(iCloseRight>-1) { iCloseRight=iCloseRight+m_pcCfg->getGOPEntry(iGOPid).m_POC-1; } if(iCloseLeft<1) { iCloseLeft=iCloseLeft+m_pcCfg->getGOPEntry(iGOPid).m_POC-1; while(iCloseLeft<0) { iCloseLeft+=m_iGopSize; } } Int iLeftQP=0, iRightQP=0; for(Int i=0; igetGOPEntry(i).m_POC==(iCloseLeft%m_iGopSize)+1) { iLeftQP= m_pcCfg->getGOPEntry(i).m_QPOffset; } if (m_pcCfg->getGOPEntry(i).m_POC==(iCloseRight%m_iGopSize)+1) { iRightQP=m_pcCfg->getGOPEntry(i).m_QPOffset; } } if(iCloseRight>-1&&iRightQPgetGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1:0); iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC; } if(pocCurr>=m_pcCfg->getFramesToBeEncoded()) { #if EFFICIENT_FIELD_IRAP if(IRAPtoReorder) { if(swapIRAPForward) { if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid +1; IRAPtoReorder = false; } else if(iGOPid == IRAPGOPid +1) { iGOPid --; } } else { if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid -1; } else if(iGOPid == IRAPGOPid -1) { iGOPid = IRAPGOPid; IRAPtoReorder = false; } } } #endif continue; } #if SVC_EXTENSION if (m_pcEncTop->getAdaptiveResolutionChange() > 0 && ((m_layerId > 0 && pocCurr < m_pcEncTop->getAdaptiveResolutionChange()) || (m_layerId == 0 && pocCurr > m_pcEncTop->getAdaptiveResolutionChange())) ) { continue; } if (pocCurr > m_pcEncTop->getLayerSwitchOffBegin() && pocCurr < m_pcEncTop->getLayerSwitchOffEnd()) { continue; } #endif if( getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_N_LP ) { m_iLastIDR = pocCurr; } // start a new access unit: create an entry in the list of output access units accessUnitsInGOP.push_back(AccessUnit()); AccessUnit& accessUnit = accessUnitsInGOP.back(); xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pcPicYuvRecOut, pocCurr, isField ); // Slice data initialization pcPic->clearSliceBuffer(); pcPic->allocateNewSlice(); m_pcSliceEncoder->setSliceIdx(0); pcPic->setCurrSliceIdx(0); #if SVC_EXTENSION pcPic->setLayerId( m_layerId ); m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iNumPicRcvd, iGOPid, pcSlice, isField ); #else m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iNumPicRcvd, iGOPid, pcSlice, &(pcPic->getPicSym()->getSPS()), &(pcPic->getPicSym()->getPPS()), isField ); #endif //Set Frame/Field coding pcSlice->getPic()->setField(isField); #if SVC_EXTENSION #if SVC_POC pcSlice->setPocValueBeforeReset( pocCurr ); // Check if the current picture is to be assigned as a reset picture determinePocResetIdc(pocCurr, pcSlice); Bool pocResettingFlag = false; if( pcSlice->getPocResetIdc() != 0 ) { if( pcSlice->getVPS()->getVpsPocLsbAlignedFlag() ) { pocResettingFlag = true; } else if( m_pcEncTop->getPocDecrementedInDPBFlag() ) { pocResettingFlag = false; } else { pocResettingFlag = true; } } // If reset, do the following steps: if( pocResettingFlag ) { updatePocValuesOfPics(pocCurr, pcSlice); } else { // Check the base layer picture is IDR. If so, just set current POC equal to 0 (alignment of POC) if( ( m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshType() == 2) && ( pocCurr % m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshInterval() == 0 ) ) { m_pcEncTop->setPocAdjustmentValue( pocCurr ); } // Just subtract POC by the current cumulative POC delta pcSlice->setPOC( pocCurr - m_pcEncTop->getPocAdjustmentValue() ); Int maxPocLsb = 1 << pcSlice->getSPS()->getBitsForPOC(); pcSlice->setPocMsbVal( pcSlice->getPOC() - ( pcSlice->getPOC() & (maxPocLsb-1) ) ); } // Update the POC of current picture, pictures in the DPB, including references inside the reference pictures #endif if( m_layerId == 0 && (getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_iLastIDR, isField) == NAL_UNIT_CODED_SLICE_IDR_N_LP) ) { pcSlice->setCrossLayerBLAFlag(m_pcEncTop->getCrossLayerBLAFlag()); } else { pcSlice->setCrossLayerBLAFlag(false); } // Set the nal unit type pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField)); #if NO_CLRAS_OUTPUT_FLAG if (m_layerId == 0 && (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)) { if (m_bFirst) { m_pcEncTop->setNoClrasOutputFlag(true); } else if (m_prevPicHasEos) { m_pcEncTop->setNoClrasOutputFlag(true); } else if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP) { m_pcEncTop->setNoClrasOutputFlag(true); } else if( pcSlice->getCrossLayerBLAFlag() && ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) ) { m_pcEncTop->setNoClrasOutputFlag(true); } else { m_pcEncTop->setNoClrasOutputFlag(false); } if( m_pcEncTop->getNoClrasOutputFlag() ) { for (UInt i = 0; i < m_pcCfg->getNumLayer(); i++) { m_ppcTEncTop[i]->setLayerInitializedFlag(false); m_ppcTEncTop[i]->setFirstPicInLayerDecodedFlag(false); } } } #endif xCheckLayerReset(pcSlice); xSetNoRaslOutputFlag(pcSlice); xSetLayerInitializedFlag(pcSlice); if (m_pcEncTop->getAdaptiveResolutionChange() > 0 && m_layerId > 0 && pocCurr > m_pcEncTop->getAdaptiveResolutionChange()) { pcSlice->setActiveNumILRRefIdx(0); pcSlice->setInterLayerPredEnabledFlag(false); pcSlice->setMFMEnabledFlag(false); } #endif //SVC_EXTENSION pcSlice->setLastIDR(m_iLastIDR); pcSlice->setSliceIdx(0); //set default slice level flag to the same as SPS level flag pcSlice->setLFCrossSliceBoundaryFlag( pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag() ); if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P') { pcSlice->setSliceType(P_SLICE); } if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I') { pcSlice->setSliceType(I_SLICE); } #if SVC_EXTENSION if (m_layerId > 0) { Int interLayerPredLayerIdcTmp[MAX_VPS_LAYER_IDX_PLUS1]; Int activeNumILRRefIdxTmp = 0; for( Int i = 0; i < pcSlice->getActiveNumILRRefIdx(); i++ ) { UInt refLayerIdc = pcSlice->getInterLayerPredLayerIdc(i); UInt refLayerId = pcSlice->getVPS()->getRefLayerId(m_layerId, refLayerIdc); TComList *cListPic = m_ppcTEncTop[pcSlice->getVPS()->getLayerIdxInVps(m_layerId)]->getRefLayerEnc(refLayerIdc)->getListPic(); pcSlice->setBaseColPic( *cListPic, refLayerIdc ); // Apply temporal layer restriction to inter-layer prediction Int maxTidIlRefPicsPlus1 = m_pcEncTop->getVPS()->getMaxTidIlRefPicsPlus1(pcSlice->getBaseColPic(refLayerIdc)->getSlice(0)->getLayerIdx(), pcSlice->getLayerIdx()); if( ((Int)(pcSlice->getBaseColPic(refLayerIdc)->getSlice(0)->getTLayer())<=maxTidIlRefPicsPlus1-1) || (maxTidIlRefPicsPlus1==0 && pcSlice->getBaseColPic(refLayerIdc)->getSlice(0)->getRapPicFlag()) ) { interLayerPredLayerIdcTmp[activeNumILRRefIdxTmp++] = refLayerIdc; // add picture to the list of valid inter-layer pictures } else { continue; // ILP is not valid due to temporal layer restriction } const Window &scalEL = m_pcEncTop->getScaledRefLayerWindowForLayer(refLayerId); const Window &windowRL = m_pcEncTop->getRefLayerWindowForLayer(pcSlice->getVPS()->getRefLayerId(m_layerId, refLayerIdc)); Int widthBL = pcSlice->getBaseColPic(refLayerIdc)->getPicYuvRec()->getWidth(COMPONENT_Y) - windowRL.getWindowLeftOffset() - windowRL.getWindowRightOffset(); Int heightBL = pcSlice->getBaseColPic(refLayerIdc)->getPicYuvRec()->getHeight(COMPONENT_Y) - windowRL.getWindowTopOffset() - windowRL.getWindowBottomOffset(); Int widthEL = pcPic->getPicYuvRec()->getWidth(COMPONENT_Y) - scalEL.getWindowLeftOffset() - scalEL.getWindowRightOffset(); Int heightEL = pcPic->getPicYuvRec()->getHeight(COMPONENT_Y) - scalEL.getWindowTopOffset() - scalEL.getWindowBottomOffset(); // conformance check: the values of RefLayerRegionWidthInSamplesY, RefLayerRegionHeightInSamplesY, ScaledRefRegionWidthInSamplesY and ScaledRefRegionHeightInSamplesY shall be greater than 0 assert(widthEL > 0 && heightEL > 0 && widthBL > 0 && widthEL > 0); // conformance check: ScaledRefRegionWidthInSamplesY shall be greater or equal to RefLayerRegionWidthInSamplesY and ScaledRefRegionHeightInSamplesY shall be greater or equal to RefLayerRegionHeightInSamplesY assert(widthEL >= widthBL && heightEL >= heightBL); // conformance check: when ScaledRefRegionWidthInSamplesY is equal to RefLayerRegionWidthInSamplesY, PhaseHorY shall be equal to 0, when ScaledRefRegionWidthInSamplesC is equal to RefLayerRegionWidthInSamplesC, PhaseHorC shall be equal to 0, when ScaledRefRegionHeightInSamplesY is equal to RefLayerRegionHeightInSamplesY, PhaseVerY shall be equal to 0, and when ScaledRefRegionHeightInSamplesC is equal to RefLayerRegionHeightInSamplesC, PhaseVerC shall be equal to 0. const ResamplingPhase &resamplingPhase = pcSlice->getPPS()->getResamplingPhase( refLayerId ); assert( ( (widthEL != widthBL) || (resamplingPhase.phaseHorLuma == 0 && resamplingPhase.phaseHorChroma == 0) ) && ( (heightEL != heightBL) || (resamplingPhase.phaseVerLuma == 0 && resamplingPhase.phaseVerChroma == 0) ) ); g_mvScalingFactor[refLayerIdc][0] = widthEL == widthBL ? 4096 : Clip3(-4096, 4095, ((widthEL << 8) + (widthBL >> 1)) / widthBL); g_mvScalingFactor[refLayerIdc][1] = heightEL == heightBL ? 4096 : Clip3(-4096, 4095, ((heightEL << 8) + (heightBL >> 1)) / heightBL); g_posScalingFactor[refLayerIdc][0] = ((widthBL << 16) + (widthEL >> 1)) / widthEL; g_posScalingFactor[refLayerIdc][1] = ((heightBL << 16) + (heightEL >> 1)) / heightEL; #if CGS_3D_ASYMLUT TComPicYuv* pBaseColRec = pcSlice->getBaseColPic(refLayerIdc)->getPicYuvRec(); if( pcSlice->getPPS()->getCGSFlag() ) { // all reference layers are currently taken as CGS reference layers m_Enc3DAsymLUTPPS.addRefLayerId( pcSlice->getVPS()->getRefLayerId(m_layerId, refLayerIdc) ); m_Enc3DAsymLUTPicUpdate.addRefLayerId( pcSlice->getVPS()->getRefLayerId(m_layerId, refLayerIdc) ); if( g_posScalingFactor[refLayerIdc][0] < (1<<16) || g_posScalingFactor[refLayerIdc][1] < (1<<16) ) //if(pcPic->isSpatialEnhLayer(refLayerIdc)) { //downsampling downScalePic(pcPic->getPicYuvOrg(), pcSlice->getBaseColPic(refLayerIdc)->getPicYuvOrg()); m_Enc3DAsymLUTPPS.setDsOrigPic(pcSlice->getBaseColPic(refLayerIdc)->getPicYuvOrg()); m_Enc3DAsymLUTPicUpdate.setDsOrigPic(pcSlice->getBaseColPic(refLayerIdc)->getPicYuvOrg()); } else { m_Enc3DAsymLUTPPS.setDsOrigPic(pcPic->getPicYuvOrg()); m_Enc3DAsymLUTPicUpdate.setDsOrigPic(pcPic->getPicYuvOrg()); } Bool bSignalPPS = m_bSeqFirst; bSignalPPS |= m_pcCfg->getGOPSize() > 1 ? pocCurr % m_pcCfg->getIntraPeriod() == 0 : pocCurr % m_pcCfg->getFrameRate() == 0; xDetermin3DAsymLUT( pcSlice, pcPic, refLayerIdc, m_pcCfg, bSignalPPS ); // update PPS in TEncTop and TComPicSym classes m_pcEncTop->getPPS()->setCGSOutputBitDepthY( m_Enc3DAsymLUTPPS.getOutputBitDepthY() ); m_pcEncTop->getPPS()->setCGSOutputBitDepthC( m_Enc3DAsymLUTPPS.getOutputBitDepthC() ); pcPic->getPicSym()->getPPSToUpdate()->setCGSOutputBitDepthY( m_Enc3DAsymLUTPPS.getOutputBitDepthY() ); pcPic->getPicSym()->getPPSToUpdate()->setCGSOutputBitDepthC( m_Enc3DAsymLUTPPS.getOutputBitDepthC() ); m_Enc3DAsymLUTPPS.colorMapping( pcSlice->getBaseColPic(refLayerIdc)->getPicYuvRec(), m_pColorMappedPic ); pBaseColRec = m_pColorMappedPic; } #endif if( pcPic->isSpatialEnhLayer(refLayerIdc) ) { // check for the sample prediction picture type if( pcSlice->getVPS()->isSamplePredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), pcSlice->getVPS()->getLayerIdxInVps(refLayerId) ) ) { m_pcPredSearch->upsampleBasePic( pcSlice, refLayerIdc, pcPic->getFullPelBaseRec(refLayerIdc), pBaseColRec, pcPic->getPicYuvRec() ); } } else { #if CGS_3D_ASYMLUT pcPic->setFullPelBaseRec( refLayerIdc, pBaseColRec ); #else pcPic->setFullPelBaseRec( refLayerIdc, pcSlice->getBaseColPic(refLayerIdc)->getPicYuvRec() ); #endif } pcSlice->setFullPelBaseRec ( refLayerIdc, pcPic->getFullPelBaseRec(refLayerIdc) ); } // Update the list of active inter-layer pictures for ( Int i = 0; i < activeNumILRRefIdxTmp; i++) { pcSlice->setInterLayerPredLayerIdc( interLayerPredLayerIdcTmp[i], i ); } pcSlice->setActiveNumILRRefIdx( activeNumILRRefIdxTmp ); if ( pcSlice->getActiveNumILRRefIdx() == 0 ) { // No valid inter-layer pictures -> disable inter-layer prediction pcSlice->setInterLayerPredEnabledFlag(false); } if( pocCurr % m_pcCfg->getIntraPeriod() == 0 ) { if(pcSlice->getVPS()->getCrossLayerIrapAlignFlag()) { TComList *cListPic = m_ppcTEncTop[pcSlice->getVPS()->getLayerIdxInVps(m_layerId)]->getRefLayerEnc(0)->getListPic(); TComPic* picLayer0 = pcSlice->getRefPic(*cListPic, pcSlice->getPOC() ); if(picLayer0) { pcSlice->setNalUnitType(picLayer0->getSlice(0)->getNalUnitType()); } else { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_CRA); } } } if( pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_CRA ) { if( pcSlice->getActiveNumILRRefIdx() == 0 && m_pcEncTop->getNumDirectRefLayers() == 0 ) { pcSlice->setSliceType(I_SLICE); } else if( !m_pcEncTop->getElRapSliceTypeB() && pcSlice->getSliceType() == B_SLICE ) { pcSlice->setSliceType(P_SLICE); } } } #else // Set the nal unit type pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField)); #endif //#if SVC_EXTENSION if(pcSlice->getTemporalLayerNonReferenceFlag()) { if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_R && #if SVC_EXTENSION ( m_iGopSize != 1 || m_ppcTEncTop[pcSlice->getVPS()->getLayerIdxInVps(m_layerId)]->getIntraPeriod() > 1 ) ) #else !(m_iGopSize == 1 && pcSlice->getSliceType() == I_SLICE)) #endif // Add this condition to avoid POC issues with encoder_intra_main.cfg configuration (see #1127 in bug tracker) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N); } if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RADL_R) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N); } if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RASL_R) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N); } } #if EFFICIENT_FIELD_IRAP if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // IRAP picture { m_associatedIRAPType = pcSlice->getNalUnitType(); #if SVC_POC m_associatedIRAPPOC = pcSlice->getPOC(); m_associatedIrapPocBeforeReset = pocCurr; #else m_associatedIRAPPOC = pocCurr; #endif } pcSlice->setAssociatedIRAPType(m_associatedIRAPType); pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC); #if SVC_POC pcSlice->setAssociatedIrapPocBeforeReset(m_associatedIrapPocBeforeReset); #endif #endif // Do decoding refresh marking if any #if NO_CLRAS_OUTPUT_FLAG pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcEncTop->getNoClrasOutputFlag()); #else pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic); #endif #if SVC_POC // m_pocCRA may have been update here; update m_pocCraWithoutReset m_pocCraWithoutReset = m_pocCRA + m_pcEncTop->getPocAdjustmentValue(); #endif m_pcEncTop->selectReferencePictureSet(pcSlice, pocCurr, iGOPid); pcSlice->getRPS()->setNumberOfLongtermPictures(0); #if !EFFICIENT_FIELD_IRAP if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // IRAP picture { m_associatedIRAPType = pcSlice->getNalUnitType(); m_associatedIRAPPOC = pocCurr; } pcSlice->setAssociatedIRAPType(m_associatedIRAPType); pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC); #endif #if ALLOW_RECOVERY_POINT_AS_RAP if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false, m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3) != 0) || (pcSlice->isIRAP()) #if EFFICIENT_FIELD_IRAP || (isField && pcSlice->getAssociatedIRAPType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getAssociatedIRAPType() <= NAL_UNIT_CODED_SLICE_CRA && pcSlice->getAssociatedIRAPPOC() == pcSlice->getPOC()+1) #endif ) { pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP(), m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3); } #else if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false) != 0) || (pcSlice->isIRAP())) { pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP()); } #endif #if ALIGNED_BUMPING pcSlice->checkLeadingPictureRestrictions(rcListPic, true); #endif pcSlice->applyReferencePictureSet(rcListPic, pcSlice->getRPS()); if(pcSlice->getTLayer() > 0 && !( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N // Check if not a leading picture || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R ) ) { if(pcSlice->isTemporalLayerSwitchingPoint(rcListPic) || pcSlice->getSPS()->getTemporalIdNestingFlag()) { if(pcSlice->getTemporalLayerNonReferenceFlag()) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_N); } else { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_R); } } else if(pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic)) { Bool isSTSA=true; for(Int ii=iGOPid+1;(iigetGOPSize() && isSTSA==true);ii++) { Int lTid= m_pcCfg->getGOPEntry(ii).m_temporalId; if(lTid==pcSlice->getTLayer()) { const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii); for(Int jj=0;jjgetNumberOfPictures();jj++) { if(nRPS->getUsed(jj)) { Int tPoc=m_pcCfg->getGOPEntry(ii).m_POC+nRPS->getDeltaPOC(jj); Int kk=0; for(kk=0;kkgetGOPSize();kk++) { if(m_pcCfg->getGOPEntry(kk).m_POC==tPoc) { break; } } Int tTid=m_pcCfg->getGOPEntry(kk).m_temporalId; if(tTid >= pcSlice->getTLayer()) { isSTSA=false; break; } } } } } if(isSTSA==true) { if(pcSlice->getTemporalLayerNonReferenceFlag()) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_N); } else { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_R); } } } } arrangeLongtermPicturesInRPS(pcSlice, rcListPic); TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification(); refPicListModification->setRefPicListModificationFlagL0(0); refPicListModification->setRefPicListModificationFlagL1(0); pcSlice->setNumRefIdx(REF_PIC_LIST_0,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures())); pcSlice->setNumRefIdx(REF_PIC_LIST_1,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures())); #if SVC_EXTENSION if( m_layerId > 0 && pcSlice->getActiveNumILRRefIdx() ) { if( pocCurr > 0 && pcSlice->isRADL() && pcPic->getSlice(0)->getBaseColPic(pcPic->getSlice(0)->getInterLayerPredLayerIdc(0))->getSlice(0)->isRASL() ) { pcSlice->setActiveNumILRRefIdx(0); pcSlice->setInterLayerPredEnabledFlag(0); } if( pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_CRA ) { pcSlice->setNumRefIdx(REF_PIC_LIST_0, pcSlice->getActiveNumILRRefIdx()); pcSlice->setNumRefIdx(REF_PIC_LIST_1, pcSlice->getActiveNumILRRefIdx()); } else { pcSlice->setNumRefIdx(REF_PIC_LIST_0, pcSlice->getNumRefIdx(REF_PIC_LIST_0)+pcSlice->getActiveNumILRRefIdx()); pcSlice->setNumRefIdx(REF_PIC_LIST_1, pcSlice->getNumRefIdx(REF_PIC_LIST_1)+pcSlice->getActiveNumILRRefIdx()); } // check for the reference pictures whether there is at least one either temporal picture or ILRP with sample prediction type if( pcSlice->getNumRefIdx( REF_PIC_LIST_0 ) - pcSlice->getActiveNumILRRefIdx() == 0 && pcSlice->getNumRefIdx( REF_PIC_LIST_1 ) - pcSlice->getActiveNumILRRefIdx() == 0 ) { Bool foundSamplePredPicture = false; for( Int i = 0; i < pcSlice->getActiveNumILRRefIdx(); i++ ) { if( pcSlice->getVPS()->isSamplePredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), pcSlice->getInterLayerPredLayerIdc(i) ) ) { foundSamplePredPicture = true; break; } } if( !foundSamplePredPicture ) { pcSlice->setSliceType(I_SLICE); pcSlice->setInterLayerPredEnabledFlag(0); pcSlice->setActiveNumILRRefIdx(0); } } } if( ( pcSlice->getTLayer() == 0 && pcSlice->getLayerId() > 0 ) // only for enhancement layer and with temporal layer 0 && !( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) ) { Bool isSTSA=true; Bool isIntra=false; for( Int i = 0; i < pcSlice->getLayerId(); i++) { TComList *cListPic = m_ppcTEncTop[pcSlice->getVPS()->getLayerIdxInVps(i)]->getListPic(); TComPic *lowerLayerPic = pcSlice->getRefPic(*cListPic, pcSlice->getPOC()); if( lowerLayerPic && pcSlice->getVPS()->getDirectDependencyFlag(pcSlice->getLayerIdx(), i) ) { if( lowerLayerPic->getSlice(0)->getSliceType() == I_SLICE) { isIntra = true; } } } for(Int ii=iGOPid+1; ii < m_pcCfg->getGOPSize() && isSTSA; ii++) { Int lTid= m_pcCfg->getGOPEntry(ii).m_temporalId; if(lTid==pcSlice->getTLayer()) { const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii); for(Int jj=0; jjgetNumberOfPictures(); jj++) { if(nRPS->getUsed(jj)) { Int tPoc=m_pcCfg->getGOPEntry(ii).m_POC+nRPS->getDeltaPOC(jj); Int kk=0; for(kk=0; kkgetGOPSize(); kk++) { if(m_pcCfg->getGOPEntry(kk).m_POC==tPoc) { break; } } Int tTid=m_pcCfg->getGOPEntry(kk).m_temporalId; if(tTid >= pcSlice->getTLayer()) { isSTSA = false; break; } } } } } if(isSTSA==true && isIntra == false) { if(pcSlice->getTemporalLayerNonReferenceFlag()) { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_N); } else { pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_R); } } } #endif //SVC_EXTENSION #if ADAPTIVE_QP_SELECTION pcSlice->setTrQuant( m_pcEncTop->getTrQuant() ); #endif #if SVC_EXTENSION if( pcSlice->getSliceType() == B_SLICE ) { pcSlice->setColFromL0Flag(1-uiColDir); } // Set reference list if(m_layerId == 0 || ( m_layerId > 0 && pcSlice->getActiveNumILRRefIdx() == 0 ) ) { pcSlice->setRefPicList( rcListPic ); } if( m_layerId > 0 && pcSlice->getActiveNumILRRefIdx() ) { pcSlice->setILRPic( m_pcEncTop->getIlpList() ); pcSlice->setRefPicListModificationSvc(); pcSlice->setRefPicList( rcListPic, false, m_pcEncTop->getIlpList()); if( pcSlice->getMFMEnabledFlag() ) { Bool found = false; UInt ColFromL0Flag = pcSlice->getColFromL0Flag(); UInt ColRefIdx = pcSlice->getColRefIdx(); for(Int colIdx = 0; colIdx < pcSlice->getNumRefIdx( RefPicList(1 - ColFromL0Flag) ); colIdx++) { RefPicList refList = RefPicList(1 - ColFromL0Flag); TComPic* refPic = pcSlice->getRefPic(refList, colIdx); // It is a requirement of bitstream conformance when the collocated picture, used for temporal motion vector prediction, is an inter-layer reference picture, // VpsInterLayerMotionPredictionEnabled[ LayerIdxInVps[ currLayerId ] ][ LayerIdxInVps[ rLId ] ] shall be equal to 1, where rLId is set equal to nuh_layer_id of the inter-layer picture. if( refPic->isILR(m_layerId) && pcSlice->getVPS()->isMotionPredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), refPic->getLayerIdx() ) && pcSlice->getBaseColPic( *m_ppcTEncTop[refPic->getLayerIdx()]->getListPic() )->checkSameRefInfo() == true ) { ColRefIdx = colIdx; found = true; break; } } if( found == false ) { ColFromL0Flag = 1 - ColFromL0Flag; for(Int colIdx = 0; colIdx < pcSlice->getNumRefIdx( RefPicList(1 - ColFromL0Flag) ); colIdx++) { RefPicList refList = RefPicList(1 - ColFromL0Flag); TComPic* refPic = pcSlice->getRefPic(refList, colIdx); // It is a requirement of bitstream conformance when the collocated picture, used for temporal motion vector prediction, is an inter-layer reference picture, // VpsInterLayerMotionPredictionEnabled[ LayerIdxInVps[ currLayerId ] ][ LayerIdxInVps[ rLId ] ] shall be equal to 1, where rLId is set equal to nuh_layer_id of the inter-layer picture. if( refPic->isILR(m_layerId) && pcSlice->getVPS()->isMotionPredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), refPic->getLayerIdx() ) && pcSlice->getBaseColPic( *m_ppcTEncTop[refPic->getLayerIdx()]->getListPic() )->checkSameRefInfo() == true ) { ColRefIdx = colIdx; found = true; break; } } } if(found == true) { pcSlice->setColFromL0Flag(ColFromL0Flag); pcSlice->setColRefIdx(ColRefIdx); } } } #else //SVC_EXTENSION // Set reference list pcSlice->setRefPicList ( rcListPic ); #endif //#if SVC_EXTENSION // Slice info. refinement if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) ) { pcSlice->setSliceType ( P_SLICE ); } pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx()); if (pcSlice->getSliceType() == B_SLICE) { #if !SVC_EXTENSION pcSlice->setColFromL0Flag(1-uiColDir); #endif Bool bLowDelay = true; Int iCurrPOC = pcSlice->getPOC(); Int iRefIdx = 0; for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++) { if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC ) { bLowDelay = false; } } for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++) { if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC ) { bLowDelay = false; } } pcSlice->setCheckLDC(bLowDelay); } else { pcSlice->setCheckLDC(true); } uiColDir = 1-uiColDir; //------------------------------------------------------------- pcSlice->setRefPOCList(); pcSlice->setList1IdxToList0Idx(); if (m_pcEncTop->getTMVPModeId() == 2) { if (iGOPid == 0) // first picture in SOP (i.e. forward B) { pcSlice->setEnableTMVPFlag(0); } else { // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0. pcSlice->setEnableTMVPFlag(1); } } else if (m_pcEncTop->getTMVPModeId() == 1) { #if SVC_EXTENSION if( pcSlice->getIdrPicFlag() ) { pcSlice->setEnableTMVPFlag(0); } else #endif pcSlice->setEnableTMVPFlag(1); } else { pcSlice->setEnableTMVPFlag(0); } #if SVC_EXTENSION if( m_layerId > 0 && !pcSlice->isIntra() ) { Int colFromL0Flag = 1; Int colRefIdx = 0; // check whether collocated picture is valid if( pcSlice->getEnableTMVPFlag() ) { colFromL0Flag = pcSlice->getColFromL0Flag(); colRefIdx = pcSlice->getColRefIdx(); TComPic* refPic = pcSlice->getRefPic(RefPicList(1-colFromL0Flag), colRefIdx); assert( refPic ); // It is a requirement of bitstream conformance when the collocated picture, used for temporal motion vector prediction, is an inter-layer reference picture, // VpsInterLayerMotionPredictionEnabled[ LayerIdxInVps[ currLayerId ] ][ LayerIdxInVps[ rLId ] ] shall be equal to 1, where rLId is set equal to nuh_layer_id of the inter-layer picture. if( refPic->isILR(m_layerId) && !pcSlice->getVPS()->isMotionPredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), refPic->getLayerIdx() ) ) { pcSlice->setEnableTMVPFlag(false); pcSlice->setMFMEnabledFlag(false); colRefIdx = 0; } } // remove motion only ILRP from the end of the colFromL0Flag reference picture list RefPicList refList = RefPicList(colFromL0Flag); Int numRefIdx = pcSlice->getNumRefIdx(refList); if( numRefIdx > 0 ) { for( Int refIdx = pcSlice->getNumRefIdx(refList) - 1; refIdx > 0; refIdx-- ) { TComPic* refPic = pcSlice->getRefPic(refList, refIdx); if( !refPic->isILR(m_layerId) || ( refPic->isILR(m_layerId) && pcSlice->getVPS()->isSamplePredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), refPic->getLayerIdx() ) ) ) { break; } else { assert( numRefIdx > 1 ); numRefIdx--; } } pcSlice->setNumRefIdx( refList, numRefIdx ); } // remove motion only ILRP from the end of the (1-colFromL0Flag) reference picture list up to colRefIdx refList = RefPicList(1 - colFromL0Flag); numRefIdx = pcSlice->getNumRefIdx(refList); if( numRefIdx > 0 ) { for( Int refIdx = pcSlice->getNumRefIdx(refList) - 1; refIdx > colRefIdx; refIdx-- ) { TComPic* refPic = pcSlice->getRefPic(refList, refIdx); if( !refPic->isILR(m_layerId) || ( refPic->isILR(m_layerId) && pcSlice->getVPS()->isSamplePredictionType( pcSlice->getVPS()->getLayerIdxInVps(m_layerId), refPic->getLayerIdx() ) ) ) { break; } else { assert( numRefIdx > 1 ); numRefIdx--; } } pcSlice->setNumRefIdx( refList, numRefIdx ); } assert( pcSlice->getNumRefIdx(REF_PIC_LIST_0) > 0 && ( pcSlice->isInterP() || (pcSlice->isInterB() && pcSlice->getNumRefIdx(REF_PIC_LIST_1) > 0) ) ); } #endif /////////////////////////////////////////////////////////////////////////////////////////////////// Compress a slice // Slice compression if (m_pcCfg->getUseASR()) { m_pcSliceEncoder->setSearchRange(pcSlice); } Bool bGPBcheck=false; if ( pcSlice->getSliceType() == B_SLICE) { if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ) { bGPBcheck=true; Int i; for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ ) { if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) ) { bGPBcheck=false; break; } } } } if(bGPBcheck) { pcSlice->setMvdL1ZeroFlag(true); } else { pcSlice->setMvdL1ZeroFlag(false); } pcPic->getSlice(pcSlice->getSliceIdx())->setMvdL1ZeroFlag(pcSlice->getMvdL1ZeroFlag()); Double lambda = 0.0; Int actualHeadBits = 0; Int actualTotalBits = 0; Int estimatedBits = 0; Int tmpBitsBeforeWriting = 0; if ( m_pcCfg->getUseRateCtrl() ) { Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid ); if ( pcPic->getSlice(0)->getSliceType() == I_SLICE ) { frameLevel = 0; } m_pcRateCtrl->initRCPic( frameLevel ); estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits(); Int sliceQP = m_pcCfg->getInitialQP(); #if SVC_EXTENSION if ( ( pocCurr == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified #else if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified #endif { Int NumberBFrames = ( m_pcCfg->getGOPSize() - 1 ); Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames ); Double dQPFactor = 0.57*dLambda_scale; Int SHIFT_QP = 12; Int bitdepth_luma_qp_scale = 0; Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP; lambda = dQPFactor*pow( 2.0, qp_temp/3.0 ); } else if ( frameLevel == 0 ) // intra case, but use the model { m_pcSliceEncoder->calCostSliceI(pcPic); if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case { Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits(); bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits ); if ( bits < 200 ) { bits = 200; } m_pcRateCtrl->getRCPic()->setTargetBits( bits ); } list listPreviousPicture = m_pcRateCtrl->getPicList(); m_pcRateCtrl->getRCPic()->getLCUInitTargetBits(); lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType()); sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture ); } else // normal case { list listPreviousPicture = m_pcRateCtrl->getPicList(); lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType()); sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture ); } #if SVC_EXTENSION sliceQP = Clip3( -pcSlice->getQpBDOffsetY(), MAX_QP, sliceQP ); #else sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, sliceQP ); #endif m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP ); m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda ); } UInt uiNumSliceSegments = 1; #if AVC_BASE if( m_layerId == 0 && m_pcEncTop->getVPS()->getNonHEVCBaseLayerFlag() ) { pcPic->getPicYuvOrg()->copyToPic( pcPic->getPicYuvRec() ); // Calculate for the base layer to be used in EL as Inter layer reference if( m_pcEncTop->getInterLayerWeightedPredFlag() ) { m_pcSliceEncoder->estimateILWpParam( pcSlice ); } return; } #endif // Allocate some coders, now the number of tiles are known. const Int numSubstreamsColumns = (pcSlice->getPPS()->getNumTileColumnsMinus1() + 1); const Int numSubstreamRows = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->getFrameHeightInCtus() : (pcSlice->getPPS()->getNumTileRowsMinus1() + 1); const Int numSubstreams = numSubstreamRows * numSubstreamsColumns; std::vector substreamsOut(numSubstreams); // now compress (trial encode) the various slice segments (slices, and dependent slices) { const UInt numberOfCtusInFrame=pcPic->getPicSym()->getNumberOfCtusInFrame(); pcSlice->setSliceCurStartCtuTsAddr( 0 ); pcSlice->setSliceSegmentCurStartCtuTsAddr( 0 ); for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; ) { m_pcSliceEncoder->precompressSlice( pcPic ); m_pcSliceEncoder->compressSlice ( pcPic ); const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr(); if (curSliceSegmentEnd < numberOfCtusInFrame) { const Bool bNextSegmentIsDependentSlice=curSliceSegmentEndgetSliceCurEndCtuTsAddr(); const UInt sliceBits=pcSlice->getSliceBits(); pcPic->allocateNewSlice(); // prepare for next slice pcPic->setCurrSliceIdx ( uiNumSliceSegments ); m_pcSliceEncoder->setSliceIdx ( uiNumSliceSegments ); pcSlice = pcPic->getSlice ( uiNumSliceSegments ); assert(pcSlice->getPPS()!=0); pcSlice->copySliceInfo ( pcPic->getSlice(uiNumSliceSegments-1) ); pcSlice->setSliceIdx ( uiNumSliceSegments ); if (bNextSegmentIsDependentSlice) { pcSlice->setSliceBits(sliceBits); } else { pcSlice->setSliceCurStartCtuTsAddr ( curSliceSegmentEnd ); pcSlice->setSliceBits(0); } pcSlice->setDependentSliceSegmentFlag(bNextSegmentIsDependentSlice); pcSlice->setSliceSegmentCurStartCtuTsAddr ( curSliceSegmentEnd ); // TODO: optimise cabac_init during compress slice to improve multi-slice operation // pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx()); uiNumSliceSegments ++; } nextCtuTsAddr = curSliceSegmentEnd; } } #if N0383_IL_CONSTRAINED_TILE_SETS_SEI if (m_pcCfg->getInterLayerConstrainedTileSetsSEIEnabled()) { xBuildTileSetsMap(pcPic->getPicSym()); } #endif pcSlice = pcPic->getSlice(0); // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoCtuBoundary() ) { m_pcSAO->getPreDBFStatistics(pcPic); } //-- Loop filter Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag(); m_pcLoopFilter->setCfg(bLFCrossTileBoundary); if ( m_pcCfg->getDeblockingFilterMetric() ) { applyDeblockingFilterMetric(pcPic, uiNumSliceSegments); } m_pcLoopFilter->loopFilterPic( pcPic ); /////////////////////////////////////////////////////////////////////////////////////////////////// File writing // Set entropy coder m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, pcSlice ); // write various header sets. if ( m_bSeqFirst ) { #if SVC_EXTENSION OutputNALUnit nalu( NAL_UNIT_VPS, 0, 0 ); // The value of nuh_layer_id of VPS NAL unit shall be equal to 0. #if AVC_BASE if( ( m_layerId > 0 && m_pcEncTop->getVPS()->getNonHEVCBaseLayerFlag() ) || ( m_layerId == 0 && !m_pcEncTop->getVPS()->getNonHEVCBaseLayerFlag() ) ) #else if( m_layerId == 0 ) #endif { //The following code also calculates the VPS VUI offset #else OutputNALUnit nalu(NAL_UNIT_VPS); #endif m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodeVPS(m_pcEncTop->getVPS()); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; #if SVC_EXTENSION } #endif #if SVC_EXTENSION nalu = NALUnit(NAL_UNIT_SPS, 0, m_layerId); if( m_pcEncTop->getVPS()->getNumDirectRefLayers(m_layerId) == 0 && m_pcEncTop->getVPS()->getNumAddLayerSets() > 0 ) { // For independent base layer rewriting nalu.m_nuhLayerId = 0; } #else nalu = NALUnit(NAL_UNIT_SPS); #endif m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if SVC_EXTENSION // dependency constraint assert( pcSlice->getSPS()->getLayerId() == 0 || pcSlice->getSPS()->getLayerId() == m_layerId || m_pcEncTop->getVPS()->getRecursiveRefLayerFlag(m_layerId, pcSlice->getSPS()->getLayerId()) ); #endif m_pcEntropyCoder->encodeSPS(pcSlice->getSPS()); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; #if SVC_EXTENSION nalu = NALUnit(NAL_UNIT_PPS, 0, m_layerId); if( m_pcEncTop->getVPS()->getNumDirectRefLayers(m_layerId) == 0 && m_pcEncTop->getVPS()->getNumAddLayerSets() > 0 ) { // For independent base layer rewriting nalu.m_nuhLayerId = 0; } #else nalu = NALUnit(NAL_UNIT_PPS); #endif m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if SVC_EXTENSION // dependency constraint assert( pcSlice->getPPS()->getLayerId() == 0 || pcSlice->getPPS()->getLayerId() == m_layerId || m_pcEncTop->getVPS()->getRecursiveRefLayerFlag(m_layerId, pcSlice->getPPS()->getLayerId()) ); #endif #if SVC_EXTENSION && CGS_3D_ASYMLUT m_pcEntropyCoder->encodePPS(pcSlice->getPPS(), &m_Enc3DAsymLUTPPS); #else m_pcEntropyCoder->encodePPS(pcSlice->getPPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; xCreateLeadingSEIMessages(accessUnit, pcSlice->getSPS(), pcSlice->getPPS()); #if O0164_MULTI_LAYER_HRD if (pcSlice->getLayerId() == 0 && m_pcEncTop->getVPS()->getVpsVuiBspHrdPresentFlag()) { Int j; TComVPS *vps = m_pcEncTop->getVPS(); for( Int i = 0; i < vps->getNumOutputLayerSets(); i++ ) { for( Int k = 0; k < vps->getNumSignalledPartitioningSchemes(i); k++ ) { for( Int l = 0; l < vps->getNumPartitionsInSchemeMinus1(i, k)+1; l++ ) { nalu = NALUnit(NAL_UNIT_PREFIX_SEI, 0, 1); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIScalableNesting *scalableBspNestingSei = xCreateBspNestingSEI(pcSlice, i, k, l); m_seiWriter.writeSEImessage(nalu.m_Bitstream, *scalableBspNestingSei, m_pcEncTop->getVPS(), pcSlice->getSPS()); writeRBSPTrailingBits(nalu.m_Bitstream); UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU + m_bufferingPeriodSEIPresentInAU + m_pictureTimingSEIPresentInAU + m_nestedPictureTimingSEIPresentInAU; // Insert SEI after APS, BP and PT SEI AccessUnit::iterator it; for( j = 0, it = accessUnit.begin(); j < seiPositionInAu + offsetPosition; j++ ) { it++; } accessUnit.insert(it, new NALUnitEBSP(nalu)); } } } } #endif m_bSeqFirst = false; } #if CGS_3D_ASYMLUT else if( m_pcCfg->getCGSFlag() && pcSlice->getLayerId() && pcSlice->getCGSOverWritePPS() ) { OutputNALUnit nalu(NAL_UNIT_PPS, 0, m_layerId); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); m_pcEntropyCoder->encodePPS(pcSlice->getPPS() , &m_Enc3DAsymLUTPPS ); writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } #endif if (writeSOP) // write SOP description SEI (if enabled) at the beginning of GOP { Int SOPcurrPOC = pocCurr; OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEISOPDescription SOPDescriptionSEI; SOPDescriptionSEI.m_sopSeqParameterSetId = pcSlice->getSPS()->getSPSId(); UInt i = 0; UInt prevEntryId = iGOPid; for (Int j = iGOPid; j < m_iGopSize; j++) { Int deltaPOC = m_pcCfg->getGOPEntry(j).m_POC - m_pcCfg->getGOPEntry(prevEntryId).m_POC; if ((SOPcurrPOC + deltaPOC) < m_pcCfg->getFramesToBeEncoded()) { SOPcurrPOC += deltaPOC; SOPDescriptionSEI.m_sopDescVclNaluType[i] = getNalUnitType(SOPcurrPOC, m_iLastIDR, isField); SOPDescriptionSEI.m_sopDescTemporalId[i] = m_pcCfg->getGOPEntry(j).m_temporalId; SOPDescriptionSEI.m_sopDescStRpsIdx[i] = m_pcEncTop->getReferencePictureSetIdxForSOP(pcSlice, SOPcurrPOC, j); SOPDescriptionSEI.m_sopDescPocDelta[i] = deltaPOC; prevEntryId = j; i++; } } SOPDescriptionSEI.m_numPicsInSopMinus1 = i - 1; #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, SOPDescriptionSEI, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, SOPDescriptionSEI, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); writeSOP = false; } #if Q0189_TMVP_CONSTRAINTS if( m_pcEncTop->getTMVPConstraintsSEIEnabled() == 1 && (m_pcEncTop->getTMVPModeId() == 1 || m_pcEncTop->getTMVPModeId() == 2) && pcSlice->getLayerId() >0 && (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP)) { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); SEITMVPConstrains seiTMVPConstrains; m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); seiTMVPConstrains.no_intra_layer_col_pic_flag = 1; seiTMVPConstrains.prev_pics_not_used_flag = 1; #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiTMVPConstrains, m_pcEncTop->getVPS(), pcSlice->getSPS() ); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiTMVPConstrains, pcSlice->getSPS() ); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } #endif #if Q0247_FRAME_FIELD_INFO if( pcSlice->getLayerId()> 0 && ( (m_pcCfg->getProgressiveSourceFlag() && m_pcCfg->getInterlacedSourceFlag()) || m_pcCfg->getFrameFieldInfoPresentFlag())) { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); SEIFrameFieldInfo seiFFInfo; m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); seiFFInfo.m_ffinfo_picStruct = (isField && pcSlice->getPic()->isTopField())? 1 : isField? 2 : 0; #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiFFInfo, m_pcEncTop->getVPS(), pcSlice->getSPS() ); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiFFInfo, pcSlice->getSPS() ); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } #endif if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { if( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) { UInt numDU = pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNumDU(); pictureTimingSEI.m_numDecodingUnitsMinus1 = ( numDU - 1 ); pictureTimingSEI.m_duCommonCpbRemovalDelayFlag = false; if( pictureTimingSEI.m_numNalusInDuMinus1 == NULL ) { pictureTimingSEI.m_numNalusInDuMinus1 = new UInt[ numDU ]; } if( pictureTimingSEI.m_duCpbRemovalDelayMinus1 == NULL ) { pictureTimingSEI.m_duCpbRemovalDelayMinus1 = new UInt[ numDU ]; } if( accumBitsDU == NULL ) { accumBitsDU = new UInt[ numDU ]; } if( accumNalsDU == NULL ) { accumNalsDU = new UInt[ numDU ]; } } pictureTimingSEI.m_auCpbRemovalDelay = std::min(std::max(1, m_totalCoded - m_lastBPSEI), static_cast(pow(2, static_cast(pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getCpbRemovalDelayLengthMinus1()+1)))); // Syntax element signalled as minus, hence the . #if SVC_EXTENSION pictureTimingSEI.m_picDpbOutputDelay = pcSlice->getSPS()->getNumReorderPics(pcSlice->getSPS()->getMaxTLayers()-1) + pocCurr - m_totalCoded; #else pictureTimingSEI.m_picDpbOutputDelay = pcSlice->getSPS()->getNumReorderPics(pcSlice->getSPS()->getMaxTLayers()-1) + pcSlice->getPOC() - m_totalCoded; #endif #if EFFICIENT_FIELD_IRAP if(IRAPGOPid > 0 && IRAPGOPid < m_iGopSize) { // if pictures have been swapped there is likely one more picture delay on their tid. Very rough approximation pictureTimingSEI.m_picDpbOutputDelay ++; } #endif Int factor = pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getTickDivisorMinus2() + 2; pictureTimingSEI.m_picDpbOutputDuDelay = factor * pictureTimingSEI.m_picDpbOutputDelay; if( m_pcCfg->getDecodingUnitInfoSEIEnabled() ) { picSptDpbOutputDuDelay = factor * pictureTimingSEI.m_picDpbOutputDelay; } } if( ( m_pcCfg->getBufferingPeriodSEIEnabled() ) && ( pcSlice->getSliceType() == I_SLICE ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIBufferingPeriod sei_buffering_period; UInt uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec sei_buffering_period.m_initialCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; Double dTmp = (Double)pcSlice->getSPS()->getVuiParameters()->getTimingInfo()->getNumUnitsInTick() / (Double)pcSlice->getSPS()->getVuiParameters()->getTimingInfo()->getTimeScale(); UInt uiTmp = (UInt)( dTmp * 90000.0 ); uiInitialCpbRemovalDelay -= uiTmp; uiInitialCpbRemovalDelay -= uiTmp / ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getTickDivisorMinus2() + 2 ); sei_buffering_period.m_initialAltCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialAltCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialAltCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; sei_buffering_period.m_initialAltCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; sei_buffering_period.m_rapCpbParamsPresentFlag = 0; //for the concatenation, it can be set to one during splicing. sei_buffering_period.m_concatenationFlag = 0; //since the temporal layer HRD is not ready, we assumed it is fixed sei_buffering_period.m_auCpbRemovalDelayDelta = 1; sei_buffering_period.m_cpbDelayOffset = 0; sei_buffering_period.m_dpbDelayOffset = 0; #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, sei_buffering_period, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, sei_buffering_period, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); { UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU; // Insert BP SEI after APS SEI AccessUnit::iterator it = accessUnit.begin(); for(Int j = 0; j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(nalu)); m_bufferingPeriodSEIPresentInAU = true; } if (m_pcCfg->getScalableNestingSEIEnabled()) { OutputNALUnit naluTmp(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&naluTmp.m_Bitstream); scalableNestingSEI.m_nestedSEIs.clear(); scalableNestingSEI.m_nestedSEIs.push_back(&sei_buffering_period); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( naluTmp.m_Bitstream, scalableNestingSEI, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage( naluTmp.m_Bitstream, scalableNestingSEI, pcSlice->getSPS()); #endif writeRBSPTrailingBits(naluTmp.m_Bitstream); UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU + m_bufferingPeriodSEIPresentInAU + m_pictureTimingSEIPresentInAU; // Insert BP SEI after non-nested APS, BP and PT SEIs AccessUnit::iterator it = accessUnit.begin(); for(Int j = 0; j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(naluTmp)); m_nestedBufferingPeriodSEIPresentInAU = true; } m_lastBPSEI = m_totalCoded; m_cpbRemovalDelay = 0; } m_cpbRemovalDelay ++; if(pcSlice->getSPS()->getVuiParametersPresentFlag() && m_pcCfg->getChromaSamplingFilterHintEnabled() && ( pcSlice->getSliceType() == I_SLICE )) { SEIChromaSamplingFilterHint *seiChromaSamplingFilterHint = xCreateSEIChromaSamplingFilterHint(m_pcCfg->getChromaLocInfoPresentFlag(), m_pcCfg->getChromaSamplingHorFilterIdc(), m_pcCfg->getChromaSamplingVerFilterIdc()); OutputNALUnit naluTmp(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&naluTmp.m_Bitstream); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(naluTmp.m_Bitstream, *seiChromaSamplingFilterHint, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(naluTmp.m_Bitstream, *seiChromaSamplingFilterHint, pcSlice->getSPS()); #endif writeRBSPTrailingBits(naluTmp.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(naluTmp)); delete seiChromaSamplingFilterHint; } if( ( m_pcEncTop->getRecoveryPointSEIEnabled() ) && ( pcSlice->getSliceType() == I_SLICE ) ) { if( m_pcEncTop->getGradualDecodingRefreshInfoEnabled() && !pcSlice->getRapPicFlag() ) { // Gradual decoding refresh SEI OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIGradualDecodingRefreshInfo seiGradualDecodingRefreshInfo; seiGradualDecodingRefreshInfo.m_gdrForegroundFlag = true; // Indicating all "foreground" #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiGradualDecodingRefreshInfo, m_pcEncTop->getVPS(), pcSlice->getSPS() ); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiGradualDecodingRefreshInfo, pcSlice->getSPS() ); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } // Recovery point SEI OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEIRecoveryPoint sei_recovery_point; sei_recovery_point.m_recoveryPocCnt = 0; #if SVC_EXTENSION sei_recovery_point.m_exactMatchingFlag = ( pocCurr == 0 ) ? (true) : (false); #else sei_recovery_point.m_exactMatchingFlag = ( pcSlice->getPOC() == 0 ) ? (true) : (false); #endif sei_recovery_point.m_brokenLinkFlag = false; #if ALLOW_RECOVERY_POINT_AS_RAP if(m_pcCfg->getDecodingRefreshType() == 3) { m_iLastRecoveryPicPOC = pocCurr; } #endif #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, sei_recovery_point, m_pcEncTop->getVPS(), pcSlice->getSPS() ); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, sei_recovery_point, pcSlice->getSPS() ); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } if( m_pcEncTop->getNoDisplaySEITLayer() ) { if( pcSlice->getTLayer() >= m_pcEncTop->getNoDisplaySEITLayer() ) { // No display SEI OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); SEINoDisplay seiNoDisplay; seiNoDisplay.m_noDisplay = true; #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiNoDisplay, m_pcEncTop->getVPS(), pcSlice->getSPS() ); #else m_seiWriter.writeSEImessage( nalu.m_Bitstream, seiNoDisplay, pcSlice->getSPS() ); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); } } // insert one CRI by picture (if the file exist) #if Q0074_COLOUR_REMAPPING_SEI freeColourCRI(); // building the CRI file name with poc num in suffix "_poc.txt" char suffix[10]; sprintf(suffix, "_%d.txt", pcSlice->getPOC()); string colourRemapSEIFileWithPoc(m_pcCfg->getCRISEIFileRoot()); colourRemapSEIFileWithPoc.append(suffix); setCRISEIFile( const_cast(colourRemapSEIFileWithPoc.c_str()) ); Int ret = readingCRIparameters(); if(ret != -1 && m_pcCfg->getCRISEIFileRoot()) { // check validity of input parameters xCheckParameter(); SEIColourRemappingInfo *sei = xCreateSEIColourRemappingInfo (); #if SVC_EXTENSION OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI, 0, pcSlice->getSPS()->getLayerId()); // SEI-CRI is applied per layer #else OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); #endif m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if SVC_EXTENSION m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, m_pcEncTop->getVPS(), pcSlice->getSPS() ); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, *sei, pcSlice->getSPS() ); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.push_back(new NALUnitEBSP(nalu)); delete sei; } #endif /* use the main bitstream buffer for storing the marshalled picture */ m_pcEntropyCoder->setBitstream(NULL); pcSlice = pcPic->getSlice(0); #if HIGHER_LAYER_IRAP_SKIP_FLAG if ( pcSlice->getSPS()->getUseSAO() && !( m_pcEncTop->getSkipPictureAtArcSwitch() && m_pcEncTop->getAdaptiveResolutionChange() > 0 && pcSlice->getLayerId() == 1 && pcSlice->getPOC() == m_pcEncTop->getAdaptiveResolutionChange()) ) #else if (pcSlice->getSPS()->getUseSAO()) #endif { Bool sliceEnabled[MAX_NUM_COMPONENT]; TComBitCounter tempBitCounter; tempBitCounter.resetBits(); m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(&tempBitCounter); m_pcSAO->initRDOCabacCoder(m_pcEncTop->getRDGoOnSbacCoder(), pcSlice); m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas() #if SAO_ENCODE_ALLOW_USE_PREDEBLOCK , m_pcCfg->getSaoCtuBoundary() #endif ); m_pcSAO->PCMLFDisableProcess(pcPic); m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(NULL); //assign SAO slice header for(Int s=0; s< uiNumSliceSegments; s++) { pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]); assert(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]); pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]); } } // pcSlice is currently slice 0. std::size_t binCountsInNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10) std::size_t numBytesInVclNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10) for( UInt sliceSegmentStartCtuTsAddr = 0, sliceIdxCount=0; sliceSegmentStartCtuTsAddr < pcPic->getPicSym()->getNumberOfCtusInFrame(); sliceIdxCount++, sliceSegmentStartCtuTsAddr=pcSlice->getSliceSegmentCurEndCtuTsAddr() ) { pcSlice = pcPic->getSlice(sliceIdxCount); if(sliceIdxCount > 0 && pcSlice->getSliceType()!= I_SLICE) { pcSlice->checkColRefIdx(sliceIdxCount, pcPic); } pcPic->setCurrSliceIdx(sliceIdxCount); m_pcSliceEncoder->setSliceIdx(sliceIdxCount); pcSlice->setRPS(pcPic->getSlice(0)->getRPS()); pcSlice->setRPSidx(pcPic->getSlice(0)->getRPSidx()); for ( UInt ui = 0 ; ui < numSubstreams; ui++ ) { substreamsOut[ui].clear(); } m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, pcSlice ); m_pcEntropyCoder->resetEntropy (); /* start slice NALunit */ #if SVC_EXTENSION OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer(), m_layerId ); #else OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer() ); #endif m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if SVC_EXTENSION if( pcSlice->isIRAP() ) { //the inference for NoOutputPriorPicsFlag // KJS: This cannot happen at the encoder if (!m_bFirst && pcSlice->isIRAP() && m_noRaslOutputFlag) { if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) { pcSlice->setNoOutputPriorPicsFlag(true); } } } #else pcSlice->setNoRaslOutputFlag(false); if (pcSlice->isIRAP()) { if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP) { pcSlice->setNoRaslOutputFlag(true); } //the inference for NoOutputPriorPicsFlag // KJS: This cannot happen at the encoder if (!m_bFirst && pcSlice->isIRAP() && pcSlice->getNoRaslOutputFlag()) { if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) { pcSlice->setNoOutputPriorPicsFlag(true); } } } #endif pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx()); tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits(); m_pcEntropyCoder->encodeSliceHeader(pcSlice); actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting ); pcSlice->setFinalized(true); #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST g_bFinalEncode = true; #endif pcSlice->clearSubstreamSizes( ); { UInt numBinsCoded = 0; m_pcSliceEncoder->encodeSlice(pcPic, &(substreamsOut[0]), numBinsCoded); binCountsInNalUnits+=numBinsCoded; } #if ENVIRONMENT_VARIABLE_DEBUG_AND_TEST g_bFinalEncode = false; #endif { // Construct the final bitstream by concatenating substreams. // The final bitstream is either nalu.m_Bitstream or pcBitstreamRedirect; // Complete the slice header info. m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, pcSlice ); m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream); #if SVC_EXTENSION tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits(); m_pcEntropyCoder->encodeTilesWPPEntryPoint( pcSlice ); actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting ); m_pcEntropyCoder->encodeSliceHeaderExtn( pcSlice, actualHeadBits ); #else m_pcEntropyCoder->encodeTilesWPPEntryPoint( pcSlice ); #endif // Append substreams... TComOutputBitstream *pcOut = pcBitstreamRedirect; const Int numZeroSubstreamsAtStartOfSlice = pcPic->getSubstreamForCtuAddr(pcSlice->getSliceSegmentCurStartCtuTsAddr(), false, pcSlice); const Int numSubstreamsToCode = pcSlice->getNumberOfSubstreamSizes()+1; for ( UInt ui = 0 ; ui < numSubstreamsToCode; ui++ ) { pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice])); } } // If current NALU is the first NALU of slice (containing slice header) and more NALUs exist (due to multiple dependent slices) then buffer it. // If current NALU is the last NALU of slice and a NALU was buffered, then (a) Write current NALU (b) Update an write buffered NALU at approproate location in NALU list. Bool bNALUAlignedWrittenToList = false; // used to ensure current NALU is not written more than once to the NALU list. xAttachSliceDataToNalUnit(nalu, pcBitstreamRedirect); accessUnit.push_back(new NALUnitEBSP(nalu)); actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8; numBytesInVclNalUnits += (std::size_t)(accessUnit.back()->m_nalUnitData.str().size()); bNALUAlignedWrittenToList = true; if (!bNALUAlignedWrittenToList) { nalu.m_Bitstream.writeAlignZero(); accessUnit.push_back(new NALUnitEBSP(nalu)); } if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) && ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) ) { UInt numNalus = 0; UInt numRBSPBytes = 0; for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++) { UInt numRBSPBytes_nal = UInt((*it)->m_nalUnitData.str().size()); if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI) { numRBSPBytes += numRBSPBytes_nal; numNalus ++; } } accumBitsDU[ pcSlice->getSliceIdx() ] = ( numRBSPBytes << 3 ); accumNalsDU[ pcSlice->getSliceIdx() ] = numNalus; // SEI not counted for bit count; hence shouldn't be counted for # of NALUs - only for consistency } } // end iteration over slices // cabac_zero_words processing { const Int log2subWidthCxsubHeightC = (pcPic->getComponentScaleX(COMPONENT_Cb)+pcPic->getComponentScaleY(COMPONENT_Cb)); const Int minCuWidth = pcPic->getMinCUWidth(); const Int minCuHeight = pcPic->getMinCUHeight(); #if SVC_EXTENSION const Int paddedWidth = ((pcSlice->getPicWidthInLumaSamples() + minCuWidth - 1) / minCuWidth) * minCuWidth; const Int paddedHeight= ((pcSlice->getPicHeightInLumaSamples() + minCuHeight - 1) / minCuHeight) * minCuHeight; #else const Int paddedWidth = ((pcSlice->getSPS()->getPicWidthInLumaSamples() + minCuWidth - 1) / minCuWidth) * minCuWidth; const Int paddedHeight= ((pcSlice->getSPS()->getPicHeightInLumaSamples() + minCuHeight - 1) / minCuHeight) * minCuHeight; #endif const Int rawBits = paddedWidth * paddedHeight * (g_bitDepth[CHANNEL_TYPE_LUMA] + 2*(g_bitDepth[CHANNEL_TYPE_CHROMA]>>log2subWidthCxsubHeightC)); const std::size_t threshold = (32/3)*numBytesInVclNalUnits + (rawBits/32); if (binCountsInNalUnits >= threshold) { // need to add additional cabac zero words (each one accounts for 3 bytes (=00 00 03)) to increase numBytesInVclNalUnits const std::size_t targetNumBytesInVclNalUnits = ((binCountsInNalUnits - (rawBits/32))*3+31)/32; if (targetNumBytesInVclNalUnits>numBytesInVclNalUnits) // It should be! { const std::size_t numberOfAdditionalBytesNeeded=targetNumBytesInVclNalUnits - numBytesInVclNalUnits; const std::size_t numberOfAdditionalCabacZeroWords=(numberOfAdditionalBytesNeeded+2)/3; const std::size_t numberOfAdditionalCabacZeroBytes=numberOfAdditionalCabacZeroWords*3; if (m_pcCfg->getCabacZeroWordPaddingEnabled()) { std::vector zeroBytesPadding((size_t)numberOfAdditionalCabacZeroBytes, Char(0)); for(std::size_t i=0; im_nalUnitData.write(&(zeroBytesPadding[0]), (size_t)numberOfAdditionalCabacZeroBytes); printf("Adding %d bytes of padding\n", UInt(numberOfAdditionalCabacZeroWords*3)); } else { printf("Standard would normally require adding %d bytes of padding\n", UInt(numberOfAdditionalCabacZeroWords*3)); } } } } pcPic->compressMotion(); //-- For time output for each slice Double dEncTime = (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC; std::string digestStr; if (m_pcCfg->getDecodedPictureHashSEIEnabled()) { /* calculate MD5sum for entire reconstructed picture */ SEIDecodedPictureHash sei_recon_picture_digest; if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 1) { sei_recon_picture_digest.method = SEIDecodedPictureHash::MD5; UInt numChar=calcMD5(*pcPic->getPicYuvRec(), sei_recon_picture_digest.m_digest); digestStr = digestToString(sei_recon_picture_digest.m_digest, numChar); } else if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 2) { sei_recon_picture_digest.method = SEIDecodedPictureHash::CRC; UInt numChar=calcCRC(*pcPic->getPicYuvRec(), sei_recon_picture_digest.m_digest); digestStr = digestToString(sei_recon_picture_digest.m_digest, numChar); } else if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 3) { sei_recon_picture_digest.method = SEIDecodedPictureHash::CHECKSUM; UInt numChar=calcChecksum(*pcPic->getPicYuvRec(), sei_recon_picture_digest.m_digest); digestStr = digestToString(sei_recon_picture_digest.m_digest, numChar); } #if SVC_EXTENSION OutputNALUnit nalu(NAL_UNIT_SUFFIX_SEI, pcSlice->getTLayer(), m_layerId); #else OutputNALUnit nalu(NAL_UNIT_SUFFIX_SEI, pcSlice->getTLayer()); #endif /* write the SEI messages */ m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_recon_picture_digest, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_recon_picture_digest, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.insert(accessUnit.end(), new NALUnitEBSP(nalu)); } if (m_pcCfg->getTemporalLevel0IndexSEIEnabled()) { SEITemporalLevel0Index sei_temporal_level0_index; if (pcSlice->getRapPicFlag()) { m_tl0Idx = 0; m_rapIdx = (m_rapIdx + 1) & 0xFF; } else { m_tl0Idx = (m_tl0Idx + (pcSlice->getTLayer() ? 0 : 1)) & 0xFF; } sei_temporal_level0_index.tl0Idx = m_tl0Idx; sei_temporal_level0_index.rapIdx = m_rapIdx; OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI); /* write the SEI messages */ m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_temporal_level0_index, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, sei_temporal_level0_index, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); /* insert the SEI message NALUnit before any Slice NALUnits */ AccessUnit::iterator it = find_if(accessUnit.begin(), accessUnit.end(), mem_fun(&NALUnit::isSlice)); accessUnit.insert(it, new NALUnitEBSP(nalu)); } m_pcCfg->setEncodedFlag(iGOPid, true); xCalculateAddPSNR( pcPic, pcPic->getPicYuvRec(), accessUnit, dEncTime, snr_conversion, printFrameMSE ); //In case of field coding, compute the interlaced PSNR for both fields if(isField) { Bool bothFieldsAreEncoded = false; Int correspondingFieldPOC = pcPic->getPOC(); Int currentPicGOPPoc = m_pcCfg->getGOPEntry(iGOPid).m_POC; if(pcPic->getPOC() == 0) { // particular case for POC 0 and 1. // If they are not encoded first and separately from other pictures, we need to change this // POC 0 is always encoded first then POC 1 is encoded bothFieldsAreEncoded = false; } else if(pcPic->getPOC() == 1) { // if we are at POC 1, POC 0 has been encoded for sure correspondingFieldPOC = 0; bothFieldsAreEncoded = true; } else { if(pcPic->getPOC()%2 == 1) { correspondingFieldPOC -= 1; // all odd POC are associated with the preceding even POC (e.g poc 1 is associated to poc 0) currentPicGOPPoc -= 1; } else { correspondingFieldPOC += 1; // all even POC are associated with the following odd POC (e.g poc 0 is associated to poc 1) currentPicGOPPoc += 1; } for(Int i = 0; i < m_iGopSize; i ++) { if(m_pcCfg->getGOPEntry(i).m_POC == currentPicGOPPoc) { bothFieldsAreEncoded = m_pcCfg->getGOPEntry(i).m_isEncoded; break; } } } if(bothFieldsAreEncoded) { //get complementary top field TComList::iterator iterPic = rcListPic.begin(); while ((*iterPic)->getPOC() != correspondingFieldPOC) { iterPic ++; } TComPic* correspondingFieldPic = *(iterPic); if( (pcPic->isTopField() && isTff) || (!pcPic->isTopField() && !isTff)) { xCalculateInterlacedAddPSNR(pcPic, correspondingFieldPic, pcPic->getPicYuvRec(), correspondingFieldPic->getPicYuvRec(), accessUnit, dEncTime, snr_conversion, printFrameMSE ); } else { xCalculateInterlacedAddPSNR(correspondingFieldPic, pcPic, correspondingFieldPic->getPicYuvRec(), pcPic->getPicYuvRec(), accessUnit, dEncTime, snr_conversion, printFrameMSE ); } } } if (!digestStr.empty()) { if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 1) { printf(" [MD5:%s]", digestStr.c_str()); } else if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 2) { printf(" [CRC:%s]", digestStr.c_str()); } else if(m_pcCfg->getDecodedPictureHashSEIEnabled() == 3) { printf(" [Checksum:%s]", digestStr.c_str()); } } if ( m_pcCfg->getUseRateCtrl() ) { Double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP(); Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda(); if ( avgLambda < 0.0 ) { avgLambda = lambda; } m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType()); m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() ); m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits ); if ( pcSlice->getSliceType() != I_SLICE ) { m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits ); } else // for intra picture, the estimated bits are used to update the current status in the GOP { m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits ); } } if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) && ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) && ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() ) || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) ) { const TComVUI *vui = pcSlice->getSPS()->getVuiParameters(); const TComHRD *hrd = vui->getHrdParameters(); if( hrd->getSubPicCpbParamsPresentFlag() ) { Int i; UInt64 ui64Tmp; UInt uiPrev = 0; UInt numDU = ( pictureTimingSEI.m_numDecodingUnitsMinus1 + 1 ); UInt *pCRD = &pictureTimingSEI.m_duCpbRemovalDelayMinus1[0]; UInt maxDiff = ( hrd->getTickDivisorMinus2() + 2 ) - 1; for( i = 0; i < numDU; i ++ ) { pictureTimingSEI.m_numNalusInDuMinus1[ i ] = ( i == 0 ) ? ( accumNalsDU[ i ] - 1 ) : ( accumNalsDU[ i ] - accumNalsDU[ i - 1] - 1 ); } if( numDU == 1 ) { pCRD[ 0 ] = 0; /* don't care */ } else { pCRD[ numDU - 1 ] = 0;/* by definition */ UInt tmp = 0; UInt accum = 0; for( i = ( numDU - 2 ); i >= 0; i -- ) { ui64Tmp = ( ( ( accumBitsDU[ numDU - 1 ] - accumBitsDU[ i ] ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) ); if( (UInt)ui64Tmp > maxDiff ) { tmp ++; } } uiPrev = 0; UInt flag = 0; for( i = ( numDU - 2 ); i >= 0; i -- ) { flag = 0; ui64Tmp = ( ( ( accumBitsDU[ numDU - 1 ] - accumBitsDU[ i ] ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) ); if( (UInt)ui64Tmp > maxDiff ) { if(uiPrev >= maxDiff - tmp) { ui64Tmp = uiPrev + 1; flag = 1; } else { ui64Tmp = maxDiff - tmp + 1; } } pCRD[ i ] = (UInt)ui64Tmp - uiPrev - 1; if( (Int)pCRD[ i ] < 0 ) { pCRD[ i ] = 0; } else if (tmp > 0 && flag == 1) { tmp --; } accum += pCRD[ i ] + 1; uiPrev = accum; } } } if( m_pcCfg->getPictureTimingSEIEnabled() ) { { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI, pcSlice->getTLayer()); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); pictureTimingSEI.m_picStruct = (isField && pcSlice->getPic()->isTopField())? 1 : isField? 2 : 0; #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, pictureTimingSEI, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, pictureTimingSEI, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU + m_bufferingPeriodSEIPresentInAU; // Insert PT SEI after APS and BP SEI AccessUnit::iterator it = accessUnit.begin(); for(Int j = 0; j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(nalu)); m_pictureTimingSEIPresentInAU = true; } if ( m_pcCfg->getScalableNestingSEIEnabled() ) // put picture timing SEI into scalable nesting SEI { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI, pcSlice->getTLayer()); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); scalableNestingSEI.m_nestedSEIs.clear(); scalableNestingSEI.m_nestedSEIs.push_back(&pictureTimingSEI); #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, scalableNestingSEI, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, scalableNestingSEI, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU + m_bufferingPeriodSEIPresentInAU + m_pictureTimingSEIPresentInAU + m_nestedBufferingPeriodSEIPresentInAU; // Insert PT SEI after APS and BP SEI AccessUnit::iterator it = accessUnit.begin(); for(Int j = 0; j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(nalu)); m_nestedPictureTimingSEIPresentInAU = true; } } if( m_pcCfg->getDecodingUnitInfoSEIEnabled() && hrd->getSubPicCpbParamsPresentFlag() ) { m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); for( Int i = 0; i < ( pictureTimingSEI.m_numDecodingUnitsMinus1 + 1 ); i ++ ) { OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI, pcSlice->getTLayer()); SEIDecodingUnitInfo tempSEI; tempSEI.m_decodingUnitIdx = i; tempSEI.m_duSptCpbRemovalDelay = pictureTimingSEI.m_duCpbRemovalDelayMinus1[i] + 1; tempSEI.m_dpbOutputDuDelayPresentFlag = false; tempSEI.m_picSptDpbOutputDuDelay = picSptDpbOutputDuDelay; // Insert the first one in the right location, before the first slice if(i == 0) { // Insert before the first slice. #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, tempSEI, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, tempSEI, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); UInt seiPositionInAu = xGetFirstSeiLocation(accessUnit); UInt offsetPosition = m_activeParameterSetSEIPresentInAU + m_bufferingPeriodSEIPresentInAU + m_pictureTimingSEIPresentInAU; // Insert DU info SEI after APS, BP and PT SEI AccessUnit::iterator it = accessUnit.begin(); for(Int j = 0; j < seiPositionInAu + offsetPosition; j++) { it++; } accessUnit.insert(it, new NALUnitEBSP(nalu)); } else { // For the second decoding unit onwards we know how many NALUs are present AccessUnit::iterator it = accessUnit.begin(); for (Int ctr = 0; it != accessUnit.end(); it++) { if(ctr == accumNalsDU[ i - 1 ]) { // Insert before the first slice. #if O0164_MULTI_LAYER_HRD m_seiWriter.writeSEImessage(nalu.m_Bitstream, tempSEI, m_pcEncTop->getVPS(), pcSlice->getSPS()); #else m_seiWriter.writeSEImessage(nalu.m_Bitstream, tempSEI, pcSlice->getSPS()); #endif writeRBSPTrailingBits(nalu.m_Bitstream); accessUnit.insert(it, new NALUnitEBSP(nalu)); break; } if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI) { ctr++; } } } } } } #if SVC_EXTENSION m_prevPicHasEos = false; if (m_pcCfg->getLayerSwitchOffBegin() < m_pcCfg->getLayerSwitchOffEnd()) { Int pocNext; if (iGOPid == m_iGopSize - 1) { pocNext = iPOCLast - iNumPicRcvd + m_iGopSize + m_pcCfg->getGOPEntry(0).m_POC; } else { pocNext = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid + 1).m_POC; } if (pocNext > m_pcCfg->getLayerSwitchOffBegin() && pocCurr < m_pcCfg->getLayerSwitchOffEnd()) { OutputNALUnit nalu(NAL_UNIT_EOS, 0, pcSlice->getLayerId()); m_pcEntropyCoder->setEntropyCoder(m_pcCavlcCoder, pcSlice); accessUnit.push_back(new NALUnitEBSP(nalu)); m_prevPicHasEos = true; } } #endif xResetNonNestedSEIPresentFlags(); xResetNestedSEIPresentFlags(); pcPic->getPicYuvRec()->copyToPic(pcPicYuvRecOut); #if SVC_EXTENSION pcPicYuvRecOut->setReconstructed(true); m_pcEncTop->setFirstPicInLayerDecodedFlag(true); #endif pcPic->setReconMark ( true ); m_bFirst = false; m_iNumPicCoded++; m_totalCoded ++; /* logging: insert a newline at end of picture period */ printf("\n"); fflush(stdout); #if EFFICIENT_FIELD_IRAP if(IRAPtoReorder) { if(swapIRAPForward) { if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid +1; IRAPtoReorder = false; } else if(iGOPid == IRAPGOPid +1) { iGOPid --; } } else { if(iGOPid == IRAPGOPid) { iGOPid = IRAPGOPid -1; } else if(iGOPid == IRAPGOPid -1) { iGOPid = IRAPGOPid; IRAPtoReorder = false; } } } #endif } // iGOPid-loop delete pcBitstreamRedirect; if( accumBitsDU != NULL) { delete accumBitsDU; } if( accumNalsDU != NULL) { delete accumNalsDU; } #if SVC_EXTENSION assert ( m_iNumPicCoded <= 1 ); #else assert ( (m_iNumPicCoded == iNumPicRcvd) ); #endif } #if !SVC_EXTENSION Void TEncGOP::printOutSummary(UInt uiNumAllPicCoded, Bool isField, const Bool printMSEBasedSNR, const Bool printSequenceMSE) { assert (uiNumAllPicCoded == m_gcAnalyzeAll.getNumPic()); //--CFG_KDY const Int rateMultiplier=(isField?2:1); m_gcAnalyzeAll.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier ); m_gcAnalyzeI.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier ); m_gcAnalyzeP.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier ); m_gcAnalyzeB.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier ); const ChromaFormat chFmt = m_pcCfg->getChromaFormatIdc(); //-- all printf( "\n\nSUMMARY --------------------------------------------------------\n" ); m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE); printf( "\n\nI Slices--------------------------------------------------------\n" ); m_gcAnalyzeI.printOut('i', chFmt, printMSEBasedSNR, printSequenceMSE); printf( "\n\nP Slices--------------------------------------------------------\n" ); m_gcAnalyzeP.printOut('p', chFmt, printMSEBasedSNR, printSequenceMSE); printf( "\n\nB Slices--------------------------------------------------------\n" ); m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE); #if _SUMMARY_OUT_ m_gcAnalyzeAll.printSummary(chFmt, printSequenceMSE); #endif #if _SUMMARY_PIC_ m_gcAnalyzeI.printSummary(chFmt, printSequenceMSE,'I'); m_gcAnalyzeP.printSummary(chFmt, printSequenceMSE,'P'); m_gcAnalyzeB.printSummary(chFmt, printSequenceMSE,'B'); #endif if(isField) { //-- interlaced summary m_gcAnalyzeAll_in.setFrmRate( m_pcCfg->getFrameRate()); m_gcAnalyzeAll_in.setBits(m_gcAnalyzeAll.getBits()); // prior to the above statement, the interlace analyser does not contain the correct total number of bits. printf( "\n\nSUMMARY INTERLACED ---------------------------------------------\n" ); m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE); #if _SUMMARY_OUT_ m_gcAnalyzeAll_in.printSummary(chFmt, printSequenceMSE); #endif } printf("\nRVM: %.3lf\n" , xCalculateRVM()); } #endif Void TEncGOP::preLoopFilterPicAll( TComPic* pcPic, UInt64& ruiDist ) { Bool bCalcDist = false; m_pcLoopFilter->setCfg(m_pcCfg->getLFCrossTileBoundaryFlag()); m_pcLoopFilter->loopFilterPic( pcPic ); if (!bCalcDist) { ruiDist = xFindDistortionFrame(pcPic->getPicYuvOrg(), pcPic->getPicYuvRec()); } } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== Void TEncGOP::xInitGOP( Int iPOCLast, Int iNumPicRcvd, TComList& rcListPic, TComList& rcListPicYuvRecOut, Bool isField ) { assert( iNumPicRcvd > 0 ); // Exception for the first frames if ( ( isField && (iPOCLast == 0 || iPOCLast == 1) ) || (!isField && (iPOCLast == 0)) ) { m_iGopSize = 1; } else { m_iGopSize = m_pcCfg->getGOPSize(); } assert (m_iGopSize > 0); return; } Void TEncGOP::xGetBuffer( TComList& rcListPic, TComList& rcListPicYuvRecOut, Int iNumPicRcvd, Int iTimeOffset, TComPic*& rpcPic, TComPicYuv*& rpcPicYuvRecOut, Int pocCurr, Bool isField) { Int i; // Rec. output TComList::iterator iterPicYuvRec = rcListPicYuvRecOut.end(); if (isField && pocCurr > 1 && m_iGopSize!=1) { iTimeOffset--; } for ( i = 0; i < (iNumPicRcvd - iTimeOffset + 1); i++ ) { iterPicYuvRec--; } rpcPicYuvRecOut = *(iterPicYuvRec); // Current pic. TComList::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); rpcPic->setCurrSliceIdx(0); if (rpcPic->getPOC() == pocCurr) { break; } iterPic++; } assert (rpcPic != NULL); assert (rpcPic->getPOC() == pocCurr); return; } UInt64 TEncGOP::xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1) { UInt64 uiTotalDiff = 0; for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); Pel* pSrc0 = pcPic0 ->getAddr(ch); Pel* pSrc1 = pcPic1 ->getAddr(ch); UInt uiShift = 2 * DISTORTION_PRECISION_ADJUSTMENT(g_bitDepth[toChannelType(ch)]-8); const Int iStride = pcPic0->getStride(ch); const Int iWidth = pcPic0->getWidth(ch); const Int iHeight = pcPic0->getHeight(ch); for(Int y = 0; y < iHeight; y++ ) { for(Int x = 0; x < iWidth; x++ ) { Intermediate_Int iTemp = pSrc0[x] - pSrc1[x]; uiTotalDiff += UInt64((iTemp*iTemp) >> uiShift); } pSrc0 += iStride; pSrc1 += iStride; } } return uiTotalDiff; } #if VERBOSE_RATE static const Char* nalUnitTypeToString(NalUnitType type) { switch (type) { case NAL_UNIT_CODED_SLICE_TRAIL_R: return "TRAIL_R"; case NAL_UNIT_CODED_SLICE_TRAIL_N: return "TRAIL_N"; case NAL_UNIT_CODED_SLICE_TSA_R: return "TSA_R"; case NAL_UNIT_CODED_SLICE_TSA_N: return "TSA_N"; case NAL_UNIT_CODED_SLICE_STSA_R: return "STSA_R"; case NAL_UNIT_CODED_SLICE_STSA_N: return "STSA_N"; case NAL_UNIT_CODED_SLICE_BLA_W_LP: return "BLA_W_LP"; case NAL_UNIT_CODED_SLICE_BLA_W_RADL: return "BLA_W_RADL"; case NAL_UNIT_CODED_SLICE_BLA_N_LP: return "BLA_N_LP"; case NAL_UNIT_CODED_SLICE_IDR_W_RADL: return "IDR_W_RADL"; case NAL_UNIT_CODED_SLICE_IDR_N_LP: return "IDR_N_LP"; case NAL_UNIT_CODED_SLICE_CRA: return "CRA"; case NAL_UNIT_CODED_SLICE_RADL_R: return "RADL_R"; case NAL_UNIT_CODED_SLICE_RADL_N: return "RADL_N"; case NAL_UNIT_CODED_SLICE_RASL_R: return "RASL_R"; case NAL_UNIT_CODED_SLICE_RASL_N: return "RASL_N"; case NAL_UNIT_VPS: return "VPS"; case NAL_UNIT_SPS: return "SPS"; case NAL_UNIT_PPS: return "PPS"; case NAL_UNIT_ACCESS_UNIT_DELIMITER: return "AUD"; case NAL_UNIT_EOS: return "EOS"; case NAL_UNIT_EOB: return "EOB"; case NAL_UNIT_FILLER_DATA: return "FILLER"; case NAL_UNIT_PREFIX_SEI: return "SEI"; case NAL_UNIT_SUFFIX_SEI: return "SEI"; default: return "UNK"; } } #endif Void TEncGOP::xCalculateAddPSNR( TComPic* pcPic, TComPicYuv* pcPicD, const AccessUnit& accessUnit, Double dEncTime, const InputColourSpaceConversion conversion, const Bool printFrameMSE ) { Double dPSNR[MAX_NUM_COMPONENT]; for(Int i=0; igetWidth(COMPONENT_Y), pcPicD->getHeight(COMPONENT_Y), pcPicD->getChromaFormat(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth); TVideoIOYuv::ColourSpaceConvert(*pcPicD, cscd, conversion, g_bitDepth, false); } TComPicYuv &picd=(conversion==IPCOLOURSPACE_UNCHANGED)?*pcPicD : cscd; //===== calculate PSNR ===== Double MSEyuvframe[MAX_NUM_COMPONENT] = {0, 0, 0}; for(Int chan=0; changetNumberValidComponents(); chan++) { const ComponentID ch=ComponentID(chan); const Pel* pOrg = (conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg()->getAddr(ch) : pcPic ->getPicYuvOrg()->getAddr(ch); Pel* pRec = picd.getAddr(ch); const Int iStride = pcPicD->getStride(ch); const Int iWidth = pcPicD->getWidth (ch) - (m_pcEncTop->getPad(0) >> pcPic->getComponentScaleX(ch)); const Int iHeight = pcPicD->getHeight(ch) - ((m_pcEncTop->getPad(1) >> (pcPic->isField()?1:0)) >> pcPic->getComponentScaleY(ch)); Int iSize = iWidth*iHeight; UInt64 uiSSDtemp=0; for(Int y = 0; y < iHeight; y++ ) { for(Int x = 0; x < iWidth; x++ ) { Intermediate_Int iDiff = (Intermediate_Int)( pOrg[x] - pRec[x] ); uiSSDtemp += iDiff * iDiff; } pOrg += iStride; pRec += iStride; } const Int maxval = 255 << (g_bitDepth[toChannelType(ch)] - 8); const Double fRefValue = (Double) maxval * maxval * iSize; dPSNR[ch] = ( uiSSDtemp ? 10.0 * log10( fRefValue / (Double)uiSSDtemp ) : 999.99 ); MSEyuvframe[ch] = (Double)uiSSDtemp/(iSize); } /* calculate the size of the access unit, excluding: * - any AnnexB contributions (start_code_prefix, zero_byte, etc.,) * - SEI NAL units */ UInt numRBSPBytes = 0; for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++) { UInt numRBSPBytes_nal = UInt((*it)->m_nalUnitData.str().size()); #if VERBOSE_RATE printf("*** %6s numBytesInNALunit: %u\n", nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal); #endif if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI) { numRBSPBytes += numRBSPBytes_nal; } } UInt uibits = numRBSPBytes * 8; m_vRVM_RP.push_back( uibits ); //===== add PSNR ===== #if SVC_EXTENSION m_gcAnalyzeAll[pcPic->getSlice(0)->getVPS()->getLayerIdxInVps(m_layerId)].addResult (dPSNR, (Double)uibits, MSEyuvframe); TComSlice* pcSlice = pcPic->getSlice(0); if (pcSlice->isIntra()) { m_gcAnalyzeI[pcPic->getSlice(0)->getVPS()->getLayerIdxInVps(m_layerId)].addResult (dPSNR, (Double)uibits, MSEyuvframe); } if (pcSlice->isInterP()) { m_gcAnalyzeP[pcPic->getSlice(0)->getVPS()->getLayerIdxInVps(m_layerId)].addResult (dPSNR, (Double)uibits, MSEyuvframe); } if (pcSlice->isInterB()) { m_gcAnalyzeB[pcPic->getSlice(0)->getVPS()->getLayerIdxInVps(m_layerId)].addResult (dPSNR, (Double)uibits, MSEyuvframe); } #else m_gcAnalyzeAll.addResult (dPSNR, (Double)uibits, MSEyuvframe); TComSlice* pcSlice = pcPic->getSlice(0); if (pcSlice->isIntra()) { m_gcAnalyzeI.addResult (dPSNR, (Double)uibits, MSEyuvframe); } if (pcSlice->isInterP()) { m_gcAnalyzeP.addResult (dPSNR, (Double)uibits, MSEyuvframe); } if (pcSlice->isInterB()) { m_gcAnalyzeB.addResult (dPSNR, (Double)uibits, MSEyuvframe); } #endif Char c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B'); if (!pcSlice->isReferenced()) { c += 32; } #if SVC_EXTENSION #if ADAPTIVE_QP_SELECTION printf("POC %4d LId: %1d TId: %1d ( %c-SLICE %s, nQP %d QP %d ) %10d bits", pcSlice->getPOC(), pcSlice->getLayerId(), pcSlice->getTLayer(), c, NaluToStr( pcSlice->getNalUnitType() ).data(), pcSlice->getSliceQpBase(), pcSlice->getSliceQp(), uibits ); #else printf("POC %4d LId: %1d TId: %1d ( %c-SLICE %s, QP %d ) %10d bits", pcSlice->getPOC()-pcSlice->getLastIDR(), pcSlice->getLayerId(), pcSlice->getTLayer(), c, NaluToStr( pcSlice->getNalUnitType() ).data(), pcSlice->getSliceQp(), uibits ); #endif #else #if ADAPTIVE_QP_SELECTION printf("POC %4d TId: %1d ( %c-SLICE, nQP %d QP %d ) %10d bits", pcSlice->getPOC(), pcSlice->getTLayer(), c, pcSlice->getSliceQpBase(), pcSlice->getSliceQp(), uibits ); #else printf("POC %4d TId: %1d ( %c-SLICE, QP %d ) %10d bits", pcSlice->getPOC()-pcSlice->getLastIDR(), pcSlice->getTLayer(), c, pcSlice->getSliceQp(), uibits ); #endif #endif printf(" [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", dPSNR[COMPONENT_Y], dPSNR[COMPONENT_Cb], dPSNR[COMPONENT_Cr] ); if (printFrameMSE) { printf(" [Y MSE %6.4lf U MSE %6.4lf V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] ); } printf(" [ET %5.0f ]", dEncTime ); for (Int iRefList = 0; iRefList < 2; iRefList++) { printf(" [L%d ", iRefList); for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++) { #if SVC_EXTENSION if( pcSlice->getRefPic(RefPicList(iRefList), iRefIndex)->isILR(m_layerId) ) { UInt refLayerId = pcSlice->getRefPic(RefPicList(iRefList), iRefIndex)->getLayerId(); UInt refLayerIdc = pcSlice->getReferenceLayerIdc(refLayerId); assert( g_posScalingFactor[refLayerIdc][0] ); assert( g_posScalingFactor[refLayerIdc][1] ); printf( "%d(%d, {%1.2f, %1.2f}x)", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex), refLayerId, 65536.0/g_posScalingFactor[refLayerIdc][0], 65536.0/g_posScalingFactor[refLayerIdc][1] ); } else { printf ("%d", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)); } if( pcSlice->getEnableTMVPFlag() && iRefList == 1 - pcSlice->getColFromL0Flag() && iRefIndex == pcSlice->getColRefIdx() ) { printf( "c" ); } printf( " " ); #else printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)-pcSlice->getLastIDR()); #endif } printf("]"); } #if CGS_3D_ASYMLUT pcPic->setFrameBit( (Int)uibits ); if( m_layerId && pcSlice->getPPS()->getCGSFlag() ) { #if R0179_ENC_OPT_3DLUT_SIZE m_Enc3DAsymLUTPicUpdate.update3DAsymLUTParam( &m_Enc3DAsymLUTPPS ); #else if( m_Enc3DAsymLUTPPS.getPPSBit() > 0 ) m_Enc3DAsymLUTPicUpdate.copy3DAsymLUT( &m_Enc3DAsymLUTPPS ); #endif m_Enc3DAsymLUTPicUpdate.updatePicCGSBits( pcSlice , m_Enc3DAsymLUTPPS.getPPSBit() ); } #endif cscd.destroy(); } Void TEncGOP::xCalculateInterlacedAddPSNR( TComPic* pcPicOrgFirstField, TComPic* pcPicOrgSecondField, TComPicYuv* pcPicRecFirstField, TComPicYuv* pcPicRecSecondField, const AccessUnit& accessUnit, Double dEncTime, const InputColourSpaceConversion conversion, const Bool printFrameMSE ) { Double dPSNR[MAX_NUM_COMPONENT]; TComPic *apcPicOrgFields[2]={pcPicOrgFirstField, pcPicOrgSecondField}; TComPicYuv *apcPicRecFields[2]={pcPicRecFirstField, pcPicRecSecondField}; for(Int i=0; igetChromaFormat()==apcPicRecFields[1]->getChromaFormat()); const UInt numValidComponents=apcPicRecFields[0]->getNumberValidComponents(); for(Int chan=0; changetWidth(ch)==apcPicRecFields[1]->getWidth(ch)); assert(apcPicRecFields[0]->getHeight(ch)==apcPicRecFields[1]->getHeight(ch)); UInt64 uiSSDtemp=0; const Int iWidth = apcPicRecFields[0]->getWidth (ch) - (m_pcEncTop->getPad(0) >> apcPicRecFields[0]->getComponentScaleX(ch)); const Int iHeight = apcPicRecFields[0]->getHeight(ch) - ((m_pcEncTop->getPad(1) >> 1) >> apcPicRecFields[0]->getComponentScaleY(ch)); Int iSize = iWidth*iHeight; for(UInt fieldNum=0; fieldNum<2; fieldNum++) { TComPic *pcPic=apcPicOrgFields[fieldNum]; TComPicYuv *pcPicD=apcPicRecFields[fieldNum]; const Pel* pOrg = (conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg()->getAddr(ch) : pcPic ->getPicYuvOrg()->getAddr(ch); Pel* pRec = pcPicD->getAddr(ch); const Int iStride = pcPicD->getStride(ch); for(Int y = 0; y < iHeight; y++ ) { for(Int x = 0; x < iWidth; x++ ) { Intermediate_Int iDiff = (Intermediate_Int)( pOrg[x] - pRec[x] ); uiSSDtemp += iDiff * iDiff; } pOrg += iStride; pRec += iStride; } } const Int maxval = 255 << (g_bitDepth[toChannelType(ch)] - 8); const Double fRefValue = (Double) maxval * maxval * iSize*2; dPSNR[ch] = ( uiSSDtemp ? 10.0 * log10( fRefValue / (Double)uiSSDtemp ) : 999.99 ); MSEyuvframe[ch] = (Double)uiSSDtemp/(iSize*2); } UInt uibits = 0; // the number of bits for the pair is not calculated here - instead the overall total is used elsewhere. //===== add PSNR ===== m_gcAnalyzeAll_in.addResult (dPSNR, (Double)uibits, MSEyuvframe); printf("\n Interlaced frame %d: [Y %6.4lf dB U %6.4lf dB V %6.4lf dB]", pcPicOrgSecondField->getPOC()/2 , dPSNR[COMPONENT_Y], dPSNR[COMPONENT_Cb], dPSNR[COMPONENT_Cr] ); if (printFrameMSE) { printf(" [Y MSE %6.4lf U MSE %6.4lf V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] ); } for(UInt fieldNum=0; fieldNum<2; fieldNum++) { cscd[fieldNum].destroy(); } } /** Function for deciding the nal_unit_type. * \param pocCurr POC of the current picture * \param lastIDR POC of the last IDR picture * \param isField true to indicate field coding * \returns the NAL unit type of the picture * This function checks the configuration and returns the appropriate nal_unit_type for the picture. */ NalUnitType TEncGOP::getNalUnitType(Int pocCurr, Int lastIDR, Bool isField) { if (pocCurr == 0) { return NAL_UNIT_CODED_SLICE_IDR_W_RADL; } #if EFFICIENT_FIELD_IRAP if(isField && pocCurr == 1) { // to avoid the picture becoming an IRAP return NAL_UNIT_CODED_SLICE_TRAIL_R; } #endif #if ALLOW_RECOVERY_POINT_AS_RAP if(m_pcCfg->getDecodingRefreshType() != 3 && (pocCurr - isField) % m_pcCfg->getIntraPeriod() == 0) #else if ((pocCurr - isField) % m_pcCfg->getIntraPeriod() == 0) #endif { if (m_pcCfg->getDecodingRefreshType() == 1) { return NAL_UNIT_CODED_SLICE_CRA; } else if (m_pcCfg->getDecodingRefreshType() == 2) { return NAL_UNIT_CODED_SLICE_IDR_W_RADL; } } #if SVC_POC if( m_pocCraWithoutReset > 0 && m_associatedIRAPType == NAL_UNIT_CODED_SLICE_CRA ) { if(pocCurr < m_pocCraWithoutReset) #else if(m_pocCRA>0) { if(pocCurr0) { if (pocCurr < lastIDR) { return NAL_UNIT_CODED_SLICE_RADL_R; } } return NAL_UNIT_CODED_SLICE_TRAIL_R; } Double TEncGOP::xCalculateRVM() { Double dRVM = 0; if( m_pcCfg->getGOPSize() == 1 && m_pcCfg->getIntraPeriod() != 1 && m_pcCfg->getFramesToBeEncoded() > RVM_VCEGAM10_M * 2 ) { // calculate RVM only for lowdelay configurations std::vector vRL , vB; size_t N = m_vRVM_RP.size(); vRL.resize( N ); vB.resize( N ); Int i; Double dRavg = 0 , dBavg = 0; vB[RVM_VCEGAM10_M] = 0; for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ ) { vRL[i] = 0; for( Int j = i - RVM_VCEGAM10_M ; j <= i + RVM_VCEGAM10_M - 1 ; j++ ) { vRL[i] += m_vRVM_RP[j]; } vRL[i] /= ( 2 * RVM_VCEGAM10_M ); vB[i] = vB[i-1] + m_vRVM_RP[i] - vRL[i]; dRavg += m_vRVM_RP[i]; dBavg += vB[i]; } dRavg /= ( N - 2 * RVM_VCEGAM10_M ); dBavg /= ( N - 2 * RVM_VCEGAM10_M ); Double dSigamB = 0; for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ ) { Double tmp = vB[i] - dBavg; dSigamB += tmp * tmp; } dSigamB = sqrt( dSigamB / ( N - 2 * RVM_VCEGAM10_M ) ); Double f = sqrt( 12.0 * ( RVM_VCEGAM10_M - 1 ) / ( RVM_VCEGAM10_M + 1 ) ); dRVM = dSigamB / dRavg * f; } return( dRVM ); } /** Attaches the input bitstream to the stream in the output NAL unit Updates rNalu to contain concatenated bitstream. rpcBitstreamRedirect is cleared at the end of this function call. * \param codedSliceData contains the coded slice data (bitstream) to be concatenated to rNalu * \param rNalu target NAL unit */ Void TEncGOP::xAttachSliceDataToNalUnit (OutputNALUnit& rNalu, TComOutputBitstream* codedSliceData) { // Byte-align rNalu.m_Bitstream.writeByteAlignment(); // Slice header byte-alignment // Perform bitstream concatenation if (codedSliceData->getNumberOfWrittenBits() > 0) { rNalu.m_Bitstream.addSubstream(codedSliceData); } m_pcEntropyCoder->setBitstream(&rNalu.m_Bitstream); codedSliceData->clear(); } // Function will arrange the long-term pictures in the decreasing order of poc_lsb_lt, // and among the pictures with the same lsb, it arranges them in increasing delta_poc_msb_cycle_lt value Void TEncGOP::arrangeLongtermPicturesInRPS(TComSlice *pcSlice, TComList& rcListPic) { TComReferencePictureSet *rps = pcSlice->getRPS(); if(!rps->getNumberOfLongtermPictures()) { return; } // Arrange long-term reference pictures in the correct order of LSB and MSB, // and assign values for pocLSBLT and MSB present flag Int longtermPicsPoc[MAX_NUM_REF_PICS], longtermPicsLSB[MAX_NUM_REF_PICS], indices[MAX_NUM_REF_PICS]; Int longtermPicsMSB[MAX_NUM_REF_PICS]; Bool mSBPresentFlag[MAX_NUM_REF_PICS]; ::memset(longtermPicsPoc, 0, sizeof(longtermPicsPoc)); // Store POC values of LTRP ::memset(longtermPicsLSB, 0, sizeof(longtermPicsLSB)); // Store POC LSB values of LTRP ::memset(longtermPicsMSB, 0, sizeof(longtermPicsMSB)); // Store POC LSB values of LTRP ::memset(indices , 0, sizeof(indices)); // Indices to aid in tracking sorted LTRPs ::memset(mSBPresentFlag , 0, sizeof(mSBPresentFlag)); // Indicate if MSB needs to be present // Get the long-term reference pictures Int offset = rps->getNumberOfNegativePictures() + rps->getNumberOfPositivePictures(); Int i, ctr = 0; Int maxPicOrderCntLSB = 1 << pcSlice->getSPS()->getBitsForPOC(); for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { longtermPicsPoc[ctr] = rps->getPOC(i); // LTRP POC longtermPicsLSB[ctr] = getLSB(longtermPicsPoc[ctr], maxPicOrderCntLSB); // LTRP POC LSB indices[ctr] = i; longtermPicsMSB[ctr] = longtermPicsPoc[ctr] - longtermPicsLSB[ctr]; } Int numLongPics = rps->getNumberOfLongtermPictures(); assert(ctr == numLongPics); // Arrange pictures in decreasing order of MSB; for(i = 0; i < numLongPics; i++) { for(Int j = 0; j < numLongPics - 1; j++) { if(longtermPicsMSB[j] < longtermPicsMSB[j+1]) { std::swap(longtermPicsPoc[j], longtermPicsPoc[j+1]); std::swap(longtermPicsLSB[j], longtermPicsLSB[j+1]); std::swap(longtermPicsMSB[j], longtermPicsMSB[j+1]); std::swap(indices[j] , indices[j+1] ); } } } for(i = 0; i < numLongPics; i++) { // Check if MSB present flag should be enabled. // Check if the buffer contains any pictures that have the same LSB. TComList::iterator iterPic = rcListPic.begin(); TComPic* pcPic; while ( iterPic != rcListPic.end() ) { pcPic = *iterPic; if( (getLSB(pcPic->getPOC(), maxPicOrderCntLSB) == longtermPicsLSB[i]) && // Same LSB (pcPic->getSlice(0)->isReferenced()) && // Reference picture (pcPic->getPOC() != longtermPicsPoc[i]) ) // Not the LTRP itself { mSBPresentFlag[i] = true; break; } iterPic++; } } // tempArray for usedByCurr flag Bool tempArray[MAX_NUM_REF_PICS]; ::memset(tempArray, 0, sizeof(tempArray)); for(i = 0; i < numLongPics; i++) { tempArray[i] = rps->getUsed(indices[i]); } // Now write the final values; ctr = 0; Int currMSB = 0, currLSB = 0; // currPicPoc = currMSB + currLSB currLSB = getLSB(pcSlice->getPOC(), maxPicOrderCntLSB); currMSB = pcSlice->getPOC() - currLSB; for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++) { rps->setPOC (i, longtermPicsPoc[ctr]); rps->setDeltaPOC (i, - pcSlice->getPOC() + longtermPicsPoc[ctr]); rps->setUsed (i, tempArray[ctr]); rps->setPocLSBLT (i, longtermPicsLSB[ctr]); rps->setDeltaPocMSBCycleLT (i, (currMSB - (longtermPicsPoc[ctr] - longtermPicsLSB[ctr])) / maxPicOrderCntLSB); rps->setDeltaPocMSBPresentFlag(i, mSBPresentFlag[ctr]); assert(rps->getDeltaPocMSBCycleLT(i) >= 0); // Non-negative value } for(i = rps->getNumberOfPictures() - 1, ctr = 1; i >= offset; i--, ctr++) { for(Int j = rps->getNumberOfPictures() - 1 - ctr; j >= offset; j--) { // Here at the encoder we know that we have set the full POC value for the LTRPs, hence we // don't have to check the MSB present flag values for this constraint. assert( rps->getPOC(i) != rps->getPOC(j) ); // If assert fails, LTRP entry repeated in RPS!!! } } } /** Function for finding the position to insert the first of APS and non-nested BP, PT, DU info SEI messages. * \param accessUnit Access Unit of the current picture * This function finds the position to insert the first of APS and non-nested BP, PT, DU info SEI messages. */ Int TEncGOP::xGetFirstSeiLocation(AccessUnit &accessUnit) { // Find the location of the first SEI message Int seiStartPos = 0; for(AccessUnit::iterator it = accessUnit.begin(); it != accessUnit.end(); it++, seiStartPos++) { if ((*it)->isSei() || (*it)->isVcl()) { break; } } // assert(it != accessUnit.end()); // Triggers with some legit configurations return seiStartPos; } Void TEncGOP::applyDeblockingFilterMetric( TComPic* pcPic, UInt uiNumSlices ) { TComPicYuv* pcPicYuvRec = pcPic->getPicYuvRec(); Pel* Rec = pcPicYuvRec->getAddr(COMPONENT_Y); Pel* tempRec = Rec; Int stride = pcPicYuvRec->getStride(COMPONENT_Y); UInt log2maxTB = pcPic->getSlice(0)->getSPS()->getQuadtreeTULog2MaxSize(); UInt maxTBsize = (1<getWidth(COMPONENT_Y); const UInt picHeight = pcPicYuvRec->getHeight(COMPONENT_Y); const UInt noCol = (picWidth>>log2maxTB); const UInt noRows = (picHeight>>log2maxTB); assert(noCol > 1); assert(noRows > 1); UInt64 *colSAD = (UInt64*)malloc(noCol*sizeof(UInt64)); UInt64 *rowSAD = (UInt64*)malloc(noRows*sizeof(UInt64)); UInt colIdx = 0; UInt rowIdx = 0; Pel p0, p1, p2, q0, q1, q2; Int qp = pcPic->getSlice(0)->getSliceQp(); Int bitdepthScale = 1 << (g_bitDepth[CHANNEL_TYPE_LUMA]-8); Int beta = TComLoopFilter::getBeta( qp ) * bitdepthScale; const Int thr2 = (beta>>2); const Int thr1 = 2*bitdepthScale; UInt a = 0; memset(colSAD, 0, noCol*sizeof(UInt64)); memset(rowSAD, 0, noRows*sizeof(UInt64)); if (maxTBsize > minBlockArtSize) { // Analyze vertical artifact edges for(Int c = maxTBsize; c < picWidth; c += maxTBsize) { for(Int r = 0; r < picHeight; r++) { p2 = Rec[c-3]; p1 = Rec[c-2]; p0 = Rec[c-1]; q0 = Rec[c]; q1 = Rec[c+1]; q2 = Rec[c+2]; a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1); if ( thr1 < a && a < thr2) { colSAD[colIdx] += abs(p0 - q0); } Rec += stride; } colIdx++; Rec = tempRec; } // Analyze horizontal artifact edges for(Int r = maxTBsize; r < picHeight; r += maxTBsize) { for(Int c = 0; c < picWidth; c++) { p2 = Rec[c + (r-3)*stride]; p1 = Rec[c + (r-2)*stride]; p0 = Rec[c + (r-1)*stride]; q0 = Rec[c + r*stride]; q1 = Rec[c + (r+1)*stride]; q2 = Rec[c + (r+2)*stride]; a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1); if (thr1 < a && a < thr2) { rowSAD[rowIdx] += abs(p0 - q0); } } rowIdx++; } } UInt64 colSADsum = 0; UInt64 rowSADsum = 0; for(Int c = 0; c < noCol-1; c++) { colSADsum += colSAD[c]; } for(Int r = 0; r < noRows-1; r++) { rowSADsum += rowSAD[r]; } colSADsum <<= 10; rowSADsum <<= 10; colSADsum /= (noCol-1); colSADsum /= picHeight; rowSADsum /= (noRows-1); rowSADsum /= picWidth; UInt64 avgSAD = ((colSADsum + rowSADsum)>>1); avgSAD >>= (g_bitDepth[CHANNEL_TYPE_LUMA]-8); if ( avgSAD > 2048 ) { avgSAD >>= 9; Int offset = Clip3(2,6,(Int)avgSAD); for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(true); pcPic->getSlice(i)->setDeblockingFilterDisable(false); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( offset ); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( offset ); } } else { for (Int i=0; igetSlice(i)->setDeblockingFilterOverrideFlag(false); pcPic->getSlice(i)->setDeblockingFilterDisable( pcPic->getSlice(i)->getPPS()->getPicDisableDeblockingFilterFlag() ); pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterBetaOffsetDiv2() ); pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterTcOffsetDiv2() ); } } free(colSAD); free(rowSAD); } #if P0123_ALPHA_CHANNEL_SEI SEIAlphaChannelInfo* TEncGOP::xCreateSEIAlphaChannelInfo() { SEIAlphaChannelInfo *sei = new SEIAlphaChannelInfo(); sei->m_alphaChannelCancelFlag = m_pcCfg->getAlphaCancelFlag(); if(!sei->m_alphaChannelCancelFlag) { sei->m_alphaChannelUseIdc = m_pcCfg->getAlphaUseIdc(); sei->m_alphaChannelBitDepthMinus8 = m_pcCfg->getAlphaBitDepthMinus8(); sei->m_alphaTransparentValue = m_pcCfg->getAlphaTransparentValue(); sei->m_alphaOpaqueValue = m_pcCfg->getAlphaOpaqueValue(); sei->m_alphaChannelIncrFlag = m_pcCfg->getAlphaIncrementFlag(); sei->m_alphaChannelClipFlag = m_pcCfg->getAlphaClipFlag(); sei->m_alphaChannelClipTypeFlag = m_pcCfg->getAlphaClipTypeFlag(); } return sei; } #endif #if Q0096_OVERLAY_SEI SEIOverlayInfo* TEncGOP::xCreateSEIOverlayInfo() { SEIOverlayInfo *sei = new SEIOverlayInfo(); sei->m_overlayInfoCancelFlag = m_pcCfg->getOverlaySEICancelFlag(); if ( !sei->m_overlayInfoCancelFlag ) { sei->m_overlayContentAuxIdMinus128 = m_pcCfg->getOverlaySEIContentAuxIdMinus128(); sei->m_overlayLabelAuxIdMinus128 = m_pcCfg->getOverlaySEILabelAuxIdMinus128(); sei->m_overlayAlphaAuxIdMinus128 = m_pcCfg->getOverlaySEIAlphaAuxIdMinus128(); sei->m_overlayElementLabelValueLengthMinus8 = m_pcCfg->getOverlaySEIElementLabelValueLengthMinus8(); sei->m_numOverlaysMinus1 = m_pcCfg->getOverlaySEINumOverlaysMinus1(); sei->m_overlayIdx = m_pcCfg->getOverlaySEIIdx(); sei->m_languageOverlayPresentFlag = m_pcCfg->getOverlaySEILanguagePresentFlag(); sei->m_overlayContentLayerId = m_pcCfg->getOverlaySEIContentLayerId(); sei->m_overlayLabelPresentFlag = m_pcCfg->getOverlaySEILabelPresentFlag(); sei->m_overlayLabelLayerId = m_pcCfg->getOverlaySEILabelLayerId(); sei->m_overlayAlphaPresentFlag = m_pcCfg->getOverlaySEIAlphaPresentFlag(); sei->m_overlayAlphaLayerId = m_pcCfg->getOverlaySEIAlphaLayerId(); sei->m_numOverlayElementsMinus1 = m_pcCfg->getOverlaySEINumElementsMinus1(); sei->m_overlayElementLabelMin = m_pcCfg->getOverlaySEIElementLabelMin(); sei->m_overlayElementLabelMax = m_pcCfg->getOverlaySEIElementLabelMax(); sei->m_overlayLanguage.resize ( sei->m_numOverlaysMinus1+1, NULL ); sei->m_overlayLanguageLength.resize ( sei->m_numOverlaysMinus1+1 ); sei->m_overlayName.resize ( sei->m_numOverlaysMinus1+1, NULL ); sei->m_overlayNameLength.resize ( sei->m_numOverlaysMinus1+1 ); sei->m_overlayElementName.resize ( sei->m_numOverlaysMinus1+1 ); sei->m_overlayElementNameLength.resize ( sei->m_numOverlaysMinus1+1 ); Int i,j; string strTmp; Int nBytes; assert( m_pcCfg->getOverlaySEILanguage().size() == sei->m_numOverlaysMinus1+1 ); assert( m_pcCfg->getOverlaySEIName().size() == sei->m_numOverlaysMinus1+1 ); assert( m_pcCfg->getOverlaySEIElementName().size() == sei->m_numOverlaysMinus1+1 ); for ( i=0 ; i<=sei->m_numOverlaysMinus1; i++ ) { //language tag if ( sei->m_languageOverlayPresentFlag[i] ) { strTmp = m_pcCfg->getOverlaySEILanguage()[i]; nBytes = (Int)m_pcCfg->getOverlaySEILanguage()[i].size(); assert( nBytes>0 ); sei->m_overlayLanguage[i] = new UChar[nBytes]; memcpy(sei->m_overlayLanguage[i], strTmp.c_str(), nBytes); sei->m_overlayLanguageLength[i] = nBytes; } //overlay name strTmp = m_pcCfg->getOverlaySEIName()[i]; nBytes = (Int)m_pcCfg->getOverlaySEIName()[i].size(); assert( nBytes>0 ); sei->m_overlayName[i] = new UChar[nBytes]; memcpy(sei->m_overlayName[i], strTmp.c_str(), nBytes); sei->m_overlayNameLength[i] = nBytes; //overlay element names if ( sei->m_overlayLabelPresentFlag[i] ) { sei->m_overlayElementName[i].resize( sei->m_numOverlayElementsMinus1[i]+1, NULL ); sei->m_overlayElementNameLength[i].resize( sei->m_numOverlayElementsMinus1[i]+1 ); assert( m_pcCfg->getOverlaySEIElementName()[i].size() == sei->m_numOverlayElementsMinus1[i]+1 ); for ( j=0 ; j<=sei->m_numOverlayElementsMinus1[i] ; j++) { strTmp = m_pcCfg->getOverlaySEIElementName()[i][j]; nBytes = (Int)m_pcCfg->getOverlaySEIElementName()[i][j].size(); assert( nBytes>0 ); sei->m_overlayElementName[i][j] = new UChar[nBytes]; memcpy(sei->m_overlayElementName[i][j], strTmp.c_str(), nBytes); sei->m_overlayElementNameLength[i][j] = nBytes; } } } sei->m_overlayInfoPersistenceFlag = true; } return sei; } #endif #if Q0074_COLOUR_REMAPPING_SEI SEIColourRemappingInfo* TEncGOP::xCreateSEIColourRemappingInfo() { SEIColourRemappingInfo *seiColourRemappingInfo = new SEIColourRemappingInfo(); seiColourRemappingInfo->m_colourRemapId = m_colourRemapSEIId; seiColourRemappingInfo->m_colourRemapCancelFlag = m_colourRemapSEICancelFlag; printf("xCreateSEIColourRemappingInfo - m_colourRemapId = %d m_colourRemapCancelFlag = %d \n",seiColourRemappingInfo->m_colourRemapId, seiColourRemappingInfo->m_colourRemapCancelFlag); if( !seiColourRemappingInfo->m_colourRemapCancelFlag ) { seiColourRemappingInfo->m_colourRemapPersistenceFlag = m_colourRemapSEIPersistenceFlag; seiColourRemappingInfo->m_colourRemapVideoSignalInfoPresentFlag = m_colourRemapSEIVideoSignalInfoPresentFlag; if( seiColourRemappingInfo->m_colourRemapVideoSignalInfoPresentFlag ) { seiColourRemappingInfo->m_colourRemapFullRangeFlag = m_colourRemapSEIFullRangeFlag; seiColourRemappingInfo->m_colourRemapPrimaries = m_colourRemapSEIPrimaries; seiColourRemappingInfo->m_colourRemapTransferFunction = m_colourRemapSEITransferFunction; seiColourRemappingInfo->m_colourRemapMatrixCoefficients = m_colourRemapSEIMatrixCoefficients; } seiColourRemappingInfo->m_colourRemapInputBitDepth = m_colourRemapSEIInputBitDepth; seiColourRemappingInfo->m_colourRemapBitDepth = m_colourRemapSEIBitDepth; for( Int c=0 ; c<3 ; c++ ) { seiColourRemappingInfo->m_preLutNumValMinus1[c] = m_colourRemapSEIPreLutNumValMinus1[c]; if( seiColourRemappingInfo->m_preLutNumValMinus1[c]>0 ) { seiColourRemappingInfo->m_preLutCodedValue[c].resize(seiColourRemappingInfo->m_preLutNumValMinus1[c]+1); seiColourRemappingInfo->m_preLutTargetValue[c].resize(seiColourRemappingInfo->m_preLutNumValMinus1[c]+1); for( Int i=0 ; i<=seiColourRemappingInfo->m_preLutNumValMinus1[c] ; i++) { seiColourRemappingInfo->m_preLutCodedValue[c][i] = m_colourRemapSEIPreLutCodedValue[c][i]; seiColourRemappingInfo->m_preLutTargetValue[c][i] = m_colourRemapSEIPreLutTargetValue[c][i]; } } } seiColourRemappingInfo->m_colourRemapMatrixPresentFlag = m_colourRemapSEIMatrixPresentFlag; if( seiColourRemappingInfo->m_colourRemapMatrixPresentFlag ) { seiColourRemappingInfo->m_log2MatrixDenom = m_colourRemapSEILog2MatrixDenom; for( Int c=0 ; c<3 ; c++ ) for( Int i=0 ; i<3 ; i++ ) seiColourRemappingInfo->m_colourRemapCoeffs[c][i] = m_colourRemapSEICoeffs[c][i]; } for( Int c=0 ; c<3 ; c++ ) { seiColourRemappingInfo->m_postLutNumValMinus1[c] = m_colourRemapSEIPostLutNumValMinus1[c]; if( seiColourRemappingInfo->m_postLutNumValMinus1[c]>0 ) { seiColourRemappingInfo->m_postLutCodedValue[c].resize(seiColourRemappingInfo->m_postLutNumValMinus1[c]+1); seiColourRemappingInfo->m_postLutTargetValue[c].resize(seiColourRemappingInfo->m_postLutNumValMinus1[c]+1); for( Int i=0 ; i<=seiColourRemappingInfo->m_postLutNumValMinus1[c] ; i++) { seiColourRemappingInfo->m_postLutCodedValue[c][i] = m_colourRemapSEIPostLutCodedValue[c][i]; seiColourRemappingInfo->m_postLutTargetValue[c][i] = m_colourRemapSEIPostLutTargetValue[c][i]; } } } } return seiColourRemappingInfo; } #endif #if SVC_EXTENSION #if LAYERS_NOT_PRESENT_SEI SEILayersNotPresent* TEncGOP::xCreateSEILayersNotPresent () { UInt i = 0; SEILayersNotPresent *seiLayersNotPresent = new SEILayersNotPresent(); seiLayersNotPresent->m_activeVpsId = m_pcCfg->getVPS()->getVPSId(); seiLayersNotPresent->m_vpsMaxLayers = m_pcCfg->getVPS()->getMaxLayers(); for ( ; i < seiLayersNotPresent->m_vpsMaxLayers; i++) { seiLayersNotPresent->m_layerNotPresentFlag[i] = true; } for ( ; i < MAX_LAYERS; i++) { seiLayersNotPresent->m_layerNotPresentFlag[i] = false; } return seiLayersNotPresent; } #endif #if N0383_IL_CONSTRAINED_TILE_SETS_SEI SEIInterLayerConstrainedTileSets* TEncGOP::xCreateSEIInterLayerConstrainedTileSets() { SEIInterLayerConstrainedTileSets *seiInterLayerConstrainedTileSets = new SEIInterLayerConstrainedTileSets(); seiInterLayerConstrainedTileSets->m_ilAllTilesExactSampleValueMatchFlag = false; seiInterLayerConstrainedTileSets->m_ilOneTilePerTileSetFlag = false; if (!seiInterLayerConstrainedTileSets->m_ilOneTilePerTileSetFlag) { seiInterLayerConstrainedTileSets->m_ilNumSetsInMessageMinus1 = m_pcCfg->getIlNumSetsInMessage() - 1; if (seiInterLayerConstrainedTileSets->m_ilNumSetsInMessageMinus1) { seiInterLayerConstrainedTileSets->m_skippedTileSetPresentFlag = m_pcCfg->getSkippedTileSetPresentFlag(); } else { seiInterLayerConstrainedTileSets->m_skippedTileSetPresentFlag = false; } seiInterLayerConstrainedTileSets->m_ilNumSetsInMessageMinus1 += seiInterLayerConstrainedTileSets->m_skippedTileSetPresentFlag ? 1 : 0; for (UInt i = 0; i < m_pcCfg->getIlNumSetsInMessage(); i++) { seiInterLayerConstrainedTileSets->m_ilctsId[i] = i; seiInterLayerConstrainedTileSets->m_ilNumTileRectsInSetMinus1[i] = 0; for( UInt j = 0; j <= seiInterLayerConstrainedTileSets->m_ilNumTileRectsInSetMinus1[i]; j++) { seiInterLayerConstrainedTileSets->m_ilTopLeftTileIndex[i][j] = m_pcCfg->getTopLeftTileIndex(i); seiInterLayerConstrainedTileSets->m_ilBottomRightTileIndex[i][j] = m_pcCfg->getBottomRightTileIndex(i); } seiInterLayerConstrainedTileSets->m_ilcIdc[i] = m_pcCfg->getIlcIdc(i); if (seiInterLayerConstrainedTileSets->m_ilAllTilesExactSampleValueMatchFlag) { seiInterLayerConstrainedTileSets->m_ilExactSampleValueMatchFlag[i] = false; } } } return seiInterLayerConstrainedTileSets; } Void TEncGOP::xBuildTileSetsMap(TComPicSym* picSym) { Int numCUs = picSym->getFrameWidthInCtus() * picSym->getFrameHeightInCtus(); for (Int i = 0; i < numCUs; i++) { picSym->setTileSetIdxMap(i, -1, 0, false); } for (Int i = 0; i < m_pcCfg->getIlNumSetsInMessage(); i++) { const TComTile* topLeftTile = picSym->getTComTile(m_pcCfg->getTopLeftTileIndex(i)); TComTile* bottomRightTile = picSym->getTComTile(m_pcCfg->getBottomRightTileIndex(i)); Int tileSetLeftEdgePosInCU = topLeftTile->getRightEdgePosInCtus() - topLeftTile->getTileWidthInCtus() + 1; Int tileSetRightEdgePosInCU = bottomRightTile->getRightEdgePosInCtus(); Int tileSetTopEdgePosInCU = topLeftTile->getBottomEdgePosInCtus() - topLeftTile->getTileHeightInCtus() + 1; Int tileSetBottomEdgePosInCU = bottomRightTile->getBottomEdgePosInCtus(); assert(tileSetLeftEdgePosInCU < tileSetRightEdgePosInCU && tileSetTopEdgePosInCU < tileSetBottomEdgePosInCU); for (Int j = tileSetTopEdgePosInCU; j <= tileSetBottomEdgePosInCU; j++) { for (Int k = tileSetLeftEdgePosInCU; k <= tileSetRightEdgePosInCU; k++) { picSym->setTileSetIdxMap(j * picSym->getFrameWidthInCtus() + k, i, m_pcCfg->getIlcIdc(i), false); } } } if (m_pcCfg->getSkippedTileSetPresentFlag()) { Int skippedTileSetIdx = m_pcCfg->getIlNumSetsInMessage(); for (Int i = 0; i < numCUs; i++) { if (picSym->getTileSetIdxMap(i) < 0) { picSym->setTileSetIdxMap(i, skippedTileSetIdx, 0, true); } } } } #endif Void TEncGOP::determinePocResetIdc(Int const pocCurr, TComSlice *const slice) { // If one picture in the AU is IDR, and another picture is not IDR, set the poc_reset_idc to 1 or 2 // If BL picture in the AU is IDR, and another picture is not IDR, set the poc_reset_idc to 2 // If BL picture is IRAP, and another picture is non-IRAP, then the poc_reset_idc is equal to 1 or 2. slice->setPocMsbNeeded(false); if( slice->getSliceIdx() == 0 ) // First slice - compute, copy for other slices { Int needReset = false; Int resetDueToBL = false; if( slice->getVPS()->getMaxLayers() > 1 ) { // If IRAP is refreshed in this access unit for base layer if( (m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshType() == 1 || m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshType() == 2) && ( pocCurr % m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshInterval() == 0 ) ) { // Check if the IRAP refresh interval of any layer does not match that of the base layer for(Int i = 1; i < slice->getVPS()->getMaxLayers(); i++) { Bool refreshIntervalFlag = ( pocCurr % m_ppcTEncTop[i]->getGOPEncoder()->getIntraRefreshInterval() == 0 ); Bool refreshTypeFlag = ( m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshType() == m_ppcTEncTop[i]->getGOPEncoder()->getIntraRefreshType() ); if( !(refreshIntervalFlag && refreshTypeFlag) ) { needReset = true; resetDueToBL = true; break; } } } } if( !needReset )// No need reset due to base layer IRAP { // Check if EL IDRs results in POC Reset for(Int i = 1; i < slice->getVPS()->getMaxLayers() && !needReset; i++) { Bool idrFlag = ( (m_ppcTEncTop[i]->getGOPEncoder()->getIntraRefreshType() == 2) && ( pocCurr % m_ppcTEncTop[i]->getGOPEncoder()->getIntraRefreshInterval() == 0 ) ); for(Int j = 0; j < slice->getVPS()->getMaxLayers(); j++) { if( j == i ) { continue; } Bool idrOtherPicFlag = ( (m_ppcTEncTop[j]->getGOPEncoder()->getIntraRefreshType() == 2) && ( pocCurr % m_ppcTEncTop[j]->getGOPEncoder()->getIntraRefreshInterval() == 0 ) ); if( idrFlag != idrOtherPicFlag ) { needReset = true; break; } } } } if( needReset ) { if( m_ppcTEncTop[0]->getGOPEncoder()->getIntraRefreshType() == 2 ) // BL IDR refresh, assuming BL picture present { if( resetDueToBL ) { slice->setPocResetIdc( 2 ); // Full reset needed if( slice->getVPS()->getVpsPocLsbAlignedFlag() && slice->getVPS()->getNumDirectRefLayers(slice->getLayerId()) == 0 ) { slice->setPocMsbNeeded(true); // Force msb writing } } else { slice->setPocResetIdc( 1 ); // Due to IDR in EL } } else { slice->setPocResetIdc( 1 ); // Only MSB reset } // Start a new POC reset period if (m_layerId == 0) // Assuming BL picture is always present at encoder; for other AU structures, need to change this { Int periodId = rand() % 64; m_lastPocPeriodId = (periodId == m_lastPocPeriodId) ? (periodId + 1) % 64 : periodId ; for( UInt i = 0; i < MAX_LAYERS; i++ ) { m_ppcTEncTop[i]->setPocDecrementedInDPBFlag(false); } } else { m_lastPocPeriodId = m_ppcTEncTop[0]->getGOPEncoder()->getLastPocPeriodId(); } slice->setPocResetPeriodId(m_lastPocPeriodId); } else { slice->setPocResetIdc( 0 ); } } } Void TEncGOP::updatePocValuesOfPics(Int const pocCurr, TComSlice *const slice) { UInt affectedLayerList[MAX_NUM_LAYER_IDS]; Int numAffectedLayers; affectedLayerList[0] = m_layerId; numAffectedLayers = 1; if (m_pcEncTop->getVPS()->getVpsPocLsbAlignedFlag()) { for (UInt j = 0; j < m_pcEncTop->getVPS()->getNumPredictedLayers(m_layerId); j++) { affectedLayerList[j + 1] = m_pcEncTop->getVPS()->getPredictedLayerId(m_layerId, j); } numAffectedLayers = m_pcEncTop->getVPS()->getNumPredictedLayers(m_layerId) + 1; } Int pocAdjustValue = pocCurr - m_pcEncTop->getPocAdjustmentValue(); // New POC reset period Int maxPocLsb, pocLsbVal, pocMsbDelta, pocLsbDelta, deltaPocVal; maxPocLsb = 1 << slice->getSPS()->getBitsForPOC(); Int adjustedPocValue = pocCurr; if (m_pcEncTop->getFirstPicInLayerDecodedFlag()) { pocLsbVal = (slice->getPocResetIdc() == 3) ? slice->getPocLsbVal() : pocAdjustValue % maxPocLsb; pocMsbDelta = pocAdjustValue - pocLsbVal; pocLsbDelta = (slice->getPocResetIdc() == 2 || ( slice->getPocResetIdc() == 3 && slice->getFullPocResetFlag() )) ? pocLsbVal : 0; deltaPocVal = pocMsbDelta + pocLsbDelta; Int origDeltaPocVal = deltaPocVal; // original value needed when updating POC adjustment value // IDR picture in base layer, non-IDR picture in other layers, poc_lsb_aligned_flag = 1 if( slice->getPocMsbNeeded() ) { if (slice->getLayerId() == 0) { Int highestPoc = INT_MIN; // Find greatest POC in DPB for layer 0 for (TComList::iterator iterPic = m_pcEncTop->getListPic()->begin(); iterPic != m_pcEncTop->getListPic()->end(); ++iterPic) { TComPic *dpbPic = *iterPic; if (dpbPic->getReconMark() && dpbPic->getLayerId() == 0 && dpbPic->getPOC() > highestPoc) { highestPoc = dpbPic->getPOC(); } } deltaPocVal = (highestPoc - (highestPoc & (maxPocLsb - 1))) + 1*maxPocLsb; m_pcEncTop->setCurrPocMsb(deltaPocVal); } else { deltaPocVal = m_ppcTEncTop[0]->getCurrPocMsb(); // copy from base layer } slice->setPocMsbVal(deltaPocVal); } for( UInt layerIdx = 0; layerIdx < numAffectedLayers; layerIdx++ ) { UInt lIdx = slice->getVPS()->getLayerIdxInVps(affectedLayerList[layerIdx]); if( !m_ppcTEncTop[lIdx]->getPocDecrementedInDPBFlag() ) { m_ppcTEncTop[lIdx]->setPocDecrementedInDPBFlag(true); // Decrement value of associatedIrapPoc of the TEncGop object m_ppcTEncTop[lIdx]->getGOPEncoder()->m_associatedIRAPPOC -= deltaPocVal; // Decrememnt the value of m_pocCRA m_ppcTEncTop[lIdx]->getGOPEncoder()->m_pocCRA -= deltaPocVal; TComList::iterator iterPic = m_ppcTEncTop[lIdx]->getListPic()->begin(); while (iterPic != m_ppcTEncTop[lIdx]->getListPic()->end()) { TComPic *dpbPic = *iterPic; if( dpbPic->getReconMark() ) { for( Int i = dpbPic->getNumAllocatedSlice() - 1; i >= 0; i-- ) { TComSlice *dpbPicSlice = dpbPic->getSlice( i ); TComReferencePictureSet *dpbPicRps = dpbPicSlice->getRPS(); // Decrement POC of slice dpbPicSlice->setPOC( dpbPicSlice->getPOC() - deltaPocVal ); // Decrement POC value stored in the RPS of each such slice for( Int j = dpbPicRps->getNumberOfPictures() - 1; j >= 0; j-- ) { dpbPicRps->setPOC( j, dpbPicRps->getPOC(j) - deltaPocVal ); } // Decrement value of refPOC dpbPicSlice->decrementRefPocValues( deltaPocVal ); // Update value of associatedIrapPoc of each slice dpbPicSlice->setAssociatedIRAPPOC( dpbPicSlice->getAssociatedIRAPPOC() - deltaPocVal ); if( slice->getPocMsbNeeded() ) { // this delta value is needed when computing delta POCs in reference picture set initialization dpbPicSlice->setPocResetDeltaPoc(dpbPicSlice->getPocResetDeltaPoc() + (deltaPocVal - pocLsbVal)); } } } iterPic++; } } } // Actual POC value before reset adjustedPocValue = pocCurr - m_pcEncTop->getPocAdjustmentValue(); // Set MSB value before reset Int tempLsbVal = adjustedPocValue & (maxPocLsb - 1); if (!slice->getPocMsbNeeded()) // set poc msb normally if special msb handling is not needed { slice->setPocMsbVal(adjustedPocValue - tempLsbVal); } // Set LSB value before reset - this is needed in the case of resetIdc = 2 slice->setPicOrderCntLsb( tempLsbVal ); // Cumulative delta deltaPocVal = origDeltaPocVal; // restore deltaPoc for correct adjustment value update m_pcEncTop->setPocAdjustmentValue( m_pcEncTop->getPocAdjustmentValue() + deltaPocVal ); } // New LSB value, after reset adjustedPocValue = pocCurr - m_pcEncTop->getPocAdjustmentValue(); Int newLsbVal = adjustedPocValue & (maxPocLsb - 1); // Set value of POC current picture after RESET if( slice->getPocResetIdc() == 1 ) { slice->setPOC( newLsbVal ); } else if( slice->getPocResetIdc() == 2 ) { slice->setPOC( 0 ); } else if( slice->getPocResetIdc() == 3 ) { Int picOrderCntMsb = slice->getCurrMsb( newLsbVal, slice->getFullPocResetFlag() ? 0 : slice->getPocLsbVal(), 0, maxPocLsb ); slice->setPOC( picOrderCntMsb + newLsbVal ); } else { assert(0); } } #if O0164_MULTI_LAYER_HRD SEIScalableNesting* TEncGOP::xCreateBspNestingSEI(TComSlice *pcSlice, Int olsIdx, Int partitioningSchemeIdx, Int bspIdx) { SEIScalableNesting *seiScalableNesting = new SEIScalableNesting(); SEIBspInitialArrivalTime *seiBspInitialArrivalTime = new SEIBspInitialArrivalTime(); SEIBspNesting *seiBspNesting = new SEIBspNesting(); SEIBufferingPeriod *seiBufferingPeriod = new SEIBufferingPeriod(); // Scalable nesting SEI seiScalableNesting->m_bitStreamSubsetFlag = 1; // If the nested SEI messages are picture buffereing SEI mesages, picure timing SEI messages or sub-picture timing SEI messages, bitstream_subset_flag shall be equal to 1 seiScalableNesting->m_nestingOpFlag = 1; seiScalableNesting->m_defaultOpFlag = 0; seiScalableNesting->m_nestingNumOpsMinus1 = 0; //nesting_num_ops_minus1 seiScalableNesting->m_nestingOpIdx[0] = pcSlice->getVPS()->getOutputLayerSetIdx(olsIdx); seiScalableNesting->m_nestingMaxTemporalIdPlus1[0] = 6 + 1; seiScalableNesting->m_allLayersFlag = 0; seiScalableNesting->m_nestingNoOpMaxTemporalIdPlus1 = 6 + 1; //nesting_no_op_max_temporal_id_plus1 seiScalableNesting->m_nestingNumLayersMinus1 = 1 - 1; //nesting_num_layers_minus1 seiScalableNesting->m_nestingLayerId[0] = 0; seiScalableNesting->m_callerOwnsSEIs = true; // Bitstream partition nesting SEI seiBspNesting->m_bspIdx = 0; seiBspNesting->m_callerOwnsSEIs = true; // Buffering period SEI UInt uiInitialCpbRemovalDelay = (90000/2); // 0.5 sec seiBufferingPeriod->m_initialCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_initialCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_initialCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_initialCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; Double dTmp = (Double)pcSlice->getSPS()->getVuiParameters()->getTimingInfo()->getNumUnitsInTick() / (Double)pcSlice->getSPS()->getVuiParameters()->getTimingInfo()->getTimeScale(); UInt uiTmp = (UInt)( dTmp * 90000.0 ); uiInitialCpbRemovalDelay -= uiTmp; uiInitialCpbRemovalDelay -= uiTmp / ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getTickDivisorMinus2() + 2 ); seiBufferingPeriod->m_initialAltCpbRemovalDelay [0][0] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_initialAltCpbRemovalDelayOffset[0][0] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_initialAltCpbRemovalDelay [0][1] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_initialAltCpbRemovalDelayOffset[0][1] = uiInitialCpbRemovalDelay; seiBufferingPeriod->m_rapCpbParamsPresentFlag = 0; //for the concatenation, it can be set to one during splicing. seiBufferingPeriod->m_concatenationFlag = 0; //since the temporal layer HRD is not ready, we assumed it is fixed seiBufferingPeriod->m_auCpbRemovalDelayDelta = 1; seiBufferingPeriod->m_cpbDelayOffset = 0; seiBufferingPeriod->m_dpbDelayOffset = 0; // Intial arrival time SEI message seiBspInitialArrivalTime->m_nalInitialArrivalDelay[0] = 0; seiBspInitialArrivalTime->m_vclInitialArrivalDelay[0] = 0; seiBspNesting->m_nestedSEIs.push_back(seiBufferingPeriod); seiBspNesting->m_nestedSEIs.push_back(seiBspInitialArrivalTime); seiBspNesting->m_bspIdx = bspIdx; seiBspNesting->m_seiOlsIdx = olsIdx; seiBspNesting->m_seiPartitioningSchemeIdx = partitioningSchemeIdx; seiScalableNesting->m_nestedSEIs.push_back(seiBspNesting); // BSP nesting SEI is contained in scalable nesting SEI return seiScalableNesting; } #endif #if CGS_3D_ASYMLUT Void TEncGOP::xDetermin3DAsymLUT( TComSlice * pSlice, TComPic * pCurPic, UInt refLayerIdc, TEncCfg * pCfg, Bool bSignalPPS ) { Int nCGSFlag = pSlice->getPPS()->getCGSFlag(); m_Enc3DAsymLUTPPS.setPPSBit( 0 ); Double dErrorUpdatedPPS = 0 , dErrorPPS = 0; #if R0179_ENC_OPT_3DLUT_SIZE Int nTLthres = m_pcCfg->getCGSLutSizeRDO() ? 2:7; Double dFrameLambda; #if FULL_NBIT Int SHIFT_QP = 12 + 6 * (pSlice->getBitDepthY() - 8); #else Int SHIFT_QP = 12; #endif Int QP = pSlice->getSliceQp(); // set frame lambda dFrameLambda = 0.68 * pow (2, (QP - SHIFT_QP) / 3.0) * (m_pcCfg->getGOPSize() > 1 && pSlice->isInterB()? 2 : 1); if(m_pcCfg->getCGSLutSizeRDO() == 1 && (!bSignalPPS && (pSlice->getDepth() < nTLthres))) dErrorUpdatedPPS = m_Enc3DAsymLUTPicUpdate.derive3DAsymLUT( pSlice , pCurPic , refLayerIdc , pCfg , bSignalPPS , m_pcEncTop->getElRapSliceTypeB(), dFrameLambda ); else if (pSlice->getDepth() >= nTLthres) dErrorUpdatedPPS = MAX_DOUBLE; else // if (m_pcCfg->getCGSLutSizeRDO() = 0 || bSignalPPS) #endif dErrorUpdatedPPS = m_Enc3DAsymLUTPicUpdate.derive3DAsymLUT( pSlice , pCurPic , refLayerIdc , pCfg , bSignalPPS , m_pcEncTop->getElRapSliceTypeB() ); if( bSignalPPS ) { m_Enc3DAsymLUTPPS.copy3DAsymLUT( &m_Enc3DAsymLUTPicUpdate ); pSlice->setCGSOverWritePPS( 1 ); // regular PPS update } else if( nCGSFlag ) { #if R0179_ENC_OPT_3DLUT_SIZE if(pSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R || pSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N) { pSlice->setCGSOverWritePPS( 0 ); } else if (pSlice->getDepth() >= nTLthres) { pSlice->setCGSOverWritePPS( 0 ); } else { #endif dErrorPPS = m_Enc3DAsymLUTPPS.estimateDistWithCur3DAsymLUT( pCurPic , refLayerIdc ); Double dFactor = pCfg->getIntraPeriod() == 1 ? 0.99 : 0.9; #if R0179_ENC_OPT_3DLUT_SIZE if( m_pcCfg->getCGSLutSizeRDO() ) { dErrorPPS = dErrorPPS/m_Enc3DAsymLUTPicUpdate.getDistFactor(pSlice->getSliceType(), pSlice->getDepth()); } #endif pSlice->setCGSOverWritePPS( dErrorUpdatedPPS < dFactor * dErrorPPS ); #if R0179_ENC_OPT_3DLUT_SIZE } #endif if( pSlice->getCGSOverWritePPS() ) { m_Enc3DAsymLUTPPS.copy3DAsymLUT( &m_Enc3DAsymLUTPicUpdate ); } } } Void TEncGOP::downScalePic( TComPicYuv* pcYuvSrc, TComPicYuv* pcYuvDest) { Int inputBitDepth = g_bitDepthLayer[CHANNEL_TYPE_LUMA][m_layerId]; Int outputBitDepth = g_bitDepthLayer[CHANNEL_TYPE_CHROMA][m_layerId]; { pcYuvSrc->setBorderExtension(false); pcYuvSrc->extendPicBorder (); // extend the border. pcYuvSrc->setBorderExtension(false); Int iWidth = pcYuvSrc->getWidth(COMPONENT_Y); Int iHeight = pcYuvSrc->getHeight(COMPONENT_Y); if(!m_temp) { initDs(iWidth, iHeight, m_pcCfg->getIntraPeriod()>1); } filterImg(pcYuvSrc->getAddr(COMPONENT_Y), pcYuvSrc->getStride(COMPONENT_Y), pcYuvDest->getAddr(COMPONENT_Y), pcYuvDest->getStride(COMPONENT_Y), iHeight, iWidth, inputBitDepth-outputBitDepth, 0); filterImg(pcYuvSrc->getAddr(COMPONENT_Cb), pcYuvSrc->getStride(COMPONENT_Cb), pcYuvDest->getAddr(COMPONENT_Cb), pcYuvDest->getStride(COMPONENT_Cb), iHeight>>1, iWidth>>1, inputBitDepth-outputBitDepth, 1); filterImg(pcYuvSrc->getAddr(COMPONENT_Cr), pcYuvSrc->getStride(COMPONENT_Cr), pcYuvDest->getAddr(COMPONENT_Cr), pcYuvDest->getStride(COMPONENT_Cr), iHeight>>1, iWidth>>1, inputBitDepth-outputBitDepth, 2); } } const Int TEncGOP::m_phase_filter_0_t0[4][13]={ {0, 2, -3, -9, 6, 39, 58, 39, 6, -9, -3, 2, 0}, {0, 0, 0, -2, 8,-20, 116, 34, -10, 2, 0, 0, 0}, //{0, 1, -1, -8, -1, 31, 57, 47, 13, -7, -5, 1, 0}, // {0, 1, 0, -7, -5, 22, 53, 53, 22, -5, -7, 0, 1}, {0, 0, 1, -5, -7, 13, 47, 57, 31, -1, -8,-1, 1} }; const Int TEncGOP::m_phase_filter_0_t1[4][13]={ {0, 4, 0, -12, 0, 40, 64, 40, 0, -12, 0, 4, 0}, {0, 0, 0, -2, 8,-20, 116,34,-10, 2, 0, 0, 0}, //{0, 1, -1, -8, -1, 31, 57, 47, 13, -7, -5, 1, 0}, // {0, 1, 0, -7, -5, 22, 53, 53, 22, -5, -7, 0, 1}, {0, 0, 1, -5, -7, 13, 47, 57, 31, -1, -8,-1, 1} }; const Int TEncGOP::m_phase_filter_0_t1_chroma[4][13]={ {0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0}, {0, 0, 0, -2, 8,-20, 116,34,-10, 2, 0, 0, 0}, //{0, 1, -1, -8, -1, 31, 57, 47, 13, -7, -5, 1, 0}, // {0, 1, 0, -7, -5, 22, 53, 53, 22, -5, -7, 0, 1}, {0, 0, 1, -5, -7, 13, 47, 57, 31, -1, -8,-1, 1} }; const Int TEncGOP::m_phase_filter_1[8][13]={ {0, 0, 5, -6, -10,37, 76, 37,-10, -6, 5, 0, 0}, {0, -1, 5, -3, -12,29, 75, 45, -7, -8, 5, 0, 0}, {0, -1, 4, -1, -13,22, 73, 52, -3, -10, 4, 1, 0}, {0, -1, 4, 1, -13,14, 70, 59, 2, -12, 3, 2, -1}, {0, -1, 3, 2, -13, 8, 65, 65, 8, -13, 2, 3, -1}, {0, -1, 2, 3, -12, 2, 59, 70, 14, -13, 1, 4, -1}, {0, 0, 1, 4, -10,-3, 52, 73, 22, -13,-1, 4, -1}, {0, 0, 0, 5, -8,-7, 45, 75, 29, -12,-3, 5, -1} }; #if CGS_GCC_NO_VECTORIZATION #ifdef __GNUC__ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) #if GCC_VERSION > 40600 __attribute__((optimize("no-tree-vectorize"))) #endif #endif #endif Void TEncGOP::filterImg( Pel *src, Int iSrcStride, Pel *dst, Int iDstStride, Int height1, Int width1, Int shift, Int plane) { Int length = m_iTap; Int height2,width2; Int k,iSum; Int i0, div_i0, i1; Int j0, div_j0, j1; const Int *p_filter; Pel *p_src, *p_dst; Pel *p_src_line, *p_dst_line; Int **p_temp, *p_tmp; Int shift2 = 2*7+shift; Int shift_round = (1 << (shift2 - 1)); Int iMax = (1<<(g_bitDepth[CHANNEL_TYPE_LUMA]-shift))-1; height2 = (height1 * m_iM) / m_iN; width2 = (width1 * m_iM) / m_iN; m_phase_filter = plane? m_phase_filter_chroma : m_phase_filter_luma; // horizontal filtering p_src_line = src; for(j1 = 0; j1 < height1; j1++) { i0=-m_iN; p_tmp = m_temp[j1]; for(i1 = 0; i1 < width2; i1++) { i0 += m_iN; div_i0 = (i0 / m_iM); p_src = p_src_line + ( div_i0 - (length >> 1)); p_filter = m_phase_filter[i0 - div_i0 * m_iM]; // phase_filter[i0 % M] iSum = 0; for(k = 0; k < length; k++) { iSum += (*p_src++) * (*p_filter++); } *p_tmp++ = iSum; } p_src_line += iSrcStride; } // pad temp (vertical) for (k=-(length>>1); k<0; k++) { memcpy(m_temp[k], m_temp[0], width2*sizeof(Int)); } for (k=height1; k<(height1+(length>>1)); k++) { memcpy(m_temp[k], m_temp[k-1], (width2)* sizeof(Int)); } // vertical filtering j0 = (plane == 0) ? -m_iN : -(m_iN-1); p_dst_line = dst; for(j1 = 0; j1 < height2; j1++) { j0 += m_iN; div_j0 = (j0 / m_iM); p_dst = p_dst_line; p_temp = &m_temp[div_j0 - (length>>1)]; p_filter = m_phase_filter[j0 - div_j0 * m_iM]; // phase_filter[j0 % M] for(i1 = 0; i1 < width2;i1++) { iSum=0; for(k = 0; k < length; k++) { iSum += p_temp[k][i1] * p_filter[k]; } iSum=((iSum + shift_round) >> shift2); *p_dst++ = (Short)(iSum > iMax ? iMax : (iSum < 0 ? 0 : iSum)); } p_dst_line += iDstStride; } } Void TEncGOP::initDs(Int iWidth, Int iHeight, Int iType) { m_iTap = 13; if(g_posScalingFactor[0][0] == (1<<15)) { m_iM = 4; m_iN = 8; m_phase_filter_luma = iType? m_phase_filter_0_t1 : m_phase_filter_0_t0; m_phase_filter_chroma = m_phase_filter_0_t1_chroma; } else { m_iM = 8; m_iN = 12; m_phase_filter_luma = m_phase_filter_chroma = m_phase_filter_1; m_phase_filter = m_phase_filter_1; } get_mem2DintWithPad (&m_temp, iHeight, iWidth*m_iM/m_iN, m_iTap>>1, 0); } Int TEncGOP::get_mem2DintWithPad(Int ***array2D, Int dim0, Int dim1, Int iPadY, Int iPadX) { Int i; Int *curr = NULL; Int iHeight, iWidth; iHeight = dim0+2*iPadY; iWidth = dim1+2*iPadX; (*array2D) = (Int**)malloc(iHeight*sizeof(Int*)); *(*array2D) = (Int* )xMalloc(Int, iHeight*iWidth); (*array2D)[0] += iPadX; curr = (*array2D)[0]; for(i = 1 ; i < iHeight; i++) { curr += iWidth; (*array2D)[i] = curr; } (*array2D) = &((*array2D)[iPadY]); return 0; } Void TEncGOP::free_mem2DintWithPad(Int **array2D, Int iPadY, Int iPadX) { if (array2D) { if (*array2D) { xFree(array2D[-iPadY]-iPadX); } else { printf("free_mem2DintWithPad: trying to free unused memory\r\nPress Any Key\r\n"); } free (&array2D[-iPadY]); } else { printf("free_mem2DintWithPad: trying to free unused memory\r\nPress Any Key\r\n"); } } #endif Void TEncGOP::xCheckLayerReset(TComSlice *slice) { Bool layerResetFlag; Int dolLayerId; if (slice->isIRAP() && slice->getLayerId() > 0) { if (m_prevPicHasEos) { layerResetFlag = true; dolLayerId = slice->getLayerId(); } else if ((slice->isCRA() && slice->getHandleCraAsBlaFlag()) || (slice->isIDR() && slice->getCrossLayerBLAFlag()) || slice->isBLA()) { layerResetFlag = true; dolLayerId = slice->getLayerId(); } else { layerResetFlag = false; } if (layerResetFlag) { for (Int i = 0; i < slice->getVPS()->getNumPredictedLayers(dolLayerId); i++) { Int iLayerId = slice->getVPS()->getPredictedLayerId(dolLayerId, i); m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(iLayerId)]->setLayerInitializedFlag(false); m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(iLayerId)]->setFirstPicInLayerDecodedFlag(false); } // Each picture that is in the DPB and has nuh_layer_id equal to dolLayerId is marked as "unused for reference". for (TComList::iterator pic = m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(dolLayerId)]->getListPic()->begin(); pic != m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(dolLayerId)]->getListPic()->end(); pic++) { if ((*pic)->getSlice(0)->getPOC() != slice->getPOC()) { (*pic)->getSlice(0)->setReferenced(false); } } // Each picture that is in DPB and has nuh_layer_id equal to any value of IdPredictedLayer[dolLayerId][i] // for the values of i in range of 0 to NumPredictedLayers[dolLayerId] - 1, inclusive, is marked as "unused for reference" for (UInt i = 0; i < slice->getVPS()->getNumPredictedLayers(dolLayerId); i++) { UInt predLId = slice->getVPS()->getPredictedLayerId(dolLayerId, i); for (TComList::iterator pic = m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(predLId)]->getListPic()->begin(); pic != m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(predLId)]->getListPic()->end(); pic++) { if ((*pic)->getSlice(0)->getPOC() != slice->getPOC()) { (*pic)->getSlice(0)->setReferenced(false); } } } } } } Void TEncGOP::xSetNoRaslOutputFlag(TComSlice *slice) { if (slice->isIRAP()) { m_noRaslOutputFlag = slice->getHandleCraAsBlaFlag(); // default value if (slice->isIDR() || slice->isBLA() || m_bFirst || m_prevPicHasEos) { m_noRaslOutputFlag = true; } else if (!m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(m_layerId)]->getLayerInitializedFlag()) { Bool refLayersInitialized = true; for (UInt j = 0; j < slice->getVPS()->getNumDirectRefLayers(m_layerId); j++) { UInt refLayerId = slice->getVPS()->getRefLayerId(m_layerId, j); if (!m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(refLayerId)]->getLayerInitializedFlag()) { refLayersInitialized = false; } } if (refLayersInitialized) { m_noRaslOutputFlag = true; } } } } Void TEncGOP::xSetLayerInitializedFlag(TComSlice *slice) { if (slice->isIRAP() && m_noRaslOutputFlag) { if (m_layerId == 0) { m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(m_layerId)]->setLayerInitializedFlag(true); } else if (!m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(m_layerId)]->getLayerInitializedFlag() && slice->getVPS()->getNumDirectRefLayers(m_layerId) == 0) { m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(m_layerId)]->setLayerInitializedFlag(true); } else if (!m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(m_layerId)]->getLayerInitializedFlag()) { Bool refLayersInitialized = true; for (UInt j = 0; j < slice->getVPS()->getNumDirectRefLayers(m_layerId); j++) { UInt refLayerId = slice->getVPS()->getRefLayerId(m_layerId, j); if (!m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(refLayerId)]->getLayerInitializedFlag()) { refLayersInitialized = false; } } if (refLayersInitialized) { m_ppcTEncTop[slice->getVPS()->getLayerIdxInVps(m_layerId)]->setLayerInitializedFlag(true); } } } } #endif //SVC_EXTENSION #if Q0074_COLOUR_REMAPPING_SEI Bool confirmParameter(Bool bflag, const Char* message) { if (!bflag) return false; printf("Error: %s\n",message); return true; } #endif //! \}