source: SHVCSoftware/branches/0.1.1-bugfix/source/Lib/TLibEncoder/WeightPredAnalysis.cpp @ 577

Last change on this file since 577 was 2, checked in by seregin, 12 years ago

Initial import by Vadim Seregin <vseregin@…>

File size: 17.6 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-2012, 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     WeightedPredAnalysis.cpp
35    \brief    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  m_weighted_pred_flag = false;
50  m_weighted_bipred_flag = false;
51  for ( Int iList =0 ; iList<2 ; iList++ )
52  {
53    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ ) 
54    {
55      for ( int comp=0 ; comp<3 ;comp++ ) 
56      {
57        wpScalingParam  *pwp   = &(m_wp[iList][iRefIdx][comp]);
58        pwp->bPresentFlag      = false;
59        pwp->uiLog2WeightDenom = 0;
60        pwp->iWeight           = 1;
61        pwp->iOffset           = 0;
62      }
63    }
64  }
65}
66
67/** calculate AC and DC values for current original image
68 * \param TComSlice *slice
69 * \returns Void
70 */
71Bool  WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *slice)
72{
73  //===== calculate AC/DC value =====
74  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
75  Int   iSample  = 0;
76
77  // calculate DC/AC value for Y
78  Pel*  pOrg    = pPic->getLumaAddr();
79  Int64  iOrgDCY = xCalcDCValueSlice(slice, pOrg, &iSample);
80  Int64  iOrgNormDCY = ((iOrgDCY+(iSample>>1)) / iSample);
81  pOrg = pPic->getLumaAddr();
82  Int64  iOrgACY  = xCalcACValueSlice(slice, pOrg, iOrgNormDCY);
83
84  // calculate DC/AC value for Cb
85  pOrg = pPic->getCbAddr();
86  Int64  iOrgDCCb = xCalcDCValueUVSlice(slice, pOrg, &iSample);
87  Int64  iOrgNormDCCb = ((iOrgDCCb+(iSample>>1)) / (iSample));
88  pOrg = pPic->getCbAddr();
89  Int64  iOrgACCb  = xCalcACValueUVSlice(slice, pOrg, iOrgNormDCCb);
90
91  // calculate DC/AC value for Cr
92  pOrg = pPic->getCrAddr();
93  Int64  iOrgDCCr = xCalcDCValueUVSlice(slice, pOrg, &iSample);
94  Int64  iOrgNormDCCr = ((iOrgDCCr+(iSample>>1)) / (iSample));
95  pOrg = pPic->getCrAddr();
96  Int64  iOrgACCr  = xCalcACValueUVSlice(slice, pOrg, iOrgNormDCCr);
97
98  wpACDCParam weightACDCParam[3];
99  weightACDCParam[0].iAC = iOrgACY;
100  weightACDCParam[0].iDC = iOrgNormDCY;
101  weightACDCParam[1].iAC = iOrgACCb;
102  weightACDCParam[1].iDC = iOrgNormDCCb;
103  weightACDCParam[2].iAC = iOrgACCr;
104  weightACDCParam[2].iDC = iOrgNormDCCr;
105
106  slice->setWpAcDcParam(weightACDCParam);
107  return (true);
108}
109
110/** store weighted_pred_flag and weighted_bipred_idc values
111 * \param weighted_pred_flag
112 * \param weighted_bipred_idc
113 * \returns Void
114 */
115Void  WeightPredAnalysis::xStoreWPparam(Bool weighted_pred_flag, Bool weighted_bipred_flag)
116{
117  m_weighted_pred_flag = weighted_pred_flag;
118  m_weighted_bipred_flag = weighted_bipred_flag;
119}
120
121/** restore weighted_pred_flag and weighted_bipred_idc values
122 * \param TComSlice *slice
123 * \returns Void
124 */
125Void  WeightPredAnalysis::xRestoreWPparam(TComSlice *slice)
126{
127  slice->getPPS()->setUseWP(m_weighted_pred_flag);
128  slice->getPPS()->setWPBiPred(m_weighted_bipred_flag);
129}
130
131/** check weighted pred or non-weighted pred
132 * \param TComSlice *slice
133 * \returns Void
134 */
135Void  WeightPredAnalysis::xCheckWPEnable(TComSlice *slice)
136{
137  Int iPresentCnt = 0;
138  for ( Int iList=0 ; iList<2 ; iList++ )
139  {
140    for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ ) 
141    {
142      for ( Int iComp=0 ; iComp<3 ;iComp++ ) 
143      {
144        wpScalingParam  *pwp = &(m_wp[iList][iRefIdx][iComp]);
145        iPresentCnt += (Int)pwp->bPresentFlag;
146      }
147    }
148  }
149
150  if(iPresentCnt==0)
151  {
152    slice->getPPS()->setUseWP(false);
153    slice->getPPS()->setWPBiPred(false);
154    for ( Int iList=0 ; iList<2 ; iList++ )
155    {
156      for ( Int iRefIdx=0 ; iRefIdx<MAX_NUM_REF ; iRefIdx++ ) 
157      {
158        for ( Int iComp=0 ; iComp<3 ;iComp++ ) 
159        {
160          wpScalingParam  *pwp = &(m_wp[iList][iRefIdx][iComp]);
161          pwp->bPresentFlag      = false;
162          pwp->uiLog2WeightDenom = 0;
163          pwp->iWeight           = 1;
164          pwp->iOffset           = 0;
165        }
166      }
167    }
168    slice->setWpScaling( m_wp );
169  }
170}
171
172/** estimate wp tables for explicit wp
173 * \param TComSlice *slice
174 * \returns Bool
175 */
176Bool  WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *slice)
177{
178  Int iDenom  = 6;
179#if WP_PARAM_RANGE_LIMIT
180  Bool validRangeFlag = false;
181#else
182  Int iRealDenom = iDenom + (g_uiBitDepth+g_uiBitIncrement-8);
183  Int iRealOffset = ((Int)1<<(iRealDenom-1));
184#endif
185
186  if(slice->getNumRefIdx(REF_PIC_LIST_0)>3)
187  {
188    iDenom  = 7;
189#if WP_PARAM_RANGE_LIMIT
190#else
191    iRealDenom = iDenom + (g_uiBitDepth+g_uiBitIncrement-8);
192    iRealOffset = ((Int)1<<(iRealDenom-1));
193#endif
194  }
195
196#if WP_PARAM_RANGE_LIMIT
197  do
198  {
199    validRangeFlag = xUpdatingWPParameters(slice, m_wp, iDenom);
200    if (!validRangeFlag)
201    {
202      iDenom--; // decrement to satisfy the range limitation
203    }
204  } while (validRangeFlag == false);
205#else
206  Int iNumPredDir = slice->isInterP() ? 1 : 2;
207  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
208  {
209    RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
210    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
211    {
212      wpACDCParam *CurrWeightACDCParam, *RefWeightACDCParam;
213      slice->getWpAcDcParam(CurrWeightACDCParam);
214      slice->getRefPic(eRefPicList, iRefIdxTemp)->getSlice(0)->getWpAcDcParam(RefWeightACDCParam);
215
216      for ( Int iComp = 0; iComp < 3; iComp++ )
217      {
218        // current frame
219        Int64 iCurrDC = CurrWeightACDCParam[iComp].iDC;
220        Int64 iCurrAC = CurrWeightACDCParam[iComp].iAC;
221        // reference frame
222        Int64 iRefDC = RefWeightACDCParam[iComp].iDC;
223        Int64 iRefAC = RefWeightACDCParam[iComp].iAC;
224
225        // calculating iWeight and iOffset params
226        Double dWeight = (iRefAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)iCurrAC / (Double)iRefAC) );
227        Int iWeight = (Int)( 0.5 + dWeight * (Double)(1<<iDenom) );
228        Int iOffset = (Int)( ((iCurrDC<<iDenom) - ((Int64)iWeight * iRefDC) + (Int64)iRealOffset) >> iRealDenom );
229
230        m_wp[iRefList][iRefIdxTemp][iComp].bPresentFlag = true;
231        m_wp[iRefList][iRefIdxTemp][iComp].iWeight = (Int)iWeight;
232        m_wp[iRefList][iRefIdxTemp][iComp].iOffset = (Int)iOffset;
233        m_wp[iRefList][iRefIdxTemp][iComp].uiLog2WeightDenom = (Int)iDenom;
234      }
235    }
236  }
237#endif
238
239  // selecting whether WP is used, or not
240  xSelectWP(slice, m_wp, iDenom);
241 
242  slice->setWpScaling( m_wp );
243
244  return (true);
245}
246
247#if WP_PARAM_RANGE_LIMIT
248/** update wp tables for explicit wp w.r.t ramge limitation
249 * \param TComSlice *slice
250 * \returns Bool
251 */
252Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *slice, wpScalingParam weightPredTable[2][MAX_NUM_REF][3], Int log2Denom)
253{
254  Int realLog2Denom = log2Denom + (g_uiBitDepth+g_uiBitIncrement-8);
255  Int realOffset = ((Int)1<<(realLog2Denom-1));
256
257  Int numPredDir = slice->isInterP() ? 1 : 2;
258  for ( Int refList = 0; refList < numPredDir; refList++ )
259  {
260    RefPicList  eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
261    for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ )
262    {
263      wpACDCParam *currWeightACDCParam, *refWeightACDCParam;
264      slice->getWpAcDcParam(currWeightACDCParam);
265      slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam);
266
267      for ( Int comp = 0; comp < 3; comp++ )
268      {
269        // current frame
270        Int64 currDC = currWeightACDCParam[comp].iDC;
271        Int64 currAC = currWeightACDCParam[comp].iAC;
272        // reference frame
273        Int64 refDC = refWeightACDCParam[comp].iDC;
274        Int64 refAC = refWeightACDCParam[comp].iAC;
275
276        // calculating iWeight and iOffset params
277        Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) );
278        Int weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) );
279        Int offset = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom );
280
281        // Chroma offset range limination
282        if(comp)
283        {
284          Int shift = ((1<<(g_uiBitDepth+g_uiBitIncrement-1)));
285          Int pred = ( shift - ( ( shift*weight)>>(log2Denom) ) );
286          Int deltaOffset = Clip3( -512, 511, (offset - pred) );    // signed 10bit
287          offset = Clip3( -128, 127, (deltaOffset + pred) );        // signed 8bit
288        }
289
290        // Weighting factor limitation
291        Int defaultWeight = (1<<log2Denom);
292        Int deltaWeight = (defaultWeight - weight);
293        if(deltaWeight > 127 || deltaWeight < -128)
294          return (false);
295
296        m_wp[refList][refIdxTemp][comp].bPresentFlag = true;
297        m_wp[refList][refIdxTemp][comp].iWeight = (Int)weight;
298        m_wp[refList][refIdxTemp][comp].iOffset = (Int)offset;
299        m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = (Int)log2Denom;
300      }
301    }
302  }
303  return (true);
304}
305#endif
306
307/** select whether weighted pred enables or not.
308 * \param TComSlice *slice
309 * \param wpScalingParam
310 * \param iDenom
311 * \returns Bool
312 */
313Bool WeightPredAnalysis::xSelectWP(TComSlice *slice, wpScalingParam weightPredTable[2][MAX_NUM_REF][3], Int iDenom)
314{
315  TComPicYuv*   pPic = slice->getPic()->getPicYuvOrg();
316  Int iWidth  = pPic->getWidth();
317  Int iHeight = pPic->getHeight();
318  Int iDefaultWeight = ((Int)1<<iDenom);
319  Int iNumPredDir = slice->isInterP() ? 1 : 2;
320
321  for ( Int iRefList = 0; iRefList < iNumPredDir; iRefList++ )
322  {
323    Int64 iSADWP = 0, iSADnoWP = 0;
324    RefPicList  eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 );
325    for ( Int iRefIdxTemp = 0; iRefIdxTemp < slice->getNumRefIdx(eRefPicList); iRefIdxTemp++ )
326    {
327      Pel*  pOrg    = pPic->getLumaAddr();
328      Pel*  pRef    = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getLumaAddr();
329      Int   iOrgStride = pPic->getStride();
330      Int   iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getStride();
331
332      // calculate SAD costs with/without wp for luma
333      iSADWP   = this->xCalcSADvalueWP(pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, iDenom, weightPredTable[iRefList][iRefIdxTemp][0].iWeight, weightPredTable[iRefList][iRefIdxTemp][0].iOffset);
334      iSADnoWP = this->xCalcSADvalueWP(pOrg, pRef, iWidth, iHeight, iOrgStride, iRefStride, iDenom, iDefaultWeight, 0);
335
336      pOrg = pPic->getCbAddr();
337      pRef = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getCbAddr();
338      iOrgStride = pPic->getCStride();
339      iRefStride = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getCStride();
340
341      // calculate SAD costs with/without wp for chroma cb
342      iSADWP   += this->xCalcSADvalueWP(pOrg, pRef, iWidth>>1, iHeight>>1, iOrgStride, iRefStride, iDenom, weightPredTable[iRefList][iRefIdxTemp][1].iWeight, weightPredTable[iRefList][iRefIdxTemp][1].iOffset);
343      iSADnoWP += this->xCalcSADvalueWP(pOrg, pRef, iWidth>>1, iHeight>>1, iOrgStride, iRefStride, iDenom, iDefaultWeight, 0);
344
345      pOrg = pPic->getCrAddr();
346      pRef = slice->getRefPic(eRefPicList, iRefIdxTemp)->getPicYuvRec()->getCrAddr();
347
348      // calculate SAD costs with/without wp for chroma cr
349      iSADWP   += this->xCalcSADvalueWP(pOrg, pRef, iWidth>>1, iHeight>>1, iOrgStride, iRefStride, iDenom, weightPredTable[iRefList][iRefIdxTemp][2].iWeight, weightPredTable[iRefList][iRefIdxTemp][2].iOffset);
350      iSADnoWP += this->xCalcSADvalueWP(pOrg, pRef, iWidth>>1, iHeight>>1, iOrgStride, iRefStride, iDenom, iDefaultWeight, 0);
351
352      Double dRatio = ((Double)iSADWP / (Double)iSADnoWP);
353      if(dRatio >= (Double)DTHRESH)
354      {
355        for ( Int iComp = 0; iComp < 3; iComp++ )
356        {
357          weightPredTable[iRefList][iRefIdxTemp][iComp].bPresentFlag = false;
358          weightPredTable[iRefList][iRefIdxTemp][iComp].iOffset = (Int)0;
359          weightPredTable[iRefList][iRefIdxTemp][iComp].iWeight = (Int)iDefaultWeight;
360          weightPredTable[iRefList][iRefIdxTemp][iComp].uiLog2WeightDenom = (Int)iDenom;
361        }
362      }
363    }
364  }
365  return (true);
366}
367
368/** calculate DC value of original image for luma.
369 * \param TComSlice *slice
370 * \param Pel *pPel
371 * \param Int *iSample
372 * \returns Int64
373 */
374Int64 WeightPredAnalysis::xCalcDCValueSlice(TComSlice *slice, Pel *pPel, Int *iSample)
375{
376  TComPicYuv* pPic = slice->getPic()->getPicYuvOrg();
377  Int iStride = pPic->getStride();
378
379  *iSample = 0;
380  Int iWidth  = pPic->getWidth();
381  Int iHeight = pPic->getHeight();
382  *iSample = iWidth*iHeight;
383  Int64 iDC = xCalcDCValue(pPel, iWidth, iHeight, iStride);
384
385  return (iDC);
386}
387
388/** calculate AC value of original image for luma.
389 * \param TComSlice *slice
390 * \param Pel *pPel
391 * \param Int iDC
392 * \returns Int64
393 */
394Int64 WeightPredAnalysis::xCalcACValueSlice(TComSlice *slice, Pel *pPel, Int64 iDC)
395{
396  TComPicYuv* pPic = slice->getPic()->getPicYuvOrg();
397  Int iStride = pPic->getStride();
398
399  Int iWidth  = pPic->getWidth();
400  Int iHeight = pPic->getHeight();
401  Int64 iAC = xCalcACValue(pPel, iWidth, iHeight, iStride, iDC);
402
403  return (iAC);
404}
405
406/** calculate DC value of original image for chroma.
407 * \param TComSlice *slice
408 * \param Pel *pPel
409 * \param Int *iSample
410 * \returns Int64
411 */
412Int64 WeightPredAnalysis::xCalcDCValueUVSlice(TComSlice *slice, Pel *pPel, Int *iSample)
413{
414  TComPicYuv* pPic = slice->getPic()->getPicYuvOrg();
415  Int iCStride = pPic->getCStride();
416
417  *iSample = 0;
418  Int iWidth  = pPic->getWidth()>>1;
419  Int iHeight = pPic->getHeight()>>1;
420  *iSample = iWidth*iHeight;
421  Int64 iDC = xCalcDCValue(pPel, iWidth, iHeight, iCStride);
422
423  return (iDC);
424}
425
426/** calculate AC value of original image for chroma.
427 * \param TComSlice *slice
428 * \param Pel *pPel
429 * \param Int iDC
430 * \returns Int64
431 */
432Int64 WeightPredAnalysis::xCalcACValueUVSlice(TComSlice *slice, Pel *pPel, Int64 iDC)
433{
434  TComPicYuv* pPic = slice->getPic()->getPicYuvOrg();
435  Int iCStride = pPic->getCStride();
436
437  Int iWidth  = pPic->getWidth()>>1;
438  Int iHeight = pPic->getHeight()>>1;
439  Int64 iAC = xCalcACValue(pPel, iWidth, iHeight, iCStride, iDC);
440
441  return (iAC);
442}
443
444/** calculate DC value.
445 * \param Pel *pPel
446 * \param Int iWidth
447 * \param Int iHeight
448 * \param Int iStride
449 * \returns Int64
450 */
451Int64 WeightPredAnalysis::xCalcDCValue(Pel *pPel, Int iWidth, Int iHeight, Int iStride)
452{
453  Int x, y;
454  Int64 iDC = 0;
455  for( y = 0; y < iHeight; y++ )
456  {
457    for( x = 0; x < iWidth; x++ )
458    {
459      iDC += (Int)( pPel[x] );
460    }
461    pPel += iStride;
462  }
463  return (iDC);
464}
465
466/** calculate AC value.
467 * \param Pel *pPel
468 * \param Int iWidth
469 * \param Int iHeight
470 * \param Int iStride
471 * \param Int iDC
472 * \returns Int64
473 */
474Int64 WeightPredAnalysis::xCalcACValue(Pel *pPel, Int iWidth, Int iHeight, Int iStride, Int64 iDC)
475{
476  Int x, y;
477  Int64 iAC = 0;
478  for( y = 0; y < iHeight; y++ )
479  {
480    for( x = 0; x < iWidth; x++ )
481    {
482      iAC += abs( (Int)pPel[x] - (Int)iDC );
483    }
484    pPel += iStride;
485  }
486  return (iAC);
487}
488
489/** calculate SAD values for both WP version and non-WP version.
490 * \param Pel *pOrgPel
491 * \param Pel *pRefPel
492 * \param Int iWidth
493 * \param Int iHeight
494 * \param Int iOrgStride
495 * \param Int iRefStride
496 * \param Int iDenom
497 * \param Int iWeight
498 * \param Int iOffset
499 * \returns Int64
500 */
501Int64 WeightPredAnalysis::xCalcSADvalueWP(Pel *pOrgPel, Pel *pRefPel, Int iWidth, Int iHeight, Int iOrgStride, Int iRefStride, Int iDenom, Int iWeight, Int iOffset)
502{
503  Int x, y;
504  Int64 iSAD = 0;
505  Int64 iSize   = iWidth*iHeight;
506  Int64 iRealDenom = iDenom + (g_uiBitDepth+g_uiBitIncrement-8);
507  for( y = 0; y < iHeight; y++ )
508  {
509    for( x = 0; x < iWidth; x++ )
510    {
511      iSAD += ABS(( ((Int64)pOrgPel[x]<<(Int64)iDenom) - ( (Int64)pRefPel[x] * (Int64)iWeight + ((Int64)iOffset<<iRealDenom) ) ) );
512    }
513    pOrgPel += iOrgStride;
514    pRefPel += iRefStride;
515  }
516  return (iSAD/iSize);
517}
518
519
Note: See TracBrowser for help on using the repository browser.