home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / opus / v5 / amipeg / source / main.c < prev    next >
C/C++ Source or Header  |  1977-12-31  |  12KB  |  556 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.  
  9. #include "video.h"
  10. #include "proto.h"
  11. #include <sys/types.h>
  12. #include <signal.h>
  13.  
  14. #include <proto/timer.h>
  15. #include <devices/timer.h>
  16.  
  17. #define ASIO_REGARGS
  18. #include <clib/asyncio_protos.h>
  19.  
  20. #include "util.h"
  21.  
  22. #define HELP_TEXT "NOB\t- ignore and not display any B frames.\n\
  23. NOP\t- ignore and not display any P frames.\n\
  24. LOOP\t- makes the player loop back to the beginning after reaching the end.\n\
  25. EACHSTAT- causes statistics to be displayed after each frame.\n\
  26. \t  Only valid when compiled with -DANALYSIS\n\
  27. NODISPLAY- dithers, but does not display, usually used for\n\
  28. \t  testing and timing purposes.\n\
  29. QUIET\t- supresses printing of frame numbers, timing information,\n\
  30. \t  and most error messages.\n\
  31. DITHER\t- selects from a variety of dither options.\n\
  32. \t  The possible values are:\n\
  33. \t\tcolor\n\
  34. \t\thiresham\n\
  35. \t\tham6\n\
  36. \t\tcybergfx\n\
  37. \t\tcybergfxgray\n\
  38. \t\tgray\n\
  39. \t\tnone\n\
  40. PUBSCREEN- open window on selected \"deep\" public screen. Only valid\n\
  41. \t  with DITHER cybergfx or cybergfxgray. Use with \"DEFAULT\" to open\n\
  42. \t  on current default public screen.\n\
  43. MODEID\t- select modeid for screen to open and play on.\n\
  44. FRAMERATE- speed in frames per second. (0 - as fast as possible).\n\
  45. BUFFER\t- size of the io buffer (default - 65536).\n\
  46. FILE\t- filename of MPEG stream.\n"
  47.  
  48. #define TEMPLATE "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,FILE/A"
  49.  
  50. #define OPT_NOB                0
  51. #define OPT_NOP                1
  52. #define OPT_LOOP            2
  53. #define OPT_EACHSTAT    3
  54. #define OPT_NODISPLAY    4
  55. #define OPT_QUIET            5
  56. #define OPT_DITHER        6
  57. #define    OPT_PUBSCREEN    7
  58. #define OPT_MODEID        8
  59. #define OPT_FPS                9
  60. #define OPT_BUFFER        10
  61. #define OPT_FILE            11
  62. #define OPT_COUNT            12
  63.  
  64.  
  65. const char *dither_names = "ham6\1color\1hiresham\1ham6\1cybergfx\1cybergfxgray\1gray\1none";
  66. /*                          01234 56789  1113151719 2123 2527293133 353739414345 474951 53
  67.    got it? :)                          10 12141618 202224 26283032 34363840424446 4850 525456
  68. */
  69.  
  70. char animname[1024];
  71. char pubscreen_name[MAXPUBSCREENNAME + 1];
  72. char *pubname_ptr;
  73.  
  74. /* Declaration of global variable to hold dither info. */
  75.  
  76. int ditherType;
  77.  
  78. /* size of the io buffer */
  79.  
  80. int buf_length = 65536;
  81.  
  82. /* Global file pointer to incoming data. */
  83. struct AsyncFile *input;
  84.  
  85. /* End of File flag. */
  86. static int EOF_flag = 0;
  87.  
  88. /* Loop flag. */
  89. int loopFlag = 0;
  90.  
  91. /* Quiet flag. */
  92. int quietFlag = 0;
  93.  
  94. /* Display image on screen? */
  95. int noDisplayFlag = 0;
  96.  
  97. /* Setjmp/Longjmp env. */
  98. jmp_buf env;
  99.  
  100. /* HAM6 rendering / HAM hires flag */
  101. extern int ham6, lores;
  102.  
  103. /* modeid of CyberGraphX screen */
  104. unsigned long modeid = 0xffffffff;
  105.  
  106. /* are we going to play on the Public Screen? */
  107. int cyber_pub = 0;
  108.  
  109. /* Framerate, -1: specified in stream (default)
  110.                0: as fast as possible
  111.                N (N>0): N frames/sec  
  112.                */
  113. int framerate = -1;
  114.  
  115. /* these are for timer.device */
  116. struct Library *TimerBase;
  117. struct MsgPort *TimerMP;           /* Message port pointer */
  118. struct timerequest *TimerIO;  /* I/O structure pointer */
  119.  
  120. /* Method of picture conversion */
  121. void (*DoDitherImage)(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
  122.               unsigned char *disp, int h, int w);
  123.  
  124. static char version[]="$VER: aMiPEG 0.7 (compiled on " __DATE__ ", " __TIME__ ")\n";
  125.  
  126. /*
  127.  *--------------------------------------------------------------
  128.  *
  129.  * get_more_data --
  130.  *
  131.  *    Called by correct_underflow in bit parsing utilities to
  132.  *      read in more data.
  133.  *
  134.  * Results:
  135.  *    Input buffer updated, buffer length updated.
  136.  *      Returns 1 if data read, 0 if EOF, -1 if error.
  137.  *
  138.  * Side effects:
  139.  *      None.
  140.  *
  141.  *--------------------------------------------------------------
  142.  */
  143.  
  144. int get_more_data(unsigned int *buf_start, int max_length, int *length_ptr, unsigned int **buf_ptr)
  145. {
  146.   
  147.   int length, num_read, request;
  148.   unsigned char *buffer, *mark;
  149.  
  150.   if (EOF_flag) return 0;
  151.  
  152.   length = *length_ptr;
  153.   buffer = (unsigned char *) *buf_ptr;
  154.  
  155.   if (length > 0) {
  156.     memcpy((unsigned char *) buf_start, buffer, (length*4));
  157.     mark = ((unsigned char *) (buf_start + length));
  158.   }
  159.   else {
  160.     mark = (unsigned char *) buf_start;
  161.     length = 0;
  162.   }
  163.  
  164.   request = (max_length-length)*4;
  165.   
  166. //  num_read = fread( mark, 1, request, input);
  167.     num_read = ReadAsync(input, mark, request);
  168.  
  169.   /* Paulo Villegas - 26/1/1993: Correction for 4-byte alignment */
  170.   {
  171.     int num_read_rounded;
  172.     unsigned char *index;
  173.  
  174.     num_read_rounded = num_read & 0xfffffffc;
  175.  
  176.     /* this can happen only if num_read<request; i.e. end of file reached */
  177.     if( num_read_rounded < num_read )
  178.       { 
  179.      num_read_rounded+=4;
  180.      /* fill in with zeros */
  181.      for( index=mark+num_read; index<mark+num_read_rounded; *(index++)=0 );
  182.      /* advance to the next 4-byte boundary */
  183.      num_read = num_read_rounded;
  184.       }
  185.   }
  186.   
  187.   if (num_read < 0) {
  188.     return -1;
  189.   }
  190.   else if (num_read == 0) {
  191.     *buf_ptr = buf_start;
  192.     
  193.     /* Make 32 bits after end equal to 0 and 32
  194.        bits after that equal to seq end code
  195.        in order to prevent messy data from infinite
  196.        recursion.
  197.     */
  198.  
  199.     *(buf_start + length) = 0x0;
  200.     *(buf_start + length+1) = SEQ_END_CODE;
  201.  
  202.     EOF_flag = 1;
  203.     return 0;
  204.   }
  205.  
  206.   num_read >>= 2;
  207.  
  208.   *buf_ptr = buf_start;
  209.   *length_ptr = length + num_read;
  210.  
  211.   return 1;
  212. }
  213.  
  214. /*
  215.  *--------------------------------------------------------------
  216.  *
  217.  * int_handler --
  218.  *
  219.  *    Handles Cntl-C interupts..
  220.  *
  221.  * Results:
  222.  *    None.
  223.  *
  224.  * Side effects:
  225.  *    None.
  226.  *
  227.  *--------------------------------------------------------------
  228.  */
  229. void int_handler(int dummy)
  230. {
  231.     if (!quietFlag) fprintf(stderr, "Interrupted!\n");
  232.     if (curVidStream) DestroyVidStream(curVidStream);
  233.  
  234.     if(input)
  235.         CloseAsync(input);
  236.  
  237.     exit(1);
  238. }
  239.  
  240.  
  241. /*
  242.  *--------------------------------------------------------------
  243.  *
  244.  * init_timer --
  245.  *
  246.  *    Prepare timer.device and IORequest for later use
  247.  *
  248.  * Results:
  249.  *    None.
  250.  *
  251.  * Side effects:
  252.  *    None.
  253.  *
  254.  *--------------------------------------------------------------
  255.  */
  256.  
  257. void init_timer(void)
  258. {
  259.     /* Create port for timer device communications */
  260.     if(TimerMP = CreatePort(NULL, 0))
  261.         /* Create message block for device IO */
  262.         if(TimerIO = (struct timerequest *)CreateExtIO(TimerMP, sizeof(struct timerequest)))
  263.  
  264.             /* Open the timer device with UNIT_MICROHZ */
  265.             if(!OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)TimerIO, 0))
  266.             {
  267.                 TimerBase = (struct Library *)TimerIO->tr_node.io_Device;
  268.                 TimerIO->tr_node.io_Command = TR_ADDREQUEST;
  269.                 return;
  270.             }
  271.             else
  272.                 fprintf(stderr, "Error: Can't open Timer.device\n");
  273.         else
  274.             fprintf(stderr, "Error: Can't create IO request\n");
  275.     else
  276.         fprintf(stderr, "Error: Can't create port\n");
  277.  
  278.     exit(1);
  279. }
  280. /*
  281.  *--------------------------------------------------------------
  282.  *
  283.  * close_timer --
  284.  *
  285.  *    Close timer.device, remove IORequest and message port
  286.  *
  287.  * Results:
  288.  *    None.
  289.  *
  290.  * Side effects:
  291.  *    None.
  292.  *
  293.  *--------------------------------------------------------------
  294.  */
  295.  
  296. void close_timer(void)
  297. {
  298.     if(TimerBase)
  299.         CloseDevice((struct IORequest *)TimerIO);  /* Close Timer device */
  300.  
  301.     if(TimerIO)
  302.         DeleteExtIO((struct IORequest *)TimerIO);
  303.  
  304.     if(TimerMP)
  305.         DeletePort(TimerMP);
  306. }
  307.  
  308. /*
  309.  *--------------------------------------------------------------
  310.  *
  311.  * main --
  312.  *
  313.  *    Parses command line, starts decoding and displaying.
  314.  *
  315.  * Results:
  316.  *    None.
  317.  *
  318.  * Side effects:
  319.  *    None.
  320.  *
  321.  *--------------------------------------------------------------
  322.  */
  323.  
  324. void main(int argc, char **argv)
  325. {
  326.   static VidStream *theStream;
  327.   extern int lores;
  328.   LONG opts[OPT_COUNT];
  329.   struct RDArgs *rdargs;
  330.  
  331.   ditherType = FULL_COLOR_DITHER;
  332.   noDisplayFlag = 0;
  333.  
  334.     memset(opts, 0, sizeof(opts));
  335.  
  336.     if(rdargs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
  337.     {
  338.         rdargs->RDA_ExtHelp = HELP_TEXT;
  339.  
  340.         if(rdargs = ReadArgs(TEMPLATE, opts, rdargs))
  341.         {
  342.             if(opts[OPT_NOP])
  343.           TogglePFlag();
  344.  
  345.             if(opts[OPT_NOB])
  346.           ToggleBFlag();
  347.  
  348.             if(opts[OPT_DITHER])
  349.             {
  350.                 switch(strstr(dither_names, strlwr((char *)opts[OPT_DITHER])) - dither_names)
  351.                 {
  352.                     case 5:        /* color */
  353.                         ditherType = FULL_COLOR_DITHER;
  354.                         break;
  355.  
  356.                     case 11:    /* hiresham */
  357.                         ditherType = FULL_COLOR_DITHER;
  358.                         lores = FALSE;
  359.                         break;
  360.  
  361.                     case 0:    /* ham6 */
  362.                         ditherType = FULL_COLOR_DITHER;
  363.                         ham6 = TRUE;
  364.                         break;
  365.  
  366.                     case 25:    /* cybergfx */
  367.                         ditherType = CYBERGFX_DITHER;
  368.                         break;
  369.  
  370.                     case 34:    /* cybergfxgray */
  371.                         ditherType = CYBERGFXGRAY_DITHER;
  372.                         break;
  373.  
  374.                     case 42:    /* gray */
  375.                         ditherType = GRAY_DITHER;
  376.                         break;
  377.  
  378.                     case 52:    /* none */
  379.                         ditherType = NO_DITHER;
  380.                         break;
  381.  
  382.                     default:
  383.                         fprintf(stderr, "You should specify legal dither name after DITHER keyword.\n");
  384.                         FreeArgs(rdargs);
  385.                         exit(10);
  386.                 }
  387.             }
  388.  
  389.             if(opts[OPT_EACHSTAT])
  390. #ifdef ANALYSIS
  391.                 showEachFlag = 1;
  392. #else
  393.             {
  394.                 fprintf(stderr, "To use EACHSTAT, recompile with DEFINE ANALYSIS in CFLAGS\n");
  395.                 exit(1);
  396.             }
  397. #endif
  398.  
  399.             if(opts[OPT_QUIET])
  400.             quietFlag = 1;
  401.  
  402.             if(opts[OPT_LOOP])
  403.                 loopFlag = 1;
  404.  
  405.             if(opts[OPT_NODISPLAY])
  406.                 noDisplayFlag = 1;
  407.  
  408.             if(opts[OPT_PUBSCREEN])
  409.             {
  410.                 if(!stricmp("default", (char *)opts[OPT_PUBSCREEN]))
  411.                     pubname_ptr = NULL;
  412.                 else
  413.                 {
  414.                     strcpy(pubscreen_name, (char *)opts[OPT_PUBSCREEN]);
  415.                     pubname_ptr = pubscreen_name;
  416.                 }
  417.  
  418.                 cyber_pub = 1;
  419.             }
  420.  
  421.             if(opts[OPT_MODEID])
  422.                 if(sscanf((char *)opts[OPT_MODEID], "%x", &modeid) != 1)
  423.                 {
  424.                     fprintf(stderr, "ModeID should be an hexadecimal value.\n");
  425.                     FreeArgs(rdargs);
  426.                     exit(10);
  427.                 }
  428.  
  429.             if(opts[OPT_FPS])
  430.                 if(sscanf((char *)opts[OPT_FPS], "%d", &framerate) != 1)
  431.                 {
  432.                     fprintf(stderr, "You should specify a number after FRAMERATE keyword.\n");
  433.                     FreeArgs(rdargs);
  434.                     exit(10);
  435.                 }
  436.  
  437.             if(opts[OPT_BUFFER])
  438.                 if(sscanf((char *)opts[OPT_BUFFER], "%d", &buf_length) != 1)
  439.                 {
  440.                     fprintf(stderr, "You should specify a number after BUFFER keyword.\n");
  441.                     FreeArgs(rdargs);
  442.                     exit(10);
  443.                 }
  444.  
  445.             if(opts[OPT_FILE])
  446.             {
  447. //                input = fopen((char *)opts[OPT_FILE], "r");
  448.  
  449.                 input = OpenAsync((char *)opts[OPT_FILE], MODE_READ, buf_length);
  450.  
  451.                 if(input == NULL)
  452.                 {
  453.                     fprintf(stderr, "Could not open file %s\n", (char *)opts[OPT_FILE]);
  454.                     FreeArgs(rdargs);
  455.                     exit(10);
  456.           }
  457.  
  458.                 strcpy(animname, (char *)opts[OPT_FILE]);
  459.  
  460.               signal(SIGINT, int_handler);
  461.  
  462.               init_tables();
  463.   
  464.               switch (ditherType)
  465.                 {
  466.                     case CYBERGFX_DITHER:
  467.                         InitColorDither();
  468.                         modeid = InitCyberGfxDisplay(modeid);
  469.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  470.                         DoDitherImage = ColorDitherImage_RGB;
  471.                         break;
  472.  
  473.                     case CYBERGFXGRAY_DITHER:
  474.                         InitColorDither();
  475.                         modeid = InitCyberGfxDisplay(modeid);
  476.                         HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
  477.                         DoDitherImage = NoDitherImage;
  478.                         break;
  479.  
  480.                     case GRAY_DITHER:
  481.                         InitColorDither();
  482.                         modeid = InitGrayDisplay(modeid);
  483.                         HAM8_draw = (void (*)(void *, int, int)) DrawGrayImage;
  484.                         DoDitherImage = NoDitherImage;
  485.                         break;
  486.  
  487.                     case FULL_COLOR_DITHER:
  488.                         InitColorDither();
  489.                         InitColorDisplay();
  490.                         break;
  491.  
  492.                     case NO_DITHER:
  493.                         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  494.                         DoDitherImage = NoDitherImage;
  495.                         break;
  496.                 }
  497.  
  498.                 init_timer();
  499.  
  500. /*
  501.  *  The new restart handling has not been checked out very closely with changing
  502.  *  (non)intra scale matrices!
  503.  */
  504.  
  505.                 theStream = NewVidStream(buf_length);
  506.  
  507.                 if (setjmp(env) != 0)
  508.                 {
  509.                     mpegInitVidRsrc(); /* fix bug in static first in mpegVidRsrc */
  510.  
  511. //                    rewind(input);
  512.                     SeekAsync(input, 0, MODE_START);
  513.  
  514.                     EOF_flag = 0;
  515.                     theStream->bit_offset = 0;
  516.                     theStream->buf_length = 0;
  517.                     theStream->buffer = NULL;
  518.                     totNumFrames = 0;
  519. #ifdef ANALYSIS 
  520.                     init_stats();
  521. #endif
  522.                 }
  523.  
  524.                 realTimeStart = ReadSysClock();
  525.                 while (mpegVidRsrc(0, theStream));
  526.  
  527.                 CloseAsync(input);
  528.             }
  529.  
  530.             FreeArgs(rdargs);
  531.         }
  532.         else
  533.         {
  534.             PrintFault(IoErr(), argv[0]);
  535.             exit(10);
  536.         }
  537.  
  538.         FreeDosObject(DOS_RDARGS, rdargs);
  539.     }
  540.     else
  541.     {
  542.         PrintFault(IoErr(), argv[0]);
  543.         exit(10);
  544.     }
  545. }
  546.     
  547.  
  548. /*
  549.  *  Dummy display method
  550.  *
  551.  */
  552. void NoDitherImage(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
  553.            unsigned char *disp, int h, int w)
  554. {}
  555.  
  556.