ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/freemol/trunk/src/mpeg_encode/src/specifics.c
Revision: 22
Committed: Mon Jul 7 22:16:37 2008 UTC (13 years, 1 month ago) by wdelano
File size: 17213 byte(s)
Log Message:
initial checkin of mpeg_encode source
Line User Rev File contents
1 wdelano 22 /*===========================================================================*
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     }