Skip to content
Snippets Groups Projects
DepQuant.cpp 67 KiB
Newer Older
/* 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-2018, 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.
 */

#include "DepQuant.h"
#include "TrQuant.h"
#include "CodingStructure.h"
#include "UnitTools.h"

#include <bitset>






namespace DQIntern
{
  /*================================================================================*/
  /*=====                                                                      =====*/
  /*=====   R A T E   E S T I M A T O R                                        =====*/
  /*=====                                                                      =====*/
  /*================================================================================*/

  struct NbInfoSbb
  {
    uint8_t   num;
    uint8_t   inPos[5];
  };
  struct NbInfoOut
  {
    uint16_t  maxDist;
    uint16_t  num;
    uint16_t  outPos[5];
  };
  struct CoeffFracBits
  {
  };


  class Rom
  {
  public:
    Rom() : m_scansInitialized(false) {}
    ~Rom() { xUninitScanArrays(); }
    void              init        ()                                  { xInitScanArrays(); }
    const NbInfoSbb*  getNbInfoSbb( int sId, int hId, int vId ) const { return m_scanId2NbInfoSbbArray[sId][hId][vId]; }
    const NbInfoOut*  getNbInfoOut( int sId, int hId, int vId ) const { return m_scanId2NbInfoOutArray[sId][hId][vId]; }
  private:
    void  xInitScanArrays   ();
    void  xUninitScanArrays ();
  private:
    bool       m_scansInitialized;
    NbInfoSbb* m_scanId2NbInfoSbbArray[ SCAN_NUMBER_OF_TYPES ][ MAX_CU_SIZE/2+1 ][ MAX_CU_SIZE/2+1 ];
    NbInfoOut* m_scanId2NbInfoOutArray[ SCAN_NUMBER_OF_TYPES ][ MAX_CU_SIZE/2+1 ][ MAX_CU_SIZE/2+1 ];
  };

