From b28f8ef04d50cc09f04d203d4a0a5028a1f2d930 Mon Sep 17 00:00:00 2001 From: avolkov Date: Sun, 19 Oct 2003 11:36:14 +0000 Subject: [PATCH] Decoder interface additions and changes in preparation for the upcoming CDP architecture -- support for registering external decoders; DukVid file IO changed from resX to uio git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@1280 8092fc87-c524-0410-9efc-e669fe64eaf9 --- sc2/src/sc2code/libs/video/dukvid.c | 137 +++++++++++-------- sc2/src/sc2code/libs/video/video.c | 2 - sc2/src/sc2code/libs/video/videodec.c | 184 ++++++++++++++++++++++---- sc2/src/sc2code/libs/video/videodec.h | 12 +- 4 files changed, 254 insertions(+), 81 deletions(-) diff --git a/sc2/src/sc2code/libs/video/dukvid.c b/sc2/src/sc2code/libs/video/dukvid.c index 8128852eb..d5cb2dc57 100644 --- a/sc2/src/sc2code/libs/video/dukvid.c +++ b/sc2/src/sc2code/libs/video/dukvid.c @@ -20,28 +20,33 @@ */ #include "video.h" -#include "libs/sndlib.h" -#include "libs/sound/sound.h" #include "dukvid.h" -#include "endian_uqm.h" #include +#include "libs/uio.h" +#include "endian_uqm.h" #define THIS_PTR TFB_VideoDecoder* This -uint32 dukv_GetStructSize (void); -int dukv_GetError (THIS_PTR); -bool dukv_Init (THIS_PTR, TFB_PixelFormat* fmt); -void dukv_Term (THIS_PTR); -bool dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); -void dukv_Close (THIS_PTR); -int dukv_DecodeNext (THIS_PTR); -uint32 dukv_SeekFrame (THIS_PTR, uint32 frame); -float dukv_SeekTime (THIS_PTR, float time); -uint32 dukv_GetFrame (THIS_PTR); -float dukv_GetTime (THIS_PTR); +static const char* dukv_GetName (void); +static bool dukv_InitModule (int flags); +static void dukv_TermModule (void); +static uint32 dukv_GetStructSize (void); +static int dukv_GetError (THIS_PTR); +static bool dukv_Init (THIS_PTR, TFB_PixelFormat* fmt); +static void dukv_Term (THIS_PTR); +static bool dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename); +static void dukv_Close (THIS_PTR); +static int dukv_DecodeNext (THIS_PTR); +static uint32 dukv_SeekFrame (THIS_PTR, uint32 frame); +static float dukv_SeekTime (THIS_PTR, float time); +static uint32 dukv_GetFrame (THIS_PTR); +static float dukv_GetTime (THIS_PTR); TFB_VideoDecoderFuncs dukv_DecoderVtbl = { + dukv_GetName, + dukv_InitModule, + dukv_TermModule, dukv_GetStructSize, dukv_GetError, dukv_Init, @@ -107,7 +112,7 @@ typedef struct tfb_duckvideodecoder #define DUCK_MAX_FRAME_SIZE 0x8000U #define DUCK_END_OF_SEQUENCE 1 -void +static void dukv_DecodeFrame (uint8* src_p, uint32* dst_p, uint32 wb, uint32 hb, TFB_DuckVideoDeltas* deltas) { @@ -205,7 +210,7 @@ dukv_DecodeFrame (uint8* src_p, uint32* dst_p, uint32 wb, uint32 hb, } } -void +static void dukv_DecodeFrameV3 (uint8* src_p, uint32* dst_p, uint32 wb, uint32 hb, TFB_DuckVideoDeltas* deltas) { @@ -270,7 +275,7 @@ dukv_DecodeFrameV3 (uint8* src_p, uint32* dst_p, uint32 wb, uint32 hb, } } -bool +static bool dukv_OpenStream (TFB_DuckVideoDecoder* dukv) { char filename[280]; @@ -278,10 +283,10 @@ dukv_OpenStream (TFB_DuckVideoDecoder* dukv) strcat (strcpy (filename, dukv->basename), ".duk"); return (dukv->stream = - res_OpenResFile (dukv->basedir, filename, "rb")) != NULL; + uio_fopen (dukv->basedir, filename, "rb")) != NULL; } -bool +static bool dukv_ReadFrames (TFB_DuckVideoDecoder* dukv) { char filename[280]; @@ -290,20 +295,23 @@ dukv_ReadFrames (TFB_DuckVideoDecoder* dukv) strcat (strcpy (filename, dukv->basename), ".frm"); - if (!(fp = res_OpenResFile (dukv->basedir, filename, "rb"))) + if (!(fp = uio_fopen (dukv->basedir, filename, "rb"))) return false; - dukv->cframes = LengthResFile (fp) / sizeof (uint32); + // get number of frames + uio_fseek (fp, 0, SEEK_END); + dukv->cframes = uio_ftell (fp) / sizeof (uint32); + uio_fseek (fp, 0, SEEK_SET); dukv->frames = (uint32*) HMalloc (dukv->cframes * sizeof (uint32)); - if ((uint32)ReadResFile (dukv->frames, sizeof (uint32), dukv->cframes, + if (uio_fread (dukv->frames, sizeof (uint32), dukv->cframes, fp) != dukv->cframes) { HFree (dukv->frames); dukv->frames = 0; return 0; } - res_CloseResFile (fp); + uio_fclose (fp); for (i = 0; i < dukv->cframes; ++i) dukv->frames[i] = UQM_SwapBE32 (dukv->frames[i]); @@ -311,7 +319,7 @@ dukv_ReadFrames (TFB_DuckVideoDecoder* dukv) return true; } -bool +static bool dukv_ReadVectors (TFB_DuckVideoDecoder* dukv, uint8* vectors) { uio_Stream *fp; @@ -320,16 +328,16 @@ dukv_ReadVectors (TFB_DuckVideoDecoder* dukv, uint8* vectors) strcat (strcpy (filename, dukv->basename), ".tbl"); - if (!(fp = res_OpenResFile (dukv->basedir, filename, "rb"))) + if (!(fp = uio_fopen (dukv->basedir, filename, "rb"))) return false; - ret = ReadResFile (vectors, NUM_VEC_ITEMS * NUM_VECTORS, 1, fp); - res_CloseResFile (fp); + ret = uio_fread (vectors, NUM_VEC_ITEMS, NUM_VECTORS, fp); + uio_fclose (fp); - return ret; + return ret == NUM_VECTORS; } -bool +static bool dukv_ReadHeader (TFB_DuckVideoDecoder* dukv, sint32* pl, sint32* pc) { uio_Stream *fp; @@ -340,11 +348,11 @@ dukv_ReadHeader (TFB_DuckVideoDecoder* dukv, sint32* pl, sint32* pc) strcat (strcpy (filename, dukv->basename), ".hdr"); - if (!(fp = res_OpenResFile (dukv->basedir, filename, "rb"))) + if (!(fp = uio_fopen (dukv->basedir, filename, "rb"))) return false; - ret = ReadResFile (&hdr, sizeof (hdr), 1, fp); - res_CloseResFile (fp); + ret = uio_fread (&hdr, sizeof (hdr), 1, fp); + uio_fclose (fp); if (!ret) return false; @@ -364,7 +372,7 @@ dukv_ReadHeader (TFB_DuckVideoDecoder* dukv, sint32* pl, sint32* pc) return true; } -sint32 +static sint32 dukv_make_delta (sint32* protos, bool is_chroma, int i1, int i2) { sint32 d1, d2; @@ -383,7 +391,7 @@ dukv_make_delta (sint32* protos, bool is_chroma, int i1, int i2) } } -sint32 +static sint32 dukv_make_corr (sint32* protos, bool is_chroma, int i1, int i2) { sint32 d1, d2; @@ -400,7 +408,7 @@ dukv_make_corr (sint32* protos, bool is_chroma, int i1, int i2) } } -void +static void dukv_DecodeVector (uint8* vec, sint32* p, bool is_chroma, sint32* deltas) { int citems = vec[0]; @@ -419,7 +427,7 @@ dukv_DecodeVector (uint8* vec, sint32* p, bool is_chroma, sint32* deltas) } -void +static void dukv_InitDeltas (TFB_DuckVideoDecoder* dukv, uint8* vectors, sint32* pl, sint32* pc) { @@ -433,7 +441,7 @@ dukv_InitDeltas (TFB_DuckVideoDecoder* dukv, uint8* vectors, } } -__inline__ uint32 +static __inline__ uint32 dukv_PixelConv (uint16 pix, const TFB_PixelFormat* fmt) { uint32 r, g, b; @@ -448,7 +456,7 @@ dukv_PixelConv (uint16 pix, const TFB_PixelFormat* fmt) ((b >> fmt->Bloss) << fmt->Bshift); } -void +static void dukv_RenderFrame (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -524,19 +532,40 @@ dukv_RenderFrame (THIS_PTR) } -uint32 +static const char* +dukv_GetName (void) +{ + return "DukVid"; +} + +static bool +dukv_InitModule (int flags) +{ + // no flags are defined for now + return true; + + (void)flags; // dodge compiler warning +} + +static void +dukv_TermModule (void) +{ + // do an extensive search on the word 'nothing' +} + +static uint32 dukv_GetStructSize (void) { return sizeof (TFB_DuckVideoDecoder); } -int +static int dukv_GetError (THIS_PTR) { return This->error; } -bool +static bool dukv_Init (THIS_PTR, TFB_PixelFormat* fmt) { This->format = fmt; @@ -544,7 +573,7 @@ dukv_Init (THIS_PTR, TFB_PixelFormat* fmt) return true; } -void +static void dukv_Term (THIS_PTR) { //TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -552,7 +581,7 @@ dukv_Term (THIS_PTR) dukv_Close (This); } -bool +static bool dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -595,7 +624,7 @@ dukv_Open (THIS_PTR, uio_DirHandle *dir, const char *filename) return true; } -void +static void dukv_Close (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -612,7 +641,7 @@ dukv_Close (THIS_PTR) } if (dukv->stream) { - res_CloseResFile (dukv->stream); + uio_fclose (dukv->stream); dukv->stream = NULL; } if (dukv->inbuf) @@ -627,7 +656,7 @@ dukv_Close (THIS_PTR) } } -int +static int dukv_DecodeNext (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -639,8 +668,8 @@ dukv_DecodeNext (THIS_PTR) if (!dukv->stream || dukv->iframe >= dukv->cframes) return 0; - SeekResFile (dukv->stream, dukv->frames[dukv->iframe], SEEK_SET); - if (ReadResFile (&fh, sizeof (fh), 1, dukv->stream) != 1) + uio_fseek (dukv->stream, dukv->frames[dukv->iframe], SEEK_SET); + if (uio_fread (&fh, sizeof (fh), 1, dukv->stream) != 1) { dukv->last_error = dukve_EOF; return 0; @@ -654,8 +683,8 @@ dukv_DecodeNext (THIS_PTR) return -1; } - SeekResFile (dukv->stream, vofs, SEEK_CUR); - if ((uint32)ReadResFile (dukv->inbuf, 1, vsize, dukv->stream) != vsize) + uio_fseek (dukv->stream, vofs, SEEK_CUR); + if (uio_fread (dukv->inbuf, 1, vsize, dukv->stream) != vsize) { dukv->last_error = dukve_EOF; return 0; @@ -676,7 +705,7 @@ dukv_DecodeNext (THIS_PTR) return 1; } -uint32 +static uint32 dukv_SeekFrame (THIS_PTR, uint32 frame) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -687,7 +716,7 @@ dukv_SeekFrame (THIS_PTR, uint32 frame) return dukv->iframe = frame; } -float +static float dukv_SeekTime (THIS_PTR, float time) { //TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -696,7 +725,7 @@ dukv_SeekTime (THIS_PTR, float time) return (float) dukv_SeekFrame (This, frame) / DUCK_GENERAL_FPS; } -uint32 +static uint32 dukv_GetFrame (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; @@ -704,7 +733,7 @@ dukv_GetFrame (THIS_PTR) return dukv->iframe; } -float +static float dukv_GetTime (THIS_PTR) { TFB_DuckVideoDecoder* dukv = (TFB_DuckVideoDecoder*) This; diff --git a/sc2/src/sc2code/libs/video/video.c b/sc2/src/sc2code/libs/video/video.c index afc4528e1..03c8b38c3 100644 --- a/sc2/src/sc2code/libs/video/video.c +++ b/sc2/src/sc2code/libs/video/video.c @@ -1,5 +1,3 @@ -//Copyright Paul Reiche, Fred Ford. 1992-2002 - /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/sc2/src/sc2code/libs/video/videodec.c b/sc2/src/sc2code/libs/video/videodec.c index 56eeee39b..64d013b7f 100644 --- a/sc2/src/sc2code/libs/video/videodec.c +++ b/sc2/src/sc2code/libs/video/videodec.c @@ -18,32 +18,47 @@ #include "videodec.h" #include "dukvid.h" +#define MAX_REG_DECODERS 31 + static bool vd_inited = 0; static TFB_PixelFormat vd_vidfmt; +static int vd_flags = 0; -static struct vd_DecoderInfo +struct TFB_RegVideoDecoder { + bool builtin; + bool used; // ever used indicator const char* ext; - const char* name; - TFB_VideoDecoderFuncs* funcs; -} -vd_decoders[] = + const TFB_VideoDecoderFuncs* funcs; +}; +static TFB_RegVideoDecoder vd_decoders[MAX_REG_DECODERS + 1] = { - {"duk", "DukVid", &dukv_DecoderVtbl}, - {NULL, NULL, NULL} // null term + {true, true, "duk", &dukv_DecoderVtbl}, + {false, false, NULL, NULL}, // null term }; static void vd_computeMasks (uint32 mask, DWORD* shift, DWORD* loss); +const char* +VideoDecoder_GetName (TFB_VideoDecoder *decoder) +{ + if (!decoder || !decoder->funcs) + return "(Null)"; + return decoder->funcs->GetName (); +} + bool VideoDecoder_Init (int flags, int depth, uint32 Rmask, uint32 Gmask, uint32 Bmask, uint32 Amask) { + TFB_RegVideoDecoder* info; + vd_inited = 0; if (depth < 15 || depth > 32) { - fprintf (stderr, "VideoDecoder_Init: Unsupported video depth %d\n", depth); + fprintf (stderr, "VideoDecoder_Init: " + "Unsupported video depth %d\n", depth); return false; } @@ -67,24 +82,142 @@ VideoDecoder_Init (int flags, int depth, uint32 Rmask, uint32 Gmask, vd_computeMasks (Amask, &vd_vidfmt.Ashift, &vd_vidfmt.Aloss); // END: adapted from SDL - vd_inited = 1; - (void)flags; // dodge compiler warning + // init built-in decoders + for (info = vd_decoders; info->ext; info++) + { + if (!info->funcs->InitModule (flags)) + { + fprintf (stderr, "VideoDecoder_Init(): " + "%s video decoder init failed\n", + info->funcs->GetName ()); + } + } - return 1; + vd_flags = flags; + vd_inited = 1; + + return true; } void VideoDecoder_Uninit (void) { + TFB_RegVideoDecoder* info; + + // uninit all decoders + // and unregister loaded decoders + for (info = vd_decoders; info->used; info++) + { + if (info->ext) // check if present + info->funcs->TermModule (); + + if (!info->builtin) + { + info->used = false; + info->ext = NULL; + } + } + vd_inited = 0; - // go for a strall in a park +} + +TFB_RegVideoDecoder* +VideoDecoder_Register (const char* fileext, TFB_VideoDecoderFuncs* decvtbl) +{ + TFB_RegVideoDecoder* info; + TFB_RegVideoDecoder* newslot = NULL; + + if (!decvtbl) + { + fprintf (stderr, "VideoDecoder_Register(): Null decoder table\n"); + return NULL; + } + if (!fileext) + { + fprintf (stderr, "VideoDecoder_Register(): Bad file type for %s\n", + decvtbl->GetName ()); + return NULL; + } + + // check if extension already registered + for (info = vd_decoders; info->used && + (!info->ext || strcmp (info->ext, fileext) != 0); + ++info) + { + // and pick up an empty slot (where available) + if (!newslot && !info->ext) + newslot = info; + } + + if (info >= vd_decoders + MAX_REG_DECODERS) + { + fprintf (stderr, "VideoDecoder_Register(): Decoders limit reached\n"); + return NULL; + } + else if (info->ext) + { + fprintf (stderr, "VideoDecoder_Register(): " + "'%s' decoder already registered (%s denied)\n", + fileext, decvtbl->GetName ()); + return NULL; + } + + if (!decvtbl->InitModule (vd_flags)) + { + fprintf (stderr, "VideoDecoder_Register(): %s decoder init failed\n", + decvtbl->GetName ()); + return NULL; + } + + if (!newslot) + { + newslot = info; + newslot->used = true; + // make next one a term + info[1].builtin = false; + info[1].used = false; + info[1].ext = NULL; + } + + newslot->ext = fileext; + newslot->funcs = decvtbl; + + return newslot; +} + +void +VideoDecoder_Unregister (TFB_RegVideoDecoder* regdec) +{ + if (regdec < vd_decoders || regdec >= vd_decoders + MAX_REG_DECODERS || + !regdec->ext || !regdec->funcs) + { + fprintf (stderr, "VideoDecoder_Unregister(): " + "Invalid or expired decoder passed\n"); + return; + } + + regdec->funcs->TermModule (); + regdec->ext = NULL; + regdec->funcs = NULL; +} + +const TFB_VideoDecoderFuncs* +VideoDecoder_Lookup (const char* fileext) +{ + TFB_RegVideoDecoder* info; + + for (info = vd_decoders; info->used && + (!info->ext || strcmp (info->ext, fileext) != 0); + ++info) + ; + return info->ext ? info->funcs : NULL; } TFB_VideoDecoder* VideoDecoder_Load (uio_DirHandle *dir, const char *filename) { const char* pext; - struct vd_DecoderInfo* dinfo; + TFB_RegVideoDecoder* info; TFB_VideoDecoder* decoder; @@ -99,27 +232,28 @@ VideoDecoder_Load (uio_DirHandle *dir, const char *filename) } ++pext; - for (dinfo = vd_decoders; - dinfo->ext && strcmp(dinfo->ext, pext) != 0; - ++dinfo) + for (info = vd_decoders; info->used && + (!info->ext || strcmp (info->ext, pext) != 0); + ++info) ; - if (!dinfo->ext) + if (!info->ext) { fprintf (stderr, "VideoDecoder_Load: Unsupported file type\n"); return NULL; } - decoder = (TFB_VideoDecoder*) HCalloc (dinfo->funcs->GetStructSize ()); - decoder->funcs = dinfo->funcs; + decoder = (TFB_VideoDecoder*) HCalloc (info->funcs->GetStructSize ()); + decoder->funcs = info->funcs; if (!decoder->funcs->Init (decoder, &vd_vidfmt)) { - fprintf (stderr, "VideoDecoder_Load: Cannot init '%s' decoder, code %d\n", - dinfo->name, decoder->funcs->GetError (decoder)); + fprintf (stderr, "VideoDecoder_Load: " + "Cannot init '%s' decoder, code %d\n", + decoder->funcs->GetName (), + decoder->funcs->GetError (decoder)); HFree (decoder); return NULL; } - decoder->decoder_info = dinfo->name; decoder->dir = dir; decoder->filename = (char *) HMalloc (strlen (filename) + 1); strcpy (decoder->filename, filename); @@ -127,8 +261,10 @@ VideoDecoder_Load (uio_DirHandle *dir, const char *filename) if (!decoder->funcs->Open (decoder, dir, filename)) { - fprintf (stderr, "VideoDecoder_Load: '%s' decoder did not load %s, code %d\n", - dinfo->name, filename, decoder->funcs->GetError (decoder)); + fprintf (stderr, "VideoDecoder_Load: " + "'%s' decoder did not load %s, code %d\n", + decoder->funcs->GetName (), filename, + decoder->funcs->GetError (decoder)); VideoDecoder_Free (decoder); return NULL; diff --git a/sc2/src/sc2code/libs/video/videodec.h b/sc2/src/sc2code/libs/video/videodec.h index aa5fbc5f2..cbec96958 100644 --- a/sc2/src/sc2code/libs/video/videodec.h +++ b/sc2/src/sc2code/libs/video/videodec.h @@ -28,6 +28,9 @@ typedef struct tfb_videodecoder TFB_VideoDecoder; typedef struct tfb_videodecoderfunc { + const char* (* GetName) (void); + bool (* InitModule) (int flags); + void (* TermModule) (); uint32 (* GetStructSize) (void); int (* GetError) (THIS_PTR); bool (* Init) (THIS_PTR, TFB_PixelFormat* fmt); @@ -81,7 +84,6 @@ struct tfb_videodecoder sint32 error; float pos; // position in seconds uint32 cur_frame; - const char *decoder_info; // semi-private uio_DirHandle *dir; @@ -97,6 +99,13 @@ enum VIDEODECODER_EOF, }; +typedef struct TFB_RegVideoDecoder TFB_RegVideoDecoder; + +TFB_RegVideoDecoder* VideoDecoder_Register (const char* fileext, + TFB_VideoDecoderFuncs* decvtbl); +void VideoDecoder_Unregister (TFB_RegVideoDecoder* regdec); +const TFB_VideoDecoderFuncs* VideoDecoder_Lookup (const char* fileext); + bool VideoDecoder_Init (int flags, int depth, uint32 Rmask, uint32 Gmask, uint32 Bmask, uint32 Amask); void VideoDecoder_Uninit (void); @@ -107,6 +116,7 @@ float VideoDecoder_Seek (TFB_VideoDecoder *decoder, float time_pos); uint32 VideoDecoder_SeekFrame (TFB_VideoDecoder *decoder, uint32 frame_pos); void VideoDecoder_Rewind (TFB_VideoDecoder *decoder); void VideoDecoder_Free (TFB_VideoDecoder *decoder); +const char* VideoDecoder_GetName (TFB_VideoDecoder *decoder); #endif // _VIDEODEC_H