HEVC Test Model (HM)  HM-16.18
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TComWeightPrediction.cpp
Go to the documentation of this file.
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-2017, 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 
38 // Include files
39 #include "CommonDef.h"
40 #include "TComYuv.h"
41 #include "TComPic.h"
43 #include "TComWeightPrediction.h"
44 
45 
46 static inline Pel weightBidir( Int w0, Pel P0, Int w1, Pel P1, Int round, Int shift, Int offset, Int clipBD)
47 {
48  return ClipBD( ( (w0*(P0 + IF_INTERNAL_OFFS) + w1*(P1 + IF_INTERNAL_OFFS) + round + (offset << (shift-1))) >> shift ), clipBD );
49 }
50 
51 
52 static inline Pel weightUnidir( Int w0, Pel P0, Int round, Int shift, Int offset, Int clipBD)
53 {
54  return ClipBD( ( (w0*(P0 + IF_INTERNAL_OFFS) + round) >> shift ) + offset, clipBD );
55 }
56 
57 static 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 
62 static 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 
68 // ====================================================================================================================
69 // Class definition
70 // ====================================================================================================================
71 
73 {
74 }
75 
76 
79  const TComYuv *pcYuvSrc1,
80  const BitDepths &bitDepths,
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,
87  const Bool bRoundLuma)
88 {
89 
90  const Bool enableRounding[MAX_NUM_COMPONENT]={ bRoundLuma, true, true };
91 
92  const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents();
93 
94  for(Int componentIndex=0; componentIndex<numValidComponent; componentIndex++)
95  {
96  const ComponentID compID=ComponentID(componentIndex);
97 
98  const Pel* pSrc0 = pcYuvSrc0->getAddr( compID, iPartUnitIdx );
99  const Pel* pSrc1 = pcYuvSrc1->getAddr( compID, iPartUnitIdx );
100  Pel* pDst = rpcYuvDst->getAddr( compID, iPartUnitIdx );
101 
102  // Luma : --------------------------------------------
103  const Int w0 = wp0[compID].w;
104  const Int offset = wp0[compID].offset;
105  const Int clipBD = bitDepths.recon[toChannelType(compID)];
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;
114 
115  const UInt iSrc0Stride = pcYuvSrc0->getStride(compID);
116  const UInt iSrc1Stride = pcYuvSrc1->getStride(compID);
117  const UInt iDstStride = rpcYuvDst->getStride(compID);
118 
119  for ( Int y = iHeight-1; y >= 0; y-- )
120  {
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
140 }
141 
142 
145  const BitDepths &bitDepths,
146  const UInt iPartUnitIdx,
147  const UInt uiWidth,
148  const UInt uiHeight,
149  const WPScalingParam *const wp0,
150  TComYuv *const pcYuvDst )
151 {
152  const UInt numValidComponent = pcYuvSrc0->getNumberValidComponents();
153 
154  for(Int componentIndex=0; componentIndex<numValidComponent; componentIndex++)
155  {
156  const ComponentID compID=ComponentID(componentIndex);
157 
158  const Pel* pSrc0 = pcYuvSrc0->getAddr( compID, iPartUnitIdx );
159  Pel* pDst = pcYuvDst->getAddr( compID, iPartUnitIdx );
160 
161  // Luma : --------------------------------------------
162  const Int w0 = wp0[compID].w;
163  const Int offset = wp0[compID].offset;
164  const Int clipBD = bitDepths.recon[toChannelType(compID)];
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 
174  if (w0 != 1 << wp0[compID].shift)
175  {
176  const Int round = (shift > 0) ? (1<<(shift-1)) : 0;
177  for (Int y = iHeight-1; y >= 0; y-- )
178  {
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;
193  }
194  }
195  else
196  {
197  const Int round = (shiftNum > 0) ? (1<<(shiftNum-1)) : 0;
198  if (offset == 0)
199  {
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  }
217  }
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  }
238  }
239  }
240 }
241 
242 
243 //=======================================================
244 // getWpScaling()
245 //=======================================================
248  const Int iRefIdx0,
249  const Int iRefIdx1,
250  WPScalingParam *&wp0,
251  WPScalingParam *&wp1)
252 {
253  assert(iRefIdx0 >= 0 || iRefIdx1 >= 0);
254 
255  TComSlice *const pcSlice = pcCU->getSlice();
256  const Bool wpBiPred = pcCU->getSlice()->getPPS()->getWPBiPred();
257  const Bool bBiPred = (iRefIdx0>=0 && iRefIdx1>=0);
258  const Bool bUniPred = !bBiPred;
259 
260  if ( bUniPred || wpBiPred )
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 
285  const UInt numValidComponent = pcCU->getPic()->getNumberValidComponents();
286  const Bool bUseHighPrecisionPredictionWeighting = pcSlice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag();
287 
288  if ( bBiPred )
289  { // Bi-predictive case
290  for ( Int yuv=0 ; yuv<numValidComponent ; yuv++ )
291  {
292  const Int bitDepth = pcSlice->getSPS()->getBitDepth(toChannelType(ComponentID(yuv)));
293  const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8));
294 
295  wp0[yuv].w = wp0[yuv].iWeight;
296  wp1[yuv].w = wp1[yuv].iWeight;
297  wp0[yuv].o = wp0[yuv].iOffset * offsetScalingFactor;
298  wp1[yuv].o = wp1[yuv].iOffset * offsetScalingFactor;
299  wp0[yuv].offset = wp0[yuv].o + wp1[yuv].o;
300  wp0[yuv].shift = wp0[yuv].uiLog2WeightDenom + 1;
301  wp0[yuv].round = (1 << wp0[yuv].uiLog2WeightDenom);
302  wp1[yuv].offset = wp0[yuv].offset;
303  wp1[yuv].shift = wp0[yuv].shift;
304  wp1[yuv].round = wp0[yuv].round;
305  }
306  }
307  else
308  { // UniPred
309  WPScalingParam *const pwp = (iRefIdx0>=0) ? wp0 : wp1 ;
310 
311  for ( Int yuv=0 ; yuv<numValidComponent ; yuv++ )
312  {
313  const Int bitDepth = pcSlice->getSPS()->getBitDepth(toChannelType(ComponentID(yuv)));
314  const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (bitDepth-8));
315 
316  pwp[yuv].w = pwp[yuv].iWeight;
317  pwp[yuv].offset = pwp[yuv].iOffset * offsetScalingFactor;
318  pwp[yuv].shift = pwp[yuv].uiLog2WeightDenom;
319  pwp[yuv].round = (pwp[yuv].uiLog2WeightDenom>=1) ? (1 << (pwp[yuv].uiLog2WeightDenom-1)) : (0);
320  }
321  }
322 }
323 
324 
327  const TComYuv *const pcYuvSrc0,
328  const TComYuv *const pcYuvSrc1,
329  const Int iRefIdx0,
330  const Int iRefIdx1,
331  const UInt uiPartIdx,
332  const Int iWidth,
333  const Int iHeight,
334  TComYuv *rpcYuvDst )
335 {
336  WPScalingParam *pwp0;
337  WPScalingParam *pwp1;
338 
339  assert(pcCU->getSlice()->getPPS()->getWPBiPred());
340 
341  getWpScaling(pcCU, iRefIdx0, iRefIdx1, pwp0, pwp1);
342 
343  if( iRefIdx0 >= 0 && iRefIdx1 >= 0 )
344  {
345  addWeightBi(pcYuvSrc0, pcYuvSrc1, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, pwp1, rpcYuvDst );
346  }
347  else if ( iRefIdx0 >= 0 && iRefIdx1 < 0 )
348  {
349  addWeightUni( pcYuvSrc0, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp0, rpcYuvDst );
350  }
351  else if ( iRefIdx0 < 0 && iRefIdx1 >= 0 )
352  {
353  addWeightUni( pcYuvSrc1, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartIdx, iWidth, iHeight, pwp1, rpcYuvDst );
354  }
355  else
356  {
357  assert (0);
358  }
359 }
360 
361 
364  const TComYuv *const pcYuvSrc,
365  const UInt uiPartAddr,
366  const Int iWidth,
367  const Int iHeight,
368  const RefPicList eRefPicList,
369  TComYuv *pcYuvPred,
370  const Int iRefIdx_input)
371 {
372  WPScalingParam *pwp, *pwpTmp;
373 
374  Int iRefIdx=iRefIdx_input;
375  if ( iRefIdx < 0 )
376  {
377  iRefIdx = pcCU->getCUMvField( eRefPicList )->getRefIdx( uiPartAddr );
378  }
379  assert (iRefIdx >= 0);
380 
381  if ( eRefPicList == REF_PIC_LIST_0 )
382  {
383  getWpScaling(pcCU, iRefIdx, -1, pwp, pwpTmp);
384  }
385  else
386  {
387  getWpScaling(pcCU, -1, iRefIdx, pwpTmp, pwp);
388  }
389  addWeightUni( pcYuvSrc, pcCU->getSlice()->getSPS()->getBitDepths(), uiPartAddr, iWidth, iHeight, pwp, pcYuvPred );
390 }
static Pel noWeightOffsetUnidir(Pel P0, Int round, Int shift, Int clipBD)
Int getRefIdx(Int iIdx) const
CU data structure class.
Definition: TComDataCU.h:64
Defines version information, constants and small in-line functions.
void Void
Definition: TypeDef.h:203
const TComSPSRExt & getSpsRangeExtension() const
Definition: TComSlice.h:941
#define NULL
Definition: CommonDef.h:107
Declaration of TComInterpolationFilter class.
general YUV buffer class (header)
unsigned int UInt
Definition: TypeDef.h:212
#define IF_INTERNAL_OFFS
Offset used internally.
Short Pel
pixel type
Definition: TypeDef.h:249
UInt getStride(const ComponentID id) const
Definition: TComYuv.h:199
Int getNumberValidComponents() const
Definition: TComPic.h:140
picture class (header)
T ClipBD(const T x, const Int bitDepth)
Definition: CommonDef.h:253
Int recon[MAX_NUM_CHANNEL_TYPE]
the bit depth as indicated in the SPS
Definition: TypeDef.h:793
#define IF_INTERNAL_PREC
Number of bits for internal precision.
general YUV buffer class
Definition: TComYuv.h:54
bool Bool
Definition: TypeDef.h:204
UInt getComponentScaleX(const ComponentID id) const
Definition: TComYuv.h:204
Void addWeightBi(const TComYuv *pcYuvSrc0, const TComYuv *pcYuvSrc1, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, const WPScalingParam *const wp1, TComYuv *const rpcYuvDst, const Bool bRoundLuma=true)
weighted averaging for bi-pred
static Pel noWeightUnidir(Pel P0, Int round, Int shift, Int offset, Int clipBD)
UInt uiLog2WeightDenom
Definition: TComSlice.h:1206
UInt getComponentScaleY(const ComponentID id) const
Definition: TComYuv.h:205
static ChannelType toChannelType(const ComponentID id)
reference list 0
Definition: TypeDef.h:372
Int getBitDepth(ChannelType type) const
Definition: TComSlice.h:894
Pel * getAddr(const ComponentID id)
Definition: TComYuv.h:150
RefPicList
reference list index
Definition: TypeDef.h:370
Void getWpScaling(RefPicList e, Int iRefIdx, WPScalingParam *&wp)
get tables for weighted prediction
Definition: TComSlice.cpp:1405
const BitDepths & getBitDepths() const
Definition: TComSlice.h:900
const TComPPS * getPPS() const
Definition: TComSlice.h:1332
static Pel weightUnidir(Int w0, Pel P0, Int round, Int shift, Int offset, Int clipBD)
reference list 1
Definition: TypeDef.h:373
static Pel weightBidir(Int w0, Pel P0, Int w1, Pel P1, Int round, Int shift, Int offset, Int clipBD)
TComPic * getPic()
Definition: TComDataCU.h:200
TComCUMvField * getCUMvField(RefPicList e)
Definition: TComDataCU.h:297
int Int
Definition: TypeDef.h:211
ComponentID
Definition: TypeDef.h:308
weighting prediction class (header)
Void xWeightedPredictionBi(TComDataCU *const pcCU, const TComYuv *const pcYuvSrc0, const TComYuv *const pcYuvSrc1, const Int iRefIdx0, const Int iRefIdx1, const UInt uiPartIdx, const Int iWidth, const Int iHeight, TComYuv *pcYuvDst)
weighted prediction for bi-pred
slice header class
Definition: TComSlice.h:1225
Void getWpScaling(TComDataCU *const pcCU, const Int iRefIdx0, const Int iRefIdx1, WPScalingParam *&wp0, WPScalingParam *&wp1)
derivation of wp tables
Bool getWPBiPred() const
Definition: TComSlice.h:1135
UInt getNumberValidComponents() const
Definition: TComYuv.h:203
Void addWeightUni(const TComYuv *const pcYuvSrc0, const BitDepths &bitDepths, const UInt iPartUnitIdx, const UInt uiWidth, const UInt uiHeight, const WPScalingParam *const wp0, TComYuv *const rpcYuvDst)
weighted averaging for uni-pred
TComSlice * getSlice()
Definition: TComDataCU.h:202
const TComSPS * getSPS() const
Definition: TComSlice.h:1329
Bool getHighPrecisionOffsetsEnabledFlag() const
Definition: TComSlice.h:729
Void xWeightedPredictionUni(TComDataCU *const pcCU, const TComYuv *const pcYuvSrc, const UInt uiPartAddr, const Int iWidth, const Int iHeight, const RefPicList eRefPicList, TComYuv *pcYuvPred, const Int iRefIdx=-1)
weighted prediction for uni-pred