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

Last change on this file since 1402 was 1400, checked in by seregin, 10 years ago

port rev 4553

  • Property svn:eol-style set to native
File size: 30.7 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<Int64>::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//! calculate SSE values for both WP version and non-WP version.
223/*
224static
225Int64 xCalcSSEvalueWP(const Int   bitDepth,
226                      const Pel  *pOrgPel,
227                      const Pel  *pRefPel,
228                      const Int   width,
229                      const Int   height,
230                      const Int   orgStride,
231                      const Int   refStride,
232                      const Int   log2Denom,
233                      const Int   weight,
234                      const Int   offset,
235                      const Bool  useHighPrecision)
236{
237  const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
238
239  Int64 SSE = 0;
240  for( Int y = 0; y < height; y++ )
241  {
242    for( Int x = 0; x < width; x++ )
243    {
244      Int64 distortion = (( ((Int64)pOrgPel[x]<<(Int64)log2Denom) - ( (Int64)pRefPel[x] * (Int64)weight + ((Int64)offset<<realLog2Denom) ) ) );
245      SSE += distortion * distortion;
246    }
247    pOrgPel += orgStride;
248    pRefPel += refStride;
249  }
250
251  return SSE;
252}*/
253
254// -----------------------------------------------------------------------------
255// Member functions
256
257WeightPredAnalysis::WeightPredAnalysis()
258{
259  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
260  {
261    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
262    {
263      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
264      {
265        WPScalingParam  *pwp   = &(m_wp[lst][refIdx][comp]);
266        pwp->bPresentFlag      = false;
267        pwp->uiLog2WeightDenom = 0;
268        pwp->iWeight           = 1;
269        pwp->iOffset           = 0;
270      }
271    }
272  }
273}
274
275
276//! calculate AC and DC values for current original image
277Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
278{
279  //===== calculate AC/DC value =====
280  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
281
282  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
283
284  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
285  {
286    const ComponentID compID = ComponentID(componentIndex);
287
288    // calculate DC/AC value for channel
289
290    const Int stride = pPic->getStride(compID);
291    const Int width  = pPic->getWidth(compID);
292    const Int height = pPic->getHeight(compID);
293
294    const Int sample = width*height;
295
296    Int64 orgDC = 0;
297    {
298      const Pel *pPel = pPic->getAddr(compID);
299
300      for(Int y = 0; y < height; y++, pPel+=stride )
301      {
302        for(Int x = 0; x < width; x++ )
303        {
304          orgDC += (Int)( pPel[x] );
305        }
306      }
307    }
308
309    const Int64 orgNormDC = ((orgDC+(sample>>1)) / sample);
310
311    Int64 orgAC = 0;
312    {
313      const Pel *pPel = pPic->getAddr(compID);
314
315      for(Int y = 0; y < height; y++, pPel += stride )
316      {
317        for(Int x = 0; x < width; x++ )
318        {
319          orgAC += abs( (Int)pPel[x] - (Int)orgNormDC );
320        }
321      }
322    }
323
324    const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
325    weightACDCParam[compID].iDC = (((orgDC<<fixedBitShift)+(sample>>1)) / sample);
326    weightACDCParam[compID].iAC = orgAC;
327#if SVC_EXTENSION
328    weightACDCParam[compID].numSamples = sample;
329#endif
330  }
331
332  slice->setWpAcDcParam(weightACDCParam);
333}
334
335
336//! check weighted pred or non-weighted pred
337Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
338{
339  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
340
341  Int presentCnt = 0;
342  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
343  {
344    for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
345    {
346      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
347      {
348        WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
349        presentCnt += (Int)pwp->bPresentFlag;
350      }
351    }
352  }
353
354  if(presentCnt==0)
355  {
356    slice->setTestWeightPred(false);
357    slice->setTestWeightBiPred(false);
358
359    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
360    {
361      for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ )
362      {
363        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
364        {
365          WPScalingParam  *pwp = &(m_wp[lst][refIdx][componentIndex]);
366
367          pwp->bPresentFlag      = false;
368          pwp->uiLog2WeightDenom = 0;
369          pwp->iWeight           = 1;
370          pwp->iOffset           = 0;
371        }
372      }
373    }
374    slice->setWpScaling( m_wp );
375  }
376  else
377  {
378    slice->setTestWeightPred  (slice->getPPS()->getUseWP());
379    slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred());
380  }
381}
382
383
384//! estimate wp tables for explicit wp
385Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method)
386{
387  Int  iDenom         = 6;
388  Bool validRangeFlag = false;
389
390  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
391  {
392    iDenom = 7;
393  }
394
395  do
396  {
397    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
398    if (!validRangeFlag)
399    {
400      iDenom--; // decrement to satisfy the range limitation
401    }
402  } while (validRangeFlag == false);
403
404  // selecting whether WP is used, or not (fast search)
405  // NOTE: This is not operating on a slice, but the entire picture.
406  switch (method)
407  {
408    case WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT:
409      xSelectWP(slice, iDenom);
410      break;
411    case WP_PER_PICTURE_WITH_SIMPLE_DC_PER_COMPONENT:
412      xSelectWPHistExtClip(slice, iDenom, false, false, false);
413      break;
414    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT:
415      xSelectWPHistExtClip(slice, iDenom, false, false, true);
416      break;
417    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING:
418      xSelectWPHistExtClip(slice, iDenom, false, true, true);
419      break;
420    case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION:
421      xSelectWPHistExtClip(slice, iDenom, true, true, true);
422      break;
423    default:
424      assert(0);
425      exit(1);
426  }
427
428  slice->setWpScaling( m_wp );
429}
430
431
432//! update wp tables for explicit wp w.r.t range limitation
433Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
434{
435  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
436  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
437  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
438
439  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
440
441  for ( Int refList = 0; refList < numPredDir; refList++ )
442  {
443    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
444
445    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
446    {
447      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
448      slice->getWpAcDcParam(currWeightACDCParam);
449      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
450
451#if SVC_EXTENSION
452      UInt currLayerId = slice->getLayerId();
453      UInt refLayerId  = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId();
454      Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0;
455
456      if( validILRPic )
457      {
458        slice->getWpAcDcParam(refWeightACDCParam);
459      }
460#endif
461
462      for ( Int comp = 0; comp < numComp; comp++ )
463      {
464        const ComponentID compID        = ComponentID(comp);
465#if SVC_EXTENSION
466        const Int         bitDepth      = slice->getBitDepth(toChannelType(compID));
467#else
468        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
469#endif
470        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
471        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
472        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
473
474        // current frame
475        const Int64 currDC = currWeightACDCParam[comp].iDC;
476        const Int64 currAC = currWeightACDCParam[comp].iAC;
477        // reference frame
478#if SVC_EXTENSION
479        Int64 refDC  = refWeightACDCParam[comp].iDC;
480        Int64 refAC  = refWeightACDCParam[comp].iAC;
481
482        if( validILRPic )
483        {
484          refAC = ( refAC * currWeightACDCParam[comp].numSamples ) / refWeightACDCParam[comp].numSamples;
485
486          const Int bitDepthLuma = slice->getBitDepth(CHANNEL_TYPE_LUMA);
487          const Int refBitDepthLuma  = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getBitDepth(CHANNEL_TYPE_LUMA);
488          const Int delta = bitDepthLuma - refBitDepthLuma;
489
490          // jonint upsampling bitshift
491          refAC <<= delta;
492          refDC <<= delta;
493        }
494#else
495        const Int64 refDC  = refWeightACDCParam[comp].iDC;
496        const Int64 refAC  = refWeightACDCParam[comp].iAC;
497#endif
498
499        // calculating iWeight and iOffset params
500#if SVC_EXTENSION
501        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
502        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
503        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
504
505        if( !validILRPic )
506        {
507          dWeight = 1;
508          offset  = 0;
509        }
510        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
511#else
512        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
513        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
514        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
515#endif
516
517        Int clippedOffset;
518        if(isChroma(compID)) // Chroma offset range limination
519        {
520          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
521          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
522
523          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
524        }
525        else // Luma offset range limitation
526        {
527          clippedOffset = Clip3( -range, range-1, offset);
528        }
529
530        // Weighting factor limitation
531        const Int defaultWeight = (1<<log2Denom);
532        const Int deltaWeight   = (weight - defaultWeight);
533
534        if(deltaWeight >= range || deltaWeight < -range)
535        {
536          return false;
537        }
538
539#if SVC_EXTENSION
540        // make sure the reference frames other than ILR are not using weighted prediction
541        else
542        if( !validILRPic )
543        {
544          continue;
545        }
546#endif
547
548        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
549        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
550        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
551        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
552      }
553    }
554  }
555  return true;
556}
557
558
559/** select whether weighted pred enables or not.
560 * \param TComSlice *slice
561 * \param log2Denom
562 * \returns Bool
563 */
564Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram)
565{
566  const TComPicYuv *const pPic             = slice->getPic()->getPicYuvOrg();
567  const Int               defaultWeight    = 1<<log2Denom;
568  const Int               numPredDir       = slice->isInterP() ? 1 : 2;
569  const Bool              useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
570
571  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
572
573  for ( Int refList = 0; refList < numPredDir; refList++ )
574  {
575    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
576
577    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
578    {
579      Bool  useChromaWeight = false;
580
581      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
582      {
583        const ComponentID  compID     = ComponentID(comp);
584        const Pel         *pOrg       = pPic->getAddr(compID);
585        const Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
586        const Int          orgStride  = pPic->getStride(compID);
587        const Int          refStride  = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
588        const Int          width      = pPic->getWidth(compID);
589        const Int          height     = pPic->getHeight(compID);
590#if SVC_EXTENSION
591        const Int          bitDepth   = slice->getBitDepth(toChannelType(compID));
592#else
593        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
594#endif
595              WPScalingParam &wp      = m_wp[refList][refIdxTemp][compID];
596              Int          weight     = wp.iWeight;
597              Int          offset     = wp.iOffset;
598              Int          weightDef  = defaultWeight;
599              Int          offsetDef  = 0;
600
601        // calculate SAD costs with/without wp for luma
602        const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP);
603        if (SADnoWP > 0)
604        {
605          const Int64 SADWP   = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight,   offset, useHighPrecision, bClipInitialSADWP);
606          const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP;
607          Double dRatioSr0SAD = std::numeric_limits<Double>::max();
608          Double dRatioSrSAD  = std::numeric_limits<Double>::max();
609
610          if (bUseHistogram)
611          {
612            std::vector<Int> histogramOrg;// = pPic->getHistogram(compID);
613            std::vector<Int> histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID);
614            std::vector<Int> searchedHistogram;
615
616            // Compute histograms
617            xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth);
618            xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth);
619
620            // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded
621            xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID);
622            // calculate updated WP SAD
623            const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision);
624            dRatioSrSAD  = (Double)SADSrWP  / (Double)SADnoWP;
625
626            if (bDoEnhancement)
627            {
628              // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded
629              xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID);
630              // calculate updated WP SAD
631              const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision);
632              dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP;
633            }
634          }
635
636          if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
637          {
638            wp.bPresentFlag      = false;
639            wp.iOffset           = 0;
640            wp.iWeight           = defaultWeight;
641            wp.uiLog2WeightDenom = log2Denom;
642          }
643          else
644          {
645            if (compID != COMPONENT_Y)
646            {
647              useChromaWeight = true;
648            }
649
650            if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD)
651            {
652              wp.bPresentFlag      = true;
653              wp.iOffset           = offsetDef;
654              wp.iWeight           = weightDef;
655              wp.uiLog2WeightDenom = log2Denom;
656            }
657            else if (dRatioSrSAD < dRatioSAD)
658            {
659              wp.bPresentFlag      = true;
660              wp.iOffset           = offset;
661              wp.iWeight           = weight;
662              wp.uiLog2WeightDenom = log2Denom;
663            }
664          }
665        }
666        else // (SADnoWP <= 0)
667        {
668          wp.bPresentFlag      = false;
669          wp.iOffset           = 0;
670          wp.iWeight           = defaultWeight;
671          wp.uiLog2WeightDenom = log2Denom;
672        }
673      }
674
675      for(Int comp=1; comp<pPic->getNumberValidComponents(); comp++)
676      {
677        m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight;
678      }
679    }
680  }
681
682  return true;
683}
684
685//! select whether weighted pred enables or not.
686Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
687{
688        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
689  const Int               defaultWeight                       = 1<<log2Denom;
690  const Int               numPredDir                          = slice->isInterP() ? 1 : 2;
691  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
692
693  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
694
695  for ( Int refList = 0; refList < numPredDir; refList++ )
696  {
697    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
698
699    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
700    {
701      Int64 SADWP = 0, SADnoWP = 0;
702
703      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
704      {
705        const ComponentID  compID     = ComponentID(comp);
706              Pel         *pOrg       = pPic->getAddr(compID);
707              Pel         *pRef       = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID);
708        const Int          orgStride = pPic->getStride(compID);
709        const Int          refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID);
710        const Int          width     = pPic->getWidth(compID);
711        const Int          height    = pPic->getHeight(compID);
712#if SVC_EXTENSION
713        const Int          bitDepth   = slice->getBitDepth(toChannelType(compID));
714#else
715        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
716#endif
717
718        // calculate SAD costs with/without wp for luma
719        SADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
720        SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting);
721      }
722
723      const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits<Double>::max();
724      if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD)
725      {
726        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
727        {
728          WPScalingParam &wp=m_wp[refList][refIdxTemp][comp];
729          wp.bPresentFlag      = false;
730          wp.iOffset           = 0;
731          wp.iWeight           = defaultWeight;
732          wp.uiLog2WeightDenom = log2Denom;
733        }
734      }
735    }
736  }
737
738  return true;
739}
740
741static
742Int64 xCalcSADvalueWP(const Int   bitDepth,
743                      const Pel  *pOrgPel,
744                      const Pel  *pRefPel,
745                      const Int   width,
746                      const Int   height,
747                      const Int   orgStride,
748                      const Int   refStride,
749                      const Int   log2Denom,
750                      const Int   weight,
751                      const Int   offset,
752                      const Bool  useHighPrecision)
753{
754  //const Int64 iSize          = iWidth*iHeight;
755  const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
756  const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
757
758  Int64 SAD = 0;
759  for( Int y = 0; y < height; y++ )
760  {
761    for( Int x = 0; x < width; x++ )
762    {
763      SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
764    }
765    pOrgPel += orgStride;
766    pRefPel += refStride;
767  }
768
769  //return (iSAD/iSize);
770  return SAD;
771}
772
773static
774Int64 xCalcSADvalueWPOptionalClip(const Int   bitDepth,
775                                  const Pel  *pOrgPel,
776                                  const Pel  *pRefPel,
777                                  const Int   width,
778                                  const Int   height,
779                                  const Int   orgStride,
780                                  const Int   refStride,
781                                  const Int   log2Denom,
782                                  const Int   weight,
783                                  const Int   offset,
784                                  const Bool  useHighPrecision,
785                                  const Bool  clipped)
786{
787  Int64 SAD = 0;
788  if (clipped)
789  {
790    const Int64 realLog2Denom = useHighPrecision ? 0 : (bitDepth - 8);
791    const Int64 realOffset    = (Int64)offset<<realLog2Denom;
792    const Int64 roundOffset = (log2Denom == 0) ? 0 : 1 << (log2Denom - 1);
793    const Int64 minValue = 0;
794    const Int64 maxValue = (1 << bitDepth) - 1;
795
796    for( Int y = 0; y < height; y++ )
797    {
798      for( Int x = 0; x < width; x++ )
799      {
800        Int64 scaledValue = Clip3(minValue, maxValue,  ((((Int64) pRefPel[x] * (Int64) weight + roundOffset) ) >>  (Int64) log2Denom) + realOffset);
801        SAD += abs((Int64)pOrgPel[x] -  scaledValue);
802      }
803      pOrgPel += orgStride;
804      pRefPel += refStride;
805    }
806  }
807  else
808  {
809    //const Int64 iSize          = iWidth*iHeight;
810    const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8));
811    const Int64 realOffset    = ((Int64)offset)<<realLog2Denom;
812
813    for( Int y = 0; y < height; y++ )
814    {
815      for( Int x = 0; x < width; x++ )
816      {
817        SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) );
818      }
819      pOrgPel += orgStride;
820      pRefPel += refStride;
821    }
822  }
823  return SAD;
824}
Note: See TracBrowser for help on using the repository browser.