source: 3DVCSoftware/branches/HTM-16.2-dev/source/Lib/TLibEncoder/TEncSlice.cpp @ 1412

Last change on this file since 1412 was 1412, checked in by tech, 7 years ago
  • Update HM-16.18
  • Cleanups
  • Encoder Extension

-- Representation formats
-- Parameter set sharing
-- GOP configuration

  • Property svn:eol-style set to native
File size: 56.3 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2017, ITU/ISO/IEC
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     TEncSlice.cpp
35    \brief    slice encoder class
36*/
37
38#include "TEncTop.h"
39#include "TEncSlice.h"
40#include <math.h>
41
42//! \ingroup TLibEncoder
43//! \{
44
45// ====================================================================================================================
46// Constructor / destructor / create / destroy
47// ====================================================================================================================
48TEncSlice::TEncSlice()
49 : m_encCABACTableIdx(I_SLICE)
50{
51}
52
53TEncSlice::~TEncSlice()
54{
55  destroy();
56}
57
58Void TEncSlice::create( Int iWidth, Int iHeight, ChromaFormat chromaFormat, UInt iMaxCUWidth, UInt iMaxCUHeight, UChar uhTotalDepth )
59{
60  // create prediction picture
61  m_picYuvPred.create( iWidth, iHeight, chromaFormat, iMaxCUWidth, iMaxCUHeight, uhTotalDepth, true );
62
63  // create residual picture
64  m_picYuvResi.create( iWidth, iHeight, chromaFormat, iMaxCUWidth, iMaxCUHeight, uhTotalDepth, true );
65}
66
67Void TEncSlice::destroy()
68{
69  m_picYuvPred.destroy();
70  m_picYuvResi.destroy();
71
72  // free lambda and QP arrays
73  m_vdRdPicLambda.clear();
74  m_vdRdPicQp.clear();
75  m_viRdPicQp.clear();
76}
77
78Void TEncSlice::init( TEncTop* pcEncTop )
79{
80  m_pcCfg             = pcEncTop;
81  m_pcListPic         = pcEncTop->getListPic();
82
83  m_pcGOPEncoder      = pcEncTop->getGOPEncoder();
84  m_pcCuEncoder       = pcEncTop->getCuEncoder();
85  m_pcPredSearch      = pcEncTop->getPredSearch();
86
87  m_pcEntropyCoder    = pcEncTop->getEntropyCoder();
88  m_pcSbacCoder       = pcEncTop->getSbacCoder();
89  m_pcBinCABAC        = pcEncTop->getBinCABAC();
90  m_pcTrQuant         = pcEncTop->getTrQuant();
91
92  m_pcRdCost          = pcEncTop->getRdCost();
93  m_pppcRDSbacCoder   = pcEncTop->getRDSbacCoder();
94  m_pcRDGoOnSbacCoder = pcEncTop->getRDGoOnSbacCoder();
95
96  // create lambda and QP arrays
97  m_vdRdPicLambda.resize(m_pcCfg->getDeltaQpRD() * 2 + 1 );
98  m_vdRdPicQp.resize(    m_pcCfg->getDeltaQpRD() * 2 + 1 );
99  m_viRdPicQp.resize(    m_pcCfg->getDeltaQpRD() * 2 + 1 );
100#if KWU_RC_MADPRED_E0227
101  if(m_pcCfg->getUseRateCtrl())
102  {
103    m_pcRateCtrl        = pcEncTop->getRateCtrl();
104  }
105  else
106  {
107    m_pcRateCtrl        = NULL;
108  }
109#else
110  m_pcRateCtrl        = pcEncTop->getRateCtrl();
111#endif
112
113}
114
115Void TEncSlice::updateLambda(TComSlice* pSlice, Double dQP)
116{
117  Int iQP = (Int)dQP;
118  Double dLambda = calculateLambda(pSlice, m_gopID, pSlice->getDepth(), pSlice->getSliceQp(), dQP, iQP);
119
120  setUpLambda(pSlice, dLambda, iQP);
121}
122
123
124Void
125TEncSlice::setUpLambda(TComSlice* slice, const Double dLambda, Int iQP)
126{
127  // store lambda
128  m_pcRdCost ->setLambda( dLambda, slice->getSPS()->getBitDepths() );
129
130  // for RDO
131  // in RdCost there is only one lambda because the luma and chroma bits are not separated, instead we weight the distortion of chroma.
132  Double dLambdas[MAX_NUM_COMPONENT] = { dLambda };
133  for(UInt compIdx=1; compIdx<MAX_NUM_COMPONENT; compIdx++)
134  {
135    const ComponentID compID=ComponentID(compIdx);
136    Int chromaQPOffset = slice->getPPS()->getQpOffset(compID) + slice->getSliceChromaQpDelta(compID);
137    Int qpc=(iQP + chromaQPOffset < 0) ? iQP : getScaledChromaQP(iQP + chromaQPOffset, m_pcCfg->getChromaFormatIdc());
138    Double tmpWeight = pow( 2.0, (iQP-qpc)/3.0 );  // takes into account of the chroma qp mapping and chroma qp Offset
139    m_pcRdCost->setDistortionWeight(compID, tmpWeight);
140    dLambdas[compIdx]=dLambda/tmpWeight;
141  }
142
143#if RDOQ_CHROMA_LAMBDA
144// for RDOQ
145  m_pcTrQuant->setLambdas( dLambdas );
146#else
147  m_pcTrQuant->setLambda( dLambda );
148#endif
149
150// For SAO
151  slice   ->setLambdas( dLambdas );
152}
153
154
155
156/**
157 - non-referenced frame marking
158 - QP computation based on temporal structure
159 - lambda computation based on QP
160 - set temporal layer ID and the parameter sets
161 .
162 \param pcPic         picture class
163 \param pocLast       POC of last picture
164 \param pocCurr       current POC
165 \param iNumPicRcvd   number of received pictures
166 \param iGOPid        POC offset for hierarchical structure
167 \param rpcSlice      slice header class
168 \param isField       true for field coding
169 */
170
171#if NH_MV
172Void TEncSlice::initEncSlice( TComPic* pcPic, Int pocLast, Int pocCurr, Int iGOPid, TComSlice*& rpcSlice, TComVPS* pVPS, Int layerId, bool isField )
173#else
174Void TEncSlice::initEncSlice( TComPic* pcPic, const Int pocLast, const Int pocCurr, const Int iGOPid, TComSlice*& rpcSlice, const Bool isField )
175#endif
176{
177  Double dQP;
178  Double dLambda;
179
180  rpcSlice = pcPic->getSlice(0);
181
182#if NH_MV
183  rpcSlice->setVPS( pVPS ); 
184
185  rpcSlice->setLayerId     ( layerId );
186  rpcSlice->setViewId      ( pVPS->getViewId      ( layerId ) );   
187  rpcSlice->setViewIndex   ( pVPS->getViewIndex   ( layerId ) );
188#if NH_3D
189  rpcSlice->setIsDepth     ( pVPS->getDepthId     ( layerId ) != 0 );   
190#endif
191#endif
192  rpcSlice->setSliceBits(0);
193  rpcSlice->setPic( pcPic );
194  rpcSlice->initSlice();
195  rpcSlice->setPicOutputFlag( true );
196  rpcSlice->setPOC( pocCurr );
197  pcPic->setField(isField);
198  m_gopID = iGOPid;
199
200#if NH_3D
201  rpcSlice->setApplyIC( false );
202#endif
203  // depth computation based on GOP size
204  Int depth;
205  {
206
207    Int poc = rpcSlice->getPOC();
208    if(isField)
209    {
210      poc = (poc/2) % (m_pcCfg->getGOPSize()/2);
211    }
212    else
213    {
214      poc = poc % m_pcCfg->getGOPSize();   
215    }
216    if ( poc == 0 )
217    {
218      depth = 0;
219    }
220    else
221    {
222      Int step = m_pcCfg->getGOPSize();
223      depth    = 0;
224      for( Int i=step>>1; i>=1; i>>=1 )
225      {
226        for ( Int j=i; j<m_pcCfg->getGOPSize(); j+=step )
227        {
228          if ( j == poc )
229          {
230            i=0;
231            break;
232          }
233        }
234        step >>= 1;
235        depth++;
236      }
237    }
238
239    if(m_pcCfg->getHarmonizeGopFirstFieldCoupleEnabled() && poc != 0)
240    {
241      if (isField && ((rpcSlice->getPOC() % 2) == 1))
242      {
243        depth ++;
244      }
245    }
246  }
247
248  // slice type
249#if NH_MV
250  SliceType eSliceTypeBaseView;
251  if( pocLast == 0 || pocCurr % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0 )
252  {
253    eSliceTypeBaseView = I_SLICE;
254  }
255  else
256  {
257    eSliceTypeBaseView = B_SLICE;
258  }
259  SliceType eSliceType = eSliceTypeBaseView;
260  if( eSliceTypeBaseView == I_SLICE && m_pcCfg->getGOPEntry(MAX_GOP).m_POC == 0 && m_pcCfg->getGOPEntry(MAX_GOP).m_sliceType != 'I' )
261  {
262    eSliceType = B_SLICE; 
263  }
264  m_eSliceTypeBaseView = eSliceTypeBaseView;
265#else
266  SliceType eSliceType;
267
268  eSliceType=B_SLICE;
269  if(!(isField && pocLast == 1) || !m_pcCfg->getEfficientFieldIRAPEnabled())
270  {
271    if(m_pcCfg->getDecodingRefreshType() == 3)
272    {
273      eSliceType = (pocLast == 0 || pocCurr % m_pcCfg->getIntraPeriod() == 0             || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
274    }
275    else
276    {
277      eSliceType = (pocLast == 0 || (pocCurr - (isField ? 1 : 0)) % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
278    }
279  }
280#endif
281  rpcSlice->setSliceType    ( eSliceType );
282
283  // ------------------------------------------------------------------------------------------------------------------
284  // Non-referenced frame marking
285  // ------------------------------------------------------------------------------------------------------------------
286
287  if(pocLast == 0)
288  {
289    rpcSlice->setTemporalLayerNonReferenceFlag(false);
290  }
291  else
292  {
293#if NH_MV
294#if 0 // Check this! NH_MV
295    rpcSlice->setTemporalLayerNonReferenceFlag(!m_pcCfg->getGOPEntry( (eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid ).m_refPic);
296#else
297    rpcSlice->setTemporalLayerNonReferenceFlag(!m_pcCfg->getGOPEntry(iGOPid).m_refPic);
298#endif
299#else
300    rpcSlice->setTemporalLayerNonReferenceFlag(!m_pcCfg->getGOPEntry(iGOPid).m_refPic);
301#endif
302  }
303  rpcSlice->setReferenced(true);
304
305  // ------------------------------------------------------------------------------------------------------------------
306  // QP setting
307  // ------------------------------------------------------------------------------------------------------------------
308
309#if X0038_LAMBDA_FROM_QP_CAPABILITY
310  dQP = m_pcCfg->getQPForPicture(iGOPid, rpcSlice);
311#else
312  dQP = m_pcCfg->getQP();
313  if(eSliceType!=I_SLICE)
314  {
315    if (!(( m_pcCfg->getMaxDeltaQP() == 0) && (!m_pcCfg->getLumaLevelToDeltaQPMapping().isEnabled()) && (dQP == -rpcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA) ) && (rpcSlice->getPPS()->getTransquantBypassEnabledFlag())))
316    {
317#if NH_MV
318      dQP += m_pcCfg->getGOPEntry( (eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid ).m_QPOffset;
319#else
320      dQP += m_pcCfg->getGOPEntry(iGOPid).m_QPOffset;
321#endif
322    }
323  }
324
325  // modify QP
326  const Int* pdQPs = m_pcCfg->getdQPs();
327  if ( pdQPs )
328  {
329    dQP += pdQPs[ rpcSlice->getPOC() ];
330  }
331
332  if (m_pcCfg->getCostMode()==COST_LOSSLESS_CODING)
333  {
334    dQP=LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP;
335    m_pcCfg->setDeltaQpRD(0);
336  }
337#endif
338
339  // ------------------------------------------------------------------------------------------------------------------
340  // Lambda computation
341  // ------------------------------------------------------------------------------------------------------------------
342
343#if X0038_LAMBDA_FROM_QP_CAPABILITY
344#if NH_MV
345  const Int temporalId=m_pcCfg->getGOPEntry((eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid).m_temporalId;
346#else
347  const Int temporalId=m_pcCfg->getGOPEntry(iGOPid).m_temporalId;
348#endif
349#endif
350
351  Int iQP;
352  Double dOrigQP = dQP;
353
354  // pre-compute lambda and QP values for all possible QP candidates
355  for ( Int iDQpIdx = 0; iDQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; iDQpIdx++ )
356  {
357    // compute QP value
358    dQP = dOrigQP + ((iDQpIdx+1)>>1)*(iDQpIdx%2 ? -1 : 1);
359
360    dLambda = calculateLambda(rpcSlice, iGOPid, depth, dQP, dQP, iQP );
361
362    m_vdRdPicLambda[iDQpIdx] = dLambda;
363    m_vdRdPicQp    [iDQpIdx] = dQP;
364    m_viRdPicQp    [iDQpIdx] = iQP;
365  }
366
367  // obtain dQP = 0 case
368  dLambda = m_vdRdPicLambda[0];
369  dQP     = m_vdRdPicQp    [0];
370  iQP     = m_viRdPicQp    [0];
371
372
373#if !X0038_LAMBDA_FROM_QP_CAPABILITY
374#if NH_MV
375  const Int temporalId=m_pcCfg->getGOPEntry((eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid).m_temporalId;
376#else
377  const Int temporalId=m_pcCfg->getGOPEntry(iGOPid).m_temporalId;
378#endif
379  const std::vector<Double> &intraLambdaModifiers=m_pcCfg->getIntraLambdaModifier();
380#endif
381
382  if(rpcSlice->getPPS()->getSliceChromaQpFlag())
383  {
384    const Bool bUseIntraOrPeriodicOffset = rpcSlice->getSliceType()==I_SLICE || (m_pcCfg->getSliceChromaOffsetQpPeriodicity()!=0 && (rpcSlice->getPOC()%m_pcCfg->getSliceChromaOffsetQpPeriodicity())==0);
385    Int cbQP = bUseIntraOrPeriodicOffset? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(false) : m_pcCfg->getGOPEntry(iGOPid).m_CbQPoffset;
386    Int crQP = bUseIntraOrPeriodicOffset? m_pcCfg->getSliceChromaOffsetQpIntraOrPeriodic(true)  : m_pcCfg->getGOPEntry(iGOPid).m_CrQPoffset;
387
388    cbQP = Clip3( -12, 12, cbQP + rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb) ) - rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb); 
389    crQP = Clip3( -12, 12, crQP + rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr) ) - rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr); 
390    rpcSlice->setSliceChromaQpDelta(COMPONENT_Cb, Clip3( -12, 12, cbQP));
391    assert(rpcSlice->getSliceChromaQpDelta(COMPONENT_Cb)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb)<=12 && rpcSlice->getSliceChromaQpDelta(COMPONENT_Cb)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cb)>=-12);
392    rpcSlice->setSliceChromaQpDelta(COMPONENT_Cr, Clip3( -12, 12, crQP));
393    assert(rpcSlice->getSliceChromaQpDelta(COMPONENT_Cr)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr)<=12 && rpcSlice->getSliceChromaQpDelta(COMPONENT_Cr)+rpcSlice->getPPS()->getQpOffset(COMPONENT_Cr)>=-12);
394  }
395  else
396  {
397    rpcSlice->setSliceChromaQpDelta( COMPONENT_Cb, 0 );
398    rpcSlice->setSliceChromaQpDelta( COMPONENT_Cr, 0 );
399  }
400
401#if !X0038_LAMBDA_FROM_QP_CAPABILITY
402  Double lambdaModifier;
403  if( rpcSlice->getSliceType( ) != I_SLICE || intraLambdaModifiers.empty())
404  {
405    lambdaModifier = m_pcCfg->getLambdaModifier( temporalId );
406  }
407  else
408  {
409    lambdaModifier = intraLambdaModifiers[ (temporalId < intraLambdaModifiers.size()) ? temporalId : (intraLambdaModifiers.size()-1) ];
410  }
411
412  dLambda *= lambdaModifier;
413#endif
414
415  setUpLambda(rpcSlice, dLambda, iQP);
416
417#if NH_3D_VSO
418  m_pcRdCost->setUseLambdaScaleVSO  ( (m_pcCfg->getUseVSO() ||  m_pcCfg->getForceLambdaScaleVSO()) && ( m_pcCfg->getIsDepth() || m_pcCfg->getIsAuxDepth() ) );
419  m_pcRdCost->setLambdaVSO          ( dLambda * m_pcCfg->getLambdaScaleVSO() );
420
421  // Should be moved to TEncTop
422 
423  // SAIT_VSO_EST_A0033
424  m_pcRdCost->setDisparityCoeff( m_pcCfg->getDispCoeff() );
425
426  // LGE_WVSO_A0119
427  if( m_pcCfg->getUseWVSO() && ( m_pcCfg->getIsDepth() || m_pcCfg->getIsAuxDepth() ) )
428  {
429    m_pcRdCost->setDWeight  ( m_pcCfg->getDWeight()   );
430    m_pcRdCost->setVSOWeight( m_pcCfg->getVSOWeight() );
431    m_pcRdCost->setVSDWeight( m_pcCfg->getVSDWeight() );
432  }
433
434#endif
435
436  if (m_pcCfg->getFastMEForGenBLowDelayEnabled())
437  {
438  // restore original slice type
439#if NH_MV
440  eSliceType = eSliceTypeBaseView;
441  if( eSliceTypeBaseView == I_SLICE && m_pcCfg->getGOPEntry(MAX_GOP).m_POC == 0 && m_pcCfg->getGOPEntry(MAX_GOP).m_sliceType != 'I' )
442  {
443    eSliceType = B_SLICE;
444  }
445#else
446    if(!(isField && pocLast == 1) || !m_pcCfg->getEfficientFieldIRAPEnabled())
447  {
448    if(m_pcCfg->getDecodingRefreshType() == 3)
449    {
450      eSliceType = (pocLast == 0 || (pocCurr)                     % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
451    }
452    else
453    {
454      eSliceType = (pocLast == 0 || (pocCurr - (isField ? 1 : 0)) % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
455
456    }
457  }
458#endif
459
460  rpcSlice->setSliceType        ( eSliceType );
461}
462
463  if (m_pcCfg->getUseRecalculateQPAccordingToLambda())
464  {
465    dQP = xGetQPValueAccordingToLambda( dLambda );
466    iQP = max( -rpcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), min( MAX_QP, (Int) floor( dQP + 0.5 ) ) );
467  }
468
469  rpcSlice->setSliceQp           ( iQP );
470#if ADAPTIVE_QP_SELECTION
471  rpcSlice->setSliceQpBase       ( iQP );
472#endif
473  rpcSlice->setSliceQpDelta      ( 0 );
474  rpcSlice->setUseChromaQpAdj( rpcSlice->getPPS()->getPpsRangeExtension().getChromaQpOffsetListEnabledFlag() );
475#if NH_MV
476  rpcSlice->setNumRefIdx(REF_PIC_LIST_0,m_pcCfg->getGOPEntry( (eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid ).m_numRefPicsActive);
477  rpcSlice->setNumRefIdx(REF_PIC_LIST_1,m_pcCfg->getGOPEntry( (eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid ).m_numRefPicsActive);
478#else
479  rpcSlice->setNumRefIdx(REF_PIC_LIST_0,m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive);
480  rpcSlice->setNumRefIdx(REF_PIC_LIST_1,m_pcCfg->getGOPEntry(iGOPid).m_numRefPicsActive);
481#endif
482
483  if ( m_pcCfg->getDeblockingFilterMetric() )
484  {
485    rpcSlice->setDeblockingFilterOverrideFlag(true);
486    rpcSlice->setDeblockingFilterDisable(false);
487    rpcSlice->setDeblockingFilterBetaOffsetDiv2( 0 );
488    rpcSlice->setDeblockingFilterTcOffsetDiv2( 0 );
489  }
490  else if (rpcSlice->getPPS()->getDeblockingFilterControlPresentFlag())
491  {
492    rpcSlice->setDeblockingFilterOverrideFlag( rpcSlice->getPPS()->getDeblockingFilterOverrideEnabledFlag() );
493    rpcSlice->setDeblockingFilterDisable( rpcSlice->getPPS()->getPPSDeblockingFilterDisabledFlag() );
494    if ( !rpcSlice->getDeblockingFilterDisable())
495    {
496      if ( rpcSlice->getDeblockingFilterOverrideFlag() && eSliceType!=I_SLICE)
497      {
498#if NH_MV
499        rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getGOPEntry((eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid).m_betaOffsetDiv2 + m_pcCfg->getLoopFilterBetaOffset()  );
500        rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getGOPEntry((eSliceTypeBaseView == I_SLICE) ? MAX_GOP : iGOPid).m_tcOffsetDiv2 + m_pcCfg->getLoopFilterTcOffset() );
501#else
502        rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_betaOffsetDiv2 + m_pcCfg->getLoopFilterBetaOffset()  );
503        rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getGOPEntry(iGOPid).m_tcOffsetDiv2 + m_pcCfg->getLoopFilterTcOffset() );
504#endif
505      }
506      else
507      {
508        rpcSlice->setDeblockingFilterBetaOffsetDiv2( m_pcCfg->getLoopFilterBetaOffset() );
509        rpcSlice->setDeblockingFilterTcOffsetDiv2( m_pcCfg->getLoopFilterTcOffset() );
510      }
511    }
512  }
513  else
514  {
515    rpcSlice->setDeblockingFilterOverrideFlag( false );
516    rpcSlice->setDeblockingFilterDisable( false );
517    rpcSlice->setDeblockingFilterBetaOffsetDiv2( 0 );
518    rpcSlice->setDeblockingFilterTcOffsetDiv2( 0 );
519  }
520
521  rpcSlice->setDepth            ( depth );
522
523  pcPic->setTLayer( temporalId );
524  if(eSliceType==I_SLICE)
525  {
526    pcPic->setTLayer(0);
527  }
528  rpcSlice->setTLayer( pcPic->getTLayer() );
529
530  pcPic->setPicYuvPred( &m_picYuvPred );
531  pcPic->setPicYuvResi( &m_picYuvResi );
532  rpcSlice->setSliceMode            ( m_pcCfg->getSliceMode()            );
533  rpcSlice->setSliceArgument        ( m_pcCfg->getSliceArgument()        );
534  rpcSlice->setSliceSegmentMode     ( m_pcCfg->getSliceSegmentMode()     );
535  rpcSlice->setSliceSegmentArgument ( m_pcCfg->getSliceSegmentArgument() );
536#if NH_3D
537#else
538  rpcSlice->setMaxNumMergeCand        ( m_pcCfg->getMaxNumMergeCand()        );
539#endif
540}
541
542Double TEncSlice::calculateLambda( const TComSlice* slice,
543                                   const Int        GOPid, // entry in the GOP table
544                                   const Int        depth, // slice GOP hierarchical depth.
545                                   const Double     refQP, // initial slice-level QP
546                                   const Double     dQP,   // initial double-precision QP
547                                         Int        &iQP )  // returned integer QP.
548{
549  enum   SliceType eSliceType    = slice->getSliceType();
550  const  Bool      isField       = slice->getPic()->isField();
551  const  Int       NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );
552  const  Int       SHIFT_QP      = 12;
553#if X0038_LAMBDA_FROM_QP_CAPABILITY
554  const Int temporalId=m_pcCfg->getGOPEntry(GOPid).m_temporalId;
555  const std::vector<Double> &intraLambdaModifiers=m_pcCfg->getIntraLambdaModifier();
556#endif
557
558#if FULL_NBIT
559  Int    bitdepth_luma_qp_scale = 6 * (slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 8);
560#else
561  Int    bitdepth_luma_qp_scale = 0;
562#endif
563  Double qp_temp = dQP + bitdepth_luma_qp_scale - SHIFT_QP;
564  // Case #1: I or P-slices (key-frame)
565#if NH_MV
566  Double dQPFactor = m_pcCfg->getGOPEntry( (m_eSliceTypeBaseView == I_SLICE) ? MAX_GOP : GOPid ).m_QPFactor;
567#else
568  Double dQPFactor = m_pcCfg->getGOPEntry(GOPid).m_QPFactor;
569#endif
570  if ( eSliceType==I_SLICE )
571  {
572    if (m_pcCfg->getIntraQpFactor()>=0.0 && m_pcCfg->getGOPEntry(GOPid).m_sliceType != I_SLICE)
573    {
574      dQPFactor=m_pcCfg->getIntraQpFactor();
575    }
576    else
577    {
578#if X0038_LAMBDA_FROM_QP_CAPABILITY
579      if(m_pcCfg->getLambdaFromQPEnable())
580      {
581        dQPFactor=0.57;
582      }
583      else
584      {
585#endif
586        Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)(isField ? NumberBFrames/2 : NumberBFrames) );
587        dQPFactor=0.57*dLambda_scale;
588#if X0038_LAMBDA_FROM_QP_CAPABILITY
589      }
590#endif
591    }
592  }
593#if X0038_LAMBDA_FROM_QP_CAPABILITY
594  else if( m_pcCfg->getLambdaFromQPEnable() )
595  {
596    dQPFactor=0.57;
597  }
598#endif
599
600  Double dLambda = dQPFactor*pow( 2.0, qp_temp/3.0 );
601
602#if X0038_LAMBDA_FROM_QP_CAPABILITY
603  if( !(m_pcCfg->getLambdaFromQPEnable()) && depth>0 )
604#else
605  if ( depth>0 )
606#endif
607  {
608#if FULL_NBIT
609    Double qp_temp_ref_orig = refQP - SHIFT_QP;
610    dLambda *= Clip3( 2.00, 4.00, (qp_temp_ref_orig / 6.0) ); // (j == B_SLICE && p_cur_frm->layer != 0 )
611#else
612    Double qp_temp_ref = refQP + bitdepth_luma_qp_scale - SHIFT_QP;
613    dLambda *= Clip3( 2.00, 4.00, (qp_temp_ref / 6.0) ); // (j == B_SLICE && p_cur_frm->layer != 0 )
614#endif
615  }
616
617  // if hadamard is used in ME process
618  if ( !m_pcCfg->getUseHADME() && slice->getSliceType( ) != I_SLICE )
619  {
620    dLambda *= 0.95;
621  }
622
623#if X0038_LAMBDA_FROM_QP_CAPABILITY
624  Double lambdaModifier;
625  if( eSliceType != I_SLICE || intraLambdaModifiers.empty())
626  {
627    lambdaModifier = m_pcCfg->getLambdaModifier( temporalId );
628  }
629  else
630  {
631    lambdaModifier = intraLambdaModifiers[ (temporalId < intraLambdaModifiers.size()) ? temporalId : (intraLambdaModifiers.size()-1) ];
632  }
633  dLambda *= lambdaModifier;
634#endif
635
636  iQP = max( -slice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), min( MAX_QP, (Int) floor( dQP + 0.5 ) ) );
637
638  // NOTE: the lambda modifiers that are sometimes applied later might be best always applied in here.
639  return dLambda;
640}
641
642
643Void TEncSlice::resetQP( TComPic* pic, Int sliceQP, Double lambda )
644{
645  TComSlice* slice = pic->getSlice(0);
646
647  // store lambda
648  slice->setSliceQp( sliceQP );
649#if ADAPTIVE_QP_SELECTION
650  slice->setSliceQpBase ( sliceQP );
651#endif
652  setUpLambda(slice, lambda, sliceQP);
653}
654
655// ====================================================================================================================
656// Public member functions
657// ====================================================================================================================
658
659//! set adaptive search range based on poc difference
660Void TEncSlice::setSearchRange( TComSlice* pcSlice )
661{
662  Int iCurrPOC = pcSlice->getPOC();
663  Int iRefPOC;
664  Int iGOPSize = m_pcCfg->getGOPSize();
665  Int iOffset = (iGOPSize >> 1);
666  Int iMaxSR = m_pcCfg->getSearchRange();
667  Int iNumPredDir = pcSlice->isInterP() ? 1 : 2;
668
669  for (Int iDir = 0; iDir < iNumPredDir; iDir++)
670  {
671    RefPicList  e = ( iDir ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
672    for (Int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(e); iRefIdx++)
673    {
674      iRefPOC = pcSlice->getRefPic(e, iRefIdx)->getPOC();
675      Int newSearchRange = Clip3(m_pcCfg->getMinSearchWindow(), iMaxSR, (iMaxSR*ADAPT_SR_SCALE*abs(iCurrPOC - iRefPOC)+iOffset)/iGOPSize);
676      m_pcPredSearch->setAdaptiveSearchRange(iDir, iRefIdx, newSearchRange);
677    }
678  }
679}
680
681/**
682 Multi-loop slice encoding for different slice QP
683
684 \param pcPic    picture class
685 */
686Void TEncSlice::precompressSlice( TComPic* pcPic )
687{
688  // if deltaQP RD is not used, simply return
689  if ( m_pcCfg->getDeltaQpRD() == 0 )
690  {
691    return;
692  }
693
694  if ( m_pcCfg->getUseRateCtrl() )
695  {
696    printf( "\nMultiple QP optimization is not allowed when rate control is enabled." );
697    assert(0);
698    return;
699  }
700
701  TComSlice* pcSlice        = pcPic->getSlice(getSliceIdx());
702
703  if (pcSlice->getDependentSliceSegmentFlag())
704  {
705    // if this is a dependent slice segment, then it was optimised
706    // when analysing the entire slice.
707    return;
708  }
709
710  if (pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES)
711  {
712    // TODO: investigate use of average cost per CTU so that this Slice Mode can be used.
713    printf( "\nUnable to optimise Slice-level QP if Slice Mode is set to FIXED_NUMBER_OF_BYTES\n" );
714    assert(0);
715    return;
716  }
717
718
719  Double     dPicRdCostBest = MAX_DOUBLE;
720  UInt       uiQpIdxBest = 0;
721
722  Double dFrameLambda;
723#if FULL_NBIT
724  Int    SHIFT_QP = 12 + 6 * (pcSlice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 8);
725#else
726  Int    SHIFT_QP = 12;
727#endif
728
729  // set frame lambda
730  if (m_pcCfg->getGOPSize() > 1)
731  {
732    dFrameLambda = 0.68 * pow (2, (m_viRdPicQp[0]  - SHIFT_QP) / 3.0) * (pcSlice->isInterB()? 2 : 1);
733  }
734  else
735  {
736    dFrameLambda = 0.68 * pow (2, (m_viRdPicQp[0] - SHIFT_QP) / 3.0);
737  }
738  m_pcRdCost      ->setFrameLambda(dFrameLambda);
739
740  // for each QP candidate
741  for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ )
742  {
743    pcSlice       ->setSliceQp             ( m_viRdPicQp    [uiQpIdx] );
744#if ADAPTIVE_QP_SELECTION
745    pcSlice       ->setSliceQpBase         ( m_viRdPicQp    [uiQpIdx] );
746#endif
747    setUpLambda(pcSlice, m_vdRdPicLambda[uiQpIdx], m_viRdPicQp    [uiQpIdx]);
748
749    // try compress
750    compressSlice   ( pcPic, true, m_pcCfg->getFastDeltaQp());
751
752#if NH_3D_VSO
753    Dist64 uiPicDist        = m_uiPicDist;
754#else
755    UInt64 uiPicDist        = m_uiPicDist; // Distortion, as calculated by compressSlice.
756    // NOTE: This distortion is the chroma-weighted SSE distortion for the slice.
757    //       Previously a standard SSE distortion was calculated (for the entire frame).
758    //       Which is correct?
759
760    // TODO: Update loop filter, SAO and distortion calculation to work on one slice only.
761    // m_pcGOPEncoder->preLoopFilterPicAll( pcPic, uiPicDist );
762
763#endif
764
765    // compute RD cost and choose the best
766#if NH_3D_VSO
767    Double dPicRdCost = m_pcRdCost->calcRdCost( (Double)m_uiPicTotalBits, uiPicDist, DF_SSE_FRAME);
768#else
769    Double dPicRdCost = m_pcRdCost->calcRdCost( (Double)m_uiPicTotalBits, (Double)uiPicDist, DF_SSE_FRAME);
770#endif
771#if H_3D
772    // Above calculation need to be fixed for VSO, including frameLambda value.
773#endif
774
775    if ( dPicRdCost < dPicRdCostBest )
776    {
777      uiQpIdxBest    = uiQpIdx;
778      dPicRdCostBest = dPicRdCost;
779    }
780  }
781
782  // set best values
783  pcSlice       ->setSliceQp             ( m_viRdPicQp    [uiQpIdxBest] );
784#if ADAPTIVE_QP_SELECTION
785  pcSlice       ->setSliceQpBase         ( m_viRdPicQp    [uiQpIdxBest] );
786#endif
787  setUpLambda(pcSlice, m_vdRdPicLambda[uiQpIdxBest], m_viRdPicQp    [uiQpIdxBest]);
788}
789
790Void TEncSlice::calCostSliceI(TComPic* pcPic) // TODO: this only analyses the first slice segment. What about the others?
791{
792  Double            iSumHadSlice      = 0;
793  TComSlice * const pcSlice           = pcPic->getSlice(getSliceIdx());
794  const TComSPS    &sps               = *(pcSlice->getSPS());
795  const Int         shift             = sps.getBitDepth(CHANNEL_TYPE_LUMA)-8;
796  const Int         offset            = (shift>0)?(1<<(shift-1)):0;
797
798  pcSlice->setSliceSegmentBits(0);
799
800  UInt startCtuTsAddr, boundingCtuTsAddr;
801  xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic );
802
803  for( UInt ctuTsAddr = startCtuTsAddr, ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr);
804       ctuTsAddr < boundingCtuTsAddr;
805       ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(++ctuTsAddr) )
806  {
807    // initialize CU encoder
808    TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr );
809    pCtu->initCtu( pcPic, ctuRsAddr );
810
811    Int height  = min( sps.getMaxCUHeight(),sps.getPicHeightInLumaSamples() - ctuRsAddr / pcPic->getFrameWidthInCtus() * sps.getMaxCUHeight() );
812    Int width   = min( sps.getMaxCUWidth(), sps.getPicWidthInLumaSamples()  - ctuRsAddr % pcPic->getFrameWidthInCtus() * sps.getMaxCUWidth() );
813
814    Int iSumHad = m_pcCuEncoder->updateCtuDataISlice(pCtu, width, height);
815
816    (m_pcRateCtrl->getRCPic()->getLCU(ctuRsAddr)).m_costIntra=(iSumHad+offset)>>shift;
817    iSumHadSlice += (m_pcRateCtrl->getRCPic()->getLCU(ctuRsAddr)).m_costIntra;
818
819  }
820  m_pcRateCtrl->getRCPic()->setTotalIntraCost(iSumHadSlice);
821}
822
823/** \param pcPic   picture class
824 */
825Void TEncSlice::compressSlice( TComPic* pcPic, const Bool bCompressEntireSlice, const Bool bFastDeltaQP )
826{
827  // if bCompressEntireSlice is true, then the entire slice (not slice segment) is compressed,
828  //   effectively disabling the slice-segment-mode.
829
830  UInt   startCtuTsAddr;
831  UInt   boundingCtuTsAddr;
832  TComSlice* const pcSlice            = pcPic->getSlice(getSliceIdx());
833  pcSlice->setSliceSegmentBits(0);
834  xDetermineStartAndBoundingCtuTsAddr ( startCtuTsAddr, boundingCtuTsAddr, pcPic );
835  if (bCompressEntireSlice)
836  {
837    boundingCtuTsAddr = pcSlice->getSliceCurEndCtuTsAddr();
838    pcSlice->setSliceSegmentCurEndCtuTsAddr(boundingCtuTsAddr);
839  }
840
841  // initialize cost values - these are used by precompressSlice (they should be parameters).
842  m_uiPicTotalBits  = 0;
843  m_dPicRdCost      = 0; // NOTE: This is a write-only variable!
844  m_uiPicDist       = 0;
845
846  m_pcEntropyCoder->setEntropyCoder   ( m_pppcRDSbacCoder[0][CI_CURR_BEST] );
847  m_pcEntropyCoder->resetEntropy      ( pcSlice );
848
849  TEncBinCABAC* pRDSbacCoder = (TEncBinCABAC *) m_pppcRDSbacCoder[0][CI_CURR_BEST]->getEncBinIf();
850  pRDSbacCoder->setBinCountingEnableFlag( false );
851  pRDSbacCoder->setBinsCoded( 0 );
852
853  TComBitCounter  tempBitCounter;
854  const UInt      frameWidthInCtus = pcPic->getPicSym()->getFrameWidthInCtus();
855 
856  m_pcCuEncoder->setFastDeltaQp(bFastDeltaQP);
857
858  //------------------------------------------------------------------------------
859  //  Weighted Prediction parameters estimation.
860  //------------------------------------------------------------------------------
861  // calculate AC/DC values for current picture
862  if( pcSlice->getPPS()->getUseWP() || pcSlice->getPPS()->getWPBiPred() )
863  {
864    xCalcACDCParamSlice(pcSlice);
865  }
866
867  const Bool bWp_explicit = (pcSlice->getSliceType()==P_SLICE && pcSlice->getPPS()->getUseWP()) || (pcSlice->getSliceType()==B_SLICE && pcSlice->getPPS()->getWPBiPred());
868
869  if ( bWp_explicit )
870  {
871    //------------------------------------------------------------------------------
872    //  Weighted Prediction implemented at Slice level. SliceMode=2 is not supported yet.
873    //------------------------------------------------------------------------------
874    if ( pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES || pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES )
875    {
876      printf("Weighted Prediction is not supported with slice mode determined by max number of bins.\n"); exit(0);
877    }
878
879    xEstimateWPParamSlice( pcSlice, m_pcCfg->getWeightedPredictionMethod() );
880    pcSlice->initWpScaling(pcSlice->getSPS());
881
882    // check WP on/off
883    xCheckWPEnable( pcSlice );
884  }
885
886#if ADAPTIVE_QP_SELECTION
887  if( m_pcCfg->getUseAdaptQpSelect() && !(pcSlice->getDependentSliceSegmentFlag()))
888  {
889    // TODO: this won't work with dependent slices: they do not have their own QP. Check fix to mask clause execution with && !(pcSlice->getDependentSliceSegmentFlag())
890    m_pcTrQuant->clearSliceARLCnt(); // TODO: this looks wrong for multiple slices - the results of all but the last slice will be cleared before they are used (all slices compressed, and then all slices encoded)
891    if(pcSlice->getSliceType()!=I_SLICE)
892    {
893      Int qpBase = pcSlice->getSliceQpBase();
894      pcSlice->setSliceQp(qpBase + m_pcTrQuant->getQpDelta(qpBase));
895    }
896  }
897#endif
898
899#if NH_3D
900  if ( m_pcCfg->getViewIndex() && m_pcCfg->getUseIC() &&
901       !( ( pcSlice->getSliceType() == P_SLICE && pcSlice->getPPS()->getUseWP() ) || ( pcSlice->getSliceType() == B_SLICE && pcSlice->getPPS()->getWPBiPred() ) )
902     )
903  {
904    pcSlice ->xSetApplyIC(m_pcCfg->getUseICLowLatencyEnc());
905    if ( pcSlice->getApplyIC() )
906    {
907      pcSlice->setIcSkipParseFlag( pcSlice->getPOC() % m_pcCfg->getIntraPeriod() != 0 );
908    }
909  }
910#endif
911
912
913
914  // Adjust initial state if this is the start of a dependent slice.
915  {
916    const UInt      ctuRsAddr               = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr);
917    const UInt      currentTileIdx          = pcPic->getPicSym()->getTileIdxMap(ctuRsAddr);
918    const TComTile *pCurrentTile            = pcPic->getPicSym()->getTComTile(currentTileIdx);
919    const UInt      firstCtuRsAddrOfTile    = pCurrentTile->getFirstCtuRsAddr();
920    if( pcSlice->getDependentSliceSegmentFlag() && ctuRsAddr != firstCtuRsAddrOfTile )
921    {
922      // This will only occur if dependent slice-segments (m_entropyCodingSyncContextState=true) are being used.
923      if( pCurrentTile->getTileWidthInCtus() >= 2 || !m_pcCfg->getEntropyCodingSyncEnabledFlag() )
924      {
925        m_pppcRDSbacCoder[0][CI_CURR_BEST]->loadContexts( &m_lastSliceSegmentEndContextState );
926      }
927    }
928  }
929
930  // for every CTU in the slice segment (may terminate sooner if there is a byte limit on the slice-segment)
931#if NH_3D_VSO
932  Int iLastPosY = -1;
933#endif
934
935  for( UInt ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ++ctuTsAddr )
936  {
937    const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr);
938    // initialize CTU encoder
939    TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr );
940    pCtu->initCtu( pcPic, ctuRsAddr );
941#if NH_3D_VSO
942    if ( m_pcRdCost->getUseRenModel() )
943    {
944      // updated renderer model if necessary
945      Int iCurPosX;
946      Int iCurPosY; 
947      pCtu->getPosInPic(0, iCurPosX, iCurPosY );
948      if ( iCurPosY != iLastPosY )
949      {
950        iLastPosY = iCurPosY;         
951        TEncTop* pcEncTop = (TEncTop*) m_pcCfg; // Fix this later.
952        pcEncTop->setupRenModel( pcSlice->getPOC() , pcSlice->getViewIndex(), pcSlice->getIsDepth() || pcSlice->getVPS()->getAuxId( pcSlice->getLayerId()  ) ? 1 : 0, iCurPosY, pcSlice->getSPS()->getMaxCUHeight() );
953      }
954    }
955#endif
956
957    // update CABAC state
958    const UInt firstCtuRsAddrOfTile = pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr))->getFirstCtuRsAddr();
959    const UInt tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus;
960    const UInt ctuXPosInCtus  = ctuRsAddr % frameWidthInCtus;
961   
962    if (ctuRsAddr == firstCtuRsAddrOfTile)
963    {
964      m_pppcRDSbacCoder[0][CI_CURR_BEST]->resetEntropy(pcSlice);
965    }
966    else if ( ctuXPosInCtus == tileXPosInCtus && m_pcCfg->getEntropyCodingSyncEnabledFlag())
967    {
968      // reset and then update contexts to the state at the end of the top-right CTU (if within current slice and tile).
969      m_pppcRDSbacCoder[0][CI_CURR_BEST]->resetEntropy(pcSlice);
970      // Sync if the Top-Right is available.
971      TComDataCU *pCtuUp = pCtu->getCtuAbove();
972      if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus)  )
973      {
974        TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 );
975        if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) )
976        {
977          // Top-Right is available, we use it.
978          m_pppcRDSbacCoder[0][CI_CURR_BEST]->loadContexts( &m_entropyCodingSyncContextState );
979        }
980      }
981    }
982
983    // set go-on entropy coder (used for all trial encodings - the cu encoder and encoder search also have a copy of the same pointer)
984    m_pcEntropyCoder->setEntropyCoder ( m_pcRDGoOnSbacCoder );
985    m_pcEntropyCoder->setBitstream( &tempBitCounter );
986    tempBitCounter.resetBits();
987    m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[0][CI_CURR_BEST] ); // this copy is not strictly necessary here, but indicates that the GoOnSbacCoder
988                                                                     // is reset to a known state before every decision process.
989
990    ((TEncBinCABAC*)m_pcRDGoOnSbacCoder->getEncBinIf())->setBinCountingEnableFlag(true);
991
992    Double oldLambda = m_pcRdCost->getLambda();
993    if ( m_pcCfg->getUseRateCtrl() )
994    {
995      Int estQP        = pcSlice->getSliceQp();
996      Double estLambda = -1.0;
997      Double bpp       = -1.0;
998
999      if ( ( pcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )
1000      {
1001        estQP = pcSlice->getSliceQp();
1002      }
1003      else
1004      {
1005#if KWU_RC_MADPRED_E0227
1006          if(pcSlice->getLayerId() != 0 && m_pcCfg->getUseDepthMADPred() && !pcSlice->getIsDepth())
1007          {
1008            Double zn, zf, focallength, position, camShift;
1009            Double basePos;
1010            Bool bInterpolated;
1011            Int direction = pcSlice->getViewId() - pcCU->getSlice()->getIvPic(false, 0)->getViewId();
1012            Int disparity;
1013
1014            pcEncTop->getCamParam()->xGetZNearZFar(pcEncTop->getCamParam()->getBaseViewNumbers()[pcSlice->getViewIndex()], pcSlice->getPOC(), zn, zf);
1015            pcEncTop->getCamParam()->xGetGeometryData(pcEncTop->getCamParam()->getBaseViewNumbers()[0], pcSlice->getPOC(), focallength, basePos, camShift, bInterpolated);
1016            pcEncTop->getCamParam()->xGetGeometryData(pcEncTop->getCamParam()->getBaseViewNumbers()[pcSlice->getViewIndex()], pcSlice->getPOC(), focallength, position, camShift, bInterpolated);
1017            bpp       = m_pcRateCtrl->getRCPic()->getLCUTargetBppforInterView( m_pcRateCtrl->getPicList(), pcCU,
1018              basePos, position, focallength, zn, zf, (direction > 0 ? 1 : -1), &disparity );
1019          }
1020          else
1021          {
1022#endif
1023        bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType());
1024        if ( pcPic->getSlice( 0 )->getSliceType() == I_SLICE)
1025        {
1026          estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);
1027        }
1028        else
1029        {
1030          estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );
1031          estQP     = m_pcRateCtrl->getRCPic()->getLCUEstQP    ( estLambda, pcSlice->getSliceQp() );
1032        }
1033#if KWU_RC_MADPRED_E0227
1034          estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );
1035          estQP     = m_pcRateCtrl->getRCPic()->getLCUEstQP    ( estLambda, pcSlice->getSliceQp() );
1036#endif
1037
1038        estQP     = Clip3( -pcSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA), MAX_QP, estQP );
1039
1040        m_pcRdCost->setLambda(estLambda, pcSlice->getSPS()->getBitDepths());
1041
1042#if RDOQ_CHROMA_LAMBDA
1043        // set lambda for RDOQ
1044        const Double chromaLambda = estLambda / m_pcRdCost->getChromaWeight();
1045        const Double lambdaArray[MAX_NUM_COMPONENT] = { estLambda, chromaLambda, chromaLambda };
1046        m_pcTrQuant->setLambdas( lambdaArray );
1047#else
1048        m_pcTrQuant->setLambda( estLambda );
1049#endif
1050      }
1051
1052      m_pcRateCtrl->setRCQP( estQP );
1053#if ADAPTIVE_QP_SELECTION
1054      pCtu->getSlice()->setSliceQpBase( estQP );
1055#endif
1056    }
1057
1058    // run CTU trial encoder
1059    m_pcCuEncoder->compressCtu( pCtu );
1060
1061
1062    // All CTU decisions have now been made. Restore entropy coder to an initial stage, ready to make a true encode,
1063    // which will result in the state of the contexts being correct. It will also count up the number of bits coded,
1064    // which is used if there is a limit of the number of bytes per slice-segment.
1065
1066    m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST] );
1067    m_pcEntropyCoder->setBitstream( &tempBitCounter );
1068    pRDSbacCoder->setBinCountingEnableFlag( true );
1069    m_pppcRDSbacCoder[0][CI_CURR_BEST]->resetBits();
1070    pRDSbacCoder->setBinsCoded( 0 );
1071
1072    // encode CTU and calculate the true bit counters.
1073    m_pcCuEncoder->encodeCtu( pCtu );
1074
1075
1076    pRDSbacCoder->setBinCountingEnableFlag( false );
1077
1078    const Int numberOfWrittenBits = m_pcEntropyCoder->getNumberOfWrittenBits();
1079
1080    // Calculate if this CTU puts us over slice bit size.
1081    // cannot terminate if current slice/slice-segment would be 0 Ctu in size,
1082    const UInt validEndOfSliceCtuTsAddr = ctuTsAddr + (ctuTsAddr == startCtuTsAddr ? 1 : 0);
1083    // Set slice end parameter
1084    if(pcSlice->getSliceMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceBits()+numberOfWrittenBits > (pcSlice->getSliceArgument()<<3))
1085    {
1086      pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
1087      pcSlice->setSliceCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
1088      boundingCtuTsAddr=validEndOfSliceCtuTsAddr;
1089    }
1090    else if((!bCompressEntireSlice) && pcSlice->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && pcSlice->getSliceSegmentBits()+numberOfWrittenBits > (pcSlice->getSliceSegmentArgument()<<3))
1091    {
1092      pcSlice->setSliceSegmentCurEndCtuTsAddr(validEndOfSliceCtuTsAddr);
1093      boundingCtuTsAddr=validEndOfSliceCtuTsAddr;
1094    }
1095
1096    if (boundingCtuTsAddr <= ctuTsAddr)
1097    {
1098      break;
1099    }
1100
1101    pcSlice->setSliceBits( (UInt)(pcSlice->getSliceBits() + numberOfWrittenBits) );
1102    pcSlice->setSliceSegmentBits(pcSlice->getSliceSegmentBits()+numberOfWrittenBits);
1103
1104    // Store probabilities of second CTU in line into buffer - used only if wavefront-parallel-processing is enabled.
1105    if ( ctuXPosInCtus == tileXPosInCtus+1 && m_pcCfg->getEntropyCodingSyncEnabledFlag())
1106    {
1107      m_entropyCodingSyncContextState.loadContexts(m_pppcRDSbacCoder[0][CI_CURR_BEST]);
1108    }
1109
1110
1111    if ( m_pcCfg->getUseRateCtrl() )
1112    {
1113#if KWU_RC_MADPRED_E0227
1114        UInt SAD    = m_pcCuEncoder->getLCUPredictionSAD();
1115        Int height  = min( pcSlice->getSPS()->getMaxCUHeight(),pcSlice->getSPS()->getPicHeightInLumaSamples() - uiCUAddr / rpcPic->getFrameWidthInCU() * pcSlice->getSPS()->getMaxCUHeight() );
1116        Int width   = min( pcSlice->getSPS()->getMaxCUWidth(),pcSlice->getSPS()->getPicWidthInLumaSamples() - uiCUAddr % rpcPic->getFrameWidthInCU() * pcSlice->getSPS()->getMaxCUWidth() );
1117        Double MAD = (Double)SAD / (Double)(height * width);
1118        MAD = MAD * MAD;
1119        ( m_pcRateCtrl->getRCPic()->getLCU(uiCUAddr) ).m_MAD = MAD;
1120#endif
1121
1122      Int actualQP        = g_RCInvalidQPValue;
1123      Double actualLambda = m_pcRdCost->getLambda();
1124      Int actualBits      = pCtu->getTotalBits();
1125      Int numberOfEffectivePixels    = 0;
1126      for ( Int idx = 0; idx < pcPic->getNumPartitionsInCtu(); idx++ )
1127      {
1128        if ( pCtu->getPredictionMode( idx ) != NUMBER_OF_PREDICTION_MODES && ( !pCtu->isSkipped( idx ) ) )
1129        {
1130          numberOfEffectivePixels = numberOfEffectivePixels + 16;
1131          break;
1132        }
1133      }
1134
1135      if ( numberOfEffectivePixels == 0 )
1136      {
1137        actualQP = g_RCInvalidQPValue;
1138      }
1139      else
1140      {
1141        actualQP = pCtu->getQP( 0 );
1142      }
1143      m_pcRdCost->setLambda(oldLambda, pcSlice->getSPS()->getBitDepths());
1144      m_pcRateCtrl->getRCPic()->updateAfterCTU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,
1145                                                pCtu->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );
1146    }
1147
1148    m_uiPicTotalBits += pCtu->getTotalBits();
1149    m_dPicRdCost     += pCtu->getTotalCost();
1150    m_uiPicDist      += pCtu->getTotalDistortion();
1151  }
1152
1153  // store context state at the end of this slice-segment, in case the next slice is a dependent slice and continues using the CABAC contexts.
1154  if( pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag() )
1155  {
1156    m_lastSliceSegmentEndContextState.loadContexts( m_pppcRDSbacCoder[0][CI_CURR_BEST] );//ctx end of dep.slice
1157  }
1158
1159  // stop use of temporary bit counter object.
1160  m_pppcRDSbacCoder[0][CI_CURR_BEST]->setBitstream(NULL);
1161  m_pcRDGoOnSbacCoder->setBitstream(NULL); // stop use of tempBitCounter.
1162
1163  // TODO: optimise cabac_init during compress slice to improve multi-slice operation
1164  //if (pcSlice->getPPS()->getCabacInitPresentFlag() && !pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag())
1165  //{
1166  //  m_encCABACTableIdx = m_pcEntropyCoder->determineCabacInitIdx();
1167  //}
1168  //else
1169  //{
1170  //  m_encCABACTableIdx = pcSlice->getSliceType();
1171  //}
1172}
1173
1174Void TEncSlice::encodeSlice   ( TComPic* pcPic, TComOutputBitstream* pcSubstreams, UInt &numBinsCoded )
1175{
1176  TComSlice *const pcSlice           = pcPic->getSlice(getSliceIdx());
1177
1178  const UInt startCtuTsAddr          = pcSlice->getSliceSegmentCurStartCtuTsAddr();
1179  const UInt boundingCtuTsAddr       = pcSlice->getSliceSegmentCurEndCtuTsAddr();
1180
1181  const UInt frameWidthInCtus        = pcPic->getPicSym()->getFrameWidthInCtus();
1182  const Bool depSliceSegmentsEnabled = pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag();
1183  const Bool wavefrontsEnabled       = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag();
1184
1185  // initialise entropy coder for the slice
1186  m_pcSbacCoder->init( (TEncBinIf*)m_pcBinCABAC );
1187  m_pcEntropyCoder->setEntropyCoder ( m_pcSbacCoder );
1188  m_pcEntropyCoder->resetEntropy    ( pcSlice );
1189
1190  numBinsCoded = 0;
1191  m_pcBinCABAC->setBinCountingEnableFlag( true );
1192  m_pcBinCABAC->setBinsCoded(0);
1193
1194#if ENC_DEC_TRACE
1195  g_bJustDoIt = g_bEncDecTraceEnable;
1196#endif
1197#if NH_MV_ENC_DEC_TRAC
1198#if ENC_DEC_TRACE
1199  incSymbolCounter();
1200#endif
1201  DTRACE_CABAC_VL( g_nSymbolCounter );
1202#else
1203  DTRACE_CABAC_VL( g_nSymbolCounter++ );
1204#endif
1205  DTRACE_CABAC_T( "\tPOC: " );
1206  DTRACE_CABAC_V( pcPic->getPOC() );
1207#if NH_MV_ENC_DEC_TRAC
1208  DTRACE_CABAC_T( " Layer: " );
1209  DTRACE_CABAC_V( pcPic->getLayerId() );
1210#endif
1211  DTRACE_CABAC_T( "\n" );
1212#if ENC_DEC_TRACE
1213  g_bJustDoIt = g_bEncDecTraceDisable;
1214#endif
1215
1216
1217  if (depSliceSegmentsEnabled)
1218  {
1219    // modify initial contexts with previous slice segment if this is a dependent slice.
1220    const UInt ctuRsAddr        = pcPic->getPicSym()->getCtuTsToRsAddrMap( startCtuTsAddr );
1221    const UInt currentTileIdx=pcPic->getPicSym()->getTileIdxMap(ctuRsAddr);
1222    const TComTile *pCurrentTile=pcPic->getPicSym()->getTComTile(currentTileIdx);
1223    const UInt firstCtuRsAddrOfTile = pCurrentTile->getFirstCtuRsAddr();
1224
1225    if( pcSlice->getDependentSliceSegmentFlag() && ctuRsAddr != firstCtuRsAddrOfTile )
1226    {
1227      if( pCurrentTile->getTileWidthInCtus() >= 2 || !wavefrontsEnabled )
1228      {
1229        m_pcSbacCoder->loadContexts(&m_lastSliceSegmentEndContextState);
1230      }
1231    }
1232  }
1233
1234  // for every CTU in the slice segment...
1235
1236  for( UInt ctuTsAddr = startCtuTsAddr; ctuTsAddr < boundingCtuTsAddr; ++ctuTsAddr )
1237  {
1238    const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr);
1239    const TComTile &currentTile = *(pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr)));
1240    const UInt firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr();
1241    const UInt tileXPosInCtus       = firstCtuRsAddrOfTile % frameWidthInCtus;
1242    const UInt tileYPosInCtus       = firstCtuRsAddrOfTile / frameWidthInCtus;
1243    const UInt ctuXPosInCtus        = ctuRsAddr % frameWidthInCtus;
1244    const UInt ctuYPosInCtus        = ctuRsAddr / frameWidthInCtus;
1245    const UInt uiSubStrm=pcPic->getSubstreamForCtuAddr(ctuRsAddr, true, pcSlice);
1246    TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr );
1247
1248    m_pcEntropyCoder->setBitstream( &pcSubstreams[uiSubStrm] );
1249
1250    // set up CABAC contexts' state for this CTU
1251    if (ctuRsAddr == firstCtuRsAddrOfTile)
1252    {
1253      if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset
1254      {
1255        m_pcEntropyCoder->resetEntropy(pcSlice);
1256      }
1257    }
1258    else if (ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled)
1259    {
1260      // Synchronize cabac probabilities with upper-right CTU if it's available and at the start of a line.
1261      if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset
1262      {
1263        m_pcEntropyCoder->resetEntropy(pcSlice);
1264      }
1265      TComDataCU *pCtuUp = pCtu->getCtuAbove();
1266      if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus)  )
1267      {
1268        TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 );
1269        if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) )
1270        {
1271          // Top-right is available, so use it.
1272          m_pcSbacCoder->loadContexts( &m_entropyCodingSyncContextState );
1273        }
1274      }
1275    }
1276
1277#if NH_3D
1278    pcPic->setReduceBitsFlag(true);
1279#endif
1280    if ( pcSlice->getSPS()->getUseSAO() )
1281    {
1282      Bool bIsSAOSliceEnabled = false;
1283      Bool sliceEnabled[MAX_NUM_COMPONENT];
1284      for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++)
1285      {
1286        ComponentID compId=ComponentID(comp);
1287        sliceEnabled[compId] = pcSlice->getSaoEnabledFlag(toChannelType(compId)) && (comp < pcPic->getNumberValidComponents());
1288        if (sliceEnabled[compId])
1289        {
1290          bIsSAOSliceEnabled=true;
1291        }
1292      }
1293      if (bIsSAOSliceEnabled)
1294      {
1295        SAOBlkParam& saoblkParam = (pcPic->getPicSym()->getSAOBlkParam())[ctuRsAddr];
1296
1297        Bool leftMergeAvail = false;
1298        Bool aboveMergeAvail= false;
1299        //merge left condition
1300        Int rx = (ctuRsAddr % frameWidthInCtus);
1301        if(rx > 0)
1302        {
1303          leftMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-1);
1304        }
1305
1306        //merge up condition
1307        Int ry = (ctuRsAddr / frameWidthInCtus);
1308        if(ry > 0)
1309        {
1310          aboveMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-frameWidthInCtus);
1311        }
1312
1313        m_pcEntropyCoder->encodeSAOBlkParam(saoblkParam, pcPic->getPicSym()->getSPS().getBitDepths(), sliceEnabled, leftMergeAvail, aboveMergeAvail);
1314      }
1315    }
1316
1317#if ENC_DEC_TRACE
1318    g_bJustDoIt = g_bEncDecTraceEnable;
1319#endif
1320      m_pcCuEncoder->encodeCtu( pCtu );
1321#if ENC_DEC_TRACE
1322    g_bJustDoIt = g_bEncDecTraceDisable;
1323#endif
1324
1325    //Store probabilities of second CTU in line into buffer
1326    if ( ctuXPosInCtus == tileXPosInCtus+1 && wavefrontsEnabled)
1327    {
1328      m_entropyCodingSyncContextState.loadContexts( m_pcSbacCoder );
1329    }
1330
1331    // terminate the sub-stream, if required (end of slice-segment, end of tile, end of wavefront-CTU-row):
1332    if (ctuTsAddr+1 == boundingCtuTsAddr ||
1333         (  ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus() &&
1334          ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getTileHeightInCtus() || wavefrontsEnabled)
1335         )
1336       )
1337    {
1338      m_pcEntropyCoder->encodeTerminatingBit(1);
1339      m_pcEntropyCoder->encodeSliceFinish();
1340      // Byte-alignment in slice_data() when new tile
1341      pcSubstreams[uiSubStrm].writeByteAlignment();
1342
1343      // write sub-stream size
1344      if (ctuTsAddr+1 != boundingCtuTsAddr)
1345      {
1346        pcSlice->addSubstreamSize( (pcSubstreams[uiSubStrm].getNumberOfWrittenBits() >> 3) + pcSubstreams[uiSubStrm].countStartCodeEmulations() );
1347      }
1348    }
1349#if NH_3D
1350    pcPic->setReduceBitsFlag(false);
1351#endif
1352  } // CTU-loop
1353
1354  if( depSliceSegmentsEnabled )
1355  {
1356    m_lastSliceSegmentEndContextState.loadContexts( m_pcSbacCoder );//ctx end of dep.slice
1357  }
1358
1359#if ADAPTIVE_QP_SELECTION
1360  if( m_pcCfg->getUseAdaptQpSelect() )
1361  {
1362    m_pcTrQuant->storeSliceQpNext(pcSlice); // TODO: this will only be storing the adaptive QP state of the very last slice-segment that is not dependent in the frame... Perhaps this should be moved to the compress slice loop.
1363  }
1364#endif
1365
1366  if (pcSlice->getPPS()->getCabacInitPresentFlag() && !pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag())
1367  {
1368    m_encCABACTableIdx = m_pcEntropyCoder->determineCabacInitIdx(pcSlice);
1369  }
1370  else
1371  {
1372    m_encCABACTableIdx = pcSlice->getSliceType();
1373  }
1374 
1375  numBinsCoded = m_pcBinCABAC->getBinsCoded();
1376}
1377
1378Void TEncSlice::calculateBoundingCtuTsAddrForSlice(UInt &startCtuTSAddrSlice, UInt &boundingCtuTSAddrSlice, Bool &haveReachedTileBoundary,
1379                                                   TComPic* pcPic, const Int sliceMode, const Int sliceArgument)
1380{
1381  TComSlice* pcSlice = pcPic->getSlice(getSliceIdx());
1382  const UInt numberOfCtusInFrame = pcPic->getNumberOfCtusInFrame();
1383  const TComPPS &pps=*(pcSlice->getPPS());
1384  boundingCtuTSAddrSlice=0;
1385  haveReachedTileBoundary=false;
1386
1387  switch (sliceMode)
1388  {
1389    case FIXED_NUMBER_OF_CTU:
1390      {
1391        UInt ctuAddrIncrement    = sliceArgument;
1392        boundingCtuTSAddrSlice  = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame;
1393      }
1394      break;
1395    case FIXED_NUMBER_OF_BYTES:
1396      boundingCtuTSAddrSlice  = numberOfCtusInFrame; // This will be adjusted later if required.
1397      break;
1398    case FIXED_NUMBER_OF_TILES:
1399      {
1400        const UInt tileIdx        = pcPic->getPicSym()->getTileIdxMap( pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTSAddrSlice) );
1401        const UInt tileTotalCount = (pcPic->getPicSym()->getNumTileColumnsMinus1()+1) * (pcPic->getPicSym()->getNumTileRowsMinus1()+1);
1402        UInt ctuAddrIncrement   = 0;
1403
1404        for(UInt tileIdxIncrement = 0; tileIdxIncrement < sliceArgument; tileIdxIncrement++)
1405        {
1406          if((tileIdx + tileIdxIncrement) < tileTotalCount)
1407          {
1408            UInt tileWidthInCtus   = pcPic->getPicSym()->getTComTile(tileIdx + tileIdxIncrement)->getTileWidthInCtus();
1409            UInt tileHeightInCtus  = pcPic->getPicSym()->getTComTile(tileIdx + tileIdxIncrement)->getTileHeightInCtus();
1410            ctuAddrIncrement    += (tileWidthInCtus * tileHeightInCtus);
1411          }
1412        }
1413
1414        boundingCtuTSAddrSlice  = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame;
1415      }
1416      break;
1417    default:
1418      boundingCtuTSAddrSlice    = numberOfCtusInFrame;
1419      break;
1420  }
1421
1422  // Adjust for tiles and wavefronts.
1423  const Bool wavefrontsAreEnabled = pps.getEntropyCodingSyncEnabledFlag();
1424
1425  if ((sliceMode == FIXED_NUMBER_OF_CTU || sliceMode == FIXED_NUMBER_OF_BYTES) &&
1426      (pps.getNumTileRowsMinus1() > 0 || pps.getNumTileColumnsMinus1() > 0))
1427  {
1428    const UInt ctuRSAddr                  = pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTSAddrSlice);
1429    const UInt startTileIdx               = pcPic->getPicSym()->getTileIdxMap(ctuRSAddr);
1430
1431    const TComTile *pStartingTile         = pcPic->getPicSym()->getTComTile(startTileIdx);
1432    const UInt tileStartTsAddr            = pcPic->getPicSym()->getCtuRsToTsAddrMap(pStartingTile->getFirstCtuRsAddr());
1433    const UInt tileStartWidth             = pStartingTile->getTileWidthInCtus();
1434    const UInt tileStartHeight            = pStartingTile->getTileHeightInCtus();
1435    const UInt tileLastTsAddr_excl        = tileStartTsAddr + tileStartWidth*tileStartHeight;
1436    const UInt tileBoundingCtuTsAddrSlice = tileLastTsAddr_excl;
1437
1438    const UInt ctuColumnOfStartingTile    = ((startCtuTSAddrSlice-tileStartTsAddr)%tileStartWidth);
1439    if (wavefrontsAreEnabled && ctuColumnOfStartingTile!=0)
1440    {
1441      // WPP: if a slice does not start at the beginning of a CTB row, it must end within the same CTB row
1442      const UInt numberOfCTUsToEndOfRow            = tileStartWidth - ctuColumnOfStartingTile;
1443      const UInt wavefrontTileBoundingCtuAddrSlice = startCtuTSAddrSlice + numberOfCTUsToEndOfRow;
1444      if (wavefrontTileBoundingCtuAddrSlice < boundingCtuTSAddrSlice)
1445      {
1446        boundingCtuTSAddrSlice = wavefrontTileBoundingCtuAddrSlice;
1447      }
1448    }
1449
1450    if (tileBoundingCtuTsAddrSlice < boundingCtuTSAddrSlice)
1451    {
1452      boundingCtuTSAddrSlice = tileBoundingCtuTsAddrSlice;
1453      haveReachedTileBoundary = true;
1454    }
1455  }
1456  else if ((sliceMode == FIXED_NUMBER_OF_CTU || sliceMode == FIXED_NUMBER_OF_BYTES) && wavefrontsAreEnabled && ((startCtuTSAddrSlice % pcPic->getFrameWidthInCtus()) != 0))
1457  {
1458    // Adjust for wavefronts (no tiles).
1459    // WPP: if a slice does not start at the beginning of a CTB row, it must end within the same CTB row
1460    boundingCtuTSAddrSlice = min(boundingCtuTSAddrSlice, startCtuTSAddrSlice - (startCtuTSAddrSlice % pcPic->getFrameWidthInCtus()) + (pcPic->getFrameWidthInCtus()));
1461  }
1462}
1463
1464/** Determines the starting and bounding CTU address of current slice / dependent slice
1465 * \param [out] startCtuTsAddr
1466 * \param [out] boundingCtuTsAddr
1467 * \param [in]  pcPic
1468
1469 * Updates startCtuTsAddr, boundingCtuTsAddr with appropriate CTU address
1470 */
1471Void TEncSlice::xDetermineStartAndBoundingCtuTsAddr  ( UInt& startCtuTsAddr, UInt& boundingCtuTsAddr, TComPic* pcPic )
1472{
1473  TComSlice* pcSlice                 = pcPic->getSlice(getSliceIdx());
1474
1475  // Non-dependent slice
1476  UInt startCtuTsAddrSlice           = pcSlice->getSliceCurStartCtuTsAddr();
1477  Bool haveReachedTileBoundarySlice  = false;
1478  UInt boundingCtuTsAddrSlice;
1479  calculateBoundingCtuTsAddrForSlice(startCtuTsAddrSlice, boundingCtuTsAddrSlice, haveReachedTileBoundarySlice, pcPic,
1480                                     m_pcCfg->getSliceMode(), m_pcCfg->getSliceArgument());
1481  pcSlice->setSliceCurEndCtuTsAddr(   boundingCtuTsAddrSlice );
1482  pcSlice->setSliceCurStartCtuTsAddr( startCtuTsAddrSlice    );
1483
1484  // Dependent slice
1485  UInt startCtuTsAddrSliceSegment          = pcSlice->getSliceSegmentCurStartCtuTsAddr();
1486  Bool haveReachedTileBoundarySliceSegment = false;
1487  UInt boundingCtuTsAddrSliceSegment;
1488  calculateBoundingCtuTsAddrForSlice(startCtuTsAddrSliceSegment, boundingCtuTsAddrSliceSegment, haveReachedTileBoundarySliceSegment, pcPic,
1489                                     m_pcCfg->getSliceSegmentMode(), m_pcCfg->getSliceSegmentArgument());
1490  if (boundingCtuTsAddrSliceSegment>boundingCtuTsAddrSlice)
1491  {
1492    boundingCtuTsAddrSliceSegment = boundingCtuTsAddrSlice;
1493  }
1494  pcSlice->setSliceSegmentCurEndCtuTsAddr( boundingCtuTsAddrSliceSegment );
1495  pcSlice->setSliceSegmentCurStartCtuTsAddr(startCtuTsAddrSliceSegment);
1496
1497  // Make a joint decision based on reconstruction and dependent slice bounds
1498  startCtuTsAddr    = max(startCtuTsAddrSlice   , startCtuTsAddrSliceSegment   );
1499  boundingCtuTsAddr = boundingCtuTsAddrSliceSegment;
1500}
1501
1502Double TEncSlice::xGetQPValueAccordingToLambda ( Double lambda )
1503{
1504  return 4.2005*log(lambda) + 13.7122;
1505}
1506
1507//! \}
Note: See TracBrowser for help on using the repository browser.