diff options
author | James Stembridge <jstembridge@users.sourceforge.net> | 2004-03-14 21:37:52 +0000 |
---|---|---|
committer | James Stembridge <jstembridge@users.sourceforge.net> | 2004-03-14 21:37:52 +0000 |
commit | 0ddc2a72f2f5fc22c60a38d42cead2c9451c0fdb (patch) | |
tree | 25417f7bba1885c4a93eee97ca9467c457a6074d | |
parent | 4e87a4ca26966875271d476a77bcd5486b808c60 (diff) | |
download | xine-lib-0ddc2a72f2f5fc22c60a38d42cead2c9451c0fdb.tar.gz xine-lib-0ddc2a72f2f5fc22c60a38d42cead2c9451c0fdb.tar.bz2 |
Move real 14.4 and 28.8 header parsing to ffmpeg decoder
CVS patchset: 6259
CVS date: 2004/03/14 21:37:52
-rw-r--r-- | src/demuxers/demux_real.c | 15 | ||||
-rw-r--r-- | src/demuxers/demux_realaudio.c | 139 | ||||
-rw-r--r-- | src/libffmpeg/audio_decoder.c | 75 |
3 files changed, 121 insertions, 108 deletions
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index 44798f371..cc61387ef 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -31,7 +31,7 @@ * * Based on FFmpeg's libav/rm.c. * - * $Id: demux_real.c,v 1.94 2004/03/01 22:33:52 jstembridge Exp $ + * $Id: demux_real.c,v 1.95 2004/03/14 21:37:52 jstembridge Exp $ */ #ifdef HAVE_CONFIG_H @@ -741,19 +741,6 @@ unknown: memcpy(buf->content, mdpr->type_specific_data + 79, buf->decoder_info[2]); - } else if(buf->type == BUF_AUDIO_14_4) { - xine_waveformatex wave; - - wave.nSamplesPerSec = buf->decoder_info[1] = 8000; - wave.wBitsPerSample = buf->decoder_info[2] = 16; - wave.nChannels = buf->decoder_info[3] = 1; - wave.nBlockAlign = 240; - - buf->decoder_flags |= BUF_FLAG_STDHEADER; - buf->size = sizeof(xine_waveformatex); - - memcpy(buf->content, &wave, sizeof(xine_waveformatex)); - } else { memcpy(buf->content, mdpr->type_specific_data, mdpr->type_specific_len); diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index d1bab47f2..ff7518811 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -22,7 +22,7 @@ * RealAudio File Demuxer by Mike Melanson (melanson@pcisys.net) * improved by James Stembridge (jstembridge@users.sourceforge.net) * - * $Id: demux_realaudio.c,v 1.29 2004/01/09 01:26:33 miguelfreitas Exp $ + * $Id: demux_realaudio.c,v 1.30 2004/03/14 21:37:52 jstembridge Exp $ */ #ifdef HAVE_CONFIG_H @@ -54,20 +54,18 @@ typedef struct { input_plugin_t *input; int status; - xine_waveformatex wave; + unsigned int fourcc; unsigned int audio_type; off_t data_start; off_t data_size; - -#if 0 - /* Needed by ffmpeg 28.8 decoder */ - unsigned short sub_packet_size; - unsigned short sub_packet_height; - unsigned short sub_packet_flavour; - unsigned int coded_frame_size; -#endif + unsigned short block_align; + unsigned int bytes_per_sec; + + unsigned char *header; + unsigned int header_size; + int seek_flag; /* this is set when a seek just occurred */ } demux_ra_t; @@ -78,8 +76,6 @@ typedef struct { /* returns 1 if the RealAudio file was opened successfully, 0 otherwise */ static int open_ra_file(demux_ra_t *this) { unsigned char file_header[RA_FILE_HEADER_PREV_SIZE], len; - unsigned char *audio_header; - unsigned int audio_fourcc = 0, hdr_size; unsigned short version; off_t offset; @@ -99,108 +95,95 @@ static int open_ra_file(demux_ra_t *this) { /* read header size according to version */ if (version == 3) - hdr_size = BE_16(&file_header[0x06]) + 8; + this->header_size = BE_16(&file_header[0x06]) + 8; else if (version == 4) - hdr_size = BE_32(&file_header[0x12]) + 16; + this->header_size = BE_32(&file_header[0x12]) + 16; else { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unknown version number %d\n", version); return 0; } /* allocate for and read header data */ - audio_header = xine_xmalloc(hdr_size); + this->header = xine_xmalloc(this->header_size); - if (_x_demux_read_header(this->input, audio_header, hdr_size) != hdr_size) { + if (_x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unable to read header\n"); - free(audio_header); + free(this->header); return 0; } /* read header data according to version */ - if((version == 3) && (hdr_size >= 32)) { - this->data_size = BE_32(&audio_header[0x12]); + if((version == 3) && (this->header_size >= 32)) { + this->data_size = BE_32(&this->header[0x12]); + + this->block_align = 240; - this->wave.nChannels = 1; - this->wave.nSamplesPerSec = 8000; - this->wave.nBlockAlign = 240; - this->wave.wBitsPerSample = 16; - offset = 0x16; - } else if(hdr_size >= 72) { - this->data_size = BE_32(&audio_header[0x1C]); + } else if(this->header_size >= 72) { + this->data_size = BE_32(&this->header[0x1C]); - this->wave.nBlockAlign = BE_16(&audio_header[0x2A]); - this->wave.nSamplesPerSec = BE_16(&audio_header[0x30]); - this->wave.wBitsPerSample = audio_header[0x35]; - this->wave.nChannels = audio_header[0x37]; - -#if 0 - this->sub_packet_size = BE_16(&audio_header[0x2C]); - this->sub_packet_height = BE_16(&audio_header[0x28]); - this->sub_packet_flavour = BE_16(&audio_header[0x16]); - this->coded_frame_size = BE_32(&audio_header[0x18]); -#endif - - if(audio_header[0x3D] == 4) - audio_fourcc = ME_32(&audio_header[0x3E]); + this->block_align = BE_16(&this->header[0x2A]); + + if(this->header[0x3D] == 4) + this->fourcc = ME_32(&this->header[0x3E]); else { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_realaudio: invalid fourcc size %d\n", audio_header[0x3D]); - free(audio_header); + "demux_realaudio: invalid fourcc size %d\n", this->header[0x3D]); + free(this->header); return 0; } offset = 0x45; } else { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: header too small\n"); - free(audio_header); + free(this->header); return 0; } /* Read title */ - len = audio_header[offset]; - if(len && ((offset+len+2) < hdr_size)) { + len = this->header[offset]; + if(len && ((offset+len+2) < this->header_size)) { _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE, - &audio_header[offset+1], len); + &this->header[offset+1], len); offset += len+1; } else offset++; /* Author */ - len = audio_header[offset]; - if(len && ((offset+len+1) < hdr_size)) { + len = this->header[offset]; + if(len && ((offset+len+1) < this->header_size)) { _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST, - &audio_header[offset+1], len); + &this->header[offset+1], len); offset += len+1; } else offset++; /* Copyright/Date */ - len = audio_header[offset]; - if(len && ((offset+len) <= hdr_size)) { + len = this->header[offset]; + if(len && ((offset+len) <= this->header_size)) { _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR, - &audio_header[offset+1], len); + &this->header[offset+1], len); offset += len+1; } else offset++; /* Fourcc for version 3 comes after meta info */ - if((version == 3) && ((offset+7) <= hdr_size)) { - if(audio_header[offset+2] == 4) - audio_fourcc = ME_32(&audio_header[offset+3]); + if((version == 3) && ((offset+7) <= this->header_size)) { + if(this->header[offset+2] == 4) + this->fourcc = ME_32(&this->header[offset+3]); else { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_realaudio: invalid fourcc size %d\n", audio_header[offset+2]); - free(audio_header); + "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]); + free(this->header); return 0; } } - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, audio_fourcc); - this->audio_type = _x_formattag_to_buf_audio(audio_fourcc); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->fourcc); + this->audio_type = _x_formattag_to_buf_audio(this->fourcc); /* seek to start of data */ - this->data_start = hdr_size; + this->data_start = this->header_size; if (this->input->seek(this->input, this->data_start, SEEK_SET) != this->data_start) { xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unable to seek to data start\n"); @@ -223,7 +206,7 @@ static int demux_ra_send_chunk(demux_plugin_t *this_gen) { /* just load data chunks from wherever the stream happens to be * pointing; issue a DEMUX_FINISHED status if EOF is reached */ - remaining_sample_bytes = this->wave.nBlockAlign; + remaining_sample_bytes = this->block_align; current_file_pos = this->input->get_current_pos(this->input) - this->data_start; @@ -279,12 +262,7 @@ static void demux_ra_send_headers(demux_plugin_t *this_gen) { /* load stream information */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_CHANNELS, - this->wave.nChannels); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, - this->wave.nSamplesPerSec); - _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, - this->wave.wBitsPerSample); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->fourcc); /* send start buffers */ _x_demux_control_start(this->stream); @@ -293,13 +271,15 @@ static void demux_ra_send_headers(demux_plugin_t *this_gen) { 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_FLAG_STDHEADER|BUF_FLAG_FRAME_END; - 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; - memcpy(buf->content, &this->wave, sizeof(this->wave)); - buf->size = sizeof(this->wave); + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END; + + if(this->header_size > buf->max_size) + buf->size = buf->max_size; + else + buf->size = this->header_size; + + memcpy(buf->content, this->header, buf->size); + this->audio_fifo->put (this->audio_fifo, buf); } } @@ -330,8 +310,8 @@ static int demux_ra_seek (demux_plugin_t *this_gen, * the block alignment integer-wise, and multiply the quotient by the * block alignment to get the new aligned offset. Add the data start * offset and seek to the new position. */ - start_pos /= this->wave.nBlockAlign; - start_pos *= this->wave.nBlockAlign; + start_pos /= this->block_align; + start_pos *= this->block_align; start_pos += this->data_start; this->input->seek(this->input, start_pos, SEEK_SET); @@ -343,6 +323,9 @@ static int demux_ra_seek (demux_plugin_t *this_gen, static void demux_ra_dispose (demux_plugin_t *this_gen) { demux_ra_t *this = (demux_ra_t *) this_gen; + + if(this->header) + free(this->header); free(this); } @@ -357,8 +340,8 @@ static int demux_ra_get_status (demux_plugin_t *this_gen) { static int demux_ra_get_stream_length (demux_plugin_t *this_gen) { demux_ra_t *this = (demux_ra_t *) this_gen; - if(this->wave.nAvgBytesPerSec) - return (int)((int64_t) this->data_size * 1000 / this->wave.nAvgBytesPerSec); + if(this->bytes_per_sec) + return (int)((int64_t) this->data_size * 1000 / this->bytes_per_sec); else return 0; } diff --git a/src/libffmpeg/audio_decoder.c b/src/libffmpeg/audio_decoder.c index 26a04ff9c..38a5b1a73 100644 --- a/src/libffmpeg/audio_decoder.c +++ b/src/libffmpeg/audio_decoder.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: audio_decoder.c,v 1.5 2004/03/13 19:42:22 jstembridge Exp $ + * $Id: audio_decoder.c,v 1.6 2004/03/14 21:37:52 jstembridge Exp $ * * xine audio decoder plugin using ffmpeg * @@ -43,6 +43,7 @@ #include "xine_internal.h" #include "buffer.h" #include "xineutils.h" +#include "bswap.h" #include "xine_decoder.h" #define AUDIOBUFSIZE 128*1024 @@ -112,7 +113,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) audio_buffer_t *audio_buffer; int bytes_to_send; - if (buf->decoder_flags & BUF_FLAG_STDHEADER) { + if (buf->decoder_flags & BUF_FLAG_HEADER) { int i, codec_type; xine_waveformatex *audio_header = (xine_waveformatex *)buf->content; @@ -137,24 +138,65 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) } this->context = avcodec_alloc_context(); + + if(buf->decoder_flags & BUF_FLAG_STDHEADER) { + this->audio_sample_rate = buf->decoder_info[1]; + this->audio_channels = buf->decoder_info[3]; + + this->context->block_align = audio_header->nBlockAlign; + this->context->bit_rate = audio_header->nAvgBytesPerSec * 8; + + if(audio_header->cbSize > 0) { + this->context->extradata = xine_xmalloc(audio_header->cbSize); + this->context->extradata_size = audio_header->cbSize; + memcpy( this->context->extradata, + (uint8_t *)audio_header + sizeof(xine_waveformatex), + audio_header->cbSize ); + } + } else { + short *ptr; + + switch(codec_type) { + case BUF_AUDIO_14_4: + this->audio_sample_rate = 8000; + this->audio_channels = 1; + + this->context->block_align = 240; + break; + case BUF_AUDIO_28_8: + this->audio_sample_rate = BE_16(&buf->content[0x30]); + this->audio_channels = buf->content[0x37]; + /* this->audio_bits = buf->content[0x35] */ + + this->context->block_align = BE_16(&buf->content[0x2A]); + + this->context->extradata_size = 5*sizeof(short); + this->context->extradata = xine_xmalloc(this->context->extradata_size); + + ptr = (short *) this->context->extradata; + + ptr[0] = BE_16(&buf->content[0x2C]); /* subpacket size */ + ptr[1] = BE_16(&buf->content[0x28]); /* subpacket height */ + ptr[2] = BE_16(&buf->content[0x16]); /* subpacket flavour */ + ptr[3] = BE_32(&buf->content[0x18]); /* coded frame size */ + ptr[4] = 0; /* codec's data length */ + break; + default: + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_audio_dec: unknown header with buf type 0x%X\n", codec_type); + break; + } + } - this->context->sample_rate = this->audio_sample_rate = buf->decoder_info[1]; /* Current ffmpeg audio decoders always use 16 bits/sample * buf->decoder_info[2] can't be used as it doesn't refer to the output * bits/sample for some codecs (e.g. MS ADPCM) */ this->audio_bits = 16; - this->context->channels = this->audio_channels = buf->decoder_info[3]; - this->context->block_align = audio_header->nBlockAlign; - this->context->bit_rate = audio_header->nAvgBytesPerSec * 8; - this->context->codec_id = this->codec->id; - this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC); - if( audio_header->cbSize > 0 ) { - this->context->extradata = malloc(audio_header->cbSize); - this->context->extradata_size = audio_header->cbSize; - memcpy( this->context->extradata, - (uint8_t *)audio_header + sizeof(xine_waveformatex), - audio_header->cbSize ); - } + + this->context->sample_rate = this->audio_sample_rate; + this->context->channels = this->audio_channels; + this->context->codec_id = this->codec->id; + this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC); this->buf = xine_xmalloc(AUDIOBUFSIZE); this->bufsize = AUDIOBUFSIZE; @@ -222,7 +264,8 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) "ffmpeg_audio_dec: error decompressing audio frame\n"); this->size=0; return; - } + } else if (bytes_consumed == 0) + return; /* dispatch the decoded audio */ out = 0; |