From edf1b64352975453748234e127a766c9f875ad6e Mon Sep 17 00:00:00 2001 From: Mike Melanson Date: Sat, 21 Sep 2002 19:47:11 +0000 Subject: bring the FLI and RoQ demuxers up to the new API spec CVS patchset: 2734 CVS date: 2002/09/21 19:47:11 --- src/demuxers/Makefile.am | 15 ++-- src/demuxers/demux_fli.c | 123 +++++++++++++++------------ src/demuxers/demux_roq.c | 217 +++++++++++++++++++++++++---------------------- 3 files changed, 194 insertions(+), 161 deletions(-) diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 7792faae6..8aed0cb13 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -40,7 +40,8 @@ lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(qt_modules) xineplug_dmx_avi.la\ xineplug_dmx_film.la xineplug_dmx_wav.la \ xineplug_dmx_aiff.la xineplug_dmx_voc.la \ xineplug_dmx_snd.la xineplug_dmx_idcin.la \ - xineplug_dmx_wc3movie.la + xineplug_dmx_wc3movie.la xineplug_dmx_fli.la \ + xineplug_dmx_roq.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS)\ @@ -91,13 +92,13 @@ xineplug_dmx_film_la_SOURCES = demux_film.c xineplug_dmx_film_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la xineplug_dmx_film_la_LDFLAGS = -avoid-version -module -#xineplug_dmx_roq_la_SOURCES = demux_roq.c -#xineplug_dmx_roq_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -#xineplug_dmx_roq_la_LDFLAGS = -avoid-version -module +xineplug_dmx_roq_la_SOURCES = demux_roq.c +xineplug_dmx_roq_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +xineplug_dmx_roq_la_LDFLAGS = -avoid-version -module -#xineplug_dmx_fli_la_SOURCES = demux_fli.c -#xineplug_dmx_fli_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -#xineplug_dmx_fli_la_LDFLAGS = -avoid-version -module +xineplug_dmx_fli_la_SOURCES = demux_fli.c +xineplug_dmx_fli_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +xineplug_dmx_fli_la_LDFLAGS = -avoid-version -module #xineplug_dmx_smjpeg_la_SOURCES = demux_smjpeg.c #xineplug_dmx_smjpeg_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la diff --git a/src/demuxers/demux_fli.c b/src/demuxers/demux_fli.c index c80e36f11..99e880711 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.10 2002/09/10 15:07:14 mroi Exp $ + * $Id: demux_fli.c,v 1.11 2002/09/21 19:47:11 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -76,6 +76,7 @@ typedef struct { /* video information */ unsigned int width; unsigned int height; + unsigned char fli_header[FLI_HEADER_SIZE]; /* playback info */ unsigned int magic_number; @@ -183,6 +184,64 @@ static void *demux_fli_loop (void *this_gen) { return NULL; } +static int load_fli_and_send_headers(demux_fli_t *this) { + + pthread_mutex_lock(&this->mutex); + + this->video_fifo = this->xine->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); + + return DEMUX_CAN_HANDLE; +} + static int demux_fli_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { @@ -204,7 +263,7 @@ static int demux_fli_open(demux_plugin_t *this_gen, input_plugin_t *input, magic_number = LE_16(&sig[0]); if ((magic_number == FLI_FILE_MAGIC_1) || (magic_number == FLI_FILE_MAGIC_2)) - return DEMUX_CAN_HANDLE; + return load_fli_and_send_headers(this); return DEMUX_CANNOT_HANDLE; } @@ -230,10 +289,8 @@ static int demux_fli_open(demux_plugin_t *this_gen, input_plugin_t *input, while(*m == ' ' || *m == '\t') m++; - if(!strcasecmp((suffix + 1), m)) { - this->input = input; - return DEMUX_CAN_HANDLE; - } + if(!strcasecmp((suffix + 1), m)) + return load_fli_and_send_headers(this); } return DEMUX_CANNOT_HANDLE; } @@ -249,66 +306,26 @@ static int demux_fli_open(demux_plugin_t *this_gen, input_plugin_t *input, } static int demux_fli_start (demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, off_t start_pos, int start_time) { demux_fli_t *this = (demux_fli_t *) this_gen; buf_element_t *buf; int err; - unsigned char fli_header[FLI_HEADER_SIZE]; pthread_mutex_lock(&this->mutex); /* if thread is not running, initialize demuxer */ if (!this->thread_running) { - this->video_fifo = video_fifo; - - /* read the whole header */ - this->input->seek(this->input, 0, SEEK_SET); - if (this->input->read(this->input, fli_header, FLI_HEADER_SIZE) != - FLI_HEADER_SIZE) { - return DEMUX_FINISHED; - } - - this->magic_number = LE_16(&fli_header[4]); - this->frame_count = LE_16(&fli_header[6]); - this->width = LE_16(&fli_header[8]); - this->height = LE_16(&fli_header[10]); - this->speed = LE_32(&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; - } /* print vital stats */ - xine_log (this->xine, XINE_LOG_FORMAT, + 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_FORMAT, + 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_FORMAT, + 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); @@ -325,7 +342,7 @@ static int demux_fli_start (demux_plugin_t *this_gen, 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, fli_header, FLI_HEADER_SIZE); + 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); @@ -378,7 +395,7 @@ static void demux_fli_stop (demux_plugin_t *this_gen) { xine_demux_control_end(this->xine, BUF_FLAG_END_USER); } -static void demux_fli_close (demux_plugin_t *this) { +static void demux_fli_dispose (demux_plugin_t *this) { free(this); } @@ -417,7 +434,7 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { this->demux_plugin.start = demux_fli_start; this->demux_plugin.seek = demux_fli_seek; this->demux_plugin.stop = demux_fli_stop; - this->demux_plugin.close = demux_fli_close; + 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; @@ -432,6 +449,6 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 10, "fli", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 11, "fli", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c index 5e90198c6..c0904acc2 100644 --- a/src/demuxers/demux_roq.c +++ b/src/demuxers/demux_roq.c @@ -21,7 +21,7 @@ * For more information regarding the RoQ file format, visit: * http://www.csse.monash.edu.au/~timf/ * - * $Id: demux_roq.c,v 1.14 2002/09/10 15:07:14 mroi Exp $ + * $Id: demux_roq.c,v 1.15 2002/09/21 19:47:11 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -124,7 +124,6 @@ static void *demux_roq_loop (void *this_gen) { /* adjust the chunk size */ chunk_size += RoQ_CHUNK_PREAMBLE_SIZE; - if( this->audio_fifo ) { /* do this calculation carefully because I can't trust the @@ -158,7 +157,6 @@ static void *demux_roq_loop (void *this_gen) { if (!chunk_size) buf->decoder_flags |= BUF_FLAG_FRAME_END; this->audio_fifo->put(this->audio_fifo, buf); -//printf ("audio packet pts = %lld\n", buf->pts); } } else { /* no audio -> skip chunk */ @@ -191,7 +189,6 @@ static void *demux_roq_loop (void *this_gen) { } /* packetize the video chunk and route it to the video fifo */ -//printf ("total video chunk size = %X\n", chunk_size); while (chunk_size) { buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); buf->type = BUF_VIDEO_ROQ; @@ -213,8 +210,6 @@ static void *demux_roq_loop (void *this_gen) { if (!chunk_size) buf->decoder_flags |= BUF_FLAG_FRAME_END; this->video_fifo->put(this->video_fifo, buf); -//printf ("loaded video packet with %X bytes, pts = %lld\n", -// buf->size, buf->pts); } video_pts_counter += this->frame_pts_inc; } else { @@ -250,6 +245,113 @@ static void *demux_roq_loop (void *this_gen) { return NULL; } +static int load_roq_and_send_headers(demux_roq_t *this) { + + char preamble[RoQ_CHUNK_PREAMBLE_SIZE]; + int i; + unsigned int chunk_type; + unsigned int chunk_size; + + pthread_mutex_lock(&this->mutex); + + this->video_fifo = this->xine->video_fifo; + this->audio_fifo = this->xine->audio_fifo; + + this->status = DEMUX_OK; + + this->input->seek(this->input, 0, SEEK_SET); + if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != + RoQ_CHUNK_PREAMBLE_SIZE) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + + this->width = this->height = 0; + this->audio_channels = 0; /* assume no audio at first */ + + /* + * RoQ files enjoy a constant framerate; pts calculation: + * + * xine pts frame # + * -------- = ------- => xine pts = 90000 * frame # / fps + * 90000 fps + * + * therefore, the frame pts increment is 90000 / fps + */ + this->fps = LE_16(&preamble[6]); + this->frame_pts_inc = 90000 / this->fps; + + /* iterate through the first 2 seconds worth of chunks searching for + * the RoQ_INFO chunk and an audio chunk */ + i = this->fps * 2; + while (i-- > 0) { + /* if this read fails, then maybe it's just a really small RoQ file + * (even less than 2 seconds) */ + if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != + RoQ_CHUNK_PREAMBLE_SIZE) + break; + chunk_type = LE_16(&preamble[0]); + chunk_size = LE_32(&preamble[2]); + + if (chunk_type == RoQ_INFO) { + /* fetch the width and height; reuse the preamble bytes */ + if (this->input->read(this->input, preamble, 8) != 8) + break; + + this->width = LE_16(&preamble[0]); + this->height = LE_16(&preamble[2]); + + /* if an audio chunk was already found, search is done */ + if (this->audio_channels) + break; + + /* prep the size for a seek */ + chunk_size -= 8; + } else { + /* if it was an audio chunk and the info chunk has already been + * found (as indicated by width and height) then break */ + if (chunk_type == RoQ_SOUND_MONO) { + this->audio_channels = 1; + if (this->width && this->height) + break; + } else if (chunk_type == RoQ_SOUND_STEREO) { + this->audio_channels = 2; + if (this->width && this->height) + break; + } + } + + /* skip the rest of the chunk */ + this->input->seek(this->input, chunk_size, SEEK_CUR); + } + + /* after all is said and done, if there is a width and a height, + * regard it as being a valid file and reset to the first chunk */ + if (this->width && this->height) { + this->input->seek(this->input, 8, SEEK_SET); + } else { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + + /* 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; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = + this->audio_channels; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = + RoQ_AUDIO_SAMPLE_RATE; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = 16; + + xine_demux_control_headers_done (this->xine); + + pthread_mutex_unlock (&this->mutex); + + return DEMUX_CAN_HANDLE; +} + static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { demux_roq_t *this = (demux_roq_t *) this_gen; @@ -270,7 +372,7 @@ static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input, /* check for the RoQ magic numbers */ if ((LE_16(&preamble[0]) == RoQ_MAGIC_NUMBER) && (LE_32(&preamble[2]) == 0xFFFFFFFF)) - return DEMUX_CAN_HANDLE; + return load_roq_and_send_headers(this); return DEMUX_CANNOT_HANDLE; } @@ -296,10 +398,8 @@ static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input, while(*m == ' ' || *m == '\t') m++; - if(!strcasecmp((suffix + 1), m)) { - this->input = input; - return DEMUX_CAN_HANDLE; - } + if(!strcasecmp((suffix + 1), m)) + return load_roq_and_send_headers(this); } return DEMUX_CANNOT_HANDLE; } @@ -315,108 +415,23 @@ static int demux_roq_open(demux_plugin_t *this_gen, input_plugin_t *input, } static int demux_roq_start (demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, off_t start_pos, int start_time) { demux_roq_t *this = (demux_roq_t *) this_gen; buf_element_t *buf; int err; - char preamble[RoQ_CHUNK_PREAMBLE_SIZE]; - int i; - unsigned int chunk_type; - unsigned int chunk_size; pthread_mutex_lock(&this->mutex); /* if thread is not running, initialize demuxer */ if (!this->thread_running) { - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - - this->input->seek(this->input, 0, SEEK_SET); - if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != - RoQ_CHUNK_PREAMBLE_SIZE) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return this->status; - } - - this->width = this->height = 0; - this->audio_channels = 0; /* assume no audio at first */ - - /* - * RoQ files enjoy a constant framerate; pts calculation: - * - * xine pts frame # - * -------- = ------- => xine pts = 90000 * frame # / fps - * 90000 fps - * - * therefore, the frame pts increment is 90000 / fps - */ - this->fps = LE_16(&preamble[6]); - this->frame_pts_inc = 90000 / this->fps; - - /* iterate through the first 2 seconds worth of chunks searching for - * the RoQ_INFO chunk and an audio chunk */ - i = this->fps * 2; - while (i-- > 0) { - /* if this read fails, then maybe it's just a really small RoQ file - * (even less than 2 seconds) */ - if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) != - RoQ_CHUNK_PREAMBLE_SIZE) - break; - chunk_type = LE_16(&preamble[0]); - chunk_size = LE_32(&preamble[2]); - - if (chunk_type == RoQ_INFO) { - /* fetch the width and height; reuse the preamble bytes */ - if (this->input->read(this->input, preamble, 8) != 8) - break; - - this->width = LE_16(&preamble[0]); - this->height = LE_16(&preamble[2]); - - /* if an audio chunk was already found, search is done */ - if (this->audio_channels) - break; - - /* prep the size for a seek */ - chunk_size -= 8; - } else { - /* if it was an audio chunk and the info chunk has already been - * found (as indicated by width and height) then break */ - if (chunk_type == RoQ_SOUND_MONO) { - this->audio_channels = 1; - if (this->width && this->height) - break; - } else if (chunk_type == RoQ_SOUND_STEREO) { - this->audio_channels = 2; - if (this->width && this->height) - break; - } - } - - /* skip the rest of the chunk */ - this->input->seek(this->input, chunk_size, SEEK_CUR); - } - - /* after all is said and done, if there is a width and a height, - * regard it as being a valid file and reset to the first chunk */ - if (this->width && this->height) { - this->input->seek(this->input, 8, SEEK_SET); - } else { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return this->status; - } /* print vital stats */ - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_roq: RoQ file, video is %dx%d, %d frames/sec\n"), this->width, this->height, this->fps); if (this->audio_channels) - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_roq: 16-bit, 22050 Hz %s RoQ DPCM audio\n"), (this->audio_channels == 1) ? "monaural" : "stereo"); @@ -500,7 +515,7 @@ static void demux_roq_stop (demux_plugin_t *this_gen) { xine_demux_control_end(this->xine, BUF_FLAG_END_USER); } -static void demux_roq_close (demux_plugin_t *this) { +static void demux_roq_dispose (demux_plugin_t *this) { free(this); } @@ -540,7 +555,7 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { this->demux_plugin.start = demux_roq_start; this->demux_plugin.seek = demux_roq_seek; this->demux_plugin.stop = demux_roq_stop; - this->demux_plugin.close = demux_roq_close; + this->demux_plugin.dispose = demux_roq_dispose; this->demux_plugin.get_status = demux_roq_get_status; this->demux_plugin.get_identifier = demux_roq_get_id; this->demux_plugin.get_stream_length = demux_roq_get_stream_length; @@ -558,6 +573,6 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { plugin_info_t xine_plugin_info[] = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_DEMUX, 10, "roq", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 11, "roq", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; -- cgit v1.2.3