/*===========================================================================* * frametype.c * * * * procedures to keep track of frame types (I, P, B) * * * * EXPORTED PROCEDURES: * * FType_Type * * FType_FutureRef * * FType_PastRef * * * * SYNOPSIS * * FType_Type returns the type of the given numbered frame * * FType_FutureRef returns the number of the future reference frame * * FType_PastRef returns the number of the past reference frame * * * * 00.12.07 change malloc from frameTable to calloc to fix bug *===========================================================================*/ /* * 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 FILES * *==============*/ #include "all.h" #include "prototypes.h" #include "frames.h" #include "frame.h" #include "param.h" static FrameTable *frameTable=NULL; static boolean use_cache = FALSE; static int firstI = 0; /*==================* * GLOBAL VARIABLES * *==================*/ boolean forceEncodeLast = FALSE; extern int framePatternLen; extern char *framePattern; /*=====================* * EXPORTED PROCEDURES * *=====================*/ /*===========================================================================* * * FType_Type * * returns the type of the given numbered frame * * RETURNS: the type * * SIDE EFFECTS: none * *===========================================================================*/ int FType_Type(frameNum) int frameNum; { if (use_cache) return (int)frameTable[frameNum].typ; if ( forceEncodeLast && (frameNum+1 == numInputFiles) ) { int result; result = framePattern[frameNum % framePatternLen]; if ( result == 'b' ) return 'i'; else return result; } else { if (specificsOn) { static int lastI = -1; int newtype; if (lastI > frameNum) lastI = -1; newtype = SpecTypeLookup(frameNum); switch (newtype) { case 1: lastI = frameNum; return 'i'; case 2: return 'p'; case 3: return 'b'; default: if (lastI != -1) return framePattern[(frameNum-lastI+firstI) % framePatternLen]; else return framePattern[frameNum % framePatternLen]; } } else return framePattern[frameNum % framePatternLen]; } } /*===========================================================================* * * FType_FutureRef * * returns the number of the future reference frame * * RETURNS: the number; -1 if none * * SIDE EFFECTS: none * *===========================================================================*/ int FType_FutureRef(currFrameNum) int currFrameNum; { int index; int futureIndex; int result; if (use_cache) { return frameTable[currFrameNum].next->number; } else { index = currFrameNum % framePatternLen; futureIndex = frameTable[index].next->number; result = currFrameNum + (((futureIndex-index)+framePatternLen) % framePatternLen); if ( (result >= numInputFiles) && forceEncodeLast ) { return numInputFiles-1; } else { return result; } } } /*===========================================================================* * * FType_PastRef * * returns the number of the past reference frame * * RETURNS: the number * * SIDE EFFECTS: none * *===========================================================================*/ int FType_PastRef(currFrameNum) int currFrameNum; { int index; int pastIndex; if (use_cache) { return frameTable[currFrameNum].prev->number; } else { index = currFrameNum % framePatternLen; pastIndex = frameTable[index].prev->number; return currFrameNum - (((index-pastIndex)+framePatternLen) % framePatternLen); } } /*===========================================================================* * * SetFramePattern * * set the IPB pattern; calls ComputeFrameTable to set up table * * RETURNS: nothing * * SIDE EFFECTS: framePattern, framePatternLen, frameTable * *===========================================================================*/ #define SIMPLE_ASCII_UPPER(x) (((x)>='a') ? ((x)-'a'+'A') : (x)) void SetFramePattern(const char * const pattern) { int len = strlen(pattern); char *buf; int index; if ( ! pattern ) { fprintf(stderr, "pattern cannot be NULL\n"); exit(1); } if ( SIMPLE_ASCII_UPPER(pattern[0]) != 'I' ) { for (index=0; index < len; index++) { if (SIMPLE_ASCII_UPPER(pattern[index]) == 'I') { break; } else if (SIMPLE_ASCII_UPPER(pattern[index]) == 'P') { fprintf(stderr, "first reference frame must be 'i'\n"); exit(1); } } } buf = (char *)malloc(sizeof(char)*(len+1)); ERRCHK(buf, "malloc"); firstI = -1; for ( index = 0; index < len; index++ ) { switch( SIMPLE_ASCII_UPPER(pattern[index]) ) { case 'I': buf[index] = 'i'; if (firstI == -1) firstI = index; break; case 'P': buf[index] = 'p'; break; case 'B': buf[index] = 'b'; break; default: fprintf(stderr, "Frame type '%c' not supported.\n", pattern[index]); exit(1); } } buf[len] = 0; if (firstI == -1) { fprintf(stderr, "Must have an I-frame in PATTERN\n"); exit(1); } framePattern = buf; framePatternLen = len; /* Used to ComputeFrameTable(), but now must wait until param parsed. (STDIN or not)*/ } /*===========================================================================* * * ComputeFrameTable * * compute a table of I, P, B frames to help in determining dependencies * * RETURNS: nothing * * SIDE EFFECTS: frameTable * *===========================================================================*/ void ComputeFrameTable() { register int index; FrameTable *lastI, *lastIP, *firstB, *secondIP; FrameTable *ptr; char typ; int table_size; if (!stdinUsed) { table_size = numInputFiles; } else { table_size = framePatternLen; } frameTable = (FrameTable *) calloc((1+table_size), sizeof(FrameTable)); ERRCHK(frameTable, "malloc"); lastI = NULL; lastIP = NULL; firstB = NULL; secondIP = NULL; for ( index = 0; index < table_size; index++ ) { frameTable[index].number = index; typ = FType_Type(index); frameTable[index].typ = typ; switch( typ ) { case 'i': ptr = firstB; while ( ptr != NULL ) { ptr->next = &(frameTable[index]); ptr = ptr->nextOutput; } frameTable[index].nextOutput = firstB; frameTable[index].prev = lastIP; /* for freeing */ if ( lastIP != NULL ) { lastIP->next = &(frameTable[index]); if ( secondIP == NULL ) { secondIP = &(frameTable[index]); } } lastIP = &(frameTable[index]); firstB = NULL; break; case 'p': ptr = firstB; while ( ptr != NULL ) { ptr->next = &(frameTable[index]); ptr = ptr->nextOutput; } frameTable[index].nextOutput = firstB; frameTable[index].prev = lastIP; if ( lastIP != NULL ) { lastIP->next = &(frameTable[index]); if ( secondIP == NULL ) { secondIP = &(frameTable[index]); } } lastIP = &(frameTable[index]); firstB = NULL; break; case 'b': if ( (index+1 == framePatternLen) || (FType_Type(index+1) != 'b') ) { frameTable[index].nextOutput = NULL; } else { frameTable[index].nextOutput = &(frameTable[index+1]); } frameTable[index].prev = lastIP; if ( firstB == NULL ) { firstB = &(frameTable[index]); } break; default: fprintf(stderr, "Programmer Error in ComputeFrameTable (%d)\n", framePattern[index]); exit(1); break; } } /* why? SRS */ frameTable[table_size].number = framePatternLen; ptr = firstB; while ( ptr != NULL ) { ptr->next = &(frameTable[table_size]); ptr = ptr->nextOutput; } frameTable[table_size].nextOutput = firstB; frameTable[table_size].prev = lastIP; if ( secondIP == NULL ) frameTable[table_size].next = &(frameTable[0]); else frameTable[table_size].next = secondIP; frameTable[0].prev = lastIP; if ( lastIP != NULL ) { lastIP->next = &(frameTable[table_size]); } if (!stdinUsed) { use_cache = TRUE; } }