Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

mpeg.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * mpeg.c                                                                    *
00003  *                                                                           *
00004  *      Procedures to generate the MPEG sequence                             *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      GetMPEGStream                                                        *
00008  *      IncrementTCTime                                                      *
00009  *      SetStatFileName                                                      *
00010  *      SetGOPSize                                                           *
00011  *      PrintStartStats                                                      *
00012  *                                                                           *
00013  *===========================================================================*/
00014 
00015 /*
00016  * Copyright (c) 1995 The Regents of the University of California.
00017  * All rights reserved.
00018  *
00019  * Permission to use, copy, modify, and distribute this software and its
00020  * documentation for any purpose, without fee, and without written agreement is
00021  * hereby granted, provided that the above copyright notice and the following
00022  * two paragraphs appear in all copies of this software.
00023  *
00024  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00025  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00026  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00027  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00028  *
00029  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00030  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00031  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00032  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00033  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00034  */
00035 
00036 /*  
00037  *  $Header: /misc/elrond0/share/cvs/AFNI/src/mpeg_encodedir/mpeg.c,v 1.4 2004/04/02 15:12:40 rwcox Exp $
00038  *  $Log: mpeg.c,v $
00039  *  Revision 1.4  2004/04/02 15:12:40  rwcox
00040  *  Cput
00041  *
00042  *  Revision 1.3  2003/12/23 13:50:08  rwcox
00043  *  Cput
00044  *
00045  *  Revision 1.2  2003/12/03 14:46:14  rwcox
00046  *  Cput
00047  *
00048  *  Revision 1.1  2001/12/17 16:11:54  rwcox
00049  *  Cadd
00050  *
00051  *  Revision 1.24  1995/08/16 18:10:48  smoot
00052  *  *** empty log message ***
00053  *
00054  *  Revision 1.23  1995/08/07 21:48:08  smoot
00055  *  stdin bugs fixed
00056  *
00057  *  Revision 1.22  1995/06/26 21:49:19  smoot
00058  *  added new frame ordering (hacks)^H^H^H^H^H code ;-)
00059  *
00060  *  Revision 1.21  1995/06/21 18:30:41  smoot
00061  *  changed time structure to be ANSI
00062  *  changed file access to be binary (DOS!)
00063  *  added time to userdata
00064  *  Added a sleep to remote reads (NFS delay)
00065  *
00066  * Revision 1.20  1995/05/02  01:49:21  eyhung
00067  * prints out true output bit rate and slightly untabified
00068  *
00069  * Revision 1.19  1995/05/02  00:45:35  eyhung
00070  * endstats now contain correct output fbit rate at the specified frame rate
00071  *
00072  * Revision 1.18  1995/03/27  23:43:20  smoot
00073  * killed printing long as int (compiler warning)
00074  *
00075  * Revision 1.17  1995/03/27  19:18:54  smoot
00076  * fixed divide by zero for very quick encodings
00077  *
00078  * Revision 1.16  1995/02/02  22:03:37  smoot
00079  * added types for MIPS
00080  *
00081  * Revision 1.15  1995/02/02  07:26:58  eyhung
00082  * removed unused tempframe
00083  *
00084  * Revision 1.14  1995/02/01  05:01:35  eyhung
00085  * Completed infinite coding-on-the-fly
00086  *
00087  * Revision 1.13  1995/02/01  02:34:02  eyhung
00088  * Added full coding-on-the-fly
00089  *
00090  * Revision 1.12  1995/01/31  23:05:14  eyhung
00091  * Added some stdin stuff
00092  *
00093  * Revision 1.11  1995/01/20  00:01:16  eyhung
00094  * Added output file to PrintEndStats
00095  *
00096  * Revision 1.10  1995/01/19  23:08:51  eyhung
00097  * Changed copyrights
00098  *
00099  * Revision 1.9  1995/01/17  18:55:54  smoot
00100  * added right version number, and error if no frames selected
00101  *
00102  * Revision 1.8  1995/01/16  08:12:54  eyhung
00103  * added realQuiet
00104  *
00105  * Revision 1.7  1994/12/07  00:40:36  smoot
00106  * Added seperate P and B search ranges
00107  *
00108  * Revision 1.6  1994/11/28  21:46:45  smoot
00109  * Added version printing
00110  *
00111  * Revision 1.5  1994/11/19  01:33:05  smoot
00112  * put in userdata
00113  *
00114  * Revision 1.4  1994/11/14  22:36:22  smoot
00115  * Merged specifics and rate control
00116  *
00117  * Revision 1.2  1994/03/15  00:27:11  keving
00118  * nothing
00119  *
00120  * Revision 1.1  1993/12/22  19:19:01  keving
00121  * nothing
00122  *
00123  * Revision 1.6  1993/07/22  22:23:43  keving
00124  * nothing
00125  *
00126  * Revision 1.5  1993/06/30  20:06:09  keving
00127  * nothing
00128  *
00129  * Revision 1.4  1993/06/03  21:08:08  keving
00130  * nothing
00131  *
00132  * Revision 1.3  1993/02/19  18:10:12  keving
00133  * nothing
00134  *
00135  * Revision 1.2  1993/02/17  23:18:20  dwallach
00136  * checkin prior to keving's joining the project
00137  *
00138  */
00139 
00140 
00141 /*==============*
00142  * HEADER FILES *
00143  *==============*/
00144 
00145 #include "all.h"
00146 #include <time.h>
00147 #include <errno.h>
00148 #include <unistd.h>
00149 #include "mtypes.h"
00150 #include "frames.h"
00151 #include "search.h"
00152 #include "mpeg.h"
00153 #include "prototypes.h"
00154 #include "parallel.h"
00155 #include "param.h"
00156 #include "readframe.h"
00157 #include "fsize.h"
00158 #include "mheaders.h"
00159 #include "rate.h"
00160 #ifdef MIPS
00161 #include <sys/types.h>
00162 #endif
00163 #include <sys/stat.h>
00164 
00165 /*===========*
00166  *  VERSION  *
00167  *===========*/
00168 
00169 #define VERSION "1.5b"
00170 
00171 
00172 /*===========*
00173  * CONSTANTS *
00174  *===========*/
00175 
00176 #define FPS_30  0x5   /* from MPEG standard sect. 2.4.3.2 */
00177 #define ASPECT_1    0x1 /* aspect ratio, from MPEG standard sect. 2.4.3.2 */
00178 
00179 
00180 /*==================*
00181  * STATIC VARIABLES *
00182  *==================*/
00183 
00184 static int32   diffTime;
00185 static int framesOutput;
00186 static int          realStart, realEnd;
00187 static int      currentGOP;
00188 static int          timeMask;
00189 static int          numI, numP, numB;
00190 
00191 
00192 /*==================*
00193  * GLOBAL VARIABLES *   
00194  *==================*/
00195 
00196 /* important -- don't initialize anything here */
00197 /* must be re-initted anyway in GenMPEGStream */
00198 
00199 extern int  IOtime;
00200 extern boolean  resizeFrame;
00201 extern int outputWidth, outputHeight;
00202 int         gopSize = 100;  /* default */
00203 int32       tc_hrs, tc_min, tc_sec, tc_pict, tc_extra;
00204 int         totalFramesSent;
00205 int         yuvWidth, yuvHeight;
00206 int         realWidth, realHeight;
00207 char        currentPath[MAXPATHLEN];
00208 char        statFileName[256];
00209 char        bitRateFileName[256];
00210 time_t      timeStart, timeEnd;
00211 FILE       *statFile;
00212 FILE       *bitRateFile = NULL;
00213 char       *framePattern;
00214 int         framePatternLen;
00215 int         referenceFrame;
00216 static int  framesRead;
00217 MpegFrame  *pastRefFrame;
00218 MpegFrame  *futureRefFrame;
00219 int         frameRate = FPS_30;
00220 int         frameRateRounded = 30;
00221 boolean     frameRateInteger = TRUE;
00222 int         aspectRatio = ASPECT_1;
00223 extern unsigned char userDataFileName[];
00224 extern int mult_seq_headers;
00225 
00226 int32 bit_rate, buf_size;
00227 
00228 /*===============================*
00229  * INTERNAL PROCEDURE prototypes *
00230  *===============================*/
00231 
00232 static void     ShowRemainingTime _ANSI_ARGS_((void));
00233 static void     ComputeDHMSTime _ANSI_ARGS_((int32 someTime, char *timeText));
00234 static void     ComputeGOPFrames _ANSI_ARGS_((int whichGOP, int *firstFrame,
00235                                               int *lastFrame, int numFrames));
00236 static void     PrintEndStats _ANSI_ARGS_((int inputFrameBits, int32 totalBits));
00237 static void     ProcessRefFrame _ANSI_ARGS_((MpegFrame *frame,
00238                                               BitBucket *bb, int lastFrame,
00239                                               char *outputFileName));
00240 static void     OpenBitRateFile _ANSI_ARGS_((void));
00241 static void     CloseBitRateFile _ANSI_ARGS_((void));
00242 
00243 
00244 /*=====================*
00245  * EXPORTED PROCEDURES *
00246  *=====================*/
00247 
00248 /*===========================================================================*
00249  *
00250  * SetReferenceFrameType
00251  *
00252  *      set the reference frame type to be original or decoded
00253  *
00254  * RETURNS:     nothing
00255  *
00256  * SIDE EFFECTS:    referenceFrame
00257  *
00258  *===========================================================================*/
00259 void
00260 SetReferenceFrameType(type)
00261     char *type;
00262 {
00263     if ( strcmp(type, "ORIGINAL") == 0 ) {
00264         referenceFrame = ORIGINAL_FRAME;
00265     } else if ( strcmp(type, "DECODED") == 0 ) {
00266         referenceFrame = DECODED_FRAME;
00267     } else {
00268         fprintf(stderr, "ERROR:  Illegal reference frame type: '%s'\n",
00269                 type);
00270         exit(1);
00271     }
00272 }
00273 
00274 void
00275 SetBitRateFileName(fileName)
00276     char *fileName;
00277 {
00278     strcpy(bitRateFileName, fileName);
00279 }
00280 
00281 
00282 /*===========================================================================*
00283  *
00284  * GenMPEGStream
00285  *
00286  *      generate an MPEG sequence stream (generally)
00287  *      if whichGOP == frameStart == -1 then does complete MPEG sequence
00288  *      if whichGOP != -1 then does numbered GOP only (without sequence
00289  *                             header)
00290  *      if frameStart != -1 then does numbered frames only (without any
00291  *                               sequence or GOP headers)                      
00292  *
00293  * RETURNS:     amount of time it took
00294  *
00295  * SIDE EFFECTS:    too numerous to mention
00296  *
00297  *===========================================================================*/
00298 int32
00299 GenMPEGStream(whichGOP, frameStart, frameEnd, qtable, niqtable, numFrames,
00300               ofp, outputFileName)
00301     int whichGOP;
00302     int frameStart;
00303     int frameEnd;
00304     int32   qtable[];
00305     int32   niqtable[];
00306     int numFrames;
00307     FILE *ofp;
00308     char *outputFileName;
00309 {
00310     extern void        PrintItoIBitRate _ANSI_ARGS_((int numBits, int frameNum));
00311     BitBucket *bb;
00312     int i;
00313     char frameType;
00314     MpegFrame        *frame = NULL;
00315     MpegFrame *tempFrame;
00316     int            firstFrame, lastFrame;
00317     int     inputFrameBits = 0;
00318     char    inputFileName[1024];
00319     time_t  tempTimeStart, tempTimeEnd;
00320     boolean firstFrameDone = FALSE;
00321     int numBits;
00322     int32 bitstreamMode, res;
00323 
00324     if ( (whichGOP == -1) && (frameStart == -1) &&
00325          (! stdinUsed) && (FType_Type(numFrames-1) == 'b') ) {
00326         fprintf(stderr, "\n");
00327         fprintf(stderr, "WARNING:  One or more B-frames at end will not be encoded.\n");
00328         fprintf(stderr, "          See FORCE_ENCODE_LAST_FRAME option in man page.\n");
00329         fprintf(stderr, "\n");
00330     }
00331 
00332     time(&timeStart);
00333 
00334     framesRead = 0;
00335 
00336     ResetIFrameStats();
00337     ResetPFrameStats();
00338     ResetBFrameStats();
00339 
00340     Fsize_Reset();
00341 
00342     framesOutput = 0;
00343 
00344     if ( childProcess && separateConversion ) {
00345         SetFileType(slaveConversion);
00346     } else {
00347         SetFileType(inputConversion);
00348     }
00349 
00350     if ( whichGOP != -1 ) {
00351         ComputeGOPFrames(whichGOP, &firstFrame, &lastFrame, numFrames);
00352 
00353         realStart = firstFrame;
00354         realEnd = lastFrame;
00355 
00356         if ( FType_Type(firstFrame) == 'b' ) {
00357 
00358             /* can't find the previous frame interactively */
00359             if ( stdinUsed ) {
00360                 fprintf(stderr, "ERROR: Cannot encode GOP from stdin when first frame is a B-frame.\n");
00361                 exit(1);
00362             }
00363 
00364             /* need to load in previous frame; call it an I frame */
00365             frame = Frame_New(firstFrame-1, 'i');
00366 
00367             time(&tempTimeStart);
00368 
00369             if ( (referenceFrame == DECODED_FRAME) &&
00370                  childProcess ) {
00371                 WaitForDecodedFrame(firstFrame);
00372 
00373                 if ( remoteIO ) {
00374                     GetRemoteDecodedRefFrame(frame, firstFrame-1);
00375                 } else {
00376                     ReadDecodedRefFrame(frame, firstFrame-1);
00377                 }
00378             } else {
00379                 if ( remoteIO ) {
00380                     GetRemoteFrame(frame, firstFrame-1);
00381                 } else {
00382                     GetNthInputFileName(inputFileName, firstFrame-1);
00383 
00384                     if ( childProcess && separateConversion ) {
00385                         ReadFrame(frame, inputFileName, slaveConversion, TRUE);
00386                     } else {
00387                         ReadFrame(frame, inputFileName, inputConversion, TRUE);
00388                     }
00389                 }
00390             }
00391 
00392             framesRead++;
00393 
00394             time(&tempTimeEnd);
00395             IOtime += (tempTimeEnd-tempTimeStart);
00396         }
00397     } else if ( frameStart != -1 ) {
00398         if ( frameEnd > numFrames-1 ) {
00399             fprintf(stderr, "ERROR:  Specified last frame is out of bounds\n");
00400             exit(1);
00401         }
00402 
00403         realStart = frameStart;
00404         realEnd = frameEnd;
00405 
00406         firstFrame = frameStart;
00407         lastFrame = frameEnd;
00408 
00409         /* if first frame is P or B, need to read in P or I frame before it */
00410         if ( FType_Type(firstFrame) != 'i' ) {
00411 
00412             /* can't find the previous frame interactively */
00413             if ( stdinUsed ) {
00414                 fprintf(stderr, "ERROR: Cannot encode frames from stdin when first frame is not an I-frame.\n");
00415                 exit(1);
00416             }
00417 
00418             firstFrame = FType_PastRef(firstFrame);
00419         }
00420 
00421         /* if last frame is B, need to read in P or I frame after it */
00422         if ( (FType_Type(lastFrame) == 'b') && (lastFrame != numFrames-1) ) {
00423 
00424             /* can't find the next reference frame interactively */
00425             if ( stdinUsed ) {
00426                 fprintf(stderr, "ERROR: Cannot encode frames from stdin when last frame is a B-frame.\n");
00427                 exit(1);
00428             }
00429 
00430             lastFrame = FType_FutureRef(lastFrame);
00431         }
00432 
00433         if ( lastFrame > numFrames-1 ) {            /* can't go last frame! */
00434             lastFrame = numFrames-1;
00435         }
00436 
00437     } else {
00438         firstFrame = 0;
00439         lastFrame = numFrames-1;
00440 
00441         realStart = 0;
00442         realEnd = numFrames-1;
00443         if ( numFrames == 0 )  {
00444             fprintf(stderr, "ERROR:  No frames selected!\n");
00445             exit(1);
00446         }
00447     }
00448 
00449     /* count number of I, P, and B frames */
00450     numI = 0;        numP = 0;   numB = 0;
00451     timeMask = 0;
00452     if (stdinUsed) {
00453       numI = numP = numB = MAXINT/4;
00454     } else {
00455       for ( i = firstFrame; i <= lastFrame; i++ ) {
00456         frameType = FType_Type(i);
00457         switch(frameType) {
00458         case 'i':        numI++;            timeMask |= 0x1;    break;
00459         case 'p':        numP++;            timeMask |= 0x2;        break;
00460         case 'b':        numB++;            timeMask |= 0x4;        break;
00461         }
00462       }
00463     }
00464 
00465     if ( ! childProcess ) {
00466         if ( showBitRatePerFrame )
00467             OpenBitRateFile();
00468         PrintStartStats(realStart, realEnd);
00469     }
00470 
00471     if ( frameStart == -1 ) {
00472         bb = Bitio_New(ofp);
00473     } else {
00474         bb = NULL;
00475     }
00476 
00477     tc_hrs = 0;        tc_min = 0; tc_sec = 0; tc_pict = 0; tc_extra = 0;
00478     for ( i = 0; i < firstFrame; i++ ) {
00479         IncrementTCTime();
00480     }
00481 
00482     totalFramesSent = firstFrame;
00483     currentGOP = gopSize;        /* so first I-frame generates GOP Header */
00484 
00485     /* Rate Control Initialization  */
00486     bitstreamMode = getRateMode();
00487     if (bitstreamMode == FIXED_RATE) {
00488       res = initRateControl();
00489       /*
00490         SetFrameRate();
00491         */
00492          }
00493     
00494 #ifdef BLEAH
00495 fprintf(stdout, "firstFrame, lastFrame = %d, %d;  real = %d, %d\n",
00496         firstFrame, lastFrame, realStart, realEnd);
00497 fflush(stdout);
00498 #endif
00499 
00500     pastRefFrame = NULL;
00501     futureRefFrame = NULL;
00502     for ( i = firstFrame; i <= lastFrame; i++) {
00503 
00504         /* break out of the near-infinite loop if input from stdin is done */
00505 #if 0 
00506       char eofcheck[1];
00507       if ( stdinUsed ) {
00508         if (scanf("%c", eofcheck) != EOF) {
00509           ungetc(eofcheck[0], stdin);
00510         } else {
00511           break;
00512         }
00513       }
00514 #else
00515         /*
00516          ** For some reason the above version of this stdin EOF check does not
00517          ** work right with jpeg files, the ungetc() is not padding anything to
00518          ** stdin, I have no idea why (perhaps because a char is passed instead
00519          ** of an int?), and it drove me nuts, so I wrote my own, slightly
00520          ** cleaner version, and this one seems to work.
00521          ** Dave Scott (dhs), UofO, 7/19/95.
00522          */
00523         if ( stdinUsed) {
00524           int eofcheck_;
00525           eofcheck_ = fgetc(stdin);
00526           if ( eofcheck_ == EOF) 
00527             break;
00528           else 
00529             ungetc(eofcheck_, stdin);
00530         } 
00531 #endif
00532         frameType = FType_Type(i);
00533         
00534         time(&tempTimeStart);
00535 
00536         /* skip non-reference frames if non-interactive
00537          * read in non-reference frames if interactive */
00538         if ( frameType == 'b' ) {
00539           if ( stdinUsed ) {
00540             frame = Frame_New(i, frameType);
00541             ReadFrame(frame, "stdin", inputConversion, TRUE);
00542 
00543             framesRead++;
00544 
00545             time(&tempTimeEnd);
00546             IOtime += (tempTimeEnd-tempTimeStart);
00547 
00548             /* Add the B frame to the end of the queue of B-frames 
00549              * for later encoding
00550              */
00551 
00552             if (futureRefFrame != NULL) {
00553               tempFrame = futureRefFrame;
00554               while (tempFrame->next != NULL) {
00555                 tempFrame = tempFrame->next;
00556               }
00557               tempFrame->next = frame;
00558             } else {
00559               fprintf(stderr, "Yow, something wrong in neverland! (hit bad code in mpeg.c\n");
00560             }
00561           }
00562           continue;
00563         }
00564 
00565         frame = Frame_New(i, frameType);
00566 
00567         pastRefFrame = futureRefFrame;
00568         futureRefFrame = frame;
00569 
00570         if ( (referenceFrame == DECODED_FRAME) &&
00571              ((i < realStart) || (i > realEnd)) ) {
00572             WaitForDecodedFrame(i);
00573 
00574             if ( remoteIO ) {
00575                 GetRemoteDecodedRefFrame(frame, i);
00576             } else {
00577                 ReadDecodedRefFrame(frame, i);
00578             }
00579         } else {
00580             if ( remoteIO ) {
00581                 GetRemoteFrame(frame, i);
00582             } else {
00583                 GetNthInputFileName(inputFileName, i);
00584                 if ( childProcess && separateConversion ) {
00585                     ReadFrame(frame, inputFileName, slaveConversion, TRUE);
00586                 } else {
00587                     ReadFrame(frame, inputFileName, inputConversion, TRUE);
00588                 }
00589             }
00590         }
00591 
00592         framesRead++;
00593 
00594         time(&tempTimeEnd);
00595         IOtime += (tempTimeEnd-tempTimeStart);
00596 
00597         if ( ! firstFrameDone ) {
00598           char *userData = (char *)NULL;
00599           int userDataSize = 0;
00600 
00601           inputFrameBits = 24*Fsize_x*Fsize_y;
00602           SetBlocksPerSlice();
00603           
00604           if ( (whichGOP == -1) && (frameStart == -1) ) {
00605             DBG_PRINT(("Generating sequence header\n"));
00606             bitstreamMode = getRateMode();
00607             if (bitstreamMode == FIXED_RATE) {
00608               bit_rate = getBitRate();
00609               buf_size = getBufferSize();
00610             }
00611             else {
00612                   bit_rate = -1;
00613                   buf_size = -1;
00614                 }
00615             
00616             if (strlen(userDataFileName) != 0) {
00617               struct stat statbuf;
00618               FILE *fp;
00619               
00620               stat(userDataFileName,&statbuf);
00621               userDataSize = statbuf.st_size;
00622               userData = malloc(userDataSize);
00623               if ((fp = fopen(userDataFileName,"rb")) == NULL) {
00624                 fprintf(stderr,"Could not open userdata file-%s.\n",
00625                         userDataFileName);
00626                 userData = NULL;
00627                 userDataSize = 0;
00628                 goto write;
00629               }
00630             if (fread(userData,1,userDataSize,fp) != userDataSize) {
00631             fprintf(stderr,"Could not read %d bytes from userdata file-%s.\n",
00632                     userDataSize,userDataFileName);
00633             userData = NULL;
00634             userDataSize = 0;
00635             goto write;
00636           }
00637         } else { /* Put in our UserData Header */
00638           time_t now;
00639 
00640           time(&now);
00641           userData = malloc(100);
00642           sprintf(userData,"MPEG stream encoded by UCB Encoder (mpeg_encode) v%s on %s.",
00643                   VERSION, ctime(&now));
00644           userDataSize = strlen(userData);
00645         }
00646           write:
00647             Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y,
00648                                     /* pratio */ aspectRatio,
00649                                     /* pict_rate */ frameRate, /* bit_rate */ bit_rate,
00650                                     /* buf_size */ buf_size, /*c_param_flag */ 1,
00651                                     /* iq_matrix */ qtable, /* niq_matrix */ niqtable,
00652                                     /* ext_data */ NULL, /* ext_data_size */ 0,
00653                                     /* user_data */ userData, /* user_data_size */ userDataSize);
00654           }
00655           
00656           firstFrameDone = TRUE;
00657         }
00658         
00659         ProcessRefFrame(frame, bb, lastFrame, outputFileName);
00660 
00661     }
00662 
00663     if ( frame != NULL ) {
00664         Frame_Free(frame);
00665     }
00666 
00667     /* SEQUENCE END CODE */
00668     if ( (whichGOP == -1) && (frameStart == -1) ) {
00669         Mhead_GenSequenceEnder(bb);
00670     }
00671 
00672     if ( frameStart == -1 ) {
00673       /* I think this is right, since (bb == NULL) if (frameStart != -1).
00674          See above where "bb" is initialized  */
00675       numBits = bb->cumulativeBits;
00676     } else {
00677       /* What should the correct value be?  Most likely 1.  "numBits" is
00678          used below, so we need to make sure it's properly initialized 
00679        to somthing (anything).  */
00680       numBits = 1;
00681     }
00682 
00683     if ( frameStart == -1 ) {
00684         Bitio_Flush(bb);
00685         bb = NULL;
00686         fclose(ofp);
00687 
00688         time(&timeEnd);
00689         diffTime = (int32)(timeEnd-timeStart);
00690 
00691         if ( ! childProcess ) {
00692             PrintEndStats(inputFrameBits, numBits);
00693         }
00694     } else {
00695         time(&timeEnd);
00696         diffTime = (int32)(timeEnd-timeStart);
00697 
00698         if ( ! childProcess ) {
00699             PrintEndStats(inputFrameBits, 1);
00700         }
00701     }
00702 
00703     if ( FType_Type(realEnd) != 'i' ) {
00704         PrintItoIBitRate(numBits, realEnd+1);
00705     }
00706 
00707     if ( (! childProcess) && showBitRatePerFrame )
00708         CloseBitRateFile();
00709 
00710 #ifdef BLEAH
00711     if ( childProcess ) {
00712         NoteFrameDone(frameStart, frameEnd);
00713     }
00714 #endif
00715 
00716     if (! realQuiet) {
00717         fprintf(stdout, "======FRAMES READ:  %d\n", framesRead);
00718         fflush(stdout);
00719     }
00720 
00721     return diffTime;
00722 }
00723 
00724 
00725 /*===========================================================================*
00726  *
00727  * IncrementTCTime
00728  *
00729  *      increment the tc time by one second (and update min, hrs if necessary)
00730  *      also increments totalFramesSent
00731  *
00732  * RETURNS:     nothing
00733  *
00734  * SIDE EFFECTS:    totalFramesSent, tc_pict, tc_sec, tc_min, tc_hrs, tc_extra
00735  *
00736  *===========================================================================*/
00737 void
00738 IncrementTCTime()
00739 {
00740     /* if fps = an integer, then tc_extra = 0 and is ignored
00741 
00742        otherwise, it is the number of extra 1/1001 frames we've passed by
00743 
00744        so far; for example, if fps = 24000/1001, then 24 frames = 24024/24000
00745        seconds = 1 second + 24/24000 seconds = 1 + 1/1000 seconds; similary,
00746        if fps = 30000/1001, then 30 frames = 30030/30000 = 1 + 1/1000 seconds
00747        and if fps = 60000/1001, then 60 frames = 1 + 1/1000 seconds
00748 
00749        if fps = 24000/1001, then 1/1000 seconds = 24/1001 frames
00750        if fps = 30000/1001, then 1/1000 seconds = 30/1001 frames
00751        if fps = 60000/1001, then 1/1000 seconds = 60/1001 frames     
00752      */
00753 
00754     totalFramesSent++;
00755     tc_pict++;
00756     if ( tc_pict >= frameRateRounded ) {
00757         tc_pict = 0;
00758         tc_sec++;
00759         if ( tc_sec == 60 ) {
00760             tc_sec = 0;
00761             tc_min++;
00762             if ( tc_min == 60 ) {
00763                 tc_min = 0;
00764                 tc_hrs++;
00765             }
00766         }
00767         if ( ! frameRateInteger ) {
00768             tc_extra += frameRateRounded;
00769             if ( tc_extra >= 1001 ) {   /* a frame's worth */
00770                 tc_pict++;
00771                 tc_extra -= 1001;
00772             }
00773         }
00774     }
00775 }
00776 
00777 
00778 /*===========================================================================*
00779  *
00780  * SetStatFileName
00781  *
00782  *      set the statistics file name
00783  *
00784  * RETURNS:     nothing
00785  *
00786  * SIDE EFFECTS:    statFileName
00787  *
00788  *===========================================================================*/
00789 void
00790 SetStatFileName(fileName)
00791     char *fileName;
00792 {
00793     strcpy(statFileName, fileName);
00794 }
00795 
00796 
00797 /*===========================================================================*
00798  *
00799  * SetGOPSize
00800  *
00801  *      set the GOP size (frames per GOP)
00802  *
00803  * RETURNS:     nothing
00804  *
00805  * SIDE EFFECTS:    gopSize
00806  *
00807  *===========================================================================*/
00808 void
00809 SetGOPSize(size)
00810     int size;
00811 {
00812     gopSize = size;
00813 }
00814 
00815 
00816 /*===========================================================================*
00817  *
00818  * PrintStartStats
00819  *
00820  *      print out the starting statistics (stuff from the param file)
00821  *      firstFrame, lastFrame represent the first, last frames to be
00822  *      encoded
00823  *
00824  * RETURNS:     nothing
00825  *
00826  * SIDE EFFECTS:    none
00827  *
00828  *===========================================================================*/
00829 void
00830 PrintStartStats(firstFrame, lastFrame)
00831     int firstFrame;
00832     int lastFrame;
00833 {
00834     FILE *fpointer;
00835     register int i;
00836     char    inputFileName[1024];
00837 
00838     if ( statFileName[0] == '\0' ) {
00839         statFile = NULL;
00840     } else {
00841         statFile = fopen(statFileName, "a");    /* open for appending */
00842         if ( statFile == NULL ) {
00843             fprintf(stderr, "ERROR:  Could not open stat file:  %s\n", statFileName);
00844             fprintf(stderr, "        Sending statistics to stdout only.\n");
00845             fprintf(stderr, "\n\n");
00846         } else if (! realQuiet) {
00847             fprintf(stdout, "Appending statistics to file:  %s\n", statFileName);
00848             fprintf(stdout, "\n\n");
00849         }
00850     }
00851         
00852     for ( i = 0; i < 2; i++ ) {
00853         if ( ( i == 0 ) && (! realQuiet) ) {
00854             fpointer = stdout;
00855         } else if ( statFile != NULL ) {
00856             fpointer = statFile;
00857         } else {
00858             continue;
00859         }
00860 
00861         fprintf(fpointer, "MPEG ENCODER STATS (%s)\n",VERSION);
00862         fprintf(fpointer, "------------------------\n");
00863         fprintf(fpointer, "TIME STARTED:  %s", ctime(&timeStart));
00864         if ( getenv("HOST") != NULL ) {
00865             fprintf(fpointer, "MACHINE:  %s\n", getenv("HOST"));
00866         } else {
00867             fprintf(fpointer, "MACHINE:  unknown\n");
00868         }
00869 
00870         if ( stdinUsed ) {
00871             fprintf(fpointer, "INPUT:  stdin\n");
00872           }
00873 
00874         
00875         if ( firstFrame == -1 ) {
00876             fprintf(fpointer, "OUTPUT:  %s\n", outputFileName);
00877         } else if ( ! stdinUsed ) {
00878             GetNthInputFileName(inputFileName, firstFrame);
00879             fprintf(fpointer, "FIRST FILE:  %s/%s\n", currentPath, inputFileName);
00880             GetNthInputFileName(inputFileName, lastFrame);
00881             fprintf(fpointer, "LAST FILE:  %s/%s\n", currentPath,
00882                     inputFileName);
00883         }
00884         if ( resizeFrame )
00885             fprintf(fpointer, "RESIZED TO:  %dx%d\n",
00886                     outputWidth, outputHeight);
00887         fprintf(fpointer, "PATTERN:  %s\n", framePattern);
00888         fprintf(fpointer, "GOP_SIZE:  %d\n", gopSize);
00889         fprintf(fpointer, "SLICES PER FRAME:  %d\n", slicesPerFrame);
00890         if (searchRangeP==searchRangeB)
00891           fprintf(fpointer, "RANGE:  +/-%d\n", searchRangeP/2);
00892         else fprintf(fpointer, "RANGES:  +/-%d %d\n", 
00893                      searchRangeP/2,searchRangeB/2);
00894         fprintf(fpointer, "PIXEL SEARCH:  %s\n", pixelFullSearch ? "FULL" : "HALF");
00895         fprintf(fpointer, "PSEARCH:  %s\n", PSearchName());
00896         fprintf(fpointer, "BSEARCH:  %s\n", BSearchName());
00897         fprintf(fpointer, "QSCALE:  %d %d %d\n", qscaleI, 
00898                 GetPQScale(), GetBQScale());
00899         if (specificsOn) 
00900           fprintf(fpointer, "(Except as modified by Specifics file)\n");
00901         if ( referenceFrame == DECODED_FRAME ) {
00902             fprintf(fpointer, "REFERENCE FRAME:  DECODED\n");
00903         } else if ( referenceFrame == ORIGINAL_FRAME ) {
00904             fprintf(fpointer, "REFERENCE FRAME:  ORIGINAL\n");
00905         } else {
00906             fprintf(stderr, "ERROR:  Illegal referenceFrame!!!\n");
00907             exit(1);
00908         }
00909         /*      For new Rate control parameters */
00910         if (getRateMode() == FIXED_RATE) {
00911           fprintf(fpointer, "PICTURE RATE:  %d\n", frameRateRounded);
00912           if (getBitRate() != -1) {
00913             fprintf(fpointer, "\nBIT RATE:  %d\n", getBitRate());
00914           }
00915           if (getBufferSize() != -1) {
00916             fprintf(fpointer, "BUFFER SIZE:  %d\n", getBufferSize());
00917           }
00918         }
00919       }
00920     if (! realQuiet) {
00921         fprintf(stdout, "\n\n");
00922     }   
00923 }
00924 
00925 
00926 /*===========================================================================*
00927  *
00928  * NonLocalRefFrame
00929  *
00930  *      decides if this frame can be referenced from a non-local process
00931  *
00932  * RETURNS:     TRUE or FALSE
00933  *
00934  * SIDE EFFECTS:    none
00935  *
00936  *===========================================================================*/
00937 boolean
00938 NonLocalRefFrame(id)
00939     int id;
00940 {
00941     int     lastIPid;
00942     int     nextIPid;
00943 
00944     if ( ! childProcess ) {
00945         return FALSE;
00946     }
00947 
00948     lastIPid = FType_PastRef(id);
00949 
00950     /* might be accessed by B-frame */
00951     if ( lastIPid+1 < realStart ) {
00952         return TRUE;
00953     }
00954 
00955     /* if B-frame is out of range, then current frame can be ref'd by it */
00956     nextIPid = FType_FutureRef(id);
00957 
00958     /* might be accessed by B-frame */
00959     if ( nextIPid-1 > realEnd ) {
00960         return TRUE;
00961     }
00962 
00963     /* might be accessed by P-frame */
00964     if ( (nextIPid > realEnd) && (FType_Type(nextIPid) == 'p') ) {
00965         return TRUE;
00966     }
00967 
00968     return FALSE;
00969 }
00970 
00971 
00972  
00973 /*===========================================================================*
00974  *
00975  * SetFrameRate
00976  *
00977  *      sets global frame rate variables.  value passed is MPEG frame rate code.
00978  *
00979  * RETURNS:     TRUE or FALSE
00980  *
00981  * SIDE EFFECTS:    frameRateRounded, frameRateInteger
00982  *
00983  *===========================================================================*/
00984 void
00985 SetFrameRate()
00986 {
00987     switch(frameRate) {
00988         case 1:
00989             frameRateRounded = 24;
00990             frameRateInteger = FALSE;
00991             break;
00992         case 2:
00993             frameRateRounded = 24;
00994             frameRateInteger = TRUE;
00995             break;
00996         case 3:
00997             frameRateRounded = 25;
00998             frameRateInteger = TRUE;
00999             break;
01000         case 4:
01001             frameRateRounded = 30;
01002             frameRateInteger = FALSE;
01003             break;
01004         case 5:
01005             frameRateRounded = 30;
01006             frameRateInteger = TRUE;
01007             break;
01008         case 6:
01009             frameRateRounded = 50;
01010             frameRateInteger = TRUE;
01011             break;
01012         case 7:
01013             frameRateRounded = 60;
01014             frameRateInteger = FALSE;
01015             break;
01016         case 8:
01017             frameRateRounded = 60;
01018             frameRateInteger = TRUE;
01019             break;
01020     }
01021         printf("frame rate(%d) set to %d\n", frameRate, frameRateRounded);
01022 }
01023 
01024 
01025 /*=====================*
01026  * INTERNAL PROCEDURES *
01027  *=====================*/
01028 
01029 /*===========================================================================*
01030  *
01031  * ComputeDHMSTime
01032  *
01033  *      turn some number of seconds (someTime) into a string which
01034  *      summarizes that time according to scale (days, hours, minutes, or
01035  *      seconds)
01036  *
01037  * RETURNS:     nothing
01038  *
01039  * SIDE EFFECTS:    none
01040  *
01041  *===========================================================================*/
01042 static void
01043 ComputeDHMSTime(someTime, timeText)
01044     int32 someTime;
01045     char *timeText;
01046 {
01047     int     days, hours, mins, secs;
01048 
01049     days = someTime / (24*60*60);
01050     someTime -= days*24*60*60;
01051     hours = someTime / (60*60);
01052     someTime -= hours*60*60;
01053     mins = someTime / 60;
01054     secs = someTime - mins*60;
01055 
01056     if ( days > 0 ) {
01057         sprintf(timeText, "Total time:  %d days and %d hours", days, hours);
01058     } else if ( hours > 0 ) {
01059         sprintf(timeText, "Total time:  %d hours and %d minutes", hours, mins);
01060     } else if ( mins > 0 ) {
01061         sprintf(timeText, "Total time:  %d minutes and %d seconds", mins, secs);
01062     } else {
01063         sprintf(timeText, "Total time:  %d seconds", secs);
01064     }
01065 }
01066 
01067 
01068 /*===========================================================================*
01069  *
01070  * ComputeGOPFrames
01071  *
01072  *      calculate the first, last frames of the numbered GOP
01073  *
01074  * RETURNS:     lastFrame, firstFrame changed
01075  *
01076  * SIDE EFFECTS:    none
01077  *
01078  *===========================================================================*/
01079 static void
01080 ComputeGOPFrames(whichGOP, firstFrame, lastFrame, numFrames)
01081     int whichGOP;
01082     int *firstFrame;
01083     int *lastFrame;
01084     int numFrames;
01085 {
01086     int     passedB;
01087     int     currGOP;
01088     int     gopNum, frameNum;
01089 
01090     /* calculate first, last frames of whichGOP GOP */
01091 
01092     *firstFrame = -1;
01093     *lastFrame = -1;
01094     gopNum = 0;
01095     frameNum = 0;
01096     passedB = 0;
01097     currGOP = 0;
01098     while ( *lastFrame == -1 ) {
01099         if ( frameNum >= numFrames ) {
01100             fprintf(stderr, "ERROR:  There aren't that many GOPs!\n");
01101             exit(1);
01102         }
01103 
01104 #ifdef BLEAH
01105 if (! realQuiet) {
01106 fprintf(stdout, "GOP STARTS AT %d\n", frameNum-passedB);
01107 }
01108 #endif
01109 
01110         if ( gopNum == whichGOP ) {
01111             *firstFrame = frameNum;
01112         }
01113 
01114         /* go past one gop */
01115         /* must go past at least one frame */
01116         do {
01117             currGOP += (1 + passedB);
01118 
01119             frameNum++;
01120 
01121             passedB = 0;
01122             while ( (frameNum < numFrames) && (FType_Type(frameNum) == 'b') ) {
01123                 frameNum++;
01124                 passedB++;
01125             }
01126         } while ( (frameNum < numFrames) && 
01127                   ((FType_Type(frameNum) != 'i') || (currGOP < gopSize)) );
01128 
01129         currGOP -= gopSize;
01130 
01131         if ( gopNum == whichGOP ) {
01132             *lastFrame = (frameNum-passedB-1);
01133         }
01134 
01135 #ifdef BLEAH
01136 if (! realQuiet) {
01137 fprintf(stdout, "GOP ENDS at %d\n", frameNum-passedB-1);
01138 }
01139 #endif
01140 
01141         gopNum++;
01142     }
01143 }
01144 
01145 
01146 /*===========================================================================*
01147  *
01148  * PrintEndStats
01149  *
01150  *      print end statistics (summary, time information)
01151  *
01152  * RETURNS:     nothing
01153  *
01154  * SIDE EFFECTS:    none
01155  *
01156  *===========================================================================*/
01157 static void
01158 PrintEndStats(inputFrameBits, totalBits)
01159     int inputFrameBits;
01160     int32 totalBits;
01161 {
01162     FILE *fpointer;
01163     register int i;
01164     char    timeText[256];
01165     float   totalCPU;
01166 
01167     if (! realQuiet) {
01168         fprintf(stdout, "\n\n");
01169     }
01170 
01171     ComputeDHMSTime(diffTime, timeText);
01172 
01173     for ( i = 0; i < 2; i++ ) {
01174         if ( ( i == 0 ) && (! realQuiet) ) {
01175             fpointer = stdout;
01176         } else if ( statFile != NULL ) {
01177             fpointer = statFile;
01178         } else {
01179             continue;
01180         }
01181 
01182         fprintf(fpointer, "TIME COMPLETED:  %s", ctime(&timeEnd));
01183         fprintf(fpointer, "%s\n\n", timeText);
01184 
01185         totalCPU = 0.0;
01186         totalCPU += ShowIFrameSummary(inputFrameBits, totalBits, fpointer);
01187         totalCPU += ShowPFrameSummary(inputFrameBits, totalBits, fpointer);
01188         totalCPU += ShowBFrameSummary(inputFrameBits, totalBits, fpointer);
01189         fprintf(fpointer, "---------------------------------------------\n");
01190         fprintf(fpointer, "Total Compression:  %3d:1     (%9.4f bpp)\n",
01191                 framesOutput*inputFrameBits/totalBits,
01192                 24.0*(float)(totalBits)/(float)(framesOutput*inputFrameBits));
01193         if (diffTime > 0) {
01194           fprintf(fpointer, "Total Frames Per Second:  %f (%ld mps)\n",
01195                   (float)framesOutput/(float)diffTime,
01196                   (long)((float)framesOutput*(float)inputFrameBits/(256.0*24.0*(float)diffTime)));
01197         } else {
01198           fprintf(fpointer, "Total Frames Per Second:  Infinite!\n");
01199         }
01200         if ( totalCPU == 0.0 ) {
01201             fprintf(fpointer, "CPU Time:  NONE!\n");
01202         } else {
01203             fprintf(fpointer, "CPU Time:  %f fps     (%ld mps)\n",
01204                     (float)framesOutput/totalCPU,
01205                      (long)((float)framesOutput*(float)inputFrameBits/(256.0*24.0*totalCPU)));
01206         }
01207         fprintf(fpointer, "Total Output Bit Rate (%d fps):  %d bits/sec\n",
01208                 frameRateRounded, frameRateRounded*totalBits/framesOutput);
01209         fprintf(fpointer, "MPEG file created in :  %s\n", outputFileName);
01210         fprintf(fpointer, "\n\n");
01211 
01212         if ( computeMVHist ) {
01213             ShowPMVHistogram(fpointer);
01214             ShowBBMVHistogram(fpointer);
01215             ShowBFMVHistogram(fpointer);
01216         }
01217     }
01218 
01219     if ( statFile != NULL ) {
01220         fclose(statFile);
01221     }
01222 }
01223 
01224 
01225 /*===========================================================================*
01226  *
01227  * ProcessRefFrame
01228  *
01229  *      process an I or P frame -- encode it, and process any B frames that
01230  *      we can now
01231  *
01232  * RETURNS:     nothing
01233  *
01234  * SIDE EFFECTS:    stuff appended to bb
01235  *
01236  *===========================================================================*/
01237 static void
01238   ProcessRefFrame(frame, bb, lastFrame, outputFileName)
01239 MpegFrame *frame;
01240 BitBucket *bb;
01241 int lastFrame;
01242 char *outputFileName;
01243 {
01244   MpegFrame *bFrame = NULL;
01245   char    fileName[1024];
01246   char    inputFileName[1024];
01247   FILE    *fpointer = NULL;
01248   boolean separateFiles;
01249   int       id;
01250   time_t  tempTimeStart, tempTimeEnd;
01251   
01252   separateFiles = (bb == NULL);
01253   
01254   if ( separateFiles && (frame->id >= realStart) &&
01255       (frame->id <= realEnd) ) {
01256     if ( remoteIO ) {
01257       bb = Bitio_New(NULL);
01258     } else {
01259       sprintf(fileName, "%s.frame.%d", outputFileName, frame->id);
01260       if ( (fpointer = fopen(fileName, "wb")) == NULL ) {
01261         fprintf(stderr, "ERROR:  Could not open output file(1):  %s\n",
01262                 fileName);
01263         exit(1);
01264       }
01265       
01266       bb = Bitio_New(fpointer);
01267     }
01268   }
01269   
01270   /* nothing to do */
01271   if ( frame->id < realStart ) {
01272     return;
01273   }
01274   
01275   /* first, output this frame */
01276   if ( frame->type == TYPE_IFRAME ) {
01277       
01278 #ifdef BLEAH
01279     fprintf(stdout, "I-frame %d, currentGOP = %d\n",
01280             frame->id, currentGOP);
01281     fflush(stdout);
01282 #endif
01283       
01284     /* only start a new GOP with I */
01285     /* don't start GOP if only doing frames */
01286     if ( (! separateFiles) && (currentGOP >= gopSize) ) {
01287       int closed;
01288       static int num_gop = 0;
01289         
01290       /* first, check to see if closed GOP */
01291       if ( totalFramesSent == frame->id || pastRefFrame == NULL) {
01292         closed = 1;
01293       } else {
01294         closed = 0;
01295       }
01296         
01297       /* new GOP */
01298       if (num_gop != 0 && mult_seq_headers && num_gop % mult_seq_headers == 0) {
01299         if (! realQuiet) {
01300           fprintf(stdout, "Creating new Sequence before GOP %d\n", num_gop);
01301           fflush(stdout);
01302         }
01303           
01304         Mhead_GenSequenceHeader(bb, Fsize_x, Fsize_y,
01305                                 /* pratio */    aspectRatio,
01306                                 /* pict_rate */ frameRate, /* bit_rate */ bit_rate,
01307                                 /* buf_size */  buf_size,  /* c_param_flag */ 1,
01308                                 /* iq_matrix */ customQtable, /* niq_matrix */ customNIQtable,
01309                                 /* ext_data */ NULL,  /* ext_data_size */ 0,
01310                                 /* user_data */ NULL, /* user_data_size */ 0);
01311       }
01312         
01313       if (! realQuiet) {
01314         fprintf(stdout, "Creating new GOP (closed = %c) before frame %d\n",
01315                 "FT"[closed], frame->id);
01316         fflush(stdout);
01317       }
01318         
01319       num_gop++;
01320       Mhead_GenGOPHeader(bb,    /* drop_frame_flag */ 0,
01321                          tc_hrs, tc_min, tc_sec, tc_pict,
01322                          closed, /* broken_link */ 0,
01323                          /* ext_data */ NULL, /* ext_data_size */ 0,
01324                          /* user_data */ NULL, /* user_data_size */ 0);
01325       currentGOP -= gopSize;
01326       if (pastRefFrame == NULL) {
01327         SetGOPStartTime(0);
01328       } else {
01329         SetGOPStartTime(pastRefFrame->id+1);
01330       }
01331     }
01332       
01333     if ( (frame->id >= realStart) && (frame->id <= realEnd) ) {
01334       GenIFrame(bb, frame);
01335         
01336       framesOutput++;
01337         
01338       if ( separateFiles ) {
01339         if ( remoteIO ) {
01340           SendRemoteFrame(frame->id, bb);
01341         } else {
01342           Bitio_Flush(bb);
01343           fclose(fpointer);
01344         }
01345       }
01346     }
01347       
01348     numI--;
01349     timeMask &= 0x6;
01350       
01351     currentGOP++;
01352     IncrementTCTime();
01353   } else {
01354     if ( (frame->id >= realStart) && (frame->id <= realEnd) ) {
01355       GenPFrame(bb, frame, pastRefFrame);
01356         
01357       framesOutput++;
01358         
01359       if ( separateFiles ) {
01360         if ( remoteIO ) {
01361           SendRemoteFrame(frame->id, bb);
01362         } else {
01363           Bitio_Flush(bb);
01364           fclose(fpointer);
01365         }
01366       }
01367     }
01368     
01369     numP--;
01370     timeMask &= 0x5;
01371     ShowRemainingTime();
01372     
01373     currentGOP++;
01374     IncrementTCTime();
01375   }
01376   
01377   /* now, output B-frames */
01378   if ( pastRefFrame != NULL ) {
01379     for ( id = pastRefFrame->id+1; id < futureRefFrame->id; id++ ) {
01380       if ( ! ((id >= realStart) && (id <= realEnd)) )
01381         continue;
01382         
01383       if ( ! stdinUsed ) {
01384         bFrame = Frame_New(id, 'b');
01385           
01386         time(&tempTimeStart);
01387           
01388         /* read B frame, output it */
01389         if ( remoteIO ) {
01390           GetRemoteFrame(bFrame, bFrame->id);
01391         } else {
01392           GetNthInputFileName(inputFileName, id);
01393           if ( childProcess && separateConversion ) {
01394             ReadFrame(bFrame, inputFileName, slaveConversion, TRUE);
01395           } else {
01396             ReadFrame(bFrame, inputFileName, inputConversion, TRUE);
01397           }
01398         }
01399           
01400         time(&tempTimeEnd);
01401         IOtime += (tempTimeEnd-tempTimeStart);
01402           
01403         framesRead++;
01404       } else {
01405           
01406         /* retrieve and remove B-frame from queue set up in 
01407          * GenMPEGStream 
01408          */
01409         bFrame = pastRefFrame->next;
01410         pastRefFrame->next = bFrame->next;
01411       }
01412         
01413         
01414       if ( separateFiles ) {
01415         if ( remoteIO ) {
01416           bb = Bitio_New(NULL);
01417         } else {
01418           sprintf(fileName, "%s.frame.%d", outputFileName, 
01419                   bFrame->id);
01420           if ( (fpointer = fopen(fileName, "wb")) == NULL ) {
01421             fprintf(stderr, "ERROR:  Could not open output file(2):  %s\n",
01422                     fileName);
01423             exit(1);
01424           }
01425           bb = Bitio_New(fpointer);
01426         }
01427       }
01428         
01429       GenBFrame(bb, bFrame, pastRefFrame, futureRefFrame);
01430       framesOutput++;
01431         
01432       if ( separateFiles ) {
01433         if ( remoteIO ) {
01434           SendRemoteFrame(bFrame->id, bb);
01435         } else {
01436           Bitio_Flush(bb);
01437           fclose(fpointer);
01438         }
01439       }
01440         
01441       /* free this B frame right away */
01442       Frame_Free(bFrame);
01443         
01444       numB--;
01445       timeMask &= 0x3;
01446       ShowRemainingTime();
01447         
01448       currentGOP++;
01449       IncrementTCTime();
01450     }
01451   } else {
01452     /* SRS replicated code */
01453     for ( id = 0; id < futureRefFrame->id; id++ ) {
01454       if ( ! ((id >= realStart) && (id <= realEnd)) )
01455         continue;
01456 
01457       if ( ! stdinUsed ) {
01458         bFrame = Frame_New(id, 'b');
01459 
01460         time(&tempTimeStart);
01461 
01462         /* read B frame, output it */
01463         if ( remoteIO ) {
01464           GetRemoteFrame(bFrame, bFrame->id);
01465         } else {
01466           GetNthInputFileName(inputFileName, id);
01467           if ( childProcess && separateConversion ) {
01468             ReadFrame(bFrame, inputFileName, slaveConversion, TRUE);
01469           } else {
01470             ReadFrame(bFrame, inputFileName, inputConversion, TRUE);
01471           }
01472         }
01473 
01474         time(&tempTimeEnd);
01475         IOtime += (tempTimeEnd-tempTimeStart);
01476 
01477         framesRead++;
01478       } else {
01479             
01480         /* retrieve and remove B-frame from queue set up in 
01481          * GenMPEGStream 
01482          */
01483         printf("Yow, I doubt this works!\n");
01484         bFrame = pastRefFrame->next;
01485         pastRefFrame->next = bFrame->next;
01486       }
01487 
01488 
01489       if ( separateFiles ) {
01490         if ( remoteIO ) {
01491           bb = Bitio_New(NULL);
01492         } else {
01493           sprintf(fileName, "%s.frame.%d", outputFileName, 
01494                   bFrame->id);
01495           if ( (fpointer = fopen(fileName, "wb")) == NULL ) {
01496             fprintf(stderr, "ERROR:  Could not open output file(2):  %s\n",
01497                     fileName);
01498             exit(1);
01499           }
01500           bb = Bitio_New(fpointer);
01501         }
01502       }
01503 
01504       GenBFrame(bb, bFrame, (MpegFrame *)NULL, futureRefFrame);
01505       framesOutput++;
01506 
01507       if ( separateFiles ) {
01508         if ( remoteIO ) {
01509           SendRemoteFrame(bFrame->id, bb);
01510         } else {
01511           Bitio_Flush(bb);
01512           fclose(fpointer);
01513         }
01514       }
01515 
01516       /* free this B frame right away */
01517       Frame_Free(bFrame);
01518 
01519       numB--;
01520       timeMask &= 0x3;
01521       ShowRemainingTime();
01522 
01523       currentGOP++;
01524       IncrementTCTime();
01525     }
01526     
01527   }
01528   
01529   /* now free previous frame, if there was one */
01530   if ( pastRefFrame != NULL ) {
01531     Frame_Free(pastRefFrame);
01532   }
01533   
01534   /* note, we may still not free last frame if lastFrame is incorrect
01535    * (if the last frames are B frames, they aren't output!)
01536    */
01537 }
01538 
01539 
01540 /*===========================================================================*
01541  *
01542  * ShowRemainingTime
01543  *
01544  *      print out an estimate of the time left to encode
01545  *
01546  * RETURNS:     nothing
01547  *
01548  * SIDE EFFECTS:    none
01549  *
01550  *===========================================================================*/
01551 static void
01552 ShowRemainingTime()
01553 {
01554     static int  lastTime = 0;
01555     float   total;
01556     time_t  nowTime;
01557     float   secondsPerFrame;
01558 
01559     if ( childProcess ) {
01560         return /* nothing */;
01561     }
01562 
01563     if ( numI + numP + numB == 0 ) {    /* no time left */
01564         return /* nothing */ ;
01565     }
01566 
01567     if ( timeMask != 0 ) {          /* haven't encoded all types yet */
01568         return /* nothing */ ;
01569     }
01570 
01571     time(&nowTime);
01572     secondsPerFrame = (nowTime-timeStart)/(float)framesOutput;
01573     total = secondsPerFrame*(float)(numI+numP+numB);
01574 
01575 #ifdef BLEAH
01576     float   timeI, timeP, timeB;
01577 
01578     timeI = EstimateSecondsPerIFrame();
01579     timeP = EstimateSecondsPerPFrame();
01580     timeB = EstimateSecondsPerBFrame();
01581     total = (float)numI*timeI + (float)numP*timeP + (float)numB*timeB;
01582 #endif
01583 
01584     if ( (quietTime >= 0) && (! realQuiet) && (! stdinUsed) &&
01585          ((lastTime < (int)total) || ((lastTime-(int)total) >= quietTime) ||
01586           (lastTime == 0) || (quietTime == 0)) ) {
01587         if ( total > 270.0 ) {
01588             fprintf(stdout, "ESTIMATED TIME OF COMPLETION:  %d minutes\n",
01589                     ((int)total+30)/60);
01590         } else {
01591             fprintf(stdout, "ESTIMATED TIME OF COMPLETION:  %d seconds\n",
01592                     (int)total);
01593         }
01594 
01595         lastTime = (int)total;
01596     }
01597 }
01598 
01599 
01600 void
01601 ReadDecodedRefFrame(frame, frameNumber)
01602     MpegFrame *frame;
01603     int frameNumber;
01604 {
01605     FILE    *fpointer;
01606     char    fileName[256];
01607     int width, height;
01608     register int y;
01609 
01610     width = Fsize_x;
01611     height = Fsize_y;
01612 
01613     sprintf(fileName, "%s.decoded.%d", outputFileName, frameNumber);
01614     if (! realQuiet) {
01615         fprintf(stdout, "reading %s\n", fileName);
01616         fflush(stdout);
01617     }
01618 
01619     if ((fpointer = fopen(fileName, "rb")) == NULL) {
01620       sleep(1);
01621       if ((fpointer = fopen(fileName, "rb")) == NULL) {
01622         fprintf(stderr, "Cannot open %s\n", fileName);
01623         exit(1);
01624       }}
01625 
01626     Frame_AllocDecoded(frame, TRUE);
01627     
01628     for ( y = 0; y < height; y++ ) {
01629       if (fread(frame->decoded_y[y], 1, width, fpointer) != width) {
01630         fprintf(stderr, "Could not read enough bytes from %s\n", fileName);
01631       }
01632     }
01633     
01634     for (y = 0; y < (height >> 1); y++) {                       /* U */
01635       if (fread(frame->decoded_cb[y], 1, width >> 1, fpointer) != (width>>1)) {
01636         fprintf(stderr, "Could not read enough bytes from %s\n", fileName);
01637       }
01638     }
01639     
01640     for (y = 0; y < (height >> 1); y++) {                       /* V */
01641       if (fread(frame->decoded_cr[y], 1, width >> 1, fpointer) != (width>>1)) {
01642         fprintf(stderr, "Could not read enough bytes from %s\n", fileName);
01643       }
01644     }
01645     
01646     fclose(fpointer);
01647 }
01648 
01649 
01650 static void
01651 OpenBitRateFile()
01652 {
01653     bitRateFile = fopen(bitRateFileName, "w");
01654     if ( bitRateFile == NULL ) {
01655         fprintf(stderr, "ERROR:  Could not open bit rate file:  %s\n", bitRateFileName);
01656         fprintf(stderr, "\n\n");
01657         showBitRatePerFrame = FALSE;
01658     }
01659 }
01660 
01661 
01662 static void
01663 CloseBitRateFile()
01664 {
01665 #ifdef BLEAH
01666     char command[256];
01667 #endif
01668 
01669     fclose(bitRateFile);
01670 #ifdef BLEAH
01671     sprintf(command, "sort -n %s > /tmp/fubahr", bitRateFileName);
01672     system(command);
01673     sprintf(command, "mv /tmp/fubahr %s", bitRateFileName);
01674     system(command);
01675 #endif
01676 }
 

Powered by Plone

This site conforms to the following standards: