Skip to content
Snippets Groups Projects
AQp.cpp 5.57 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* The copyright in this software is being made available under the BSD
     * License, included below. This software may be subject to other third party
     * and contributor rights, including patent rights, and no such rights are
     * granted under this license.
     *
    
     * Copyright (c) 2010-2019, ITU/ISO/IEC
    
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *  * Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     *  * Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
     *    be used to endorse or promote products derived from this software without
     *    specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     * THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /** \file     AQp.cpp
        \brief    class of picture which includes side information for encoder
    */
    
    #include "AQp.h"
    #include <float.h>
    
    //! \ingroup EncoderLib
    //! \{
    
    /** Constructor
     */
    AQpLayer::AQpLayer( int iWidth, int iHeight, uint32_t uiAQPartWidth, uint32_t uiAQPartHeight )
    : m_uiAQPartWidth(uiAQPartWidth)
    , m_uiAQPartHeight(uiAQPartHeight)
    , m_uiNumAQPartInWidth((iWidth + uiAQPartWidth-1) / uiAQPartWidth)
    , m_uiNumAQPartInHeight((iHeight + uiAQPartHeight-1) / uiAQPartHeight)
    , m_dAvgActivity(0.0)
    , m_acEncAQU( m_uiNumAQPartInWidth * m_uiNumAQPartInHeight, 0.0 )
    {
    }
    
    /** Destructor
     */
    AQpLayer::~AQpLayer()
    {
    }
    
    
    
    /** Analyze source picture and compute local image characteristics used for QP adaptation
     * \param pcEPic Picture object to be analyzed
     * \return void
     */
    
    void AQpPreanalyzer::preanalyze( Picture* pcEPic )
    {
      const CPelBuf lumaPlane = pcEPic->getOrigBuf().Y();
      const int iWidth  = lumaPlane.width;
      const int iHeight = lumaPlane.height;
      const int iStride = lumaPlane.stride;
    
      for ( uint32_t d = 0; d < pcEPic->aqlayer.size(); d++ )
      {
        const Pel* pLineY = lumaPlane.bufAt( 0, 0);
        AQpLayer* pcAQLayer = pcEPic->aqlayer[d];
        const uint32_t uiAQPartWidth = pcAQLayer->getAQPartWidth();
        const uint32_t uiAQPartHeight = pcAQLayer->getAQPartHeight();
        double* pcAQU = &pcAQLayer->getQPAdaptationUnit()[0];
    
        double dSumAct = 0.0;
        for ( uint32_t y = 0; y < iHeight; y += uiAQPartHeight )
        {
          const uint32_t uiCurrAQPartHeight = std::min(uiAQPartHeight, iHeight-y);
          for ( uint32_t x = 0; x < iWidth; x += uiAQPartWidth, pcAQU++ )
          {
            const uint32_t uiCurrAQPartWidth = std::min(uiAQPartWidth, iWidth-x);
            const Pel* pBlkY = &pLineY[x];
            uint64_t uiSum[4] = {0, 0, 0, 0};
            uint64_t uiSumSq[4] = {0, 0, 0, 0};
            uint32_t by = 0;
            for ( ; by < uiCurrAQPartHeight>>1; by++ )
            {
              uint32_t bx = 0;
              for ( ; bx < uiCurrAQPartWidth>>1; bx++ )
              {
                uiSum  [0] += pBlkY[bx];
                uiSumSq[0] += pBlkY[bx] * pBlkY[bx];
              }
              for ( ; bx < uiCurrAQPartWidth; bx++ )
              {
                uiSum  [1] += pBlkY[bx];
                uiSumSq[1] += pBlkY[bx] * pBlkY[bx];
              }
              pBlkY += iStride;
            }
            for ( ; by < uiCurrAQPartHeight; by++ )
            {
              uint32_t bx = 0;
              for ( ; bx < uiCurrAQPartWidth>>1; bx++ )
              {
                uiSum  [2] += pBlkY[bx];
                uiSumSq[2] += pBlkY[bx] * pBlkY[bx];
              }
              for ( ; bx < uiCurrAQPartWidth; bx++ )
              {
                uiSum  [3] += pBlkY[bx];
                uiSumSq[3] += pBlkY[bx] * pBlkY[bx];
              }
              pBlkY += iStride;
            }
    
            CHECK((uiCurrAQPartWidth&1)!=0,  "Odd part width unsupported");
            CHECK((uiCurrAQPartHeight&1)!=0, "Odd part height unsupported");
            const uint32_t pixelWidthOfQuadrants  = uiCurrAQPartWidth >>1;
            const uint32_t pixelHeightOfQuadrants = uiCurrAQPartHeight>>1;
            const uint32_t numPixInAQPart         = pixelWidthOfQuadrants * pixelHeightOfQuadrants;
    
            double dMinVar = DBL_MAX;
            if (numPixInAQPart!=0)
            {
              for ( int i=0; i<4; i++)
              {
                const double dAverage = double(uiSum[i]) / numPixInAQPart;
                const double dVariance = double(uiSumSq[i]) / numPixInAQPart - dAverage * dAverage;
                dMinVar = std::min(dMinVar, dVariance);
              }
            }
            else
            {
              dMinVar = 0.0;
            }
            const double dActivity = 1.0 + dMinVar;
            *pcAQU = dActivity;
            dSumAct += dActivity;
          }
          pLineY += iStride * uiCurrAQPartHeight;
        }
    
        const double dAvgAct = dSumAct / (pcAQLayer->getNumAQPartInWidth() * pcAQLayer->getNumAQPartInHeight());
        pcAQLayer->setAvgActivity( dAvgAct );
      }
    }
    
    
    
    //! \}