source: SHVCSoftware/branches/SHM-dev/source/Lib/TLibCommon/TComWeightPrediction.cpp @ 1499

Last change on this file since 1499 was 1399, checked in by seregin, 9 years ago

port rev 4552

  • Property svn:eol-style set to native
File size: 16.1 KB
RevLine 
[313]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
[1029]4 * granted under this license.
[313]5 *
[1259]6 * Copyright (c) 2010-2015, ITU/ISO/IEC
[313]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     TComWeightPrediction.h
35    \brief    weighting prediction class (header)
36*/
37
38// Include files
[1262]39#include "CommonDef.h"
40#include "TComYuv.h"
41#include "TComPic.h"
42#include "TComInterpolationFilter.h"
[313]43#include "TComWeightPrediction.h"
44
[1029]45
46static inline Pel weightBidir( Int w0, Pel P0, Int w1, Pel P1, Int round, Int shift, Int offset, Int clipBD)
[313]47{
[1029]48  return ClipBD( ( (w0*(P0 + IF_INTERNAL_OFFS) + w1*(P1 + IF_INTERNAL_OFFS) + round + (offset << (shift-1))) >> shift ), clipBD );
[313]49}
50
[1029]51
52static inline Pel weightUnidir( Int w0, Pel P0, Int round, Int shift, Int offset, Int clipBD)
[313]53{
[1029]54  return ClipBD( ( (w0*(P0 + IF_INTERNAL_OFFS) + round) >> shift ) + offset, clipBD );
[313]55}
56
[1399]57static inline Pel noWeightUnidir( Pel P0, Int round, Int shift, Int offset, Int clipBD)
58{
59  return ClipBD( ( ((P0 + IF_INTERNAL_OFFS) + round) >> shift ) + offset, clipBD );
60}
61
62static inline Pel noWeightOffsetUnidir( Pel P0, Int round, Int shift, Int clipBD)
63{
64  return ClipBD( ( ((P0 + IF_INTERNAL_OFFS) + round) >> shift ), clipBD );
65}
66
67
[313]68// ====================================================================================================================
69// Class definition
70// ====================================================================================================================
[1029]71
[313]72TComWeightPrediction::TComWeightPrediction()
73{
74}
75
[1029]76
[1260]77//! weighted averaging for bi-pred
[1029]78Void TComWeightPrediction::addWeightBi( const TComYuv              *pcYuvSrc0,
79                                        const TComYuv              *pcYuvSrc1,
[1287]80                                        const BitDepths            &bitDepths,
[1029]81                                        const UInt                  iPartUnitIdx,
82                                        const UInt                  uiWidth,
83                                        const UInt                  uiHeight,
84                                        const WPScalingParam *const wp0,
85                                        const WPScalingParam *const wp1,
86                                              TComYuv        *const rpcYuvDst,
[1287]87                                        const Bool                  bRoundLuma)
[313]88{
89
[1029]90  const Bool enableRounding[MAX_NUM_COMPONENT]={ bRoundLuma, true, true };
[313]91
[1029]92  const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents();
93
94  for(Int componentIndex=0; componentIndex<numValidComponent; componentIndex++)
[313]95  {
[1029]96    const ComponentID compID=ComponentID(componentIndex);
[313]97
[1029]98    const Pel* pSrc0       = pcYuvSrc0->getAddr( compID,  iPartUnitIdx );
99    const Pel* pSrc1       = pcYuvSrc1->getAddr( compID,  iPartUnitIdx );
100          Pel* pDst        = rpcYuvDst->getAddr( compID,  iPartUnitIdx );
[313]101
[1029]102    // Luma : --------------------------------------------
103    const Int  w0          = wp0[compID].w;
104    const Int  offset      = wp0[compID].offset;
[1287]105    const Int  clipBD      = bitDepths.recon[toChannelType(compID)];
[1029]106    const Int  shiftNum    = std::max<Int>(2, (IF_INTERNAL_PREC - clipBD));
107    const Int  shift       = wp0[compID].shift + shiftNum;
108    const Int  round       = (enableRounding[compID] && (shift > 0)) ? (1<<(shift-1)) : 0;
109    const Int  w1          = wp1[compID].w;
110    const UInt csx         = pcYuvSrc0->getComponentScaleX(compID);
111    const UInt csy         = pcYuvSrc0->getComponentScaleY(compID);
112    const Int  iHeight     = uiHeight>>csy;
113    const Int  iWidth      = uiWidth>>csx;
[313]114
[1029]115    const UInt iSrc0Stride = pcYuvSrc0->getStride(compID);
116    const UInt iSrc1Stride = pcYuvSrc1->getStride(compID);
117    const UInt iDstStride  = rpcYuvDst->getStride(compID);
[313]118
[1029]119    for ( Int y = iHeight-1; y >= 0; y-- )
[313]120    {
[1029]121      // do it in batches of 4 (partial unroll)
122      Int x = iWidth-1;
123      for ( ; x >= 3; )
124      {
125        pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--;
126        pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--;
127        pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--;
128        pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD); x--;
129      }
130      for( ; x >= 0; x-- )
131      {
132        pDst[x] = weightBidir(w0,pSrc0[x], w1,pSrc1[x], round, shift, offset, clipBD);
133      }
134
135      pSrc0 += iSrc0Stride;
136      pSrc1 += iSrc1Stride;
137      pDst  += iDstStride;
138    } // y loop
139  } // compID loop
[313]140}
141
[1029]142
[1260]143//! weighted averaging for uni-pred
[1029]144Void TComWeightPrediction::addWeightUni( const TComYuv        *const pcYuvSrc0,
[1287]145                                         const BitDepths            &bitDepths,
[1029]146                                         const UInt                  iPartUnitIdx,
147                                         const UInt                  uiWidth,
148                                         const UInt                  uiHeight,
149                                         const WPScalingParam *const wp0,
150                                               TComYuv        *const pcYuvDst )
[313]151{
[1029]152  const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents();
[313]153
[1029]154  for(Int componentIndex=0; componentIndex<numValidComponent; componentIndex++)
[313]155  {
[1029]156    const ComponentID compID=ComponentID(componentIndex);
[313]157
[1029]158    const Pel* pSrc0       = pcYuvSrc0->getAddr( compID,  iPartUnitIdx );
159          Pel* pDst        = pcYuvDst->getAddr( compID,  iPartUnitIdx );
[313]160
[1029]161    // Luma : --------------------------------------------
162    const Int  w0          = wp0[compID].w;
163    const Int  offset      = wp0[compID].offset;
[1287]164    const Int  clipBD      = bitDepths.recon[toChannelType(compID)];
[1029]165    const Int  shiftNum    = std::max<Int>(2, (IF_INTERNAL_PREC - clipBD));
166    const Int  shift       = wp0[compID].shift + shiftNum;
167    const UInt iSrc0Stride = pcYuvSrc0->getStride(compID);
168    const UInt iDstStride  = pcYuvDst->getStride(compID);
169    const UInt csx         = pcYuvSrc0->getComponentScaleX(compID);
170    const UInt csy         = pcYuvSrc0->getComponentScaleY(compID);
171    const Int  iHeight     = uiHeight>>csy;
172    const Int  iWidth      = uiWidth>>csx;
173
[1399]174    if (w0 != 1 << wp0[compID].shift)
[313]175    {
[1399]176      const Int  round       = (shift > 0) ? (1<<(shift-1)) : 0;
177      for (Int y = iHeight-1; y >= 0; y-- )
[1029]178      {
[1399]179        Int x = iWidth-1;
180        for ( ; x >= 3; )
181        {
182          pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--;
183          pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--;
184          pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--;
185          pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD); x--;
186        }
187        for( ; x >= 0; x--)
188        {
189          pDst[x] = weightUnidir(w0, pSrc0[x], round, shift, offset, clipBD);
190        }
191        pSrc0 += iSrc0Stride;
192        pDst  += iDstStride;
[1029]193      }
[1399]194    }
195    else
196    {
197      const Int  round       = (shiftNum > 0) ? (1<<(shiftNum-1)) : 0;
198      if (offset == 0)
[1029]199      {
[1399]200        for (Int y = iHeight-1; y >= 0; y-- )
201        {
202          Int x = iWidth-1;
203          for ( ; x >= 3; )
204          {
205            pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--;
206            pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--;
207            pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--;
208            pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD); x--;
209          }
210          for( ; x >= 0; x--)
211          {
212            pDst[x] = noWeightOffsetUnidir(pSrc0[x], round, shiftNum, clipBD);
213          }
214          pSrc0 += iSrc0Stride;
215          pDst  += iDstStride;
216        }
[1029]217      }
[1399]218      else
219      {
220        for (Int y = iHeight-1; y >= 0; y-- )
221        {
222          Int x = iWidth-1;
223          for ( ; x >= 3; )
224          {
225            pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--;
226            pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--;
227            pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--;
228            pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD); x--;
229          }
230          for( ; x >= 0; x--)
231          {
232            pDst[x] = noWeightUnidir(pSrc0[x], round, shiftNum, offset, clipBD);
233          }
234          pSrc0 += iSrc0Stride;
235          pDst  += iDstStride;
236        }
237      }
[313]238    }
239  }
240}
241
[1029]242
[313]243//=======================================================
244//  getWpScaling()
245//=======================================================
[1260]246//! derivation of wp tables
[1029]247Void TComWeightPrediction::getWpScaling(       TComDataCU *const pcCU,
248                                         const Int               iRefIdx0,
249                                         const Int               iRefIdx1,
250                                               WPScalingParam  *&wp0,
251                                               WPScalingParam  *&wp1)
[313]252{
253  assert(iRefIdx0 >= 0 || iRefIdx1 >= 0);
254
[1029]255        TComSlice *const pcSlice  = pcCU->getSlice();
256  const Bool             wpBiPred = pcCU->getSlice()->getPPS()->getWPBiPred();
[1399]257  const Bool             bBiPred  = (iRefIdx0>=0 && iRefIdx1>=0);
258  const Bool             bUniPred = !bBiPred;
[1029]259
[1399]260  if ( bUniPred || wpBiPred )
[313]261  { // explicit --------------------
262    if ( iRefIdx0 >= 0 )
263    {
264      pcSlice->getWpScaling(REF_PIC_LIST_0, iRefIdx0, wp0);
265    }
266    if ( iRefIdx1 >= 0 )
267    {
268      pcSlice->getWpScaling(REF_PIC_LIST_1, iRefIdx1, wp1);
269    }
270  }
271  else
272  {
273    assert(0);
274  }
275
276  if ( iRefIdx0 < 0 )
277  {
278    wp0 = NULL;
279  }
280  if ( iRefIdx1 < 0 )
281  {
282    wp1 = NULL;
283  }
284
[1029]285  const UInt numValidComponent                    = pcCU->getPic()->getNumberValidComponents();
[1316]286  const Bool bUseHighPrecisionPredictionWeighting = pcSlice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
[1029]287
[1399]288  if ( bBiPred )
289  { // Bi-predictive case
[1029]290    for ( Int yuv=0 ; yuv<numValidComponent ; yuv++ )
[313]291    {
[1287]292#if SVC_EXTENSION
293      const Int bitDepth            = pcSlice->getBitDepth(toChannelType(ComponentID(yuv)));
294#else
295      const Int bitDepth            = pcSlice->getSPS()->getBitDepth(toChannelType(ComponentID(yuv)));
296#endif
[1029]297      const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8));
298
[313]299      wp0[yuv].w      = wp0[yuv].iWeight;
300      wp1[yuv].w      = wp1[yuv].iWeight;
[1029]301      wp0[yuv].o      = wp0[yuv].iOffset * offsetScalingFactor;
302      wp1[yuv].o      = wp1[yuv].iOffset * offsetScalingFactor;
[313]303      wp0[yuv].offset = wp0[yuv].o + wp1[yuv].o;
304      wp0[yuv].shift  = wp0[yuv].uiLog2WeightDenom + 1;
305      wp0[yuv].round  = (1 << wp0[yuv].uiLog2WeightDenom);
306      wp1[yuv].offset = wp0[yuv].offset;
307      wp1[yuv].shift  = wp0[yuv].shift;
308      wp1[yuv].round  = wp0[yuv].round;
309    }
310  }
311  else
[1399]312  {  // UniPred
[1029]313    WPScalingParam *const pwp = (iRefIdx0>=0) ? wp0 : wp1 ;
314
315    for ( Int yuv=0 ; yuv<numValidComponent ; yuv++ )
[313]316    {
[1287]317#if SVC_EXTENSION
318      const Int bitDepth            = pcSlice->getBitDepth(toChannelType(ComponentID(yuv)));
319#else
320      const Int bitDepth            = pcSlice->getSPS()->getBitDepth(toChannelType(ComponentID(yuv)));
321#endif
[1029]322      const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8));
323
[313]324      pwp[yuv].w      = pwp[yuv].iWeight;
[1029]325      pwp[yuv].offset = pwp[yuv].iOffset * offsetScalingFactor;
[313]326      pwp[yuv].shift  = pwp[yuv].uiLog2WeightDenom;
327      pwp[yuv].round  = (pwp[yuv].uiLog2WeightDenom>=1) ? (1 << (pwp[yuv].uiLog2WeightDenom-1)) : (0);
328    }
329  }
330}
331
[1029]332
[1260]333//! weighted prediction for bi-pred
[1029]334Void TComWeightPrediction::xWeightedPredictionBi(       TComDataCU *const pcCU,
335                                                  const TComYuv    *const pcYuvSrc0,
336                                                  const TComYuv    *const pcYuvSrc1,
337                                                  const Int               iRefIdx0,
338                                                  const Int               iRefIdx1,
339                                                  const UInt              uiPartIdx,
340                                                  const Int               iWidth,
341                                                  const Int               iHeight,
342                                                        TComYuv          *rpcYuvDst )
[313]343{
[1029]344  WPScalingParam  *pwp0;
345  WPScalingParam  *pwp1;
[313]346
[1029]347  assert(pcCU->getSlice()->getPPS()->getWPBiPred());
348
[313]349  getWpScaling(pcCU, iRefIdx0, iRefIdx1, pwp0, pwp1);
350
351  if( iRefIdx0 >= 0 && iRefIdx1 >= 0 )
352  {
[1287]353#if SVC_EXTENSION
354    addWeightBi(pcYuvSrc0, pcYuvSrc1, pcCU->getSlice()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, pwp1, rpcYuvDst );
355#else
356    addWeightBi(pcYuvSrc0, pcYuvSrc1, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, pwp1, rpcYuvDst );
357#endif
[313]358  }
359  else if ( iRefIdx0 >= 0 && iRefIdx1 <  0 )
360  {
[1287]361#if SVC_EXTENSION
362    addWeightUni( pcYuvSrc0, pcCU->getSlice()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, rpcYuvDst );
363#else
364    addWeightUni( pcYuvSrc0, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, rpcYuvDst );
365#endif
[313]366  }
367  else if ( iRefIdx0 <  0 && iRefIdx1 >= 0 )
368  {
[1287]369#if SVC_EXTENSION
370    addWeightUni( pcYuvSrc1, pcCU->getSlice()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp1, rpcYuvDst );
371#else
372    addWeightUni( pcYuvSrc1, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp1, rpcYuvDst );
373#endif
[313]374  }
375  else
376  {
377    assert (0);
378  }
379}
380
[1029]381
[1260]382//! weighted prediction for uni-pred
[1029]383Void TComWeightPrediction::xWeightedPredictionUni(       TComDataCU *const pcCU,
384                                                   const TComYuv    *const pcYuvSrc,
385                                                   const UInt              uiPartAddr,
386                                                   const Int               iWidth,
387                                                   const Int               iHeight,
388                                                   const RefPicList        eRefPicList,
389                                                         TComYuv          *pcYuvPred,
390                                                   const Int               iRefIdx_input)
391{
392  WPScalingParam  *pwp, *pwpTmp;
393
394  Int iRefIdx=iRefIdx_input;
[313]395  if ( iRefIdx < 0 )
396  {
397    iRefIdx   = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr );
398  }
399  assert (iRefIdx >= 0);
400
401  if ( eRefPicList == REF_PIC_LIST_0 )
402  {
403    getWpScaling(pcCU, iRefIdx, -1, pwp, pwpTmp);
404  }
405  else
406  {
407    getWpScaling(pcCU, -1, iRefIdx, pwpTmp, pwp);
408  }
[1287]409#if SVC_EXTENSION
410  addWeightUni( pcYuvSrc, pcCU->getSlice()->getBitDepths(), uiPartAddr, iWidth, iHeight, pwp, pcYuvPred );
411#else
412  addWeightUni( pcYuvSrc, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartAddr, iWidth, iHeight, pwp, pcYuvPred );
413#endif
[313]414}
Note: See TracBrowser for help on using the repository browser.