1 /*===========================================================================*
2  * frametype.c								     *
3  *									     *
4  *	procedures to keep track of frame types (I, P, B)		     *
5  *									     *
6  * EXPORTED PROCEDURES:							     *
7  *	FType_Type						             *
8  *	FType_FutureRef						             *
9  *	FType_PastRef						             *
10  *									     *
11  * SYNOPSIS								     *
12  *	FType_Type	returns the type of the given numbered frame	     *
13  *	FType_FutureRef	returns the number of the future reference frame     *
14  *	FType_PastRef	returns the number of the past reference frame	     *
15  *									     *
16  *===========================================================================*/
17 
18 /*
19  * Copyright (c) 1995 The Regents of the University of California.
20  * All rights reserved.
21  *
22  * Permission to use, copy, modify, and distribute this software and its
23  * documentation for any purpose, without fee, and without written agreement is
24  * hereby granted, provided that the above copyright notice and the following
25  * two paragraphs appear in all copies of this software.
26  *
27  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
28  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
29  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
30  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
33  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
34  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
35  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
36  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
37  */
38 
39 
40 /*==============*
41  * HEADER FILES *
42  *==============*/
43 
44 #include "all.h"
45 #include "prototypes.h"
46 #include "frames.h"
47 #include "frame.h"
48 #include "param.h"
49 
50 
51 static FrameTable *frameTable=NULL;
52 static boolean use_cache = FALSE;
53 static int firstI = 0;
54 
55 /*==================*
56  * GLOBAL VARIABLES *
57  *==================*/
58 
59 boolean	    forceEncodeLast = FALSE;
60 extern int framePatternLen;
61 extern char *framePattern;
62 
63 
64 /*=====================*
65  * EXPORTED PROCEDURES *
66  *=====================*/
67 
68 /*===========================================================================*
69  *
70  * FType_Type
71  *
72  *	returns the type of the given numbered frame
73  *
74  * RETURNS:	the type
75  *
76  * SIDE EFFECTS:    none
77  *
78  *===========================================================================*/
79 int
FType_Type(frameNum)80 FType_Type(frameNum)
81     int frameNum;
82 {
83   if (use_cache) return (int)frameTable[frameNum].typ;
84 
85   if ( forceEncodeLast && (frameNum+1 == numInputFiles) ) {
86     int result;
87 
88     result = framePattern[frameNum % framePatternLen];
89     if ( result == 'b' ) return 'i';
90     else return result;
91   } else {
92     if (specificsOn) {
93       static int lastI = -1;
94       int newtype;
95 
96       if (lastI > frameNum) lastI = -1;
97       newtype = SpecTypeLookup(frameNum);
98       switch (newtype) {
99       case 1:
100 	lastI = frameNum;
101 	return 'i';
102       case 2:
103 	return 'p';
104       case 3:
105 	return 'b';
106       default:
107 	if (lastI != -1) return framePattern[(frameNum-lastI+firstI) % framePatternLen];
108 	else return framePattern[frameNum % framePatternLen];
109       }
110     } else return framePattern[frameNum % framePatternLen];
111   }
112 }
113 
114 
115 /*===========================================================================*
116  *
117  * FType_FutureRef
118  *
119  *	returns the number of the future reference frame
120  *
121  * RETURNS:	the number; -1 if none
122  *
123  * SIDE EFFECTS:    none
124  *
125  *===========================================================================*/
126 int
FType_FutureRef(currFrameNum)127 FType_FutureRef(currFrameNum)
128     int currFrameNum;
129 {
130     int	    index;
131     int	    futureIndex;
132     int	    result;
133 
134     if (use_cache) {
135       return frameTable[currFrameNum].next->number;
136     } else {
137       index = currFrameNum % framePatternLen;
138       futureIndex = frameTable[index].next->number;
139 
140       result = currFrameNum +
141 	(((futureIndex-index)+framePatternLen) % framePatternLen);
142 
143       if ( (result >= numInputFiles) && forceEncodeLast ) {
144 	return numInputFiles-1;
145       } else {
146 	return result;
147       }
148     }
149 }
150 
151 
152 /*===========================================================================*
153  *
154  * FType_PastRef
155  *
156  *	returns the number of the past reference frame
157  *
158  * RETURNS:	the number
159  *
160  * SIDE EFFECTS:    none
161  *
162  *===========================================================================*/
163 int
FType_PastRef(currFrameNum)164 FType_PastRef(currFrameNum)
165     int currFrameNum;
166 {
167     int	    index;
168     int	    pastIndex;
169 
170     if (use_cache) {
171       return frameTable[currFrameNum].prev->number;
172     } else {
173       index = currFrameNum % framePatternLen;
174       pastIndex = frameTable[index].prev->number;
175 
176       return currFrameNum -
177 	(((index-pastIndex)+framePatternLen) % framePatternLen);
178     }
179 }
180 
181 
182 /*===========================================================================*
183  *
184  * SetFramePattern
185  *
186  *	set the IPB pattern; calls ComputeFrameTable to set up table
187  *
188  * RETURNS:	nothing
189  *
190  * SIDE EFFECTS:    framePattern, framePatternLen, frameTable
191  *
192  *===========================================================================*/
193 #define SIMPLE_ASCII_UPPER(x)  (((x)>='a') ? ((x)-'a'+'A') : (x))
194 void
SetFramePattern(pattern)195 SetFramePattern(pattern)
196     char *pattern;
197 {
198     int len = strlen(pattern);
199     char *buf;
200     int index;
201 
202     if ( ! pattern ) {
203 	fprintf(stderr, "pattern cannot be NULL\n");
204 	exit(1);
205     }
206 
207     if ( SIMPLE_ASCII_UPPER(pattern[0]) != 'I' ) {
208       for (index=0; index < len; index++) {
209 
210 	if (SIMPLE_ASCII_UPPER(pattern[index]) == 'I') {
211 	  break;
212 	} else if (SIMPLE_ASCII_UPPER(pattern[index]) == 'P') {
213 	  fprintf(stderr, "first reference frame must be 'i'\n");
214 	  exit(1);
215 	}
216       }
217     }
218 
219     buf = (char *)malloc(sizeof(char)*(len+1));
220     ERRCHK(buf, "malloc");
221 
222     firstI = -1;
223     for ( index = 0; index < len; index++ ) {
224       switch( SIMPLE_ASCII_UPPER(pattern[index]) ) {
225       case 'I':
226 	buf[index] = 'i';
227 	if (firstI == -1) firstI = index;
228 	break;
229       case 'P':
230 	buf[index] = 'p';
231 	break;
232       case 'B':
233 	buf[index] = 'b';
234 	break;
235       default:
236 	fprintf(stderr, "Frame type '%c' not supported.\n", pattern[index]);
237 	exit(1);
238       }
239     }
240     buf[len] = 0;
241 
242     if (firstI == -1) {
243       fprintf(stderr, "Must have an I-frame in PATTERN\n");
244       exit(1);
245     }
246 
247     framePattern = buf;
248     framePatternLen = len;
249 
250     /* Used to ComputeFrameTable(), but now must wait until param parsed. (STDIN or not)*/
251 }
252 
253 
254 /*===========================================================================*
255  *
256  * ComputeFrameTable
257  *
258  *	compute a table of I, P, B frames to help in determining dependencies
259  *
260  * RETURNS:	nothing
261  *
262  * SIDE EFFECTS:    frameTable
263  *
264  *===========================================================================*/
265 void
ComputeFrameTable()266 ComputeFrameTable()
267 {
268     register int index;
269     FrameTable	*lastI, *lastIP, *firstB, *secondIP;
270     FrameTable	*ptr;
271     char typ;
272     int table_size;
273 
274     if (!stdinUsed) {
275       table_size = numInputFiles;
276     } else {
277       table_size = framePatternLen;
278     }
279 
280     frameTable = (FrameTable *) malloc((1+table_size)*sizeof(FrameTable));
281     ERRCHK(frameTable, "malloc");
282 
283     lastI = NULL;
284     lastIP = NULL;
285     firstB = NULL;
286     secondIP = NULL;
287     for ( index = 0; index < table_size; index++ ) {
288 	frameTable[index].number = index;
289 	typ = FType_Type(index);
290 	frameTable[index].typ = typ;
291 	switch( typ ) {
292 	    case 'i':
293 		ptr = firstB;
294 		while ( ptr != NULL ) {
295 		    ptr->next = &(frameTable[index]);
296 		    ptr = ptr->nextOutput;
297 		}
298 		frameTable[index].nextOutput = firstB;
299 		frameTable[index].prev = lastIP;	/* for freeing */
300 		if ( lastIP != NULL ) {
301 		    lastIP->next = &(frameTable[index]);
302 		    if ( secondIP == NULL ) {
303 			secondIP = &(frameTable[index]);
304 		    }
305 		}
306 		lastIP = &(frameTable[index]);
307 		firstB = NULL;
308 		break;
309 	    case 'p':
310 		ptr = firstB;
311 		while ( ptr != NULL ) {
312 		    ptr->next = &(frameTable[index]);
313 		    ptr = ptr->nextOutput;
314 		}
315 		frameTable[index].nextOutput = firstB;
316 		frameTable[index].prev = lastIP;
317 		if ( lastIP != NULL ) {
318 		    lastIP->next = &(frameTable[index]);
319 		    if ( secondIP == NULL ) {
320 			secondIP = &(frameTable[index]);
321 		    }
322 		}
323 		lastIP = &(frameTable[index]);
324 		firstB = NULL;
325 		break;
326 	    case 'b':
327 		if ( (index+1 == framePatternLen) ||
328 		     (FType_Type(index+1) != 'b') ) {
329 		    frameTable[index].nextOutput = NULL;
330 		} else {
331 		    frameTable[index].nextOutput = &(frameTable[index+1]);
332 		}
333 		frameTable[index].prev = lastIP;
334 		if ( firstB == NULL ) {
335 		    firstB = &(frameTable[index]);
336 		}
337 		break;
338 	    default:
339 	        fprintf(stderr, "Programmer Error in ComputeFrameTable (%d)\n",
340 			framePattern[index]);
341 	        exit(1);
342 	        break;
343 	}
344     }
345 
346     /* why? SRS */
347     frameTable[table_size].number = framePatternLen;
348     ptr = firstB;
349     while ( ptr != NULL ) {
350 	ptr->next = &(frameTable[table_size]);
351 	ptr = ptr->nextOutput;
352     }
353     frameTable[table_size].nextOutput = firstB;
354     frameTable[table_size].prev = lastIP;
355     if ( secondIP == NULL )
356 	frameTable[table_size].next = &(frameTable[0]);
357     else
358 	frameTable[table_size].next = secondIP;
359 
360     frameTable[0].prev = lastIP;
361     if ( lastIP != NULL ) {
362 	lastIP->next = &(frameTable[table_size]);
363     }
364 
365     if (!stdinUsed) {
366       use_cache = TRUE;
367     }
368 }
369 
370