source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibEncoder/TEncSlice.cpp @ 1529

Last change on this file since 1529 was 1527, checked in by seregin, 9 years ago

replace layerId with layerIdx

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