diff options
Diffstat (limited to 'src/demuxers')
59 files changed, 2156 insertions, 978 deletions
diff --git a/src/demuxers/.cvsignore b/src/demuxers/.hgignore index 7d926a554..7d926a554 100644 --- a/src/demuxers/.cvsignore +++ b/src/demuxers/.hgignore diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index 4523afc27..8a931c2d6 100644 --- a/src/demuxers/Makefile.am +++ b/src/demuxers/Makefile.am @@ -1,12 +1,7 @@ include $(top_srcdir)/misc/Makefile.common -AM_CFLAGS = $(VORBIS_CFLAGS) $(THEORA_CFLAGS) $(SPEEX_CFLAGS) \ - $(LIBMODPLUG_CFLAGS) $(VISIBILITY_FLAG) -AM_CPPFLAGS = $(ZLIB_CPPFLAGS) - -libdir = $(XINE_PLUGINDIR) - -# Sensing of OGG/VORBIS, ZLIB and ASF is broken in cvscompile.sh. +AM_CFLAGS = $(VISIBILITY_FLAG) +AM_LDFLAGS = $(xineplug_ldflags) if HAVE_VORBIS ogg_module = xineplug_dmx_ogg.la @@ -29,7 +24,7 @@ endif # --------- # All of xine demuxer plugins should be named like the scheme "xineplug_dmx_" -lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module) \ +xineplug_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module) \ xineplug_dmx_games.la \ xineplug_dmx_audio.la \ xineplug_dmx_mpeg_ts.la \ @@ -52,65 +47,53 @@ lib_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module) \ xineplug_dmx_flv.la xineplug_dmx_ogg_la_SOURCES = demux_ogg.c -xineplug_dmx_ogg_la_LIBADD = $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(XINE_LIB) -xineplug_dmx_ogg_la_LDFLAGS = -avoid-version -module +xineplug_dmx_ogg_la_LIBADD = $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(XINE_LIB) +xineplug_dmx_ogg_la_CFLAGS = $(AM_CFLAGS) $(VORBIS_CFLAGS) $(SPEEX_CFLAGS) $(THEORA_CFLAGS) $(OGG_CFLAGS) xineplug_dmx_avi_la_SOURCES = demux_avi.c xineplug_dmx_avi_la_LIBADD = $(XINE_LIB) -xineplug_dmx_avi_la_LDFLAGS = -avoid-version -module xineplug_dmx_mpeg_block_la_SOURCES = demux_mpeg_block.c xineplug_dmx_mpeg_block_la_LIBADD = $(XINE_LIB) -xineplug_dmx_mpeg_block_la_LDFLAGS = -avoid-version -module xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB) -xineplug_dmx_mpeg_la_LDFLAGS = -avoid-version -module xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB) -xineplug_dmx_mpeg_elem_la_LDFLAGS = -avoid-version -module xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) -xineplug_dmx_mpeg_pes_la_LDFLAGS = -avoid-version -module xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB) -xineplug_dmx_mpeg_ts_la_LDFLAGS = -avoid-version -module xineplug_dmx_qt_la_SOURCES = demux_qt.c xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) -xineplug_dmx_qt_la_LDFLAGS = -avoid-version -module +xineplug_dmx_qt_la_CPPFLAGS = $(ZLIB_CPPFLAGS) xineplug_dmx_asf_la_SOURCES = demux_asf.c asfheader.c xineplug_dmx_asf_la_LIBADD = $(XINE_LIB) -xineplug_dmx_asf_la_CFLAGS = -fno-strict-aliasing -xineplug_dmx_asf_la_LDFLAGS = -avoid-version -module +xineplug_dmx_asf_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing xineplug_dmx_fli_la_SOURCES = demux_fli.c xineplug_dmx_fli_la_LIBADD = $(XINE_LIB) -xineplug_dmx_fli_la_LDFLAGS = -avoid-version -module xineplug_dmx_yuv4mpeg2_la_SOURCES = demux_yuv4mpeg2.c xineplug_dmx_yuv4mpeg2_la_LIBADD = $(XINE_LIB) -xineplug_dmx_yuv4mpeg2_la_LDFLAGS = -avoid-version -module xineplug_dmx_real_la_SOURCES = demux_real.c xineplug_dmx_real_la_LIBADD = $(XINE_LIB) -xineplug_dmx_real_la_LDFLAGS = -avoid-version -module xineplug_dmx_rawdv_la_SOURCES = demux_rawdv.c xineplug_dmx_rawdv_la_LIBADD = $(XINE_LIB) -xineplug_dmx_rawdv_la_LDFLAGS = -avoid-version -module xineplug_dmx_mng_la_SOURCES = demux_mng.c xineplug_dmx_mng_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(MNG_LIBS) -xineplug_dmx_mng_la_LDFLAGS = -avoid-version -module +xineplug_dmx_mng_la_CPPFLAGS = $(ZLIB_CPPFLAGS) xineplug_dmx_pva_la_SOURCES = demux_pva.c xineplug_dmx_pva_la_LIBADD = $(XINE_LIB) -xineplug_dmx_pva_la_LDFLAGS = -avoid-version -module xineplug_dmx_games_la_SOURCES = group_games.c demux_eawve.c \ demux_idcin.c demux_ipmovie.c demux_roq.c \ @@ -125,38 +108,33 @@ xineplug_dmx_audio_la_SOURCES = group_audio.c demux_aud.c demux_aiff.c \ demux_realaudio.c demux_snd.c demux_voc.c \ demux_vox.c demux_wav.c demux_ac3.c id3.c \ demux_aac.c demux_mod.c demux_flac.c \ - demux_mpc.c demux_dts.c demux_shn.c + demux_mpc.c demux_dts.c demux_shn.c \ + demux_tta.c xineplug_dmx_audio_la_LIBADD = $(XINE_LIB) $(LIBMODPLUG_LIBS) -xineplug_dmx_audio_la_LDFLAGS = -avoid-version -module +xineplug_dmx_audio_la_CFLAGS = $(AM_CFLAGS) $(LIBMODPLUG_CFLAGS) xineplug_dmx_yuv_frames_la_SOURCES = demux_yuv_frames.c xineplug_dmx_yuv_frames_la_LIBADD = $(XINE_LIB) -xineplug_dmx_yuv_frames_la_LDFLAGS = -avoid-version -module xineplug_dmx_slave_la_SOURCES = demux_slave.c xineplug_dmx_slave_la_LIBADD = $(XINE_LIB) -xineplug_dmx_slave_la_LDFLAGS = -avoid-version -module xineplug_dmx_image_la_SOURCES = demux_image.c xineplug_dmx_image_la_LIBADD = $(XINE_LIB) -xineplug_dmx_image_la_LDFLAGS = -avoid-version -module xineplug_dmx_nsv_la_SOURCES = demux_nsv.c xineplug_dmx_nsv_la_LIBADD = $(XINE_LIB) -xineplug_dmx_nsv_la_LDFLAGS = -avoid-version -module xineplug_dmx_matroska_la_SOURCES = demux_matroska.c ebml.c xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) -xineplug_dmx_matroska_la_CFLAGS = -fno-strict-aliasing -xineplug_dmx_matroska_la_LDFLAGS = -avoid-version -module +xineplug_dmx_matroska_la_CPPFLAGS = $(ZLIB_CPPFLAGS) +xineplug_dmx_matroska_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing xineplug_dmx_iff_la_SOURCES = demux_iff.c xineplug_dmx_iff_la_LIBADD = $(XINE_LIB) -xineplug_dmx_iff_la_LDFLAGS = -avoid-version -module xineplug_dmx_flv_la_SOURCES = demux_flv.c xineplug_dmx_flv_la_LIBADD = $(XINE_LIB) -xineplug_dmx_flv_la_LDFLAGS = -avoid-version -module -include_HEADERS = demux.h +xineinclude_HEADERS = demux.h noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h iff.h flacutils.h diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h index 0ce33b090..157519a87 100644 --- a/src/demuxers/demux.h +++ b/src/demuxers/demux.h @@ -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.h,v 1.39 2005/02/06 15:26:00 tmattern Exp $ + * $Id: demux.h,v 1.40 2007/01/19 00:26:39 dgp85 Exp $ */ #ifndef HAVE_DEMUX_H @@ -58,19 +58,19 @@ struct demux_class_s { /* * return human readable (verbose = 1 line) description for this plugin */ - char* (*get_description) (demux_class_t *this); + const char* (*get_description) (demux_class_t *this); /* * return human readable identifier for this plugin */ - char* (*get_identifier) (demux_class_t *this); + const char* (*get_identifier) (demux_class_t *this); /* * return MIME types supported for this plugin */ - char* (*get_mimetypes) (demux_class_t *this); + const char* (*get_mimetypes) (demux_class_t *this); /* * return ' ' seperated list of file extensions this @@ -79,7 +79,7 @@ struct demux_class_s { * file selection dialogs) */ - char* (*get_extensions) (demux_class_t *this); + const char* (*get_extensions) (demux_class_t *this); /* * close down, free all resources diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c index c6d2d3f0e..56360542c 100644 --- a/src/demuxers/demux_4xm.c +++ b/src/demuxers/demux_4xm.c @@ -23,7 +23,7 @@ * For more information on the 4xm file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_4xm.c,v 1.15 2004/06/13 21:28:52 miguelfreitas Exp $ + * $Id: demux_4xm.c,v 1.16 2007/01/19 00:26:39 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -493,7 +493,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -523,19 +523,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "4X Technologies (4xm) demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "4X Technologies"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "4xm"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_aac.c b/src/demuxers/demux_aac.c index b9e4c4084..ab71e8382 100644 --- a/src/demuxers/demux_aac.c +++ b/src/demuxers/demux_aac.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2001-2005 the xine project + * Copyright (C) 2001-2007 the xine project * * This file is part of xine, a free video player. * @@ -21,7 +21,7 @@ * This demuxer detects ADIF and ADTS headers in AAC files. * Then it shovels buffer-sized chunks over to the AAC decoder. * - * $Id: demux_aac.c,v 1.12 2006/11/14 21:51:32 dsalt Exp $ + * $Id: demux_aac.c,v 1.17 2007/03/03 01:41:16 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -48,6 +48,8 @@ #include "bswap.h" #include "group_audio.h" +#include "id3.h" + typedef struct { demux_plugin_t demux_plugin; @@ -57,7 +59,6 @@ typedef struct { input_plugin_t *input; int status; - off_t data_start; off_t data_size; int seek_flag; /* this is set when a seek just occurred */ @@ -72,11 +73,30 @@ static int open_aac_file(demux_aac_t *this) { int i; uint8_t peak[MAX_PREVIEW_SIZE]; uint16_t syncword = 0; + uint32_t id3size = 0; + off_t data_start = 0; - /* Check for an ADIF header - should be at the start of the file */ - if (_x_demux_read_header(this->input, peak, 4) != 4) + _x_assert(MAX_PREVIEW_SIZE > 10); + + /* Get enough data to be able to check the size of ID3 tag */ + if (_x_demux_read_header(this->input, peak, 10) != 10) return 0; + /* Check if there's an ID3v2 tag at the start */ + if ( id3v2_istag(peak) ) { + id3size = id3v2_tagsize(&peak[6]); + + this->input->seek(this->input, 4, SEEK_SET); + + id3v2_parse_tag(this->input, this->stream, peak); + + lprintf("ID3v2 tag encountered, skipping %u bytes.\n", id3size); + } + + if ( this->input->read(this->input, peak, 4) != 4 ) + return 0; + + /* Check for an ADIF header - should be at the start of the file */ if ((peak[0] == 'A') && (peak[1] == 'D') && (peak[2] == 'I') && (peak[3] == 'F')) { lprintf("found ADIF header\n"); @@ -84,13 +104,20 @@ static int open_aac_file(demux_aac_t *this) { } /* Look for an ADTS header - might not be at the start of the file */ - if (_x_demux_read_header(this->input, peak, MAX_PREVIEW_SIZE) != - MAX_PREVIEW_SIZE) + if ( id3size != 0 && this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE ) { + lprintf("Getting a buffer of size %u starting from %u\n", MAX_PREVIEW_SIZE, id3size); + + this->input->seek(this->input, id3size, SEEK_SET); + if ( this->input->read(this->input, peak, MAX_PREVIEW_SIZE) != MAX_PREVIEW_SIZE ) + return 0; + this->input->seek(this->input, 0, SEEK_SET); + } else if (_x_demux_read_header(this->input, peak, MAX_PREVIEW_SIZE) != + MAX_PREVIEW_SIZE) return 0; for (i=0; i<MAX_PREVIEW_SIZE; i++) { if ((syncword & 0xfff6) == 0xfff0) { - this->data_start = i - 2; + data_start = i - 2; lprintf("found ADTS header at offset %d\n", i-2); break; } @@ -99,27 +126,27 @@ static int open_aac_file(demux_aac_t *this) { } /* Look for second ADTS header to confirm it's really aac */ - if (this->data_start + 5 < MAX_PREVIEW_SIZE) { - int frame_size = ((peak[this->data_start+3] & 0x03) << 11) | - (peak[this->data_start+4] << 3) | - ((peak[this->data_start+5] & 0xe0) >> 5); + if (data_start + 5 < MAX_PREVIEW_SIZE) { + int frame_size = ((peak[data_start+3] & 0x03) << 11) | + (peak[data_start+4] << 3) | + ((peak[data_start+5] & 0xe0) >> 5); lprintf("first frame size %d\n", frame_size); if ((frame_size > 0) && - (this->data_start+frame_size < MAX_PREVIEW_SIZE-1) && + (data_start+frame_size < MAX_PREVIEW_SIZE-1) && /* first 28 bits must be identical */ - (peak[this->data_start ] ==peak[this->data_start+frame_size ]) && - (peak[this->data_start+1] ==peak[this->data_start+frame_size+1]) && - (peak[this->data_start+2] ==peak[this->data_start+frame_size+2]) && - (peak[this->data_start+3]>>4==peak[this->data_start+frame_size+3]>>4)) + (peak[data_start ] ==peak[data_start+frame_size ]) && + (peak[data_start+1] ==peak[data_start+frame_size+1]) && + (peak[data_start+2] ==peak[data_start+frame_size+2]) && + (peak[data_start+3]>>4==peak[data_start+frame_size+3]>>4)) { lprintf("found second ADTS header\n"); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 0); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1); - this->input->seek(this->input, this->data_start, SEEK_SET); + this->input->seek(this->input, data_start+id3size, SEEK_SET); return 1; } } @@ -255,7 +282,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -283,19 +310,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "ADIF/ADTS AAC demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "AAC"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "aac"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c index fa2dddfed..7f3dadeb7 100644 --- a/src/demuxers/demux_ac3.c +++ b/src/demuxers/demux_ac3.c @@ -23,7 +23,7 @@ * This demuxer detects raw AC3 data in a file and shovels AC3 data * directly to the AC3 decoder. * - * $Id: demux_ac3.c,v 1.19 2005/06/04 20:32:08 jstembridge Exp $ + * $Id: demux_ac3.c,v 1.21 2007/03/19 16:42:32 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -51,7 +51,6 @@ #include "group_audio.h" #define DATA_TAG 0x61746164 -#define PEAK_SIZE 7056 /* 3 raw cd frames */ typedef struct { demux_plugin_t demux_plugin; @@ -129,31 +128,29 @@ static const struct frmsize_s frmsizecod_tbl[64] = static int open_ac3_file(demux_ac3_t *this) { int i; int offset = 0; - int peak_size = 0; + size_t peak_size = 0; int spdif_mode = 0; uint32_t syncword = 0; uint32_t blocksize; - uint8_t peak[PEAK_SIZE]; + uint8_t *peak; - lprintf("open_ac3_file\n"); - - /* block based demuxer (i.e. cdda) will only allow reads in block - * sized pieces */ blocksize = this->input->get_blocksize(this->input); - if (blocksize && INPUT_IS_SEEKABLE(this->input)) { - int read; - + if (blocksize) { this->input->seek(this->input, 0, SEEK_SET); - while (peak_size < PEAK_SIZE) { - read = this->input->read(this->input, &peak[peak_size], blocksize); - if (read) - peak_size += read; - else - break; - } + buf_element_t *buf = this->input->read_block(this->input, + this->audio_fifo, + blocksize); this->input->seek(this->input, 0, SEEK_SET); + + if (!buf) + return 0; + + peak = alloca(peak_size = buf->size); + xine_fast_memcpy(peak, buf->content, peak_size); + + buf->free_buffer(buf); } else { - peak_size = MAX_PREVIEW_SIZE; + peak = alloca(peak_size = MAX_PREVIEW_SIZE); if (_x_demux_read_header(this->input, peak, peak_size) != peak_size) return 0; @@ -163,10 +160,7 @@ static int open_ac3_file(demux_ac3_t *this) { /* Check for wav header, as we'll handle AC3 with a wav header shoved * on the front for CD burning */ - if ((peak[0] == 'R') && (peak[1] == 'I') && (peak[2] == 'F') && - (peak[3] == 'F') && (peak[8] == 'W') && (peak[9] == 'A') && - (peak[10] == 'V') && (peak[11] == 'E') && (peak[12] == 'f') && - (peak[13] == 'm') && (peak[14] == 't') && (peak[15] == ' ')) { + if ( memcmp(peak, "RIFF", 4) == 0 || memcmp(&peak[8], "WAVEfmt ", 8) == 0 ) { /* Check this looks like a cd audio wav */ unsigned int audio_type; xine_waveformatex *wave = (xine_waveformatex *) &peak[20]; @@ -441,7 +435,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -471,19 +465,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Raw AC3 demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "AC3"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "ac3"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_aiff.c b/src/demuxers/demux_aiff.c index 253827454..f88c58572 100644 --- a/src/demuxers/demux_aiff.c +++ b/src/demuxers/demux_aiff.c @@ -21,7 +21,7 @@ /* * AIFF File Demuxer by Mike Melanson (melanson@pcisys.net) * - * $Id: demux_aiff.c,v 1.40 2004/12/15 21:03:02 mroi Exp $ + * $Id: demux_aiff.c,v 1.41 2007/01/19 00:26:40 dgp85 Exp $ * */ @@ -359,7 +359,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -389,19 +389,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "AIFF file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "AIFF"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "aif aiff"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-aiff: aif, aiff: AIFF audio;" "audio/aiff: aif, aiff: AIFF audio;" "audio/x-pn-aiff: aif, aiff: AIFF audio;"; diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c index ba31d6e51..65838138f 100644 --- a/src/demuxers/demux_asf.c +++ b/src/demuxers/demux_asf.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_asf.c,v 1.188 2006/11/29 21:26:52 dgp85 Exp $ + * $Id: demux_asf.c,v 1.194 2007/03/09 23:18:19 dgp85 Exp $ * * demultiplexer for asf streams * @@ -38,6 +38,9 @@ #include <unistd.h> #include <string.h> #include <stdlib.h> +#ifdef HAVE_ALLOCA_H +#include <alloca.h> +#endif #define LOG_MODULE "demux_asf" #define LOG_VERBOSE @@ -408,7 +411,9 @@ static int asf_read_header (demux_asf_t *this) { this->length = 0; /* compute average byterate (needed for seeking) */ - if (this->length) + if (this->asf_header->file->max_bitrate) + this->rate = this->asf_header->file->max_bitrate >> 3; + else if (this->length) this->rate = (int64_t) this->input->get_length(this->input) * 1000 / this->length; _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->asf_header->file->max_bitrate); @@ -639,15 +644,15 @@ static void check_newpts (demux_asf_t *this, int64_t pts, int video, int frame_e #ifdef LOG if (pts) { if (video) { - printf ("demux_asf: VIDEO: pts = %8lld, diff = %8lld\n", pts, pts - this->last_pts[video]); + printf ("demux_asf: VIDEO: pts = %8"PRId64", diff = %8"PRId64"\n", pts, pts - this->last_pts[video]); } else { - printf ("demux_asf: AUDIO: pts = %8lld, diff = %8lld\n", pts, pts - this->last_pts[video]); + printf ("demux_asf: AUDIO: pts = %8"PRId64", diff = %8"PRId64"\n", pts, pts - this->last_pts[video]); } } #endif if (pts && (this->send_newpts || (this->last_pts[video] && abs(diff) > WRAP_THRESHOLD))) { - lprintf ("sending newpts %lld (video = %d diff = %lld)\n", pts, video, diff); + lprintf ("sending newpts %"PRId64" (video = %d diff = %"PRId64")\n", pts, video, diff); if (this->buf_flag_seek) { _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); @@ -674,7 +679,7 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str int bufsize; int package_done; - lprintf ("pts=%lld, off=%d, len=%d, total=%d\n", + lprintf ("pts=%"PRId64", off=%d, len=%d, total=%d\n", timestamp * 90, frag_offset, frag_len, stream->payload_size); if (frag_offset == 0) { @@ -758,7 +763,7 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *strea printf("asf_send_buffer seq=%d frag_offset=%d frag_len=%d\n", seq, frag_offset, frag_len ); */ - lprintf ("asf_send_buffer_defrag: timestamp=%lld, pts=%lld\n", timestamp, timestamp * 90); + lprintf ("asf_send_buffer_defrag: timestamp=%"PRId64", pts=%"PRId64"\n", timestamp, timestamp * 90); if (frag_offset == 0) { /* new packet */ @@ -864,11 +869,11 @@ static int asf_parse_packet_align(demux_asf_t *this) { /* check packet_count */ packet_num = (packet_pos - this->first_packet_pos) / this->packet_size; - lprintf("packet_num=%lld, packet_count=%lld\n", packet_num, this->packet_count); + lprintf("packet_num=%"PRId64", packet_count=%"PRId64"\n", packet_num, this->packet_count); if (packet_num >= this->packet_count) { /* end of payload data */ current_pos = this->input->get_current_pos (this->input); - lprintf("end of payload data, current_pos=%lld\n", current_pos); + lprintf("end of payload data, current_pos=%"PRId64"\n", current_pos); { /* check new asf header */ if (get_guid(this) == GUID_ASF_HEADER) { @@ -998,7 +1003,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz timestamp = get_le32(this); p_hdr_size += 4; duration = get_le16(this); p_hdr_size += 2; - lprintf ("timestamp=%lld, duration=%lld\n", timestamp, duration); + lprintf ("timestamp=%"PRId64", duration=%"PRId64"\n", timestamp, duration); if ((this->packet_len_flags >> 5) & 3) { /* absolute data size */ @@ -1354,7 +1359,6 @@ static int demux_asf_parse_http_references( demux_asf_t *this) { int buf_used = 0; int len; char *href = NULL; - char *mrl; int free_href = 0; /* read file to memory. @@ -1379,7 +1383,7 @@ static int demux_asf_parse_http_references( demux_asf_t *this) { ptr = buf; if (!strncmp(ptr, "[Reference]", 11)) { - mrl = this->input->get_mrl(this->input); + const char *const mrl = this->input->get_mrl(this->input); if (!strncmp(mrl, "http", 4)) { /* never trust a ms server, reopen the same mrl with the mms input plugin * some servers are badly configured and return a incorrect reference. @@ -1789,11 +1793,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, int i, state; int64_t ts; - start_time /= 1000; - start_pos = (off_t) ( (double) start_pos / 65535 * - this->input->get_length (this->input) ); - - lprintf ("demux_asf_seek: start_pos=%lld, start_time=%d\n", + lprintf ("demux_asf_seek: start_pos=%"PRId64", start_time=%d\n", start_pos, start_time); this->status = DEMUX_OK; @@ -1824,6 +1824,10 @@ static int demux_asf_seek (demux_plugin_t *this_gen, _x_demux_flush_engine(this->stream); + start_time /= 1000; + start_pos = (off_t) ( (double) start_pos / 65535 * + this->input->get_length (this->input) ); + if ( (!start_pos) && (start_time)) start_pos = start_time * this->rate; @@ -1910,13 +1914,13 @@ static int demux_asf_seek (demux_plugin_t *this_gen, } state = 1; /* search an audio packet with pts < this->keyframe_pts */ - lprintf ("demux_asf_seek: keyframe found at %lld, timestamp = %lld\n", start_pos, ts); + lprintf ("demux_asf_seek: keyframe found at %"PRId64", timestamp = %"PRId64"\n", start_pos, ts); check_newpts (this, ts * 90, 1, 0); } } else if (state == 1) { if ((this->audio_stream != -1 && stream_id == this->asf_header->streams[this->audio_stream]->stream_number) && ts && (ts <= this->keyframe_ts)) { - lprintf ("demux_asf_seek: audio packet found at %lld, ts = %lld\n", start_pos, ts); + lprintf ("demux_asf_seek: audio packet found at %"PRId64", ts = %"PRId64"\n", start_pos, ts); state = 5; /* end */ break; @@ -1927,7 +1931,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, this->keyframe_ts = ts; state = 5; /* end */ - lprintf ("demux_asf_seek: audio packet found at %lld, timestamp = %lld\n", start_pos, ts); + lprintf ("demux_asf_seek: audio packet found at %"PRId64", timestamp = %"PRId64"\n", start_pos, ts); check_newpts (this, ts * 90, 0, 0); } } @@ -1941,7 +1945,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen, } else { this->input->seek (this->input, start_pos + this->packet_size, SEEK_SET); } - lprintf ("demux_asf_seek: keyframe_found=%d, keyframe_ts=%lld\n", + lprintf ("demux_asf_seek: keyframe_found=%d, keyframe_ts=%"PRId64"\n", this->keyframe_found, this->keyframe_ts); if (this->video_stream >= 0) { this->streams[this->video_stream].resync = 1; @@ -1951,6 +1955,22 @@ static int demux_asf_seek (demux_plugin_t *this_gen, this->streams[this->audio_stream].resync = 1; this->streams[this->audio_stream].skip = 1; } + } else if (!playing && this->input->seek_time != NULL) { + if (start_pos && !start_time) + start_time = this->length * start_pos / 65535; + + this->input->seek_time (this->input, start_time, SEEK_SET); + + this->keyframe_ts = 0; + this->keyframe_found = 0; /* means next keyframe */ + if (this->video_stream >= 0) { + this->streams[this->video_stream].resync = 1; + this->streams[this->video_stream].skip = 1; + } + if (this->audio_stream >= 0) { + this->streams[this->audio_stream].resync = 0; + this->streams[this->audio_stream].skip = 0; + } } else { /* "streaming" mode */ this->keyframe_ts = 0; @@ -2034,15 +2054,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; - - mrl = input->get_mrl (input); - - /* - * check extension - */ - - ending = strrchr (mrl, '.'); + const char *const mrl = input->get_mrl (input); + const char *const ending = strrchr (mrl, '.'); if (!ending) return NULL; @@ -2105,20 +2118,20 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "ASF demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "ASF"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { /* asx, wvx, wax are metafile or playlist */ return "asf wmv wma asx wvx wax"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "video/x-ms-asf: asf: ASF stream;" "video/x-ms-wmv: wmv: Windows Media Video;" diff --git a/src/demuxers/demux_aud.c b/src/demuxers/demux_aud.c index 5ebf25e13..ea57a6939 100644 --- a/src/demuxers/demux_aud.c +++ b/src/demuxers/demux_aud.c @@ -34,7 +34,7 @@ * data. This makes seeking conceptually impossible. Upshot: Random * seeking is not supported. * - * $Id: demux_aud.c,v 1.19 2004/06/13 21:28:52 miguelfreitas Exp $ + * $Id: demux_aud.c,v 1.20 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -292,7 +292,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str case METHOD_BY_CONTENT: /* no reliable detection */ case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -320,19 +320,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Westwood Studios AUD file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Westwood Studios AUD"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "aud"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c index 4f4cbc428..fe324c2f4 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_avi.c,v 1.228 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_avi.c,v 1.232 2007/03/29 19:24:18 dgp85 Exp $ * * demultiplexer for avi streams * @@ -194,8 +194,8 @@ typedef struct{ uint32_t audio_posb; /* Audio position: byte within chunk */ + int wavex_len; xine_waveformatex *wavex; - int wavex_len; audio_index_t audio_idx; @@ -251,28 +251,27 @@ typedef struct demux_avi_s { input_plugin_t *input; int status; - avi_t *avi; - - int no_audio; - uint32_t video_step; uint32_t AVI_errno; - idx_grow_t idx_grow; - - int streaming; - int last_index_entry_type; - int has_index; - /* seeking args backup */ - int seek_request; - off_t seek_start_pos; int seek_start_time; + off_t seek_start_pos; + + avi_t *avi; + + idx_grow_t idx_grow; + + uint8_t no_audio:1; + + uint8_t streaming:1; + uint8_t has_index:1; + + uint8_t seek_request:1; /* discontinuity detection (only at seek) */ - int send_newpts; - int buf_flag_seek; - + uint8_t buf_flag_seek:1; + uint8_t send_newpts:1; } demux_avi_t ; typedef struct { @@ -1392,7 +1391,7 @@ static avi_t *AVI_init(demux_avi_t *this) { AVI->video_posf = 0; AVI->video_posb = 0; - lprintf("done, pos=%lld, AVI->movi_start=%" PRIdMAX "\n", this->input->get_current_pos(this->input), (intmax_t)AVI->movi_start); + lprintf("done, pos=%"PRId64", AVI->movi_start=%" PRIdMAX "\n", this->input->get_current_pos(this->input), (intmax_t)AVI->movi_start); return AVI; } @@ -2259,7 +2258,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -2316,19 +2315,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str * demux avi class */ -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "AVI/RIFF demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "AVI"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "avi"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "video/msvideo: avi: AVI video;" "video/x-msvideo: avi: AVI video;"; } diff --git a/src/demuxers/demux_cdda.c b/src/demuxers/demux_cdda.c index 3790ee6b9..d92a8ba23 100644 --- a/src/demuxers/demux_cdda.c +++ b/src/demuxers/demux_cdda.c @@ -24,7 +24,7 @@ * linear PCM "decoder" (which in turn sends them directly to the audio * output target; this is a really fancy CD-playing architecture). * - * $Id: demux_cdda.c,v 1.19 2004/06/13 21:28:52 miguelfreitas Exp $ + * $Id: demux_cdda.c,v 1.20 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -227,19 +227,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "CD Digital Audio demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "CDDA"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return NULL; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c index 16f14211d..7baeae377 100644 --- a/src/demuxers/demux_dts.c +++ b/src/demuxers/demux_dts.c @@ -19,7 +19,7 @@ * * Raw DTS Demuxer by James Stembridge (jstembridge@gmail.com) * - * $Id: demux_dts.c,v 1.6 2005/06/04 20:32:08 jstembridge Exp $ + * $Id: demux_dts.c,v 1.8 2007/03/19 16:42:32 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -47,7 +47,6 @@ #include "group_audio.h" #define DATA_TAG 0x61746164 -#define PEAK_SIZE 7056 /* 3 raw cd frames */ typedef struct { demux_plugin_t demux_plugin; @@ -79,29 +78,29 @@ static const int dts_sample_rates[] = static int open_dts_file(demux_dts_t *this) { int i, offset = 0; uint32_t syncword = 0; - int peak_size = 0; + size_t peak_size = 0; uint32_t blocksize; - uint8_t peak[PEAK_SIZE]; + uint8_t *peak; lprintf("open_dts_file\n"); - /* block based demuxer (i.e. cdda) will only allow reads in block - * sized pieces */ blocksize = this->input->get_blocksize(this->input); - if (blocksize && INPUT_IS_SEEKABLE(this->input)) { - int read; - + if (blocksize) { this->input->seek(this->input, 0, SEEK_SET); - while (peak_size < PEAK_SIZE) { - read = this->input->read(this->input, &peak[peak_size], blocksize); - if (read) - peak_size += read; - else - break; - } + buf_element_t *buf = this->input->read_block(this->input, + this->audio_fifo, + blocksize); this->input->seek(this->input, 0, SEEK_SET); + + if (!buf) + return 0; + + peak = alloca(peak_size = buf->size); + xine_fast_memcpy(peak, buf->content, peak_size); + + buf->free_buffer(buf); } else { - peak_size = MAX_PREVIEW_SIZE; + peak = alloca(peak_size = MAX_PREVIEW_SIZE); if (_x_demux_read_header(this->input, peak, peak_size) != peak_size) return 0; @@ -111,10 +110,7 @@ static int open_dts_file(demux_dts_t *this) { /* Check for wav header, as we'll handle DTS with a wav header shoved * on the front for CD burning */ - if ((peak[0] == 'R') && (peak[1] == 'I') && (peak[2] == 'F') && - (peak[3] == 'F') && (peak[8] == 'W') && (peak[9] == 'A') && - (peak[10] == 'V') && (peak[11] == 'E') && (peak[12] == 'f') && - (peak[13] == 'm') && (peak[14] == 't') && (peak[15] == ' ')) { + if ( memcmp(peak, "RIFF", 4) == 0 || memcmp(&peak[8], "WAVEfmt ", 8) == 0 ) { /* Check this looks like a cd audio wav */ unsigned int audio_type; xine_waveformatex *wave = (xine_waveformatex *) &peak[20]; @@ -368,7 +364,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -396,19 +392,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Raw DTS demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "DTS"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "dts"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_eawve.c b/src/demuxers/demux_eawve.c index 7d7cc922a..67c087208 100644 --- a/src/demuxers/demux_eawve.c +++ b/src/demuxers/demux_eawve.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_eawve.c,v 1.28 2004/06/13 21:28:52 miguelfreitas Exp $ + * $Id: demux_eawve.c,v 1.29 2007/01/19 00:26:40 dgp85 Exp $ * * demux_eawve.c, Demuxer plugin for Electronic Arts' WVE file format * @@ -370,7 +370,7 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -400,19 +400,19 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre return &this->demux_plugin; } -static char *get_description(demux_class_t *this_gen){ +static const char *get_description(demux_class_t *this_gen){ return "Electronics Arts WVE format demux plugin"; } -static char *get_identifier(demux_class_t *this_gen){ +static const char *get_identifier(demux_class_t *this_gen){ return "EA WVE"; } -static char *get_extensions(demux_class_t *this_gen){ +static const char *get_extensions(demux_class_t *this_gen){ return "wve"; } -static char *get_mimetypes(demux_class_t *this_gen){ +static const char *get_mimetypes(demux_class_t *this_gen){ return NULL; } diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c index 2645992bc..be86b32ed 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_elem.c,v 1.89 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_elem.c,v 1.91 2007/02/20 00:34:55 dgp85 Exp $ * * demultiplexer for elementary mpeg streams */ @@ -73,7 +73,7 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) { buf = this->video_fifo->buffer_pool_alloc(this->video_fifo); blocksize = (this->blocksize ? this->blocksize : buf->max_size); done = this->input->read(this->input, buf->mem, blocksize); - lprintf ("read size = %lld\n", done); + lprintf ("read size = %"PRId64"\n", done); if (done <= 0) { buf->free_buffer (buf); @@ -160,7 +160,7 @@ static int demux_mpeg_elem_seek (demux_plugin_t *this_gen, this->status = DEMUX_FINISHED; return this->status; } - lprintf ("seeking to %lld\n", start_pos); + lprintf ("seeking to %"PRId64"\n", start_pos); } /* @@ -225,7 +225,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -261,19 +261,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Elementary MPEG stream demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MPEG_ELEM"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mpv"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c index f4a27c22b..d3cedc0e1 100644 --- a/src/demuxers/demux_film.c +++ b/src/demuxers/demux_film.c @@ -21,7 +21,7 @@ * For more information on the FILM file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_film.c,v 1.81 2006/11/19 16:07:50 dgp85 Exp $ + * $Id: demux_film.c,v 1.82 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -874,7 +874,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -904,19 +904,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "FILM (CPK) demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "FILM (CPK)"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "cpk cak film"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c index bd5c19350..f52da4d03 100644 --- a/src/demuxers/demux_flac.c +++ b/src/demuxers/demux_flac.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2004 the xine project + * Copyright (C) 2000-2007 the xine project * * This file is part of xine, a free video player. * @@ -23,7 +23,7 @@ * For more information on the FLAC file format, visit: * http://flac.sourceforge.net/ * - * $Id: demux_flac.c,v 1.12 2006/11/09 23:51:29 dgp85 Exp $ + * $Id: demux_flac.c,v 1.17 2007/03/29 16:52:23 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -49,6 +49,7 @@ #include "bswap.h" #include "group_audio.h" +#include "id3.h" #include "flacutils.h" typedef struct { @@ -66,10 +67,10 @@ typedef struct { off_t data_start; off_t data_size; - unsigned char streaminfo[sizeof(xine_waveformatex) + FLAC_STREAMINFO_SIZE]; flac_seekpoint_t *seekpoints; int seekpoint_count; + unsigned char streaminfo[sizeof(xine_waveformatex) + FLAC_STREAMINFO_SIZE]; } demux_flac_t; typedef struct { @@ -81,7 +82,7 @@ typedef struct { * It returns 1 if flac file was opened successfully. */ static int open_flac_file(demux_flac_t *flac) { - unsigned char preamble[4]; + unsigned char preamble[10]; unsigned int block_length; unsigned char buffer[FLAC_SEEKPOINT_SIZE]; unsigned char *streaminfo = flac->streaminfo + sizeof(xine_waveformatex); @@ -89,26 +90,19 @@ static int open_flac_file(demux_flac_t *flac) { flac->seekpoints = NULL; - /* fetch the file signature */ - if (_x_demux_read_header(flac->input, preamble, 4) != 4) + /* fetch the file signature, get enough bytes so that id3 can also + be skipped and/or parsed */ + if (_x_demux_read_header(flac->input, preamble, 10) != 10) return 0; - /* validate signature */ - if ((preamble[0] != 'f') || - (preamble[1] != 'L') || - (preamble[2] != 'a') || - (preamble[3] != 'C')) { - + /* Unfortunately some FLAC files have an ID3 flag prefixed on them + * before the actual FLAC headers... these are barely legal, but + * users use them and want them working, so check and skip the ID3 + * tag if present. + */ + if ( id3v2_istag(preamble) ) { uint32_t id3size; - /* Unfortunately some FLAC files have an ID3 flag prefixed on them - * before the actual FLAC headers... these are barely legal, but - * users use them and want them working, so check and skip the ID3 - * tag if present. - */ - if ( preamble[0] != 'I' || preamble[1] != 'D' || preamble[2] != '3' ) - return 0; - /* First 3 bytes are the ID3 signature as above, then comes two bytes * encoding the major and minor version of ID3 used, that we can ignore * as long as we don't try to read the metadata; after those there's a @@ -117,24 +111,22 @@ static int open_flac_file(demux_flac_t *flac) { * is encoded as four bytes.. but only 7 out of 8 bits of every byte is * used... don't ask. */ - flac->input->seek(flac->input, 6, SEEK_SET); - if ( flac->input->read(flac->input, preamble, 4) != 4 ) - return 0; + id3size = id3v2_tagsize(&preamble[6]); - id3size = (preamble[0] << 7*3) + (preamble[1] << 7*2) + (preamble[2] << 7) + preamble[3]; - - flac->input->seek(flac->input, id3size, SEEK_CUR); + id3v2_parse_tag(flac->input, flac->stream, preamble); + + flac->input->seek(flac->input, id3size, SEEK_SET); if ( flac->input->read(flac->input, preamble, 4) != 4 ) return 0; - - if ( preamble[0] != 'f' || preamble[1] != 'L' || preamble[2] != 'a' || preamble[3] != 'C' ) - return 0; - - } else - /* file is qualified; skip over the signature bytes in the stream */ + } else flac->input->seek(flac->input, 4, SEEK_SET); + /* validate signature */ + if ((preamble[0] != 'f') || (preamble[1] != 'L') || + (preamble[2] != 'a') || (preamble[3] != 'C')) + return 0; + /* loop through the metadata blocks; use a do-while construct since there * will always be 1 metadata block */ do { @@ -166,7 +158,7 @@ static int open_flac_file(demux_flac_t *flac) { flac->bits_per_sample = ((flac->sample_rate >> 4) & 0x1F) + 1; flac->sample_rate >>= 12; flac->total_samples = BE_64(&streaminfo[10]) & UINT64_C(0x0FFFFFFFFF); /* 36 bits */ - lprintf ("%d Hz, %d bits, %d channels, %lld total samples\n", + lprintf ("%d Hz, %d bits, %d channels, %"PRId64" total samples\n", flac->sample_rate, flac->bits_per_sample, flac->channels, flac->total_samples); break; @@ -193,15 +185,15 @@ static int open_flac_file(demux_flac_t *flac) { if (flac->input->read(flac->input, buffer, FLAC_SEEKPOINT_SIZE) != FLAC_SEEKPOINT_SIZE) return 0; flac->seekpoints[i].sample_number = BE_64(&buffer[0]); - lprintf (" %d: sample %lld, ", i, flac->seekpoints[i].sample_number); + lprintf (" %d: sample %"PRId64", ", i, flac->seekpoints[i].sample_number); flac->seekpoints[i].offset = BE_64(&buffer[8]); flac->seekpoints[i].size = BE_16(&buffer[16]); - lprintf ("@ 0x%llX, size = %d bytes, ", + lprintf ("@ 0x%"PRIX64", size = %d bytes, ", flac->seekpoints[i].offset, flac->seekpoints[i].size); flac->seekpoints[i].pts = flac->seekpoints[i].sample_number; flac->seekpoints[i].pts *= 90000; flac->seekpoints[i].pts /= flac->sample_rate; - lprintf ("pts = %lld\n", flac->seekpoints[i].pts); + lprintf ("pts = %"PRId64"\n", flac->seekpoints[i].pts); } break; @@ -524,7 +516,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -554,19 +546,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Free Lossless Audio Codec (flac) demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "FLAC"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "flac"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_fli.c b/src/demuxers/demux_fli.c index e17e47258..c9cc26cf1 100644 --- a/src/demuxers/demux_fli.c +++ b/src/demuxers/demux_fli.c @@ -24,7 +24,7 @@ * avoid while programming a FLI decoder, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_fli.c,v 1.59 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_fli.c,v 1.60 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -324,7 +324,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -354,19 +354,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Autodesk Animator FLI/FLC demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "FLI/FLC"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "fli flc"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "video/x-flic: fli,flc: Autodesk FLIC files;"; } diff --git a/src/demuxers/demux_flv.c b/src/demuxers/demux_flv.c index 57f83e002..0588b408e 100644 --- a/src/demuxers/demux_flv.c +++ b/src/demuxers/demux_flv.c @@ -20,11 +20,13 @@ /* * Flash Video (.flv) File Demuxer - * by Mike Melanson (melanson@pcisys.net) + * by Mike Melanson (melanson@pcisys.net) and + * Claudio Ciccani (klan@directfb.org) + * * For more information on the FLV file format, visit: * http://download.macromedia.com/pub/flash/flash_file_format_specification.pdf * - * $Id: demux_flv.c,v 1.9 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_flv.c,v 1.21 2007/03/17 11:29:43 klan Exp $ */ #ifdef HAVE_CONFIG_H @@ -42,7 +44,6 @@ /* #define LOG */ - #include "xine_internal.h" #include "xineutils.h" #include "compat.h" @@ -51,103 +52,448 @@ #include "group_games.h" typedef struct { + unsigned int pts; + unsigned int offset; +} flv_index_entry_t; + +typedef struct { demux_plugin_t demux_plugin; + xine_t *xine; xine_stream_t *stream; fifo_buffer_t *video_fifo; fifo_buffer_t *audio_fifo; input_plugin_t *input; int status; - unsigned int video_type; - unsigned int audio_type; - - off_t data_start; - off_t data_size; - - unsigned char bih[sizeof(xine_bmiheader)]; - xine_waveformatex wave; - + unsigned char flags; + off_t start; /* in bytes */ + off_t size; /* in bytes */ + + unsigned char got_video; + unsigned char got_audio; + + unsigned int length; /* in ms */ + int width; + int height; + double framerate; + + flv_index_entry_t *index; + int num_indices; + + unsigned int cur_pts; + + int64_t last_pts[2]; + int send_newpts; + int buf_flag_seek; } demux_flv_t ; typedef struct { demux_class_t demux_class; } demux_flv_class_t; + +#define FLV_FLAG_HAS_VIDEO 0x01 +#define FLV_FLAG_HAS_AUDIO 0x04 + +#define FLV_TAG_TYPE_AUDIO 0x08 +#define FLV_TAG_TYPE_VIDEO 0x09 +#define FLV_TAG_TYPE_SCRIPT 0x12 + +#define FLV_SOUND_FORMAT_PCM_BE 0x00 +#define FLV_SOUND_FORMAT_ADPCM 0x01 +#define FLV_SOUND_FORMAT_MP3 0x02 +#define FLV_SOUND_FORMAT_PCM_LE 0x03 +#define FLV_SOUND_FORMAT_NELLY8 0x05 /* Nellymoser 8KHz */ +#define FLV_SOUND_FORMAT_NELLY 0x06 /* Nellymoser */ + +#define FLV_VIDEO_FORMAT_FLV1 0x02 /* Sorenson H.263 */ +#define FLV_VIDEO_FORMAT_SCREEN 0x03 +#define FLV_VIDEO_FORMAT_VP6 0x04 /* On2 VP6 */ +#define FLV_VIDEO_FORMAT_VP6A 0x05 /* On2 VP6 with alphachannel */ +#define FLV_VIDEO_FORMAT_SCREEN2 0x06 + +#define FLV_DATA_TYPE_NUMBER 0x00 +#define FLV_DATA_TYPE_BOOL 0x01 +#define FLV_DATA_TYPE_STRING 0x02 +#define FLV_DATA_TYPE_OBJECT 0x03 +#define FLC_DATA_TYPE_CLIP 0x04 +#define FLV_DATA_TYPE_REFERENCE 0x07 +#define FLV_DATA_TYPE_ECMARRAY 0x08 +#define FLV_DATA_TYPE_ENDOBJECT 0x09 +#define FLV_DATA_TYPE_ARRAY 0x0a +#define FLV_DATA_TYPE_DATE 0x0b +#define FLV_DATA_TYPE_LONGSTRING 0x0c + + +/* redefine abs as macro to handle 64-bit diffs. + i guess llabs may not be available everywhere */ +#define abs(x) ( ((x)<0) ? -(x) : (x) ) + +#define WRAP_THRESHOLD 220000 +#define PTS_AUDIO 0 +#define PTS_VIDEO 1 + +static void check_newpts(demux_flv_t *this, int64_t pts, int video) { + int64_t diff; + + diff = pts - this->last_pts[video]; + lprintf ("check_newpts %"PRId64"\n", pts); + + if (pts && (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD))) { + lprintf ("diff=%"PRId64"\n", diff); + + if (this->buf_flag_seek) { + _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); + this->buf_flag_seek = 0; + } else { + _x_demux_control_newpts(this->stream, pts, 0); + } + this->send_newpts = 0; + this->last_pts[1-video] = 0; + } + + if (pts) + this->last_pts[video] = pts; +} + /* returns 1 if the FLV file was opened successfully, 0 otherwise */ static int open_flv_file(demux_flv_t *this) { + unsigned char buffer[9]; - unsigned char buffer[4]; - off_t first_offset; - - if (_x_demux_read_header(this->input, buffer, 4) != 4) + if (_x_demux_read_header(this->input, buffer, 9) != 9) return 0; if ((buffer[0] != 'F') || (buffer[1] != 'L') || (buffer[2] != 'V')) return 0; + + if (buffer[3] != 0x01) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("unsupported FLV version (%d).\n"), buffer[3]); + return 0; + } - this->video_type = this->audio_type = 0; - if (buffer[3] & 0x1) - this->video_type = BUF_VIDEO_FLV1; -/* buffer[3] * 0x4 indicates audio, possibly always MP3; deal with - that later */ - - /* file is qualified at this point; position to start of first packet */ - this->input->seek(this->input, 5, SEEK_SET); - if (this->input->read(this->input, buffer, 4) != 4) + this->flags = buffer[4]; + if ((this->flags & (FLV_FLAG_HAS_VIDEO | FLV_FLAG_HAS_AUDIO)) == 0) { + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("neither video nor audio stream in this file.\n")); return 0; + } - first_offset = BE_32(buffer); - this->input->seek(this->input, first_offset, SEEK_SET); + this->start = BE_32(&buffer[5]); + this->size = this->input->get_length(this->input); + + if (INPUT_IS_SEEKABLE(this->input)) + this->input->seek(this->input, this->start, SEEK_SET); + else if (this->start > 9) + this->input->seek(this->input, this->start-9, SEEK_CUR); + lprintf(" qualified FLV file, repositioned @ offset 0x%" PRIxMAX "\n", - (intmax_t)first_offset); + (intmax_t)this->start); return 1; } -static int demux_flv_send_chunk(demux_plugin_t *this_gen) { - - demux_flv_t *this = (demux_flv_t *) this_gen; - buf_element_t *buf = NULL; - unsigned int remaining_bytes; - unsigned char chunk_type, sub_type; - int64_t pts; - - unsigned char buffer[12]; +#define BE_F64(buf) ({\ + union { uint64_t q; double d; } _tmp;\ + _tmp.q = BE_64(buf);\ + _tmp.d;\ +})\ + +static int parse_flv_var(demux_flv_t *this, + unsigned char *buf, int size, char *key, int keylen) { + unsigned char *tmp = buf; + unsigned char *end = buf + size; + char *str; + unsigned char type; + int len, num; + + if (size < 1) + return 0; + + type = *tmp++; + + switch (type) { + case FLV_DATA_TYPE_NUMBER: + lprintf(" got number (%f)\n", BE_F64(tmp)); + if (key) { + double val = BE_F64(tmp); + if (keylen == 8 && !strncmp(key, "duration", 8)) { + this->length = val * 1000.0; + } + else if (keylen == 5 && !strncmp(key, "width", 5)) { + this->width = val; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, this->width); + } + else if (keylen == 6 && !strncmp(key, "height", 6)) { + this->height = val; + _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, this->height); + } + else if (keylen == 9 && !strncmp(key, "framerate", 9)) { + this->framerate = val; + } + else if (keylen == 13 && !strncmp(key, "videodatarate", 13)) { + _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, val*1000.0); + } + } + tmp += 8; + break; + case FLV_DATA_TYPE_BOOL: + lprintf(" got bool (%d)\n", *tmp); + tmp++; + break; + case FLV_DATA_TYPE_STRING: + lprintf(" got string (%s)\n", tmp+2); + len = BE_16(tmp); + tmp += len + 2; + break; + case FLV_DATA_TYPE_OBJECT: + while ((len = BE_16(tmp)) && tmp < end) { + lprintf(" got object var (%s)\n", tmp+2); + str = tmp + 2; + tmp += len + 2; + len = parse_flv_var(this, tmp, end-tmp, str, len); + tmp += len; + } + if (*tmp++ != FLV_DATA_TYPE_ENDOBJECT) + return 0; + break; + case FLV_DATA_TYPE_ECMARRAY: + lprintf(" got EMCA array (%d indices)\n", BE_32(tmp)); + num = BE_32(tmp); + tmp += 4; + while (num-- && tmp < end) { + lprintf(" got array key (%s)\n", tmp+2); + len = BE_16(tmp); + str = tmp + 2; + tmp += len + 2; + len = parse_flv_var(this, tmp, end-tmp, str, len); + tmp += len; + } + break; + case FLV_DATA_TYPE_ARRAY: + lprintf(" got array (%d indices)\n", BE_32(tmp)); + num = BE_32(tmp); + tmp += 4; + if (key && keylen == 5 && !strncmp(key, "times", 5)) { + if (this->index) + free (this->index); + this->index = xine_xmalloc(num*sizeof(flv_index_entry_t)); + this->num_indices = num; + for (num = 0; num < this->num_indices && tmp < end; num++) { + if (*tmp++ == FLV_DATA_TYPE_NUMBER) { + lprintf(" got number (%f)\n", BE_F64(tmp)); + this->index[num].pts = BE_F64(tmp) * 1000.0; + tmp += 8; + } + } + break; + } + if (key && keylen == 13 && !strncmp(key, "filepositions", 13)) { + if (this->index && this->num_indices == num) { + for (num = 0; num < this->num_indices && tmp < end; num++) { + if (*tmp++ == FLV_DATA_TYPE_NUMBER) { + lprintf(" got number (%f)\n", BE_F64(tmp)); + this->index[num].offset = BE_F64(tmp); + tmp += 8; + } + } + break; + } + } + while (num-- && tmp < end) { + len = parse_flv_var(this, tmp, end-tmp, NULL, 0); + tmp += len; + } + break; + case FLV_DATA_TYPE_DATE: + lprintf(" got date (%"PRId64", %d)\n", BE_64(tmp), BE_16(tmp+8)); + tmp += 10; + break; + default: + lprintf(" got type %d\n", type); + break; + } + + return (tmp - buf); +} - lprintf (" sending FLV chunk...\n"); - this->input->seek(this->input, 4, SEEK_CUR); - if (this->input->read(this->input, buffer, 12) != 12) { +static void parse_flv_script(demux_flv_t *this, int size) { + unsigned char *buf = xine_xmalloc(size); + unsigned char *tmp = buf; + unsigned char *end = buf + size; + int len; + + if (this->input->read(this->input, buf, size ) != size) { this->status = DEMUX_FINISHED; - return this->status; + free(buf); + return; } - chunk_type = buffer[0]; - remaining_bytes = BE_32(&buffer[0]); - remaining_bytes &= 0x00FFFFFF; - pts = BE_32(&buffer[3]); - pts &= 0x00FFFFFF; - sub_type = buffer[11]; - - /* Flash timestamps are in milliseconds; multiply by 90 to get xine pts */ - pts *= 90; - - lprintf (" chunk_type = %X, 0x%X -1 bytes, pts %lld, sub-type = %X\n", - chunk_type, remaining_bytes, pts, sub_type); - - /* only handle the chunk right now if chunk type is 9 and lower nibble - * of sub-type is 2 */ - if ((chunk_type != 9) || ((sub_type & 0x0F) != 2)) { - this->input->seek(this->input, remaining_bytes - 1, SEEK_CUR); - } else { - /* send the chunk off to the video demuxer */ - remaining_bytes--; /* sub-type byte does not count */ + while (tmp < end) { + len = parse_flv_var(this, tmp, end-tmp, NULL, 0); + if (len < 1) + break; + tmp += len; + } + + free(buf); +} + +static int read_flv_packet(demux_flv_t *this) { + fifo_buffer_t *fifo = NULL; + buf_element_t *buf = NULL; + unsigned char buffer[12]; + unsigned char tag_type; + unsigned int remaining_bytes; + unsigned int buf_type = 0; + unsigned int buf_flags = 0; + unsigned int pts; + + while (1) { + lprintf (" reading FLV tag...\n"); + this->input->seek(this->input, 4, SEEK_CUR); + if (this->input->read(this->input, buffer, 11) != 11) { + this->status = DEMUX_FINISHED; + return this->status; + } + + tag_type = buffer[0]; + remaining_bytes = BE_24(&buffer[1]); + pts = BE_24(&buffer[4]) | (buffer[7] << 24); + + lprintf(" tag_type = 0x%02X, 0x%X bytes, pts %u\n", + tag_type, remaining_bytes, pts/90); + + switch (tag_type) { + case FLV_TAG_TYPE_AUDIO: + lprintf(" got audio tag..\n"); + if (this->input->read(this->input, buffer, 1) != 1) { + this->status = DEMUX_FINISHED; + return this->status; + } + remaining_bytes--; + + switch (buffer[0] >> 4) { + case FLV_SOUND_FORMAT_PCM_BE: + buf_type = BUF_AUDIO_LPCM_BE; + break; + case FLV_SOUND_FORMAT_ADPCM: + buf_type = BUF_AUDIO_FLVADPCM; + break; + case FLV_SOUND_FORMAT_MP3: + buf_type = BUF_AUDIO_MPEG; + break; + case FLV_SOUND_FORMAT_PCM_LE: + buf_type = BUF_AUDIO_LPCM_LE; + break; + default: + lprintf(" unsupported audio format (%d)...\n", buffer[0] >> 4); + buf_type = BUF_AUDIO_UNKNOWN; + break; + } + + fifo = this->audio_fifo; + if (!this->got_audio) { + /* send init info to audio decoder */ + buf = fifo->buffer_pool_alloc(fifo); + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = 44100 >> (3 - ((buffer[0] >> 2) & 3)); /* samplerate */ + buf->decoder_info[2] = (buffer[0] & 2) ? 16 : 8; /* bits per sample */ + buf->decoder_info[3] = (buffer[0] & 1) + 1; /* channels */ + buf->size = 0; /* no extra data */ + buf->type = buf_type; + + fifo->put(fifo, buf); + + this->got_audio = 1; + } + break; + + case FLV_TAG_TYPE_VIDEO: + lprintf(" got video tag..\n"); + if (this->input->read(this->input, buffer, 1) != 1) { + this->status = DEMUX_FINISHED; + return this->status; + } + remaining_bytes--; + + if ((buffer[0] >> 4) == 0x01) + buf_flags = BUF_FLAG_KEYFRAME; + + switch (buffer[0] & 0x0F) { + case FLV_VIDEO_FORMAT_FLV1: + buf_type = BUF_VIDEO_FLV1; + break; + case FLV_VIDEO_FORMAT_VP6: + buf_type = BUF_VIDEO_VP6F; + /* VP6 extra header */ + this->input->read(this->input, buffer, 1 ); + remaining_bytes--; + break; + case FLV_VIDEO_FORMAT_VP6A: + buf_type = BUF_VIDEO_VP6F; + /* VP6A extra header */ + this->input->read(this->input, buffer, 4); + remaining_bytes -= 4; + break; + default: + lprintf(" unsupported video format (%d)...\n", buffer[0] & 0x0F); + buf_type = BUF_VIDEO_UNKNOWN; + break; + } + + fifo = this->video_fifo; + if (!this->got_video) { + xine_bmiheader *bih; + /* send init info to video decoder; send the bitmapinfo header to the decoder + * primarily as a formality since there is no real data inside */ + buf = fifo->buffer_pool_alloc(fifo); + buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_STDHEADER | + BUF_FLAG_FRAMERATE | BUF_FLAG_FRAME_END; + buf->decoder_info[0] = this->framerate ? (90000.0/this->framerate) : 0; + bih = (xine_bmiheader *) buf->content; + memset(bih, 0, sizeof(xine_bmiheader)); + bih->biSize = sizeof(xine_bmiheader); + bih->biWidth = this->width; + bih->biHeight = this->height; + buf->size = sizeof(xine_bmiheader); + buf->type = buf_type; + if (buf_type == BUF_VIDEO_VP6F) { + *((unsigned char *)buf->content+buf->size) = buffer[0]; + bih->biSize++; + buf->size++; + } + + fifo->put(fifo, buf); + + this->got_video = 1; + } + break; + + case FLV_TAG_TYPE_SCRIPT: + lprintf(" got script tag...\n"); + parse_flv_script(this, remaining_bytes); + continue; + + default: + lprintf(" skipping packet...\n"); + this->input->seek(this->input, remaining_bytes, SEEK_CUR); + continue; + } + while (remaining_bytes) { - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->type = BUF_VIDEO_FLV1; - if( this->input->get_length (this->input) ) - buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) * - 65535 / this->input->get_length (this->input) ); + buf = fifo->buffer_pool_alloc(fifo); + buf->type = buf_type; + buf->pts = (int64_t) pts * 90; + check_newpts(this, buf->pts, (tag_type == FLV_TAG_TYPE_VIDEO)); + + buf->extra_info->input_time = pts; + if (this->input->get_length(this->input)) { + buf->extra_info->input_normpos = + (int)((double)this->input->get_current_pos(this->input) * 65535.0 / this->size); + } if (remaining_bytes > buf->max_size) buf->size = buf->max_size; @@ -155,28 +501,120 @@ static int demux_flv_send_chunk(demux_plugin_t *this_gen) { buf->size = remaining_bytes; remaining_bytes -= buf->size; + buf->decoder_flags = buf_flags; if (!remaining_bytes) buf->decoder_flags |= BUF_FLAG_FRAME_END; - if (this->input->read(this->input, buf->content, buf->size) != - buf->size) { + if (this->input->read(this->input, buf->content, buf->size) != buf->size) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; break; } - buf->pts = pts; - buf->extra_info->input_time = buf->pts / 90; - this->video_fifo->put(this->video_fifo, buf); + fifo->put(fifo, buf); } + + this->cur_pts = pts; + break; } - + return this->status; } +static void seek_flv_file(demux_flv_t *this, int seek_pts) { + unsigned char buffer[16]; + unsigned int pts = this->cur_pts; + int len = 0; + int next_tag = 0; + int do_rewind = (seek_pts < this->cur_pts); + + lprintf(" seeking %s to %d...\n", + do_rewind ? "backward" : "forward", seek_pts); + + if (seek_pts == 0) { + this->input->seek(this->input, this->start, SEEK_SET); + this->cur_pts = 0; + return; + } + + if (this->index) { + int i; + + if (do_rewind) { + for (i = this->num_indices-1; i > 0; i--) { + if (this->index[i-1].pts < seek_pts) + break; + } + } + else { + for (i = 0; i < (this->num_indices-1); i++) { + if (this->index[i+1].pts > seek_pts) + break; + } + } + + if (this->index[i].offset >= this->start+4) { + lprintf(" seeking to index entry %d (pts:%u, offset:%u).\n", + i, this->index[i].pts, this->index[i].offset); + + this->input->seek(this->input, this->index[i].offset-4, SEEK_SET); + this->cur_pts = this->index[i].pts; + return; + } + } + + while (do_rewind ? (seek_pts < this->cur_pts) : (seek_pts > this->cur_pts)) { + unsigned char tag_type; + int data_size; + int ptag_size; + + if (next_tag) + this->input->seek(this->input, next_tag, SEEK_CUR); + + len = this->input->read(this->input, buffer, 16); + if (len != 16) { + len = (len < 0) ? 0 : len; + break; + } + + ptag_size = BE_32(&buffer[0]); + tag_type = buffer[4]; + data_size = BE_24(&buffer[5]); + pts = BE_24(&buffer[8]) | (buffer[11] << 24); + + if (do_rewind) { + if (!ptag_size) break; /* beginning of movie */ + next_tag = -(ptag_size + 16 + 4); + } + else { + next_tag = data_size - 1; + } + + if (this->flags & FLV_FLAG_HAS_VIDEO) { + /* sync to video key frame */ + if (tag_type != FLV_TAG_TYPE_VIDEO || (buffer[15] >> 4) != 0x01) + continue; + lprintf(" video keyframe found at %d...\n", pts); + } + this->cur_pts = pts; + } + + /* seek back to the beginning of the tag */ + this->input->seek(this->input, -len, SEEK_CUR); + + lprintf( " seeked to %d.\n", pts); +} + + +static int demux_flv_send_chunk(demux_plugin_t *this_gen) { + demux_flv_t *this = (demux_flv_t *) this_gen; + + return read_flv_packet(this); +} + static void demux_flv_send_headers(demux_plugin_t *this_gen) { demux_flv_t *this = (demux_flv_t *) this_gen; - buf_element_t *buf; + int i; this->video_fifo = this->stream->video_fifo; this->audio_fifo = this->stream->audio_fifo; @@ -185,24 +623,23 @@ static void demux_flv_send_headers(demux_plugin_t *this_gen) { /* load stream information */ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, - (this->video_type ? 1 : 0)); + (this->flags & FLV_FLAG_HAS_VIDEO) ? 1 : 0); _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, - (this->audio_type ? 1 : 0)); + (this->flags & FLV_FLAG_HAS_AUDIO) ? 1 : 0); /* send start buffers */ _x_demux_control_start(this->stream); - /* send init info to decoders; send the bitmapinfo header to the decoder - * primarily as a formality since there is no real data inside */ - buf = this->video_fifo->buffer_pool_alloc (this->video_fifo); - buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE| - BUF_FLAG_FRAME_END; - buf->decoder_info[0] = 7470; /* initial duration */ - memcpy(buf->content, this->bih, sizeof(xine_bmiheader)); - buf->size = sizeof(xine_bmiheader); - buf->type = BUF_VIDEO_FLV1; - this->video_fifo->put (this->video_fifo, buf); - + /* find first audio/video packets and send headers */ + for (i = 0; i < 20; i++) { + if (read_flv_packet(this) != DEMUX_OK) + break; + if (((this->flags & FLV_FLAG_HAS_VIDEO) && this->got_video) && + ((this->flags & FLV_FLAG_HAS_AUDIO) && this->got_audio)) { + lprintf(" headers sent...\n"); + break; + } + } } static int demux_flv_seek (demux_plugin_t *this_gen, @@ -210,10 +647,21 @@ static int demux_flv_seek (demux_plugin_t *this_gen, demux_flv_t *this = (demux_flv_t *) this_gen; - /* if thread is not running, initialize demuxer */ - if( !playing ) { - this->status = DEMUX_OK; - } + this->status = DEMUX_OK; + + if (INPUT_IS_SEEKABLE(this->input)) { + if (start_pos && !start_time) + start_time = (int64_t) this->length * start_pos / 65535; + + if (!this->length || start_time < this->length) { + seek_flv_file(this, start_time); + + if (playing) { + this->buf_flag_seek = 1; + _x_demux_flush_engine(this->stream); + } + } + } return this->status; } @@ -221,6 +669,8 @@ static int demux_flv_seek (demux_plugin_t *this_gen, static void demux_flv_dispose (demux_plugin_t *this_gen) { demux_flv_t *this = (demux_flv_t *) this_gen; + if (this->index) + free(this->index); free(this); } @@ -231,9 +681,9 @@ static int demux_flv_get_status (demux_plugin_t *this_gen) { } static int demux_flv_get_stream_length (demux_plugin_t *this_gen) { -/* demux_flv_t *this = (demux_flv_t *) this_gen;*/ + demux_flv_t *this = (demux_flv_t *) this_gen; - return 0; + return this->length; } static uint32_t demux_flv_get_capabilities(demux_plugin_t *this_gen) { @@ -247,10 +697,10 @@ static int demux_flv_get_optional_data(demux_plugin_t *this_gen, static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, input_plugin_t *input) { + demux_flv_t *this; - demux_flv_t *this; - - this = xine_xmalloc (sizeof (demux_flv_t)); + this = xine_xmalloc(sizeof (demux_flv_t)); + this->xine = stream->xine; this->stream = stream; this->input = input; @@ -267,52 +717,43 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->status = DEMUX_FINISHED; switch (stream->content_detection_method) { + case METHOD_BY_EXTENSION: + if (!_x_demux_check_extension(input->get_mrl(input), "flv")) { + free (this); + return NULL; + } + + /* falling through is intended */ + case METHOD_BY_CONTENT: + case METHOD_EXPLICIT: + if (!open_flv_file(this)) { + free (this); + return NULL; + } + break; - case METHOD_BY_EXTENSION: { - char *extensions, *mrl; - - mrl = input->get_mrl (input); - extensions = class_gen->get_extensions (class_gen); - - if (!_x_demux_check_extension (mrl, extensions)) { - free (this); - return NULL; - } - } - /* falling through is intended */ - - case METHOD_BY_CONTENT: - case METHOD_EXPLICIT: - - if (!open_flv_file(this)) { + default: free (this); return NULL; - } - - break; - - default: - free (this); - return NULL; } return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Flash Video file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "FLV"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "flv"; } -static char *get_mimetypes (demux_class_t *this_gen) { - return NULL; +static const char *get_mimetypes (demux_class_t *this_gen) { + return "video/x-flv: flv: Flash video;"; } static void class_dispose (demux_class_t *this_gen) { diff --git a/src/demuxers/demux_idcin.c b/src/demuxers/demux_idcin.c index a778d4c6f..461771425 100644 --- a/src/demuxers/demux_idcin.c +++ b/src/demuxers/demux_idcin.c @@ -65,7 +65,7 @@ * - if any bytes exceed 63, do not shift the bytes at all before * transmitting them to the video decoder * - * $Id: demux_idcin.c,v 1.53 2005/11/21 10:28:18 valtri Exp $ + * $Id: demux_idcin.c,v 1.55 2007/02/20 00:34:55 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -222,7 +222,7 @@ static int demux_idcin_send_chunk(demux_plugin_t *this_gen) { if (!remaining_sample_bytes) buf->decoder_flags |= BUF_FLAG_FRAME_END; - lprintf("sending video buf with %d bytes, %lld pts\n", buf->size, buf->pts); + lprintf("sending video buf with %d bytes, %"PRId64" pts\n", buf->size, buf->pts); this->video_fifo->put(this->video_fifo, buf); } @@ -263,7 +263,7 @@ static int demux_idcin_send_chunk(demux_plugin_t *this_gen) { if (!remaining_sample_bytes) buf->decoder_flags |= BUF_FLAG_FRAME_END; - lprintf("sending audio buf with %d bytes, %lld pts\n", buf->size, buf->pts); + lprintf("sending audio buf with %d bytes, %"PRId64" pts\n", buf->size, buf->pts); this->audio_fifo->put(this->audio_fifo, buf); } } @@ -493,7 +493,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -524,19 +524,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Id Quake II Cinematic file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Id CIN"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "cin"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_iff.c b/src/demuxers/demux_iff.c index 213ac4c99..cc4df0c85 100644 --- a/src/demuxers/demux_iff.c +++ b/src/demuxers/demux_iff.c @@ -36,7 +36,7 @@ * * ANIM (Animations) * - Animation works fine, without seeking. * - * $Id: demux_iff.c,v 1.17 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_iff.c,v 1.19 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -827,7 +827,8 @@ static int demux_iff_send_chunk(demux_plugin_t *this_gen) { } } else { for (j = 0, k = (interleave_index / 2); j < (buf->size / 2); j += this->audio_channels) { - zw_16 = BE_16(&pointer16_from[k++]); + zw_16 = BE_16(&pointer16_from[k]); + k++; zw_rescale = zw_16; zw_rescale *= this->audio_volume_left; zw_rescale /= max_volume; @@ -856,7 +857,8 @@ static int demux_iff_send_chunk(demux_plugin_t *this_gen) { } } else { for (j = 1; j < (buf->size / 2); j += this->audio_channels) { - zw_16 = BE_16(&pointer16_from[k++]); + zw_16 = BE_16(&pointer16_from[k]); + k++; zw_rescale = zw_16; zw_rescale *= this->audio_volume_left; zw_rescale /= max_volume; @@ -1253,7 +1255,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -1283,19 +1285,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "IFF demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "IFF"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "iff svx 8svx 16sv ilbm ham ham6 ham8 anim anim3 anim5 anim7 anim8"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-8svx: 8svx: IFF-8SVX Audio;" "audio/8svx: 8svx: IFF-8SVX Audio;" "audio/x-16sv: 16sv: IFF-16SV Audio;" diff --git a/src/demuxers/demux_image.c b/src/demuxers/demux_image.c index 727d80a29..d799c2324 100644 --- a/src/demuxers/demux_image.c +++ b/src/demuxers/demux_image.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_image.c,v 1.25 2006/08/13 23:51:33 miguelfreitas Exp $ + * $Id: demux_image.c,v 1.26 2007/01/19 00:26:40 dgp85 Exp $ * * image dummy demultiplexer */ @@ -177,7 +177,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -225,19 +225,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, * image demuxer class */ -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "image demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "imagedmx"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "png gif jpg jpeg"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_ipmovie.c b/src/demuxers/demux_ipmovie.c index 20c1c3118..6fe185b1a 100644 --- a/src/demuxers/demux_ipmovie.c +++ b/src/demuxers/demux_ipmovie.c @@ -23,7 +23,7 @@ * For more information regarding the Interplay MVE file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_ipmovie.c,v 1.25 2004/06/13 21:28:53 miguelfreitas Exp $ + * $Id: demux_ipmovie.c,v 1.27 2007/02/20 00:34:55 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -326,7 +326,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { audio_pts *= this->audio_frame_count; audio_pts /= this->wave.nSamplesPerSec; - lprintf("sending audio frame with pts %lld (%d audio frames)\n", + lprintf("sending audio frame with pts %"PRId64" (%d audio frames)\n", audio_pts, this->audio_frame_count); if(this->audio_fifo) { @@ -432,7 +432,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) { lprintf("set video data\n"); current_file_pos = this->input->get_current_pos(this->input); - lprintf("sending video data with pts %lld\n", + lprintf("sending video data with pts %"PRId64"\n", this->video_pts); /* send off any new palette data */ @@ -693,7 +693,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -723,19 +723,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Interplay MVE Movie demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Interplay MVE"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mve mv8"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c index bcc5f52ea..2bd8f3540 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2005 the xine project + * Copyright (C) 2000-2007 the xine project * * This file is part of xine, a free video player. * @@ -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_matroska.c,v 1.49 2006/11/14 14:17:31 dgp85 Exp $ + * $Id: demux_matroska.c,v 1.53 2007/03/12 16:27:21 dgp85 Exp $ * * demultiplexer for matroska streams * @@ -362,6 +362,140 @@ static int parse_audio_track (demux_matroska_t *this, matroska_audio_track_t *at } +static int parse_content_compression (demux_matroska_t *this, matroska_track_t *track) { + ebml_parser_t *ebml = this->ebml; + int next_level = 6; + + while (next_level == 6) { + ebml_elem_t elem; + uint64_t val; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CE_COMPALGO: + lprintf("ContentCompAlgo\n"); + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + switch (val) + { + case MATROSKA_COMPRESS_ZLIB: + case MATROSKA_COMPRESS_BZLIB: + case MATROSKA_COMPRESS_LZO1X: + case MATROSKA_COMPRESS_HEADER_STRIP: + track->compress_algo = val; + break; + default: + track->compress_algo = MATROSKA_COMPRESS_UNKNOWN; + break; + } + break; + case MATROSKA_ID_CE_COMPSETTINGS: + lprintf("ContentCompSettings (UNSUPPORTED)\n"); + if (!ebml_skip(ebml, &elem)) + return 0; + break; + default: + lprintf("Unhandled ID: 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + next_level = ebml_get_next_level(ebml, &elem); + } + return 1; +} + + +static int parse_content_encoding (demux_matroska_t *this, matroska_track_t *track) { + ebml_parser_t *ebml = this->ebml; + int next_level = 5; + + while (next_level == 5) { + ebml_elem_t elem; + uint64_t val; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CE_ORDER: + lprintf("ContentEncodingOrder\n"); + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + if (val != 0) { // multiple content encoding isn't supported + lprintf(" warning: a non-zero encoding order is UNSUPPORTED\n"); + return 0; + } + break; + case MATROSKA_ID_CE_SCOPE: + lprintf("ContentEncodingScope\n"); + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + if (val != 1) { // 1 (all frame contents) is the only supported option + lprintf(" warning: UNSUPPORTED encoding scope (%" PRId64 ")\n", val); + return 0; + } + break; + case MATROSKA_ID_CE_TYPE: + lprintf("ContentEncodingType\n"); + if (!ebml_read_uint(ebml, &elem, &val)) + return 0; + if (val != 0) // only compression (0) is supported + return 0; + break; + case MATROSKA_ID_CE_COMPRESSION: + lprintf("ContentCompression\n"); + if (!ebml_read_master (ebml, &elem)) + return 0; + if ((elem.len > 0) && !parse_content_compression(this, track)) + return 0; + break; + case MATROSKA_ID_CE_ENCRYPTION: + lprintf("ContentEncryption (UNSUPPORTED)\n"); + if (!ebml_skip(ebml, &elem)) + return 0; + break; + default: + lprintf("Unhandled ID: 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + next_level = ebml_get_next_level(ebml, &elem); + } + return 1; +} + + +static int parse_content_encodings (demux_matroska_t *this, matroska_track_t *track) { + ebml_parser_t *ebml = this->ebml; + int next_level = 4; + + while (next_level == 4) { + ebml_elem_t elem; + + if (!ebml_read_elem_head(ebml, &elem)) + return 0; + + switch (elem.id) { + case MATROSKA_ID_CONTENTENCODING: + lprintf("ContentEncoding\n"); + if (!ebml_read_master (ebml, &elem)) + return 0; + if ((elem.len > 0) && !parse_content_encoding(this, track)) + return 0; + break; + default: + lprintf("Unhandled ID: 0x%x\n", elem.id); + if (!ebml_skip(ebml, &elem)) + return 0; + } + next_level = ebml_get_next_level(ebml, &elem); + } + return 1; +} + + static void init_codec_video(demux_matroska_t *this, matroska_track_t *track) { buf_element_t *buf; @@ -937,45 +1071,67 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, int input_normpos, int input_time) { demux_matroska_t *this = (demux_matroska_t *) this_gen; buf_element_t *buf; - z_stream zstream; - uint8_t *dest; - int old_data_len, result; - - old_data_len = data_len; - zstream.zalloc = (alloc_func) 0; - zstream.zfree = (free_func) 0; - zstream.opaque = (voidpf) 0; - if (inflateInit (&zstream) != Z_OK) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_matroska: VobSub: zlib inflateInit failed.\n"); - return; - } - zstream.next_in = (Bytef *)data; - zstream.avail_in = data_len; - dest = (uint8_t *)malloc(data_len); - zstream.avail_out = data_len; - do { - data_len += 4000; - dest = (uint8_t *)realloc(dest, data_len); - zstream.next_out = (Bytef *)(dest + zstream.total_out); - result = inflate (&zstream, Z_NO_FLUSH); - if ((result != Z_OK) && (result != Z_STREAM_END)) { + if (track->compress_algo == MATROSKA_COMPRESS_ZLIB || + track->compress_algo == MATROSKA_COMPRESS_UNKNOWN) { + z_stream zstream; + uint8_t *dest; + int old_data_len, result; + + old_data_len = data_len; + zstream.zalloc = (alloc_func) 0; + zstream.zfree = (free_func) 0; + zstream.opaque = (voidpf) 0; + if (inflateInit (&zstream) != Z_OK) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_matroska: VobSub: zlib decompression failed.\n"); - free(dest); - inflateEnd(&zstream); + "demux_matroska: VobSub: zlib inflateInit failed.\n"); return; } - zstream.avail_out += 4000; - } while ((zstream.avail_out == 4000) && - (zstream.avail_in != 0) && (result != Z_STREAM_END)); - - data_len = zstream.total_out; - inflateEnd(&zstream); - - lprintf("VobSub: decompression for track %d from %d to %d\n", - (int)track->track_num, old_data_len, data_len); + zstream.next_in = (Bytef *)data; + zstream.avail_in = data_len; + + dest = (uint8_t *)malloc(data_len); + zstream.avail_out = data_len; + do { + data_len += 4000; + dest = (uint8_t *)realloc(dest, data_len); + zstream.next_out = (Bytef *)(dest + zstream.total_out); + result = inflate (&zstream, Z_NO_FLUSH); + if ((result != Z_OK) && (result != Z_STREAM_END)) { + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: VobSub: zlib decompression failed for track %d (result = %d).\n", + (int)track->track_num, result); + free(dest); + inflateEnd(&zstream); + + if (result == Z_DATA_ERROR && track->compress_algo == MATROSKA_COMPRESS_UNKNOWN) { + track->compress_algo = MATROSKA_COMPRESS_NONE; + data_len = old_data_len; + xprintf(this->stream->xine, XINE_VERBOSITY_LOG, + "demux_matroska: VobSub: falling back to uncompressed mode.\n"); + break; + } + return; + } + zstream.avail_out += 4000; + } while ((zstream.avail_out == 4000) && + (zstream.avail_in != 0) && (result != Z_STREAM_END)); + + if (track->compress_algo != MATROSKA_COMPRESS_NONE) { + data_len = zstream.total_out; + inflateEnd(&zstream); + + data = dest; + track->compress_algo = MATROSKA_COMPRESS_ZLIB; + lprintf("VobSub: decompression for track %d from %d to %d\n", + (int)track->track_num, old_data_len, data_len); + } + } + else + { + lprintf("VobSub: track %d isn't compressed (%d bytes)\n", + (int)track->track_num, data_len); + } buf = track->fifo->buffer_pool_alloc(track->fifo); @@ -986,8 +1142,8 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, buf->decoder_info[2] = SPU_DVD_SUBTYPE_VOBSUB_PACKAGE; buf->type = track->buf_type; - xine_fast_memcpy(buf->content, dest, data_len); - + xine_fast_memcpy(buf->content, data, data_len); + buf->extra_info->input_normpos = input_normpos; buf->extra_info->input_time = input_time; @@ -1000,7 +1156,8 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track, buf->free_buffer(buf); } - free(dest); + if (track->compress_algo == MATROSKA_COMPRESS_ZLIB) + free(data); } static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { @@ -1100,7 +1257,16 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { if (!ebml_read_uint(ebml, &elem, &val)) return 0; track->default_duration = val; - lprintf("Default Duration: %lld\n", track->default_duration); + lprintf("Default Duration: %"PRIu64"\n", track->default_duration); + } + break; + + case MATROSKA_ID_CONTENTENCODINGS: { + lprintf("ContentEncodings\n"); + if (!ebml_read_master (ebml, &elem)) + return 0; + if ((elem.len > 0) && !parse_content_encodings(this, track)) + return 0; } break; @@ -1230,6 +1396,10 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { init_codec = init_codec_audio; } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_DTS)) { + lprintf("MATROSKA_CODEC_ID_A_DTS\n"); + track->buf_type = BUF_AUDIO_DTS; + init_codec = init_codec_audio; + } else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_VORBIS)) { lprintf("MATROSKA_CODEC_ID_A_VORBIS\n"); @@ -1289,6 +1459,14 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { track->buf_type = BUF_SPU_DVD; track->handle_content = handle_vobsub; init_codec = init_codec_vobsub; + + /* Enable autodetection of the zlib compression, unless it was + * explicitely set. Most vobsubs are compressed with zlib but + * are not declared as such. + */ + if (track->compress_algo == MATROSKA_COMPRESS_NONE) { + track->compress_algo = MATROSKA_COMPRESS_UNKNOWN; + } } else { lprintf("unknown codec\n"); } @@ -1339,12 +1517,17 @@ static int parse_tracks(demux_matroska_t *this) { switch (elem.id) { case MATROSKA_ID_TR_ENTRY: { + matroska_track_t *track; + /* alloc and initialize a track with 0 */ - this->tracks[this->num_tracks] = xine_xmalloc(sizeof(matroska_track_t)); + track = xine_xmalloc(sizeof(matroska_track_t)); + track->compress_algo = MATROSKA_COMPRESS_NONE; + this->tracks[this->num_tracks] = track; + lprintf("TrackEntry\n"); if (!ebml_read_master (ebml, &elem)) return 0; - if ((elem.len > 0) && !parse_track_entry(this, this->tracks[this->num_tracks])) + if ((elem.len > 0) && !parse_track_entry(this, track)) return 0; this->num_tracks++; } @@ -2623,13 +2806,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *mrl = input->get_mrl(input); - char *extensions; + const char *const mrl = input->get_mrl(input); + const char *const extensions = class_gen->get_extensions (class_gen);; lprintf ("stage by extension %s\n", mrl); - extensions = class_gen->get_extensions (class_gen); - if (!_x_demux_check_extension (mrl, extensions)) return NULL; @@ -2687,22 +2868,22 @@ error: * demux matroska class */ -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "matroska demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "matroska"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mkv"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "video/mkv: mkv: matroska;"; } diff --git a/src/demuxers/demux_mng.c b/src/demuxers/demux_mng.c index 7f7b5bd84..e2ab1e4ea 100644 --- a/src/demuxers/demux_mng.c +++ b/src/demuxers/demux_mng.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_mng.c,v 1.28 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_mng.c,v 1.29 2007/01/19 00:26:40 dgp85 Exp $ * * demux_mng.c, Demuxer plugin for Multiple-image Network Graphics format * @@ -288,7 +288,7 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl(input); extensions = class_gen->get_extensions (class_gen); @@ -336,19 +336,19 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre return &this->demux_plugin; } -static char *get_description(demux_class_t *this_gen){ +static const char *get_description(demux_class_t *this_gen){ return "Multiple-image Network Graphics demux plugin"; } -static char *get_identifier(demux_class_t *this_gen){ +static const char *get_identifier(demux_class_t *this_gen){ return "MNG"; } -static char *get_extensions(demux_class_t *this_gen){ +static const char *get_extensions(demux_class_t *this_gen){ return "png mng"; } -static char *get_mimetypes(demux_class_t *this_gen){ +static const char *get_mimetypes(demux_class_t *this_gen){ return "image/png: png: PNG image;" "image/x-png: png: PNG image;" "video/mng: mng: MNG animation;" diff --git a/src/demuxers/demux_mod.c b/src/demuxers/demux_mod.c index 185ef5c97..37e066b13 100644 --- a/src/demuxers/demux_mod.c +++ b/src/demuxers/demux_mod.c @@ -50,6 +50,7 @@ #include "demux.h" #include "group_audio.h" #include "modplug.h" +#include "bswap.h" #define MOD_SAMPLERATE 44100 #define MOD_BITS 16 @@ -89,6 +90,43 @@ typedef struct { demux_class_t demux_class; } demux_mod_class_t; +#define FOURCC_32(a, b, c, d) (d + (c<<8) + (b<<16) + (a<<24)) + +/** + * @brief Probes if the given file can be demuxed using modplug or not + * @retval 0 The file is not a valid modplug file (or the probe isn't complete yet) + * @retval 1 The file has been identified as a valid modplug file + * @todo Just Protracker files are detected right now. + */ +static int probe_mod_file(demux_mod_t *this) { + /* We need the value present at offset 1080, of size 4 */ + union { + uint8_t buffer[1080+4]; /* The raw buffer */ + uint32_t values[(1080+4)/sizeof(uint32_t)]; + } header; + + if (_x_demux_read_header(this->input, header.buffer, 1080+4) != 1080+4) + return 0; + + /* Magic numbers taken from GNU file's magic description */ + switch( ABE_32(header.values + (1080/sizeof(uint32_t))) ) { + case FOURCC_32('M', '.', 'K', '.'): /* 4-channel Protracker module sound data */ + case FOURCC_32('M', '!', 'K', '!'): /* 4-channel Protracker module sound data */ + case FOURCC_32('F', 'L', 'T', '4'): /* 4-channel Startracker module sound data */ + case FOURCC_32('F', 'L', 'T', '8'): /* 8-channel Startracker module sound data */ + case FOURCC_32('4', 'C', 'H', 'N'): /* 4-channel Fasttracker module sound data */ + case FOURCC_32('6', 'C', 'H', 'N'): /* 6-channel Fasttracker module sound data */ + case FOURCC_32('8', 'C', 'H', 'N'): /* 8-channel Fasttracker module sound data */ + case FOURCC_32('C', 'D', '8', '1'): /* 8-channel Octalyser module sound data */ + case FOURCC_32('O', 'K', 'T', 'A'): /* 8-channel Oktalyzer module sound data */ + case FOURCC_32('1', '6', 'C', 'N'): /* 16-channel Taketracker module sound data */ + case FOURCC_32('3', '2', 'C', 'N'): /* 32-channel Taketracker module sound data */ + return 1; + } + + return 0; +} + /* returns 1 if the MOD file was opened successfully, 0 otherwise */ static int open_mod_file(demux_mod_t *this) { int total_read; @@ -289,7 +327,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str case METHOD_EXPLICIT: case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -306,6 +344,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_CONTENT: + if (probe_mod_file(this) && open_mod_file(this)) + break; + default: free (this); return NULL; @@ -314,19 +355,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "ModPlug Amiga MOD Music file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "mod"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mod it stm s3m 669 amf med mdl xm"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_mpc.c b/src/demuxers/demux_mpc.c index ab2ef511d..e1a3f28b9 100644 --- a/src/demuxers/demux_mpc.c +++ b/src/demuxers/demux_mpc.c @@ -24,7 +24,7 @@ * APE tag reading * Seeking?? * - * $Id: demux_mpc.c,v 1.3 2005/03/06 11:41:00 jstembridge Exp $ + * $Id: demux_mpc.c,v 1.5 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -119,11 +119,11 @@ static int open_mpc_file(demux_mpc_t *this) { } } - /* Validate signature - We only support SV7 at the moment */ + /* Validate signature - We only support SV 7.x at the moment */ if ((this->header[0] != 'M') || (this->header[1] != 'P') || (this->header[2] != '+') || - (this->header[3] != 0x07)) + ((this->header[3]&0x0f) != 0x07)) return 0; /* Get frame count */ @@ -344,7 +344,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -374,19 +374,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Musepack demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Musepack"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mpc mp+"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c index 61d7cc3ca..c9d49efa2 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_mpeg.c,v 1.150 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_mpeg.c,v 1.152 2007/02/20 00:34:55 dgp85 Exp $ * * demultiplexer for mpeg 1/2 program streams * reads streams of variable blocksizes @@ -310,7 +310,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) check_newpts( this, this->pts, PTS_VIDEO ); */ this->video_fifo->put (this->video_fifo, buf); - lprintf ("SPU SVCD PACK (pts: %lld, spu id: %d) put on FIFO\n", + lprintf ("SPU SVCD PACK (pts: %"PRId64", spu id: %d) put on FIFO\n", buf->pts, spu_id); return; @@ -1199,7 +1199,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str } case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -1222,19 +1222,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "MPEG program stream demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MPEG"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mpg mpeg"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "video/mpeg: mpeg, mpg, mpe: MPEG animation;" "video/x-mpeg: mpeg, mpg, mpe: MPEG animation;"; } diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index ef17ac948..7083d33d9 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.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_mpeg_block.c,v 1.217 2006/10/16 22:18:24 valtri Exp $ + * $Id: demux_mpeg_block.c,v 1.220 2007/02/20 00:34:55 dgp85 Exp $ * * demultiplexer for mpeg 1/2 program streams * used with fixed blocksize devices (like dvd/vcd) @@ -458,7 +458,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_ this->scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); */ - lprintf ("SCR=%lld\n", this->scr); + lprintf ("SCR=%"PRId64"\n", this->scr); /* mux_rate */ @@ -525,7 +525,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_ this->last_begin_time = buf->extra_info->input_time; } - lprintf ("NAV packet, start pts = %lld, end_pts = %lld\n", + lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n", start_pts, end_pts); if (this->nav_last_end_pts != start_pts && !this->preview_mode) { @@ -664,7 +664,7 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme this->pts |= p[12] << 7 ; this->pts |= (p[13] & 0xFE) >> 1 ; - lprintf ("pts = %lld\n", this->pts); + lprintf ("pts = %"PRId64"\n", this->pts); } else this->pts = 0; @@ -731,7 +731,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ check_newpts( this, this->pts, PTS_VIDEO ); */ this->video_fifo->put (this->video_fifo, buf); - lprintf ("SPU SVCD PACK (%lld, %d) put on fifo\n", this->pts, spu_id); + lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); return -1; } @@ -749,7 +749,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_ check_newpts( this, this->pts, PTS_VIDEO ); */ this->video_fifo->put (this->video_fifo, buf); - lprintf ("SPU CVD PACK (%lld, %d) put on fifo\n", this->pts, spu_id); + lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); return -1; } @@ -1146,7 +1146,7 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) { count ++; /* - printf ("demux_mpeg_block: stream_id %02x, pos: %lld, pts: %d, cur_rate = %d, overall rate : %d\n", + printf ("demux_mpeg_block: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n", stream_id, pos, pts, cur_rate, rate); */ } @@ -1456,9 +1456,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; + char *ending; - mrl = input->get_mrl (input); + const char *const mrl = input->get_mrl (input); if(!strncmp(mrl, "vcd:", 4)) { this->blocksize = 2324; @@ -1516,19 +1516,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "DVD/VOB demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MPEG_BLOCK"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "vob"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c index cb9732e53..c5769e3e3 100644 --- a/src/demuxers/demux_mpeg_pes.c +++ b/src/demuxers/demux_mpeg_pes.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_mpeg_pes.c,v 1.37 2006/10/16 22:18:24 valtri Exp $ + * $Id: demux_mpeg_pes.c,v 1.43 2007/03/29 17:11:36 dgp85 Exp $ * * demultiplexer for mpeg 2 PES (Packetized Elementary Streams) * reads streams of variable blocksizes @@ -81,20 +81,23 @@ typedef struct demux_mpeg_pes_s { int64_t nav_last_end_pts; int64_t nav_last_start_pts; int64_t last_pts[2]; - int send_newpts; - int preview_mode; - int buf_flag_seek; int64_t scr; uint32_t packet_len; + uint32_t stream_id; + int64_t pts; int64_t dts; - uint32_t stream_id; - int32_t mpeg1; - int32_t wait_for_program_stream_pack_header; + uint8_t send_newpts:1; + uint8_t buf_flag_seek:1; + uint8_t preview_mode:1; + uint8_t mpeg1:1; + uint8_t wait_for_program_stream_pack_header:1; + uint8_t mpeg12_h264_detected:2; + + int last_begin_time; int64_t last_cell_time; off_t last_cell_pos; - int last_begin_time; uint8_t preview_data[ MAX_PREVIEW_SIZE ]; off_t preview_size, preview_done; @@ -417,6 +420,9 @@ static int32_t parse_padding_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elem done += i; } + /* trigger detection of MPEG 1/2 respectively H.264 content */ + this->mpeg12_h264_detected = 0; + buf->free_buffer(buf); return this->packet_len + 6; } @@ -572,7 +578,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_pes_t *this, uint8_t this->scr += ( (p[8] & 0x03 << 7) | (p[9] & 0xFE >> 1) ); */ - lprintf ("SCR=%lld\n", this->scr); + lprintf ("SCR=%"PRId64"\n", this->scr); /* mux_rate */ @@ -649,7 +655,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el this->last_begin_time = buf->extra_info->input_time; } - lprintf ("NAV packet, start pts = %lld, end_pts = %lld\n", + lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n", start_pts, end_pts); if (this->nav_last_end_pts != start_pts && !this->preview_mode) { @@ -795,7 +801,7 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element this->pts |= (int64_t) p[12] << 7 ; this->pts |= (int64_t) (p[13] & 0xFE) >> 1 ; - lprintf ("pts = %lld\n", this->pts); + lprintf ("pts = %"PRId64"\n", this->pts); } else this->pts = 0; @@ -862,7 +868,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el check_newpts( this, this->pts, PTS_VIDEO ); */ this->video_fifo->put (this->video_fifo, buf); - lprintf ("SPU SVCD PACK (%lld, %d) put on fifo\n", this->pts, spu_id); + lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); return this->packet_len + result; } @@ -880,7 +886,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el check_newpts( this, this->pts, PTS_VIDEO ); */ this->video_fifo->put (this->video_fifo, buf); - lprintf ("SPU CVD PACK (%lld, %d) put on fifo\n", this->pts, spu_id); + lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id); return this->packet_len + result; } @@ -1062,21 +1068,102 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen uint32_t todo_length=0; uint32_t i; uint32_t chunk_length; + int buf_type = BUF_VIDEO_MPEG; + int payload_size; result = parse_pes_for_pts(this, p, buf); if (result < 0) return -1; p += result; - buf->content = p; + buf->content = p; + payload_size = buf->max_size - result; + if (payload_size > this->packet_len) + payload_size = this->packet_len; + + /* H.264 broadcasts via DVB-S use standard video PES packets, + so there is no way other than scanning the video data to + detect whether BUF_VIDEO_H264 needs to be used. + For performance reasons, this is not a general scanner for + H.264 content, as this kind of data format is likely to be + used only by VDR and VDR will ensure that an AUD-NAL unit + will be at the beginning of the PES packet's payload. + To minimize false hits, the whole payload is scanned for + MPEG 1/2 start codes, so there is only a little chance left + that a MPEG 1/2 slice 9 start code will be considered as a + H.264 access unit delimiter (should only happen after a seek). + + Meaning of bit 0 and 1 of mpeg12_h264_detected: + Bit 0: H.264 access unit delimiter seen + Bit 1: H.264 AUD seen again or MPEG 1/2 start code seen + + For performance reasons, the scanner is only active until + a H.264 AUD has been seen a second time or a MPEG 1/2 start + code has been seen. The scanner get's activated initially + (e. g. when opening the stream), after seeking or when VDR + sends a padding packet. + Until the scanner is convinced of it's decision by setting + bit 1, the default behaviour is to assume MPEG 1/2 unless + an AUD has been found at the beginning of the payload. + */ + if (this->mpeg12_h264_detected < 2) { + uint8_t *pp = p + 2, *pp_limit = p + payload_size - 1; + while (0 < pp && pp < pp_limit) { + if (pp[0] == 0x01 && pp[-1] == 0x00 && pp[-2] == 0x00) { + if (pp[1] >= 0x80) { /* MPEG 1/2 start code */ + this->mpeg12_h264_detected = 2; + break; + } else { + int nal_type_code = pp[1] & 0x1f; + if (nal_type_code == 9 && pp == (p + 2)) { /* access unit delimiter */ + if (this->mpeg12_h264_detected == 1) { + this->mpeg12_h264_detected = 3; + break; + } + this->mpeg12_h264_detected = 1; + } + } + } + pp++; + pp = memchr(pp, 0x01, pp_limit - pp); + } + lprintf("%s%c\n", (this->mpeg12_h264_detected & 1) ? "H.264" : "MPEG1/2", (this->mpeg12_h264_detected & 2) ? '!' : '?'); + } - if (this->packet_len <= (buf->max_size - 6)) { - buf->size = this->packet_len; + /* when an H.264 AUD is seen, we first need to tell the decoder that the + previous frame was complete. + */ + if (this->mpeg12_h264_detected & 1) { + buf_type = BUF_VIDEO_H264; + int nal_type_code = -1; + if (payload_size >= 4 && p[2] == 0x01 && p[1] == 0x00 && p[0] == 0x00) + nal_type_code = p[3] & 0x1f; + if (nal_type_code == 9) { /* access unit delimiter */ + buf_element_t *b = this->video_fifo->buffer_pool_alloc (this->video_fifo); + b->content = b->mem; + b->size = 0; + b->pts = 0; + b->type = buf_type; + b->decoder_flags = BUF_FLAG_FRAME_END; + this->video_fifo->put (this->video_fifo, b); + } + } + + if (this->packet_len <= (buf->max_size - result)) { + buf->size = this->packet_len; + /* VDR ensures that H.264 still images end with an end of sequence NAL unit. We + need to detect this to inform the decoder that the current frame is complete. + */ + if (this->mpeg12_h264_detected & 1) { + uint8_t *t = buf->content + buf->size; + if (buf->size >=4 && t[-1] == 10 && t[-2] == 0x01 && t[-3] == 0x00 && t[-4] == 0x00) /* end of sequence */ + buf->decoder_flags = BUF_FLAG_FRAME_END; + } } else { - buf->size = buf->max_size - result; - todo_length = this->packet_len - buf->size; + buf->size = buf->max_size - result; + todo_length = this->packet_len - buf->size; } - buf->type = BUF_VIDEO_MPEG; + buf->type = buf_type; buf->pts = this->pts; buf->decoder_info[0] = this->pts - this->dts; if( !this->preview_mode ) @@ -1098,10 +1185,20 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen } buf->content = buf->mem; buf->size = chunk_length; - buf->type = BUF_VIDEO_MPEG; + buf->type = buf_type; buf->pts = 0; - this->video_fifo->put (this->video_fifo, buf); todo_length -= chunk_length; + + /* VDR ensures that H.264 still images end with an end of sequence NAL unit. We + need to detect this to inform the decoder that the current frame is complete. + */ + if ((this->mpeg12_h264_detected & 1) && todo_length <= 0) { + uint8_t *t = buf->content + buf->size; + if (buf->size >= 4 && t[-1] == 10 && t[-2] == 0x01 && t[-3] == 0x00 && t[-4] == 0x00) /* end of sequence */ + buf->decoder_flags = BUF_FLAG_FRAME_END; + } + + this->video_fifo->put (this->video_fifo, buf); } lprintf ("MPEG Video PACK put on fifo\n"); @@ -1283,7 +1380,7 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) { count ++; /* - printf ("demux_mpeg_pes: stream_id %02x, pos: %lld, pts: %d, cur_rate = %d, overall rate : %d\n", + printf ("demux_mpeg_pes: stream_id %02x, pos: %"PRId64", pts: %d, cur_rate = %d, overall rate : %d\n", stream_id, pos, pts, cur_rate, rate); */ } @@ -1426,6 +1523,8 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen, } else { this->buf_flag_seek = 1; this->nav_last_end_pts = this->nav_last_start_pts = 0; + /* trigger detection of MPEG 1/2 respectively H.264 content */ + this->mpeg12_h264_detected = 0; _x_demux_flush_engine(this->stream); } @@ -1500,7 +1599,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str this->status = DEMUX_FINISHED; /* Don't start demuxing stream until we see a program_stream_pack_header */ /* We need to system header in order to identify is the stream is mpeg1 or mpeg2. */ - this->wait_for_program_stream_pack_header=1; + this->wait_for_program_stream_pack_header = 1; + /* trigger detection of MPEG 1/2 respectively H.264 content */ + this->mpeg12_h264_detected = 0; this->preview_size = 0; @@ -1594,11 +1695,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; - - mrl = input->get_mrl (input); - - ending = strrchr(mrl, '.'); + const char *const mrl = input->get_mrl (input); + const char *const ending = strrchr(mrl, '.'); if (!ending) { free (this->scratch_base); @@ -1630,19 +1728,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "mpeg pes demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MPEG_PES"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "pes"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 13724026c..31b2d33ff 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2003 the xine project + * Copyright (C) 2000-2007 the xine project * * This file is part of xine, a free video player. * @@ -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_mpgaudio.c,v 1.145 2006/09/03 02:03:21 dgp85 Exp $ + * $Id: demux_mpgaudio.c,v 1.156 2007/03/29 16:32:12 dgp85 Exp $ * * demultiplexer for mpeg audio (i.e. mp3) streams * @@ -79,28 +79,16 @@ /* mp3 frame struct */ typedef struct { /* header */ - uint16_t frame_sync; - uint8_t mpeg25_bit; - uint8_t lsf_bit; - uint8_t layer; - uint8_t protection_bit; - uint8_t bitrate_idx; - uint8_t freq_idx; - uint8_t padding_bit; - uint8_t private_bit; - uint8_t channel_mode; - uint8_t mode_extension; - uint8_t copyright; - uint8_t original; - uint8_t emphasis; - - uint8_t version_idx; /* 0: mpeg1, 1: mpeg2, 2: mpeg2.5 */ - int bitrate; /* in bit per second */ - int freq; /* in Hz */ - int samples; /* samples per frame */ - int padding; /* padding bytes (0, 1 or 4)*/ - int size; /* in bytes */ - double duration; /* in xine pts */ + double duration; + uint32_t size; /* in bytes */ + uint32_t bitrate; /* in bit per second */ + uint16_t freq; /* in Hz */ + + uint8_t layer; + + uint8_t version_idx:2; /* 0: mpeg1, 1: mpeg2, 2: mpeg2.5 */ + uint8_t lsf_bit:1; + uint8_t channel_mode:3; } mpg_audio_frame_t; /* Xing Vbr Header struct */ @@ -163,61 +151,72 @@ typedef struct { } demux_mpgaudio_class_t; -/* bitrate table[mpeg version][layer][bitrate index] - * values stored in kbps - */ -const int mp3_bitrates[3][3][16] = { - { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,}, - {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,}, - {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,} }, - { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,} }, - { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, - {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,} } -}; - -/* frequency table[mpeg version][frequence index] (in KHz) */ -static int mp3_freqs[3][3] = { - { 44100, 48000, 32000 }, - { 22050, 24000, 16000 }, - { 11025, 12000, 8000 } -}; - -/* samples per frame table[mpeg version][layer] */ -static int mp3_samples[3][3] = { - { 384, 1152, 1152 }, - { 384, 1152, 576 }, - { 384, 1152, 576 } -}; - -/* samples per frame table[layer][padding bit] */ -static int mp3_paddings[3][2] = { - { 0, 4 }, - { 0, 1 }, - { 0, 1 } -}; - /* * Parse a mp3 frame * return 1 on success */ -static int parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) { - uint32_t head; +static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *const buf) { + /* bitrate table[mpeg version][layer][bitrate index] + * values stored in kbps + */ + static const uint16_t mp3_bitrates[3][3][16] = { + { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448,}, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384,}, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320,} }, + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,} }, + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256,}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160,} } + }; + + /* frequency table[mpeg version][frequence index] (in KHz) */ + static const uint16_t mp3_freqs[3][3] = { + { 44100, 48000, 32000 }, + { 22050, 24000, 16000 }, + { 11025, 12000, 8000 } + }; + + /* samples per frame table[mpeg version][layer] */ + static const uint16_t mp3_samples[3][3] = { + { 384, 1152, 1152 }, + { 384, 1152, 576 }, + { 384, 1152, 576 } + }; + + struct { + uint16_t mpeg25_bit:1; + uint16_t bitrate_idx:4; + uint16_t freq_idx:3; + uint16_t padding_bit:1; + uint16_t channel_mode:3; + +#if 0 /* Unused */ + uint16_t protection_bit:1; + uint16_t private_bit:1; + uint16_t mode_extension:3; + uint16_t copyright:1; + uint16_t original:1; +#endif - head = BE_32(buf); +#if defined(OPT_STRICT) + uint16_t emphasis:3; +#endif + } frame_header; + + const uint32_t head = BE_32(buf); + const uint16_t frame_sync = head >> 21; lprintf("header: %08X\n", head); - frame->frame_sync = head >> 21; - if (frame->frame_sync != 0x7ff) { + if (frame_sync != 0x7ff) { lprintf("invalid frame sync\n"); return 0; } - frame->mpeg25_bit = (head >> 20) & 0x1; + frame_header.mpeg25_bit = (head >> 20) & 0x1; frame->lsf_bit = (head >> 19) & 0x1; - if (!frame->mpeg25_bit) { + if (!frame_header.mpeg25_bit) { if (frame->lsf_bit) { lprintf("reserved mpeg25 lsf combination\n"); return 0; @@ -236,54 +235,60 @@ static int parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) { return 0; } - frame->protection_bit = (head >> 16) & 0x1; - frame->bitrate_idx = (head >> 12) & 0xf; - if ((frame->bitrate_idx == 0) || (frame->bitrate_idx == 15)) { + frame_header.bitrate_idx = (head >> 12) & 0xf; + if ((frame_header.bitrate_idx == 0) || (frame_header.bitrate_idx == 15)) { lprintf("invalid bitrate index\n"); return 0; } - frame->freq_idx = (head >> 10) & 0x3; - if (frame->freq_idx == 3) { + frame_header.freq_idx = (head >> 10) & 0x3; + if (frame_header.freq_idx == 3) { lprintf("invalid frequence index\n"); return 0; } - frame->padding_bit = (head >> 9) & 0x1; - frame->private_bit = (head >> 8) & 0x1; - frame->channel_mode = (head >> 6) & 0x3; - frame->mode_extension = (head >> 4) & 0x3; - frame->copyright = (head >> 3) & 0x1; - frame->original = (head >> 2) & 0x1; - frame->emphasis = head & 0x3; + frame_header.padding_bit = (head >> 9) & 0x1; + frame_header.channel_mode = (head >> 6) & 0x3; + +#if 0 /* Unused */ + frame_header.protection_bit = (head >> 16) & 0x1; + frame_header.private_bit = (head >> 8) & 0x1; + frame_header.mode_extension = (head >> 4) & 0x3; + frame_header.copyright = (head >> 3) & 0x1; + frame_header.original = (head >> 2) & 0x1; +#endif #if defined(OPT_STRICT) + frame_header.emphasis = head & 0x3; + /* * ISO/IEC 11172-3 says this is a reserved emphasis value, but * streams exist which use it anyway. Since the value is not important * to the decoder proper, we allow it unless OPT_STRICT is defined. */ - if (frame->emphasis == 2) { + if (frame_header.emphasis == 2) { lprintf("reserved emphasis\n"); return 0; } #endif - frame->bitrate = mp3_bitrates[frame->version_idx][frame->layer - 1][frame->bitrate_idx] * 1000; - frame->freq = mp3_freqs[frame->version_idx][frame->freq_idx]; - frame->samples = mp3_samples[frame->version_idx][frame->layer - 1]; - frame->padding = mp3_paddings[frame->layer - 1][frame->padding_bit]; + { + const uint16_t samples = mp3_samples[frame->version_idx][frame->layer - 1]; + frame->bitrate = mp3_bitrates[frame->version_idx][frame->layer - 1][frame_header.bitrate_idx] * 1000; + frame->freq = mp3_freqs[frame->version_idx][frame_header.freq_idx]; - frame->size = frame->samples * (frame->bitrate / 8); - frame->size /= frame->freq; - frame->size += frame->padding; + frame->size = samples * (frame->bitrate / 8); + frame->size /= frame->freq; + /* Padding: only if padding_bit is set; 4 bytes for Layer 1 and 1 byte for others */ + frame->size += ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 ); - frame->duration = 1000.0f * (double)frame->samples / (double)frame->freq; + frame->duration = 1000.0f * (double)samples / (double)frame->freq; + } lprintf("mpeg %d, layer %d\n", frame->version_idx + 1, frame->layer); lprintf("bitrate: %d bps, samplerate: %d Hz\n", frame->bitrate, frame->freq); lprintf("length: %d bytes, %f ms\n", frame->size, frame->duration); - lprintf("padding: %d bytes\n", frame->padding); + lprintf("padding: %d bytes\n", ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 )); return 1; } @@ -294,7 +299,9 @@ static int parse_frame_header(mpg_audio_frame_t *frame, uint8_t *buf) { static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, uint8_t *buf, int bufsize) { +#ifdef LOG int i; +#endif uint8_t *ptr = buf; xing_header_t *xing; @@ -338,14 +345,12 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, lprintf("toc found\n"); if (ptr >= (buf + bufsize - XING_TOC_LENGTH)) return 0; - for (i = 0; i < XING_TOC_LENGTH; i++) { - xing->toc[i] = *(ptr + i); + memcpy(xing->toc, ptr, XING_TOC_LENGTH); #ifdef LOG - printf("%d ", xing->toc[i]); -#endif + for (i = 0; i < XING_TOC_LENGTH; i++) { + lprintf("%d ", xing->toc[i]); } -#ifdef LOG - printf("\n"); + lprintf("\n"); #endif ptr += XING_TOC_LENGTH; } @@ -437,7 +442,7 @@ static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame, for (i = 0; i <= vbri->toc_entries; i++) { toc_stream_size += vbri->toc[i]; } - lprintf("stream size from toc: %lld\n", toc_stream_size); + lprintf("stream size from toc: %"PRId64"\n", toc_stream_size); } return vbri; @@ -460,7 +465,7 @@ static int parse_frame_payload(demux_mpgaudio_t *this, uint64_t pts = 0; frame_pos = this->input->get_current_pos(this->input) - 4; - lprintf("frame_pos = %lld\n", frame_pos); + lprintf("frame_pos = %"PRId64"\n", frame_pos); buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); @@ -510,7 +515,7 @@ static int parse_frame_payload(demux_mpgaudio_t *this, buf->decoder_flags = decoder_flags|BUF_FLAG_FRAME_END; this->audio_fifo->put(this->audio_fifo, buf); - lprintf("send buffer: pts=%lld\n", pts); + lprintf("send buffer: pts=%"PRId64"\n", pts); this->cur_time += this->cur_frame.duration; return 1; } @@ -606,39 +611,14 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags, int s return parse_frame_payload(this, header_buf, decoder_flags); - } else if ((BE_32(header_buf)) == ID3V22_TAG) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: ID3V2.2 tag\n"); - if (!id3v22_parse_tag(this->input, this->stream, header_buf)) { + } else if ( id3v2_istag(header_buf) ) { + if (!id3v2_parse_tag(this->input, this->stream, header_buf)) { xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: ID3V2.2 tag parsing error\n"); + LOG_MODULE ": ID3V2 tag parsing error\n"); bytes = 1; /* resync */ } else { bytes = 4; } - - } else if ((BE_32(header_buf)) == ID3V23_TAG) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: ID3V2.3 tag\n"); - if (!id3v23_parse_tag(this->input, this->stream, header_buf)) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: ID3V2.3 tag parsing error\n"); - bytes = 1; /* resync */ - } else { - bytes = 4; - } - - } else if ((BE_32(header_buf)) == ID3V24_TAG) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: ID3V2.4 tag\n"); - if (!id3v24_parse_tag(this->input, this->stream, header_buf)) { - xprintf(this->stream->xine, XINE_VERBOSITY_LOG, - "demux_mpgaudio: ID3V2.4 tag parsing error\n"); - bytes = 1; /* resync */ - } else { - bytes = 4; - } - } else { /* skip */ bytes = 1; @@ -718,10 +698,7 @@ static int detect_mpgaudio_file(input_plugin_t *input) { * flac files can contain id3v2 tags */ uint8_t *ptr = &buf[6]; - uint32_t tag_size = ((uint32_t)ptr[0] << 21) + - ((uint32_t)ptr[1] << 14) + - ((uint32_t)ptr[2] << 7) + - (uint32_t)ptr[3]; + uint32_t tag_size = id3v2_tagsize(ptr); lprintf("try to skip id3v2 tag (%d bytes)\n", tag_size); if ((10 + tag_size) >= preview_len) { lprintf("cannot skip id3v2 tag\n"); @@ -823,9 +800,9 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) { _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->br); _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITRATE, this->br); - lprintf("frame_start: %lld, frame_end: %lld\n", + lprintf("frame_start: %"PRId64", frame_end: %"PRId64"\n", this->mpg_frame_start, this->mpg_frame_end); - lprintf("stream size: %lld, mp3 size: %lld\n", + lprintf("stream size: %"PRId64", mp3 size: %"PRId64"\n", this->input->get_length(this->input), this->mpg_size); lprintf("stream_length: %d ms\n", this->stream_length); @@ -939,7 +916,7 @@ static int demux_mpgaudio_seek (demux_plugin_t *this_gen, /* Convert position seek to time seek */ if (!start_time) { start_time = (int)((double)start_pos * (double)this->stream_length / 65535.0f); - lprintf("position seek: start_pos=%lld => start_time=%d\n", start_pos, start_time); + lprintf("position seek: start_pos=%"PRId64" => start_time=%d\n", start_pos, start_time); } if (start_time < 0) @@ -951,14 +928,14 @@ static int demux_mpgaudio_seek (demux_plugin_t *this_gen, if (this->xing_header && (this->xing_header->flags & (XING_TOC_FLAG | XING_BYTES_FLAG))) { seek_pos += xing_get_seek_point(this->xing_header, start_time, this->stream_length); - lprintf("time seek: xing: time=%d, pos=%lld\n", start_time, seek_pos); + lprintf("time seek: xing: time=%d, pos=%"PRId64"\n", start_time, seek_pos); } else if (this->vbri_header) { seek_pos += vbri_get_seek_point(this->vbri_header, start_time, this->stream_length); - lprintf("time seek: vbri: time=%d, pos=%lld\n", start_time, seek_pos); + lprintf("time seek: vbri: time=%d, pos=%"PRId64"\n", start_time, seek_pos); } else { /* cbr */ seek_pos += ((double)start_time / 1000.0) * ((double)this->br / 8.0); - lprintf("time seek: cbr: time=%d, pos=%lld\n", start_time, seek_pos); + lprintf("time seek: cbr: time=%d, pos=%"PRId64"\n", start_time, seek_pos); } } /* assume seeking is always perfect... */ @@ -1016,8 +993,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *mrl = input->get_mrl(input); - char *extensions = class_gen->get_extensions (class_gen); + const char *const mrl = input->get_mrl(input); + const char *const extensions = class_gen->get_extensions (class_gen); lprintf ("stage by extension %s\n", mrl); @@ -1058,15 +1035,15 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str * demux mpegaudio class */ -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "MPEG audio demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MPEGAUDIO"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { demux_mpgaudio_class_t *this = (demux_mpgaudio_class_t *) this_gen; if( _x_decoder_available(this->xine, BUF_AUDIO_MPEG) ) @@ -1075,7 +1052,7 @@ static char *get_extensions (demux_class_t *this_gen) { return ""; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { demux_mpgaudio_class_t *this = (demux_mpgaudio_class_t *) this_gen; if( _x_decoder_available(this->xine, BUF_AUDIO_MPEG) ) @@ -1085,7 +1062,7 @@ static char *get_mimetypes (demux_class_t *this_gen) { "audio/x-mpeg3: mp3: MPEG audio;" "audio/mpeg: mpa,abs,mpega: MPEG audio;" "audio/x-mpeg: mpa,abs,mpega: MPEG audio;" - "x-mpegurl: mp3: MPEG audio;" + "audio/x-mpegurl: mp3: MPEG audio;" "audio/mpegurl: mp3: MPEG audio;" "audio/mp3: mp3: MPEG audio;" "audio/x-mp3: mp3: MPEG audio;"; diff --git a/src/demuxers/demux_nsf.c b/src/demuxers/demux_nsf.c index dae756d8d..7408274d5 100644 --- a/src/demuxers/demux_nsf.c +++ b/src/demuxers/demux_nsf.c @@ -30,7 +30,7 @@ * For more information regarding the NSF format, visit: * http://www.tripoint.org/kevtris/nes/nsfspec.txt * - * $Id: demux_nsf.c,v 1.22 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_nsf.c,v 1.24 2007/03/29 17:03:06 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -71,12 +71,14 @@ typedef struct { input_plugin_t *input; int status; - char *title; - char *artist; - char *copyright; int total_songs; int current_song; int new_song; /* indicates song change */ + + char *title; + char *artist; + char *copyright; + off_t filesize; int64_t current_pts; @@ -322,7 +324,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -352,19 +354,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "NES Music file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "NSF"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "nsf"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_nsv.c b/src/demuxers/demux_nsv.c index 6f71a6264..6d43b247c 100644 --- a/src/demuxers/demux_nsv.c +++ b/src/demuxers/demux_nsv.c @@ -23,7 +23,7 @@ * For more information regarding the NSV file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_nsv.c,v 1.24 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_nsv.c,v 1.25 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -615,7 +615,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -645,19 +645,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Nullsoft Video demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Nullsoft NSV"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "nsv"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c index 3ea07306b..f868018af 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_ogg.c,v 1.171 2006/11/10 14:53:23 dgp85 Exp $ + * $Id: demux_ogg.c,v 1.177 2007/03/29 19:38:51 dgp85 Exp $ * * demultiplexer for ogg streams * @@ -126,17 +126,20 @@ typedef struct demux_ogg_s { input_plugin_t *input; int status; + int frame_duration; + #ifdef HAVE_THEORA theora_info t_info; theora_comment t_comment; #endif - int frame_duration; - ogg_sync_state oy; ogg_page og; int64_t start_pts; + int64_t last_pts[2]; + + int time_length; int num_streams; stream_info_t *si[MAX_STREAMS]; /* stream info */ @@ -148,16 +151,14 @@ typedef struct demux_ogg_s { off_t avg_bitrate; - int64_t last_pts[2]; - int send_newpts; - int buf_flag_seek; - int keyframe_needed; - int ignore_keyframes; - int time_length; - char *title; chapter_info_t *chapter_info; xine_event_queue_t *event_queue; + + uint8_t send_newpts:1; + uint8_t buf_flag_seek:1; + uint8_t keyframe_needed:1; + uint8_t ignore_keyframes:1; } demux_ogg_t ; typedef struct { @@ -536,7 +537,11 @@ static void update_chapter_display (demux_ogg_t *this, int stream_num, ogg_packe if (chapter >= 0) { char t_title[256]; - snprintf(t_title, sizeof (t_title), "%s / %s", this->title, this->chapter_info->entries[chapter].name); + if (this->title) { + snprintf(t_title, sizeof (t_title), "%s / %s", this->title, this->chapter_info->entries[chapter].name); + } else { + snprintf(t_title, sizeof (t_title), "%s", this->chapter_info->entries[chapter].name); + } title = t_title; } else { title = this->title; @@ -714,7 +719,7 @@ static void send_ogg_buf (demux_ogg_t *this, buf->size = 12 + op->bytes + 1; - lprintf ("CMML stream %d (bytes=%ld): PTS %lld: %s\n", + lprintf ("CMML stream %d (bytes=%ld): PTS %"PRId64": %s\n", stream_num, op->bytes, buf->pts, str); this->video_fifo->put (this->video_fifo, buf); @@ -1861,9 +1866,7 @@ static int format_lang_string (demux_ogg_t * this, uint32_t buf_mask, uint32_t b for (stream_num=0; stream_num<this->num_streams; stream_num++) { if ((this->si[stream_num]->buf_types & buf_mask) == buf_type) { if (this->si[stream_num]->language) { - strncpy (str, this->si[stream_num]->language, XINE_LANG_MAX); - str[XINE_LANG_MAX - 1] = '\0'; - if (strlen(this->si[stream_num]->language) >= XINE_LANG_MAX) + if (snprintf (str, XINE_LANG_MAX, "%s", this->si[stream_num]->language) >= XINE_LANG_MAX) /* the string got truncated */ str[XINE_LANG_MAX - 2] = str[XINE_LANG_MAX - 3] = str[XINE_LANG_MAX - 4] = '.'; /* TODO: provide long version in XINE_META_INFO_FULL_LANG */ @@ -1926,7 +1929,7 @@ static int detect_ogg_content (int detection_method, demux_class_t *class_gen, } case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -1988,7 +1991,7 @@ static int detect_anx_content (int detection_method, demux_class_t *class_gen, #undef ANNODEX_SIGNATURE_SEARCH case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -2099,19 +2102,19 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen, * Annodex demuxer class */ -static char *anx_get_description (demux_class_t *this_gen) { +static const char *anx_get_description (demux_class_t *this_gen) { return "Annodex demux plugin"; } -static char *anx_get_identifier (demux_class_t *this_gen) { +static const char *anx_get_identifier (demux_class_t *this_gen) { return "Annodex"; } -static char *anx_get_extensions (demux_class_t *this_gen) { +static const char *anx_get_extensions (demux_class_t *this_gen) { return "anx axa axv"; } -static char *anx_get_mimetypes (demux_class_t *this_gen) { +static const char *anx_get_mimetypes (demux_class_t *this_gen) { return "application/x-annodex: ogg: Annodex media;"; } @@ -2140,22 +2143,23 @@ static void *anx_init_class (xine_t *xine, void *data) { * ogg demuxer class */ -static char *ogg_get_description (demux_class_t *this_gen) { +static const char *ogg_get_description (demux_class_t *this_gen) { return "OGG demux plugin"; } -static char *ogg_get_identifier (demux_class_t *this_gen) { +static const char *ogg_get_identifier (demux_class_t *this_gen) { return "OGG"; } -static char *ogg_get_extensions (demux_class_t *this_gen) { +static const char *ogg_get_extensions (demux_class_t *this_gen) { return "ogg ogm spx"; } -static char *ogg_get_mimetypes (demux_class_t *this_gen) { +static const char *ogg_get_mimetypes (demux_class_t *this_gen) { return "audio/x-ogg: ogg: OggVorbis Audio;" "audio/x-speex: ogg: Speex Audio;" - "application/x-ogg: ogg: OggVorbis Audio;"; + "application/x-ogg: ogg: Ogg Stream;" + "application/ogg: ogg: Ogg Stream;"; } static void ogg_class_dispose (demux_class_t *this_gen) { diff --git a/src/demuxers/demux_pva.c b/src/demuxers/demux_pva.c index 44e5112c6..55b1f7644 100644 --- a/src/demuxers/demux_pva.c +++ b/src/demuxers/demux_pva.c @@ -23,7 +23,7 @@ * For more information regarding the PVA file format, refer to this PDF: * http://www.technotrend.de/download/av_format_v1.pdf * - * $Id: demux_pva.c,v 1.24 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_pva.c,v 1.25 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -451,7 +451,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -480,19 +480,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "TechnoTrend PVA demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "TechnoTrend PVA"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "pva"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c index b4646b3e5..4144f3049 100644 --- a/src/demuxers/demux_qt.c +++ b/src/demuxers/demux_qt.c @@ -30,7 +30,7 @@ * build_frame_table * free_qt_info * - * $Id: demux_qt.c,v 1.212 2006/11/11 12:23:44 molivier Exp $ + * $Id: demux_qt.c,v 1.214 2007/01/19 01:05:24 dgp85 Exp $ * */ @@ -2993,11 +2993,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *ending, *mrl; - - mrl = input->get_mrl (input); - - ending = strrchr(mrl, '.'); + const char *const mrl = input->get_mrl (input); + const char *const ending = strrchr(mrl, '.'); if (!ending) { free (this); @@ -3041,19 +3038,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Apple Quicktime (MOV) and MPEG-4 demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MOV/MPEG-4"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mov qt mp4 m4a m4b"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "video/quicktime: mov,qt: Quicktime animation;" "video/x-quicktime: mov,qt: Quicktime animation;" "audio/x-m4a: m4a,m4b: MPEG-4 audio;" diff --git a/src/demuxers/demux_rawdv.c b/src/demuxers/demux_rawdv.c index 6c7d672e8..7a4cbaec9 100644 --- a/src/demuxers/demux_rawdv.c +++ b/src/demuxers/demux_rawdv.c @@ -19,7 +19,7 @@ */ /* - * $Id: demux_rawdv.c,v 1.29 2006/08/08 03:15:02 miguelfreitas Exp $ + * $Id: demux_rawdv.c,v 1.30 2007/01/19 00:26:40 dgp85 Exp $ * * demultiplexer for raw dv streams */ @@ -385,7 +385,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -413,19 +413,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Raw DV Video stream"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "raw_dv"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "dv dif"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c index 7441c8619..11b0dbf38 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.109 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_real.c,v 1.113 2007/02/20 00:34:56 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -181,7 +181,7 @@ static void real_parse_index(demux_real_t *this) { real_index_entry_t **index; while(next_index_chunk) { - lprintf("reading index chunk at %llX\n", next_index_chunk); + lprintf("reading index chunk at %"PRIX64"\n", next_index_chunk); /* Seek to index chunk */ this->input->seek(this->input, next_index_chunk, SEEK_SET); @@ -401,9 +401,9 @@ static void real_parse_headers (demux_real_t *this) { this->avg_bitrate = BE_32(&chunk_buffer[6]); lprintf("PROP: duration: %d ms\n", this->duration); - lprintf("PROP: index start: %llX\n", this->index_start); - lprintf("PROP: data start: %llX\n", this->data_start); - lprintf("PROP: average bit rate: %lld\n", this->avg_bitrate); + lprintf("PROP: index start: %"PRIX64"\n", this->index_start); + lprintf("PROP: data start: %"PRIX64"\n", this->data_start); + lprintf("PROP: average bit rate: %"PRId64"\n", this->avg_bitrate); if (this->avg_bitrate<1) this->avg_bitrate = 1; @@ -854,12 +854,12 @@ static void check_newpts (demux_real_t *this, int64_t pts, int video, int previe int64_t diff; diff = pts - this->last_pts[video]; - lprintf ("check_newpts %lld\n", pts); + lprintf ("check_newpts %"PRId64"\n", pts); if (!preview && pts && (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) { - lprintf ("diff=%lld\n", diff); + lprintf ("diff=%"PRId64"\n", diff); if (this->buf_flag_seek) { _x_demux_control_newpts(this->stream, pts, BUF_FLAG_SEEK); @@ -1012,7 +1012,7 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { size--; } - lprintf ("packet of stream %d, 0x%X bytes @ %llX, pts = %lld%s\n", + lprintf ("packet of stream %d, 0x%X bytes @ %"PRIX64", pts = %"PRId64"%s\n", stream, size, offset, pts, keyframe ? ", keyframe" : ""); if (this->video_stream && (stream == this->video_stream->mdpr->stream_number)) { @@ -1409,12 +1409,15 @@ static int demux_real_seek (demux_plugin_t *this_gen, real_index_entry_t *index, *other_index = NULL; int i = 0, entries; - start_pos = (off_t) ( (double) start_pos / 65535 * - this->input->get_length (this->input) ); + lprintf("seek start_pos=%d, start_time=%d, playing=%d\n", + (int)start_pos, start_time, playing); if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) && ((this->audio_stream && this->audio_stream->index) || (this->video_stream && this->video_stream->index))) { + + start_pos = (off_t) ( (double) start_pos / 65535 * + this->input->get_length (this->input) ); /* video index has priority over audio index */ if(this->video_stream && this->video_stream->index) { @@ -1453,6 +1456,13 @@ static int demux_real_seek (demux_plugin_t *this_gen, _x_demux_flush_engine(this->stream); } } + else if (!playing && this->input->seek_time != NULL) { + /* RTSP supports only time based seek */ + if (start_pos && !start_time) + start_time = (int64_t) this->duration * start_pos / 65535; + + this->input->seek_time(this->input, start_time, SEEK_SET); + } this->send_newpts = 1; this->old_seqnum = -1; @@ -1555,7 +1565,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -1608,19 +1618,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "RealMedia file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Real"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "rm rmvb ram"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-pn-realaudio: ra, rm, ram: Real Media file;" "audio/x-pn-realaudio-plugin: rpm: Real Media plugin file;" "audio/x-real-audio: ra, rm, ram: Real Media file;" diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c index d1de83015..bf8de0dad 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.32 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_realaudio.c,v 1.34 2007/03/29 17:00:32 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -57,16 +57,15 @@ typedef struct { unsigned int fourcc; unsigned int audio_type; + unsigned short block_align; + + uint8_t seek_flag:1; /* this is set when a seek just occurred */ + off_t data_start; off_t data_size; - 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; typedef struct { @@ -316,10 +315,7 @@ 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->bytes_per_sec) - return (int)((int64_t) this->data_size * 1000 / this->bytes_per_sec); - else - return 0; + return 0; } static uint32_t demux_ra_get_capabilities(demux_plugin_t *this_gen) { @@ -355,7 +351,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -385,19 +381,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "RealAudio file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "RA"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "ra"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-realaudio: ra: RealAudio File;"; } diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c index ed261d728..0e7c93b97 100644 --- a/src/demuxers/demux_roq.c +++ b/src/demuxers/demux_roq.c @@ -23,7 +23,7 @@ * For more information regarding the RoQ file format, visit: * http://www.csse.monash.edu.au/~timf/ * - * $Id: demux_roq.c,v 1.53 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_roq.c,v 1.54 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -432,7 +432,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -462,19 +462,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Id RoQ file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "RoQ"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "roq"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_shn.c b/src/demuxers/demux_shn.c index 8e3602634..3db568aab 100644 --- a/src/demuxers/demux_shn.c +++ b/src/demuxers/demux_shn.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_shn.c,v 1.2 2006/09/28 22:27:52 dgp85 Exp $ + * $Id: demux_shn.c,v 1.4 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -67,8 +67,8 @@ static int open_shn_file(demux_shn_t *this) { if (_x_demux_read_header(this->input, peak, 4) != 4) return 0; - if ((peak[0] != 'a') && (peak[1] != 'j') && - (peak[2] != 'k') && (peak[3] != 'g')) { + if ((peak[0] != 'a') || (peak[1] != 'j') || + (peak[2] != 'k') || (peak[3] != 'g')) { return 0; } @@ -202,7 +202,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -230,19 +230,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Shorten demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "Shorten"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "shn"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_slave.c b/src/demuxers/demux_slave.c index 306b14ed4..a00ad0661 100644 --- a/src/demuxers/demux_slave.c +++ b/src/demuxers/demux_slave.c @@ -21,7 +21,7 @@ */ /* - * $Id: demux_slave.c,v 1.21 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_slave.c,v 1.23 2007/01/19 01:05:24 dgp85 Exp $ * * demuxer for slave "protocol" * master xine must be started with XINE_PARAM_BROADCASTER_PORT set, that is, @@ -338,9 +338,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *mrl; - - mrl = input->get_mrl (input); + const char *const mrl = input->get_mrl (input); if(!strncmp(mrl, "slave://", 8)) break; @@ -393,19 +391,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return ""; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "slave"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return ""; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_smjpeg.c b/src/demuxers/demux_smjpeg.c index afe28328d..9c86314c5 100644 --- a/src/demuxers/demux_smjpeg.c +++ b/src/demuxers/demux_smjpeg.c @@ -23,7 +23,7 @@ * For more information on the SMJPEG file format, visit: * http://www.lokigames.com/development/smjpeg.php3 * - * $Id: demux_smjpeg.c,v 1.50 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_smjpeg.c,v 1.51 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -421,7 +421,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -451,19 +451,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "SMJPEG file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "SMJPEG"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mjpg"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_snd.c b/src/demuxers/demux_snd.c index c1925bc71..99415890a 100644 --- a/src/demuxers/demux_snd.c +++ b/src/demuxers/demux_snd.c @@ -21,7 +21,7 @@ /* * SND/AU File Demuxer by Mike Melanson (melanson@pcisys.net) * - * $Id: demux_snd.c,v 1.40 2004/10/18 18:20:32 miguelfreitas Exp $ + * $Id: demux_snd.c,v 1.41 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -339,7 +339,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -369,19 +369,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "SND/AU file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "SND/AU"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "snd au"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/basic: snd,au: ULAW (Sun) audio;" "audio/x-basic: snd,au: ULAW (Sun) audio;" "audio/x-pn-au: snd,au: ULAW (Sun) audio;"; diff --git a/src/demuxers/demux_str.c b/src/demuxers/demux_str.c index ddb800260..90dbf2117 100644 --- a/src/demuxers/demux_str.c +++ b/src/demuxers/demux_str.c @@ -24,7 +24,7 @@ * This demuxer handles either raw STR files (which are just a concatenation * of raw compact disc sectors) or STR files with RIFF headers. * - * $Id: demux_str.c,v 1.25 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_str.c,v 1.26 2007/01/19 00:26:40 dgp85 Exp $ */ /* @@ -576,7 +576,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -605,20 +605,20 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Sony Playstation STR file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "PSX STR"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { /* also .mov, but we don't want to hijack that extension */ return "str iki ik2 dps dat xa xa1 xa2 xas xap"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c index ef68cb698..aea0c8ca1 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.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_ts.c,v 1.123 2006/08/08 03:58:15 miguelfreitas Exp $ + * $Id: demux_ts.c,v 1.129 2007/04/02 10:46:08 dgp85 Exp $ * * Demultiplexer for MPEG2 Transport Streams. * @@ -254,7 +254,7 @@ typedef struct { } demux_ts_media; /* DVBSUB */ -#define MAX_NO_SPU_LANGS 16 +#define MAX_SPU_LANGS 16 typedef struct { spu_dvb_descriptor_t desc; @@ -262,6 +262,14 @@ typedef struct { int media_index; } demux_ts_spu_lang; +/* Audio Channels */ +#define MAX_AUDIO_TRACKS 16 + +typedef struct { + int pid; + int media_index; + char lang[4]; +} demux_ts_audio_track; typedef struct { /* @@ -299,10 +307,10 @@ typedef struct { unsigned int pid; unsigned int pid_count; unsigned int videoPid; - unsigned int audioPid; unsigned int videoMedia; - unsigned int audioMedia; - char audioLang[4]; + + demux_ts_audio_track audio_tracks[MAX_AUDIO_TRACKS]; + int audio_tracks_count; int send_end_buffers; int64_t last_pts[2]; @@ -319,8 +327,8 @@ typedef struct { /* DVBSUB */ unsigned int spu_pid; unsigned int spu_media; - demux_ts_spu_lang spu_langs[MAX_NO_SPU_LANGS]; - int no_spu_langs; + demux_ts_spu_lang spu_langs[MAX_SPU_LANGS]; + int spu_langs_count; int current_spu_channel; /* dvb */ @@ -457,7 +465,7 @@ static void demux_ts_update_spu_channel(demux_ts_t *this) buf->size = 0; if (this->current_spu_channel >= 0 - && this->current_spu_channel < this->no_spu_langs) + && this->current_spu_channel < this->spu_langs_count) { demux_ts_spu_lang *lang = &this->spu_langs[this->current_spu_channel]; @@ -627,7 +635,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt, /* force PMT reparsing when pmt_pid changes */ if (this->pmt_pid[program_count] != pmt_pid) { this->pmt_pid[program_count] = pmt_pid; - this->audioPid = INVALID_PID; + this->audio_tracks_count = 0; this->videoPid = INVALID_PID; this->spu_pid = INVALID_PID; } @@ -737,7 +745,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, (p[0] == 0x0B && p[1] == 0x77)) { /* ac3 - syncword */ m->content = p; m->size = packet_len; - m->type = BUF_AUDIO_A52; + m->type |= BUF_AUDIO_A52; return 1; } else if (m->descriptor_tag == 0x06 @@ -761,7 +769,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, m->content = p+4; m->size = packet_len - 4; - m->type = BUF_AUDIO_A52 + track; + m->type |= BUF_AUDIO_A52 + track; return 1; } else if ((p[0]&0xf0) == 0xa0) { @@ -777,7 +785,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, m->content = p+pcm_offset; m->size = packet_len-pcm_offset; - m->type = BUF_AUDIO_LPCM_BE + track; + m->type |= BUF_AUDIO_LPCM_BE + track; return 1; } @@ -818,16 +826,16 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m, case ISO_11172_AUDIO: case ISO_13818_AUDIO: lprintf ("demux_ts: found MPEG audio track.\n"); - m->type = BUF_AUDIO_MPEG + track; + m->type |= BUF_AUDIO_MPEG + track; break; case ISO_13818_PART7_AUDIO: case ISO_14496_PART3_AUDIO: lprintf ("demux_ts: found AAC audio track.\n"); - m->type = BUF_AUDIO_AAC + track; + m->type |= BUF_AUDIO_AAC + track; break; default: lprintf ("demux_ts: unknown audio type: %d, defaulting to MPEG.\n", m->descriptor_tag); - m->type = BUF_AUDIO_MPEG + track; + m->type |= BUF_AUDIO_MPEG + track; break; } return 1; @@ -1212,7 +1220,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num /* * Extract the elementary streams. */ - this->no_spu_langs = 0; + this->spu_langs_count = 0; while (section_length > 0) { unsigned int stream_info_length; @@ -1248,15 +1256,26 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num case ISO_13818_AUDIO: case ISO_13818_PART7_AUDIO: case ISO_14496_PART3_AUDIO: - if (this->audioPid == INVALID_PID) { + if (this->audio_tracks_count < MAX_AUDIO_TRACKS) { + int i, found = 0; + for(i = 0; i < this->audio_tracks_count; i++) { + if(this->audio_tracks[i].pid == pid) { + found = 1; + break; + } + } + if(!found) { #ifdef TS_PMT_LOG - printf ("demux_ts: PMT audio pid 0x%.4x\n", pid); + printf ("demux_ts: PMT audio pid 0x%.4x\n", pid); #endif - demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo,stream[0]); - this->audioPid = pid; - this->audioMedia = this->media_num; - demux_ts_get_lang_desc(this, this->audioLang, + demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo,stream[0]); + this->audio_tracks[this->audio_tracks_count].pid = pid; + this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; + this->media[this->media_num].type = this->audio_tracks_count; + demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang, stream + 5, stream_info_length); + this->audio_tracks_count++; + } } break; case ISO_13818_PRIVATE: @@ -1275,30 +1294,31 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num break; case ISO_13818_PES_PRIVATE: for (i = 5; i < coded_length; i += stream[i+1] + 2) { - if ((stream[i] == 0x6a) && (this->audioPid == INVALID_PID)) { + if ((stream[i] == 0x6a) && (this->audio_tracks_count < MAX_AUDIO_TRACKS)) { uint32_t format_identifier=0; + int i, found = 0; + for(i = 0; i < this->audio_tracks_count; i++) { + if(this->audio_tracks[i].pid == pid) { + found = 1; + break; + } + } + if(!found) { #ifdef TS_PMT_LOG - printf ("demux_ts: PMT AC3 audio pid 0x%.4x\n", pid); + printf ("demux_ts: PMT AC3 audio pid 0x%.4x\n", pid); #endif - demux_ts_get_reg_desc(this, &format_identifier, - stream + 5, stream_info_length); - if (format_identifier == 0x41432d33) /* AC-3 */ - demux_ts_pes_new(this, this->media_num, pid, - this->audio_fifo, 0x81); - else if((stream[i+1]>1) && (stream[i+2] & 0x80 ) && (stream[3] & 0x40)) /* AC3 Full Service */ - demux_ts_pes_new(this, this->media_num, pid, - this->audio_fifo, 0x81); - else - demux_ts_pes_new(this, this->media_num, pid, - this->audio_fifo,stream[0]); - - this->audioPid = pid; - this->audioMedia = this->media_num; - demux_ts_get_lang_desc(this, this->audioLang, - stream + 5, stream_info_length); + demux_ts_pes_new(this, this->media_num, pid, + this->audio_fifo, 0x81); + + this->audio_tracks[this->audio_tracks_count].pid = pid; + this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; + this->media[this->media_num].type = this->audio_tracks_count; + demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang, + stream + 5, stream_info_length); + this->audio_tracks_count++; break; + } } - /* Teletext */ else if (stream[i] == 0x56) { @@ -1318,13 +1338,13 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num int pos; for (pos = i + 2; pos + 8 <= i + 2 + stream[i + 1] - && this->no_spu_langs < MAX_NO_SPU_LANGS; + && this->spu_langs_count < MAX_SPU_LANGS; pos += 8) { - int no = this->no_spu_langs; + int no = this->spu_langs_count; demux_ts_spu_lang *lang = &this->spu_langs[no]; - this->no_spu_langs++; + this->spu_langs_count++; memcpy(lang->desc.lang, &stream[pos], 3); lang->desc.lang[3] = 0; @@ -1356,18 +1376,29 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num * if is does, we tag this as an audio stream. * FIXME: This will need expanding if we ever see a DTS or other media format here. */ - if (this->audioPid == INVALID_PID && (stream[0] >= 0x80) ) { - uint32_t format_identifier=0; - demux_ts_get_reg_desc(this, &format_identifier, - stream + 5, stream_info_length); - /* If no format identifier, assume A52 */ - if ((format_identifier == 0x41432d33) || (format_identifier == 0)) { - demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo, stream[0]); - this->audioPid = pid; - this->audioMedia = this->media_num; - demux_ts_get_lang_desc(this, this->audioLang, - stream + 5, stream_info_length); - break; + if ((this->audio_tracks_count < MAX_AUDIO_TRACKS) && (stream[0] >= 0x80) ) { + int i, found = 0; + for(i = 0; i < this->audio_tracks_count; i++) { + if(this->audio_tracks[i].pid == pid) { + found = 1; + break; + } + } + if(!found) { + uint32_t format_identifier=0; + demux_ts_get_reg_desc(this, &format_identifier, + stream + 5, stream_info_length); + /* If no format identifier, assume A52 */ + if ((format_identifier == 0x41432d33) || (format_identifier == 0)) { + demux_ts_pes_new(this, this->media_num, pid, this->audio_fifo, stream[0]); + this->audio_tracks[this->audio_tracks_count].pid = pid; + this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; + this->media[this->media_num].type = this->audio_tracks_count; + demux_ts_get_lang_desc(this, this->audio_tracks[this->audio_tracks_count].lang, + stream + 5, stream_info_length); + this->audio_tracks_count++; + break; + } } } else { #ifdef TS_PMT_LOG @@ -1612,6 +1643,16 @@ static int64_t demux_ts_adaptation_field_parse(uint8_t *data, return PCR; } +/* check if an apid is in the list of known apids */ +static int apid_check(demux_ts_t*this, unsigned int pid) { + int i; + for(i=0; i<this->audio_tracks_count; i++) { + if(this->audio_tracks[i].pid == pid) + return i; + } + return -1; +} + /* transport stream packet layer */ static void demux_ts_parse_packet (demux_ts_t*this) { @@ -1753,15 +1794,27 @@ static void demux_ts_parse_packet (demux_ts_t*this) { demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, pes_stream_id); } } else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) ) { - if ( this->audioPid == INVALID_PID) { - - xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, - "demux_ts: auto-detected audio pid 0x%.4x\n", pid); - - this->audioPid = pid; - this->audioMedia = this->media_num; - demux_ts_pes_new(this, this->media_num++, pid, this->audio_fifo, pes_stream_id); - } + if (this->audio_tracks_count < MAX_AUDIO_TRACKS) { + int i, found = 0; + for(i = 0; i < this->audio_tracks_count; i++) { + if(this->audio_tracks[i].pid == pid) { + found = 1; + break; + } + } + if(!found) { +#ifdef TS_PMT_LOG + xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, + "demux_ts: auto-detected audio pid 0x%.4x\n", pid); +#endif + this->audio_tracks[this->audio_tracks_count].pid = pid; + this->audio_tracks[this->audio_tracks_count].media_index = this->media_num; + this->media[this->media_num].type = this->audio_tracks_count; + demux_ts_pes_new(this, this->media_num++, pid, + this->audio_fifo,pes_stream_id); + this->audio_tracks_count++; + } + } } } @@ -1775,6 +1828,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) { /* * Do the demuxing in descending order of packet frequency! */ + int index; if (pid == this->videoPid) { #ifdef TS_LOG printf ("demux_ts: Video pid: 0x%.4x\n", pid); @@ -1785,12 +1839,13 @@ static void demux_ts_parse_packet (demux_ts_t*this) { data_len); return; } - else if (pid == this->audioPid) { + else if ((index = apid_check(this, pid)) > -1) { #ifdef TS_LOG printf ("demux_ts: Audio pid: 0x%.4x\n", pid); #endif - check_newpts(this, this->media[this->audioMedia].pts, PTS_AUDIO); - demux_ts_buffer_pes (this, originalPkt+data_offset, this->audioMedia, + check_newpts(this, this->media[this->audio_tracks[index].media_index].pts, PTS_AUDIO); + demux_ts_buffer_pes (this, originalPkt+data_offset, + this->audio_tracks[index].media_index, payload_unit_start_indicator, continuity_counter, data_len); return; @@ -1830,12 +1885,12 @@ static void demux_ts_event_handler (demux_ts_t *this) { case XINE_EVENT_PIDS_CHANGE: this->videoPid = INVALID_PID; - this->audioPid = INVALID_PID; + this->audio_tracks_count = 0; this->media_num = 0; this->send_newpts = 1; this->spu_pid = INVALID_PID; this->spu_media = 0; - this->no_spu_langs= 0; + this->spu_langs_count= 0; _x_demux_control_start (this->stream); break; @@ -1909,7 +1964,7 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) { */ this->videoPid = INVALID_PID; - this->audioPid = INVALID_PID; + this->audio_tracks_count = 0; this->media_num= 0; _x_demux_control_start (this->stream); @@ -1927,7 +1982,7 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) { /* DVBSUB */ this->spu_pid = INVALID_PID; - this->no_spu_langs = 0; + this->spu_langs_count = 0; this->current_spu_channel = this->stream->spu_channel; /* FIXME ? */ @@ -2005,6 +2060,8 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, { demux_ts_t *this = (demux_ts_t *) this_gen; char *str = data; + int channel = *((int *)data); + int track_num; /* be a bit paranoid */ if (this == NULL || this->stream == NULL) @@ -2013,22 +2070,24 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, switch (data_type) { case DEMUX_OPTIONAL_DATA_AUDIOLANG: - if (this->audioLang[0]) - { - strcpy(str, this->audioLang); - } + if ((channel >= 0) && (channel < this->audio_tracks_count)) { + if(this->audio_tracks[channel].lang) + strcpy(str, this->audio_tracks[channel].lang); + else + sprintf(str, "%3i", _x_get_audio_channel(this->stream)); + } else { - sprintf(str, "%3i", _x_get_audio_channel(this->stream)); + snprintf(str, XINE_LANG_MAX, "%3i", _x_get_audio_channel(this->stream)); } return DEMUX_OPTIONAL_SUCCESS; case DEMUX_OPTIONAL_DATA_SPULANG: if (this->current_spu_channel >= 0 - && this->current_spu_channel < this->no_spu_langs) + && this->current_spu_channel < this->spu_langs_count) { memcpy(str, this->spu_langs[this->current_spu_channel].desc.lang, 3); - str[4] = 0; + str[3] = 0; } else if (this->current_spu_channel == -1) { @@ -2036,7 +2095,7 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen, } else { - sprintf(str, "%3i", this->current_spu_channel); + snprintf(str, XINE_LANG_MAX, "%3i", this->current_spu_channel); } return DEMUX_OPTIONAL_SUCCESS; @@ -2089,12 +2148,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, break; case METHOD_BY_EXTENSION: { - char *extensions, *mrl; - - mrl = input->get_mrl (input); + const char *const mrl = input->get_mrl (input); /* check extension */ - extensions = class_gen->get_extensions (class_gen); + const char *const extensions = class_gen->get_extensions (class_gen); if (_x_demux_check_extension (mrl, extensions)) break; @@ -2163,7 +2220,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->pcrPid = INVALID_PID; this->scrambled_npids = 0; this->videoPid = INVALID_PID; - this->audioPid = INVALID_PID; + this->audio_tracks_count = 0; this->rate = 16000; /* FIXME */ @@ -2177,7 +2234,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, /* DVBSUB */ this->spu_pid = INVALID_PID; - this->no_spu_langs = 0; + this->spu_langs_count = 0; this->current_spu_channel = this->stream->spu_channel; /* dvb */ @@ -2190,19 +2247,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, * ts demuxer class */ -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "MPEG Transport Stream demuxer"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "MPEG_TS"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "ts m2t trp"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c new file mode 100644 index 000000000..2e4808b9c --- /dev/null +++ b/src/demuxers/demux_tta.c @@ -0,0 +1,322 @@ +/* + * Copyright (C) 2006 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * True Audio demuxer by Diego Pettenò <flameeyes@gentoo.org> + * Inspired by tta libavformat demuxer by Alex Beregszaszi + * + * $Id: demux_tta.c,v 1.4 2007/03/29 16:46:23 dgp85 Exp $ + */ + +#define LOG_MODULE "demux_tta" +#define LOG_VERBOSE + +#include "xine_internal.h" +#include "xineutils.h" +#include "demux.h" +#include "buffer.h" +#include "bswap.h" +#include "group_audio.h" + +typedef struct { + demux_plugin_t demux_plugin; + + xine_stream_t *stream; + fifo_buffer_t *video_fifo; + fifo_buffer_t *audio_fifo; + input_plugin_t *input; + + uint32_t *seektable; + uint32_t totalframes; + uint32_t currentframe; + + int status; + + union { + struct tta_header { + uint32_t signature; /* TTA1 */ + uint16_t flags; /* Skipped */ + uint16_t channels; + uint16_t bits_per_sample; + uint32_t samplerate; + uint32_t data_length; + uint32_t crc32; + } __attribute__((__packed__)) tta; + uint8_t buffer[22]; /* This is the size of the header */ + } header; +} demux_tta_t; + +typedef struct { + demux_class_t demux_class; +} demux_tta_class_t; + +#define FOURCC_32(a, b, c, d) (d + (c<<8) + (b<<16) + (a<<24)) + +static int open_tta_file(demux_tta_t *this) { + uint8_t peek[4]; + uint32_t framelen; + + if (_x_demux_read_header(this->input, peek, 4) != 4) + return 0; + + if ( BE_32(peek) != FOURCC_32('T', 'T', 'A', '1') ) + return 0; + + if ( this->input->read(this->input, this->header.buffer, sizeof(this->header)) != sizeof(this->header) ) + return 0; + + framelen = 1.04489795918367346939 * le2me_32(this->header.tta.samplerate); + this->totalframes = le2me_32(this->header.tta.data_length) / framelen + ((le2me_32(this->header.tta.data_length) % framelen) ? 1 : 0); + this->currentframe = 0; + + if(this->totalframes >= UINT_MAX/sizeof(uint32_t)) { + xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, _("demux_tta: total frames count too high\n")); + return 0; + } + + this->seektable = xine_xmalloc(sizeof(uint32_t)*this->totalframes); + this->input->read(this->input, this->seektable, sizeof(uint32_t)*this->totalframes); + + /* Skip the CRC32 */ + this->input->seek(this->input, 4, SEEK_CUR); + + return 1; +} + +static int demux_tta_send_chunk(demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + uint32_t bytes_to_read; + + if ( this->currentframe > this->totalframes ) { + this->status = DEMUX_FINISHED; + return this->status; + } + + bytes_to_read = le2me_32(this->seektable[this->currentframe]); + + while(bytes_to_read) { + off_t bytes_read = 0; + buf_element_t *buf = NULL; + + /* Get a buffer */ + buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo); + buf->type = BUF_AUDIO_TTA; + buf->pts = 0; + buf->extra_info->total_time = this->totalframes; + buf->decoder_flags = 0; + + /* Set normalised position */ + buf->extra_info->input_normpos = + (int) ((double) this->currentframe * 65535 / this->totalframes); + + /* Set time */ + /* buf->extra_info->input_time = this->current_sample / this->samplerate; */ + + bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read); + + buf->size = bytes_read; + + bytes_to_read -= bytes_read; + + if ( bytes_to_read <= 0 ) + buf->decoder_flags |= BUF_FLAG_FRAME_END; + + this->audio_fifo->put(this->audio_fifo, buf); + } + + this->currentframe++; + + return this->status; +} + +static void demux_tta_send_headers(demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + buf_element_t *buf; + + this->audio_fifo = this->stream->audio_fifo; + + this->status = DEMUX_OK; + + _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, + le2me_16(this->header.tta.channels)); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, + le2me_32(this->header.tta.samplerate)); + _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS, + le2me_16(this->header.tta.bits_per_sample)); + + /* send start buffers */ + _x_demux_control_start(this->stream); + + /* send init info to decoders */ + if (this->audio_fifo) { + xine_waveformatex wave; + + buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo); + buf->type = BUF_AUDIO_TTA; + buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = le2me_32(this->header.tta.samplerate); + buf->decoder_info[2] = le2me_16(this->header.tta.bits_per_sample); + buf->decoder_info[3] = le2me_16(this->header.tta.channels); + + buf->size = sizeof(xine_waveformatex) + sizeof(this->header) + sizeof(uint32_t)*this->totalframes; + memcpy(buf->content+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header)); + memcpy(buf->content+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes); + + wave.cbSize = buf->size - sizeof(xine_waveformatex); + memcpy(buf->content, &wave, sizeof(wave)); + + this->audio_fifo->put (this->audio_fifo, buf); + } +} + +static int demux_tta_seek (demux_plugin_t *this_gen, + off_t start_pos, int start_time, int playing) { + demux_tta_t *this = (demux_tta_t *) this_gen; + + /* if thread is not running, initialize demuxer */ + if( !playing ) { + + /* send new pts */ + _x_demux_control_newpts(this->stream, 0, 0); + + this->status = DEMUX_OK; + } + + return this->status; +} + +static void demux_tta_dispose (demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + + free(this); +} + +static int demux_tta_get_status (demux_plugin_t *this_gen) { + demux_tta_t *this = (demux_tta_t *) this_gen; + + return this->status; +} + +static int demux_tta_get_stream_length (demux_plugin_t *this_gen) { +// demux_tta_t *this = (demux_tta_t *) this_gen; + + return 0; +} + +static uint32_t demux_tta_get_capabilities(demux_plugin_t *this_gen) { + return DEMUX_CAP_NOCAP; +} + +static int demux_tta_get_optional_data(demux_plugin_t *this_gen, + void *data, int data_type) { + return DEMUX_OPTIONAL_UNSUPPORTED; +} + +static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream, + input_plugin_t *input) { + + demux_tta_t *this; + + this = xine_xmalloc (sizeof (demux_tta_t)); + this->stream = stream; + this->input = input; + + this->demux_plugin.send_headers = demux_tta_send_headers; + this->demux_plugin.send_chunk = demux_tta_send_chunk; + this->demux_plugin.seek = demux_tta_seek; + this->demux_plugin.dispose = demux_tta_dispose; + this->demux_plugin.get_status = demux_tta_get_status; + this->demux_plugin.get_stream_length = demux_tta_get_stream_length; + this->demux_plugin.get_capabilities = demux_tta_get_capabilities; + this->demux_plugin.get_optional_data = demux_tta_get_optional_data; + this->demux_plugin.demux_class = class_gen; + + this->status = DEMUX_FINISHED; + + this->seektable = NULL; + + switch (stream->content_detection_method) { + + case METHOD_BY_EXTENSION: { + const char *extensions, *mrl; + + mrl = input->get_mrl (input); + extensions = class_gen->get_extensions (class_gen); + + if (!_x_demux_check_extension (mrl, extensions)) { + free (this); + return NULL; + } + } + /* Falling through is intended */ + + case METHOD_BY_CONTENT: + case METHOD_EXPLICIT: + if (!open_tta_file(this)) { + free (this); + return NULL; + } + break; + + default: + free (this); + return NULL; + } + + return &this->demux_plugin; +} + +static const char *get_description (demux_class_t *this_gen) { + return "True Audio demux plugin"; +} + +static const char *get_identifier (demux_class_t *this_gen) { + return "True Audio"; +} + +static const char *get_extensions (demux_class_t *this_gen) { + return "tta"; +} + +static const char *get_mimetypes (demux_class_t *this_gen) { + return NULL; +} + +static void class_dispose (demux_class_t *this_gen) { + demux_tta_class_t *this = (demux_tta_class_t *) this_gen; + + free (this); +} + +void *demux_tta_init_plugin (xine_t *xine, void *data) { + demux_tta_class_t *this; + + this = xine_xmalloc (sizeof (demux_tta_class_t)); + + 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 this; +} diff --git a/src/demuxers/demux_vmd.c b/src/demuxers/demux_vmd.c index fb7174031..e2b68fbb1 100644 --- a/src/demuxers/demux_vmd.c +++ b/src/demuxers/demux_vmd.c @@ -28,7 +28,7 @@ * checking the first 2 bytes, which are 0x2E 0x03 in a Sierra VMD file. * There is a 1/65536 chance of a false positive using this method. * - * $Id: demux_vmd.c,v 1.3 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_vmd.c,v 1.4 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -442,7 +442,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -472,19 +472,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Sierra VMD file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "VMD"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "vmd"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_voc.c b/src/demuxers/demux_voc.c index cfd67a9e6..1c1675b92 100644 --- a/src/demuxers/demux_voc.c +++ b/src/demuxers/demux_voc.c @@ -25,7 +25,7 @@ * It will only play that block if it is PCM data. More variations will be * supported as they are encountered. * - * $Id: demux_voc.c,v 1.40 2005/12/24 00:08:42 tmmm Exp $ + * $Id: demux_voc.c,v 1.41 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -317,7 +317,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -347,19 +347,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "VOC file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "VOC"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "voc"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_vox.c b/src/demuxers/demux_vox.c index 53e8d2399..c772e4978 100644 --- a/src/demuxers/demux_vox.c +++ b/src/demuxers/demux_vox.c @@ -22,7 +22,7 @@ * VOX Demuxer by Mike Melanson (melanson@pcisys.net) * This a demuxer for .vox files containing raw Dialogic ADPCM data. * - * $Id: demux_vox.c,v 1.13 2004/06/13 21:28:54 miguelfreitas Exp $ + * $Id: demux_vox.c,v 1.14 2007/01/19 00:26:40 dgp85 Exp $ * */ @@ -192,7 +192,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str case METHOD_BY_CONTENT: case METHOD_EXPLICIT: case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -225,19 +225,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Dialogic VOX file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "VOX"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "vox"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_vqa.c b/src/demuxers/demux_vqa.c index 41209ce75..56fbde7d1 100644 --- a/src/demuxers/demux_vqa.c +++ b/src/demuxers/demux_vqa.c @@ -29,7 +29,7 @@ * block needs information from the previous audio block in order to be * decoded, thus making random seeking difficult. * - * $Id: demux_vqa.c,v 1.41 2004/06/13 21:28:55 miguelfreitas Exp $ + * $Id: demux_vqa.c,v 1.42 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -355,7 +355,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -385,19 +385,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Westwood Studios VQA file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "VQA"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "vqa"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c index e23f43aa5..1e46d8526 100644 --- a/src/demuxers/demux_wav.c +++ b/src/demuxers/demux_wav.c @@ -22,7 +22,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.63 2005/06/04 20:29:16 jstembridge Exp $ + * $Id: demux_wav.c,v 1.65 2007/03/17 20:57:04 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -86,18 +86,7 @@ static int open_wav_file(demux_wav_t *this) { if (_x_demux_read_header(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] != ' ')) + if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVEfmt ", 8) ) return 0; /* file is qualified; skip over the header bytes in the stream */ @@ -108,7 +97,7 @@ static int open_wav_file(demux_wav_t *this) { (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 ); + this->wave = xine_xmalloc( this->wave_size ); if (this->input->read(this->input, (void *)this->wave, this->wave_size) != this->wave_size) { @@ -365,7 +354,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -404,19 +393,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "WAV file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "WAV"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "wav"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return "audio/x-wav: wav: WAV audio;" "audio/wav: wav: WAV audio;" "audio/x-pn-wav: wav: WAV audio;" diff --git a/src/demuxers/demux_wc3movie.c b/src/demuxers/demux_wc3movie.c index a41637ba1..fa1cfb17d 100644 --- a/src/demuxers/demux_wc3movie.c +++ b/src/demuxers/demux_wc3movie.c @@ -24,7 +24,7 @@ * For more information on the MVE file format, visit: * http://www.pcisys.net/~melanson/codecs/ * - * $Id: demux_wc3movie.c,v 1.53 2005/07/26 22:10:40 tmattern Exp $ + * $Id: demux_wc3movie.c,v 1.54 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -688,7 +688,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -718,19 +718,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "Wing Commander III Movie (MVE) demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "WC3 Movie"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "mve"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_yuv4mpeg2.c b/src/demuxers/demux_yuv4mpeg2.c index 126370453..4e0bb1069 100644 --- a/src/demuxers/demux_yuv4mpeg2.c +++ b/src/demuxers/demux_yuv4mpeg2.c @@ -24,7 +24,7 @@ * tools, visit: * http://mjpeg.sourceforge.net/ * - * $Id: demux_yuv4mpeg2.c,v 1.43 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_yuv4mpeg2.c,v 1.44 2007/01/19 00:26:40 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -424,7 +424,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str switch (stream->content_detection_method) { case METHOD_BY_EXTENSION: { - char *extensions, *mrl; + const char *extensions, *mrl; mrl = input->get_mrl (input); extensions = class_gen->get_extensions (class_gen); @@ -454,19 +454,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str return &this->demux_plugin; } -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "YUV4MPEG2 file demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "YUV4MPEG2"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return "y4m"; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/demux_yuv_frames.c b/src/demuxers/demux_yuv_frames.c index 06115a4d3..3866f0437 100644 --- a/src/demuxers/demux_yuv_frames.c +++ b/src/demuxers/demux_yuv_frames.c @@ -20,7 +20,7 @@ */ /* - * $Id: demux_yuv_frames.c,v 1.22 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: demux_yuv_frames.c,v 1.24 2007/01/19 01:05:24 dgp85 Exp $ * * dummy demultiplexer for raw yuv frames (delivered by v4l) */ @@ -185,9 +185,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, break; case METHOD_BY_EXTENSION: { - char *mrl; - - mrl = input->get_mrl (input); + const char *const mrl = input->get_mrl (input); if (strncmp (mrl, "v4l:/", 5)) return NULL; @@ -232,19 +230,19 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, * demuxer class */ -static char *get_description (demux_class_t *this_gen) { +static const char *get_description (demux_class_t *this_gen) { return "YUV frames dummy demux plugin"; } -static char *get_identifier (demux_class_t *this_gen) { +static const char *get_identifier (demux_class_t *this_gen) { return "YUV_FRAMES"; } -static char *get_extensions (demux_class_t *this_gen) { +static const char *get_extensions (demux_class_t *this_gen) { return NULL; } -static char *get_mimetypes (demux_class_t *this_gen) { +static const char *get_mimetypes (demux_class_t *this_gen) { return NULL; } diff --git a/src/demuxers/group_audio.c b/src/demuxers/group_audio.c index 7139ee5b9..b8f0e1ed4 100644 --- a/src/demuxers/group_audio.c +++ b/src/demuxers/group_audio.c @@ -19,7 +19,7 @@ * * This file contains plugin entries for several demuxers used in games * - * $Id: group_audio.c,v 1.24 2006/07/10 22:08:13 dgp85 Exp $ + * $Id: group_audio.c,v 1.26 2007/03/03 02:06:09 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -36,7 +36,7 @@ */ static const demuxer_info_t demux_info_aac = { - 0 /* priority */ + -1 /* priority */ }; static const demuxer_info_t demux_info_ac3 = { @@ -87,6 +87,10 @@ static const demuxer_info_t demux_info_snd = { 10 /* priority */ }; +static const demuxer_info_t demux_info_tta = { + 10 /* priority */ +}; + static const demuxer_info_t demux_info_voc = { 10 /* priority */ }; @@ -120,6 +124,7 @@ const plugin_info_t xine_plugin_info[] EXPORTED = { { PLUGIN_DEMUX, 26, "realaudio", XINE_VERSION_CODE, &demux_info_realaudio, demux_realaudio_init_plugin }, { PLUGIN_DEMUX, 26, "shn", XINE_VERSION_CODE, &demux_info_shn, demux_shn_init_plugin }, { PLUGIN_DEMUX, 26, "snd", XINE_VERSION_CODE, &demux_info_snd, demux_snd_init_plugin }, + { PLUGIN_DEMUX, 26, "tta", XINE_VERSION_CODE, &demux_info_tta, demux_tta_init_plugin }, { PLUGIN_DEMUX, 26, "voc", XINE_VERSION_CODE, &demux_info_voc, demux_voc_init_plugin }, { PLUGIN_DEMUX, 26, "vox", XINE_VERSION_CODE, &demux_info_vox, demux_vox_init_plugin }, { PLUGIN_DEMUX, 26, "wav", XINE_VERSION_CODE, &demux_info_wav, demux_wav_init_plugin }, diff --git a/src/demuxers/group_audio.h b/src/demuxers/group_audio.h index fba22cffa..7f1fccc5e 100644 --- a/src/demuxers/group_audio.h +++ b/src/demuxers/group_audio.h @@ -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: group_audio.h,v 1.8 2005/05/29 19:20:48 jstembridge Exp $ + * $Id: group_audio.h,v 1.9 2006/12/26 16:59:55 dgp85 Exp $ */ #ifndef HAVE_GROUP_AUDIO_H @@ -38,6 +38,7 @@ void *demux_nsf_init_plugin (xine_t *xine, void *data); void *demux_realaudio_init_plugin (xine_t *xine, void *data); void *demux_shn_init_plugin (xine_t *xine, void *data); void *demux_snd_init_plugin (xine_t *xine, void *data); +void *demux_tta_init_plugin (xine_t *xine, void *data); void *demux_voc_init_plugin (xine_t *xine, void *data); void *demux_vox_init_plugin (xine_t *xine, void *data); void *demux_wav_init_plugin (xine_t *xine, void *data); diff --git a/src/demuxers/id3.c b/src/demuxers/id3.c index ffa022a59..b707166b6 100644 --- a/src/demuxers/id3.c +++ b/src/demuxers/id3.c @@ -29,7 +29,7 @@ * * ID3v2 specs: http://www.id3.org/ * - * $Id: id3.c,v 1.12 2006/04/05 22:12:18 valtri Exp $ + * $Id: id3.c,v 1.13 2007/03/03 00:58:52 dgp85 Exp $ */ #ifdef HAVE_CONFIG_H @@ -878,3 +878,33 @@ int id3v24_parse_tag(input_plugin_t *input, return 0; } } + +int id3v2_parse_tag(input_plugin_t *input, + xine_stream_t *stream, + int8_t *mp3_frame_header) { + _x_assert(mp3_frame_header[0] == 'I' && mp3_frame_header[1] == 'D' && mp3_frame_header[2] == '3'); + + int result = 0; + + switch(mp3_frame_header[3]) { + case 2: + xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.2 tag\n"); + result = id3v22_parse_tag(input, stream, mp3_frame_header); + break; + + case 3: + xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.3 tag\n"); + result = id3v23_parse_tag(input, stream, mp3_frame_header); + break; + + case 4: + xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.3 tag\n"); + result = id3v24_parse_tag(input, stream, mp3_frame_header); + break; + + default: + xprintf(stream->xine, XINE_VERBOSITY_LOG, "Unknown ID3v2 version: 0x%02x.\n", mp3_frame_header[3]); + } + + return result; +} diff --git a/src/demuxers/id3.h b/src/demuxers/id3.h index 2d8970ea7..9d08f6817 100644 --- a/src/demuxers/id3.h +++ b/src/demuxers/id3.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2003 the xine project + * Copyright (C) 2000-2007 the xine project * * This file is part of xine, a free video player. * @@ -21,7 +21,7 @@ * * Supported versions: v1, v1.1, v2.2, v2.3, v2.4 * - * $Id: id3.h,v 1.4 2005/09/15 18:45:15 tmattern Exp $ + * $Id: id3.h,v 1.6 2007/03/03 01:41:16 dgp85 Exp $ */ #ifndef ID3_H @@ -38,6 +38,7 @@ #define ID3V24_TAG FOURCC_TAG('I', 'D', '3', 4) /* id3 v2.4 header tag */ #define ID3V24_FOOTER_TAG FOURCC_TAG('3', 'D', 'I', 0) /* id3 v2.4 footer tag */ + /* * ID3 v2.2 */ @@ -164,4 +165,24 @@ int id3v24_parse_tag(input_plugin_t *input, xine_stream_t *stream, int8_t *mp3_frame_header); +/* Generic function that switch between the three above */ +int id3v2_parse_tag(input_plugin_t *input, + xine_stream_t *stream, + int8_t *mp3_frame_header); + +static inline int id3v2_istag(uint8_t *ptr) { + return + (ptr[0] == 'I') && + (ptr[1] == 'D') && + (ptr[2] == '3'); +} + +static inline uint32_t id3v2_tagsize(uint8_t *ptr) { + return + ((uint32_t)ptr[0] << 21) + + ((uint32_t)ptr[1] << 14) + + ((uint32_t)ptr[2] << 7) + + (uint32_t)ptr[3]; +} + #endif /* ID3_H */ diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h index 926d6d0a6..3bfdbdc0c 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2003 the xine project + * Copyright (C) 2000-2007 the xine project * * This file is part of xine, a free video player. * @@ -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: matroska.h,v 1.10 2006/11/14 07:09:46 molivier Exp $ + * $Id: matroska.h,v 1.11 2007/01/07 12:33:50 molivier Exp $ * */ #ifndef MATROSKA_H @@ -224,6 +224,7 @@ struct matroska_track_s { uint8_t *codec_private; uint32_t codec_private_len; int default_flag; + uint32_t compress_algo; uint32_t buf_type; fifo_buffer_t *fifo; @@ -305,4 +306,12 @@ struct matroska_track_s { #define MATROSKA_TRACK_SUBTITLE 0x11 #define MATROSKA_TRACK_CONTROL 0x20 +/* compression algorithms */ +#define MATROSKA_COMPRESS_ZLIB 0x00 +#define MATROSKA_COMPRESS_BZLIB 0x01 +#define MATROSKA_COMPRESS_LZO1X 0x02 +#define MATROSKA_COMPRESS_HEADER_STRIP 0x03 +#define MATROSKA_COMPRESS_UNKNOWN 0xFFFFFFFE /* Xine internal type */ +#define MATROSKA_COMPRESS_NONE 0xFFFFFFFF /* Xine internal type */ + #endif /* MATROSKA_H */ |