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

Last change on this file since 1265 was 1260, checked in by seregin, 9 years ago

port rev 4257

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