home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / indispensabili / grafica / amipeg_1.1 / src / main.c < prev    next >
C/C++ Source or Header  |  1998-01-27  |  17KB  |  683 lines

  1. /*
  2.  *  This is the main part
  3.  */
  4.  
  5. #include <intuition/screens.h>
  6. #include <proto/dos.h>
  7. #include <proto/exec.h>
  8. #include <string.h>
  9.  
  10. #include "video.h"
  11. #include "proto.h"
  12. #include <sys/types.h>
  13. #include <signal.h>
  14.  
  15. #include <proto/timer.h>
  16. #include <devices/timer.h>
  17.  
  18. #include <proto/asyncio.h>
  19. #include <proto/asl.h>
  20.  
  21. #include "util.h"
  22.  
  23. #define HELP_TEXT "FILES\t- filename(s) of MPEG stream(s). Supports wildcards.\n\
  24. NOB\t- ignore and not display any B frames.\n\
  25. NOP\t- ignore and not display any P frames.\n\
  26. LOOP\t- makes the player loop back to the beginning after reaching the end.\n\
  27. EACHSTAT- causes statistics to be displayed after each frame.\n\
  28. \t  Only valid when compiled with -DANALYSIS\n\
  29. NODISPLAY- dithers, but does not display, usually used for\n\
  30. \t  testing and timing purposes.\n\
  31. QUIET\t- supresses printing of frame numbers, timing information,\n\
  32. \t  and most error messages.\n\
  33. DITHER\t- selects from a variety of dither options.\n\
  34. \t  The possible values are:\n\
  35. \t\tcolor\n\
  36. \t\thiresham\n\
  37. \t\tham6\n\
  38. \t\tcybergfx\n\
  39. \t\tcybergfxgray\n\
  40. \t\tgray\n\
  41. \t\tvlayer\n\
  42. \t\tvlayergray\n\
  43. \t\tpivpip\n\
  44. \t\tnone\n\
  45. PUBSCREEN- open window on selected \"deep\" public screen. Only valid with\n\
  46. \t  DITHER cybergfx or cybergfxgray. Use with \"DEFAULT\" to open on current\n\
  47. \t  default public screen. When used with vlayer(gray), may name any\n\
  48. \t  public screen, as long as it is the screen of a gfx-board compatible\n\
  49. \t  with cgxvideo.library.\n\
  50. MODEID\t- select modeid for screen to open and play on.\n\
  51. FRAMERATE- speed in frames per second. (0 - as fast as possible).\n\
  52. BUFFER\t- size of the I/O buffer (default - 65536).\n\
  53. FULL\t- open full-screen, borderless window. Most useful with vlayer(gray).\n"
  54.  
  55. #define TEMPLATE "FILES/M,NOB/S,NOP/S,LOOP/S,EACHSTAT/S,ND=NODISPLAY/S,QUIET/S,DITHER/K,PS=PUBSCREEN/K,MODEID/K,FRAMERATE=FPS/K,BUFFER=BUF/K,FULL/S"
  56.  
  57. #define OPT_FILES           0
  58. #define OPT_NOB                1
  59. #define OPT_NOP                2
  60. #define OPT_LOOP            3
  61. #define OPT_EACHSTAT        4
  62. #define OPT_NODISPLAY       5
  63. #define OPT_QUIET           6
  64. #define OPT_DITHER          7
  65. #define    OPT_PUBSCREEN       8
  66. #define OPT_MODEID          9
  67. #define OPT_FPS             10
  68. #define OPT_BUFFER          11
  69. #define OPT_FULL                        12
  70. #define OPT_COUNT           13
  71.  
  72. #define AP_BUFFSIZE         240
  73.  
  74. struct Files                /* to keep the names from MatchFirst() etc or ASL req... */
  75. {
  76.   unsigned char *name;
  77.   struct Files *next;
  78. };
  79.  
  80. const char *dither_names = "ham6\1color\1hiresham\1ham6\1cybergfx\1cybergfxgray\1vlayer\1vlayergray\1pivpip\1none";
  81. /*                          01234 56789  1113151719 2123 2527293133 353739414345 47495153 5557596163 65676971
  82.    got it? :)                          10 12141618 202224 26283032 34363840424446 485052 545658606264 666870 72
  83. */
  84.  
  85. char animname[1024];
  86. char pubscreen_name[MAXPUBSCREENNAME + 1];
  87. char *pubname_ptr;
  88.  
  89. /* Declaration of global variable to hold dither info. */
  90.  
  91. int ditherType;
  92.  
  93. /* size of the io buffer */
  94.  
  95. int buf_length = 65536;
  96.  
  97. /* Global file pointer to incoming data. */
  98. struct AsyncFile *input;
  99.  
  100. /* End of File flag. */
  101. int EOF_flag = 0;
  102.  
  103. /* Loop flag. */
  104. int loopFlag = 0;
  105.  
  106. /* Quiet flag. */
  107. int quietFlag = 0;
  108.  
  109. /* full screen output */
  110. int fullFlag = 0;
  111.  
  112. /* User wants to quit? */
  113. int doneFlag = 0;
  114.  
  115. /* how many files to show? */
  116. int number_of_files = 0;
  117.  
  118. /* Display image on screen? */
  119. int noDisplayFlag = 0;
  120.  
  121. /* Setjmp/Longjmp env. */
  122. jmp_buf env;
  123.  
  124. /* HAM6 rendering / HAM hires flag */
  125. extern int ham6, lores;
  126.  
  127. /* modeid of CyberGraphX screen */
  128. unsigned long modeid = 0xffffffff;
  129.  
  130. /* are we going to play on the Public Screen? */
  131. int cyber_pub = 0;
  132.  
  133. /* Framerate, -1: specified in stream (default)
  134.                0: as fast as possible
  135.                N (N>0): N frames/sec  
  136.                */
  137. int framerate = -1;
  138.  
  139. /* these are for timer.device */
  140. struct Library *TimerBase;
  141. struct MsgPort *TimerMP;           /* Message port pointer */
  142. struct timerequest *TimerIO;  /* I/O structure pointer */
  143.  
  144. /* Method of picture conversion */
  145. void (*DoDitherImage)(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
  146.               unsigned char *disp, int h, int w);
  147.  
  148. static char version[]="$VER: aMiPEG 1.1 " __AMIGADATE__;
  149.  
  150.  
  151. /*
  152.  *--------------------------------------------------------------
  153.  *
  154.  * int_handler --
  155.  *
  156.  *    Handles Cntl-C interupts..
  157.  *
  158.  * Results:
  159.  *    None.
  160.  *
  161.  * Side effects:
  162.  *    None.
  163.  *
  164.  *--------------------------------------------------------------
  165.  */
  166. void int_handler(int dummy)
  167. {
  168.     if (!quietFlag) fprintf(stderr, "Interrupted!\n");
  169.     if (curVidStream) DestroyVidStream(curVidStream);
  170.  
  171.     if(input)
  172.     {
  173.         CloseAsync(input);
  174.         input = NULL;
  175.     }
  176.  
  177.     exit(1);
  178. }
  179.  
  180.  
  181. /*
  182.  *--------------------------------------------------------------
  183.  *
  184.  * init_timer --
  185.  *
  186.  *    Prepare timer.device and IORequest for later use
  187.  *
  188.  * Results:
  189.  *    None.
  190.  *
  191.  * Side effects:
  192.  *    None.
  193.  *
  194.  *--------------------------------------------------------------
  195.  */
  196.  
  197. void init_timer(void)
  198. {
  199.     /* Create port for timer device communications */
  200.     if(TimerMP = CreatePort(NULL, 0))
  201.         /* Create message block for device IO */
  202.         if(TimerIO = (struct timerequest *)CreateExtIO(TimerMP, sizeof(struct timerequest)))
  203.  
  204.             /* Open the timer device with UNIT_MICROHZ */
  205.             if(!OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)TimerIO, 0))
  206.             {
  207.                 TimerBase = (struct Library *)TimerIO->tr_node.io_Device;
  208.                 TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  209.                 return;
  210.             }
  211.             else
  212.                 fprintf(stderr, "Error: Can't open Timer.device\n");
  213.         else
  214.             fprintf(stderr, "Error: Can't create IO request\n");
  215.     else
  216.         fprintf(stderr, "Error: Can't create port\n");
  217.  
  218.     exit(1);
  219. }
  220. /*
  221.  *--------------------------------------------------------------
  222.  *
  223.  * close_timer --
  224.  *
  225.  *    Close timer.device, remove IORequest and message port
  226.  *
  227.  * Results:
  228.  *    None.
  229.  *
  230.  * Side effects:
  231.  *    None.
  232.  *
  233.  *--------------------------------------------------------------
  234.  */
  235.  
  236. void close_timer(void)
  237. {
  238.     if(TimerBase)
  239.         CloseDevice((struct IORequest *)TimerIO);  /* Close Timer device */
  240.  
  241.     if(TimerIO)
  242.         DeleteExtIO((struct IORequest *)TimerIO);
  243.  
  244.     if(TimerMP)
  245.         DeletePort(TimerMP);
  246. }
  247.  
  248. /*
  249.  *--------------------------------------------------------------
  250.  *
  251.  * main --
  252.  *
  253.  *    Parses command line, starts decoding and displaying.
  254.  *
  255.  * Results:
  256.  *    None.
  257.  *
  258.  * Side effects:
  259.  *    None.
  260.  *
  261.  *--------------------------------------------------------------
  262.  */
  263.  
  264. void main(int argc, char **argv)
  265. {
  266.   static VidStream *theStream;
  267.   extern int lores;
  268.   LONG opts[OPT_COUNT];
  269.   struct RDArgs *rdargs;
  270.   struct FileRequester *fr;
  271.   struct Library *AslBase;
  272.   unsigned char **fnames;
  273.   struct AnchorPath *ap;
  274.   struct Files *namestuff=NULL;
  275.   struct Files *p;
  276.   struct Files *q;
  277.   int i;
  278.   LONG err;
  279.  
  280.   ditherType = FULL_COLOR_DITHER;
  281.   noDisplayFlag = 0;
  282.  
  283.     memset(opts, 0, sizeof(opts));
  284.  
  285.     if(rdargs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
  286.     {
  287.         rdargs->RDA_ExtHelp = HELP_TEXT;
  288.  
  289.         if(rdargs = ReadArgs(TEMPLATE, opts, rdargs))
  290.         {
  291.             if(opts[OPT_NOP])
  292.           TogglePFlag();
  293.  
  294.             if(opts[OPT_NOB])
  295.           ToggleBFlag();
  296.  
  297.             if(opts[OPT_DITHER])
  298.             {
  299.                 switch(strstr(dither_names, strlwr((char *)opts[OPT_DITHER])) - dither_names)
  300.                 {
  301.                     case 5:        /* color */
  302.                         ditherType = FULL_COLOR_DITHER;
  303.                         break;
  304.  
  305.                     case 11:    /* hiresham */
  306.                         ditherType = FULL_COLOR_DITHER;
  307.                         lores = FALSE;
  308.                         break;
  309.  
  310.                     case 0:    /* ham6 */
  311.                         ditherType = FULL_COLOR_DITHER;
  312.                         ham6 = TRUE;
  313.                         break;
  314.  
  315.                     case 25:    /* cybergfx */
  316.                         ditherType = CYBERGFX_DITHER;
  317.                         break;
  318.  
  319.                     case 34:    /* cybergfxgray */
  320.                         ditherType = CYBERGFXGRAY_DITHER;
  321.                         break;
  322.  
  323.                     case 42:    /* gray */
  324.                         ditherType = GRAY_DITHER;
  325.                         break;
  326.  
  327.                     case 47:
  328.                         ditherType = CYBERGFXVLAYER_DITHER;
  329.                         break;
  330.  
  331.                     case 54:
  332.                         ditherType = CYBERGFXVLAYERGRAY_DITHER;
  333.                         break;
  334.  
  335.                     case 65:
  336.                         ditherType = PIV_DITHER;
  337.                         break;
  338.  
  339.                     case 72:
  340.                         ditherType = NO_DITHER;
  341.                         break;
  342.  
  343.                     default:
  344.                         fprintf(stderr, "You should specify legal dither name after DITHER keyword.\n");
  345.                         FreeArgs(rdargs);
  346.                         exit(10);
  347.                 }
  348.             }
  349.  
  350.             if(opts[OPT_EACHSTAT])
  351. #ifdef ANALYSIS
  352.                 showEachFlag = 1;
  353. #else
  354.             {
  355.                 fprintf(stderr, "To use EACHSTAT, recompile with DEFINE ANALYSIS in CFLAGS\n");
  356.                 exit(1);
  357.             }
  358. #endif
  359.  
  360.             if(opts[OPT_QUIET])
  361.                 quietFlag = 1;
  362.  
  363.             if(opts[OPT_LOOP])
  364.                 loopFlag = 1;
  365.  
  366.             if(opts[OPT_NODISPLAY])
  367.                 noDisplayFlag = 1;
  368.  
  369.             if(opts[OPT_PUBSCREEN])
  370.             {
  371.                 if(!stricmp("default", (char *)opts[OPT_PUBSCREEN]))
  372.                     pubname_ptr = NULL;
  373.                 else
  374.                 {
  375.                     strcpy(pubscreen_name, (char *)opts[OPT_PUBSCREEN]);
  376.                     pubname_ptr = pubscreen_name;
  377.                 }
  378.  
  379.                 cyber_pub = 1;
  380.             }
  381.  
  382.             if(opts[OPT_MODEID])
  383.                 if(sscanf((char *)opts[OPT_MODEID], "%x", &modeid) != 1)
  384.                 {
  385.                     fprintf(stderr, "ModeID should be an hexadecimal value.\n");
  386.                     FreeArgs(rdargs);
  387.                     exit(10);
  388.                 }
  389.  
  390.             if(opts[OPT_FPS])
  391.                 if(sscanf((char *)opts[OPT_FPS], "%d", &framerate) != 1)
  392.                 {
  393.                     fprintf(stderr, "You should specify a number after FRAMERATE keyword.\n");
  394.                     FreeArgs(rdargs);
  395.                     exit(10);
  396.                 }
  397.  
  398.             if(opts[OPT_BUFFER])
  399.                 if(sscanf((char *)opts[OPT_BUFFER], "%d", &buf_length) != 1)
  400.                 {
  401.                     fprintf(stderr, "You should specify a number after BUFFER keyword.\n");
  402.                     FreeArgs(rdargs);
  403.                     exit(10);
  404.                 }
  405.  
  406.             if(opts[OPT_FULL])
  407.                 fullFlag = 1;
  408.  
  409.             fnames = (char **) opts[OPT_FILES];
  410.  
  411.             if(fnames!=NULL)
  412.             {
  413.  
  414.               if ((ap = malloc (sizeof (struct AnchorPath) + AP_BUFFSIZE)))
  415.               {
  416.                 memset(ap, 0, sizeof(struct AnchorPath) + AP_BUFFSIZE);
  417.                 ap->ap_Strlen = AP_BUFFSIZE;
  418.         
  419.                 while (*fnames != NULL)
  420.                 {
  421.  
  422.                   for (err = MatchFirst (*fnames, ap); (err == 0); err = MatchNext (ap))
  423.                   {
  424.                       number_of_files++;
  425.  
  426.                     if ((q = malloc (sizeof (struct Files))) && (q->name=malloc(AP_BUFFSIZE)))
  427.                     {
  428.                       struct Files *old_pointer = NULL;
  429.  
  430.                                             if(ap->ap_Buf[0])                     // dirty hack for PIPE: stuff
  431.                                               strcpy (q->name, ap->ap_Buf);
  432.                                             else
  433.                                               strcpy (q->name, *fnames);
  434.  
  435.                       p=namestuff;
  436.  
  437.                       if(p==NULL)
  438.                       { 
  439.                          namestuff=q;
  440.                          q->next = NULL;
  441.                       }
  442.                       else    
  443.                       {
  444.  
  445.                         /* crappy"sort" :) O(n^2) at worst */
  446.  
  447.                         /* Move slowly down the list and try to fit in the structure: */
  448.                         while (p && stricmp (p->name, q->name) <= 0)
  449.                         {
  450.                            old_pointer = p;
  451.                            p = p->next;
  452.                         }
  453.  
  454.                         if (p)
  455.                         {
  456.                            if (old_pointer)
  457.                            {
  458.                               q->next = old_pointer->next;
  459.                               old_pointer->next = q;
  460.                            }
  461.                            else
  462.                            {
  463.                               q->next = namestuff;
  464.                               namestuff = q;
  465.                            }
  466.                         }
  467.                         else
  468.                         {
  469.                            old_pointer->next=q;
  470.                            q->next = NULL;
  471.                         }
  472.                       }
  473.                     }
  474.                   }
  475.                   if(err==ERROR_OBJECT_NOT_FOUND && !quietFlag)
  476.                     printf("Couldn't show '%s': object not found\n", *fnames);
  477.                   MatchEnd (ap);
  478.                   fnames++;
  479.                 }
  480.                 free(ap);
  481.               }
  482.             }
  483.             else
  484.             {
  485.               if ((AslBase = OpenLibrary ("asl.library", 37)) != NULL)
  486.               {
  487.  
  488.                 if ((fr = (struct FileRequester *) AllocAslRequestTags (ASL_FileRequest,
  489.                               ASLFR_TitleText, (ULONG) "Select files to play",
  490.                                        ASLFR_InitialPattern, (ULONG) "#?.mpg",
  491.                               (AslBase->lib_Version < 38) ? TAG_DONE :
  492.                                                     ASLFR_DoMultiSelect, TRUE,
  493.                                                        ASLFR_DoPatterns, TRUE,
  494.                                                                    TAG_DONE)))
  495.                 {
  496.                    if (AslRequest (fr, NULL))
  497.                    {
  498.                      for (i = (fr->fr_NumArgs)-1; i>=0 ; i--)
  499.                      {
  500.                                                 number_of_files++;
  501.  
  502.                        if ((q = malloc (sizeof (struct Files))) && (q->name=malloc(AP_BUFFSIZE)))
  503.                        {
  504.                           strcpy (q->name, fr->fr_Drawer);
  505.                           AddPart (q->name, fr->fr_ArgList[i].wa_Name, AP_BUFFSIZE);
  506.  
  507.                           p=namestuff;
  508.                           if(p==NULL)
  509.                           {
  510.                             namestuff=q;
  511.                             q->next=NULL;
  512.                           }
  513.                           else
  514.                           {
  515.                             q->next=p;
  516.                             namestuff=q;
  517.                           }
  518.                        }
  519.                      }
  520.                    }
  521.                    FreeAslRequest(fr);
  522.                 }
  523.                 else
  524.                 {
  525.                   printf ("Can't allocate file requester.\n");
  526.                   CloseLibrary(AslBase);
  527.                   FreeArgs(rdargs);
  528.                   return;
  529.                 }
  530.                 CloseLibrary(AslBase);
  531.               }
  532.               else
  533.               {
  534.                 fprintf(stderr, "Error opening asl.library V37\n");
  535.                 FreeArgs(rdargs);
  536.                 return;
  537.               }
  538.             }
  539.  
  540.               p=namestuff;
  541.         
  542.               if(p!=NULL)
  543.               {
  544.                 signal(SIGINT, int_handler);
  545.  
  546.                 init_tables();
  547.                 init_timer();
  548.  
  549.                 switch (ditherType)
  550.                 {
  551.                     case PIV_DITHER:
  552.                         CheckPIV();
  553.                         InitColorDither();
  554.                         modeid = InitP96Display(modeid);
  555.                         HAM8_draw = (void (*)(void *, int, int)) DrawP96Image;
  556.                         DoDitherImage = ColorDitherImage_VideoLayerYCbCr;
  557.                         
  558.                         break;
  559.  
  560.                     case CYBERGFXVLAYERGRAY_DITHER:
  561.                         InitColorDither();
  562.                         modeid = InitCyberGfxDisplay(modeid);
  563.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  564.                         DoDitherImage = ColorDitherImage_VideoLayerGray;
  565.                         
  566.                         break;
  567.  
  568.                     case CYBERGFXVLAYER_DITHER:
  569.                         InitColorDither();
  570.                         modeid = InitCyberGfxDisplay(modeid);
  571.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  572.                         DoDitherImage = ColorDitherImage_VideoLayerYCbCr;
  573.                         
  574.                         break;
  575.  
  576.                     case CYBERGFX_DITHER:
  577.                         InitColorDither();
  578.                         modeid = InitCyberGfxDisplay(modeid);
  579.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  580.                         DoDitherImage = ColorDitherImage_RGB;
  581.                         break;
  582.  
  583.                     case CYBERGFXGRAY_DITHER:
  584.                         InitColorDither();
  585.                         modeid = InitCyberGfxDisplay(modeid);
  586.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  587.                         DoDitherImage = NoDitherImage;
  588.                         break;
  589.  
  590.                     case GRAY_DITHER:
  591.                         InitColorDither();
  592.                         modeid = InitGrayDisplay(modeid);
  593.                         HAM8_draw = (void (*)(void *, int, int)) DrawGrayImage;
  594.                         DoDitherImage = NoDitherImage;
  595.                         break;
  596.  
  597.                     case FULL_COLOR_DITHER:
  598.                         InitColorDither();
  599.                         InitColorDisplay();
  600.                         break;
  601.  
  602.                     case NO_DITHER:
  603.                         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  604.                         DoDitherImage = NoDitherImage;
  605.                         break;
  606.                 }
  607.               }
  608.  
  609. /*
  610.  *  The new restart handling has not been checked out very closely with changing
  611.  *  (non)intra scale matrixes!
  612.  */
  613.  
  614.               while(p!=NULL && doneFlag != DONE_REALLY)
  615.               {
  616.                   if(number_of_files == 1 && doneFlag == DONE_NOT_REALLY)
  617.                       break;
  618.  
  619.                                 while(p!=NULL && !(input = OpenAsync(p->name, MODE_READ, buf_length)))
  620.                 {
  621.                                     fprintf(stderr, "Could not open file %s\n", p->name);
  622.                                     p=p->next;
  623.                 }
  624.  
  625.                 if(p==NULL) break;
  626.                 if(!quietFlag) printf("file: %s\n", p->name);
  627.                 strcpy(animname, p->name);
  628.                 p=p->next;
  629.  
  630.                 theStream = NewVidStream(buf_length);
  631.  
  632.                 mpegInitVidRsrc();
  633.  
  634.                 EOF_flag=0;
  635.                 sys_layer=-1;
  636.                 totNumFrames=0;
  637.  
  638.                 realTimeStart = ReadSysClock();
  639.  
  640.                 if (setjmp(env) == 0)
  641.                   while (mpegVidRsrc(0, theStream));
  642.  
  643.                 if(input)
  644.                 {
  645.                     CloseAsync(input);
  646.                     input = NULL;
  647.                 }
  648.  
  649.                 if(p==NULL && loopFlag)
  650.                     p=namestuff;
  651.  
  652.               }
  653.  
  654.               p=namestuff;
  655.               while(p)
  656.               {
  657.                   free(p->name);
  658.                   q=p;
  659.                   p=p->next;
  660.                   free(q);
  661.               }
  662.  
  663.         FreeArgs(rdargs);
  664.         }
  665.  
  666.         FreeDosObject(DOS_RDARGS, rdargs);
  667.     }
  668.     else
  669.     {
  670.         PrintFault(IoErr(), argv[0]);
  671.         exit(10);
  672.     }
  673. }
  674.     
  675.  
  676. /*
  677.  *  Dummy display method
  678.  *
  679.  */
  680. void NoDitherImage(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
  681.            unsigned char *disp, int h, int w)
  682. {}
  683.