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

Last change on this file since 1313 was 1313, checked in by tech, 9 years ago

Merged 14.1-update-dev1@1312.

  • Property svn:eol-style set to native
File size: 13.0 KB
RevLine 
[5]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
[1313]4 * granted under this license.
[5]5 *
[1313]6 * Copyright (c) 2010-2015, ITU/ISO/IEC
[5]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.
[56]17 *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
[5]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 */
[2]33
[608]34/** \file     WeightPredAnalysis.cpp
35    \brief    weighted prediction encoder class
[2]36*/
37
[1313]38#include "../TLibCommon/CommonDef.h"
[2]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))
[56]45#define DTHRESH (0.99)
[2]46
47WeightPredAnalysis::WeightPredAnalysis()
48{
[1313]49  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[56]50  {
[1313]51    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[56]52    {
[1313]53      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
[56]54      {
[1313]55        WPScalingParam  *pwp   = &(m_wp[lst][iRefIdx][comp]);
[2]56        pwp->bPresentFlag      = false;
57        pwp->uiLog2WeightDenom = 0;
58        pwp->iWeight           = 1;
59        pwp->iOffset           = 0;
60      }
61    }
[56]62  }
[2]63}
64
[1313]65
66//! calculate AC and DC values for current original image
67Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
[2]68{
69  //===== calculate AC/DC value =====
70  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
71
[1313]72  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
[2]73
[1313]74  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
75  {
76    const ComponentID compID = ComponentID(componentIndex);
[2]77
[1313]78    // calculate DC/AC value for channel
[2]79
[1313]80    const Int iStride = pPic->getStride(compID);
81    const Int iWidth  = pPic->getWidth(compID);
82    const Int iHeight = pPic->getHeight(compID);
[2]83
[1313]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 )
91      {
92        for(Int x = 0; x < iWidth; x++ )
93        {
94          iOrgDC += (Int)( pPel[x] );
95        }
96      }
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 )
106      {
107        for(Int x = 0; x < iWidth; x++ )
108        {
109          iOrgAC += abs( (Int)pPel[x] - (Int)iOrgNormDC );
110        }
111      }
112    }
113
114    const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
115    weightACDCParam[compID].iDC = (((iOrgDC<<fixedBitShift)+(iSample>>1)) / iSample);
116    weightACDCParam[compID].iAC = iOrgAC;
117  }
118
[2]119  slice->setWpAcDcParam(weightACDCParam);
120}
[56]121
122
[1313]123//! check weighted pred or non-weighted pred
124Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
[56]125{
[1313]126  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
[56]127
128  Int iPresentCnt = 0;
[1313]129  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[56]130  {
[1313]131    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[56]132    {
[1313]133      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[56]134      {
[1313]135        WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
[56]136        iPresentCnt += (Int)pwp->bPresentFlag;
137      }
138    }
139  }
140
141  if(iPresentCnt==0)
142  {
[1313]143    slice->setTestWeightPred(false);
144    slice->setTestWeightBiPred(false);
145
146    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[56]147    {
[1313]148      for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[56]149      {
[1313]150        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[56]151        {
[1313]152          WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
153
[56]154          pwp->bPresentFlag      = false;
155          pwp->uiLog2WeightDenom = 0;
156          pwp->iWeight           = 1;
157          pwp->iOffset           = 0;
158        }
159      }
160    }
161    slice->setWpScaling( m_wp );
162  }
[1313]163  else
164  {
165    slice->setTestWeightPred(slice->getPPS()->getUseWP());
166    slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred());
167  }
[56]168}
169
[1313]170
171//! estimate wp tables for explicit wp
172Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice)
[2]173{
[1313]174  Int  iDenom         = 6;
[608]175  Bool validRangeFlag = false;
[2]176
177  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
178  {
[1313]179    iDenom = 7;
[2]180  }
[608]181
182  do
183  {
[1313]184    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
[608]185    if (!validRangeFlag)
186    {
187      iDenom--; // decrement to satisfy the range limitation
188    }
189  } while (validRangeFlag == false);
190
[1313]191  // selecting whether WP is used, or not (fast search)
192  // NOTE: This is not operating on a slice, but the entire picture.
193  xSelectWP(slice, iDenom);
194
[608]195  slice->setWpScaling( m_wp );
196}
197
[1313]198
199//! update wp tables for explicit wp w.r.t range limitation
200Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
[608]201{
[1313]202  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
203  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
204  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
205
206  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
207
[608]208  for ( Int refList = 0; refList < numPredDir; refList++ )
[2]209  {
[1313]210    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
211
[608]212    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
[2]213    {
[1313]214      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
[608]215      slice->getWpAcDcParam(currWeightACDCParam);
216      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
[2]217
[1313]218      for ( Int comp = 0; comp < numComp; comp++ )
[2]219      {
[1313]220        const ComponentID compID        = ComponentID(comp);
221        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
222        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
223        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
224        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
[608]225
[2]226        // current frame
[1313]227        const Int64 currDC = currWeightACDCParam[comp].iDC;
228        const Int64 currAC = currWeightACDCParam[comp].iAC;
[2]229        // reference frame
[1313]230        const Int64 refDC  = refWeightACDCParam[comp].iDC;
231        const Int64 refAC  = refWeightACDCParam[comp].iAC;
[2]232
[56]233        // calculating iWeight and iOffset params
[1313]234        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
235        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
236        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
[2]237
[1313]238        Int clippedOffset;
239        if(isChroma(compID)) // Chroma offset range limination
[608]240        {
[1313]241          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
242          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
243
244          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
[608]245        }
[1313]246        else // Luma offset range limitation
[608]247        {
[1313]248          clippedOffset = Clip3( -range, range-1, offset);
[608]249        }
250
251        // Weighting factor limitation
[1313]252        const Int defaultWeight = (1<<log2Denom);
253        const Int deltaWeight   = (defaultWeight - weight);
[608]254
[1313]255        if(deltaWeight >= range || deltaWeight < -range)
256        {
257          return false;
258        }
259
260        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
261        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
262        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
263        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[2]264      }
265    }
266  }
[1313]267  return true;
[2]268}
[56]269
[1313]270
271//! select whether weighted pred enables or not.
272Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
[2]273{
[1313]274        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
275  const Int               iDefaultWeight                      = ((Int)1<<log2Denom);
276  const Int               iNumPredDir                         = slice->isInterP() ? 1 : 2;
277  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
[2]278
[1313]279  assert (iNumPredDir <= Int(NUM_REF_PIC_LIST_01));
280
[2]281  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
282  {
[1313]283    const RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
284
[2]285    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
286    {
[1313]287      Int64 iSADWP = 0, iSADnoWP = 0;
[2]288
[1313]289      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
290      {
291        const ComponentID  compID     = ComponentID(comp);
292              Pel         *pOrg       = pPic->getAddr(compID);
293              Pel         *pRef       = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getAddr(compID);
294        const Int          iOrgStride = pPic->getStride(compID);
295        const Int          iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getStride(compID);
296        const Int          iWidth     = pPic->getWidth(compID);
297        const Int          iHeight    = pPic->getHeight(compID);
298        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
[2]299
[1313]300        // calculate SAD costs with/without wp for luma
301        iSADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, m_wp[iRefList][iRefIdxTemp][compID].iWeight, m_wp[iRefList][iRefIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
302        iSADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, iDefaultWeight, 0, useHighPrecisionPredictionWeighting);
303      }
[2]304
[1313]305      const Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
[56]306      if(dRatio >= (Double)DTHRESH)
[2]307      {
[1313]308        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
[2]309        {
[1313]310          m_wp[iRefList][iRefIdxTemp][comp].bPresentFlag      = false;
311          m_wp[iRefList][iRefIdxTemp][comp].iOffset           = 0;
312          m_wp[iRefList][iRefIdxTemp][comp].iWeight           = iDefaultWeight;
313          m_wp[iRefList][iRefIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[2]314        }
315      }
316    }
317  }
[56]318
[1313]319  return true;
[2]320}
[56]321
[2]322
[1313]323//! calculate SAD values for both WP version and non-WP version.
324Int64 WeightPredAnalysis::xCalcSADvalueWP(const Int   bitDepth,
325                                          const Pel  *pOrgPel,
326                                          const Pel  *pRefPel,
327                                          const Int   iWidth,
328                                          const Int   iHeight,
329                                          const Int   iOrgStride,
330                                          const Int   iRefStride,
331                                          const Int   iLog2Denom,
332                                          const Int   iWeight,
333                                          const Int   iOffset,
334                                          const Bool  useHighPrecisionPredictionWeighting)
[2]335{
[1313]336  const Int64 iSize          = iWidth*iHeight;
337  const Int64 iRealLog2Denom = useHighPrecisionPredictionWeighting ? iLog2Denom : (iLog2Denom + (bitDepth - 8));
[2]338
339  Int64 iSAD = 0;
[1313]340  for( Int y = 0; y < iHeight; y++ )
[2]341  {
[1313]342    for( Int x = 0; x < iWidth; x++ )
[2]343    {
[1313]344      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iLog2Denom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealLog2Denom) ) ) );
[2]345    }
346    pOrgPel += iOrgStride;
347    pRefPel += iRefStride;
348  }
[1313]349
[2]350  return (iSAD/iSize);
351}
Note: See TracBrowser for help on using the repository browser.