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

Last change on this file since 1306 was 1287, checked in by seregin, 10 years ago

port rev 4322 (g_bitDepth)

  • Property svn:eol-style set to native
File size: 14.9 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 = slice->getWpAcDcParam(); 
218      WPACDCParam *refWeightACDCParam  = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam();
219
220#if SVC_EXTENSION
221      UInt currLayerId = slice->getLayerId();
222      UInt refLayerId  = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId();
223      Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0;
224
225      if( validILRPic )
226      {
227        refWeightACDCParam = slice->getWpAcDcParam();
228      }
229#endif
230
231      for ( Int comp = 0; comp < numComp; comp++ )
232      {
233        const ComponentID compID        = ComponentID(comp);
234#if SVC_EXTENSION
235        const Int         bitDepth      = slice->getBitDepth(toChannelType(compID));
236#else
237        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
238#endif
239        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
240        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
241        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
242
243        // current frame
244        const Int64 currDC = currWeightACDCParam[comp].iDC;
245        const Int64 currAC = currWeightACDCParam[comp].iAC;
246        // reference frame
247#if SVC_EXTENSION
248        Int64 refDC  = refWeightACDCParam[comp].iDC;
249        Int64 refAC  = refWeightACDCParam[comp].iAC;
250
251        if( validILRPic )
252        {
253          refAC = ( refAC * currWeightACDCParam[comp].iSamples ) /refWeightACDCParam[comp].iSamples;
254
255          const Int bitDepthLuma = slice->getBitDepth(CHANNEL_TYPE_LUMA);
256          const Int refBitDepthLuma  = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getBitDepth(CHANNEL_TYPE_LUMA);
257          const Int delta = bitDepthLuma - refBitDepthLuma;
258
259          // jonint upsampling bitshift
260          refAC <<= delta;
261          refDC <<= delta;
262        }
263#else
264        const Int64 refDC  = refWeightACDCParam[comp].iDC;
265        const Int64 refAC  = refWeightACDCParam[comp].iAC;
266#endif
267
268        // calculating iWeight and iOffset params
269#if SVC_EXTENSION
270        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
271        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
272        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
273
274        if( !validILRPic )
275        {
276          dWeight = 1;
277          offset  = 0;
278        }
279        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
280#else
281        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
282        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
283        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
284#endif
285
286        Int clippedOffset;
287        if(isChroma(compID)) // Chroma offset range limination
288        {
289          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
290          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
291
292          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
293        }
294        else // Luma offset range limitation
295        {
296          clippedOffset = Clip3( -range, range-1, offset);
297        }
298
299        // Weighting factor limitation
300        const Int defaultWeight = (1<<log2Denom);
301        const Int deltaWeight   = (defaultWeight - weight);
302
303        if(deltaWeight >= range || deltaWeight < -range)
304        {
305          return false;
306        }
307
308#if SVC_EXTENSION
309        // make sure the reference frames other than ILR are not using weighted prediction
310        else
311        if( !validILRPic )
312        {
313          continue;
314        }
315#endif
316
317        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
318        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
319        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
320        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
321      }
322    }
323  }
324  return true;
325}
326
327
328//! select whether weighted pred enables or not.
329Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
330{
331        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
332  const Int               iDefaultWeight                      = ((Int)1<<log2Denom);
333  const Int               iNumPredDir                         = slice->isInterP() ? 1 : 2;
334  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getUseHighPrecisionPredictionWeighting();
335
336  assert (iNumPredDir <= Int(NUM_REF_PIC_LIST_01));
337
338  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
339  {
340    const RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
341
342    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
343    {
344      Int64 iSADWP = 0, iSADnoWP = 0;
345
346      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
347      {
348        const ComponentID  compID     = ComponentID(comp);
349              Pel         *pOrg       = pPic->getAddr(compID);
350              Pel         *pRef       = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getAddr(compID);
351        const Int          iOrgStride = pPic->getStride(compID);
352        const Int          iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getStride(compID);
353        const Int          iWidth     = pPic->getWidth(compID);
354        const Int          iHeight    = pPic->getHeight(compID);
355#if SVC_EXTENSION
356        const Int          bitDepth   = slice->getBitDepth(toChannelType(compID));
357#else
358        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
359#endif
360
361        // calculate SAD costs with/without wp for luma
362        iSADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, m_wp[iRefList][iRefIdxTemp][compID].iWeight, m_wp[iRefList][iRefIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
363        iSADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, iDefaultWeight, 0, useHighPrecisionPredictionWeighting);
364      }
365
366      const Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
367      if(dRatio >= (Double)DTHRESH)
368      {
369        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
370        {
371          m_wp[iRefList][iRefIdxTemp][comp].bPresentFlag      = false;
372          m_wp[iRefList][iRefIdxTemp][comp].iOffset           = 0;
373          m_wp[iRefList][iRefIdxTemp][comp].iWeight           = iDefaultWeight;
374          m_wp[iRefList][iRefIdxTemp][comp].uiLog2WeightDenom = log2Denom;
375        }
376      }
377    }
378  }
379
380  return true;
381}
382
383
384//! calculate SAD values for both WP version and non-WP version.
385Int64 WeightPredAnalysis::xCalcSADvalueWP(const Int   bitDepth,
386                                          const Pel  *pOrgPel,
387                                          const Pel  *pRefPel,
388                                          const Int   iWidth,
389                                          const Int   iHeight,
390                                          const Int   iOrgStride,
391                                          const Int   iRefStride,
392                                          const Int   iLog2Denom,
393                                          const Int   iWeight,
394                                          const Int   iOffset,
395                                          const Bool  useHighPrecisionPredictionWeighting)
396{
397  const Int64 iSize          = iWidth*iHeight;
398  const Int64 iRealLog2Denom = useHighPrecisionPredictionWeighting ? iLog2Denom : (iLog2Denom + (bitDepth - 8));
399
400  Int64 iSAD = 0;
401  for( Int y = 0; y < iHeight; y++ )
402  {
403    for( Int x = 0; x < iWidth; x++ )
404    {
405      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iLog2Denom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealLog2Denom) ) ) );
406    }
407    pOrgPel += iOrgStride;
408    pRefPel += iRefStride;
409  }
410
411  return (iSAD/iSize);
412}
Note: See TracBrowser for help on using the repository browser.