Ticket #42: TEncSlice.cpp

File TEncSlice.cpp, 30.1 KB (added by anonymous, 14 years ago)
Line 
1/* ====================================================================================================================
2
3  The copyright in this software is being made available under the License included below.
4  This software may be subject to other third party and   contributor rights, including patent rights, and no such
5  rights are granted under this license.
6
7  Copyright (c) 2010, SAMSUNG ELECTRONICS CO., LTD. and BRITISH BROADCASTING CORPORATION
8  All rights reserved.
9
10  Redistribution and use in source and binary forms, with or without modification, are permitted only for
11  the purpose of developing standards within the Joint Collaborative Team on Video Coding and for testing and
12  promoting such standards. The following conditions are required to be met:
13
14    * Redistributions of source code must retain the above copyright notice, this list of conditions and
15      the following disclaimer.
16    * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
17      the following disclaimer in the documentation and/or other materials provided with the distribution.
18    * Neither the name of SAMSUNG ELECTRONICS CO., LTD. nor the name of the BRITISH BROADCASTING CORPORATION
19      may be used to endorse or promote products derived from this software without specific prior written permission.
20
21  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
22  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
29 * ====================================================================================================================
30*/
31
32/** \file     TEncSlice.cpp
33    \brief    slice encoder class
34*/
35
36#include "TEncTop.h"
37#include "TEncSlice.h"
38
39// ====================================================================================================================
40// Constructor / destructor / create / destroy
41// ====================================================================================================================
42
43TEncSlice::TEncSlice()
44{
45  m_apcPicYuvPred = NULL;
46  m_apcPicYuvResi = NULL;
47
48  for (Int i=0; i<GRF_MAX_NUM_EFF; i++)
49  for (Int j=0; j<2; j++)
50  {
51    m_apcVirtPic[j][i] = NULL;
52  }
53
54  m_pdRdPicLambda = NULL;
55  m_pdRdPicQp     = NULL;
56  m_piRdPicQp     = NULL;
57
58  m_uiV2V = 0;
59}
60TEncSlice::~TEncSlice()
61{
62}
63
64Void TEncSlice::create( Int iWidth, Int iHeight, 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, iMaxCUWidth, iMaxCUHeight, uhTotalDepth );
71  }
72
73  // create residual picture
74  if( m_apcPicYuvResi == NULL )
75  {
76    m_apcPicYuvResi  = new TComPicYuv;
77    m_apcPicYuvResi->create( iWidth, iHeight, iMaxCUWidth, iMaxCUHeight, uhTotalDepth );
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 virtual reference pictures if they were allocated
100  for (Int i=0; i<GRF_MAX_NUM_EFF; i++)
101  for (Int j=0; j<2; j++)
102  {
103    if(m_apcVirtPic[j][i])
104    {
105      m_apcVirtPic[j][i]->destroy();
106      delete m_apcVirtPic[j][i];
107      m_apcVirtPic[j][i]=NULL;
108    }
109  }
110
111  // free lambda and QP arrays
112  if ( m_pdRdPicLambda ) { xFree( m_pdRdPicLambda ); m_pdRdPicLambda = NULL; }
113  if ( m_pdRdPicQp     ) { xFree( m_pdRdPicQp     ); m_pdRdPicQp     = NULL; }
114  if ( m_piRdPicQp     ) { xFree( m_piRdPicQp     ); m_piRdPicQp     = NULL; }
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_pcCavlcCoder      = pcEncTop->getCavlcCoder();
128  m_pcSbacCoder       = pcEncTop->getSbacCoder();
129  m_pcBinCABAC        = pcEncTop->getBinCABAC();
130  m_pcBinMultiCABAC   = pcEncTop->getBinMultiCABAC();
131  m_pcBinPIPE         = pcEncTop->getBinPIPE();
132  m_pcBinMultiPIPE    = pcEncTop->getBinMultiPIPE();
133  m_pcBinV2VwLB       = pcEncTop->getBinV2VwLB();
134  m_pcTrQuant         = pcEncTop->getTrQuant();
135  m_pcBinCABAC4V2V    = pcEncTop->getBinCABAC4V2V();
136
137  m_pcBitCounter      = pcEncTop->getBitCounter();
138  m_pcRdCost          = pcEncTop->getRdCost();
139  m_pppcRDSbacCoder   = pcEncTop->getRDSbacCoder();
140  m_pcRDGoOnSbacCoder = pcEncTop->getRDGoOnSbacCoder();
141
142  // create lambda and QP arrays
143  m_pdRdPicLambda     = (Double*)xMalloc( Double, m_pcCfg->getDeltaQpRD() * 2 + 1 );
144  m_pdRdPicQp         = (Double*)xMalloc( Double, m_pcCfg->getDeltaQpRD() * 2 + 1 );
145  m_piRdPicQp         = (Int*   )xMalloc( Int,    m_pcCfg->getDeltaQpRD() * 2 + 1 );
146
147  // allocate additional reference frame here
148  if ( m_pcCfg->getGRefMode() != NULL )
149  {
150    UInt uiNumEffFrames = 0;
151    if ( pcEncTop->getSPS()->getUseWPG() || pcEncTop->getSPS()->getUseWPO() ) uiNumEffFrames++;
152
153    Int iWidth    = m_apcPicYuvPred->getWidth ();
154    Int iHeight   = m_apcPicYuvPred->getHeight();
155
156    for ( Int i=0; i<uiNumEffFrames; i++ )
157    for ( Int j=0; j<2; j++ )
158    {
159      if ( m_apcVirtPic[j][i] == NULL)
160      {
161        m_apcVirtPic[j][i] = new TComPic;
162        m_apcVirtPic[j][i]->create( iWidth, iHeight, g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth, true );
163      }
164    }
165  }
166}
167
168/**
169   - non-referenced frame marking
170   - QP computation based on temporal structure
171   - lambda computation based on QP
172   .
173   \param pcPic         picture class
174   \param iPOCLast      POC of last picture
175   \param uiPOCCurr     current POC
176   \param iNumPicRcvd   number of received pictures
177   \param iTimeOffset   POC offset for hierarchical structure
178   \param iDepth        temporal layer depth
179   \param rpcSlice      slice header class
180 */
181Void TEncSlice::initEncSlice( TComPic* pcPic, Int iPOCLast, UInt uiPOCCurr, Int iNumPicRcvd, Int iTimeOffset, Int iDepth, TComSlice*& rpcSlice )
182{
183  Double dQP;
184  Double dLambda;
185
186  rpcSlice = pcPic->getSlice();
187  rpcSlice->setPic( pcPic );
188  rpcSlice->initSlice();
189
190  // depth re-computation based on rate GOP size
191  if ( m_pcCfg->getGOPSize() != m_pcCfg->getRateGOPSize() )
192  {
193    Int i, j;
194    Int iPOC = rpcSlice->getPOC()%m_pcCfg->getRateGOPSize();
195    if ( iPOC == 0 ) iDepth = 0;
196    else
197    {
198      Int iStep = m_pcCfg->getRateGOPSize();
199      iDepth    = 0;
200      for( i=iStep>>1; i>=1; i>>=1 )
201      {
202        for ( j=i; j<m_pcCfg->getRateGOPSize(); j+=iStep )
203        {
204          if ( j == iPOC )
205          {
206            i=0;
207            break;
208          }
209        }
210        iStep>>=1;
211        iDepth++;
212      }
213    }
214  }
215
216  // slice type
217  SliceType eSliceType;
218
219#if !HB_LAMBDA_FOR_LDC
220  if ( m_pcCfg->getUseLDC() )
221  {
222    eSliceType = P_SLICE;
223  }
224  else
225#endif
226  {
227    eSliceType = iDepth > 0 ? B_SLICE : P_SLICE;
228  }
229  eSliceType = (iPOCLast == 0 || uiPOCCurr % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
230
231  rpcSlice->setSliceType    ( eSliceType );
232  rpcSlice->setPOC          ( iPOCLast - iNumPicRcvd + iTimeOffset );
233
234  // ------------------------------------------------------------------------------------------------------------------
235  // Non-referenced frame marking
236  // ------------------------------------------------------------------------------------------------------------------
237
238  if ( m_pcCfg->getUseNRF() )
239  {
240    if ( ( m_pcCfg->getRateGOPSize() != 1) && (m_pcCfg->getRateGOPSize() >> (iDepth+1)) == 0 )
241    {
242      rpcSlice->setReferenced(false);
243    }
244    else
245    {
246      rpcSlice->setReferenced(true);
247    }
248  }
249  else
250  {
251    rpcSlice->setReferenced(true);
252  }
253
254  // ------------------------------------------------------------------------------------------------------------------
255  // QP setting
256  // ------------------------------------------------------------------------------------------------------------------
257
258  dQP = m_pcCfg->getQP();
259  if ( iDepth < MAX_TLAYER && m_pcCfg->getTemporalLayerQPOffset(iDepth) != ( MAX_QP + 1 ) )
260  {
261    dQP += m_pcCfg->getTemporalLayerQPOffset(iDepth);
262  }
263  else
264  {
265    if ( ( iPOCLast != 0 ) && ( ( uiPOCCurr % m_pcCfg->getIntraPeriod() ) != 0 ) && ( m_pcGOPEncoder->getGOPSize() != 0 ) ) // P or B-slice
266    {
267      if ( m_pcCfg->getUseLDC() && !m_pcCfg->getUseBQP() )
268      {
269        if ( iDepth == 0 ) dQP += 1.0;
270        else
271        {
272          dQP += iDepth+3;
273        }
274      }
275      else
276      {
277         dQP += iDepth+1;
278      }
279    }
280  }
281
282  // modify QP
283  Int* pdQPs = m_pcCfg->getdQPs();
284  if ( pdQPs )
285  {
286    dQP += pdQPs[ pcPic->getSlice()->getPOC() ];
287  }
288
289  // ------------------------------------------------------------------------------------------------------------------
290  // Lambda computation
291  // ------------------------------------------------------------------------------------------------------------------
292
293  Int iQP;
294  Double dOrigQP = dQP;
295
296  // pre-compute lambda and QP values for all possible QP candidates
297  for ( Int iDQpIdx = 0; iDQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; iDQpIdx++ )
298  {
299    // compute QP value
300    dQP = dOrigQP + ((iDQpIdx+1)>>1)*(iDQpIdx%2 ? -1 : 1);
301
302    // compute lambda value
303    Int    NumberBFrames = ( m_pcCfg->getRateGOPSize() - 1 );
304    Int    SHIFT_QP = 12;
305    Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );
306    Int    bitdepth_luma_qp_scale = 0;
307    Double qp_temp = (double) dQP + bitdepth_luma_qp_scale - SHIFT_QP;
308
309    // Case #1: I or P-slices (key-frame)
310    if ( iDepth == 0 )
311    {
312#if QC_MDDT
313      if ( pcPic->getSlice()->isIntra() && dQP == dOrigQP )
314#else
315      if ( m_pcCfg->getUseRDOQ() && pcPic->getSlice()->isIntra() && dQP == dOrigQP )
316#endif
317      {
318        dLambda = 0.57 * pow( 2.0, qp_temp/3.0 );
319      }
320      else
321      {
322        if ( NumberBFrames > 0 ) // HB structure or HP structure
323        {
324          dLambda = 0.68 * pow( 2.0, qp_temp/3.0 );
325        }
326        else                     // IPP structure
327        {
328          dLambda = 0.85 * pow( 2.0, qp_temp/3.0 );
329        }
330      }
331      dLambda *= dLambda_scale;
332    }
333    else // P or B slices for HB or HP structure
334    {
335      dLambda = 0.68 * pow( 2.0, qp_temp/3.0 );
336      if ( pcPic->getSlice()->isInterB () )
337      {
338        dLambda *= Clip3( 2.00, 4.00, (qp_temp / 6.0) ); // (j == B_SLICE && p_cur_frm->layer != 0 )
339        if ( rpcSlice->isReferenced() ) // HB structure and referenced
340        {
341          Int    iMaxDepth = 0;
342          Int    iCnt = 1;
343          Int    hierarchy_layer;
344
345          while ( iCnt < m_pcCfg->getRateGOPSize() ) { iCnt <<= 1; iMaxDepth++; }
346          hierarchy_layer = iMaxDepth - iDepth;
347
348          dLambda *= 0.80;
349          dLambda *= dLambda_scale;
350        }
351      }
352      else
353      {
354        dLambda *= dLambda_scale;
355      }
356    }
357    // if hadamard is used in ME process
358    if ( !m_pcCfg->getUseHADME() ) dLambda *= 0.95;
359
360    iQP = Max( MIN_QP, Min( MAX_QP, (Int)floor( dQP + 0.5 ) ) );
361
362    m_pdRdPicLambda[iDQpIdx] = dLambda;
363    m_pdRdPicQp    [iDQpIdx] = dQP;
364    m_piRdPicQp    [iDQpIdx] = iQP;
365  }
366
367  // obtain dQP = 0 case
368  dLambda = m_pdRdPicLambda[0];
369  dQP     = m_pdRdPicQp    [0];
370  iQP     = m_piRdPicQp    [0];
371
372  // store lambda
373  m_pcRdCost ->setLambda( dLambda );
374  m_pcTrQuant->setLambda( dLambda );
375  rpcSlice   ->setLambda( dLambda );
376
377#if HB_LAMBDA_FOR_LDC
378  // restore original slice type
379  if ( m_pcCfg->getUseLDC() )
380  {
381    eSliceType = P_SLICE;
382  }
383  eSliceType = (iPOCLast == 0 || uiPOCCurr % m_pcCfg->getIntraPeriod() == 0 || m_pcGOPEncoder->getGOPSize() == 0) ? I_SLICE : eSliceType;
384
385  rpcSlice->setSliceType        ( eSliceType );
386#endif
387
388  rpcSlice->setSliceQp          ( iQP );
389  rpcSlice->setSliceQpDelta     ( 0 );
390  rpcSlice->setNumRefIdx        ( REF_PIC_LIST_0, eSliceType == P_SLICE ? m_pcCfg->getNumOfReference() : (eSliceType == B_SLICE ? (m_pcCfg->getNumOfReferenceB_L0()) : 0 ) );
391  rpcSlice->setNumRefIdx        ( REF_PIC_LIST_1, eSliceType == B_SLICE ? (m_pcCfg->getNumOfReferenceB_L1()) : 0 );
392
393  rpcSlice->setSymbolMode       ( m_pcCfg->getSymbolMode());
394  rpcSlice->setMultiCodeword    ( false );
395  rpcSlice->setMaxPIPEDelay     ( m_pcCfg->getMaxPIPEDelay() );
396  rpcSlice->setLoopFilterDisable( m_pcCfg->getLoopFilterDisable() );
397
398  rpcSlice->setDepth            ( iDepth );
399
400  // reference picture usage indicator for next frames
401  rpcSlice->setDRBFlag          ( true );
402  rpcSlice->setERBIndex         ( ERB_NONE );
403
404  // generalized B info. (for non-reference B)
405  if ( m_pcCfg->getHierarchicalCoding() == false && iDepth != 0 )
406  {
407    rpcSlice->setDRBFlag        ( false );
408    rpcSlice->setERBIndex       ( ERB_NONE );
409  }
410
411  assert( m_apcPicYuvPred );
412  assert( m_apcPicYuvResi );
413
414  pcPic->setPicYuvPred( m_apcPicYuvPred );
415  pcPic->setPicYuvResi( m_apcPicYuvResi );
416#ifdef EDGE_BASED_PREDICTION
417  //Initialisation of edge based prediction for this slice
418  m_pcPredSearch->getEdgeBasedPred()->setEdgePredictionEnable(m_pcCfg->getEdgePredictionEnable());
419  m_pcPredSearch->getEdgeBasedPred()->setThreshold(m_pcCfg->getEdgeDetectionThreshold());
420  rpcSlice->setEdgePredictionEnable(m_pcCfg->getEdgePredictionEnable());
421  rpcSlice->setEdgeDetectionThreshold(m_pcCfg->getEdgeDetectionThreshold());
422#endif //EDGE_BASED_PREDICTION
423#if HHI_INTERP_FILTER
424  rpcSlice->setInterpFilterType ( m_pcCfg->getInterpFilterType() );
425#endif
426}
427
428// ====================================================================================================================
429// Public member functions
430// ====================================================================================================================
431
432Void TEncSlice::setSearchRange( TComSlice* pcSlice )
433{
434  Int iCurrPOC = pcSlice->getPOC();
435  Int iRefPOC;
436  Int iRateGOPSize = m_pcCfg->getRateGOPSize();
437  Int iOffset = (iRateGOPSize >> 1);
438  Int iMaxSR = m_pcCfg->getSearchRange();
439  Int iNumPredDir = pcSlice->isInterP() ? 1 : 2;
440
441  for (Int iDir = 0; iDir <= iNumPredDir; iDir++)
442  {
443    RefPicList e = (RefPicList)iDir;
444    for (Int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(e); iRefIdx++)
445    {
446      iRefPOC = pcSlice->getRefPic(e, iRefIdx)->getPOC();
447      Int iNewSR = Clip3(8, iMaxSR, (iMaxSR*ADAPT_SR_SCALE*abs(iCurrPOC - iRefPOC)+iOffset)/iRateGOPSize);
448      m_pcPredSearch->setAdaptiveSearchRange(iDir, iRefIdx, iNewSR);
449    }
450  }
451}
452
453/**
454   - multi-loop slice encoding for different slice QP
455   .
456   \param rpcPic    picture class
457 */
458Void TEncSlice::precompressSlice( TComPic*& rpcPic )
459{
460  // if deltaQP RD is not used, simply return
461  if ( m_pcCfg->getDeltaQpRD() == 0 ) return;
462
463  TComSlice* pcSlice        = rpcPic->getSlice();
464  Double     dPicRdCostBest = MAX_DOUBLE;
465  Double dSumCURdCostBest;
466  UInt64     uiPicDistBest;
467  UInt64     uiPicBitsBest;
468  UInt       uiQpIdxBest = 0;
469
470  Double dFrameLambda;
471  Int    SHIFT_QP = 12;
472
473  // set frame lambda
474  if (m_pcCfg->getGOPSize() > 1)
475  {
476    dFrameLambda = 0.68 * pow (2, (m_piRdPicQp[0]  - SHIFT_QP) / 3.0) * (pcSlice->isInterB()? 2 : 1);
477  }
478  else
479  {
480    dFrameLambda = 0.68 * pow (2, (m_piRdPicQp[0] - SHIFT_QP) / 3.0);
481  }
482  m_pcRdCost      ->setFrameLambda(dFrameLambda);
483
484  // for each QP candidate
485  for ( UInt uiQpIdx = 0; uiQpIdx < 2 * m_pcCfg->getDeltaQpRD() + 1; uiQpIdx++ )
486  {
487    pcSlice       ->setSliceQp             ( m_piRdPicQp    [uiQpIdx] );
488    m_pcRdCost    ->setLambda              ( m_pdRdPicLambda[uiQpIdx] );
489    m_pcTrQuant   ->setLambda              ( m_pdRdPicLambda[uiQpIdx] );
490    pcSlice       ->setLambda              ( m_pdRdPicLambda[uiQpIdx] );
491
492    // try compress
493    compressSlice   ( rpcPic );
494
495    Double dPicRdCost;
496      UInt64 uiPicDist        = m_uiPicDist;
497    UInt64 uiALFBits        = 0;
498
499    m_pcGOPEncoder->preLoopFilterPicAll( rpcPic, uiPicDist, uiALFBits );
500
501    // compute RD cost and choose the best
502    dPicRdCost = m_pcRdCost->calcRdCost64( m_uiPicTotalBits + uiALFBits, uiPicDist, true, DF_SSE_FRAME);
503
504    if ( dPicRdCost < dPicRdCostBest )
505    {
506      uiQpIdxBest    = uiQpIdx;
507      dPicRdCostBest = dPicRdCost;
508      dSumCURdCostBest = m_dPicRdCost;
509
510      uiPicBitsBest = m_uiPicTotalBits + uiALFBits;
511      uiPicDistBest = uiPicDist;
512    }
513  }
514
515  // set best values
516  pcSlice       ->setSliceQp             ( m_piRdPicQp    [uiQpIdxBest] );
517  m_pcRdCost    ->setLambda              ( m_pdRdPicLambda[uiQpIdxBest] );
518  m_pcTrQuant   ->setLambda              ( m_pdRdPicLambda[uiQpIdxBest] );
519  pcSlice       ->setLambda              ( m_pdRdPicLambda[uiQpIdxBest] );
520}
521
522/** \param rpcPic   picture class
523 */
524Void TEncSlice::compressSlice( TComPic*& rpcPic )
525{
526  UInt  uiCUAddr;
527
528  // initialize cost values
529  m_uiPicTotalBits  = 0;
530  m_dPicRdCost      = 0;
531  m_uiPicDist       = 0;
532
533#if QC_MDDT
534    InitScanOrderForSlice(); 
535#endif
536
537  // set entropy coder
538  if( m_pcCfg->getUseSBACRD() )
539  {
540    m_pcSbacCoder->init( m_pcBinCABAC );
541    m_pcEntropyCoder->setEntropyCoder   ( m_pcSbacCoder, rpcPic->getSlice() );
542    m_pcEntropyCoder->resetEntropy      ();
543    m_pppcRDSbacCoder[0][CI_CURR_BEST]->load(m_pcSbacCoder);
544  }
545  else
546  {
547    m_pcCavlcCoder  ->setAdaptFlag    ( false );
548    m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, rpcPic->getSlice() );
549    m_pcEntropyCoder->resetEntropy      ();
550    m_pcEntropyCoder->setBitstream    ( m_pcBitCounter );
551  }
552
553  // initialize ALF parameters
554  m_pcEntropyCoder->setAlfCtrl(false);
555  m_pcEntropyCoder->setMaxAlfCtrlDepth(0); //unnecessary
556
557#if !HHI_TRANSFORM_CODING
558  m_pcTrQuant->precalculateUnaryExpGolombLevel();
559#endif
560
561  // for every CU
562  for( uiCUAddr = 0; uiCUAddr < rpcPic->getPicSym()->getNumberOfCUsInFrame() ; uiCUAddr++ )
563  {
564    // set QP
565    m_pcCuEncoder->setQpLast( rpcPic->getSlice()->getSliceQp() );
566
567    // initialize CU encoder
568    TComDataCU*& pcCU = rpcPic->getCU( uiCUAddr );
569    pcCU->initCU( rpcPic, uiCUAddr );
570
571    // if RD based on SBAC is used
572    if( m_pcCfg->getUseSBACRD() )
573    {
574      // set go-on entropy coder
575      m_pcEntropyCoder->setEntropyCoder ( m_pcRDGoOnSbacCoder, rpcPic->getSlice() );
576      m_pcEntropyCoder->setBitstream    ( m_pcBitCounter );
577
578      // run CU encoder
579      m_pcCuEncoder->compressCU( pcCU );
580
581      // restore entropy coder to an initial stage
582      m_pcEntropyCoder->setEntropyCoder ( m_pppcRDSbacCoder[0][CI_CURR_BEST], rpcPic->getSlice() );
583      m_pcEntropyCoder->setBitstream    ( m_pcBitCounter );
584
585      m_pcCuEncoder->encodeCU( pcCU );
586#if QC_MDDT//ADAPTIVE_SCAN
587      updateScanOrder(0);
588      normalizeScanStats();
589#endif
590    }
591    // other case: encodeCU is not called
592    else
593    {
594      m_pcCuEncoder->compressCU( pcCU );
595#if NEWVLC_ADAPT_ENABLE
596      m_pcCavlcCoder ->setAdaptFlag(true);
597      m_pcCuEncoder->encodeCU( pcCU );
598
599#if QC_MDDT
600      updateScanOrder(0);
601            normalizeScanStats();
602#endif
603      m_pcCavlcCoder ->setAdaptFlag(false);
604#endif
605    }
606
607    m_uiPicTotalBits += pcCU->getTotalBits();
608    m_dPicRdCost     += pcCU->getTotalCost();
609    m_uiPicDist      += pcCU->getTotalDistortion();
610  }
611}
612
613/** \param  rpcPic        picture class
614    \retval rpcBitstream  bitstream class
615 */
616Void TEncSlice::encodeSlice   ( TComPic*& rpcPic, TComBitstream*& rpcBitstream )
617{
618  UInt       uiCUAddr;
619  TComSlice* pcSlice = rpcPic->getSlice();
620
621  // choose entropy coder
622  Int iSymbolMode = pcSlice->getSymbolMode();
623  if (iSymbolMode)
624  {
625    if( pcSlice->getSymbolMode() == 3 )
626    {
627      m_pcSbacCoder->init( (TEncBinIf*)m_pcBinV2VwLB );
628    }
629    else if( pcSlice->getSymbolMode() == 1 )
630    {
631      if(m_uiV2V)
632      {
633        m_pcSbacCoder->init( (TEncBinIf*)m_pcBinCABAC4V2V );
634      }
635      else
636      {
637        m_pcSbacCoder->init( pcSlice->getMultiCodeword() ? (TEncBinIf*)m_pcBinMultiCABAC : (TEncBinIf*)m_pcBinCABAC );
638      }
639    }
640    else if( pcSlice->getMultiCodeword() )
641    {
642      m_pcSbacCoder->init( (TEncBinIf*)m_pcBinMultiPIPE );
643    }
644    else
645    {
646      m_pcSbacCoder->init( (TEncBinIf*)m_pcBinPIPE );
647      m_pcBinPIPE ->initDelay( pcSlice->getMaxPIPEDelay() );
648    }
649    m_pcEntropyCoder->setEntropyCoder ( m_pcSbacCoder, pcSlice );
650  }
651  else
652  {
653    m_pcCavlcCoder  ->setAdaptFlag( true );
654    m_pcEntropyCoder->setEntropyCoder ( m_pcCavlcCoder, pcSlice );
655#if NEWVLC_ADAPT_ENABLE
656    m_pcEntropyCoder->resetEntropy();
657#endif
658  }
659
660  // set bitstream
661  m_pcEntropyCoder->setBitstream( rpcBitstream );
662#if QC_MDDT//ADAPTIVE_SCAN
663    InitScanOrderForSlice(); 
664#endif
665  // for every CU
666#if HHI_RQT
667#if ENC_DEC_TRACE
668  g_bJustDoIt = g_bEncDecTraceEnable;
669#endif
670  DTRACE_CABAC_V( g_nSymbolCounter++ );
671  DTRACE_CABAC_T( "\tPOC: " );
672  DTRACE_CABAC_V( rpcPic->getPOC() );
673  DTRACE_CABAC_T( "\n" );
674#if ENC_DEC_TRACE
675  g_bJustDoIt = g_bEncDecTraceDisable;
676#endif
677#endif
678  for( uiCUAddr = 0; uiCUAddr < rpcPic->getPicSym()->getNumberOfCUsInFrame() ; uiCUAddr++ )
679  {
680    m_pcCuEncoder->setQpLast( rpcPic->getSlice()->getSliceQp() );
681
682    TComDataCU*& pcCU = rpcPic->getCU( uiCUAddr );
683#if HHI_RQT
684#if ENC_DEC_TRACE
685    g_bJustDoIt = g_bEncDecTraceEnable;
686#endif
687#endif
688    m_pcCuEncoder->encodeCU( pcCU );
689#if HHI_RQT
690#if ENC_DEC_TRACE
691    g_bJustDoIt = g_bEncDecTraceDisable;
692#endif
693#endif
694
695#if QC_MDDT//ADAPTIVE_SCAN
696        // synchronize with the scanning table with the one we obtain in compressSlice()
697    updateScanOrder(0);
698        normalizeScanStats();
699#endif
700  }
701}
702
703Void TEncSlice::generateRefPicNew ( TComSlice* rpcSlice )
704{
705  if (rpcSlice->getSliceType() == I_SLICE)
706  {
707    return;
708  }
709
710  // initialize number of additional reference count
711  rpcSlice->clearAddRefCnt(REF_PIC_LIST_0);
712  rpcSlice->clearAddRefCnt(REF_PIC_LIST_1);
713
714  // check generation modes
715  if ( rpcSlice->getSPS()->getUseWPG() )
716  {
717    rpcSlice->setWPmode(REF_PIC_LIST_0, 1);
718    rpcSlice->addEffectMode(REF_PIC_LIST_0, EFF_WP_SO);   // scale + offset
719
720    rpcSlice->setWPmode(REF_PIC_LIST_1, 1);
721    rpcSlice->addEffectMode(REF_PIC_LIST_1, EFF_WP_SO);   // scale + offset
722  }
723
724  if ( rpcSlice->getSPS()->getUseWPO() )
725  {
726    rpcSlice->setWPmode(REF_PIC_LIST_0, 1);
727    rpcSlice->addEffectMode(REF_PIC_LIST_0, EFF_WP_O);    // scale
728
729    rpcSlice->setWPmode(REF_PIC_LIST_1, 1);
730    rpcSlice->addEffectMode(REF_PIC_LIST_1, EFF_WP_O);    // scale
731  }
732
733  // if no virtual reference is needed, return
734  if (rpcSlice->getAddRefCnt(REF_PIC_LIST_0) == 0 && rpcSlice->getAddRefCnt(REF_PIC_LIST_1) == 0) return;
735
736  // set virtual reference buffer
737  rpcSlice->setVirtRefBuffer( m_apcVirtPic );
738
739  // for each direction
740  for ( Int iDir = 0; iDir < (rpcSlice->getSliceType() == P_SLICE ? 1 :2); iDir++ )
741  {
742    RefPicList eRefPicList = (RefPicList) iDir;
743
744    // for each added effect
745    for ( Int i = 0; i < rpcSlice->getAddRefCnt(eRefPicList); i++ )
746    {
747      EFF_MODE eEffMode = rpcSlice->getEffectMode(eRefPicList, i);
748      if (eEffMode >= EFF_WP_SO && eEffMode <= EFF_WP_O)
749      {
750        Bool bGen = xEstimateWPSlice(rpcSlice, eRefPicList, eEffMode);
751        if (bGen) rpcSlice->generateWPSlice(eRefPicList, eEffMode, i);
752      }
753    }
754
755    // remove unnecessary virtual references here if net effect is same
756    if ( rpcSlice->getWPmode(eRefPicList) )
757    {
758      EFF_MODE eEffMode = (rpcSlice->getSPS()->getUseWPG()? EFF_WP_SO : EFF_WP_O);
759      if (rpcSlice->isEqualWPAllParam(eRefPicList, eEffMode, EFF_NONE))
760      {
761        rpcSlice->removeEffectMode(eRefPicList, eEffMode);
762        rpcSlice->setWPmode(eRefPicList, 0);
763      }
764    }
765  }
766
767  // add virtual reference to reference list
768  rpcSlice->linkVirtRefPic();
769}
770
771Bool TEncSlice::xEstimateWPSlice( TComSlice* rpcSlice, RefPicList eRefPicList, EFF_MODE eEffMode )
772{
773  Int iDefaultWeight[3];
774  Int iWeight       [3] = {0, 0, 0};
775  Int iOffset       [3] = {0, 0, 0};
776
777  Double dDCOrg   = 0.;
778  Double dDCRef   = 0.;
779  Double dNormOrg = 0.;
780  Double dNormRef = 0.;
781  Double dNumer   = 0.;
782  Double dDenom   = 0.;
783
784  TComPicYuv* pcPicYuvOrg = rpcSlice->getPic()->getPicYuvOrg();
785  TComPicYuv* pcPicYuvRef;
786
787  Int iWidth = pcPicYuvOrg->getWidth();
788  Int iHeight = pcPicYuvOrg->getHeight();
789  Int iStride = pcPicYuvOrg->getStride();
790
791  rpcSlice->initWPAllParam(eRefPicList, eEffMode);
792
793  iDefaultWeight[0] = rpcSlice->getWPWeight(eRefPicList, eEffMode, 0);
794  iDefaultWeight[1] = rpcSlice->getWPWeight(eRefPicList, eEffMode, 1);
795  iDefaultWeight[2] = rpcSlice->getWPWeight(eRefPicList, eEffMode, 2);
796
797  dDCOrg   = xComputeImgSum(pcPicYuvOrg->getLumaAddr(), iWidth, iHeight, iStride);
798  dNormOrg = dDCOrg / (Double)(iWidth * iHeight);
799  dNumer   = xComputeNormMean(pcPicYuvOrg->getLumaAddr(), dNormOrg, iWidth, iHeight, iStride);
800
801  Int iShift = g_uiBitDepth+g_uiBitIncrement-8;
802
803  // Luma
804  pcPicYuvRef = rpcSlice->getRefPic(eRefPicList, 0)->getPicYuvRec();
805  iWidth      = pcPicYuvRef->getWidth ();
806  iHeight     = pcPicYuvRef->getHeight();
807  iStride     = pcPicYuvRef->getStride();
808
809  dDCRef    = xComputeImgSum(pcPicYuvRef->getLumaAddr(), iWidth, iHeight, iStride);
810  dNormRef  = dDCRef / (Double)(iWidth*iHeight);
811  dDenom    = xComputeNormMean(pcPicYuvRef->getLumaAddr(), dNormRef, iWidth, iHeight, iStride);
812
813  // scale + offset mode
814  if (eEffMode==EFF_WP_SO)
815  {
816    if (dDenom != 0.)
817    {
818      iWeight[0] = (Int) ((Double)(iDefaultWeight[0]) * dNumer / dDenom + 0.5);
819    }
820    else
821    {
822      iWeight[0] = iDefaultWeight[0];
823    }
824    iWeight[0] = Clip3(-128, 127, iWeight[0]);
825
826    iOffset[0] = (Int) (dNormOrg - ((Double) iWeight[0] * dNormRef / (Double) iDefaultWeight[0]) + 0.5);
827
828    if (iShift)
829    {
830      iOffset[0] = (iOffset[0]+(1<<(iShift-1)))>>iShift;
831      iOffset[0] = Clip3( -128, 127, iOffset[0]);
832      iOffset[0] = iOffset[0]<<iShift;
833    }
834    else
835    {
836      iOffset[0] = Clip3( -128, 127, iOffset[0]);
837    }
838  }
839  // offset mode
840  else if (eEffMode==EFF_WP_O)
841  {
842    iOffset[0] = (Int) ((dDCOrg - dDCRef)/(iWidth*iHeight)+0.5);
843
844    if (iShift)
845    {
846      iOffset[0] = (iOffset[0]+(1<<(iShift-1)))>>iShift;
847      iOffset[0] = Clip3( -128, 127, iOffset[0]);
848      iOffset[0] = iOffset[0]<<iShift;
849    }
850    else
851    {
852      iOffset[0] = Clip3( -128, 127, iOffset[0]);
853    }
854    iWeight[0] = iDefaultWeight[0];
855  }
856
857  rpcSlice->setWPWeight(eRefPicList, eEffMode, 0, iWeight[0]);
858  rpcSlice->setWPOffset(eRefPicList, eEffMode, 0, iOffset[0]);
859
860#if GRF_WP_CHROMA
861  iWidth  = iWidth>>1;
862  iHeight = iHeight>>1;
863  iStride = pcPicYuvOrg->getCStride();
864
865  Double dDCOrgU = xComputeImgSum(pcPicYuvOrg->getCbAddr(), iWidth, iHeight, iStride);
866  Double dDCOrgV = xComputeImgSum(pcPicYuvOrg->getCrAddr(), iWidth, iHeight, iStride);
867  Double dDCRefU = xComputeImgSum(pcPicYuvRef->getCbAddr(), iWidth, iHeight, iStride);
868  Double dDCRefV = xComputeImgSum(pcPicYuvRef->getCrAddr(), iWidth, iHeight, iStride);
869
870  // scale + offset mode
871  if ( eEffMode==EFF_WP_SO )
872  {
873    if (dDCRefU != 0.)
874    {
875      iWeight[1] = (Int) (iDefaultWeight[1] * dDCOrgU / dDCRefU + 0.5);
876    }
877    else
878    {
879      iWeight[1] = iDefaultWeight[1];
880    }
881    iWeight[1] = Clip3(-128, 127, iWeight[1]);
882
883    if (dDCRefV != 0.)
884    {
885      iWeight[2] = (Int) (iDefaultWeight[2] * dDCOrgV / dDCRefV + 0.5);
886    }
887    else
888    {
889      iWeight[2] = iDefaultWeight[2];
890    }
891    iWeight[2] = Clip3(-128, 127, iWeight[2]);
892  }
893  // offset mode
894  else if (eEffMode==EFF_WP_O)
895  {
896    iOffset[1] = (Int) ((dDCOrgU - dDCRefU)/(iWidth*iHeight)+0.5);
897
898    if (iShift)
899    {
900      iOffset[1] = (iOffset[1]+(1<<(iShift-1)))>>iShift;
901      iOffset[1] = Clip3( -128, 127, iOffset[1]);
902      iOffset[1] = iOffset[1]<<iShift;
903    }
904    else
905    {
906      iOffset[1] = Clip3( -128, 127, iOffset[1]);
907    }
908    iWeight[1] = iDefaultWeight[1];
909
910    iOffset[2] = (Int) ((dDCOrgV - dDCRefV)/(iWidth*iHeight)+0.5);
911    if (iShift)
912    {
913      iOffset[2] = (iOffset[2]+(1<<(iShift-1)))>>iShift;
914      iOffset[2] = Clip3( -128, 127, iOffset[2]);
915      iOffset[2] = iOffset[2]<<iShift;
916    }
917    else
918    {
919      iOffset[2] = Clip3( -128, 127, iOffset[2]);
920    }
921    iWeight[2] = iDefaultWeight[2];
922  }
923
924  rpcSlice->setWPWeight(eRefPicList, eEffMode, 1, iWeight[1]);
925  rpcSlice->setWPOffset(eRefPicList, eEffMode, 1, iOffset[1]);
926  rpcSlice->setWPWeight(eRefPicList, eEffMode, 2, iWeight[2]);
927  rpcSlice->setWPOffset(eRefPicList, eEffMode, 2, iOffset[2]);
928#endif
929
930#if GRF_WP_CHROMA
931  if (iWeight[0] == iDefaultWeight[0] && iOffset[0] == 0 &&
932      iWeight[1] == iDefaultWeight[1] && iOffset[1] == 0 &&
933      iWeight[2] == iDefaultWeight[2] && iOffset[2] == 0 )   //-> same to original reference
934#else
935  if (iWeight[0] == iDefaultWeight[0] && iOffset[0] == 0)    //-> same to original reference
936#endif
937  {
938    return false;
939  }
940
941  return true;
942}
943
944Double TEncSlice::xComputeImgSum( Pel* img, Int width, Int height, Int stride )
945{
946  Int x, y;
947  Double sum=0.;
948
949  for (y=0; y<height; y++)
950  {
951    for (x=0; x<width; x++)
952    {
953      sum += (Double)(img[x]);
954    }
955    img += stride;
956  }
957  return sum;
958}
959
960Double TEncSlice::xComputeNormMean( Pel* img, Double meanValue, Int width, Int height, Int stride )
961{
962  Int x, y;
963  Double sum=0.;
964
965  for (y=0; y<height; y++)
966  {
967    for (x=0; x<width; x++)
968    {
969      sum += fabs((Double)(img[x]) - meanValue);
970    }
971    img += stride;
972  }
973  return sum;
974}
975