/*===========================================================================* * main.c * * * * Main procedure * * * * EXPORTED PROCEDURES: * * main * * * *===========================================================================*/ /* * Copyright (c) 1995 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ /* * $Header: /n/picasso/project/mpeg/mpeg_dist/mpeg_encode/RCS/main.c,v 1.25 1995/08/07 21:44:21 smoot Exp $ * $Log: main.c,v $ * Revision 1.25 1995/08/07 21:44:21 smoot * renamed index -> idx; save the encoder's name; compute frame types ahead of time * * Revision 1.24 1995/06/21 18:25:57 smoot * added binary write flag (DOS!) * * Revision 1.23 1995/05/16 06:25:28 smoot * added TUNEing init and float-dct == float_dct * * Revision 1.22 1995/05/16 00:15:05 smoot * fixed usage print * * Revision 1.21 1995/05/11 23:59:56 smoot * *** empty log message *** * * Revision 1.20 1995/02/02 20:05:37 eyhung * fixed smoot typo in 1.19 * * Revision 1.19 1995/02/02 18:56:11 smoot * ANSI-ified some prototypes * * Revision 1.18 1995/02/01 21:47:37 smoot * cleanup * * Revision 1.17 1995/01/31 22:22:49 eyhung * Fixed steve's typo and added float_dct to Usage() * * Revision 1.16 1995/01/31 21:44:08 smoot * Added -float_dct option * * Revision 1.15 1995/01/31 01:19:39 eyhung * removed -interactive * * Revision 1.14 1995/01/27 21:56:57 eyhung * Deleted setting JMOVIE_TYPE to JPEG_TYPE since we need to know * if we started with a JMOVIE for getting input files * * Revision 1.13 1995/01/19 23:50:06 eyhung * Removed printing of output file to screen - done at end of encoding now. * * Revision 1.12 1995/01/19 23:08:41 eyhung * Changed copyrights * * Revision 1.11 1995/01/17 08:25:44 eyhung * added -interactive to Usage * * Revision 1.10 1995/01/17 08:24:53 eyhung * Added -interactive option * * Revision 1.9 1995/01/16 08:04:10 eyhung * More realQuiet stuff. * * Revision 1.8 1995/01/16 07:38:49 eyhung * Added realquiet option * * Revision 1.7 1994/11/14 22:32:01 smoot * Merged specifics and rate control * * Revision 1.6 1994/11/12 02:11:52 keving * nothing * * Revision 1.5 1994/03/15 00:27:11 keving * nothing * * Revision 1.4 1993/12/22 19:19:01 keving * nothing * * Revision 1.3 1993/07/22 22:23:43 keving * nothing * * Revision 1.2 1993/06/30 20:06:09 keving * nothing * * Revision 1.1 1993/02/17 23:18:20 dwallach * Initial revision * */ /*==============* * HEADER FILES * *==============*/ #include #include "all.h" #include "mtypes.h" #include "mpeg.h" #include "motion_search.h" #include "prototypes.h" #include "param.h" #include "parallel.h" #include "readframe.h" #include "combine.h" #include "frames.h" #include "jpeg.h" #include "specifics.h" #include "opts.h" #include "ppm.h" #include int main _ANSI_ARGS_((int argc, char **argv)); /*==================* * STATIC VARIABLES * *==================*/ static int frameStart = -1; static int frameEnd; /*==================* * GLOBAL VARIABLES * *==================*/ extern time_t IOtime; int whichGOP = -1; boolean childProcess = FALSE; boolean ioServer = FALSE; boolean outputServer = FALSE; boolean decodeServer = FALSE; int quietTime = 0; boolean realQuiet = FALSE; boolean frameSummary = TRUE; boolean debugSockets = FALSE; boolean debugMachines = FALSE; boolean showBitRatePerFrame = FALSE; boolean computeMVHist = FALSE; int baseFormat; extern boolean specificsOn; extern FrameSpecList *fsl; boolean pureDCT=FALSE; char encoder_name[1024]; /*===============================* * INTERNAL PROCEDURE prototypes * *===============================*/ static void Usage _ANSI_ARGS_((void)); static void CompileTests _ANSI_ARGS_((void)); /*================================* * External PROCEDURE prototypes * *================================*/ void init_idctref _ANSI_ARGS_((void)); void init_fdct _ANSI_ARGS_((void)); /*=====================* * EXPORTED PROCEDURES * *=====================*/ /*===========================================================================* * * main * * see man page. run without arguments to see usage * * RETURNS: 0 if all is well; 1 on most if not all errors * *===========================================================================*/ int main(int argc, char **argv) { FILE *ofp = NULL; register int idx; int function = ENCODE_FRAMES; int portNumber = 0; char *hostName = NULL; int32 totalTime = -1; int maxMachines = 0x7fffffff; int outputFrames = 0; time_t initTimeStart; time_t framesTimeStart, framesTimeEnd; ppm_init(&argc, argv); strcpy(encoder_name, argv[0]); CompileTests(); time(&initTimeStart); if ( argc == 1 ) { Usage(); } SetStatFileName(""); /* parse the arguments */ idx = 1; while ( idx < argc-1 ) { if ( argv[idx][0] != '-' ) { Usage(); } if ( strcmp(argv[idx], "-stat") == 0 ) { if ( idx+1 < argc-1 ) { SetStatFileName(argv[idx+1]); idx += 2; } else { Usage(); } } else if ( strcmp(argv[idx], "-gop") == 0 ) { if ( (function != ENCODE_FRAMES) || (frameStart != -1) ) { Usage(); } if ( idx+1 < argc-1 ) { whichGOP = atoi(argv[idx+1]); idx += 2; } else { Usage(); } } else if ( strcmp(argv[idx], "-frames") == 0 ) { if ( (function != ENCODE_FRAMES) || (whichGOP != -1) ) { Usage(); } if ( idx+2 < argc-1 ) { frameStart = atoi(argv[idx+1]); frameEnd = atoi(argv[idx+2]); if ( (frameStart > frameEnd) || (frameStart < 0) ) { fprintf(stderr, "ERROR: bad frame numbers!\n"); Usage(); } idx += 3; } else { Usage(); } } else if ( strcmp(argv[idx], "-combine_gops") == 0 ) { if ( (function != ENCODE_FRAMES) || (whichGOP != -1) || (frameStart != -1) ) { Usage(); } function = COMBINE_GOPS; idx++; } else if ( strcmp(argv[idx], "-combine_frames") == 0 ) { if ( (function != ENCODE_FRAMES) || (whichGOP != -1) || (frameStart != -1) ) { Usage(); } function = COMBINE_FRAMES; idx++; } else if ( strcmp(argv[idx], "-child") == 0 ) { if ( idx+7 < argc-1 ) { hostName = argv[idx+1]; portNumber = atoi(argv[idx+2]); ioPortNumber = atoi(argv[idx+3]); combinePortNumber = atoi(argv[idx+4]); decodePortNumber = atoi(argv[idx+5]); machineNumber = atoi(argv[idx+6]); remoteIO = atoi(argv[idx+7]); IOhostName = hostName; } else { Usage(); } childProcess = TRUE; idx += 8; } else if ( strcmp(argv[idx], "-io_server") == 0 ) { if ( idx+2 < argc-1 ) { hostName = argv[idx+1]; portNumber = atoi(argv[idx+2]); } else { Usage(); } ioServer = TRUE; idx += 3; } else if ( strcmp(argv[idx], "-output_server") == 0 ) { if ( idx+3 < argc-1 ) { hostName = argv[idx+1]; portNumber = atoi(argv[idx+2]); outputFrames = atoi(argv[idx+3]); } else { Usage(); } function = COMBINE_FRAMES; outputServer = TRUE; idx += 4; } else if ( strcmp(argv[idx], "-decode_server") == 0 ) { if ( idx+3 < argc-1 ) { hostName = argv[idx+1]; portNumber = atoi(argv[idx+2]); outputFrames = atoi(argv[idx+3]); } else { Usage(); } function = COMBINE_FRAMES; decodeServer = TRUE; idx += 4; } else if ( strcmp(argv[idx], "-nice") == 0 ) { niceProcesses = TRUE; idx++; } else if ( strcmp(argv[idx], "-max_machines") == 0 ) { if ( idx+1 < argc-1 ) { maxMachines = atoi(argv[idx+1]); } else { Usage(); } idx += 2; } else if ( strcmp(argv[idx], "-quiet") == 0 ) { if ( idx+1 < argc-1 ) { quietTime = atoi(argv[idx+1]); } else { Usage(); } idx += 2; } else if ( strcmp(argv[idx], "-realquiet") == 0 ) { realQuiet = TRUE; idx++; } else if (( strcmp(argv[idx], "-float_dct") == 0 ) || ( strcmp(argv[idx], "-float-dct") == 0 )) { pureDCT = TRUE; init_idctref(); init_fdct(); idx++; } else if ( strcmp(argv[idx], "-no_frame_summary") == 0 ) { if ( idx < argc-1 ) { frameSummary = FALSE; } else { Usage(); } idx++; } else if ( strcmp(argv[idx], "-snr") == 0 ) { printSNR = TRUE; idx++; } else if ( strcmp(argv[idx], "-mse") == 0 ) { printSNR = printMSE = TRUE; idx++; } else if ( strcmp(argv[idx], "-debug_sockets") == 0 ) { debugSockets = TRUE; idx++; } else if ( strcmp(argv[idx], "-debug_machines") == 0 ) { debugMachines = TRUE; idx++; } else if ( strcmp(argv[idx], "-bit_rate_info") == 0 ) { if ( idx+1 < argc-1 ) { showBitRatePerFrame = TRUE; SetBitRateFileName(argv[idx+1]); idx += 2; } else { Usage(); } } else if ( strcmp(argv[idx], "-mv_histogram") == 0 ) { computeMVHist = TRUE; idx++; } else { Usage(); } } if ( ! ReadParamFile(argv[argc-1], function) ) { Usage(); } /* Jim Boucher's stuff: if we are using a movie format then break up into frames*/ if ( (!childProcess) && (baseFormat == JMOVIE_FILE_TYPE) ) { JM2JPEG(); } if ( printSNR || (referenceFrame == DECODED_FRAME) ) { decodeRefFrames = TRUE; } numMachines = min(numMachines, maxMachines); Tune_Init(); Frame_Init(); if (specificsOn) Specifics_Init(); ComputeFrameTable(); if ( ioServer ) { StartIOServer(numInputFiles, hostName, portNumber); return 0; } else if ( outputServer ) { StartCombineServer(outputFrames, outputFileName, hostName, portNumber); return 0; } else if ( decodeServer ) { StartDecodeServer(outputFrames, outputFileName, hostName, portNumber); return 0; } if ( (frameStart == -1) && ((numMachines == 0) || (function != ENCODE_FRAMES)) ) { if ( (ofp = fopen(outputFileName, "wb")) == NULL ) { fprintf(stderr, "ERROR: Could not open output file!\n"); exit(1); } } if ( function == ENCODE_FRAMES ) { if ( (numMachines == 0) || (frameStart != -1) ) { time(&framesTimeStart); totalTime = GenMPEGStream(whichGOP, frameStart, frameEnd, customQtable, customNIQtable, numInputFiles, ofp, outputFileName); time(&framesTimeEnd); if ( childProcess && (! realQuiet) ) { fprintf(stdout, "%s: FRAMES %d-%d (%d seconds)\n", getenv("HOST"), frameStart, frameEnd, (int) (framesTimeEnd-framesTimeStart)); fflush(stdout); } } else { /* check if parameter file has absolute path */ if ( (argv[argc-1][0] != '/') && (argv[argc-1][0] != '~') ) { fprintf(stderr, "ERROR: For parallel execution, " "please use absolute path for parameter file!\n"); exit(1); } else { StartMasterServer(numInputFiles, argv[argc-1], outputFileName); } } } else if ( function == COMBINE_GOPS ) { GOPStoMPEG(numInputFiles, outputFileName, ofp); } else if ( function == COMBINE_FRAMES ) { FramesToMPEG(numInputFiles, outputFileName, ofp, FALSE); } if ( childProcess ) { bool moreWorkToDo; moreWorkToDo = TRUE; /* initial assumption */ while (moreWorkToDo) { NotifyMasterDone(hostName, portNumber, machineNumber, totalTime, &frameStart, &frameEnd); if (frameStart < 0) moreWorkToDo = FALSE; else { /* do more frames */ time(&framesTimeStart); totalTime = GenMPEGStream(-1, frameStart, frameEnd, customQtable, customNIQtable, numInputFiles, NULL, outputFileName); time(&framesTimeEnd); if (! realQuiet) { fprintf(stdout, "%s: FRAMES %d-%d (%d seconds)\n", getenv("HOST"), frameStart, frameEnd, (int) (framesTimeEnd-framesTimeStart)); fflush(stdout); } } } } Frame_Exit(); return 0; /* all is well */ } /*=====================* * INTERNAL PROCEDURES * *=====================*/ /*===========================================================================* * * Usage * * prints out usage for the program * * RETURNS: nothing * * SIDE EFFECTS: none * *===========================================================================*/ static void Usage() { fprintf(stderr, "Usage: ppmtompeg [options] param_file\n"); fprintf(stderr, "Options:\n"); fprintf(stderr, "\t-stat stat_file: append stats to stat_file\n"); fprintf(stderr, "\t-quiet n: don't report remaining time for at least n seconds\n"); fprintf(stderr, "\t-realquiet: output nothing at all if successful\n"); fprintf(stderr, "\t-no_frame_summary: suppress frame summary lines\n"); fprintf(stderr, "\t-float_dct: use more accurate floating point DCT\n"); fprintf(stderr, "\t-gop gop_num: encode only the numbered GOP\n"); fprintf(stderr, "\t-combine_gops: combine GOP files instead of encode\n"); fprintf(stderr, "\t-frames first_frame last_frame: encode only the specified frames\n"); fprintf(stderr, "\t-combine_frames: combine frame files instead of encode\n"); fprintf(stderr, "\t-nice: run slave processes nicely\n"); fprintf(stderr, "\t-max_machines num_machines: use at most num_machines machines\n"); fprintf(stderr, "\t-snr: print signal-to-noise ratio\n"); fprintf(stderr, "\t-bit_rate_info rate_file: put bit rate in specified file\n"); fprintf(stderr, "\t-mv_histogram: show histograms of motion vectors\n"); exit(1); /* extended usage (used by parallel code; shouldn't be called by user): -child parallelHostName portNumber ioPortNumber combinePortNumber machineNumber remote -io_server parallelHostName portNumber (remote = 1 if need to use ioPortNumber) */ } static void CompileTests() { /* There was code here (assert() calls) that verified that uint16 is 16 bits, etc. It caused compiler warnings that said, "Of course it is!" (actually, "statement has no effect"). There isn't enough chance that uint16, etc. are defined incorrectly to warrant those asserts. 2000.05.07 */ if ( (-8 >> 3) != -1 ) { fprintf(stderr, "ERROR: Right shifts are NOT arithmetic!!!\n"); fprintf(stderr, "Change >> to multiplies by powers of 2\n"); exit(1); } }