source: 3DVCSoftware/branches/HTM-15.1-dev0/source/Lib/TLibEncoder/TEncSlice.cpp @ 1327

Last change on this file since 1327 was 1313, checked in by tech, 9 years ago

Merged 14.1-update-dev1@1312.

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