[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 |
---|
[494] | 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 WeightPredAnalysis.cpp |
---|
| 35 | \brief weighted prediction encoder class |
---|
| 36 | */ |
---|
| 37 | |
---|
[1335] | 38 | #include "../TLibCommon/CommonDef.h" |
---|
[313] | 39 | #include "../TLibCommon/TComSlice.h" |
---|
| 40 | #include "../TLibCommon/TComPic.h" |
---|
| 41 | #include "../TLibCommon/TComPicYuv.h" |
---|
| 42 | #include "WeightPredAnalysis.h" |
---|
[1400] | 43 | #include <limits> |
---|
[313] | 44 | |
---|
[1400] | 45 | static const Double WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD=0.99; // NOTE: U0040 used 0.95 |
---|
[313] | 46 | |
---|
[1400] | 47 | //! calculate SAD values for both WP version and non-WP version. |
---|
| 48 | static |
---|
| 49 | Int64 xCalcSADvalueWP(const Int bitDepth, |
---|
| 50 | const Pel *pOrgPel, |
---|
| 51 | const Pel *pRefPel, |
---|
| 52 | const Int width, |
---|
| 53 | const Int height, |
---|
| 54 | const Int orgStride, |
---|
| 55 | const Int refStride, |
---|
| 56 | const Int log2Denom, |
---|
| 57 | const Int weight, |
---|
| 58 | const Int offset, |
---|
| 59 | const Bool useHighPrecision); |
---|
| 60 | |
---|
| 61 | //! calculate SAD values for both WP version and non-WP version. |
---|
| 62 | static |
---|
| 63 | Int64 xCalcSADvalueWPOptionalClip(const Int bitDepth, |
---|
| 64 | const Pel *pOrgPel, |
---|
| 65 | const Pel *pRefPel, |
---|
| 66 | const Int width, |
---|
| 67 | const Int height, |
---|
| 68 | const Int orgStride, |
---|
| 69 | const Int refStride, |
---|
| 70 | const Int log2Denom, |
---|
| 71 | const Int weight, |
---|
| 72 | const Int offset, |
---|
| 73 | const Bool useHighPrecision, |
---|
| 74 | const Bool clipped); |
---|
| 75 | |
---|
| 76 | // ----------------------------------------------------------------------------- |
---|
| 77 | // Helper functions |
---|
| 78 | |
---|
| 79 | |
---|
| 80 | //! calculate Histogram for array of pixels |
---|
| 81 | static |
---|
| 82 | Void xCalcHistogram(const Pel *pPel, |
---|
| 83 | std::vector<Int> &histogram, |
---|
| 84 | const Int width, |
---|
| 85 | const Int height, |
---|
| 86 | const Int stride, |
---|
| 87 | const Int maxPel) |
---|
| 88 | { |
---|
| 89 | histogram.clear(); |
---|
| 90 | histogram.resize(maxPel); |
---|
| 91 | for( Int y = 0; y < height; y++ ) |
---|
| 92 | { |
---|
| 93 | for( Int x = 0; x < width; x++ ) |
---|
| 94 | { |
---|
| 95 | const Pel v=pPel[x]; |
---|
| 96 | histogram[v<0?0:(v>=maxPel)?maxPel-1:v]++; |
---|
| 97 | } |
---|
| 98 | pPel += stride; |
---|
| 99 | } |
---|
| 100 | } |
---|
| 101 | |
---|
| 102 | static |
---|
| 103 | Distortion xCalcHistDistortion (const std::vector<Int> &histogram0, |
---|
| 104 | const std::vector<Int> &histogram1) |
---|
| 105 | { |
---|
| 106 | Distortion distortion = 0; |
---|
| 107 | assert(histogram0.size()==histogram1.size()); |
---|
| 108 | const Int numElements=Int(histogram0.size()); |
---|
| 109 | |
---|
| 110 | // Scan histograms to compute histogram distortion |
---|
| 111 | for (Int i = 0; i <= numElements; i++) |
---|
| 112 | { |
---|
| 113 | distortion += (Distortion)(abs(histogram0[i] - histogram1[i])); |
---|
| 114 | } |
---|
| 115 | |
---|
| 116 | return distortion; |
---|
| 117 | } |
---|
| 118 | |
---|
| 119 | static |
---|
| 120 | void xScaleHistogram(const std::vector<Int> &histogramInput, |
---|
| 121 | std::vector<Int> &histogramOutput, // cannot be the same as the input |
---|
| 122 | const Int bitDepth, |
---|
| 123 | const Int log2Denom, |
---|
| 124 | const Int weight, |
---|
| 125 | const Int offset, |
---|
| 126 | const Bool bHighPrecision) |
---|
| 127 | { |
---|
| 128 | assert(&histogramInput != &histogramOutput); |
---|
| 129 | const Int numElements=Int(histogramInput.size()); |
---|
| 130 | histogramOutput.clear(); |
---|
| 131 | histogramOutput.resize(numElements); |
---|
| 132 | |
---|
| 133 | const Int64 iRealLog2Denom = bHighPrecision ? 0 : (bitDepth - 8); |
---|
| 134 | const Int64 iRealOffset = ((Int64)offset)<<iRealLog2Denom; |
---|
| 135 | |
---|
| 136 | const Int divOffset = log2Denom == 0 ? 0 : 1 << (log2Denom - 1); |
---|
| 137 | // Scan histogram and apply illumination parameters appropriately |
---|
| 138 | // Then compute updated histogram. |
---|
| 139 | // Note that this technique only works with single list weights/offsets. |
---|
| 140 | |
---|
| 141 | for (Int i = 0; i < numElements; i++) |
---|
| 142 | { |
---|
| 143 | const Int j = Clip3(0, numElements - 1, (Int)(((weight * i + divOffset) >> log2Denom) + iRealOffset)); |
---|
| 144 | histogramOutput[j] += histogramInput[i]; |
---|
| 145 | } |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | static |
---|
| 149 | Distortion xSearchHistogram(const std::vector<Int> &histogramSource, |
---|
| 150 | const std::vector<Int> &histogramRef, |
---|
| 151 | std::vector<Int> &outputHistogram, |
---|
| 152 | const Int bitDepth, |
---|
| 153 | const Int log2Denom, |
---|
| 154 | Int &weightToUpdate, |
---|
| 155 | Int &offsetToUpdate, |
---|
| 156 | const Bool bHighPrecision, |
---|
| 157 | const ComponentID compID) |
---|
| 158 | { |
---|
| 159 | const Int initialWeight = weightToUpdate; |
---|
| 160 | const Int initialOffset = offsetToUpdate; |
---|
| 161 | const Int weightRange = 10; |
---|
| 162 | const Int offsetRange = 10; |
---|
| 163 | const Int maxOffset = 1 << ((bHighPrecision == true) ? (bitDepth - 1) : 7); |
---|
| 164 | const Int range = bHighPrecision ? (1<<bitDepth) / 2 : 128; |
---|
| 165 | const Int defaultWeight = (1<<log2Denom); |
---|
| 166 | const Int minSearchWeight = std::max<Int>(initialWeight - weightRange, defaultWeight - range); |
---|
| 167 | const Int maxSearchWeight = std::min<Int>(initialWeight + weightRange+1, defaultWeight + range); |
---|
| 168 | |
---|
[1411] | 169 | Distortion minDistortion = std::numeric_limits<Distortion>::max(); |
---|
[1400] | 170 | Int bestWeight = initialWeight; |
---|
| 171 | Int bestOffset = initialOffset; |
---|
| 172 | |
---|
| 173 | for (Int searchWeight = minSearchWeight; searchWeight < maxSearchWeight; searchWeight++) |
---|
| 174 | { |
---|
| 175 | if (compID == COMPONENT_Y) |
---|
| 176 | { |
---|
| 177 | for (Int searchOffset = std::max<Int>(initialOffset - offsetRange, -maxOffset); |
---|
| 178 | searchOffset <= initialOffset + offsetRange && searchOffset<=(maxOffset-1); |
---|
| 179 | searchOffset++) |
---|
| 180 | { |
---|
| 181 | xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, searchWeight, searchOffset, bHighPrecision); |
---|
| 182 | const Distortion distortion = xCalcHistDistortion(histogramSource, outputHistogram); |
---|
| 183 | |
---|
| 184 | if (distortion < minDistortion) |
---|
| 185 | { |
---|
| 186 | minDistortion = distortion; |
---|
| 187 | bestWeight = searchWeight; |
---|
| 188 | bestOffset = searchOffset; |
---|
| 189 | } |
---|
| 190 | } |
---|
| 191 | } |
---|
| 192 | else |
---|
| 193 | { |
---|
| 194 | const Int pred = ( maxOffset - ( ( maxOffset*searchWeight)>>(log2Denom) ) ); |
---|
| 195 | |
---|
| 196 | for (Int searchOffset = initialOffset - offsetRange; searchOffset <= initialOffset + offsetRange; searchOffset++) |
---|
| 197 | { |
---|
| 198 | const Int deltaOffset = Clip3( -4*maxOffset, 4*maxOffset-1, (searchOffset - pred) ); // signed 10bit (if !bHighPrecision) |
---|
| 199 | const Int clippedOffset = Clip3( -1*maxOffset, 1*maxOffset-1, (deltaOffset + pred) ); // signed 8bit (if !bHighPrecision) |
---|
| 200 | xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, searchWeight, clippedOffset, bHighPrecision); |
---|
| 201 | const Distortion distortion = xCalcHistDistortion(histogramSource, outputHistogram); |
---|
| 202 | |
---|
| 203 | if (distortion < minDistortion) |
---|
| 204 | { |
---|
| 205 | minDistortion = distortion; |
---|
| 206 | bestWeight = searchWeight; |
---|
| 207 | bestOffset = clippedOffset; |
---|
| 208 | } |
---|
| 209 | } |
---|
| 210 | } |
---|
| 211 | } |
---|
| 212 | |
---|
| 213 | weightToUpdate = bestWeight; |
---|
| 214 | offsetToUpdate = bestOffset; |
---|
| 215 | |
---|
| 216 | // regenerate best histogram |
---|
| 217 | xScaleHistogram(histogramRef, outputHistogram, bitDepth, log2Denom, bestWeight, bestOffset, bHighPrecision); |
---|
| 218 | |
---|
| 219 | return minDistortion; |
---|
| 220 | } |
---|
| 221 | |
---|
| 222 | |
---|
| 223 | // ----------------------------------------------------------------------------- |
---|
| 224 | // Member functions |
---|
| 225 | |
---|
[313] | 226 | WeightPredAnalysis::WeightPredAnalysis() |
---|
| 227 | { |
---|
[1029] | 228 | for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ ) |
---|
[313] | 229 | { |
---|
[1400] | 230 | for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ ) |
---|
[313] | 231 | { |
---|
[1029] | 232 | for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ ) |
---|
[313] | 233 | { |
---|
[1400] | 234 | WPScalingParam *pwp = &(m_wp[lst][refIdx][comp]); |
---|
[313] | 235 | pwp->bPresentFlag = false; |
---|
| 236 | pwp->uiLog2WeightDenom = 0; |
---|
| 237 | pwp->iWeight = 1; |
---|
| 238 | pwp->iOffset = 0; |
---|
| 239 | } |
---|
| 240 | } |
---|
| 241 | } |
---|
| 242 | } |
---|
| 243 | |
---|
[1029] | 244 | |
---|
[1260] | 245 | //! calculate AC and DC values for current original image |
---|
[1029] | 246 | Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice) |
---|
[313] | 247 | { |
---|
| 248 | //===== calculate AC/DC value ===== |
---|
| 249 | TComPicYuv* pPic = slice->getPic()->getPicYuvOrg(); |
---|
| 250 | |
---|
[1029] | 251 | WPACDCParam weightACDCParam[MAX_NUM_COMPONENT]; |
---|
[313] | 252 | |
---|
[1029] | 253 | for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) |
---|
| 254 | { |
---|
| 255 | const ComponentID compID = ComponentID(componentIndex); |
---|
[313] | 256 | |
---|
[1029] | 257 | // calculate DC/AC value for channel |
---|
| 258 | |
---|
[1400] | 259 | const Int stride = pPic->getStride(compID); |
---|
| 260 | const Int width = pPic->getWidth(compID); |
---|
| 261 | const Int height = pPic->getHeight(compID); |
---|
[1029] | 262 | |
---|
[1400] | 263 | const Int sample = width*height; |
---|
[1029] | 264 | |
---|
[1400] | 265 | Int64 orgDC = 0; |
---|
[1029] | 266 | { |
---|
| 267 | const Pel *pPel = pPic->getAddr(compID); |
---|
| 268 | |
---|
[1400] | 269 | for(Int y = 0; y < height; y++, pPel+=stride ) |
---|
[1246] | 270 | { |
---|
[1400] | 271 | for(Int x = 0; x < width; x++ ) |
---|
[1246] | 272 | { |
---|
[1400] | 273 | orgDC += (Int)( pPel[x] ); |
---|
[1246] | 274 | } |
---|
| 275 | } |
---|
[1029] | 276 | } |
---|
| 277 | |
---|
[1400] | 278 | const Int64 orgNormDC = ((orgDC+(sample>>1)) / sample); |
---|
[1029] | 279 | |
---|
[1400] | 280 | Int64 orgAC = 0; |
---|
[1029] | 281 | { |
---|
| 282 | const Pel *pPel = pPic->getAddr(compID); |
---|
| 283 | |
---|
[1400] | 284 | for(Int y = 0; y < height; y++, pPel += stride ) |
---|
[1246] | 285 | { |
---|
[1400] | 286 | for(Int x = 0; x < width; x++ ) |
---|
[1246] | 287 | { |
---|
[1400] | 288 | orgAC += abs( (Int)pPel[x] - (Int)orgNormDC ); |
---|
[1246] | 289 | } |
---|
| 290 | } |
---|
[1029] | 291 | } |
---|
| 292 | |
---|
[1316] | 293 | const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0; |
---|
[1400] | 294 | weightACDCParam[compID].iDC = (((orgDC<<fixedBitShift)+(sample>>1)) / sample); |
---|
| 295 | weightACDCParam[compID].iAC = orgAC; |
---|
[1201] | 296 | #if SVC_EXTENSION |
---|
[1400] | 297 | weightACDCParam[compID].numSamples = sample; |
---|
[494] | 298 | #endif |
---|
[1029] | 299 | } |
---|
[313] | 300 | |
---|
| 301 | slice->setWpAcDcParam(weightACDCParam); |
---|
| 302 | } |
---|
| 303 | |
---|
[1246] | 304 | |
---|
[1260] | 305 | //! check weighted pred or non-weighted pred |
---|
[1029] | 306 | Void WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice) |
---|
[313] | 307 | { |
---|
[1029] | 308 | const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg(); |
---|
| 309 | |
---|
[1400] | 310 | Int presentCnt = 0; |
---|
[1029] | 311 | for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ ) |
---|
[313] | 312 | { |
---|
[1400] | 313 | for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ ) |
---|
[313] | 314 | { |
---|
[1029] | 315 | for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) |
---|
[313] | 316 | { |
---|
[1400] | 317 | WPScalingParam *pwp = &(m_wp[lst][refIdx][componentIndex]); |
---|
| 318 | presentCnt += (Int)pwp->bPresentFlag; |
---|
[313] | 319 | } |
---|
| 320 | } |
---|
| 321 | } |
---|
| 322 | |
---|
[1400] | 323 | if(presentCnt==0) |
---|
[313] | 324 | { |
---|
[1235] | 325 | slice->setTestWeightPred(false); |
---|
| 326 | slice->setTestWeightBiPred(false); |
---|
[1029] | 327 | |
---|
| 328 | for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ ) |
---|
[313] | 329 | { |
---|
[1400] | 330 | for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ ) |
---|
[313] | 331 | { |
---|
[1029] | 332 | for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) |
---|
[313] | 333 | { |
---|
[1400] | 334 | WPScalingParam *pwp = &(m_wp[lst][refIdx][componentIndex]); |
---|
[1029] | 335 | |
---|
[313] | 336 | pwp->bPresentFlag = false; |
---|
| 337 | pwp->uiLog2WeightDenom = 0; |
---|
| 338 | pwp->iWeight = 1; |
---|
| 339 | pwp->iOffset = 0; |
---|
| 340 | } |
---|
| 341 | } |
---|
| 342 | } |
---|
| 343 | slice->setWpScaling( m_wp ); |
---|
| 344 | } |
---|
[1235] | 345 | else |
---|
| 346 | { |
---|
[1400] | 347 | slice->setTestWeightPred (slice->getPPS()->getUseWP()); |
---|
[1235] | 348 | slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred()); |
---|
| 349 | } |
---|
[313] | 350 | } |
---|
| 351 | |
---|
[1029] | 352 | |
---|
[1260] | 353 | //! estimate wp tables for explicit wp |
---|
[1400] | 354 | Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method) |
---|
[313] | 355 | { |
---|
[1029] | 356 | Int iDenom = 6; |
---|
[313] | 357 | Bool validRangeFlag = false; |
---|
| 358 | |
---|
| 359 | if(slice->getNumRefIdx(REF_PIC_LIST_0)>3) |
---|
| 360 | { |
---|
[1029] | 361 | iDenom = 7; |
---|
[313] | 362 | } |
---|
| 363 | |
---|
| 364 | do |
---|
| 365 | { |
---|
[1029] | 366 | validRangeFlag = xUpdatingWPParameters(slice, iDenom); |
---|
[313] | 367 | if (!validRangeFlag) |
---|
| 368 | { |
---|
| 369 | iDenom--; // decrement to satisfy the range limitation |
---|
| 370 | } |
---|
| 371 | } while (validRangeFlag == false); |
---|
| 372 | |
---|
[1235] | 373 | // selecting whether WP is used, or not (fast search) |
---|
| 374 | // NOTE: This is not operating on a slice, but the entire picture. |
---|
[1400] | 375 | switch (method) |
---|
| 376 | { |
---|
| 377 | case WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT: |
---|
| 378 | xSelectWP(slice, iDenom); |
---|
| 379 | break; |
---|
| 380 | case WP_PER_PICTURE_WITH_SIMPLE_DC_PER_COMPONENT: |
---|
| 381 | xSelectWPHistExtClip(slice, iDenom, false, false, false); |
---|
| 382 | break; |
---|
| 383 | case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT: |
---|
| 384 | xSelectWPHistExtClip(slice, iDenom, false, false, true); |
---|
| 385 | break; |
---|
| 386 | case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING: |
---|
| 387 | xSelectWPHistExtClip(slice, iDenom, false, true, true); |
---|
| 388 | break; |
---|
| 389 | case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION: |
---|
| 390 | xSelectWPHistExtClip(slice, iDenom, true, true, true); |
---|
| 391 | break; |
---|
| 392 | default: |
---|
| 393 | assert(0); |
---|
| 394 | exit(1); |
---|
| 395 | } |
---|
[494] | 396 | |
---|
[313] | 397 | slice->setWpScaling( m_wp ); |
---|
| 398 | } |
---|
| 399 | |
---|
[1029] | 400 | |
---|
[1260] | 401 | //! update wp tables for explicit wp w.r.t range limitation |
---|
[1029] | 402 | Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom) |
---|
[313] | 403 | { |
---|
[1029] | 404 | const Int numComp = slice->getPic()->getPicYuvOrg()->getNumberValidComponents(); |
---|
[1316] | 405 | const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); |
---|
[1029] | 406 | const Int numPredDir = slice->isInterP() ? 1 : 2; |
---|
| 407 | |
---|
| 408 | assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); |
---|
| 409 | |
---|
[313] | 410 | for ( Int refList = 0; refList < numPredDir; refList++ ) |
---|
| 411 | { |
---|
[1029] | 412 | const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); |
---|
| 413 | |
---|
[313] | 414 | for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) |
---|
| 415 | { |
---|
[1316] | 416 | WPACDCParam *currWeightACDCParam, *refWeightACDCParam; |
---|
| 417 | slice->getWpAcDcParam(currWeightACDCParam); |
---|
| 418 | slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam); |
---|
[1029] | 419 | |
---|
[1201] | 420 | #if SVC_EXTENSION |
---|
[494] | 421 | UInt currLayerId = slice->getLayerId(); |
---|
| 422 | UInt refLayerId = slice->getRefPic(eRefPicList, refIdxTemp)->getLayerId(); |
---|
| 423 | Bool validILRPic = slice->getRefPic(eRefPicList, refIdxTemp)->isILR( currLayerId ) && refLayerId == 0; |
---|
[313] | 424 | |
---|
[494] | 425 | if( validILRPic ) |
---|
| 426 | { |
---|
[1316] | 427 | slice->getWpAcDcParam(refWeightACDCParam); |
---|
[494] | 428 | } |
---|
| 429 | #endif |
---|
| 430 | |
---|
[1029] | 431 | for ( Int comp = 0; comp < numComp; comp++ ) |
---|
[313] | 432 | { |
---|
[1029] | 433 | const ComponentID compID = ComponentID(comp); |
---|
[1287] | 434 | #if SVC_EXTENSION |
---|
| 435 | const Int bitDepth = slice->getBitDepth(toChannelType(compID)); |
---|
| 436 | #else |
---|
| 437 | const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); |
---|
| 438 | #endif |
---|
| 439 | const Int range = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128; |
---|
| 440 | const Int realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8)); |
---|
[1029] | 441 | const Int realOffset = ((Int)1<<(realLog2Denom-1)); |
---|
[313] | 442 | |
---|
| 443 | // current frame |
---|
[1029] | 444 | const Int64 currDC = currWeightACDCParam[comp].iDC; |
---|
| 445 | const Int64 currAC = currWeightACDCParam[comp].iAC; |
---|
[313] | 446 | // reference frame |
---|
[1201] | 447 | #if SVC_EXTENSION |
---|
[1029] | 448 | Int64 refDC = refWeightACDCParam[comp].iDC; |
---|
| 449 | Int64 refAC = refWeightACDCParam[comp].iAC; |
---|
| 450 | |
---|
[494] | 451 | if( validILRPic ) |
---|
| 452 | { |
---|
[1400] | 453 | refAC = ( refAC * currWeightACDCParam[comp].numSamples ) / refWeightACDCParam[comp].numSamples; |
---|
[1202] | 454 | |
---|
[1287] | 455 | const Int bitDepthLuma = slice->getBitDepth(CHANNEL_TYPE_LUMA); |
---|
| 456 | const Int refBitDepthLuma = slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getBitDepth(CHANNEL_TYPE_LUMA); |
---|
| 457 | const Int delta = bitDepthLuma - refBitDepthLuma; |
---|
| 458 | |
---|
[1202] | 459 | // jonint upsampling bitshift |
---|
[1287] | 460 | refAC <<= delta; |
---|
| 461 | refDC <<= delta; |
---|
[494] | 462 | } |
---|
[1029] | 463 | #else |
---|
| 464 | const Int64 refDC = refWeightACDCParam[comp].iDC; |
---|
| 465 | const Int64 refAC = refWeightACDCParam[comp].iAC; |
---|
[494] | 466 | #endif |
---|
[313] | 467 | |
---|
| 468 | // calculating iWeight and iOffset params |
---|
[1201] | 469 | #if SVC_EXTENSION |
---|
[313] | 470 | Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) ); |
---|
[1029] | 471 | Int weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) ); |
---|
| 472 | Int offset = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom ); |
---|
| 473 | |
---|
[494] | 474 | if( !validILRPic ) |
---|
| 475 | { |
---|
| 476 | dWeight = 1; |
---|
| 477 | offset = 0; |
---|
| 478 | } |
---|
| 479 | weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) ); |
---|
[1029] | 480 | #else |
---|
| 481 | const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) ); |
---|
| 482 | const Int weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) ); |
---|
| 483 | const Int offset = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom ); |
---|
[494] | 484 | #endif |
---|
[313] | 485 | |
---|
[1029] | 486 | Int clippedOffset; |
---|
| 487 | if(isChroma(compID)) // Chroma offset range limination |
---|
[313] | 488 | { |
---|
[1029] | 489 | const Int pred = ( range - ( ( range*weight)>>(log2Denom) ) ); |
---|
| 490 | const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit |
---|
| 491 | |
---|
| 492 | clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) ); // signed 8bit |
---|
[313] | 493 | } |
---|
[1029] | 494 | else // Luma offset range limitation |
---|
[313] | 495 | { |
---|
[1029] | 496 | clippedOffset = Clip3( -range, range-1, offset); |
---|
[313] | 497 | } |
---|
| 498 | |
---|
| 499 | // Weighting factor limitation |
---|
[1029] | 500 | const Int defaultWeight = (1<<log2Denom); |
---|
[1392] | 501 | const Int deltaWeight = (weight - defaultWeight); |
---|
[1029] | 502 | |
---|
| 503 | if(deltaWeight >= range || deltaWeight < -range) |
---|
[1246] | 504 | { |
---|
[1029] | 505 | return false; |
---|
[1246] | 506 | } |
---|
[1029] | 507 | |
---|
[1201] | 508 | #if SVC_EXTENSION |
---|
[494] | 509 | // make sure the reference frames other than ILR are not using weighted prediction |
---|
| 510 | else |
---|
| 511 | if( !validILRPic ) |
---|
| 512 | { |
---|
| 513 | continue; |
---|
| 514 | } |
---|
| 515 | #endif |
---|
[313] | 516 | |
---|
[1029] | 517 | m_wp[refList][refIdxTemp][comp].bPresentFlag = true; |
---|
| 518 | m_wp[refList][refIdxTemp][comp].iWeight = weight; |
---|
| 519 | m_wp[refList][refIdxTemp][comp].iOffset = clippedOffset; |
---|
| 520 | m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom; |
---|
[313] | 521 | } |
---|
| 522 | } |
---|
| 523 | } |
---|
[1029] | 524 | return true; |
---|
[313] | 525 | } |
---|
| 526 | |
---|
[1029] | 527 | |
---|
[1400] | 528 | /** select whether weighted pred enables or not. |
---|
| 529 | * \param TComSlice *slice |
---|
| 530 | * \param log2Denom |
---|
| 531 | * \returns Bool |
---|
| 532 | */ |
---|
| 533 | Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram) |
---|
| 534 | { |
---|
| 535 | const TComPicYuv *const pPic = slice->getPic()->getPicYuvOrg(); |
---|
| 536 | const Int defaultWeight = 1<<log2Denom; |
---|
| 537 | const Int numPredDir = slice->isInterP() ? 1 : 2; |
---|
| 538 | const Bool useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); |
---|
| 539 | |
---|
| 540 | assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); |
---|
| 541 | |
---|
| 542 | for ( Int refList = 0; refList < numPredDir; refList++ ) |
---|
| 543 | { |
---|
| 544 | const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); |
---|
| 545 | |
---|
| 546 | for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) |
---|
| 547 | { |
---|
| 548 | Bool useChromaWeight = false; |
---|
| 549 | |
---|
| 550 | for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++) |
---|
| 551 | { |
---|
| 552 | const ComponentID compID = ComponentID(comp); |
---|
| 553 | const Pel *pOrg = pPic->getAddr(compID); |
---|
| 554 | const Pel *pRef = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID); |
---|
| 555 | const Int orgStride = pPic->getStride(compID); |
---|
| 556 | const Int refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID); |
---|
| 557 | const Int width = pPic->getWidth(compID); |
---|
| 558 | const Int height = pPic->getHeight(compID); |
---|
| 559 | #if SVC_EXTENSION |
---|
| 560 | const Int bitDepth = slice->getBitDepth(toChannelType(compID)); |
---|
| 561 | #else |
---|
| 562 | const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); |
---|
| 563 | #endif |
---|
| 564 | WPScalingParam &wp = m_wp[refList][refIdxTemp][compID]; |
---|
| 565 | Int weight = wp.iWeight; |
---|
| 566 | Int offset = wp.iOffset; |
---|
| 567 | Int weightDef = defaultWeight; |
---|
| 568 | Int offsetDef = 0; |
---|
| 569 | |
---|
| 570 | // calculate SAD costs with/without wp for luma |
---|
| 571 | const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP); |
---|
| 572 | if (SADnoWP > 0) |
---|
| 573 | { |
---|
| 574 | const Int64 SADWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision, bClipInitialSADWP); |
---|
| 575 | const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP; |
---|
| 576 | Double dRatioSr0SAD = std::numeric_limits<Double>::max(); |
---|
| 577 | Double dRatioSrSAD = std::numeric_limits<Double>::max(); |
---|
| 578 | |
---|
| 579 | if (bUseHistogram) |
---|
| 580 | { |
---|
| 581 | std::vector<Int> histogramOrg;// = pPic->getHistogram(compID); |
---|
| 582 | std::vector<Int> histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID); |
---|
| 583 | std::vector<Int> searchedHistogram; |
---|
| 584 | |
---|
| 585 | // Compute histograms |
---|
| 586 | xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth); |
---|
| 587 | xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth); |
---|
| 588 | |
---|
| 589 | // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded |
---|
| 590 | xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID); |
---|
| 591 | // calculate updated WP SAD |
---|
| 592 | const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision); |
---|
| 593 | dRatioSrSAD = (Double)SADSrWP / (Double)SADnoWP; |
---|
| 594 | |
---|
| 595 | if (bDoEnhancement) |
---|
| 596 | { |
---|
| 597 | // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded |
---|
| 598 | xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID); |
---|
| 599 | // calculate updated WP SAD |
---|
| 600 | const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision); |
---|
| 601 | dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP; |
---|
| 602 | } |
---|
| 603 | } |
---|
| 604 | |
---|
| 605 | if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD) |
---|
| 606 | { |
---|
| 607 | wp.bPresentFlag = false; |
---|
| 608 | wp.iOffset = 0; |
---|
| 609 | wp.iWeight = defaultWeight; |
---|
| 610 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 611 | } |
---|
| 612 | else |
---|
| 613 | { |
---|
| 614 | if (compID != COMPONENT_Y) |
---|
| 615 | { |
---|
| 616 | useChromaWeight = true; |
---|
| 617 | } |
---|
| 618 | |
---|
| 619 | if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD) |
---|
| 620 | { |
---|
| 621 | wp.bPresentFlag = true; |
---|
| 622 | wp.iOffset = offsetDef; |
---|
| 623 | wp.iWeight = weightDef; |
---|
| 624 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 625 | } |
---|
| 626 | else if (dRatioSrSAD < dRatioSAD) |
---|
| 627 | { |
---|
| 628 | wp.bPresentFlag = true; |
---|
| 629 | wp.iOffset = offset; |
---|
| 630 | wp.iWeight = weight; |
---|
| 631 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 632 | } |
---|
| 633 | } |
---|
| 634 | } |
---|
| 635 | else // (SADnoWP <= 0) |
---|
| 636 | { |
---|
| 637 | wp.bPresentFlag = false; |
---|
| 638 | wp.iOffset = 0; |
---|
| 639 | wp.iWeight = defaultWeight; |
---|
| 640 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 641 | } |
---|
| 642 | } |
---|
| 643 | |
---|
| 644 | for(Int comp=1; comp<pPic->getNumberValidComponents(); comp++) |
---|
| 645 | { |
---|
| 646 | m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight; |
---|
| 647 | } |
---|
| 648 | } |
---|
| 649 | } |
---|
| 650 | |
---|
| 651 | return true; |
---|
| 652 | } |
---|
| 653 | |
---|
[1260] | 654 | //! select whether weighted pred enables or not. |
---|
[1029] | 655 | Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom) |
---|
[313] | 656 | { |
---|
[1029] | 657 | TComPicYuv *const pPic = slice->getPic()->getPicYuvOrg(); |
---|
[1400] | 658 | const Int defaultWeight = 1<<log2Denom; |
---|
| 659 | const Int numPredDir = slice->isInterP() ? 1 : 2; |
---|
[1316] | 660 | const Bool useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); |
---|
[313] | 661 | |
---|
[1400] | 662 | assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); |
---|
[1029] | 663 | |
---|
[1400] | 664 | for ( Int refList = 0; refList < numPredDir; refList++ ) |
---|
[313] | 665 | { |
---|
[1400] | 666 | const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); |
---|
[1029] | 667 | |
---|
[1400] | 668 | for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) |
---|
[313] | 669 | { |
---|
[1400] | 670 | Int64 SADWP = 0, SADnoWP = 0; |
---|
[313] | 671 | |
---|
[1029] | 672 | for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++) |
---|
| 673 | { |
---|
| 674 | const ComponentID compID = ComponentID(comp); |
---|
| 675 | Pel *pOrg = pPic->getAddr(compID); |
---|
[1400] | 676 | Pel *pRef = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID); |
---|
| 677 | const Int orgStride = pPic->getStride(compID); |
---|
| 678 | const Int refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID); |
---|
| 679 | const Int width = pPic->getWidth(compID); |
---|
| 680 | const Int height = pPic->getHeight(compID); |
---|
[1287] | 681 | #if SVC_EXTENSION |
---|
| 682 | const Int bitDepth = slice->getBitDepth(toChannelType(compID)); |
---|
| 683 | #else |
---|
| 684 | const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); |
---|
| 685 | #endif |
---|
[313] | 686 | |
---|
[1029] | 687 | // calculate SAD costs with/without wp for luma |
---|
[1400] | 688 | SADWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting); |
---|
| 689 | SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting); |
---|
[1029] | 690 | } |
---|
[313] | 691 | |
---|
[1400] | 692 | const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits<Double>::max(); |
---|
| 693 | if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD) |
---|
[313] | 694 | { |
---|
[1029] | 695 | for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++) |
---|
[313] | 696 | { |
---|
[1400] | 697 | WPScalingParam &wp=m_wp[refList][refIdxTemp][comp]; |
---|
| 698 | wp.bPresentFlag = false; |
---|
| 699 | wp.iOffset = 0; |
---|
| 700 | wp.iWeight = defaultWeight; |
---|
| 701 | wp.uiLog2WeightDenom = log2Denom; |
---|
[313] | 702 | } |
---|
| 703 | } |
---|
| 704 | } |
---|
| 705 | } |
---|
| 706 | |
---|
[1029] | 707 | return true; |
---|
[313] | 708 | } |
---|
| 709 | |
---|
[1409] | 710 | // Alternatively, a SSE-based measure could be used instead. |
---|
| 711 | // The respective function has been removed as it currently redundant. |
---|
[1400] | 712 | static |
---|
| 713 | Int64 xCalcSADvalueWP(const Int bitDepth, |
---|
| 714 | const Pel *pOrgPel, |
---|
| 715 | const Pel *pRefPel, |
---|
| 716 | const Int width, |
---|
| 717 | const Int height, |
---|
| 718 | const Int orgStride, |
---|
| 719 | const Int refStride, |
---|
| 720 | const Int log2Denom, |
---|
| 721 | const Int weight, |
---|
| 722 | const Int offset, |
---|
| 723 | const Bool useHighPrecision) |
---|
[313] | 724 | { |
---|
[1400] | 725 | //const Int64 iSize = iWidth*iHeight; |
---|
| 726 | const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8)); |
---|
| 727 | const Int64 realOffset = ((Int64)offset)<<realLog2Denom; |
---|
[1029] | 728 | |
---|
[1400] | 729 | Int64 SAD = 0; |
---|
| 730 | for( Int y = 0; y < height; y++ ) |
---|
[313] | 731 | { |
---|
[1400] | 732 | for( Int x = 0; x < width; x++ ) |
---|
[313] | 733 | { |
---|
[1400] | 734 | SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) ); |
---|
[313] | 735 | } |
---|
[1400] | 736 | pOrgPel += orgStride; |
---|
| 737 | pRefPel += refStride; |
---|
[313] | 738 | } |
---|
[1029] | 739 | |
---|
[1400] | 740 | //return (iSAD/iSize); |
---|
| 741 | return SAD; |
---|
[313] | 742 | } |
---|
[1400] | 743 | |
---|
| 744 | static |
---|
| 745 | Int64 xCalcSADvalueWPOptionalClip(const Int bitDepth, |
---|
| 746 | const Pel *pOrgPel, |
---|
| 747 | const Pel *pRefPel, |
---|
| 748 | const Int width, |
---|
| 749 | const Int height, |
---|
| 750 | const Int orgStride, |
---|
| 751 | const Int refStride, |
---|
| 752 | const Int log2Denom, |
---|
| 753 | const Int weight, |
---|
| 754 | const Int offset, |
---|
| 755 | const Bool useHighPrecision, |
---|
| 756 | const Bool clipped) |
---|
| 757 | { |
---|
| 758 | Int64 SAD = 0; |
---|
| 759 | if (clipped) |
---|
| 760 | { |
---|
| 761 | const Int64 realLog2Denom = useHighPrecision ? 0 : (bitDepth - 8); |
---|
| 762 | const Int64 realOffset = (Int64)offset<<realLog2Denom; |
---|
| 763 | const Int64 roundOffset = (log2Denom == 0) ? 0 : 1 << (log2Denom - 1); |
---|
| 764 | const Int64 minValue = 0; |
---|
| 765 | const Int64 maxValue = (1 << bitDepth) - 1; |
---|
| 766 | |
---|
| 767 | for( Int y = 0; y < height; y++ ) |
---|
| 768 | { |
---|
| 769 | for( Int x = 0; x < width; x++ ) |
---|
| 770 | { |
---|
| 771 | Int64 scaledValue = Clip3(minValue, maxValue, ((((Int64) pRefPel[x] * (Int64) weight + roundOffset) ) >> (Int64) log2Denom) + realOffset); |
---|
| 772 | SAD += abs((Int64)pOrgPel[x] - scaledValue); |
---|
| 773 | } |
---|
| 774 | pOrgPel += orgStride; |
---|
| 775 | pRefPel += refStride; |
---|
| 776 | } |
---|
| 777 | } |
---|
| 778 | else |
---|
| 779 | { |
---|
| 780 | //const Int64 iSize = iWidth*iHeight; |
---|
| 781 | const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8)); |
---|
| 782 | const Int64 realOffset = ((Int64)offset)<<realLog2Denom; |
---|
| 783 | |
---|
| 784 | for( Int y = 0; y < height; y++ ) |
---|
| 785 | { |
---|
| 786 | for( Int x = 0; x < width; x++ ) |
---|
| 787 | { |
---|
| 788 | SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) ); |
---|
| 789 | } |
---|
| 790 | pOrgPel += orgStride; |
---|
| 791 | pRefPel += refStride; |
---|
| 792 | } |
---|
| 793 | } |
---|
| 794 | return SAD; |
---|
| 795 | } |
---|