1 /* stats.c, coding statistics                                               */
2 
3 /* Copyright (C) 1996, MPEG Software Simulation Group. All Rights Reserved. */
4 
5 /*
6  * Disclaimer of Warranty
7  *
8  * These software programs are available to the user without any license fee or
9  * royalty on an "as is" basis.  The MPEG Software Simulation Group disclaims
10  * any and all warranties, whether express, implied, or statuary, including any
11  * implied warranties or merchantability or of fitness for a particular
12  * purpose.  In no event shall the copyright-holder be liable for any
13  * incidental, punitive, or consequential damages of any kind whatsoever
14  * arising from the use of these programs.
15  *
16  * This disclaimer of warranty extends to the user of these programs and user's
17  * customers, employees, agents, transferees, successors, and assigns.
18  *
19  * The MPEG Software Simulation Group does not represent or warrant that the
20  * programs furnished hereunder are free of infringement of any third-party
21  * patents.
22  *
23  * Commercial implementations of MPEG-1 and MPEG-2 video, including shareware,
24  * are subject to royalty fees to patent holders.  Many of these patents are
25  * general enough such that they are unavoidable regardless of implementation
26  * design.
27  *
28  */
29 
30 #include <stdio.h>
31 #include <math.h>
32 #include "mpeg2enc_config.h"
33 #include "mpeg2enc_global.h"
34 
35 /* private prototypes */
36 static void MPEG2_calcSNR1 _ANSI_ARGS_((unsigned char *org, unsigned char *rec,
37   int lx, int w, int h, double *pv, double *pe));
38 
39 
MPEG2_calcSNR(org,rec,mpeg2_struct)40 void MPEG2_calcSNR(org,rec,mpeg2_struct)
41 unsigned char *org[3];
42 unsigned char *rec[3];
43 struct MPEG2_structure *mpeg2_struct;
44 {
45   int w,h,offs;
46   double v,e;
47 
48   w = mpeg2_struct->horizontal_size;
49   h = (mpeg2_struct->pict_struct==FRAME_PICTURE) ? mpeg2_struct->vertical_size : (mpeg2_struct->vertical_size>>1);
50   offs = (mpeg2_struct->pict_struct==BOTTOM_FIELD) ? mpeg2_struct->width : 0;
51 
52   MPEG2_calcSNR1(org[0]+offs,rec[0]+offs,mpeg2_struct->width2,w,h,&v,&e);
53   if ( mpeg2_struct->statfile )
54     {
55     fprintf(mpeg2_struct->statfile,"Y: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n",
56       v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e));
57     }
58 
59   if (mpeg2_struct->chroma_format!=CHROMA444)
60   {
61     w >>= 1;
62     offs >>= 1;
63   }
64 
65   if (mpeg2_struct->chroma_format==CHROMA420)
66     h >>= 1;
67 
68   MPEG2_calcSNR1(org[1]+offs,rec[1]+offs,mpeg2_struct->chrom_width2,w,h,&v,&e);
69   if ( mpeg2_struct->statfile )
70     {
71     fprintf(mpeg2_struct->statfile,"U: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n",
72       v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e));
73     }
74 
75   MPEG2_calcSNR1(org[2]+offs,rec[2]+offs,mpeg2_struct->chrom_width2,w,h,&v,&e);
76   if ( mpeg2_struct->statfile )
77     {
78     fprintf(mpeg2_struct->statfile,"V: variance=%4.4g, MSE=%3.3g (%3.3g dB), SNR=%3.3g dB\n",
79       v, e, 10.0*log10(255.0*255.0/e), 10.0*log10(v/e));
80     }
81 }
82 
MPEG2_calcSNR1(org,rec,lx,w,h,pv,pe)83 static void MPEG2_calcSNR1(org,rec,lx,w,h,pv,pe)
84 unsigned char *org;
85 unsigned char *rec;
86 int lx,w,h;
87 double *pv,*pe;
88 {
89   int i, j;
90   double v1, s1, s2, e2;
91 
92   s1 = s2 = e2 = 0.0;
93 
94   for (j=0; j<h; j++)
95   {
96     for (i=0; i<w; i++)
97     {
98       v1 = org[i];
99       s1+= v1;
100       s2+= v1*v1;
101       v1-= rec[i];
102       e2+= v1*v1;
103     }
104     org += lx;
105     rec += lx;
106   }
107 
108   s1 /= w*h;
109   s2 /= w*h;
110   e2 /= w*h;
111 
112   /* prevent division by zero in calcSNR() */
113   if(e2==0.0)
114     e2 = 0.00001;
115 
116   *pv = s2 - s1*s1; /* variance */
117   *pe = e2;         /* MSE */
118 }
119 
MPEG2_stats(mpeg2_struct)120 void MPEG2_stats(mpeg2_struct)
121   struct MPEG2_structure *mpeg2_struct;
122 {
123   int i, j, k, nmb, mb_type;
124   int n_skipped, n_intra, n_ncoded, n_blocks, n_interp, n_forward, n_backward;
125   struct mbinfo *mbi;
126 
127   nmb = mpeg2_struct->mb_width*mpeg2_struct->mb_height2;
128 
129   n_skipped=n_intra=n_ncoded=n_blocks=n_interp=n_forward=n_backward=0;
130 
131   for (k=0; k<nmb; k++)
132   {
133     mbi = mpeg2_struct->mbinfo+k;
134     if (mbi->skipped)
135       n_skipped++;
136     else if (mbi->mb_type & MB_INTRA)
137       n_intra++;
138     else if (!(mbi->mb_type & MB_PATTERN))
139       n_ncoded++;
140 
141     for (i=0; i<mpeg2_struct->block_count; i++)
142       if (mbi->cbp & (1<<i))
143         n_blocks++;
144 
145     if (mbi->mb_type & MB_FORWARD)
146     {
147       if (mbi->mb_type & MB_BACKWARD)
148         n_interp++;
149       else
150         n_forward++;
151     }
152     else if (mbi->mb_type & MB_BACKWARD)
153       n_backward++;
154   }
155 
156   if ( mpeg2_struct->statfile )
157     {
158     fprintf(mpeg2_struct->statfile,"\npicture statistics:\n");
159     fprintf(mpeg2_struct->statfile," # of intra coded macroblocks:  %4d (%.1f%%)\n",
160       n_intra,100.0*(double)n_intra/nmb);
161     fprintf(mpeg2_struct->statfile," # of coded blocks:             %4d (%.1f%%)\n",
162       n_blocks,100.0*(double)n_blocks/(mpeg2_struct->block_count*nmb));
163     fprintf(mpeg2_struct->statfile," # of not coded macroblocks:    %4d (%.1f%%)\n",
164       n_ncoded,100.0*(double)n_ncoded/nmb);
165     fprintf(mpeg2_struct->statfile," # of skipped macroblocks:      %4d (%.1f%%)\n",
166       n_skipped,100.0*(double)n_skipped/nmb);
167     fprintf(mpeg2_struct->statfile," # of forw. pred. macroblocks:  %4d (%.1f%%)\n",
168       n_forward,100.0*(double)n_forward/nmb);
169     fprintf(mpeg2_struct->statfile," # of backw. pred. macroblocks: %4d (%.1f%%)\n",
170       n_backward,100.0*(double)n_backward/nmb);
171     fprintf(mpeg2_struct->statfile," # of interpolated macroblocks: %4d (%.1f%%)\n",
172       n_interp,100.0*(double)n_interp/nmb);
173 
174     fprintf(mpeg2_struct->statfile,"\nmacroblock_type map:\n");
175 
176     k = 0;
177 
178     for (j=0; j<mpeg2_struct->mb_height2; j++)
179       {
180       for (i=0; i<mpeg2_struct->mb_width; i++)
181         {
182         mbi = mpeg2_struct->mbinfo + k;
183         mb_type = mbi->mb_type;
184         if (mbi->skipped)
185           putc('S',mpeg2_struct->statfile);
186         else if (mb_type & MB_INTRA)
187           putc('I',mpeg2_struct->statfile);
188         else switch (mb_type & (MB_FORWARD|MB_BACKWARD))
189           {
190         case MB_FORWARD:
191           putc(mbi->motion_type==MC_FIELD ? 'f' :
192             mbi->motion_type==MC_DMV   ? 'p' :
193             'F',mpeg2_struct->statfile); break;
194         case MB_BACKWARD:
195           putc(mbi->motion_type==MC_FIELD ? 'b' :
196             'B',mpeg2_struct->statfile); break;
197         case MB_FORWARD|MB_BACKWARD:
198           putc(mbi->motion_type==MC_FIELD ? 'd' :
199             'D',mpeg2_struct->statfile); break;
200         default:
201           putc('0',mpeg2_struct->statfile); break;
202           }
203 
204         if (mb_type & MB_QUANT)
205           putc('Q',mpeg2_struct->statfile);
206         else if (mb_type & (MB_PATTERN|MB_INTRA))
207           putc(' ',mpeg2_struct->statfile);
208         else
209           putc('N',mpeg2_struct->statfile);
210 
211         putc(' ',mpeg2_struct->statfile);
212 
213         k++;
214         }
215       putc('\n',mpeg2_struct->statfile);
216       }
217 
218     fprintf(mpeg2_struct->statfile,"\nmquant map:\n");
219 
220     k=0;
221     for (j=0; j<mpeg2_struct->mb_height2; j++)
222       {
223       for (i=0; i<mpeg2_struct->mb_width; i++)
224         {
225         if (i==0 || mpeg2_struct->mbinfo[k].mquant!=mpeg2_struct->mbinfo[k-1].mquant)
226           fprintf(mpeg2_struct->statfile,"%3d",mpeg2_struct->mbinfo[k].mquant);
227         else
228           fprintf(mpeg2_struct->statfile,"   ");
229 
230         k++;
231         }
232       putc('\n',mpeg2_struct->statfile);
233       }
234 
235 #if 0
236     fprintf(mpeg2_struct->statfile,"\ncbp map:\n");
237 
238     k=0;
239     for (j=0; j<mpeg2_struct->mb_height2; j++)
240       {
241       for (i=0; i<mpeg2_struct->mb_width; i++)
242         {
243         fprintf(mpeg2_struct->statfile,"%02x ",mpeg2_struct->mbinfo[k].cbp);
244 
245         k++;
246         }
247       putc('\n',mpeg2_struct->statfile);
248       }
249 
250     if (mpeg2_struct->pict_struct==FRAME_PICTURE && !mpeg2_struct->frame_pred_dct)
251       {
252       fprintf(mpeg2_struct->statfile,"\ndct_type map:\n");
253 
254       k=0;
255       for (j=0; j<mpeg2_struct->mb_height2; j++)
256         {
257         for (i=0; i<mpeg2_struct->mb_width; i++)
258           {
259           if (mpeg2_struct->mbinfo[k].mb_type & (MB_PATTERN|MB_INTRA))
260             fprintf(mpeg2_struct->statfile,"%d  ",mpeg2_struct->mbinfo[k].dct_type);
261           else
262             fprintf(mpeg2_struct->statfile,"   ");
263 
264           k++;
265           }
266         putc('\n',mpeg2_struct->statfile);
267         }
268       }
269 
270     if (mpeg2_struct->pict_type!=I_TYPE)
271       {
272       fprintf(mpeg2_struct->statfile,"\nforward motion vectors (first vector, horizontal):\n");
273 
274       k=0;
275       for (j=0; j<mpeg2_struct->mb_height2; j++)
276         {
277         for (i=0; i<mpeg2_struct->mb_width; i++)
278           {
279           if (mpeg2_struct->mbinfo[k].mb_type & MB_FORWARD)
280             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[0][0][0]);
281           else
282             fprintf(mpeg2_struct->statfile,"   .");
283 
284           k++;
285           }
286         putc('\n',mpeg2_struct->statfile);
287         }
288 
289       fprintf(mpeg2_struct->statfile,"\nforward motion vectors (first vector, vertical):\n");
290 
291       k=0;
292       for (j=0; j<mpeg2_struct->mb_height2; j++)
293         {
294         for (i=0; i<mpeg2_struct->mb_width; i++)
295           {
296           if (mpeg2_struct->mbinfo[k].mb_type & MB_FORWARD)
297             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[0][0][1]);
298           else
299             fprintf(mpeg2_struct->statfile,"   .");
300 
301           k++;
302           }
303         putc('\n',mpeg2_struct->statfile);
304         }
305 
306       fprintf(mpeg2_struct->statfile,"\nforward motion vectors (second vector, horizontal):\n");
307 
308       k=0;
309       for (j=0; j<mpeg2_struct->mb_height2; j++)
310         {
311         for (i=0; i<mpeg2_struct->mb_width; i++)
312           {
313           if (mpeg2_struct->mbinfo[k].mb_type & MB_FORWARD
314             && ((mpeg2_struct->pict_struct==FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_FIELD) ||
315               (mpeg2_struct->pict_struct!=FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_16X8)))
316             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[1][0][0]);
317           else
318             fprintf(mpeg2_struct->statfile,"   .");
319 
320           k++;
321           }
322         putc('\n',mpeg2_struct->statfile);
323         }
324 
325       fprintf(mpeg2_struct->statfile,"\nforward motion vectors (second vector, vertical):\n");
326 
327       k=0;
328       for (j=0; j<mpeg2_struct->mb_height2; j++)
329         {
330         for (i=0; i<mpeg2_struct->mb_width; i++)
331           {
332           if (mpeg2_struct->mbinfo[k].mb_type & MB_FORWARD
333             && ((mpeg2_struct->pict_struct==FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_FIELD) ||
334               (mpeg2_struct->pict_struct!=FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_16X8)))
335             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[1][0][1]);
336           else
337             fprintf(mpeg2_struct->statfile,"   .");
338 
339           k++;
340           }
341         putc('\n',mpeg2_struct->statfile);
342         }
343 
344 
345       }
346 
347     if (mpeg2_struct->pict_type==B_TYPE)
348       {
349       fprintf(mpeg2_struct->statfile,"\nbackward motion vectors (first vector, horizontal):\n");
350 
351       k=0;
352       for (j=0; j<mpeg2_struct->mb_height2; j++)
353         {
354         for (i=0; i<mpeg2_struct->mb_width; i++)
355           {
356           if (mpeg2_struct->mbinfo[k].mb_type & MB_BACKWARD)
357             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[0][1][0]);
358           else
359             fprintf(mpeg2_struct->statfile,"   .");
360 
361           k++;
362           }
363         putc('\n',mpeg2_struct->statfile);
364         }
365 
366       fprintf(mpeg2_struct->statfile,"\nbackward motion vectors (first vector, vertical):\n");
367 
368       k=0;
369       for (j=0; j<mpeg2_struct->mb_height2; j++)
370         {
371         for (i=0; i<mpeg2_struct->mb_width; i++)
372           {
373           if (mpeg2_struct->mbinfo[k].mb_type & MB_BACKWARD)
374             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[0][1][1]);
375           else
376             fprintf(mpeg2_struct->statfile,"   .");
377 
378           k++;
379           }
380         putc('\n',mpeg2_struct->statfile);
381         }
382 
383       fprintf(mpeg2_struct->statfile,"\nbackward motion vectors (second vector, horizontal):\n");
384 
385       k=0;
386       for (j=0; j<mpeg2_struct->mb_height2; j++)
387         {
388         for (i=0; i<mpeg2_struct->mb_width; i++)
389           {
390           if (mpeg2_struct->mbinfo[k].mb_type & MB_BACKWARD
391             && ((mpeg2_struct->pict_struct==FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_FIELD) ||
392               (mpeg2_struct->pict_struct!=FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_16X8)))
393             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[1][1][0]);
394           else
395             fprintf(mpeg2_struct->statfile,"   .");
396 
397           k++;
398           }
399         putc('\n',mpeg2_struct->statfile);
400         }
401 
402       fprintf(mpeg2_struct->statfile,"\nbackward motion vectors (second vector, vertical):\n");
403 
404       k=0;
405       for (j=0; j<mpeg2_struct->mb_height2; j++)
406         {
407         for (i=0; i<mpeg2_struct->mb_width; i++)
408           {
409           if (mpeg2_struct->mbinfo[k].mb_type & MB_BACKWARD
410             && ((mpeg2_struct->pict_struct==FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_FIELD) ||
411               (mpeg2_struct->pict_struct!=FRAME_PICTURE && mpeg2_struct->mbinfo[k].motion_type==MC_16X8)))
412             fprintf(mpeg2_struct->statfile,"%4d",mpeg2_struct->mbinfo[k].MV[1][1][1]);
413           else
414             fprintf(mpeg2_struct->statfile,"   .");
415 
416           k++;
417           }
418         putc('\n',mpeg2_struct->statfile);
419         }
420 
421 
422       }
423 #endif
424 
425 #if 0
426     /* useful for debugging */
427     fprintf(mpeg2_struct->statfile,"\nmacroblock info dump:\n");
428 
429     k=0;
430     for (j=0; j<mpeg2_struct->mb_height2; j++)
431       {
432       for (i=0; i<mpeg2_struct->mb_width; i++)
433         {
434         fprintf(mpeg2_struct->statfile,"%d: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
435           k,
436           mpeg2_struct->mbinfo[k].mb_type,
437           mpeg2_struct->mbinfo[k].motion_type,
438           mpeg2_struct->mbinfo[k].dct_type,
439           mpeg2_struct->mbinfo[k].mquant,
440           mpeg2_struct->mbinfo[k].cbp,
441           mpeg2_struct->mbinfo[k].skipped,
442           mpeg2_struct->mbinfo[k].MV[0][0][0],
443           mpeg2_struct->mbinfo[k].MV[0][0][1],
444           mpeg2_struct->mbinfo[k].MV[0][1][0],
445           mpeg2_struct->mbinfo[k].MV[0][1][1],
446           mpeg2_struct->mbinfo[k].MV[1][0][0],
447           mpeg2_struct->mbinfo[k].MV[1][0][1],
448           mpeg2_struct->mbinfo[k].MV[1][1][0],
449           mpeg2_struct->mbinfo[k].MV[1][1][1],
450           mpeg2_struct->mbinfo[k].mv_field_sel[0][0],
451           mpeg2_struct->mbinfo[k].mv_field_sel[0][1],
452           mpeg2_struct->mbinfo[k].mv_field_sel[1][0],
453           mpeg2_struct->mbinfo[k].mv_field_sel[1][1]);
454 
455         k++;
456         }
457       }
458 #endif
459     }
460 }
461