  void Rom::xInitScanArrays()
  {
    if( m_scansInitialized )
    {
      return;
    }
    ::memset( m_scanId2NbInfoSbbArray, 0, sizeof(m_scanId2NbInfoSbbArray) );
    ::memset( m_scanId2NbInfoOutArray, 0, sizeof(m_scanId2NbInfoOutArray) );

    SizeIndexInfoLog2 sizeInfo;
    sizeInfo.init ( MAX_CU_SIZE );
    uint32_t raster2id[ MAX_CU_SIZE * MAX_CU_SIZE ];

    for( uint32_t blockHeightIdx = 0; blockHeightIdx < sizeInfo.numHeights(); blockHeightIdx++ )
    {
      for( uint32_t blockWidthIdx = 0; blockWidthIdx < sizeInfo.numWidths(); blockWidthIdx++ )
      {
        const uint32_t blockWidth   = sizeInfo.sizeFrom( blockWidthIdx  );
        const uint32_t blockHeight  = sizeInfo.sizeFrom( blockHeightIdx );
        const uint32_t totalValues  = blockWidth * blockHeight;
        const uint32_t log2CGWidth  = (blockWidth & 3) + (blockHeight & 3) > 0 ? 1 : 2;
        const uint32_t log2CGHeight = (blockWidth & 3) + (blockHeight & 3) > 0 ? 1 : 2;
        const uint32_t groupWidth   = 1 << log2CGWidth;
        const uint32_t groupHeight  = 1 << log2CGHeight;
        const uint32_t groupSize    = groupWidth * groupHeight;
        if( ((blockWidth>>log2CGWidth)<<log2CGWidth)!=blockWidth || ((blockHeight>>log2CGHeight)<<log2CGHeight)!=blockHeight )
        {
          continue;
        }
        for( uint32_t scanTypeIdx = 0; scanTypeIdx < SCAN_NUMBER_OF_TYPES; scanTypeIdx++ )
        {
          const CoeffScanType scanType  = CoeffScanType(scanTypeIdx);
          const uint32_t*         scanId2RP = g_scanOrder     [SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx];
          const uint32_t*         scanId2X  = g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx][0];
          const uint32_t*         scanId2Y  = g_scanOrderPosXY[SCAN_GROUPED_4x4][scanType][blockWidthIdx][blockHeightIdx][1];
          NbInfoSbb*&         sId2NbSbb = m_scanId2NbInfoSbbArray           [scanType][blockWidthIdx][blockHeightIdx];
          NbInfoOut*&         sId2NbOut = m_scanId2NbInfoOutArray           [scanType][blockWidthIdx][blockHeightIdx];

          sId2NbSbb = new NbInfoSbb[ totalValues ];
          sId2NbOut = new NbInfoOut[ totalValues ];

          for( uint32_t scanId = 0; scanId < totalValues; scanId++ )
          {
            raster2id[ scanId2RP[ scanId ] ] = scanId;
          }

          for( unsigned scanId = 0; scanId < totalValues; scanId++ )
          {
            const int posX = scanId2X [ scanId ];
            const int posY = scanId2Y [ scanId ];
            const int rpos = scanId2RP[ scanId ];
            {
              //===== inside subband neighbours =====
              NbInfoSbb&     nbSbb  = sId2NbSbb[ scanId ];
              const int      begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
              int            cpos[5];
              cpos[0] = ( posX < blockWidth -1                         ? ( raster2id[rpos+1           ] - begSbb < groupSize ? raster2id[rpos+1           ] - begSbb : 0 ) : 0 );
              cpos[1] = ( posX < blockWidth -2                         ? ( raster2id[rpos+2           ] - begSbb < groupSize ? raster2id[rpos+2           ] - begSbb : 0 ) : 0 );
              cpos[2] = ( posX < blockWidth -1 && posY < blockHeight-1 ? ( raster2id[rpos+1+blockWidth] - begSbb < groupSize ? raster2id[rpos+1+blockWidth] - begSbb : 0 ) : 0 );
              cpos[3] = ( posY < blockHeight-1                         ? ( raster2id[rpos+  blockWidth] - begSbb < groupSize ? raster2id[rpos+  blockWidth] - begSbb : 0 ) : 0 );
              cpos[4] = ( posY < blockHeight-2                         ? ( raster2id[rpos+2*blockWidth] - begSbb < groupSize ? raster2id[rpos+2*blockWidth] - begSbb : 0 ) : 0 );
              for( nbSbb.num = 0; true; )
              {
                int nk = -1;
                for( int k = 0; k < 5; k++ )
                {
                  if( cpos[k] != 0 && ( nk < 0 || cpos[k] < cpos[nk] ) )
                  {
                    nk = k;
                  }
                }
                if( nk < 0 )
                {
                  break;
                }
                nbSbb.inPos[ nbSbb.num++ ] = uint8_t( cpos[nk] );
                cpos[nk] = 0;
              }
              for( int k = nbSbb.num; k < 5; k++ )
              {
                nbSbb.inPos[k] = 0;
              }
            }
            {
              //===== outside subband neighbours =====
              NbInfoOut&     nbOut  = sId2NbOut[ scanId ];
              const int      begSbb = scanId - ( scanId & (groupSize-1) ); // first pos in current subblock
              int            cpos[5];
              cpos[0] = ( posX < blockWidth -1                         ? ( raster2id[rpos+1           ] - begSbb >= groupSize ? raster2id[rpos+1           ] : 0 ) : 0 );
              cpos[1] = ( posX < blockWidth -2                         ? ( raster2id[rpos+2           ] - begSbb >= groupSize ? raster2id[rpos+2           ] : 0 ) : 0 );
              cpos[2] = ( posX < blockWidth -1 && posY < blockHeight-1 ? ( raster2id[rpos+1+blockWidth] - begSbb >= groupSize ? raster2id[rpos+1+blockWidth] : 0 ) : 0 );
              cpos[3] = ( posY < blockHeight-1                         ? ( raster2id[rpos+  blockWidth] - begSbb >= groupSize ? raster2id[rpos+  blockWidth] : 0 ) : 0 );
              cpos[4] = ( posY < blockHeight-2                         ? ( raster2id[rpos+2*blockWidth] - begSbb >= groupSize ? raster2id[rpos+2*blockWidth] : 0 ) : 0 );
              for( nbOut.num = 0; true; )
              {
                int nk = -1;
                for( int k = 0; k < 5; k++ )
                {
                  if( cpos[k] != 0 && ( nk < 0 || cpos[k] < cpos[nk] ) )
                  {
                    nk = k;
                  }
                }
                if( nk < 0 )
                {
                  break;
                }
                nbOut.outPos[ nbOut.num++ ] = uint16_t( cpos[nk] );
Loading
Loading full blame...