diff options
-rw-r--r-- | src/demuxers/Makefile.am | 29 | ||||
-rw-r--r-- | src/demuxers/demux_cda.c | 42 | ||||
-rw-r--r-- | src/demuxers/demux_smjpeg.c | 235 | ||||
-rw-r--r-- | src/demuxers/demux_vqa.c | 225 |
4 files changed, 297 insertions, 234 deletions
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 8aed0cb13..249afd797 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -37,11 +37,12 @@ endif lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(qt_modules) xineplug_dmx_avi.la\ xineplug_dmx_mpeg_block.la xineplug_dmx_mpeg.la \ xineplug_dmx_mpeg_elem.la xineplug_dmx_mpeg_audio.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_fli.la \ - xineplug_dmx_roq.la + xineplug_dmx_cda.la xineplug_dmx_film.la \ + xineplug_dmx_roq.la xineplug_dmx_fli.la \ + xineplug_dmx_smjpeg.la xineplug_dmx_wav.la \ + xineplug_dmx_idcin.la xineplug_dmx_wc3movie.la \ + xineplug_dmx_vqa.la xineplug_dmx_voc.la \ + xineplug_dmx_aiff.la xineplug_dmx_snd.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c xineplug_dmx_ogg_la_LIBADD = $(OGG_LIBS) $(VORBIS_LIBS)\ @@ -84,9 +85,9 @@ xineplug_dmx_asf_la_SOURCES = demux_asf.c xineplug_dmx_asf_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la xineplug_dmx_asf_la_LDFLAGS = -avoid-version -module -#xineplug_dmx_cda_la_SOURCES = demux_cda.c -#xineplug_dmx_cda_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -#xineplug_dmx_cda_la_LDFLAGS = -avoid-version -module +xineplug_dmx_cda_la_SOURCES = demux_cda.c +xineplug_dmx_cda_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +xineplug_dmx_cda_la_LDFLAGS = -avoid-version -module xineplug_dmx_film_la_SOURCES = demux_film.c xineplug_dmx_film_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la @@ -100,9 +101,9 @@ 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 -#xineplug_dmx_smjpeg_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 +xineplug_dmx_smjpeg_la_LDFLAGS = -avoid-version -module xineplug_dmx_wav_la_SOURCES = demux_wav.c xineplug_dmx_wav_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la @@ -116,9 +117,9 @@ xineplug_dmx_wc3movie_la_SOURCES = demux_wc3movie.c xineplug_dmx_wc3movie_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la xineplug_dmx_wc3movie_la_LDFLAGS = -avoid-version -module -#xineplug_dmx_vqa_la_SOURCES = demux_vqa.c -#xineplug_dmx_vqa_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la -#xineplug_dmx_vqa_la_LDFLAGS = -avoid-version -module +xineplug_dmx_vqa_la_SOURCES = demux_vqa.c +xineplug_dmx_vqa_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la +xineplug_dmx_vqa_la_LDFLAGS = -avoid-version -module xineplug_dmx_voc_la_SOURCES = demux_voc.c xineplug_dmx_voc_la_LIBADD = $(top_builddir)/src/xine-engine/libxine.la diff --git a/src/demuxers/demux_cda.c b/src/demuxers/demux_cda.c index 19311f007..efbb0d3b1 100644 --- a/src/demuxers/demux_cda.c +++ b/src/demuxers/demux_cda.c @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: demux_cda.c,v 1.24 2002/09/10 15:07:13 mroi Exp $ + * $Id: demux_cda.c,v 1.25 2002/09/21 20:27:02 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -170,8 +170,6 @@ static int demux_cda_get_status (demux_plugin_t *this_gen) { * */ static int demux_cda_start (demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, off_t start_pos, int start_time) { demux_cda_t *this = (demux_cda_t *) this_gen; int err; @@ -184,9 +182,6 @@ static int demux_cda_start (demux_plugin_t *this_gen, this->blocksize = this->input->get_blocksize(this->input); if( !this->thread_running ) { - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - xine_demux_control_start(this->xine); } @@ -218,15 +213,38 @@ static int demux_cda_start (demux_plugin_t *this_gen, static int demux_cda_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time) { - demux_cda_t *this = (demux_cda_t *) this_gen; - return demux_cda_start (this_gen, this->video_fifo, this->audio_fifo, + return demux_cda_start (this_gen, start_pos, start_time); } /* * */ +static int demux_cda_send_headers(demux_cda_t *this) { + + pthread_mutex_lock(&this->mutex); + + this->video_fifo = this->xine->video_fifo; + this->audio_fifo = this->xine->audio_fifo; + + this->status = DEMUX_OK; + + /* hardwired stream information */ + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = 2; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = 44100; + 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_cda_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { demux_cda_t *this = (demux_cda_t *) this_gen; @@ -244,7 +262,7 @@ static int demux_cda_open(demux_plugin_t *this_gen, input_plugin_t *input, int s if(media) { if(!strncasecmp(MRL, "cda", 3)) { this->input = input; - return DEMUX_CAN_HANDLE; + return demux_cda_send_headers(this); } } } @@ -275,7 +293,7 @@ static char *demux_cda_get_mimetypes(void) { /* * */ -static void demux_cda_close (demux_plugin_t *this) { +static void demux_cda_dispose (demux_plugin_t *this) { free (this); } @@ -301,7 +319,7 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { this->demux_plugin.start = demux_cda_start; this->demux_plugin.seek = demux_cda_seek; this->demux_plugin.stop = demux_cda_stop; - this->demux_plugin.close = demux_cda_close; + this->demux_plugin.dispose = demux_cda_dispose; this->demux_plugin.get_status = demux_cda_get_status; this->demux_plugin.get_identifier = demux_cda_get_id; this->demux_plugin.get_stream_length = demux_cda_get_stream_length; @@ -319,6 +337,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, "cda", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 11, "cda", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_smjpeg.c b/src/demuxers/demux_smjpeg.c index 2100959ee..ad3301bb2 100644 --- a/src/demuxers/demux_smjpeg.c +++ b/src/demuxers/demux_smjpeg.c @@ -21,7 +21,7 @@ * For more information on the SMJPEG file format, visit: * http://www.lokigames.com/development/smjpeg.php3 * - * $Id: demux_smjpeg.c,v 1.14 2002/09/10 15:07:14 mroi Exp $ + * $Id: demux_smjpeg.c,v 1.15 2002/09/21 20:27:02 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -249,6 +249,124 @@ static void *demux_smjpeg_loop (void *this_gen) { return NULL; } +static int load_smjpeg_and_send_headers(demux_smjpeg_t *this) { + + unsigned int chunk_tag; + unsigned char header_chunk[SMJPEG_HEADER_CHUNK_MAX_SIZE]; + + pthread_mutex_lock(&this->mutex); + + this->video_fifo = this->xine->video_fifo; + this->audio_fifo = this->xine->audio_fifo; + + this->status = DEMUX_OK; + + /* initial state: no video and no audio (until headers found) */ + this->video_type = this->audio_type = 0; + this->input_length = this->input->get_length (this->input); + + /* jump over the signature and version to the duration */ + this->input->seek(this->input, 12, SEEK_SET); + if (this->input->read(this->input, header_chunk, 4) != 4) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + this->duration = BE_32(&header_chunk[0]); + + /* traverse the header chunks until the HEND tag is found */ + chunk_tag = 0; + while (chunk_tag != HEND_TAG) { + + if (this->input->read(this->input, header_chunk, 4) != 4) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_FINISHED; + } + chunk_tag = BE_32(&header_chunk[0]); + + switch(chunk_tag) { + + case HEND_TAG: + /* this indicates the end of the header; do nothing and fall + * out of the loop on the next iteration */ + break; + + case _VID_TAG: + if (this->input->read(this->input, header_chunk, + SMJPEG_VIDEO_HEADER_SIZE) != SMJPEG_VIDEO_HEADER_SIZE) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + + this->bih.biWidth = BE_16(&header_chunk[8]); + this->bih.biHeight = BE_16(&header_chunk[10]); + this->bih.biCompression = *(uint32_t *)&header_chunk[12]; + this->video_type = fourcc_to_buf_video(this->bih.biCompression); + break; + + case _SND_TAG: + if (this->input->read(this->input, header_chunk, + SMJPEG_AUDIO_HEADER_SIZE) != SMJPEG_AUDIO_HEADER_SIZE) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + + this->audio_sample_rate = BE_16(&header_chunk[4]); + this->audio_bits = header_chunk[6]; + this->audio_channels = header_chunk[7]; + /* ADPCM in these files is ID'd by 'APCM' which is used in other + * files to denote a slightly different format; thus, use the + * following special case */ + if (BE_32(&header_chunk[8]) == APCM_TAG) { + this->audio_codec = be2me_32(APCM_TAG); + this->audio_type = BUF_AUDIO_SMJPEG_IMA; + } else { + this->audio_codec = *(uint32_t *)&header_chunk[8]&header_chunk[8]; + this->audio_type = formattag_to_buf_audio(this->audio_codec); + } + break; + + default: + /* for all other chunk types, read the length and skip the rest + * of the chunk */ + if (this->input->read(this->input, header_chunk, 4) != 4) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + this->input->seek(this->input, BE_32(&header_chunk[0]), SEEK_CUR); + break; + } + } + + if(!this->video_type) + xine_report_codec(this->xine, XINE_CODEC_VIDEO, + this->bih.biCompression, 0, 0); + + if(!this->audio_type && this->audio_codec) + xine_report_codec(this->xine, XINE_CODEC_AUDIO, + this->audio_codec, 0, 0); + + /* load stream information */ + this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->bih.biWidth; + this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->bih.biHeight; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = + this->audio_channels; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = + this->audio_sample_rate; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = + this->audio_bits; + + xine_demux_control_headers_done (this->xine); + + pthread_mutex_unlock (&this->mutex); + + return DEMUX_CAN_HANDLE; +} + static int demux_smjpeg_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen; @@ -275,7 +393,7 @@ static int demux_smjpeg_open(demux_plugin_t *this_gen, input_plugin_t *input, (signature[5] == 'P') && (signature[6] == 'E') && (signature[7] == 'G')) - return DEMUX_CAN_HANDLE; + return load_smjpeg_and_send_headers(this); return DEMUX_CANNOT_HANDLE; } @@ -301,10 +419,8 @@ static int demux_smjpeg_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_smjpeg_and_send_headers(this); } return DEMUX_CANNOT_HANDLE; } @@ -320,13 +436,9 @@ static int demux_smjpeg_open(demux_plugin_t *this_gen, input_plugin_t *input, } static int demux_smjpeg_start (demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, off_t start_pos, int start_time) { demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen; - unsigned int chunk_tag; - unsigned char header_chunk[SMJPEG_HEADER_CHUNK_MAX_SIZE]; buf_element_t *buf; int err; @@ -334,105 +446,14 @@ static int demux_smjpeg_start (demux_plugin_t *this_gen, /* if thread is not running, initialize demuxer */ if (!this->thread_running) { - this->video_fifo = video_fifo; - this->audio_fifo = audio_fifo; - - /* initial state: no video and no audio (until headers found) */ - this->video_type = this->audio_type = 0; - this->input_length = this->input->get_length (this->input); - - /* jump over the signature and version to the duration */ - this->input->seek(this->input, 12, SEEK_SET); - if (this->input->read(this->input, header_chunk, 4) != 4) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - this->duration = BE_32(&header_chunk[0]); - - /* traverse the header chunks until the HEND tag is found */ - chunk_tag = 0; - while (chunk_tag != HEND_TAG) { - - if (this->input->read(this->input, header_chunk, 4) != 4) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - chunk_tag = BE_32(&header_chunk[0]); - - switch(chunk_tag) { - - case HEND_TAG: - /* this indicates the end of the header; do nothing and fall - * out of the loop on the next iteration */ - break; - - case _VID_TAG: - if (this->input->read(this->input, header_chunk, - SMJPEG_VIDEO_HEADER_SIZE) != SMJPEG_VIDEO_HEADER_SIZE) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - - this->bih.biWidth = BE_16(&header_chunk[8]); - this->bih.biHeight = BE_16(&header_chunk[10]); - this->bih.biCompression = *(uint32_t *)&header_chunk[12]; - this->video_type = fourcc_to_buf_video(this->bih.biCompression); - break; - - case _SND_TAG: - if (this->input->read(this->input, header_chunk, - SMJPEG_AUDIO_HEADER_SIZE) != SMJPEG_AUDIO_HEADER_SIZE) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - - this->audio_sample_rate = BE_16(&header_chunk[4]); - this->audio_bits = header_chunk[6]; - this->audio_channels = header_chunk[7]; - /* ADPCM in these files is ID'd by 'APCM' which is used in other - * files to denote a slightly different format; thus, use the - * following special case */ - if (BE_32(&header_chunk[8]) == APCM_TAG) { - this->audio_codec = be2me_32(APCM_TAG); - this->audio_type = BUF_AUDIO_SMJPEG_IMA; - } else { - this->audio_codec = *(uint32_t *)&header_chunk[8]&header_chunk[8]; - this->audio_type = formattag_to_buf_audio(this->audio_codec); - } - break; - - default: - /* for all other chunk types, read the length and skip the rest - * of the chunk */ - if (this->input->read(this->input, header_chunk, 4) != 4) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - this->input->seek(this->input, BE_32(&header_chunk[0]), SEEK_CUR); - break; - } - } - - if(!this->video_type) - xine_report_codec(this->xine, XINE_CODEC_VIDEO, - this->bih.biCompression, 0, 0); - - if(!this->audio_type && this->audio_codec) - xine_report_codec(this->xine, XINE_CODEC_AUDIO, - this->audio_codec, 0, 0); /* print vital stats */ - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_smjpeg: SMJPEG file, running time: %d min, %d sec\n"), this->duration / 1000 / 60, this->duration / 1000 % 60); if (this->video_type) - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_smjpeg: '%c%c%c%c' video @ %dx%d\n"), *((char *)&this->bih.biCompression + 0), *((char *)&this->bih.biCompression + 1), @@ -441,7 +462,7 @@ static int demux_smjpeg_start (demux_plugin_t *this_gen, this->bih.biWidth, this->bih.biHeight); if (this->audio_type) - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_smjpeg: '%c%c%c%c' audio @ %d Hz, %d bits, %d %s\n"), *((char *)&this->audio_codec + 0), *((char *)&this->audio_codec + 1), @@ -525,7 +546,7 @@ static void demux_smjpeg_stop (demux_plugin_t *this_gen) { xine_demux_control_end(this->xine, BUF_FLAG_END_USER); } -static void demux_smjpeg_close (demux_plugin_t *this_gen) { +static void demux_smjpeg_dispose (demux_plugin_t *this_gen) { demux_smjpeg_t *this = (demux_smjpeg_t *) this_gen; pthread_mutex_destroy (&this->mutex); @@ -569,7 +590,7 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { this->demux_plugin.start = demux_smjpeg_start; this->demux_plugin.seek = demux_smjpeg_seek; this->demux_plugin.stop = demux_smjpeg_stop; - this->demux_plugin.close = demux_smjpeg_close; + this->demux_plugin.dispose = demux_smjpeg_dispose; this->demux_plugin.get_status = demux_smjpeg_get_status; this->demux_plugin.get_identifier = demux_smjpeg_get_id; this->demux_plugin.get_stream_length = demux_smjpeg_get_stream_length; @@ -587,6 +608,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, "smjpeg", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 11, "smjpeg", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; diff --git a/src/demuxers/demux_vqa.c b/src/demuxers/demux_vqa.c index e6599a80b..4d272498f 100644 --- a/src/demuxers/demux_vqa.c +++ b/src/demuxers/demux_vqa.c @@ -21,7 +21,7 @@ * For more information regarding the VQA file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_vqa.c,v 1.6 2002/09/10 15:07:14 mroi Exp $ + * $Id: demux_vqa.c,v 1.7 2002/09/21 20:27:02 tmmm Exp $ */ #ifdef HAVE_CONFIG_H @@ -257,6 +257,119 @@ static void *demux_vqa_loop (void *this_gen) { return NULL; } +static int load_vqa_and_send_headers(demux_vqa_t *this) { + + unsigned char header[VQA_HEADER_SIZE]; + unsigned char *finf_chunk; + int i; + off_t last_offset; + uint64_t audio_pts_counter = 0; + uint64_t video_pts_counter = 0; + + pthread_mutex_lock(&this->mutex); + + this->video_fifo = this->xine->video_fifo; + this->audio_fifo = this->xine->audio_fifo; + + this->status = DEMUX_OK; + + /* get the file size (a.k.a., last offset) as reported by the file */ + this->input->seek(this->input, 4, SEEK_SET); + if (this->input->read(this->input, header, 4) != 4) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + last_offset = BE_32(&header[0]); + + /* get the actual filesize */ + this->filesize = this->input->get_length(this->input); + + /* skip to the VQA header */ + this->input->seek(this->input, 20, SEEK_SET); + if (this->input->read(this->input, header, VQA_HEADER_SIZE) + != VQA_HEADER_SIZE) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + + /* fetch the interesting information */ + this->total_frames = LE_16(&header[4]); + this->video_width = LE_16(&header[6]); + this->video_height = LE_16(&header[8]); + this->vector_width = header[10]; + this->vector_height = header[11]; + this->audio_sample_rate = LE_16(&header[24]); + this->audio_channels = header[26]; + + /* fetch the chunk table */ + this->input->seek(this->input, 8, SEEK_CUR); /* skip FINF and length */ + finf_chunk = xine_xmalloc(this->total_frames * 4); + this->frame_table = xine_xmalloc(this->total_frames * sizeof(vqa_frame_t)); + if (this->input->read(this->input, finf_chunk, this->total_frames * 4) != + this->total_frames * 4) { + this->status = DEMUX_FINISHED; + pthread_mutex_unlock(&this->mutex); + return DEMUX_CANNOT_HANDLE; + } + for (i = 0; i < this->total_frames; i++) { + this->frame_table[i].frame_offset = (LE_32(&finf_chunk[i * 4]) * 2) & + 0x03FFFFFF; + if (i < this->total_frames - 1) + this->frame_table[i].frame_size = LE_32(&finf_chunk[(i + 1) * 4]) * 2 - + this->frame_table[i].frame_offset; + else + this->frame_table[i].frame_size = last_offset - + this->frame_table[i].frame_offset; + + /* + * VQA files play at a constant rate of 15 frames/second. The file data + * begins with 1/15 sec of compressed audio followed by 1 video frame + * that will be displayed for 1/15 sec. + * + * xine pts frame # + * -------- = ------- => xine pts = 90000 * frame # / 15 + * 90000 15 + * + * Thus, each frame has a duration of 90000 / 15 (VQA_PTS_INC, in + * this code). + * + * If this is the first frame in the file, it contains 1/2 sec + * of audio and no video. Each successive frame represents 1/15 sec. + */ + if (i == 0) { + this->frame_table[i].audio_pts = 0; + this->frame_table[i].video_pts = 0; + audio_pts_counter += (90000 / 2); + } else { + this->frame_table[i].audio_pts = audio_pts_counter; + this->frame_table[i].video_pts = video_pts_counter; + audio_pts_counter += VQA_PTS_INC; + video_pts_counter += VQA_PTS_INC; + } + } + + this->total_time = this->frame_table[this->total_frames - 1].video_pts / + 90000; + + /* load stream information */ + this->xine->stream_info[XINE_STREAM_INFO_VIDEO_WIDTH] = this->video_width; + this->xine->stream_info[XINE_STREAM_INFO_VIDEO_HEIGHT] = this->video_height; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = + this->audio_channels; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = + this->audio_sample_rate; + this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = + this->audio_bits; + + xine_demux_control_headers_done (this->xine); + + pthread_mutex_unlock (&this->mutex); + + return DEMUX_CAN_HANDLE; +} + static int demux_vqa_open(demux_plugin_t *this_gen, input_plugin_t *input, int stage) { demux_vqa_t *this = (demux_vqa_t *) this_gen; @@ -276,7 +389,7 @@ static int demux_vqa_open(demux_plugin_t *this_gen, input_plugin_t *input, /* check for the VQA signatures */ if ((BE_32(&header[0]) == FORM_TAG) && (BE_32(&header[8]) == WVQA_TAG)) - return DEMUX_CAN_HANDLE; + return load_vqa_and_send_headers(this); return DEMUX_CANNOT_HANDLE; } @@ -302,10 +415,8 @@ static int demux_vqa_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_vqa_and_send_headers(this); } return DEMUX_CANNOT_HANDLE; } @@ -321,113 +432,23 @@ static int demux_vqa_open(demux_plugin_t *this_gen, input_plugin_t *input, } static int demux_vqa_start (demux_plugin_t *this_gen, - fifo_buffer_t *video_fifo, - fifo_buffer_t *audio_fifo, off_t start_pos, int start_time) { demux_vqa_t *this = (demux_vqa_t *) this_gen; buf_element_t *buf; int err; - unsigned char header[VQA_HEADER_SIZE]; - unsigned char *finf_chunk; - int i; - off_t last_offset; - uint64_t audio_pts_counter = 0; - uint64_t video_pts_counter = 0; 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; - - /* get the file size (a.k.a., last offset) as reported by the file */ - this->input->seek(this->input, 4, SEEK_SET); - if (this->input->read(this->input, header, 4) != 4) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - last_offset = BE_32(&header[0]); - - /* get the actual filesize */ - this->filesize = this->input->get_length(this->input); - - /* skip to the VQA header */ - this->input->seek(this->input, 20, SEEK_SET); - if (this->input->read(this->input, header, VQA_HEADER_SIZE) - != VQA_HEADER_SIZE) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - - /* fetch the interesting information */ - this->total_frames = LE_16(&header[4]); - this->video_width = LE_16(&header[6]); - this->video_height = LE_16(&header[8]); - this->vector_width = header[10]; - this->vector_height = header[11]; - this->audio_sample_rate = LE_16(&header[24]); - this->audio_channels = header[26]; - - /* fetch the chunk table */ - this->input->seek(this->input, 8, SEEK_CUR); /* skip FINF and length */ - finf_chunk = xine_xmalloc(this->total_frames * 4); - this->frame_table = xine_xmalloc(this->total_frames * sizeof(vqa_frame_t)); - if (this->input->read(this->input, finf_chunk, this->total_frames * 4) != - this->total_frames * 4) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_FINISHED; - } - for (i = 0; i < this->total_frames; i++) { - this->frame_table[i].frame_offset = (LE_32(&finf_chunk[i * 4]) * 2) & - 0x03FFFFFF; - if (i < this->total_frames - 1) - this->frame_table[i].frame_size = LE_32(&finf_chunk[(i + 1) * 4]) * 2 - - this->frame_table[i].frame_offset; - else - this->frame_table[i].frame_size = last_offset - - this->frame_table[i].frame_offset; - - /* - * VQA files play at a constant rate of 15 frames/second. The file data - * begins with 1/15 sec of compressed audio followed by 1 video frame - * that will be displayed for 1/15 sec. - * - * xine pts frame # - * -------- = ------- => xine pts = 90000 * frame # / 15 - * 90000 15 - * - * Thus, each frame has a duration of 90000 / 15 (VQA_PTS_INC, in - * this code). - * - * If this is the first frame in the file, it contains 1/2 sec - * of audio and no video. Each successive frame represents 1/15 sec. - */ - if (i == 0) { - this->frame_table[i].audio_pts = 0; - this->frame_table[i].video_pts = 0; - audio_pts_counter += (90000 / 2); - } else { - this->frame_table[i].audio_pts = audio_pts_counter; - this->frame_table[i].video_pts = video_pts_counter; - audio_pts_counter += VQA_PTS_INC; - video_pts_counter += VQA_PTS_INC; - } - } - - this->total_time = this->frame_table[this->total_frames - 1].video_pts / - 90000; /* print vital stats */ - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_vqa: running time: %d min, %d sec\n"), this->total_time / 60, this->total_time % 60); - xine_log (this->xine, XINE_LOG_FORMAT, + xine_log (this->xine, XINE_LOG_MSG, _("demux_vqa: %dx%d VQA video; %d-channel %d Hz IMA ADPCM audio\n"), this->video_width, this->video_height, @@ -496,6 +517,8 @@ static int demux_vqa_start (demux_plugin_t *this_gen, static int demux_vqa_seek (demux_plugin_t *this_gen, off_t start_pos, int start_time) { + /* VQA files are not built for seeking; don't even bother */ + return 0; } @@ -522,7 +545,7 @@ static void demux_vqa_stop (demux_plugin_t *this_gen) { xine_demux_control_end(this->xine, BUF_FLAG_END_USER); } -static void demux_vqa_close (demux_plugin_t *this_gen) { +static void demux_vqa_dispose (demux_plugin_t *this_gen) { demux_vqa_t *this = (demux_vqa_t *) this_gen; @@ -566,7 +589,7 @@ static void *init_demuxer_plugin(xine_t *xine, void *data) { this->demux_plugin.start = demux_vqa_start; this->demux_plugin.seek = demux_vqa_seek; this->demux_plugin.stop = demux_vqa_stop; - this->demux_plugin.close = demux_vqa_close; + this->demux_plugin.dispose = demux_vqa_dispose; this->demux_plugin.get_status = demux_vqa_get_status; this->demux_plugin.get_identifier = demux_vqa_get_id; this->demux_plugin.get_stream_length = demux_vqa_get_stream_length; @@ -584,6 +607,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, "vqa", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 11, "vqa", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |