-
Karsten Suehring authoredKarsten Suehring authored
CodingStatistics.h 27.48 KiB
/* 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.
*/
#ifndef __CODINGSTATISTICS__
#define __CODINGSTATISTICS__
#include "CommonDef.h"
#include <stdio.h>
#include <string>
#include <map>
#include <math.h>
#include <cinttypes>
#include "ChromaFormat.h"
static const int64_t CODINGSTATISTICS_ENTROPYSCALE = 32768;
enum CodingStatisticsType
{
STATS__NAL_UNIT_TOTAL_BODY,// This is a special case and is not included in the total sums.
STATS__NAL_UNIT_PACKING,
STATS__EMULATION_PREVENTION_3_BYTES,
STATS__NAL_UNIT_HEADER_BITS,
STATS__CABAC_INITIALISATION,
STATS__CABAC_BITS__TQ_BYPASS_FLAG,
STATS__CABAC_BITS__SKIP_FLAG,
STATS__CABAC_BITS__MERGE_FLAG,
STATS__CABAC_BITS__MERGE_INDEX,
STATS__CABAC_BITS__MVP_IDX,
STATS__CABAC_BITS__SPLIT_FLAG,
STATS__CABAC_BITS__PART_SIZE,
STATS__CABAC_BITS__PRED_MODE,
STATS__CABAC_BITS__INTRA_DIR_ANG,
STATS__CABAC_BITS__INTRA_PDPC_FLAG,
STATS__CABAC_BITS__INTER_DIR,
STATS__CABAC_BITS__REF_FRM_IDX,
STATS__CABAC_BITS__MVD,
STATS__CABAC_BITS__MVD_EP,
STATS__CABAC_BITS__AFFINE_FLAG,
STATS__CABAC_BITS__AFFINE_TYPE,
STATS__CABAC_BITS__ISP_MODE_FLAG,
STATS__CABAC_BITS__ISP_SPLIT_FLAG,
STATS__CABAC_BITS__TRANSFORM_SUBDIV_FLAG,
STATS__CABAC_BITS__QT_ROOT_CBF,
STATS__CABAC_BITS__DELTA_QP_EP,
STATS__CABAC_BITS__CHROMA_QP_ADJUSTMENT,
STATS__CABAC_BITS__QT_CBF,
STATS__CABAC_BITS__CROSS_COMPONENT_PREDICTION,
STATS__CABAC_BITS__MTS_FLAGS,
STATS__CABAC_BITS__LAST_SIG_X_Y,
STATS__CABAC_BITS__SIG_COEFF_GROUP_FLAG,
STATS__CABAC_BITS__SIG_COEFF_MAP_FLAG,
STATS__CABAC_BITS__PAR_FLAG,
STATS__CABAC_BITS__GT1_FLAG,
STATS__CABAC_BITS__GT2_FLAG,
STATS__CABAC_BITS__SIGN_BIT,
STATS__CABAC_BITS__ESCAPE_BITS,
STATS__CABAC_BITS__SAO,
STATS__CABAC_BITS__ALF,
STATS__CABAC_TRM_BITS,
STATS__CABAC_FIXED_BITS,
STATS__CABAC_PCM_ALIGN_BITS,
STATS__CABAC_PCM_CODE_BITS,
STATS__BYTE_ALIGNMENT_BITS,
STATS__TRAILING_BITS,
STATS__EXPLICIT_RDPCM_BITS,
STATS__CABAC_EP_BIT_ALIGNMENT,
STATS__CABAC_BITS__ALIGNED_SIGN_BIT,
STATS__CABAC_BITS__ALIGNED_ESCAPE_BITS,
STATS__CABAC_BITS__OTHER,
STATS__CABAC_BITS__INVALID,
STATS__CABAC_BITS__IMV_FLAG,
STATS__CABAC_BITS__GBI_IDX,
STATS__CABAC_BITS__SBT_MODE,
STATS__CABAC_BITS__MH_INTRA_FLAG,
STATS__CABAC_BITS__TRIANGLE_FLAG,
STATS__CABAC_BITS__TRIANGLE_INDEX,
STATS__CABAC_BITS__MULTI_REF_LINE,
STATS__CABAC_BITS__SYMMVD_FLAG,
STATS__TOOL_TOTAL_FRAME,// This is a special case and is not included in the report.
STATS__TOOL_AFF,
STATS__TOOL_EMT,
STATS__TOOL_TOTAL,
STATS__NUM_STATS
};
enum CodingStatisticsMode
{
STATS__MODE_NONE = 0,
STATS__MODE_BITS = 1,
STATS__MODE_TOOLS = 2,
STATS__MODE_ALL =
STATS__MODE_BITS | STATS__MODE_TOOLS
};
static inline const char* getName(CodingStatisticsType name)
{
static const char *statNames[]=
{
"NAL_UNIT_TOTAL_BODY", // This is a special case and is not included in the total sums.
"NAL_UNIT_PACKING",
"EMULATION_PREVENTION_3_BYTES",
"NAL_UNIT_HEADER_BITS",
"CABAC_INITIALISATION-and-rounding",
"CABAC_BITS__TQ_BYPASS_FLAG",
"CABAC_BITS__SKIP_FLAG",
"CABAC_BITS__MERGE_FLAG",
"CABAC_BITS__MERGE_INDEX",
"CABAC_BITS__MVP_IDX",
"CABAC_BITS__SPLIT_FLAG",
"CABAC_BITS__PART_SIZE",
"CABAC_BITS__PRED_MODE",
"CABAC_BITS__INTRA_DIR_ANG",
"CABAC_BITS__INTRA_PDPC_FLAG",
"CABAC_BITS__INTER_DIR",
"CABAC_BITS__REF_FRM_IDX",
"CABAC_BITS__MVD",
"CABAC_BITS__MVD_EP",
"CABAC_BITS__AFFINE_FLAG",
"CABAC_BITS__AFFINE_TYPE",
"CABAC_BITS__ISP_MODE_FLAG",
"CABAC_BITS__ISP_SPLIT_FLAG",
"CABAC_BITS__TRANSFORM_SUBDIV_FLAG",
"CABAC_BITS__QT_ROOT_CBF",
"CABAC_BITS__DELTA_QP_EP",
"CABAC_BITS__CHROMA_QP_ADJUSTMENT",
"CABAC_BITS__QT_CBF",
"CABAC_BITS__CROSS_COMPONENT_PREDICTION",
"CABAC_BITS__MTS_FLAGS",
"CABAC_BITS__LAST_SIG_X_Y",
"CABAC_BITS__SIG_COEFF_GROUP_FLAG",
"CABAC_BITS__SIG_COEFF_MAP_FLAG",
"CABAC_BITS__PAR_FLAG",
"CABAC_BITS__GT1_FLAG",
"CABAC_BITS__GT2_FLAG",
"CABAC_BITS__SIGN_BIT",
"CABAC_BITS__ESCAPE_BITS",
"CABAC_BITS__SAO",
"CABAC_BITS__ALF",
"CABAC_TRM_BITS",
"CABAC_FIXED_BITS",
"CABAC_PCM_ALIGN_BITS",
"CABAC_PCM_CODE_BITS",
"BYTE_ALIGNMENT_BITS",
"TRAILING_BITS",
"EXPLICIT_RDPCM_BITS",
"CABAC_EP_BIT_ALIGNMENT",
"CABAC_BITS__ALIGNED_SIGN_BIT",
"CABAC_BITS__ALIGNED_ESCAPE_BITS",
"CABAC_BITS__OTHER",
"CABAC_BITS__INVALID",
"CABAC_BITS__IMV_FLAG",
"CABAC_BITS__GBI_IDX",
"CABAC_BITS__SBT_MODE",
"CABAC_BITS__MH_INTRA_FLAG",
"CABAC_BITS__TRIANGLE_FLAG",
"CABAC_BITS__TRIANGLE_INDEX",
"CABAC_BITS__MULTI_REF_LINE",
"CABAC_BITS__SYMMVD_FLAG",
"TOOL_FRAME",
"TOOL_AFFINE",
"TOOL_EMT",
"TOOL_TOTAL"
};
CHECK( STATS__NUM_STATS != sizeof( statNames ) / sizeof( char* ) || name >= STATS__NUM_STATS, "stats out of range" );
return statNames[name];
}
static inline bool isAlignedBins( CodingStatisticsType statT ) { return statT == STATS__CABAC_BITS__ALIGNED_SIGN_BIT || statT == STATS__CABAC_BITS__ALIGNED_ESCAPE_BITS; }
static const uint32_t CODING_STATS_NUM_WIDTHS = 20; // just define the number of widths and heigts as 15
static const uint32_t CODING_STATS_NUM_HEIGHTS = 20;
static const uint32_t CODING_STATS_NUM_SIZES = CODING_STATS_NUM_HEIGHTS * CODING_STATS_NUM_WIDTHS;
static const uint32_t CODING_STATS_NUM_SUBCLASSES = CODING_STATS_NUM_SIZES * (1 + MAX_NUM_COMPONENT + MAX_NUM_CHANNEL_TYPE);
class CodingStatisticsClassType
{
public:
CodingStatisticsClassType( const CodingStatisticsType t ) : type( t ), subClass( 0 )
{
}
CodingStatisticsClassType( const CodingStatisticsType t, const uint32_t width, const uint32_t height ) : type( t ), subClass( gp_sizeIdxInfo->idxFrom( height ) * CODING_STATS_NUM_WIDTHS + gp_sizeIdxInfo->idxFrom( width ) )
{
}
CodingStatisticsClassType( const CodingStatisticsType t, const int width, const int height ) : type( t ), subClass( gp_sizeIdxInfo->idxFrom( height ) * CODING_STATS_NUM_WIDTHS + gp_sizeIdxInfo->idxFrom( width ) )
{
}
CodingStatisticsClassType( const CodingStatisticsType t, const ComponentID cid ) : type( t ), subClass( ( cid + 1 ) * CODING_STATS_NUM_SIZES )
{
}
CodingStatisticsClassType( const CodingStatisticsType t, const ChannelType chid ) : type( t ), subClass( ( chid + MAX_NUM_COMPONENT + 1 ) * CODING_STATS_NUM_SIZES )
{
}
CodingStatisticsClassType( const CodingStatisticsType t, const uint32_t width, const uint32_t height, const ComponentID cid ) : type( t ), subClass( ( cid + 1 ) * CODING_STATS_NUM_SIZES + gp_sizeIdxInfo->idxFrom( height ) * CODING_STATS_NUM_WIDTHS + gp_sizeIdxInfo->idxFrom( width ) )
{
}
CodingStatisticsClassType( const CodingStatisticsType t, const uint32_t width, const uint32_t height, const ChannelType chid ) : type( t ), subClass( ( chid + MAX_NUM_COMPONENT + 1 ) * CODING_STATS_NUM_SIZES + gp_sizeIdxInfo->idxFrom( height ) * CODING_STATS_NUM_WIDTHS + gp_sizeIdxInfo->idxFrom( width ) )
{
}
~CodingStatisticsClassType()
{
// should not be relevant, but it looks like some instances are used after they are destroyed
type = STATS__CABAC_BITS__INVALID;
subClass = 0;
}
static uint32_t GetSubClassWidth( const uint32_t subClass )
{
return subClass % CODING_STATS_NUM_WIDTHS;
}
static uint32_t GetSubClassHeight( const uint32_t subClass )
{
return ( subClass % CODING_STATS_NUM_SIZES ) / CODING_STATS_NUM_WIDTHS;
}
static const char *GetSubClassString( const uint32_t subClass )
{
CHECK( subClass >= CODING_STATS_NUM_SUBCLASSES, "Subclass does not exist" );
static const char *strings[1 + MAX_NUM_COMPONENT + MAX_NUM_CHANNEL_TYPE] = { "-", "Y", "Cb", "Cr", "Luma", "Chroma" };
return strings[subClass / CODING_STATS_NUM_SIZES];
}
CodingStatisticsType type;
uint32_t subClass;
};
class CodingStatistics
{
public:
struct StatLogValue
{
uint32_t values[512 + 1];
StatLogValue()
{
const double es = double( CODINGSTATISTICS_ENTROPYSCALE );
values[0] = 0;
for( uint32_t i = 1; i < sizeof( values ) / sizeof( uint32_t ); i++ )
{
values[i] = uint32_t( log( double( i ) )*es / log( 2.0 ) );
}
}
};
struct SStat
{
SStat() : bits( 0 ), count( 0 ), sum( 0 ), classCount( 0 ) { }
int64_t bits;
int64_t count;
int64_t sum;
int64_t classCount;
void clear() { bits = 0; count = 0; sum = 0; classCount = 0; }
SStat &operator+=( const SStat &src )
{
bits += src.bits; count += src.count; sum += src.sum; classCount += src.classCount; return *this;
}
};
struct StatTool
{
StatTool() : count( 0 ), pixels( 0 ), classCount( 0 ) { }
int64_t count;
int64_t pixels;
int64_t classCount;
void clear() { count = 0; pixels = 0; classCount = 0; }
StatTool &operator+=( const StatTool &src )
{
count += src.count; pixels += src.pixels; classCount += src.classCount; return *this;
}
};
class CodingStatisticsData
{
private:
SStat statistics [STATS__NUM_STATS + 1][CODING_STATS_NUM_SUBCLASSES];
SStat statistics_ep [STATS__NUM_STATS + 1][CODING_STATS_NUM_SUBCLASSES];
StatTool statistics_tool [STATS__NUM_STATS + 1][CODING_STATS_NUM_SUBCLASSES];
std::map<std::string, SStat> mappings_ep;
friend class CodingStatistics;
};
int m_mode;
private:
CodingStatisticsData data;
CodingStatistics() : m_mode(STATS__MODE_ALL), data()
{
}
static void OutputLine( const char *pName, const char sep, uint32_t wIdx, uint32_t hIdx, const char *pSubClassStr, const SStat &sCABAC, const SStat &sEP )
{
if( wIdx == 0 && hIdx == 0 )
{
OutputLine( pName, sep, "-", "-", pSubClassStr, sCABAC, sEP );
}
else
{
printf( "%c%-45s%c %6d %6d %6s ", sep == '~' ? '[' : ' ', pName, sep, gp_sizeIdxInfo->sizeFrom( wIdx ), gp_sizeIdxInfo->sizeFrom( hIdx ), pSubClassStr );
if( sCABAC.count > 0 )
{
const double quote = 100.0 * sCABAC.count / ( double ) sCABAC.classCount;
const double ratio = 100.0 * sCABAC.bits / ( double ) sCABAC.count;
printf( "%11.2f%% %12" PRId64 " %12" PRId64 " %12" PRId64 " %11.2f%%", quote, sCABAC.count, sCABAC.sum, sCABAC.bits, ratio );
}
else
{
printf( " -/- %12" PRId64 " %12" PRId64 " %12" PRId64 " -/-", sCABAC.count, sCABAC.sum, sCABAC.bits );
}
printf( " %12" PRId64 " %12" PRId64 " %12" PRId64 " %12" PRId64 " (%12" PRId64 ")%c\n", sEP.count, sEP.sum, sEP.bits, sCABAC.bits + sEP.bits, ( sCABAC.bits + sEP.bits ) / 8, sep == '~' ? ']' : ' ' );
}
}
static void OutputLine( const char *pName, const char sep, const char *pWidthString, const char *pHeightString, const char *pSubClassStr, const SStat &sCABAC, const SStat &sEP )
{
printf( "%c%-45s%c %6s %6s %6s ", sep == '~' ? '[' : ' ', pName, sep, pWidthString, pHeightString, pSubClassStr );
if( sCABAC.count > 0 )
{
const double quote = 100.0 * sCABAC.count / ( double ) sCABAC.classCount;
const double ratio = 100.0 * sCABAC.bits / ( double ) sCABAC.count;
printf( "%11.2f%% %12" PRId64 " %12" PRId64 " %12" PRId64 " %11.2f%%", quote, sCABAC.count, sCABAC.sum, sCABAC.bits, ratio );
}
else
{
printf( " -/- %12" PRId64 " %12" PRId64 " %12" PRId64 " -/-", sCABAC.count, sCABAC.sum, sCABAC.bits );
}
printf( " %12" PRId64 " %12" PRId64 " %12" PRId64 " %12" PRId64 " (%12" PRId64 ")%c\n", sEP.count, sEP.sum, sEP.bits, sCABAC.bits + sEP.bits, ( sCABAC.bits + sEP.bits ) / 8, sep == '~' ? ']' : ' ' );
}
static void OutputLine( const char *pName, const char sep, const char *pWidthString, const char *pHeightString, const char *pSubClassStr, const SStat &sEP )
{
printf( "%c%-45s%c %6s %6s %6s -/- %12s %12s %12s %9s-/- %12" PRId64 " %12" PRId64 " %12" PRId64 " %12" PRId64 " (%12" PRId64 ")%c\n",
sep == '~' ? '[' : ' ', pName, sep, pWidthString, pHeightString, pSubClassStr,
"", "", "", "", sEP.count, sEP.sum, sEP.bits, sEP.bits, ( sEP.bits ) / 8, sep == '~' ? ']' : ' ' );
}
static void OutputLine( const char *pName, const char sep, const char *pWidthString, const char *pHeightString, const char *pSubClassStr, const StatTool &sTool, uint64_t totalPixels )
{
const double ratio = 100.0 * sTool.pixels / ( double ) totalPixels;
printf( "%c%-45s%c %6s %6s %6s %12" PRId64 " %12" PRId64 " %11.2f%%%c\n",
sep == '~' ? '[' : ' ', pName, sep, pWidthString, pHeightString, pSubClassStr,
sTool.count, sTool.pixels, ratio, sep == '~' ? ']' : ' ' );
}
static void OutputLine( const char *pName, const char sep, uint32_t wIdx, uint32_t hIdx, const char *pSubClassStr, const StatTool &sTool, uint64_t totalPixels )
{
const double ratio = 100.0 * sTool.pixels / ( double ) totalPixels;
printf( "%c%-45s%c %6d %6d %6s %12" PRId64 " %12" PRId64 " %11.2f%%%c\n",
sep == '~' ? '[' : ' ', pName, sep, gp_sizeIdxInfo->sizeFrom( wIdx ), gp_sizeIdxInfo->sizeFrom( hIdx ), pSubClassStr,
sTool.count, sTool.pixels, ratio, sep == '~' ? ']' : ' ' );
}
static void OutputDashedLine( const char *pText )
{
printf( "--%s", pText );
uint32_t tot = 0;
for( ; pText[tot] != 0; tot++ );
tot += 2;
for( ; tot < 202; tot++ )
{
printf( "-" );
}
printf( "\n" );
}
void OutputBitStats()
{
const int64_t es = CODINGSTATISTICS_ENTROPYSCALE;
int64_t countTotal = 0;
int64_t classCounts[STATS__NUM_STATS];
std::fill_n( classCounts, ( size_t ) STATS__NUM_STATS, 0 );
int64_t cr = 0; // CABAC remainder, which is added to "STATS__CABAC_INITIALISATION"
{
int64_t totalCABACbits = 0, roundedCABACbits = 0;
for( int i = STATS__NAL_UNIT_PACKING; i < STATS__NUM_STATS; i++ )
{
int64_t classCount = 0;
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c++ )
{
totalCABACbits += data.statistics[i][c].bits;
roundedCABACbits += data.statistics[i][c].bits / es;
classCount += data.statistics[i][c].count;
}
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c++ )
{
data.statistics[i][c].classCount = classCount;
}
classCounts[i] = classCount;
countTotal += classCount;
}
int64_t remainder = totalCABACbits - roundedCABACbits * es;
cr = ( remainder + es / 2 ) / es;
}
classCounts[0] = countTotal;
printf( "Note %s will be excluded from the total as it should be the sum of all the other entries (except for %s)\n", getName( STATS__NAL_UNIT_TOTAL_BODY ), getName( STATS__NAL_UNIT_PACKING ) );
printf( " %-45s- Width Height Type CABAC quote CABAC count CABAC Sum CABAC bits CABAC ratio EP Count EP Sum EP bits Total bits ( Total bytes)\n", "Decoder statistics" );
OutputDashedLine( "" );
SStat cabacTotalBits, epTotalBits;
cabacTotalBits.classCount = countTotal;
epTotalBits .classCount = countTotal;
SStat statTotals_cabac[CODING_STATS_NUM_SUBCLASSES];
SStat statTotals_ep [CODING_STATS_NUM_SUBCLASSES];
for( int i = 0; i < STATS__NUM_STATS; i++ )
{
SStat cabacSubTotal, epSubTotal;
cabacSubTotal.classCount = classCounts[i];
epSubTotal .classCount = classCounts[i];
bool bHadClassifiedEntry = false;
const char *pName = getName( CodingStatisticsType( i ) );
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c++ )
{
SStat &sCABACorig = data.statistics[i][c];
SStat &sEP = data.statistics_ep[i][c];
if( sCABACorig.bits == 0 && sEP.bits == 0 )
{
continue;
}
SStat sCABAC;
{
int64_t thisCABACbits = sCABACorig.bits / es;
if( i == STATS__CABAC_INITIALISATION && sCABACorig.bits != 0 )
{
thisCABACbits += cr;
cr = 0;
}
sCABAC.bits = thisCABACbits;
sCABAC.count = sCABACorig.count;
sCABAC.sum = sCABACorig.sum;
sCABAC.classCount = classCounts[i];
}
uint32_t wIdx = CodingStatisticsClassType::GetSubClassWidth( c );
uint32_t hIdx = CodingStatisticsClassType::GetSubClassHeight( c );
OutputLine( pName, ':', wIdx, hIdx, CodingStatisticsClassType::GetSubClassString( c ), sCABAC, sEP );
cabacSubTotal += sCABAC;
epSubTotal += sEP;
if( i != STATS__NAL_UNIT_TOTAL_BODY )
{
cabacTotalBits += sCABAC;
epTotalBits += sEP;
statTotals_cabac[c] += sCABAC;
statTotals_ep[c] += sEP;
}
bHadClassifiedEntry = bHadClassifiedEntry || ( c != 0 );
}
if( bHadClassifiedEntry )
{
cabacSubTotal.classCount = classCounts[i];
OutputLine( pName, '~', "~~ST~~", "~~ST~~", "~~ST~~", cabacSubTotal, epSubTotal );
}
if( i == STATS__NAL_UNIT_TOTAL_BODY )
{
OutputDashedLine( "" );
}
}
OutputDashedLine( "" );
OutputLine( "CABAC Sub-total", '~', "~~ST~~", "~~ST~~", "~~ST~~", cabacTotalBits, epTotalBits );
OutputDashedLine( "CAVLC HEADER BITS" );
SStat cavlcTotalBits;
for( std::map<std::string, SStat>::iterator it = data.mappings_ep.begin(); it != data.mappings_ep.end(); it++ )
{
SStat s = it->second;
cavlcTotalBits += s;
OutputLine( it->first.c_str(), ':', "-", "-", "-", s );
}
OutputDashedLine( "" );
OutputLine( "CAVLC Header Sub-total", '~', "~~ST~~", "~~ST~~", "~~ST~~", cavlcTotalBits );
// Now output the breakdowns
OutputDashedLine( "CABAC Break down by size" );
for( uint32_t w = 0; w < CODING_STATS_NUM_WIDTHS; w++ )
{
for( uint32_t h = 0; h < CODING_STATS_NUM_HEIGHTS; h++ )
{
SStat subTotalCabac, subTotalEP;
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c += CODING_STATS_NUM_SIZES )
{
subTotalCabac += statTotals_cabac[c + h * CODING_STATS_NUM_WIDTHS + w];
subTotalEP += statTotals_ep [c + h * CODING_STATS_NUM_WIDTHS + w];
}
if( subTotalCabac.bits != 0 || subTotalEP.bits != 0 )
{
OutputLine( "CABAC by size Sub-total", '=', w, h, "All", subTotalCabac, subTotalEP );
}
}
}
OutputDashedLine( "Break down by component/Channel type" );
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c += CODING_STATS_NUM_SIZES )
{
SStat subTotalCabac, subTotalEP;
for( uint32_t w = 0; w < CODING_STATS_NUM_WIDTHS; w++ )
{
for( uint32_t h = 0; h < CODING_STATS_NUM_HEIGHTS; h++ )
{
subTotalCabac += statTotals_cabac[c + h * CODING_STATS_NUM_WIDTHS + w];
subTotalEP += statTotals_ep [c + h * CODING_STATS_NUM_WIDTHS + w];
}
}
if( subTotalCabac.bits != 0 || subTotalEP.bits != 0 )
{
OutputLine( "CABAC by type Sub-total", '=', "-", "-", CodingStatisticsClassType::GetSubClassString( c ), subTotalCabac, subTotalEP );
}
}
OutputDashedLine( "Break down by size and component/Channel type" );
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c += CODING_STATS_NUM_SIZES )
{
for( uint32_t w = 0; w < CODING_STATS_NUM_WIDTHS; w++ )
{
for( uint32_t h = 0; h < CODING_STATS_NUM_HEIGHTS; h++ )
{
SStat subTotalCabac, subTotalEP;
subTotalCabac += statTotals_cabac[c + h * CODING_STATS_NUM_WIDTHS + w];
subTotalEP += statTotals_ep [c + h * CODING_STATS_NUM_WIDTHS + w];
if( subTotalCabac.bits != 0 || subTotalEP.bits != 0 )
{
OutputLine( "CABAC by size and type Sub-total", '=', w, h, CodingStatisticsClassType::GetSubClassString( c ), subTotalCabac, subTotalEP );
}
}
}
}
OutputDashedLine( "" );
cabacTotalBits.classCount = countTotal;
OutputLine ( "CABAC Sub-total", '~', "~~ST~~", "~~ST~~", "~~ST~~", cabacTotalBits, epTotalBits );
OutputLine ( "CAVLC Header Sub-total", '~', "~~ST~~", "~~ST~~", "~~ST~~", cavlcTotalBits );
OutputDashedLine( "GRAND TOTAL" );
epTotalBits += cavlcTotalBits;
OutputLine ( "TOTAL", '~', "~~GT~~", "~~GT~~", "~~GT~~", cabacTotalBits, epTotalBits );
}
void OutputToolStats()
{
printf("\n");
printf( " %-45s- Width Height Type Count Impacted pixels %% Impacted pixels\n", "Tools statistics" );
OutputDashedLine( "" );
const uint64_t toolCount = STATS__TOOL_TOTAL - (STATS__TOOL_TOTAL_FRAME + 1);
StatTool subTotalTool[toolCount];
StatTool statTotalTool[toolCount][CODING_STATS_NUM_SUBCLASSES];
uint64_t totalPixels = GetStatisticTool( STATS__TOOL_TOTAL_FRAME ).pixels;
for( int i = 0; i < toolCount; i++ )
{
const int type = i + (STATS__TOOL_TOTAL_FRAME + 1);
const char *pName = getName( CodingStatisticsType( type ) );
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c++ )
{
StatTool &sTool = data.statistics_tool[type][c];
if( sTool.count == 0 )
{
continue;
}
uint32_t wIdx = CodingStatisticsClassType::GetSubClassWidth( c );
uint32_t hIdx = CodingStatisticsClassType::GetSubClassHeight( c );
OutputLine( pName, ':', wIdx, hIdx, CodingStatisticsClassType::GetSubClassString( c ), sTool, totalPixels );
statTotalTool[i][c] += sTool;
subTotalTool[i] += sTool;
}
if (subTotalTool[i].count != 0)
{
OutputLine( pName, '~', "~~ST~~", "~~ST~~", "~~ST~~", subTotalTool[i], totalPixels );
}
}
for( int i = 0; i < toolCount; i++ )
{
const int type = i + (STATS__TOOL_TOTAL_FRAME + 1);
const char *pName = getName( CodingStatisticsType( type ) );
if (subTotalTool[i].count != 0)
OutputDashedLine( "Break down by tool/Channel type" );
for( uint32_t c = 0; c < CODING_STATS_NUM_SUBCLASSES; c += CODING_STATS_NUM_SIZES )
{
StatTool typeTotalTool;
for( uint32_t w = 0; w < CODING_STATS_NUM_WIDTHS; w++ )
{
for( uint32_t h = 0; h < CODING_STATS_NUM_HEIGHTS; h++ )
typeTotalTool += statTotalTool[i][c + h * CODING_STATS_NUM_WIDTHS + w];
}
if( typeTotalTool.count != 0 )
{
OutputLine( pName, '=', "-", "-", CodingStatisticsClassType::GetSubClassString( c ), typeTotalTool, totalPixels );
}
}
}
}
public:
~CodingStatistics()
{
#if RExt__DECODER_DEBUG_BIT_STATISTICS
if (m_mode & STATS__MODE_BITS)
OutputBitStats();
#endif //RExt__DECODER_DEBUG_BIT_STATISTICS
#ifdef RExt__DECODER_DEBUG_TOOL_STATISTICS
if (m_mode & STATS__MODE_TOOLS)
OutputToolStats();
#endif //RExt__DECODER_DEBUG_TOOL_STATISTICS
}
static CodingStatistics& GetSingletonInstance()
{
static CodingStatistics* inst = nullptr;
if( !inst )
{
inst = new CodingStatistics;
}
return *inst;
}
static void DestroyInstance()
{
CodingStatistics* cs = &GetSingletonInstance();
delete cs;
}
static const CodingStatisticsData &GetStatistics() { return GetSingletonInstance().data; }
static void SetStatistics ( const CodingStatisticsData &src ) { GetSingletonInstance().data = src; }
static SStat &GetStatisticEP ( const CodingStatisticsClassType &stat ) { return GetSingletonInstance().data.statistics_ep[stat.type][stat.subClass]; }
static SStat &GetStatisticEP ( const std::string &str ) { return GetSingletonInstance().data.mappings_ep[str]; }
static SStat &GetStatisticEP ( const char *pKey ) { return GetStatisticEP( std::string( pKey ) ); }
static StatTool &GetStatisticTool ( const CodingStatisticsClassType &stat ) { return GetSingletonInstance().data.statistics_tool[stat.type][stat.subClass]; }
static int getNumOnes( int bins )
{
CHECK( bins < 0, "Bins should not be nagative" );
int count = 0;
while( bins )
{
count += bins & 1;
bins >>= 1;
}
return count;
}
static void IncrementStatisticEP( const CodingStatisticsClassType &stat, const int numBits, const int value )
{
CHECK( stat.type == STATS__CABAC_BITS__INVALID, "Should never be used." );
SStat &s = GetStatisticEP( stat );
s.bits += numBits;
s.count++;
s.sum += getNumOnes( value );
}
static void IncrementStatisticEP( const std::string &str, const int numBits, const int value )
{
SStat &s = GetStatisticEP( str );
s.bits += numBits;
s.count++;
s.sum += getNumOnes( value );
}
static void IncrementStatisticEP( const char *pKey, const int numBits, const int value )
{
SStat &s = GetStatisticEP( pKey );
s.bits += numBits;
s.count++;
s.sum += getNumOnes( value );
}
static void IncrementStatisticTool( const CodingStatisticsClassType &stat )
{
CHECK( stat.type < STATS__TOOL_TOTAL_FRAME || stat.type >= STATS__TOOL_TOTAL, "Should never be used." );
StatTool &s = GetStatisticTool( stat );
s.count++;
uint32_t wIdx = CodingStatisticsClassType::GetSubClassWidth( stat.subClass );
uint32_t hIdx = CodingStatisticsClassType::GetSubClassHeight( stat.subClass );
s.pixels = s.count * gp_sizeIdxInfo->sizeFrom( wIdx ) * gp_sizeIdxInfo->sizeFrom( hIdx );
}
StatLogValue values;
static void UpdateCABACStat( const CodingStatisticsClassType &stat, uint32_t uiRangeBefore, uint32_t uiRangeAfter, int val )
{
CHECK( stat.type == STATS__CABAC_BITS__INVALID, "Should never be used." );
CodingStatistics &inst = GetSingletonInstance();
// doing rangeBefore*p(x)=rangeAfter
// p(x)=rangeAfter/rangeBefore
// entropy = -log2(p(x))=-log(p(x))/log(2) = -(log rangeAfter - log rangeBefore) / log(2) = (log rangeBefore / log 2 - log rangeAfter / log 2)
SStat &s = inst.data.statistics[stat.type][stat.subClass];
s.bits += inst.values.values[uiRangeBefore] - inst.values.values[uiRangeAfter];
s.count++;
s.sum += val;
}
};
#endif