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

Last change on this file since 1369 was 1335, checked in by seregin, 9 years ago

port rev 4413

  • Property svn:eol-style set to native
File size: 15.0 KB
RevLine 
[313]1/* The copyright in this software is being made available under the BSD
2 * License, included below. This software may be subject to other third party
3 * and contributor rights, including patent rights, and no such rights are
[494]4 * granted under this license.
[313]5 *
[1259]6 * Copyright (c) 2010-2015, ITU/ISO/IEC
[313]7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
11 *
12 *  * Redistributions of source code must retain the above copyright notice,
13 *    this list of conditions and the following disclaimer.
14 *  * Redistributions in binary form must reproduce the above copyright notice,
15 *    this list of conditions and the following disclaimer in the documentation
16 *    and/or other materials provided with the distribution.
17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
18 *    be used to endorse or promote products derived from this software without
19 *    specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
31 * THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34/** \file     WeightPredAnalysis.cpp
35    \brief    weighted prediction encoder class
36*/
37
[1335]38#include "../TLibCommon/CommonDef.h"
[313]39#include "../TLibCommon/TComSlice.h"
40#include "../TLibCommon/TComPic.h"
41#include "../TLibCommon/TComPicYuv.h"
42#include "WeightPredAnalysis.h"
43
44#define ABS(a)    ((a) < 0 ? - (a) : (a))
45#define DTHRESH (0.99)
46
47WeightPredAnalysis::WeightPredAnalysis()
48{
[1029]49  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]50  {
[494]51    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[313]52    {
[1029]53      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
[313]54      {
[1029]55        WPScalingParam  *pwp   = &(m_wp[lst][iRefIdx][comp]);
[313]56        pwp->bPresentFlag      = false;
57        pwp->uiLog2WeightDenom = 0;
58        pwp->iWeight           = 1;
59        pwp->iOffset           = 0;
60      }
61    }
62  }
63}
64
[1029]65
[1260]66//! calculate AC and DC values for current original image
[1029]67Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
[313]68{
69  //===== calculate AC/DC value =====
70  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
71
[1029]72  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
[313]73
[1029]74  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
75  {
76    const ComponentID compID = ComponentID(componentIndex);
[313]77
[1029]78    // calculate DC/AC value for channel
79
80    const Int iStride = pPic->getStride(compID);
81    const Int iWidth  = pPic->getWidth(compID);
82    const Int iHeight = pPic->getHeight(compID);
83
84    const Int iSample = iWidth*iHeight;
85
86    Int64 iOrgDC = 0;
87    {
88      const Pel *pPel = pPic->getAddr(compID);
89
90      for(Int y = 0; y < iHeight; y++, pPel+=iStride )
[1246]91      {
[1029]92        for(Int x = 0; x < iWidth; x++ )
[1246]93        {
[1029]94          iOrgDC += (Int)( pPel[x] );
[1246]95        }
96      }
[1029]97    }
98
99    const Int64 iOrgNormDC = ((iOrgDC+(iSample>>1)) / iSample);
100
101    Int64 iOrgAC = 0;
102    {
103      const Pel *pPel = pPic->getAddr(compID);
104
105      for(Int y = 0; y < iHeight; y++, pPel += iStride )
[1246]106      {
[1029]107        for(Int x = 0; x < iWidth; x++ )
[1246]108        {
[1029]109          iOrgAC += abs( (Int)pPel[x] - (Int)iOrgNormDC );
[1246]110        }
111      }
[1029]112    }
113
[1316]114    const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
[1201]115    weightACDCParam[compID].iDC = (((iOrgDC<<fixedBitShift)+(iSample>>1)) / iSample);
116    weightACDCParam[compID].iAC = iOrgAC;
117#if SVC_EXTENSION
[1029]118    weightACDCParam[compID].iSamples = iSample;
[494]119#endif
[1029]120  }
[313]121
122  slice->setWpAcDcParam(weightACDCParam);
123}
124
[1246]125
[1260]126//! check weighted pred or non-weighted pred
[1029]127Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
[313]128{
[1029]129  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
130
[313]131  Int iPresentCnt = 0;
[1029]132  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]133  {
[494]134    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[313]135    {
[1029]136      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[313]137      {
[1029]138        WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
[313]139        iPresentCnt += (Int)pwp->bPresentFlag;
140      }
141    }
142  }
143
144  if(iPresentCnt==0)
145  {
[1235]146    slice->setTestWeightPred(false);
147    slice->setTestWeightBiPred(false);
[1029]148
149    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]150    {
[494]151      for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[313]152      {
[1029]153        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[313]154        {
[1029]155          WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
156
[313]157          pwp->bPresentFlag      = false;
158          pwp->uiLog2WeightDenom = 0;
159          pwp->iWeight           = 1;
160          pwp->iOffset           = 0;
161        }
162      }
163    }
164    slice->setWpScaling( m_wp );
165  }
[1235]166  else
167  {
168    slice->setTestWeightPred(slice->getPPS()->getUseWP());
169    slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred());
170  }
[313]171}
172
[1029]173
[1260]174//! estimate wp tables for explicit wp
[1029]175Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice)
[313]176{
[1029]177  Int  iDenom         = 6;
[313]178  Bool validRangeFlag = false;
179
180  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
181  {
[1029]182    iDenom = 7;
[313]183  }
184
185  do
186  {
[1029]187    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
[313]188    if (!validRangeFlag)
189    {
190      iDenom--; // decrement to satisfy the range limitation
191    }
192  } while (validRangeFlag == false);
193
[1235]194  // selecting whether WP is used, or not (fast search)
195  // NOTE: This is not operating on a slice, but the entire picture.
[1029]196  xSelectWP(slice, iDenom);
[494]197
[313]198  slice->setWpScaling( m_wp );
199}
200
[1029]201
[1260]202//! update wp tables for explicit wp w.r.t range limitation
[1029]203Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
[313]204{
[1029]205  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
[1316]206  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
[1029]207  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
208
209  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
210
[313]211  for ( Int refList = 0; refList < numPredDir; refList++ )
212  {
[1029]213    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
214
[313]215    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
216    {
[1316]217      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
218      slice->getWpAcDcParam(currWeightACDCParam);
219      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
[1029]220
[1201]221#if SVC_EXTENSION
[494]222      UInt currLayerId = slice->getLayerId();
223      UInt refLayerId  = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId();
224      Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0;
[313]225
[494]226      if( validILRPic )
227      {
[1316]228        slice->getWpAcDcParam(refWeightACDCParam);
[494]229      }
230#endif
231
[1029]232      for ( Int comp = 0; comp < numComp; comp++ )
[313]233      {
[1029]234        const ComponentID compID        = ComponentID(comp);
[1287]235#if SVC_EXTENSION
236        const Int         bitDepth      = slice->getBitDepth(toChannelType(compID));
237#else
238        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
239#endif
240        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
241        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
[1029]242        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
[313]243
244        // current frame
[1029]245        const Int64 currDC = currWeightACDCParam[comp].iDC;
246        const Int64 currAC = currWeightACDCParam[comp].iAC;
[313]247        // reference frame
[1201]248#if SVC_EXTENSION
[1029]249        Int64 refDC  = refWeightACDCParam[comp].iDC;
250        Int64 refAC  = refWeightACDCParam[comp].iAC;
251
[494]252        if( validILRPic )
253        {
254          refAC = ( refAC * currWeightACDCParam[comp].iSamples ) /refWeightACDCParam[comp].iSamples;
[1202]255
[1287]256          const Int bitDepthLuma = slice->getBitDepth(CHANNEL_TYPE_LUMA);
257          const Int refBitDepthLuma  = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getBitDepth(CHANNEL_TYPE_LUMA);
258          const Int delta = bitDepthLuma - refBitDepthLuma;
259
[1202]260          // jonint upsampling bitshift
[1287]261          refAC <<= delta;
262          refDC <<= delta;
[494]263        }
[1029]264#else
265        const Int64 refDC  = refWeightACDCParam[comp].iDC;
266        const Int64 refAC  = refWeightACDCParam[comp].iAC;
[494]267#endif
[313]268
269        // calculating iWeight and iOffset params
[1201]270#if SVC_EXTENSION
[313]271        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
[1029]272        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
273        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
274
[494]275        if( !validILRPic )
276        {
277          dWeight = 1;
278          offset  = 0;
279        }
280        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
[1029]281#else
282        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
283        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
284        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
[494]285#endif
[313]286
[1029]287        Int clippedOffset;
288        if(isChroma(compID)) // Chroma offset range limination
[313]289        {
[1029]290          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
291          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
292
293          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
[313]294        }
[1029]295        else // Luma offset range limitation
[313]296        {
[1029]297          clippedOffset = Clip3( -range, range-1, offset);
[313]298        }
299
300        // Weighting factor limitation
[1029]301        const Int defaultWeight = (1<<log2Denom);
302        const Int deltaWeight   = (defaultWeight - weight);
303
304        if(deltaWeight >= range || deltaWeight < -range)
[1246]305        {
[1029]306          return false;
[1246]307        }
[1029]308
[1201]309#if SVC_EXTENSION
[494]310        // make sure the reference frames other than ILR are not using weighted prediction
311        else
312        if( !validILRPic )
313        {
314          continue;
315        }
316#endif
[313]317
[1029]318        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
319        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
320        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
321        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[313]322      }
323    }
324  }
[1029]325  return true;
[313]326}
327
[1029]328
[1260]329//! select whether weighted pred enables or not.
[1029]330Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
[313]331{
[1029]332        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
333  const Int               iDefaultWeight                      = ((Int)1<<log2Denom);
334  const Int               iNumPredDir                         = slice->isInterP() ? 1 : 2;
[1316]335  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
[313]336
[1029]337  assert (iNumPredDir <= Int(NUM_REF_PIC_LIST_01));
338
[313]339  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
340  {
[1029]341    const RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
342
[313]343    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
344    {
[1029]345      Int64 iSADWP = 0, iSADnoWP = 0;
[313]346
[1029]347      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
348      {
349        const ComponentID  compID     = ComponentID(comp);
350              Pel         *pOrg       = pPic->getAddr(compID);
351              Pel         *pRef       = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getAddr(compID);
352        const Int          iOrgStride = pPic->getStride(compID);
353        const Int          iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getStride(compID);
354        const Int          iWidth     = pPic->getWidth(compID);
355        const Int          iHeight    = pPic->getHeight(compID);
[1287]356#if SVC_EXTENSION
357        const Int          bitDepth   = slice->getBitDepth(toChannelType(compID));
358#else
359        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
360#endif
[313]361
[1029]362        // calculate SAD costs with/without wp for luma
363        iSADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, m_wp[iRefList][iRefIdxTemp][compID].iWeight, m_wp[iRefList][iRefIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
364        iSADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, iDefaultWeight, 0, useHighPrecisionPredictionWeighting);
365      }
[313]366
[1029]367      const Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
[313]368      if(dRatio >= (Double)DTHRESH)
369      {
[1029]370        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
[313]371        {
[1029]372          m_wp[iRefList][iRefIdxTemp][comp].bPresentFlag      = false;
373          m_wp[iRefList][iRefIdxTemp][comp].iOffset           = 0;
374          m_wp[iRefList][iRefIdxTemp][comp].iWeight           = iDefaultWeight;
375          m_wp[iRefList][iRefIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[313]376        }
377      }
378    }
379  }
380
[1029]381  return true;
[313]382}
383
384
[1260]385//! calculate SAD values for both WP version and non-WP version.
[1029]386Int64 WeightPredAnalysis::xCalcSADvalueWP(const Int   bitDepth,
387                                          const Pel  *pOrgPel,
388                                          const Pel  *pRefPel,
389                                          const Int   iWidth,
390                                          const Int   iHeight,
391                                          const Int   iOrgStride,
392                                          const Int   iRefStride,
393                                          const Int   iLog2Denom,
394                                          const Int   iWeight,
395                                          const Int   iOffset,
396                                          const Bool  useHighPrecisionPredictionWeighting)
[313]397{
[1029]398  const Int64 iSize          = iWidth*iHeight;
399  const Int64 iRealLog2Denom = useHighPrecisionPredictionWeighting ? iLog2Denom : (iLog2Denom + (bitDepth - 8));
400
[313]401  Int64 iSAD = 0;
[1029]402  for( Int y = 0; y < iHeight; y++ )
[313]403  {
[1029]404    for( Int x = 0; x < iWidth; x++ )
[313]405    {
[1029]406      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iLog2Denom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealLog2Denom) ) ) );
[313]407    }
408    pOrgPel += iOrgStride;
409    pRefPel += iRefStride;
410  }
[1029]411
[313]412  return (iSAD/iSize);
413}
Note: See TracBrowser for help on using the repository browser.