00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
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
00167
00168
00169 #define VERSION "1.5b"
00170
00171
00172
00173
00174
00175
00176 #define FPS_30 0x5
00177 #define ASPECT_1 0x1
00178
00179
00180
00181
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
00194
00195
00196
00197
00198
00199 extern int IOtime;
00200 extern boolean resizeFrame;
00201 extern int outputWidth, outputHeight;
00202 int gopSize = 100;
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
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
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
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
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
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
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
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
00410 if ( FType_Type(firstFrame) != 'i' ) {
00411
00412
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
00422 if ( (FType_Type(lastFrame) == 'b') && (lastFrame != numFrames-1) ) {
00423
00424
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 ) {
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
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;
00484
00485
00486 bitstreamMode = getRateMode();
00487 if (bitstreamMode == FIXED_RATE) {
00488 res = initRateControl();
00489
00490
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
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
00517
00518
00519
00520
00521
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
00537
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
00549
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 {
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 aspectRatio,
00649 frameRate, bit_rate,
00650 buf_size, 1,
00651 qtable, niqtable,
00652 NULL, 0,
00653 userData, 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
00668 if ( (whichGOP == -1) && (frameStart == -1) ) {
00669 Mhead_GenSequenceEnder(bb);
00670 }
00671
00672 if ( frameStart == -1 ) {
00673
00674
00675 numBits = bb->cumulativeBits;
00676 } else {
00677
00678
00679
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
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737 void
00738 IncrementTCTime()
00739 {
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
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 ) {
00770 tc_pict++;
00771 tc_extra -= 1001;
00772 }
00773 }
00774 }
00775 }
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 void
00790 SetStatFileName(fileName)
00791 char *fileName;
00792 {
00793 strcpy(statFileName, fileName);
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808 void
00809 SetGOPSize(size)
00810 int size;
00811 {
00812 gopSize = size;
00813 }
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
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");
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
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
00929
00930
00931
00932
00933
00934
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
00951 if ( lastIPid+1 < realStart ) {
00952 return TRUE;
00953 }
00954
00955
00956 nextIPid = FType_FutureRef(id);
00957
00958
00959 if ( nextIPid-1 > realEnd ) {
00960 return TRUE;
00961 }
00962
00963
00964 if ( (nextIPid > realEnd) && (FType_Type(nextIPid) == 'p') ) {
00965 return TRUE;
00966 }
00967
00968 return FALSE;
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
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
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
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
01071
01072
01073
01074
01075
01076
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
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
01115
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
01149
01150
01151
01152
01153
01154
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
01228
01229
01230
01231
01232
01233
01234
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
01271 if ( frame->id < realStart ) {
01272 return;
01273 }
01274
01275
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
01285
01286 if ( (! separateFiles) && (currentGOP >= gopSize) ) {
01287 int closed;
01288 static int num_gop = 0;
01289
01290
01291 if ( totalFramesSent == frame->id || pastRefFrame == NULL) {
01292 closed = 1;
01293 } else {
01294 closed = 0;
01295 }
01296
01297
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 aspectRatio,
01306 frameRate, bit_rate,
01307 buf_size, 1,
01308 customQtable, customNIQtable,
01309 NULL, 0,
01310 NULL, 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, 0,
01321 tc_hrs, tc_min, tc_sec, tc_pict,
01322 closed, 0,
01323 NULL, 0,
01324 NULL, 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
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
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
01407
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
01442 Frame_Free(bFrame);
01443
01444 numB--;
01445 timeMask &= 0x3;
01446 ShowRemainingTime();
01447
01448 currentGOP++;
01449 IncrementTCTime();
01450 }
01451 } else {
01452
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
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
01481
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
01517 Frame_Free(bFrame);
01518
01519 numB--;
01520 timeMask &= 0x3;
01521 ShowRemainingTime();
01522
01523 currentGOP++;
01524 IncrementTCTime();
01525 }
01526
01527 }
01528
01529
01530 if ( pastRefFrame != NULL ) {
01531 Frame_Free(pastRefFrame);
01532 }
01533
01534
01535
01536
01537 }
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
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 ;
01561 }
01562
01563 if ( numI + numP + numB == 0 ) {
01564 return ;
01565 }
01566
01567 if ( timeMask != 0 ) {
01568 return ;
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++) {
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++) {
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 }