source: 3DVCSoftware/trunk/source/Lib/TLibEncoder/WeightPredAnalysis.cpp

Last change on this file was 1413, checked in by tech, 6 years ago

Merged HTM-16.2-dev@1412

  • Property svn:eol-style set to native
File size: 27.8 KB
Line 
1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
4 * granted under this license.
5 *
6 * Copyright (c) 2010-2017, 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  }
297
298  slice->setWpAcDcParam(weightACDCParam);
299}
300
301
302//! check weighted pred or non-weighted pred
303Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
304{
305  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
306
307  Int presentCnt = 0;
308  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
309  {
310    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
311    {
312      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
313      {
314        WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
315        presentCnt += (Int)pwp->bPresentFlag;
316      }
317    }
318  }
319
320  if(presentCnt==0)
321  {
322    slice->setTestWeightPred(false);
323    slice->setTestWeightBiPred(false);
324
325    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
326    {
327      for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
328      {
329        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
330        {
331          WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
332
333          pwp->bPresentFlag      = false;
334          pwp->uiLog2WeightDenom = 0;
335          pwp->iWeight           = 1;
336          pwp->iOffset           = 0;
337        }
338      }
339    }
340    slice->setWpScaling( m_wp );
341  }
342  else
343  {
344    slice->setTestWeightPred  (slice->getPPS()->getUseWP());
345    slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred());
346  }
347}
348
349
350//! estimate wp tables for explicit wp
351Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method)
352{
353  Int  iDenom         = 6;
354  Bool validRangeFlag = false;
355
356  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
357  {
358    iDenom = 7;
359  }
360
361  do
362  {
363    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
364    if (!validRangeFlag)
365    {
366      iDenom--; // decrement to satisfy the range limitation
367    }
368  } while (validRangeFlag == false);
369
370  // selecting whether WP is used, or not (fast search)
371  // NOTE: This is not operating on a slice, but the entire picture.
372  switch (method)
373  {
374    case WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT:
375      xSelectWP(slice, iDenom);
376      break;
377    case WP_PER_PICTURE_WITH_SIMPLE_DC_PER_COMPONENT:
378      xSelectWPHistExtClip(slice, iDenom, false, false, false);
379      break;
380    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT:
381      xSelectWPHistExtClip(slice, iDenom, false, false, true);
382      break;
383    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING:
384      xSelectWPHistExtClip(slice, iDenom, false, true, true);
385      break;
386    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION:
387      xSelectWPHistExtClip(slice, iDenom, true, true, true);
388      break;
389    default:
390      assert(0);
391      exit(1);
392  }
393
394  slice->setWpScaling( m_wp );
395}
396
397
398//! update wp tables for explicit wp w.r.t range limitation
399Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
400{
401  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
402  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
403  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
404
405  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
406
407  for ( Int refList = 0; refList < numPredDir; refList++ )
408  {
409    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
410
411    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
412    {
413      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
414      slice->getWpAcDcParam(currWeightACDCParam);
415      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
416
417      for ( Int comp = 0; comp < numComp; comp++ )
418      {
419        const ComponentID compID        = ComponentID(comp);
420        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
421        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
422        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
423        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
424
425        // current frame
426        const Int64 currDC = currWeightACDCParam[comp].iDC;
427        const Int64 currAC = currWeightACDCParam[comp].iAC;
428        // reference frame
429        const Int64 refDC  = refWeightACDCParam[comp].iDC;
430        const Int64 refAC  = refWeightACDCParam[comp].iAC;
431
432        // calculating iWeight and iOffset params
433        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
434        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
435        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
436
437        Int clippedOffset;
438        if(isChroma(compID)) // Chroma offset range limination
439        {
440          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
441          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
442
443          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
444        }
445        else // Luma offset range limitation
446        {
447          clippedOffset = Clip3( -range, range-1, offset);
448        }
449
450        // Weighting factor limitation
451        const Int defaultWeight = (1<<log2Denom);
452        const Int deltaWeight   = (weight - defaultWeight);
453
454        if(deltaWeight >= range || deltaWeight < -range)
455        {
456          return false;
457        }
458
459        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
460        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
461        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
462        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
463      }
464    }
465  }
466  return true;
467}
468
469
470/** select whether weighted pred enables or not.
471 * \param TComSlice *slice
472 * \param log2Denom
473 * \returns Bool
474 */
475Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram)
476{
477  const TComPicYuv *const pPic             = slice->getPic()->getPicYuvOrg();
478  const Int               defaultWeight    = 1<<log2Denom;
479  const Int               numPredDir       = slice->isInterP() ? 1 : 2;
480  const Bool              useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
481
482  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
483
484  for ( Int refList = 0; refList < numPredDir; refList++ )
485  {
486    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
487
488    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
489    {
490      Bool  useChromaWeight = false;
491
492      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
493      {
494        const ComponentID  compID     = ComponentID(comp);
495        const Pel         *pOrg       = pPic->getAddr(compID);
496        const Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
497        const Int          orgStride  = pPic->getStride(compID);
498        const Int          refStride  = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
499        const Int          width      = pPic->getWidth(compID);
500        const Int          height     = pPic->getHeight(compID);
501        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
502              WPScalingParam &wp      = m_wp[refList][refIdxTemp][compID];
503              Int          weight     = wp.iWeight;
504              Int          offset     = wp.iOffset;
505              Int          weightDef  = defaultWeight;
506              Int          offsetDef  = 0;
507
508        // calculate SAD costs with/without wp for luma
509        const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP);
510        if (SADnoWP > 0)
511        {
512          const Int64 SADWP   = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight,   offset, useHighPrecision, bClipInitialSADWP);
513          const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP;
514          Double dRatioSr0SAD = std::numeric_limits<Double>::max();
515          Double dRatioSrSAD  = std::numeric_limits<Double>::max();
516
517          if (bUseHistogram)
518          {
519            std::vector<Int> histogramOrg;// = pPic->getHistogram(compID);
520            std::vector<Int> histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID);
521            std::vector<Int> searchedHistogram;
522
523            // Compute histograms
524            xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth);
525            xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth);
526
527            // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded
528            xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID);
529            // calculate updated WP SAD
530            const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision);
531            dRatioSrSAD  = (Double)SADSrWP  / (Double)SADnoWP;
532
533            if (bDoEnhancement)
534            {
535              // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded
536              xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID);
537              // calculate updated WP SAD
538              const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision);
539              dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP;
540            }
541          }
542
543          if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
544          {
545            wp.bPresentFlag      = false;
546            wp.iOffset           = 0;
547            wp.iWeight           = defaultWeight;
548            wp.uiLog2WeightDenom = log2Denom;
549          }
550          else
551          {
552            if (compID != COMPONENT_Y)
553            {
554              useChromaWeight = true;
555            }
556
557            if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD)
558            {
559              wp.bPresentFlag      = true;
560              wp.iOffset           = offsetDef;
561              wp.iWeight           = weightDef;
562              wp.uiLog2WeightDenom = log2Denom;
563            }
564            else if (dRatioSrSAD < dRatioSAD)
565            {
566              wp.bPresentFlag      = true;
567              wp.iOffset           = offset;
568              wp.iWeight           = weight;
569              wp.uiLog2WeightDenom = log2Denom;
570            }
571          }
572        }
573        else // (SADnoWP <= 0)
574        {
575          wp.bPresentFlag      = false;
576          wp.iOffset           = 0;
577          wp.iWeight           = defaultWeight;
578          wp.uiLog2WeightDenom = log2Denom;
579        }
580      }
581
582      for(Int comp=1; comp<pPic->getNumberValidComponents(); comp++)
583      {
584        m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight;
585      }
586    }
587  }
588
589  return true;
590}
591
592//! select whether weighted pred enables or not.
593Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
594{
595        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
596  const Int               defaultWeight                       = 1<<log2Denom;
597  const Int               numPredDir                          = slice->isInterP() ? 1 : 2;
598  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
599
600  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
601
602  for ( Int refList = 0; refList < numPredDir; refList++ )
603  {
604    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
605
606    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
607    {
608      Int64 SADWP = 0, SADnoWP = 0;
609
610      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
611      {
612        const ComponentID  compID     = ComponentID(comp);
613              Pel         *pOrg       = pPic->getAddr(compID);
614              Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
615        const Int          orgStride = pPic->getStride(compID);
616        const Int          refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
617        const Int          width     = pPic->getWidth(compID);
618        const Int          height    = pPic->getHeight(compID);
619        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
620
621        // calculate SAD costs with/without wp for luma
622        SADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
623        SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting);
624      }
625
626      const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits<Double>::max();
627      if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
628      {
629        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
630        {
631          WPScalingParam &wp=m_wp[refList][refIdxTemp][comp];
632          wp.bPresentFlag      = false;
633          wp.iOffset           = 0;
634          wp.iWeight           = defaultWeight;
635          wp.uiLog2WeightDenom = log2Denom;
636        }
637      }
638    }
639  }
640
641  return true;
642}
643
644// Alternatively, a SSE-based measure could be used instead.
645// The respective function has been removed as it currently redundant.
646static
647Int64 xCalcSADvalueWP(const Int   bitDepth,
648                      const Pel  *pOrgPel,
649                      const Pel  *pRefPel,
650                      const Int   width,
651                      const Int   height,
652                      const Int   orgStride,
653                      const Int   refStride,
654                      const Int   log2Denom,
655                      const Int   weight,
656                      const Int   offset,
657                      const Bool  useHighPrecision)
658{
659  //const Int64 iSize          = iWidth*iHeight;
660  const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
661  const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
662
663  Int64 SAD = 0;
664  for( Int y = 0; y < height; y++ )
665  {
666    for( Int x = 0; x < width; x++ )
667    {
668      SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
669    }
670    pOrgPel += orgStride;
671    pRefPel += refStride;
672  }
673
674  //return (iSAD/iSize);
675  return SAD;
676}
677
678static
679Int64 xCalcSADvalueWPOptionalClip(const Int   bitDepth,
680                                  const Pel  *pOrgPel,
681                                  const Pel  *pRefPel,
682                                  const Int   width,
683                                  const Int   height,
684                                  const Int   orgStride,
685                                  const Int   refStride,
686                                  const Int   log2Denom,
687                                  const Int   weight,
688                                  const Int   offset,
689                                  const Bool  useHighPrecision,
690                                  const Bool  clipped)
691{
692  Int64 SAD = 0;
693  if (clipped)
694  {
695    const Int64 realLog2Denom = useHighPrecision ? 0 : (bitDepth - 8);
696    const Int64 realOffset    = (Int64)offset<<realLog2Denom;
697    const Int64 roundOffset = (log2Denom == 0) ? 0 : 1 << (log2Denom - 1);
698    const Int64 minValue = 0;
699    const Int64 maxValue = (1 << bitDepth) - 1;
700
701    for( Int y = 0; y < height; y++ )
702    {
703      for( Int x = 0; x < width; x++ )
704      {
705        Int64 scaledValue = Clip3(minValue, maxValue,  ((((Int64) pRefPel[x] * (Int64) weight + roundOffset) ) >>  (Int64) log2Denom) + realOffset);
706        SAD += abs((Int64)pOrgPel[x] -  scaledValue);
707      }
708      pOrgPel += orgStride;
709      pRefPel += refStride;
710    }
711  }
712  else
713  {
714    //const Int64 iSize          = iWidth*iHeight;
715    const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
716    const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
717
718    for( Int y = 0; y < height; y++ )
719    {
720      for( Int x = 0; x < width; x++ )
721      {
722        SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
723      }
724      pOrgPel += orgStride;
725      pRefPel += refStride;
726    }
727  }
728  return SAD;
729}
Note: See TracBrowser for help on using the repository browser.