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

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

port rev 4565

  • Property svn:eol-style set to native
File size: 29.9 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     WeightPredAnalysis.cpp
35    \brief    weighted prediction encoder class
36*/
37
38#include "../TLibCommon/CommonDef.h"
39#include "../TLibCommon/TComSlice.h"
40#include "../TLibCommon/TComPic.h"
41#include "../TLibCommon/TComPicYuv.h"
42#include "WeightPredAnalysis.h"
43#include <limits>
44
45static const Double WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD=0.99; // NOTE: U0040 used 0.95
46
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
169  Distortion minDistortion   = std::numeric_limits<Distortion>::max();
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
226WeightPredAnalysis::WeightPredAnalysis()
227{
228  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
229  {
230    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
231    {
232      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
233      {
234        WPScalingParam  *pwp   = &(m_wp[lst][refIdx][comp]);
235        pwp->bPresentFlag      = false;
236        pwp->uiLog2WeightDenom = 0;
237        pwp->iWeight           = 1;
238        pwp->iOffset           = 0;
239      }
240    }
241  }
242}
243
244
245//! calculate AC and DC values for current original image
246Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
247{
248  //===== calculate AC/DC value =====
249  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
250
251  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
252
253  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
254  {
255    const ComponentID compID = ComponentID(componentIndex);
256
257    // calculate DC/AC value for channel
258
259    const Int stride = pPic->getStride(compID);
260    const Int width  = pPic->getWidth(compID);
261    const Int height = pPic->getHeight(compID);
262
263    const Int sample = width*height;
264
265    Int64 orgDC = 0;
266    {
267      const Pel *pPel = pPic->getAddr(compID);
268
269      for(Int y = 0; y < height; y++, pPel+=stride )
270      {
271        for(Int x = 0; x < width; x++ )
272        {
273          orgDC += (Int)( pPel[x] );
274        }
275      }
276    }
277
278    const Int64 orgNormDC = ((orgDC+(sample>>1)) / sample);
279
280    Int64 orgAC = 0;
281    {
282      const Pel *pPel = pPic->getAddr(compID);
283
284      for(Int y = 0; y < height; y++, pPel += stride )
285      {
286        for(Int x = 0; x < width; x++ )
287        {
288          orgAC += abs( (Int)pPel[x] - (Int)orgNormDC );
289        }
290      }
291    }
292
293    const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
294    weightACDCParam[compID].iDC = (((orgDC<<fixedBitShift)+(sample>>1)) / sample);
295    weightACDCParam[compID].iAC = orgAC;
296#if SVC_EXTENSION
297    weightACDCParam[compID].numSamples = sample;
298#endif
299  }
300
301  slice->setWpAcDcParam(weightACDCParam);
302}
303
304
305//! check weighted pred or non-weighted pred
306Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
307{
308  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
309
310  Int presentCnt = 0;
311  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
312  {
313    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
314    {
315      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
316      {
317        WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
318        presentCnt += (Int)pwp->bPresentFlag;
319      }
320    }
321  }
322
323  if(presentCnt==0)
324  {
325    slice->setTestWeightPred(false);
326    slice->setTestWeightBiPred(false);
327
328    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
329    {
330      for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
331      {
332        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
333        {
334          WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
335
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  }
345  else
346  {
347    slice->setTestWeightPred  (slice->getPPS()->getUseWP());
348    slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred());
349  }
350}
351
352
353//! estimate wp tables for explicit wp
354Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method)
355{
356  Int  iDenom         = 6;
357  Bool validRangeFlag = false;
358
359  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
360  {
361    iDenom = 7;
362  }
363
364  do
365  {
366    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
367    if (!validRangeFlag)
368    {
369      iDenom--; // decrement to satisfy the range limitation
370    }
371  } while (validRangeFlag == false);
372
373  // selecting whether WP is used, or not (fast search)
374  // NOTE: This is not operating on a slice, but the entire picture.
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  }
396
397  slice->setWpScaling( m_wp );
398}
399
400
401//! update wp tables for explicit wp w.r.t range limitation
402Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
403{
404  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
405  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
406  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
407
408  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
409
410  for ( Int refList = 0; refList < numPredDir; refList++ )
411  {
412    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
413
414    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
415    {
416      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
417      slice->getWpAcDcParam(currWeightACDCParam);
418      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
419
420#if SVC_EXTENSION
421      UInt currLayerId = slice->getLayerId();
422      UInt refLayerId  = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId();
423      Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0;
424
425      if( validILRPic )
426      {
427        slice->getWpAcDcParam(refWeightACDCParam);
428      }
429#endif
430
431      for ( Int comp = 0; comp < numComp; comp++ )
432      {
433        const ComponentID compID        = ComponentID(comp);
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));
441        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
442
443        // current frame
444        const Int64 currDC = currWeightACDCParam[comp].iDC;
445        const Int64 currAC = currWeightACDCParam[comp].iAC;
446        // reference frame
447#if SVC_EXTENSION
448        Int64 refDC  = refWeightACDCParam[comp].iDC;
449        Int64 refAC  = refWeightACDCParam[comp].iAC;
450
451        if( validILRPic )
452        {
453          refAC = ( refAC * currWeightACDCParam[comp].numSamples ) / refWeightACDCParam[comp].numSamples;
454
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
459          // jonint upsampling bitshift
460          refAC <<= delta;
461          refDC <<= delta;
462        }
463#else
464        const Int64 refDC  = refWeightACDCParam[comp].iDC;
465        const Int64 refAC  = refWeightACDCParam[comp].iAC;
466#endif
467
468        // calculating iWeight and iOffset params
469#if SVC_EXTENSION
470        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
471        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
472        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
473
474        if( !validILRPic )
475        {
476          dWeight = 1;
477          offset  = 0;
478        }
479        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
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 );
484#endif
485
486        Int clippedOffset;
487        if(isChroma(compID)) // Chroma offset range limination
488        {
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
493        }
494        else // Luma offset range limitation
495        {
496          clippedOffset = Clip3( -range, range-1, offset);
497        }
498
499        // Weighting factor limitation
500        const Int defaultWeight = (1<<log2Denom);
501        const Int deltaWeight   = (weight - defaultWeight);
502
503        if(deltaWeight >= range || deltaWeight < -range)
504        {
505          return false;
506        }
507
508#if SVC_EXTENSION
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
516
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;
521      }
522    }
523  }
524  return true;
525}
526
527
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
654//! select whether weighted pred enables or not.
655Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
656{
657        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
658  const Int               defaultWeight                       = 1<<log2Denom;
659  const Int               numPredDir                          = slice->isInterP() ? 1 : 2;
660  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
661
662  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
663
664  for ( Int refList = 0; refList < numPredDir; refList++ )
665  {
666    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
667
668    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
669    {
670      Int64 SADWP = 0, SADnoWP = 0;
671
672      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
673      {
674        const ComponentID  compID     = ComponentID(comp);
675              Pel         *pOrg       = pPic->getAddr(compID);
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);
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
686
687        // calculate SAD costs with/without wp for luma
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);
690      }
691
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)
694      {
695        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
696        {
697          WPScalingParam &wp=m_wp[refList][refIdxTemp][comp];
698          wp.bPresentFlag      = false;
699          wp.iOffset           = 0;
700          wp.iWeight           = defaultWeight;
701          wp.uiLog2WeightDenom = log2Denom;
702        }
703      }
704    }
705  }
706
707  return true;
708}
709
710// Alternatively, a SSE-based measure could be used instead.
711// The respective function has been removed as it currently redundant.
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)
724{
725  //const Int64 iSize          = iWidth*iHeight;
726  const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
727  const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
728
729  Int64 SAD = 0;
730  for( Int y = 0; y < height; y++ )
731  {
732    for( Int x = 0; x < width; x++ )
733    {
734      SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
735    }
736    pOrgPel += orgStride;
737    pRefPel += refStride;
738  }
739
740  //return (iSAD/iSize);
741  return SAD;
742}
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.