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