home *** CD-ROM | disk | FTP | other *** search
/ Skunkware 5 / Skunkware 5.iso / src / Tools / mpeg_stat-2.2 / filter.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-10  |  22.6 KB  |  755 lines

  1. /* MPEGSTAT - analyzing tool for MPEG-I video streams
  2.  * 
  3.  *
  4.  *  Copyright (c) 1995 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * Technical University of Berlin, Germany, Dept. of Computer Science
  8.  * Tom Pfeifer - Multimedia systems project - pfeifer@fokus.gmd.de
  9.  *
  10.  * Jens Brettin, Harald Masche, Alexander Schulze, Dirk Schubert
  11.  *
  12.  * ---------------------------
  13.  *
  14.  * Copyright (c) 1993 Technical University of Berlin, Germany
  15.  * All rights reserved.
  16.  *
  17.  * ---------------------------
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software and its
  20.  * documentation for any purpose, without fee, and without written agreement is
  21.  * hereby granted, provided that the above copyright notices and the following
  22.  * two paragraphs appear in all copies of this software.
  23.  * 
  24.  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA 
  25.  * or the Technical University of Berlin BE LIABLE TO ANY PARTY FOR
  26.  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
  27.  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
  28.  * CALIFORNIA or the Technical University of Berlin HAS BEEN ADVISED OF THE 
  29.  * POSSIBILITY OF SUCH DAMAGE.
  30.  * 
  31.  * THE UNIVERSITY OF CALIFORNIA and the Technical University of Berlin 
  32.  * SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
  33.  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.  * PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE 
  35.  * UNIVERSITY OF CALIFORNIA and the Technical University of Berlin HAVE NO 
  36.  * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, 
  37.  * OR MODIFICATIONS.
  38.  */
  39.  
  40. /*
  41.  * analyzing routines
  42.  * Most of the specilized statistics routines are here.
  43.  */
  44.  
  45. #include <stdio.h>
  46. #include "video.h"
  47. #include "opts.h"
  48. #include "proto.h"
  49. #ifndef MIPS
  50. #include <sys/time.h>
  51. #else
  52. #include <sys/types.h>
  53. #include <sys/system.h>
  54. #endif
  55.  
  56. /* Variables from Video.c */
  57. extern Statval stat_a[4];
  58. extern BlockVals blks;
  59. extern char *VidRate[16];
  60. extern double VidRateNum[16];
  61. extern char *PelRatio[16];
  62. extern int sys_layer, vidBytes, audBytes, sysBytes;
  63. extern int rate_disp, rate_max, rate_min, f_code_ok;
  64.  
  65. /* Local Routines */
  66. #define max(a,b)  (a>b?a:b)
  67. static void init_stat_struct();
  68.  
  69. /*
  70.  * mvstat
  71.  * 
  72.  * Keep motion vector statistics
  73.  *
  74.  */
  75. int mvstat (value, mode)
  76. int value, mode;
  77. {
  78.   static int max_horizontal_f = 0, max_vertical_f = 0;
  79.   static int  max_horizontal_b = 0, max_vertical_b = 0;
  80.   static int ave_h_b = 0, ave_h_f = 0, ave_v_b = 0, ave_v_f = 0;
  81.   static int count_h_b = 0, count_h_f = 0, count_v_b = 0, count_v_f = 0;
  82.   int *ip;
  83.   
  84.   switch (mode) {
  85.   case 0:
  86.     ip = &max_horizontal_f;
  87.     count_h_f++;
  88.     ave_h_f += abs(value);
  89.     break;
  90.   case 1:
  91.     ip = &max_vertical_f;
  92.     count_v_f++;
  93.     ave_v_f += abs(value);
  94.     break;
  95.   case 2:
  96.     ip = &max_horizontal_b;
  97.     count_h_b++;
  98.     ave_h_b += abs(value);
  99.     break;
  100.   case 3:
  101.     ip = &max_vertical_b;
  102.       count_v_b++;
  103.       ave_v_b += abs(value);
  104.     break;
  105.   case 5:
  106.     return max_horizontal_f;
  107.   case 6:
  108.     return max_vertical_f;
  109.   case 7:
  110.     return max_horizontal_b;
  111.   case 8:
  112.     return max_vertical_b;
  113.   case 10 :
  114.     if (count_h_f > 0)
  115.       return( ave_h_f / count_h_f);
  116.     else return -1;
  117.   case 11 :
  118.     if (count_v_f > 0)
  119.       return( ave_v_f / count_v_f);
  120.     else return -1;
  121.   case 12 :
  122.     if (count_h_b > 0)
  123.       return( ave_h_b / count_h_b);
  124.     else return -1;
  125.   case 13 :
  126.     if (count_v_b > 0)
  127.       return( ave_v_b / count_v_b);
  128.     else return -1;
  129.     
  130.   }
  131.   *ip = max (*ip, abs (value));
  132.   return 0;
  133. }
  134.  
  135.  
  136. /*
  137.  * printtype prints the frame type during data parsing.
  138.  */
  139. printtype(vs)
  140. VidStream *vs;
  141. {
  142.  
  143.   static int first_time = 1;
  144.   
  145.   if(first_time) {
  146.     printf("Picture coding types (bitstream order / display order):\n");
  147.     first_time = 0;
  148.   }
  149.   
  150.   switch (vs->picture.code_type) {
  151.   case B_TYPE:
  152.     printf("B");
  153.     break;
  154.   case P_TYPE:
  155.     printf("P");
  156.     break;
  157.   case I_TYPE:
  158.     printf("I");
  159.     break;
  160.   default:
  161.     printf("?");
  162.   }
  163.   fflush(stdout);
  164. }
  165.  
  166. /*
  167.  * init_block_struct
  168.  *
  169.  * Setup the block data structure to collect detailed data.
  170.  *
  171.  */
  172. void init_block_struct(a)
  173. BlockVals *a;
  174. {
  175.    int i,j;
  176.    a->frame=-1;
  177.    a->slice=-1;
  178.    a->block=0;
  179.    a->btype=0;
  180.    a->qs=0;
  181.    a->mb_skipped=0;
  182.    a->mb_coded=0;
  183.    a->cblks=0;
  184.    a->nblks=0;
  185.    for (i=0; i<6; i++) a->chist[i]=0;
  186.    for (i=1; i<4; i++) {
  187.      for (j=1; j<32;j++) {
  188.        a->q[i][j]=0;
  189.      }}
  190.  }
  191.  
  192.  
  193. /*
  194.  * init_stats
  195.  *
  196.  * Setup the statistics structures
  197.  *
  198.  */
  199. void
  200. init_stats()
  201. {
  202.   int i, j;
  203.  
  204.   for (i = 0; i < 4; i++) {
  205.     init_stat_struct(&(stat_a[i]));
  206.     stat_a[i].frametype = i;
  207.   }
  208.   bitCount = 0;
  209.   init_block_struct(&blks);
  210. }
  211.  
  212. /*
  213.  * PrintAllStats
  214.  *
  215.  * Print the summary statistics for the entire stream
  216.  *
  217.  */
  218. void
  219. PrintAllStats()
  220. {
  221.   int i, j;
  222.   int average, pixelnum;
  223.  
  224.   unsigned int supertot, supernum;
  225.   double supertime;
  226.  
  227.   pixelnum = curVidStream->mb_width * 16 * curVidStream->mb_height * 16;
  228.  
  229.   printf("\nSUMMARY:\n\n");
  230.  
  231.   supertot = stat_a[1].totsize + stat_a[2].totsize + stat_a[3].totsize;
  232.   supernum = stat_a[1].number + stat_a[2].number + stat_a[3].number;
  233.   supertime = stat_a[1].tottime + stat_a[2].tottime + stat_a[3].tottime;
  234.  
  235.   if (sys_layer) {
  236.     printf("Total number of frames: %d.  Length is %2.2f sec\n\n",
  237.        supernum, supernum*1.0/VidRateNum[curVidStream->picture_rate]);
  238.     } else {
  239.       printf("Total Bytes read: %d. Total number of frames: %d.  Length is %2.2f sec\n\n",
  240.          bitCountRead()/8, supernum, supernum*1.0/VidRateNum[curVidStream->picture_rate]);
  241.     }
  242.   printf("Width: %d\tHeight: %d\n", curVidStream->h_size,curVidStream->v_size);
  243.  
  244.   printf("Avg. Frame Size: %d bytes + %d bits  (average rate %2.2f bits/sec)\n",
  245.      supertot / (8 * supernum), (supertot / supernum) % 8,
  246.      1.0*supertot* VidRateNum[curVidStream->picture_rate] / supernum );
  247.   if (opts&RATE_INFO) {
  248.     if (opts&RATE_LENGTH_SET) {
  249.       if (sys_layer) {
  250.     int totBytes=vidBytes+audBytes+sysBytes;
  251.     printf("Breakdown of system layer:\n");
  252.     printf("\tVideo (with packet headers): %d bytes (%2.2f%%) %d/(%d frames)\n",
  253.            vidBytes,vidBytes*100.0/totBytes, vidBytes/rate_disp,rate_disp);
  254.     printf("\tAudio (with packet headers): %d bytes (%2.2f%%) %d/(%d frames)\n",
  255.            audBytes,audBytes*100.0/totBytes,audBytes/rate_disp,rate_disp);
  256.     printf("\tSystem (other headers, other packets, etc): %d bytes (%2.2f%%) %d/(%d frames)\n",
  257.            sysBytes,sysBytes*100.0/totBytes,sysBytes/rate_disp,rate_disp);
  258.       }
  259.       printf("Max instantaneous video rate %d, minimum %d bits/(%d frames)\n",
  260.          rate_max,rate_min,rate_disp);
  261.     } else {
  262.       if (sys_layer) {
  263.     int totBytes=vidBytes+audBytes+sysBytes;
  264.     int rate_disp=(int)(VidRateNum[curVidStream->picture_rate]+0.5);
  265.     printf("Breakdown of system layer:\n");
  266.     printf("    Video (no packet headers): %d bytes (%2.2f%%) %d bytes/sec\n",
  267.            vidBytes,vidBytes*100.0/totBytes, vidBytes/rate_disp);
  268.     printf("    Audio (no packet headers): %d bytes (%2.2f%%) %d bytes/sec\n",
  269.            audBytes,audBytes*100.0/totBytes,audBytes/rate_disp);
  270.     printf("    System (other headers, packets, etc): %d bytes (%2.2f%%) %d bytes/sec\n",
  271.            sysBytes,sysBytes*100.0/totBytes,sysBytes/rate_disp);
  272.       }
  273.       printf("Max instantaneous video rate %d, minimum %d bits/sec\n",
  274.          rate_max,rate_min);
  275.     }
  276.   } else {
  277.     if (sys_layer) {
  278.       int totBytes=vidBytes+audBytes+sysBytes;
  279.       int rate_disp=(int)(VidRateNum[curVidStream->picture_rate]+0.5);
  280.       printf("Breakdown of system layer:\n");
  281.       printf("    Video (no packet headers): %d bytes (%2.2f%%) %d bytes/sec\n",
  282.          vidBytes,vidBytes*100.0/totBytes, vidBytes/rate_disp);
  283.       printf("    Audio (no packet headers): %d bytes (%2.2f%%) %d bytes/sec\n",
  284.          audBytes,audBytes*100.0/totBytes,audBytes/rate_disp);
  285.       printf("    System (other headers, packets, etc): %d bytes (%2.2f%%) %d bytes/sec\n",
  286.          sysBytes,sysBytes*100.0/totBytes,sysBytes/rate_disp);
  287.     }
  288.   }
  289.   
  290.   printf("\nTotal Compression Rate: %5.2f %% of uncompressed 24 bit images\n", 
  291.         ((float)supertot/(8.0*(float)supernum))*100.0 / 
  292.                 ((float)pixelnum*3.0) );
  293.  
  294.   printf("                        = %5.2f bits per pixel\n\n", 
  295.         .24 * (((float)supertot/(8.0*(float)supernum))*100.0 / 
  296.                 ((float)pixelnum*3.0)) );
  297.  
  298.   printf("Number of Macroblocks");
  299.   printf(" [width * height = sum]: %d x %d = %d per frame\n", 
  300.          curVidStream->mb_width, curVidStream->mb_height,
  301.      curVidStream->mb_width * curVidStream->mb_height);
  302.   printf("Skipped Macroblocks = %d (%2.2f%%), Coded Macroblocks = %d (%2.2f%%)\n",
  303.      blks.mb_skipped,blks.mb_skipped*100.0/(blks.mb_skipped+blks.mb_coded),
  304.      blks.mb_coded,blks.mb_coded*100.0/(blks.mb_skipped+blks.mb_coded));
  305.   if (blks.cblks==0) printf("\tNo partially coded macroblocks.\n\n");
  306.   else {
  307.     printf("\tCoded blocks: %2.2f%%\t[",100.0*blks.cblks/blks.nblks);
  308.     for (i=0; i<6; i++) {
  309.       printf(" %2.2f ",100.0*blks.chist[i]/blks.cblks);
  310.     }
  311.     printf("]\n\n");
  312.   }
  313.  
  314.   if (opts&TIME_MEASURE)
  315.     printf("Total Time Decoding: %.4g secs. %.4g sec/frame or %.4g frames/sec.\n\n", 
  316.        supertime,supertime / ((double) supernum),((double) supernum) / supertime);
  317.  
  318.   printf("MPEG-Viewer requirements:\n");
  319.   printf("\tPixel aspect ratio of %s\n",PelRatio[curVidStream->aspect_ratio]);
  320.   printf("\tRequired display speed: %s\n",VidRate[curVidStream->picture_rate]);
  321.   printf("\tSpecified bit rate is ");
  322.   if (curVidStream->bit_rate==0x3FFFF) printf ("variable\n");
  323.   else {
  324.     int rt=curVidStream->bit_rate;
  325.     if (rt<3) printf("%d bits/sec",400*rt);
  326.     else if (rt<2500) printf("%4.2f KBits/sec",rt*0.4);
  327.     else printf("%4.2f MBits/sec",rt*0.0004);
  328.     printf(" (%d * 400bits/sec)\n",rt);
  329.   }
  330.   printf("\tRequested buffer size is %dK ints (16 bits/int).\n",
  331.      curVidStream->vbv_buffer_size);
  332.   printf("\tAnd the constrained parameter flag is %s.\n",
  333.      curVidStream->const_param_flag?"on":"off");
  334.   { /* Check to see if it actually *meets* the constrained parameters */
  335.     int num_mb = curVidStream->mb_width * curVidStream->mb_height;
  336.     int pict_rate = curVidStream->orig_picture_rate;
  337.  
  338.     if ((curVidStream->bit_rate <= 3712) &&
  339.     (curVidStream->vbv_buffer_size <= 20) &&
  340.     (pict_rate >= 1) &&
  341.     (pict_rate <= 5) &&
  342.     (curVidStream->h_size <= 768) &&
  343.     (curVidStream->v_size <= 576) &&
  344.     (num_mb * VidRateNum[pict_rate] <= 9900) &&
  345.     f_code_ok &&
  346.     (num_mb <= 396))
  347.       printf("\tThe stream meets the constrained parameter requirements.\n");
  348.     else {
  349.       if ((curVidStream->vbv_buffer_size <= 20) &&
  350.       (num_mb*15 <= 9900) &&
  351.       (curVidStream->h_size <= 768) &&
  352.       (curVidStream->v_size <= 576) &&
  353.       f_code_ok &&
  354.       (pict_rate==9) &&  /* Illegal Xing sequence */
  355.       (num_mb <= 396)) {
  356.     printf("\tOther than its invalid picture & bit rates, the stream meets the\n");
  357.     printf("\t\tconstrained parameters (with rate corrected to 15).\n");
  358.       } else {
  359.     printf("\tThe stream does not meet the constrained parameter requirements,\n");
  360.     printf("\tdue to the following factors:\n");
  361.     if (curVidStream->bit_rate > 3712) 
  362.       printf("\t\tBit rate is %s.\n",
  363.          (curVidStream->bit_rate==0x3FFFF) ? "variable":"too high");
  364.     if (curVidStream->vbv_buffer_size > 20) 
  365.       printf("\t\tVBV buffer is too large (%d bits).\n",
  366.          curVidStream->vbv_buffer_size*20*1024);
  367.     if (pict_rate == 0) 
  368.       printf("\t\tPicture rate is invalid (0).\n");
  369.     if (VidRateNum[pict_rate] > 31) 
  370.       printf("\t\tPicture rate is too high.\n");
  371.     if (curVidStream->h_size > 768) 
  372.       printf("\t\tPicture is too wide.\n");
  373.     if (curVidStream->v_size > 576) 
  374.       printf("\t\tPicture is too high (tall).\n");
  375.     if (pict_rate > 8) 
  376.       printf("\t\tPicture rate is invalid (code is %d).\n",pict_rate);
  377.     if (num_mb*VidRateNum[pict_rate] > 9900)
  378.       printf("\t\tPixels per second is too high.\n");
  379.     if (!f_code_ok) 
  380.       printf("\t\tMotion vectors are larger than 8 (f_code>4)\n");
  381.     if (num_mb > 396) 
  382.       printf("\t\tThere are too many macroblocks per second.\n");
  383.       }}}
  384.   
  385.   if (mvstat(0,5)==0 && mvstat(0,6)==0 && mvstat(0,7)==0 && mvstat(8,0)==0) {
  386.     printf("\nNo motion vectors.\n");
  387.   } else {
  388.     printf("\nLength of vectors in half pixels:\n");
  389.     
  390.     printf ("\tHorizontal forward vectors, maximum : %3d\taverage: %3d\n", 
  391.         mvstat (0, 5), mvstat(0, 10));
  392.     printf ("\tVertical forward vectors, maximum   : %3d\taverage: %3d\n\n", 
  393.         mvstat (0, 6), mvstat(0, 11));
  394.     printf ("\tHorizontal backward vectors, maximum: %3d\taverage: %3d\n", 
  395.         mvstat (0, 7), mvstat(0, 12));
  396.     printf ("\tVertical backward vectors, maximum  : %3d\taverage: %3d\n", 
  397.         mvstat (0, 8), mvstat(0, 13));
  398.   }
  399.   
  400.   printf("\n\nFrame specific information:\n\n");
  401.   
  402.   for (i = 1; i < 4; i++) {
  403.  
  404.     if (stat_a[i].number == 0)
  405.       continue;
  406.  
  407.     printf("    %-3d %c FRAMES, average is:\n", stat_a[i].number, "IPB"[i-1]);
  408.  
  409.     average = stat_a[i].totsize / (8 * stat_a[i].number);
  410.     printf("\tSize: %d bytes + %d bits (%2.2f%%)\n",
  411.        average, (stat_a[i].totsize / stat_a[i].number) % 8,
  412.        100.0*stat_a[i].totsize/supertot);
  413.  
  414.     printf("\tCompression Rate: %5.2f%%\n", 
  415.     (float)average*100.0/ ( (float) pixelnum*3.0));
  416.  
  417.     printf("\tQ Factor [scales quantization matrix]: %2.2f\n", 
  418.        (1.0*stat_a[i].qual)/stat_a[i].qnum);
  419.  
  420.     if (stat_a[i].bi_mbnum > 0) {
  421.       printf("\t%5.2f%% interpolated Macro Blocks\n", 
  422.     ((float) stat_a[i].bi_mbnum*100.0) / (stat_a[i].i_mbnum + 
  423.     stat_a[i].p_mbnum + stat_a[i].b_mbnum + stat_a[i].bi_mbnum));
  424.     }
  425.     if (opts&TIME_MEASURE) 
  426.       printf("\tTime to Decode: %f secs.\n",
  427.          (stat_a[i].tottime / ((double) stat_a[i].number)));
  428.     printf("\n");
  429.     if (opts&QSCALE_INFO) {
  430.       fprintf(qscale_fp,"Block Quality Information (for %c Frames)\n\tQuality\tNumber\n",
  431.           "0IPB"[i]);
  432.       for (j=1; j<32; j++) {
  433.     if (blks.q[i][j]!=0) {
  434.       fprintf(qscale_fp,"\t%d\t%d\n",j,blks.q[i][j]);
  435.     }}
  436.       fprintf(qscale_fp,"\n");
  437.     }
  438.   }
  439.   if (curVidStream->user_data != NULL) {
  440.     printf("\tUser Data Specified (at sequence level):\n");
  441.     print_binary(stdout, curVidStream->user_data, curVidStream->user_size);
  442.   }
  443.  
  444.   if (opts&HIST_INFO) {
  445.     PrintSummaryStat(1);
  446.     PrintSummaryStat(2);
  447.     PrintSummaryStat(3);
  448.   }
  449. }
  450.  
  451.  
  452. /*
  453.  * PrintSummaryStat
  454.  *
  455.  * Print the detailed Historgrams on particular frame types
  456.  *
  457.  */
  458. void
  459. PrintSummaryStat(typ)
  460. int typ;
  461. {
  462.   int i;
  463.   
  464.   fprintf(hist_fp,"\n");
  465.   switch (stat_a[typ].frametype) {
  466.   case I_TYPE:
  467.     fprintf(hist_fp,"I FRAME\n");
  468.     break;
  469.   case P_TYPE:
  470.     fprintf(hist_fp,"P FRAME\n");
  471.     break;
  472.   case B_TYPE:
  473.     fprintf(hist_fp,"B FRAME\n");
  474.     break;
  475.   }
  476.   
  477.   fprintf(hist_fp,"Size: %d bytes + %d bits\n", stat_a[typ].totsize / 8, stat_a[typ].totsize % 8);
  478.   if (stat_a[typ].i_mbnum > 0) {
  479.     fprintf(hist_fp,"\tI Macro Block Stats:\n");
  480.     fprintf(hist_fp,"\t%d I Macroblocks\n", stat_a[typ].i_mbnum);
  481.     fprintf(hist_fp,"\tAvg. Size: %d bytes + %d bits\n",
  482.         stat_a[typ].i_mbsize / (8 * stat_a[typ].i_mbnum),
  483.         (stat_a[typ].i_mbsize * stat_a[typ].i_mbnum) % 8);
  484.     fprintf(hist_fp,"\t\tCoded Block Pattern Histogram:\n");
  485.     for (i = 0; i < 64; i += 8) {
  486.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].i_mbcbp[i],
  487.           stat_a[typ].i_mbcbp[i + 1], stat_a[typ].i_mbcbp[i + 2], stat_a[typ].i_mbcbp[i + 3],
  488.           stat_a[typ].i_mbcbp[i + 4], stat_a[typ].i_mbcbp[i + 5], stat_a[typ].i_mbcbp[i + 6],
  489.           stat_a[typ].i_mbcbp[i + 7]);
  490.     }
  491.     fprintf(hist_fp,"\n\t\tNumber of Coefficients/Block Histogram:\n");
  492.     for (i = 0; i < 64; i += 8) {
  493.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].i_mbcoeff[i],
  494.           stat_a[typ].i_mbcoeff[i + 1], stat_a[typ].i_mbcoeff[i + 2],
  495.           stat_a[typ].i_mbcoeff[i + 3], stat_a[typ].i_mbcoeff[i + 4],
  496.           stat_a[typ].i_mbcoeff[i + 5], stat_a[typ].i_mbcoeff[i + 6],
  497.           stat_a[typ].i_mbcoeff[i + 7]);
  498.     }
  499.   }
  500.   if (stat_a[typ].p_mbnum > 0) {
  501.     fprintf(hist_fp,"\tP Macro Block Stats:\n");
  502.     fprintf(hist_fp,"\t%d P Macroblocks\n", stat_a[typ].p_mbnum);
  503.     fprintf(hist_fp,"\tAvg. Size: %d bytes + %d bits\n",
  504.         stat_a[typ].p_mbsize / (8 * stat_a[typ].p_mbnum),
  505.         (stat_a[typ].p_mbsize / stat_a[typ].p_mbnum) % 8);
  506.     fprintf(hist_fp,"\t\tCoded Block Pattern Histogram:\n");
  507.     for (i = 0; i < 64; i += 8) {
  508.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].p_mbcbp[i],
  509.           stat_a[typ].p_mbcbp[i + 1], stat_a[typ].p_mbcbp[i + 2], stat_a[typ].p_mbcbp[i + 3],
  510.           stat_a[typ].p_mbcbp[i + 4], stat_a[typ].p_mbcbp[i + 5], stat_a[typ].p_mbcbp[i + 6],
  511.           stat_a[typ].p_mbcbp[i + 7]);
  512.     }
  513.     fprintf(hist_fp,"\n\t\tNumber of Coefficients/Block Histogram:\n");
  514.     for (i = 0; i < 64; i += 8) {
  515.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].p_mbcoeff[i],
  516.           stat_a[typ].p_mbcoeff[i + 1], stat_a[typ].p_mbcoeff[i + 2],
  517.           stat_a[typ].p_mbcoeff[i + 3], stat_a[typ].p_mbcoeff[i + 4],
  518.           stat_a[typ].p_mbcoeff[i + 5], stat_a[typ].p_mbcoeff[i + 6],
  519.           stat_a[typ].p_mbcoeff[i + 7]);
  520.     }
  521.   }
  522.   if (stat_a[typ].b_mbnum > 0) {
  523.     fprintf(hist_fp,"\tB Macro Block Stats:\n");
  524.     fprintf(hist_fp,"\t%d B Macroblocks\n", stat_a[typ].b_mbnum);
  525.     fprintf(hist_fp,"\tAvg. Size: %d bytes + %d bits\n",
  526.         stat_a[typ].b_mbsize / (8 * stat_a[typ].b_mbnum),
  527.         (stat_a[typ].b_mbsize / stat_a[typ].b_mbnum) % 8);
  528.     fprintf(hist_fp,"\t\tCoded Block Pattern Histogram:\n");
  529.     for (i = 0; i < 64; i += 8) {
  530.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].b_mbcbp[i],
  531.           stat_a[typ].b_mbcbp[i + 1], stat_a[typ].b_mbcbp[i + 2], stat_a[typ].b_mbcbp[i + 3],
  532.           stat_a[typ].b_mbcbp[i + 4], stat_a[typ].b_mbcbp[i + 5], stat_a[typ].b_mbcbp[i + 6],
  533.           stat_a[typ].b_mbcbp[i + 7]);
  534.     }
  535.     fprintf(hist_fp,"\n\t\tNumber of Coefficients/Block Histogram:\n");
  536.     for (i = 0; i < 64; i += 8) {
  537.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].b_mbcoeff[i],
  538.           stat_a[typ].b_mbcoeff[i + 1], stat_a[typ].b_mbcoeff[i + 2],
  539.           stat_a[typ].b_mbcoeff[i + 3], stat_a[typ].b_mbcoeff[i + 4],
  540.           stat_a[typ].b_mbcoeff[i + 5], stat_a[typ].b_mbcoeff[i + 6],
  541.           stat_a[typ].b_mbcoeff[i + 7]);
  542.     }
  543.   }
  544.   if (stat_a[typ].bi_mbnum > 0) {
  545.     fprintf(hist_fp,"\tBi Macro Block Stats:\n");
  546.     fprintf(hist_fp,"\t%d Bi Macroblocks\n", stat_a[typ].bi_mbnum);
  547.     fprintf(hist_fp,"\tAvg. Size: %d bytes + %d bits\n",
  548.         stat_a[typ].bi_mbsize / (8 * stat_a[typ].bi_mbnum),
  549.         (stat_a[typ].bi_mbsize * stat_a[typ].bi_mbnum) % 8);
  550.     fprintf(hist_fp,"\t\tCoded Block Pattern Histogram:\n");
  551.     for (i = 0; i < 64; i += 8) {
  552.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].bi_mbcbp[i],
  553.           stat_a[typ].bi_mbcbp[i + 1], stat_a[typ].bi_mbcbp[i + 2], stat_a[typ].bi_mbcbp[i + 3],
  554.           stat_a[typ].bi_mbcbp[i + 4], stat_a[typ].bi_mbcbp[i + 5], stat_a[typ].bi_mbcbp[i + 6],
  555.           stat_a[typ].bi_mbcbp[i + 7]);
  556.     }
  557.     fprintf(hist_fp,"\n\t\tNumber of Coefficients/Block Histogram:\n");
  558.     for (i = 0; i < 64; i += 8) {
  559.       fprintf(hist_fp,"\t%6d %6d %6d %6d %6d %6d %6d %6d\n", stat_a[typ].bi_mbcoeff[i],
  560.           stat_a[typ].bi_mbcoeff[i + 1], stat_a[typ].bi_mbcoeff[i + 2],
  561.           stat_a[typ].bi_mbcoeff[i + 3], stat_a[typ].bi_mbcoeff[i + 4],
  562.           stat_a[typ].bi_mbcoeff[i + 5], stat_a[typ].bi_mbcoeff[i + 6],
  563.           stat_a[typ].bi_mbcoeff[i + 7]);
  564.     }
  565.   }
  566. }
  567.  
  568. /*
  569.  * init_stat_struct
  570.  *
  571.  * clear for use a sinlge statistics structure
  572.  */
  573. void
  574. init_stat_struct(astat)
  575.   Statval *astat;
  576. {
  577.   int j;
  578.  
  579.   astat->frametype = 0;
  580.   astat->totsize = 0;
  581.   astat->number = 0;
  582.   astat->i_mbsize = 0;
  583.   astat->p_mbsize = 0;
  584.   astat->b_mbsize = 0;
  585.   astat->bi_mbsize = 0;
  586.   astat->i_mbnum = 0;
  587.   astat->p_mbnum = 0;
  588.   astat->b_mbnum = 0;
  589.   astat->bi_mbnum = 0;
  590.  
  591.   for (j = 0; j < 64; j++) {
  592.  
  593.     astat->i_mbcbp[j] = 0;
  594.     astat->p_mbcbp[j] = 0;
  595.     astat->b_mbcbp[j] = 0;
  596.     astat->bi_mbcbp[j] = 0;
  597.     astat->i_mbcoeff[j] = 0;
  598.     astat->p_mbcoeff[j] = 0;
  599.     astat->b_mbcoeff[j] = 0;
  600.     astat->bi_mbcoeff[j] = 0;
  601.   }
  602.   astat->tottime = 0.0;
  603.   astat->qual=0;  
  604.   astat->qnum=0;
  605. }
  606.  
  607.  
  608. /*
  609.  * CollectStats
  610.  *
  611.  * Move the proggressively collected data into its home
  612.  *
  613.  */
  614. void
  615. CollectStats()
  616. {
  617.   int i, j;
  618.  
  619.   i = stat_a[0].frametype;
  620.  
  621.   stat_a[i].totsize += stat_a[0].totsize;
  622.   stat_a[i].number += stat_a[0].number;
  623.   stat_a[i].i_mbsize += stat_a[0].i_mbsize;
  624.   stat_a[i].p_mbsize += stat_a[0].p_mbsize;
  625.   stat_a[i].b_mbsize += stat_a[0].b_mbsize;
  626.   stat_a[i].bi_mbsize += stat_a[0].bi_mbsize;
  627.   stat_a[i].i_mbnum += stat_a[0].i_mbnum;
  628.   stat_a[i].p_mbnum += stat_a[0].p_mbnum;
  629.   stat_a[i].b_mbnum += stat_a[0].b_mbnum;
  630.   stat_a[i].bi_mbnum += stat_a[0].bi_mbnum;
  631.  
  632.   for (j = 0; j < 64; j++) {
  633.  
  634.     stat_a[i].i_mbcbp[j] += stat_a[0].i_mbcbp[j];
  635.     stat_a[i].p_mbcbp[j] += stat_a[0].p_mbcbp[j];
  636.     stat_a[i].b_mbcbp[j] += stat_a[0].b_mbcbp[j];
  637.     stat_a[i].bi_mbcbp[j] += stat_a[0].bi_mbcbp[j];
  638.     stat_a[i].i_mbcoeff[j] += stat_a[0].i_mbcoeff[j];
  639.     stat_a[i].p_mbcoeff[j] += stat_a[0].p_mbcoeff[j];
  640.     stat_a[i].b_mbcoeff[j] += stat_a[0].b_mbcoeff[j];
  641.     stat_a[i].bi_mbcoeff[j] += stat_a[0].bi_mbcoeff[j];
  642.   }
  643.  
  644.   stat_a[i].tottime += stat_a[0].tottime;
  645.  
  646.   init_stat_struct(&(stat_a[0]));
  647.  
  648. }
  649.  
  650.  
  651. /*********************************/
  652. /* A bunch of "obvious" routines */
  653. /*********************************/
  654.  
  655. unsigned int
  656. bitCountRead()
  657. {
  658.   return bitCount;
  659. }
  660.  
  661. void
  662. StartTime()
  663. {
  664.   stat_a[0].tottime = ReadSysClock();
  665. }
  666.  
  667. void
  668. EndTime()
  669. {
  670.   stat_a[0].tottime = ReadSysClock() - stat_a[0].tottime;
  671. }
  672.  
  673. double
  674. ReadSysClock()
  675. {
  676.   struct timeval tv;
  677.   (void) gettimeofday(&tv, (struct timezone *)NULL);
  678.   return (tv.tv_sec + tv.tv_usec / 1000000.0);
  679. }
  680.  
  681. void
  682. PrintTimeInfo()
  683. {
  684.   double spent;
  685.  
  686.   spent = ReadSysClock() - realTimeStart;
  687.  
  688. }
  689.  
  690.  
  691.  
  692.  
  693. /*
  694.  *
  695.  *-------------------------------------------------------------
  696.  *
  697.  * PrintQT --
  698.  *
  699.  *    Called to print out Q tables
  700.  *
  701.  * Results:
  702.  *    adds info to stream.
  703.  *
  704.  * Side effects:
  705.  *     Writes to stream.
  706.  *
  707.  *-------------------------------------------------------------
  708.  */
  709. void PrintQT(stream,title,changed,ptr)
  710. FILE *stream;
  711. char *title;
  712. int changed;
  713. unsigned char ptr[];
  714. {
  715.   int i;
  716.   
  717.   if (changed) {
  718.     fprintf(stream,"\nCustom %s matrix (offset %d, frame %d):\n",
  719.         title,bitCountRead(), blks.frame+1);
  720.     for (i = 0; i < 64; i++) {
  721.       if (i%8!=7) fprintf(stream,"%2d ",ptr[i]);
  722.       else fprintf(stream,"%2d\n",ptr[i]);
  723.     }
  724.     fprintf(stream,"\n");
  725.   } else fprintf(stream,"\nCustom %s matrix repeated at (offset %d, frame %d)\n",
  726.         title,bitCountRead(),blks.frame+1);
  727. }
  728.  
  729.  
  730.  
  731. /* Utility routine to print possibly binary data */
  732. void print_binary(fp, buf, size)
  733. FILE *fp;
  734. char *buf;
  735. int size;
  736. {
  737.   int i,line,num_lines;
  738.   char printables[17];
  739.   
  740.   num_lines=size/16;
  741.   printables[16]=0;
  742.   for (i=0;i<16;i++) printables[i]=' ';
  743.   for (line=0; line<=num_lines; line++) {
  744.     for (i=0; (i<16) && (i<size); i++) {
  745.       fprintf(fp, "%2x ",*buf);
  746.       printables[i]= isprint(*buf) ? *buf: '.';
  747.       buf++;
  748.     }
  749.     if (i!=16) for(;i<16; i++) fprintf(fp, "   ");
  750.     size-=16;
  751.     fprintf(fp, "\t%s\n",printables);
  752.     for (i=0;i<16;i++) printables[i]=' ';
  753.   }}
  754.  
  755.