/*===========================================================================* * input.c * * Stuff for getting the raw frame input for the program * *===========================================================================*/ /* 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 #include #include #include #include "nstring.h" #include "mallocvar.h" #include "parallel.h" #include "readframe.h" #include "param.h" #include "jpeg.h" #include "input.h" extern boolean realQuiet; /* TRUE = no messages to stdout */ struct InputFileEntry { char left[256]; char right[256]; bool glob; /* if FALSE, left is complete name */ int startID; int endID; int skip; int numPadding; /* -1 if there is none */ int numFiles; bool repeat; }; struct inputSource inputSource; void GetNthInputFileName(struct inputSource * const inputSourceP, unsigned int const n, const char ** const fileNameP) { /*---------------------------------------------------------------------------- Return the file name of the Nth input file. -----------------------------------------------------------------------------*/ static int lastN = 0, lastMapN = 0, lastSoFar = 0; int mapN; int index; int soFar; int numPadding; struct InputFileEntry * mapNEntryP; assert(!inputSourceP->stdinUsed); assert(n < inputSourceP->numInputFiles); if (n >= lastN) { soFar = lastSoFar; index = lastMapN; } else { soFar = 0; index = 0; } assert(index < inputSourceP->numInputFileEntries); while (soFar + inputSourceP->inputFileEntries[index]->numFiles <= n) { soFar += inputSourceP->inputFileEntries[index]->numFiles; ++index; assert(index < inputSourceP->numInputFileEntries); } mapN = index; mapNEntryP = inputSourceP->inputFileEntries[mapN]; index = mapNEntryP->startID + mapNEntryP->skip*(n - soFar); numPadding = mapNEntryP->numPadding; if (numPadding != -1) { char numBuffer[33]; int loop; sprintf(numBuffer, "%32d", index); for (loop = 32-numPadding; loop < 32; ++loop) { if (numBuffer[loop] != ' ') break; else numBuffer[loop] = '0'; } if (mapNEntryP->repeat != TRUE) pm_asprintf(fileNameP, "%s%s%s", mapNEntryP->left, &numBuffer[32-numPadding], mapNEntryP->right); else pm_asprintf(fileNameP, "%s", mapNEntryP->left); } else { if (mapNEntryP->repeat != TRUE) pm_asprintf(fileNameP, "%s%d%s", mapNEntryP->left, index, mapNEntryP->right); else pm_asprintf(fileNameP, "%s", mapNEntryP->left); } lastN = n; lastMapN = mapN; lastSoFar = soFar; } void ReadNthFrame(struct inputSource * const inputSourceP, unsigned int const frameNumber, boolean const remoteIO, boolean const childProcess, boolean const separateConversion, const char * const slaveConversion, const char * const inputConversion, MpegFrame * const frameP, bool * const endOfStreamP) { if (remoteIO) /* Get the frame from the remote I/O server */ GetRemoteFrame(frameP, frameNumber); else { /* Get the frame out of the file in which it lives */ const char * conversion; if (childProcess && separateConversion) conversion = slaveConversion; else conversion = inputConversion; ReadFrame(frameP, inputSourceP, frameNumber, conversion, endOfStreamP); } } /* Jim Boucher's code */ void JM2JPEG(struct inputSource * const inputSourceP) { char full_path[1024]; char inter_file[1024]; int ci; for(ci = 0; ci < inputSourceP->numInputFileEntries; ci++) { inter_file[0] = '\0'; full_path[0] = '\0'; strcpy(full_path, currentPath); if (!inputSource.stdinUsed) { strcat(full_path, "/"); strcat(full_path, inputSourceP->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, inputSourceP->inputFileEntries[ci]->startID, inputSourceP->inputFileEntries[ci]->endID); } else pm_error("ERROR: Cannot use JMovie format on Standard Input"); } } static const char * SkipSpacesTabs(const char * const start) { const char * p; for (p = start; *p == ' ' || *p == '\t'; ++p); return p; } static void processGlob(const char * const input, struct 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, struct InputFileEntry * const inputFileEntryP) { FILE *jmovie; char full_path[1024]; 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, struct 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; } #define INPUT_ENTRY_BLOCK_SIZE 128 void AddInputFiles(struct inputSource * const inputSourceP, const char * const input) { unsigned int const currentIndex = inputSourceP->numInputFileEntries; struct InputFileEntry * currentEntryP; if (currentIndex >= inputSourceP->ifArraySize) { /* Get more space */ inputSourceP->ifArraySize += INPUT_ENTRY_BLOCK_SIZE; REALLOCARRAY_NOFAIL(inputSourceP->inputFileEntries, inputSourceP->ifArraySize); } MALLOCVAR_NOFAIL(inputSourceP->inputFileEntries[currentIndex]); currentEntryP = inputSourceP->inputFileEntries[currentIndex]; if (input[strlen(input)-1] == ']') processGlob(input, currentEntryP); else { strcpy(currentEntryP->left, input); if (baseFormat == JMOVIE_FILE_TYPE) processJmovie(input, currentEntryP); else processSimpleFileName(input, currentEntryP); } inputSourceP->numInputFiles += currentEntryP->numFiles; ++inputSourceP->numInputFileEntries; } void SetStdinInput(struct inputSource * const inputSourceP) { assert(inputSourceP->numInputFileEntries == 0); inputSourceP->stdinUsed = TRUE; inputSourceP->numInputFiles = INT_MAX; } void CreateInputSource(struct inputSource ** const inputSourcePP) { struct inputSource * inputSourceP; MALLOCVAR_NOFAIL(inputSourceP); inputSourceP->stdinUsed = FALSE; inputSourceP->numInputFileEntries = 0; inputSourceP->ifArraySize = 1; inputSourceP->numInputFiles = 0; MALLOCARRAY_NOFAIL(inputSourceP->inputFileEntries, 1); *inputSourcePP = inputSourceP; } void DestroyInputSource(struct inputSource * const inputSourceP) { unsigned int i; for (i = 0; i < inputSourceP->numInputFileEntries; ++i) free(inputSourceP->inputFileEntries[i]); free(inputSourceP->inputFileEntries); free(inputSourceP); } /* * 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. */