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

Last change on this file since 1164 was 1029, checked in by seregin, 10 years ago

merge with SHM-upgrade branch

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