source: 3DVCSoftware/trunk/source/Lib/TLibEncoder/WeightPredAnalysis.cpp @ 1313

Last change on this file since 1313 was 1313, checked in by tech, 9 years ago

Merged 14.1-update-dev1@1312.

  • Property svn:eol-style set to native
File size: 13.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-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/CommonDef.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()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0;
115    weightACDCParam[compID].iDC = (((iOrgDC<<fixedBitShift)+(iSample>>1)) / iSample);
116    weightACDCParam[compID].iAC = iOrgAC;
117  }
118
119  slice->setWpAcDcParam(weightACDCParam);
120}
121
122
123//! check weighted pred or non-weighted pred
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
172Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice)
173{
174  Int  iDenom         = 6;
175  Bool validRangeFlag = false;
176
177  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
178  {
179    iDenom = 7;
180  }
181
182  do
183  {
184    validRangeFlag = xUpdatingWPParameters(slice, iDenom);
185    if (!validRangeFlag)
186    {
187      iDenom--; // decrement to satisfy the range limitation
188    }
189  } while (validRangeFlag == false);
190
191  // selecting whether WP is used, or not (fast search)
192  // NOTE: This is not operating on a slice, but the entire picture.
193  xSelectWP(slice, iDenom);
194
195  slice->setWpScaling( m_wp );
196}
197
198
199//! update wp tables for explicit wp w.r.t range limitation
200Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom)
201{
202  const Int  numComp                    = slice->getPic()->getPicYuvOrg()->getNumberValidComponents();
203  const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
204  const Int numPredDir                  = slice->isInterP() ? 1 : 2;
205
206  assert (numPredDir <= Int(NUM_REF_PIC_LIST_01));
207
208  for ( Int refList = 0; refList < numPredDir; refList++ )
209  {
210    const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
211
212    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
213    {
214      WPACDCParam *currWeightACDCParam, *refWeightACDCParam;
215      slice->getWpAcDcParam(currWeightACDCParam);
216      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
217
218      for ( Int comp = 0; comp < numComp; comp++ )
219      {
220        const ComponentID compID        = ComponentID(comp);
221        const Int         bitDepth      = slice->getSPS()->getBitDepth(toChannelType(compID));
222        const Int         range         = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128;
223        const Int         realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8));
224        const Int         realOffset    = ((Int)1<<(realLog2Denom-1));
225
226        // current frame
227        const Int64 currDC = currWeightACDCParam[comp].iDC;
228        const Int64 currAC = currWeightACDCParam[comp].iAC;
229        // reference frame
230        const Int64 refDC  = refWeightACDCParam[comp].iDC;
231        const Int64 refAC  = refWeightACDCParam[comp].iAC;
232
233        // calculating iWeight and iOffset params
234        const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
235        const Int weight     = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
236        const Int offset     = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
237
238        Int clippedOffset;
239        if(isChroma(compID)) // Chroma offset range limination
240        {
241          const Int pred        = ( range - ( ( range*weight)>>(log2Denom) ) );
242          const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit
243
244          clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) );  // signed 8bit
245        }
246        else // Luma offset range limitation
247        {
248          clippedOffset = Clip3( -range, range-1, offset);
249        }
250
251        // Weighting factor limitation
252        const Int defaultWeight = (1<<log2Denom);
253        const Int deltaWeight   = (defaultWeight - weight);
254
255        if(deltaWeight >= range || deltaWeight < -range)
256        {
257          return false;
258        }
259
260        m_wp[refList][refIdxTemp][comp].bPresentFlag      = true;
261        m_wp[refList][refIdxTemp][comp].iWeight           = weight;
262        m_wp[refList][refIdxTemp][comp].iOffset           = clippedOffset;
263        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom;
264      }
265    }
266  }
267  return true;
268}
269
270
271//! select whether weighted pred enables or not.
272Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom)
273{
274        TComPicYuv *const pPic                                = slice->getPic()->getPicYuvOrg();
275  const Int               iDefaultWeight                      = ((Int)1<<log2Denom);
276  const Int               iNumPredDir                         = slice->isInterP() ? 1 : 2;
277  const Bool              useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
278
279  assert (iNumPredDir <= Int(NUM_REF_PIC_LIST_01));
280
281  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
282  {
283    const RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
284
285    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
286    {
287      Int64 iSADWP = 0, iSADnoWP = 0;
288
289      for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
290      {
291        const ComponentID  compID     = ComponentID(comp);
292              Pel         *pOrg       = pPic->getAddr(compID);
293              Pel         *pRef       = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getAddr(compID);
294        const Int          iOrgStride = pPic->getStride(compID);
295        const Int          iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getStride(compID);
296        const Int          iWidth     = pPic->getWidth(compID);
297        const Int          iHeight    = pPic->getHeight(compID);
298        const Int          bitDepth   = slice->getSPS()->getBitDepth(toChannelType(compID));
299
300        // calculate SAD costs with/without wp for luma
301        iSADWP   += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, m_wp[iRefList][iRefIdxTemp][compID].iWeight, m_wp[iRefList][iRefIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting);
302        iSADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, log2Denom, iDefaultWeight, 0, useHighPrecisionPredictionWeighting);
303      }
304
305      const Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
306      if(dRatio >= (Double)DTHRESH)
307      {
308        for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++)
309        {
310          m_wp[iRefList][iRefIdxTemp][comp].bPresentFlag      = false;
311          m_wp[iRefList][iRefIdxTemp][comp].iOffset           = 0;
312          m_wp[iRefList][iRefIdxTemp][comp].iWeight           = iDefaultWeight;
313          m_wp[iRefList][iRefIdxTemp][comp].uiLog2WeightDenom = log2Denom;
314        }
315      }
316    }
317  }
318
319  return true;
320}
321
322
323//! calculate SAD values for both WP version and non-WP version.
324Int64 WeightPredAnalysis::xCalcSADvalueWP(const Int   bitDepth,
325                                          const Pel  *pOrgPel,
326                                          const Pel  *pRefPel,
327                                          const Int   iWidth,
328                                          const Int   iHeight,
329                                          const Int   iOrgStride,
330                                          const Int   iRefStride,
331                                          const Int   iLog2Denom,
332                                          const Int   iWeight,
333                                          const Int   iOffset,
334                                          const Bool  useHighPrecisionPredictionWeighting)
335{
336  const Int64 iSize          = iWidth*iHeight;
337  const Int64 iRealLog2Denom = useHighPrecisionPredictionWeighting ? iLog2Denom : (iLog2Denom + (bitDepth - 8));
338
339  Int64 iSAD = 0;
340  for( Int y = 0; y < iHeight; y++ )
341  {
342    for( Int x = 0; x < iWidth; x++ )
343    {
344      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iLog2Denom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealLog2Denom) ) ) );
345    }
346    pOrgPel += iOrgStride;
347    pRefPel += iRefStride;
348  }
349
350  return (iSAD/iSize);
351}
Note: See TracBrowser for help on using the repository browser.