diff options
author | Mike Melanson <mike@multimedia.cx> | 2002-10-23 03:46:32 +0000 |
---|---|---|
committer | Mike Melanson <mike@multimedia.cx> | 2002-10-23 03:46:32 +0000 |
commit | a9421aeb3412500c17c63481cf0ec05aa0304232 (patch) | |
tree | 2c8491ac37af3d171aa9b0369c5110a36ac9d3c1 | |
parent | db7b8514d28d78565ee6299510eea12dd873214d (diff) | |
download | xine-lib-a9421aeb3412500c17c63481cf0ec05aa0304232.tar.gz xine-lib-a9421aeb3412500c17c63481cf0ec05aa0304232.tar.bz2 |
bring the WAV demuxer in line with the latest API revision
CVS patchset: 2951
CVS date: 2002/10/23 03:46:32
-rw-r--r-- | src/demuxers/demux_wav.c | 436 |
1 files changed, 235 insertions, 201 deletions
diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c index a7669e9f7..7a70df86d 100644 --- a/src/demuxers/demux_wav.c +++ b/src/demuxers/demux_wav.c @@ -20,7 +20,7 @@ * MS WAV File Demuxer by Mike Melanson (melanson@pcisys.net) * based on WAV specs that are available far and wide * - * $Id: demux_wav.c,v 1.18 2002/10/12 17:11:59 jkeil Exp $ + * $Id: demux_wav.c,v 1.19 2002/10/23 03:46:32 tmmm Exp $ * */ @@ -43,7 +43,6 @@ #include "buffer.h" #include "bswap.h" -#define VALID_ENDS "wav" #define WAV_SIGNATURE_SIZE 16 /* this is the hex value for 'data' */ #define data_TAG 0x61746164 @@ -53,7 +52,7 @@ typedef struct { demux_plugin_t demux_plugin; - xine_t *xine; + xine_stream_t *stream; config_values_t *config; @@ -76,8 +75,86 @@ typedef struct { off_t data_size; int seek_flag; /* this is set when a seek just occurred */ + + char last_mrl[1024]; } demux_wav_t; +typedef struct { + + demux_class_t demux_class; + + /* class-wide, global variables here */ + + xine_t *xine; + config_values_t *config; +} demux_wav_class_t; + +/* returns 1 if the WAV file was opened successfully, 0 otherwise */ +static int open_wav_file(demux_wav_t *this) { + + unsigned char signature[WAV_SIGNATURE_SIZE]; + unsigned int chunk_tag; + unsigned int chunk_size; + unsigned char chunk_preamble[8]; + + /* check the signature */ + this->input->seek(this->input, 0, SEEK_SET); + if (this->input->read(this->input, signature, WAV_SIGNATURE_SIZE) != + WAV_SIGNATURE_SIZE) + return 0; + + if ((signature[0] != 'R') || + (signature[1] != 'I') || + (signature[2] != 'F') || + (signature[3] != 'F') || + (signature[8] != 'W') || + (signature[9] != 'A') || + (signature[10] != 'V') || + (signature[11] != 'E') || + (signature[12] != 'f') || + (signature[13] != 'm') || + (signature[14] != 't') || + (signature[15] != ' ')) + return 0; + + /* go after the format structure */ + this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET); + if (this->input->read(this->input, + (unsigned char *)&this->wave_size, 4) != 4) + return 0; + this->wave_size = le2me_32(this->wave_size); + this->wave = (xine_waveformatex *) malloc( this->wave_size ); + + if (this->input->read(this->input, (void *)this->wave, this->wave_size) != + this->wave_size) + return 0; + xine_waveformatex_le2me(this->wave); + this->audio_type = formattag_to_buf_audio(this->wave->wFormatTag); + if(!this->audio_type) { + xine_report_codec(this->stream, XINE_CODEC_AUDIO, this->audio_type, 0, 0); + return 0; + } + + /* traverse through the chunks to find the 'data' chunk */ + this->data_start = this->data_size = 0; + while (this->data_start == 0) { + + if (this->input->read(this->input, chunk_preamble, 8) != 8) + return 0; + chunk_tag = LE_32(&chunk_preamble[0]); + chunk_size = LE_32(&chunk_preamble[4]); + + if (chunk_tag == data_TAG) { + this->data_start = this->input->get_current_pos(this->input); + this->data_size = chunk_size; + } else { + this->input->seek(this->input, chunk_size, SEEK_CUR); + } + } + + return 1; +} + static void *demux_wav_loop (void *this_gen) { demux_wav_t *this = (demux_wav_t *) this_gen; @@ -111,7 +188,7 @@ static void *demux_wav_loop (void *this_gen) { current_pts /= this->wave->nAvgBytesPerSec; if (this->seek_flag) { - xine_demux_control_newpts(this->xine, current_pts, 0); + xine_demux_control_newpts(this->stream, current_pts, 0); this->seek_flag = 0; } @@ -163,7 +240,7 @@ static void *demux_wav_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; @@ -171,149 +248,46 @@ static void *demux_wav_loop (void *this_gen) { return NULL; } -static int load_wav_and_send_headers(demux_wav_t *this) { +static void demux_wav_send_headers(demux_plugin_t *this_gen) { - unsigned int chunk_tag; - unsigned int chunk_size; - unsigned char chunk_preamble[8]; + demux_wav_t *this = (demux_wav_t *) this_gen; + buf_element_t *buf; pthread_mutex_lock(&this->mutex); - this->video_fifo = this->xine->video_fifo; - this->audio_fifo = this->xine->audio_fifo; + this->video_fifo = this->stream->video_fifo; + this->audio_fifo = this->stream->audio_fifo; this->status = DEMUX_OK; - /* go straight for the format structure */ - this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET); - if (this->input->read(this->input, - (unsigned char *)&this->wave_size, 4) != 4) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_CANNOT_HANDLE; - } - this->wave_size = le2me_32(this->wave_size); - this->wave = (xine_waveformatex *) malloc( this->wave_size ); - - if (this->input->read(this->input, (void *)this->wave, this->wave_size) != - this->wave_size) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_CANNOT_HANDLE; - } - xine_waveformatex_le2me(this->wave); - this->audio_type = formattag_to_buf_audio(this->wave->wFormatTag); - if(!this->audio_type) { - xine_report_codec( this->xine, XINE_CODEC_AUDIO, this->audio_type, 0, 0); - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_CANNOT_HANDLE; - } - - /* traverse through the chunks to find the 'data' chunk */ - this->data_start = this->data_size = 0; - while (this->data_start == 0) { - - if (this->input->read(this->input, chunk_preamble, 8) != 8) { - this->status = DEMUX_FINISHED; - pthread_mutex_unlock(&this->mutex); - return DEMUX_CANNOT_HANDLE; - } - chunk_tag = LE_32(&chunk_preamble[0]); - chunk_size = LE_32(&chunk_preamble[4]); - - if (chunk_tag == data_TAG) { - this->data_start = this->input->get_current_pos(this->input); - this->data_size = chunk_size; - } else { - this->input->seek(this->input, chunk_size, SEEK_CUR); - } - } - /* load stream information */ - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_CHANNELS] = this->wave->nChannels; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_SAMPLERATE] = this->wave->nSamplesPerSec; - this->xine->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = + this->stream->stream_info[XINE_STREAM_INFO_AUDIO_BITS] = this->wave->wBitsPerSample; - xine_demux_control_headers_done (this->xine); - - pthread_mutex_unlock (&this->mutex); - - return DEMUX_CAN_HANDLE; -} - -static int demux_wav_open(demux_plugin_t *this_gen, - input_plugin_t *input, int stage) { - - demux_wav_t *this = (demux_wav_t *) this_gen; - unsigned char signature[WAV_SIGNATURE_SIZE]; - - 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, 0, SEEK_SET); - if (input->read(input, signature, WAV_SIGNATURE_SIZE) != - WAV_SIGNATURE_SIZE) - return DEMUX_CANNOT_HANDLE; - - /* check the signature */ - if ((signature[0] == 'R') && - (signature[1] == 'I') && - (signature[2] == 'F') && - (signature[3] == 'F') && - (signature[8] == 'W') && - (signature[9] == 'A') && - (signature[10] == 'V') && - (signature[11] == 'E') && - (signature[12] == 'f') && - (signature[13] == 'm') && - (signature[14] == 't') && - (signature[15] == ' ')) - return load_wav_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_wav", VALID_ENDS, - _("valid mrls ending for wav demuxer"), - NULL, 20, NULL, NULL))); while((m = xine_strsep(&valid_ends, ",")) != NULL) { - - while(*m == ' ' || *m == '\t') m++; - - if(!strcasecmp((suffix + 1), m)) - return load_wav_and_send_headers(this); - } - return DEMUX_CANNOT_HANDLE; + /* send start buffers */ + xine_demux_control_start(this->stream); + + /* send init info to decoders */ + if (this->audio_fifo && this->audio_type) { + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = this->audio_type; + buf->decoder_flags = BUF_FLAG_HEADER; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = this->wave->nSamplesPerSec; + buf->decoder_info[2] = this->wave->wBitsPerSample; + buf->decoder_info[3] = this->wave->nChannels; + buf->content = (void *)this->wave; + buf->size = this->wave_size; + this->audio_fifo->put (this->audio_fifo, buf); } - break; - default: - return DEMUX_CANNOT_HANDLE; - break; - } + xine_demux_control_headers_done (this->stream); - return DEMUX_CANNOT_HANDLE; + pthread_mutex_unlock (&this->mutex); } static int demux_wav_seek (demux_plugin_t *this_gen, @@ -323,7 +297,6 @@ static int demux_wav_start (demux_plugin_t *this_gen, off_t start_pos, int start_time) { demux_wav_t *this = (demux_wav_t *) this_gen; - buf_element_t *buf; int err; demux_wav_seek(this_gen, start_pos, start_time); @@ -333,46 +306,6 @@ static int demux_wav_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_wav: format 0x%X audio, %d Hz, %d bits/sample, %d %s\n"), - this->wave->wFormatTag, - this->wave->nSamplesPerSec, - this->wave->wBitsPerSample, - this->wave->nChannels, - ngettext("channel", "channels", this->wave->nChannels)); - xine_log(this->xine, XINE_LOG_MSG, - _("demux_wav: running time = %lld min, %lld sec\n"), - this->data_size / this->wave->nAvgBytesPerSec / 60, - this->data_size / this->wave->nAvgBytesPerSec % 60); - xine_log(this->xine, XINE_LOG_MSG, - _("demux_wav: average bytes/sec = %d, block alignment = %d\n"), - this->wave->nAvgBytesPerSec, - this->wave->nBlockAlign); - - /* special block alignment hack so that the demuxer doesn't send - * packets with individual PCM samples */ - if ((this->wave->nAvgBytesPerSec / this->wave->nBlockAlign) == - this->wave->nSamplesPerSec) - this->wave->nBlockAlign = PCM_BLOCK_ALIGN; - - /* send start buffers */ - xine_demux_control_start(this->xine); - - /* send init info to decoders */ - if (this->audio_fifo && this->audio_type) { - buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); - buf->type = this->audio_type; - buf->decoder_flags = BUF_FLAG_HEADER; - buf->decoder_info[0] = 0; - buf->decoder_info[1] = this->wave->nSamplesPerSec; - buf->decoder_info[2] = this->wave->wBitsPerSample; - buf->decoder_info[3] = this->wave->nChannels; - buf->content = (void *)this->wave; - buf->size = this->wave_size; - this->audio_fifo->put (this->audio_fifo, buf); - } - this->status = DEMUX_OK; this->send_end_buffers = 1; this->thread_running = 1; @@ -418,7 +351,7 @@ static int demux_wav_seek (demux_plugin_t *this_gen, this->seek_flag = 1; status = this->status = DEMUX_OK; - xine_demux_flush_engine (this->xine); + xine_demux_flush_engine (this->stream); pthread_mutex_unlock(&this->mutex); return status; @@ -446,9 +379,9 @@ static void demux_wav_stop (demux_plugin_t *this_gen) { 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_wav_dispose (demux_plugin_t *this_gen) { @@ -461,15 +394,7 @@ static void demux_wav_dispose (demux_plugin_t *this_gen) { static int demux_wav_get_status (demux_plugin_t *this_gen) { demux_wav_t *this = (demux_wav_t *) this_gen; - return this->status; -} - -static char *demux_wav_get_id(void) { - return "WAV"; -} - -static char *demux_wav_get_mimetypes(void) { - return NULL; + return (this->thread_running?DEMUX_OK:DEMUX_FINISHED); } /* return the approximate length in seconds */ @@ -480,33 +405,142 @@ static int demux_wav_get_stream_length (demux_plugin_t *this_gen) { return (int)(this->data_size / this->wave->nAvgBytesPerSec); } -static void *init_demuxer_plugin(xine_t *xine, void *data) { +static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, + input_plugin_t *input_gen) { - demux_wav_t *this; + input_plugin_t *input = (input_plugin_t *) input_gen; + demux_wav_t *this; - this = xine_xmalloc (sizeof (demux_wav_t)); - this->config = xine->config; - this->xine = xine; + if (! (input->get_capabilities(input) & INPUT_CAP_SEEKABLE)) { + printf(_("demux_wav.c: input not seekable, can not handle!\n")); + return NULL; + } - (void*) this->config->register_string(this->config, - "mrl.ends_wav", VALID_ENDS, - _("valid mrls ending for wav demuxer"), - NULL, 20, NULL, NULL); + this = xine_xmalloc (sizeof (demux_wav_t)); + this->stream = stream; + this->input = input; - this->demux_plugin.open = demux_wav_open; + this->demux_plugin.send_headers = demux_wav_send_headers; this->demux_plugin.start = demux_wav_start; this->demux_plugin.seek = demux_wav_seek; this->demux_plugin.stop = demux_wav_stop; this->demux_plugin.dispose = demux_wav_dispose; this->demux_plugin.get_status = demux_wav_get_status; - this->demux_plugin.get_identifier = demux_wav_get_id; this->demux_plugin.get_stream_length = demux_wav_get_stream_length; - this->demux_plugin.get_mimetypes = demux_wav_get_mimetypes; + this->demux_plugin.demux_class = class_gen; this->status = DEMUX_FINISHED; - pthread_mutex_init( &this->mutex, NULL ); + pthread_mutex_init (&this->mutex, NULL); + + switch (stream->content_detection_method) { + + case METHOD_BY_CONTENT: + + if (!open_wav_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, ".wav", 4)) { + free (this); + return NULL; + } + + if (!open_wav_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_wav: format 0x%X audio, %d Hz, %d bits/sample, %d %s\n"), + this->wave->wFormatTag, + this->wave->nSamplesPerSec, + this->wave->wBitsPerSample, + this->wave->nChannels, + ngettext("channel", "channels", this->wave->nChannels)); + xine_log(this->stream->xine, XINE_LOG_MSG, + _("demux_wav: running time = %lld min, %lld sec\n"), + this->data_size / this->wave->nAvgBytesPerSec / 60, + this->data_size / this->wave->nAvgBytesPerSec % 60); + xine_log(this->stream->xine, XINE_LOG_MSG, + _("demux_wav: average bytes/sec = %d, block alignment = %d\n"), + this->wave->nAvgBytesPerSec, + this->wave->nBlockAlign); + + /* special block alignment hack so that the demuxer doesn't send + * packets with individual PCM samples */ + if ((this->wave->nAvgBytesPerSec / this->wave->nBlockAlign) == + this->wave->nSamplesPerSec) + this->wave->nBlockAlign = PCM_BLOCK_ALIGN; + + return &this->demux_plugin; +} + +static char *get_description (demux_class_t *this_gen) { + return "WAV file demux plugin"; +} + +static char *get_identifier (demux_class_t *this_gen) { + return "WAV"; +} + +static char *get_extensions (demux_class_t *this_gen) { + return "wav"; +} + +static char *get_mimetypes (demux_class_t *this_gen) { + return NULL; +} + +static void class_dispose (demux_class_t *this_gen) { + + demux_wav_class_t *this = (demux_wav_class_t *) this_gen; + + free (this); +} + +static void *init_plugin (xine_t *xine, void *data) { + + demux_wav_class_t *this; + + this = xine_xmalloc (sizeof (demux_wav_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 (demux_plugin_t *) this; + return this; } /* @@ -515,6 +549,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, 11, "wav", XINE_VERSION_CODE, NULL, init_demuxer_plugin }, + { PLUGIN_DEMUX, 14, "wav", XINE_VERSION_CODE, NULL, init_plugin }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |