libbpg/jctvc/TAppEncTop.cpp

696 lines
34 KiB
C++
Raw Normal View History

2015-01-16 12:46:18 +00:00
/* 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-2014, 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 TAppEncTop.cpp
\brief Encoder application class
*/
#include <list>
#include <fstream>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <assert.h>
#include <iomanip>
#include "TAppEncTop.h"
#include "TLibEncoder/AnnexBwrite.h"
using namespace std;
//! \ingroup TAppEncoder
//! \{
// ====================================================================================================================
// Constructor / destructor / initialization / destroy
// ====================================================================================================================
TAppEncTop::TAppEncTop()
{
m_iFrameRcvd = 0;
m_totalBytes = 0;
m_essentialBytes = 0;
}
TAppEncTop::~TAppEncTop()
{
}
Void TAppEncTop::xInitLibCfg()
{
TComVPS vps;
vps.setMaxTLayers ( m_maxTempLayer );
if (m_maxTempLayer == 1)
{
vps.setTemporalNestingFlag(true);
}
vps.setMaxLayers ( 1 );
for(Int i = 0; i < MAX_TLAYER; i++)
{
vps.setNumReorderPics ( m_numReorderPics[i], i );
vps.setMaxDecPicBuffering ( m_maxDecPicBuffering[i], i );
}
m_cTEncTop.setVPS(&vps);
m_cTEncTop.setProfile ( m_profile);
m_cTEncTop.setLevel ( m_levelTier, m_level);
m_cTEncTop.setProgressiveSourceFlag ( m_progressiveSourceFlag);
m_cTEncTop.setInterlacedSourceFlag ( m_interlacedSourceFlag);
m_cTEncTop.setNonPackedConstraintFlag ( m_nonPackedConstraintFlag);
m_cTEncTop.setFrameOnlyConstraintFlag ( m_frameOnlyConstraintFlag);
m_cTEncTop.setBitDepthConstraintValue ( m_bitDepthConstraint );
m_cTEncTop.setChromaFormatConstraintValue ( m_chromaFormatConstraint );
m_cTEncTop.setIntraConstraintFlag ( m_intraConstraintFlag );
m_cTEncTop.setLowerBitRateConstraintFlag ( m_lowerBitRateConstraintFlag );
m_cTEncTop.setPrintMSEBasedSequencePSNR ( m_printMSEBasedSequencePSNR);
m_cTEncTop.setPrintFrameMSE ( m_printFrameMSE);
m_cTEncTop.setPrintSequenceMSE ( m_printSequenceMSE);
m_cTEncTop.setCabacZeroWordPaddingEnabled ( m_cabacZeroWordPaddingEnabled );
m_cTEncTop.setFrameRate ( m_iFrameRate );
m_cTEncTop.setFrameSkip ( m_FrameSkip );
m_cTEncTop.setSourceWidth ( m_iSourceWidth );
m_cTEncTop.setSourceHeight ( m_iSourceHeight );
m_cTEncTop.setConformanceWindow ( m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom );
m_cTEncTop.setFramesToBeEncoded ( m_framesToBeEncoded );
//====== Coding Structure ========
m_cTEncTop.setIntraPeriod ( m_iIntraPeriod );
m_cTEncTop.setDecodingRefreshType ( m_iDecodingRefreshType );
m_cTEncTop.setGOPSize ( m_iGOPSize );
m_cTEncTop.setGopList ( m_GOPList );
m_cTEncTop.setExtraRPSs ( m_extraRPSs );
for(Int i = 0; i < MAX_TLAYER; i++)
{
m_cTEncTop.setNumReorderPics ( m_numReorderPics[i], i );
m_cTEncTop.setMaxDecPicBuffering ( m_maxDecPicBuffering[i], i );
}
for( UInt uiLoop = 0; uiLoop < MAX_TLAYER; ++uiLoop )
{
m_cTEncTop.setLambdaModifier ( uiLoop, m_adLambdaModifier[ uiLoop ] );
}
m_cTEncTop.setQP ( m_iQP );
m_cTEncTop.setPad ( m_aiPad );
m_cTEncTop.setMaxTempLayer ( m_maxTempLayer );
m_cTEncTop.setUseAMP( m_enableAMP );
//===== Slice ========
//====== Loop/Deblock Filter ========
m_cTEncTop.setLoopFilterDisable ( m_bLoopFilterDisable );
m_cTEncTop.setLoopFilterOffsetInPPS ( m_loopFilterOffsetInPPS );
m_cTEncTop.setLoopFilterBetaOffset ( m_loopFilterBetaOffsetDiv2 );
m_cTEncTop.setLoopFilterTcOffset ( m_loopFilterTcOffsetDiv2 );
m_cTEncTop.setDeblockingFilterControlPresent ( m_DeblockingFilterControlPresent);
m_cTEncTop.setDeblockingFilterMetric ( m_DeblockingFilterMetric );
//====== Motion search ========
m_cTEncTop.setFastSearch ( m_iFastSearch );
m_cTEncTop.setSearchRange ( m_iSearchRange );
m_cTEncTop.setBipredSearchRange ( m_bipredSearchRange );
//====== Quality control ========
m_cTEncTop.setMaxDeltaQP ( m_iMaxDeltaQP );
m_cTEncTop.setMaxCuDQPDepth ( m_iMaxCuDQPDepth );
m_cTEncTop.setMaxCUChromaQpAdjustmentDepth ( m_maxCUChromaQpAdjustmentDepth );
m_cTEncTop.setChromaCbQpOffset ( m_cbQpOffset );
m_cTEncTop.setChromaCrQpOffset ( m_crQpOffset );
m_cTEncTop.setChromaFormatIdc ( m_chromaFormatIDC );
#if ADAPTIVE_QP_SELECTION
m_cTEncTop.setUseAdaptQpSelect ( m_bUseAdaptQpSelect );
#endif
m_cTEncTop.setUseAdaptiveQP ( m_bUseAdaptiveQP );
m_cTEncTop.setQPAdaptationRange ( m_iQPAdaptationRange );
m_cTEncTop.setUseExtendedPrecision ( m_useExtendedPrecision );
m_cTEncTop.setUseHighPrecisionPredictionWeighting ( m_useHighPrecisionPredictionWeighting );
//====== Tool list ========
m_cTEncTop.setDeltaQpRD ( m_uiDeltaQpRD );
m_cTEncTop.setUseASR ( m_bUseASR );
m_cTEncTop.setUseHADME ( m_bUseHADME );
m_cTEncTop.setdQPs ( m_aidQP );
m_cTEncTop.setUseRDOQ ( m_useRDOQ );
m_cTEncTop.setUseRDOQTS ( m_useRDOQTS );
m_cTEncTop.setRDpenalty ( m_rdPenalty );
m_cTEncTop.setQuadtreeTULog2MaxSize ( m_uiQuadtreeTULog2MaxSize );
m_cTEncTop.setQuadtreeTULog2MinSize ( m_uiQuadtreeTULog2MinSize );
m_cTEncTop.setQuadtreeTUMaxDepthInter ( m_uiQuadtreeTUMaxDepthInter );
m_cTEncTop.setQuadtreeTUMaxDepthIntra ( m_uiQuadtreeTUMaxDepthIntra );
m_cTEncTop.setUseFastEnc ( m_bUseFastEnc );
m_cTEncTop.setUseEarlyCU ( m_bUseEarlyCU );
m_cTEncTop.setUseFastDecisionForMerge ( m_useFastDecisionForMerge );
m_cTEncTop.setUseCbfFastMode ( m_bUseCbfFastMode );
m_cTEncTop.setUseEarlySkipDetection ( m_useEarlySkipDetection );
m_cTEncTop.setUseCrossComponentPrediction ( m_useCrossComponentPrediction );
m_cTEncTop.setUseReconBasedCrossCPredictionEstimate ( m_reconBasedCrossCPredictionEstimate );
m_cTEncTop.setSaoOffsetBitShift ( CHANNEL_TYPE_LUMA , m_saoOffsetBitShift[CHANNEL_TYPE_LUMA] );
m_cTEncTop.setSaoOffsetBitShift ( CHANNEL_TYPE_CHROMA, m_saoOffsetBitShift[CHANNEL_TYPE_CHROMA] );
m_cTEncTop.setUseTransformSkip ( m_useTransformSkip );
m_cTEncTop.setUseTransformSkipFast ( m_useTransformSkipFast );
m_cTEncTop.setUseResidualRotation ( m_useResidualRotation );
m_cTEncTop.setUseSingleSignificanceMapContext ( m_useSingleSignificanceMapContext );
m_cTEncTop.setUseGolombRiceParameterAdaptation ( m_useGolombRiceParameterAdaptation );
m_cTEncTop.setAlignCABACBeforeBypass ( m_alignCABACBeforeBypass );
m_cTEncTop.setTransformSkipLog2MaxSize ( m_transformSkipLog2MaxSize );
for (UInt signallingModeIndex = 0; signallingModeIndex < NUMBER_OF_RDPCM_SIGNALLING_MODES; signallingModeIndex++)
{
m_cTEncTop.setUseResidualDPCM ( RDPCMSignallingMode(signallingModeIndex), m_useResidualDPCM[signallingModeIndex]);
}
m_cTEncTop.setUseConstrainedIntraPred ( m_bUseConstrainedIntraPred );
m_cTEncTop.setPCMLog2MinSize ( m_uiPCMLog2MinSize);
m_cTEncTop.setUsePCM ( m_usePCM );
m_cTEncTop.setPCMLog2MaxSize ( m_pcmLog2MaxSize);
m_cTEncTop.setMaxNumMergeCand ( m_maxNumMergeCand );
//====== Weighted Prediction ========
m_cTEncTop.setUseWP ( m_useWeightedPred );
m_cTEncTop.setWPBiPred ( m_useWeightedBiPred );
//====== Parallel Merge Estimation ========
m_cTEncTop.setLog2ParallelMergeLevelMinus2 ( m_log2ParallelMergeLevel - 2 );
//====== Slice ========
m_cTEncTop.setSliceMode ( (SliceConstraint) m_sliceMode );
m_cTEncTop.setSliceArgument ( m_sliceArgument );
//====== Dependent Slice ========
m_cTEncTop.setSliceSegmentMode ( (SliceConstraint) m_sliceSegmentMode );
m_cTEncTop.setSliceSegmentArgument ( m_sliceSegmentArgument );
if(m_sliceMode == NO_SLICES )
{
m_bLFCrossSliceBoundaryFlag = true;
}
m_cTEncTop.setLFCrossSliceBoundaryFlag ( m_bLFCrossSliceBoundaryFlag );
m_cTEncTop.setUseSAO ( m_bUseSAO );
m_cTEncTop.setMaxNumOffsetsPerPic ( m_maxNumOffsetsPerPic);
m_cTEncTop.setSaoCtuBoundary ( m_saoCtuBoundary);
m_cTEncTop.setPCMInputBitDepthFlag ( m_bPCMInputBitDepthFlag);
m_cTEncTop.setPCMFilterDisableFlag ( m_bPCMFilterDisableFlag);
m_cTEncTop.setDisableIntraReferenceSmoothing (!m_enableIntraReferenceSmoothing );
m_cTEncTop.setDecodedPictureHashSEIEnabled ( m_decodedPictureHashSEIEnabled );
m_cTEncTop.setRecoveryPointSEIEnabled ( m_recoveryPointSEIEnabled );
m_cTEncTop.setBufferingPeriodSEIEnabled ( m_bufferingPeriodSEIEnabled );
m_cTEncTop.setPictureTimingSEIEnabled ( m_pictureTimingSEIEnabled );
m_cTEncTop.setToneMappingInfoSEIEnabled ( m_toneMappingInfoSEIEnabled );
m_cTEncTop.setTMISEIToneMapId ( m_toneMapId );
m_cTEncTop.setTMISEIToneMapCancelFlag ( m_toneMapCancelFlag );
m_cTEncTop.setTMISEIToneMapPersistenceFlag ( m_toneMapPersistenceFlag );
m_cTEncTop.setTMISEICodedDataBitDepth ( m_toneMapCodedDataBitDepth );
m_cTEncTop.setTMISEITargetBitDepth ( m_toneMapTargetBitDepth );
m_cTEncTop.setTMISEIModelID ( m_toneMapModelId );
m_cTEncTop.setTMISEIMinValue ( m_toneMapMinValue );
m_cTEncTop.setTMISEIMaxValue ( m_toneMapMaxValue );
m_cTEncTop.setTMISEISigmoidMidpoint ( m_sigmoidMidpoint );
m_cTEncTop.setTMISEISigmoidWidth ( m_sigmoidWidth );
m_cTEncTop.setTMISEIStartOfCodedInterva ( m_startOfCodedInterval );
m_cTEncTop.setTMISEINumPivots ( m_numPivots );
m_cTEncTop.setTMISEICodedPivotValue ( m_codedPivotValue );
m_cTEncTop.setTMISEITargetPivotValue ( m_targetPivotValue );
m_cTEncTop.setTMISEICameraIsoSpeedIdc ( m_cameraIsoSpeedIdc );
m_cTEncTop.setTMISEICameraIsoSpeedValue ( m_cameraIsoSpeedValue );
m_cTEncTop.setTMISEIExposureIndexIdc ( m_exposureIndexIdc );
m_cTEncTop.setTMISEIExposureIndexValue ( m_exposureIndexValue );
m_cTEncTop.setTMISEIExposureCompensationValueSignFlag ( m_exposureCompensationValueSignFlag );
m_cTEncTop.setTMISEIExposureCompensationValueNumerator ( m_exposureCompensationValueNumerator );
m_cTEncTop.setTMISEIExposureCompensationValueDenomIdc ( m_exposureCompensationValueDenomIdc );
m_cTEncTop.setTMISEIRefScreenLuminanceWhite ( m_refScreenLuminanceWhite );
m_cTEncTop.setTMISEIExtendedRangeWhiteLevel ( m_extendedRangeWhiteLevel );
m_cTEncTop.setTMISEINominalBlackLevelLumaCodeValue ( m_nominalBlackLevelLumaCodeValue );
m_cTEncTop.setTMISEINominalWhiteLevelLumaCodeValue ( m_nominalWhiteLevelLumaCodeValue );
m_cTEncTop.setTMISEIExtendedWhiteLevelLumaCodeValue ( m_extendedWhiteLevelLumaCodeValue );
m_cTEncTop.setChromaSamplingFilterHintEnabled ( m_chromaSamplingFilterSEIenabled );
m_cTEncTop.setChromaSamplingHorFilterIdc ( m_chromaSamplingHorFilterIdc );
m_cTEncTop.setChromaSamplingVerFilterIdc ( m_chromaSamplingVerFilterIdc );
m_cTEncTop.setFramePackingArrangementSEIEnabled ( m_framePackingSEIEnabled );
m_cTEncTop.setFramePackingArrangementSEIType ( m_framePackingSEIType );
m_cTEncTop.setFramePackingArrangementSEIId ( m_framePackingSEIId );
m_cTEncTop.setFramePackingArrangementSEIQuincunx ( m_framePackingSEIQuincunx );
m_cTEncTop.setFramePackingArrangementSEIInterpretation ( m_framePackingSEIInterpretation );
m_cTEncTop.setSegmentedRectFramePackingArrangementSEIEnabled ( m_segmentedRectFramePackingSEIEnabled );
m_cTEncTop.setSegmentedRectFramePackingArrangementSEICancel ( m_segmentedRectFramePackingSEICancel );
m_cTEncTop.setSegmentedRectFramePackingArrangementSEIType ( m_segmentedRectFramePackingSEIType );
m_cTEncTop.setSegmentedRectFramePackingArrangementSEIPersistence( m_segmentedRectFramePackingSEIPersistence );
m_cTEncTop.setDisplayOrientationSEIAngle ( m_displayOrientationSEIAngle );
m_cTEncTop.setTemporalLevel0IndexSEIEnabled ( m_temporalLevel0IndexSEIEnabled );
m_cTEncTop.setGradualDecodingRefreshInfoEnabled ( m_gradualDecodingRefreshInfoEnabled );
m_cTEncTop.setNoDisplaySEITLayer ( m_noDisplaySEITLayer );
m_cTEncTop.setDecodingUnitInfoSEIEnabled ( m_decodingUnitInfoSEIEnabled );
m_cTEncTop.setSOPDescriptionSEIEnabled ( m_SOPDescriptionSEIEnabled );
m_cTEncTop.setScalableNestingSEIEnabled ( m_scalableNestingSEIEnabled );
m_cTEncTop.setTMCTSSEIEnabled ( m_tmctsSEIEnabled );
m_cTEncTop.setTimeCodeSEIEnabled ( m_timeCodeSEIEnabled );
m_cTEncTop.setNumberOfTimeSets ( m_timeCodeSEINumTs );
for(Int i = 0; i < m_timeCodeSEINumTs; i++) { m_cTEncTop.setTimeSet(m_timeSetArray[i], i); }
m_cTEncTop.setKneeSEIEnabled ( m_kneeSEIEnabled );
m_cTEncTop.setKneeSEIId ( m_kneeSEIId );
m_cTEncTop.setKneeSEICancelFlag ( m_kneeSEICancelFlag );
m_cTEncTop.setKneeSEIPersistenceFlag ( m_kneeSEIPersistenceFlag );
m_cTEncTop.setKneeSEIInputDrange ( m_kneeSEIInputDrange );
m_cTEncTop.setKneeSEIInputDispLuminance ( m_kneeSEIInputDispLuminance );
m_cTEncTop.setKneeSEIOutputDrange ( m_kneeSEIOutputDrange );
m_cTEncTop.setKneeSEIOutputDispLuminance ( m_kneeSEIOutputDispLuminance );
m_cTEncTop.setKneeSEINumKneePointsMinus1 ( m_kneeSEINumKneePointsMinus1 );
m_cTEncTop.setKneeSEIInputKneePoint ( m_kneeSEIInputKneePoint );
m_cTEncTop.setKneeSEIOutputKneePoint ( m_kneeSEIOutputKneePoint );
m_cTEncTop.setMasteringDisplaySEI ( m_masteringDisplay );
m_cTEncTop.setTileUniformSpacingFlag ( m_tileUniformSpacingFlag );
m_cTEncTop.setNumColumnsMinus1 ( m_numTileColumnsMinus1 );
m_cTEncTop.setNumRowsMinus1 ( m_numTileRowsMinus1 );
if(!m_tileUniformSpacingFlag)
{
m_cTEncTop.setColumnWidth ( m_tileColumnWidth );
m_cTEncTop.setRowHeight ( m_tileRowHeight );
}
m_cTEncTop.xCheckGSParameters();
Int uiTilesCount = (m_numTileRowsMinus1+1) * (m_numTileColumnsMinus1+1);
if(uiTilesCount == 1)
{
m_bLFCrossTileBoundaryFlag = true;
}
m_cTEncTop.setLFCrossTileBoundaryFlag ( m_bLFCrossTileBoundaryFlag );
m_cTEncTop.setWaveFrontSynchro ( m_iWaveFrontSynchro );
m_cTEncTop.setWaveFrontSubstreams ( m_iWaveFrontSubstreams );
m_cTEncTop.setTMVPModeId ( m_TMVPModeId );
m_cTEncTop.setUseScalingListId ( m_useScalingListId );
m_cTEncTop.setScalingListFile ( m_scalingListFile );
m_cTEncTop.setSignHideFlag ( m_signHideFlag);
m_cTEncTop.setUseRateCtrl ( m_RCEnableRateControl );
m_cTEncTop.setTargetBitrate ( m_RCTargetBitrate );
m_cTEncTop.setKeepHierBit ( m_RCKeepHierarchicalBit );
m_cTEncTop.setLCULevelRC ( m_RCLCULevelRC );
m_cTEncTop.setUseLCUSeparateModel ( m_RCUseLCUSeparateModel );
m_cTEncTop.setInitialQP ( m_RCInitialQP );
m_cTEncTop.setForceIntraQP ( m_RCForceIntraQP );
m_cTEncTop.setTransquantBypassEnableFlag ( m_TransquantBypassEnableFlag );
m_cTEncTop.setCUTransquantBypassFlagForceValue ( m_CUTransquantBypassFlagForce );
m_cTEncTop.setCostMode ( m_costMode );
m_cTEncTop.setUseRecalculateQPAccordingToLambda ( m_recalculateQPAccordingToLambda );
m_cTEncTop.setUseStrongIntraSmoothing ( m_useStrongIntraSmoothing );
m_cTEncTop.setActiveParameterSetsSEIEnabled ( m_activeParameterSetsSEIEnabled );
m_cTEncTop.setVuiParametersPresentFlag ( m_vuiParametersPresentFlag );
m_cTEncTop.setAspectRatioInfoPresentFlag ( m_aspectRatioInfoPresentFlag);
m_cTEncTop.setAspectRatioIdc ( m_aspectRatioIdc );
m_cTEncTop.setSarWidth ( m_sarWidth );
m_cTEncTop.setSarHeight ( m_sarHeight );
m_cTEncTop.setOverscanInfoPresentFlag ( m_overscanInfoPresentFlag );
m_cTEncTop.setOverscanAppropriateFlag ( m_overscanAppropriateFlag );
m_cTEncTop.setVideoSignalTypePresentFlag ( m_videoSignalTypePresentFlag );
m_cTEncTop.setVideoFormat ( m_videoFormat );
m_cTEncTop.setVideoFullRangeFlag ( m_videoFullRangeFlag );
m_cTEncTop.setColourDescriptionPresentFlag ( m_colourDescriptionPresentFlag );
m_cTEncTop.setColourPrimaries ( m_colourPrimaries );
m_cTEncTop.setTransferCharacteristics ( m_transferCharacteristics );
m_cTEncTop.setMatrixCoefficients ( m_matrixCoefficients );
m_cTEncTop.setChromaLocInfoPresentFlag ( m_chromaLocInfoPresentFlag );
m_cTEncTop.setChromaSampleLocTypeTopField ( m_chromaSampleLocTypeTopField );
m_cTEncTop.setChromaSampleLocTypeBottomField ( m_chromaSampleLocTypeBottomField );
m_cTEncTop.setNeutralChromaIndicationFlag ( m_neutralChromaIndicationFlag );
m_cTEncTop.setDefaultDisplayWindow ( m_defDispWinLeftOffset, m_defDispWinRightOffset, m_defDispWinTopOffset, m_defDispWinBottomOffset );
m_cTEncTop.setFrameFieldInfoPresentFlag ( m_frameFieldInfoPresentFlag );
m_cTEncTop.setPocProportionalToTimingFlag ( m_pocProportionalToTimingFlag );
m_cTEncTop.setNumTicksPocDiffOneMinus1 ( m_numTicksPocDiffOneMinus1 );
m_cTEncTop.setBitstreamRestrictionFlag ( m_bitstreamRestrictionFlag );
m_cTEncTop.setTilesFixedStructureFlag ( m_tilesFixedStructureFlag );
m_cTEncTop.setMotionVectorsOverPicBoundariesFlag ( m_motionVectorsOverPicBoundariesFlag );
m_cTEncTop.setMinSpatialSegmentationIdc ( m_minSpatialSegmentationIdc );
m_cTEncTop.setMaxBytesPerPicDenom ( m_maxBytesPerPicDenom );
m_cTEncTop.setMaxBitsPerMinCuDenom ( m_maxBitsPerMinCuDenom );
m_cTEncTop.setLog2MaxMvLengthHorizontal ( m_log2MaxMvLengthHorizontal );
m_cTEncTop.setLog2MaxMvLengthVertical ( m_log2MaxMvLengthVertical );
}
Void TAppEncTop::xCreateLib()
{
// Video I/O
m_cTVideoIOYuvInputFile.open( m_pchInputFile, false, m_inputBitDepth, m_MSBExtendedBitDepth, m_internalBitDepth ); // read mode
m_cTVideoIOYuvInputFile.skipFrames(m_FrameSkip, m_iSourceWidth - m_aiPad[0], m_iSourceHeight - m_aiPad[1], m_InputChromaFormatIDC);
if (m_pchReconFile)
{
m_cTVideoIOYuvReconFile.open(m_pchReconFile, true, m_outputBitDepth, m_outputBitDepth, m_internalBitDepth); // write mode
}
// Neo Decoder
m_cTEncTop.create();
}
Void TAppEncTop::xDestroyLib()
{
// Video I/O
m_cTVideoIOYuvInputFile.close();
m_cTVideoIOYuvReconFile.close();
// Neo Decoder
m_cTEncTop.destroy();
}
Void TAppEncTop::xInitLib(Bool isFieldCoding)
{
m_cTEncTop.init(isFieldCoding);
}
// ====================================================================================================================
// Public member functions
// ====================================================================================================================
/**
- create internal class
- initialize internal variable
- until the end of input YUV file, call encoding function in TEncTop class
- delete allocated buffers
- destroy internal class
.
*/
Void TAppEncTop::encode()
{
fstream bitstreamFile(m_pchBitstreamFile, fstream::binary | fstream::out);
if (!bitstreamFile)
{
fprintf(stderr, "\nfailed to open bitstream file `%s' for writing\n", m_pchBitstreamFile);
exit(EXIT_FAILURE);
}
TComPicYuv* pcPicYuvOrg = new TComPicYuv;
TComPicYuv* pcPicYuvRec = NULL;
// initialize internal class & member variables
xInitLibCfg();
xCreateLib();
xInitLib(m_isField);
if (m_verboseLevel) {
printChromaFormat();
}
// main encoder loop
Int iNumEncoded = 0;
Bool bEos = false;
const InputColourSpaceConversion ipCSC = m_inputColourSpaceConvert;
const InputColourSpaceConversion snrCSC = (!m_snrInternalColourSpace) ? m_inputColourSpaceConvert : IPCOLOURSPACE_UNCHANGED;
list<AccessUnit> outputAccessUnits; ///< list of access units to write out. is populated by the encoding process
TComPicYuv cPicYuvTrueOrg;
// allocate original YUV buffer
if( m_isField )
{
pcPicYuvOrg->create( m_iSourceWidth, m_iSourceHeightOrg, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth );
cPicYuvTrueOrg.create(m_iSourceWidth, m_iSourceHeightOrg, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth);
}
else
{
pcPicYuvOrg->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth );
cPicYuvTrueOrg.create(m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth);
}
while ( !bEos )
{
// get buffers
xGetBuffer(pcPicYuvRec);
// read input YUV file
m_cTVideoIOYuvInputFile.read( pcPicYuvOrg, &cPicYuvTrueOrg, ipCSC, m_aiPad, m_InputChromaFormatIDC );
// increase number of received frames
m_iFrameRcvd++;
bEos = (m_isField && (m_iFrameRcvd == (m_framesToBeEncoded >> 1) )) || ( !m_isField && (m_iFrameRcvd == m_framesToBeEncoded) );
Bool flush = 0;
// if end of file (which is only detected on a read failure) flush the encoder of any queued pictures
if (m_cTVideoIOYuvInputFile.isEof())
{
flush = true;
bEos = true;
m_iFrameRcvd--;
m_cTEncTop.setFramesToBeEncoded(m_iFrameRcvd);
}
// call encoding function for one frame
if ( m_isField ) m_cTEncTop.encode( bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded, m_isTopFieldFirst );
else m_cTEncTop.encode( bEos, flush ? 0 : pcPicYuvOrg, flush ? 0 : &cPicYuvTrueOrg, snrCSC, m_cListPicYuvRec, outputAccessUnits, iNumEncoded );
// write bistream to file if necessary
if ( iNumEncoded > 0 )
{
xWriteOutput(bitstreamFile, iNumEncoded, outputAccessUnits);
outputAccessUnits.clear();
}
}
if (m_verboseLevel) {
m_cTEncTop.printSummary(m_isField);
}
// delete original YUV buffer
pcPicYuvOrg->destroy();
delete pcPicYuvOrg;
pcPicYuvOrg = NULL;
// delete used buffers in encoder class
m_cTEncTop.deletePicBuffer();
cPicYuvTrueOrg.destroy();
// delete buffers & classes
xDeleteBuffer();
xDestroyLib();
if (m_verboseLevel) {
printRateSummary();
}
return;
}
// ====================================================================================================================
// Protected member functions
// ====================================================================================================================
/**
- application has picture buffer list with size of GOP
- picture buffer list acts as ring buffer
- end of the list has the latest picture
.
*/
Void TAppEncTop::xGetBuffer( TComPicYuv*& rpcPicYuvRec)
{
assert( m_iGOPSize > 0 );
// org. buffer
if ( m_cListPicYuvRec.size() >= (UInt)m_iGOPSize ) // buffer will be 1 element longer when using field coding, to maintain first field whilst processing second.
{
rpcPicYuvRec = m_cListPicYuvRec.popFront();
}
else
{
rpcPicYuvRec = new TComPicYuv;
rpcPicYuvRec->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_uiMaxCUWidth, m_uiMaxCUHeight, m_uiMaxCUDepth );
}
m_cListPicYuvRec.pushBack( rpcPicYuvRec );
}
Void TAppEncTop::xDeleteBuffer( )
{
TComList<TComPicYuv*>::iterator iterPicYuvRec = m_cListPicYuvRec.begin();
Int iSize = Int( m_cListPicYuvRec.size() );
for ( Int i = 0; i < iSize; i++ )
{
TComPicYuv* pcPicYuvRec = *(iterPicYuvRec++);
pcPicYuvRec->destroy();
delete pcPicYuvRec; pcPicYuvRec = NULL;
}
}
/** \param iNumEncoded number of encoded frames
*/
Void TAppEncTop::xWriteOutput(std::ostream& bitstreamFile, Int iNumEncoded, const std::list<AccessUnit>& accessUnits)
{
const InputColourSpaceConversion ipCSC = (!m_outputInternalColourSpace) ? m_inputColourSpaceConvert : IPCOLOURSPACE_UNCHANGED;
if (m_isField)
{
//Reinterlace fields
Int i;
TComList<TComPicYuv*>::iterator iterPicYuvRec = m_cListPicYuvRec.end();
list<AccessUnit>::const_iterator iterBitstream = accessUnits.begin();
for ( i = 0; i < iNumEncoded; i++ )
{
--iterPicYuvRec;
}
for ( i = 0; i < iNumEncoded/2; i++ )
{
TComPicYuv* pcPicYuvRecTop = *(iterPicYuvRec++);
TComPicYuv* pcPicYuvRecBottom = *(iterPicYuvRec++);
if (m_pchReconFile)
{
m_cTVideoIOYuvReconFile.write( pcPicYuvRecTop, pcPicYuvRecBottom, ipCSC, m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom, NUM_CHROMA_FORMAT, m_isTopFieldFirst );
}
const AccessUnit& auTop = *(iterBitstream++);
const vector<UInt>& statsTop = writeAnnexB(bitstreamFile, auTop);
rateStatsAccum(auTop, statsTop);
const AccessUnit& auBottom = *(iterBitstream++);
const vector<UInt>& statsBottom = writeAnnexB(bitstreamFile, auBottom);
rateStatsAccum(auBottom, statsBottom);
}
}
else
{
Int i;
TComList<TComPicYuv*>::iterator iterPicYuvRec = m_cListPicYuvRec.end();
list<AccessUnit>::const_iterator iterBitstream = accessUnits.begin();
for ( i = 0; i < iNumEncoded; i++ )
{
--iterPicYuvRec;
}
for ( i = 0; i < iNumEncoded; i++ )
{
TComPicYuv* pcPicYuvRec = *(iterPicYuvRec++);
if (m_pchReconFile)
{
m_cTVideoIOYuvReconFile.write( pcPicYuvRec, ipCSC, m_confWinLeft, m_confWinRight, m_confWinTop, m_confWinBottom );
}
const AccessUnit& au = *(iterBitstream++);
const vector<UInt>& stats = writeAnnexB(bitstreamFile, au);
rateStatsAccum(au, stats);
}
}
}
/**
*
*/
Void TAppEncTop::rateStatsAccum(const AccessUnit& au, const std::vector<UInt>& annexBsizes)
{
AccessUnit::const_iterator it_au = au.begin();
vector<UInt>::const_iterator it_stats = annexBsizes.begin();
for (; it_au != au.end(); it_au++, it_stats++)
{
switch ((*it_au)->m_nalUnitType)
{
case NAL_UNIT_CODED_SLICE_TRAIL_R:
case NAL_UNIT_CODED_SLICE_TRAIL_N:
case NAL_UNIT_CODED_SLICE_TSA_R:
case NAL_UNIT_CODED_SLICE_TSA_N:
case NAL_UNIT_CODED_SLICE_STSA_R:
case NAL_UNIT_CODED_SLICE_STSA_N:
case NAL_UNIT_CODED_SLICE_BLA_W_LP:
case NAL_UNIT_CODED_SLICE_BLA_W_RADL:
case NAL_UNIT_CODED_SLICE_BLA_N_LP:
case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
case NAL_UNIT_CODED_SLICE_IDR_N_LP:
case NAL_UNIT_CODED_SLICE_CRA:
case NAL_UNIT_CODED_SLICE_RADL_N:
case NAL_UNIT_CODED_SLICE_RADL_R:
case NAL_UNIT_CODED_SLICE_RASL_N:
case NAL_UNIT_CODED_SLICE_RASL_R:
case NAL_UNIT_VPS:
case NAL_UNIT_SPS:
case NAL_UNIT_PPS:
m_essentialBytes += *it_stats;
break;
default:
break;
}
m_totalBytes += *it_stats;
}
}
Void TAppEncTop::printRateSummary()
{
Double time = (Double) m_iFrameRcvd / m_iFrameRate;
printf("Bytes written to file: %u (%.3f kbps)\n", m_totalBytes, 0.008 * m_totalBytes / time);
#if VERBOSE_RATE
printf("Bytes for SPS/PPS/Slice (Incl. Annex B): %u (%.3f kbps)\n", m_essentialBytes, 0.008 * m_essentialBytes / time);
#endif
}
Void TAppEncTop::printChromaFormat()
{
std::cout << std::setw(43) << "Input ChromaFormatIDC = ";
switch (m_InputChromaFormatIDC)
{
case CHROMA_400: std::cout << " 4:0:0"; break;
case CHROMA_420: std::cout << " 4:2:0"; break;
case CHROMA_422: std::cout << " 4:2:2"; break;
case CHROMA_444: std::cout << " 4:4:4"; break;
default:
std::cerr << "Invalid";
exit(1);
}
std::cout << std::endl;
std::cout << std::setw(43) << "Output (internal) ChromaFormatIDC = ";
switch (m_cTEncTop.getChromaFormatIdc())
{
case CHROMA_400: std::cout << " 4:0:0"; break;
case CHROMA_420: std::cout << " 4:2:0"; break;
case CHROMA_422: std::cout << " 4:2:2"; break;
case CHROMA_444: std::cout << " 4:4:4"; break;
default:
std::cerr << "Invalid";
exit(1);
}
std::cout << "\n" << std::endl;
}
//! \}