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

Last change on this file since 1242 was 1235, checked in by seregin, 9 years ago

port rev 4219 and rev 4246

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