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

Last change on this file since 1114 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
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-2014, 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  m_weighted_pred_flag = false;
50  m_weighted_bipred_flag = false;
51
52  for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
53  {
54    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
55    {
56      for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ )
57      {
58        WPScalingParam  *pwp   = &(m_wp[lst][iRefIdx][comp]);
59        pwp->bPresentFlag      = false;
60        pwp->uiLog2WeightDenom = 0;
61        pwp->iWeight           = 1;
62        pwp->iOffset           = 0;
63      }
64    }
65  }
66}
67
68
69/** calculate AC and DC values for current original image
70 * \param TComSlice *slice
71 * \returns Void
72 */
73Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice)
74{
75  //===== calculate AC/DC value =====
76  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
77
78  WPACDCParam weightACDCParam[MAX_NUM_COMPONENT];
79
80  for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
81  {
82    const ComponentID compID = ComponentID(componentIndex);
83
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;
113#if O0194_WEIGHTED_PREDICTION_CGS
114    weightACDCParam[compID].iSamples = iSample;
115#endif
116    weightACDCParam[compID].iDC = (((iOrgDC<<fixedBitShift)+(iSample>>1)) / iSample);
117    weightACDCParam[compID].iAC = iOrgAC;
118  }
119
120  slice->setWpAcDcParam(weightACDCParam);
121}
122
123
124/** store weighted_pred_flag and weighted_bipred_idc values
125 * \param weighted_pred_flag
126 * \param weighted_bipred_idc
127 * \returns Void
128 */
129Void  WeightPredAnalysis::xStoreWPparam(const Bool weighted_pred_flag, const Bool weighted_bipred_flag)
130{
131  m_weighted_pred_flag   = weighted_pred_flag;
132  m_weighted_bipred_flag = weighted_bipred_flag;
133}
134
135
136/** restore weighted_pred_flag and weighted_bipred_idc values
137 * \param TComSlice *slice
138 * \returns Void
139 */
140Void  WeightPredAnalysis::xRestoreWPparam(TComSlice *const slice)
141{
142  slice->getPPS()->setUseWP   (m_weighted_pred_flag);
143  slice->getPPS()->setWPBiPred(m_weighted_bipred_flag);
144}
145
146
147/** check weighted pred or non-weighted pred
148 * \param TComSlice *slice
149 * \returns Void
150 */
151Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice)
152{
153  const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg();
154
155  Int iPresentCnt = 0;
156  for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
157  {
158    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
159    {
160      for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
161      {
162        WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
163        iPresentCnt += (Int)pwp->bPresentFlag;
164      }
165    }
166  }
167
168  if(iPresentCnt==0)
169  {
170    slice->getPPS()->setUseWP(false);
171    slice->getPPS()->setWPBiPred(false);
172
173    for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ )
174    {
175      for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ )
176      {
177        for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++)
178        {
179          WPScalingParam  *pwp = &(m_wp[lst][iRefIdx][componentIndex]);
180
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
192
193/** estimate wp tables for explicit wp
194 * \param TComSlice *slice
195 */
196Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice)
197{
198  Int  iDenom         = 6;
199  Bool validRangeFlag = false;
200
201  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
202  {
203    iDenom = 7;
204  }
205
206  do
207  {
208    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
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
216  xSelectWP(slice, iDenom);
217
218  slice->setWpScaling( m_wp );
219}
220
221
222/** update wp tables for explicit wp w.r.t ramge limitation
223 * \param TComSlice *slice
224 * \returns Bool
225 */
226Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
227{
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
234  for ( Int refList = 0; refList < numPredDir; refList++ )
235  {
236    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
237
238    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
239    {
240      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
241      slice->getWpAcDcParam(currWeightACDCParam);
242      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
243
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;
248
249      if( validILRPic )
250      {
251        refWeightACDCParam = (WPACDCParam *)g_refWeightACDCParam;
252      }
253#endif
254
255      for ( Int comp = 0; comp < numComp; comp++ )
256      {
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));
261
262        // current frame
263        const Int64 currDC = currWeightACDCParam[comp].iDC;
264        const Int64 currAC = currWeightACDCParam[comp].iAC;
265        // reference frame
266#if O0194_WEIGHTED_PREDICTION_CGS
267        Int64 refDC  = refWeightACDCParam[comp].iDC;
268        Int64 refAC  = refWeightACDCParam[comp].iAC;
269
270        if( validILRPic )
271        {
272          refAC = ( refAC * currWeightACDCParam[comp].iSamples ) /refWeightACDCParam[comp].iSamples;
273#if O0194_JOINT_US_BITSHIFT
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]);
276#endif
277        }
278#else
279        const Int64 refDC  = refWeightACDCParam[comp].iDC;
280        const Int64 refAC  = refWeightACDCParam[comp].iAC;
281#endif
282
283        // calculating iWeight and iOffset params
284#if O0194_WEIGHTED_PREDICTION_CGS
285        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
286        Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
287        Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
288
289        if( !validILRPic )
290        {
291          dWeight = 1;
292          offset  = 0;
293        }
294        weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
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 );
299#endif
300
301        Int clippedOffset;
302        if(isChroma(compID)) // Chroma offset range limination
303        {
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
308        }
309        else // Luma offset range limitation
310        {
311          clippedOffset = Clip3( -range, range-1, offset);
312        }
313
314        // Weighting factor limitation
315        const Int defaultWeight = (1<<log2Denom);
316        const Int deltaWeight   = (defaultWeight - weight);
317
318        if(deltaWeight >= range || deltaWeight < -range)
319          return false;
320
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
329
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;
334      }
335    }
336  }
337  return true;
338}
339
340
341/** select whether weighted pred enables or not.
342 * \param TComSlice *slice
343 * \param log2Denom
344 * \returns Bool
345 */
346Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
347{
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();
352
353  assert (iNumPredDir <= Int(NUM_REF_PIC_LIST_01));
354
355  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
356  {
357    const RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
358
359    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
360    {
361      Int64 iSADWP = 0, iSADnoWP = 0;
362
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)];
373
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      }
378
379      const Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
380      if(dRatio >= (Double)DTHRESH)
381      {
382        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
383        {
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;
388        }
389      }
390    }
391  }
392
393  return true;
394}
395
396
397/** calculate SAD values for both WP version and non-WP version.
398 * \param Pel *pOrgPel
399 * \param Pel *pRefPel
400 * \param Int iWidth
401 * \param Int iHeight
402 * \param Int iOrgStride
403 * \param Int iRefStride
404 * \param Int iLog2Denom
405 * \param Int iWeight
406 * \param Int iOffset
407 * \returns Int64
408 */
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)
420{
421  const Int64 iSize          = iWidth*iHeight;
422  const Int64 iRealLog2Denom = useHighPrecisionPredictionWeighting ? iLog2Denom : (iLog2Denom + (bitDepth - 8));
423
424  Int64 iSAD = 0;
425  for( Int y = 0; y < iHeight; y++ )
426  {
427    for( Int x = 0; x < iWidth; x++ )
428    {
429      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iLog2Denom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealLog2Denom) ) ) );
430    }
431    pOrgPel += iOrgStride;
432    pRefPel += iRefStride;
433  }
434
435  return (iSAD/iSize);
436}
Note: See TracBrowser for help on using the repository browser.