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

Last change on this file since 1257 was 1246, checked in by seregin, 9 years ago

port rev 4240

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