diff options
author | Mike Melanson <mike@multimedia.cx> | 2002-10-23 03:21:19 +0000 |
---|---|---|
committer | Mike Melanson <mike@multimedia.cx> | 2002-10-23 03:21:19 +0000 |
commit | db7b8514d28d78565ee6299510eea12dd873214d (patch) | |
tree | 60f584a73a539c3db280fcdf0c819047bc4ea5a8 | |
parent | 3fd3d7d33515f867316010fe4fbe63bd57d1f7d3 (diff) | |
download | xine-lib-db7b8514d28d78565ee6299510eea12dd873214d.tar.gz xine-lib-db7b8514d28d78565ee6299510eea12dd873214d.tar.bz2 |
bring the FLI subsystem in line with the latest API revision
CVS patchset: 2950
CVS date: 2002/10/23 03:21:19
-rw-r--r-- | src/demuxers/demux_fli.c | 372 | ||||
-rw-r--r-- | src/libxinevdec/fli.c | 106 |
2 files changed, 260 insertions, 218 deletions
diff --git a/src/demuxers/demux_fli.c b/src/demuxers/demux_fli.c index 53f85d545..68ad37d61 100644 --- a/src/demuxers/demux_fli.c +++ b/src/demuxers/demux_fli.c @@ -22,7 +22,7 @@ * avoid while programming a FLI decoder, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_fli.c,v 1.16 2002/10/12 17:11:58 jkeil Exp $ + * $Id: demux_fli.c,v 1.17 2002/10/23 03:21:19 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -55,7 +55,7 @@ typedef struct { demux_plugin_t demux_plugin; - xine_t *xine; + xine_stream_t *stream; config_values_t *config; @@ -81,8 +81,66 @@ typedef struct { unsigned int speed; unsigned int frame_pts_inc; unsigned int frame_count; + + char last_mrl[1024]; } demux_fli_t; +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + config_values_t *config; +} demux_fli_class_t; + +/* returns 1 if the CIN file was opened successfully, 0 otherwise */ +static int open_fli_file(demux_fli_t *this) { + + /* read the whole header */ + this->input->seek(this->input, 0, SEEK_SET); + if (this->input->read(this->input, this->fli_header, FLI_HEADER_SIZE) != + FLI_HEADER_SIZE) + return 0; + + /* validate the file */ + this->magic_number = LE_16(&this->fli_header[4]); + if ((this->magic_number != FLI_FILE_MAGIC_1) && + (this->magic_number != FLI_FILE_MAGIC_2)) + return 0; + + this->frame_count = LE_16(&this->fli_header[6]); + this->width = LE_16(&this->fli_header[8]); + this->height = LE_16(&this->fli_header[10]); + this->speed = LE_32(&this->fli_header[16]); + if (this->magic_number == 0xAF11) { + /* + * in this case, the speed (n) is number of 1/70s ticks between frames: + * + * xine pts n * frame # + * -------- = ----------- => xine pts = n * (90000/70) * frame # + * 90000 70 + * + * therefore, the frame pts increment = n * 1285.7 + */ + this->frame_pts_inc = this->speed * 1285.7; + } else { + /* + * in this case, the speed (n) is number of milliseconds between frames: + * + * xine pts n * frame # + * -------- = ----------- => xine pts = n * 90 * frame # + * 90000 1000 + * + * therefore, the frame pts increment = n * 90 + */ + this->frame_pts_inc = this->speed * 90; + } + + return 1; +} + static void *demux_fli_loop (void *this_gen) { demux_fli_t *this = (demux_fli_t *) this_gen; @@ -175,7 +233,7 @@ static void *demux_fli_loop (void *this_gen) { this->status = DEMUX_FINISHED; if (this->send_end_buffers) { - xine_demux_control_end(this->xine, BUF_FLAG_END_STREAM); + xine_demux_control_end(this->stream, BUF_FLAG_END_STREAM); } this->thread_running = 0; @@ -184,132 +242,45 @@ static void *demux_fli_loop (void *this_gen) { return NULL; } -static int load_fli_and_send_headers(demux_fli_t *this) { +static void demux_fli_send_headers(demux_plugin_t *this_gen) { + + demux_fli_t *this = (demux_fli_t *) this_gen; + buf_element_t *buf; pthread_mutex_lock(&this->mutex); - this->video_fifo = this->xine->video_fifo; + this->video_fifo = this->stream->video_fifo; /* video-only format, don't worry about audio_fifo */ this->status = DEMUX_OK; - /* read the whole header */ - this->input->seek(this->input, 0, SEEK_SET); - if (this->input->read(this->input, this->fli_header, FLI_HEADER_SIZE) != - FLI_HEADER_SIZE) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock (&this->mutex); - return DEMUX_CANNOT_HANDLE; - } - - this->magic_number = LE_16(&this->fli_header[4]); - this->frame_count = LE_16(&this->fli_header[6]); - this->width = LE_16(&this->fli_header[8]); - this->height = LE_16(&this->fli_header[10]); - this->speed = LE_32(&this->fli_header[16]); - if (this->magic_number == 0xAF11) { - /* - * in this case, the speed (n) is number of 1/70s ticks between frames: - * - * xine pts n * frame # - * -------- = ----------- => xine pts = n * (90000/70) * frame # - * 90000 70 - * - * therefore, the frame pts increment = n * 1285.7 - */ - this->frame_pts_inc = this->speed * 1285.7; - } else { - /* - * in this case, the speed (n) is number of milliseconds between frames: - * - * xine pts n * frame # - * -------- = ----------- => xine pts = n * 90 * frame # - * 90000 1000 - * - * therefore, the frame pts increment = n * 90 - */ - this->frame_pts_inc = this->speed * 90; - } - /* load stream information */ - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width; - this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height; - - xine_demux_control_headers_done (this->xine); - - pthread_mutex_unlock (&this->mutex); + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->width; + this->stream->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->height; - return DEMUX_CAN_HANDLE; -} - -static int demux_fli_open(demux_plugin_t *this_gen, input_plugin_t *input, - int stage) { - - demux_fli_t *this = (demux_fli_t *) this_gen; - char sig[2]; - unsigned int magic_number; - - this->input = input; - - switch(stage) { - case STAGE_BY_CONTENT: { - if ((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) == 0) - return DEMUX_CANNOT_HANDLE; - - input->seek(input, 4, SEEK_SET); - if (input->read(input, sig, 2) != 2) { - return DEMUX_CANNOT_HANDLE; - } - magic_number = LE_16(&sig[0]); - if ((magic_number == FLI_FILE_MAGIC_1) || - (magic_number == FLI_FILE_MAGIC_2)) - return load_fli_and_send_headers(this); - - return DEMUX_CANNOT_HANDLE; - } - break; - - case STAGE_BY_EXTENSION: { - char *suffix; - char *MRL; - char *m, *valid_ends; - - MRL = input->get_mrl (input); - - suffix = strrchr(MRL, '.'); - - if(!suffix) - return DEMUX_CANNOT_HANDLE; - - xine_strdupa(valid_ends, (this->config->register_string(this->config, - "mrl.ends_fli", VALID_ENDS, - "valid mrls ending for fli demuxer", - NULL, 20, NULL, NULL))); - while((m = xine_strsep(&valid_ends, ",")) != NULL) { - - while(*m == ' ' || *m == '\t') m++; - - if(!strcasecmp((suffix + 1), m)) - return load_fli_and_send_headers(this); - } - return DEMUX_CANNOT_HANDLE; - } - break; + /* send start buffers */ + xine_demux_control_start(this->stream); - default: - return DEMUX_CANNOT_HANDLE; - break; + /* send init info to FLI decoder */ + buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); + buf->decoder_flags = BUF_FLAG_HEADER; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = this->frame_pts_inc; /* initial video_step */ + /* be a rebel and send the FLI header instead of the bih */ + memcpy(buf->content, this->fli_header, FLI_HEADER_SIZE); + buf->size = FLI_HEADER_SIZE; + buf->type = BUF_VIDEO_FLI; + this->video_fifo->put (this->video_fifo, buf); - } + xine_demux_control_headers_done (this->stream); - return DEMUX_CANNOT_HANDLE; + pthread_mutex_unlock (&this->mutex); } static int demux_fli_start (demux_plugin_t *this_gen, off_t start_pos, int start_time) { demux_fli_t *this = (demux_fli_t *) this_gen; - buf_element_t *buf; int err; pthread_mutex_lock(&this->mutex); @@ -317,35 +288,8 @@ static int demux_fli_start (demux_plugin_t *this_gen, /* if thread is not running, initialize demuxer */ if (!this->thread_running) { - /* print vital stats */ - xine_log (this->xine, XINE_LOG_MSG, - _("demux_fli: FLI type: %04X, speed: %d/%d\n"), - this->magic_number, this->speed, - (this->magic_number == FLI_FILE_MAGIC_1) ? 70 : 1000); - xine_log (this->xine, XINE_LOG_MSG, - _("demux_fli: %d frames, %dx%d\n"), - this->frame_count, this->width, this->height); - xine_log (this->xine, XINE_LOG_MSG, - _("demux_fli: running time: %d min, %d sec\n"), - this->frame_count * this->frame_pts_inc / 90000 / 60, - this->frame_count * this->frame_pts_inc / 90000 % 60); - - /* send start buffers */ - xine_demux_control_start(this->xine); - /* send new pts */ - xine_demux_control_newpts(this->xine, 0, 0); - - /* send init info to FLI decoder */ - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->decoder_flags = BUF_FLAG_HEADER; - buf->decoder_info[0] = 0; - buf->decoder_info[1] = this->frame_pts_inc; /* initial video_step */ - /* be a rebel and send the FLI header instead of the bih */ - memcpy(buf->content, this->fli_header, FLI_HEADER_SIZE); - buf->size = FLI_HEADER_SIZE; - buf->type = BUF_VIDEO_FLI; - this->video_fifo->put (this->video_fifo, buf); + xine_demux_control_newpts(this->stream, 0, 0); this->status = DEMUX_OK; this->send_end_buffers = 1; @@ -365,11 +309,10 @@ static int demux_fli_start (demux_plugin_t *this_gen, static int demux_fli_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time) { - demux_fli_t *this = (demux_fli_t *) this_gen; - /* FLI files are not meant to be seekable */ + /* FLI files are not meant to be seekable; don't even bother */ - return this->status; + return 0; } static void demux_fli_stop (demux_plugin_t *this_gen) { @@ -384,15 +327,18 @@ static void demux_fli_stop (demux_plugin_t *this_gen) { return; } + /* seek to the start of the data in case there's another start command */ + this->input->seek(this->input, FLI_HEADER_SIZE, SEEK_SET); + this->send_end_buffers = 0; this->status = DEMUX_FINISHED; pthread_mutex_unlock( &this->mutex ); pthread_join (this->thread, &p); - xine_demux_flush_engine(this->xine); + xine_demux_flush_engine(this->stream); - xine_demux_control_end(this->xine, BUF_FLAG_END_USER); + xine_demux_control_end(this->stream, BUF_FLAG_END_USER); } static void demux_fli_dispose (demux_plugin_t *this) { @@ -402,11 +348,7 @@ static void demux_fli_dispose (demux_plugin_t *this) { static int demux_fli_get_status (demux_plugin_t *this_gen) { demux_fli_t *this = (demux_fli_t *) this_gen; - return this->status; -} - -static char *demux_fli_get_id(void) { - return "FLI"; + return (this->thread_running?DEMUX_OK:DEMUX_FINISHED); } static int demux_fli_get_stream_length (demux_plugin_t *this_gen) { @@ -414,41 +356,141 @@ static int demux_fli_get_stream_length (demux_plugin_t *this_gen) { return 0; } -static char *demux_fli_get_mimetypes(void) { - return NULL; -} +static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, + input_plugin_t *input_gen) { -static void *init_demuxer_plugin(xine_t *xine, void *data) { - demux_fli_t *this; + input_plugin_t *input = (input_plugin_t *) input_gen; + demux_fli_t *this; - this = (demux_fli_t *) xine_xmalloc(sizeof(demux_fli_t)); - this->config = xine->config; - this->xine = xine; + if (! (input->get_capabilities(input) & INPUT_CAP_SEEKABLE)) { + printf(_("demux_fli.c: input not seekable, can not handle!\n")); + return NULL; + } - (void *) this->config->register_string(this->config, - "mrl.ends_fli", VALID_ENDS, - "valid mrls ending for fli demuxer", - NULL, 10, NULL, NULL); + this = xine_xmalloc (sizeof (demux_fli_t)); + this->stream = stream; + this->input = input; - this->demux_plugin.open = demux_fli_open; + this->demux_plugin.send_headers = demux_fli_send_headers; this->demux_plugin.start = demux_fli_start; this->demux_plugin.seek = demux_fli_seek; this->demux_plugin.stop = demux_fli_stop; this->demux_plugin.dispose = demux_fli_dispose; this->demux_plugin.get_status = demux_fli_get_status; - this->demux_plugin.get_identifier = demux_fli_get_id; this->demux_plugin.get_stream_length = demux_fli_get_stream_length; - this->demux_plugin.get_mimetypes = demux_fli_get_mimetypes; + this->demux_plugin.demux_class = class_gen; + + this->status = DEMUX_FINISHED; + pthread_mutex_init (&this->mutex, NULL); + + switch (stream->content_detection_method) { + + case METHOD_BY_CONTENT: + + if (!open_fli_file(this)) { + free (this); + return NULL; + } + + break; + + case METHOD_BY_EXTENSION: { + char *ending, *mrl; + + mrl = input->get_mrl (input); + + ending = strrchr(mrl, '.'); + + if (!ending) { + free (this); + return NULL; + } + + if (strncasecmp (ending, ".fli", 4) && + strncasecmp (ending, ".flc", 4)) { + free (this); + return NULL; + } + + if (!open_fli_file(this)) { + free (this); + return NULL; + } + + } + + break; + + default: + free (this); + return NULL; + } + + strncpy (this->last_mrl, input->get_mrl (input), 1024); + + /* print vital stats */ + xine_log (this->stream->xine, XINE_LOG_MSG, + _("demux_fli: FLI type: %04X, speed: %d/%d\n"), + this->magic_number, this->speed, + (this->magic_number == FLI_FILE_MAGIC_1) ? 70 : 1000); + xine_log (this->stream->xine, XINE_LOG_MSG, + _("demux_fli: %d frames, %dx%d\n"), + this->frame_count, this->width, this->height); + xine_log (this->stream->xine, XINE_LOG_MSG, + _("demux_fli: running time: %d min, %d sec\n"), + this->frame_count * this->frame_pts_inc / 90000 / 60, + this->frame_count * this->frame_pts_inc / 90000 % 60); return &this->demux_plugin; } +static char *get_description (demux_class_t *this_gen) { + return "Autodesk Animator FLI/FLC demux plugin"; +} + +static char *get_identifier (demux_class_t *this_gen) { + return "FLI/FLC"; +} + +static char *get_extensions (demux_class_t *this_gen) { + return "fli,flc"; +} + +static char *get_mimetypes (demux_class_t *this_gen) { + return NULL; +} + +static void class_dispose (demux_class_t *this_gen) { + + demux_fli_class_t *this = (demux_fli_class_t *) this_gen; + + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) { + + demux_fli_class_t *this; + + this = xine_xmalloc (sizeof (demux_fli_class_t)); + this->config = xine->config; + this->xine = xine; + + this->demux_class.open_plugin = open_plugin; + this->demux_class.get_description = get_description; + this->demux_class.get_identifier = get_identifier; + this->demux_class.get_mimetypes = get_mimetypes; + this->demux_class.get_extensions = get_extensions; + this->demux_class.dispose = class_dispose; + + return this; +} + /* * exported plugin catalog entry */ plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 11, "fli", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 14, "fli", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/libxinevdec/fli.c b/src/libxinevdec/fli.c index 9cf7a9142..47cb8028d 100644 --- a/src/libxinevdec/fli.c +++ b/src/libxinevdec/fli.c @@ -23,7 +23,7 @@ * avoid when implementing a FLI decoder, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: fli.c,v 1.7 2002/10/06 03:48:13 komadori Exp $ + * $Id: fli.c,v 1.8 2002/10/23 03:21:20 tmmm Exp $ */ #include <stdio.h> @@ -55,11 +55,17 @@ * fli specific decode functions *************************************************************************/ +typedef struct { + video_decoder_class_t decoder_class; +} fli_class_t; + typedef struct fli_decoder_s { video_decoder_t video_decoder; /* parent video decoder structure */ + fli_class_t *class; + xine_stream_t *stream; + /* these are traditional variables in a video decoder object */ - vo_instance_t *video_out; /* object that will receive frames */ uint64_t video_step; /* frame duration in pts units */ int decoder_ok; /* current decoder status */ int skipframes; @@ -401,22 +407,6 @@ void decode_fli_frame(fli_decoder_t *this) { *************************************************************************/ /* - * This function is responsible is called to initialize the video decoder - * for use. Initialization usually involves setting up the fields in your - * private video decoder object. - */ -static void fli_init (video_decoder_t *this_gen, - vo_instance_t *video_out) { - fli_decoder_t *this = (fli_decoder_t *) this_gen; - - /* set our own video_out object to the one that xine gives us */ - this->video_out = video_out; - - /* indicate that the decoder is not quite ready yet */ - this->decoder_ok = 0; -} - -/* * This function receives a buffer of data from the demuxer layer and * figures out how to handle it based on its header flags. */ @@ -431,7 +421,7 @@ static void fli_decode_data (video_decoder_t *this_gen, return; if (buf->decoder_flags & BUF_FLAG_HEADER) { /* need to initialize */ - this->video_out->open (this->video_out); + this->stream->video_out->open (this->stream->video_out); if(this->buf) free(this->buf); @@ -449,7 +439,7 @@ static void fli_decode_data (video_decoder_t *this_gen, this->buf = malloc(this->bufsize); this->size = 0; - this->video_out->open (this->video_out); + this->stream->video_out->open (this->stream->video_out); this->decoder_ok = 1; return; @@ -469,7 +459,7 @@ static void fli_decode_data (video_decoder_t *this_gen, if (buf->decoder_flags & BUF_FLAG_FRAME_END) { - img = this->video_out->get_frame (this->video_out, + img = this->stream->video_out->get_frame (this->stream->video_out, this->width, this->height, XINE_VO_ASPECT_DONT_TOUCH, XINE_IMGFMT_YUY2, VO_BOTH_FIELDS); @@ -517,11 +507,10 @@ static void fli_reset (video_decoder_t *this_gen) { } /* - * This function is called when xine shuts down the decoder. It should - * free any memory and release any other resources allocated during the - * execution of the decoder. + * This function frees the video decoder instance allocated to the decoder. */ -static void fli_close (video_decoder_t *this_gen) { +static void fli_dispose (video_decoder_t *this_gen) { + fli_decoder_t *this = (fli_decoder_t *) this_gen; if (this->buf) { @@ -534,44 +523,55 @@ static void fli_close (video_decoder_t *this_gen) { if (this->decoder_ok) { this->decoder_ok = 0; - this->video_out->close(this->video_out); + this->stream->video_out->close(this->stream->video_out); } -} - -/* - * This function returns the human-readable ID string to identify - * this decoder. - */ -static char *fli_get_id(void) { - return "FLI Video"; -} -/* - * This function frees the video decoder instance allocated to the decoder. - */ -static void fli_dispose (video_decoder_t *this_gen) { free (this_gen); } -/* - * This function should be the plugin's only advertised function to the - * outside world. It allows xine to query the plugin module for the addresses - * to the necessary functions in the video decoder object. - */ -static void *init_video_decoder_plugin (xine_t *xine, void *data) { +static video_decoder_t *open_plugin (video_decoder_class_t *class_gen, xine_stream_t *stream) { - fli_decoder_t *this ; + fli_decoder_t *this ; - this = (fli_decoder_t *) malloc (sizeof (fli_decoder_t)); - memset(this, 0, sizeof (fli_decoder_t)); + this = (fli_decoder_t *) xine_xmalloc (sizeof (fli_decoder_t)); - this->video_decoder.init = fli_init; this->video_decoder.decode_data = fli_decode_data; this->video_decoder.flush = fli_flush; this->video_decoder.reset = fli_reset; - this->video_decoder.close = fli_close; - this->video_decoder.get_identifier = fli_get_id; this->video_decoder.dispose = fli_dispose; + this->size = 0; + + this->stream = stream; + this->class = (fli_class_t *) class_gen; + + this->decoder_ok = 0; + this->buf = NULL; + + return &this->video_decoder; +} + +static char *get_identifier (video_decoder_class_t *this) { + return "FLI Video"; +} + +static char *get_description (video_decoder_class_t *this) { + return "Autodesk Animator FLI/FLC video decoder plugin"; +} + +static void dispose_class (video_decoder_class_t *this) { + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) { + + fli_class_t *this; + + this = (fli_class_t *) xine_xmalloc (sizeof (fli_class_t)); + + this->decoder_class.open_plugin = open_plugin; + this->decoder_class.get_identifier = get_identifier; + this->decoder_class.get_description = get_description; + this->decoder_class.dispose = dispose_class; return this; } @@ -587,12 +587,12 @@ static uint32_t video_types[] = { static decoder_info_t dec_info_video = { video_types, /* supported types */ - 1 /* priority */ + 5 /* priority */ }; plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_VIDEO_DECODER, 10, "fli", XINE_VERSION_CODE, &dec_info_video, init_video_decoder_plugin }, + { PLUGIN_VIDEO_DECODER, 11, "fli", XINE_VERSION_CODE, &dec_info_video, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |