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

Last change on this file since 1154 was 1029, checked in by seregin, 10 years ago

merge with SHM-upgrade branch

  • Property svn:eol-style set to native
File size: 15.5 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 *
[595]6 * Copyright (c) 2010-2014, 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
38#include "../TLibCommon/TypeDef.h"
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{
49  m_weighted_pred_flag = false;
50  m_weighted_bipred_flag = false;
[1029]51
52  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]53  {
[494]54    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[313]55    {
[1029]56      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
[313]57      {
[1029]58        WPScalingParam  *pwp   = &(m_wp[lst][iRefIdx][comp]);
[313]59        pwp->bPresentFlag      = false;
60        pwp->uiLog2WeightDenom = 0;
61        pwp->iWeight           = 1;
62        pwp->iOffset           = 0;
63      }
64    }
65  }
66}
67
[1029]68
[313]69/** calculate AC and DC values for current original image
70 * \param TComSlice *slice
71 * \returns Void
72 */
[1029]73Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
[313]74{
75  //===== calculate AC/DC value =====
76  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
77
[1029]78  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
[313]79
[1029]80  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
81  {
82    const ComponentID compID = ComponentID(componentIndex);
[313]83
[1029]84    // calculate DC/AC value for channel
85
86    const Int iStride = pPic->getStride(compID);
87    const Int iWidth  = pPic->getWidth(compID);
88    const Int iHeight = pPic->getHeight(compID);
89
90    const Int iSample = iWidth*iHeight;
91
92    Int64 iOrgDC = 0;
93    {
94      const Pel *pPel = pPic->getAddr(compID);
95
96      for(Int y = 0; y < iHeight; y++, pPel+=iStride )
97        for(Int x = 0; x < iWidth; x++ )
98          iOrgDC += (Int)( pPel[x] );
99    }
100
101    const Int64 iOrgNormDC = ((iOrgDC+(iSample>>1)) / iSample);
102
103    Int64 iOrgAC = 0;
104    {
105      const Pel *pPel = pPic->getAddr(compID);
106
107      for(Int y = 0; y < iHeight; y++, pPel += iStride )
108        for(Int x = 0; x < iWidth; x++ )
109          iOrgAC += abs( (Int)pPel[x] - (Int)iOrgNormDC );
110    }
111
112    const Int fixedBitShift = (slice->getSPS()->getUseHighPrecisionPredictionWeighting())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
[494]113#if O0194_WEIGHTED_PREDICTION_CGS
[1029]114    weightACDCParam[compID].iSamples = iSample;
[494]115#endif
[1029]116    weightACDCParam[compID].iDC = (((iOrgDC<<fixedBitShift)+(iSample>>1)) / iSample);
117    weightACDCParam[compID].iAC = iOrgAC;
118  }
[313]119
120  slice->setWpAcDcParam(weightACDCParam);
121}
122
[1029]123
[313]124/** store weighted_pred_flag and weighted_bipred_idc values
125 * \param weighted_pred_flag
126 * \param weighted_bipred_idc
127 * \returns Void
128 */
[1029]129Void  WeightPredAnalysis::xStoreWPparam(const Bool weighted_pred_flag, const Bool weighted_bipred_flag)
[313]130{
[1029]131  m_weighted_pred_flag   = weighted_pred_flag;
[313]132  m_weighted_bipred_flag = weighted_bipred_flag;
133}
134
[1029]135
[313]136/** restore weighted_pred_flag and weighted_bipred_idc values
137 * \param TComSlice *slice
138 * \returns Void
139 */
[1029]140Void  WeightPredAnalysis::xRestoreWPparam(TComSlice *const slice)
[313]141{
[1029]142  slice->getPPS()->setUseWP   (m_weighted_pred_flag);
[313]143  slice->getPPS()->setWPBiPred(m_weighted_bipred_flag);
144}
145
[1029]146
[313]147/** check weighted pred or non-weighted pred
148 * \param TComSlice *slice
149 * \returns Void
150 */
[1029]151Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
[313]152{
[1029]153  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
154
[313]155  Int iPresentCnt = 0;
[1029]156  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]157  {
[494]158    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[313]159    {
[1029]160      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[313]161      {
[1029]162        WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
[313]163        iPresentCnt += (Int)pwp->bPresentFlag;
164      }
165    }
166  }
167
168  if(iPresentCnt==0)
169  {
170    slice->getPPS()->setUseWP(false);
171    slice->getPPS()->setWPBiPred(false);
[1029]172
173    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
[313]174    {
[494]175      for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
[313]176      {
[1029]177        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
[313]178        {
[1029]179          WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
180
[313]181          pwp->bPresentFlag      = false;
182          pwp->uiLog2WeightDenom = 0;
183          pwp->iWeight           = 1;
184          pwp->iOffset           = 0;
185        }
186      }
187    }
188    slice->setWpScaling( m_wp );
189  }
190}
191
[1029]192
[313]193/** estimate wp tables for explicit wp
194 * \param TComSlice *slice
195 */
[1029]196Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice)
[313]197{
[1029]198  Int  iDenom         = 6;
[313]199  Bool validRangeFlag = false;
200
201  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
202  {
[1029]203    iDenom = 7;
[313]204  }
205
206  do
207  {
[1029]208    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
[313]209    if (!validRangeFlag)
210    {
211      iDenom--; // decrement to satisfy the range limitation
212    }
213  } while (validRangeFlag == false);
214
215  // selecting whether WP is used, or not
[1029]216  xSelectWP(slice, iDenom);
[494]217
[313]218  slice->setWpScaling( m_wp );
219}
220
[1029]221
[313]222/** update wp tables for explicit wp w.r.t ramge limitation
223 * \param TComSlice *slice
224 * \returns Bool
225 */
[1029]226Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
[313]227{
[1029]228  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
229  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getUseHighPrecisionPredictionWeighting();
230  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
231
232  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
233
[313]234  for ( Int refList = 0; refList < numPredDir; refList++ )
235  {
[1029]236    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
237
[313]238    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
239    {
[1029]240      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
[313]241      slice->getWpAcDcParam(currWeightACDCParam);
242      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
[1029]243
[494]244#if O0194_WEIGHTED_PREDICTION_CGS
245      UInt currLayerId = slice->getLayerId();
246      UInt refLayerId  = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId();
247      Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0;
[313]248
[494]249      if( validILRPic )
250      {
[1029]251        refWeightACDCParam = (WPACDCParam *)g_refWeightACDCParam;
[494]252      }
253#endif
254
[1029]255      for ( Int comp = 0; comp < numComp; comp++ )
[313]256      {
[1029]257        const ComponentID compID        = ComponentID(comp);
258        const Int         range         = bUseHighPrecisionWeighting ? (1<<g_bitDepth[toChannelType(compID)])/2 : 128;
259        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (g_bitDepth[toChannelType(compID)] - 8));
260        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
[313]261
262        // current frame
[1029]263        const Int64 currDC = currWeightACDCParam[comp].iDC;
264        const Int64 currAC = currWeightACDCParam[comp].iAC;
[313]265        // reference frame
[494]266#if O0194_WEIGHTED_PREDICTION_CGS
[1029]267        Int64 refDC  = refWeightACDCParam[comp].iDC;
268        Int64 refAC  = refWeightACDCParam[comp].iAC;
269
[494]270        if( validILRPic )
271        {
272          refAC = ( refAC * currWeightACDCParam[comp].iSamples ) /refWeightACDCParam[comp].iSamples;
273#if O0194_JOINT_US_BITSHIFT
[1029]274          refAC <<= (g_bitDepthLayer[CHANNEL_TYPE_LUMA][currLayerId] - g_bitDepthLayer[CHANNEL_TYPE_LUMA][refLayerId]);
275          refDC <<= (g_bitDepthLayer[CHANNEL_TYPE_LUMA][currLayerId] - g_bitDepthLayer[CHANNEL_TYPE_LUMA][refLayerId]);
[494]276#endif
277        }
[1029]278#else
279        const Int64 refDC  = refWeightACDCParam[comp].iDC;
280        const Int64 refAC  = refWeightACDCParam[comp].iAC;
[494]281#endif
[313]282
283        // calculating iWeight and iOffset params
[1029]284#if O0194_WEIGHTED_PREDICTION_CGS
[313]285        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
[1029]286        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
287        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
288
[494]289        if( !validILRPic )
290        {
291          dWeight = 1;
292          offset  = 0;
293        }
294        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
[1029]295#else
296        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
297        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
298        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
[494]299#endif
[313]300
[1029]301        Int clippedOffset;
302        if(isChroma(compID)) // Chroma offset range limination
[313]303        {
[1029]304          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
305          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
306
307          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
[313]308        }
[1029]309        else // Luma offset range limitation
[313]310        {
[1029]311          clippedOffset = Clip3( -range, range-1, offset);
[313]312        }
313
314        // Weighting factor limitation
[1029]315        const Int defaultWeight = (1<<log2Denom);
316        const Int deltaWeight   = (defaultWeight - weight);
317
318        if(deltaWeight >= range || deltaWeight < -range)
319          return false;
320
[494]321#if O0194_WEIGHTED_PREDICTION_CGS
322        // make sure the reference frames other than ILR are not using weighted prediction
323        else
324        if( !validILRPic )
325        {
326          continue;
327        }
328#endif
[313]329
[1029]330        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
331        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
332        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
333        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[313]334      }
335    }
336  }
[1029]337  return true;
[313]338}
339
[1029]340
[494]341/** select whether weighted pred enables or not.
[313]342 * \param TComSlice *slice
[1029]343 * \param log2Denom
[313]344 * \returns Bool
345 */
[1029]346Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
[313]347{
[1029]348        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
349  const Int               iDefaultWeight                      = ((Int)1<<log2Denom);
350  const Int               iNumPredDir                         = slice->isInterP() ? 1 : 2;
351  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getUseHighPrecisionPredictionWeighting();
[313]352
[1029]353  assert (iNumPredDir <= Int(NUM_REF_PIC_LIST_01));
354
[313]355  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
356  {
[1029]357    const RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
358
[313]359    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
360    {
[1029]361      Int64 iSADWP = 0, iSADnoWP = 0;
[313]362
[1029]363      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
364      {
365        const ComponentID  compID     = ComponentID(comp);
366              Pel         *pOrg       = pPic->getAddr(compID);
367              Pel         *pRef       = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getAddr(compID);
368        const Int          iOrgStride = pPic->getStride(compID);
369        const Int          iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getStride(compID);
370        const Int          iWidth     = pPic->getWidth(compID);
371        const Int          iHeight    = pPic->getHeight(compID);
372        const Int          bitDepth   = g_bitDepth[toChannelType(compID)];
[313]373
[1029]374        // calculate SAD costs with/without wp for luma
375        iSADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, m_wp[iRefList][iRefIdxTemp][compID].iWeight, m_wp[iRefList][iRefIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
376        iSADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, iDefaultWeight, 0, useHighPrecisionPredictionWeighting);
377      }
[313]378
[1029]379      const Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
[313]380      if(dRatio >= (Double)DTHRESH)
381      {
[1029]382        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
[313]383        {
[1029]384          m_wp[iRefList][iRefIdxTemp][comp].bPresentFlag      = false;
385          m_wp[iRefList][iRefIdxTemp][comp].iOffset           = 0;
386          m_wp[iRefList][iRefIdxTemp][comp].iWeight           = iDefaultWeight;
387          m_wp[iRefList][iRefIdxTemp][comp].uiLog2WeightDenom = log2Denom;
[313]388        }
389      }
390    }
391  }
392
[1029]393  return true;
[313]394}
395
396
[494]397/** calculate SAD values for both WP version and non-WP version.
[313]398 * \param Pel *pOrgPel
399 * \param Pel *pRefPel
400 * \param Int iWidth
401 * \param Int iHeight
402 * \param Int iOrgStride
403 * \param Int iRefStride
[1029]404 * \param Int iLog2Denom
[313]405 * \param Int iWeight
406 * \param Int iOffset
407 * \returns Int64
408 */
[1029]409Int64 WeightPredAnalysis::xCalcSADvalueWP(const Int   bitDepth,
410                                          const Pel  *pOrgPel,
411                                          const Pel  *pRefPel,
412                                          const Int   iWidth,
413                                          const Int   iHeight,
414                                          const Int   iOrgStride,
415                                          const Int   iRefStride,
416                                          const Int   iLog2Denom,
417                                          const Int   iWeight,
418                                          const Int   iOffset,
419                                          const Bool  useHighPrecisionPredictionWeighting)
[313]420{
[1029]421  const Int64 iSize          = iWidth*iHeight;
422  const Int64 iRealLog2Denom = useHighPrecisionPredictionWeighting ? iLog2Denom : (iLog2Denom + (bitDepth - 8));
423
[313]424  Int64 iSAD = 0;
[1029]425  for( Int y = 0; y < iHeight; y++ )
[313]426  {
[1029]427    for( Int x = 0; x < iWidth; x++ )
[313]428    {
[1029]429      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iLog2Denom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealLog2Denom) ) ) );
[313]430    }
431    pOrgPel += iOrgStride;
432    pRefPel += iRefStride;
433  }
[1029]434
[313]435  return (iSAD/iSize);
436}
Note: See TracBrowser for help on using the repository browser.