You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
453 lines
11 KiB
453 lines
11 KiB
/* *************************************************************************
|
|
** INTEL Corporation Proprietary Information
|
|
**
|
|
** This listing is supplied under the terms of a license
|
|
** agreement with INTEL Corporation and may not be copied
|
|
** nor disclosed except in accordance with the terms of
|
|
** that agreement.
|
|
**
|
|
** Copyright (c) 1996 Intel Corporation.
|
|
** All Rights Reserved.
|
|
**
|
|
****************************************************************************
|
|
*
|
|
* e3stat.cpp
|
|
*
|
|
* Description:
|
|
* This modules contains the encoder statistics routines
|
|
*
|
|
* Routines: All routines declared in e3stat.h
|
|
* StatsFrameSize
|
|
* InitFrameSizeStats
|
|
* OutputFrameSizeStats
|
|
*
|
|
* StatsUsedQuant
|
|
* InitQuantStats
|
|
* OutputQuantStats
|
|
*
|
|
* InitPSNRStats
|
|
* OutputPSNRStats
|
|
* InitStats
|
|
* IncrementPSNRCounter
|
|
* ComputeYPSNR
|
|
* ComputeVPSNR
|
|
* ComputeUPSNR
|
|
*
|
|
* Data:
|
|
|
|
// $Header: R:\h26x\h26x\src\enc\e3stat.cpv 1.0 22 Apr 1996 17:46:22 BECHOLS $
|
|
// $Log: R:\h26x\h26x\src\enc\e3stat.cpv $
|
|
//
|
|
// Rev 1.0 22 Apr 1996 17:46:22 BECHOLS
|
|
// Initial revision.
|
|
//
|
|
// Rev 1.1 08 Mar 1996 14:14:26 DBRUCKS
|
|
// add framesize stats and fixed PSNR to use energy instead of the signal
|
|
//
|
|
// Rev 1.0 01 Mar 1996 16:34:40 DBRUCKS
|
|
// Initial revision.
|
|
*/
|
|
|
|
#include "precomp.h"
|
|
|
|
#ifdef ENCODE_STATS
|
|
|
|
|
|
#define MAX_FRAME_SIZE_INDEX 255
|
|
static U32 uArrayFrameSize[MAX_FRAME_SIZE_INDEX+1];
|
|
static U32 uArrayBitStreamSize[MAX_FRAME_SIZE_INDEX+1];
|
|
static int iFrameSizeIndex = 0;
|
|
|
|
static U32 uQuantCount[32];
|
|
|
|
#define MAX_PSNR_INDEX 255
|
|
static double dArrayYPSNR[MAX_PSNR_INDEX+1];
|
|
static double dArrayVPSNR[MAX_PSNR_INDEX+1];
|
|
static double dArrayUPSNR[MAX_PSNR_INDEX+1];
|
|
static int iPSNRIndex = 0;
|
|
|
|
static double ComputePSNR(U8 * pu8Input,
|
|
int iInputPitch,
|
|
U8 * pu8Output,
|
|
int iOutputPitch,
|
|
UN unWidth,
|
|
UN unHeight);
|
|
|
|
|
|
/************************************************************************
|
|
*
|
|
* StatsFrameSize
|
|
*
|
|
* Save the frame size information - with possbily different bitstream
|
|
* and frame sizes.
|
|
*/
|
|
extern void StatsFrameSize(U32 uBitStreamSize, U32 uFrameSize)
|
|
{
|
|
ASSERT(uFrameSize >= uBitStreamSize);
|
|
|
|
if (iFrameSizeIndex <= MAX_FRAME_SIZE_INDEX)
|
|
{
|
|
uArrayBitStreamSize[iFrameSizeIndex] = uBitStreamSize;
|
|
uArrayFrameSize[iFrameSizeIndex] = uFrameSize;
|
|
iFrameSizeIndex++; /* can grow to one larger than MAX_FRAME_SIZE_INDEX */
|
|
}
|
|
} /* end StatsFrameSize() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitFrameSizeStats
|
|
*/
|
|
extern void InitFrameSizeStats()
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i <= MAX_FRAME_SIZE_INDEX ; i++)
|
|
{
|
|
uArrayFrameSize[i] = 0;
|
|
uArrayBitStreamSize[i] = 0;
|
|
}
|
|
iFrameSizeIndex = 0;
|
|
} /* end InitFrameSizeStats() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* OutputFrameSizeStats
|
|
*/
|
|
extern void OutputFrameSizeStats(char * filename)
|
|
{
|
|
U32 uSumBitStream;
|
|
U32 uSumFrame;
|
|
FILE * fp;
|
|
int i;
|
|
|
|
FX_ENTRY("OutputFrameSizeStats")
|
|
|
|
ASSERT(iFrameSizeIndex <= (MAX_FRAME_SIZE_INDEX+1));
|
|
fp = fopen(filename, "a");
|
|
if (fp == NULL)
|
|
{
|
|
ERRORMESSAGE(("%s: Error opening stats file\r\n", _fx_));
|
|
}
|
|
else
|
|
{
|
|
uSumBitStream = 0;
|
|
uSumFrame = 0;
|
|
for (i = 0; i < iFrameSizeIndex ; i++)
|
|
{
|
|
uSumFrame += uArrayFrameSize[i];
|
|
uSumBitStream += uArrayBitStreamSize[i];
|
|
if (uArrayFrameSize[i] != uArrayBitStreamSize[i])
|
|
{
|
|
fprintf(fp, "Frame[%d] Sizes: Frame=%d BitStream=%d Other=%d\n",
|
|
i, (int) uArrayFrameSize[i], (int) uArrayBitStreamSize[i],
|
|
(int) (uArrayFrameSize[i] - uArrayBitStreamSize[i]));
|
|
}
|
|
else
|
|
{
|
|
fprintf(fp,"Frame[%d] Size=%d\n", (int) i, (int) uArrayFrameSize[i]);
|
|
}
|
|
}
|
|
if (iFrameSizeIndex > 0)
|
|
{
|
|
if (uSumFrame != uSumBitStream)
|
|
{
|
|
fprintf(fp,"Count = %ld Average Sizes: Frm=%f BS=%f Other=%f\n",
|
|
(long) iFrameSizeIndex,
|
|
((float)uSumFrame)/((float)iFrameSizeIndex),
|
|
((float)uSumBitStream)/((float)iFrameSizeIndex),
|
|
((float)(uSumFrame - uSumBitStream))/((float)iFrameSizeIndex));
|
|
}
|
|
else
|
|
{
|
|
fprintf(fp,"Count = %ld Average Size=%f\n", (long) iFrameSizeIndex,
|
|
((float)uSumFrame)/((float)iFrameSizeIndex));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
fprintf(fp,"No frame size statistics available\n");
|
|
}
|
|
fclose(fp);
|
|
}
|
|
} /* end OutputFrameSizeStats() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitQuantStats
|
|
*/
|
|
extern void InitQuantStats()
|
|
{
|
|
int i;
|
|
for (i = 0 ; i < 32 ; i++)
|
|
{
|
|
uQuantCount[i] = 0;
|
|
}
|
|
} /* end InitQuantStats() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* StatsUsedQuant
|
|
*/
|
|
extern void StatsUsedQuant(
|
|
int iQuant)
|
|
{
|
|
ASSERT(iQuant >= 1 && iQuant <= 31);
|
|
uQuantCount[iQuant]++;
|
|
} /* end StatsUsedQuant() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* OutputQuantStats
|
|
*/
|
|
extern void OutputQuantStats(char * filename)
|
|
{
|
|
U32 uCount;
|
|
U32 uTotal;
|
|
FILE * fp;
|
|
int i;
|
|
|
|
FX_ENTRY("OutputQuantStats")
|
|
|
|
fp = fopen(filename, "a");
|
|
if (fp == NULL)
|
|
{
|
|
ERRORMESSAGE(("%s: Error opening stats file\r\n", _fx_));
|
|
}
|
|
else
|
|
{
|
|
uCount = 0;
|
|
uTotal = 0;
|
|
for (i = 0; i < 32 ; i++)
|
|
{
|
|
if (uQuantCount[i] > 0)
|
|
{
|
|
uCount += uQuantCount[i];
|
|
uTotal += (uQuantCount[i] * i);
|
|
fprintf(fp,"Quant[%d] = %ld\n",
|
|
(int)i, (long) uQuantCount[i]);
|
|
}
|
|
}
|
|
if (uCount > 0)
|
|
{
|
|
fprintf(fp,"Count = %ld Average = %f\n",
|
|
(long) uCount, ((float)uTotal)/((float)uCount));
|
|
}
|
|
else
|
|
{
|
|
fprintf(fp,"No quantization statistics available\n");
|
|
}
|
|
fclose(fp);
|
|
}
|
|
} /* end OutputQuantStats() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* InitPSNRStats - initialize the PSNR data structures
|
|
*/
|
|
extern void InitPSNRStats()
|
|
{
|
|
int i;
|
|
for (i = 0; i <= MAX_PSNR_INDEX; i++)
|
|
{
|
|
dArrayYPSNR[i] = 0.0;
|
|
dArrayVPSNR[i] = 0.0;
|
|
dArrayUPSNR[i] = 0.0;
|
|
}
|
|
iPSNRIndex = 0;
|
|
} /* end InitPSNRStats() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* OutputPSNRStats - output the PSNR data to the specified file
|
|
*/
|
|
extern void OutputPSNRStats(
|
|
char * filename)
|
|
{
|
|
int i;
|
|
FILE * fp;
|
|
double dYTotal;
|
|
double dVTotal;
|
|
double dUTotal;
|
|
|
|
FX_ENTRY("OutputPSNRStats")
|
|
|
|
ASSERT(iPSNRIndex <= (MAX_PSNR_INDEX+1));
|
|
|
|
fp = fopen(filename, "a");
|
|
if (fp == NULL)
|
|
{
|
|
ERRORMESSAGE(("%s: Unable to open PSNR output file\r\n", _fx_));
|
|
}
|
|
else
|
|
{
|
|
if (iPSNRIndex <= 0)
|
|
{
|
|
fprintf(fp,"No PSNR data available\n");
|
|
}
|
|
else
|
|
{
|
|
dYTotal = 0.0;
|
|
dVTotal = 0.0;
|
|
dUTotal = 0.0;
|
|
for (i = 0; i < iPSNRIndex ; i++)
|
|
{
|
|
dYTotal += dArrayYPSNR[i];
|
|
dVTotal += dArrayVPSNR[i];
|
|
dUTotal += dArrayUPSNR[i];
|
|
fprintf(fp, "YVU#%d = %f %f %f\n", (int)i,
|
|
dArrayYPSNR[i],dArrayVPSNR[i],dArrayUPSNR[i]);
|
|
}
|
|
fprintf(fp, "Average = %f %f %f\n",
|
|
dYTotal/((double)iPSNRIndex),
|
|
dVTotal/((double)iPSNRIndex),
|
|
dUTotal/((double)iPSNRIndex));
|
|
}
|
|
fclose(fp);
|
|
}
|
|
} /* end OutputPSNRStats */
|
|
|
|
/********************************************************************
|
|
*
|
|
* IncrementPSNRCounter()
|
|
*/
|
|
extern void IncrementPSNRCounter()
|
|
{
|
|
if (iPSNRIndex <= MAX_PSNR_INDEX)
|
|
{
|
|
iPSNRIndex++;
|
|
}
|
|
} /* end IncrementPSNRCounter() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* ComputeYPSNR - compute the Y PSNR Value
|
|
*/
|
|
extern void ComputeYPSNR(
|
|
U8 * pu8Input,
|
|
int iInputPitch,
|
|
U8 * pu8Output,
|
|
int iOutputPitch,
|
|
UN unWidth,
|
|
UN unHeight)
|
|
{
|
|
double dPSNR;
|
|
if (iPSNRIndex <= MAX_PSNR_INDEX)
|
|
{
|
|
dPSNR = ComputePSNR(pu8Input,iInputPitch,
|
|
pu8Output,iOutputPitch,
|
|
unWidth,unHeight);
|
|
dArrayYPSNR[iPSNRIndex] = dPSNR;
|
|
}
|
|
} /* end ComputeYPSNR() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* ComputeVPSNR - compute the V PSNR Value
|
|
*/
|
|
extern void ComputeVPSNR(
|
|
U8 * pu8Input,
|
|
int iInputPitch,
|
|
U8 * pu8Output,
|
|
int iOutputPitch,
|
|
UN unWidth,
|
|
UN unHeight)
|
|
{
|
|
double dPSNR;
|
|
if (iPSNRIndex <= MAX_PSNR_INDEX)
|
|
{
|
|
dPSNR = ComputePSNR(pu8Input,iInputPitch,
|
|
pu8Output,iOutputPitch,
|
|
unWidth,unHeight);
|
|
dArrayVPSNR[iPSNRIndex] = dPSNR;
|
|
}
|
|
} /* end ComputeVPSNR() */
|
|
|
|
/************************************************************************
|
|
*
|
|
* ComputeUPSNR - compute the U PSNR Value
|
|
*/
|
|
extern void ComputeUPSNR(
|
|
U8 * pu8Input,
|
|
int iInputPitch,
|
|
U8 * pu8Output,
|
|
int iOutputPitch,
|
|
UN unWidth,
|
|
UN unHeight)
|
|
{
|
|
double dPSNR;
|
|
if (iPSNRIndex <= MAX_PSNR_INDEX)
|
|
{
|
|
dPSNR = ComputePSNR(pu8Input,iInputPitch,
|
|
pu8Output,iOutputPitch,
|
|
unWidth,unHeight);
|
|
dArrayUPSNR[iPSNRIndex] = dPSNR;
|
|
}
|
|
} /* end ComputeUPSNR() */
|
|
|
|
/***************************** STATIC ROUTINES *************************/
|
|
|
|
/************************************************************************
|
|
*
|
|
* ComputePSNR - compute Peek Signal to Noise Ratio over this plane
|
|
*
|
|
* 255*255
|
|
* PSNR = 10log ----------------------------
|
|
* 10 SUM((I-O)(I-O))/Wdith*Height
|
|
*/
|
|
static double ComputePSNR(
|
|
U8 * pu8Input,
|
|
int iInputPitch,
|
|
U8 * pu8Output,
|
|
int iOutputPitch,
|
|
UN unWidth,
|
|
UN unHeight)
|
|
{
|
|
UN unW;
|
|
UN unH;
|
|
U32 uSum;
|
|
double dMSE;
|
|
double dPSNR;
|
|
double dTemp;
|
|
int iInput;
|
|
int iOutput;
|
|
int iDiff;
|
|
int iSquareOfDiff;
|
|
|
|
/* Obtain the sum of the square of the differences
|
|
*/
|
|
uSum = 0;
|
|
for (unH = 0; unH < unHeight; unH++)
|
|
{
|
|
for (unW = 0; unW < unWidth; unW++)
|
|
{
|
|
iInput = (int)*pu8Input++;
|
|
iOutput = (int)*pu8Output++;
|
|
iDiff = iInput - iOutput;
|
|
iSquareOfDiff = iDiff*iDiff;
|
|
uSum += (U32) iSquareOfDiff;
|
|
}
|
|
pu8Input += (iInputPitch - (int)unWidth);
|
|
pu8Output += (iOutputPitch - (int)unWidth);
|
|
}
|
|
|
|
/* Obtain the Mean Squared Error
|
|
*/
|
|
if (uSum == 0)
|
|
{
|
|
dMSE = 0.01; /* a non-zero value */
|
|
}
|
|
else
|
|
{
|
|
dMSE = ((double)uSum)/((double)(unWidth*unHeight));
|
|
}
|
|
|
|
/* Obtain PSNR
|
|
*/
|
|
dTemp = (255.0 * 255.0) / dMSE;
|
|
dTemp = log10(dTemp);
|
|
dPSNR = 10.0 * dTemp;
|
|
|
|
return dPSNR;
|
|
} /* end ComputePSNR() */
|
|
|
|
#endif /* ENCODE_STATS */
|