Skip to content

AFNI/NIfTI Server

Sections
Personal tools
You are here: Home » AFNI » Documentation

Doxygen Source Code Documentation


Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals   Search  

specifics.c

Go to the documentation of this file.
00001 /*===========================================================================*
00002  * specifics.c                                                               *
00003  *                                                                           *
00004  *      basic procedures to deal with the specifics file                     *
00005  *                                                                           *
00006  * EXPORTED PROCEDURES:                                                      *
00007  *      Specifics_Init                                                       *
00008  *      Spec_Lookup                                                          *
00009  *      SpecTypeLookup                                                       *
00010  *                                                                           *
00011  *===========================================================================*/
00012 
00013 /*
00014  * Copyright (c) 1995 The Regents of the University of California.
00015  * All rights reserved.
00016  *
00017  * Permission to use, copy, modify, and distribute this software and its
00018  * documentation for any purpose, without fee, and without written agreement is
00019  * hereby granted, provided that the above copyright notice and the following
00020  * two paragraphs appear in all copies of this software.
00021  *
00022  * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
00023  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
00024  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF
00025  * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00026  *
00027  * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
00028  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
00029  * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
00030  * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
00031  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
00032  */
00033 
00034 
00035 /*==============*
00036  * HEADER FILES *
00037  *==============*/
00038 
00039 #include "all.h"
00040 #include "mtypes.h"
00041 #include "frames.h"
00042 #include "frame.h"
00043 #include "fsize.h"
00044 #include "dct.h"
00045 #include "specifics.h"
00046 #include <stdio.h>
00047 #include <string.h>
00048 #include "prototypes.h"
00049 
00050 /*====================*
00051  * System Information *
00052  *====================*/
00053 
00054 #define CPP_LOC "/lib/cpp"
00055 
00056 /*==================*
00057  * GLOBAL VARIABLES *
00058  *==================*/
00059 
00060 extern boolean specificsOn;
00061 extern char specificsFile[];
00062 extern char specificsDefines[];
00063 FrameSpecList *fsl;
00064 
00065 /*=====================*
00066  * Internal procedures *
00067  *=====================*/
00068 
00069 void Parse_Specifics_File _ANSI_ARGS_((FILE *fp));
00070 void Parse_Specifics_File_v1 _ANSI_ARGS_((FILE *fp));
00071 void Parse_Specifics_File_v2 _ANSI_ARGS_((FILE *fp));
00072 FrameSpecList *MakeFslEntry _ANSI_ARGS_((void));
00073 void AddSlc _ANSI_ARGS_((FrameSpecList *c,int snum, int qs));
00074 Block_Specifics *AddBs _ANSI_ARGS_((FrameSpecList *c,int bnum, 
00075                                     boolean rel, int qs));
00076 FrameSpecList *MakeFslEntry _ANSI_ARGS_((void));
00077 #define my_upper(c) (((c>='a') && (c<='z')) ? (c-'a'+'A') : c)
00078 #define CvtType(x) ReallyCvt(my_upper(x))
00079 #define ReallyCvt(x) (x=='I' ? 1 : (x=='P')?2: ((x=='B')?3:-1))
00080 #define SkipToSpace(lp) while ((*lp != ' ') && (*lp != '\n') && (*lp != '\0')) lp++
00081 #define EndString(lp)  ((*lp == '\n') || (*lp == '\0'))
00082 
00083 /*=============================================================
00084  * SPEC FILE FORMAT (version 1):
00085 
00086 Specs files are processed with the c preprecoessor, so use C style comments
00087 and #defines if you wish.
00088 
00089 frames, blocks, and slices are numbered from 0.
00090 (sorry)
00091 
00092 In order by frame number, slice number, block number
00093 (if you skip slices it's fine).
00094 Can have specifics for any frame, block, or slice.
00095 Format:
00096 version N
00097   Specify the version of the specifics file format (this is 1)
00098 frame N T M
00099   Sets frame number N to type T and Qscale M
00100   (type T is I,B,P,other, other means unspec.  I recomend - )
00101 slice M Q
00102   Sets slice M (in frame N as defined by a previous frame command)
00103   to qscale Q
00104 block M Q
00105   Sets block M to qscale Q, in frame N previously specified.
00106 
00107 Unspecified frame types are set via the last I frame set, which is forced
00108 to act as the first I of the GOP.
00109 FORCE_ENCODE_LAST_FRAME overrides specifics on the final frame type.
00110 Note that Qscale changes in skipped blocks will be lost!
00111 
00112 Version 2:
00113 frames and slices are the same as above, but Q in blocks can be relative, i.e.
00114 +N or -N.  Clipping to 1..31 is done but sequences like
00115 block 1 2
00116 block 2 -3
00117 block 3 +3
00118 
00119 has undefined results (as present block 3 would be Qscale 2).
00120 
00121 In addition motion vectors can be specified:
00122 block M Q skip
00123   Says to skip the block  (not really an MV, but....)
00124 block M Q bi fx fy bx by
00125   Sets block M to quality Q.  It will be a bidirectional block.
00126   fx/fy is the forward (like a P frame) vector, bx/y is the back
00127 block M Q forw fx fy
00128 block M Q back bx by
00129   Single directional.
00130 
00131 All vectors are specified in HALF PIXEL fixed point units, i.e.
00132 3.5 pixels is 7
00133 To specify a vector but not touch the q factor, set Q to 0
00134 
00135 *=============================================================*/
00136 
00137 
00138 /*=============*
00139  * Local State *
00140  *=============*/
00141 
00142 static char version = -1;
00143 
00144 /*================================================================
00145  *
00146  *   Specifics_Init
00147  *
00148  *   Cpp's and reads in the specifics file.  Creates fsl data structure.
00149  *
00150  *   Returns: nothing
00151  * 
00152  *   Modifies: fsl, file specificsFile".cpp"
00153  *
00154  *================================================================
00155  */
00156 void Specifics_Init()
00157 {
00158   char command[1100];
00159   FILE *specificsFP;
00160   
00161   sprintf(command, "/bin/rm -f %s.cpp", specificsFile);
00162   system(command);
00163   sprintf(command, "%s -P %s %s %s.cpp",
00164           CPP_LOC, specificsDefines, specificsFile, specificsFile);
00165   system(command);
00166   strcat(specificsFile, ".cpp");
00167   if ((specificsFP = fopen(specificsFile, "r")) == NULL) {
00168     fprintf(stderr, "Error with specifics file, cannot open %s\n", specificsFile);
00169     exit(1);
00170   }
00171   printf("Specifics file: %s\n", specificsFile);
00172   Parse_Specifics_File(specificsFP);
00173   sprintf(command, "/bin/rm -f %s.cpp", specificsFile);
00174   system(command);
00175 
00176 }
00177 
00178 
00179 
00180 
00181 /*================================================================
00182  *
00183  *   Parse_Specifics_File
00184  *
00185  *   Read through the file passed in creating the fsl data structure
00186  *   There is a primary routine, and helpers for the specific versions.
00187  *
00188  *   Returns: Nothing
00189  *
00190  *   Modifies: fsl
00191  *
00192  *================================================================
00193  */
00194 void Parse_Specifics_File(fp)
00195 FILE *fp;
00196 {
00197   char line[1024], *lp;
00198   int vers;
00199 
00200   while ((fgets(line, 1023, fp)) != NULL) {
00201     lp = &line[0];
00202     while ((*lp == ' ') || (*lp == '\t')) lp++;
00203     if (( *lp == '#' ) || (*lp=='\n')) {
00204       continue;
00205     }
00206 
00207     switch (my_upper(*lp)) {
00208     case 'F': case 'S': case 'B':
00209       fprintf(stderr, "Must specify version at beginning of specifics file\n");
00210       exit(0);
00211       break;
00212     case 'V':
00213       lp += 7;
00214       if (1 != sscanf(lp, "%d", &vers)) {
00215         fprintf(stderr," Improper version line in specs file: %s\n", line);
00216       } else {
00217         switch (vers) {
00218         case 1:
00219           version = vers;
00220           Parse_Specifics_File_v1(fp);
00221           break;
00222         case 2:
00223           version = vers;
00224           Parse_Specifics_File_v2(fp);
00225           break;
00226         default:
00227           fprintf(stderr, "Improper version line in specs file: %s\n", line);
00228           fprintf(stderr, "\tSpecifics file will be IGNORED.\n");
00229           specificsOn = FALSE;
00230           return;
00231           break;
00232         }}
00233       break;
00234     default:
00235       fprintf(stderr, "Specifics file: What? *%s*\n", line);
00236       break;
00237     }}
00238   
00239 }
00240 
00241 /* Version 1 */
00242 void Parse_Specifics_File_v1(fp)
00243 FILE *fp;
00244 {
00245   char line[1024],*lp;
00246   FrameSpecList *current, *new;
00247   char typ; 
00248   int fnum,snum, bnum, qs, newqs;
00249   int num_scanned;
00250 
00251   fsl = MakeFslEntry();
00252   current = fsl;
00253 
00254   while ((fgets(line,1023, fp)) != NULL) {
00255     lp = &line[0];
00256     while ((*lp == ' ') || (*lp == '\t')) lp++;
00257     if (( *lp == '#' ) || (*lp=='\n')) {
00258       continue;
00259     }
00260 
00261     switch (my_upper(*lp)) {
00262     case 'F':
00263       lp += 6;
00264       sscanf(lp, "%d %c %d", &fnum, &typ, &qs);
00265       if (current->framenum != -1) {
00266         new=MakeFslEntry();
00267         current->next = new;
00268         current = new;
00269       }
00270       current->framenum = fnum;
00271       current->frametype = CvtType(typ);
00272       if (qs <= 0) qs = -1;
00273       current->qscale = qs;
00274       break;
00275     case 'S':
00276       lp += 6;
00277       sscanf(lp, "%d %d", &snum, &newqs);
00278       if (qs == newqs) break;
00279       qs = newqs;
00280       AddSlc(current, snum, qs);
00281       break;
00282     case 'B':
00283       lp += 6;
00284       num_scanned = sscanf(lp, "%d %d", &bnum, &newqs);
00285       if (qs == newqs) break;
00286       qs = newqs;
00287       AddBs(current, bnum, FALSE, qs);
00288       break;
00289     case 'V':
00290       fprintf(stderr, "Cannot specify version twice!  Taking first (%d)\n", version);
00291       break;
00292     default:
00293       fprintf(stderr," What? *%s*\n", line);
00294       break;
00295     }}
00296   
00297 }
00298 
00299 /* Version 2 */
00300 void Parse_Specifics_File_v2(fp)
00301 FILE *fp;
00302 {
00303   char line[1024], *lp;
00304   FrameSpecList *current, *new;
00305   char typ;
00306   int fnum, snum, bnum, qs, newqs;
00307   int num_scanned, fx=0, fy=0, sx=0, sy=0;
00308   char kind[100];
00309   Block_Specifics *new_blk;
00310   boolean relative;
00311 
00312   fsl = MakeFslEntry();
00313   current = fsl;
00314 
00315   while ((fgets(line,1023,fp))!=NULL) {
00316     lp = &line[0];
00317     while ((*lp == ' ') || (*lp == '\t')) lp++;
00318     if (( *lp == '#' ) || (*lp=='\n')) {
00319       continue;
00320     }
00321 
00322     switch (my_upper(*lp)) {
00323     case 'F':
00324       lp += 6;
00325       sscanf(lp,"%d %c %d", &fnum, &typ, &qs);
00326       new = MakeFslEntry();
00327       if (current->framenum != -1) {
00328         current->next = new;
00329         current = new;
00330       }
00331       current->framenum = fnum;
00332       current->frametype = CvtType(typ);
00333       if (qs <= 0) qs = -1;
00334       current->qscale = qs;
00335       break;
00336     case 'S':
00337       lp += 6;
00338       sscanf(lp,"%d %d", &snum, &newqs);
00339       if (qs == newqs) break;
00340       qs = newqs;
00341       AddSlc(current, snum, qs);
00342       break;
00343     case 'B':
00344       lp += 6;
00345       num_scanned = 0;
00346       bnum = atoi(lp);
00347       SkipToSpace(lp);
00348       while ((*lp != '-') && (*lp != '+') &&
00349              ((*lp < '0') || (*lp > '9'))) lp++;
00350       relative = ((*lp == '-') || (*lp == '+'));
00351       newqs = atoi(lp);
00352       SkipToSpace(lp);
00353       if (EndString(lp)) {
00354         num_scanned = 2;
00355       } else {
00356         num_scanned = 2+sscanf(lp, "%s %d %d %d %d", kind, &fx, &fy, &sx, &sy); 
00357       }
00358 
00359       qs = newqs;
00360       new_blk = AddBs(current, bnum, relative, qs);
00361       if (num_scanned > 2) {
00362         BlockMV *tmp;
00363         tmp = (BlockMV *) malloc(sizeof(BlockMV));
00364         switch (num_scanned) {
00365         case 7:
00366           tmp->typ = TYP_BOTH;
00367           tmp->fx = fx;
00368           tmp->fy = fy;
00369           tmp->bx = sx;
00370           tmp->by = sy;
00371           new_blk->mv = tmp;
00372           break;
00373         case 3:
00374           tmp->typ = TYP_SKIP;
00375           new_blk->mv = tmp;
00376           break;
00377         case 5:
00378           if (my_upper(kind[0]) == 'B') {
00379             tmp->typ = TYP_BACK;
00380             tmp->bx = fx;
00381             tmp->by = fy;
00382           } else {
00383             tmp->typ = TYP_FORW;
00384             tmp->fx = fx;
00385             tmp->fy = fy;
00386           }
00387           new_blk->mv = tmp;
00388           break;
00389         default:
00390           fprintf(stderr,
00391                   "Bug in specifics file!  Skipping short/long entry: %s\n",line);
00392           break;
00393         }
00394       } else {
00395         new_blk->mv = (BlockMV *) NULL;
00396       }
00397 
00398       break;
00399     case 'V':
00400       fprintf(stderr,
00401               "Cannot specify version twice!  Taking first (%d).\n",
00402               version);
00403       break;
00404     default:
00405       printf("What? *%s*\n",line);
00406       break;
00407     }}
00408   
00409 }
00410 
00411 
00412 
00413 
00414 /*=================================================================
00415  *
00416  *     MakeFslEntry
00417  *
00418  *     Makes a single entry in for the fsl linked list (makes a frame)
00419  *
00420  *     Returns: the new entry
00421  *
00422  *     Modifies: nothing
00423  *
00424  *=================================================================
00425  */
00426 FrameSpecList *MakeFslEntry()
00427 {
00428   FrameSpecList *fslp;
00429   fslp = (FrameSpecList *) malloc(sizeof(FrameSpecList));
00430   fslp->framenum = -1;
00431   fslp->slc = (Slice_Specifics *) NULL;
00432   fslp->bs = (Block_Specifics *) NULL;
00433   return fslp;
00434 }
00435 
00436 
00437 
00438 
00439 
00440 /*================================================================
00441  *
00442  *   AddSlc
00443  *
00444  *   Adds a slice to framespeclist c with values snum and qs
00445  *
00446  *   Returns: nothing
00447  *
00448  *   Modifies: fsl's structure
00449  *
00450  *================================================================
00451  */
00452 void AddSlc(c, snum, qs)
00453 FrameSpecList *c;
00454 int snum,qs;
00455 {
00456   Slice_Specifics *new;
00457   static Slice_Specifics *last;
00458 
00459   new = (Slice_Specifics *) malloc(sizeof(Slice_Specifics));
00460   new->num = snum;
00461   new->qscale = qs;
00462   new->next = (Slice_Specifics *)NULL;
00463   if (c->slc == (Slice_Specifics *)NULL) {
00464     last = new;
00465     c->slc = new;
00466   } else {
00467     last->next = new;
00468     last = new;
00469   }
00470 }
00471 
00472 
00473 
00474 
00475 
00476 /*================================================================
00477  *
00478  *   AddBs
00479  *
00480  *   Adds a sliceblock to framespeclist c with values bnum and qs
00481  *
00482  *   Returns: pointer to the new block spec
00483  *
00484  *   Modifies: fsl's structure
00485  *
00486  *================================================================
00487  */
00488 Block_Specifics *AddBs(c,bnum,rel,qs)
00489 FrameSpecList *c;
00490 boolean rel;
00491 int bnum,qs;
00492 {
00493   Block_Specifics *new;
00494   static Block_Specifics *last;
00495 
00496   new = (Block_Specifics *) malloc(sizeof(Block_Specifics));
00497   new->num = bnum;
00498   if (qs == 0) rel = TRUE;
00499   new->relative = rel;
00500   new->qscale = qs;
00501   new->next = (Block_Specifics *)NULL;
00502   new->mv = (BlockMV *) NULL;
00503   if (c->bs == (Block_Specifics *)NULL) {
00504     last = new;
00505     c->bs = new;
00506   } else {
00507     last->next = new;
00508     last = new;
00509   }
00510   return new;
00511 }
00512 
00513 
00514 
00515 
00516 
00517 
00518 /*================================================================
00519  *
00520  *  SpecLookup
00521  *
00522  *  Find out if there is any changes to be made for the qscale
00523  *  at entry fn.num (which is of type typ).  Sets info to point to
00524  *  motion vector info (if any), else NULL.
00525  *
00526  *  Returns: new qscale or -1
00527  *
00528  *  Modifies: *info (well, internal cache can change)
00529  *
00530  *================================================================
00531  */
00532 
00533 int SpecLookup(fn,typ,num,info,start_qs)
00534 int fn,typ,num;
00535 BlockMV **info;
00536 int start_qs;
00537 {
00538   static FrameSpecList *last = (FrameSpecList *) NULL;
00539   Slice_Specifics *sptr=(Slice_Specifics *) NULL;
00540   Block_Specifics *bptr=(Block_Specifics *) NULL;
00541   FrameSpecList *tmp;
00542   boolean found_it;
00543   static int leftovers = 0;  /* Used in case of forced movement into 1..31 range */
00544   
00545   *info = (BlockMV * )NULL;
00546   if (last == (FrameSpecList *) NULL){
00547     /* No cache, try to find number fn */
00548     tmp = fsl;
00549     found_it = FALSE;
00550     while (tmp != (FrameSpecList *) NULL) {
00551       if (tmp->framenum == fn) {
00552         found_it = TRUE;
00553         break;
00554       } else tmp = tmp->next;
00555     }
00556     if (!found_it) return -1;
00557     last=tmp;
00558   } else {
00559     if (last->framenum != fn) { /* cache miss! */
00560       /* first check if it is next */
00561       if ((last->next != (FrameSpecList *) NULL) && 
00562           (last->next->framenum == fn)) {
00563         last = last->next;
00564       } else {
00565         /* if not next, check from the start.
00566            (this allows people to put frames out of order,even
00567            though the spec doesnt allow it.) */
00568         tmp = fsl;
00569         found_it = FALSE;
00570         while (tmp != (FrameSpecList *) NULL) {
00571           if (tmp->framenum==fn) {found_it = TRUE; break;}
00572           tmp = tmp->next;
00573         }
00574         if (!found_it) return -1;
00575         last = tmp;
00576       }
00577     }
00578   }
00579   /* neither of these should ever be true, unless there is a bug above */
00580   if (last == (FrameSpecList *) NULL) {
00581     fprintf(stderr, "PROGRAMMER ERROR: last is null!\n");
00582     return -1;
00583   }
00584   if (last->framenum!=fn) {
00585     fprintf(stderr, "PROGRAMMER ERROR: last has wrong number!\n");
00586     return -1; /* no data on it */
00587   }
00588   
00589   switch(typ) {
00590   case 0: /* Frame: num is ignored */
00591     leftovers = 0;
00592 #ifdef BLEAH
00593     printf("QSchange frame %d to %d\n", fn, last->qscale);
00594 #endif 
00595     return last->qscale;
00596     break;
00597 
00598   case 1: /* Slice */
00599     leftovers = 0;
00600     /* So, any data on slices? */
00601     if (last->slc == (Slice_Specifics *) NULL) return -1;
00602     for (sptr = last->slc; sptr != (Slice_Specifics *) NULL; sptr = sptr->next) {
00603       if (sptr->num == num) {
00604 #ifdef BLEAH
00605         printf("QSchange Slice %d.%d to %d\n", fn, num, sptr->qscale);
00606 #endif
00607         if (sptr->qscale == 0) return -1;
00608         return sptr->qscale;
00609       }
00610     }
00611     break;
00612 
00613   case 2:  /* block */
00614     /* So, any data on blocks? */
00615     if (last->bs == (Block_Specifics *) NULL) {
00616       return -1;
00617     }
00618     for (bptr=last->bs; bptr != (Block_Specifics *) NULL; bptr=bptr->next) {
00619       if (bptr->num == num) {
00620         int new_one;
00621 #ifdef BLEAH
00622         printf("QSchange Block %d.%d to %d\n", fn, num, bptr->qscale);
00623 #endif
00624         *info = bptr->mv;
00625         if (bptr->relative) {
00626           if (bptr->qscale == 0) {
00627             /* Do nothing! */
00628             new_one = start_qs;
00629           } else {
00630             new_one = start_qs + bptr->qscale + leftovers;
00631             if (new_one < 1) {
00632               leftovers = new_one - 1;
00633               new_one = 1;
00634             } else if (new_one > 31) {
00635               leftovers = new_one - 31;
00636               new_one = 31;
00637             } else leftovers = 0;
00638           }}
00639         else {
00640           new_one = bptr->qscale;
00641           leftovers = 0;
00642         }
00643         return new_one;
00644       }
00645     }
00646     break;
00647   default:
00648     fprintf(stderr, "PROGRAMMER ERROR:  reached unreachable code in SpecLookup\n");
00649     break;
00650   }
00651   /* no luck */
00652   return -1;
00653 }
00654      
00655     
00656 /*================================================================
00657  *
00658  *  SpecTypeLookup
00659  *
00660  *  Find out if there is any changes to be made for the type of frame
00661  *  at frame fn.
00662  *
00663  *  Returns: new type or -1 (unspecified)
00664  *
00665  *================================================================
00666  */
00667 int SpecTypeLookup(fn)
00668 int fn;
00669 {
00670   FrameSpecList *tmp;
00671 
00672   /* try to find number fn */
00673   tmp = fsl;
00674   do {
00675     if (tmp->framenum == fn) break;
00676     else tmp = tmp->next;
00677   } while (tmp != (FrameSpecList *) NULL);
00678   if (tmp == (FrameSpecList *) NULL) {
00679 #ifdef BLEAH
00680     printf("Frame %d type not specified\n", fn);
00681 #endif
00682     return -1;
00683   }
00684 #ifdef BLEAH
00685   printf("Frame %d type set to %d\n", fn, tmp->frametype);
00686 #endif
00687   return tmp->frametype;
00688 }
 

Powered by Plone

This site conforms to the following standards: