diff options
Diffstat (limited to 'converter/ppm/ppmtompeg/frametype.c')
-rw-r--r-- | converter/ppm/ppmtompeg/frametype.c | 365 |
1 files changed, 365 insertions, 0 deletions
diff --git a/converter/ppm/ppmtompeg/frametype.c b/converter/ppm/ppmtompeg/frametype.c new file mode 100644 index 00000000..b7daacc9 --- /dev/null +++ b/converter/ppm/ppmtompeg/frametype.c @@ -0,0 +1,365 @@ +/*===========================================================================* + * 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 "mallocvar.h" +#include "all.h" +#include "frames.h" +#include "frame.h" +#include "param.h" +#include "specifics.h" +#include "frametype.h" + + +static FrameTable *frameTable=NULL; +static boolean use_cache = FALSE; +static int firstI = 0; +static int numFrames; + +/*==================* + * GLOBAL VARIABLES * + *==================*/ + +extern int framePatternLen; +extern char * framePattern; + + +/*=====================* + * EXPORTED PROCEDURES * + *=====================*/ + +/*===========================================================================* + * + * FType_Type + * + * returns the type of the given numbered frame + * + * RETURNS: the type + * + * SIDE EFFECTS: none + * + *===========================================================================*/ +char +FType_Type(unsigned int const frameNum) { + + char const patternedType = framePattern[frameNum % framePatternLen]; + + char retval; + + if (use_cache) + return frameTable[frameNum].typ; + + if (frameNum+1 == numFrames) { + /* It's the last frame in the sequence. If the pattern says it's + a B, we convert it to I because a B frame makes no sense as the + last frame of a sequence. + */ + if (patternedType == 'b') + retval = 'i'; + else + retval = patternedType; + } else { + if (specificsOn) { + static int lastI = -1; + int newtype; + + if (lastI > frameNum) + lastI = -1; + newtype = SpecTypeLookup(frameNum); + switch (newtype) { + case 1: + lastI = frameNum; + retval = 'i'; + break; + case 2: + retval = 'p'; + break; + case 3: + retval = 'b'; + break; + default: + if (lastI != -1) { + unsigned int const pretendFrameNumber = + (frameNum - lastI + firstI) % framePatternLen; + retval = framePattern[pretendFrameNumber]; + } else + retval = patternedType; + } + } else + retval = patternedType; + } + return retval; +} + + + +unsigned int +FType_FutureRef(unsigned int const currFrameNum) { +/*---------------------------------------------------------------------------- + Return the number of the future reference frame for the B frame + 'currentFrameNum'. +-----------------------------------------------------------------------------*/ + unsigned int retval; + + if (use_cache) { + retval = frameTable[currFrameNum].next->number; + } else { + int const index = currFrameNum % framePatternLen; + int const futureIndex = frameTable[index].next->number; + unsigned int const patternedFutureRef = + currFrameNum + + (((futureIndex-index)+framePatternLen) % framePatternLen); + + retval = MIN(patternedFutureRef, numFrames-1); + } + return retval; +} + + + +/*===========================================================================* + * + * 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) { + unsigned int const len = strlen(pattern); + + char *buf; + unsigned int index; + + if (!pattern) + pm_error("INTERNAL ERROR: pattern cannot be NULL " + "in SetFramePattern"); + + if (SIMPLE_ASCII_UPPER(pattern[0]) != 'I') { + unsigned int index; + for (index = 0; index < len; ++index) { + if (SIMPLE_ASCII_UPPER(pattern[index]) == 'I') { + break; + } else if (SIMPLE_ASCII_UPPER(pattern[index]) == 'P') + pm_error("first reference frame must be 'i', not '%c'", + pattern[index]); + } + } + + 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: + pm_error("Invalid MPEG Frame type '%c'.", pattern[index]); + } + } + buf[len] = 0; + + if (firstI == -1) + pm_error("Must have an I-frame in PATTERN"); + + framePattern = buf; + framePatternLen = len; + + /* Used to ComputeFrameTable(), but now must wait until param + parsed. (STDIN or not) + */ +} + + + +void +ComputeFrameTable(unsigned int const numFramesArg) { +/*---------------------------------------------------------------------------- + Compute a table of I, P, B frames to help in determining dependencie + + 'numFrames' == 0 means number of frames is not known at this time. +-----------------------------------------------------------------------------*/ + int index; + FrameTable *lastI, *lastIP, *firstB, *secondIP; + FrameTable *ptr; + char typ; + int table_size; + + numFrames = numFramesArg; + + if (numFrames) + table_size = numFrames; + else + table_size = framePatternLen; + + MALLOCARRAY_NOFAIL(frameTable, 1 + table_size); + + 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 (numFrames) + use_cache = TRUE; +} |