[5] | 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 |
---|
[1313] | 4 | * granted under this license. |
---|
[5] | 5 | * |
---|
[1413] | 6 | * Copyright (c) 2010-2017, ITU/ISO/IEC |
---|
[5] | 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. |
---|
[56] | 17 | * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may |
---|
[5] | 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 | */ |
---|
[2] | 33 | |
---|
[608] | 34 | /** \file WeightPredAnalysis.cpp |
---|
| 35 | \brief weighted prediction encoder class |
---|
[2] | 36 | */ |
---|
| 37 | |
---|
[1313] | 38 | #include "../TLibCommon/CommonDef.h" |
---|
[2] | 39 | #include "../TLibCommon/TComSlice.h" |
---|
| 40 | #include "../TLibCommon/TComPic.h" |
---|
| 41 | #include "../TLibCommon/TComPicYuv.h" |
---|
| 42 | #include "WeightPredAnalysis.h" |
---|
[1386] | 43 | #include <limits> |
---|
[2] | 44 | |
---|
[1386] | 45 | static const Double WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD=0.99; // NOTE: U0040 used 0.95 |
---|
[2] | 46 | |
---|
[1386] | 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 | |
---|
| 169 | Distortion minDistortion = std::numeric_limits<Distortion>::max(); |
---|
| 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 | |
---|
[2] | 226 | WeightPredAnalysis::WeightPredAnalysis() |
---|
| 227 | { |
---|
[1313] | 228 | for ( UInt lst =0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ ) |
---|
[56] | 229 | { |
---|
[1386] | 230 | for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ ) |
---|
[56] | 231 | { |
---|
[1313] | 232 | for ( Int comp=0 ; comp<MAX_NUM_COMPONENT ;comp++ ) |
---|
[56] | 233 | { |
---|
[1386] | 234 | WPScalingParam *pwp = &(m_wp[lst][refIdx][comp]); |
---|
[2] | 235 | pwp->bPresentFlag = false; |
---|
| 236 | pwp->uiLog2WeightDenom = 0; |
---|
| 237 | pwp->iWeight = 1; |
---|
| 238 | pwp->iOffset = 0; |
---|
| 239 | } |
---|
| 240 | } |
---|
[56] | 241 | } |
---|
[2] | 242 | } |
---|
| 243 | |
---|
[1313] | 244 | |
---|
| 245 | //! calculate AC and DC values for current original image |
---|
| 246 | Void WeightPredAnalysis::xCalcACDCParamSlice(TComSlice *const slice) |
---|
[2] | 247 | { |
---|
| 248 | //===== calculate AC/DC value ===== |
---|
| 249 | TComPicYuv* pPic = slice->getPic()->getPicYuvOrg(); |
---|
| 250 | |
---|
[1313] | 251 | WPACDCParam weightACDCParam[MAX_NUM_COMPONENT]; |
---|
[2] | 252 | |
---|
[1313] | 253 | for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) |
---|
| 254 | { |
---|
| 255 | const ComponentID compID = ComponentID(componentIndex); |
---|
[2] | 256 | |
---|
[1313] | 257 | // calculate DC/AC value for channel |
---|
[2] | 258 | |
---|
[1386] | 259 | const Int stride = pPic->getStride(compID); |
---|
| 260 | const Int width = pPic->getWidth(compID); |
---|
| 261 | const Int height = pPic->getHeight(compID); |
---|
[2] | 262 | |
---|
[1386] | 263 | const Int sample = width*height; |
---|
[1313] | 264 | |
---|
[1386] | 265 | Int64 orgDC = 0; |
---|
[1313] | 266 | { |
---|
| 267 | const Pel *pPel = pPic->getAddr(compID); |
---|
| 268 | |
---|
[1386] | 269 | for(Int y = 0; y < height; y++, pPel+=stride ) |
---|
[1313] | 270 | { |
---|
[1386] | 271 | for(Int x = 0; x < width; x++ ) |
---|
[1313] | 272 | { |
---|
[1386] | 273 | orgDC += (Int)( pPel[x] ); |
---|
[1313] | 274 | } |
---|
| 275 | } |
---|
| 276 | } |
---|
| 277 | |
---|
[1386] | 278 | const Int64 orgNormDC = ((orgDC+(sample>>1)) / sample); |
---|
[1313] | 279 | |
---|
[1386] | 280 | Int64 orgAC = 0; |
---|
[1313] | 281 | { |
---|
| 282 | const Pel *pPel = pPic->getAddr(compID); |
---|
| 283 | |
---|
[1386] | 284 | for(Int y = 0; y < height; y++, pPel += stride ) |
---|
[1313] | 285 | { |
---|
[1386] | 286 | for(Int x = 0; x < width; x++ ) |
---|
[1313] | 287 | { |
---|
[1386] | 288 | orgAC += abs( (Int)pPel[x] - (Int)orgNormDC ); |
---|
[1313] | 289 | } |
---|
| 290 | } |
---|
| 291 | } |
---|
| 292 | |
---|
| 293 | const Int fixedBitShift = (slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag())?RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION:0; |
---|
[1386] | 294 | weightACDCParam[compID].iDC = (((orgDC<<fixedBitShift)+(sample>>1)) / sample); |
---|
| 295 | weightACDCParam[compID].iAC = orgAC; |
---|
[1313] | 296 | } |
---|
| 297 | |
---|
[2] | 298 | slice->setWpAcDcParam(weightACDCParam); |
---|
| 299 | } |
---|
[56] | 300 | |
---|
| 301 | |
---|
[1313] | 302 | //! check weighted pred or non-weighted pred |
---|
| 303 | Void WeightPredAnalysis::xCheckWPEnable(TComSlice *const slice) |
---|
[56] | 304 | { |
---|
[1313] | 305 | const TComPicYuv *pPic = slice->getPic()->getPicYuvOrg(); |
---|
[56] | 306 | |
---|
[1386] | 307 | Int presentCnt = 0; |
---|
[1313] | 308 | for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ ) |
---|
[56] | 309 | { |
---|
[1386] | 310 | for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ ) |
---|
[56] | 311 | { |
---|
[1313] | 312 | for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) |
---|
[56] | 313 | { |
---|
[1386] | 314 | WPScalingParam *pwp = &(m_wp[lst][refIdx][componentIndex]); |
---|
| 315 | presentCnt += (Int)pwp->bPresentFlag; |
---|
[56] | 316 | } |
---|
| 317 | } |
---|
| 318 | } |
---|
| 319 | |
---|
[1386] | 320 | if(presentCnt==0) |
---|
[56] | 321 | { |
---|
[1313] | 322 | slice->setTestWeightPred(false); |
---|
| 323 | slice->setTestWeightBiPred(false); |
---|
| 324 | |
---|
| 325 | for ( UInt lst=0 ; lst<NUM_REF_PIC_LIST_01 ; lst++ ) |
---|
[56] | 326 | { |
---|
[1386] | 327 | for ( Int refIdx=0 ; refIdx<MAX_NUM_REF ; refIdx++ ) |
---|
[56] | 328 | { |
---|
[1313] | 329 | for(Int componentIndex = 0; componentIndex < pPic->getNumberValidComponents(); componentIndex++) |
---|
[56] | 330 | { |
---|
[1386] | 331 | WPScalingParam *pwp = &(m_wp[lst][refIdx][componentIndex]); |
---|
[1313] | 332 | |
---|
[56] | 333 | pwp->bPresentFlag = false; |
---|
| 334 | pwp->uiLog2WeightDenom = 0; |
---|
| 335 | pwp->iWeight = 1; |
---|
| 336 | pwp->iOffset = 0; |
---|
| 337 | } |
---|
| 338 | } |
---|
| 339 | } |
---|
| 340 | slice->setWpScaling( m_wp ); |
---|
| 341 | } |
---|
[1313] | 342 | else |
---|
| 343 | { |
---|
[1386] | 344 | slice->setTestWeightPred (slice->getPPS()->getUseWP()); |
---|
[1313] | 345 | slice->setTestWeightBiPred(slice->getPPS()->getWPBiPred()); |
---|
| 346 | } |
---|
[56] | 347 | } |
---|
| 348 | |
---|
[1313] | 349 | |
---|
| 350 | //! estimate wp tables for explicit wp |
---|
[1386] | 351 | Void WeightPredAnalysis::xEstimateWPParamSlice(TComSlice *const slice, const WeightedPredictionMethod method) |
---|
[2] | 352 | { |
---|
[1313] | 353 | Int iDenom = 6; |
---|
[608] | 354 | Bool validRangeFlag = false; |
---|
[2] | 355 | |
---|
| 356 | if(slice->getNumRefIdx(REF_PIC_LIST_0)>3) |
---|
| 357 | { |
---|
[1313] | 358 | iDenom = 7; |
---|
[2] | 359 | } |
---|
[608] | 360 | |
---|
| 361 | do |
---|
| 362 | { |
---|
[1313] | 363 | validRangeFlag = xUpdatingWPParameters(slice, iDenom); |
---|
[608] | 364 | if (!validRangeFlag) |
---|
| 365 | { |
---|
| 366 | iDenom--; // decrement to satisfy the range limitation |
---|
| 367 | } |
---|
| 368 | } while (validRangeFlag == false); |
---|
| 369 | |
---|
[1313] | 370 | // selecting whether WP is used, or not (fast search) |
---|
| 371 | // NOTE: This is not operating on a slice, but the entire picture. |
---|
[1386] | 372 | switch (method) |
---|
| 373 | { |
---|
| 374 | case WP_PER_PICTURE_WITH_SIMPLE_DC_COMBINED_COMPONENT: |
---|
| 375 | xSelectWP(slice, iDenom); |
---|
| 376 | break; |
---|
| 377 | case WP_PER_PICTURE_WITH_SIMPLE_DC_PER_COMPONENT: |
---|
| 378 | xSelectWPHistExtClip(slice, iDenom, false, false, false); |
---|
| 379 | break; |
---|
| 380 | case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT: |
---|
| 381 | xSelectWPHistExtClip(slice, iDenom, false, false, true); |
---|
| 382 | break; |
---|
| 383 | case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING: |
---|
| 384 | xSelectWPHistExtClip(slice, iDenom, false, true, true); |
---|
| 385 | break; |
---|
| 386 | case WP_PER_PICTURE_WITH_HISTOGRAM_AND_PER_COMPONENT_AND_CLIPPING_AND_EXTENSION: |
---|
| 387 | xSelectWPHistExtClip(slice, iDenom, true, true, true); |
---|
| 388 | break; |
---|
| 389 | default: |
---|
| 390 | assert(0); |
---|
| 391 | exit(1); |
---|
| 392 | } |
---|
[1313] | 393 | |
---|
[608] | 394 | slice->setWpScaling( m_wp ); |
---|
| 395 | } |
---|
| 396 | |
---|
[1313] | 397 | |
---|
| 398 | //! update wp tables for explicit wp w.r.t range limitation |
---|
| 399 | Bool WeightPredAnalysis::xUpdatingWPParameters(TComSlice *const slice, const Int log2Denom) |
---|
[608] | 400 | { |
---|
[1313] | 401 | const Int numComp = slice->getPic()->getPicYuvOrg()->getNumberValidComponents(); |
---|
| 402 | const Bool bUseHighPrecisionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); |
---|
| 403 | const Int numPredDir = slice->isInterP() ? 1 : 2; |
---|
| 404 | |
---|
| 405 | assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); |
---|
| 406 | |
---|
[608] | 407 | for ( Int refList = 0; refList < numPredDir; refList++ ) |
---|
[2] | 408 | { |
---|
[1313] | 409 | const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); |
---|
| 410 | |
---|
[608] | 411 | for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) |
---|
[2] | 412 | { |
---|
[1313] | 413 | WPACDCParam *currWeightACDCParam, *refWeightACDCParam; |
---|
[608] | 414 | slice->getWpAcDcParam(currWeightACDCParam); |
---|
| 415 | slice->getRefPic(eRefPicList, refIdxTemp)->getSlice(0)->getWpAcDcParam(refWeightACDCParam); |
---|
[2] | 416 | |
---|
[1313] | 417 | for ( Int comp = 0; comp < numComp; comp++ ) |
---|
[2] | 418 | { |
---|
[1313] | 419 | const ComponentID compID = ComponentID(comp); |
---|
| 420 | const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); |
---|
| 421 | const Int range = bUseHighPrecisionWeighting ? (1<<bitDepth)/2 : 128; |
---|
| 422 | const Int realLog2Denom = log2Denom + (bUseHighPrecisionWeighting ? RExt__PREDICTION_WEIGHTING_ANALYSIS_DC_PRECISION : (bitDepth - 8)); |
---|
| 423 | const Int realOffset = ((Int)1<<(realLog2Denom-1)); |
---|
[608] | 424 | |
---|
[2] | 425 | // current frame |
---|
[1313] | 426 | const Int64 currDC = currWeightACDCParam[comp].iDC; |
---|
| 427 | const Int64 currAC = currWeightACDCParam[comp].iAC; |
---|
[2] | 428 | // reference frame |
---|
[1313] | 429 | const Int64 refDC = refWeightACDCParam[comp].iDC; |
---|
| 430 | const Int64 refAC = refWeightACDCParam[comp].iAC; |
---|
[2] | 431 | |
---|
[56] | 432 | // calculating iWeight and iOffset params |
---|
[1313] | 433 | const Double dWeight = (refAC==0) ? (Double)1.0 : Clip3( -16.0, 15.0, ((Double)currAC / (Double)refAC) ); |
---|
| 434 | const Int weight = (Int)( 0.5 + dWeight * (Double)(1<<log2Denom) ); |
---|
| 435 | const Int offset = (Int)( ((currDC<<log2Denom) - ((Int64)weight * refDC) + (Int64)realOffset) >> realLog2Denom ); |
---|
[2] | 436 | |
---|
[1313] | 437 | Int clippedOffset; |
---|
| 438 | if(isChroma(compID)) // Chroma offset range limination |
---|
[608] | 439 | { |
---|
[1313] | 440 | const Int pred = ( range - ( ( range*weight)>>(log2Denom) ) ); |
---|
| 441 | const Int deltaOffset = Clip3( -4*range, 4*range-1, (offset - pred) ); // signed 10bit |
---|
| 442 | |
---|
| 443 | clippedOffset = Clip3( -range, range-1, (deltaOffset + pred) ); // signed 8bit |
---|
[608] | 444 | } |
---|
[1313] | 445 | else // Luma offset range limitation |
---|
[608] | 446 | { |
---|
[1313] | 447 | clippedOffset = Clip3( -range, range-1, offset); |
---|
[608] | 448 | } |
---|
| 449 | |
---|
| 450 | // Weighting factor limitation |
---|
[1313] | 451 | const Int defaultWeight = (1<<log2Denom); |
---|
[1386] | 452 | const Int deltaWeight = (weight - defaultWeight); |
---|
[608] | 453 | |
---|
[1313] | 454 | if(deltaWeight >= range || deltaWeight < -range) |
---|
| 455 | { |
---|
| 456 | return false; |
---|
| 457 | } |
---|
| 458 | |
---|
| 459 | m_wp[refList][refIdxTemp][comp].bPresentFlag = true; |
---|
| 460 | m_wp[refList][refIdxTemp][comp].iWeight = weight; |
---|
| 461 | m_wp[refList][refIdxTemp][comp].iOffset = clippedOffset; |
---|
| 462 | m_wp[refList][refIdxTemp][comp].uiLog2WeightDenom = log2Denom; |
---|
[2] | 463 | } |
---|
| 464 | } |
---|
| 465 | } |
---|
[1313] | 466 | return true; |
---|
[2] | 467 | } |
---|
[56] | 468 | |
---|
[1313] | 469 | |
---|
[1386] | 470 | /** select whether weighted pred enables or not. |
---|
| 471 | * \param TComSlice *slice |
---|
| 472 | * \param log2Denom |
---|
| 473 | * \returns Bool |
---|
| 474 | */ |
---|
| 475 | Bool WeightPredAnalysis::xSelectWPHistExtClip(TComSlice *const slice, const Int log2Denom, const Bool bDoEnhancement, const Bool bClipInitialSADWP, const Bool bUseHistogram) |
---|
| 476 | { |
---|
| 477 | const TComPicYuv *const pPic = slice->getPic()->getPicYuvOrg(); |
---|
| 478 | const Int defaultWeight = 1<<log2Denom; |
---|
| 479 | const Int numPredDir = slice->isInterP() ? 1 : 2; |
---|
| 480 | const Bool useHighPrecision = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); |
---|
| 481 | |
---|
| 482 | assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); |
---|
| 483 | |
---|
| 484 | for ( Int refList = 0; refList < numPredDir; refList++ ) |
---|
| 485 | { |
---|
| 486 | const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); |
---|
| 487 | |
---|
| 488 | for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) |
---|
| 489 | { |
---|
| 490 | Bool useChromaWeight = false; |
---|
| 491 | |
---|
| 492 | for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++) |
---|
| 493 | { |
---|
| 494 | const ComponentID compID = ComponentID(comp); |
---|
| 495 | const Pel *pOrg = pPic->getAddr(compID); |
---|
| 496 | const Pel *pRef = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID); |
---|
| 497 | const Int orgStride = pPic->getStride(compID); |
---|
| 498 | const Int refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID); |
---|
| 499 | const Int width = pPic->getWidth(compID); |
---|
| 500 | const Int height = pPic->getHeight(compID); |
---|
| 501 | const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); |
---|
| 502 | WPScalingParam &wp = m_wp[refList][refIdxTemp][compID]; |
---|
| 503 | Int weight = wp.iWeight; |
---|
| 504 | Int offset = wp.iOffset; |
---|
| 505 | Int weightDef = defaultWeight; |
---|
| 506 | Int offsetDef = 0; |
---|
| 507 | |
---|
| 508 | // calculate SAD costs with/without wp for luma |
---|
| 509 | const Int64 SADnoWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecision, bClipInitialSADWP); |
---|
| 510 | if (SADnoWP > 0) |
---|
| 511 | { |
---|
| 512 | const Int64 SADWP = xCalcSADvalueWPOptionalClip(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision, bClipInitialSADWP); |
---|
| 513 | const Double dRatioSAD = (Double)SADWP / (Double)SADnoWP; |
---|
| 514 | Double dRatioSr0SAD = std::numeric_limits<Double>::max(); |
---|
| 515 | Double dRatioSrSAD = std::numeric_limits<Double>::max(); |
---|
| 516 | |
---|
| 517 | if (bUseHistogram) |
---|
| 518 | { |
---|
| 519 | std::vector<Int> histogramOrg;// = pPic->getHistogram(compID); |
---|
| 520 | std::vector<Int> histogramRef;// = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getHistogram(compID); |
---|
| 521 | std::vector<Int> searchedHistogram; |
---|
| 522 | |
---|
| 523 | // Compute histograms |
---|
| 524 | xCalcHistogram(pOrg, histogramOrg, width, height, orgStride, 1 << bitDepth); |
---|
| 525 | xCalcHistogram(pRef, histogramRef, width, height, refStride, 1 << bitDepth); |
---|
| 526 | |
---|
| 527 | // Do a histogram search around DC WP parameters; resulting distortion and 'searchedHistogram' is discarded |
---|
| 528 | xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weight, offset, useHighPrecision, compID); |
---|
| 529 | // calculate updated WP SAD |
---|
| 530 | const Int64 SADSrWP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weight, offset, useHighPrecision); |
---|
| 531 | dRatioSrSAD = (Double)SADSrWP / (Double)SADnoWP; |
---|
| 532 | |
---|
| 533 | if (bDoEnhancement) |
---|
| 534 | { |
---|
| 535 | // Do the same around the default ones; resulting distortion and 'searchedHistogram' is discarded |
---|
| 536 | xSearchHistogram(histogramOrg, histogramRef, searchedHistogram, bitDepth, log2Denom, weightDef, offsetDef, useHighPrecision, compID); |
---|
| 537 | // calculate updated WP SAD |
---|
| 538 | const Int64 SADSr0WP = xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, weightDef, offsetDef, useHighPrecision); |
---|
| 539 | dRatioSr0SAD = (Double)SADSr0WP / (Double)SADnoWP; |
---|
| 540 | } |
---|
| 541 | } |
---|
| 542 | |
---|
| 543 | if(min(dRatioSr0SAD, min(dRatioSAD, dRatioSrSAD)) >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD) |
---|
| 544 | { |
---|
| 545 | wp.bPresentFlag = false; |
---|
| 546 | wp.iOffset = 0; |
---|
| 547 | wp.iWeight = defaultWeight; |
---|
| 548 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 549 | } |
---|
| 550 | else |
---|
| 551 | { |
---|
| 552 | if (compID != COMPONENT_Y) |
---|
| 553 | { |
---|
| 554 | useChromaWeight = true; |
---|
| 555 | } |
---|
| 556 | |
---|
| 557 | if (dRatioSr0SAD < dRatioSrSAD && dRatioSr0SAD < dRatioSAD) |
---|
| 558 | { |
---|
| 559 | wp.bPresentFlag = true; |
---|
| 560 | wp.iOffset = offsetDef; |
---|
| 561 | wp.iWeight = weightDef; |
---|
| 562 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 563 | } |
---|
| 564 | else if (dRatioSrSAD < dRatioSAD) |
---|
| 565 | { |
---|
| 566 | wp.bPresentFlag = true; |
---|
| 567 | wp.iOffset = offset; |
---|
| 568 | wp.iWeight = weight; |
---|
| 569 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 570 | } |
---|
| 571 | } |
---|
| 572 | } |
---|
| 573 | else // (SADnoWP <= 0) |
---|
| 574 | { |
---|
| 575 | wp.bPresentFlag = false; |
---|
| 576 | wp.iOffset = 0; |
---|
| 577 | wp.iWeight = defaultWeight; |
---|
| 578 | wp.uiLog2WeightDenom = log2Denom; |
---|
| 579 | } |
---|
| 580 | } |
---|
| 581 | |
---|
| 582 | for(Int comp=1; comp<pPic->getNumberValidComponents(); comp++) |
---|
| 583 | { |
---|
| 584 | m_wp[refList][refIdxTemp][comp].bPresentFlag = useChromaWeight; |
---|
| 585 | } |
---|
| 586 | } |
---|
| 587 | } |
---|
| 588 | |
---|
| 589 | return true; |
---|
| 590 | } |
---|
| 591 | |
---|
[1313] | 592 | //! select whether weighted pred enables or not. |
---|
| 593 | Bool WeightPredAnalysis::xSelectWP(TComSlice *const slice, const Int log2Denom) |
---|
[2] | 594 | { |
---|
[1313] | 595 | TComPicYuv *const pPic = slice->getPic()->getPicYuvOrg(); |
---|
[1386] | 596 | const Int defaultWeight = 1<<log2Denom; |
---|
| 597 | const Int numPredDir = slice->isInterP() ? 1 : 2; |
---|
[1313] | 598 | const Bool useHighPrecisionPredictionWeighting = slice->getSPS()->getSpsRangeExtension().getHighPrecisionOffsetsEnabledFlag(); |
---|
[2] | 599 | |
---|
[1386] | 600 | assert (numPredDir <= Int(NUM_REF_PIC_LIST_01)); |
---|
[1313] | 601 | |
---|
[1386] | 602 | for ( Int refList = 0; refList < numPredDir; refList++ ) |
---|
[2] | 603 | { |
---|
[1386] | 604 | const RefPicList eRefPicList = ( refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); |
---|
[1313] | 605 | |
---|
[1386] | 606 | for ( Int refIdxTemp = 0; refIdxTemp < slice->getNumRefIdx(eRefPicList); refIdxTemp++ ) |
---|
[2] | 607 | { |
---|
[1386] | 608 | Int64 SADWP = 0, SADnoWP = 0; |
---|
[2] | 609 | |
---|
[1313] | 610 | for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++) |
---|
| 611 | { |
---|
| 612 | const ComponentID compID = ComponentID(comp); |
---|
| 613 | Pel *pOrg = pPic->getAddr(compID); |
---|
[1386] | 614 | Pel *pRef = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getAddr(compID); |
---|
| 615 | const Int orgStride = pPic->getStride(compID); |
---|
| 616 | const Int refStride = slice->getRefPic(eRefPicList, refIdxTemp)->getPicYuvRec()->getStride(compID); |
---|
| 617 | const Int width = pPic->getWidth(compID); |
---|
| 618 | const Int height = pPic->getHeight(compID); |
---|
[1313] | 619 | const Int bitDepth = slice->getSPS()->getBitDepth(toChannelType(compID)); |
---|
[2] | 620 | |
---|
[1313] | 621 | // calculate SAD costs with/without wp for luma |
---|
[1386] | 622 | SADWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, m_wp[refList][refIdxTemp][compID].iWeight, m_wp[refList][refIdxTemp][compID].iOffset, useHighPrecisionPredictionWeighting); |
---|
| 623 | SADnoWP += xCalcSADvalueWP(bitDepth, pOrg, pRef, width, height, orgStride, refStride, log2Denom, defaultWeight, 0, useHighPrecisionPredictionWeighting); |
---|
[1313] | 624 | } |
---|
[2] | 625 | |
---|
[1386] | 626 | const Double dRatio = SADnoWP > 0 ? (((Double)SADWP / (Double)SADnoWP)) : std::numeric_limits<Double>::max(); |
---|
| 627 | if(dRatio >= WEIGHT_PRED_SAD_RELATIVE_TO_NON_WEIGHT_PRED_SAD) |
---|
[2] | 628 | { |
---|
[1313] | 629 | for(Int comp=0; comp<pPic->getNumberValidComponents(); comp++) |
---|
[2] | 630 | { |
---|
[1386] | 631 | WPScalingParam &wp=m_wp[refList][refIdxTemp][comp]; |
---|
| 632 | wp.bPresentFlag = false; |
---|
| 633 | wp.iOffset = 0; |
---|
| 634 | wp.iWeight = defaultWeight; |
---|
| 635 | wp.uiLog2WeightDenom = log2Denom; |
---|
[2] | 636 | } |
---|
| 637 | } |
---|
| 638 | } |
---|
| 639 | } |
---|
[56] | 640 | |
---|
[1313] | 641 | return true; |
---|
[2] | 642 | } |
---|
[56] | 643 | |
---|
[1386] | 644 | // Alternatively, a SSE-based measure could be used instead. |
---|
| 645 | // The respective function has been removed as it currently redundant. |
---|
| 646 | static |
---|
| 647 | Int64 xCalcSADvalueWP(const Int bitDepth, |
---|
| 648 | const Pel *pOrgPel, |
---|
| 649 | const Pel *pRefPel, |
---|
| 650 | const Int width, |
---|
| 651 | const Int height, |
---|
| 652 | const Int orgStride, |
---|
| 653 | const Int refStride, |
---|
| 654 | const Int log2Denom, |
---|
| 655 | const Int weight, |
---|
| 656 | const Int offset, |
---|
| 657 | const Bool useHighPrecision) |
---|
[2] | 658 | { |
---|
[1386] | 659 | //const Int64 iSize = iWidth*iHeight; |
---|
| 660 | const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8)); |
---|
| 661 | const Int64 realOffset = ((Int64)offset)<<realLog2Denom; |
---|
[2] | 662 | |
---|
[1386] | 663 | Int64 SAD = 0; |
---|
| 664 | for( Int y = 0; y < height; y++ ) |
---|
[2] | 665 | { |
---|
[1386] | 666 | for( Int x = 0; x < width; x++ ) |
---|
[2] | 667 | { |
---|
[1386] | 668 | SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) ); |
---|
[2] | 669 | } |
---|
[1386] | 670 | pOrgPel += orgStride; |
---|
| 671 | pRefPel += refStride; |
---|
[2] | 672 | } |
---|
[1313] | 673 | |
---|
[1386] | 674 | //return (iSAD/iSize); |
---|
| 675 | return SAD; |
---|
[2] | 676 | } |
---|
[1386] | 677 | |
---|
| 678 | static |
---|
| 679 | Int64 xCalcSADvalueWPOptionalClip(const Int bitDepth, |
---|
| 680 | const Pel *pOrgPel, |
---|
| 681 | const Pel *pRefPel, |
---|
| 682 | const Int width, |
---|
| 683 | const Int height, |
---|
| 684 | const Int orgStride, |
---|
| 685 | const Int refStride, |
---|
| 686 | const Int log2Denom, |
---|
| 687 | const Int weight, |
---|
| 688 | const Int offset, |
---|
| 689 | const Bool useHighPrecision, |
---|
| 690 | const Bool clipped) |
---|
| 691 | { |
---|
| 692 | Int64 SAD = 0; |
---|
| 693 | if (clipped) |
---|
| 694 | { |
---|
| 695 | const Int64 realLog2Denom = useHighPrecision ? 0 : (bitDepth - 8); |
---|
| 696 | const Int64 realOffset = (Int64)offset<<realLog2Denom; |
---|
| 697 | const Int64 roundOffset = (log2Denom == 0) ? 0 : 1 << (log2Denom - 1); |
---|
| 698 | const Int64 minValue = 0; |
---|
| 699 | const Int64 maxValue = (1 << bitDepth) - 1; |
---|
| 700 | |
---|
| 701 | for( Int y = 0; y < height; y++ ) |
---|
| 702 | { |
---|
| 703 | for( Int x = 0; x < width; x++ ) |
---|
| 704 | { |
---|
| 705 | Int64 scaledValue = Clip3(minValue, maxValue, ((((Int64) pRefPel[x] * (Int64) weight + roundOffset) ) >> (Int64) log2Denom) + realOffset); |
---|
| 706 | SAD += abs((Int64)pOrgPel[x] - scaledValue); |
---|
| 707 | } |
---|
| 708 | pOrgPel += orgStride; |
---|
| 709 | pRefPel += refStride; |
---|
| 710 | } |
---|
| 711 | } |
---|
| 712 | else |
---|
| 713 | { |
---|
| 714 | //const Int64 iSize = iWidth*iHeight; |
---|
| 715 | const Int64 realLog2Denom = useHighPrecision ? log2Denom : (log2Denom + (bitDepth - 8)); |
---|
| 716 | const Int64 realOffset = ((Int64)offset)<<realLog2Denom; |
---|
| 717 | |
---|
| 718 | for( Int y = 0; y < height; y++ ) |
---|
| 719 | { |
---|
| 720 | for( Int x = 0; x < width; x++ ) |
---|
| 721 | { |
---|
| 722 | SAD += abs(( ((Int64)pOrgPel[x] << (Int64) log2Denom) - ( (Int64) pRefPel[x] * (Int64) weight + (realOffset) ) ) ); |
---|
| 723 | } |
---|
| 724 | pOrgPel += orgStride; |
---|
| 725 | pRefPel += refStride; |
---|
| 726 | } |
---|
| 727 | } |
---|
| 728 | return SAD; |
---|
| 729 | } |
---|