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 |
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 |
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 |
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 |
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 |
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 |
} |