/*===========================================================================* * param.c * * Procedures to read in parameter file * * EXPORTED PROCEDURES: * ReadParamFile * GetNthInputFileName * *===========================================================================*/ /* COPYRIGHT INFORMATION IS AT THE END OF THIS FILE */ #define _XOPEN_SOURCE 1 /* This makes sure popen() is in stdio.h. In GNU libc 2.1.3, _POSIX_C_SOURCE = 2 is sufficient, but on AIX 4.3, the higher level _XOPEN_SOURCE is required. 2000.09.09 */ /*==============* * HEADER FILES * *==============*/ #include "nstring.h" #include "all.h" #include "mtypes.h" #include "mpeg.h" #include "motion_search.h" #include "prototypes.h" #include "parallel.h" #include "param.h" #include "readframe.h" #include "fsize.h" #include "frames.h" #include "jpeg.h" #include #include #include #include "rate.h" #include "opts.h" /*===========* * CONSTANTS * *===========*/ #define INPUT_ENTRY_BLOCK_SIZE 128 #define FIRST_OPTION 0 #define OPTION_GOP 0 #define OPTION_PATTERN 1 #define OPTION_PIXEL 2 #define OPTION_PQSCALE 3 #define OPTION_OUTPUT 4 #define OPTION_RANGE 5 #define OPTION_PSEARCH_ALG 6 #define OPTION_IQSCALE 7 #define OPTION_INPUT_DIR 8 #define OPTION_INPUT_CONVERT 9 #define OPTION_INPUT 10 #define OPTION_BQSCALE 11 #define OPTION_BASE_FORMAT 12 #define OPTION_SPF 13 #define OPTION_BSEARCH_ALG 14 #define OPTION_REF_FRAME 15 #define LAST_OPTION 15 /* put any non-required options after LAST_OPTION */ #define OPTION_RESIZE 16 #define OPTION_IO_CONVERT 17 #define OPTION_SLAVE_CONVERT 18 #define OPTION_IQTABLE 19 #define OPTION_NIQTABLE 20 #define OPTION_FRAME_RATE 21 #define OPTION_ASPECT_RATIO 22 #define OPTION_YUV_SIZE 23 #define OPTION_SPECIFICS 24 #define OPTION_DEFS_SPECIFICS 25 #define OPTION_BUFFER_SIZE 26 #define OPTION_BIT_RATE 27 #define OPTION_USER_DATA 28 #define OPTION_YUV_FORMAT 29 #define OPTION_GAMMA 30 #define OPTION_PARALLEL 31 #define NUM_OPTIONS 31 /*=======================* * STRUCTURE DEFINITIONS * *=======================*/ typedef struct InputFileEntryStruct { char left[256]; char right[256]; boolean glob; /* if FALSE, left is complete name */ int startID; int endID; int skip; int numPadding; /* -1 if there is none */ int numFiles; boolean repeat; } InputFileEntry; /*==================* * STATIC VARIABLES * *==================*/ static InputFileEntry **inputFileEntries; static int numInputFileEntries = 0; static int maxInputFileEntries; /*==================* * GLOBAL VARIABLES * *==================*/ extern char currentPath[MAXPATHLEN]; extern char currentGOPPath[MAXPATHLEN]; extern char currentFramePath[MAXPATHLEN]; char outputFileName[256]; int outputWidth, outputHeight; int numInputFiles = 0; char inputConversion[1024]; char ioConversion[1024]; char slaveConversion[1024]; char yuvConversion[256]; char specificsFile[256],specificsDefines[1024]=""; boolean GammaCorrection=FALSE; float GammaValue; char userDataFileName[256]={0}; boolean specificsOn = FALSE; static const char * const optionText[LAST_OPTION+1] = { "GOP_SIZE", "PATTERN", "PIXEL", "PQSCALE", "OUTPUT", "RANGE", "PSEARCH_ALG", "IQSCALE", "INPUT_DIR", "INPUT_CONVERT", "INPUT", "BQSCALE", "BASE_FILE_FORMAT", "SLICES_PER_FRAME", "BSEARCH_ALG", "REFERENCE_FRAME"}; static boolean optionSeen[NUM_OPTIONS+1]; /* optionSeen[x] means we have seen option x in the parameter file we've been reading OR we've determined we don't need to see it. */ int numMachines; char machineName[MAX_MACHINES][256]; char userName[MAX_MACHINES][256]; char executable[MAX_MACHINES][1024]; char remoteParamFile[MAX_MACHINES][1024]; boolean remote[MAX_MACHINES]; boolean stdinUsed = FALSE; int mult_seq_headers = 0; /* 0 for none, N for header/N GOPs */ /* Prototype for recursively called subroutine: */ static void ReadInputFileNames(FILE * const fpointer, const char * const endInput); /*===========================================================================* * * SkipSpacesTabs * * skip all spaces and tabs * * RETURNS: point to next character not a space or tab * * SIDE EFFECTS: none * *===========================================================================*/ static const char * SkipSpacesTabs(const char * const start) { const char * p; for (p = start; *p == ' ' || *p == '\t'; ++p); return p; } /*===========================================================================* * * GetAspectRatio * * take a character string with the pixel aspect ratio * and returns the correct aspect ratio code for use in the Sequence header * * RETURNS: aspect ratio code as per MPEG-I spec * * SIDE EFFECTS: none * *===========================================================================*/ static int GetAspectRatio(const char * const p) { float ratio; int ttRatio; int retval; sscanf(p, "%f", &ratio); ttRatio = (int)(0.5+ratio*10000.0); if ( ttRatio == 10000 ) retval = 1; else if ( ttRatio == 6735 ) retval = 2; else if ( ttRatio == 7031 ) retval = 3; else if ( ttRatio == 7615 ) retval = 4; else if ( ttRatio == 8055 ) retval = 5; else if ( ttRatio == 8437 ) retval = 6; else if ( ttRatio == 8935 ) retval = 7; else if ( ttRatio == 9157 ) retval = 8; else if ( ttRatio == 9815 ) retval = 9; else if ( ttRatio == 10255 ) retval = 10; else if ( ttRatio == 10695 ) retval = 11; else if ( ttRatio == 10950 ) retval = 12; else if ( ttRatio == 11575 ) retval = 13; else if ( ttRatio == 12015 ) retval = 14; else { fprintf(stderr,"INVALID ASPECT RATIO: %s frames/sec\n", p); exit(1); } return retval; } static void expandBackTickLine(const char * const input) { FILE *fp; char cmd[300]; const char * start; const char * end; char cdcmd[110]; start = &input[1]; end = &input[strlen(input)-1]; while (*end != '`') { end--; } end--; if (optionSeen[OPTION_INPUT_DIR] == TRUE) { sprintf(cdcmd,"cd %s;",currentPath); } else { strcpy(cdcmd,""); } { char tmp[300]; strncpy(tmp,start,end-start+1); sprintf(cmd,"(%s %s)", cdcmd, tmp); } fp = popen(cmd,"r"); if (fp == NULL) { fprintf(stderr, "Command failed! " "Could not open piped command:\n%s\n",cmd); } else ReadInputFileNames(fp,"HOPE-THIS_ISNT_A_FILENAME.xyz5555"); } /*===========================================================================* * * ReadMachineNames * * read a list of machine names for parallel execution * * RETURNS: nothing * * SIDE EFFECTS: machine info updated * *===========================================================================*/ static void ReadMachineNames(FILE * const fpointer) { char input[256]; const char *charPtr; while ( (fgets(input, 256, fpointer) != NULL) && (strncmp(input, "END_PARALLEL", 12) != 0) ) { if ( input[0] == '#' || input[0] == '\n') { continue; } if ( strncmp(input, "REMOTE", 6) == 0 ) { charPtr = SkipSpacesTabs(&input[6]); remote[numMachines] = TRUE; sscanf(charPtr, "%s %s %s %s", machineName[numMachines], userName[numMachines], executable[numMachines], remoteParamFile[numMachines]); } else { remote[numMachines] = FALSE; sscanf(input, "%s %s %s", machineName[numMachines], userName[numMachines], executable[numMachines]); } numMachines++; } } /*===========================================================================* * * GetFrameRate * * take a character string with the input frame rate * and return the correct frame rate code for use in the Sequence header * * RETURNS: frame rate code as per MPEG-I spec * * SIDE EFFECTS: none * *===========================================================================*/ static int GetFrameRate(const char * const p) { float rate; int thouRate; int retval; sscanf(p, "%f", &rate); thouRate = (int)(0.5+1000.0*rate); if ( thouRate == 23976 ) retval = 1; else if ( thouRate == 24000 ) retval = 2; else if ( thouRate == 25000 ) retval = 3; else if ( thouRate == 29970 ) retval = 4; else if ( thouRate == 30000 ) retval = 5; else if ( thouRate == 50000 ) retval = 6; else if ( thouRate == 59940 ) retval = 7; else if ( thouRate == 60000 ) retval = 8; else { fprintf(stderr,"INVALID FRAME RATE: %s frames/sec\n", p); exit(1); } return retval; } static void processGlob(const char * const input, InputFileEntry * const inputFileEntryP) { const char *globPtr; char * charPtr; char left[256], right[256]; char leftNumText[256], rightNumText[256]; char skipNumText[256]; int leftNum, rightNum; int skipNum; boolean padding; int numPadding = 0; inputFileEntryP->glob = TRUE; inputFileEntryP->repeat = FALSE; /* star expand */ globPtr = input; charPtr = left; /* copy left of '*' */ while ( (*globPtr != '\0') && (*globPtr != '*') ) { *charPtr = *globPtr; charPtr++; globPtr++; } *charPtr = '\0'; if (*globPtr == '\0') { fprintf(stderr, "WARNING: expanding non-star regular expression\n"); inputFileEntryP->repeat = TRUE; globPtr = input; charPtr = left; /* recopy left of whitespace */ while ( (*globPtr != '\0') && (*globPtr != '*') && (*globPtr != ' ') && (*globPtr != '\t')) { *charPtr = *globPtr; charPtr++; globPtr++; } *charPtr = '\0'; *right = '\0'; } else { globPtr++; charPtr = right; /* copy right of '*' */ while ( (*globPtr != '\0') && (*globPtr != ' ') && (*globPtr != '\t') ) { *charPtr = *globPtr; charPtr++; globPtr++; } *charPtr = '\0'; } globPtr = SkipSpacesTabs(globPtr); if ( *globPtr != '[' ) { fprintf(stderr, "ERROR: " "Invalid input file expansion expression (no '[')\n"); exit(1); } globPtr++; charPtr = leftNumText; /* copy left number */ while ( ISDIGIT(*globPtr) ) { *charPtr = *globPtr; charPtr++; globPtr++; } *charPtr = '\0'; if ( *globPtr != '-' ) { fprintf(stderr, "ERROR: " "Invalid input file expansion expression (no '-')\n"); exit(1); } globPtr++; charPtr = rightNumText; /* copy right number */ while ( ISDIGIT(*globPtr) ) { *charPtr = *globPtr; charPtr++; globPtr++; } *charPtr = '\0'; if ( atoi(rightNumText) < atoi(leftNumText) ) { fprintf(stderr, "ERROR: " "Beginning of input range is higher than end.\n"); exit(1); } if ( *globPtr != ']' ) { if ( *globPtr != '+' ) { fprintf(stderr, "ERROR: " "Invalid input file expansion expression " "(no ']')\n"); exit(1); } globPtr++; charPtr = skipNumText; /* copy skip number */ while ( ISDIGIT(*globPtr) ) { *charPtr = *globPtr; charPtr++; globPtr++; } *charPtr = '\0'; if ( *globPtr != ']' ) { fprintf(stderr, "ERROR: Invalid input file expansion expression " "(no ']')\n"); exit(1); } skipNum = atoi(skipNumText); } else { skipNum = 1; } leftNum = atoi(leftNumText); rightNum = atoi(rightNumText); if ( (leftNumText[0] == '0') && (leftNumText[1] != '\0') ) { padding = TRUE; numPadding = strlen(leftNumText); } else { padding = FALSE; } inputFileEntryP->startID = leftNum; inputFileEntryP->endID = rightNum; inputFileEntryP->skip = skipNum; inputFileEntryP->numFiles = (rightNum-leftNum+1)/skipNum; strcpy(inputFileEntryP->left, left); strcpy(inputFileEntryP->right, right); if ( padding ) { inputFileEntryP->numPadding = numPadding; } else { inputFileEntryP->numPadding = -1; } } static void processJmovie(const char * const input, InputFileEntry * const inputFileEntryP) { FILE *jmovie; char full_path[MAXPATHLEN + 256]; inputFileEntryP->glob = TRUE; full_path[0] = '\0'; strcpy(full_path, currentPath); strcat(full_path, "/"); strcat(full_path, input); jmovie = fopen(input, "rb"); if (jmovie == NULL) { perror (input); exit (1); } fseek (jmovie, (8*sizeof(char)), 0); fseek (jmovie, (2*sizeof(int)), 1); if (fread(&(inputFileEntryP->numFiles), sizeof(int), 1, jmovie) != 1) { perror ("Error in reading number of frames in JMOVIE"); exit(1); } fclose (jmovie); strcpy(inputFileEntryP->right,".jpg"); inputFileEntryP->numPadding = -1; inputFileEntryP->startID = 1; inputFileEntryP->endID = (inputFileEntryP->numFiles-1); inputFileEntryP->skip = 1; if (! realQuiet) { fprintf (stdout, "Encoding all %d frames from JMOVIE.\n", inputFileEntryP->endID); } } static void processSimpleFileName(const char * const input, InputFileEntry * const inputFileEntryP) { inputFileEntryP->glob = FALSE; inputFileEntryP->numFiles = 1; /* fixes a bug from version 1.3: */ inputFileEntryP->numPadding = 0; /* fixes a bug from version 1.4 */ strcpy(inputFileEntryP->right,"\0"); inputFileEntryP->startID = 0; inputFileEntryP->endID = 0; inputFileEntryP->skip = 0; } /*===========================================================================* * * ReadInputFileNames * * read a list of input file names * * RETURNS: nothing * * SIDE EFFECTS: info stored for retrieval using GetNthInputFileName * *===========================================================================*/ static void ReadInputFileNames(FILE * const fpointer, const char * const endInput) { char input[256]; inputFileEntries = (InputFileEntry **) malloc(INPUT_ENTRY_BLOCK_SIZE* sizeof(InputFileEntry *)); maxInputFileEntries = INPUT_ENTRY_BLOCK_SIZE; /* read param file up through endInput statement. Each line until endInput is a file specification. */ while ( (fgets(input, sizeof(input), fpointer) != NULL) && (strncmp(input, endInput, strlen(endInput)) != 0) ) { if ((input[0] == '#') || (input[0] == '\n')) { /* It's a comment or blank line. Ignore it */ } else if (stdinUsed) { /* Input is from Standard Input; ignore this input file specification. */ } else if (input[0] == '`' ) { expandBackTickLine(input); } else { /* get rid of trailing whitespace including newline */ while (ISSPACE(input[strlen(input)-1])) { input[strlen(input)-1] = '\0'; } if (numInputFileEntries == maxInputFileEntries) { /* Get more space */ maxInputFileEntries += INPUT_ENTRY_BLOCK_SIZE; inputFileEntries = (InputFileEntry **) realloc(inputFileEntries, maxInputFileEntries* sizeof(InputFileEntry *)); } inputFileEntries[numInputFileEntries] = (InputFileEntry *) malloc(sizeof(InputFileEntry)); if ( input[strlen(input)-1] == ']' ) processGlob(input, inputFileEntries[numInputFileEntries]); else { strcpy(inputFileEntries[numInputFileEntries]->left, input); if (baseFormat == JMOVIE_FILE_TYPE) processJmovie(input, inputFileEntries[numInputFileEntries]); else processSimpleFileName( input, inputFileEntries[numInputFileEntries]); } numInputFiles += inputFileEntries[numInputFileEntries]->numFiles; ++numInputFileEntries; } } } static void initOptionSeen(int const function) { unsigned int index; switch(function) { case ENCODE_FRAMES: for (index = FIRST_OPTION; index <= LAST_OPTION; ++index) { optionSeen[index] = FALSE; } optionSeen[OPTION_IO_CONVERT] = FALSE; optionSeen[OPTION_SLAVE_CONVERT] = FALSE; break; case COMBINE_GOPS: for (index = FIRST_OPTION; index <= LAST_OPTION; ++index) { optionSeen[index] = TRUE; } optionSeen[OPTION_YUV_SIZE] = FALSE; optionSeen[OPTION_OUTPUT] = FALSE; break; case COMBINE_FRAMES: for (index = FIRST_OPTION; index <= LAST_OPTION; ++index) { optionSeen[index] = TRUE; } optionSeen[OPTION_GOP] = FALSE; optionSeen[OPTION_YUV_SIZE] = FALSE; optionSeen[OPTION_OUTPUT] = FALSE; break; } for (index=LAST_OPTION+1; index <= NUM_OPTIONS; ++index) { optionSeen[index] = FALSE; } } static void verifyNoMissingOption(boolean const stdinUsed) { /*---------------------------------------------------------------------------- Verify that the parameter file contains every option it is supposed to. Abort program if not. -----------------------------------------------------------------------------*/ unsigned int index; for (index = FIRST_OPTION; index <= LAST_OPTION; ++index) { if (!optionSeen[index]) { /* INPUT unnecessary when stdin is used */ if ((index == OPTION_INPUT) && stdinUsed) { continue; } fprintf(stderr, "ERROR: Missing option '%s'\n", optionText[index]); exit(1); } } } /*=====================* * EXPORTED PROCEDURES * *=====================*/ /*===========================================================================* * * ReadParamFile * * read the parameter file * function is ENCODE_FRAMES, COMBINE_GOPS, or COMBINE_FRAMES, and * will slightly modify the procedure's behavior as to what it * is looking for in the parameter file * * RETURNS: TRUE if the parameter file was read correctly; FALSE if not * * SIDE EFFECTS: sets parameters accordingly, as well as machine info for * parallel execution and input file names * *===========================================================================*/ boolean ReadParamFile(fileName, function) char *fileName; int function; { FILE *fpointer; char input[256]; const char *charPtr; boolean yuvUsed = FALSE; register int row, col; if ( (fpointer = fopen(fileName, "r")) == NULL ) { fprintf(stderr, "Error: Cannot open parameter file: %s\n", fileName); return FALSE; } /* should set defaults */ numInputFiles = 0; numMachines = 0; sprintf(currentPath, "."); sprintf(currentGOPPath, "."); sprintf(currentFramePath, "."); #ifndef HPUX SetRemoteShell("rsh"); #else SetRemoteShell("remsh"); #endif initOptionSeen(function); while ( fgets(input, 256, fpointer) != NULL ) { /* skip comments */ if ( input[0] == '#' ) { continue; } { int len = strlen(input); if (input[len-1] == '\n') { len--; input[len] = '\0'; /* get rid of newline */ /* Junk whitespace */ while ((len >= 0) && ((input[len-1] == ' ') || (input[len-1] == '\t'))) { input[--len] = '\0'; } } } if (strlen(SkipSpacesTabs(input)) == 0) continue; switch(input[0]) { case 'A': if ( strncmp(input, "ASPECT_RATIO", 12) == 0 ) { charPtr = SkipSpacesTabs(&input[12]); aspectRatio = GetAspectRatio(charPtr); optionSeen[OPTION_ASPECT_RATIO] = TRUE; } break; case 'B': if ( strncmp(input, "BQSCALE", 7) == 0 ) { charPtr = SkipSpacesTabs(&input[7]); SetBQScale(atoi(charPtr)); optionSeen[OPTION_BQSCALE] = TRUE; } else if ( strncmp(input, "BASE_FILE_FORMAT", 16) == 0 ) { charPtr = SkipSpacesTabs(&input[16]); SetFileFormat(charPtr); if ( (strncmp(charPtr,"YUV",3) == 0) || (strcmp(charPtr,"Y") == 0) ) { yuvUsed = TRUE; } optionSeen[OPTION_BASE_FORMAT] = TRUE; } else if ( strncmp(input, "BSEARCH_ALG", 11) == 0 ) { charPtr = SkipSpacesTabs(&input[11]); SetBSearchAlg(charPtr); optionSeen[OPTION_BSEARCH_ALG] = TRUE; } else if ( strncmp(input, "BIT_RATE", 8) == 0 ) { charPtr = SkipSpacesTabs(&input[8]); setBitRate(charPtr); optionSeen[OPTION_BIT_RATE] = TRUE; } else if ( strncmp(input, "BUFFER_SIZE", 11) == 0 ) { charPtr = SkipSpacesTabs(&input[11]); setBufferSize(charPtr); optionSeen[OPTION_BUFFER_SIZE] = TRUE; } break; case 'C': if ( strncmp(input, "CDL_FILE", 8) == 0 ) { charPtr = SkipSpacesTabs(&input[8]); strcpy(specificsFile, charPtr); specificsOn=TRUE; optionSeen[OPTION_SPECIFICS] = TRUE; } else if ( strncmp(input, "CDL_DEFINES", 11) == 0 ) { charPtr = SkipSpacesTabs(&input[11]); strcpy(specificsDefines, charPtr); optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; } break; case 'F': if ( strncmp(input, "FRAME_INPUT_DIR", 15) == 0 ) { charPtr = SkipSpacesTabs(&input[15]); if ( strncmp(charPtr, "stdin", 5) == 0 || strncmp(charPtr, "STDIN", 5) == 0 ) { stdinUsed = TRUE; numInputFiles = MAXINT; numInputFileEntries = 1; } strcpy(currentFramePath, charPtr); } else if ( strncmp(input, "FRAME_INPUT", 11) == 0 ) { if ( function == COMBINE_FRAMES ) { ReadInputFileNames(fpointer, "FRAME_END_INPUT"); } } else if ( strncmp(input, "FORCE_I_ALIGN", 13) == 0 ) { forceIalign = TRUE; } else if ( strncmp(input, "FORCE_ENCODE_LAST_FRAME", 23) == 0 ) { forceEncodeLast = TRUE; } else if ( strncmp(input, "FRAME_RATE", 10) == 0 ) { charPtr = SkipSpacesTabs(&input[10]); frameRate = GetFrameRate(charPtr); frameRateRounded = (int) VidRateNum[frameRate]; if ( (frameRate % 3) == 1) { frameRateInteger = FALSE; } optionSeen[OPTION_FRAME_RATE] = TRUE; } break; case 'G': if ( strncmp(input, "GOP_SIZE", 8) == 0 ) { charPtr = SkipSpacesTabs(&input[8]); SetGOPSize(atoi(charPtr)); optionSeen[OPTION_GOP] = TRUE; } else if ( strncmp(input, "GOP_INPUT_DIR", 13) == 0 ) { charPtr = SkipSpacesTabs(&input[13]); if ( strncmp(charPtr, "stdin", 5) == 0 || strncmp(charPtr, "STDIN", 5) == 0 ) { stdinUsed = TRUE; numInputFiles = MAXINT; numInputFileEntries = 1; } strcpy(currentGOPPath, charPtr); } else if ( strncmp(input, "GOP_INPUT", 9) == 0 ) { if ( function == COMBINE_GOPS ) { ReadInputFileNames(fpointer, "GOP_END_INPUT"); } } else if ( strncmp(input, "GAMMA", 5) == 0) { charPtr = SkipSpacesTabs(&input[5]); GammaCorrection = TRUE; sscanf(charPtr,"%f",&GammaValue); optionSeen[OPTION_GAMMA] = TRUE; } break; case 'I': if ( strncmp(input, "IQSCALE", 7) == 0 ) { charPtr = SkipSpacesTabs(&input[7]); SetIQScale(atoi(charPtr)); optionSeen[OPTION_IQSCALE] = TRUE; } else if ( strncmp(input, "INPUT_DIR", 9) == 0 ) { charPtr = SkipSpacesTabs(&input[9]); if ( strncmp(charPtr, "stdin", 5) == 0 || strncmp(charPtr, "STDIN", 5) == 0 ) { stdinUsed = TRUE; numInputFiles = MAXINT; numInputFileEntries = 1; } strcpy(currentPath, charPtr); optionSeen[OPTION_INPUT_DIR] = TRUE; } else if ( strncmp(input, "INPUT_CONVERT", 13) == 0 ) { charPtr = SkipSpacesTabs(&input[13]); strcpy(inputConversion, charPtr); optionSeen[OPTION_INPUT_CONVERT] = TRUE; } else if ( strcmp(input, "INPUT") == 0 ) { /* yes, strcmp */ if ( function == ENCODE_FRAMES ) { ReadInputFileNames(fpointer, "END_INPUT"); optionSeen[OPTION_INPUT] = TRUE; } } else if ( strncmp(input, "IO_SERVER_CONVERT", 17) == 0 ) { charPtr = SkipSpacesTabs(&input[17]); strcpy(ioConversion, charPtr); optionSeen[OPTION_IO_CONVERT] = TRUE; } else if ( strncmp(input, "IQTABLE", 7) == 0 ) { for ( row = 0; row < 8; row ++ ) { fgets(input, 256, fpointer); charPtr = input; if (8!=sscanf(charPtr,"%d %d %d %d %d %d %d %d", &qtable[row*8+0], &qtable[row*8+1], &qtable[row*8+2], &qtable[row*8+3], &qtable[row*8+4], &qtable[row*8+5], &qtable[row*8+6], &qtable[row*8+7])) { fprintf(stderr, "Line %d of IQTABLE doesn't have 8 elements!\n", row); exit(1); } for ( col = 0; col < 8; col ++ ) { if ((qtable[row*8+col]<1) || (qtable[row*8+col]>255)) { fprintf(stderr, "Warning: IQTable Element %1d,%1d (%d) " "corrected to 1-255.\n", row+1, col+1, qtable[row*8+col]); qtable[row*8+col] = (qtable[row*8+col]<1)?1:255; }} } if ( qtable[0] != 8 ) { fprintf(stderr, "Warning: IQTable Element 1,1 reset to 8, " "since it must be 8.\n"); qtable[0] = 8; } customQtable = qtable; optionSeen[OPTION_IQTABLE] = TRUE; } else if ( strncmp(input, "INPUT", 5) == 0 ) { /* handle spaces after input */ log(10.0); charPtr = SkipSpacesTabs(&input[5]); if ( function == ENCODE_FRAMES && *charPtr==0) { ReadInputFileNames(fpointer, "END_INPUT"); optionSeen[OPTION_INPUT] = TRUE; } } break; case 'N': if ( strncmp(input, "NIQTABLE", 8) == 0 ) { for ( row = 0; row < 8; row ++ ) { fgets(input, 256, fpointer); charPtr = input; if (8!=sscanf(charPtr,"%d %d %d %d %d %d %d %d", &niqtable[row*8+0], &niqtable[row*8+1], &niqtable[row*8+2], &niqtable[row*8+3], &niqtable[row*8+4], &niqtable[row*8+5], &niqtable[row*8+6], &niqtable[row*8+7])) { fprintf(stderr, "Line %d of NIQTABLE doesn't have 8 elements!\n", row); exit(1); } for ( col = 0; col < 8; col++ ) { if ((niqtable[row*8+col]<1) || (niqtable[row*8+col]>255)) { fprintf(stderr, "Warning: NIQTable Element %1d,%1d (%d) " "corrected to 1-255.\n", row+1, col+1, niqtable[row*8+col]); niqtable[row*8+col]=(niqtable[row*8+col]<1)?1:255; }} } customNIQtable = niqtable; optionSeen[OPTION_NIQTABLE] = TRUE; } break; case 'O': if ( strncmp(input, "OUTPUT", 6) == 0 ) { charPtr = SkipSpacesTabs(&input[6]); if ( whichGOP == -1 ) { strcpy(outputFileName, charPtr); } else { sprintf(outputFileName, "%s.gop.%d", charPtr, whichGOP); } optionSeen[OPTION_OUTPUT] = TRUE; } break; case 'P': if ( strncmp(input, "PATTERN", 7) == 0 ) { charPtr = SkipSpacesTabs(&input[7]); SetFramePattern(charPtr); optionSeen[OPTION_PATTERN] = TRUE; } else if ( strncmp(input, "PIXEL", 5) == 0 ) { charPtr = SkipSpacesTabs(&input[5]); SetPixelSearch(charPtr); optionSeen[OPTION_PIXEL] = TRUE; } else if ( strncmp(input, "PQSCALE", 7) == 0 ) { charPtr = SkipSpacesTabs(&input[7]); SetPQScale(atoi(charPtr)); optionSeen[OPTION_PQSCALE] = TRUE; } else if ( strncmp(input, "PSEARCH_ALG", 11) == 0 ) { charPtr = SkipSpacesTabs(&input[11]); SetPSearchAlg(charPtr); optionSeen[OPTION_PSEARCH_ALG] = TRUE; } else if ( strncmp(input, "PARALLEL_TEST_FRAMES", 20) == 0 ) { SetParallelPerfect(FALSE); charPtr = SkipSpacesTabs(&input[20]); parallelTestFrames = atoi(charPtr); } else if ( strncmp(input, "PARALLEL_TIME_CHUNKS", 20) == 0 ) { SetParallelPerfect(FALSE); charPtr = SkipSpacesTabs(&input[20]); parallelTimeChunks = atoi(charPtr); } else if ( strncmp(input, "PARALLEL_CHUNK_TAPER", 20) == 0 ) { SetParallelPerfect(FALSE); parallelTimeChunks = -1; } else if ( strncmp(input, "PARALLEL_PERFECT", 16) == 0 ) { SetParallelPerfect(TRUE); } else if ( strncmp(input, "PARALLEL", 8) == 0 ) { ReadMachineNames(fpointer); optionSeen[OPTION_PARALLEL] = TRUE; } break; case 'R': if ( strncmp(input, "RANGE", 5) == 0 ) { int num_ranges=0,a,b; charPtr = SkipSpacesTabs(&input[5]); optionSeen[OPTION_RANGE] = TRUE; num_ranges=sscanf(charPtr,"%d %d",&a,&b); if (num_ranges==2) { SetSearchRange(a,b); } else if (sscanf(charPtr,"%d [%d]",&a,&b)==2) { SetSearchRange(a,b); } else SetSearchRange(a,a); } else if ( strncmp(input, "REFERENCE_FRAME", 15) == 0 ) { charPtr = SkipSpacesTabs(&input[15]); SetReferenceFrameType(charPtr); optionSeen[OPTION_REF_FRAME] = TRUE; } else if ( strncmp(input, "RSH", 3) == 0 ) { charPtr = SkipSpacesTabs(&input[3]); SetRemoteShell(charPtr); } else if ( strncmp(input, "RESIZE", 6) == 0 ) { charPtr = SkipSpacesTabs(&input[6]); sscanf(charPtr, "%dx%d", &outputWidth, &outputHeight); outputWidth &= ~(DCTSIZE * 2 - 1); outputHeight &= ~(DCTSIZE * 2 - 1); optionSeen[OPTION_RESIZE] = TRUE; } break; case 'S': if ( strncmp(input, "SLICES_PER_FRAME", 16) == 0 ) { charPtr = SkipSpacesTabs(&input[16]); SetSlicesPerFrame(atoi(charPtr)); optionSeen[OPTION_SPF] = TRUE; } else if ( strncmp(input, "SLAVE_CONVERT", 13) == 0 ) { charPtr = SkipSpacesTabs(&input[13]); strcpy(slaveConversion, charPtr); optionSeen[OPTION_SLAVE_CONVERT] = TRUE; } else if ( strncmp(input, "SPECIFICS_FILE", 14) == 0 ) { charPtr = SkipSpacesTabs(&input[14]); strcpy(specificsFile, charPtr); specificsOn=TRUE; optionSeen[OPTION_SPECIFICS] = TRUE; } else if ( strncmp(input, "SPECIFICS_DEFINES", 16) == 0 ) { charPtr = SkipSpacesTabs(&input[17]); strcpy(specificsDefines, charPtr); optionSeen[OPTION_DEFS_SPECIFICS] = TRUE; } else if (strncmp(input, "SEQUENCE_SIZE", 13) == 0) { charPtr = SkipSpacesTabs(&input[13]); mult_seq_headers = atoi(charPtr); } else if (strncmp(input, "SIZE", 4) == 0 ) { charPtr = SkipSpacesTabs(&input[4]); sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); realWidth = yuvWidth; realHeight = yuvHeight; Fsize_Validate(&yuvWidth, &yuvHeight); optionSeen[OPTION_YUV_SIZE] = TRUE; } break; case 'T': if ( strncmp(input, "TUNE", 4) == 0) { tuneingOn = TRUE; charPtr = SkipSpacesTabs(&input[4]); ParseTuneParam(charPtr); } break; case 'U': if ( strncmp(input, "USER_DATA", 9) == 0 ) { charPtr = SkipSpacesTabs(&input[9]); strcpy(userDataFileName, charPtr); optionSeen[OPTION_USER_DATA] = TRUE; } break; case 'Y': if (strncmp(input, "YUV_SIZE", 8) == 0 ) { charPtr = SkipSpacesTabs(&input[8]); sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); realWidth = yuvWidth; realHeight = yuvHeight; Fsize_Validate(&yuvWidth, &yuvHeight); optionSeen[OPTION_YUV_SIZE] = TRUE; } else if (strncmp(input, "Y_SIZE", 6) == 0 ) { charPtr = SkipSpacesTabs(&input[6]); sscanf(charPtr, "%dx%d", &yuvWidth, &yuvHeight); realWidth = yuvWidth; realHeight = yuvHeight; Fsize_Validate(&yuvWidth, &yuvHeight); optionSeen[OPTION_YUV_SIZE] = TRUE; } else if ( strncmp(input, "YUV_FORMAT", 10) == 0 ) { charPtr = SkipSpacesTabs(&input[10]); strcpy(yuvConversion, charPtr); optionSeen[OPTION_YUV_FORMAT] = TRUE; } break; } } fclose(fpointer); verifyNoMissingOption(stdinUsed); /* error checking */ if ( yuvUsed ) { if (! optionSeen[OPTION_YUV_SIZE]) { fprintf(stderr, "ERROR: YUV format used but YUV_SIZE not given\n"); exit(1); } if (! optionSeen[OPTION_YUV_FORMAT]) { strcpy (yuvConversion, "EYUV"); fprintf(stderr, "WARNING: YUV format not specified; defaulting to Berkeley YUV (EYUV)\n\n"); } } if ( stdinUsed && optionSeen[OPTION_PARALLEL] ) { fprintf(stderr, "ERROR: stdin reading for parallel execution not enabled yet.\n"); exit(1); } if ( optionSeen[OPTION_PARALLEL] && !optionSeen[OPTION_YUV_SIZE]) { fprintf(stderr, "ERROR: Specify SIZE WxH for parallel encoding\n"); exit(1); } if ( optionSeen[OPTION_IO_CONVERT] != optionSeen[OPTION_SLAVE_CONVERT] ) { fprintf(stderr, "ERROR: must have either both IO_SERVER_CONVERT and SLAVE_CONVERT\n"); fprintf(stderr, " or neither\n"); exit(1); } if ( optionSeen[OPTION_DEFS_SPECIFICS] && !optionSeen[OPTION_SPECIFICS]) { fprintf(stderr, "ERROR: does not make sense to define Specifics file options, but no specifics file!\n"); exit(1); } SetIOConvert(optionSeen[OPTION_IO_CONVERT]); SetResize(optionSeen[OPTION_RESIZE]); if ( function == ENCODE_FRAMES ) { SetFCode(); if ( psearchAlg == PSEARCH_TWOLEVEL ) SetPixelSearch("HALF"); } return TRUE; } /*===========================================================================* * * GetNthInputFileName * * finds the nth input file name * * RETURNS: name is placed in already allocated fileName string * * SIDE EFFECTS: none * *===========================================================================*/ void GetNthInputFileName(fileName, n) char *fileName; int n; { static int lastN = 0, lastMapN = 0, lastSoFar = 0; int mapN; register int index; int soFar; int loop; int numPadding; char numBuffer[33]; if ( stdinUsed ) { return; } /* assumes n is within bounds 0...numInputFiles-1 */ if ( n >= lastN ) { soFar = lastSoFar; index = lastMapN; } else { soFar = 0; index = 0; } while ( soFar + inputFileEntries[index]->numFiles <= n ) { soFar += inputFileEntries[index]->numFiles; index++; } mapN = index; index = inputFileEntries[mapN]->startID + inputFileEntries[mapN]->skip*(n-soFar); numPadding = inputFileEntries[mapN]->numPadding; if ( numPadding != -1 ) { sprintf(numBuffer, "%32d", index); for ( loop = 32-numPadding; loop < 32; loop++ ) { if ( numBuffer[loop] != ' ' ) { break; } else { numBuffer[loop] = '0'; } } if (inputFileEntries[mapN]->repeat != TRUE) { sprintf(fileName, "%s%s%s", inputFileEntries[mapN]->left, &numBuffer[32-numPadding], inputFileEntries[mapN]->right); } else { sprintf(fileName, "%s", inputFileEntries[mapN]->left); } } else { if (inputFileEntries[mapN]->repeat != TRUE) { sprintf(fileName, "%s%d%s", inputFileEntries[mapN]->left, index, inputFileEntries[mapN]->right); } else { sprintf(fileName, "%s", inputFileEntries[mapN]->left); } } lastN = n; lastMapN = mapN; lastSoFar = soFar; } /*=====================* * INTERNAL PROCEDURES * *=====================*/ /**************************************************************** * Jim Boucher's code * * ****************************************************************/ void JM2JPEG() { char full_path[MAXPATHLEN + 256]; char inter_file[MAXPATHLEN +256]; int ci; for(ci = 0; ci < numInputFileEntries; ci++) { inter_file[0] = '\0'; full_path[0] = '\0'; strcpy(full_path, currentPath); if (! stdinUsed) { strcat(full_path, "/"); strcat(full_path, inputFileEntries[ci]->left); strcpy(inter_file,full_path); if (! realQuiet) { fprintf(stdout, "Extracting JPEG's in the JMOVIE from %s\n",full_path); } JMovie2JPEG(full_path, inter_file, inputFileEntries[ci]->startID, inputFileEntries[ci]->endID); } else { fprintf (stderr, "ERROR: JMovie format not supported with stdin yet.\n"); exit(1); } } } /* * 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/param.c,v 1.38 1995/08/14 22:29:13 smoot Exp smoot $ * $Log: param.c,v $ * Revision 1.38 1995/08/14 22:29:13 smoot * cleaned up subcommand for file name generation * fixed bug where foo* didnt work as input string * * Revision 1.37 1995/08/07 21:47:01 smoot * allows spaces after lines in param files * added SIZE == YUV_SIZE for parallel encoding (otherwise you'd have * to parse PPM files in the master server... Ick. * So we have it specified) * * Revision 1.36 1995/06/26 21:52:52 smoot * allow uppercase stdin * * Revision 1.35 1995/06/21 18:35:01 smoot * moved TUNE stuff to opts.c * Added ability to do: * INPUT * file.ppm [1-10] * to do 10 copies * added CDL = SPECIFICS * * Revision 1.34 1995/05/02 01:48:25 eyhung * deleted some smootisms. fixed framerate settings, added check for * invalid input range * * Revision 1.33 1995/05/02 01:20:10 smoot * *** empty log message *** * * Revision 1.31 1995/03/09 06:22:36 eyhung * more robust input checking (whitespace at end of input file spec) * * Revision 1.30 1995/02/02 01:06:18 eyhung * Added error checking for JMOVIE and stdin ; deleted smoot's "understand" * param file ideas. * * Revision 1.29 1995/02/01 21:09:59 eyhung * Finished infinite coding-on-the-fly * * Revision 1.28 1995/01/31 22:34:28 eyhung * Added stdin as a parameter to INPUT_DIR for interactive encoding * * Revision 1.27 1995/01/27 21:58:07 eyhung * Fixed a bug with reading JMOVIES in GetNthInputFileName * * Revision 1.26 1995/01/25 23:00:05 smoot * Checks out Qtable entries * * Revision 1.25 1995/01/23 02:09:51 darryl * removed "PICT_RATE" code * * Revision 1.24 1995/01/20 00:07:46 smoot * requires unistd.c now * * Revision 1.23 1995/01/20 00:05:33 smoot * Added gamma correction option * * Revision 1.22 1995/01/19 23:55:55 eyhung * Fixed up smoot's "style" and made YUV_FORMAT default to EYUV * * Revision 1.21 1995/01/19 23:09:03 eyhung * Changed copyrights * * Revision 1.20 1995/01/17 22:04:14 smoot * Added `commands` to file name listing * * Revision 1.19 1995/01/17 06:28:01 eyhung * StdinUsed added. * * Revision 1.18 1995/01/16 09:33:35 eyhung * Fixed stupid commenting error. * * Revision 1.17 1995/01/16 06:07:53 eyhung * Made it look a little nicer * * Revision 1.16 1995/01/13 23:57:25 smoot * added Y format * * Revision 1.15 1995/01/08 06:20:39 eyhung * *** empty log message *** * * Revision 1.14 1995/01/08 06:15:57 eyhung * *** empty log message *** * * Revision 1.13 1995/01/08 05:50:32 eyhung * Added YUV Format parameter * * Revision 1.12 1994/12/16 00:55:30 smoot * Fixed INPU_FILES bug * * Revision 1.11 1994/12/12 23:54:36 smoot * Fixed GOP-missing error message (GOP to GOP_SIZE) * * Revision 1.10 1994/12/07 00:40:36 smoot * Added seperate P and B search ranges * * Revision 1.9 1994/11/18 23:19:22 smoot * Added USER_DATA parameter * * Revision 1.8 1994/11/16 22:33:40 smoot * Put in ifdef for rsh in param.c * * Revision 1.7 1994/11/16 22:25:05 smoot * Corrected ASPECT_RATIO bug * * Revision 1.6 1994/11/14 22:39:26 smoot * merged specifics and rate control * * Revision 1.5 1994/11/01 05:01:41 darryl * with rate control changes added * * Revision 1.1 1994/09/27 00:16:28 darryl * Initial revision * * Revision 1.4 1994/03/15 00:27:11 keving * nothing * * Revision 1.3 1993/12/22 19:19:01 keving * nothing * * Revision 1.2 1993/07/22 22:23:43 keving * nothing * * Revision 1.1 1993/06/30 20:06:09 keving * nothing * */