source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibEncoder/WeightPredAnalysis.cpp @ 1497

Last change on this file since 1497 was 1411, checked in by seregin, 9 years ago

port rev 4565

  • Property svn:eol-style set to native
File size: 29.9 KB
RevLine 
[313]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
[494]4 * granted under this license.
[313]5 *
[1259]6 * Copyright (c) 2010-2015, ITU/ISO/IEC
[313]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     WeightPredAnalysis.cpp
35    \brief    weighted prediction encoder class
36*/
37
[1335]38#include "../TLibCommon/CommonDef.h"
[313]39#include "../TLibCommon/TComSlice.h"
40#include "../TLibCommon/TComPic.h"
41#include "../TLibCommon/TComPicYuv.h"
42#include "WeightPredAnalysis.h"
[1400]43#include <limits>
[313]44
[1400]45static const Double WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD=0.99; // NOTE: U0040 used 0.95
[313]46
[1400]47//! calculate SAD values for both WP version and non-WP version.
48static
49Int64 xCalcSADvalueWP(const Int   bitDepth,
50                      const Pel  *pOrgPel,
51                      const Pel  *pRefPel,
52                      const Int   width,
53                      const Int   height,
54                      const Int   orgStride,
55                      const Int   refStride,
56                      const Int   log2Denom,
57                      const Int   weight,
58                      const Int   offset,
59                      const Bool  useHighPrecision);
60
61//! calculate SAD values for both WP version and non-WP version.
62static
63Int64 xCalcSADvalueWPOptionalClip(const Int   bitDepth,
64                                  const Pel  *pOrgPel,
65                                  const Pel  *pRefPel,
66                                  const Int   width,
67                                  const Int   height,
68                                  const Int   orgStride,
69                                  const Int   refStride,
70                                  const Int   log2Denom,
71                                  const Int   weight,
72                                  const Int   offset,
73                                  const Bool  useHighPrecision,
74                                  const Bool  clipped);
75
76// -----------------------------------------------------------------------------
77// Helper functions
78
79
80//! calculate Histogram for array of pixels
81static
82Void xCalcHistogram(const Pel  *pPel,
83                    std::vector<Int> &histogram,
84                    const Int   width,
85                    const Int   height,
86                    const Int   stride,
87                    const Int   maxPel)
88{
89  histogram.clear();
90  histogram.resize(maxPel);
91  for( Int y = 0; y < height; y++ )
92  {
93    for( Int x = 0; x < width; x++ )
94    {
95      const Pel v=pPel[x];
96      histogram[v<0?0:(v>=maxPel)?maxPel-1:v]++;
97    }
98    pPel += stride;
99  }
100}
101
102static
103Distortion xCalcHistDistortion (const std::vector<Int> &histogram0,
104                                const std::vector<Int> &histogram1)
105{
106  Distortion distortion = 0;
107  assert(histogram0.size()==histogram1.size());
108  const Int numElements=Int(histogram0.size());
109
110  // Scan histograms to compute histogram distortion
111  for (Int i = 0; i <= numElements; i++)
112  {
113    distortion += (Distortion)(abs(histogram0[i] - histogram1[i]));
114  }
115
116  return distortion;
117}
118
119static
120void xScaleHistogram(const std::vector<Int> &histogramInput,
121                           std::vector<Int> &histogramOutput, // cannot be the same as the input
122                     const Int               bitDepth,
123                     const Int               log2Denom,
124                     const Int               weight,
125                     const Int               offset,
126                     const Bool              bHighPrecision)
127{
128  assert(&histogramInput != &histogramOutput);
129  const Int numElements=Int(histogramInput.size());
130  histogramOutput.clear();
131  histogramOutput.resize(numElements);
132
133  const Int64 iRealLog2Denom = bHighPrecision ? 0 : (bitDepth - 8);
134  const Int64 iRealOffset    = ((Int64)offset)<<iRealLog2Denom;
135
136  const Int divOffset = log2Denom == 0 ? 0 : 1 << (log2Denom - 1);
137  // Scan histogram and apply illumination parameters appropriately
138  // Then compute updated histogram.
139  // Note that this technique only works with single list weights/offsets.
140
141  for (Int i = 0; i < numElements; i++)
142  {
143    const Int j = Clip3(0, numElements - 1, (Int)(((weight * i + divOffset) >> log2Denom) + iRealOffset));
144    histogramOutput[j] += histogramInput[i];
145  }
146}
147
148static
149Distortion xSearchHistogram(const std::vector<Int> &histogramSource,
150                            const std::vector<Int> &histogramRef,
151                                  std::vector<Int> &outputHistogram,
152                            const Int               bitDepth,
153                            const Int               log2Denom,
154                                  Int              &weightToUpdate,
155                                  Int              &offsetToUpdate,
156                            const Bool              bHighPrecision,
157                            const ComponentID       compID)
158{
159  const Int initialWeight   = weightToUpdate;
160  const Int initialOffset   = offsetToUpdate;
161  const Int weightRange     = 10;
162  const Int offsetRange     = 10;
163  const Int maxOffset       = 1 << ((bHighPrecision == true) ? (bitDepth - 1) : 7);
164  const Int range           = bHighPrecision ? (1<<bitDepth) / 2 : 128;
165  const Int defaultWeight   = (1<<log2Denom);
166  const Int minSearchWeight = std::max<Int>(initialWeight - weightRange, defaultWeight - range);
167  const Int maxSearchWeight = std::min<Int>(initialWeight + weightRange+1, defaultWeight + range);
168
[1411]169  Distortion minDistortion   = std::numeric_limits<Distortion>::max();
[1400]170  Int        bestWeight      = initialWeight;
171  Int        bestOffset      = initialOffset;
172
173  for (Int searchWeight = minSearchWeight; searchWeight < maxSearchWeight; searchWeight++)
174  {
175    if (compID == COMPONENT_Y)
176    {
177      for (Int searchOffset = std::max<Int>(initialOffset - offsetRange, -maxOffset);
178               searchOffset <= initialOffset + offsetRange && searchOffset<=(maxOffset-1);
179               searchOffset++)
180      {
181        xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, searchWeight, searchOffset, bHighPrecision);
182        const Distortion distortion = xCalcHistDistortion(histogramSource, outputHistogram);
183
184        if (distortion < minDistortion)
185        {
186          minDistortion = distortion;
187          bestWeight    = searchWeight;
188          bestOffset    = searchOffset;
189        }
190      }
191    }
192    else
193    {
194      const Int pred        = ( maxOffset - ( ( maxOffset*searchWeight)>>(log2Denom) ) );
195
196      for (Int searchOffset = initialOffset - offsetRange; searchOffset <= initialOffset + offsetRange; searchOffset++)
197      {
198        const Int deltaOffset   = Clip3( -4*maxOffset, 4*maxOffset-1, (searchOffset - pred) ); // signed 10bit (if !bHighPrecision)
199        const Int clippedOffset = Clip3( -1*maxOffset, 1*maxOffset-1, (deltaOffset  + pred) ); // signed 8bit  (if !bHighPrecision)
200        xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, searchWeight, clippedOffset, bHighPrecision);
201        const Distortion distortion = xCalcHistDistortion(histogramSource, outputHistogram);
202
203        if (distortion < minDistortion)
204        {
205          minDistortion = distortion;
206          bestWeight    = searchWeight;
207          bestOffset    = clippedOffset;
208        }
209      }
210    }
211  }
212
213  weightToUpdate = bestWeight;
214  offsetToUpdate = bestOffset;
215
216  // regenerate best histogram
217  xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, bestWeight, bestOffset, bHighPrecision);
218
219  return minDistortion;
220}
221
222
223// -----------------------------------------------------------------------------
224// Member functions
225
[313]226WeightPredAnalysis::WeightPredAnalysis()
227{
[1029]228  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]229  {
[1400]230    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
[313]231    {
[1029]232      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
[313]233      {
[1400]234        WPScalingParam  *pwp   = &(m_wp[lst][refIdx][comp]);
[313]235        pwp->bPresentFlag      = false;
236        pwp->uiLog2WeightDenom = 0;
237        pwp->iWeight           = 1;
238        pwp->iOffset           = 0;
239      }
240    }
241  }
242}
243
[1029]244
[1260]245//! calculate AC and DC values for current original image
[1029]246Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
[313]247{
248  //===== calculate AC/DC value =====
249  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
250
[1029]251  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
[313]252
[1029]253  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
254  {
255    const ComponentID compID = ComponentID(componentIndex);
[313]256
[1029]257    // calculate DC/AC value for channel
258
[1400]259    const Int stride = pPic->getStride(compID);
260    const Int width  = pPic->getWidth(compID);
261    const Int height = pPic->getHeight(compID);
[1029]262
[1400]263    const Int sample = width*height;
[1029]264
[1400]265    Int64 orgDC = 0;
[1029]266    {
267      const Pel *pPel = pPic->getAddr(compID);
268
[1400]269      for(Int y = 0; y < height; y++, pPel+=stride )
[1246]270      {
[1400]271        for(Int x = 0; x < width; x++ )
[1246]272        {
[1400]273          orgDC += (Int)( pPel[x] );
[1246]274        }
275      }
[1029]276    }
277
[1400]278    const Int64 orgNormDC = ((orgDC+(sample>>1)) / sample);
[1029]279
[1400]280    Int64 orgAC = 0;
[1029]281    {
282      const Pel *pPel = pPic->getAddr(compID);
283
[1400]284      for(Int y = 0; y < height; y++, pPel += stride )
[1246]285      {
[1400]286        for(Int x = 0; x < width; x++ )
[1246]287        {
[1400]288          orgAC += abs( (Int)pPel[x] - (Int)orgNormDC );
[1246]289        }
290      }
[1029]291    }
292
[1316]293    const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
[1400]294    weightACDCParam[compID].iDC = (((orgDC<<fixedBitShift)+(sample>>1)) / sample);
295    weightACDCParam[compID].iAC = orgAC;
[1201]296#if SVC_EXTENSION
[1400]297    weightACDCParam[compID].numSamples = sample;
[494]298#endif
[1029]299  }
[313]300
301  slice->setWpAcDcParam(weightACDCParam);
302}
303
[1246]304
[1260]305//! check weighted pred or non-weighted pred
[1029]306Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
[313]307{
[1029]308  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
309
[1400]310  Int presentCnt = 0;
[1029]311  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]312  {
[1400]313    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
[313]314    {
[1029]315      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[313]316      {
[1400]317        WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
318        presentCnt += (Int)pwp->bPresentFlag;
[313]319      }
320    }
321  }
322
[1400]323  if(presentCnt==0)
[313]324  {
[1235]325    slice->setTestWeightPred(false);
326    slice->setTestWeightBiPred(false);
[1029]327
328    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]329    {
[1400]330      for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
[313]331      {
[1029]332        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[313]333        {
[1400]334          WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
[1029]335
[313]336          pwp->bPresentFlag      = false;
337          pwp->uiLog2WeightDenom = 0;
338          pwp->iWeight           = 1;
339          pwp->iOffset           = 0;
340        }
341      }
342    }
343    slice->setWpScaling( m_wp );
344  }
[1235]345  else
346  {
[1400]347    slice->setTestWeightPred  (slice->getPPS()->getUseWP());
[1235]348    slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred());
349  }
[313]350}
351
[1029]352
[1260]353//! estimate wp tables for explicit wp
[1400]354Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method)
[313]355{
[1029]356  Int  iDenom         = 6;
[313]357  Bool validRangeFlag = false;
358
359  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
360  {
[1029]361    iDenom = 7;
[313]362  }
363
364  do
365  {
[1029]366    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
[313]367    if (!validRangeFlag)
368    {
369      iDenom--; // decrement to satisfy the range limitation
370    }
371  } while (validRangeFlag == false);
372
[1235]373  // selecting whether WP is used, or not (fast search)
374  // NOTE: This is not operating on a slice, but the entire picture.
[1400]375  switch (method)
376  {
377    case WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT:
378      xSelectWP(slice, iDenom);
379      break;
380    case WP_PER_PICTURE_WITH_SIMPLE_DC_PER_COMPONENT:
381      xSelectWPHistExtClip(slice, iDenom, false, false, false);
382      break;
383    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT:
384      xSelectWPHistExtClip(slice, iDenom, false, false, true);
385      break;
386    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING:
387      xSelectWPHistExtClip(slice, iDenom, false, true, true);
388      break;
389    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION:
390      xSelectWPHistExtClip(slice, iDenom, true, true, true);
391      break;
392    default:
393      assert(0);
394      exit(1);
395  }
[494]396
[313]397  slice->setWpScaling( m_wp );
398}
399
[1029]400
[1260]401//! update wp tables for explicit wp w.r.t range limitation
[1029]402Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
[313]403{
[1029]404  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
[1316]405  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
[1029]406  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
407
408  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
409
[313]410  for ( Int refList = 0; refList < numPredDir; refList++ )
411  {
[1029]412    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
413
[313]414    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
415    {
[1316]416      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
417      slice->getWpAcDcParam(currWeightACDCParam);
418      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
[1029]419
[1201]420#if SVC_EXTENSION
[494]421      UInt currLayerId = slice->getLayerId();
422      UInt refLayerId  = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId();
423      Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0;
[313]424
[494]425      if( validILRPic )
426      {
[1316]427        slice->getWpAcDcParam(refWeightACDCParam);
[494]428      }
429#endif
430
[1029]431      for ( Int comp = 0; comp < numComp; comp++ )
[313]432      {
[1029]433        const ComponentID compID        = ComponentID(comp);
[1287]434#if SVC_EXTENSION
435        const Int         bitDepth      = slice->getBitDepth(toChannelType(compID));
436#else
437        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
438#endif
439        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
440        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
[1029]441        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
[313]442
443        // current frame
[1029]444        const Int64 currDC = currWeightACDCParam[comp].iDC;
445        const Int64 currAC = currWeightACDCParam[comp].iAC;
[313]446        // reference frame
[1201]447#if SVC_EXTENSION
[1029]448        Int64 refDC  = refWeightACDCParam[comp].iDC;
449        Int64 refAC  = refWeightACDCParam[comp].iAC;
450
[494]451        if( validILRPic )
452        {
[1400]453          refAC = ( refAC * currWeightACDCParam[comp].numSamples ) / refWeightACDCParam[comp].numSamples;
[1202]454
[1287]455          const Int bitDepthLuma = slice->getBitDepth(CHANNEL_TYPE_LUMA);
456          const Int refBitDepthLuma  = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getBitDepth(CHANNEL_TYPE_LUMA);
457          const Int delta = bitDepthLuma - refBitDepthLuma;
458
[1202]459          // jonint upsampling bitshift
[1287]460          refAC <<= delta;
461          refDC <<= delta;
[494]462        }
[1029]463#else
464        const Int64 refDC  = refWeightACDCParam[comp].iDC;
465        const Int64 refAC  = refWeightACDCParam[comp].iAC;
[494]466#endif
[313]467
468        // calculating iWeight and iOffset params
[1201]469#if SVC_EXTENSION
[313]470        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
[1029]471        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
472        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
473
[494]474        if( !validILRPic )
475        {
476          dWeight = 1;
477          offset  = 0;
478        }
479        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
[1029]480#else
481        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
482        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
483        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
[494]484#endif
[313]485
[1029]486        Int clippedOffset;
487        if(isChroma(compID)) // Chroma offset range limination
[313]488        {
[1029]489          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
490          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
491
492          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
[313]493        }
[1029]494        else // Luma offset range limitation
[313]495        {
[1029]496          clippedOffset = Clip3( -range, range-1, offset);
[313]497        }
498
499        // Weighting factor limitation
[1029]500        const Int defaultWeight = (1<<log2Denom);
[1392]501        const Int deltaWeight   = (weight - defaultWeight);
[1029]502
503        if(deltaWeight >= range || deltaWeight < -range)
[1246]504        {
[1029]505          return false;
[1246]506        }
[1029]507
[1201]508#if SVC_EXTENSION
[494]509        // make sure the reference frames other than ILR are not using weighted prediction
510        else
511        if( !validILRPic )
512        {
513          continue;
514        }
515#endif
[313]516
[1029]517        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
518        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
519        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
520        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[313]521      }
522    }
523  }
[1029]524  return true;
[313]525}
526
[1029]527
[1400]528/** select whether weighted pred enables or not.
529 * \param TComSlice *slice
530 * \param log2Denom
531 * \returns Bool
532 */
533Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram)
534{
535  const TComPicYuv *const pPic             = slice->getPic()->getPicYuvOrg();
536  const Int               defaultWeight    = 1<<log2Denom;
537  const Int               numPredDir       = slice->isInterP() ? 1 : 2;
538  const Bool              useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
539
540  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
541
542  for ( Int refList = 0; refList < numPredDir; refList++ )
543  {
544    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
545
546    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
547    {
548      Bool  useChromaWeight = false;
549
550      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
551      {
552        const ComponentID  compID     = ComponentID(comp);
553        const Pel         *pOrg       = pPic->getAddr(compID);
554        const Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
555        const Int          orgStride  = pPic->getStride(compID);
556        const Int          refStride  = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
557        const Int          width      = pPic->getWidth(compID);
558        const Int          height     = pPic->getHeight(compID);
559#if SVC_EXTENSION
560        const Int          bitDepth   = slice->getBitDepth(toChannelType(compID));
561#else
562        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
563#endif
564              WPScalingParam &wp      = m_wp[refList][refIdxTemp][compID];
565              Int          weight     = wp.iWeight;
566              Int          offset     = wp.iOffset;
567              Int          weightDef  = defaultWeight;
568              Int          offsetDef  = 0;
569
570        // calculate SAD costs with/without wp for luma
571        const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP);
572        if (SADnoWP > 0)
573        {
574          const Int64 SADWP   = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight,   offset, useHighPrecision, bClipInitialSADWP);
575          const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP;
576          Double dRatioSr0SAD = std::numeric_limits<Double>::max();
577          Double dRatioSrSAD  = std::numeric_limits<Double>::max();
578
579          if (bUseHistogram)
580          {
581            std::vector<Int> histogramOrg;// = pPic->getHistogram(compID);
582            std::vector<Int> histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID);
583            std::vector<Int> searchedHistogram;
584
585            // Compute histograms
586            xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth);
587            xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth);
588
589            // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded
590            xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID);
591            // calculate updated WP SAD
592            const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision);
593            dRatioSrSAD  = (Double)SADSrWP  / (Double)SADnoWP;
594
595            if (bDoEnhancement)
596            {
597              // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded
598              xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID);
599              // calculate updated WP SAD
600              const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision);
601              dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP;
602            }
603          }
604
605          if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
606          {
607            wp.bPresentFlag      = false;
608            wp.iOffset           = 0;
609            wp.iWeight           = defaultWeight;
610            wp.uiLog2WeightDenom = log2Denom;
611          }
612          else
613          {
614            if (compID != COMPONENT_Y)
615            {
616              useChromaWeight = true;
617            }
618
619            if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD)
620            {
621              wp.bPresentFlag      = true;
622              wp.iOffset           = offsetDef;
623              wp.iWeight           = weightDef;
624              wp.uiLog2WeightDenom = log2Denom;
625            }
626            else if (dRatioSrSAD < dRatioSAD)
627            {
628              wp.bPresentFlag      = true;
629              wp.iOffset           = offset;
630              wp.iWeight           = weight;
631              wp.uiLog2WeightDenom = log2Denom;
632            }
633          }
634        }
635        else // (SADnoWP <= 0)
636        {
637          wp.bPresentFlag      = false;
638          wp.iOffset           = 0;
639          wp.iWeight           = defaultWeight;
640          wp.uiLog2WeightDenom = log2Denom;
641        }
642      }
643
644      for(Int comp=1; comp<pPic->getNumberValidComponents(); comp++)
645      {
646        m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight;
647      }
648    }
649  }
650
651  return true;
652}
653
[1260]654//! select whether weighted pred enables or not.
[1029]655Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
[313]656{
[1029]657        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
[1400]658  const Int               defaultWeight                       = 1<<log2Denom;
659  const Int               numPredDir                          = slice->isInterP() ? 1 : 2;
[1316]660  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
[313]661
[1400]662  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
[1029]663
[1400]664  for ( Int refList = 0; refList < numPredDir; refList++ )
[313]665  {
[1400]666    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
[1029]667
[1400]668    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
[313]669    {
[1400]670      Int64 SADWP = 0, SADnoWP = 0;
[313]671
[1029]672      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
673      {
674        const ComponentID  compID     = ComponentID(comp);
675              Pel         *pOrg       = pPic->getAddr(compID);
[1400]676              Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
677        const Int          orgStride = pPic->getStride(compID);
678        const Int          refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
679        const Int          width     = pPic->getWidth(compID);
680        const Int          height    = pPic->getHeight(compID);
[1287]681#if SVC_EXTENSION
682        const Int          bitDepth   = slice->getBitDepth(toChannelType(compID));
683#else
684        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
685#endif
[313]686
[1029]687        // calculate SAD costs with/without wp for luma
[1400]688        SADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
689        SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting);
[1029]690      }
[313]691
[1400]692      const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits<Double>::max();
693      if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
[313]694      {
[1029]695        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
[313]696        {
[1400]697          WPScalingParam &wp=m_wp[refList][refIdxTemp][comp];
698          wp.bPresentFlag      = false;
699          wp.iOffset           = 0;
700          wp.iWeight           = defaultWeight;
701          wp.uiLog2WeightDenom = log2Denom;
[313]702        }
703      }
704    }
705  }
706
[1029]707  return true;
[313]708}
709
[1409]710// Alternatively, a SSE-based measure could be used instead.
711// The respective function has been removed as it currently redundant.
[1400]712static
713Int64 xCalcSADvalueWP(const Int   bitDepth,
714                      const Pel  *pOrgPel,
715                      const Pel  *pRefPel,
716                      const Int   width,
717                      const Int   height,
718                      const Int   orgStride,
719                      const Int   refStride,
720                      const Int   log2Denom,
721                      const Int   weight,
722                      const Int   offset,
723                      const Bool  useHighPrecision)
[313]724{
[1400]725  //const Int64 iSize          = iWidth*iHeight;
726  const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
727  const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
[1029]728
[1400]729  Int64 SAD = 0;
730  for( Int y = 0; y < height; y++ )
[313]731  {
[1400]732    for( Int x = 0; x < width; x++ )
[313]733    {
[1400]734      SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
[313]735    }
[1400]736    pOrgPel += orgStride;
737    pRefPel += refStride;
[313]738  }
[1029]739
[1400]740  //return (iSAD/iSize);
741  return SAD;
[313]742}
[1400]743
744static
745Int64 xCalcSADvalueWPOptionalClip(const Int   bitDepth,
746                                  const Pel  *pOrgPel,
747                                  const Pel  *pRefPel,
748                                  const Int   width,
749                                  const Int   height,
750                                  const Int   orgStride,
751                                  const Int   refStride,
752                                  const Int   log2Denom,
753                                  const Int   weight,
754                                  const Int   offset,
755                                  const Bool  useHighPrecision,
756                                  const Bool  clipped)
757{
758  Int64 SAD = 0;
759  if (clipped)
760  {
761    const Int64 realLog2Denom = useHighPrecision ? 0 : (bitDepth - 8);
762    const Int64 realOffset    = (Int64)offset<<realLog2Denom;
763    const Int64 roundOffset = (log2Denom == 0) ? 0 : 1 << (log2Denom - 1);
764    const Int64 minValue = 0;
765    const Int64 maxValue = (1 << bitDepth) - 1;
766
767    for( Int y = 0; y < height; y++ )
768    {
769      for( Int x = 0; x < width; x++ )
770      {
771        Int64 scaledValue = Clip3(minValue, maxValue,  ((((Int64) pRefPel[x] * (Int64) weight + roundOffset) ) >>  (Int64) log2Denom) + realOffset);
772        SAD += abs((Int64)pOrgPel[x] -  scaledValue);
773      }
774      pOrgPel += orgStride;
775      pRefPel += refStride;
776    }
777  }
778  else
779  {
780    //const Int64 iSize          = iWidth*iHeight;
781    const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
782    const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
783
784    for( Int y = 0; y < height; y++ )
785    {
786      for( Int x = 0; x < width; x++ )
787      {
788        SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
789      }
790      pOrgPel += orgStride;
791      pRefPel += refStride;
792    }
793  }
794  return SAD;
795}
Note: See TracBrowser for help on using the repository browser.