source: 3DVCSoftware/trunk/source/Lib/TLibEncoder/TEncGOP.cpp

Last change on this file was 1413, checked in by tech, 7 years ago

Merged HTM-16.2-dev@1412

  • Property svn:eol-style set to native
File size: 130.5 KB
RevLine 
[5]1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
[1313]4 * granted under this license.
[5]5 *
[1413]6 * Copyright (c) 2010-2017, ITU/ISO/IEC
[5]7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
[56]17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
[5]18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
[2]33
[56]34/** \file     TEncGOP.cpp
[2]35    \brief    GOP encoder class
36*/
37
[56]38#include <list>
39#include <algorithm>
[608]40#include <functional>
[56]41
[2]42#include "TEncTop.h"
43#include "TEncGOP.h"
44#include "TEncAnalyze.h"
[56]45#include "libmd5/MD5.h"
46#include "TLibCommon/SEI.h"
47#include "TLibCommon/NAL.h"
48#include "NALwrite.h"
[2]49#include <time.h>
[56]50#include <math.h>
[2]51
[1313]52#include <deque>
[56]53using namespace std;
[1313]54
[56]55//! \ingroup TLibEncoder
56//! \{
57
[2]58// ====================================================================================================================
59// Constructor / destructor / initialization / destroy
60// ====================================================================================================================
[608]61Int getLSB(Int poc, Int maxLSB)
62{
63  if (poc >= 0)
64  {
65    return poc % maxLSB;
66  }
67  else
68  {
69    return (maxLSB - ((-poc) % maxLSB)) % maxLSB;
70  }
71}
[2]72
[56]73TEncGOP::TEncGOP()
[2]74{
[56]75  m_iLastIDR            = 0;
76  m_iGopSize            = 0;
77  m_iNumPicCoded        = 0; //Niko
78  m_bFirst              = true;
[964]79  m_iLastRecoveryPicPOC = 0;
[1313]80
[2]81  m_pcCfg               = NULL;
82  m_pcSliceEncoder      = NULL;
83  m_pcListPic           = NULL;
[1313]84
[2]85  m_pcEntropyCoder      = NULL;
86  m_pcCavlcCoder        = NULL;
87  m_pcSbacCoder         = NULL;
88  m_pcBinCABAC          = NULL;
[1313]89
[56]90  m_bSeqFirst           = true;
[1313]91
[2]92  m_bRefreshPending     = 0;
[608]93  m_pocCRA            = 0;
94  m_numLongTermRefPicSPS = 0;
95  ::memset(m_ltRefPicPocLsbSps, 0, sizeof(m_ltRefPicPocLsbSps));
96  ::memset(m_ltRefPicUsedByCurrPicFlag, 0, sizeof(m_ltRefPicUsedByCurrPicFlag));
97  m_lastBPSEI         = 0;
[1313]98  m_bufferingPeriodSEIPresentInAU = false;
99#if NH_MV
[608]100  m_layerId      = 0;
101  m_viewId       = 0;
[1356]102  m_pocLastCoded = -1;
[1313]103#if NH_3D
[1356]104  m_viewIndex  =   0;
[608]105  m_isDepth = false;
106#endif
107#endif
[872]108  m_associatedIRAPType = NAL_UNIT_CODED_SLICE_IDR_N_LP;
109  m_associatedIRAPPOC  = 0;
[1405]110  m_pcDeblockingTempPicYuv = NULL;
[2]111}
112
[56]113TEncGOP::~TEncGOP()
[2]114{
115}
116
[1313]117/** Create list to contain pointers to CTU start addresses of slice.
[2]118 */
[608]119Void  TEncGOP::create()
[2]120{
[56]121  m_bLongtermTestPictureHasBeenCoded = 0;
122  m_bLongtermTestPictureHasBeenCoded2 = 0;
[2]123}
124
[56]125Void  TEncGOP::destroy()
[2]126{
[1405]127  if (m_pcDeblockingTempPicYuv)
128  {
129    m_pcDeblockingTempPicYuv->destroy();
130    delete m_pcDeblockingTempPicYuv;
131    m_pcDeblockingTempPicYuv = NULL;
132  }
[2]133}
134
[56]135Void TEncGOP::init ( TEncTop* pcTEncTop )
[2]136{
137  m_pcEncTop     = pcTEncTop;
138  m_pcCfg                = pcTEncTop;
[1313]139  m_seiEncoder.init(m_pcCfg, pcTEncTop, this);
[2]140  m_pcSliceEncoder       = pcTEncTop->getSliceEncoder();
141  m_pcListPic            = pcTEncTop->getListPic();
[1313]142
[2]143  m_pcEntropyCoder       = pcTEncTop->getEntropyCoder();
144  m_pcCavlcCoder         = pcTEncTop->getCavlcCoder();
145  m_pcSbacCoder          = pcTEncTop->getSbacCoder();
146  m_pcBinCABAC           = pcTEncTop->getBinCABAC();
147  m_pcLoopFilter         = pcTEncTop->getLoopFilter();
[1313]148
[608]149  m_pcSAO                = pcTEncTop->getSAO();
150  m_pcRateCtrl           = pcTEncTop->getRateCtrl();
151  m_lastBPSEI          = 0;
152  m_totalCoded         = 0;
153
[1313]154#if NH_MV
[1356]155  m_ivPicLists           = pcTEncTop->getIvPicLists();
[608]156  m_layerId              = pcTEncTop->getLayerId();
157  m_viewId               = pcTEncTop->getViewId();
[1413]158#endif
159
[1313]160#if NH_3D
[608]161  m_viewIndex            = pcTEncTop->getViewIndex();
162  m_isDepth              = pcTEncTop->getIsDepth();
[1413]163
[1356]164  m_aICEnableCandidate   = pcTEncTop->getICEnableCandidate();
165  m_aICEnableNum         = pcTEncTop->getICEnableNum();
[1066]166#endif
[655]167#if KWU_FIX_URQ
168  m_pcRateCtrl           = pcTEncTop->getRateCtrl();
169#endif
[2]170}
171
[1313]172Int TEncGOP::xWriteVPS (AccessUnit &accessUnit, const TComVPS *vps)
[608]173{
[1313]174  OutputNALUnit nalu(NAL_UNIT_VPS);
175  m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
176  m_pcEntropyCoder->encodeVPS(vps);
177  accessUnit.push_back(new NALUnitEBSP(nalu));
178  return (Int)(accessUnit.back()->m_nalUnitData.str().size()) * 8;
[608]179}
180
[1313]181Int TEncGOP::xWriteSPS (AccessUnit &accessUnit, const TComSPS *sps)
[608]182{
[1313]183#if NH_MV
184  OutputNALUnit nalu(NAL_UNIT_SPS, 0, getLayerId() );
185#else
186  OutputNALUnit nalu(NAL_UNIT_SPS);
187#endif
188  m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
189  m_pcEntropyCoder->encodeSPS(sps);
190  accessUnit.push_back(new NALUnitEBSP(nalu));
191  return (Int)(accessUnit.back()->m_nalUnitData.str().size()) * 8;
192
[608]193}
194
[1313]195Int TEncGOP::xWritePPS (AccessUnit &accessUnit, const TComPPS *pps)
[608]196{
[1313]197#if NH_MV
198  OutputNALUnit nalu(NAL_UNIT_PPS, 0, getLayerId() );
199#else
200  OutputNALUnit nalu(NAL_UNIT_PPS);
201#endif
202  m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
203  m_pcEntropyCoder->encodePPS(pps);
204  accessUnit.push_back(new NALUnitEBSP(nalu));
205  return (Int)(accessUnit.back()->m_nalUnitData.str().size()) * 8;
[608]206}
207
[1313]208
[1413]209#if NH_MV
210Int TEncGOP::xWriteParameterSets (AccessUnit &accessUnit, TComSlice *slice, const Bool bSeqFirst, const Bool bWriteVps )
211#else
212Int TEncGOP::xWriteParameterSets (AccessUnit &accessUnit, TComSlice *slice, const Bool bSeqFirst)
213#endif
[608]214{
[1313]215  Int actualTotalBits = 0;
[608]216
[1313]217#if NH_MV
[1413]218  if ( bWriteVps )
[1356]219  {
[1313]220    actualTotalBits += xWriteVPS(accessUnit, m_pcEncTop->getVPS());
221  }
222#else
[1413]223  if (bSeqFirst)
224  {
225    actualTotalBits += xWriteVPS(accessUnit, m_pcEncTop->getVPS());
226  }
[1313]227#endif
[1413]228  if (m_pcEncTop->SPSNeedsWriting(slice->getSPS()->getSPSId())) // Note this assumes that all changes to the SPS are made at the TEncTop level prior to picture creation (TEncTop::xGetNewPicBuffer).
229  {
230    assert(bSeqFirst); // Implementations that use more than 1 SPS need to be aware of activation issues.
231    actualTotalBits += xWriteSPS(accessUnit, slice->getSPS());
232  }
233  if (m_pcEncTop->PPSNeedsWriting(slice->getPPS()->getPPSId())) // Note this assumes that all changes to the PPS are made at the TEncTop level prior to picture creation (TEncTop::xGetNewPicBuffer).
234  {
235    actualTotalBits += xWritePPS(accessUnit, slice->getPPS());
236  }
[608]237
[1313]238  return actualTotalBits;
239}
240
[1386]241Void TEncGOP::xWriteAccessUnitDelimiter (AccessUnit &accessUnit, TComSlice *slice)
242{
243  AUDWriter audWriter;
244  OutputNALUnit nalu(NAL_UNIT_ACCESS_UNIT_DELIMITER);
245
246  Int picType = slice->isIntra() ? 0 : (slice->isInterP() ? 1 : 2);
247
248  audWriter.codeAUD(nalu.m_Bitstream, picType);
249  accessUnit.push_front(new NALUnitEBSP(nalu));
250}
251
[1313]252// write SEI list into one NAL unit and add it to the Access unit at auPos
253Void TEncGOP::xWriteSEI (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, Int temporalId, const TComSPS *sps)
254{
255  // don't do anything, if we get an empty list
256  if (seiMessages.empty())
[608]257  {
[1313]258    return;
259  }
260#if NH_MV
261  OutputNALUnit nalu(naluType, temporalId, getLayerId() );
262#else
263  OutputNALUnit nalu(naluType, temporalId);
264#endif
265  m_seiWriter.writeSEImessages(nalu.m_Bitstream, seiMessages, sps, false);
266  auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu));
267  auPos++;
268}
269
270Void TEncGOP::xWriteSEISeparately (NalUnitType naluType, SEIMessages& seiMessages, AccessUnit &accessUnit, AccessUnit::iterator &auPos, Int temporalId, const TComSPS *sps)
271{
272  // don't do anything, if we get an empty list
273  if (seiMessages.empty())
274  {
275    return;
276  }
277  for (SEIMessages::const_iterator sei = seiMessages.begin(); sei!=seiMessages.end(); sei++ )
278  {
279    SEIMessages tmpMessages;
280    tmpMessages.push_back(*sei);
281#if NH_MV
282    OutputNALUnit nalu(naluType, temporalId, getLayerId() );
283#else
284    OutputNALUnit nalu(naluType, temporalId);
285#endif
286    m_seiWriter.writeSEImessages(nalu.m_Bitstream, tmpMessages, sps, false);
287    auPos = accessUnit.insert(auPos, new NALUnitEBSP(nalu));
288    auPos++;
289  }
290}
291
292Void TEncGOP::xClearSEIs(SEIMessages& seiMessages, Bool deleteMessages)
293{
294  if (deleteMessages)
295  {
296    deleteSEIs(seiMessages);
297  }
298  else
299  {
300    seiMessages.clear();
301  }
302}
303
304// write SEI messages as separate NAL units ordered
305Void TEncGOP::xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, Bool testWrite)
306{
307  AccessUnit::iterator itNalu = accessUnit.begin();
308
309  while ( (itNalu!=accessUnit.end())&&
[1356]310    ( (*itNalu)->m_nalUnitType==NAL_UNIT_ACCESS_UNIT_DELIMITER
[1313]311    || (*itNalu)->m_nalUnitType==NAL_UNIT_VPS
312    || (*itNalu)->m_nalUnitType==NAL_UNIT_SPS
313    || (*itNalu)->m_nalUnitType==NAL_UNIT_PPS
314    ))
315  {
316    itNalu++;
317  }
318
319  SEIMessages localMessages = seiMessages;
320  SEIMessages currentMessages;
[1356]321
[1313]322#if ENC_DEC_TRACE
323  g_HLSTraceEnable = !testWrite;
324#endif
325  // The case that a specific SEI is not present is handled in xWriteSEI (empty list)
326
327  // Active parameter sets SEI must always be the first SEI
328  currentMessages = extractSeisByType(localMessages, SEI::ACTIVE_PARAMETER_SETS);
329  assert (currentMessages.size() <= 1);
330  xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps);
331  xClearSEIs(currentMessages, !testWrite);
[1356]332
[1313]333  // Buffering period SEI must always be following active parameter sets
334  currentMessages = extractSeisByType(localMessages, SEI::BUFFERING_PERIOD);
335  assert (currentMessages.size() <= 1);
336  xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps);
337  xClearSEIs(currentMessages, !testWrite);
338
339  // Picture timing SEI must always be following buffering period
340  currentMessages = extractSeisByType(localMessages, SEI::PICTURE_TIMING);
341  assert (currentMessages.size() <= 1);
342  xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps);
343  xClearSEIs(currentMessages, !testWrite);
344
345  // Decoding unit info SEI must always be following picture timing
346  if (!duInfoSeiMessages.empty())
347  {
348    currentMessages.push_back(duInfoSeiMessages.front());
349    if (!testWrite)
[608]350    {
[1313]351      duInfoSeiMessages.pop_front();
[608]352    }
[1313]353    xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps);
354    xClearSEIs(currentMessages, !testWrite);
355  }
356
357  // Scalable nesting SEI must always be the following DU info
358  currentMessages = extractSeisByType(localMessages, SEI::SCALABLE_NESTING);
359  xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps);
360  xClearSEIs(currentMessages, !testWrite);
361
[1386]362#if NH_MV
[1356]363  // Layers not present SEI message
364  currentMessages = extractSeisByType(localMessages, SEI::LAYERS_NOT_PRESENT);
365  xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId, sps);
366  xClearSEIs(currentMessages, !testWrite);
367#endif
368
[1313]369  // And finally everything else one by one
370  xWriteSEISeparately(NAL_UNIT_PREFIX_SEI, localMessages, accessUnit, itNalu, temporalId, sps);
371  xClearSEIs(localMessages, !testWrite);
372
373  if (!testWrite)
374  {
375    seiMessages.clear();
376  }
377}
378
379
380Void TEncGOP::xWriteLeadingSEIMessages (SEIMessages& seiMessages, SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, std::deque<DUData> &duData)
381{
382  AccessUnit testAU;
383  SEIMessages picTimingSEIs = getSeisByType(seiMessages, SEI::PICTURE_TIMING);
384  assert (picTimingSEIs.size() < 2);
385  SEIPictureTiming * picTiming = picTimingSEIs.empty() ? NULL : (SEIPictureTiming*) picTimingSEIs.front();
386
387  // test writing
388  xWriteLeadingSEIOrdered(seiMessages, duInfoSeiMessages, testAU, temporalId, sps, true);
389  // update Timing and DU info SEI
390  xUpdateDuData(testAU, duData);
391  xUpdateTimingSEI(picTiming, duData, sps);
392  xUpdateDuInfoSEI(duInfoSeiMessages, picTiming);
393  // actual writing
394  xWriteLeadingSEIOrdered(seiMessages, duInfoSeiMessages, accessUnit, temporalId, sps, false);
395
396  // testAU will automatically be cleaned up when losing scope
397}
398
399Void TEncGOP::xWriteTrailingSEIMessages (SEIMessages& seiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps)
400{
401  // Note: using accessUnit.end() works only as long as this function is called after slice coding and before EOS/EOB NAL units
402  AccessUnit::iterator pos = accessUnit.end();
403  xWriteSEISeparately(NAL_UNIT_SUFFIX_SEI, seiMessages, accessUnit, pos, temporalId, sps);
404  deleteSEIs(seiMessages);
405}
406
407Void TEncGOP::xWriteDuSEIMessages (SEIMessages& duInfoSeiMessages, AccessUnit &accessUnit, Int temporalId, const TComSPS *sps, std::deque<DUData> &duData)
408{
409  const TComHRD *hrd = sps->getVuiParameters()->getHrdParameters();
410
411  if( m_pcCfg->getDecodingUnitInfoSEIEnabled() && hrd->getSubPicCpbParamsPresentFlag() )
412  {
413    Int naluIdx = 0;
414    AccessUnit::iterator nalu = accessUnit.begin();
415
416    // skip over first DU, we have a DU info SEI there already
417    while (naluIdx < duData[0].accumNalsDU && nalu!=accessUnit.end())
[608]418    {
[1313]419      naluIdx++;
420      nalu++;
[608]421    }
[1313]422
423    SEIMessages::iterator duSEI = duInfoSeiMessages.begin();
424    // loop over remaining DUs
425    for (Int duIdx = 1; duIdx < duData.size(); duIdx++)
[608]426    {
[1313]427      if (duSEI == duInfoSeiMessages.end())
[608]428      {
[1313]429        // if the number of generated SEIs matches the number of DUs, this should not happen
430        assert (false);
431        return;
[608]432      }
[1313]433      // write the next SEI
434      SEIMessages tmpSEI;
435      tmpSEI.push_back(*duSEI);
436      xWriteSEI(NAL_UNIT_PREFIX_SEI, tmpSEI, accessUnit, nalu, temporalId, sps);
437      // nalu points to the position after the SEI, so we have to increase the index as well
438      naluIdx++;
439      while ((naluIdx < duData[duIdx].accumNalsDU) && nalu!=accessUnit.end())
440      {
441        naluIdx++;
442        nalu++;
443      }
444      duSEI++;
[608]445    }
[1313]446  }
447  deleteSEIs(duInfoSeiMessages);
448}
449
450Void TEncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const TComSPS *sps, const TComPPS *pps)
451{
452  OutputNALUnit nalu(NAL_UNIT_PREFIX_SEI);
[1356]453
[1313]454  if(m_pcCfg->getActiveParameterSetsSEIEnabled())
455  {
456    SEIActiveParameterSets *sei = new SEIActiveParameterSets;
457    m_seiEncoder.initSEIActiveParameterSets (sei, m_pcCfg->getVPS(), sps);
458    seiMessages.push_back(sei);
459  }
460
461  if(m_pcCfg->getFramePackingArrangementSEIEnabled())
462  {
463    SEIFramePacking *sei = new SEIFramePacking;
464    m_seiEncoder.initSEIFramePacking (sei, m_iNumPicCoded);
465    seiMessages.push_back(sei);
466  }
467
468  if(m_pcCfg->getSegmentedRectFramePackingArrangementSEIEnabled())
469  {
470    SEISegmentedRectFramePacking *sei = new SEISegmentedRectFramePacking;
471    m_seiEncoder.initSEISegmentedRectFramePacking(sei);
472    seiMessages.push_back(sei);
473  }
474
475  if (m_pcCfg->getDisplayOrientationSEIAngle())
476  {
477    SEIDisplayOrientation *sei = new SEIDisplayOrientation;
478    m_seiEncoder.initSEIDisplayOrientation(sei);
479    seiMessages.push_back(sei);
480  }
481
482  if(m_pcCfg->getToneMappingInfoSEIEnabled())
483  {
484    SEIToneMappingInfo *sei = new SEIToneMappingInfo;
485    m_seiEncoder.initSEIToneMappingInfo (sei);
486    seiMessages.push_back(sei);
487  }
488
489  if(m_pcCfg->getTMCTSSEIEnabled())
490  {
491    SEITempMotionConstrainedTileSets *sei = new SEITempMotionConstrainedTileSets;
492    m_seiEncoder.initSEITempMotionConstrainedTileSets(sei, pps);
493    seiMessages.push_back(sei);
494  }
495
496  if(m_pcCfg->getTimeCodeSEIEnabled())
497  {
498    SEITimeCode *seiTimeCode = new SEITimeCode;
499    m_seiEncoder.initSEITimeCode(seiTimeCode);
500    seiMessages.push_back(seiTimeCode);
501  }
502
503  if(m_pcCfg->getKneeSEIEnabled())
504  {
505    SEIKneeFunctionInfo *sei = new SEIKneeFunctionInfo;
506    m_seiEncoder.initSEIKneeFunctionInfo(sei);
507    seiMessages.push_back(sei);
508  }
[1356]509
[1313]510  if(m_pcCfg->getMasteringDisplaySEI().colourVolumeSEIEnabled)
511  {
512    const TComSEIMasteringDisplay &seiCfg=m_pcCfg->getMasteringDisplaySEI();
513    SEIMasteringDisplayColourVolume *sei = new SEIMasteringDisplayColourVolume;
514    sei->values = seiCfg;
515    seiMessages.push_back(sei);
516  }
517
[1386]518  if(m_pcCfg->getChromaResamplingFilterHintEnabled())
[1313]519  {
[1386]520    SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint = new SEIChromaResamplingFilterHint;
521    m_seiEncoder.initSEIChromaResamplingFilterHint(seiChromaResamplingFilterHint, m_pcCfg->getChromaResamplingHorFilterIdc(), m_pcCfg->getChromaResamplingVerFilterIdc());
522    seiMessages.push_back(seiChromaResamplingFilterHint);
[1313]523  }
[1405]524  if(m_pcCfg->getSEIAlternativeTransferCharacteristicsSEIEnable())
525  {
526    SEIAlternativeTransferCharacteristics *seiAlternativeTransferCharacteristics = new SEIAlternativeTransferCharacteristics;
527    m_seiEncoder.initSEIAlternativeTransferCharacteristics(seiAlternativeTransferCharacteristics);
528    seiMessages.push_back(seiAlternativeTransferCharacteristics);
529  }
[1313]530}
531
532Void TEncGOP::xCreatePerPictureSEIMessages (Int picInGOP, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, TComSlice *slice)
533{
534  if( ( m_pcCfg->getBufferingPeriodSEIEnabled() ) && ( slice->getSliceType() == I_SLICE ) &&
535    ( slice->getSPS()->getVuiParametersPresentFlag() ) &&
536    ( ( slice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() )
537    || ( slice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) )
538  {
539    SEIBufferingPeriod *bufferingPeriodSEI = new SEIBufferingPeriod();
540    m_seiEncoder.initSEIBufferingPeriod(bufferingPeriodSEI, slice);
541    seiMessages.push_back(bufferingPeriodSEI);
542    m_bufferingPeriodSEIPresentInAU = true;
543
544    if (m_pcCfg->getScalableNestingSEIEnabled())
[608]545    {
[1313]546      SEIBufferingPeriod *bufferingPeriodSEIcopy = new SEIBufferingPeriod();
547      bufferingPeriodSEI->copyTo(*bufferingPeriodSEIcopy);
548      nestedSeiMessages.push_back(bufferingPeriodSEIcopy);
[608]549    }
[1313]550  }
551
552  if (picInGOP ==0 && m_pcCfg->getSOPDescriptionSEIEnabled() ) // write SOP description SEI (if enabled) at the beginning of GOP
553  {
554    SEISOPDescription* sopDescriptionSEI = new SEISOPDescription();
555    m_seiEncoder.initSEISOPDescription(sopDescriptionSEI, slice, picInGOP, m_iLastIDR, m_iGopSize);
556    seiMessages.push_back(sopDescriptionSEI);
557  }
558
559  if( ( m_pcEncTop->getRecoveryPointSEIEnabled() ) && ( slice->getSliceType() == I_SLICE ) )
560  {
561    if( m_pcEncTop->getGradualDecodingRefreshInfoEnabled() && !slice->getRapPicFlag() )
[608]562    {
[1313]563      // Gradual decoding refresh SEI
[1413]564      SEIRegionRefreshInfo *gradualDecodingRefreshInfoSEI = new SEIRegionRefreshInfo();
[1313]565      gradualDecodingRefreshInfoSEI->m_gdrForegroundFlag = true; // Indicating all "foreground"
566      seiMessages.push_back(gradualDecodingRefreshInfoSEI);
[608]567    }
[1313]568    // Recovery point SEI
569    SEIRecoveryPoint *recoveryPointSEI = new SEIRecoveryPoint();
570    m_seiEncoder.initSEIRecoveryPoint(recoveryPointSEI, slice);
571    seiMessages.push_back(recoveryPointSEI);
[608]572  }
[1313]573  if (m_pcCfg->getTemporalLevel0IndexSEIEnabled())
574  {
575    SEITemporalLevel0Index *temporalLevel0IndexSEI = new SEITemporalLevel0Index();
576    m_seiEncoder.initTemporalLevel0IndexSEI(temporalLevel0IndexSEI, slice);
577    seiMessages.push_back(temporalLevel0IndexSEI);
578  }
579
580  if( m_pcEncTop->getNoDisplaySEITLayer() && ( slice->getTLayer() >= m_pcEncTop->getNoDisplaySEITLayer() ) )
581  {
582    SEINoDisplay *seiNoDisplay = new SEINoDisplay;
583    seiNoDisplay->m_noDisplay = true;
584    seiMessages.push_back(seiNoDisplay);
585  }
[1386]586
587  // insert one Colour Remapping Info SEI for the picture (if the file exists)
588  if (!m_pcCfg->getColourRemapInfoSEIFileRoot().empty())
589  {
590    SEIColourRemappingInfo *seiColourRemappingInfo = new SEIColourRemappingInfo();
591    const Bool success = m_seiEncoder.initSEIColourRemappingInfo(seiColourRemappingInfo, slice->getPOC() );
592
593    if(success)
594    {
595      seiMessages.push_back(seiColourRemappingInfo);
596    }
597    else
598    {
599      delete seiColourRemappingInfo;
600    }
601  }
[608]602}
603
[1313]604Void TEncGOP::xCreateScalableNestingSEI (SEIMessages& seiMessages, SEIMessages& nestedSeiMessages)
[872]605{
[1313]606  SEIMessages tmpMessages;
607  while (!nestedSeiMessages.empty())
608  {
609    SEI* sei=nestedSeiMessages.front();
610    nestedSeiMessages.pop_front();
611    tmpMessages.push_back(sei);
612    SEIScalableNesting *nestingSEI = new SEIScalableNesting();
613    m_seiEncoder.initSEIScalableNesting(nestingSEI, tmpMessages);
614    seiMessages.push_back(nestingSEI);
615    tmpMessages.clear();
616  }
617}
[872]618
[1313]619Void TEncGOP::xCreatePictureTimingSEI  (Int IRAPGOPid, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, SEIMessages& duInfoSeiMessages, TComSlice *slice, Bool isField, std::deque<DUData> &duData)
620{
[872]621
[1313]622  const TComVUI *vui = slice->getSPS()->getVuiParameters();
623  const TComHRD *hrd = vui->getHrdParameters();
624
625  // update decoding unit parameters
626  if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) &&
627    ( slice->getSPS()->getVuiParametersPresentFlag() ) &&
628    (  hrd->getNalHrdParametersPresentFlag() || hrd->getVclHrdParametersPresentFlag() ) )
629  {
[1386]630    Int picSptDpbOutputDuDelay = 0;
[1313]631    SEIPictureTiming *pictureTimingSEI = new SEIPictureTiming();
[872]632
[1313]633    // DU parameters
634    if( hrd->getSubPicCpbParamsPresentFlag() )
635    {
636      UInt numDU = (UInt) duData.size();
637      pictureTimingSEI->m_numDecodingUnitsMinus1     = ( numDU - 1 );
638      pictureTimingSEI->m_duCommonCpbRemovalDelayFlag = false;
639      pictureTimingSEI->m_numNalusInDuMinus1.resize( numDU );
640      pictureTimingSEI->m_duCpbRemovalDelayMinus1.resize( numDU );
641    }
642    pictureTimingSEI->m_auCpbRemovalDelay = std::min<Int>(std::max<Int>(1, m_totalCoded - m_lastBPSEI), static_cast<Int>(pow(2, static_cast<Double>(hrd->getCpbRemovalDelayLengthMinus1()+1)))); // Syntax element signalled as minus, hence the .
643    pictureTimingSEI->m_picDpbOutputDelay = slice->getSPS()->getNumReorderPics(slice->getSPS()->getMaxTLayers()-1) + slice->getPOC() - m_totalCoded;
644    if(m_pcCfg->getEfficientFieldIRAPEnabled() && IRAPGOPid > 0 && IRAPGOPid < m_iGopSize)
645    {
646      // if pictures have been swapped there is likely one more picture delay on their tid. Very rough approximation
647      pictureTimingSEI->m_picDpbOutputDelay ++;
648    }
649    Int factor = hrd->getTickDivisorMinus2() + 2;
650    pictureTimingSEI->m_picDpbOutputDuDelay = factor * pictureTimingSEI->m_picDpbOutputDelay;
651    if( m_pcCfg->getDecodingUnitInfoSEIEnabled() )
652    {
653      picSptDpbOutputDuDelay = factor * pictureTimingSEI->m_picDpbOutputDelay;
654    }
655    if (m_bufferingPeriodSEIPresentInAU)
656    {
657      m_lastBPSEI = m_totalCoded;
658    }
659
660    if( hrd->getSubPicCpbParamsPresentFlag() )
661    {
662      Int i;
663      UInt64 ui64Tmp;
664      UInt uiPrev = 0;
665      UInt numDU = ( pictureTimingSEI->m_numDecodingUnitsMinus1 + 1 );
666      std::vector<UInt> &rDuCpbRemovalDelayMinus1 = pictureTimingSEI->m_duCpbRemovalDelayMinus1;
667      UInt maxDiff = ( hrd->getTickDivisorMinus2() + 2 ) - 1;
668
669      for( i = 0; i < numDU; i ++ )
670      {
671        pictureTimingSEI->m_numNalusInDuMinus1[ i ]       = ( i == 0 ) ? ( duData[i].accumNalsDU - 1 ) : ( duData[i].accumNalsDU- duData[i-1].accumNalsDU - 1 );
672      }
673
674      if( numDU == 1 )
675      {
676        rDuCpbRemovalDelayMinus1[ 0 ] = 0; /* don't care */
677      }
678      else
679      {
680        rDuCpbRemovalDelayMinus1[ numDU - 1 ] = 0;/* by definition */
681        UInt tmp = 0;
682        UInt accum = 0;
683
684        for( i = ( numDU - 2 ); i >= 0; i -- )
685        {
686          ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU  - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) );
687          if( (UInt)ui64Tmp > maxDiff )
688          {
689            tmp ++;
690          }
691        }
692        uiPrev = 0;
693
694        UInt flag = 0;
695        for( i = ( numDU - 2 ); i >= 0; i -- )
696        {
697          flag = 0;
698          ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU  - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) );
699
700          if( (UInt)ui64Tmp > maxDiff )
701          {
702            if(uiPrev >= maxDiff - tmp)
703            {
704              ui64Tmp = uiPrev + 1;
705              flag = 1;
706            }
707            else                            ui64Tmp = maxDiff - tmp + 1;
708          }
709          rDuCpbRemovalDelayMinus1[ i ] = (UInt)ui64Tmp - uiPrev - 1;
710          if( (Int)rDuCpbRemovalDelayMinus1[ i ] < 0 )
711          {
712            rDuCpbRemovalDelayMinus1[ i ] = 0;
713          }
714          else if (tmp > 0 && flag == 1)
715          {
716            tmp --;
717          }
718          accum += rDuCpbRemovalDelayMinus1[ i ] + 1;
719          uiPrev = accum;
720        }
721      }
722    }
[1356]723
[1313]724    if( m_pcCfg->getPictureTimingSEIEnabled() )
725    {
726      pictureTimingSEI->m_picStruct = (isField && slice->getPic()->isTopField())? 1 : isField? 2 : 0;
727      seiMessages.push_back(pictureTimingSEI);
728
729      if ( m_pcCfg->getScalableNestingSEIEnabled() ) // put picture timing SEI into scalable nesting SEI
730      {
731          SEIPictureTiming *pictureTimingSEIcopy = new SEIPictureTiming();
732          pictureTimingSEI->copyTo(*pictureTimingSEIcopy);
733          nestedSeiMessages.push_back(pictureTimingSEIcopy);
734        }
735    }
736
737    if( m_pcCfg->getDecodingUnitInfoSEIEnabled() && hrd->getSubPicCpbParamsPresentFlag() )
738    {
739      for( Int i = 0; i < ( pictureTimingSEI->m_numDecodingUnitsMinus1 + 1 ); i ++ )
740      {
741        SEIDecodingUnitInfo *duInfoSEI = new SEIDecodingUnitInfo();
742        duInfoSEI->m_decodingUnitIdx = i;
743        duInfoSEI->m_duSptCpbRemovalDelay = pictureTimingSEI->m_duCpbRemovalDelayMinus1[i] + 1;
744        duInfoSEI->m_dpbOutputDuDelayPresentFlag = false;
745        duInfoSEI->m_picSptDpbOutputDuDelay = picSptDpbOutputDuDelay;
746
747        duInfoSeiMessages.push_back(duInfoSEI);
748      }
749    }
[1386]750
751    if( !m_pcCfg->getPictureTimingSEIEnabled() && pictureTimingSEI )
752    {
753      delete pictureTimingSEI;
754    }
[1313]755  }
756}
757
758Void TEncGOP::xUpdateDuData(AccessUnit &testAU, std::deque<DUData> &duData)
[608]759{
[1313]760  if (duData.empty())
761  {
762    return;
763  }
[1356]764  // fix first
[1313]765  UInt numNalUnits = (UInt)testAU.size();
766  UInt numRBSPBytes = 0;
767  for (AccessUnit::const_iterator it = testAU.begin(); it != testAU.end(); it++)
768  {
769    numRBSPBytes += UInt((*it)->m_nalUnitData.str().size());
770  }
771  duData[0].accumBitsDU += ( numRBSPBytes << 3 );
772  duData[0].accumNalsDU += numNalUnits;
[608]773
[1313]774  // adapt cumulative sums for all following DUs
775  // and add one DU info SEI, if enabled
776  for (Int i=1; i<duData.size(); i++)
[608]777  {
[1313]778    if (m_pcCfg->getDecodingUnitInfoSEIEnabled())
779    {
780      numNalUnits  += 1;
781      numRBSPBytes += ( 5 << 3 );
782    }
783    duData[i].accumBitsDU += numRBSPBytes; // probably around 5 bytes
784    duData[i].accumNalsDU += numNalUnits;
785  }
[608]786
[1313]787  // The last DU may have a trailing SEI
[1386]788  if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE)
[1313]789  {
790    duData.back().accumBitsDU += ( 20 << 3 ); // probably around 20 bytes - should be further adjusted, e.g. by type
791    duData.back().accumNalsDU += 1;
[608]792  }
793
[1313]794}
795Void TEncGOP::xUpdateTimingSEI(SEIPictureTiming *pictureTimingSEI, std::deque<DUData> &duData, const TComSPS *sps)
796{
797  if (!pictureTimingSEI)
[608]798  {
[1313]799    return;
[608]800  }
[1313]801  const TComVUI *vui = sps->getVuiParameters();
802  const TComHRD *hrd = vui->getHrdParameters();
803  if( hrd->getSubPicCpbParamsPresentFlag() )
[608]804  {
[1313]805    Int i;
806    UInt64 ui64Tmp;
807    UInt uiPrev = 0;
808    UInt numDU = ( pictureTimingSEI->m_numDecodingUnitsMinus1 + 1 );
809    std::vector<UInt> &rDuCpbRemovalDelayMinus1 = pictureTimingSEI->m_duCpbRemovalDelayMinus1;
810    UInt maxDiff = ( hrd->getTickDivisorMinus2() + 2 ) - 1;
[608]811
[1313]812    for( i = 0; i < numDU; i ++ )
813    {
814      pictureTimingSEI->m_numNalusInDuMinus1[ i ]       = ( i == 0 ) ? ( duData[i].accumNalsDU - 1 ) : ( duData[i].accumNalsDU- duData[i-1].accumNalsDU - 1 );
815    }
816
817    if( numDU == 1 )
818    {
819      rDuCpbRemovalDelayMinus1[ 0 ] = 0; /* don't care */
820    }
821    else
822    {
823      rDuCpbRemovalDelayMinus1[ numDU - 1 ] = 0;/* by definition */
824      UInt tmp = 0;
825      UInt accum = 0;
826
827      for( i = ( numDU - 2 ); i >= 0; i -- )
828      {
829        ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU  - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) );
830        if( (UInt)ui64Tmp > maxDiff )
831        {
832          tmp ++;
833        }
834      }
835      uiPrev = 0;
836
837      UInt flag = 0;
838      for( i = ( numDU - 2 ); i >= 0; i -- )
839      {
840        flag = 0;
841        ui64Tmp = ( ( ( duData[numDU - 1].accumBitsDU  - duData[i].accumBitsDU ) * ( vui->getTimingInfo()->getTimeScale() / vui->getTimingInfo()->getNumUnitsInTick() ) * ( hrd->getTickDivisorMinus2() + 2 ) ) / ( m_pcCfg->getTargetBitrate() ) );
842
843        if( (UInt)ui64Tmp > maxDiff )
844        {
845          if(uiPrev >= maxDiff - tmp)
846          {
847            ui64Tmp = uiPrev + 1;
848            flag = 1;
849          }
850          else                            ui64Tmp = maxDiff - tmp + 1;
851        }
852        rDuCpbRemovalDelayMinus1[ i ] = (UInt)ui64Tmp - uiPrev - 1;
853        if( (Int)rDuCpbRemovalDelayMinus1[ i ] < 0 )
854        {
855          rDuCpbRemovalDelayMinus1[ i ] = 0;
856        }
857        else if (tmp > 0 && flag == 1)
858        {
859          tmp --;
860        }
861        accum += rDuCpbRemovalDelayMinus1[ i ] + 1;
862        uiPrev = accum;
863      }
864    }
[608]865  }
[1313]866}
867Void TEncGOP::xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI)
868{
869  if (duInfoSeiMessages.empty() || (pictureTimingSEI == NULL))
[608]870  {
[1313]871    return;
[608]872  }
[1313]873
874  Int i=0;
875
876  for (SEIMessages::iterator du = duInfoSeiMessages.begin(); du!= duInfoSeiMessages.end(); du++)
[872]877  {
[1313]878    SEIDecodingUnitInfo *duInfoSEI = (SEIDecodingUnitInfo*) (*du);
879    duInfoSEI->m_decodingUnitIdx = i;
880    duInfoSEI->m_duSptCpbRemovalDelay = pictureTimingSEI->m_duCpbRemovalDelayMinus1[i] + 1;
881    duInfoSEI->m_dpbOutputDuDelayPresentFlag = false;
882    i++;
[872]883  }
[608]884}
885
[1313]886static Void
887cabac_zero_word_padding(TComSlice *const pcSlice, TComPic *const pcPic, const std::size_t binCountsInNalUnits, const std::size_t numBytesInVclNalUnits, std::ostringstream &nalUnitData, const Bool cabacZeroWordPaddingEnabled)
[2]888{
[1313]889  const TComSPS &sps=*(pcSlice->getSPS());
890  const Int log2subWidthCxsubHeightC = (pcPic->getComponentScaleX(COMPONENT_Cb)+pcPic->getComponentScaleY(COMPONENT_Cb));
891  const Int minCuWidth  = pcPic->getMinCUWidth();
892  const Int minCuHeight = pcPic->getMinCUHeight();
893  const Int paddedWidth = ((sps.getPicWidthInLumaSamples()  + minCuWidth  - 1) / minCuWidth) * minCuWidth;
894  const Int paddedHeight= ((sps.getPicHeightInLumaSamples() + minCuHeight - 1) / minCuHeight) * minCuHeight;
895  const Int rawBits = paddedWidth * paddedHeight *
896                         (sps.getBitDepth(CHANNEL_TYPE_LUMA) + 2*(sps.getBitDepth(CHANNEL_TYPE_CHROMA)>>log2subWidthCxsubHeightC));
897  const std::size_t threshold = (32/3)*numBytesInVclNalUnits + (rawBits/32);
898  if (binCountsInNalUnits >= threshold)
899  {
900    // need to add additional cabac zero words (each one accounts for 3 bytes (=00 00 03)) to increase numBytesInVclNalUnits
901    const std::size_t targetNumBytesInVclNalUnits = ((binCountsInNalUnits - (rawBits/32))*3+31)/32;
902
903    if (targetNumBytesInVclNalUnits>numBytesInVclNalUnits) // It should be!
904    {
905      const std::size_t numberOfAdditionalBytesNeeded=targetNumBytesInVclNalUnits - numBytesInVclNalUnits;
906      const std::size_t numberOfAdditionalCabacZeroWords=(numberOfAdditionalBytesNeeded+2)/3;
907      const std::size_t numberOfAdditionalCabacZeroBytes=numberOfAdditionalCabacZeroWords*3;
908      if (cabacZeroWordPaddingEnabled)
909      {
[1386]910        std::vector<UChar> zeroBytesPadding(numberOfAdditionalCabacZeroBytes, UChar(0));
[1313]911        for(std::size_t i=0; i<numberOfAdditionalCabacZeroWords; i++)
912        {
913          zeroBytesPadding[i*3+2]=3;  // 00 00 03
914        }
[1386]915        nalUnitData.write(reinterpret_cast<const TChar*>(&(zeroBytesPadding[0])), numberOfAdditionalCabacZeroBytes);
[1313]916        printf("Adding %d bytes of padding\n", UInt(numberOfAdditionalCabacZeroWords*3));
917      }
918      else
919      {
920        printf("Standard would normally require adding %d bytes of padding\n", UInt(numberOfAdditionalCabacZeroWords*3));
921      }
922    }
923  }
[56]924}
[1313]925
926class EfficientFieldIRAPMapping
[56]927{
[1313]928  private:
929    Int  IRAPGOPid;
930    Bool IRAPtoReorder;
931    Bool swapIRAPForward;
[5]932
[1313]933  public:
934    EfficientFieldIRAPMapping() :
935      IRAPGOPid(-1),
936      IRAPtoReorder(false),
937      swapIRAPForward(false)
938    { }
[655]939
[1313]940    Void initialize(const Bool isField, const Int gopSize, const Int POCLast, const Int numPicRcvd, const Int lastIDR, TEncGOP *pEncGop, TEncCfg *pCfg);
941
942    Int adjustGOPid(const Int gopID);
943    Int restoreGOPid(const Int gopID);
944    Int GetIRAPGOPid() const { return IRAPGOPid; }
945};
946
947Void EfficientFieldIRAPMapping::initialize(const Bool isField, const Int gopSize, const Int POCLast, const Int numPicRcvd, const Int lastIDR, TEncGOP *pEncGop, TEncCfg *pCfg )
948{
[964]949  if(isField)
950  {
951    Int pocCurr;
[1313]952    for ( Int iGOPid=0; iGOPid < gopSize; iGOPid++ )
[964]953    {
954      // determine actual POC
[1313]955      if(POCLast == 0) //case first frame or first top field
[964]956      {
957        pocCurr=0;
958      }
[1313]959      else if(POCLast == 1 && isField) //case first bottom field, just like the first frame, the poc computation is not right anymore, we set the right value
[964]960      {
961        pocCurr = 1;
962      }
963      else
964      {
[1313]965        pocCurr = POCLast - numPicRcvd + pCfg->getGOPEntry(iGOPid).m_POC - isField;
[964]966      }
967
968      // check if POC corresponds to IRAP
[1313]969      NalUnitType tmpUnitType = pEncGop->getNalUnitType(pocCurr, lastIDR, isField);
[964]970      if(tmpUnitType >= NAL_UNIT_CODED_SLICE_BLA_W_LP && tmpUnitType <= NAL_UNIT_CODED_SLICE_CRA) // if picture is an IRAP
971      {
[1313]972        if(pocCurr%2 == 0 && iGOPid < gopSize-1 && pCfg->getGOPEntry(iGOPid).m_POC == pCfg->getGOPEntry(iGOPid+1).m_POC-1)
[964]973        { // if top field and following picture in enc order is associated bottom field
974          IRAPGOPid = iGOPid;
975          IRAPtoReorder = true;
[1356]976          swapIRAPForward = true;
[964]977          break;
978        }
[1313]979        if(pocCurr%2 != 0 && iGOPid > 0 && pCfg->getGOPEntry(iGOPid).m_POC == pCfg->getGOPEntry(iGOPid-1).m_POC+1)
[964]980        {
981          // if picture is an IRAP remember to process it first
982          IRAPGOPid = iGOPid;
983          IRAPtoReorder = true;
[1356]984          swapIRAPForward = false;
[964]985          break;
986        }
987      }
988    }
989  }
[1313]990}
991
992Int EfficientFieldIRAPMapping::adjustGOPid(const Int GOPid)
993{
994  if(IRAPtoReorder)
[56]995  {
[1313]996    if(swapIRAPForward)
[964]997    {
[1313]998      if(GOPid == IRAPGOPid)
[964]999      {
[1313]1000        return IRAPGOPid +1;
[964]1001      }
[1313]1002      else if(GOPid == IRAPGOPid +1)
[964]1003      {
[1313]1004        return IRAPGOPid;
[964]1005      }
1006    }
[1313]1007    else
[608]1008    {
[1313]1009      if(GOPid == IRAPGOPid -1)
[56]1010      {
[1313]1011        return IRAPGOPid;
[56]1012      }
[1313]1013      else if(GOPid == IRAPGOPid)
[56]1014      {
[1313]1015        return IRAPGOPid -1;
[56]1016      }
[608]1017    }
[1313]1018  }
1019  return GOPid;
1020}
1021
1022Int EfficientFieldIRAPMapping::restoreGOPid(const Int GOPid)
1023{
1024  if(IRAPtoReorder)
1025  {
1026    if(swapIRAPForward)
[608]1027    {
[1313]1028      if(GOPid == IRAPGOPid)
[56]1029      {
[1313]1030        IRAPtoReorder = false;
1031        return IRAPGOPid +1;
[56]1032      }
[1313]1033      else if(GOPid == IRAPGOPid +1)
1034      {
1035        return GOPid -1;
1036      }
[608]1037    }
[1313]1038    else
[608]1039    {
[1313]1040      if(GOPid == IRAPGOPid)
[56]1041      {
[1313]1042        return IRAPGOPid -1;
[56]1043      }
[1313]1044      else if(GOPid == IRAPGOPid -1)
[56]1045      {
[1313]1046        IRAPtoReorder = false;
1047        return IRAPGOPid;
[56]1048      }
[608]1049    }
[1313]1050  }
1051  return GOPid;
1052}
1053
1054
[1413]1055#if X0038_LAMBDA_FROM_QP_CAPABILITY
1056static UInt calculateCollocatedFromL0Flag(const TComSlice *pSlice)
1057{
1058  const Int refIdx = 0; // Zero always assumed
1059  const TComPic *refPicL0 = pSlice->getRefPic(REF_PIC_LIST_0, refIdx);
1060  const TComPic *refPicL1 = pSlice->getRefPic(REF_PIC_LIST_1, refIdx);
1061  return refPicL0->getSlice(0)->getSliceQp() > refPicL1->getSlice(0)->getSliceQp();
1062}
1063#else
[1313]1064static UInt calculateCollocatedFromL1Flag(TEncCfg *pCfg, const Int GOPid, const Int gopSize)
1065{
1066  Int iCloseLeft=1, iCloseRight=-1;
1067  for(Int i = 0; i<pCfg->getGOPEntry(GOPid).m_numRefPics; i++)
1068  {
1069    Int iRef = pCfg->getGOPEntry(GOPid).m_referencePics[i];
1070    if(iRef>0&&(iRef<iCloseRight||iCloseRight==-1))
[608]1071    {
[1313]1072      iCloseRight=iRef;
[608]1073    }
[1313]1074    else if(iRef<0&&(iRef>iCloseLeft||iCloseLeft==1))
1075    {
1076      iCloseLeft=iRef;
1077    }
1078  }
1079  if(iCloseRight>-1)
1080  {
1081    iCloseRight=iCloseRight+pCfg->getGOPEntry(GOPid).m_POC-1;
1082  }
1083  if(iCloseLeft<1)
1084  {
1085    iCloseLeft=iCloseLeft+pCfg->getGOPEntry(GOPid).m_POC-1;
1086    while(iCloseLeft<0)
1087    {
1088      iCloseLeft+=gopSize;
1089    }
1090  }
1091  Int iLeftQP=0, iRightQP=0;
1092  for(Int i=0; i<gopSize; i++)
1093  {
1094    if(pCfg->getGOPEntry(i).m_POC==(iCloseLeft%gopSize)+1)
1095    {
1096      iLeftQP= pCfg->getGOPEntry(i).m_QPOffset;
1097    }
1098    if (pCfg->getGOPEntry(i).m_POC==(iCloseRight%gopSize)+1)
1099    {
1100      iRightQP=pCfg->getGOPEntry(i).m_QPOffset;
1101    }
1102  }
1103  if(iCloseRight>-1&&iRightQP<iLeftQP)
1104  {
1105    return 0;
1106  }
1107  else
1108  {
1109    return 1;
1110  }
1111}
[1413]1112#endif
[2]1113
[1386]1114
1115static Void
1116printHash(const HashType hashType, const std::string &digestStr)
1117{
1118  const TChar *decodedPictureHashModeName;
1119  switch (hashType)
1120  {
1121    case HASHTYPE_MD5:
1122      decodedPictureHashModeName = "MD5";
1123      break;
1124    case HASHTYPE_CRC:
1125      decodedPictureHashModeName = "CRC";
1126      break;
1127    case HASHTYPE_CHECKSUM:
1128      decodedPictureHashModeName = "Checksum";
1129      break;
1130    default:
1131      decodedPictureHashModeName = NULL;
1132      break;
1133  }
1134  if (decodedPictureHashModeName != NULL)
1135  {
1136    if (digestStr.empty())
1137    {
1138      printf(" [%s:%s]", decodedPictureHashModeName, "?");
1139    }
1140    else
1141    {
1142      printf(" [%s:%s]", decodedPictureHashModeName, digestStr.c_str());
1143    }
1144  }
1145}
1146
[1313]1147// ====================================================================================================================
1148// Public member functions
1149// ====================================================================================================================
1150#if NH_MV
1151Void TEncGOP::initGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsInGOP)
1152{
1153  xInitGOP( iPOCLast, iNumPicRcvd, false );
1154  m_iNumPicCoded = 0;
1155}
1156#endif
1157#if NH_MV
[1356]1158Void TEncGOP::compressPicInGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,
1159                                TComList<TComPicYuv*>& rcListPicYuvRecOut,  std::list<AccessUnit>& accessUnitsInGOP,
[1413]1160                                Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE, const Bool printMSSSIM, Int iGOPid )
[1313]1161#else
1162Void TEncGOP::compressGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,
1163                           TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsInGOP,
[1413]1164#if JVET_F0064_MSSSIM           
1165                           Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE, const Bool printMSSSIM )
1166#else
1167
[1313]1168                           Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE )
1169#endif
[1413]1170#endif
[1313]1171{
1172  // TODO: Split this function up.
1173
1174  TComPic*        pcPic = NULL;
1175  TComPicYuv*     pcPicYuvRecOut;
1176  TComSlice*      pcSlice;
1177  TComOutputBitstream  *pcBitstreamRedirect;
1178  pcBitstreamRedirect = new TComOutputBitstream;
1179  AccessUnit::iterator  itLocationToPushSliceHeaderNALU; // used to store location where NALU containing slice header is to be inserted
1180#if !NH_MV
1181  xInitGOP( iPOCLast, iNumPicRcvd, isField );
1182#endif
1183
1184  m_iNumPicCoded = 0;
1185  SEIMessages leadingSeiMessages;
1186  SEIMessages nestedSeiMessages;
1187  SEIMessages duInfoSeiMessages;
1188  SEIMessages trailingSeiMessages;
1189  std::deque<DUData> duData;
1190  SEIDecodingUnitInfo decodingUnitInfoSEI;
1191
1192  EfficientFieldIRAPMapping effFieldIRAPMap;
1193  if (m_pcCfg->getEfficientFieldIRAPEnabled())
1194  {
1195   effFieldIRAPMap.initialize(isField, m_iGopSize, iPOCLast, iNumPicRcvd, m_iLastIDR, this, m_pcCfg);
1196  }
1197
1198  // reset flag indicating whether pictures have been encoded
1199#if !NH_MV
1200  for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ )
1201#endif
1202  {
1203    m_pcCfg->setEncodedFlag(iGOPid, false);
1204  }
1205#if !NH_MV
1206  for ( Int iGOPid=0; iGOPid < m_iGopSize; iGOPid++ )
1207#endif
1208  {
1209    if (m_pcCfg->getEfficientFieldIRAPEnabled())
1210    {
1211      iGOPid=effFieldIRAPMap.adjustGOPid(iGOPid);
1212    }
1213
1214    //-- For time output for each slice
1215    clock_t iBeforeTime = clock();
1216
[1413]1217#if !X0038_LAMBDA_FROM_QP_CAPABILITY
[1313]1218    UInt uiColDir = calculateCollocatedFromL1Flag(m_pcCfg, iGOPid, m_iGopSize);
[1413]1219#endif
[1313]1220
[608]1221    /////////////////////////////////////////////////////////////////////////////////////////////////// Initial to start encoding
[655]1222    Int iTimeOffset;
1223    Int pocCurr;
1224    if(iPOCLast == 0) //case first frame or first top field
[608]1225    {
1226      pocCurr=0;
1227      iTimeOffset = 1;
1228    }
[655]1229    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
1230    {
1231      pocCurr = 1;
1232      iTimeOffset = 1;
1233    }
1234    else
1235    {
[1313]1236      pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1:0);
[655]1237      iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC;
1238    }
[1313]1239
[608]1240    if(pocCurr>=m_pcCfg->getFramesToBeEncoded())
1241    {
[1313]1242      if (m_pcCfg->getEfficientFieldIRAPEnabled())
[964]1243      {
[1313]1244        iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
[964]1245      }
[1313]1246#if NH_MV
[608]1247      delete pcBitstreamRedirect;
1248      return;
1249#else
1250      continue;
1251#endif
1252    }
[5]1253
[872]1254    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 )
[608]1255    {
1256      m_iLastIDR = pocCurr;
[1313]1257    }
[608]1258    // start a new access unit: create an entry in the list of output access units
1259    accessUnitsInGOP.push_back(AccessUnit());
1260    AccessUnit& accessUnit = accessUnitsInGOP.back();
[1313]1261    xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pcPicYuvRecOut, pocCurr, isField );
[56]1262
[1413]1263#if REDUCED_ENCODER_MEMORY
1264    pcPic->prepareForReconstruction();
1265
1266#endif
[608]1267    //  Slice data initialization
1268    pcPic->clearSliceBuffer();
[1313]1269    pcPic->allocateNewSlice();
[608]1270    m_pcSliceEncoder->setSliceIdx(0);
1271    pcPic->setCurrSliceIdx(0);
[1313]1272#if NH_MV
[1356]1273    m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, m_pcEncTop->getVPS(), getLayerId(), isField  );
[622]1274#else
[1313]1275    m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField );
[622]1276#endif
[1313]1277
[608]1278    pcSlice->setLastIDR(m_iLastIDR);
1279    pcSlice->setSliceIdx(0);
[1313]1280#if NH_MV
[1356]1281    pcSlice->setRefPicSetInterLayer ( &m_refPicSetInterLayer0, &m_refPicSetInterLayer1 );
[608]1282    pcPic  ->setLayerId     ( getLayerId()   );
[1356]1283    pcPic  ->setViewId      ( getViewId()    );
[1313]1284#if !NH_3D
[608]1285    pcSlice->setLayerId     ( getLayerId() );
[1356]1286    pcSlice->setViewId      ( getViewId()  );
[608]1287    pcSlice->setVPS         ( m_pcEncTop->getVPS() );
[77]1288#else
[1356]1289    pcPic  ->setViewIndex   ( getViewIndex() );
[608]1290    pcPic  ->setIsDepth( getIsDepth() );
[1356]1291    pcSlice->setCamparaSlice( pcPic->getCodedScale(), pcPic->getCodedOffset() );
[77]1292#endif
[1356]1293#endif
[608]1294    //set default slice level flag to the same as SPS level flag
1295    pcSlice->setLFCrossSliceBoundaryFlag(  pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag()  );
[1313]1296#if NH_MV
[608]1297    // Set the nal unit type
[872]1298    pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
[608]1299    if( pcSlice->getSliceType() == B_SLICE )
1300    {
[1356]1301      if( m_pcCfg->getGOPEntry( ( pcSlice->getRapPicFlag() && getLayerId() > 0 ) ? MAX_GOP : iGOPid ).m_sliceType == 'P' )
1302      {
[608]1303        pcSlice->setSliceType( P_SLICE );
1304      }
1305    }
[872]1306
1307// To be checked!
1308    if( pcSlice->getSliceType() == B_SLICE )
1309    {
[1356]1310      if( m_pcCfg->getGOPEntry( ( pcSlice->getRapPicFlag() && getLayerId() > 0 ) ? MAX_GOP : iGOPid ).m_sliceType == 'I' )
1311      {
[872]1312        pcSlice->setSliceType( I_SLICE );
1313      }
1314    }
[608]1315#else
[1313]1316
[608]1317    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P')
1318    {
1319      pcSlice->setSliceType(P_SLICE);
1320    }
[872]1321    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I')
1322    {
1323      pcSlice->setSliceType(I_SLICE);
1324    }
[1356]1325
[608]1326    // Set the nal unit type
[872]1327    pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
[608]1328#endif
1329    if(pcSlice->getTemporalLayerNonReferenceFlag())
1330    {
[655]1331      if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_R &&
1332          !(m_iGopSize == 1 && pcSlice->getSliceType() == I_SLICE))
1333        // Add this condition to avoid POC issues with encoder_intra_main.cfg configuration (see #1127 in bug tracker)
[56]1334      {
[608]1335        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N);
[56]1336      }
[608]1337      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RADL_R)
[56]1338      {
[608]1339        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N);
[56]1340      }
[608]1341      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RASL_R)
[56]1342      {
[608]1343        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N);
[56]1344      }
[210]1345    }
[1313]1346    if (m_pcCfg->getEfficientFieldIRAPEnabled())
1347    {
[964]1348    if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP
1349      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL
1350      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP
1351      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
1352      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
1353      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )  // IRAP picture
1354    {
1355      m_associatedIRAPType = pcSlice->getNalUnitType();
1356      m_associatedIRAPPOC = pocCurr;
1357    }
1358    pcSlice->setAssociatedIRAPType(m_associatedIRAPType);
1359    pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);
[1313]1360    }
1361    // Do decoding refresh marking if any
1362    pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcCfg->getEfficientFieldIRAPEnabled());
[608]1363    m_pcEncTop->selectReferencePictureSet(pcSlice, pocCurr, iGOPid);
[1313]1364    if (!m_pcCfg->getEfficientFieldIRAPEnabled())
1365    {
[872]1366    if ( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP
1367      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL
1368      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP
1369      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
1370      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
1371      || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA )  // IRAP picture
1372    {
1373      m_associatedIRAPType = pcSlice->getNalUnitType();
1374      m_associatedIRAPPOC = pocCurr;
1375    }
1376    pcSlice->setAssociatedIRAPType(m_associatedIRAPType);
1377    pcSlice->setAssociatedIRAPPOC(m_associatedIRAPPOC);
[1313]1378    }
[1356]1379    if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false, m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3) != 0) || (pcSlice->isIRAP())
[1313]1380      || (m_pcCfg->getEfficientFieldIRAPEnabled() && isField && pcSlice->getAssociatedIRAPType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getAssociatedIRAPType() <= NAL_UNIT_CODED_SLICE_CRA && pcSlice->getAssociatedIRAPPOC() == pcSlice->getPOC()+1)
[964]1381      )
1382    {
[1313]1383      pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP(), m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3, m_pcCfg->getEfficientFieldIRAPEnabled());
[964]1384    }
[1313]1385
[608]1386    pcSlice->applyReferencePictureSet(rcListPic, pcSlice->getRPS());
[56]1387
[1356]1388    if(pcSlice->getTLayer() > 0
[872]1389      &&  !( pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N     // Check if not a leading picture
1390          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R
1391          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N
1392          || pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R )
1393        )
[608]1394    {
1395      if(pcSlice->isTemporalLayerSwitchingPoint(rcListPic) || pcSlice->getSPS()->getTemporalIdNestingFlag())
[56]1396      {
[608]1397        if(pcSlice->getTemporalLayerNonReferenceFlag())
1398        {
1399          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_N);
1400        }
1401        else
1402        {
[872]1403          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_R);
[608]1404        }
[56]1405      }
[608]1406      else if(pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic))
[56]1407      {
[608]1408        Bool isSTSA=true;
1409        for(Int ii=iGOPid+1;(ii<m_pcCfg->getGOPSize() && isSTSA==true);ii++)
1410        {
1411          Int lTid= m_pcCfg->getGOPEntry(ii).m_temporalId;
[1313]1412          if(lTid==pcSlice->getTLayer())
[608]1413          {
[1313]1414            const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii);
[608]1415            for(Int jj=0;jj<nRPS->getNumberOfPictures();jj++)
1416            {
[1313]1417              if(nRPS->getUsed(jj))
[608]1418              {
1419                Int tPoc=m_pcCfg->getGOPEntry(ii).m_POC+nRPS->getDeltaPOC(jj);
1420                Int kk=0;
1421                for(kk=0;kk<m_pcCfg->getGOPSize();kk++)
1422                {
1423                  if(m_pcCfg->getGOPEntry(kk).m_POC==tPoc)
[1313]1424                  {
[608]1425                    break;
[1313]1426                  }
[608]1427                }
1428                Int tTid=m_pcCfg->getGOPEntry(kk).m_temporalId;
1429                if(tTid >= pcSlice->getTLayer())
1430                {
1431                  isSTSA=false;
1432                  break;
1433                }
1434              }
1435            }
1436          }
1437        }
1438        if(isSTSA==true)
[1313]1439        {
[608]1440          if(pcSlice->getTemporalLayerNonReferenceFlag())
1441          {
1442            pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_N);
1443          }
1444          else
1445          {
1446            pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_STSA_R);
1447          }
1448        }
[56]1449      }
[608]1450    }
1451    arrangeLongtermPicturesInRPS(pcSlice, rcListPic);
1452    TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification();
1453    refPicListModification->setRefPicListModificationFlagL0(0);
1454    refPicListModification->setRefPicListModificationFlagL1(0);
[1313]1455#if NH_MV
[738]1456    if ( pcSlice->getPPS()->getNumExtraSliceHeaderBits() > 0 )
[622]1457    {
[1356]1458      // Some more sophisticated algorithm to determine discardable_flag might be added here.
1459      pcSlice->setDiscardableFlag           ( false );
1460    }
[622]1461
[1356]1462    const TComVPS*           vps = pcSlice->getVPS();
[1313]1463#if NH_3D
[1356]1464    Int numDirectRefLayers = vps    ->getNumRefListLayers( getLayerId() );
[1124]1465#else
[1356]1466    Int numDirectRefLayers = vps    ->getNumDirectRefLayers( getLayerId() );
[1124]1467#endif
[1413]1468
1469#if NH_3D
[1386]1470    pcSlice->setIvPicLists( m_ivPicLists );
[1179]1471    Int gopNum = (pcSlice->getRapPicFlag() && getLayerId() > 0) ? MAX_GOP : iGOPid;
[1356]1472    GOPEntry gopEntry      = m_pcCfg->getGOPEntry( gopNum );
[1179]1473#else
[1356]1474    GOPEntry gopEntry      = m_pcCfg->getGOPEntry( (pcSlice->getRapPicFlag() && getLayerId() > 0) ? MAX_GOP : iGOPid );
[1179]1475#endif
[1196]1476
1477
[1356]1478
1479    Bool interLayerPredLayerIdcPresentFlag = false;
[622]1480    if ( getLayerId() > 0 && !vps->getAllRefLayersActiveFlag() && numDirectRefLayers > 0 )
[1356]1481    {
1482      pcSlice->setInterLayerPredEnabledFlag ( gopEntry.m_numActiveRefLayerPics > 0 );
[622]1483      if ( pcSlice->getInterLayerPredEnabledFlag() && numDirectRefLayers > 1 )
1484      {
1485        if ( !vps->getMaxOneActiveRefLayerFlag() )
[1356]1486        {
1487          pcSlice->setNumInterLayerRefPicsMinus1( gopEntry.m_numActiveRefLayerPics - 1 );
[622]1488        }
[1313]1489#if NH_3D
[1124]1490        if ( gopEntry.m_numActiveRefLayerPics != vps->getNumRefListLayers( getLayerId() ) )
1491#else
[622]1492        if ( gopEntry.m_numActiveRefLayerPics != vps->getNumDirectRefLayers( getLayerId() ) )
[1124]1493#endif
[1356]1494        {
1495          interLayerPredLayerIdcPresentFlag = true;
[622]1496          for (Int i = 0; i < gopEntry.m_numActiveRefLayerPics; i++ )
1497          {
[1356]1498            pcSlice->setInterLayerPredLayerIdc( i, gopEntry.m_interLayerPredLayerIdc[ i ] );
[622]1499          }
1500        }
1501      }
1502    }
[738]1503    if ( !interLayerPredLayerIdcPresentFlag )
1504    {
[1356]1505      for( Int i = 0; i < pcSlice->getNumActiveRefLayerPics(); i++ )
[738]1506      {
1507        pcSlice->setInterLayerPredLayerIdc(i, pcSlice->getRefLayerPicIdc( i ) );
1508      }
1509    }
1510
1511
[1356]1512    assert( pcSlice->getNumActiveRefLayerPics() == gopEntry.m_numActiveRefLayerPics );
1513
[1313]1514#if NH_3D
[1179]1515    if ( m_pcEncTop->decProcAnnexI() )
[1356]1516    {
1517      pcSlice->deriveInCmpPredAndCpAvailFlag( );
[1179]1518      if ( pcSlice->getInCmpPredAvailFlag() )
[1356]1519      {
1520        pcSlice->setInCompPredFlag( gopEntry.m_interCompPredFlag );
[1179]1521      }
1522      else
1523      {
1524        if (gopEntry.m_interCompPredFlag )
1525        {
1526          if ( gopNum == MAX_GOP)
1527          {
[1321]1528            printf( "\nError: FrameI_l%d cannot enable inter-component prediction on slice level. All reference layers need to be available and at least one tool using inter-component prediction must be enabled in the SPS. \n", pcSlice->getVPS()->getLayerIdInVps( getLayerId() ) );
[1179]1529          }
1530          else
1531          {
[1321]1532            printf( "\nError: Frame%d_l%d cannot enable inter-component prediction on slice level. All reference layers need to be available and at least one tool using inter-component prediction must be enabled in the SPS. \n", gopNum, pcSlice->getVPS()->getLayerIdInVps( getLayerId() ) );
[1179]1533          }
[1356]1534
[1179]1535          exit(EXIT_FAILURE);
1536        }
1537      }
[1356]1538      pcSlice->init3dToolParameters();
1539      pcSlice->checkInCompPredRefLayers();
1540    }
[1313]1541    // This needs to be done after initialization of 3D tool parameters.
[1179]1542    pcSlice->setMaxNumMergeCand      ( m_pcCfg->getMaxNumMergeCand()   + ( ( pcSlice->getMpiFlag( ) || pcSlice->getIvMvPredFlag( ) || pcSlice->getViewSynthesisPredFlag( )   ) ? 1 : 0 ));
1543#endif
1544
[1356]1545    pcSlice->createInterLayerReferencePictureSet( m_ivPicLists, m_refPicSetInterLayer0, m_refPicSetInterLayer1 );
[622]1546    pcSlice->setNumRefIdx(REF_PIC_LIST_0,min(gopEntry.m_numRefPicsActive,( pcSlice->getRPS()->getNumberOfPictures() + (Int) m_refPicSetInterLayer0.size() + (Int) m_refPicSetInterLayer1.size()) ) );
1547    pcSlice->setNumRefIdx(REF_PIC_LIST_1,min(gopEntry.m_numRefPicsActive,( pcSlice->getRPS()->getNumberOfPictures() + (Int) m_refPicSetInterLayer0.size() + (Int) m_refPicSetInterLayer1.size()) ) );
1548
1549    std::vector< TComPic* >    tempRefPicLists[2];
1550    std::vector< Bool     >    usedAsLongTerm [2];
1551    Int       numPocTotalCurr;
1552
1553    pcSlice->getTempRefPicLists( rcListPic, m_refPicSetInterLayer0, m_refPicSetInterLayer1, tempRefPicLists, usedAsLongTerm, numPocTotalCurr, true );
1554
[1356]1555
1556    xSetRefPicListModificationsMv( tempRefPicLists, pcSlice, iGOPid );
[622]1557#else
[608]1558    pcSlice->setNumRefIdx(REF_PIC_LIST_0,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures()));
1559    pcSlice->setNumRefIdx(REF_PIC_LIST_1,min(m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive,pcSlice->getRPS()->getNumberOfPictures()));
[210]1560#endif
[608]1561    //  Set reference list
[1356]1562#if NH_MV
1563    pcSlice->setRefPicList( tempRefPicLists, usedAsLongTerm, numPocTotalCurr );
[622]1564#else
1565    pcSlice->setRefPicList ( rcListPic );
1566#endif
[1413]1567#if NH_3D
[1124]1568    pcSlice->setDefaultRefView();
[622]1569    //GT: This seems to be broken when layerId in vps is not equal to layerId in nuh
[724]1570    pcSlice->setARPStepNum(m_ivPicLists);
[1356]1571    pcSlice->setICEnableCandidate( m_aICEnableCandidate );
1572    pcSlice->setICEnableNum( m_aICEnableNum );
[1066]1573#endif
[1313]1574
[608]1575    //  Slice info. refinement
[1313]1576#if NH_MV
[608]1577    if ( pcSlice->getSliceType() == B_SLICE )
1578    {
[1356]1579      if( m_pcCfg->getGOPEntry( ( pcSlice->getRapPicFlag() == true && getLayerId() > 0 ) ? MAX_GOP : iGOPid ).m_sliceType == 'P' )
1580      {
1581        pcSlice->setSliceType( P_SLICE );
[443]1582      }
[608]1583    }
[210]1584#else
[608]1585    if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) )
1586    {
1587      pcSlice->setSliceType ( P_SLICE );
1588    }
[210]1589#endif
[1313]1590    pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
1591
[608]1592    if (pcSlice->getSliceType() == B_SLICE)
1593    {
[1413]1594#if X0038_LAMBDA_FROM_QP_CAPABILITY
1595      const UInt uiColFromL0 = calculateCollocatedFromL0Flag(pcSlice);
1596      pcSlice->setColFromL0Flag(uiColFromL0);
1597#else
[608]1598      pcSlice->setColFromL0Flag(1-uiColDir);
[1413]1599#endif
[608]1600      Bool bLowDelay = true;
1601      Int  iCurrPOC  = pcSlice->getPOC();
1602      Int iRefIdx = 0;
1603
1604      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++)
[56]1605      {
[608]1606        if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )
[56]1607        {
[608]1608          bLowDelay = false;
[56]1609        }
1610      }
[608]1611      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)
[56]1612      {
[608]1613        if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )
[56]1614        {
[608]1615          bLowDelay = false;
[56]1616        }
1617      }
1618
[1313]1619      pcSlice->setCheckLDC(bLowDelay);
[608]1620    }
1621    else
1622    {
[1313]1623      pcSlice->setCheckLDC(true);
[608]1624    }
1625
[1413]1626#if !X0038_LAMBDA_FROM_QP_CAPABILITY
[608]1627    uiColDir = 1-uiColDir;
[1413]1628#endif
[608]1629
1630    //-------------------------------------------------------------
1631    pcSlice->setRefPOCList();
1632
1633    pcSlice->setList1IdxToList0Idx();
[1413]1634#if NH_3D
[608]1635    if(pcSlice->getLayerId())
1636      pcSlice->generateAlterRefforTMVP();
1637#endif
[1313]1638
[608]1639    if (m_pcEncTop->getTMVPModeId() == 2)
1640    {
1641      if (iGOPid == 0) // first picture in SOP (i.e. forward B)
[56]1642      {
[608]1643        pcSlice->setEnableTMVPFlag(0);
[56]1644      }
[608]1645      else
1646      {
1647        // Note: pcSlice->getColFromL0Flag() is assumed to be always 0 and getcolRefIdx() is always 0.
1648        pcSlice->setEnableTMVPFlag(1);
1649      }
1650    }
1651    else if (m_pcEncTop->getTMVPModeId() == 1)
1652    {
1653      pcSlice->setEnableTMVPFlag(1);
1654    }
1655    else
1656    {
1657      pcSlice->setEnableTMVPFlag(0);
1658    }
[1313]1659#if NH_MV
[608]1660    if( pcSlice->getIdrPicFlag() )
1661    {
1662      pcSlice->setEnableTMVPFlag(0);
1663    }
[100]1664#endif
[2]1665
[1313]1666#if NH_3D_VSO
[1356]1667  // Should be moved to TEncTop !!!
[608]1668  Bool bUseVSO = m_pcEncTop->getUseVSO();
1669
[1356]1670  TComRdCost* pcRdCost = m_pcEncTop->getRdCost();
1671
[608]1672  pcRdCost->setUseVSO( bUseVSO );
1673
1674  // SAIT_VSO_EST_A0033
1675  pcRdCost->setUseEstimatedVSD( m_pcEncTop->getUseEstimatedVSD() );
1676
[2]1677  if ( bUseVSO )
[5]1678  {
[2]1679    Int iVSOMode = m_pcEncTop->getVSOMode();
[608]1680    pcRdCost->setVSOMode( iVSOMode  );
1681    pcRdCost->setAllowNegDist( m_pcEncTop->getAllowNegDist() );
[120]1682
[608]1683    // SAIT_VSO_EST_A0033
[1386]1684    Int curAuxId     = pcSlice->getVPS()->getAuxId( getLayerId() ); 
1685    Int curDepthFlag = pcSlice->getIsDepth(); 
1686    assert( curAuxId == 2 || curDepthFlag  ); 
1687    pcRdCost->setVideoRecPicYuv( m_pcEncTop->getIvPicLists()->getPicYuv( pcSlice->getViewIndex(), false       , 0       , pcSlice->getPOC(), true ) );
1688    pcRdCost->setDepthPicYuv   ( m_pcEncTop->getIvPicLists()->getPicYuv( pcSlice->getViewIndex(), curDepthFlag, curAuxId, pcSlice->getPOC(), false ) );
[1413]1689
[608]1690    // LGE_WVSO_A0119
[120]1691    Bool bUseWVSO  = m_pcEncTop->getUseWVSO();
[608]1692    pcRdCost->setUseWVSO( bUseWVSO );
[100]1693
[2]1694  }
[5]1695#endif
[1386]1696    // set adaptive search range for non-intra-slices
1697    if (m_pcCfg->getUseASR() && pcSlice->getSliceType()!=I_SLICE)
[608]1698    {
1699      m_pcSliceEncoder->setSearchRange(pcSlice);
1700    }
[2]1701
[608]1702    Bool bGPBcheck=false;
1703    if ( pcSlice->getSliceType() == B_SLICE)
1704    {
1705      if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )
[2]1706      {
[608]1707        bGPBcheck=true;
1708        Int i;
1709        for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ )
[2]1710        {
[1313]1711          if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) )
[2]1712          {
[608]1713            bGPBcheck=false;
1714            break;
[2]1715          }
1716        }
1717      }
[608]1718    }
1719    if(bGPBcheck)
1720    {
1721      pcSlice->setMvdL1ZeroFlag(true);
1722    }
1723    else
1724    {
1725      pcSlice->setMvdL1ZeroFlag(false);
1726    }
1727
[1313]1728
[608]1729    Double lambda            = 0.0;
1730    Int actualHeadBits       = 0;
1731    Int actualTotalBits      = 0;
1732    Int estimatedBits        = 0;
1733    Int tmpBitsBeforeWriting = 0;
[1313]1734    if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments?
[608]1735    {
1736      Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
1737      if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
[2]1738      {
[608]1739        frameLevel = 0;
[2]1740      }
[608]1741      m_pcRateCtrl->initRCPic( frameLevel );
[1386]1742      estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits();
[655]1743
1744#if KWU_RC_MADPRED_E0227
1745      if(m_pcCfg->getLayerId() != 0)
1746      {
1747        m_pcRateCtrl->getRCPic()->setIVPic( m_pcEncTop->getEncTop()->getTEncTop(0)->getRateCtrl()->getRCPic() );
1748      }
1749#endif
1750
[1386]1751      if (m_pcRateCtrl->getCpbSaturationEnabled() && frameLevel != 0)
1752      {
1753        Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
[608]1754
[1386]1755        // prevent overflow
1756        if (estimatedCpbFullness - estimatedBits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f))
1757        {
1758          estimatedBits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f);
1759        }
1760
1761        estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate();
1762        // prevent underflow
[1405]1763        if (estimatedCpbFullness - estimatedBits < m_pcRateCtrl->getRCPic()->getLowerBound())
1764        {
1765          estimatedBits = max(200, estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound());
1766        }
[1386]1767        m_pcRateCtrl->getRCPic()->setTargetBits(estimatedBits);
1768      }
1769
[608]1770      Int sliceQP = m_pcCfg->getInitialQP();
1771      if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified
[56]1772      {
[608]1773        Int    NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );
1774        Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );
1775        Double dQPFactor     = 0.57*dLambda_scale;
1776        Int    SHIFT_QP      = 12;
1777        Int    bitdepth_luma_qp_scale = 0;
1778        Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP;
1779        lambda = dQPFactor*pow( 2.0, qp_temp/3.0 );
[56]1780      }
[608]1781      else if ( frameLevel == 0 )   // intra case, but use the model
1782      {
[1313]1783        m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others?
1784
[608]1785        if ( m_pcCfg->getIntraPeriod() != 1 )   // do not refine allocated bits for all intra case
1786        {
1787          Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits();
1788          bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits );
[1386]1789
1790          if (m_pcRateCtrl->getCpbSaturationEnabled() )
1791          {
1792            Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
1793
1794            // prevent overflow
1795            if (estimatedCpbFullness - bits > (Int)(m_pcRateCtrl->getCpbSize()*0.9f))
1796            {
1797              bits = estimatedCpbFullness - (Int)(m_pcRateCtrl->getCpbSize()*0.9f);
1798            }
1799
1800            estimatedCpbFullness -= m_pcRateCtrl->getBufferingRate();
1801            // prevent underflow
[1405]1802            if (estimatedCpbFullness - bits < m_pcRateCtrl->getRCPic()->getLowerBound())
1803            {
1804              bits = estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound();
1805            }
[1386]1806          }
1807
[608]1808          if ( bits < 200 )
1809          {
1810            bits = 200;
1811          }
1812          m_pcRateCtrl->getRCPic()->setTargetBits( bits );
1813        }
[5]1814
[608]1815        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
1816        m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();
1817        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
1818        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
[2]1819      }
[608]1820      else    // normal case
[2]1821      {
[655]1822#if KWU_RC_MADPRED_E0227
1823        if(m_pcRateCtrl->getLayerID() != 0)
1824        {
1825          list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
1826          lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambdaIV( listPreviousPicture, pcSlice->getPOC() );
1827          sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
1828        }
1829        else
1830        {
1831#endif
[608]1832        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
1833        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
1834        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
[655]1835#if KWU_RC_MADPRED_E0227
1836        }
1837#endif
[2]1838      }
1839
[1313]1840      sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, sliceQP );
[608]1841      m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );
1842
1843      m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda );
1844    }
1845
[1313]1846    UInt uiNumSliceSegments = 1;
[608]1847
[1413]1848#if NH_3D
[608]1849      if(pcSlice->getViewIndex() && !pcSlice->getIsDepth()) //Notes from QC: this condition shall be changed once the configuration is completed, e.g. in pcSlice->getSPS()->getMultiviewMvPredMode() || ARP in prev. HTM. Remove this comment once it is done.
[313]1850      {
[1313]1851        Int iColPoc = pcSlice->getRefPOC(RefPicList(1 - pcSlice->getColFromL0Flag()), pcSlice->getColRefIdx());
[608]1852        pcPic->setNumDdvCandPics(pcPic->getDisCandRefPictures(iColPoc));
[313]1853      }
[1356]1854      pcSlice->setDepthToDisparityLUTs();
[313]1855
[608]1856      if(pcSlice->getViewIndex() && !pcSlice->getIsDepth() && !pcSlice->isIntra()) //Notes from QC: this condition shall be changed once the configuration is completed, e.g. in pcSlice->getSPS()->getMultiviewMvPredMode() || ARP in prev. HTM. Remove this comment once it is done.
1857      {
1858        pcPic->checkTemporalIVRef();
1859      }
[655]1860
[608]1861      if(pcSlice->getIsDepth())
[189]1862      {
[608]1863        pcPic->checkTextureRef();
[189]1864      }
1865#endif
[1313]1866    // Allocate some coders, now the number of tiles are known.
1867    const Int numSubstreamsColumns = (pcSlice->getPPS()->getNumTileColumnsMinus1() + 1);
1868    const Int numSubstreamRows     = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcPic->getFrameHeightInCtus() : (pcSlice->getPPS()->getNumTileRowsMinus1() + 1);
1869    const Int numSubstreams        = numSubstreamRows * numSubstreamsColumns;
1870    std::vector<TComOutputBitstream> substreamsOut(numSubstreams);
1871
1872    // now compress (trial encode) the various slice segments (slices, and dependent slices)
[608]1873    {
[1313]1874      const UInt numberOfCtusInFrame=pcPic->getPicSym()->getNumberOfCtusInFrame();
1875      pcSlice->setSliceCurStartCtuTsAddr( 0 );
1876      pcSlice->setSliceSegmentCurStartCtuTsAddr( 0 );
[608]1877
[1313]1878      for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
[2]1879      {
[1313]1880        m_pcSliceEncoder->precompressSlice( pcPic );
1881        m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
[608]1882
[1313]1883        const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr();
1884        if (curSliceSegmentEnd < numberOfCtusInFrame)
[2]1885        {
[1313]1886          const Bool bNextSegmentIsDependentSlice=curSliceSegmentEnd<pcSlice->getSliceCurEndCtuTsAddr();
1887          const UInt sliceBits=pcSlice->getSliceBits();
1888          pcPic->allocateNewSlice();
1889          // prepare for next slice
1890          pcPic->setCurrSliceIdx                    ( uiNumSliceSegments );
1891          m_pcSliceEncoder->setSliceIdx             ( uiNumSliceSegments   );
1892          pcSlice = pcPic->getSlice                 ( uiNumSliceSegments   );
1893          assert(pcSlice->getPPS()!=0);
1894          pcSlice->copySliceInfo                    ( pcPic->getSlice(uiNumSliceSegments-1)  );
1895          pcSlice->setSliceIdx                      ( uiNumSliceSegments   );
1896          if (bNextSegmentIsDependentSlice)
1897          {
1898            pcSlice->setSliceBits(sliceBits);
1899          }
1900          else
1901          {
1902            pcSlice->setSliceCurStartCtuTsAddr      ( curSliceSegmentEnd );
1903            pcSlice->setSliceBits(0);
1904          }
1905          pcSlice->setDependentSliceSegmentFlag(bNextSegmentIsDependentSlice);
1906          pcSlice->setSliceSegmentCurStartCtuTsAddr ( curSliceSegmentEnd );
1907          // TODO: optimise cabac_init during compress slice to improve multi-slice operation
1908          // pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
1909          uiNumSliceSegments ++;
[2]1910        }
[1313]1911        nextCtuTsAddr = curSliceSegmentEnd;
[2]1912      }
[608]1913    }
[2]1914
[1313]1915    duData.clear();
[608]1916    pcSlice = pcPic->getSlice(0);
[2]1917
[1313]1918    // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
1919    if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoCtuBoundary() )
[608]1920    {
[872]1921      m_pcSAO->getPreDBFStatistics(pcPic);
[608]1922    }
1923
1924    //-- Loop filter
1925    Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag();
1926    m_pcLoopFilter->setCfg(bLFCrossTileBoundary);
1927    if ( m_pcCfg->getDeblockingFilterMetric() )
1928    {
[1405]1929      if ( m_pcCfg->getDeblockingFilterMetric()==2 )
1930      {
1931        applyDeblockingFilterParameterSelection(pcPic, uiNumSliceSegments, iGOPid);
1932      }
1933      else
1934      {
[1313]1935      applyDeblockingFilterMetric(pcPic, uiNumSliceSegments);
[1405]1936      }
[608]1937    }
1938    m_pcLoopFilter->loopFilterPic( pcPic );
1939
1940    /////////////////////////////////////////////////////////////////////////////////////////////////// File writing
1941    // Set entropy coder
[1313]1942    m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
[1413]1943
1944    // write various parameter sets
1945#if JCTVC_Y0038_PARAMS
1946    //bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcPic->getSlice(0)->getSliceType() == I_SLICE));
1947#if NH_MV
1948    bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcSlice->isIRAP())  );
1949#else
1950    bool writePS = m_bSeqFirst || (m_pcCfg->getReWriteParamSetsFlag() && (pcSlice->isIRAP()));
1951#endif
1952    if (writePS)
[608]1953    {
[1413]1954#if NH_MV
1955      if ( m_layerId == pcSlice->getSPS()->getLayerId() )
[773]1956      {
[1413]1957        m_pcEncTop->setParamSetChanged(pcSlice->getSPS()->getSPSId(), false );
[773]1958      }
[1413]1959     
1960      if ( m_layerId == pcSlice->getPPS()->getLayerId() )
1961      {
1962        m_pcEncTop->setParamSetChanged(pcSlice->getPPS()->getSPSId(), true  );       
1963      }
1964
1965#else
1966      m_pcEncTop->setParamSetChanged(pcSlice->getSPS()->getSPSId(), pcSlice->getPPS()->getPPSId());
[773]1967#endif
[1413]1968    }
1969#if NH_MV
1970    actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, writePS, (getLayerId() == 0) && m_bSeqFirst );
1971#else
1972    actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, writePS);
1973#endif
[608]1974
[1413]1975    if (writePS)
1976#else
1977    actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, m_bSeqFirst);
[1313]1978
[1413]1979    if ( m_bSeqFirst )
1980#endif
1981    {
[1313]1982      // create prefix SEI messages at the beginning of the sequence
1983      assert(leadingSeiMessages.empty());
1984      xCreateIRAPLeadingSEIMessages(leadingSeiMessages, pcSlice->getSPS(), pcSlice->getPPS());
1985
[210]1986      m_bSeqFirst = false;
1987    }
[1386]1988    if (m_pcCfg->getAccessUnitDelimiter())
1989    {
1990      xWriteAccessUnitDelimiter(accessUnit, pcSlice);
1991    }
[5]1992
[1313]1993    // reset presence of BP SEI indication
1994    m_bufferingPeriodSEIPresentInAU = false;
1995    // create prefix SEI associated with a picture
1996    xCreatePerPictureSEIMessages(iGOPid, leadingSeiMessages, nestedSeiMessages, pcSlice);
1997
[1386]1998#if NH_MV
[1356]1999    m_seiEncoder.createAnnexFGISeiMessages( leadingSeiMessages, pcSlice );
2000#endif
2001
[1313]2002    /* use the main bitstream buffer for storing the marshalled picture */
2003    m_pcEntropyCoder->setBitstream(NULL);
2004
2005    pcSlice = pcPic->getSlice(0);
2006
2007    if (pcSlice->getSPS()->getUseSAO())
[608]2008    {
[1313]2009      Bool sliceEnabled[MAX_NUM_COMPONENT];
2010      TComBitCounter tempBitCounter;
2011      tempBitCounter.resetBits();
2012      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(&tempBitCounter);
2013      m_pcSAO->initRDOCabacCoder(m_pcEncTop->getRDGoOnSbacCoder(), pcSlice);
[1405]2014      m_pcSAO->SAOProcess(pcPic, sliceEnabled, pcPic->getSlice(0)->getLambdas(),
2015                          m_pcCfg->getTestSAODisableAtPictureLevel(),
2016                          m_pcCfg->getSaoEncodingRate(),
2017                          m_pcCfg->getSaoEncodingRateChroma(),
2018                          m_pcCfg->getSaoCtuBoundary(),
2019                          m_pcCfg->getSaoResetEncoderStateAfterIRAP());
[1313]2020      m_pcSAO->PCMLFDisableProcess(pcPic);
2021      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(NULL);
[2]2022
[1313]2023      //assign SAO slice header
2024      for(Int s=0; s< uiNumSliceSegments; s++)
2025      {
2026        pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);
2027        assert(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]);
2028        pcPic->getSlice(s)->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);
2029      }
2030    }
[2]2031
[1313]2032    // pcSlice is currently slice 0.
2033    std::size_t binCountsInNalUnits   = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)
2034    std::size_t numBytesInVclNalUnits = 0; // For implementation of cabac_zero_word stuffing (section 7.4.3.10)
[56]2035
[1313]2036    for( UInt sliceSegmentStartCtuTsAddr = 0, sliceIdxCount=0; sliceSegmentStartCtuTsAddr < pcPic->getPicSym()->getNumberOfCtusInFrame(); sliceIdxCount++, sliceSegmentStartCtuTsAddr=pcSlice->getSliceSegmentCurEndCtuTsAddr() )
2037    {
2038      pcSlice = pcPic->getSlice(sliceIdxCount);
2039      if(sliceIdxCount > 0 && pcSlice->getSliceType()!= I_SLICE)
[2]2040      {
[1313]2041        pcSlice->checkColRefIdx(sliceIdxCount, pcPic);
[608]2042      }
[1313]2043      pcPic->setCurrSliceIdx(sliceIdxCount);
2044      m_pcSliceEncoder->setSliceIdx(sliceIdxCount);
[2]2045
[1313]2046      pcSlice->setRPS(pcPic->getSlice(0)->getRPS());
2047      pcSlice->setRPSidx(pcPic->getSlice(0)->getRPSidx());
[2]2048
[1313]2049      for ( UInt ui = 0 ; ui < numSubstreams; ui++ )
2050      {
2051        substreamsOut[ui].clear();
2052      }
[2]2053
[1313]2054      m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
2055      m_pcEntropyCoder->resetEntropy      ( pcSlice );
2056      /* start slice NALunit */
2057#if NH_MV
2058      OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer(), getLayerId() );
2059#else
2060      OutputNALUnit nalu( pcSlice->getNalUnitType(), pcSlice->getTLayer() );
2061#endif
2062      m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
[2]2063
[1313]2064      pcSlice->setNoRaslOutputFlag(false);
2065      if (pcSlice->isIRAP())
[608]2066      {
[1313]2067        if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP)
[2]2068        {
[1313]2069          pcSlice->setNoRaslOutputFlag(true);
[2]2070        }
[1313]2071        //the inference for NoOutputPriorPicsFlag
2072        // KJS: This cannot happen at the encoder
2073        if (!m_bFirst && pcSlice->isIRAP() && pcSlice->getNoRaslOutputFlag())
[56]2074        {
[1313]2075          if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
2076          {
2077            pcSlice->setNoOutputPriorPicsFlag(true);
2078          }
[56]2079        }
[608]2080      }
[2]2081
[1313]2082      pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
[608]2083
[1313]2084      tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits();
2085      m_pcEntropyCoder->encodeSliceHeader(pcSlice);
2086      actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting );
[608]2087
[1313]2088      pcSlice->setFinalized(true);
[608]2089
[1313]2090      pcSlice->clearSubstreamSizes(  );
[608]2091      {
[1313]2092        UInt numBinsCoded = 0;
2093        m_pcSliceEncoder->encodeSlice(pcPic, &(substreamsOut[0]), numBinsCoded);
2094        binCountsInNalUnits+=numBinsCoded;
[608]2095      }
2096
2097      {
[1313]2098        // Construct the final bitstream by concatenating substreams.
2099        // The final bitstream is either nalu.m_Bitstream or pcBitstreamRedirect;
2100        // Complete the slice header info.
2101        m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
2102        m_pcEntropyCoder->setBitstream(&nalu.m_Bitstream);
2103        m_pcEntropyCoder->encodeTilesWPPEntryPoint( pcSlice );
2104
2105        // Append substreams...
2106        TComOutputBitstream *pcOut = pcBitstreamRedirect;
2107        const Int numZeroSubstreamsAtStartOfSlice  = pcPic->getSubstreamForCtuAddr(pcSlice->getSliceSegmentCurStartCtuTsAddr(), false, pcSlice);
2108        const Int numSubstreamsToCode  = pcSlice->getNumberOfSubstreamSizes()+1;
2109        for ( UInt ui = 0 ; ui < numSubstreamsToCode; ui++ )
[56]2110        {
[1313]2111          pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice]));
[56]2112        }
[608]2113      }
[5]2114
[1313]2115      // If current NALU is the first NALU of slice (containing slice header) and more NALUs exist (due to multiple dependent slices) then buffer it.
2116      // 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.
2117      Bool bNALUAlignedWrittenToList    = false; // used to ensure current NALU is not written more than once to the NALU list.
2118      xAttachSliceDataToNalUnit(nalu, pcBitstreamRedirect);
2119      accessUnit.push_back(new NALUnitEBSP(nalu));
2120      actualTotalBits += UInt(accessUnit.back()->m_nalUnitData.str().size()) * 8;
2121      numBytesInVclNalUnits += (std::size_t)(accessUnit.back()->m_nalUnitData.str().size());
2122      bNALUAlignedWrittenToList = true;
2123
2124      if (!bNALUAlignedWrittenToList)
[608]2125      {
[1313]2126        nalu.m_Bitstream.writeAlignZero();
[608]2127        accessUnit.push_back(new NALUnitEBSP(nalu));
2128      }
2129
[1313]2130      if( ( m_pcCfg->getPictureTimingSEIEnabled() || m_pcCfg->getDecodingUnitInfoSEIEnabled() ) &&
2131          ( pcSlice->getSPS()->getVuiParametersPresentFlag() ) &&
2132          ( ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getNalHrdParametersPresentFlag() )
2133         || ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getVclHrdParametersPresentFlag() ) ) &&
2134          ( pcSlice->getSPS()->getVuiParameters()->getHrdParameters()->getSubPicCpbParamsPresentFlag() ) )
[964]2135      {
[1313]2136          UInt numNalus = 0;
2137        UInt numRBSPBytes = 0;
2138        for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)
2139        {
2140          numRBSPBytes += UInt((*it)->m_nalUnitData.str().size());
2141          numNalus ++;
2142        }
2143        duData.push_back(DUData());
2144        duData.back().accumBitsDU = ( numRBSPBytes << 3 );
2145        duData.back().accumNalsDU = numNalus;
[964]2146      }
[1313]2147    } // end iteration over slices
[608]2148
[1313]2149    // cabac_zero_words processing
2150    cabac_zero_word_padding(pcSlice, pcPic, binCountsInNalUnits, numBytesInVclNalUnits, accessUnit.back()->m_nalUnitData, m_pcCfg->getCabacZeroWordPaddingEnabled());
2151#if NH_3D
[1356]2152      pcPic->compressMotion(2);
[608]2153#else
[1313]2154    pcPic->compressMotion();
[608]2155#endif
[1313]2156#if NH_MV
2157      m_pocLastCoded = pcPic->getPOC();
[964]2158#endif
2159
[1313]2160    //-- For time output for each slice
2161    Double dEncTime = (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
[608]2162
[1313]2163    std::string digestStr;
[1386]2164    if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE)
[1313]2165    {
2166      SEIDecodedPictureHash *decodedPictureHashSei = new SEIDecodedPictureHash();
2167      m_seiEncoder.initDecodedPictureHashSEI(decodedPictureHashSei, pcPic, digestStr, pcSlice->getSPS()->getBitDepths());
2168      trailingSeiMessages.push_back(decodedPictureHashSei);
2169    }
[608]2170
[1313]2171    m_pcCfg->setEncodedFlag(iGOPid, true);
[5]2172
[1413]2173    Double PSNR_Y;
2174#if JVET_F0064_MSSSIM
2175    xCalculateAddPSNRs( isField, isTff, iGOPid, pcPic, accessUnit, rcListPic, dEncTime, snr_conversion, printFrameMSE, printMSSSIM, &PSNR_Y );
2176#else
2177    xCalculateAddPSNRs( isField, isTff, iGOPid, pcPic, accessUnit, rcListPic, dEncTime, snr_conversion, printFrameMSE, &PSNR_Y );
2178#endif
2179   
2180    // Only produce the Green Metadata SEI message with the last picture.
2181    if( m_pcCfg->getSEIGreenMetadataInfoSEIEnable() && pcSlice->getPOC() == ( m_pcCfg->getFramesToBeEncoded() - 1 )  )
2182    {
2183      SEIGreenMetadataInfo *seiGreenMetadataInfo = new SEIGreenMetadataInfo;
2184      m_seiEncoder.initSEIGreenMetadataInfo(seiGreenMetadataInfo, (UInt)(PSNR_Y * 100 + 0.5));
2185      trailingSeiMessages.push_back(seiGreenMetadataInfo);
2186    }
2187   
2188    xWriteTrailingSEIMessages(trailingSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS());
[56]2189
[1386]2190    printHash(m_pcCfg->getDecodedPictureHashSEIType(), digestStr);
[1313]2191
2192    if ( m_pcCfg->getUseRateCtrl() )
[872]2193    {
[1313]2194      Double avgQP     = m_pcRateCtrl->getRCPic()->calAverageQP();
2195      Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();
2196      if ( avgLambda < 0.0 )
[872]2197      {
[1313]2198        avgLambda = lambda;
[872]2199      }
[1313]2200
2201      m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());
2202      m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );
2203
2204      m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );
2205      if ( pcSlice->getSliceType() != I_SLICE )
[608]2206      {
[1313]2207        m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );
[608]2208      }
[1313]2209      else    // for intra picture, the estimated bits are used to update the current status in the GOP
[608]2210      {
[1313]2211        m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );
[608]2212      }
[1386]2213      if (m_pcRateCtrl->getCpbSaturationEnabled())
2214      {
2215        m_pcRateCtrl->updateCpbState(actualTotalBits);
2216        printf(" [CPB %6d bits]", m_pcRateCtrl->getCpbState());
2217      }
[1313]2218    }
[5]2219
[1313]2220    xCreatePictureTimingSEI(m_pcCfg->getEfficientFieldIRAPEnabled()?effFieldIRAPMap.GetIRAPGOPid():0, leadingSeiMessages, nestedSeiMessages, duInfoSeiMessages, pcSlice, isField, duData);
2221    if (m_pcCfg->getScalableNestingSEIEnabled())
2222    {
2223      xCreateScalableNestingSEI (leadingSeiMessages, nestedSeiMessages);
2224    }
2225    xWriteLeadingSEIMessages(leadingSeiMessages, duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData);
2226    xWriteDuSEIMessages(duInfoSeiMessages, accessUnit, pcSlice->getTLayer(), pcSlice->getSPS(), duData);
[56]2227
[1313]2228    pcPic->getPicYuvRec()->copyToPic(pcPicYuvRecOut);
[56]2229
[1313]2230    pcPic->setReconMark   ( true );
2231#if NH_MV
[1356]2232      TComSlice::markIvRefPicsAsShortTerm( m_refPicSetInterLayer0, m_refPicSetInterLayer1 );
2233      std::vector<Int> temp;
2234      TComSlice::markCurrPic( pcPic );
[608]2235#endif
[1313]2236    m_bFirst = false;
2237    m_iNumPicCoded++;
2238    m_totalCoded ++;
2239    /* logging: insert a newline at end of picture period */
2240    printf("\n");
2241    fflush(stdout);
[56]2242
[1313]2243    if (m_pcCfg->getEfficientFieldIRAPEnabled())
[964]2244    {
[1313]2245    iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
[964]2246    }
[1413]2247#if REDUCED_ENCODER_MEMORY
2248
2249    pcPic->releaseReconstructionIntermediateData();
2250    if (!isField) // don't release the source data for field-coding because the fields are dealt with in pairs. // TODO: release source data for interlace simulations.
2251    {
2252      pcPic->releaseEncoderSourceImageData();
2253    }
2254
2255#endif
[1313]2256  } // iGOPid-loop
2257
[608]2258  delete pcBitstreamRedirect;
[56]2259
[1313]2260#if !NH_MV
2261  assert ( (m_iNumPicCoded == iNumPicRcvd) );
[608]2262#endif
[56]2263}
2264
[1413]2265#if JVET_F0064_MSSSIM
2266Void TEncGOP::printOutSummary(UInt uiNumAllPicCoded, Bool isField, const Bool printMSEBasedSNR, const Bool printSequenceMSE, const Bool printMSSSIM, const BitDepths &bitDepths)
2267#else
[1313]2268Void TEncGOP::printOutSummary(UInt uiNumAllPicCoded, Bool isField, const Bool printMSEBasedSNR, const Bool printSequenceMSE, const BitDepths &bitDepths)
[1413]2269#endif
[56]2270{
[608]2271  assert (uiNumAllPicCoded == m_gcAnalyzeAll.getNumPic());
[1313]2272
2273
[608]2274  //--CFG_KDY
[1313]2275  const Int rateMultiplier=(isField?2:1);
[1405]2276  m_gcAnalyzeAll.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio());
2277  m_gcAnalyzeI.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio());
2278  m_gcAnalyzeP.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio());
2279  m_gcAnalyzeB.setFrmRate( m_pcCfg->getFrameRate()*rateMultiplier / (Double)m_pcCfg->getTemporalSubsampleRatio());
[1313]2280  const ChromaFormat chFmt = m_pcCfg->getChromaFormatIdc();
2281
[1413]2282
2283#if JVET_F0064_MSSSIM
[608]2284  //-- all
[1313]2285#if NH_MV
[1356]2286  printf( "\n\nSUMMARY -------------------------------------------- LayerId %2d\n", getLayerId() );
[1313]2287#else
[608]2288  printf( "\n\nSUMMARY --------------------------------------------------------\n" );
[1313]2289#endif
[1413]2290  m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printMSSSIM, bitDepths);
2291
2292  printf( "\n\nI Slices--------------------------------------------------------\n" );
2293  m_gcAnalyzeI.printOut('i', chFmt, printMSEBasedSNR, printSequenceMSE, printMSSSIM, bitDepths);
2294
2295  printf( "\n\nP Slices--------------------------------------------------------\n" );
2296  m_gcAnalyzeP.printOut('p', chFmt, printMSEBasedSNR, printSequenceMSE, printMSSSIM, bitDepths);
2297
2298  printf( "\n\nB Slices--------------------------------------------------------\n" );
2299  m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE, printMSSSIM, bitDepths);
2300#else
2301  //-- all
2302#if NH_MV
2303  printf( "\n\nSUMMARY -------------------------------------------- LayerId %2d\n", getLayerId() );
2304#else
2305  printf( "\n\nSUMMARY --------------------------------------------------------\n" );
2306#endif
2307
[1313]2308  m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2309
[608]2310  printf( "\n\nI Slices--------------------------------------------------------\n" );
[1313]2311  m_gcAnalyzeI.printOut('i', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2312
[608]2313  printf( "\n\nP Slices--------------------------------------------------------\n" );
[1313]2314  m_gcAnalyzeP.printOut('p', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2315
[608]2316  printf( "\n\nB Slices--------------------------------------------------------\n" );
[1313]2317  m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
[1413]2318#endif
[1313]2319  if (!m_pcCfg->getSummaryOutFilename().empty())
2320  {
2321    m_gcAnalyzeAll.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryOutFilename());
2322  }
2323
2324  if (!m_pcCfg->getSummaryPicFilenameBase().empty())
2325  {
2326    m_gcAnalyzeI.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"I.txt");
2327    m_gcAnalyzeP.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"P.txt");
2328    m_gcAnalyzeB.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryPicFilenameBase()+"B.txt");
2329  }
2330
[655]2331  if(isField)
2332  {
2333    //-- interlaced summary
[1405]2334    m_gcAnalyzeAll_in.setFrmRate( m_pcCfg->getFrameRate() / (Double)m_pcCfg->getTemporalSubsampleRatio());
[1313]2335    m_gcAnalyzeAll_in.setBits(m_gcAnalyzeAll.getBits());
2336    // prior to the above statement, the interlace analyser does not contain the correct total number of bits.
2337
[655]2338    printf( "\n\nSUMMARY INTERLACED ---------------------------------------------\n" );
[1413]2339#if JVET_F0064_MSSSIM
2340    m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printMSSSIM, bitDepths);
2341#else
[1313]2342    m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
[1413]2343#endif
[1313]2344
2345    if (!m_pcCfg->getSummaryOutFilename().empty())
2346    {
2347      m_gcAnalyzeAll_in.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryOutFilename());
2348    }
[655]2349  }
2350
[608]2351  printf("\nRVM: %.3lf\n" , xCalculateRVM());
[56]2352}
[1313]2353
2354#if NH_3D_VSO
2355Void TEncGOP::preLoopFilterPicAll( TComPic* pcPic, Dist64& ruiDist )
[608]2356#else
[1313]2357Void TEncGOP::preLoopFilterPicAll( TComPic* pcPic, UInt64& ruiDist )
[608]2358#endif
[56]2359{
[2]2360  Bool bCalcDist = false;
[608]2361  m_pcLoopFilter->setCfg(m_pcCfg->getLFCrossTileBoundaryFlag());
[2]2362  m_pcLoopFilter->loopFilterPic( pcPic );
[1313]2363
[2]2364  if (!bCalcDist)
[1313]2365  {
2366    ruiDist = xFindDistortionFrame(pcPic->getPicYuvOrg(), pcPic->getPicYuvRec(), pcPic->getPicSym()->getSPS().getBitDepths());
2367  }
[2]2368}
2369
2370// ====================================================================================================================
2371// Protected member functions
2372// ====================================================================================================================
2373
[655]2374
[1313]2375Void TEncGOP::xInitGOP( Int iPOCLast, Int iNumPicRcvd, Bool isField )
[655]2376{
2377  assert( iNumPicRcvd > 0 );
2378  //  Exception for the first frames
2379  if ( ( isField && (iPOCLast == 0 || iPOCLast == 1) ) || (!isField  && (iPOCLast == 0))  )
2380  {
2381    m_iGopSize    = 1;
2382  }
2383  else
2384  {
2385    m_iGopSize    = m_pcCfg->getGOPSize();
2386  }
2387  assert (m_iGopSize > 0);
[1313]2388
[655]2389  return;
2390}
2391
[1313]2392
[608]2393Void TEncGOP::xGetBuffer( TComList<TComPic*>&      rcListPic,
[56]2394                         TComList<TComPicYuv*>&    rcListPicYuvRecOut,
2395                         Int                       iNumPicRcvd,
2396                         Int                       iTimeOffset,
2397                         TComPic*&                 rpcPic,
2398                         TComPicYuv*&              rpcPicYuvRecOut,
[655]2399                         Int                       pocCurr,
[1313]2400                         Bool                      isField)
[56]2401{
2402  Int i;
2403  //  Rec. output
2404  TComList<TComPicYuv*>::iterator     iterPicYuvRec = rcListPicYuvRecOut.end();
[1313]2405
2406  if (isField && pocCurr > 1 && m_iGopSize!=1)
[56]2407  {
[1313]2408    iTimeOffset--;
[655]2409  }
[1313]2410
2411  for ( i = 0; i < (iNumPicRcvd - iTimeOffset + 1); i++ )
[655]2412  {
[56]2413    iterPicYuvRec--;
2414  }
[1313]2415
[56]2416  rpcPicYuvRecOut = *(iterPicYuvRec);
[1313]2417
[56]2418  //  Current pic.
2419  TComList<TComPic*>::iterator        iterPic       = rcListPic.begin();
2420  while (iterPic != rcListPic.end())
2421  {
2422    rpcPic = *(iterPic);
2423    rpcPic->setCurrSliceIdx(0);
[608]2424    if (rpcPic->getPOC() == pocCurr)
[56]2425    {
2426      break;
2427    }
2428    iterPic++;
2429  }
[655]2430
[1313]2431  assert (rpcPic != NULL);
[608]2432  assert (rpcPic->getPOC() == pocCurr);
[1313]2433
[56]2434  return;
2435}
2436
[1313]2437#if NH_3D_VSO
2438Dist64 TEncGOP::xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1, const BitDepths &bitDepths)
[608]2439#else
[1313]2440UInt64 TEncGOP::xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1, const BitDepths &bitDepths)
[608]2441#endif
[56]2442{
[1313]2443#if NH_3D_VSO
[608]2444  Dist64  uiTotalDiff = 0;
2445#else
[2]2446  UInt64  uiTotalDiff = 0;
[608]2447#endif
[1313]2448
2449  for(Int chan=0; chan<pcPic0 ->getNumberValidComponents(); chan++)
[2]2450  {
[1313]2451    const ComponentID ch=ComponentID(chan);
2452    Pel*  pSrc0   = pcPic0 ->getAddr(ch);
2453    Pel*  pSrc1   = pcPic1 ->getAddr(ch);
2454    UInt  uiShift     = 2 * DISTORTION_PRECISION_ADJUSTMENT(bitDepths.recon[toChannelType(ch)]-8);
2455
2456    const Int   iStride = pcPic0->getStride(ch);
2457    const Int   iWidth  = pcPic0->getWidth(ch);
2458    const Int   iHeight = pcPic0->getHeight(ch);
2459
2460    for(Int y = 0; y < iHeight; y++ )
[2]2461    {
[1313]2462      for(Int x = 0; x < iWidth; x++ )
2463      {
2464        Intermediate_Int iTemp = pSrc0[x] - pSrc1[x];
2465        uiTotalDiff += UInt64((iTemp*iTemp) >> uiShift);
2466      }
2467      pSrc0 += iStride;
2468      pSrc1 += iStride;
[2]2469    }
2470  }
[1313]2471
2472  return uiTotalDiff;
2473}
2474
[1413]2475#if JVET_F0064_MSSSIM
2476Void TEncGOP::xCalculateAddPSNRs( const Bool isField, const Bool isFieldTopFieldFirst, const Int iGOPid, TComPic* pcPic, const AccessUnit&accessUnit, TComList<TComPic*> &rcListPic, const Double dEncTime, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE, const Bool printMSSSIM, Double* PSNR_Y )
[1313]2477{
[1413]2478  xCalculateAddPSNR( pcPic, pcPic->getPicYuvRec(), accessUnit, dEncTime, snr_conversion, printFrameMSE, printMSSSIM, PSNR_Y );
2479#else
2480Void TEncGOP::xCalculateAddPSNRs( const Bool isField, const Bool isFieldTopFieldFirst, const Int iGOPid, TComPic* pcPic, const AccessUnit&accessUnit, TComList<TComPic*> &rcListPic, const Double dEncTime, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE, Double* PSNR_Y )
2481{
2482  xCalculateAddPSNR( pcPic, pcPic->getPicYuvRec(), accessUnit, dEncTime, snr_conversion, printFrameMSE, PSNR_Y );
2483#endif
[1313]2484
2485  //In case of field coding, compute the interlaced PSNR for both fields
2486  if(isField)
[2]2487  {
[1313]2488    Bool bothFieldsAreEncoded = false;
2489    Int correspondingFieldPOC = pcPic->getPOC();
2490    Int currentPicGOPPoc = m_pcCfg->getGOPEntry(iGOPid).m_POC;
2491    if(pcPic->getPOC() == 0)
[2]2492    {
[1313]2493      // particular case for POC 0 and 1.
2494      // If they are not encoded first and separately from other pictures, we need to change this
2495      // POC 0 is always encoded first then POC 1 is encoded
2496      bothFieldsAreEncoded = false;
[2]2497    }
[1313]2498    else if(pcPic->getPOC() == 1)
[2]2499    {
[1313]2500      // if we are at POC 1, POC 0 has been encoded for sure
2501      correspondingFieldPOC = 0;
2502      bothFieldsAreEncoded = true;
[2]2503    }
[1313]2504    else
2505    {
2506      if(pcPic->getPOC()%2 == 1)
2507      {
2508        correspondingFieldPOC -= 1; // all odd POC are associated with the preceding even POC (e.g poc 1 is associated to poc 0)
2509        currentPicGOPPoc      -= 1;
2510      }
2511      else
2512      {
2513        correspondingFieldPOC += 1; // all even POC are associated with the following odd POC (e.g poc 0 is associated to poc 1)
2514        currentPicGOPPoc      += 1;
2515      }
2516      for(Int i = 0; i < m_iGopSize; i ++)
2517      {
2518        if(m_pcCfg->getGOPEntry(i).m_POC == currentPicGOPPoc)
2519        {
2520          bothFieldsAreEncoded = m_pcCfg->getGOPEntry(i).m_isEncoded;
2521          break;
2522        }
2523      }
2524    }
2525
2526    if(bothFieldsAreEncoded)
2527    {
2528      //get complementary top field
2529      TComList<TComPic*>::iterator   iterPic = rcListPic.begin();
2530      while ((*iterPic)->getPOC() != correspondingFieldPOC)
2531      {
2532        iterPic ++;
2533      }
2534      TComPic* correspondingFieldPic = *(iterPic);
2535
2536      if( (pcPic->isTopField() && isFieldTopFieldFirst) || (!pcPic->isTopField() && !isFieldTopFieldFirst))
2537      {
[1413]2538#if JVET_F0064_MSSSIM
2539        xCalculateInterlacedAddPSNR(pcPic, correspondingFieldPic, pcPic->getPicYuvRec(), correspondingFieldPic->getPicYuvRec(), snr_conversion, printFrameMSE, printMSSSIM, PSNR_Y );
2540#else
2541        xCalculateInterlacedAddPSNR(pcPic, correspondingFieldPic, pcPic->getPicYuvRec(), correspondingFieldPic->getPicYuvRec(), snr_conversion, printFrameMSE, PSNR_Y );
2542#endif
[1313]2543      }
2544      else
2545      {
[1413]2546#if JVET_F0064_MSSSIM
2547        xCalculateInterlacedAddPSNR(correspondingFieldPic, pcPic, correspondingFieldPic->getPicYuvRec(), pcPic->getPicYuvRec(), snr_conversion, printFrameMSE, printMSSSIM, PSNR_Y );
2548#else
2549        xCalculateInterlacedAddPSNR(correspondingFieldPic, pcPic, correspondingFieldPic->getPicYuvRec(), pcPic->getPicYuvRec(), snr_conversion, printFrameMSE, PSNR_Y );
2550#endif
[1313]2551      }
2552    }
[2]2553  }
2554}
2555
[1413]2556#if JVET_F0064_MSSSIM
2557Void TEncGOP::xCalculateAddPSNR( TComPic* pcPic, TComPicYuv* pcPicD, const AccessUnit& accessUnit, Double dEncTime, const InputColourSpaceConversion conversion, const Bool printFrameMSE, const Bool printMSSSIM, Double* PSNR_Y )
2558#else
2559Void TEncGOP::xCalculateAddPSNR( TComPic* pcPic, TComPicYuv* pcPicD, const AccessUnit& accessUnit, Double dEncTime, const InputColourSpaceConversion conversion, const Bool printFrameMSE, Double* PSNR_Y )
2560#endif
[2]2561{
[1313]2562  Double  dPSNR[MAX_NUM_COMPONENT];
2563
2564  for(Int i=0; i<MAX_NUM_COMPONENT; i++)
[56]2565  {
[1313]2566    dPSNR[i]=0.0;
[56]2567  }
2568
[1313]2569  TComPicYuv cscd;
2570  if (conversion!=IPCOLOURSPACE_UNCHANGED)
2571  {
[1386]2572    cscd.createWithoutCUInfo(pcPicD->getWidth(COMPONENT_Y), pcPicD->getHeight(COMPONENT_Y), pcPicD->getChromaFormat() );
[1313]2573    TVideoIOYuv::ColourSpaceConvert(*pcPicD, cscd, conversion, false);
2574  }
2575  TComPicYuv &picd=(conversion==IPCOLOURSPACE_UNCHANGED)?*pcPicD : cscd;
2576
[2]2577  //===== calculate PSNR =====
[1313]2578  Double MSEyuvframe[MAX_NUM_COMPONENT] = {0, 0, 0};
2579
2580  for(Int chan=0; chan<pcPicD->getNumberValidComponents(); chan++)
[2]2581  {
[1313]2582    const ComponentID ch=ComponentID(chan);
2583    const TComPicYuv *pOrgPicYuv =(conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg() : pcPic ->getPicYuvOrg();
2584    const Pel*  pOrg       = pOrgPicYuv->getAddr(ch);
2585    const Int   iOrgStride = pOrgPicYuv->getStride(ch);
2586    Pel*  pRec    = picd.getAddr(ch);
2587    const Int   iRecStride = picd.getStride(ch);
2588
2589    const Int   iWidth  = pcPicD->getWidth (ch) - (m_pcEncTop->getPad(0) >> pcPic->getComponentScaleX(ch));
2590    const Int   iHeight = pcPicD->getHeight(ch) - ((m_pcEncTop->getPad(1) >> (pcPic->isField()?1:0)) >> pcPic->getComponentScaleY(ch));
2591
2592    Int   iSize   = iWidth*iHeight;
2593
2594    UInt64 uiSSDtemp=0;
2595    for(Int y = 0; y < iHeight; y++ )
[2]2596    {
[1313]2597      for(Int x = 0; x < iWidth; x++ )
2598      {
2599        Intermediate_Int iDiff = (Intermediate_Int)( pOrg[x] - pRec[x] );
2600        uiSSDtemp   += iDiff * iDiff;
2601      }
2602      pOrg += iOrgStride;
2603      pRec += iRecStride;
[2]2604    }
[1313]2605#if NH_3D_VSO
[608]2606#if H_3D_VSO_SYNTH_DIST_OUT
[2]2607  if ( m_pcRdCost->getUseRenModel() )
2608  {
[56]2609    unsigned int maxval = 255 * (1<<(g_uiBitDepth + g_uiBitIncrement -8));
2610    Double fRefValueY = (double) maxval * maxval * iSize;
2611    Double fRefValueC = fRefValueY / 4.0;
[5]2612    TRenModel*  pcRenModel = m_pcEncTop->getEncTop()->getRenModel();
2613    Int64 iDistVSOY, iDistVSOU, iDistVSOV;
2614    pcRenModel->getTotalSSE( iDistVSOY, iDistVSOU, iDistVSOV );
[2]2615    dYPSNR = ( iDistVSOY ? 10.0 * log10( fRefValueY / (Double) iDistVSOY ) : 99.99 );
2616    dUPSNR = ( iDistVSOU ? 10.0 * log10( fRefValueC / (Double) iDistVSOU ) : 99.99 );
2617    dVPSNR = ( iDistVSOV ? 10.0 * log10( fRefValueC / (Double) iDistVSOV ) : 99.99 );
2618  }
2619  else
[608]2620  {
[5]2621#endif
[77]2622#endif
[1313]2623    const Int maxval = 255 << (pcPic->getPicSym()->getSPS().getBitDepth(toChannelType(ch)) - 8);
2624    const Double fRefValue = (Double) maxval * maxval * iSize;
2625    dPSNR[ch]         = ( uiSSDtemp ? 10.0 * log10( fRefValue / (Double)uiSSDtemp ) : 999.99 );
2626    MSEyuvframe[ch]   = (Double)uiSSDtemp/(iSize);
[2]2627  }
[1313]2628
[1413]2629#if EXTENSION_360_VIDEO
2630  m_ext360.calculatePSNRs(pcPic);
2631#endif
2632
2633#if JVET_F0064_MSSSIM
2634  //===== calculate MS-SSIM =====
2635  Double  MSSSIM[MAX_NUM_COMPONENT] = {0,0,0};
2636  if (printMSSSIM) 
2637  {
2638    for(Int chan=0; chan<pcPicD->getNumberValidComponents(); chan++)
2639    {
2640      const ComponentID ch  = ComponentID(chan);
2641      const TComPicYuv *pOrgPicYuv =(conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg() : pcPic ->getPicYuvOrg();
2642      const Pel*  pOrg      = pOrgPicYuv->getAddr(ch);
2643      const Int   orgStride = pOrgPicYuv->getStride(ch);
2644      const Pel*  pRec      = picd.getAddr(ch);
2645      const Int   recStride = picd.getStride(ch);
2646      const Int   width     = pcPicD->getWidth (ch) - (m_pcEncTop->getPad(0) >> pcPic->getComponentScaleX(ch));
2647      const Int   height    = pcPicD->getHeight(ch) - ((m_pcEncTop->getPad(1) >> (pcPic->isField()?1:0)) >> pcPic->getComponentScaleY(ch));
2648      const UInt  bitDepth  = pcPic->getPicSym()->getSPS().getBitDepth(toChannelType(ch));
2649 
2650      MSSSIM[ch] = xCalculateMSSSIM (pOrg, orgStride, pRec, recStride, width, height, bitDepth);
2651    }
2652  }
2653#endif
2654
2655
[1313]2656#if NH_3D_VSO
[608]2657#if H_3D_VSO_SYNTH_DIST_OUT
2658}
[1356]2659#endif
2660#endif
[56]2661  /* calculate the size of the access unit, excluding:
2662   *  - SEI NAL units
2663   */
[608]2664  UInt numRBSPBytes = 0;
[56]2665  for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)
2666  {
[608]2667    UInt numRBSPBytes_nal = UInt((*it)->m_nalUnitData.str().size());
[1313]2668    if (m_pcCfg->getSummaryVerboseness() > 0)
2669    {
[56]2670    printf("*** %6s numBytesInNALunit: %u\n", nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal);
[1313]2671    }
[608]2672    if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI)
2673    {
[56]2674      numRBSPBytes += numRBSPBytes_nal;
[1413]2675      // add start code bytes (Annex B)
2676      if (it == accessUnit.begin() || (*it)->m_nalUnitType == NAL_UNIT_VPS || (*it)->m_nalUnitType == NAL_UNIT_SPS || (*it)->m_nalUnitType == NAL_UNIT_PPS)
2677      {
2678        numRBSPBytes += 4;
2679      }
2680      else
2681      {
2682        numRBSPBytes += 3;
2683      }
[608]2684    }
[56]2685  }
[5]2686
[608]2687  UInt uibits = numRBSPBytes * 8;
[2]2688  m_vRVM_RP.push_back( uibits );
2689
2690  //===== add PSNR =====
[1413]2691#if JVET_F0064_MSSSIM
2692  m_gcAnalyzeAll.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2693#else
[1313]2694  m_gcAnalyzeAll.addResult (dPSNR, (Double)uibits, MSEyuvframe);
[1413]2695#endif
2696#if EXTENSION_360_VIDEO
2697  m_ext360.addResult(m_gcAnalyzeAll);
2698#endif
[1313]2699
[2]2700  TComSlice*  pcSlice = pcPic->getSlice(0);
2701  if (pcSlice->isIntra())
2702  {
[1413]2703#if JVET_F0064_MSSSIM
2704    m_gcAnalyzeI.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2705#else
[1313]2706    m_gcAnalyzeI.addResult (dPSNR, (Double)uibits, MSEyuvframe);
[1413]2707#endif
2708#if EXTENSION_360_VIDEO
2709    m_ext360.addResult(m_gcAnalyzeI);
2710#endif
2711    *PSNR_Y = dPSNR[COMPONENT_Y];
[2]2712  }
2713  if (pcSlice->isInterP())
2714  {
[1413]2715#if JVET_F0064_MSSSIM
2716    m_gcAnalyzeP.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2717#else
[1313]2718    m_gcAnalyzeP.addResult (dPSNR, (Double)uibits, MSEyuvframe);
[1413]2719#endif
2720#if EXTENSION_360_VIDEO
2721    m_ext360.addResult(m_gcAnalyzeP);
2722#endif
2723    *PSNR_Y = dPSNR[COMPONENT_Y];
[2]2724  }
2725  if (pcSlice->isInterB())
2726  {
[1413]2727#if JVET_F0064_MSSSIM
2728    m_gcAnalyzeB.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2729#else
[1313]2730    m_gcAnalyzeB.addResult (dPSNR, (Double)uibits, MSEyuvframe);
[1413]2731#endif
2732#if EXTENSION_360_VIDEO
2733    m_ext360.addResult(m_gcAnalyzeB);
2734#endif
2735    *PSNR_Y = dPSNR[COMPONENT_Y];
[2]2736  }
2737
[1386]2738  TChar c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B');
[1313]2739  if (!pcSlice->isReferenced())
2740  {
2741    c += 32;
2742  }
[5]2743
[56]2744#if ADAPTIVE_QP_SELECTION
[1313]2745#if NH_MV
[608]2746  printf("Layer %3d   POC %4d TId: %1d ( %c-SLICE, nQP %d QP %d ) %10d  bits",
2747    pcSlice->getLayerId(),
2748    pcSlice->getPOC(),
2749    pcSlice->getTLayer(),
2750    c,
2751    pcSlice->getSliceQpBase(),
2752    pcSlice->getSliceQp(),
2753    uibits );
2754#else
2755  printf("POC %4d TId: %1d ( %c-SLICE, nQP %d QP %d ) %10d bits",
[56]2756         pcSlice->getPOC(),
2757         pcSlice->getTLayer(),
2758         c,
2759         pcSlice->getSliceQpBase(),
2760         pcSlice->getSliceQp(),
2761         uibits );
[608]2762#endif
[56]2763#else
[1313]2764#if NH_MV
[608]2765  printf("Layer %3d   POC %4d TId: %1d ( %c-SLICE, QP %d ) %10d bits",
2766    pcSlice->getLayerId(),
2767    pcSlice->getPOC()-pcSlice->getLastIDR(),
2768    pcSlice->getTLayer(),
2769    c,
2770    pcSlice->getSliceQp(),
2771    uibits );
2772#else
2773  printf("POC %4d TId: %1d ( %c-SLICE, QP %d ) %10d bits",
[56]2774         pcSlice->getPOC()-pcSlice->getLastIDR(),
2775         pcSlice->getTLayer(),
2776         c,
2777         pcSlice->getSliceQp(),
2778         uibits );
2779#endif
[608]2780#endif
[1313]2781#if NH_MV
2782  printf(" [Y %8.4lf dB    U %8.4lf dB    V %8.4lf dB]", dPSNR[COMPONENT_Y], dPSNR[COMPONENT_Cb], dPSNR[COMPONENT_Cr] );
2783#else
2784  printf(" [Y %6.4lf dB    U %6.4lf dB    V %6.4lf dB]", dPSNR[COMPONENT_Y], dPSNR[COMPONENT_Cb], dPSNR[COMPONENT_Cr] );
2785#endif
[1413]2786#if JVET_F0064_MSSSIM
2787  if (printMSSSIM)
2788  {
2789    printf(" [MS-SSIM Y %1.6lf    U %1.6lf    V %1.6lf]", MSSSIM[COMPONENT_Y], MSSSIM[COMPONENT_Cb], MSSSIM[COMPONENT_Cr] );
2790  } 
2791#endif
[1313]2792  if (printFrameMSE)
2793  {
2794    printf(" [Y MSE %6.4lf  U MSE %6.4lf  V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] );
2795  }
[1413]2796#if EXTENSION_360_VIDEO
2797  m_ext360.printPerPOCInfo();
2798#endif
[1313]2799  printf(" [ET %5.0f ]", dEncTime );
[56]2800
[1386]2801  // printf(" [WP %d]", pcSlice->getUseWeightedPrediction());
2802
[2]2803  for (Int iRefList = 0; iRefList < 2; iRefList++)
2804  {
[56]2805    printf(" [L%d ", iRefList);
[2]2806    for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++)
2807    {
[1313]2808#if NH_MV
[608]2809      if( pcSlice->getLayerId() != pcSlice->getRefLayerId( RefPicList(iRefList), iRefIndex ) )
[2]2810      {
[608]2811        printf( "V%d ", pcSlice->getRefLayerId( RefPicList(iRefList), iRefIndex ) );
[2]2812      }
2813      else
[56]2814      {
[608]2815#endif
2816      printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)-pcSlice->getLastIDR());
[1313]2817#if NH_MV
[56]2818      }
[608]2819#endif
[2]2820    }
[56]2821    printf("]");
[2]2822  }
[1313]2823
2824  cscd.destroy();
[2]2825}
2826
[1413]2827#if JVET_F0064_MSSSIM
2828Double TEncGOP::xCalculateMSSSIM (const Pel *pOrg, const Int orgStride, const Pel* pRec, const Int recStride, const Int width, const Int height, const UInt bitDepth)
2829{
2830  const Int MAX_MSSSIM_SCALE  = 5;
2831  const Int WEIGHTING_MID_TAP = 5;
2832  const Int WEIGHTING_SIZE    = WEIGHTING_MID_TAP*2+1;
2833
2834  UInt maxScale;
2835
2836  // For low resolution videos determine number of scales
2837  if (width < 22 || height < 22)
2838  {
2839    maxScale = 1; 
2840  }
2841  else if (width < 44 || height < 44)
2842  {
2843    maxScale = 2; 
2844  }
2845  else if (width < 88 || height < 88)
2846  {
2847    maxScale = 3; 
2848  }
2849  else if (width < 176 || height < 176)
2850  {
2851    maxScale = 4; 
2852  }
2853  else
2854  {
2855    maxScale = 5;
2856  }
2857
2858  assert(maxScale>0 && maxScale<=MAX_MSSSIM_SCALE);
2859
2860  //Normalized Gaussian mask design, 11*11, s.d. 1.5
2861  Double weights[WEIGHTING_SIZE][WEIGHTING_SIZE];
2862  {
2863    Double coeffSum=0.0;
2864    for(Int y=0; y<WEIGHTING_SIZE; y++)
2865    {
2866      for(Int x=0; x<WEIGHTING_SIZE; x++)
2867      {
2868        weights[y][x]=exp(-((y-WEIGHTING_MID_TAP)*(y-WEIGHTING_MID_TAP)+(x-WEIGHTING_MID_TAP)*(x-WEIGHTING_MID_TAP))/(WEIGHTING_MID_TAP-0.5));
2869        coeffSum +=weights[y][x];
2870      }
2871    }
2872
2873    for(Int y=0; y<WEIGHTING_SIZE; y++)
2874    {
2875      for(Int x=0; x<WEIGHTING_SIZE; x++)
2876      {
2877        weights[y][x] /=coeffSum;
2878      }
2879    }
2880  }
2881
2882  //Resolution based weights
2883  const Double exponentWeights[MAX_MSSSIM_SCALE][MAX_MSSSIM_SCALE] = {{1.0,    0,      0,      0,      0     },
2884                                                                      {0.1356, 0.8644, 0,      0,      0     },
2885                                                                      {0.0711, 0.4530, 0.4760, 0,      0     },
2886                                                                      {0.0517, 0.3295, 0.3462, 0.2726, 0     },
2887                                                                      {0.0448, 0.2856, 0.3001, 0.2363, 0.1333}};
2888
2889  //Downsampling of data:
2890  std::vector<Double> original[MAX_MSSSIM_SCALE];
2891  std::vector<Double> recon[MAX_MSSSIM_SCALE];
2892
2893  for(UInt scale=0; scale<maxScale; scale++)
2894  {
2895    const Int scaledHeight = height >> scale;
2896    const Int scaledWidth  = width  >> scale;
2897    original[scale].resize(scaledHeight*scaledWidth, Double(0));
2898    recon[scale].resize(scaledHeight*scaledWidth, Double(0));
2899  }
2900
2901  // Initial [0] arrays to be a copy of the source data (but stored in array "Double", not Pel array).
2902  for(Int y=0; y<height; y++)
2903  {
2904    for(Int x=0; x<width; x++)
2905    {
2906      original[0][y*width+x] = pOrg[y*orgStride+x];
2907      recon[0][   y*width+x] = pRec[y*recStride+x];
2908    }
2909  }
2910
2911  // Set up other arrays to be average value of each 2x2 sample.
2912  for(UInt scale=1; scale<maxScale; scale++)
2913  {
2914    const Int scaledHeight = height >> scale;
2915    const Int scaledWidth  = width  >> scale;
2916    for(Int y=0; y<scaledHeight; y++)
2917    {
2918      for(Int x=0; x<scaledWidth; x++)
2919      {
2920        original[scale][y*scaledWidth+x]= (original[scale-1][ 2*y   *(2*scaledWidth)+2*] +
2921                                           original[scale-1][ 2*y   *(2*scaledWidth)+2*x+1] +
2922                                           original[scale-1][(2*y+1)*(2*scaledWidth)+2*] +
2923                                           original[scale-1][(2*y+1)*(2*scaledWidth)+2*x+1]) / 4.0;
2924        recon[scale][y*scaledWidth+x]=    (   recon[scale-1][ 2*y   *(2*scaledWidth)+2*] +
2925                                              recon[scale-1][ 2*y   *(2*scaledWidth)+2*x+1] +
2926                                              recon[scale-1][(2*y+1)*(2*scaledWidth)+2*] +
2927                                              recon[scale-1][(2*y+1)*(2*scaledWidth)+2*x+1]) / 4.0;
2928      }
2929    }
2930  }
2931 
2932  // Calculate MS-SSIM:
2933  const UInt   maxValue  = (1<<bitDepth)-1;
2934  const Double c1        = (0.01*maxValue)*(0.01*maxValue);
2935  const Double c2        = (0.03*maxValue)*(0.03*maxValue);
2936 
2937  Double finalMSSSIM = 1.0;
2938
2939  for(UInt scale=0; scale<maxScale; scale++)
2940  {
2941    const Int scaledHeight    = height >> scale;
2942    const Int scaledWidth     = width  >> scale;
2943    const Int blocksPerRow    = scaledWidth-WEIGHTING_SIZE+1;
2944    const Int blocksPerColumn = scaledHeight-WEIGHTING_SIZE+1;
2945    const Int totalBlocks     = blocksPerRow*blocksPerColumn;
2946
2947    Double meanSSIM= 0.0;
2948
2949    for(Int blockIndexY=0; blockIndexY<blocksPerColumn; blockIndexY++)
2950    {
2951      for(Int blockIndexX=0; blockIndexX<blocksPerRow; blockIndexX++)
2952      {
2953        Double muOrg          =0.0;
2954        Double muRec          =0.0;
2955        Double muOrigSqr      =0.0;
2956        Double muRecSqr       =0.0;
2957        Double muOrigMultRec  =0.0;
2958
2959        for(Int y=0; y<WEIGHTING_SIZE; y++)
2960        {
2961          for(Int x=0;x<WEIGHTING_SIZE; x++)
2962          {
2963            const Double gaussianWeight=weights[y][x];
2964            const Int    sampleOffset=(blockIndexY+y)*scaledWidth+(blockIndexX+x);
2965            const Double orgPel=original[scale][sampleOffset];
2966            const Double recPel=   recon[scale][sampleOffset];
2967
2968            muOrg        +=orgPel*       gaussianWeight;
2969            muRec        +=recPel*       gaussianWeight;
2970            muOrigSqr    +=orgPel*orgPel*gaussianWeight;
2971            muRecSqr     +=recPel*recPel*gaussianWeight;
2972            muOrigMultRec+=orgPel*recPel*gaussianWeight;
2973          }
2974        }
2975
2976        const Double sigmaSqrOrig = muOrigSqr    -(muOrg*muOrg);
2977        const Double sigmaSqrRec  = muRecSqr     -(muRec*muRec);
2978        const Double sigmaOrigRec = muOrigMultRec-(muOrg*muRec);
2979
2980        Double blockSSIMVal = ((2.0*sigmaOrigRec + c2)/(sigmaSqrOrig+sigmaSqrRec + c2));
2981        if(scale == maxScale-1)
2982        {
2983          blockSSIMVal*=(2.0*muOrg*muRec + c1)/(muOrg*muOrg+muRec*muRec + c1);
2984        }
2985
2986        meanSSIM += blockSSIMVal;
2987      }
2988    }
2989
2990    meanSSIM /=totalBlocks;
2991
2992    finalMSSSIM *= pow(meanSSIM, exponentWeights[maxScale-1][scale]);
2993  }
2994
2995  return finalMSSSIM;
2996}
2997#endif
2998
2999
[1313]3000Void TEncGOP::xCalculateInterlacedAddPSNR( TComPic* pcPicOrgFirstField, TComPic* pcPicOrgSecondField,
3001                                           TComPicYuv* pcPicRecFirstField, TComPicYuv* pcPicRecSecondField,
[1413]3002#if JVET_F0064_MSSSIM
3003                                           const InputColourSpaceConversion conversion, const Bool printFrameMSE, const Bool printMSSSIM, Double* PSNR_Y )
3004#else
3005                                           const InputColourSpaceConversion conversion, const Bool printFrameMSE, Double* PSNR_Y )
3006#endif
[655]3007{
3008
[1313]3009#if  NH_MV
[1356]3010  assert( 0 ); // Field coding and MV need to be aligned.
[655]3011#else
[1313]3012
3013  const TComSPS &sps=pcPicOrgFirstField->getPicSym()->getSPS();
3014  Double  dPSNR[MAX_NUM_COMPONENT];
3015  TComPic    *apcPicOrgFields[2]={pcPicOrgFirstField, pcPicOrgSecondField};
3016  TComPicYuv *apcPicRecFields[2]={pcPicRecFirstField, pcPicRecSecondField};
3017
3018  for(Int i=0; i<MAX_NUM_COMPONENT; i++)
[655]3019  {
[1313]3020    dPSNR[i]=0.0;
[655]3021  }
[1313]3022
3023  TComPicYuv cscd[2 /* first/second field */];
3024  if (conversion!=IPCOLOURSPACE_UNCHANGED)
[655]3025  {
[1313]3026    for(UInt fieldNum=0; fieldNum<2; fieldNum++)
[655]3027    {
[1313]3028      TComPicYuv &reconField=*(apcPicRecFields[fieldNum]);
[1386]3029      cscd[fieldNum].createWithoutCUInfo(reconField.getWidth(COMPONENT_Y), reconField.getHeight(COMPONENT_Y), reconField.getChromaFormat() );
[1313]3030      TVideoIOYuv::ColourSpaceConvert(reconField, cscd[fieldNum], conversion, false);
3031      apcPicRecFields[fieldNum]=cscd+fieldNum;
[655]3032    }
3033  }
[1313]3034
[655]3035  //===== calculate PSNR =====
[1313]3036  Double MSEyuvframe[MAX_NUM_COMPONENT] = {0, 0, 0};
3037
3038  assert(apcPicRecFields[0]->getChromaFormat()==apcPicRecFields[1]->getChromaFormat());
3039  const UInt numValidComponents=apcPicRecFields[0]->getNumberValidComponents();
3040
3041  for(Int chan=0; chan<numValidComponents; chan++)
[655]3042  {
[1313]3043    const ComponentID ch=ComponentID(chan);
3044    assert(apcPicRecFields[0]->getWidth(ch)==apcPicRecFields[1]->getWidth(ch));
3045    assert(apcPicRecFields[0]->getHeight(ch)==apcPicRecFields[1]->getHeight(ch));
3046
3047    UInt64 uiSSDtemp=0;
3048    const Int   iWidth  = apcPicRecFields[0]->getWidth (ch) - (m_pcEncTop->getPad(0) >> apcPicRecFields[0]->getComponentScaleX(ch));
3049    const Int   iHeight = apcPicRecFields[0]->getHeight(ch) - ((m_pcEncTop->getPad(1) >> 1) >> apcPicRecFields[0]->getComponentScaleY(ch));
3050
3051    Int   iSize   = iWidth*iHeight;
3052
3053    for(UInt fieldNum=0; fieldNum<2; fieldNum++)
[655]3054    {
[1313]3055      TComPic *pcPic=apcPicOrgFields[fieldNum];
3056      TComPicYuv *pcPicD=apcPicRecFields[fieldNum];
3057
3058      const Pel*  pOrg    = (conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg()->getAddr(ch) : pcPic ->getPicYuvOrg()->getAddr(ch);
3059      Pel*  pRec    = pcPicD->getAddr(ch);
3060      const Int   iStride = pcPicD->getStride(ch);
3061
3062
3063      for(Int y = 0; y < iHeight; y++ )
3064      {
3065        for(Int x = 0; x < iWidth; x++ )
3066        {
3067          Intermediate_Int iDiff = (Intermediate_Int)( pOrg[x] - pRec[x] );
3068          uiSSDtemp   += iDiff * iDiff;
3069        }
3070        pOrg += iStride;
3071        pRec += iStride;
3072      }
[655]3073    }
[1313]3074    const Int maxval = 255 << (sps.getBitDepth(toChannelType(ch)) - 8);
3075    const Double fRefValue = (Double) maxval * maxval * iSize*2;
3076    dPSNR[ch]         = ( uiSSDtemp ? 10.0 * log10( fRefValue / (Double)uiSSDtemp ) : 999.99 );
3077    MSEyuvframe[ch]   = (Double)uiSSDtemp/(iSize*2);
[655]3078  }
[1313]3079
[1413]3080#if JVET_F0064_MSSSIM
3081  //===== calculate MS-SSIM =====
3082  Double MSSSIM[MAX_NUM_COMPONENT] = {0,0,0};
3083  if (printMSSSIM)
3084  {
3085    for(Int chan=0; chan<numValidComponents; chan++)
3086    {
3087      const ComponentID ch=ComponentID(chan);
3088      assert(apcPicRecFields[0]->getWidth(ch) ==apcPicRecFields[1]->getWidth(ch) );
3089      assert(apcPicRecFields[0]->getHeight(ch)==apcPicRecFields[1]->getHeight(ch));
3090
3091      Double sumOverFieldsMSSSIM = 0.0;
3092      const Int   width  = apcPicRecFields[0]->getWidth (ch) - ( m_pcEncTop->getPad(0)       >> apcPicRecFields[0]->getComponentScaleX(ch));
3093      const Int   height = apcPicRecFields[0]->getHeight(ch) - ((m_pcEncTop->getPad(1) >> 1) >> apcPicRecFields[0]->getComponentScaleY(ch));
3094
3095      for(UInt fieldNum=0; fieldNum<2; fieldNum++)
3096      {
3097        TComPic    *pcPic      = apcPicOrgFields[fieldNum];
3098        TComPicYuv *pcPicD     = apcPicRecFields[fieldNum];
3099
3100        const Pel*  pOrg       = (conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg()->getAddr(ch)   : pcPic ->getPicYuvOrg()->getAddr(ch);
3101        const Int   orgStride  = (conversion!=IPCOLOURSPACE_UNCHANGED) ? pcPic ->getPicYuvTrueOrg()->getStride(ch) : pcPic ->getPicYuvOrg()->getStride(ch);
3102        Pel*        pRec       = pcPicD->getAddr(ch);
3103        const Int   recStride  = pcPicD->getStride(ch);
3104        const UInt  bitDepth   = sps.getBitDepth(toChannelType(ch));
3105
3106        sumOverFieldsMSSSIM += xCalculateMSSSIM (pOrg, orgStride, pRec, recStride, width, height, bitDepth);
3107      }
3108
3109      MSSSIM[ch] = sumOverFieldsMSSSIM/2;
3110    }
3111  }
3112#endif
3113
[1313]3114  UInt uibits = 0; // the number of bits for the pair is not calculated here - instead the overall total is used elsewhere.
3115
3116  //===== add PSNR =====
[1413]3117#if JVET_F0064_MSSSIM
3118  m_gcAnalyzeAll_in.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
3119#else
[1313]3120  m_gcAnalyzeAll_in.addResult (dPSNR, (Double)uibits, MSEyuvframe);
[1413]3121#endif
[1313]3122
[1413]3123  *PSNR_Y = dPSNR[COMPONENT_Y];
3124
[1313]3125  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] );
[1413]3126#if JVET_F0064_MSSSIM 
3127  if (printMSSSIM)
3128  {
3129    printf(" [MS-SSIM Y %1.6lf    U %1.6lf    V %1.6lf]", MSSSIM[COMPONENT_Y], MSSSIM[COMPONENT_Cb], MSSSIM[COMPONENT_Cr] );
3130  }
3131#endif
[1313]3132  if (printFrameMSE)
[655]3133  {
[1313]3134    printf(" [Y MSE %6.4lf  U MSE %6.4lf  V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] );
[655]3135  }
[1313]3136
3137  for(UInt fieldNum=0; fieldNum<2; fieldNum++)
3138  {
3139    cscd[fieldNum].destroy();
3140  }
[655]3141#endif
3142}
[1313]3143
[2]3144/** Function for deciding the nal_unit_type.
[608]3145 * \param pocCurr POC of the current picture
[1313]3146 * \param lastIDR  POC of the last IDR picture
3147 * \param isField  true to indicate field coding
3148 * \returns the NAL unit type of the picture