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

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

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

  • Property svn:eol-style set to native
File size: 29.5 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        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
435        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
436        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
437        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
438
439        // current frame
440        const Int64 currDC = currWeightACDCParam[comp].iDC;
441        const Int64 currAC = currWeightACDCParam[comp].iAC;
442        // reference frame
443#if SVC_EXTENSION
444        Int64 refDC  = refWeightACDCParam[comp].iDC;
445        Int64 refAC  = refWeightACDCParam[comp].iAC;
446
447        if( validILRPic )
448        {
449          refAC = ( refAC * currWeightACDCParam[comp].numSamples ) / refWeightACDCParam[comp].numSamples;
450
451          const Int bitDepthLuma = slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
452          const Int refBitDepthLuma  = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA);
453          const Int delta = bitDepthLuma - refBitDepthLuma;
454
455          // jonint upsampling bitshift
456          refAC <<= delta;
457          refDC <<= delta;
458        }
459#else
460        const Int64 refDC  = refWeightACDCParam[comp].iDC;
461        const Int64 refAC  = refWeightACDCParam[comp].iAC;
462#endif
463
464        // calculating iWeight and iOffset params
465#if SVC_EXTENSION
466        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
467        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
468        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
469
470        if( !validILRPic )
471        {
472          dWeight = 1;
473          offset  = 0;
474        }
475        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
476#else
477        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
478        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
479        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
480#endif
481
482        Int clippedOffset;
483        if(isChroma(compID)) // Chroma offset range limination
484        {
485          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
486          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
487
488          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
489        }
490        else // Luma offset range limitation
491        {
492          clippedOffset = Clip3( -range, range-1, offset);
493        }
494
495        // Weighting factor limitation
496        const Int defaultWeight = (1<<log2Denom);
497        const Int deltaWeight   = (weight - defaultWeight);
498
499        if(deltaWeight >= range || deltaWeight < -range)
500        {
501          return false;
502        }
503
504#if SVC_EXTENSION
505        // make sure the reference frames other than ILR are not using weighted prediction
506        else
507        if( !validILRPic )
508        {
509          continue;
510        }
511#endif
512
513        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
514        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
515        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
516        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
517      }
518    }
519  }
520  return true;
521}
522
523
524/** select whether weighted pred enables or not.
525 * \param TComSlice *slice
526 * \param log2Denom
527 * \returns Bool
528 */
529Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram)
530{
531  const TComPicYuv *const pPic             = slice->getPic()->getPicYuvOrg();
532  const Int               defaultWeight    = 1<<log2Denom;
533  const Int               numPredDir       = slice->isInterP() ? 1 : 2;
534  const Bool              useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
535
536  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
537
538  for ( Int refList = 0; refList < numPredDir; refList++ )
539  {
540    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
541
542    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
543    {
544      Bool  useChromaWeight = false;
545
546      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
547      {
548        const ComponentID  compID     = ComponentID(comp);
549        const Pel         *pOrg       = pPic->getAddr(compID);
550        const Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
551        const Int          orgStride  = pPic->getStride(compID);
552        const Int          refStride  = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
553        const Int          width      = pPic->getWidth(compID);
554        const Int          height     = pPic->getHeight(compID);
555        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
556              WPScalingParam &wp      = m_wp[refList][refIdxTemp][compID];
557              Int          weight     = wp.iWeight;
558              Int          offset     = wp.iOffset;
559              Int          weightDef  = defaultWeight;
560              Int          offsetDef  = 0;
561
562        // calculate SAD costs with/without wp for luma
563        const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP);
564        if (SADnoWP > 0)
565        {
566          const Int64 SADWP   = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight,   offset, useHighPrecision, bClipInitialSADWP);
567          const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP;
568          Double dRatioSr0SAD = std::numeric_limits<Double>::max();
569          Double dRatioSrSAD  = std::numeric_limits<Double>::max();
570
571          if (bUseHistogram)
572          {
573            std::vector<Int> histogramOrg;// = pPic->getHistogram(compID);
574            std::vector<Int> histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID);
575            std::vector<Int> searchedHistogram;
576
577            // Compute histograms
578            xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth);
579            xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth);
580
581            // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded
582            xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID);
583            // calculate updated WP SAD
584            const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision);
585            dRatioSrSAD  = (Double)SADSrWP  / (Double)SADnoWP;
586
587            if (bDoEnhancement)
588            {
589              // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded
590              xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID);
591              // calculate updated WP SAD
592              const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision);
593              dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP;
594            }
595          }
596
597          if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
598          {
599            wp.bPresentFlag      = false;
600            wp.iOffset           = 0;
601            wp.iWeight           = defaultWeight;
602            wp.uiLog2WeightDenom = log2Denom;
603          }
604          else
605          {
606            if (compID != COMPONENT_Y)
607            {
608              useChromaWeight = true;
609            }
610
611            if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD)
612            {
613              wp.bPresentFlag      = true;
614              wp.iOffset           = offsetDef;
615              wp.iWeight           = weightDef;
616              wp.uiLog2WeightDenom = log2Denom;
617            }
618            else if (dRatioSrSAD < dRatioSAD)
619            {
620              wp.bPresentFlag      = true;
621              wp.iOffset           = offset;
622              wp.iWeight           = weight;
623              wp.uiLog2WeightDenom = log2Denom;
624            }
625          }
626        }
627        else // (SADnoWP <= 0)
628        {
629          wp.bPresentFlag      = false;
630          wp.iOffset           = 0;
631          wp.iWeight           = defaultWeight;
632          wp.uiLog2WeightDenom = log2Denom;
633        }
634      }
635
636      for(Int comp=1; comp<pPic->getNumberValidComponents(); comp++)
637      {
638        m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight;
639      }
640    }
641  }
642
643  return true;
644}
645
646//! select whether weighted pred enables or not.
647Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
648{
649        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
650  const Int               defaultWeight                       = 1<<log2Denom;
651  const Int               numPredDir                          = slice->isInterP() ? 1 : 2;
652  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
653
654  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
655
656  for ( Int refList = 0; refList < numPredDir; refList++ )
657  {
658    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
659
660    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
661    {
662      Int64 SADWP = 0, SADnoWP = 0;
663
664      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
665      {
666        const ComponentID  compID     = ComponentID(comp);
667              Pel         *pOrg       = pPic->getAddr(compID);
668              Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
669        const Int          orgStride = pPic->getStride(compID);
670        const Int          refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
671        const Int          width     = pPic->getWidth(compID);
672        const Int          height    = pPic->getHeight(compID);
673        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
674
675        // calculate SAD costs with/without wp for luma
676        SADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
677        SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting);
678      }
679
680      const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits<Double>::max();
681      if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
682      {
683        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
684        {
685          WPScalingParam &wp=m_wp[refList][refIdxTemp][comp];
686          wp.bPresentFlag      = false;
687          wp.iOffset           = 0;
688          wp.iWeight           = defaultWeight;
689          wp.uiLog2WeightDenom = log2Denom;
690        }
691      }
692    }
693  }
694
695  return true;
696}
697
698// Alternatively, a SSE-based measure could be used instead.
699// The respective function has been removed as it currently redundant.
700static
701Int64 xCalcSADvalueWP(const Int   bitDepth,
702                      const Pel  *pOrgPel,
703                      const Pel  *pRefPel,
704                      const Int   width,
705                      const Int   height,
706                      const Int   orgStride,
707                      const Int   refStride,
708                      const Int   log2Denom,
709                      const Int   weight,
710                      const Int   offset,
711                      const Bool  useHighPrecision)
712{
713  //const Int64 iSize          = iWidth*iHeight;
714  const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
715  const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
716
717  Int64 SAD = 0;
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 (iSAD/iSize);
729  return SAD;
730}
731
732static
733Int64 xCalcSADvalueWPOptionalClip(const Int   bitDepth,
734                                  const Pel  *pOrgPel,
735                                  const Pel  *pRefPel,
736                                  const Int   width,
737                                  const Int   height,
738                                  const Int   orgStride,
739                                  const Int   refStride,
740                                  const Int   log2Denom,
741                                  const Int   weight,
742                                  const Int   offset,
743                                  const Bool  useHighPrecision,
744                                  const Bool  clipped)
745{
746  Int64 SAD = 0;
747  if (clipped)
748  {
749    const Int64 realLog2Denom = useHighPrecision ? 0 : (bitDepth - 8);
750    const Int64 realOffset    = (Int64)offset<<realLog2Denom;
751    const Int64 roundOffset = (log2Denom == 0) ? 0 : 1 << (log2Denom - 1);
752    const Int64 minValue = 0;
753    const Int64 maxValue = (1 << bitDepth) - 1;
754
755    for( Int y = 0; y < height; y++ )
756    {
757      for( Int x = 0; x < width; x++ )
758      {
759        Int64 scaledValue = Clip3(minValue, maxValue,  ((((Int64) pRefPel[x] * (Int64) weight + roundOffset) ) >>  (Int64) log2Denom) + realOffset);
760        SAD += abs((Int64)pOrgPel[x] -  scaledValue);
761      }
762      pOrgPel += orgStride;
763      pRefPel += refStride;
764    }
765  }
766  else
767  {
768    //const Int64 iSize          = iWidth*iHeight;
769    const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
770    const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
771
772    for( Int y = 0; y < height; y++ )
773    {
774      for( Int x = 0; x < width; x++ )
775      {
776        SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
777      }
778      pOrgPel += orgStride;
779      pRefPel += refStride;
780    }
781  }
782  return SAD;
783}
Note: See TracBrowser for help on using the repository browser.