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