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

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

Merged HTM-16.2-dev@1412

  • Property svn:eol-style set to native
File size: 130.5 KB
Line 
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
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2017, ITU/ISO/IEC
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.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
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 */
33
34/** \file     TEncGOP.cpp
35    \brief    GOP encoder class
36*/
37
38#include <list>
39#include <algorithm>
40#include <functional>
41
42#include "TEncTop.h"
43#include "TEncGOP.h"
44#include "TEncAnalyze.h"
45#include "libmd5/MD5.h"
46#include "TLibCommon/SEI.h"
47#include "TLibCommon/NAL.h"
48#include "NALwrite.h"
49#include <time.h>
50#include <math.h>
51
52#include <deque>
53using namespace std;
54
55//! \ingroup TLibEncoder
56//! \{
57
58// ====================================================================================================================
59// Constructor / destructor / initialization / destroy
60// ====================================================================================================================
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}
72
73TEncGOP::TEncGOP()
74{
75  m_iLastIDR            = 0;
76  m_iGopSize            = 0;
77  m_iNumPicCoded        = 0; //Niko
78  m_bFirst              = true;
79  m_iLastRecoveryPicPOC = 0;
80
81  m_pcCfg               = NULL;
82  m_pcSliceEncoder      = NULL;
83  m_pcListPic           = NULL;
84
85  m_pcEntropyCoder      = NULL;
86  m_pcCavlcCoder        = NULL;
87  m_pcSbacCoder         = NULL;
88  m_pcBinCABAC          = NULL;
89
90  m_bSeqFirst           = true;
91
92  m_bRefreshPending     = 0;
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;
98  m_bufferingPeriodSEIPresentInAU = false;
99#if NH_MV
100  m_layerId      = 0;
101  m_viewId       = 0;
102  m_pocLastCoded = -1;
103#if NH_3D
104  m_viewIndex  =   0;
105  m_isDepth = false;
106#endif
107#endif
108  m_associatedIRAPType = NAL_UNIT_CODED_SLICE_IDR_N_LP;
109  m_associatedIRAPPOC  = 0;
110  m_pcDeblockingTempPicYuv = NULL;
111}
112
113TEncGOP::~TEncGOP()
114{
115}
116
117/** Create list to contain pointers to CTU start addresses of slice.
118 */
119Void  TEncGOP::create()
120{
121  m_bLongtermTestPictureHasBeenCoded = 0;
122  m_bLongtermTestPictureHasBeenCoded2 = 0;
123}
124
125Void  TEncGOP::destroy()
126{
127  if (m_pcDeblockingTempPicYuv)
128  {
129    m_pcDeblockingTempPicYuv->destroy();
130    delete m_pcDeblockingTempPicYuv;
131    m_pcDeblockingTempPicYuv = NULL;
132  }
133}
134
135Void TEncGOP::init ( TEncTop* pcTEncTop )
136{
137  m_pcEncTop     = pcTEncTop;
138  m_pcCfg                = pcTEncTop;
139  m_seiEncoder.init(m_pcCfg, pcTEncTop, this);
140  m_pcSliceEncoder       = pcTEncTop->getSliceEncoder();
141  m_pcListPic            = pcTEncTop->getListPic();
142
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();
148
149  m_pcSAO                = pcTEncTop->getSAO();
150  m_pcRateCtrl           = pcTEncTop->getRateCtrl();
151  m_lastBPSEI          = 0;
152  m_totalCoded         = 0;
153
154#if NH_MV
155  m_ivPicLists           = pcTEncTop->getIvPicLists();
156  m_layerId              = pcTEncTop->getLayerId();
157  m_viewId               = pcTEncTop->getViewId();
158#endif
159
160#if NH_3D
161  m_viewIndex            = pcTEncTop->getViewIndex();
162  m_isDepth              = pcTEncTop->getIsDepth();
163
164  m_aICEnableCandidate   = pcTEncTop->getICEnableCandidate();
165  m_aICEnableNum         = pcTEncTop->getICEnableNum();
166#endif
167#if KWU_FIX_URQ
168  m_pcRateCtrl           = pcTEncTop->getRateCtrl();
169#endif
170}
171
172Int TEncGOP::xWriteVPS (AccessUnit &accessUnit, const TComVPS *vps)
173{
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;
179}
180
181Int TEncGOP::xWriteSPS (AccessUnit &accessUnit, const TComSPS *sps)
182{
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
193}
194
195Int TEncGOP::xWritePPS (AccessUnit &accessUnit, const TComPPS *pps)
196{
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;
206}
207
208
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
214{
215  Int actualTotalBits = 0;
216
217#if NH_MV
218  if ( bWriteVps )
219  {
220    actualTotalBits += xWriteVPS(accessUnit, m_pcEncTop->getVPS());
221  }
222#else
223  if (bSeqFirst)
224  {
225    actualTotalBits += xWriteVPS(accessUnit, m_pcEncTop->getVPS());
226  }
227#endif
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  }
237
238  return actualTotalBits;
239}
240
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
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())
257  {
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())&&
310    ( (*itNalu)->m_nalUnitType==NAL_UNIT_ACCESS_UNIT_DELIMITER
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;
321
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);
332
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)
350    {
351      duInfoSeiMessages.pop_front();
352    }
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
362#if NH_MV
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
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())
418    {
419      naluIdx++;
420      nalu++;
421    }
422
423    SEIMessages::iterator duSEI = duInfoSeiMessages.begin();
424    // loop over remaining DUs
425    for (Int duIdx = 1; duIdx < duData.size(); duIdx++)
426    {
427      if (duSEI == duInfoSeiMessages.end())
428      {
429        // if the number of generated SEIs matches the number of DUs, this should not happen
430        assert (false);
431        return;
432      }
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++;
445    }
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);
453
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  }
509
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
518  if(m_pcCfg->getChromaResamplingFilterHintEnabled())
519  {
520    SEIChromaResamplingFilterHint *seiChromaResamplingFilterHint = new SEIChromaResamplingFilterHint;
521    m_seiEncoder.initSEIChromaResamplingFilterHint(seiChromaResamplingFilterHint, m_pcCfg->getChromaResamplingHorFilterIdc(), m_pcCfg->getChromaResamplingVerFilterIdc());
522    seiMessages.push_back(seiChromaResamplingFilterHint);
523  }
524  if(m_pcCfg->getSEIAlternativeTransferCharacteristicsSEIEnable())
525  {
526    SEIAlternativeTransferCharacteristics *seiAlternativeTransferCharacteristics = new SEIAlternativeTransferCharacteristics;
527    m_seiEncoder.initSEIAlternativeTransferCharacteristics(seiAlternativeTransferCharacteristics);
528    seiMessages.push_back(seiAlternativeTransferCharacteristics);
529  }
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())
545    {
546      SEIBufferingPeriod *bufferingPeriodSEIcopy = new SEIBufferingPeriod();
547      bufferingPeriodSEI->copyTo(*bufferingPeriodSEIcopy);
548      nestedSeiMessages.push_back(bufferingPeriodSEIcopy);
549    }
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() )
562    {
563      // Gradual decoding refresh SEI
564      SEIRegionRefreshInfo *gradualDecodingRefreshInfoSEI = new SEIRegionRefreshInfo();
565      gradualDecodingRefreshInfoSEI->m_gdrForegroundFlag = true; // Indicating all "foreground"
566      seiMessages.push_back(gradualDecodingRefreshInfoSEI);
567    }
568    // Recovery point SEI
569    SEIRecoveryPoint *recoveryPointSEI = new SEIRecoveryPoint();
570    m_seiEncoder.initSEIRecoveryPoint(recoveryPointSEI, slice);
571    seiMessages.push_back(recoveryPointSEI);
572  }
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  }
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  }
602}
603
604Void TEncGOP::xCreateScalableNestingSEI (SEIMessages& seiMessages, SEIMessages& nestedSeiMessages)
605{
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}
618
619Void TEncGOP::xCreatePictureTimingSEI  (Int IRAPGOPid, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, SEIMessages& duInfoSeiMessages, TComSlice *slice, Bool isField, std::deque<DUData> &duData)
620{
621
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  {
630    Int picSptDpbOutputDuDelay = 0;
631    SEIPictureTiming *pictureTimingSEI = new SEIPictureTiming();
632
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    }
723
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    }
750
751    if( !m_pcCfg->getPictureTimingSEIEnabled() && pictureTimingSEI )
752    {
753      delete pictureTimingSEI;
754    }
755  }
756}
757
758Void TEncGOP::xUpdateDuData(AccessUnit &testAU, std::deque<DUData> &duData)
759{
760  if (duData.empty())
761  {
762    return;
763  }
764  // fix first
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;
773
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++)
777  {
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  }
786
787  // The last DU may have a trailing SEI
788  if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE)
789  {
790    duData.back().accumBitsDU += ( 20 << 3 ); // probably around 20 bytes - should be further adjusted, e.g. by type
791    duData.back().accumNalsDU += 1;
792  }
793
794}
795Void TEncGOP::xUpdateTimingSEI(SEIPictureTiming *pictureTimingSEI, std::deque<DUData> &duData, const TComSPS *sps)
796{
797  if (!pictureTimingSEI)
798  {
799    return;
800  }
801  const TComVUI *vui = sps->getVuiParameters();
802  const TComHRD *hrd = vui->getHrdParameters();
803  if( hrd->getSubPicCpbParamsPresentFlag() )
804  {
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;
811
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    }
865  }
866}
867Void TEncGOP::xUpdateDuInfoSEI(SEIMessages &duInfoSeiMessages, SEIPictureTiming *pictureTimingSEI)
868{
869  if (duInfoSeiMessages.empty() || (pictureTimingSEI == NULL))
870  {
871    return;
872  }
873
874  Int i=0;
875
876  for (SEIMessages::iterator du = duInfoSeiMessages.begin(); du!= duInfoSeiMessages.end(); du++)
877  {
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++;
883  }
884}
885
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)
888{
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      {
910        std::vector<UChar> zeroBytesPadding(numberOfAdditionalCabacZeroBytes, UChar(0));
911        for(std::size_t i=0; i<numberOfAdditionalCabacZeroWords; i++)
912        {
913          zeroBytesPadding[i*3+2]=3;  // 00 00 03
914        }
915        nalUnitData.write(reinterpret_cast<const TChar*>(&(zeroBytesPadding[0])), numberOfAdditionalCabacZeroBytes);
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  }
924}
925
926class EfficientFieldIRAPMapping
927{
928  private:
929    Int  IRAPGOPid;
930    Bool IRAPtoReorder;
931    Bool swapIRAPForward;
932
933  public:
934    EfficientFieldIRAPMapping() :
935      IRAPGOPid(-1),
936      IRAPtoReorder(false),
937      swapIRAPForward(false)
938    { }
939
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{
949  if(isField)
950  {
951    Int pocCurr;
952    for ( Int iGOPid=0; iGOPid < gopSize; iGOPid++ )
953    {
954      // determine actual POC
955      if(POCLast == 0) //case first frame or first top field
956      {
957        pocCurr=0;
958      }
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
960      {
961        pocCurr = 1;
962      }
963      else
964      {
965        pocCurr = POCLast - numPicRcvd + pCfg->getGOPEntry(iGOPid).m_POC - isField;
966      }
967
968      // check if POC corresponds to IRAP
969      NalUnitType tmpUnitType = pEncGop->getNalUnitType(pocCurr, lastIDR, isField);
970      if(tmpUnitType >= NAL_UNIT_CODED_SLICE_BLA_W_LP && tmpUnitType <= NAL_UNIT_CODED_SLICE_CRA) // if picture is an IRAP
971      {
972        if(pocCurr%2 == 0 && iGOPid < gopSize-1 && pCfg->getGOPEntry(iGOPid).m_POC == pCfg->getGOPEntry(iGOPid+1).m_POC-1)
973        { // if top field and following picture in enc order is associated bottom field
974          IRAPGOPid = iGOPid;
975          IRAPtoReorder = true;
976          swapIRAPForward = true;
977          break;
978        }
979        if(pocCurr%2 != 0 && iGOPid > 0 && pCfg->getGOPEntry(iGOPid).m_POC == pCfg->getGOPEntry(iGOPid-1).m_POC+1)
980        {
981          // if picture is an IRAP remember to process it first
982          IRAPGOPid = iGOPid;
983          IRAPtoReorder = true;
984          swapIRAPForward = false;
985          break;
986        }
987      }
988    }
989  }
990}
991
992Int EfficientFieldIRAPMapping::adjustGOPid(const Int GOPid)
993{
994  if(IRAPtoReorder)
995  {
996    if(swapIRAPForward)
997    {
998      if(GOPid == IRAPGOPid)
999      {
1000        return IRAPGOPid +1;
1001      }
1002      else if(GOPid == IRAPGOPid +1)
1003      {
1004        return IRAPGOPid;
1005      }
1006    }
1007    else
1008    {
1009      if(GOPid == IRAPGOPid -1)
1010      {
1011        return IRAPGOPid;
1012      }
1013      else if(GOPid == IRAPGOPid)
1014      {
1015        return IRAPGOPid -1;
1016      }
1017    }
1018  }
1019  return GOPid;
1020}
1021
1022Int EfficientFieldIRAPMapping::restoreGOPid(const Int GOPid)
1023{
1024  if(IRAPtoReorder)
1025  {
1026    if(swapIRAPForward)
1027    {
1028      if(GOPid == IRAPGOPid)
1029      {
1030        IRAPtoReorder = false;
1031        return IRAPGOPid +1;
1032      }
1033      else if(GOPid == IRAPGOPid +1)
1034      {
1035        return GOPid -1;
1036      }
1037    }
1038    else
1039    {
1040      if(GOPid == IRAPGOPid)
1041      {
1042        return IRAPGOPid -1;
1043      }
1044      else if(GOPid == IRAPGOPid -1)
1045      {
1046        IRAPtoReorder = false;
1047        return IRAPGOPid;
1048      }
1049    }
1050  }
1051  return GOPid;
1052}
1053
1054
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
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))
1071    {
1072      iCloseRight=iRef;
1073    }
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}
1112#endif
1113
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
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
1158Void TEncGOP::compressPicInGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,
1159                                TComList<TComPicYuv*>& rcListPicYuvRecOut,  std::list<AccessUnit>& accessUnitsInGOP,
1160                                Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE, const Bool printMSSSIM, Int iGOPid )
1161#else
1162Void TEncGOP::compressGOP( Int iPOCLast, Int iNumPicRcvd, TComList<TComPic*>& rcListPic,
1163                           TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsInGOP,
1164#if JVET_F0064_MSSSIM           
1165                           Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE, const Bool printMSSSIM )
1166#else
1167
1168                           Bool isField, Bool isTff, const InputColourSpaceConversion snr_conversion, const Bool printFrameMSE )
1169#endif
1170#endif
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
1217#if !X0038_LAMBDA_FROM_QP_CAPABILITY
1218    UInt uiColDir = calculateCollocatedFromL1Flag(m_pcCfg, iGOPid, m_iGopSize);
1219#endif
1220
1221    /////////////////////////////////////////////////////////////////////////////////////////////////// Initial to start encoding
1222    Int iTimeOffset;
1223    Int pocCurr;
1224    if(iPOCLast == 0) //case first frame or first top field
1225    {
1226      pocCurr=0;
1227      iTimeOffset = 1;
1228    }
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    {
1236      pocCurr = iPOCLast - iNumPicRcvd + m_pcCfg->getGOPEntry(iGOPid).m_POC - ((isField && m_iGopSize>1) ? 1:0);
1237      iTimeOffset = m_pcCfg->getGOPEntry(iGOPid).m_POC;
1238    }
1239
1240    if(pocCurr>=m_pcCfg->getFramesToBeEncoded())
1241    {
1242      if (m_pcCfg->getEfficientFieldIRAPEnabled())
1243      {
1244        iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
1245      }
1246#if NH_MV
1247      delete pcBitstreamRedirect;
1248      return;
1249#else
1250      continue;
1251#endif
1252    }
1253
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 )
1255    {
1256      m_iLastIDR = pocCurr;
1257    }
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();
1261    xGetBuffer( rcListPic, rcListPicYuvRecOut, iNumPicRcvd, iTimeOffset, pcPic, pcPicYuvRecOut, pocCurr, isField );
1262
1263#if REDUCED_ENCODER_MEMORY
1264    pcPic->prepareForReconstruction();
1265
1266#endif
1267    //  Slice data initialization
1268    pcPic->clearSliceBuffer();
1269    pcPic->allocateNewSlice();
1270    m_pcSliceEncoder->setSliceIdx(0);
1271    pcPic->setCurrSliceIdx(0);
1272#if NH_MV
1273    m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, m_pcEncTop->getVPS(), getLayerId(), isField  );
1274#else
1275    m_pcSliceEncoder->initEncSlice ( pcPic, iPOCLast, pocCurr, iGOPid, pcSlice, isField );
1276#endif
1277
1278    pcSlice->setLastIDR(m_iLastIDR);
1279    pcSlice->setSliceIdx(0);
1280#if NH_MV
1281    pcSlice->setRefPicSetInterLayer ( &m_refPicSetInterLayer0, &m_refPicSetInterLayer1 );
1282    pcPic  ->setLayerId     ( getLayerId()   );
1283    pcPic  ->setViewId      ( getViewId()    );
1284#if !NH_3D
1285    pcSlice->setLayerId     ( getLayerId() );
1286    pcSlice->setViewId      ( getViewId()  );
1287    pcSlice->setVPS         ( m_pcEncTop->getVPS() );
1288#else
1289    pcPic  ->setViewIndex   ( getViewIndex() );
1290    pcPic  ->setIsDepth( getIsDepth() );
1291    pcSlice->setCamparaSlice( pcPic->getCodedScale(), pcPic->getCodedOffset() );
1292#endif
1293#endif
1294    //set default slice level flag to the same as SPS level flag
1295    pcSlice->setLFCrossSliceBoundaryFlag(  pcSlice->getPPS()->getLoopFilterAcrossSlicesEnabledFlag()  );
1296#if NH_MV
1297    // Set the nal unit type
1298    pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
1299    if( pcSlice->getSliceType() == B_SLICE )
1300    {
1301      if( m_pcCfg->getGOPEntry( ( pcSlice->getRapPicFlag() && getLayerId() > 0 ) ? MAX_GOP : iGOPid ).m_sliceType == 'P' )
1302      {
1303        pcSlice->setSliceType( P_SLICE );
1304      }
1305    }
1306
1307// To be checked!
1308    if( pcSlice->getSliceType() == B_SLICE )
1309    {
1310      if( m_pcCfg->getGOPEntry( ( pcSlice->getRapPicFlag() && getLayerId() > 0 ) ? MAX_GOP : iGOPid ).m_sliceType == 'I' )
1311      {
1312        pcSlice->setSliceType( I_SLICE );
1313      }
1314    }
1315#else
1316
1317    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='P')
1318    {
1319      pcSlice->setSliceType(P_SLICE);
1320    }
1321    if(pcSlice->getSliceType()==B_SLICE&&m_pcCfg->getGOPEntry(iGOPid).m_sliceType=='I')
1322    {
1323      pcSlice->setSliceType(I_SLICE);
1324    }
1325
1326    // Set the nal unit type
1327    pcSlice->setNalUnitType(getNalUnitType(pocCurr, m_iLastIDR, isField));
1328#endif
1329    if(pcSlice->getTemporalLayerNonReferenceFlag())
1330    {
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)
1334      {
1335        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N);
1336      }
1337      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RADL_R)
1338      {
1339        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N);
1340      }
1341      if(pcSlice->getNalUnitType()==NAL_UNIT_CODED_SLICE_RASL_R)
1342      {
1343        pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N);
1344      }
1345    }
1346    if (m_pcCfg->getEfficientFieldIRAPEnabled())
1347    {
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);
1360    }
1361    // Do decoding refresh marking if any
1362    pcSlice->decodingRefreshMarking(m_pocCRA, m_bRefreshPending, rcListPic, m_pcCfg->getEfficientFieldIRAPEnabled());
1363    m_pcEncTop->selectReferencePictureSet(pcSlice, pocCurr, iGOPid);
1364    if (!m_pcCfg->getEfficientFieldIRAPEnabled())
1365    {
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);
1378    }
1379    if ((pcSlice->checkThatAllRefPicsAreAvailable(rcListPic, pcSlice->getRPS(), false, m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3) != 0) || (pcSlice->isIRAP())
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)
1381      )
1382    {
1383      pcSlice->createExplicitReferencePictureSetFromReference(rcListPic, pcSlice->getRPS(), pcSlice->isIRAP(), m_iLastRecoveryPicPOC, m_pcCfg->getDecodingRefreshType() == 3, m_pcCfg->getEfficientFieldIRAPEnabled());
1384    }
1385
1386    pcSlice->applyReferencePictureSet(rcListPic, pcSlice->getRPS());
1387
1388    if(pcSlice->getTLayer() > 0
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        )
1394    {
1395      if(pcSlice->isTemporalLayerSwitchingPoint(rcListPic) || pcSlice->getSPS()->getTemporalIdNestingFlag())
1396      {
1397        if(pcSlice->getTemporalLayerNonReferenceFlag())
1398        {
1399          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_N);
1400        }
1401        else
1402        {
1403          pcSlice->setNalUnitType(NAL_UNIT_CODED_SLICE_TSA_R);
1404        }
1405      }
1406      else if(pcSlice->isStepwiseTemporalLayerSwitchingPointCandidate(rcListPic))
1407      {
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;
1412          if(lTid==pcSlice->getTLayer())
1413          {
1414            const TComReferencePictureSet* nRPS = pcSlice->getSPS()->getRPSList()->getReferencePictureSet(ii);
1415            for(Int jj=0;jj<nRPS->getNumberOfPictures();jj++)
1416            {
1417              if(nRPS->getUsed(jj))
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)
1424                  {
1425                    break;
1426                  }
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)
1439        {
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        }
1449      }
1450    }
1451    arrangeLongtermPicturesInRPS(pcSlice, rcListPic);
1452    TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification();
1453    refPicListModification->setRefPicListModificationFlagL0(0);
1454    refPicListModification->setRefPicListModificationFlagL1(0);
1455#if NH_MV
1456    if ( pcSlice->getPPS()->getNumExtraSliceHeaderBits() > 0 )
1457    {
1458      // Some more sophisticated algorithm to determine discardable_flag might be added here.
1459      pcSlice->setDiscardableFlag           ( false );
1460    }
1461
1462    const TComVPS*           vps = pcSlice->getVPS();
1463#if NH_3D
1464    Int numDirectRefLayers = vps    ->getNumRefListLayers( getLayerId() );
1465#else
1466    Int numDirectRefLayers = vps    ->getNumDirectRefLayers( getLayerId() );
1467#endif
1468
1469#if NH_3D
1470    pcSlice->setIvPicLists( m_ivPicLists );
1471    Int gopNum = (pcSlice->getRapPicFlag() && getLayerId() > 0) ? MAX_GOP : iGOPid;
1472    GOPEntry gopEntry      = m_pcCfg->getGOPEntry( gopNum );
1473#else
1474    GOPEntry gopEntry      = m_pcCfg->getGOPEntry( (pcSlice->getRapPicFlag() && getLayerId() > 0) ? MAX_GOP : iGOPid );
1475#endif
1476
1477
1478
1479    Bool interLayerPredLayerIdcPresentFlag = false;
1480    if ( getLayerId() > 0 && !vps->getAllRefLayersActiveFlag() && numDirectRefLayers > 0 )
1481    {
1482      pcSlice->setInterLayerPredEnabledFlag ( gopEntry.m_numActiveRefLayerPics > 0 );
1483      if ( pcSlice->getInterLayerPredEnabledFlag() && numDirectRefLayers > 1 )
1484      {
1485        if ( !vps->getMaxOneActiveRefLayerFlag() )
1486        {
1487          pcSlice->setNumInterLayerRefPicsMinus1( gopEntry.m_numActiveRefLayerPics - 1 );
1488        }
1489#if NH_3D
1490        if ( gopEntry.m_numActiveRefLayerPics != vps->getNumRefListLayers( getLayerId() ) )
1491#else
1492        if ( gopEntry.m_numActiveRefLayerPics != vps->getNumDirectRefLayers( getLayerId() ) )
1493#endif
1494        {
1495          interLayerPredLayerIdcPresentFlag = true;
1496          for (Int i = 0; i < gopEntry.m_numActiveRefLayerPics; i++ )
1497          {
1498            pcSlice->setInterLayerPredLayerIdc( i, gopEntry.m_interLayerPredLayerIdc[ i ] );
1499          }
1500        }
1501      }
1502    }
1503    if ( !interLayerPredLayerIdcPresentFlag )
1504    {
1505      for( Int i = 0; i < pcSlice->getNumActiveRefLayerPics(); i++ )
1506      {
1507        pcSlice->setInterLayerPredLayerIdc(i, pcSlice->getRefLayerPicIdc( i ) );
1508      }
1509    }
1510
1511
1512    assert( pcSlice->getNumActiveRefLayerPics() == gopEntry.m_numActiveRefLayerPics );
1513
1514#if NH_3D
1515    if ( m_pcEncTop->decProcAnnexI() )
1516    {
1517      pcSlice->deriveInCmpPredAndCpAvailFlag( );
1518      if ( pcSlice->getInCmpPredAvailFlag() )
1519      {
1520        pcSlice->setInCompPredFlag( gopEntry.m_interCompPredFlag );
1521      }
1522      else
1523      {
1524        if (gopEntry.m_interCompPredFlag )
1525        {
1526          if ( gopNum == MAX_GOP)
1527          {
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() ) );
1529          }
1530          else
1531          {
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() ) );
1533          }
1534
1535          exit(EXIT_FAILURE);
1536        }
1537      }
1538      pcSlice->init3dToolParameters();
1539      pcSlice->checkInCompPredRefLayers();
1540    }
1541    // This needs to be done after initialization of 3D tool parameters.
1542    pcSlice->setMaxNumMergeCand      ( m_pcCfg->getMaxNumMergeCand()   + ( ( pcSlice->getMpiFlag( ) || pcSlice->getIvMvPredFlag( ) || pcSlice->getViewSynthesisPredFlag( )   ) ? 1 : 0 ));
1543#endif
1544
1545    pcSlice->createInterLayerReferencePictureSet( m_ivPicLists, m_refPicSetInterLayer0, m_refPicSetInterLayer1 );
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
1555
1556    xSetRefPicListModificationsMv( tempRefPicLists, pcSlice, iGOPid );
1557#else
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()));
1560#endif
1561    //  Set reference list
1562#if NH_MV
1563    pcSlice->setRefPicList( tempRefPicLists, usedAsLongTerm, numPocTotalCurr );
1564#else
1565    pcSlice->setRefPicList ( rcListPic );
1566#endif
1567#if NH_3D
1568    pcSlice->setDefaultRefView();
1569    //GT: This seems to be broken when layerId in vps is not equal to layerId in nuh
1570    pcSlice->setARPStepNum(m_ivPicLists);
1571    pcSlice->setICEnableCandidate( m_aICEnableCandidate );
1572    pcSlice->setICEnableNum( m_aICEnableNum );
1573#endif
1574
1575    //  Slice info. refinement
1576#if NH_MV
1577    if ( pcSlice->getSliceType() == B_SLICE )
1578    {
1579      if( m_pcCfg->getGOPEntry( ( pcSlice->getRapPicFlag() == true && getLayerId() > 0 ) ? MAX_GOP : iGOPid ).m_sliceType == 'P' )
1580      {
1581        pcSlice->setSliceType( P_SLICE );
1582      }
1583    }
1584#else
1585    if ( (pcSlice->getSliceType() == B_SLICE) && (pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0) )
1586    {
1587      pcSlice->setSliceType ( P_SLICE );
1588    }
1589#endif
1590    pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
1591
1592    if (pcSlice->getSliceType() == B_SLICE)
1593    {
1594#if X0038_LAMBDA_FROM_QP_CAPABILITY
1595      const UInt uiColFromL0 = calculateCollocatedFromL0Flag(pcSlice);
1596      pcSlice->setColFromL0Flag(uiColFromL0);
1597#else
1598      pcSlice->setColFromL0Flag(1-uiColDir);
1599#endif
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++)
1605      {
1606        if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )
1607        {
1608          bLowDelay = false;
1609        }
1610      }
1611      for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)
1612      {
1613        if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )
1614        {
1615          bLowDelay = false;
1616        }
1617      }
1618
1619      pcSlice->setCheckLDC(bLowDelay);
1620    }
1621    else
1622    {
1623      pcSlice->setCheckLDC(true);
1624    }
1625
1626#if !X0038_LAMBDA_FROM_QP_CAPABILITY
1627    uiColDir = 1-uiColDir;
1628#endif
1629
1630    //-------------------------------------------------------------
1631    pcSlice->setRefPOCList();
1632
1633    pcSlice->setList1IdxToList0Idx();
1634#if NH_3D
1635    if(pcSlice->getLayerId())
1636      pcSlice->generateAlterRefforTMVP();
1637#endif
1638
1639    if (m_pcEncTop->getTMVPModeId() == 2)
1640    {
1641      if (iGOPid == 0) // first picture in SOP (i.e. forward B)
1642      {
1643        pcSlice->setEnableTMVPFlag(0);
1644      }
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    }
1659#if NH_MV
1660    if( pcSlice->getIdrPicFlag() )
1661    {
1662      pcSlice->setEnableTMVPFlag(0);
1663    }
1664#endif
1665
1666#if NH_3D_VSO
1667  // Should be moved to TEncTop !!!
1668  Bool bUseVSO = m_pcEncTop->getUseVSO();
1669
1670  TComRdCost* pcRdCost = m_pcEncTop->getRdCost();
1671
1672  pcRdCost->setUseVSO( bUseVSO );
1673
1674  // SAIT_VSO_EST_A0033
1675  pcRdCost->setUseEstimatedVSD( m_pcEncTop->getUseEstimatedVSD() );
1676
1677  if ( bUseVSO )
1678  {
1679    Int iVSOMode = m_pcEncTop->getVSOMode();
1680    pcRdCost->setVSOMode( iVSOMode  );
1681    pcRdCost->setAllowNegDist( m_pcEncTop->getAllowNegDist() );
1682
1683    // SAIT_VSO_EST_A0033
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 ) );
1689
1690    // LGE_WVSO_A0119
1691    Bool bUseWVSO  = m_pcEncTop->getUseWVSO();
1692    pcRdCost->setUseWVSO( bUseWVSO );
1693
1694  }
1695#endif
1696    // set adaptive search range for non-intra-slices
1697    if (m_pcCfg->getUseASR() && pcSlice->getSliceType()!=I_SLICE)
1698    {
1699      m_pcSliceEncoder->setSearchRange(pcSlice);
1700    }
1701
1702    Bool bGPBcheck=false;
1703    if ( pcSlice->getSliceType() == B_SLICE)
1704    {
1705      if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) )
1706      {
1707        bGPBcheck=true;
1708        Int i;
1709        for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ )
1710        {
1711          if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) )
1712          {
1713            bGPBcheck=false;
1714            break;
1715          }
1716        }
1717      }
1718    }
1719    if(bGPBcheck)
1720    {
1721      pcSlice->setMvdL1ZeroFlag(true);
1722    }
1723    else
1724    {
1725      pcSlice->setMvdL1ZeroFlag(false);
1726    }
1727
1728
1729    Double lambda            = 0.0;
1730    Int actualHeadBits       = 0;
1731    Int actualTotalBits      = 0;
1732    Int estimatedBits        = 0;
1733    Int tmpBitsBeforeWriting = 0;
1734    if ( m_pcCfg->getUseRateCtrl() ) // TODO: does this work with multiple slices and slice-segments?
1735    {
1736      Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
1737      if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
1738      {
1739        frameLevel = 0;
1740      }
1741      m_pcRateCtrl->initRCPic( frameLevel );
1742      estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits();
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
1751      if (m_pcRateCtrl->getCpbSaturationEnabled() && frameLevel != 0)
1752      {
1753        Int estimatedCpbFullness = m_pcRateCtrl->getCpbState() + m_pcRateCtrl->getBufferingRate();
1754
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
1763        if (estimatedCpbFullness - estimatedBits < m_pcRateCtrl->getRCPic()->getLowerBound())
1764        {
1765          estimatedBits = max(200, estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound());
1766        }
1767        m_pcRateCtrl->getRCPic()->setTargetBits(estimatedBits);
1768      }
1769
1770      Int sliceQP = m_pcCfg->getInitialQP();
1771      if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified
1772      {
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 );
1780      }
1781      else if ( frameLevel == 0 )   // intra case, but use the model
1782      {
1783        m_pcSliceEncoder->calCostSliceI(pcPic); // TODO: This only analyses the first slice segment - what about the others?
1784
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 );
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
1802            if (estimatedCpbFullness - bits < m_pcRateCtrl->getRCPic()->getLowerBound())
1803            {
1804              bits = estimatedCpbFullness - m_pcRateCtrl->getRCPic()->getLowerBound();
1805            }
1806          }
1807
1808          if ( bits < 200 )
1809          {
1810            bits = 200;
1811          }
1812          m_pcRateCtrl->getRCPic()->setTargetBits( bits );
1813        }
1814
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 );
1819      }
1820      else    // normal case
1821      {
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
1832        list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
1833        lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
1834        sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
1835#if KWU_RC_MADPRED_E0227
1836        }
1837#endif
1838      }
1839
1840      sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, sliceQP );
1841      m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );
1842
1843      m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda );
1844    }
1845
1846    UInt uiNumSliceSegments = 1;
1847
1848#if NH_3D
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.
1850      {
1851        Int iColPoc = pcSlice->getRefPOC(RefPicList(1 - pcSlice->getColFromL0Flag()), pcSlice->getColRefIdx());
1852        pcPic->setNumDdvCandPics(pcPic->getDisCandRefPictures(iColPoc));
1853      }
1854      pcSlice->setDepthToDisparityLUTs();
1855
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      }
1860
1861      if(pcSlice->getIsDepth())
1862      {
1863        pcPic->checkTextureRef();
1864      }
1865#endif
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)
1873    {
1874      const UInt numberOfCtusInFrame=pcPic->getPicSym()->getNumberOfCtusInFrame();
1875      pcSlice->setSliceCurStartCtuTsAddr( 0 );
1876      pcSlice->setSliceSegmentCurStartCtuTsAddr( 0 );
1877
1878      for(UInt nextCtuTsAddr = 0; nextCtuTsAddr < numberOfCtusInFrame; )
1879      {
1880        m_pcSliceEncoder->precompressSlice( pcPic );
1881        m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
1882
1883        const UInt curSliceSegmentEnd = pcSlice->getSliceSegmentCurEndCtuTsAddr();
1884        if (curSliceSegmentEnd < numberOfCtusInFrame)
1885        {
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 ++;
1910        }
1911        nextCtuTsAddr = curSliceSegmentEnd;
1912      }
1913    }
1914
1915    duData.clear();
1916    pcSlice = pcPic->getSlice(0);
1917
1918    // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
1919    if( pcSlice->getSPS()->getUseSAO() && m_pcCfg->getSaoCtuBoundary() )
1920    {
1921      m_pcSAO->getPreDBFStatistics(pcPic);
1922    }
1923
1924    //-- Loop filter
1925    Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag();
1926    m_pcLoopFilter->setCfg(bLFCrossTileBoundary);
1927    if ( m_pcCfg->getDeblockingFilterMetric() )
1928    {
1929      if ( m_pcCfg->getDeblockingFilterMetric()==2 )
1930      {
1931        applyDeblockingFilterParameterSelection(pcPic, uiNumSliceSegments, iGOPid);
1932      }
1933      else
1934      {
1935      applyDeblockingFilterMetric(pcPic, uiNumSliceSegments);
1936      }
1937    }
1938    m_pcLoopFilter->loopFilterPic( pcPic );
1939
1940    /////////////////////////////////////////////////////////////////////////////////////////////////// File writing
1941    // Set entropy coder
1942    m_pcEntropyCoder->setEntropyCoder   ( m_pcCavlcCoder );
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)
1953    {
1954#if NH_MV
1955      if ( m_layerId == pcSlice->getSPS()->getLayerId() )
1956      {
1957        m_pcEncTop->setParamSetChanged(pcSlice->getSPS()->getSPSId(), false );
1958      }
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());
1967#endif
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
1974
1975    if (writePS)
1976#else
1977    actualTotalBits += xWriteParameterSets(accessUnit, pcSlice, m_bSeqFirst);
1978
1979    if ( m_bSeqFirst )
1980#endif
1981    {
1982      // create prefix SEI messages at the beginning of the sequence
1983      assert(leadingSeiMessages.empty());
1984      xCreateIRAPLeadingSEIMessages(leadingSeiMessages, pcSlice->getSPS(), pcSlice->getPPS());
1985
1986      m_bSeqFirst = false;
1987    }
1988    if (m_pcCfg->getAccessUnitDelimiter())
1989    {
1990      xWriteAccessUnitDelimiter(accessUnit, pcSlice);
1991    }
1992
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
1998#if NH_MV
1999    m_seiEncoder.createAnnexFGISeiMessages( leadingSeiMessages, pcSlice );
2000#endif
2001
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())
2008    {
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);
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());
2020      m_pcSAO->PCMLFDisableProcess(pcPic);
2021      m_pcEncTop->getRDGoOnSbacCoder()->setBitstream(NULL);
2022
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    }
2031
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)
2035
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)
2040      {
2041        pcSlice->checkColRefIdx(sliceIdxCount, pcPic);
2042      }
2043      pcPic->setCurrSliceIdx(sliceIdxCount);
2044      m_pcSliceEncoder->setSliceIdx(sliceIdxCount);
2045
2046      pcSlice->setRPS(pcPic->getSlice(0)->getRPS());
2047      pcSlice->setRPSidx(pcPic->getSlice(0)->getRPSidx());
2048
2049      for ( UInt ui = 0 ; ui < numSubstreams; ui++ )
2050      {
2051        substreamsOut[ui].clear();
2052      }
2053
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);
2063
2064      pcSlice->setNoRaslOutputFlag(false);
2065      if (pcSlice->isIRAP())
2066      {
2067        if (pcSlice->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && pcSlice->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP)
2068        {
2069          pcSlice->setNoRaslOutputFlag(true);
2070        }
2071        //the inference for NoOutputPriorPicsFlag
2072        // KJS: This cannot happen at the encoder
2073        if (!m_bFirst && pcSlice->isIRAP() && pcSlice->getNoRaslOutputFlag())
2074        {
2075          if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
2076          {
2077            pcSlice->setNoOutputPriorPicsFlag(true);
2078          }
2079        }
2080      }
2081
2082      pcSlice->setEncCABACTableIdx(m_pcSliceEncoder->getEncCABACTableIdx());
2083
2084      tmpBitsBeforeWriting = m_pcEntropyCoder->getNumberOfWrittenBits();
2085      m_pcEntropyCoder->encodeSliceHeader(pcSlice);
2086      actualHeadBits += ( m_pcEntropyCoder->getNumberOfWrittenBits() - tmpBitsBeforeWriting );
2087
2088      pcSlice->setFinalized(true);
2089
2090      pcSlice->clearSubstreamSizes(  );
2091      {
2092        UInt numBinsCoded = 0;
2093        m_pcSliceEncoder->encodeSlice(pcPic, &(substreamsOut[0]), numBinsCoded);
2094        binCountsInNalUnits+=numBinsCoded;
2095      }
2096
2097      {
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++ )
2110        {
2111          pcOut->addSubstream(&(substreamsOut[ui+numZeroSubstreamsAtStartOfSlice]));
2112        }
2113      }
2114
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)
2125      {
2126        nalu.m_Bitstream.writeAlignZero();
2127        accessUnit.push_back(new NALUnitEBSP(nalu));
2128      }
2129
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() ) )
2135      {
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;
2146      }
2147    } // end iteration over slices
2148
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
2152      pcPic->compressMotion(2);
2153#else
2154    pcPic->compressMotion();
2155#endif
2156#if NH_MV
2157      m_pocLastCoded = pcPic->getPOC();
2158#endif
2159
2160    //-- For time output for each slice
2161    Double dEncTime = (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC;
2162
2163    std::string digestStr;
2164    if (m_pcCfg->getDecodedPictureHashSEIType()!=HASHTYPE_NONE)
2165    {
2166      SEIDecodedPictureHash *decodedPictureHashSei = new SEIDecodedPictureHash();
2167      m_seiEncoder.initDecodedPictureHashSEI(decodedPictureHashSei, pcPic, digestStr, pcSlice->getSPS()->getBitDepths());
2168      trailingSeiMessages.push_back(decodedPictureHashSei);
2169    }
2170
2171    m_pcCfg->setEncodedFlag(iGOPid, true);
2172
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());
2189
2190    printHash(m_pcCfg->getDecodedPictureHashSEIType(), digestStr);
2191
2192    if ( m_pcCfg->getUseRateCtrl() )
2193    {
2194      Double avgQP     = m_pcRateCtrl->getRCPic()->calAverageQP();
2195      Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();
2196      if ( avgLambda < 0.0 )
2197      {
2198        avgLambda = lambda;
2199      }
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 )
2206      {
2207        m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );
2208      }
2209      else    // for intra picture, the estimated bits are used to update the current status in the GOP
2210      {
2211        m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );
2212      }
2213      if (m_pcRateCtrl->getCpbSaturationEnabled())
2214      {
2215        m_pcRateCtrl->updateCpbState(actualTotalBits);
2216        printf(" [CPB %6d bits]", m_pcRateCtrl->getCpbState());
2217      }
2218    }
2219
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);
2227
2228    pcPic->getPicYuvRec()->copyToPic(pcPicYuvRecOut);
2229
2230    pcPic->setReconMark   ( true );
2231#if NH_MV
2232      TComSlice::markIvRefPicsAsShortTerm( m_refPicSetInterLayer0, m_refPicSetInterLayer1 );
2233      std::vector<Int> temp;
2234      TComSlice::markCurrPic( pcPic );
2235#endif
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);
2242
2243    if (m_pcCfg->getEfficientFieldIRAPEnabled())
2244    {
2245    iGOPid=effFieldIRAPMap.restoreGOPid(iGOPid);
2246    }
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
2256  } // iGOPid-loop
2257
2258  delete pcBitstreamRedirect;
2259
2260#if !NH_MV
2261  assert ( (m_iNumPicCoded == iNumPicRcvd) );
2262#endif
2263}
2264
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
2268Void TEncGOP::printOutSummary(UInt uiNumAllPicCoded, Bool isField, const Bool printMSEBasedSNR, const Bool printSequenceMSE, const BitDepths &bitDepths)
2269#endif
2270{
2271  assert (uiNumAllPicCoded == m_gcAnalyzeAll.getNumPic());
2272
2273
2274  //--CFG_KDY
2275  const Int rateMultiplier=(isField?2:1);
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());
2280  const ChromaFormat chFmt = m_pcCfg->getChromaFormatIdc();
2281
2282
2283#if JVET_F0064_MSSSIM
2284  //-- all
2285#if NH_MV
2286  printf( "\n\nSUMMARY -------------------------------------------- LayerId %2d\n", getLayerId() );
2287#else
2288  printf( "\n\nSUMMARY --------------------------------------------------------\n" );
2289#endif
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
2308  m_gcAnalyzeAll.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2309
2310  printf( "\n\nI Slices--------------------------------------------------------\n" );
2311  m_gcAnalyzeI.printOut('i', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2312
2313  printf( "\n\nP Slices--------------------------------------------------------\n" );
2314  m_gcAnalyzeP.printOut('p', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2315
2316  printf( "\n\nB Slices--------------------------------------------------------\n" );
2317  m_gcAnalyzeB.printOut('b', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2318#endif
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
2331  if(isField)
2332  {
2333    //-- interlaced summary
2334    m_gcAnalyzeAll_in.setFrmRate( m_pcCfg->getFrameRate() / (Double)m_pcCfg->getTemporalSubsampleRatio());
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
2338    printf( "\n\nSUMMARY INTERLACED ---------------------------------------------\n" );
2339#if JVET_F0064_MSSSIM
2340    m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, printMSSSIM, bitDepths);
2341#else
2342    m_gcAnalyzeAll_in.printOut('a', chFmt, printMSEBasedSNR, printSequenceMSE, bitDepths);
2343#endif
2344
2345    if (!m_pcCfg->getSummaryOutFilename().empty())
2346    {
2347      m_gcAnalyzeAll_in.printSummary(chFmt, printSequenceMSE, bitDepths, m_pcCfg->getSummaryOutFilename());
2348    }
2349  }
2350
2351  printf("\nRVM: %.3lf\n" , xCalculateRVM());
2352}
2353
2354#if NH_3D_VSO
2355Void TEncGOP::preLoopFilterPicAll( TComPic* pcPic, Dist64& ruiDist )
2356#else
2357Void TEncGOP::preLoopFilterPicAll( TComPic* pcPic, UInt64& ruiDist )
2358#endif
2359{
2360  Bool bCalcDist = false;
2361  m_pcLoopFilter->setCfg(m_pcCfg->getLFCrossTileBoundaryFlag());
2362  m_pcLoopFilter->loopFilterPic( pcPic );
2363
2364  if (!bCalcDist)
2365  {
2366    ruiDist = xFindDistortionFrame(pcPic->getPicYuvOrg(), pcPic->getPicYuvRec(), pcPic->getPicSym()->getSPS().getBitDepths());
2367  }
2368}
2369
2370// ====================================================================================================================
2371// Protected member functions
2372// ====================================================================================================================
2373
2374
2375Void TEncGOP::xInitGOP( Int iPOCLast, Int iNumPicRcvd, Bool isField )
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);
2388
2389  return;
2390}
2391
2392
2393Void TEncGOP::xGetBuffer( TComList<TComPic*>&      rcListPic,
2394                         TComList<TComPicYuv*>&    rcListPicYuvRecOut,
2395                         Int                       iNumPicRcvd,
2396                         Int                       iTimeOffset,
2397                         TComPic*&                 rpcPic,
2398                         TComPicYuv*&              rpcPicYuvRecOut,
2399                         Int                       pocCurr,
2400                         Bool                      isField)
2401{
2402  Int i;
2403  //  Rec. output
2404  TComList<TComPicYuv*>::iterator     iterPicYuvRec = rcListPicYuvRecOut.end();
2405
2406  if (isField && pocCurr > 1 && m_iGopSize!=1)
2407  {
2408    iTimeOffset--;
2409  }
2410
2411  for ( i = 0; i < (iNumPicRcvd - iTimeOffset + 1); i++ )
2412  {
2413    iterPicYuvRec--;
2414  }
2415
2416  rpcPicYuvRecOut = *(iterPicYuvRec);
2417
2418  //  Current pic.
2419  TComList<TComPic*>::iterator        iterPic       = rcListPic.begin();
2420  while (iterPic != rcListPic.end())
2421  {
2422    rpcPic = *(iterPic);
2423    rpcPic->setCurrSliceIdx(0);
2424    if (rpcPic->getPOC() == pocCurr)
2425    {
2426      break;
2427    }
2428    iterPic++;
2429  }
2430
2431  assert (rpcPic != NULL);
2432  assert (rpcPic->getPOC() == pocCurr);
2433
2434  return;
2435}
2436
2437#if NH_3D_VSO
2438Dist64 TEncGOP::xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1, const BitDepths &bitDepths)
2439#else
2440UInt64 TEncGOP::xFindDistortionFrame (TComPicYuv* pcPic0, TComPicYuv* pcPic1, const BitDepths &bitDepths)
2441#endif
2442{
2443#if NH_3D_VSO
2444  Dist64  uiTotalDiff = 0;
2445#else
2446  UInt64  uiTotalDiff = 0;
2447#endif
2448
2449  for(Int chan=0; chan<pcPic0 ->getNumberValidComponents(); chan++)
2450  {
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++ )
2461    {
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;
2469    }
2470  }
2471
2472  return uiTotalDiff;
2473}
2474
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 )
2477{
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
2484
2485  //In case of field coding, compute the interlaced PSNR for both fields
2486  if(isField)
2487  {
2488    Bool bothFieldsAreEncoded = false;
2489    Int correspondingFieldPOC = pcPic->getPOC();
2490    Int currentPicGOPPoc = m_pcCfg->getGOPEntry(iGOPid).m_POC;
2491    if(pcPic->getPOC() == 0)
2492    {
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;
2497    }
2498    else if(pcPic->getPOC() == 1)
2499    {
2500      // if we are at POC 1, POC 0 has been encoded for sure
2501      correspondingFieldPOC = 0;
2502      bothFieldsAreEncoded = true;
2503    }
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      {
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
2543      }
2544      else
2545      {
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
2551      }
2552    }
2553  }
2554}
2555
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
2561{
2562  Double  dPSNR[MAX_NUM_COMPONENT];
2563
2564  for(Int i=0; i<MAX_NUM_COMPONENT; i++)
2565  {
2566    dPSNR[i]=0.0;
2567  }
2568
2569  TComPicYuv cscd;
2570  if (conversion!=IPCOLOURSPACE_UNCHANGED)
2571  {
2572    cscd.createWithoutCUInfo(pcPicD->getWidth(COMPONENT_Y), pcPicD->getHeight(COMPONENT_Y), pcPicD->getChromaFormat() );
2573    TVideoIOYuv::ColourSpaceConvert(*pcPicD, cscd, conversion, false);
2574  }
2575  TComPicYuv &picd=(conversion==IPCOLOURSPACE_UNCHANGED)?*pcPicD : cscd;
2576
2577  //===== calculate PSNR =====
2578  Double MSEyuvframe[MAX_NUM_COMPONENT] = {0, 0, 0};
2579
2580  for(Int chan=0; chan<pcPicD->getNumberValidComponents(); chan++)
2581  {
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++ )
2596    {
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;
2604    }
2605#if NH_3D_VSO
2606#if H_3D_VSO_SYNTH_DIST_OUT
2607  if ( m_pcRdCost->getUseRenModel() )
2608  {
2609    unsigned int maxval = 255 * (1<<(g_uiBitDepth + g_uiBitIncrement -8));
2610    Double fRefValueY = (double) maxval * maxval * iSize;
2611    Double fRefValueC = fRefValueY / 4.0;
2612    TRenModel*  pcRenModel = m_pcEncTop->getEncTop()->getRenModel();
2613    Int64 iDistVSOY, iDistVSOU, iDistVSOV;
2614    pcRenModel->getTotalSSE( iDistVSOY, iDistVSOU, iDistVSOV );
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
2620  {
2621#endif
2622#endif
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);
2627  }
2628
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
2656#if NH_3D_VSO
2657#if H_3D_VSO_SYNTH_DIST_OUT
2658}
2659#endif
2660#endif
2661  /* calculate the size of the access unit, excluding:
2662   *  - SEI NAL units
2663   */
2664  UInt numRBSPBytes = 0;
2665  for (AccessUnit::const_iterator it = accessUnit.begin(); it != accessUnit.end(); it++)
2666  {
2667    UInt numRBSPBytes_nal = UInt((*it)->m_nalUnitData.str().size());
2668    if (m_pcCfg->getSummaryVerboseness() > 0)
2669    {
2670    printf("*** %6s numBytesInNALunit: %u\n", nalUnitTypeToString((*it)->m_nalUnitType), numRBSPBytes_nal);
2671    }
2672    if ((*it)->m_nalUnitType != NAL_UNIT_PREFIX_SEI && (*it)->m_nalUnitType != NAL_UNIT_SUFFIX_SEI)
2673    {
2674      numRBSPBytes += numRBSPBytes_nal;
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      }
2684    }
2685  }
2686
2687  UInt uibits = numRBSPBytes * 8;
2688  m_vRVM_RP.push_back( uibits );
2689
2690  //===== add PSNR =====
2691#if JVET_F0064_MSSSIM
2692  m_gcAnalyzeAll.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2693#else
2694  m_gcAnalyzeAll.addResult (dPSNR, (Double)uibits, MSEyuvframe);
2695#endif
2696#if EXTENSION_360_VIDEO
2697  m_ext360.addResult(m_gcAnalyzeAll);
2698#endif
2699
2700  TComSlice*  pcSlice = pcPic->getSlice(0);
2701  if (pcSlice->isIntra())
2702  {
2703#if JVET_F0064_MSSSIM
2704    m_gcAnalyzeI.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2705#else
2706    m_gcAnalyzeI.addResult (dPSNR, (Double)uibits, MSEyuvframe);
2707#endif
2708#if EXTENSION_360_VIDEO
2709    m_ext360.addResult(m_gcAnalyzeI);
2710#endif
2711    *PSNR_Y = dPSNR[COMPONENT_Y];
2712  }
2713  if (pcSlice->isInterP())
2714  {
2715#if JVET_F0064_MSSSIM
2716    m_gcAnalyzeP.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2717#else
2718    m_gcAnalyzeP.addResult (dPSNR, (Double)uibits, MSEyuvframe);
2719#endif
2720#if EXTENSION_360_VIDEO
2721    m_ext360.addResult(m_gcAnalyzeP);
2722#endif
2723    *PSNR_Y = dPSNR[COMPONENT_Y];
2724  }
2725  if (pcSlice->isInterB())
2726  {
2727#if JVET_F0064_MSSSIM
2728    m_gcAnalyzeB.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
2729#else
2730    m_gcAnalyzeB.addResult (dPSNR, (Double)uibits, MSEyuvframe);
2731#endif
2732#if EXTENSION_360_VIDEO
2733    m_ext360.addResult(m_gcAnalyzeB);
2734#endif
2735    *PSNR_Y = dPSNR[COMPONENT_Y];
2736  }
2737
2738  TChar c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B');
2739  if (!pcSlice->isReferenced())
2740  {
2741    c += 32;
2742  }
2743
2744#if ADAPTIVE_QP_SELECTION
2745#if NH_MV
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",
2756         pcSlice->getPOC(),
2757         pcSlice->getTLayer(),
2758         c,
2759         pcSlice->getSliceQpBase(),
2760         pcSlice->getSliceQp(),
2761         uibits );
2762#endif
2763#else
2764#if NH_MV
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",
2774         pcSlice->getPOC()-pcSlice->getLastIDR(),
2775         pcSlice->getTLayer(),
2776         c,
2777         pcSlice->getSliceQp(),
2778         uibits );
2779#endif
2780#endif
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
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
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  }
2796#if EXTENSION_360_VIDEO
2797  m_ext360.printPerPOCInfo();
2798#endif
2799  printf(" [ET %5.0f ]", dEncTime );
2800
2801  // printf(" [WP %d]", pcSlice->getUseWeightedPrediction());
2802
2803  for (Int iRefList = 0; iRefList < 2; iRefList++)
2804  {
2805    printf(" [L%d ", iRefList);
2806    for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++)
2807    {
2808#if NH_MV
2809      if( pcSlice->getLayerId() != pcSlice->getRefLayerId( RefPicList(iRefList), iRefIndex ) )
2810      {
2811        printf( "V%d ", pcSlice->getRefLayerId( RefPicList(iRefList), iRefIndex ) );
2812      }
2813      else
2814      {
2815#endif
2816      printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)-pcSlice->getLastIDR());
2817#if NH_MV
2818      }
2819#endif
2820    }
2821    printf("]");
2822  }
2823
2824  cscd.destroy();
2825}
2826
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
3000Void TEncGOP::xCalculateInterlacedAddPSNR( TComPic* pcPicOrgFirstField, TComPic* pcPicOrgSecondField,
3001                                           TComPicYuv* pcPicRecFirstField, TComPicYuv* pcPicRecSecondField,
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
3007{
3008
3009#if  NH_MV
3010  assert( 0 ); // Field coding and MV need to be aligned.
3011#else
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++)
3019  {
3020    dPSNR[i]=0.0;
3021  }
3022
3023  TComPicYuv cscd[2 /* first/second field */];
3024  if (conversion!=IPCOLOURSPACE_UNCHANGED)
3025  {
3026    for(UInt fieldNum=0; fieldNum<2; fieldNum++)
3027    {
3028      TComPicYuv &reconField=*(apcPicRecFields[fieldNum]);
3029      cscd[fieldNum].createWithoutCUInfo(reconField.getWidth(COMPONENT_Y), reconField.getHeight(COMPONENT_Y), reconField.getChromaFormat() );
3030      TVideoIOYuv::ColourSpaceConvert(reconField, cscd[fieldNum], conversion, false);
3031      apcPicRecFields[fieldNum]=cscd+fieldNum;
3032    }
3033  }
3034
3035  //===== calculate PSNR =====
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++)
3042  {
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++)
3054    {
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      }
3073    }
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);
3078  }
3079
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
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 =====
3117#if JVET_F0064_MSSSIM
3118  m_gcAnalyzeAll_in.addResult (dPSNR, (Double)uibits, MSEyuvframe, MSSSIM);
3119#else
3120  m_gcAnalyzeAll_in.addResult (dPSNR, (Double)uibits, MSEyuvframe);
3121#endif
3122
3123  *PSNR_Y = dPSNR[COMPONENT_Y];
3124
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] );
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
3132  if (printFrameMSE)
3133  {
3134    printf(" [Y MSE %6.4lf  U MSE %6.4lf  V MSE %6.4lf]", MSEyuvframe[COMPONENT_Y], MSEyuvframe[COMPONENT_Cb], MSEyuvframe[COMPONENT_Cr] );
3135  }
3136
3137  for(UInt fieldNum=0; fieldNum<2; fieldNum++)
3138  {
3139    cscd[fieldNum].destroy();
3140  }
3141#endif
3142}
3143
3144/** Function for deciding the nal_unit_type.
3145 * \param pocCurr POC of the current picture
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
3149 * This function checks the configuration and returns the appropriate nal_unit_type for the picture.
3150 */
3151NalUnitType TEncGOP::getNalUnitType(Int pocCurr, Int lastIDR, Bool isField)
3152{
3153  if (pocCurr == 0)
3154  {
3155    return NAL_UNIT_CODED_SLICE_IDR_W_RADL;
3156  }
3157
3158  if(m_pcCfg->getEfficientFieldIRAPEnabled() && isField && pocCurr == 1)
3159  {
3160    // to avoid the picture becoming an IRAP
3161    return NAL_UNIT_CODED_SLICE_TRAIL_R;
3162  }
3163
3164  if(m_pcCfg->getDecodingRefreshType() != 3 && (pocCurr - isField) % m_pcCfg->getIntraPeriod() == 0)
3165  {
3166    if (m_pcCfg->getDecodingRefreshType() == 1)
3167    {
3168      return NAL_UNIT_CODED_SLICE_CRA;
3169    }
3170    else if (m_pcCfg->getDecodingRefreshType() == 2)
3171    {
3172      return NAL_UNIT_CODED_SLICE_IDR_W_RADL;
3173    }
3174  }
3175  if(m_pocCRA>0)
3176  {
3177    if(pocCurr<m_pocCRA)
3178    {
3179      // All leading pictures are being marked as TFD pictures here since current encoder uses all
3180      // reference pictures while encoding leading pictures. An encoder can ensure that a leading
3181      // picture can be still decodable when random accessing to a CRA/CRANT/BLA/BLANT picture by
3182      // controlling the reference pictures used for encoding that leading picture. Such a leading
3183      // picture need not be marked as a TFD picture.
3184      return NAL_UNIT_CODED_SLICE_RASL_R;
3185    }
3186  }
3187  if (lastIDR>0)
3188  {
3189    if (pocCurr < lastIDR)
3190    {
3191      return NAL_UNIT_CODED_SLICE_RADL_R;
3192    }
3193  }
3194  return NAL_UNIT_CODED_SLICE_TRAIL_R;
3195}
3196
3197
3198Double TEncGOP::xCalculateRVM()
3199{
3200  Double dRVM = 0;
3201
3202  if( m_pcCfg->getGOPSize() == 1 && m_pcCfg->getIntraPeriod() != 1 && m_pcCfg->getFramesToBeEncoded() > RVM_VCEGAM10_M * 2 )
3203  {
3204    // calculate RVM only for lowdelay configurations
3205    std::vector<Double> vRL , vB;
3206    size_t N = m_vRVM_RP.size();
3207    vRL.resize( N );
3208    vB.resize( N );
3209
3210    Int i;
3211    Double dRavg = 0 , dBavg = 0;
3212    vB[RVM_VCEGAM10_M] = 0;
3213    for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ )
3214    {
3215      vRL[i] = 0;
3216      for( Int j = i - RVM_VCEGAM10_M ; j <= i + RVM_VCEGAM10_M - 1 ; j++ )
3217      {
3218        vRL[i] += m_vRVM_RP[j];
3219      }
3220      vRL[i] /= ( 2 * RVM_VCEGAM10_M );
3221      vB[i] = vB[i-1] + m_vRVM_RP[i] - vRL[i];
3222      dRavg += m_vRVM_RP[i];
3223      dBavg += vB[i];
3224    }
3225
3226    dRavg /= ( N - 2 * RVM_VCEGAM10_M );
3227    dBavg /= ( N - 2 * RVM_VCEGAM10_M );
3228
3229    Double dSigamB = 0;
3230    for( i = RVM_VCEGAM10_M + 1 ; i < N - RVM_VCEGAM10_M + 1 ; i++ )
3231    {
3232      Double tmp = vB[i] - dBavg;
3233      dSigamB += tmp * tmp;
3234    }
3235    dSigamB = sqrt( dSigamB / ( N - 2 * RVM_VCEGAM10_M ) );
3236
3237    Double f = sqrt( 12.0 * ( RVM_VCEGAM10_M - 1 ) / ( RVM_VCEGAM10_M + 1 ) );
3238
3239    dRVM = dSigamB / dRavg * f;
3240  }
3241
3242  return( dRVM );
3243}
3244/** Attaches the input bitstream to the stream in the output NAL unit
3245    Updates rNalu to contain concatenated bitstream. rpcBitstreamRedirect is cleared at the end of this function call.
3246 *  \param codedSliceData contains the coded slice data (bitstream) to be concatenated to rNalu
3247 *  \param rNalu          target NAL unit
3248 */
3249Void TEncGOP::xAttachSliceDataToNalUnit (OutputNALUnit& rNalu, TComOutputBitstream* codedSliceData)
3250{
3251  // Byte-align
3252  rNalu.m_Bitstream.writeByteAlignment();   // Slice header byte-alignment
3253
3254  // Perform bitstream concatenation
3255  if (codedSliceData->getNumberOfWrittenBits() > 0)
3256  {
3257    rNalu.m_Bitstream.addSubstream(codedSliceData);
3258  }
3259
3260  m_pcEntropyCoder->setBitstream(&rNalu.m_Bitstream);
3261
3262  codedSliceData->clear();
3263}
3264
3265// Function will arrange the long-term pictures in the decreasing order of poc_lsb_lt,
3266// and among the pictures with the same lsb, it arranges them in increasing delta_poc_msb_cycle_lt value
3267Void TEncGOP::arrangeLongtermPicturesInRPS(TComSlice *pcSlice, TComList<TComPic*>& rcListPic)
3268{
3269  if(pcSlice->getRPS()->getNumberOfLongtermPictures() == 0)
3270  {
3271    return;
3272  }
3273  // we can only modify the local RPS!
3274  assert (pcSlice->getRPSidx()==-1);
3275  TComReferencePictureSet *rps = pcSlice->getLocalRPS();
3276
3277  // Arrange long-term reference pictures in the correct order of LSB and MSB,
3278  // and assign values for pocLSBLT and MSB present flag
3279  Int longtermPicsPoc[MAX_NUM_REF_PICS], longtermPicsLSB[MAX_NUM_REF_PICS], indices[MAX_NUM_REF_PICS];
3280  Int longtermPicsMSB[MAX_NUM_REF_PICS];
3281  Bool mSBPresentFlag[MAX_NUM_REF_PICS];
3282  ::memset(longtermPicsPoc, 0, sizeof(longtermPicsPoc));    // Store POC values of LTRP
3283  ::memset(longtermPicsLSB, 0, sizeof(longtermPicsLSB));    // Store POC LSB values of LTRP
3284  ::memset(longtermPicsMSB, 0, sizeof(longtermPicsMSB));    // Store POC LSB values of LTRP
3285  ::memset(indices        , 0, sizeof(indices));            // Indices to aid in tracking sorted LTRPs
3286  ::memset(mSBPresentFlag , 0, sizeof(mSBPresentFlag));     // Indicate if MSB needs to be present
3287
3288  // Get the long-term reference pictures
3289  Int offset = rps->getNumberOfNegativePictures() + rps->getNumberOfPositivePictures();
3290  Int i, ctr = 0;
3291  Int maxPicOrderCntLSB = 1 << pcSlice->getSPS()->getBitsForPOC();
3292  for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++)
3293  {
3294    longtermPicsPoc[ctr] = rps->getPOC(i);                                  // LTRP POC
3295    longtermPicsLSB[ctr] = getLSB(longtermPicsPoc[ctr], maxPicOrderCntLSB); // LTRP POC LSB
3296    indices[ctr]      = i;
3297    longtermPicsMSB[ctr] = longtermPicsPoc[ctr] - longtermPicsLSB[ctr];
3298  }
3299  Int numLongPics = rps->getNumberOfLongtermPictures();
3300  assert(ctr == numLongPics);
3301
3302  // Arrange pictures in decreasing order of MSB;
3303  for(i = 0; i < numLongPics; i++)
3304  {
3305    for(Int j = 0; j < numLongPics - 1; j++)
3306    {
3307      if(longtermPicsMSB[j] < longtermPicsMSB[j+1])
3308      {
3309        std::swap(longtermPicsPoc[j], longtermPicsPoc[j+1]);
3310        std::swap(longtermPicsLSB[j], longtermPicsLSB[j+1]);
3311        std::swap(longtermPicsMSB[j], longtermPicsMSB[j+1]);
3312        std::swap(indices[j]        , indices[j+1]        );
3313      }
3314    }
3315  }
3316
3317  for(i = 0; i < numLongPics; i++)
3318  {
3319    // Check if MSB present flag should be enabled.
3320    // Check if the buffer contains any pictures that have the same LSB.
3321    TComList<TComPic*>::iterator  iterPic = rcListPic.begin();
3322    TComPic*                      pcPic;
3323    while ( iterPic != rcListPic.end() )
3324    {
3325      pcPic = *iterPic;
3326      if( (getLSB(pcPic->getPOC(), maxPicOrderCntLSB) == longtermPicsLSB[i])   &&     // Same LSB
3327                                      (pcPic->getSlice(0)->isReferenced())     &&    // Reference picture
3328                                        (pcPic->getPOC() != longtermPicsPoc[i])    )  // Not the LTRP itself
3329      {
3330        mSBPresentFlag[i] = true;
3331        break;
3332      }
3333      iterPic++;
3334    }
3335  }
3336
3337  // tempArray for usedByCurr flag
3338  Bool tempArray[MAX_NUM_REF_PICS]; ::memset(tempArray, 0, sizeof(tempArray));
3339  for(i = 0; i < numLongPics; i++)
3340  {
3341    tempArray[i] = rps->getUsed(indices[i]);
3342  }
3343  // Now write the final values;
3344  ctr = 0;
3345  Int currMSB = 0, currLSB = 0;
3346  // currPicPoc = currMSB + currLSB
3347  currLSB = getLSB(pcSlice->getPOC(), maxPicOrderCntLSB);
3348  currMSB = pcSlice->getPOC() - currLSB;
3349
3350  for(i = rps->getNumberOfPictures() - 1; i >= offset; i--, ctr++)
3351  {
3352    rps->setPOC                   (i, longtermPicsPoc[ctr]);
3353    rps->setDeltaPOC              (i, - pcSlice->getPOC() + longtermPicsPoc[ctr]);
3354    rps->setUsed                  (i, tempArray[ctr]);
3355    rps->setPocLSBLT              (i, longtermPicsLSB[ctr]);
3356    rps->setDeltaPocMSBCycleLT    (i, (currMSB - (longtermPicsPoc[ctr] - longtermPicsLSB[ctr])) / maxPicOrderCntLSB);
3357    rps->setDeltaPocMSBPresentFlag(i, mSBPresentFlag[ctr]);
3358
3359    assert(rps->getDeltaPocMSBCycleLT(i) >= 0);   // Non-negative value
3360  }
3361  for(i = rps->getNumberOfPictures() - 1, ctr = 1; i >= offset; i--, ctr++)
3362  {
3363    for(Int j = rps->getNumberOfPictures() - 1 - ctr; j >= offset; j--)
3364    {
3365      // Here at the encoder we know that we have set the full POC value for the LTRPs, hence we
3366      // don't have to check the MSB present flag values for this constraint.
3367      assert( rps->getPOC(i) != rps->getPOC(j) ); // If assert fails, LTRP entry repeated in RPS!!!
3368    }
3369  }
3370}
3371
3372Void TEncGOP::applyDeblockingFilterMetric( TComPic* pcPic, UInt uiNumSlices )
3373{
3374  TComPicYuv* pcPicYuvRec = pcPic->getPicYuvRec();
3375  Pel* Rec    = pcPicYuvRec->getAddr(COMPONENT_Y);
3376  Pel* tempRec = Rec;
3377  Int  stride = pcPicYuvRec->getStride(COMPONENT_Y);
3378  UInt log2maxTB = pcPic->getSlice(0)->getSPS()->getQuadtreeTULog2MaxSize();
3379  UInt maxTBsize = (1<<log2maxTB);
3380  const UInt minBlockArtSize = 8;
3381  const UInt picWidth = pcPicYuvRec->getWidth(COMPONENT_Y);
3382  const UInt picHeight = pcPicYuvRec->getHeight(COMPONENT_Y);
3383  const UInt noCol = (picWidth>>log2maxTB);
3384  const UInt noRows = (picHeight>>log2maxTB);
3385  assert(noCol > 1);
3386  assert(noRows > 1);
3387  std::vector<UInt64> colSAD(noCol,  UInt64(0));
3388  std::vector<UInt64> rowSAD(noRows, UInt64(0));
3389  UInt colIdx = 0;
3390  UInt rowIdx = 0;
3391  Pel p0, p1, p2, q0, q1, q2;
3392
3393  Int qp = pcPic->getSlice(0)->getSliceQp();
3394  const Int bitDepthLuma=pcPic->getSlice(0)->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
3395  Int bitdepthScale = 1 << (bitDepthLuma-8);
3396  Int beta = TComLoopFilter::getBeta( qp ) * bitdepthScale;
3397  const Int thr2 = (beta>>2);
3398  const Int thr1 = 2*bitdepthScale;
3399  UInt a = 0;
3400
3401  if (maxTBsize > minBlockArtSize)
3402  {
3403    // Analyze vertical artifact edges
3404    for(Int c = maxTBsize; c < picWidth; c += maxTBsize)
3405    {
3406      for(Int r = 0; r < picHeight; r++)
3407      {
3408        p2 = Rec[c-3];
3409        p1 = Rec[c-2];
3410        p0 = Rec[c-1];
3411        q0 = Rec[c];
3412        q1 = Rec[c+1];
3413        q2 = Rec[c+2];
3414        a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1);
3415        if ( thr1 < a && a < thr2)
3416        {
3417          colSAD[colIdx] += abs(p0 - q0);
3418        }
3419        Rec += stride;
3420      }
3421      colIdx++;
3422      Rec = tempRec;
3423    }
3424
3425    // Analyze horizontal artifact edges
3426    for(Int r = maxTBsize; r < picHeight; r += maxTBsize)
3427    {
3428      for(Int c = 0; c < picWidth; c++)
3429      {
3430        p2 = Rec[c + (r-3)*stride];
3431        p1 = Rec[c + (r-2)*stride];
3432        p0 = Rec[c + (r-1)*stride];
3433        q0 = Rec[c + r*stride];
3434        q1 = Rec[c + (r+1)*stride];
3435        q2 = Rec[c + (r+2)*stride];
3436        a = ((abs(p2-(p1<<1)+p0)+abs(q0-(q1<<1)+q2))<<1);
3437        if (thr1 < a && a < thr2)
3438        {
3439          rowSAD[rowIdx] += abs(p0 - q0);
3440        }
3441      }
3442      rowIdx++;
3443    }
3444  }
3445
3446  UInt64 colSADsum = 0;
3447  UInt64 rowSADsum = 0;
3448  for(Int c = 0; c < noCol-1; c++)
3449  {
3450    colSADsum += colSAD[c];
3451  }
3452  for(Int r = 0; r < noRows-1; r++)
3453  {
3454    rowSADsum += rowSAD[r];
3455  }
3456
3457  colSADsum <<= 10;
3458  rowSADsum <<= 10;
3459  colSADsum /= (noCol-1);
3460  colSADsum /= picHeight;
3461  rowSADsum /= (noRows-1);
3462  rowSADsum /= picWidth;
3463
3464  UInt64 avgSAD = ((colSADsum + rowSADsum)>>1);
3465  avgSAD >>= (bitDepthLuma-8);
3466
3467  if ( avgSAD > 2048 )
3468  {
3469    avgSAD >>= 9;
3470    Int offset = Clip3(2,6,(Int)avgSAD);
3471    for (Int i=0; i<uiNumSlices; i++)
3472    {
3473      pcPic->getSlice(i)->setDeblockingFilterOverrideFlag(true);
3474      pcPic->getSlice(i)->setDeblockingFilterDisable(false);
3475      pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( offset );
3476      pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( offset );
3477    }
3478  }
3479  else
3480  {
3481    for (Int i=0; i<uiNumSlices; i++)
3482    {
3483      pcPic->getSlice(i)->setDeblockingFilterOverrideFlag(false);
3484      pcPic->getSlice(i)->setDeblockingFilterDisable(        pcPic->getSlice(i)->getPPS()->getPPSDeblockingFilterDisabledFlag() );
3485      pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterBetaOffsetDiv2() );
3486      pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2(   pcPic->getSlice(i)->getPPS()->getDeblockingFilterTcOffsetDiv2()   );
3487    }
3488  }
3489}
3490
3491Void TEncGOP::applyDeblockingFilterParameterSelection( TComPic* pcPic, const UInt numSlices, const Int gopID )
3492{
3493  enum DBFltParam
3494  {
3495    DBFLT_PARAM_AVAILABLE = 0,
3496    DBFLT_DISABLE_FLAG,
3497    DBFLT_BETA_OFFSETD2,
3498    DBFLT_TC_OFFSETD2,
3499    //NUM_DBFLT_PARAMS
3500  };
3501  const Int MAX_BETA_OFFSET = 3;
3502  const Int MIN_BETA_OFFSET = -3;
3503  const Int MAX_TC_OFFSET = 3;
3504  const Int MIN_TC_OFFSET = -3;
3505
3506  TComPicYuv* pcPicYuvRec = pcPic->getPicYuvRec();
3507  TComPicYuv* pcPicYuvOrg = pcPic ->getPicYuvOrg();
3508
3509  const Int currQualityLayer = (pcPic->getSlice(0)->getSliceType() != I_SLICE) ? m_pcCfg->getGOPEntry(gopID).m_temporalId+1 : 0;
3510  assert(currQualityLayer <MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS);
3511
3512  if(!m_pcDeblockingTempPicYuv)
3513  {
3514    m_pcDeblockingTempPicYuv         = new TComPicYuv;
3515    m_pcDeblockingTempPicYuv->create( m_pcEncTop->getSourceWidth(), m_pcEncTop->getSourceHeight(), m_pcEncTop->getChromaFormatIdc(),  pcPic->getSlice(0)->getSPS()->getMaxCUWidth(), pcPic->getSlice(0)->getSPS()->getMaxCUHeight(), pcPic->getSlice(0)->getSPS()->getMaxTotalCUDepth(),true );
3516    memset(m_DBParam, 0, sizeof(m_DBParam));
3517  }
3518
3519  //preserve current reconstruction
3520  pcPicYuvRec->copyToPic(m_pcDeblockingTempPicYuv);
3521
3522  const Bool bNoFiltering      = m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] && m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG]==false /*&& pcPic->getTLayer()==0*/;
3523  const Int  maxBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]+1) : MAX_BETA_OFFSET;
3524  const Int  minBetaOffsetDiv2 = bNoFiltering? Clip3(MIN_BETA_OFFSET, MAX_BETA_OFFSET, m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]-1) : MIN_BETA_OFFSET;
3525  const Int  maxTcOffsetDiv2   = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]+2)       : MAX_TC_OFFSET;
3526  const Int  minTcOffsetDiv2   = bNoFiltering? Clip3(MIN_TC_OFFSET, MAX_TC_OFFSET, m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]-2)       : MIN_TC_OFFSET;
3527
3528  UInt64 distBetaPrevious      = std::numeric_limits<UInt64>::max();
3529  UInt64 distMin               = std::numeric_limits<UInt64>::max();
3530  Bool   bDBFilterDisabledBest = true;
3531  Int    betaOffsetDiv2Best    = 0;
3532  Int    tcOffsetDiv2Best      = 0;
3533
3534  for(Int betaOffsetDiv2=maxBetaOffsetDiv2; betaOffsetDiv2>=minBetaOffsetDiv2; betaOffsetDiv2--)
3535  {
3536    UInt64 distTcMin = std::numeric_limits<UInt64>::max();
3537    for(Int tcOffsetDiv2=maxTcOffsetDiv2; tcOffsetDiv2 >= minTcOffsetDiv2; tcOffsetDiv2--)
3538    {
3539      for (Int i=0; i<numSlices; i++)
3540      {
3541        pcPic->getSlice(i)->setDeblockingFilterOverrideFlag(true);
3542        pcPic->getSlice(i)->setDeblockingFilterDisable(false);
3543        pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( betaOffsetDiv2 );
3544        pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2( tcOffsetDiv2 );
3545      }
3546      m_pcDeblockingTempPicYuv->copyToPic(pcPicYuvRec); // restore reconstruction
3547      m_pcLoopFilter->loopFilterPic( pcPic );
3548      const UInt64 dist = xFindDistortionFrame(pcPicYuvOrg, pcPicYuvRec, pcPic->getPicSym()->getSPS().getBitDepths());
3549      if(dist < distMin)
3550      {
3551        distMin = dist;
3552        bDBFilterDisabledBest = false;
3553        betaOffsetDiv2Best  = betaOffsetDiv2;
3554        tcOffsetDiv2Best = tcOffsetDiv2;
3555      }
3556      if(dist < distTcMin)
3557      {
3558        distTcMin = dist;
3559      }
3560      else if(tcOffsetDiv2 <-2)
3561      {
3562        break;
3563      }
3564    }
3565    if(betaOffsetDiv2<-1 && distTcMin >= distBetaPrevious)
3566    {
3567      break;
3568    }
3569    distBetaPrevious = distTcMin;
3570  }
3571
3572  //update:
3573  m_DBParam[currQualityLayer][DBFLT_PARAM_AVAILABLE] = 1;
3574  m_DBParam[currQualityLayer][DBFLT_DISABLE_FLAG]    = bDBFilterDisabledBest;
3575  m_DBParam[currQualityLayer][DBFLT_BETA_OFFSETD2]   = betaOffsetDiv2Best;
3576  m_DBParam[currQualityLayer][DBFLT_TC_OFFSETD2]     = tcOffsetDiv2Best;
3577
3578  m_pcDeblockingTempPicYuv->copyToPic(pcPicYuvRec); //restore reconstruction
3579
3580  if(bDBFilterDisabledBest)
3581  {
3582    for (Int i=0; i<numSlices; i++)
3583    {
3584      pcPic->getSlice(i)->setDeblockingFilterOverrideFlag(true);
3585      pcPic->getSlice(i)->setDeblockingFilterDisable(true);
3586    }
3587  }
3588  else if(betaOffsetDiv2Best ==pcPic->getSlice(0)->getPPS()->getDeblockingFilterBetaOffsetDiv2() &&  tcOffsetDiv2Best==pcPic->getSlice(0)->getPPS()->getDeblockingFilterTcOffsetDiv2())
3589  {
3590    for (Int i=0; i<numSlices; i++)
3591    {
3592      pcPic->getSlice(i)->setDeblockingFilterOverrideFlag(false);
3593      pcPic->getSlice(i)->setDeblockingFilterDisable(        pcPic->getSlice(i)->getPPS()->getPPSDeblockingFilterDisabledFlag() );
3594      pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2( pcPic->getSlice(i)->getPPS()->getDeblockingFilterBetaOffsetDiv2() );
3595      pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2(   pcPic->getSlice(i)->getPPS()->getDeblockingFilterTcOffsetDiv2()   );
3596    }
3597  }
3598  else
3599  {
3600    for (Int i=0; i<numSlices; i++)
3601    {
3602      pcPic->getSlice(i)->setDeblockingFilterOverrideFlag(true);
3603      pcPic->getSlice(i)->setDeblockingFilterDisable( false );
3604      pcPic->getSlice(i)->setDeblockingFilterBetaOffsetDiv2(betaOffsetDiv2Best);
3605      pcPic->getSlice(i)->setDeblockingFilterTcOffsetDiv2(tcOffsetDiv2Best);
3606    }
3607  }
3608}
3609
3610#if NH_MV
3611Void TEncGOP::xSetRefPicListModificationsMv( std::vector<TComPic*> tempPicLists[2], TComSlice* pcSlice, UInt iGOPid )
3612{
3613
3614  if( pcSlice->getSliceType() == I_SLICE || !(pcSlice->getPPS()->getListsModificationPresentFlag()) || pcSlice->getNumActiveRefLayerPics() == 0 )
3615  {
3616    return;
3617  }
3618
3619  GOPEntry ge = m_pcCfg->getGOPEntry( (pcSlice->getRapPicFlag() && ( pcSlice->getLayerId( ) > 0) ) ? MAX_GOP : iGOPid );
3620  assert( ge.m_numActiveRefLayerPics == pcSlice->getNumActiveRefLayerPics() );
3621
3622  Int numPicsInTempList     = pcSlice->getNumRpsCurrTempList();
3623
3624  // GT: check if SliceType should be checked here.
3625  for (Int li = 0; li < 2; li ++) // Loop over lists L0 and L1
3626  {
3627    Int numPicsInFinalRefList = pcSlice->getNumRefIdx( ( li == 0 ) ? REF_PIC_LIST_0 : REF_PIC_LIST_1 );
3628
3629    Int finalIdxToTempIdxMap[16];
3630    for( Int k = 0; k < 16; k++ )
3631    {
3632      finalIdxToTempIdxMap[ k ] = -1;
3633    }
3634
3635    Bool isModified = false;
3636    if ( numPicsInTempList > 1 )
3637    {
3638      for( Int k = 0; k < pcSlice->getNumActiveRefLayerPics(); k++ )
3639      {
3640        // get position in temp. list
3641        Int refPicLayerId = pcSlice->getRefPicLayerId(k);
3642        Int idxInTempList = 0;
3643        for (; idxInTempList < numPicsInTempList; idxInTempList++)
3644        {
3645          if ( (tempPicLists[li][idxInTempList])->getLayerId() == refPicLayerId )
3646          {
3647            break;
3648          }
3649        }
3650
3651        Int idxInFinalList = ge.m_interViewRefPosL[ li ][ k ];
3652
3653        // Add negative from behind
3654        idxInFinalList = ( idxInFinalList < 0 )? ( numPicsInTempList + idxInFinalList ) : idxInFinalList;
3655
3656        Bool curIsModified = ( idxInFinalList != idxInTempList ) && ( ( idxInTempList < numPicsInFinalRefList ) || ( idxInFinalList < numPicsInFinalRefList ) ) ;
3657        if ( curIsModified )
3658        {
3659          isModified = true;
3660          assert( finalIdxToTempIdxMap[ idxInFinalList ] == -1 ); // Assert when two inter layer reference pictures are sorted to the same position
3661        }
3662        finalIdxToTempIdxMap[ idxInFinalList ] = idxInTempList;
3663      }
3664    }
3665
3666    TComRefPicListModification* refPicListModification = pcSlice->getRefPicListModification();
3667    refPicListModification->setRefPicListModificationFlagL( li, isModified );
3668
3669    if( isModified )
3670    {
3671      Int refIdx = 0;
3672
3673      for( Int i = 0; i < numPicsInFinalRefList; i++ )
3674      {
3675        if( finalIdxToTempIdxMap[i] >= 0 )
3676        {
3677          refPicListModification->setRefPicSetIdxL( li, i, finalIdxToTempIdxMap[i] );
3678        }
3679        else
3680        {
3681          ///* Fill gaps with temporal references *///
3682          // Forward inter layer reference pictures
3683          while( ( refIdx < numPicsInTempList ) && ( tempPicLists[li][refIdx]->getLayerId() != getLayerId())  )
3684          {
3685            refIdx++;
3686          }
3687          refPicListModification->setRefPicSetIdxL( li, i, refIdx );
3688          refIdx++;
3689        }
3690      }
3691    }
3692  }
3693}
3694#endif
3695//! \}
Note: See TracBrowser for help on using the repository browser.