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

Last change on this file since 1502 was 1502, checked in by seregin, 8 years ago

infer parameters in SPS after activation, fixing chroma scaling for non 4:2:0

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