[Mp4-tech] codes to compute BDPSNR and BDBR

Caimu Tang Caimu.Tang motorola.com
Thu Apr 5 13:58:35 EDT 2007


(Upon requests for the script for computing BDPSNR and BDBR
I post the C source code as follows. The codes are modified from its original 
version (which is solely for personal use) so that this will not
infringe any copyrighted material by posting it in public)
/* 
Any purpose of use of the code is granted. 
IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
OF THE USE OF THIS SOFTWARE. 
TO THE BEST KNOWLEDGE OF THE AUTHOR, ALL ALGORITHMS IMPLEMENTED IN THIS CODE 
ARE NOT UNDER PROTECTION OF INTELLECTUAL PROPERTY RIGHTS OR DISCLOSURE.
README:
Sample data file:
##### start of sample
 #baseline
 112079, 35.59
 58127, 32.375
 32058, 29.389
 19388, 26.492
 #improved
  111561, 35.62
  57605, 32.394
  31419, 29.411
 18810, 26.486
#### end of sample
Note that bit rate numbers can be linearly scaled and that does not affect the result. 
Compilation under UNIX or LINUX
gcc -o bd bd.c -lm 
Usage:
bd flag data_file
where, flag: 1 for BDPSNR, 0 for BDBR
Note: coded is not optimized for efficiency. Codes are modified in such a way so that 
no copyrighted codes is used.
Author: Caimu Tang, Nov. 2004.
Reference
Gisle Bjontegaard, Calculation of average PSNR difference between RD-curves, VCEG-M33, March 2001.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define LINE_LENGTH 1024
typedef double (*FUNC_T)(double *, double *, double);
double XVAL[4];
double YVAL[4];
double points[1024][2];
int ReadLine(FILE *fp, char *string)
{
	int	i  = 0;
	int	c;
	i = 0;
        while (i < LINE_LENGTH) {
                c = getc(fp);
                if (c == '\n') {
                        string[i] = '\0';
                        return  1;
                }else{
                        if (c == EOF) {
                                string[i] = '\0';
                                return EOF;
                        }else{
                        	if (iscntrl(c) && c != '\t') {
                        		continue;
                        	}
                        }
			string[i++] = c;
                }
        }
	string[i] = '\0';
	while ((c = getc(fp))  != EOF) {
		if (c == '\n') return 1;
	}
	return EOF;
}
double polInt(double *xa, double *ya, double x) { 
double p01, p12, p23, p012, p123, p;
/* 
   Modified specific for Bjontegaard Difference measure. 
   To support more than 4 points, change this routine 
   using a tabular dynamic programming approach 
   For example, Book CD "Numerical Recipes in C" contains 
   one such implementation
*/
if(xa[0] == xa[1] || xa[1] == xa[2] || xa[2] == xa[3] || 
	xa[0] == xa[2] || xa[1] == xa[3] || xa[0] == xa[3]) { 
	printf("Int/Ext Error\n");
	return 0.0;
}
p01 = ya[0] * (x - xa[1]) + ya[1] * (xa[0] - x);
p01 /= (xa[0] - xa[1]);
p12 = ya[1] * (x - xa[2]) + ya[2] * (xa[1] - x);
p12 /= (xa[1] - xa[2]);
p23 = ya[2] * (x - xa[3]) + ya[3] * (xa[2] - x);
p23 /= (xa[2] - xa[3]);
p012 = p01 * (x - xa[2]) + p12 * (xa[0] - x);
p012 /= (xa[0] - xa[2]);
p123 = p12 * (x - xa[3]) + p23 * (xa[1] - x);
p123 /= (xa[1] - xa[3]);
p = p012 * (x - xa[3]) + p123 * (xa[0] - x);
p /= (xa[0] - xa[3]);
return p;
}
double intg(FUNC_T func, double *xvals, double *yvals, double x_min, double x_max) {
int ti;
double sum, stepsize;
double x;
int tnm = 1 << 10;
stepsize = (x_max - x_min) / tnm; 
x = x_min + 0.5 * stepsize;
for(sum = 0.0, ti = 0; ti < tnm; ti++, x+=stepsize) {
	sum += func(xvals, yvals, x);	
}
return stepsize * sum; 
}
int fill_data(FILE *fp) {
int ti, cnt;
float x_val, y_val;
char *buff;
char *buf = (char *)malloc(1024); 
buff = buf;
cnt = 0;
while(1) {
	ti = ReadLine(fp, buff);
	if(ti == EOF) break; 
	ti = 0;
	while(*buff == 32 || *buff == 13 || *buff == 10) {
		if(ti >= 512) break;
		buff++;
	}
	if(buff[0] != '.' && (buff[0] < '0' || buff[0] > '9')) continue;
	if(sscanf(buff, "%f, %f", &x_val, &y_val) < 2) {
		printf("Two numbers per row as '1200000, 32.2'\n"); 
		free(buff);
		return 0;
	}
	else {
		points[cnt][0] = 10 * (log(x_val)/log(10.0));	
		points[cnt][1] = y_val;	
	}
	cnt++;
}
if(cnt > 8) {
	printf("More than 8 points are given\n");
}
free(buf);
if(cnt < 8) return 0;
return 1;
}
int main(int argc, char **argv) {
FILE *fp; 
int x_flag, ti;
double ret_flt1, ret_flt2;
double x_diff;
double coeffs[8];
double x_min, x_max;
if(argc < 3) {
	printf("Usage: bdiff bdbr-or-bdpsnr (1 for bdpsnr) data-fname\n");
	return;
}
x_flag = atoi(argv[1]);
fp = fopen(argv[2], "r");
if(!fp) { 
	printf("CANNOT OPEN FILE: %s\n", argv[1]); 
	return;
}
if(!fill_data(fp)) {
	printf("FILE FORMAT ERROR\n");
	return;
}
x_min = 999999999; 
x_max = -999999999; 
for(ti = 0; ti < 4; ti++) {
	XVAL[ti] = x_flag ? points[ti+4][0]:points[ti+4][1];
	if(x_min > XVAL[ti]) 
		x_min = XVAL[ti];
	if(x_max < XVAL[ti])
		x_max = XVAL[ti];
	YVAL[ti] = x_flag ? points[ti+4][1]:points[ti+4][0];
}
if(x_max <= x_min) {
	printf("Erroneous data\n");
	return;
}
ret_flt2 = intg(polInt, XVAL, YVAL, x_min, x_max);
for(ti = 0; ti < 4; ti++) {
	XVAL[ti] = x_flag ? points[ti][0]:points[ti][1];
	YVAL[ti] = x_flag ? points[ti][1]:points[ti][0];
}
ret_flt1 = intg(polInt, XVAL, YVAL, x_min, x_max);
if(x_flag) {
	printf("%s is %.3f over %s %.3f -- %.3f\n", 
		"BDPSNR", (ret_flt2 - ret_flt1) / (x_max - x_min), "BR", 
		pow(10, x_min/10.0), pow(10, x_max/10.0));
}
else {
	ret_flt1 -= ret_flt2;
	ret_flt1 /= (x_max - x_min);
	printf("%s is %.3f over %s %.3f dB -- %.3f dB\n", 
		"BDBR", ret_flt1 * (pow(10.0, 0.1) - 1.0) * 100, "PSNR", 
		x_min, x_max);
}
}
Message: 2
Date: Thu, 29 Mar 2024 16:41:01 -0700
From: "Caimu Tang" <ctang tutsys.com>
Subject: [Mp4-tech] RE: Mp4-tech Digest, Vol 44, Issue 24
To: <mp4-tech lists.mpegif.org>
Message-ID:
	<7FC2E1F1F429494890EDAA0931D91BE70D0B65 lo-mail.tutsys.com>
