diff options
author | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2008-04-08 01:00:10 +0100 |
---|---|---|
committer | Darren Salt <linux@youmustbejoking.demon.co.uk> | 2008-04-08 01:00:10 +0100 |
commit | 628c4cbd9d023e74a7c6805d7ec0f163f2c172d1 (patch) | |
tree | b74ddd76dc7fb3080ea269c6d3776f84aca36837 | |
parent | 3f255412a55880c7323debef2bff0fc2dd5ed554 (diff) | |
parent | 964f55aef546a1f1574c9f6ec10b3410fe390c34 (diff) | |
download | xine-lib-628c4cbd9d023e74a7c6805d7ec0f163f2c172d1.tar.gz xine-lib-628c4cbd9d023e74a7c6805d7ec0f163f2c172d1.tar.bz2 |
Merge from 1.1.
--HG--
rename : src/xine-engine/buffer.h => include/xine/buffer.h
rename : src/libmad/xine_mad_decoder.c => src/audio_dec/xine_mad_decoder.c
rename : src/combined/combined_wavpack.c => src/combined/wavpack_combined.c
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | doc/man/en/Makefile.am | 4 | ||||
-rw-r--r-- | include/Makefile.am | 3 | ||||
-rw-r--r-- | include/xine/buffer.h | 1 | ||||
-rw-r--r-- | src/audio_dec/xine_mad_decoder.c | 2 | ||||
-rw-r--r-- | src/combined/ffmpeg/ff_audio_decoder.c | 81 | ||||
-rw-r--r-- | src/combined/ffmpeg/ff_video_decoder.c | 20 | ||||
-rw-r--r-- | src/combined/wavpack_combined.c | 2 | ||||
-rw-r--r-- | src/demuxers/Makefile.am | 2 | ||||
-rw-r--r-- | src/demuxers/demux_matroska.c | 4 | ||||
-rw-r--r-- | src/demuxers/demux_real.c | 151 | ||||
-rw-r--r-- | src/demuxers/demux_realaudio.c | 88 | ||||
-rw-r--r-- | src/demuxers/real_common.h | 56 | ||||
-rw-r--r-- | src/libreal/xine_real_audio_decoder.c | 166 | ||||
-rw-r--r-- | src/libreal/xine_real_video_decoder.c | 46 | ||||
-rw-r--r-- | src/video_out/video_out_macosx.m | 2 | ||||
-rw-r--r-- | src/xine-engine/buffer_types.c | 8 |
17 files changed, 459 insertions, 180 deletions
@@ -70,6 +70,9 @@ xine-lib (1.1.12) 2008-??-?? * And another, this time in the Matroska demuxer. * Added a tool to assist with generating front ends' desktop files. It lists MIME types & filename extensions known to the installed xine-lib. + * Various Real codec improvements, including: + - RV20 no longer causes segfaults (observed on amd64); + - Cook is now handled by ffmpeg. xine-lib (1.1.11.1) 2008-03-30 * Security fixes: diff --git a/doc/man/en/Makefile.am b/doc/man/en/Makefile.am index 8cdf212a6..9fe87cc11 100644 --- a/doc/man/en/Makefile.am +++ b/doc/man/en/Makefile.am @@ -7,7 +7,7 @@ man_MANS = $(STATICMANS) $(DYNAMICMANS) BUILT_SOURCES = $(DYNAMICMANS) DISTCLEANFILES = $(DYNAMICMANS) -EXTRA_DIST = $(STATICMANS) $(suffix .in,$(DYNAMICMANS)) +EXTRA_DIST = $(STATICMANS) xine-list.1.in xine-list-@XINE_SERIES@.1: xine-list.1.in - (echo '.ds xl xine\-list\-@XINE_MAJOR@.@XINE_MINOR@'; cat $<) >$@ + (echo '.ds xl xine\-list\-@XINE_SERIES@'; cat $<) >$@ diff --git a/include/Makefile.am b/include/Makefile.am index 7f569f498..aa26094a6 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -46,7 +46,8 @@ nobase_include_HEADERS = xine.h \ xine/xmllexer.h \ xine/xmlparser.h -noinst_HEADERS = config.h configure.h +noinst_HEADERS = config.h +nodist_noinst_HEADERS = configure.h nodist_include_HEADERS = $(inttypes_h) diff --git a/include/xine/buffer.h b/include/xine/buffer.h index 9401f8852..a53b99db3 100644 --- a/include/xine/buffer.h +++ b/include/xine/buffer.h @@ -264,6 +264,7 @@ extern "C" { #define BUF_AUDIO_SMACKER 0x033B0000 #define BUF_AUDIO_FLVADPCM 0x033C0000 #define BUF_AUDIO_WAVPACK 0x033D0000 +#define BUF_AUDIO_MP3ADU 0x033E0000 /*@}*/ /** diff --git a/src/audio_dec/xine_mad_decoder.c b/src/audio_dec/xine_mad_decoder.c index 74c04924f..abad70f4f 100644 --- a/src/audio_dec/xine_mad_decoder.c +++ b/src/audio_dec/xine_mad_decoder.c @@ -393,7 +393,7 @@ static const uint32_t audio_types[] = { static const decoder_info_t dec_info_audio = { audio_types, /* supported types */ - 7 /* priority */ + 8 /* priority */ }; const plugin_info_t xine_plugin_info[] EXPORTED = { diff --git a/src/combined/ffmpeg/ff_audio_decoder.c b/src/combined/ffmpeg/ff_audio_decoder.c index f79014fde..2b42cfb33 100644 --- a/src/combined/ffmpeg/ff_audio_decoder.c +++ b/src/combined/ffmpeg/ff_audio_decoder.c @@ -81,6 +81,7 @@ static const ff_codec_t ff_audio_lookup[] = { {BUF_AUDIO_14_4, CODEC_ID_RA_144, "Real 14.4 (ffmpeg)"}, {BUF_AUDIO_28_8, CODEC_ID_RA_288, "Real 28.8 (ffmpeg)"}, {BUF_AUDIO_MPEG, CODEC_ID_MP3, "MP3 (ffmpeg)"}, + {BUF_AUDIO_MP3ADU, CODEC_ID_MP3ADU, "MPEG-3 adu (ffmpeg)"}, {BUF_AUDIO_MSADPCM, CODEC_ID_ADPCM_MS, "MS ADPCM (ffmpeg)"}, {BUF_AUDIO_QTIMAADPCM, CODEC_ID_ADPCM_IMA_QT, "QT IMA ADPCM (ffmpeg)"}, {BUF_AUDIO_MSIMAADPCM, CODEC_ID_ADPCM_IMA_WAV, "MS IMA ADPCM (ffmpeg)"}, @@ -201,8 +202,8 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->audio_channels = this->buf[0x37]; /* this->audio_bits = buf->content[0x35] */ - this->context->block_align = _X_BE_16(&this->buf[0x2A]); - + this->context->block_align = _X_BE_32(&this->buf[0x18]); + this->context->extradata_size = 5*sizeof(short); this->context->extradata = xine_xmalloc(this->context->extradata_size); @@ -213,7 +214,49 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) ptr[2] = _X_BE_16(&this->buf[0x16]); /* subpacket flavour */ ptr[3] = _X_BE_32(&this->buf[0x18]); /* coded frame size */ ptr[4] = 0; /* codec's data length */ + + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_audio_dec: 28_8 audio channels %d bits %d sample rate %d block align %d\n", + this->audio_channels, this->audio_bits, this->audio_sample_rate, + this->context->block_align); break; + case BUF_AUDIO_COOK: + { + int version; + int data_len; + int extradata; + + version = _X_BE_16 (this->buf+4); + if (version == 4) { + this->audio_sample_rate = _X_BE_16 (this->buf+48); + this->audio_bits = _X_BE_16 (this->buf+52); + this->audio_channels = _X_BE_16 (this->buf+54); + data_len = _X_BE_32 (this->buf+67); + extradata = 71; + } else { + this->audio_sample_rate = _X_BE_16 (this->buf+54); + this->audio_bits = _X_BE_16 (this->buf+58); + this->audio_channels = _X_BE_16 (this->buf+60); + data_len = _X_BE_32 (this->buf+74); + extradata = 78; + } + this->context->block_align = _X_BE_16 (this->buf+44); + + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_audio_dec: cook audio channels %d bits %d sample rate %d block align %d\n", + this->audio_channels, this->audio_bits, this->audio_sample_rate, + this->context->block_align); + + if (extradata + data_len > this->size) + break; /* abort early - extradata length is bad */ + + this->context->extradata_size = data_len; + this->context->extradata = xine_xmalloc(this->context->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + xine_fast_memcpy (this->context->extradata, this->buf + extradata, + this->context->extradata_size); + break; + } default: xprintf(this->stream->xine, XINE_VERBOSITY_LOG, "ffmpeg_audio_dec: unknown header with buf type 0x%X\n", codec_type); @@ -230,6 +273,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->context->sample_rate = this->audio_sample_rate; this->context->channels = this->audio_channels; this->context->codec_id = this->codec->id; + this->context->codec_type = this->codec->type; this->context->codec_tag = _x_stream_info_get(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC); this->size = 0; @@ -269,7 +313,26 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->decoder_ok = 1; } + if( buf->decoder_flags & BUF_FLAG_PREVIEW ) + return; + + ff_audio_ensure_buffer_size(this, this->size + buf->size); + xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); + this->size += buf->size; + if (!this->output_open) { + if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) { + avcodec_decode_audio (this->context, + (int16_t *)this->decode_buffer, + &decode_buffer_size, + &this->buf[0], + this->size); + this->audio_bits = this->context->bits_per_sample; + this->audio_sample_rate = this->context->sample_rate; + this->audio_channels = this->context->channels; + if (!this->audio_bits || !this->audio_sample_rate || !this->audio_channels) + return; + } this->output_open = (this->stream->audio_out->open) (this->stream->audio_out, this->stream, this->audio_bits, this->audio_sample_rate, _x_ao_channels2mode(this->audio_channels)); @@ -279,13 +342,6 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) if (!this->output_open) return; - if( buf->decoder_flags & BUF_FLAG_PREVIEW ) - return; - - ff_audio_ensure_buffer_size(this, this->size + buf->size); - xine_fast_memcpy (&this->buf[this->size], buf->content, buf->size); - this->size += buf->size; - if (buf->decoder_flags & BUF_FLAG_FRAME_END) { /* time to decode a frame */ offset = 0; @@ -326,7 +382,7 @@ static void ff_audio_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) /* fill up this buffer */ xine_fast_memcpy(audio_buffer->mem, &this->decode_buffer[out], - bytes_to_send); + bytes_to_send); /* byte count / 2 (bytes / sample) / channels */ audio_buffer->num_frames = bytes_to_send / 2 / this->audio_channels; @@ -357,7 +413,8 @@ static void ff_audio_reset (audio_decoder_t *this_gen) { if( this->context && this->decoder_ok ) { pthread_mutex_lock (&ffmpeg_lock); avcodec_close (this->context); - avcodec_open (this->context, this->codec); + if (avcodec_open (this->context, this->codec) < 0) + this->decoder_ok = 0; pthread_mutex_unlock (&ffmpeg_lock); } } @@ -537,5 +594,5 @@ static const uint32_t supported_audio_types[] = { decoder_info_t dec_info_ffmpeg_audio = { supported_audio_types, /* supported types */ - 6 /* priority */ + 7 /* priority */ }; diff --git a/src/combined/ffmpeg/ff_video_decoder.c b/src/combined/ffmpeg/ff_video_decoder.c index 58305aa13..10b326d45 100644 --- a/src/combined/ffmpeg/ff_video_decoder.c +++ b/src/combined/ffmpeg/ff_video_decoder.c @@ -946,6 +946,26 @@ static void ff_handle_header_buffer (ff_video_decoder_t *this, buf_element_t *bu this->context->slice_offset = xine_xmalloc(sizeof(int)*SLICE_OFFSET_SIZE); this->slice_offset_size = SLICE_OFFSET_SIZE; + this->context->extradata_size = this->size - 26; + if (this->context->extradata_size < 8) { + this->context->extradata_size= 8; + this->context->extradata = malloc(this->context->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + ((uint32_t *)this->context->extradata)[0] = 0; + if (codec_type == BUF_VIDEO_RV10) + ((uint32_t *)this->context->extradata)[1] = 0x10000000; + else + ((uint32_t *)this->context->extradata)[1] = 0x10003001; + } else { + this->context->extradata = malloc(this->context->extradata_size + + FF_INPUT_BUFFER_PADDING_SIZE); + memcpy(this->context->extradata, this->buf + 26, + this->context->extradata_size); + } + + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "ffmpeg_video_dec: buf size %d\n", this->size); + lprintf("w=%d, h=%d\n", this->bih.biWidth, this->bih.biHeight); break; diff --git a/src/combined/wavpack_combined.c b/src/combined/wavpack_combined.c index 8a4b488ae..ca54635e7 100644 --- a/src/combined/wavpack_combined.c +++ b/src/combined/wavpack_combined.c @@ -33,7 +33,7 @@ static const uint32_t audio_types[] = { static const decoder_info_t decoder_info_wv = { audio_types, /* supported types */ - 7 /* priority */ + 8 /* priority */ }; const plugin_info_t xine_plugin_info[] EXPORTED = { diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 276505521..876b64f7a 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -8,7 +8,7 @@ AM_LDFLAGS = $(xineplug_ldflags) # --------- # All of xine demuxer plugins should be named like the scheme "xineplug_dmx_" -noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h iff.h flacutils.h +noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h iff.h flacutils.h real_common.h if ENABLE_ASF asf_module = xineplug_dmx_asf.la diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index e0e8c9e78..713995e97 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -635,9 +635,7 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { } buf->size = frame[i]; - buf->decoder_flags = BUF_FLAG_HEADER; - if (i == 2) - buf->decoder_flags |= BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_START | BUF_FLAG_FRAME_END; buf->type = track->buf_type; buf->pts = 0; diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index 7b5f7530d..cc6a214e0 100644 --- a/src/demuxers/demux_real.c +++ b/src/demuxers/demux_real.c @@ -55,6 +55,8 @@ #include <xine/demux.h> #include "bswap.h" +#include "real_common.h" + #define FOURCC_TAG BE_FOURCC #define RMF_TAG FOURCC_TAG('.', 'R', 'M', 'F') #define PROP_TAG FOURCC_TAG('P', 'R', 'O', 'P') @@ -113,6 +115,12 @@ typedef struct { int index_entries; mdpr_t *mdpr; + int sps, cfs, w, h; + int block_align; + int frame_size; + uint8_t *frame_buffer; + uint32_t frame_num_bytes; + uint32_t sub_packet_cnt; } real_stream_t; typedef struct { @@ -168,7 +176,6 @@ typedef struct { demux_class_t demux_class; } demux_real_class_t; - static void real_parse_index(demux_real_t *this) { off_t next_index_chunk = this->index_start; @@ -310,6 +317,64 @@ static void real_free_mdpr (mdpr_t *mdpr) { free (mdpr); } +static void real_parse_audio_specific_data (demux_real_t *this, + real_stream_t * stream, + uint8_t * data, int len) +{ + int coded_frame_size; + int codec_data_length; + int coded_frame_size2; + int subpacket_size; + + coded_frame_size = _X_BE_32 (data+24); + codec_data_length = _X_BE_16 (data+40); + coded_frame_size2 = _X_BE_16 (data+42); + subpacket_size = _X_BE_16 (data+44); + + stream->sps = subpacket_size; + stream->w = coded_frame_size2; + stream->h = codec_data_length; + stream->block_align = coded_frame_size2; + stream->cfs = coded_frame_size; + + switch (stream->buf_type) { + case BUF_AUDIO_COOK: + case BUF_AUDIO_ATRK: + stream->block_align = subpacket_size; + break; + + case BUF_AUDIO_14_4: + break; + + case BUF_AUDIO_28_8: + stream->block_align = stream->cfs; + break; + + case BUF_AUDIO_SIPRO: + /* this->block_align = 19; */ + break; + + default: + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: error, i don't handle buf type 0x%08x\n", stream->buf_type); + } + + if (stream->sps) { + stream->frame_size = stream->w / stream->sps * stream->h * stream->sps; + stream->frame_buffer = xine_xmalloc (stream->frame_size); + stream->frame_num_bytes = 0; + } else { + stream->frame_size = stream->w * stream->h; + stream->frame_buffer = xine_xmalloc (stream->frame_size); + stream->frame_num_bytes = 0; + } + stream->sub_packet_cnt = 0; + + xprintf (this->stream->xine, XINE_VERBOSITY_LOG, + "demux_real: buf type 0x%08x frame size %dblock align %d\n", stream->buf_type, + stream->frame_size, stream->block_align); + +} static void real_parse_headers (demux_real_t *this) { @@ -420,8 +485,16 @@ static void real_parse_headers (demux_real_t *this) { mdpr = real_parse_mdpr (chunk_buffer); lprintf ("parsing type specific data...\n"); + if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) { + lprintf ("mpeg layer 3 audio detected...\n"); - if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) { + fourcc = ME_FOURCC('a', 'd', 'u', 0x55); + this->audio_streams[this->num_audio_streams].fourcc = fourcc; + this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc); + this->audio_streams[this->num_audio_streams].index = NULL; + this->audio_streams[this->num_audio_streams].mdpr = mdpr; + this->num_audio_streams++; + } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) { int version, len; if(this->num_audio_streams == MAX_AUDIO_STREAMS) { @@ -459,6 +532,10 @@ static void real_parse_headers (demux_real_t *this) { this->audio_streams[this->num_audio_streams].index = NULL; this->audio_streams[this->num_audio_streams].mdpr = mdpr; + real_parse_audio_specific_data (this, + &this->audio_streams[this->num_audio_streams], + mdpr->type_specific_data, + mdpr->type_specific_len); this->num_audio_streams++; if (!this->audio_streams[this->num_audio_streams].buf_type) @@ -747,6 +824,13 @@ unknown: memcpy(buf->content, mdpr->type_specific_data + 79, buf->decoder_info[2]); + } else if(buf->type == BUF_AUDIO_MP3ADU) { + buf->decoder_flags |= BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END; + buf->size = 0; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = 0; + buf->decoder_info[2] = 0; + buf->decoder_info[3] = 0; } else { memcpy(buf->content, mdpr->type_specific_data, mdpr->type_specific_len); @@ -985,6 +1069,7 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { off_t offset, input_length = 0; int normpos = 0; + read_next_packet: if(this->reference_mode) return demux_real_parse_references(this); @@ -1322,6 +1407,64 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { } free(sizes); + } else if (this->audio_stream->buf_type == BUF_AUDIO_COOK || + this->audio_stream->buf_type == BUF_AUDIO_ATRK || + this->audio_stream->buf_type == BUF_AUDIO_28_8 || + this->audio_stream->buf_type == BUF_AUDIO_SIPRO) { + /* reorder */ + uint8_t * buffer = this->audio_stream->frame_buffer; + int sps = this->audio_stream->sps; + int sph = this->audio_stream->h; + int cfs = this->audio_stream->cfs; + int w = this->audio_stream->w; + int spc = this->audio_stream->sub_packet_cnt; + int x, pos; + + switch (this->audio_stream->buf_type) { + case BUF_AUDIO_28_8: + for (x = 0; x < sph / 2; x++) { + pos = x * 2 * w + spc * cfs; + if(this->input->read(this->input, buffer + pos, cfs) < cfs) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + } + break; + case BUF_AUDIO_COOK: + case BUF_AUDIO_ATRK: + for (x = 0; x < w / sps; x++) { + pos = sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1)); + if(this->input->read(this->input, buffer + pos, sps) < sps) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + } + break; + case BUF_AUDIO_SIPRO: + pos = spc * w; + if(this->input->read(this->input, buffer + pos, w) < w) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_real: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + if (spc == sph - 1) + demux_real_sipro_swap (buffer, sph * w * 2 / 96); + break; + } + if(++this->audio_stream->sub_packet_cnt == sph) { + this->audio_stream->sub_packet_cnt = 0; + _x_demux_send_data(this->audio_fifo, buffer, this->audio_stream->frame_size, + pts, this->audio_stream->buf_type, 0, normpos, input_time, + this->duration, 0); + } } else { if(_x_demux_read_send_data(this->audio_fifo, this->input, size, pts, this->audio_stream->buf_type, 0, normpos, @@ -1471,6 +1614,9 @@ static int demux_real_seek (demux_plugin_t *this_gen, this->input->seek(this->input, index[i].offset, SEEK_SET); if(playing) { + if(this->audio_stream) + this->audio_stream->sub_packet_cnt = 0; + this->buf_flag_seek = 1; _x_demux_flush_engine(this->stream); } @@ -1507,6 +1653,7 @@ static void demux_real_dispose (demux_plugin_t *this_gen) { for(i = 0; i < this->num_audio_streams; i++) { real_free_mdpr(this->audio_streams[i].mdpr); free(this->audio_streams[i].index); + free(this->audio_streams[i].frame_buffer); } free(this->fragment_tab); diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index 7ee608c83..2873a522e 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -41,6 +41,8 @@ #include "bswap.h" #include "group_audio.h" +#include "real_common.h" + #define RA_FILE_HEADER_PREV_SIZE 22 typedef struct { @@ -62,6 +64,10 @@ typedef struct { off_t data_start; off_t data_size; + int sps, cfs, w, h; + int frame_size; + uint8_t *frame_buffer; + unsigned char *header; unsigned int header_size; } demux_ra_t; @@ -70,6 +76,9 @@ typedef struct { demux_class_t demux_class; } demux_ra_class_t; +/* Map flavour to bytes per second */ +static int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second + /* 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; @@ -165,20 +174,41 @@ static int open_ra_file(demux_ra_t *this) { offset++; /* Fourcc for version 3 comes after meta info */ - if((version == 3) && ((offset+7) <= this->header_size)) { - if(this->header[offset+2] == 4) - this->fourcc = _X_ME_32(&this->header[offset+3]); - else { - xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]); - free(this->header); - return 0; + if(version == 3) { + if (((offset+7) <= this->header_size)) { + if(this->header[offset+2] == 4) + this->fourcc = _X_ME_32(&this->header[offset+3]); + else { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]); + free(this->header); + return 0; + } + } else { + this->fourcc = ME_FOURCC('l', 'p', 'c', 'J'); } } _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->fourcc); this->audio_type = _x_formattag_to_buf_audio(this->fourcc); + if (version == 4) { + this->sps = _X_BE_16 (this->header+44); + this->w = _X_BE_16 (this->header+42); + this->h = _X_BE_16 (this->header+40); + this->cfs = _X_BE_32 (this->header+24); + if (this->sps) { + this->frame_size = this->sps * this->h * this->sps; + this->frame_buffer = xine_xmalloc (this->frame_size); + } else { + this->frame_size = this->w * this->h; + this->frame_buffer = xine_xmalloc (this->frame_size); + } + + if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) + this->block_align = this->cfs; + } + /* seek to start of data */ this->data_start = this->header_size; if (this->input->seek(this->input, this->data_start, SEEK_SET) != @@ -212,7 +242,45 @@ static int demux_ra_send_chunk(demux_plugin_t *this_gen) { this->seek_flag = 0; } - if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align, + if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) { + int x; + uint8_t * buffer; + + buffer = this->frame_buffer; + if (this->audio_type == BUF_AUDIO_SIPRO) { + int n; + int len = this->h * this->w; + if(this->input->read(this->input, this->frame_buffer, len) < len) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_realaudio: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + demux_real_sipro_swap (this->frame_buffer, len * 2 / 96); + } else { + int x, y; + int pos; + + for (y = 0; y < this->h; y++) + for (x = 0; x < this->h / 2; x++) { + pos = x * 2 * this->w + y * this->cfs; + if(this->input->read(this->input, this->frame_buffer + pos, + this->cfs) < this->cfs) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_realaudio: failed to read audio chunk\n"); + + this->status = DEMUX_FINISHED; + return this->status; + } + } + } + + _x_demux_send_data(this->audio_fifo, + buffer, this->frame_size, + current_pts, this->audio_type, 0, + current_normpos, current_pts / 90, 0, 0); + } else if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align, current_pts, this->audio_type, 0, current_normpos, current_pts / 90, 0, 0) < 0) { this->status = DEMUX_FINISHED; @@ -298,6 +366,7 @@ static void demux_ra_dispose (demux_plugin_t *this_gen) { demux_ra_t *this = (demux_ra_t *) this_gen; free(this->header); + free(this->frame_buffer); free(this); } @@ -329,6 +398,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this = xine_xmalloc (sizeof (demux_ra_t)); this->stream = stream; this->input = input; + this->frame_buffer = NULL; this->demux_plugin.send_headers = demux_ra_send_headers; this->demux_plugin.send_chunk = demux_ra_send_chunk; diff --git a/src/demuxers/real_common.h b/src/demuxers/real_common.h new file mode 100644 index 000000000..4945a65ff --- /dev/null +++ b/src/demuxers/real_common.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA + */ + +static inline void demux_real_sipro_swap (char buffer[], int bs) +{ + /* bs = nybbles per subpacket */ + static const unsigned char sipr_swaps[38][2] = { + {0, 63}, {1, 22}, {2, 44}, {3, 90}, {5, 81}, {7, 31}, {8, 86}, {9, 58}, + {10, 36}, {12, 68}, {13, 39}, {14, 73}, {15, 53}, {16, 69}, {17, 57}, + {19, 88}, {20, 34}, {21, 71}, {24, 46}, {25, 94}, {26, 54}, {28, 75}, + {29, 50}, {32, 70}, {33, 92}, {35, 74}, {38, 85}, {40, 56}, {42, 87}, + {43, 65}, {45, 59}, {48, 79}, {49, 93}, {51, 89}, {55, 95}, {61, 76}, + {67, 83}, {77, 80} + }; + int n; + + for (n = 0; n < 38; ++n) + { + int j; + int i = bs * sipr_swaps[n][0]; + int o = bs * sipr_swaps[n][1]; + /* swap nibbles of block 'i' with 'o' TODO: optimize */ + for (j = 0; j < bs; ++j) + { + int x = (i & 1) ? (buffer[i >> 1] >> 4) : (buffer[i >> 1] & 0x0F); + int y = (o & 1) ? (buffer[o >> 1] >> 4) : (buffer[o >> 1] & 0x0F); + if (o & 1) + buffer[o >> 1] = (buffer[o >> 1] & 0x0F) | (x << 4); + else + buffer[o >> 1] = (buffer[o >> 1] & 0xF0) | x; + if (i & 1) + buffer[i >> 1] = (buffer[i >> 1] & 0x0F) | (y << 4); + else + buffer[i >> 1] = (buffer[i >> 1] & 0xF0) | y; + ++i; + ++o; + } + } +} diff --git a/src/libreal/xine_real_audio_decoder.c b/src/libreal/xine_real_audio_decoder.c index b9231a2b7..a12518c1e 100644 --- a/src/libreal/xine_real_audio_decoder.c +++ b/src/libreal/xine_real_audio_decoder.c @@ -51,6 +51,8 @@ typedef struct { /* empty so far */ } real_class_t; +typedef void * ra_codec_t; + typedef struct realdec_decoder_s { audio_decoder_t audio_decoder; @@ -60,18 +62,18 @@ typedef struct realdec_decoder_s { void *ra_handle; - unsigned long (*raCloseCodec)(void*); - unsigned long (*raDecode)(void*, char*,unsigned long,char*,unsigned int*,long); - unsigned long (*raFlush)(unsigned long,unsigned long,unsigned long); - unsigned long (*raFreeDecoder)(void*); - void* (*raGetFlavorProperty)(void*,unsigned long,unsigned long,int*); - unsigned long (*raInitDecoder)(void*, void*); - unsigned long (*raOpenCodec2)(void*); - unsigned long (*raSetFlavor)(void*,unsigned long); - void (*raSetDLLAccessPath)(char*); - void (*raSetPwd)(char*,char*); + uint32_t (*raCloseCodec)(ra_codec_t); + uint32_t (*raDecode)(ra_codec_t, char *, uint32_t, char *, uint32_t *, uint32_t); + uint32_t (*raFlush)(ra_codec_t, char *, uint32_t *); + uint32_t (*raFreeDecoder)(ra_codec_t); + void * (*raGetFlavorProperty)(ra_codec_t, uint16_t, uint16_t, uint16_t *); + uint32_t (*raInitDecoder)(ra_codec_t, void *); + uint32_t (*raOpenCodec2)(ra_codec_t *, const char *); + uint32_t (*raSetFlavor)(ra_codec_t, uint16_t); + void (*raSetDLLAccessPath)(char *); + void (*raSetPwd)(ra_codec_t, char *); - void *context; + ra_codec_t context; int sps, w, h; int block_align; @@ -92,14 +94,14 @@ typedef struct realdec_decoder_s { } realdec_decoder_t; typedef struct { - int samplerate; - short bits; - short channels; - int unk1; - int subpacket_size; - int coded_frame_size; - int codec_data_length; - void *extras; + uint32_t samplerate; + uint16_t bits; + uint16_t channels; + uint16_t quality; + uint32_t subpacket_size; + uint32_t coded_frame_size; + uint32_t codec_data_length; + void *extras; } ra_init_t; static int load_syms_linux (realdec_decoder_t *this, const char *const codec_name, const char *const codec_alternate) { @@ -216,13 +218,14 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Cook"); if (!load_syms_linux (this, "cook.so", "cook.so.6.0")) return 0; + this->block_align = subpacket_size; break; case BUF_AUDIO_ATRK: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_AUDIOCODEC, "Atrac"); if (!load_syms_linux (this, "atrc.so", "atrc.so.6.0")) return 0; - this->block_align = 384; + this->block_align = subpacket_size; break; case BUF_AUDIO_14_4: @@ -254,7 +257,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { * init codec */ - result = this->raOpenCodec2 (&this->context); + result = this->raOpenCodec2 (&this->context, NULL); if (result) { xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "libareal: error in raOpenCodec2: %d\n", result); return 0; @@ -266,7 +269,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { init_data.samplerate = samples_per_sec; init_data.bits = bits_per_sample; init_data.channels = num_channels; - init_data.unk1 = 100; /* ??? */ + init_data.quality = 100; /* ??? */ init_data.subpacket_size = subpacket_size; /* subpacket size */ init_data.coded_frame_size = coded_frame_size; /* coded frame size */ init_data.codec_data_length = data_len; /* codec data length */ @@ -350,13 +353,6 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { return 1; } -static const unsigned char sipr_swaps[38][2]={ - {0,63},{1,22},{2,44},{3,90},{5,81},{7,31},{8,86},{9,58},{10,36},{12,68}, - {13,39},{14,73},{15,53},{16,69},{17,57},{19,88},{20,34},{21,71},{24,46}, - {25,94},{26,54},{28,75},{29,50},{32,70},{33,92},{35,74},{38,85},{40,56}, - {42,87},{43,65},{45,59},{48,79},{49,93},{51,89},{55,95},{61,76},{67,83}, - {77,80} }; - static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) { realdec_decoder_t *this = (realdec_decoder_t *) this_gen; @@ -383,116 +379,32 @@ static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->pts = buf->pts; size = buf->size; - while (size) { + int need; - int needed; - - needed = this->frame_size - this->frame_num_bytes; - - if (needed>size) { - - memcpy (this->frame_buffer+this->frame_num_bytes, buf->content, size); + need = this->frame_size - this->frame_num_bytes; + if (size < need) { + memcpy (this->frame_buffer + this->frame_num_bytes, + buf->content + buf->size - size, size); this->frame_num_bytes += size; - - lprintf ("buffering %d/%d bytes\n", this->frame_num_bytes, this->frame_size); - size = 0; - } else { - - int result; - int len =-1; - int n; - int sps = this->sps; - int w = this->w; - int h = this->h; audio_buffer_t *audio_buffer; + int n, len; + int result; - lprintf ("buffering %d bytes\n", needed); - - memcpy (this->frame_buffer+this->frame_num_bytes, buf->content, needed); - - size -= needed; + memcpy (this->frame_buffer + this->frame_num_bytes, + buf->content + buf->size - size, need); + size -= need; this->frame_num_bytes = 0; - lprintf ("frame completed. reordering...\n"); - lprintf ("bs=%d sps=%d w=%d h=%d \n",/*sh->wf->nBlockAlign*/-1,sps,w,h); - - if (!sps) { - - int j,n; - int bs=h*w*2/96; /* nibbles per subpacket */ - unsigned char *p=this->frame_buffer; - - /* 'sipr' way */ - /* demux_read_data(sh->ds, p, h*w); */ - for (n=0;n<38;n++){ - int i=bs*sipr_swaps[n][0]; - int o=bs*sipr_swaps[n][1]; - /* swap nibbles of block 'i' with 'o' TODO: optimize */ - for (j=0;j<bs;j++) { - int x=(i&1) ? (p[(i>>1)]>>4) : (p[(i>>1)]&15); - int y=(o&1) ? (p[(o>>1)]>>4) : (p[(o>>1)]&15); - if (o&1) - p[(o>>1)]=(p[(o>>1)]&0x0F)|(x<<4); - else - p[(o>>1)]=(p[(o>>1)]&0xF0)|x; - - if (i&1) - p[(i>>1)]=(p[(i>>1)]&0x0F)|(y<<4); - else - p[(i>>1)]=(p[(i>>1)]&0xF0)|y; - - ++i; - ++o; - } - } - /* - sh->a_in_buffer_size= - sh->a_in_buffer_len=w*h; - */ - - } else { - int x, y; - uint8_t *s; - - /* 'cook' way */ - - w /= sps; s = this->frame_buffer; - - for (y=0; y<h; y++) - - for (x=0; x<w; x++) { - - lprintf ("x=%d, y=%d, off %d\n", - x, y, sps*(h*x+((h+1)/2)*(y&1)+(y>>1))); - - memcpy (this->frame_reordered+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), - s, sps); - s+=sps; - - /* demux_read_data(sh->ds, sh->a_in_buffer+sps*(h*x+((h+1)/2)*(y&1)+(y>>1)), - sps); */ - - } - /* - sh->a_in_buffer_size= - sh->a_in_buffer_len=w*h*sps; - */ - } - -#ifdef LOG - xine_hexdump (this->frame_reordered, buf->size); -#endif - n = 0; - while (n<this->frame_size) { + while (n < this->frame_size) { audio_buffer = this->stream->audio_out->get_buffer (this->stream->audio_out); result = this->raDecode (this->context, - this->frame_reordered+n, + this->frame_buffer + n, this->block_align, (char *) audio_buffer->mem, &len, -1); @@ -506,7 +418,7 @@ static void realdec_decode_data (audio_decoder_t *this_gen, buf_element_t *buf) this->stream->audio_out->put_buffer (this->stream->audio_out, audio_buffer, this->stream); - n+=this->block_align; + n += this->block_align; } } } @@ -609,5 +521,5 @@ static const uint32_t audio_types[] = { const decoder_info_t dec_info_realaudio = { audio_types, /* supported types */ - 7 /* priority */ + 6 /* priority */ }; diff --git a/src/libreal/xine_real_video_decoder.c b/src/libreal/xine_real_video_decoder.c index 28fddafda..2b5eafa16 100644 --- a/src/libreal/xine_real_video_decoder.c +++ b/src/libreal/xine_real_video_decoder.c @@ -63,9 +63,9 @@ typedef struct realdec_decoder_s { uint32_t (*rvyuv_custom_message)(void*, void*); uint32_t (*rvyuv_free)(void*); - uint32_t (*rvyuv_hive_message)(uint32_t, uint32_t); + uint32_t (*rvyuv_hive_message)(uint32_t, void*); uint32_t (*rvyuv_init)(void*, void*); /* initdata,context */ - uint32_t (*rvyuv_transform)(char*, char*, void*, uint32_t*,void*); + uint32_t (*rvyuv_transform)(char*, char*, void*, void*, void*); void *context; @@ -113,13 +113,21 @@ typedef struct cmsg_data_s { typedef struct transform_in_s { uint32_t len; - uint32_t unknown1; - uint32_t chunks; - uint32_t* extra; - uint32_t unknown2; + uint32_t interpolate; + uint32_t nsegments; + void *segments; + uint32_t flags; uint32_t timestamp; } transform_in_t; +typedef struct { + uint32_t frames; + uint32_t notes; + uint32_t timestamp; + uint32_t width; + uint32_t height; +} transform_out_t; + /* * real codec loader */ @@ -169,7 +177,6 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { int result; rv_init_t init_data = {11, 0, 0, 0, 0, 0, 1, 0}; /* rv30 */ - switch (buf->type) { case BUF_VIDEO_RV20: _x_meta_info_set_utf8(this->stream, XINE_META_INFO_VIDEOCODEC, "Real Video 2.0"); @@ -258,7 +265,7 @@ static int init_codec (realdec_decoder_t *this, buf_element_t *buf) { #ifdef LOG printf ("libreal: CustomMessage cmsg_data:\n"); - xine_hexdump ((uint8_t *) cmsg_data, sizeof (cmsg_data)); + xine_hexdump ((uint8_t *) &cmsg_data, sizeof (cmsg_data)); printf ("libreal: cmsg24:\n"); xine_hexdump ((uint8_t *) cmsg24, (buf->size - 34 + 2) * sizeof(uint32_t)); #endif @@ -342,7 +349,7 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) int result; vo_frame_t *img; - uint32_t transform_out[5]; + transform_out_t transform_out; transform_in_t transform_in = { this->chunk_buffer_size, /* length of the packet (sub-packets appended) */ @@ -369,7 +376,7 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) xine_hexdump (this->chunk_buffer, this->chunk_buffer_size); printf ("libreal: transform_in:\n"); - xine_hexdump ((uint8_t *) transform_in, 6 * 4); + xine_hexdump ((uint8_t *) &transform_in, sizeof(rv_xform_in_t)); printf ("libreal: chunk_table:\n"); xine_hexdump ((uint8_t *) buf->decoder_info_ptr[2], @@ -379,21 +386,21 @@ static void realdec_decode_data (video_decoder_t *this_gen, buf_element_t *buf) result = this->rvyuv_transform (this->chunk_buffer, this->frame_buffer, &transform_in, - transform_out, + &transform_out, this->context); lprintf ("transform result: %08x\n", result); lprintf ("transform_out:\n"); - #ifdef LOG - xine_hexdump ((uint8_t *) transform_out, 5 * 4); - #endif +#ifdef LOG + xine_hexdump ((uint8_t *) &transform_out, 5 * 4); +#endif /* Sometimes the stream contains video of a different size * to that specified in the realmedia header */ - if(transform_out[0] && ((transform_out[3] != this->width) || - (transform_out[4] != this->height))) { - this->width = transform_out[3]; - this->height = transform_out[4]; + if(transform_out.frames && ((transform_out.width != this->width) || + (transform_out.height != this->height))) { + this->width = transform_out.width; + this->height = transform_out.height; this->frame_size = this->width * this->height; @@ -531,8 +538,7 @@ void *init_realvdec (xine_t *xine, void *data) { * exported plugin catalog entry */ -static const uint32_t supported_types[] = { BUF_VIDEO_RV20, - BUF_VIDEO_RV30, +static const uint32_t supported_types[] = { BUF_VIDEO_RV30, BUF_VIDEO_RV40, 0 }; diff --git a/src/video_out/video_out_macosx.m b/src/video_out/video_out_macosx.m index 70cffaeb8..085387a44 100644 --- a/src/video_out/video_out_macosx.m +++ b/src/video_out/video_out_macosx.m @@ -207,7 +207,7 @@ static void macosx_display_frame(vo_driver_t *vo_driver, vo_frame_t *vo_frame) { break; case XINE_IMGFMT_YUY2: xine_fast_memcpy (texture_buffer, vo_frame->base[0], - vo_frame->pitches[0] * vo_frame->height * 2); + vo_frame->pitches[0] * vo_frame->height); [driver->view updateTexture]; break; default: diff --git a/src/xine-engine/buffer_types.c b/src/xine-engine/buffer_types.c index b0e01db31..15b5ff952 100644 --- a/src/xine-engine/buffer_types.c +++ b/src/xine-engine/buffer_types.c @@ -808,6 +808,14 @@ static const audio_db_t audio_db[] = { }, { { + ME_FOURCC('a', 'd', 'u', 0x55), + 0 + }, + BUF_AUDIO_MP3ADU, + "MPEG layer-3 adu" +}, +{ + { ME_FOURCC('t','w','o','s'), ME_FOURCC('i','n','2','4'), 0 |