home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Enigma Amiga Life 106
/
EnigmaAmiga106CD.iso
/
indispensabili
/
grafica
/
amipeg_1.1
/
src
/
main.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-01-27
|
17KB
|
683 lines
/*
* This is the main part
*/
#include <intuition/screens.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <string.h>
#include "video.h"
#include "proto.h"
#include <sys/types.h>
#include <signal.h>
#include <proto/timer.h>
#include <devices/timer.h>
#include <proto/asyncio.h>
#include <proto/asl.h>
#include "util.h"
#define HELP_TEXT "FILES\t- filename(s) of MPEG stream(s). Supports wildcards.\n\
NOB\t- ignore and not display any B frames.\n\
NOP\t- ignore and not display any P frames.\n\
LOOP\t- makes the player loop back to the beginning after reaching the end.\n\
EACHSTAT- causes statistics to be displayed after each frame.\n\
\t Only valid when compiled with -DANALYSIS\n\
NODISPLAY- dithers, but does not display, usually used for\n\
\t testing and timing purposes.\n\
QUIET\t- supresses printing of frame numbers, timing information,\n\
\t and most error messages.\n\
DITHER\t- selects from a variety of dither options.\n\
\t The possible values are:\n\
\t\tcolor\n\
\t\thiresham\n\
\t\tham6\n\
\t\tcybergfx\n\
\t\tcybergfxgray\n\
\t\tgray\n\
\t\tvlayer\n\
\t\tvlayergray\n\
\t\tpivpip\n\
\t\tnone\n\
PUBSCREEN- open window on selected \"deep\" public screen. Only valid with\n\
\t DITHER cybergfx or cybergfxgray. Use with \"DEFAULT\" to open on current\n\
\t default public screen. When used with vlayer(gray), may name any\n\
\t public screen, as long as it is the screen of a gfx-board compatible\n\
\t with cgxvideo.library.\n\
MODEID\t- select modeid for screen to open and play on.\n\
FRAMERATE- speed in frames per second. (0 - as fast as possible).\n\
BUFFER\t- size of the I/O buffer (default - 65536).\n\
FULL\t- open full-screen, borderless window. Most useful with vlayer(gray).\n"
#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"
#define OPT_FILES 0
#define OPT_NOB 1
#define OPT_NOP 2
#define OPT_LOOP 3
#define OPT_EACHSTAT 4
#define OPT_NODISPLAY 5
#define OPT_QUIET 6
#define OPT_DITHER 7
#define OPT_PUBSCREEN 8
#define OPT_MODEID 9
#define OPT_FPS 10
#define OPT_BUFFER 11
#define OPT_FULL 12
#define OPT_COUNT 13
#define AP_BUFFSIZE 240
struct Files /* to keep the names from MatchFirst() etc or ASL req... */
{
unsigned char *name;
struct Files *next;
};
const char *dither_names = "ham6\1color\1hiresham\1ham6\1cybergfx\1cybergfxgray\1vlayer\1vlayergray\1pivpip\1none";
/* 01234 56789 1113151719 2123 2527293133 353739414345 47495153 5557596163 65676971
got it? :) 10 12141618 202224 26283032 34363840424446 485052 545658606264 666870 72
*/
char animname[1024];
char pubscreen_name[MAXPUBSCREENNAME + 1];
char *pubname_ptr;
/* Declaration of global variable to hold dither info. */
int ditherType;
/* size of the io buffer */
int buf_length = 65536;
/* Global file pointer to incoming data. */
struct AsyncFile *input;
/* End of File flag. */
int EOF_flag = 0;
/* Loop flag. */
int loopFlag = 0;
/* Quiet flag. */
int quietFlag = 0;
/* full screen output */
int fullFlag = 0;
/* User wants to quit? */
int doneFlag = 0;
/* how many files to show? */
int number_of_files = 0;
/* Display image on screen? */
int noDisplayFlag = 0;
/* Setjmp/Longjmp env. */
jmp_buf env;
/* HAM6 rendering / HAM hires flag */
extern int ham6, lores;
/* modeid of CyberGraphX screen */
unsigned long modeid = 0xffffffff;
/* are we going to play on the Public Screen? */
int cyber_pub = 0;
/* Framerate, -1: specified in stream (default)
0: as fast as possible
N (N>0): N frames/sec
*/
int framerate = -1;
/* these are for timer.device */
struct Library *TimerBase;
struct MsgPort *TimerMP; /* Message port pointer */
struct timerequest *TimerIO; /* I/O structure pointer */
/* Method of picture conversion */
void (*DoDitherImage)(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
unsigned char *disp, int h, int w);
static char version[]="$VER: aMiPEG 1.1 " __AMIGADATE__;
/*
*--------------------------------------------------------------
*
* int_handler --
*
* Handles Cntl-C interupts..
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void int_handler(int dummy)
{
if (!quietFlag) fprintf(stderr, "Interrupted!\n");
if (curVidStream) DestroyVidStream(curVidStream);
if(input)
{
CloseAsync(input);
input = NULL;
}
exit(1);
}
/*
*--------------------------------------------------------------
*
* init_timer --
*
* Prepare timer.device and IORequest for later use
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void init_timer(void)
{
/* Create port for timer device communications */
if(TimerMP = CreatePort(NULL, 0))
/* Create message block for device IO */
if(TimerIO = (struct timerequest *)CreateExtIO(TimerMP, sizeof(struct timerequest)))
/* Open the timer device with UNIT_MICROHZ */
if(!OpenDevice(TIMERNAME, UNIT_MICROHZ, (struct IORequest *)TimerIO, 0))
{
TimerBase = (struct Library *)TimerIO->tr_node.io_Device;
TimerIO->tr_node.io_Command = TR_ADDREQUEST;
return;
}
else
fprintf(stderr, "Error: Can't open Timer.device\n");
else
fprintf(stderr, "Error: Can't create IO request\n");
else
fprintf(stderr, "Error: Can't create port\n");
exit(1);
}
/*
*--------------------------------------------------------------
*
* close_timer --
*
* Close timer.device, remove IORequest and message port
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void close_timer(void)
{
if(TimerBase)
CloseDevice((struct IORequest *)TimerIO); /* Close Timer device */
if(TimerIO)
DeleteExtIO((struct IORequest *)TimerIO);
if(TimerMP)
DeletePort(TimerMP);
}
/*
*--------------------------------------------------------------
*
* main --
*
* Parses command line, starts decoding and displaying.
*
* Results:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------
*/
void main(int argc, char **argv)
{
static VidStream *theStream;
extern int lores;
LONG opts[OPT_COUNT];
struct RDArgs *rdargs;
struct FileRequester *fr;
struct Library *AslBase;
unsigned char **fnames;
struct AnchorPath *ap;
struct Files *namestuff=NULL;
struct Files *p;
struct Files *q;
int i;
LONG err;
ditherType = FULL_COLOR_DITHER;
noDisplayFlag = 0;
memset(opts, 0, sizeof(opts));
if(rdargs = (struct RDArgs *)AllocDosObject(DOS_RDARGS, NULL))
{
rdargs->RDA_ExtHelp = HELP_TEXT;
if(rdargs = ReadArgs(TEMPLATE, opts, rdargs))
{
if(opts[OPT_NOP])
TogglePFlag();
if(opts[OPT_NOB])
ToggleBFlag();
if(opts[OPT_DITHER])
{
switch(strstr(dither_names, strlwr((char *)opts[OPT_DITHER])) - dither_names)
{
case 5: /* color */
ditherType = FULL_COLOR_DITHER;
break;
case 11: /* hiresham */
ditherType = FULL_COLOR_DITHER;
lores = FALSE;
break;
case 0: /* ham6 */
ditherType = FULL_COLOR_DITHER;
ham6 = TRUE;
break;
case 25: /* cybergfx */
ditherType = CYBERGFX_DITHER;
break;
case 34: /* cybergfxgray */
ditherType = CYBERGFXGRAY_DITHER;
break;
case 42: /* gray */
ditherType = GRAY_DITHER;
break;
case 47:
ditherType = CYBERGFXVLAYER_DITHER;
break;
case 54:
ditherType = CYBERGFXVLAYERGRAY_DITHER;
break;
case 65:
ditherType = PIV_DITHER;
break;
case 72:
ditherType = NO_DITHER;
break;
default:
fprintf(stderr, "You should specify legal dither name after DITHER keyword.\n");
FreeArgs(rdargs);
exit(10);
}
}
if(opts[OPT_EACHSTAT])
#ifdef ANALYSIS
showEachFlag = 1;
#else
{
fprintf(stderr, "To use EACHSTAT, recompile with DEFINE ANALYSIS in CFLAGS\n");
exit(1);
}
#endif
if(opts[OPT_QUIET])
quietFlag = 1;
if(opts[OPT_LOOP])
loopFlag = 1;
if(opts[OPT_NODISPLAY])
noDisplayFlag = 1;
if(opts[OPT_PUBSCREEN])
{
if(!stricmp("default", (char *)opts[OPT_PUBSCREEN]))
pubname_ptr = NULL;
else
{
strcpy(pubscreen_name, (char *)opts[OPT_PUBSCREEN]);
pubname_ptr = pubscreen_name;
}
cyber_pub = 1;
}
if(opts[OPT_MODEID])
if(sscanf((char *)opts[OPT_MODEID], "%x", &modeid) != 1)
{
fprintf(stderr, "ModeID should be an hexadecimal value.\n");
FreeArgs(rdargs);
exit(10);
}
if(opts[OPT_FPS])
if(sscanf((char *)opts[OPT_FPS], "%d", &framerate) != 1)
{
fprintf(stderr, "You should specify a number after FRAMERATE keyword.\n");
FreeArgs(rdargs);
exit(10);
}
if(opts[OPT_BUFFER])
if(sscanf((char *)opts[OPT_BUFFER], "%d", &buf_length) != 1)
{
fprintf(stderr, "You should specify a number after BUFFER keyword.\n");
FreeArgs(rdargs);
exit(10);
}
if(opts[OPT_FULL])
fullFlag = 1;
fnames = (char **) opts[OPT_FILES];
if(fnames!=NULL)
{
if ((ap = malloc (sizeof (struct AnchorPath) + AP_BUFFSIZE)))
{
memset(ap, 0, sizeof(struct AnchorPath) + AP_BUFFSIZE);
ap->ap_Strlen = AP_BUFFSIZE;
while (*fnames != NULL)
{
for (err = MatchFirst (*fnames, ap); (err == 0); err = MatchNext (ap))
{
number_of_files++;
if ((q = malloc (sizeof (struct Files))) && (q->name=malloc(AP_BUFFSIZE)))
{
struct Files *old_pointer = NULL;
if(ap->ap_Buf[0]) // dirty hack for PIPE: stuff
strcpy (q->name, ap->ap_Buf);
else
strcpy (q->name, *fnames);
p=namestuff;
if(p==NULL)
{
namestuff=q;
q->next = NULL;
}
else
{
/* crappy"sort" :) O(n^2) at worst */
/* Move slowly down the list and try to fit in the structure: */
while (p && stricmp (p->name, q->name) <= 0)
{
old_pointer = p;
p = p->next;
}
if (p)
{
if (old_pointer)
{
q->next = old_pointer->next;
old_pointer->next = q;
}
else
{
q->next = namestuff;
namestuff = q;
}
}
else
{
old_pointer->next=q;
q->next = NULL;
}
}
}
}
if(err==ERROR_OBJECT_NOT_FOUND && !quietFlag)
printf("Couldn't show '%s': object not found\n", *fnames);
MatchEnd (ap);
fnames++;
}
free(ap);
}
}
else
{
if ((AslBase = OpenLibrary ("asl.library", 37)) != NULL)
{
if ((fr = (struct FileRequester *) AllocAslRequestTags (ASL_FileRequest,
ASLFR_TitleText, (ULONG) "Select files to play",
ASLFR_InitialPattern, (ULONG) "#?.mpg",
(AslBase->lib_Version < 38) ? TAG_DONE :
ASLFR_DoMultiSelect, TRUE,
ASLFR_DoPatterns, TRUE,
TAG_DONE)))
{
if (AslRequest (fr, NULL))
{
for (i = (fr->fr_NumArgs)-1; i>=0 ; i--)
{
number_of_files++;
if ((q = malloc (sizeof (struct Files))) && (q->name=malloc(AP_BUFFSIZE)))
{
strcpy (q->name, fr->fr_Drawer);
AddPart (q->name, fr->fr_ArgList[i].wa_Name, AP_BUFFSIZE);
p=namestuff;
if(p==NULL)
{
namestuff=q;
q->next=NULL;
}
else
{
q->next=p;
namestuff=q;
}
}
}
}
FreeAslRequest(fr);
}
else
{
printf ("Can't allocate file requester.\n");
CloseLibrary(AslBase);
FreeArgs(rdargs);
return;
}
CloseLibrary(AslBase);
}
else
{
fprintf(stderr, "Error opening asl.library V37\n");
FreeArgs(rdargs);
return;
}
}
p=namestuff;
if(p!=NULL)
{
signal(SIGINT, int_handler);
init_tables();
init_timer();
switch (ditherType)
{
case PIV_DITHER:
CheckPIV();
InitColorDither();
modeid = InitP96Display(modeid);
HAM8_draw = (void (*)(void *, int, int)) DrawP96Image;
DoDitherImage = ColorDitherImage_VideoLayerYCbCr;
break;
case CYBERGFXVLAYERGRAY_DITHER:
InitColorDither();
modeid = InitCyberGfxDisplay(modeid);
HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
DoDitherImage = ColorDitherImage_VideoLayerGray;
break;
case CYBERGFXVLAYER_DITHER:
InitColorDither();
modeid = InitCyberGfxDisplay(modeid);
HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
DoDitherImage = ColorDitherImage_VideoLayerYCbCr;
break;
case CYBERGFX_DITHER:
InitColorDither();
modeid = InitCyberGfxDisplay(modeid);
HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
DoDitherImage = ColorDitherImage_RGB;
break;
case CYBERGFXGRAY_DITHER:
InitColorDither();
modeid = InitCyberGfxDisplay(modeid);
HAM8_draw = (void (*)(void *, int, int)) DrawCyberGfxImage;
DoDitherImage = NoDitherImage;
break;
case GRAY_DITHER:
InitColorDither();
modeid = InitGrayDisplay(modeid);
HAM8_draw = (void (*)(void *, int, int)) DrawGrayImage;
DoDitherImage = NoDitherImage;
break;
case FULL_COLOR_DITHER:
InitColorDither();
InitColorDisplay();
break;
case NO_DITHER:
HAM8_draw = (void (*)(void *, int, int)) NoDitherImage; // method casting ... argh!
DoDitherImage = NoDitherImage;
break;
}
}
/*
* The new restart handling has not been checked out very closely with changing
* (non)intra scale matrixes!
*/
while(p!=NULL && doneFlag != DONE_REALLY)
{
if(number_of_files == 1 && doneFlag == DONE_NOT_REALLY)
break;
while(p!=NULL && !(input = OpenAsync(p->name, MODE_READ, buf_length)))
{
fprintf(stderr, "Could not open file %s\n", p->name);
p=p->next;
}
if(p==NULL) break;
if(!quietFlag) printf("file: %s\n", p->name);
strcpy(animname, p->name);
p=p->next;
theStream = NewVidStream(buf_length);
mpegInitVidRsrc();
EOF_flag=0;
sys_layer=-1;
totNumFrames=0;
realTimeStart = ReadSysClock();
if (setjmp(env) == 0)
while (mpegVidRsrc(0, theStream));
if(input)
{
CloseAsync(input);
input = NULL;
}
if(p==NULL && loopFlag)
p=namestuff;
}
p=namestuff;
while(p)
{
free(p->name);
q=p;
p=p->next;
free(q);
}
FreeArgs(rdargs);
}
FreeDosObject(DOS_RDARGS, rdargs);
}
else
{
PrintFault(IoErr(), argv[0]);
exit(10);
}
}
/*
* Dummy display method
*
*/
void NoDitherImage(unsigned char *l, unsigned char *Cr, unsigned char *Cb,
unsigned char *disp, int h, int w)
{}