1 |
/*===========================================================================* |
2 |
* specifics.c * |
3 |
* * |
4 |
* basic procedures to deal with the specifics file * |
5 |
* * |
6 |
* EXPORTED PROCEDURES: * |
7 |
* Specifics_Init * |
8 |
* Spec_Lookup * |
9 |
* SpecTypeLookup * |
10 |
* * |
11 |
*===========================================================================*/ |
12 |
|
13 |
/* |
14 |
* Copyright (c) 1995 The Regents of the University of California. |
15 |
* All rights reserved. |
16 |
* |
17 |
* Permission to use, copy, modify, and distribute this software and its |
18 |
* documentation for any purpose, without fee, and without written agreement is |
19 |
* hereby granted, provided that the above copyright notice and the following |
20 |
* two paragraphs appear in all copies of this software. |
21 |
* |
22 |
* IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR |
23 |
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT |
24 |
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF |
25 |
* CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 |
* |
27 |
* THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, |
28 |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
29 |
* AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS |
30 |
* ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO |
31 |
* PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. |
32 |
*/ |
33 |
|
34 |
|
35 |
/*==============* |
36 |
* HEADER FILES * |
37 |
*==============*/ |
38 |
|
39 |
#include "all.h" |
40 |
#include "mtypes.h" |
41 |
#include "frames.h" |
42 |
#include "frame.h" |
43 |
#include "fsize.h" |
44 |
#include "dct.h" |
45 |
#include "specifics.h" |
46 |
#include <stdio.h> |
47 |
#include <string.h> |
48 |
#include "prototypes.h" |
49 |
|
50 |
/*====================* |
51 |
* System Information * |
52 |
*====================*/ |
53 |
|
54 |
#define CPP_LOC "/lib/cpp" |
55 |
|
56 |
/*==================* |
57 |
* GLOBAL VARIABLES * |
58 |
*==================*/ |
59 |
|
60 |
extern boolean specificsOn; |
61 |
extern char specificsFile[]; |
62 |
extern char specificsDefines[]; |
63 |
FrameSpecList *fsl; |
64 |
|
65 |
/*=====================* |
66 |
* Internal procedures * |
67 |
*=====================*/ |
68 |
|
69 |
void Parse_Specifics_File _ANSI_ARGS_((FILE *fp)); |
70 |
void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp)); |
71 |
void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp)); |
72 |
FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); |
73 |
void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs)); |
74 |
Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, |
75 |
boolean rel, int qs)); |
76 |
FrameSpecList *MakeFslEntry _ANSI_ARGS_((void)); |
77 |
#define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c) |
78 |
#define CvtType(x) ReallyCvt(my_upper(x)) |
79 |
#define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1)) |
80 |
#define SkipToSpace(lp) while ((*lp != ' ') && (*lp != '\n') && (*lp != '\0')) lp++ |
81 |
#define EndString(lp) ((*lp == '\n') || (*lp == '\0')) |
82 |
|
83 |
/*============================================================= |
84 |
* SPEC FILE FORMAT (version 1): |
85 |
|
86 |
Specs files are processed with the c preprecoessor, so use C style comments |
87 |
and #defines if you wish. |
88 |
|
89 |
frames, blocks, and slices are numbered from 0. |
90 |
(sorry) |
91 |
|
92 |
In order by frame number, slice number, block number |
93 |
(if you skip slices it's fine). |
94 |
Can have specifics for any frame, block, or slice. |
95 |
Format: |
96 |
version N |
97 |
Specify the version of the specifics file format (this is 1) |
98 |
frame N T M |
99 |
Sets frame number N to type T and Qscale M |
100 |
(type T is I,B,P,other, other means unspec. I recomend - ) |
101 |
slice M Q |
102 |
Sets slice M (in frame N as defined by a previous frame command) |
103 |
to qscale Q |
104 |
block M Q |
105 |
Sets block M to qscale Q, in frame N previously specified. |
106 |
|
107 |
Unspecified frame types are set via the last I frame set, which is forced |
108 |
to act as the first I of the GOP. |
109 |
FORCE_ENCODE_LAST_FRAME overrides specifics on the final frame type. |
110 |
Note that Qscale changes in skipped blocks will be lost! |
111 |
|
112 |
Version 2: |
113 |
frames and slices are the same as above, but Q in blocks can be relative, i.e. |
114 |
+N or -N. Clipping to 1..31 is done but sequences like |
115 |
block 1 2 |
116 |
block 2 -3 |
117 |
block 3 +3 |
118 |
|
119 |
has undefined results (as present block 3 would be Qscale 2). |
120 |
|
121 |
In addition motion vectors can be specified: |
122 |
block M Q skip |
123 |
Says to skip the block (not really an MV, but....) |
124 |
block M Q bi fx fy bx by |
125 |
Sets block M to quality Q. It will be a bidirectional block. |
126 |
fx/fy is the forward (like a P frame) vector, bx/y is the back |
127 |
block M Q forw fx fy |
128 |
block M Q back bx by |
129 |
Single directional. |
130 |
|
131 |
All vectors are specified in HALF PIXEL fixed point units, i.e. |
132 |
3.5 pixels is 7 |
133 |
To specify a vector but not touch the q factor, set Q to 0 |
134 |
|
135 |
*=============================================================*/ |
136 |
|
137 |
|
138 |
/*=============* |
139 |
* Local State * |
140 |
*=============*/ |
141 |
|
142 |
static char version = -1; |
143 |
|
144 |
/*================================================================ |
145 |
* |
146 |
* Specifics_Init |
147 |
* |
148 |
* Cpp's and reads in the specifics file. Creates fsl data structure. |
149 |
* |
150 |
* Returns: nothing |
151 |
* |
152 |
* Modifies: fsl, file specificsFile".cpp" |
153 |
* |
154 |
*================================================================ |
155 |
*/ |
156 |
void Specifics_Init() |
157 |
{ |
158 |
char command[1100]; |
159 |
FILE *specificsFP; |
160 |
|
161 |
sprintf(command, "/bin/rm -f %s.cpp", specificsFile); |
162 |
system(command); |
163 |
sprintf(command, "%s -P %s %s %s.cpp", |
164 |
CPP_LOC, specificsDefines, specificsFile, specificsFile); |
165 |
system(command); |
166 |
strcat(specificsFile, ".cpp"); |
167 |
if ((specificsFP = fopen(specificsFile, "r")) == NULL) { |
168 |
fprintf(stderr, "Error with specifics file, cannot open %s\n", specificsFile); |
169 |
exit(1); |
170 |
} |
171 |
printf("Specifics file: %s\n", specificsFile); |
172 |
Parse_Specifics_File(specificsFP); |
173 |
sprintf(command, "/bin/rm -f %s.cpp", specificsFile); |
174 |
system(command); |
175 |
|
176 |
} |
177 |
|
178 |
|
179 |
|
180 |
|
181 |
/*================================================================ |
182 |
* |
183 |
* Parse_Specifics_File |
184 |
* |
185 |
* Read through the file passed in creating the fsl data structure |
186 |
* There is a primary routine, and helpers for the specific versions. |
187 |
* |
188 |
* Returns: Nothing |
189 |
* |
190 |
* Modifies: fsl |
191 |
* |
192 |
*================================================================ |
193 |
*/ |
194 |
void Parse_Specifics_File(fp) |
195 |
FILE *fp; |
196 |
{ |
197 |
char line[1024], *lp; |
198 |
int vers; |
199 |
|
200 |
while ((fgets(line, 1023, fp)) != NULL) { |
201 |
lp = &line[0]; |
202 |
while ((*lp == ' ') || (*lp == '\t')) lp++; |
203 |
if (( *lp == '#' ) || (*lp=='\n')) { |
204 |
continue; |
205 |
} |
206 |
|
207 |
switch (my_upper(*lp)) { |
208 |
case 'F': case 'S': case 'B': |
209 |
fprintf(stderr, "Must specify version at beginning of specifics file\n"); |
210 |
exit(0); |
211 |
break; |
212 |
case 'V': |
213 |
lp += 7; |
214 |
if (1 != sscanf(lp, "%d", &vers)) { |
215 |
fprintf(stderr," Improper version line in specs file: %s\n", line); |
216 |
} else { |
217 |
switch (vers) { |
218 |
case 1: |
219 |
version = vers; |
220 |
Parse_Specifics_File_v1(fp); |
221 |
break; |
222 |
case 2: |
223 |
version = vers; |
224 |
Parse_Specifics_File_v2(fp); |
225 |
break; |
226 |
default: |
227 |
fprintf(stderr, "Improper version line in specs file: %s\n", line); |
228 |
fprintf(stderr, "\tSpecifics file will be IGNORED.\n"); |
229 |
specificsOn = FALSE; |
230 |
return; |
231 |
break; |
232 |
}} |
233 |
break; |
234 |
default: |
235 |
fprintf(stderr, "Specifics file: What? *%s*\n", line); |
236 |
break; |
237 |
}} |
238 |
|
239 |
} |
240 |
|
241 |
/* Version 1 */ |
242 |
void Parse_Specifics_File_v1(fp) |
243 |
FILE *fp; |
244 |
{ |
245 |
char line[1024],*lp; |
246 |
FrameSpecList *current, *new; |
247 |
char typ; |
248 |
int fnum,snum, bnum, qs, newqs; |
249 |
int num_scanned; |
250 |
|
251 |
fsl = MakeFslEntry(); |
252 |
current = fsl; |
253 |
|
254 |
while ((fgets(line,1023, fp)) != NULL) { |
255 |
lp = &line[0]; |
256 |
while ((*lp == ' ') || (*lp == '\t')) lp++; |
257 |
if (( *lp == '#' ) || (*lp=='\n')) { |
258 |
continue; |
259 |
} |
260 |
|
261 |
switch (my_upper(*lp)) { |
262 |
case 'F': |
263 |
lp += 6; |
264 |
sscanf(lp, "%d %c %d", &fnum, &typ, &qs); |
265 |
if (current->framenum != -1) { |
266 |
new=MakeFslEntry(); |
267 |
current->next = new; |
268 |
current = new; |
269 |
} |
270 |
current->framenum = fnum; |
271 |
current->frametype = CvtType(typ); |
272 |
if (qs <= 0) qs = -1; |
273 |
current->qscale = qs; |
274 |
break; |
275 |
case 'S': |
276 |
lp += 6; |
277 |
sscanf(lp, "%d %d", &snum, &newqs); |
278 |
if (qs == newqs) break; |
279 |
qs = newqs; |
280 |
AddSlc(current, snum, qs); |
281 |
break; |
282 |
case 'B': |
283 |
lp += 6; |
284 |
num_scanned = sscanf(lp, "%d %d", &bnum, &newqs); |
285 |
if (qs == newqs) break; |
286 |
qs = newqs; |
287 |
AddBs(current, bnum, FALSE, qs); |
288 |
break; |
289 |
case 'V': |
290 |
fprintf(stderr, "Cannot specify version twice! Taking first (%d)\n", version); |
291 |
break; |
292 |
default: |
293 |
fprintf(stderr," What? *%s*\n", line); |
294 |
break; |
295 |
}} |
296 |
|
297 |
} |
298 |
|
299 |
/* Version 2 */ |
300 |
void Parse_Specifics_File_v2(fp) |
301 |
FILE *fp; |
302 |
{ |
303 |
char line[1024], *lp; |
304 |
FrameSpecList *current, *new; |
305 |
char typ; |
306 |
int fnum, snum, bnum, qs, newqs; |
307 |
int num_scanned, fx=0, fy=0, sx=0, sy=0; |
308 |
char kind[100]; |
309 |
Block_Specifics *new_blk; |
310 |
boolean relative; |
311 |
|
312 |
fsl = MakeFslEntry(); |
313 |
current = fsl; |
314 |
|
315 |
while ((fgets(line,1023,fp))!=NULL) { |
316 |
lp = &line[0]; |
317 |
while ((*lp == ' ') || (*lp == '\t')) lp++; |
318 |
if (( *lp == '#' ) || (*lp=='\n')) { |
319 |
continue; |
320 |
} |
321 |
|
322 |
switch (my_upper(*lp)) { |
323 |
case 'F': |
324 |
lp += 6; |
325 |
sscanf(lp,"%d %c %d", &fnum, &typ, &qs); |
326 |
new = MakeFslEntry(); |
327 |
if (current->framenum != -1) { |
328 |
current->next = new; |
329 |
current = new; |
330 |
} |
331 |
current->framenum = fnum; |
332 |
current->frametype = CvtType(typ); |
333 |
if (qs <= 0) qs = -1; |
334 |
current->qscale = qs; |
335 |
break; |
336 |
case 'S': |
337 |
lp += 6; |
338 |
sscanf(lp,"%d %d", &snum, &newqs); |
339 |
if (qs == newqs) break; |
340 |
qs = newqs; |
341 |
AddSlc(current, snum, qs); |
342 |
break; |
343 |
case 'B': |
344 |
lp += 6; |
345 |
num_scanned = 0; |
346 |
bnum = atoi(lp); |
347 |
SkipToSpace(lp); |
348 |
while ((*lp != '-') && (*lp != '+') && |
349 |
((*lp < '0') || (*lp > '9'))) lp++; |
350 |
relative = ((*lp == '-') || (*lp == '+')); |
351 |
newqs = atoi(lp); |
352 |
SkipToSpace(lp); |
353 |
if (EndString(lp)) { |
354 |
num_scanned = 2; |
355 |
} else { |
356 |
num_scanned = 2+sscanf(lp, "%s %d %d %d %d", kind, &fx, &fy, &sx, &sy); |
357 |
} |
358 |
|
359 |
qs = newqs; |
360 |
new_blk = AddBs(current, bnum, relative, qs); |
361 |
if (num_scanned > 2) { |
362 |
BlockMV *tmp; |
363 |
tmp = (BlockMV *) malloc(sizeof(BlockMV)); |
364 |
switch (num_scanned) { |
365 |
case 7: |
366 |
tmp->typ = TYP_BOTH; |
367 |
tmp->fx = fx; |
368 |
tmp->fy = fy; |
369 |
tmp->bx = sx; |
370 |
tmp->by = sy; |
371 |
new_blk->mv = tmp; |
372 |
break; |
373 |
case 3: |
374 |
tmp->typ = TYP_SKIP; |
375 |
new_blk->mv = tmp; |
376 |
break; |
377 |
case 5: |
378 |
if (my_upper(kind[0]) == 'B') { |
379 |
tmp->typ = TYP_BACK; |
380 |
tmp->bx = fx; |
381 |
tmp->by = fy; |
382 |
} else { |
383 |
tmp->typ = TYP_FORW; |
384 |
tmp->fx = fx; |
385 |
tmp->fy = fy; |
386 |
} |
387 |
new_blk->mv = tmp; |
388 |
break; |
389 |
default: |
390 |
fprintf(stderr, |
391 |
"Bug in specifics file! Skipping short/long entry: %s\n",line); |
392 |
break; |
393 |
} |
394 |
} else { |
395 |
new_blk->mv = (BlockMV *) NULL; |
396 |
} |
397 |
|
398 |
break; |
399 |
case 'V': |
400 |
fprintf(stderr, |
401 |
"Cannot specify version twice! Taking first (%d).\n", |
402 |
version); |
403 |
break; |
404 |
default: |
405 |
printf("What? *%s*\n",line); |
406 |
break; |
407 |
}} |
408 |
|
409 |
} |
410 |
|
411 |
|
412 |
|
413 |
|
414 |
/*================================================================= |
415 |
* |
416 |
* MakeFslEntry |
417 |
* |
418 |
* Makes a single entry in for the fsl linked list (makes a frame) |
419 |
* |
420 |
* Returns: the new entry |
421 |
* |
422 |
* Modifies: nothing |
423 |
* |
424 |
*================================================================= |
425 |
*/ |
426 |
FrameSpecList *MakeFslEntry() |
427 |
{ |
428 |
FrameSpecList *fslp; |
429 |
fslp = (FrameSpecList *) malloc(sizeof(FrameSpecList)); |
430 |
fslp->framenum = -1; |
431 |
fslp->slc = (Slice_Specifics *) NULL; |
432 |
fslp->bs = (Block_Specifics *) NULL; |
433 |
return fslp; |
434 |
} |
435 |
|
436 |
|
437 |
|
438 |
|
439 |
|
440 |
/*================================================================ |
441 |
* |
442 |
* AddSlc |
443 |
* |
444 |
* Adds a slice to framespeclist c with values snum and qs |
445 |
* |
446 |
* Returns: nothing |
447 |
* |
448 |
* Modifies: fsl's structure |
449 |
* |
450 |
*================================================================ |
451 |
*/ |
452 |
void AddSlc(c, snum, qs) |
453 |
FrameSpecList *c; |
454 |
int snum,qs; |
455 |
{ |
456 |
Slice_Specifics *new; |
457 |
static Slice_Specifics *last; |
458 |
|
459 |
new = (Slice_Specifics *) malloc(sizeof(Slice_Specifics)); |
460 |
new->num = snum; |
461 |
new->qscale = qs; |
462 |
new->next = (Slice_Specifics *)NULL; |
463 |
if (c->slc == (Slice_Specifics *)NULL) { |
464 |
last = new; |
465 |
c->slc = new; |
466 |
} else { |
467 |
last->next = new; |
468 |
last = new; |
469 |
} |
470 |
} |
471 |
|
472 |
|
473 |
|
474 |
|
475 |
|
476 |
/*================================================================ |
477 |
* |
478 |
* AddBs |
479 |
* |
480 |
* Adds a sliceblock to framespeclist c with values bnum and qs |
481 |
* |
482 |
* Returns: pointer to the new block spec |
483 |
* |
484 |
* Modifies: fsl's structure |
485 |
* |
486 |
*================================================================ |
487 |
*/ |
488 |
Block_Specifics *AddBs(c,bnum,rel,qs) |
489 |
FrameSpecList *c; |
490 |
boolean rel; |
491 |
int bnum,qs; |
492 |
{ |
493 |
Block_Specifics *new; |
494 |
static Block_Specifics *last; |
495 |
|
496 |
new = (Block_Specifics *) malloc(sizeof(Block_Specifics)); |
497 |
new->num = bnum; |
498 |
if (qs == 0) rel = TRUE; |
499 |
new->relative = rel; |
500 |
new->qscale = qs; |
501 |
new->next = (Block_Specifics *)NULL; |
502 |
new->mv = (BlockMV *) NULL; |
503 |
if (c->bs == (Block_Specifics *)NULL) { |
504 |
last = new; |
505 |
c->bs = new; |
506 |
} else { |
507 |
last->next = new; |
508 |
last = new; |
509 |
} |
510 |
return new; |
511 |
} |
512 |
|
513 |
|
514 |
|
515 |
|
516 |
|
517 |
|
518 |
/*================================================================ |
519 |
* |
520 |
* SpecLookup |
521 |
* |
522 |
* Find out if there is any changes to be made for the qscale |
523 |
* at entry fn.num (which is of type typ). Sets info to point to |
524 |
* motion vector info (if any), else NULL. |
525 |
* |
526 |
* Returns: new qscale or -1 |
527 |
* |
528 |
* Modifies: *info (well, internal cache can change) |
529 |
* |
530 |
*================================================================ |
531 |
*/ |
532 |
|
533 |
int SpecLookup(fn,typ,num,info,start_qs) |
534 |
int fn,typ,num; |
535 |
BlockMV **info; |
536 |
int start_qs; |
537 |
{ |
538 |
static FrameSpecList *last = (FrameSpecList *) NULL; |
539 |
Slice_Specifics *sptr=(Slice_Specifics *) NULL; |
540 |
Block_Specifics *bptr=(Block_Specifics *) NULL; |
541 |
FrameSpecList *tmp; |
542 |
boolean found_it; |
543 |
static int leftovers = 0; /* Used in case of forced movement into 1..31 range */ |
544 |
|
545 |
*info = (BlockMV * )NULL; |
546 |
if (last == (FrameSpecList *) NULL){ |
547 |
/* No cache, try to find number fn */ |
548 |
tmp = fsl; |
549 |
found_it = FALSE; |
550 |
while (tmp != (FrameSpecList *) NULL) { |
551 |
if (tmp->framenum == fn) { |
552 |
found_it = TRUE; |
553 |
break; |
554 |
} else tmp = tmp->next; |
555 |
} |
556 |
if (!found_it) return -1; |
557 |
last=tmp; |
558 |
} else { |
559 |
if (last->framenum != fn) { /* cache miss! */ |
560 |
/* first check if it is next */ |
561 |
if ((last->next != (FrameSpecList *) NULL) && |
562 |
(last->next->framenum == fn)) { |
563 |
last = last->next; |
564 |
} else { |
565 |
/* if not next, check from the start. |
566 |
(this allows people to put frames out of order,even |
567 |
though the spec doesnt allow it.) */ |
568 |
tmp = fsl; |
569 |
found_it = FALSE; |
570 |
while (tmp != (FrameSpecList *) NULL) { |
571 |
if (tmp->framenum==fn) {found_it = TRUE; break;} |
572 |
tmp = tmp->next; |
573 |
} |
574 |
if (!found_it) return -1; |
575 |
last = tmp; |
576 |
} |
577 |
} |
578 |
} |
579 |
/* neither of these should ever be true, unless there is a bug above */ |
580 |
if (last == (FrameSpecList *) NULL) { |
581 |
fprintf(stderr, "PROGRAMMER ERROR: last is null!\n"); |
582 |
return -1; |
583 |
} |
584 |
if (last->framenum!=fn) { |
585 |
fprintf(stderr, "PROGRAMMER ERROR: last has wrong number!\n"); |
586 |
return -1; /* no data on it */ |
587 |
} |
588 |
|
589 |
switch(typ) { |
590 |
case 0: /* Frame: num is ignored */ |
591 |
leftovers = 0; |
592 |
#ifdef BLEAH |
593 |
printf("QSchange frame %d to %d\n", fn, last->qscale); |
594 |
#endif |
595 |
return last->qscale; |
596 |
break; |
597 |
|
598 |
case 1: /* Slice */ |
599 |
leftovers = 0; |
600 |
/* So, any data on slices? */ |
601 |
if (last->slc == (Slice_Specifics *) NULL) return -1; |
602 |
for (sptr = last->slc; sptr != (Slice_Specifics *) NULL; sptr = sptr->next) { |
603 |
if (sptr->num == num) { |
604 |
#ifdef BLEAH |
605 |
printf("QSchange Slice %d.%d to %d\n", fn, num, sptr->qscale); |
606 |
#endif |
607 |
if (sptr->qscale == 0) return -1; |
608 |
return sptr->qscale; |
609 |
} |
610 |
} |
611 |
break; |
612 |
|
613 |
case 2: /* block */ |
614 |
/* So, any data on blocks? */ |
615 |
if (last->bs == (Block_Specifics *) NULL) { |
616 |
return -1; |
617 |
} |
618 |
for (bptr=last->bs; bptr != (Block_Specifics *) NULL; bptr=bptr->next) { |
619 |
if (bptr->num == num) { |
620 |
int new_one; |
621 |
#ifdef BLEAH |
622 |
printf("QSchange Block %d.%d to %d\n", fn, num, bptr->qscale); |
623 |
#endif |
624 |
*info = bptr->mv; |
625 |
if (bptr->relative) { |
626 |
if (bptr->qscale == 0) { |
627 |
/* Do nothing! */ |
628 |
new_one = start_qs; |
629 |
} else { |
630 |
new_one = start_qs + bptr->qscale + leftovers; |
631 |
if (new_one < 1) { |
632 |
leftovers = new_one - 1; |
633 |
new_one = 1; |
634 |
} else if (new_one > 31) { |
635 |
leftovers = new_one - 31; |
636 |
new_one = 31; |
637 |
} else leftovers = 0; |
638 |
}} |
639 |
else { |
640 |
new_one = bptr->qscale; |
641 |
leftovers = 0; |
642 |
} |
643 |
return new_one; |
644 |
} |
645 |
} |
646 |
break; |
647 |
default: |
648 |
fprintf(stderr, "PROGRAMMER ERROR: reached unreachable code in SpecLookup\n"); |
649 |
break; |
650 |
} |
651 |
/* no luck */ |
652 |
return -1; |
653 |
} |
654 |
|
655 |
|
656 |
/*================================================================ |
657 |
* |
658 |
* SpecTypeLookup |
659 |
* |
660 |
* Find out if there is any changes to be made for the type of frame |
661 |
* at frame fn. |
662 |
* |
663 |
* Returns: new type or -1 (unspecified) |
664 |
* |
665 |
*================================================================ |
666 |
*/ |
667 |
int SpecTypeLookup(fn) |
668 |
int fn; |
669 |
{ |
670 |
FrameSpecList *tmp; |
671 |
|
672 |
/* try to find number fn */ |
673 |
tmp = fsl; |
674 |
do { |
675 |
if (tmp->framenum == fn) break; |
676 |
else tmp = tmp->next; |
677 |
} while (tmp != (FrameSpecList *) NULL); |
678 |
if (tmp == (FrameSpecList *) NULL) { |
679 |
#ifdef BLEAH |
680 |
printf("Frame %d type not specified\n", fn); |
681 |
#endif |
682 |
return -1; |
683 |
} |
684 |
#ifdef BLEAH |
685 |
printf("Frame %d type set to %d\n", fn, tmp->frametype); |
686 |
#endif |
687 |
return tmp->frametype; |
688 |
} |