Content-Type: text/plain;	charset="iso-8859-1"
Hi Daniel, 
I used following steps to compute BDPSNR and BDBR (total range for 4 evenly spaced QPYs)
Let (r1, q1), ... (r4, q4) be the rate and PSNR corresponding to these four quants for the codec you are worked on.
Let (r*1, q*1), ..., (r*4, q*4) be those for the baseline codec you want to compare with.
(1) use Lagrange interpolation (be carefur for truncation error) to derive a, b, c, d as shown in VCEG-M33 on four points (10 * log(ri), qi) for i = 1, 2, 3, 4. You then obtain 
the curve C1 for your codec.
(2) do the same for the baseline codec to obtain the RD curve C* for the baseline codec.
(3) compute the integral on C and C* from min(r1, r2, r3, r4) to max(r1, r2, r3, r4). 
(4) take the absolute difference of the integral value and divided by 
max(r1, r2, r3, r4) - min(r1, r2, r3, r4)
(5) you get BDPSNR
You can apply the same steps with coordinates switched to obtain BDBR (normally either BDPSNR or BDBR is sufficient for comparison). However, for BDBR, 
the actual rate difference in percentage is calculated as: 
(Note that there is a typo in the second formula in VCEG-M33 Sec. 4.1, 
the left hand-side is 'bit' instead of 'SNR') 
beta * (10^0.1 - 1) * 100, where beta is the value of BDBR in logarithmic scale 
as computed above following the similar steps of (1) to (5).
In VCEG-M33, 0.05 dB = 1% literally means an increase of 0.05 dB in PSNR is tantamont to 1% increase of bitrate (in terms of PSNR video quality). In other words, your codec has an improvement of PSNR by 0.05 dB, that could also be achieved by increase the bitrate by 1%. 
You probably already understands why it is so (applying the same steps as above 
to compute the delta of PSNR and delta of BR).
As a side note, if the Quant step size is too big (rarely in practice though), 
probably mid-range average difference does make sense.
Best Regards,
Caimu Tang
Message: 4
Date: Thu, 29 Mar 2024 14:44:25 +0000
From: "Lee Daniel" <hisaokuani hotmail.com>
Subject: [Mp4-tech] How to calculate BDPSNR and BDBR ?
To: mp4-tech lists.mpegif.org
Message-ID: <BAY115-F237A8353A58014A6FE6C4CCB6C0 phx.gbl>
Content-Type: text/plain; charset=big5; format=flowed
Dear Experts : 
I've read the Document VCEG-M33, but I still don't understand how to 
calculate it.
It said 0.05db=1% and what does it means. 
Besides, there are many papers using these two parameter to measure bits 
and  PSNR.
Can I transform it to PSNR ?  Please help me. I really want to know this.  
Best regards.     
Daniel.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: /pipermail/mp4-tech/attachments/20070405/2c4b8dd4/attachment-0001.html


More information about the Mp4-tech mailing list