summaryrefslogtreecommitdiff
path: root/src/demuxers
diff options
context:
space:
mode:
Diffstat (limited to 'src/demuxers')
-rw-r--r--src/demuxers/Makefile.am17
-rw-r--r--src/demuxers/asfheader.c92
-rw-r--r--src/demuxers/asfheader.h3
-rw-r--r--src/demuxers/demux.h34
-rw-r--r--src/demuxers/demux_4xm.c69
-rw-r--r--src/demuxers/demux_aac.c17
-rw-r--r--src/demuxers/demux_ac3.c19
-rw-r--r--src/demuxers/demux_aiff.c49
-rw-r--r--src/demuxers/demux_asf.c236
-rw-r--r--src/demuxers/demux_aud.c8
-rw-r--r--src/demuxers/demux_avi.c144
-rw-r--r--src/demuxers/demux_cdda.c22
-rw-r--r--src/demuxers/demux_dts.c97
-rw-r--r--src/demuxers/demux_eawve.c36
-rw-r--r--src/demuxers/demux_elem.c20
-rw-r--r--src/demuxers/demux_film.c55
-rw-r--r--src/demuxers/demux_flac.c95
-rw-r--r--src/demuxers/demux_fli.c10
-rw-r--r--src/demuxers/demux_flv.c408
-rw-r--r--src/demuxers/demux_idcin.c10
-rw-r--r--src/demuxers/demux_iff.c38
-rw-r--r--src/demuxers/demux_image.c18
-rw-r--r--src/demuxers/demux_ipmovie.c27
-rw-r--r--src/demuxers/demux_matroska-chapters.c433
-rw-r--r--src/demuxers/demux_matroska.c844
-rw-r--r--src/demuxers/demux_matroska.h150
-rw-r--r--src/demuxers/demux_mng.c20
-rw-r--r--src/demuxers/demux_mod.c77
-rw-r--r--src/demuxers/demux_mpc.c106
-rw-r--r--src/demuxers/demux_mpeg.c112
-rw-r--r--src/demuxers/demux_mpeg_block.c237
-rw-r--r--src/demuxers/demux_mpeg_pes.c250
-rw-r--r--src/demuxers/demux_mpgaudio.c400
-rw-r--r--src/demuxers/demux_nsf.c22
-rw-r--r--src/demuxers/demux_nsv.c77
-rw-r--r--src/demuxers/demux_ogg.c215
-rw-r--r--src/demuxers/demux_pva.c14
-rw-r--r--src/demuxers/demux_qt.c378
-rw-r--r--src/demuxers/demux_rawdv.c40
-rw-r--r--src/demuxers/demux_real.c1094
-rw-r--r--src/demuxers/demux_realaudio.c219
-rw-r--r--src/demuxers/demux_roq.c28
-rw-r--r--src/demuxers/demux_shn.c10
-rw-r--r--src/demuxers/demux_slave.c29
-rw-r--r--src/demuxers/demux_smjpeg.c26
-rw-r--r--src/demuxers/demux_snd.c26
-rw-r--r--src/demuxers/demux_str.c49
-rw-r--r--src/demuxers/demux_ts.c515
-rw-r--r--src/demuxers/demux_tta.c132
-rw-r--r--src/demuxers/demux_vmd.c18
-rw-r--r--src/demuxers/demux_voc.c14
-rw-r--r--src/demuxers/demux_vox.c10
-rw-r--r--src/demuxers/demux_vqa.c12
-rw-r--r--src/demuxers/demux_wav.c115
-rw-r--r--src/demuxers/demux_wc3movie.c61
-rw-r--r--src/demuxers/demux_yuv4mpeg2.c114
-rw-r--r--src/demuxers/demux_yuv_frames.c39
-rw-r--r--src/demuxers/ebml.c52
-rw-r--r--src/demuxers/ebml.h8
-rw-r--r--src/demuxers/group_audio.c2
-rw-r--r--src/demuxers/group_audio.h10
-rw-r--r--src/demuxers/group_games.c2
-rw-r--r--src/demuxers/group_games.h10
-rw-r--r--src/demuxers/id3.c176
-rw-r--r--src/demuxers/id3.h35
-rw-r--r--src/demuxers/iff.h4
-rw-r--r--src/demuxers/matroska.h58
-rw-r--r--src/demuxers/qtpalette.h4
-rw-r--r--src/demuxers/real_common.h56
69 files changed, 4860 insertions, 2967 deletions
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am
index ffbfa0a8d..027f6750f 100644
--- a/src/demuxers/Makefile.am
+++ b/src/demuxers/Makefile.am
@@ -1,3 +1,4 @@
+include $(top_builddir)/misc/Makefile.plugins
include $(top_srcdir)/misc/Makefile.common
AM_CFLAGS = $(VISIBILITY_FLAG)
@@ -8,7 +9,7 @@ ogg_module = xineplug_dmx_ogg.la
endif
if BUILD_ASF
-asf_module = xineplug_dmx_asf.la
+asf_module = xineplug_dmx_asf.la
endif
if BUILD_NOSEFART
@@ -48,7 +49,7 @@ xineplug_LTLIBRARIES = $(ogg_module) $(asf_module) $(mng_module) $(image_module)
xineplug_dmx_nsv.la \
xineplug_dmx_matroska.la \
xineplug_dmx_iff.la \
- xineplug_dmx_flv.la
+ xineplug_dmx_flv.la
xineplug_dmx_ogg_la_SOURCES = demux_ogg.c
xineplug_dmx_ogg_la_LIBADD = $(XINE_LIB) $(VORBIS_LIBS) $(SPEEX_LIBS) $(THEORA_LIBS) $(OGG_LIBS) $(LTLIBINTL)
@@ -61,7 +62,7 @@ xineplug_dmx_mpeg_block_la_SOURCES = demux_mpeg_block.c
xineplug_dmx_mpeg_block_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
xineplug_dmx_mpeg_la_SOURCES = demux_mpeg.c
-xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB)
+xineplug_dmx_mpeg_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
xineplug_dmx_mpeg_elem_la_SOURCES = demux_elem.c
xineplug_dmx_mpeg_elem_la_LIBADD = $(XINE_LIB)
@@ -70,10 +71,10 @@ xineplug_dmx_mpeg_pes_la_SOURCES = demux_mpeg_pes.c
xineplug_dmx_mpeg_pes_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
xineplug_dmx_mpeg_ts_la_SOURCES = demux_ts.c
-xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB)
+xineplug_dmx_mpeg_ts_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
xineplug_dmx_qt_la_SOURCES = demux_qt.c
-xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS)
+xineplug_dmx_qt_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(LTLIBINTL)
xineplug_dmx_qt_la_CPPFLAGS = $(ZLIB_CPPFLAGS)
xineplug_dmx_asf_la_SOURCES = demux_asf.c asfheader.c
@@ -129,8 +130,8 @@ xineplug_dmx_image_la_LIBADD = $(XINE_LIB)
xineplug_dmx_nsv_la_SOURCES = demux_nsv.c
xineplug_dmx_nsv_la_LIBADD = $(XINE_LIB)
-xineplug_dmx_matroska_la_SOURCES = demux_matroska.c ebml.c
-xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS)
+xineplug_dmx_matroska_la_SOURCES = demux_matroska.c demux_matroska-chapters.c ebml.c
+xineplug_dmx_matroska_la_LIBADD = $(XINE_LIB) $(ZLIB_LIBS) $(LTLIBINTL)
xineplug_dmx_matroska_la_CPPFLAGS = $(ZLIB_CPPFLAGS)
xineplug_dmx_matroska_la_CFLAGS = $(AM_CFLAGS) -fno-strict-aliasing
@@ -141,4 +142,4 @@ xineplug_dmx_flv_la_SOURCES = demux_flv.c
xineplug_dmx_flv_la_LIBADD = $(XINE_LIB) $(LTLIBINTL)
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
+noinst_HEADERS = asfheader.h qtpalette.h group_games.h group_audio.h id3.h ebml.h matroska.h demux_matroska.h iff.h flacutils.h real_common.h
diff --git a/src/demuxers/asfheader.c b/src/demuxers/asfheader.c
index ea92f878b..e9a36fc29 100644
--- a/src/demuxers/asfheader.c
+++ b/src/demuxers/asfheader.c
@@ -142,9 +142,9 @@ static uint8_t *asf_reader_get_bytes(asf_reader_t *reader, size_t size) {
static char *asf_reader_get_string(asf_reader_t *reader, size_t size, iconv_t cd) {
char *inbuf, *outbuf;
size_t inbytesleft, outbytesleft;
- char scratch[2048];
+ char scratch[2048];
- if ((reader->size - reader->pos) < size)
+ if ((size == 0) ||((reader->size - reader->pos) < size))
return NULL;
inbuf = (char *)reader->buffer + reader->pos;
@@ -399,7 +399,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin
if (asf_stream_extension->stream_name_count) {
asf_stream_extension->stream_names = malloc (asf_stream_extension->stream_name_count * sizeof(void*));
for (i = 0; i < asf_stream_extension->stream_name_count; i++) {
- uint16_t lang_index, length;
+ uint16_t lang_index, length = 0;
asf_reader_get_16(&reader, &lang_index);
asf_reader_get_16(&reader, &length);
asf_stream_extension->stream_names[i] = (char*)asf_reader_get_bytes(&reader, length); /* store them */
@@ -411,7 +411,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin
for (i = 0; i < asf_stream_extension->payload_extension_system_count; i++) {
GUID guid;
uint16_t data_size;
- uint32_t length;
+ uint32_t length = 0;
asf_reader_get_guid(&reader, &guid);
asf_reader_get_16(&reader, &data_size);
asf_reader_get_32(&reader, &length);
@@ -427,7 +427,7 @@ static int asf_header_parse_stream_extended_properties(asf_header_t *header, uin
/* embeded stream properties */
if (asf_reader_get_size(&reader) >= 24) {
GUID guid;
- uint64_t object_length;
+ uint64_t object_length = 0;
asf_reader_get_guid(&reader, &guid);
asf_reader_get_64(&reader, &object_length);
@@ -490,8 +490,8 @@ static int asf_header_parse_stream_bitrate_properties(asf_header_t *header_pub,
lprintf (" bitrate count: %d\n", bitrate_count);
for(i = 0; i < bitrate_count; i++) {
- uint16_t flags;
- uint32_t bitrate;
+ uint16_t flags = 0;
+ uint32_t bitrate = 0;
int stream_number;
uint8_t *bitrate_pointer;
@@ -511,6 +511,61 @@ static int asf_header_parse_stream_bitrate_properties(asf_header_t *header_pub,
return 1;
}
+static int asf_header_parse_metadata(asf_header_t *header_pub, uint8_t *buffer, int buffer_len)
+{
+ asf_header_internal_t *header = (asf_header_internal_t *)header_pub;
+ asf_reader_t reader;
+ uint16_t i, records_count;
+ iconv_t iconv_cd;
+
+ if (buffer_len < 2)
+ return 0;
+
+ if ((iconv_cd = iconv_open ("UTF-8", "UCS-2LE")) == (iconv_t)-1)
+ return 0;
+
+ asf_reader_init(&reader, buffer, buffer_len);
+ asf_reader_get_16(&reader, &records_count);
+
+ for (i = 0; i < records_count; i++)
+ {
+ uint16_t index, stream, name_len = 0, data_type;
+ uint32_t data_len = 0;
+ int stream_id;
+
+ asf_reader_get_16 (&reader, &index);
+ asf_reader_get_16 (&reader, &stream);
+ stream &= 0x7f;
+ asf_reader_get_16 (&reader, &name_len);
+ asf_reader_get_16 (&reader, &data_type);
+ asf_reader_get_32 (&reader, &data_len);
+
+ stream_id = asf_header_get_stream_id (&header->pub, stream);
+
+ if (data_len >= 4)
+ {
+ char *name = asf_reader_get_string (&reader, name_len, iconv_cd);
+ if (name && !strcmp (name, "AspectRatioX"))
+ {
+ asf_reader_get_32 (&reader, &header->pub.aspect_ratios[stream_id].x);
+ data_len -= 4;
+ }
+ else if (name && !strcmp (name, "AspectRatioY"))
+ {
+ asf_reader_get_32 (&reader, &header->pub.aspect_ratios[stream_id].y);
+ data_len -= 4;
+ }
+ free (name);
+ asf_reader_skip (&reader, data_len);
+ }
+ else
+ asf_reader_skip (&reader, data_len + name_len);
+ }
+
+ iconv_close (iconv_cd);
+ return 1;
+}
+
static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buffer, int buffer_len) {
asf_reader_t reader;
@@ -533,7 +588,7 @@ static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buff
GUID guid;
int object_id;
- uint64_t object_length, object_data_length;
+ uint64_t object_length = 0, object_data_length;
if (asf_reader_get_size(&reader) < 24) {
printf("invalid buffer size\n");
@@ -549,12 +604,14 @@ static int asf_header_parse_header_extension(asf_header_t *header, uint8_t *buff
case GUID_EXTENDED_STREAM_PROPERTIES:
asf_header_parse_stream_extended_properties(header, asf_reader_get_buffer(&reader), object_data_length);
break;
+ case GUID_METADATA:
+ asf_header_parse_metadata(header, asf_reader_get_buffer(&reader), object_data_length);
+ break;
case GUID_ADVANCED_MUTUAL_EXCLUSION:
case GUID_GROUP_MUTUAL_EXCLUSION:
case GUID_STREAM_PRIORITIZATION:
case GUID_BANDWIDTH_SHARING:
case GUID_LANGUAGE_LIST:
- case GUID_METADATA:
case GUID_METADATA_LIBRARY:
case GUID_INDEX_PARAMETERS:
case GUID_MEDIA_OBJECT_INDEX_PARAMETERS:
@@ -581,10 +638,9 @@ static int asf_header_parse_content_description(asf_header_t *header_pub, uint8_
if (buffer_len < 10)
return 0;
- content = malloc(sizeof(asf_content_t));
+ content = calloc(1, sizeof(asf_content_t));
if (!content)
return 0;
- memset(content, 0, sizeof(asf_content_t));
asf_reader_init(&reader, buffer, buffer_len);
asf_reader_get_16(&reader, &title_length);
@@ -599,6 +655,12 @@ static int asf_header_parse_content_description(asf_header_t *header_pub, uint8_
content->description = asf_reader_get_string(&reader, description_length, header->iconv_cd);
content->rating = asf_reader_get_string(&reader, rating_length, header->iconv_cd);
+ lprintf("title: %d chars: \"%s\"\n", title_length, content->title);
+ lprintf("author: %d chars: \"%s\"\n", author_length, content->author);
+ lprintf("copyright: %d chars: \"%s\"\n", copyright_length, content->copyright);
+ lprintf("description: %d chars: \"%s\"\n", description_length, content->description);
+ lprintf("rating: %d chars: \"%s\"\n", rating_length, content->rating);
+
header->pub.content = content;
return 1;
}
@@ -611,10 +673,9 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) {
uint32_t object_count;
uint16_t junk;
- asf_header = malloc(sizeof(asf_header_internal_t));
+ asf_header = calloc(1, sizeof(asf_header_internal_t));
if (!asf_header)
return NULL;
- memset(asf_header, 0, sizeof(asf_header_internal_t));
lprintf("parsing_asf_header\n");
if (buffer_len < 6) {
@@ -638,7 +699,7 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) {
GUID guid;
int object_id;
- uint64_t object_length, object_data_length;
+ uint64_t object_length = 0, object_data_length;
if (asf_reader_get_size(&reader) < 24) {
printf("invalid buffer size\n");
@@ -697,10 +758,9 @@ asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) {
}
if (!asf_header->pub.content) {
lprintf("no content object present\n");
- asf_header->pub.content = malloc(sizeof(asf_content_t));
+ asf_header->pub.content = calloc(1, sizeof(asf_content_t));
if (!asf_header->pub.content)
goto exit_error;
- memset(asf_header->pub.content, 0, sizeof(asf_content_t));
}
return &asf_header->pub;
diff --git a/src/demuxers/asfheader.h b/src/demuxers/asfheader.h
index 4bd13ab3f..265f0e643 100644
--- a/src/demuxers/asfheader.h
+++ b/src/demuxers/asfheader.h
@@ -320,6 +320,7 @@ struct asf_header_s {
asf_stream_t *streams[ASF_MAX_NUM_STREAMS];
asf_stream_extension_t *stream_extensions[ASF_MAX_NUM_STREAMS];
uint32_t bitrates[ASF_MAX_NUM_STREAMS];
+ struct { uint32_t x, y; } aspect_ratios[ASF_MAX_NUM_STREAMS];
};
struct asf_file_s {
@@ -389,7 +390,7 @@ struct asf_stream_extension_s {
int asf_find_object_id (GUID *g);
void asf_get_guid (uint8_t *buffer, GUID *value);
-asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len);
+asf_header_t *asf_header_new (uint8_t *buffer, int buffer_len) XINE_MALLOC;
void asf_header_choose_streams (asf_header_t *header, uint32_t bandwidth,
int *video_id, int *audio_id);
void asf_header_disable_streams (asf_header_t *header,
diff --git a/src/demuxers/demux.h b/src/demuxers/demux.h
index 81907cfcf..a824730ea 100644
--- a/src/demuxers/demux.h
+++ b/src/demuxers/demux.h
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -63,7 +63,7 @@ struct demux_class_s {
*/
const char* (*get_identifier) (demux_class_t *this);
-
+
/*
* return MIME types supported for this plugin
*/
@@ -73,7 +73,7 @@ struct demux_class_s {
/*
* return ' ' seperated list of file extensions this
* demuxer is likely to handle
- * (will be used to filter media files in
+ * (will be used to filter media files in
* file selection dialogs)
*/
@@ -100,7 +100,7 @@ struct demux_plugin_s {
void (*send_headers) (demux_plugin_t *this);
/*
- * ask demux to seek
+ * ask demux to seek
*
* for seekable streams, a start position can be specified
*
@@ -118,11 +118,11 @@ struct demux_plugin_s {
* starting the demuxer)
*/
- int (*seek) (demux_plugin_t *this,
+ int (*seek) (demux_plugin_t *this,
off_t start_pos, int start_time, int playing );
/*
- * send a chunk of data down to decoder fifos
+ * send a chunk of data down to decoder fifos
*
* the meaning of "chunk" is specific to every demux, usually
* it involves parsing one unit of data from stream.
@@ -132,15 +132,15 @@ struct demux_plugin_s {
*/
int (*send_chunk) (demux_plugin_t *this);
-
+
/*
- * free resources
+ * free resources
*/
void (*dispose) (demux_plugin_t *this) ;
/*
- * returns DEMUX_OK or DEMUX_FINISHED
+ * returns DEMUX_OK or DEMUX_FINISHED
*/
int (*get_status) (demux_plugin_t *this) ;
@@ -157,12 +157,12 @@ struct demux_plugin_s {
*/
uint32_t (*get_capabilities) (demux_plugin_t *this);
-
+
/*
* request optional data from input plugin.
*/
int (*get_optional_data) (demux_plugin_t *this, void *data, int data_type);
-
+
/*
* "backwards" link to plugin class
*/
@@ -181,8 +181,8 @@ struct demux_plugin_s {
/*
* DEMUX_CAP_AUDIOLANG:
* DEMUX_CAP_SPULANG:
- * demux plugin knows something about audio/spu languages,
- * e.g. knows that audio stream #0 is english,
+ * demux plugin knows something about audio/spu languages,
+ * e.g. knows that audio stream #0 is english,
* audio stream #1 is german, ... Same bits as INPUT
* capabilities .
*/
diff --git a/src/demuxers/demux_4xm.c b/src/demuxers/demux_4xm.c
index 24aee1ac4..a58cf0f22 100644
--- a/src/demuxers/demux_4xm.c
+++ b/src/demuxers/demux_4xm.c
@@ -125,25 +125,15 @@ static float get_le_float(unsigned char *buffer)
* This function is called from the _open() function of this demuxer.
* It returns 1 if 4xm file was opened successfully. */
static int open_fourxm_file(demux_fourxm_t *fourxm) {
-
unsigned char preview[12];
- int header_size;
- unsigned char *header;
- int i;
- unsigned int fourcc_tag;
- unsigned int size;
- unsigned int current_track;
- unsigned int audio_type;
- unsigned int total_frames;
- float fps;
/* the file signature will be in the first 12 bytes */
if (_x_demux_read_header(fourxm->input, preview, 12) != 12)
return 0;
/* check for the signature tags */
- if ((_X_LE_32(&preview[0]) != RIFF_TAG) ||
- (_X_LE_32(&preview[8]) != _4XMV_TAG))
+ if (!_x_is_fourcc(&preview[0], "RIFF") ||
+ !_x_is_fourcc(&preview[8], "4XMV"))
return 0;
/* file is qualified; skip over the header bytes in the stream */
@@ -152,14 +142,14 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
/* fetch the LIST-HEAD header */
if (fourxm->input->read(fourxm->input, preview, 12) != 12)
return 0;
- if ((_X_LE_32(&preview[0]) != LIST_TAG) ||
- (_X_LE_32(&preview[8]) != HEAD_TAG))
+ if (!_x_is_fourcc(&preview[0], "LIST") ||
+ !_x_is_fourcc(&preview[8], "HEAD") )
return 0;
/* read the whole header */
- header_size = _X_LE_32(&preview[4]) - 4;
- header = xine_xmalloc(header_size);
- if (fourxm->input->read(fourxm->input, header, header_size) != header_size) {
+ const uint32_t header_size = _X_LE_32(&preview[4]) - 4;
+ uint8_t *const header = malloc(header_size);
+ if (!header || fourxm->input->read(fourxm->input, header, header_size) != header_size) {
free(header);
return 0;
}
@@ -171,12 +161,13 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
fourxm->video_pts_inc = 0;
/* take the lazy approach and search for any and all vtrk and strk chunks */
+ int i;
for (i = 0; i < header_size - 8; i++) {
- fourcc_tag = _X_LE_32(&header[i]);
- size = _X_LE_32(&header[i + 4]);
+ const uint32_t fourcc_tag = _X_LE_32(&header[i]);
+ const uint32_t size = _X_LE_32(&header[i + 4]);
if (fourcc_tag == std__TAG) {
- fps = get_le_float(&header[i + 12]);
+ const float fps = get_le_float(&header[i + 12]);
fourxm->video_pts_inc = (int64_t)(90000.0 / fps);
} else if (fourcc_tag == vtrk_TAG) {
/* check that there is enough data */
@@ -184,7 +175,7 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
free(header);
return 0;
}
- total_frames = _X_LE_32(&header[i + 24]);
+ const uint32_t total_frames = _X_LE_32(&header[i + 24]);
fourxm->duration_in_ms = total_frames;
fourxm->duration_in_ms *= fourxm->video_pts_inc;
fourxm->duration_in_ms /= 90000;
@@ -198,9 +189,13 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
free(header);
return 0;
}
- current_track = _X_LE_32(&header[i + 8]);
- if (current_track + 1 > fourxm->track_count) {
+ const uint32_t current_track = _X_LE_32(&header[i + 8]);
+ if (current_track >= fourxm->track_count) {
fourxm->track_count = current_track + 1;
+ if (!fourxm->track_count || fourxm->track_count >= UINT_MAX / sizeof(audio_track_t)) {
+ free(header);
+ return 0;
+ }
fourxm->tracks = realloc(fourxm->tracks,
fourxm->track_count * sizeof(audio_track_t));
if (!fourxm->tracks) {
@@ -212,7 +207,7 @@ static int open_fourxm_file(demux_fourxm_t *fourxm) {
fourxm->tracks[current_track].channels = _X_LE_32(&header[i + 36]);
fourxm->tracks[current_track].sample_rate = _X_LE_32(&header[i + 40]);
fourxm->tracks[current_track].bits = _X_LE_32(&header[i + 44]);
- audio_type = _X_LE_32(&header[i + 12]);
+ const uint32_t audio_type = _X_LE_32(&header[i + 12]);
if (audio_type == 0)
fourxm->tracks[current_track].audio_type = BUF_AUDIO_LPCM_LE;
else if (audio_type == 1)
@@ -239,20 +234,18 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) {
demux_fourxm_t *this = (demux_fourxm_t *) this_gen;
buf_element_t *buf = NULL;
- unsigned int fourcc_tag;
- unsigned int size;
- unsigned char header[8];
unsigned int remaining_bytes;
unsigned int current_track;
/* read the next header */
+ uint8_t header[8];
if (this->input->read(this->input, header, 8) != 8) {
this->status = DEMUX_FINISHED;
return this->status;
}
- fourcc_tag = _X_LE_32(&header[0]);
- size = _X_LE_32(&header[4]);
+ const uint32_t fourcc_tag = _X_LE_32(&header[0]);
+ const uint32_t size = _X_LE_32(&header[4]);
switch (fourcc_tag) {
@@ -263,7 +256,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_4XM;
if( this->filesize )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->filesize );
buf->extra_info->input_time = this->video_pts / 90;
buf->pts = this->video_pts;
@@ -278,7 +271,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_4XM;
if( this->filesize )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->filesize );
buf->extra_info->input_time = this->video_pts / 90;
buf->pts = this->video_pts;
@@ -327,7 +320,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = this->tracks[current_track].audio_type;
if( this->filesize )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->filesize );
/* let the engine sort it out */
buf->extra_info->input_time = 0;
@@ -361,7 +354,7 @@ static int demux_fourxm_send_chunk(demux_plugin_t *this_gen) {
break;
default:
- lprintf("bad chunk: %c%c%c%c (%02X%02X%02X%02X)\n",
+ lprintf("bad chunk: %c%c%c%c (%02X%02X%02X%02X)\n",
header[0], header[1], header[2], header[3],
header[0], header[1], header[2], header[3]);
this->status = DEMUX_FINISHED;
@@ -472,7 +465,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_fourxm_t *this;
- this = xine_xmalloc (sizeof (demux_fourxm_t));
+ this = calloc(1, sizeof(demux_fourxm_t));
this->stream = stream;
this->input = input;
@@ -491,10 +484,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
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);
+ const char *const mrl = input->get_mrl (input);
+ const char *const extensions = class_gen->get_extensions (class_gen);
if (!_x_demux_check_extension (mrl, extensions)) {
free (this);
@@ -546,7 +537,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_fourxm_init_plugin (xine_t *xine, void *data) {
demux_fourxm_class_t *this;
- this = xine_xmalloc (sizeof (demux_fourxm_class_t));
+ this = calloc(1, sizeof(demux_fourxm_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_aac.c b/src/demuxers/demux_aac.c
index d80413f83..6615f4f61 100644
--- a/src/demuxers/demux_aac.c
+++ b/src/demuxers/demux_aac.c
@@ -95,8 +95,7 @@ static int open_aac_file(demux_aac_t *this) {
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')) {
+ if (_x_is_fourcc(peak, "AIDF")) {
lprintf("found ADIF header\n");
return 1;
}
@@ -109,7 +108,7 @@ static int open_aac_file(demux_aac_t *this) {
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) !=
+ } else if (_x_demux_read_header(this->input, peak, MAX_PREVIEW_SIZE) !=
MAX_PREVIEW_SIZE)
return 0;
@@ -134,9 +133,7 @@ static int open_aac_file(demux_aac_t *this) {
if ((frame_size > 0) &&
(data_start+frame_size < MAX_PREVIEW_SIZE-1) &&
/* first 28 bits must be identical */
- (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]) &&
+ memcmp(&peak[data_start], &peak[data_start+frame_size], 4) == 0 &&
(peak[data_start+3]>>4==peak[data_start+frame_size+3]>>4))
{
lprintf("found second ADTS header\n");
@@ -176,11 +173,11 @@ static int demux_aac_send_chunk(demux_plugin_t *this_gen) {
buf->extra_info->input_time = (8*current_pos) / (bitrate/1000);
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
- } else
+ } else
buf->size = bytes_read;
/* each buffer stands on its own */
@@ -262,7 +259,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_aac_t *this;
- this = xine_xmalloc (sizeof (demux_aac_t));
+ this = calloc(1, sizeof(demux_aac_t));
this->stream = stream;
this->input = input;
@@ -333,7 +330,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_aac_init_plugin (xine_t *xine, void *data) {
demux_aac_class_t *this;
- this = xine_xmalloc (sizeof (demux_aac_class_t));
+ this = calloc(1, sizeof(demux_aac_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_ac3.c b/src/demuxers/demux_ac3.c
index c0fae275b..f13144254 100644
--- a/src/demuxers/demux_ac3.c
+++ b/src/demuxers/demux_ac3.c
@@ -37,6 +37,9 @@
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#define LOG_MODULE "demux_ac3"
#define LOG_VERBOSE
@@ -304,17 +307,11 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) {
}
} else {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- buf->size = this->input->read(this->input, buf->content,
+ buf->size = this->input->read(this->input, buf->content,
this->frame_size);
}
- if (buf->size == 0) {
- buf->free_buffer(buf);
- this->status = DEMUX_FINISHED;
- return this->status;
- }
-
- if (buf->size == 0) {
+ if (buf->size <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
@@ -322,7 +319,7 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) {
buf->type = this->buf_type;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) current_stream_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_stream_pos *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = audio_pts / 90;
buf->pts = audio_pts;
@@ -417,7 +414,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_ac3_t *this;
- this = xine_xmalloc (sizeof (demux_ac3_t));
+ this = calloc(1, sizeof(demux_ac3_t));
this->stream = stream;
this->input = input;
@@ -491,7 +488,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_ac3_init_plugin (xine_t *xine, void *data) {
demux_ac3_class_t *this;
- this = xine_xmalloc (sizeof (demux_ac3_class_t));
+ this = calloc(1, sizeof(demux_ac3_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_aiff.c b/src/demuxers/demux_aiff.c
index 3f2d0df11..ee45963a5 100644
--- a/src/demuxers/demux_aiff.c
+++ b/src/demuxers/demux_aiff.c
@@ -46,6 +46,10 @@
#define COMM_TAG FOURCC_TAG('C', 'O', 'M', 'M')
#define SSND_TAG FOURCC_TAG('S', 'S', 'N', 'D')
#define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M')
+#define NAME_TAG FOURCC_TAG('N', 'A', 'M', 'E')
+#define AUTH_TAG FOURCC_TAG('A', 'U', 'T', 'H')
+#define COPY_TAG FOURCC_TAG('(', 'c', ')', ' ')
+#define ANNO_TAG FOURCC_TAG('A', 'N', 'N', 'O')
#define PREAMBLE_SIZE 8
#define AIFF_SIGNATURE_SIZE 12
@@ -80,6 +84,24 @@ typedef struct {
demux_class_t demux_class;
} demux_aiff_class_t;
+/* converts IEEE 80bit extended into int, based on FFMPEG code */
+static int extended_to_int(const unsigned char p[10])
+{
+ uint64_t m = 0;
+ int e, i;
+
+ for (i = 0; i < 8; i++)
+ m = (m<<8) + p[2+i];;
+ e = (((int)p[0]&0x7f)<<8) | p[1];
+ if (e == 0x7fff && m)
+ return 0.0/0.0;
+ e -= 16383 + 63;
+
+ if (p[0]&0x80)
+ m= -m;
+ return (int) ldexp(m, e);
+}
+
/* returns 1 if the AIFF file was opened successfully, 0 otherwise */
static int open_aiff_file(demux_aiff_t *this) {
@@ -87,13 +109,14 @@ static int open_aiff_file(demux_aiff_t *this) {
unsigned char preamble[PREAMBLE_SIZE];
unsigned int chunk_type;
unsigned int chunk_size;
+ unsigned char extended_sample_rate[10];
if (_x_demux_read_header(this->input, signature, AIFF_SIGNATURE_SIZE) != AIFF_SIGNATURE_SIZE)
return 0;
/* check the signature */
- if ((_X_BE_32(&signature[0]) != FORM_TAG) ||
- (_X_BE_32(&signature[8]) != AIFF_TAG))
+ if( !_x_is_fourcc(&signature[0], "FORM") ||
+ !_x_is_fourcc(&signature[8], "AIFF") )
return 0;
/* file is qualified; skip over the header bytes in the stream */
@@ -116,7 +139,7 @@ static int open_aiff_file(demux_aiff_t *this) {
}
chunk_type = _X_BE_32(&preamble[0]);
chunk_size = _X_BE_32(&preamble[4]);
-
+
if (chunk_type == COMM_TAG) {
unsigned char buffer[100];
@@ -135,7 +158,8 @@ static int open_aiff_file(demux_aiff_t *this) {
this->audio_channels = _X_BE_16(&buffer[0]);
this->audio_frames = _X_BE_32(&buffer[2]);
this->audio_bits = _X_BE_16(&buffer[6]);
- this->audio_sample_rate = _X_BE_16(&buffer[0x0A]);
+ memcpy(&extended_sample_rate, &buffer[8], sizeof(extended_sample_rate));
+ this->audio_sample_rate = extended_to_int(extended_sample_rate);
this->audio_bytes_per_second = this->audio_channels *
(this->audio_bits / 8) * this->audio_sample_rate;
@@ -150,11 +174,18 @@ static int open_aiff_file(demux_aiff_t *this) {
(this->audio_bits / 8);
this->running_time = (this->audio_frames / this->audio_sample_rate) * 1000;
- this->audio_block_align = PCM_BLOCK_ALIGN;
+ /* we should send only complete frames to decoder, as it
+ * doesn't handle underconsumption yet */
+ this->audio_block_align = PCM_BLOCK_ALIGN - PCM_BLOCK_ALIGN % (this->audio_bits / 8 * this->audio_channels);
break;
} else {
+ /* if chunk contains metadata, it will be word-aligned (as seen at sox and ffmpeg) */
+ if ( ((chunk_type == NAME_TAG) || (chunk_type==AUTH_TAG) ||
+ (chunk_type == COPY_TAG) || (chunk_type==ANNO_TAG)) && (chunk_size&1))
+ chunk_size++;
+
/* unrecognized; skip it */
this->input->seek(this->input, chunk_size, SEEK_CUR);
}
@@ -179,7 +210,7 @@ static int demux_aiff_send_chunk (demux_plugin_t *this_gen) {
/* just load data chunks from wherever the stream happens to be
* pointing; issue a DEMUX_FINISHED status if EOF is reached */
remaining_sample_bytes = this->audio_block_align;
- current_file_pos =
+ current_file_pos =
this->input->get_current_pos(this->input) - this->data_start;
current_pts = current_file_pos;
@@ -227,7 +258,7 @@ static int demux_aiff_send_chunk (demux_plugin_t *this_gen) {
this->audio_fifo->put (this->audio_fifo, buf);
}
-
+
return this->status;
}
@@ -338,7 +369,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_aiff_t *this;
- this = xine_xmalloc (sizeof (demux_aiff_t));
+ this = calloc(1, sizeof(demux_aiff_t));
this->stream = stream;
this->input = input;
@@ -414,7 +445,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_aiff_init_plugin (xine_t *xine, void *data) {
demux_aiff_class_t *this;
- this = xine_xmalloc (sizeof (demux_aiff_class_t));
+ this = calloc(1, sizeof(demux_aiff_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_asf.c b/src/demuxers/demux_asf.c
index 9aab59977..e2da05c75 100644
--- a/src/demuxers/demux_asf.c
+++ b/src/demuxers/demux_asf.c
@@ -70,6 +70,7 @@
#define ASF_MODE_HTTP_REF 2
#define ASF_MODE_ASF_REF 3
#define ASF_MODE_ENCRYPTED_CONTENT 4
+#define ASF_MODE_NO_CONTENT 5
typedef struct {
int seq;
@@ -87,13 +88,13 @@ typedef struct {
int skip;
int resync;
int first_seq;
-
+
int payload_size;
/* palette handling */
int palette_count;
palette_entry_t palette[256];
-
+
} asf_demux_stream_t;
typedef struct demux_asf_s {
@@ -108,13 +109,13 @@ typedef struct demux_asf_s {
int64_t keyframe_ts;
int keyframe_found;
-
+
int seqno;
uint32_t packet_size;
uint8_t packet_len_flags;
uint32_t data_size;
uint64_t packet_count;
-
+
asf_demux_stream_t streams[MAX_NUM_STREAMS];
int video_stream;
int audio_stream;
@@ -144,7 +145,7 @@ typedef struct demux_asf_s {
int reorder_b;
int buf_flag_seek;
-
+
/* first packet position */
int64_t first_packet_pos;
@@ -266,7 +267,7 @@ static int get_guid (demux_asf_t *this) {
for(i = 0; i < 8; i++) {
g.Data4[i] = get_byte(this);
}
-
+
return get_guid_id(this, &g);
}
@@ -305,7 +306,7 @@ static void asf_send_audio_header (demux_asf_t *this, int stream) {
this->status = DEMUX_FINISHED;
return;
}
-
+
memcpy (buf->content, wavex, asf_stream->private_data_length);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, wavex->wFormatTag);
@@ -346,11 +347,19 @@ static void asf_send_video_header (demux_asf_t *this, int stream) {
this->status = DEMUX_FINISHED;
return;
}
-
+
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAMERATE|
BUF_FLAG_FRAME_END;
-
+
buf->decoder_info[0] = 0;
+
+ if (this->asf_header->aspect_ratios[stream].x && this->asf_header->aspect_ratios[stream].y)
+ {
+ buf->decoder_flags |= BUF_FLAG_ASPECT;
+ buf->decoder_info[1] = bih->biWidth * this->asf_header->aspect_ratios[stream].x;
+ buf->decoder_info[2] = bih->biHeight * this->asf_header->aspect_ratios[stream].y;
+ }
+
buf->size = asf_stream->private_data_length - 11;
memcpy (buf->content, bih, buf->size);
buf->type = this->streams[stream].buf_type;
@@ -360,7 +369,7 @@ static void asf_send_video_header (demux_asf_t *this, int stream) {
/* send off the palette, if there is one */
if (demux_stream->palette_count) {
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_asf: stream %d, palette : %d entries\n", stream, demux_stream->palette_count);
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER;
@@ -379,10 +388,21 @@ static int asf_read_header (demux_asf_t *this) {
char *asf_header_buffer = NULL;
asf_header_len = get_le64(this);
- asf_header_buffer = alloca(asf_header_len);
+ if (asf_header_len > 4 * 1024 * 1024)
+ {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_asf: asf_read_header: overly-large header? (%"PRIu64" bytes)\n",
+ asf_header_len);
+ return 0;
+ }
+
+ asf_header_buffer = malloc (asf_header_len);
if (this->input->read (this->input, asf_header_buffer, asf_header_len) != asf_header_len)
+ {
+ free (asf_header_buffer);
return 0;
+ }
/* delete previous header */
if (this->asf_header) {
@@ -395,19 +415,23 @@ static int asf_read_header (demux_asf_t *this) {
*/
this->asf_header = asf_header_new(asf_header_buffer, asf_header_len);
if (!this->asf_header)
+ {
+ free (asf_header_buffer);
return 0;
+ }
+ free (asf_header_buffer);
lprintf("asf header parsing ok\n");
this->packet_size = this->asf_header->file->packet_size;
this->packet_count = this->asf_header->file->data_packet_count;
-
+
/* compute stream duration */
- this->length = (this->asf_header->file->send_duration -
+ this->length = (this->asf_header->file->send_duration -
this->asf_header->file->preroll) / 10000;
if (this->length < 0)
this->length = 0;
-
+
/* compute average byterate (needed for seeking) */
if (this->asf_header->file->max_bitrate)
this->rate = this->asf_header->file->max_bitrate >> 3;
@@ -420,6 +444,17 @@ static int asf_read_header (demux_asf_t *this) {
asf_stream_t *asf_stream = this->asf_header->streams[i];
asf_demux_stream_t *demux_stream = &this->streams[i];
+ if (!asf_stream) {
+ if (this->mode != ASF_MODE_NO_CONTENT) {
+ xine_log(this->stream->xine, XINE_LOG_MSG,
+ _("demux_asf: warning: A stream appears to be missing.\n"));
+ _x_message(this->stream, XINE_MSG_READ_ERROR,
+ _("Media stream missing?"), NULL);
+ this->mode = ASF_MODE_NO_CONTENT;
+ }
+ return 0;
+ }
+
if (asf_stream->encrypted_flag) {
if (this->mode != ASF_MODE_ENCRYPTED_CONTENT) {
xine_log(this->stream->xine, XINE_LOG_MSG,
@@ -438,14 +473,14 @@ static int asf_read_header (demux_asf_t *this) {
this->reorder_w = (asf_stream->error_correction_data[2]<<8)|asf_stream->error_correction_data[1];
this->reorder_b = (asf_stream->error_correction_data[4]<<8)|asf_stream->error_correction_data[3];
this->reorder_w /= this->reorder_b;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_asf: audio conceal interleave detected (%d x %d x %d)\n",
this->reorder_w, this->reorder_h, this->reorder_b );
} else {
this->reorder_b = this->reorder_h = this->reorder_w = 1;
}
-
-
+
+
demux_stream->buf_type = _x_formattag_to_buf_audio
( ((xine_waveformatex *)asf_stream->private_data)->wFormatTag );
if ( !demux_stream->buf_type ) {
@@ -454,9 +489,9 @@ static int asf_read_header (demux_asf_t *this) {
((xine_waveformatex *)asf_stream->private_data)->wFormatTag);
demux_stream->buf_type = BUF_AUDIO_UNKNOWN;
}
-
+
_x_meta_info_set(this->stream, XINE_META_INFO_AUDIOCODEC, _x_buf_audio_name(demux_stream->buf_type));
-
+
this->streams[i].fifo = this->audio_fifo;
this->streams[i].frag_offset = 0;
this->streams[i].seq = 0;
@@ -466,12 +501,12 @@ static int asf_read_header (demux_asf_t *this) {
this->streams[i].defrag = 1;
} else
this->streams[i].defrag = 0;
-
+
lprintf ("found an audio stream id=%d \n", asf_stream->stream_number);
break;
-
+
case GUID_ASF_VIDEO_MEDIA:
- {
+ {
/* video private data
* 11 bytes : header
* 40 bytes : bmiheader
@@ -480,38 +515,38 @@ static int asf_read_header (demux_asf_t *this) {
uint32_t width, height;
uint16_t bmiheader_size;
xine_bmiheader *bmiheader;
-
+
width = _X_LE_32(asf_stream->private_data);
height = _X_LE_32(asf_stream->private_data + 4);
/* there is one unknown byte between height and the bmiheader size */
bmiheader_size = _X_LE_16(asf_stream->private_data + 9);
-
+
/* FIXME: bmiheader_size must be >= sizeof(xine_bmiheader) */
-
+
bmiheader = (xine_bmiheader *) (asf_stream->private_data + 11);
_x_bmiheader_le2me(bmiheader);
-
+
/* FIXME: check if (bmi_header_size == bmiheader->biSize) ? */
demux_stream->buf_type = _x_fourcc_to_buf_video(bmiheader->biCompression);
if( !demux_stream->buf_type ) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_asf: unknown video format %.4s\n", (char*)&(bmiheader->biCompression));
-
+
demux_stream->buf_type = BUF_VIDEO_UNKNOWN;
}
-
+
_x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name(demux_stream->buf_type));
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH, width);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT, height);
-
+
this->streams[i].fifo = this->video_fifo;
this->streams[i].frag_offset = 0;
this->streams[i].defrag = 0;
-
+
/* load the palette, if there is one */
demux_stream->palette_count = bmiheader->biClrUsed;
-
+
lprintf ("palette_count: %d\n", demux_stream->palette_count);
if (demux_stream->palette_count > 256) {
lprintf ("number of colours exceeded 256 (%d)", demux_stream->palette_count);
@@ -520,10 +555,10 @@ static int asf_read_header (demux_asf_t *this) {
if ((asf_stream->private_data_length - sizeof(xine_bmiheader) - 11) >= (demux_stream->palette_count * 4)) {
int j;
uint8_t *palette;
-
+
/* according to msdn the palette is located here : */
palette = (uint8_t *)bmiheader + bmiheader->biSize;
-
+
/* load the palette */
for (j = 0; j < demux_stream->palette_count; j++) {
demux_stream->palette[j].b = *(palette + j * 4 + 0);
@@ -532,7 +567,7 @@ static int asf_read_header (demux_asf_t *this) {
}
} else {
int j;
-
+
/* generate a greyscale palette */
demux_stream->palette_count = 256;
for (j = 0; j < demux_stream->palette_count; j++) {
@@ -541,7 +576,7 @@ static int asf_read_header (demux_asf_t *this) {
demux_stream->palette[j].b = j;
}
}
-
+
lprintf ("found a video stream id=%d, buf_type=%08x \n",
this->asf_header->streams[i]->stream_number, this->streams[i].buf_type);
}
@@ -703,12 +738,15 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str
bufsize = stream->fifo->buffer_pool_buf_size;
buf = stream->fifo->buffer_pool_alloc (stream->fifo);
- this->input->read (this->input, buf->content, bufsize);
+ if (this->input->read (this->input, buf->content, bufsize) != bufsize) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n");
+ return ;
+ }
lprintf ("data: %d %d %d %d\n", buf->content[0], buf->content[1], buf->content[2], buf->content[3]);
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = timestamp;
@@ -723,6 +761,9 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str
buf->size = bufsize;
timestamp = 0;
+ if (stream->frag_offset == 0)
+ buf->decoder_flags |= BUF_FLAG_FRAME_START;
+
stream->frag_offset += bufsize;
frag_len -= bufsize;
@@ -733,10 +774,6 @@ static void asf_send_buffer_nodefrag (demux_asf_t *this, asf_demux_stream_t *str
else
check_newpts (this, buf->pts, PTS_AUDIO, package_done);
-
- if (frag_offset == 0)
- buf->decoder_flags |= BUF_FLAG_FRAME_START;
-
/* test if whole packet read */
if (package_done) {
buf->decoder_flags |= BUF_FLAG_FRAME_END;
@@ -783,7 +820,10 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *strea
if( stream->frag_offset + frag_len > DEFRAG_BUFSIZE ) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: buffer overflow on defrag!\n");
} else {
- this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len);
+ if (this->input->read (this->input, &stream->buffer[stream->frag_offset], frag_len) != frag_len) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: input buffer starved\n");
+ return ;
+ }
stream->frag_offset += frag_len;
}
@@ -792,46 +832,46 @@ static void asf_send_buffer_defrag (demux_asf_t *this, asf_demux_stream_t *strea
if (package_done) {
int bufsize;
uint8_t *p;
-
+
lprintf("packet done: offset=%d, payload=%d\n", stream->frag_offset, stream->payload_size);
if (stream->fifo == this->audio_fifo &&
this->reorder_h > 1 && this->reorder_w > 1 ) {
asf_reorder(this,stream->buffer,stream->frag_offset);
}
-
+
p = stream->buffer;
while( stream->frag_offset ) {
if ( stream->frag_offset < stream->fifo->buffer_pool_buf_size )
bufsize = stream->frag_offset;
else
bufsize = stream->fifo->buffer_pool_buf_size;
-
+
buf = stream->fifo->buffer_pool_alloc (stream->fifo);
xine_fast_memcpy (buf->content, p, bufsize);
-
+
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = stream->timestamp;
-
+
/* send the same pts for the entire frame */
buf->pts = stream->timestamp * 90;
-
+
buf->type = stream->buf_type;
buf->size = bufsize;
-
+
lprintf ("buffer type %08x %8d bytes, %8lld pts\n",
buf->type, buf->size, buf->pts);
-
+
stream->frag_offset -= bufsize;
p+=bufsize;
-
+
if ((buf->type & BUF_MAJOR_MASK) == BUF_VIDEO_BASE)
check_newpts (this, buf->pts, PTS_VIDEO, !stream->frag_offset);
else
check_newpts (this, buf->pts, PTS_AUDIO, !stream->frag_offset);
-
+
/* test if whole packet read */
if ( !stream->frag_offset )
buf->decoder_flags |= BUF_FLAG_FRAME_END;
@@ -848,9 +888,9 @@ static int asf_parse_packet_align(demux_asf_t *this) {
uint32_t mod;
uint64_t packet_num;
-
+
current_pos = this->input->get_current_pos (this->input);
-
+
/* seek to the beginning of the next packet */
mod = (current_pos - this->first_packet_pos) % this->packet_size;
this->packet_size_left = mod ? this->packet_size - mod : 0;
@@ -864,7 +904,7 @@ static int asf_parse_packet_align(demux_asf_t *this) {
}
}
this->packet_size_left = 0;
-
+
/* check packet_count */
packet_num = (packet_pos - this->first_packet_pos) / this->packet_size;
lprintf("packet_num=%"PRId64", packet_count=%"PRId64"\n", packet_num, this->packet_count);
@@ -885,7 +925,7 @@ static int asf_parse_packet_align(demux_asf_t *this) {
}
}
}
-
+
return 0;
}
@@ -911,7 +951,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) {
ecd_opaque = (ecd_flags >> 4) & 0x1;
ecd_len_type = (ecd_flags >> 5) & 0x3;
ecd_present = (ecd_flags >> 7) & 0x1;
-
+
/* skip ecd */
if (ecd_present && !ecd_opaque && !ecd_len_type) {
int read_size;
@@ -925,7 +965,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) {
} else {
GUID *guid = (GUID *)buf;
-
+
/* check if it's a new stream */
buf[0] = ecd_flags;
if (this->input->read (this->input, buf + 1, 15) != 15) {
@@ -942,7 +982,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) {
if (demux_asf_send_headers_common(this))
return 1;
} else {
-
+
/* skip invalid packet */
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: skip invalid packet: %2X\n", ecd_flags);
this->input->seek (this->input, this->packet_size - *p_hdr_size, SEEK_CUR);
@@ -951,7 +991,7 @@ static int asf_parse_packet_ecd(demux_asf_t *this, uint32_t *p_hdr_size) {
}
}
} while (invalid_packet);
-
+
return 0;
}
@@ -1020,7 +1060,7 @@ static int asf_parse_packet_payload_header(demux_asf_t *this, uint32_t p_hdr_siz
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: invalid padsize: %d\n", this->packet_padsize);
return 1;
}
-
+
/* Multiple frames */
if (this->packet_len_flags & 0x01) {
this->frame_flag = get_byte(this); p_hdr_size += 1;
@@ -1057,7 +1097,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
*stream = NULL;
lprintf ("got raw_id=%d, stream_id=%d\n", raw_id, stream_id);
-
+
for (i = 0; i < this->asf_header->stream_count; i++) {
lprintf ("stream_number = %d\n", this->asf_header->streams[i]->stream_number);
if ((this->asf_header->streams[i]->stream_number == stream_id) &&
@@ -1067,7 +1107,7 @@ static int asf_parse_packet_payload_common(demux_asf_t *this,
break;
}
}
-
+
switch ((this->packet_prop_flags >> 4) & 3){
case 1:
seq = get_byte(this); s_hdr_size += 1;
@@ -1224,10 +1264,10 @@ static int asf_parse_packet_compressed_payload(demux_asf_t *this,
stream->resync = 0;
stream->skip = 0;
}
-
+
if (!stream->skip) {
lprintf ("sending buffer of type %08x\n", stream->buf_type);
-
+
if (stream->defrag)
asf_send_buffer_defrag (this, stream, 0, *timestamp, object_length);
else
@@ -1399,15 +1439,15 @@ static int demux_asf_parse_http_references( demux_asf_t *this) {
if (!end) goto failure;
*end = '\0';
}
-
+
/* replace http by mmsh */
if (!strncmp(href, "http", 4)) {
memcpy(href, "mmsh", 4);
}
-
+
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: http ref: %s\n", href);
_x_demux_send_mrl_reference (this->stream, 0, href, NULL, 0, 0);
-
+
if (free_href)
free(href);
}
@@ -1504,6 +1544,7 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) {
int buf_used = 0;
int len;
xml_node_t *xml_tree, *asx_entry, *asx_ref;
+ xml_parser_t *xml_parser;
int result;
@@ -1526,9 +1567,13 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) {
if(buf_used)
buf[buf_used] = '\0';
- xml_parser_init(buf, buf_used, XML_PARSER_CASE_INSENSITIVE);
- if((result = xml_parser_build_tree(&xml_tree)) != XML_PARSER_OK)
+ xml_parser = xml_parser_init_r(buf, buf_used, XML_PARSER_CASE_INSENSITIVE);
+ if((result = xml_parser_build_tree_r(xml_parser, &xml_tree)) != XML_PARSER_OK) {
+ xml_parser_finalize_r(xml_parser);
goto failure;
+ }
+
+ xml_parser_finalize_r(xml_parser);
if(!strcasecmp(xml_tree->name, "ASX")) {
/* Attributes: VERSION, PREVIEWMODE, BANNERBAR
@@ -1586,13 +1631,13 @@ static int demux_asf_parse_asx_references( demux_asf_t *this) {
else if (!strcasecmp (asx_ref->name, "STARTTIME"))
{
- if (start_time == (uint32_t)-1)
+ if (start_time == (uint32_t)-1)
start_time = asx_get_time_value (asx_ref);
}
else if (!strcasecmp (asx_ref->name, "DURATION"))
{
- if (duration == (uint32_t)-1)
+ if (duration == (uint32_t)-1)
duration = asx_get_time_value (asx_ref);
}
@@ -1645,7 +1690,7 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) {
uint32_t rlen = 0;
uint8_t raw_id = 0;
int64_t ts = 0;
-
+
switch (this->mode) {
case ASF_MODE_ASX_REF:
return demux_asf_parse_asx_references(this);
@@ -1657,13 +1702,14 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) {
return demux_asf_parse_asf_references(this);
case ASF_MODE_ENCRYPTED_CONTENT:
+ case ASF_MODE_NO_CONTENT:
this->status = DEMUX_FINISHED;
return this->status;
default:
- {
+ {
int header_size = 0;
-
+
if (asf_parse_packet_align(this)) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_asf: asf_parse_packet_align failed\n");
this->status = DEMUX_FINISHED;
@@ -1679,7 +1725,7 @@ static int demux_asf_send_chunk (demux_plugin_t *this_gen) {
this->status = DEMUX_FINISHED;
return this->status;
}
-
+
for (this->frame = 0; this->frame < (this->nb_frames & 0x3f); this->frame++) {
raw_id = get_byte(this); this->packet_size_left -= 1;
@@ -1704,7 +1750,7 @@ static void demux_asf_dispose (demux_plugin_t *this_gen) {
if (this->asf_header) {
int i;
-
+
for (i=0; i<this->asf_header->stream_count; i++) {
asf_demux_stream_t *asf_stream;
@@ -1717,7 +1763,7 @@ static void demux_asf_dispose (demux_plugin_t *this_gen) {
asf_header_delete (this->asf_header);
}
-
+
free (this);
}
@@ -1777,11 +1823,11 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
start_pos, start_time);
this->status = DEMUX_OK;
-
+
if (this->mode != ASF_MODE_NORMAL) {
return this->status;
}
-
+
/*
* seek to start position
*/
@@ -1795,7 +1841,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
this->last_pts[PTS_AUDIO] = 0;
this->keyframe_ts = 0;
this->keyframe_found = 0;
-
+
/* engine sync stuff */
this->send_newpts = 1;
this->buf_flag_seek = 1;
@@ -1803,11 +1849,11 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
if (this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) {
_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;
@@ -1868,7 +1914,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
this->status = DEMUX_FINISHED;
return this->status;
}
-
+
for (this->frame = 0; this->frame < (this->nb_frames & 0x3f); this->frame++) {
raw_id = get_byte(this); this->packet_size_left -= 1;
@@ -1877,7 +1923,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
stream_id = raw_id & 0x7f;
if (asf_parse_packet_payload_common(this, raw_id, &stream, &frag_offset, &rlen))
break;
-
+
if (rlen == 1) {
if (asf_parse_packet_compressed_payload(this, stream, raw_id, frag_offset, &ts))
break;
@@ -1885,7 +1931,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
if (asf_parse_packet_payload(this, stream, raw_id, frag_offset, rlen, &ts))
break;
}
-
+
if (state == 0) {
if (this->keyframe_found) {
if (this->audio_stream == -1) {
@@ -1935,12 +1981,12 @@ 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) {
+ } 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) {
@@ -1965,7 +2011,7 @@ static int demux_asf_seek (demux_plugin_t *this_gen,
}
}
return this->status;
-
+
error:
this->status = DEMUX_FINISHED;
return this->status;
@@ -2059,7 +2105,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
return NULL;
}
- this = xine_xmalloc (sizeof (demux_asf_t));
+ this = calloc(1, sizeof(demux_asf_t));
this->stream = stream;
this->input = input;
@@ -2094,7 +2140,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->demux_plugin.demux_class = class_gen;
this->status = DEMUX_FINISHED;
-
+
return &this->demux_plugin;
}
@@ -2134,7 +2180,7 @@ static void *init_class (xine_t *xine, void *data) {
demux_asf_class_t *this;
- this = xine_xmalloc (sizeof (demux_asf_class_t));
+ this = calloc(1, sizeof(demux_asf_class_t));
this->config = xine->config;
this->xine = xine;
@@ -2155,7 +2201,7 @@ static void *init_class (xine_t *xine, void *data) {
static const demuxer_info_t demux_info_asf = {
10 /* priority */
};
-
+
const plugin_info_t xine_plugin_info[] EXPORTED = {
/* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "asf", XINE_VERSION_CODE, &demux_info_asf, init_class },
diff --git a/src/demuxers/demux_aud.c b/src/demuxers/demux_aud.c
index a6f88ff48..caaa4e91a 100644
--- a/src/demuxers/demux_aud.c
+++ b/src/demuxers/demux_aud.c
@@ -105,7 +105,7 @@ remove this case for the time being since this audio type is not supported
anyway.
if (header[11] == 1)
this->audio_type = BUF_AUDIO_WESTWOOD;
- else
+ else
#endif
if (header[11] == 99)
this->audio_type = BUF_AUDIO_VQA_IMA;
@@ -143,7 +143,7 @@ static int demux_aud_send_chunk(demux_plugin_t *this_gen) {
}
/* validate the chunk */
- if (_X_LE_32(&chunk_preamble[4]) != 0x0000DEAF) {
+ if (!_x_is_fourcc(&chunk_preamble[4], "\xAF\xDE\x00\x00")) {
this->status = DEMUX_FINISHED;
return this->status;
}
@@ -270,7 +270,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_aud_t *this;
- this = xine_xmalloc (sizeof (demux_aud_t));
+ this = calloc(1, sizeof(demux_aud_t));
this->stream = stream;
this->input = input;
@@ -343,7 +343,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_aud_init_plugin (xine_t *xine, void *data) {
demux_aud_class_t *this;
- this = xine_xmalloc (sizeof (demux_aud_class_t));
+ this = calloc(1, sizeof(demux_aud_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_avi.c b/src/demuxers/demux_avi.c
index 6bb0b289c..100828bd2 100644
--- a/src/demuxers/demux_avi.c
+++ b/src/demuxers/demux_avi.c
@@ -7,12 +7,12 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -134,7 +134,7 @@ typedef struct _avistdindex_chunk {
uint32_t dwReserved3; /* must be 0 */
avistdindex_entry *aIndex;
} avistdindex_chunk;
-
+
/* Base Index Form 'indx' */
typedef struct _avisuperindex_chunk {
@@ -150,7 +150,7 @@ typedef struct _avisuperindex_chunk {
avisuperindex_entry *aIndex; /* where are the ix## chunks */
avistdindex_chunk **stdindex; /* the ix## chunks itself (array) */
} avisuperindex_chunk;
-
+
/* These next three are the video and audio structures that can grow
* during the playback of a streaming file. */
@@ -317,6 +317,8 @@ typedef struct {
getIndex==0, but an operation has been
performed that needs an index */
+#define AVI_ERR_BAD_SIZE 14 /* A chunk has an invalid size */
+
#define AVI_HEADER_UNKNOWN -1
#define AVI_HEADER_AUDIO 0
#define AVI_HEADER_VIDEO 1
@@ -471,7 +473,7 @@ static int start_pos_stopper(demux_avi_t *this, void *data) {
maxframe--;
}
return -1;
-}
+}
/* Use this one to ensure that a video frame with the given timestamp
* is in the index. */
@@ -598,11 +600,11 @@ static int idx_grow(demux_avi_t *this, int (*stopper)(demux_avi_t *, void *),
}
} else {
int i;
-
+
/* Audio chunk */
for(i = 0; i < this->avi->n_audio; ++i) {
avi_audio_t *audio = this->avi->audio[i];
-
+
if ((data[0] == audio->audio_tag[0]) &&
(data[1] == audio->audio_tag[1])) {
off_t pos = chunk_pos + AVI_HEADER_SIZE;
@@ -615,7 +617,7 @@ static int idx_grow(demux_avi_t *this, int (*stopper)(demux_avi_t *, void *),
} else {
audio->block_no += 1;
}
-
+
if (audio_index_append(this->avi, i, pos, chunk_len, audio->audio_tot,
audio->block_no) == -1) {
/* As above. */
@@ -709,17 +711,17 @@ do { \
static void reset_idx(demux_avi_t *this, avi_t *AVI) {
int n;
-
+
this->idx_grow.nexttagoffset = AVI->movi_start;
this->has_index = 0;
-
+
AVI->video_idx.video_frames = 0;
for(n = 0; n < AVI->n_audio; n++) {
AVI->audio[n]->audio_idx.audio_chunks = 0;
}
}
-static avi_t *AVI_init(demux_avi_t *this) {
+static avi_t *XINE_MALLOC AVI_init(demux_avi_t *this) {
avi_t *AVI;
int i, j, idx_type;
@@ -739,7 +741,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* Create avi_t structure */
lprintf("start\n");
- AVI = (avi_t *) xine_xmalloc(sizeof(avi_t));
+ AVI = (avi_t *) calloc(1, sizeof(avi_t));
if(AVI==NULL) {
this->AVI_errno = AVI_ERR_NO_MEM;
return 0;
@@ -776,28 +778,28 @@ static avi_t *AVI_init(demux_avi_t *this) {
n = _X_LE_32(data + 4);
n = PAD_EVEN(n);
next_chunk = this->idx_grow.nexttagoffset + 8 + n;
-
+
lprintf("chunk: %c%c%c%c, size: %" PRId64 "\n",
data[0], data[1], data[2], data[3], (int64_t)n);
-
- if((strncasecmp(data,"LIST",4) == 0) && (n >= 4)) {
+
+ if (n >= 4 && strncasecmp(data,"LIST",4) == 0) {
if( this->input->read(this->input, data,4) != 4 ) ERR_EXIT(AVI_ERR_READ);
n -= 4;
-
+
lprintf(" chunk: %c%c%c%c\n",
data[0], data[1], data[2], data[3]);
if(strncasecmp(data,"hdrl",4) == 0) {
hdrl_len = n;
- hdrl_data = (unsigned char *) xine_xmalloc(n);
+ hdrl_data = (unsigned char *) malloc(n);
if(hdrl_data==0)
ERR_EXIT(AVI_ERR_NO_MEM);
if (this->input->read(this->input, hdrl_data,n) != n )
ERR_EXIT(AVI_ERR_READ);
} else if(strncasecmp(data,"movi",4) == 0) {
-
+
AVI->movi_start = this->input->get_current_pos(this->input);
AVI->movi_end = AVI->movi_start + n - 1;
@@ -812,9 +814,8 @@ static avi_t *AVI_init(demux_avi_t *this) {
break if this is not the case */
AVI->n_idx = AVI->max_idx = n / 16;
- if (AVI->idx)
- free(AVI->idx); /* On the off chance there are multiple index chunks */
- AVI->idx = (unsigned char((*)[16])) xine_xmalloc(n);
+ free(AVI->idx); /* On the off chance there are multiple index chunks */
+ AVI->idx = (unsigned char((*)[16])) malloc(n);
if (AVI->idx == 0)
ERR_EXIT(AVI_ERR_NO_MEM);
@@ -836,6 +837,8 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* Interpret the header list */
for (i = 0; i < hdrl_len;) {
+ const int old_i = i;
+
/* List tags are completly ignored */
lprintf("tag: %c%c%c%c\n",
hdrl_data[i], hdrl_data[i+1], hdrl_data[i+2], hdrl_data[i+3]);
@@ -874,15 +877,14 @@ static avi_t *AVI_init(demux_avi_t *this) {
lasttag = 1; /* vids */
lprintf("dwScale=%d, dwRate=%d, dwInitialFrames=%d, dwStart=%d, num_stream=%d\n",
AVI->dwScale, AVI->dwRate, AVI->dwInitialFrames, AVI->dwStart, num_stream);
-
+
} else if (strncasecmp (hdrl_data+i,"auds",4) ==0 /* && ! auds_strh_seen*/) {
if(AVI->n_audio < MAX_AUDIO_STREAMS) {
- avi_audio_t *a = (avi_audio_t *) xine_xmalloc(sizeof(avi_audio_t));
+ avi_audio_t *a = (avi_audio_t *) calloc(1, sizeof(avi_audio_t));
if(a==NULL) {
this->AVI_errno = AVI_ERR_NO_MEM;
return 0;
}
- memset((void *)a,0,sizeof(avi_audio_t));
AVI->audio[AVI->n_audio] = a;
a->audio_strn = num_stream;
@@ -890,10 +892,10 @@ static avi_t *AVI_init(demux_avi_t *this) {
a->dwScale = _X_LE_32(hdrl_data + i + 20);
a->dwRate = _X_LE_32(hdrl_data + i + 24);
a->dwStart = _X_LE_32(hdrl_data + i + 28);
-
+
lprintf("dwScale=%d, dwRate=%d, dwInitialFrames=%d, dwStart=%d, num_stream=%d\n",
a->dwScale, a->dwRate, a->dwInitialFrames, a->dwStart, num_stream);
-
+
a->dwSampleSize = _X_LE_32(hdrl_data + i + 44);
a->audio_tot = 0;
auds_strh_seen = 1;
@@ -907,14 +909,14 @@ static avi_t *AVI_init(demux_avi_t *this) {
lasttag = 0;
}
num_stream++;
-
+
} else if(strncasecmp(hdrl_data+i,"dmlh",4) == 0) {
AVI->total_frames = _X_LE_32(hdrl_data+i+8);
#ifdef DEBUG_ODML
lprintf( "AVI: real number of frames %d\n", AVI->total_frames);
#endif
i += 8;
-
+
} else if(strncasecmp(hdrl_data + i, "strf", 4) == 0) {
i += 4;
strf_size = _X_LE_32(hdrl_data + i);
@@ -922,7 +924,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
if(lasttag == 1) {
/* lprintf ("size : %d\n",sizeof(AVI->bih)); */
AVI->bih = (xine_bmiheader *)
- xine_xmalloc((n < sizeof(xine_bmiheader)) ? sizeof(xine_bmiheader) : n);
+ malloc((n < sizeof(xine_bmiheader)) ? sizeof(xine_bmiheader) : n);
if(AVI->bih == NULL) {
this->AVI_errno = AVI_ERR_NO_MEM;
return 0;
@@ -971,8 +973,12 @@ static avi_t *AVI_init(demux_avi_t *this) {
} else if(lasttag == 2) {
xine_waveformatex *wavex;
-
+
wavex = (xine_waveformatex *)malloc(n);
+ if (!wavex) {
+ this->AVI_errno = AVI_ERR_NO_MEM;
+ return 0;
+ }
memcpy((void *)wavex, hdrl_data+i, n);
_x_waveformatex_le2me( wavex );
@@ -1079,6 +1085,8 @@ static avi_t *AVI_init(demux_avi_t *this) {
lasttag = 0;
}
i += n;
+ if (i <= old_i)
+ ERR_EXIT(AVI_ERR_BAD_SIZE);
}
if( hdrl_data )
@@ -1167,7 +1175,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
}
lprintf("idx_type=%d, AVI->n_idx=%d\n", idx_type, AVI->n_idx);
-
+
if (idx_type != 0 && !AVI->is_opendml) {
/* Now generate the video index and audio index arrays from the
* idx1 record. */
@@ -1224,7 +1232,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
"demux_avi: This is an OpenDML stream\n");
nvi = 0;
- for(audtr=0; audtr<AVI->n_audio; ++audtr) nai[audtr] = 0;
+ for(audtr=0; audtr<AVI->n_audio; ++audtr) nai[audtr] = 0;
/* ************************ */
/* VIDEO */
@@ -1237,6 +1245,9 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* read from file */
chunk_start = en = malloc (AVI->video_superindex->aIndex[j].dwSize+hdrl_len);
+ if (!chunk_start)
+ ERR_EXIT(AVI_ERR_NO_MEM);
+
if (this->input->seek(this->input, AVI->video_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) {
lprintf("cannot seek to 0x%" PRIx64 "\n", AVI->video_superindex->aIndex[j].qwOffset);
free(chunk_start);
@@ -1289,7 +1300,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
"demux_avi: Warning: the video super index is NULL\n");
}
-
+
/* ************************ */
/* AUDIO */
/* ************************ */
@@ -1308,6 +1319,9 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* read from file */
chunk_start = en = malloc (audio->audio_superindex->aIndex[j].dwSize+hdrl_len);
+ if (!chunk_start)
+ ERR_EXIT(AVI_ERR_NO_MEM);
+
if (this->input->seek(this->input, audio->audio_superindex->aIndex[j].qwOffset, SEEK_SET) == (off_t)-1) {
lprintf("cannot seek to 0x%" PRIx64 "\n", audio->audio_superindex->aIndex[j].qwOffset);
free(chunk_start);
@@ -1330,7 +1344,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
/* skip header */
en += hdrl_len;
nai[audtr] += nrEntries;
-
+
while (k < nai[audtr]) {
off_t pos;
@@ -1338,7 +1352,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
pos = offset + _X_LE_32(en); en += 4;
len = odml_len(en); en += 4;
-
+
/* VBR streams (hack from mplayer) */
if (audio->wavex && audio->wavex->nBlockAlign) {
audio->block_no += (len + audio->wavex->nBlockAlign - 1) /
@@ -1380,7 +1394,7 @@ static avi_t *AVI_init(demux_avi_t *this) {
this->idx_grow.nexttagoffset = AVI->movi_start;
this->has_index = 0;
}
-
+
/* Reposition the file */
if (!this->streaming)
this->input->seek(this->input, AVI->movi_start, SEEK_SET);
@@ -1466,7 +1480,7 @@ static int AVI_read_video(demux_avi_t *this, avi_t *AVI, char *vidbuf,
nr = 0; /* total number of bytes read */
left = vie->len - AVI->video_posb;
-
+
while ((bytes > 0) && (left > 0)) {
if (bytes < left)
todo = bytes;
@@ -1508,7 +1522,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
int audio_sent = 0;
lprintf("begin\n");
-
+
/* Try to grow the index, in case more of the avi file has shown up
* since we last checked. If it's still too small, well then we're at
* the end of the stream. */
@@ -1517,7 +1531,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
lprintf("end of stream\n");
}
}
-
+
for (i = 0; i < this->avi->n_audio; i++) {
avi_audio_t *audio = this->avi->audio[i];
@@ -1528,7 +1542,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
}
}
}
-
+
video_pts = get_video_pts (this, this->avi->video_posf);
for (i=0; i < this->avi->n_audio; i++) {
@@ -1554,7 +1568,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
/* read audio */
buf->pts = audio_pts;
-
+
buf->size = AVI_read_audio (this, audio, buf->mem, buf->max_size, &buf->decoder_flags);
buf->decoder_flags |= decoder_flags;
@@ -1566,12 +1580,12 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
buf->type = audio->audio_type | i;
buf->extra_info->input_time = audio_pts / 90;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
-
+
check_newpts (this, buf->pts, PTS_AUDIO);
this->audio_fifo->put (this->audio_fifo, buf);
-
+
audio_sent++;
}
} else
@@ -1581,7 +1595,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
if (audio_sent == 0) {
do_read_video = 1;
}
-
+
if (do_read_video) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
@@ -1597,12 +1611,12 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
if (this->has_index && this->avi->video_idx.video_frames > 2) {
/* use video_frames-2 instead of video_frames-1 to fix problems with weird
non-interleaved streams */
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 /
this->avi->video_idx.vindex[this->avi->video_idx.video_frames - 2].pos);
} else {
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
}
buf->extra_info->frame_number = this->avi->video_posf;
@@ -1617,7 +1631,7 @@ static int demux_avi_next (demux_avi_t *this, int decoder_flags) {
lprintf ("adding buf %d to video fifo, decoder_info[0]: %d\n",
buf, buf->decoder_info[0]);
*/
-
+
check_newpts (this, buf->pts, PTS_VIDEO);
this->video_fifo->put (this->video_fifo, buf);
video_sent++;
@@ -1738,7 +1752,7 @@ static int demux_avi_next_streaming (demux_avi_t *this, int decoder_flags) {
}
buf->extra_info->input_time = audio_pts / 90;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->type = audio->audio_type | audio_stream;
@@ -1769,7 +1783,7 @@ static int demux_avi_next_streaming (demux_avi_t *this, int decoder_flags) {
/* read video */
buf->pts = video_pts;
lprintf("video pts: %" PRId64 "\n", video_pts);
-
+
if (left > this->video_fifo->buffer_pool_buf_size) {
buf->size = this->video_fifo->buffer_pool_buf_size;
buf->decoder_flags = 0;
@@ -1824,7 +1838,7 @@ static int demux_avi_send_chunk (demux_plugin_t *this_gen) {
this->seek_request = 0;
demux_avi_seek_internal(this);
}
-
+
if (!demux_avi_next (this, 0)) {
this->status = DEMUX_FINISHED;
}
@@ -1904,7 +1918,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) {
this->avi->bih->biCompression = this->avi->compressor;
this->avi->video_type = BUF_VIDEO_XVID;
}
-
+
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, !this->no_audio);
_x_meta_info_set(this->stream, XINE_META_INFO_VIDEOCODEC, _x_buf_video_name(this->avi->video_type));
@@ -1922,7 +1936,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) {
_x_demux_control_start (this->stream);
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
-
+
if (this->avi->bih->biSize > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_avi: private video decoder data length (%d) is greater than fifo buffer length (%d)\n",
@@ -1931,9 +1945,9 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) {
this->status = DEMUX_FINISHED;
return;
}
-
+
/* wait, before sending out the video header, one more special case hack:
- * if the video type is RGB, indicate that it is upside down with a
+ * if the video type is RGB, indicate that it is upside down with a
* negative height */
if (this->avi->video_type == BUF_VIDEO_RGB) {
this->avi->bih->biHeight = -this->avi->bih->biHeight;
@@ -1944,7 +1958,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) {
buf->decoder_info[0] = this->video_step;
memcpy (buf->content, this->avi->bih, this->avi->bih->biSize);
buf->size = this->avi->bih->biSize;
-
+
if (this->avi->video_type) {
this->avi->compressor = this->avi->bih->biCompression;
} else {
@@ -1992,7 +2006,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) {
buf->size = todo;
}
todo -= buf->size;
-
+
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER;
if (todo == 0)
buf->decoder_flags |= BUF_FLAG_FRAME_END;
@@ -2009,7 +2023,7 @@ static void demux_avi_send_headers (demux_plugin_t *this_gen) {
}
if(this->avi->n_audio == 1)
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC,
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC,
this->avi->audio[0]->wavex->wFormatTag);
}
@@ -2059,7 +2073,7 @@ static int demux_avi_seek_internal (demux_avi_t *this) {
int64_t audio_pts;
off_t start_pos = this->seek_start_pos;
int start_time = this->seek_start_time;
-
+
start_pos = (off_t) ( (double) start_pos / 65535 *
this->input->get_length (this->input) );
@@ -2094,12 +2108,12 @@ static int demux_avi_seek_internal (demux_avi_t *this) {
video_pts = start_time * 90;
idx_grow(this, start_time_stopper, &video_pts);
}
-
+
if (start_pos || start_time)
max_pos = this->avi->video_idx.video_frames - 1;
else
max_pos=0;
-
+
cur_pos = this->avi->video_posf;
if (max_pos < 0) {
this->status = DEMUX_FINISHED;
@@ -2127,7 +2141,7 @@ static int demux_avi_seek_internal (demux_avi_t *this) {
}
}
}
-
+
while (vie && !(vie->flags & AVIIF_KEYFRAME) && cur_pos) {
this->avi->video_posf = --cur_pos;
vie = video_cur_index_entry(this);
@@ -2150,7 +2164,7 @@ static int demux_avi_seek_internal (demux_avi_t *this) {
if (!this->no_audio && this->status == DEMUX_OK) {
audio_index_entry_t *aie;
int i;
-
+
for(i = 0; i < this->avi->n_audio; i++) {
max_pos = this->avi->audio[i]->audio_idx.audio_chunks - 1;
min_pos = 0;
@@ -2271,7 +2285,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_avi_t));
+ this = calloc(1, sizeof(demux_avi_t));
this->stream = stream;
this->input = input;
@@ -2337,7 +2351,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_class (xine_t *xine, void *data) {
demux_avi_class_t *this;
- this = xine_xmalloc (sizeof (demux_avi_class_t));
+ this = calloc(1, sizeof(demux_avi_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_cdda.c b/src/demuxers/demux_cdda.c
index 0f34a7cec..6aee5042e 100644
--- a/src/demuxers/demux_cdda.c
+++ b/src/demuxers/demux_cdda.c
@@ -60,6 +60,7 @@ typedef struct {
input_plugin_t *input;
int status;
+ int send_newpts;
int seek_flag; /* this is set when a seek just occurred */
} demux_cdda_t;
@@ -83,7 +84,7 @@ static int demux_cdda_send_chunk (demux_plugin_t *this_gen) {
buf->type = BUF_AUDIO_LPCM_LE;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->pts = this->input->get_current_pos(this->input);
buf->pts *= 90000;
@@ -91,9 +92,9 @@ static int demux_cdda_send_chunk (demux_plugin_t *this_gen) {
buf->extra_info->input_time = buf->pts / 90;
buf->decoder_flags |= BUF_FLAG_FRAME_END;
- if (this->seek_flag) {
- _x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK);
- this->seek_flag = 0;
+ if (this->send_newpts) {
+ _x_demux_control_newpts(this->stream, buf->pts, this->seek_flag);
+ this->send_newpts = this->seek_flag = 0;
}
this->audio_fifo->put (this->audio_fifo, buf);
@@ -146,9 +147,14 @@ static int demux_cdda_seek (demux_plugin_t *this_gen, off_t start_pos, int start
this->input->seek(this->input, start_pos & ~3, SEEK_SET);
else
this->input->seek(this->input, start_time * CD_BYTES_PER_SECOND, SEEK_SET);
- this->seek_flag = 1;
+
this->status = DEMUX_OK;
- _x_demux_flush_engine (this->stream);
+
+ this->send_newpts = 1;
+ if (playing) {
+ this->seek_flag = BUF_FLAG_SEEK;
+ _x_demux_flush_engine (this->stream);
+ }
return this->status;
}
@@ -187,7 +193,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_cdda_t *this;
- this = xine_xmalloc (sizeof (demux_cdda_t));
+ this = calloc(1, sizeof(demux_cdda_t));
this->stream = stream;
this->input = input;
@@ -250,7 +256,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_cdda_init_plugin (xine_t *xine, void *data) {
demux_cdda_class_t *this;
- this = xine_xmalloc (sizeof (demux_cdda_class_t));
+ this = calloc(1, sizeof(demux_cdda_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_dts.c b/src/demuxers/demux_dts.c
index 7c9b47fcd..0c73877e9 100644
--- a/src/demuxers/demux_dts.c
+++ b/src/demuxers/demux_dts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005 the xine project
+ * Copyright (C) 2005-2008 the xine project
*
* This file is part of xine, a free video player.
*
@@ -33,6 +33,9 @@
#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#define LOG_MODULE "demux_dts"
#define LOG_VERBOSE
@@ -140,29 +143,69 @@ static int open_dts_file(demux_dts_t *this) {
}
}
+ /* DTS bitstream encoding version
+ * -1 - not detected
+ * 0 - 16 bits and big endian
+ * 1 - 16 bits and low endian (detection not implemented)
+ * 2 - 14 bits and big endian (detection not implemented)
+ * 3 - 14 bits and low endian
+ */
+ int dts_version = -1;
+
/* Look for a valid DTS syncword */
for (i=offset; i<peak_size-1; i++) {
+ /* 16 bits and big endian bitstream */
+ if (syncword == 0x7ffe8001) {
+ dts_version = 0;
+ break;
+ }
/* 14 bits and little endian bitstream */
- if ((syncword == 0xff1f00e8) &&
- ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) {
- this->data_start = i-4;
- lprintf("found DTS syncword at offset %d\n", i-4);
- break;
+ else if ((syncword == 0xff1f00e8) &&
+ ((peak[i] & 0xf0) == 0xf0) && (peak[i+1] == 0x07)) {
+ dts_version = 3;
+ break;
}
syncword = (syncword << 8) | peak[i];
}
+ if (dts_version == -1) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": unsupported DTS stream type, or not a DTS stream\n");
+ return 0;
+ }
+
+ this->data_start = i-4;
+ lprintf("found DTS syncword at offset %d\n", i-4);
+
if (i < peak_size-9) {
unsigned int nblks, fsize, sfreq;
+ switch (dts_version)
+ {
+ case 0: /* BE16 */
+ nblks = ((peak[this->data_start+4] & 0x01) << 6) |
+ ((peak[this->data_start+5] & 0xfc) >> 2);
+ fsize = (((peak[this->data_start+5] & 0x03) << 12) |(peak[this->data_start+6] << 4) |
+ ((peak[this->data_start+7] & 0xf0) >> 4)) + 1;
+ sfreq = (peak[this->data_start+8] & 0x3c) >> 2;
+ break;
- /* 14 bits and little endian bitstream */
- nblks = ((peak[this->data_start+4] & 0x07) << 4) |
- ((peak[this->data_start+7] & 0x3c) >> 2);
- fsize = (((peak[this->data_start+7] & 0x03) << 12) |
- (peak[this->data_start+6] << 4) |
- ((peak[this->data_start+9] & 0x3c) >> 2)) + 1;
- sfreq = peak[this->data_start+8] & 0x0f;
+ case 3: /* LE14 */
+ nblks = ((peak[this->data_start+4] & 0x07) << 4) |
+ ((peak[this->data_start+7] & 0x3c) >> 2);
+ fsize = (((peak[this->data_start+7] & 0x03) << 12) |
+ (peak[this->data_start+6] << 4) |
+ ((peak[this->data_start+9] & 0x3c) >> 2)) + 1;
+ sfreq = peak[this->data_start+8] & 0x0f;
+ break;
+
+ default:
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": unsupported DTS bitstream encoding %d\n",
+ dts_version);
+ return 0;
+
+ }
if ((sfreq > sizeof(dts_sample_rates)/sizeof(int)) ||
(dts_sample_rates[sfreq] == 0))
@@ -170,7 +213,19 @@ static int open_dts_file(demux_dts_t *this) {
/* Big assumption - this is CBR data */
this->samples_per_frame = (nblks + 1) * 32;
- this->frame_size = fsize * 8 / 14 * 2;
+
+ switch (dts_version)
+ {
+ case 0: /* BE16 */
+ case 1: /* LE16 */
+ this->frame_size = fsize * 8 / 16 * 2;
+ break;
+ case 2: /* BE14 */
+ case 3: /* LE14 */
+ this->frame_size = fsize * 8 / 14 * 2;
+ break;
+ }
+
this->sample_rate = dts_sample_rates[sfreq];
lprintf("samples per frame: %d\n", this->samples_per_frame);
@@ -195,7 +250,7 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) {
int frame_number;
uint32_t blocksize;
- current_stream_pos = this->input->get_current_pos(this->input) -
+ current_stream_pos = this->input->get_current_pos(this->input) -
this->data_start;
frame_number = current_stream_pos / this->frame_size;
@@ -219,11 +274,11 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) {
}
} else {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
- buf->size = this->input->read(this->input, buf->content,
+ buf->size = this->input->read(this->input, buf->content,
this->frame_size);
}
- if (buf->size == 0) {
+ if (buf->size <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
@@ -231,7 +286,7 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) {
buf->type = BUF_AUDIO_DTS;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) current_stream_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_stream_pos *
65535 / (this->input->get_length(this->input) - this->data_start) );
buf->extra_info->input_time = audio_pts / 90;
buf->pts = audio_pts;
@@ -305,7 +360,7 @@ static int demux_dts_seek (demux_plugin_t *this_gen,
if (start_time) {
int length = demux_dts_get_stream_length (this_gen);
if (length != 0) {
- start_pos = start_time *
+ start_pos = start_time *
(this->input->get_length(this->input) - this->data_start) / length;
}
}
@@ -346,7 +401,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_dts_t *this;
- this = xine_xmalloc (sizeof (demux_dts_t));
+ this = calloc(1, sizeof(demux_dts_t));
this->stream = stream;
this->input = input;
@@ -418,7 +473,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_dts_init_plugin (xine_t *xine, void *data) {
demux_dts_class_t *this;
- this = xine_xmalloc (sizeof (demux_dts_class_t));
+ this = calloc(1, sizeof(demux_dts_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_eawve.c b/src/demuxers/demux_eawve.c
index 2359d3baf..2e393847c 100644
--- a/src/demuxers/demux_eawve.c
+++ b/src/demuxers/demux_eawve.c
@@ -78,16 +78,16 @@ typedef struct {
*/
static uint32_t read_arbitary(input_plugin_t *input){
- uint8_t size, byte;
- int i;
- uint32_t word;
+ uint8_t size;
if (input->read(input, (void*)&size, 1) != 1) {
return 0;
}
- word = 0;
+ uint32_t word = 0;
+ int i;
for (i=0;i<size;i++) {
+ uint8_t byte;
if (input->read(input, (void*)&byte, 1) != 1) {
return 0;
}
@@ -104,33 +104,25 @@ static uint32_t read_arbitary(input_plugin_t *input){
*/
static int process_header(demux_eawve_t *this){
- int inHeader;
- uint32_t blockid, size;
+ uint8_t header[12];
if (this->input->get_current_pos(this->input) != 0)
this->input->seek(this->input, 0, SEEK_SET);
- if (this->input->read(this->input, (void*)&blockid, 4) != 4) {
- return 0;
- }
- if (be2me_32(blockid) != FOURCC_TAG('S', 'C', 'H', 'l')) {
+ if (this->input->read(this->input, header, sizeof(header)) != sizeof(header))
return 0;
- }
- if (this->input->read(this->input, (void*)&size, 4) != 4) {
+ if (!_x_is_fourcc(&header[0], "SCHl"))
return 0;
- }
- size = le2me_32(size);
- if (this->input->read(this->input, (void*)&blockid, 4) != 4) {
- return 0;
- }
- if (be2me_32(blockid) != FOURCC_TAG('P', 'T', '\0', '\0')) {
+ if (!_x_is_fourcc(&header[8], "PT\0\0")) {
lprintf("PT header missing\n");
return 0;
}
- inHeader = 1;
+ const uint32_t size = _X_LE_32(&header[4]);
+
+ int inHeader = 1;
while (inHeader) {
int inSubheader;
uint8_t byte;
@@ -221,7 +213,7 @@ static int demux_eawve_send_chunk(demux_eawve_t *this){
buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
buf->type = BUF_AUDIO_EA_ADPCM;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = (int)((int64_t)this->sample_counter * 1000 / 22050);
buf->pts = this->sample_counter;
@@ -349,7 +341,7 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre
if (!INPUT_IS_SEEKABLE(input))
return NULL;
- this = xine_xmalloc(sizeof(demux_eawve_t));
+ this = calloc(1, sizeof(demux_eawve_t));
this->stream = stream;
this->input = input;
@@ -421,7 +413,7 @@ static void class_dispose(demux_class_t *this){
void *demux_eawve_init_plugin(xine_t *xine, void *data) {
demux_eawve_class_t *this;
- this = xine_xmalloc(sizeof(demux_eawve_class_t));
+ this = calloc(1, sizeof(demux_eawve_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_elem.c b/src/demuxers/demux_elem.c
index d0a821504..d38fe3c62 100644
--- a/src/demuxers/demux_elem.c
+++ b/src/demuxers/demux_elem.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -46,7 +46,7 @@
#define NUM_PREVIEW_BUFFERS 50
#define SCRATCH_SIZE 256
-typedef struct {
+typedef struct {
demux_plugin_t demux_plugin;
xine_stream_t *stream;
@@ -83,7 +83,7 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) {
buf->content = buf->mem;
buf->pts = 0;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->type = BUF_VIDEO_MPEG;
@@ -91,7 +91,7 @@ static int demux_mpeg_elem_next (demux_mpeg_elem_t *this, int preview_mode) {
buf->decoder_flags = BUF_FLAG_PREVIEW;
this->video_fifo->put(this->video_fifo, buf);
-
+
return 1;
}
@@ -240,7 +240,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_mpeg_elem_t));
+ this = calloc(1, sizeof(demux_mpeg_elem_t));
this->stream = stream;
this->input = input;
@@ -284,7 +284,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_mpeg_elem_class_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_elem_class_t));
+ this = calloc(1, sizeof(demux_mpeg_elem_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
@@ -304,7 +304,7 @@ static const demuxer_info_t demux_info_elem = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "elem", XINE_VERSION_CODE, &demux_info_elem, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c
index 13036afc1..a8bd0b288 100644
--- a/src/demuxers/demux_film.c
+++ b/src/demuxers/demux_film.c
@@ -141,9 +141,9 @@ static int open_film_file(demux_film_t *film) {
return 0;
/* FILM signature correct? */
- if (strncmp(scratch, "FILM", 4)) {
+ if (!_x_is_fourcc(scratch, "FILM"))
return 0;
- }
+
llprintf(DEBUG_FILM_LOAD, "found 'FILM' signature\n");
/* file is qualified; skip over the header bytes in the stream */
@@ -151,7 +151,7 @@ static int open_film_file(demux_film_t *film) {
/* header size = header size - 16-byte FILM signature */
film_header_size = _X_BE_32(&scratch[4]) - 16;
- film_header = xine_xmalloc(film_header_size);
+ film_header = malloc(film_header_size);
if (!film_header)
return 0;
strncpy(film->version, &scratch[8], 4);
@@ -163,7 +163,7 @@ static int open_film_file(demux_film_t *film) {
film->version[3]);
/* load the rest of the FILM header */
- if (film->input->read(film->input, film_header, film_header_size) !=
+ if (film->input->read(film->input, film_header, film_header_size) !=
film_header_size) {
free (film->interleave_buffer);
free (film->sample_table);
@@ -202,7 +202,7 @@ static int open_film_file(demux_film_t *film) {
if( !film->video_type )
film->video_type = BUF_VIDEO_UNKNOWN;
-
+
/* fetch the audio information if the chunk size checks out */
if (chunk_size == 32) {
film->audio_channels = film_header[21];
@@ -256,7 +256,9 @@ static int open_film_file(demux_film_t *film) {
film->frequency = _X_BE_32(&film_header[i + 8]);
film->sample_count = _X_BE_32(&film_header[i + 12]);
film->sample_table =
- xine_xmalloc(film->sample_count * sizeof(film_sample_t));
+ calloc(film->sample_count, sizeof(film_sample_t));
+ if (!film->sample_table)
+ goto film_abort;
for (j = 0; j < film->sample_count; j++) {
film->sample_table[j].sample_offset =
@@ -329,15 +331,16 @@ static int open_film_file(demux_film_t *film) {
/* allocate enough space in the interleave preload buffer for the
* first chunk (which will be more than enough for successive chunks) */
if (film->audio_type) {
- if (film->interleave_buffer)
- free(film->interleave_buffer);
- film->interleave_buffer =
- xine_xmalloc(film->sample_table[0].sample_size);
+ free(film->interleave_buffer);
+ film->interleave_buffer = calloc(1, film->sample_table[0].sample_size);
+ if (!film->interleave_buffer)
+ goto film_abort;
}
break;
default:
xine_log(film->stream->xine, XINE_LOG_MSG, _("unrecognized FILM chunk\n"));
+ film_abort:
free (film->interleave_buffer);
free (film->sample_table);
free (film_header);
@@ -385,7 +388,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
}
/* check if we're only sending audio samples until the next keyframe */
- if ((this->waiting_for_keyframe) &&
+ if ((this->waiting_for_keyframe) &&
(!this->sample_table[i].audio)) {
if (this->sample_table[i].keyframe) {
this->waiting_for_keyframe = 0;
@@ -425,7 +428,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
/* set the frame duration */
buf->decoder_flags |= BUF_FLAG_FRAMERATE;
buf->decoder_info[0] = this->sample_table[i].duration;
-
+
if (remaining_sample_bytes > buf->max_size)
buf->size = buf->max_size;
else
@@ -440,11 +443,11 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
}
/* skip over the extra non-spec CVID bytes */
- this->input->seek(this->input,
+ this->input->seek(this->input,
this->sample_table[i].sample_size - cvid_chunk_size, SEEK_CUR);
/* load the rest of the chunk */
- if (this->input->read(this->input, buf->content + 10,
+ if (this->input->read(this->input, buf->content + 10,
buf->size - 10) != buf->size - 10) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
@@ -496,7 +499,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
/* set the frame duration */
buf->decoder_flags |= BUF_FLAG_FRAMERATE;
buf->decoder_info[0] = this->sample_table[i].duration;
-
+
if (remaining_sample_bytes > buf->max_size)
buf->size = buf->max_size;
else
@@ -624,8 +627,8 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
buf->content[j] = this->interleave_buffer[k];
buf->content[j + 1] = this->interleave_buffer[k + 1];
}
- for (j = 2,
- k = interleave_index + this->sample_table[i].sample_size / 2;
+ for (j = 2,
+ k = interleave_index + this->sample_table[i].sample_size / 2;
j < buf->size; j += 4, k += 2) {
buf->content[j] = this->interleave_buffer[k];
buf->content[j + 1] = this->interleave_buffer[k + 1];
@@ -635,8 +638,8 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
for (j = 0, k = interleave_index; j < buf->size; j += 2, k += 1) {
buf->content[j] = this->interleave_buffer[k] += 0x80;
}
- for (j = 1,
- k = interleave_index + this->sample_table[i].sample_size / 2;
+ for (j = 1,
+ k = interleave_index + this->sample_table[i].sample_size / 2;
j < buf->size; j += 2, k += 1) {
buf->content[j] = this->interleave_buffer[k] += 0x80;
}
@@ -651,7 +654,7 @@ static int demux_film_send_chunk(demux_plugin_t *this_gen) {
this->audio_fifo->put(this->audio_fifo, buf);
}
}
-
+
return this->status;
}
@@ -734,13 +737,13 @@ static int demux_film_seek (demux_plugin_t *this_gen, off_t start_pos, int start
this->waiting_for_keyframe = 0;
this->last_sample = 0;
}
-
+
/* if input is non-seekable, do not proceed with the rest of this
* seek function */
if (!INPUT_IS_SEEKABLE(this->input))
return this->status;
- /* perform a binary search on the sample table, testing the offset
+ /* perform a binary search on the sample table, testing the offset
* boundaries first */
if (start_pos) {
if (start_pos <= 0)
@@ -757,7 +760,7 @@ static int demux_film_seek (demux_plugin_t *this_gen, off_t start_pos, int start
while (!found) {
middle = (left + right) / 2;
if ((start_pos >= this->sample_table[middle].sample_offset) &&
- (start_pos <= this->sample_table[middle].sample_offset +
+ (start_pos <= this->sample_table[middle].sample_offset +
this->sample_table[middle].sample_size)) {
found = 1;
} else if (start_pos < this->sample_table[middle].sample_offset) {
@@ -814,7 +817,7 @@ static int demux_film_seek (demux_plugin_t *this_gen, off_t start_pos, int start
}
this->current_sample = best_index;
-
+
return this->status;
}
@@ -853,7 +856,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_film_t *this;
- this = xine_xmalloc (sizeof (demux_film_t));
+ this = calloc(1, sizeof(demux_film_t));
this->stream = stream;
this->input = input;
@@ -927,7 +930,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_film_init_plugin (xine_t *xine, void *data) {
demux_film_class_t *this;
- this = xine_xmalloc (sizeof (demux_film_class_t));
+ this = calloc(1, sizeof(demux_film_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_flac.c b/src/demuxers/demux_flac.c
index 3afb5b031..976656016 100644
--- a/src/demuxers/demux_flac.c
+++ b/src/demuxers/demux_flac.c
@@ -33,6 +33,9 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#define LOG_MODULE "demux_flac"
#define LOG_VERBOSE
@@ -116,7 +119,7 @@ static int open_flac_file(demux_flac_t *flac) {
* will always be 1 metadata block */
do {
- if (flac->input->read(flac->input, preamble, FLAC_SIGNATURE_SIZE) !=
+ if (flac->input->read(flac->input, preamble, FLAC_SIGNATURE_SIZE) !=
FLAC_SIGNATURE_SIZE)
return 0;
@@ -130,11 +133,11 @@ static int open_flac_file(demux_flac_t *flac) {
case 0:
lprintf ("STREAMINFO metadata\n");
if (block_length != FLAC_STREAMINFO_SIZE) {
- lprintf ("expected STREAMINFO chunk of %d bytes\n",
+ lprintf ("expected STREAMINFO chunk of %d bytes\n",
FLAC_STREAMINFO_SIZE);
return 0;
}
- if (flac->input->read(flac->input,
+ if (flac->input->read(flac->input,
flac->streaminfo + sizeof(xine_waveformatex),
FLAC_STREAMINFO_SIZE) != FLAC_STREAMINFO_SIZE)
return 0;
@@ -143,8 +146,8 @@ 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 = _X_BE_64(&streaminfo[10]) & UINT64_C(0x0FFFFFFFFF); /* 36 bits */
- lprintf ("%d Hz, %d bits, %d channels, %"PRId64" total samples\n",
- flac->sample_rate, flac->bits_per_sample,
+ lprintf ("%d Hz, %d bits, %d channels, %"PRId64" total samples\n",
+ flac->sample_rate, flac->bits_per_sample,
flac->channels, flac->total_samples);
break;
@@ -164,8 +167,10 @@ static int open_flac_file(demux_flac_t *flac) {
case 3:
lprintf ("SEEKTABLE metadata, %d bytes\n", block_length);
flac->seekpoint_count = block_length / FLAC_SEEKPOINT_SIZE;
- flac->seekpoints = xine_xmalloc(flac->seekpoint_count *
+ flac->seekpoints = calloc(flac->seekpoint_count,
sizeof(flac_seekpoint_t));
+ if (flac->seekpoint_count && !flac->seekpoints)
+ return 0;
for (i = 0; i < flac->seekpoint_count; i++) {
if (flac->input->read(flac->input, buffer, FLAC_SEEKPOINT_SIZE) != FLAC_SEEKPOINT_SIZE)
return 0;
@@ -173,7 +178,7 @@ static int open_flac_file(demux_flac_t *flac) {
lprintf (" %d: sample %"PRId64", ", i, flac->seekpoints[i].sample_number);
flac->seekpoints[i].offset = _X_BE_64(&buffer[8]);
flac->seekpoints[i].size = _X_BE_16(&buffer[16]);
- lprintf ("@ 0x%"PRIX64", 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;
@@ -182,14 +187,14 @@ static int open_flac_file(demux_flac_t *flac) {
}
break;
- /* VORBIS_COMMENT
+ /* VORBIS_COMMENT
*
* For a description of the format please have a look at
* http://www.xiph.org/vorbis/doc/v-comment.html */
case 4:
lprintf ("VORBIS_COMMENT metadata\n");
{
- char comments[block_length];
+ char comments[block_length + 1]; /* last byte for NUL termination */
char *ptr = comments;
uint32_t length, user_comment_list_length;
int cn;
@@ -202,27 +207,37 @@ static int open_flac_file(demux_flac_t *flac) {
length = _X_LE_32(ptr);
ptr += 4 + length;
+ if (length > block_length - 8)
+ return 0; /* bad length or too little left in the buffer */
user_comment_list_length = _X_LE_32(ptr);
ptr += 4;
cn = 0;
for (; cn < user_comment_list_length; cn++) {
+ if (ptr > comments + block_length - 4)
+ return 0; /* too little left in the buffer */
+
length = _X_LE_32(ptr);
ptr += 4;
+ if (length >= block_length || ptr + length > comments + block_length)
+ return 0; /* bad length */
comment = (char*) ptr;
c = comment[length];
- comment[length] = 0;
+ comment[length] = 0; /* NUL termination */
lprintf ("comment[%02d] = %s\n", cn, comment);
- if ((strncasecmp ("TITLE=", comment, 6) == 0)
+ if ((strncasecmp ("TITLE=", comment, 6) == 0)
&& (length - 6 > 0)) {
_x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_TITLE, comment + 6);
} else if ((strncasecmp ("ARTIST=", comment, 7) == 0)
&& (length - 7 > 0)) {
_x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_ARTIST, comment + 7);
+ } else if ((strncasecmp ("COMPOSER=", comment, 9) == 0)
+ && (length - 9 > 0)) {
+ _x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_COMPOSER, comment + 9);
} else if ((strncasecmp ("ALBUM=", comment, 6) == 0)
&& (length - 6 > 0)) {
_x_meta_info_set_utf8 (flac->stream, XINE_META_INFO_ALBUM, comment + 6);
@@ -248,8 +263,8 @@ static int open_flac_file(demux_flac_t *flac) {
}
if ((tracknumber > 0) && (tracktotal > 0)) {
- char tn[16];
- snprintf (tn, 16, "%02d/%02d", tracknumber, tracktotal);
+ char tn[24];
+ snprintf (tn, 24, "%02d/%02d", tracknumber, tracktotal);
_x_meta_info_set(flac->stream, XINE_META_INFO_TRACK_NUMBER, tn);
}
else if (tracknumber > 0) {
@@ -381,12 +396,13 @@ static int demux_flac_seek (demux_plugin_t *this_gen,
demux_flac_t *this = (demux_flac_t *) this_gen;
int seekpoint_index = 0;
int64_t start_pts;
-
+ unsigned char buf[4];
+
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
/* if thread is not running, initialize demuxer */
- if( !playing ) {
+ if( !playing && !start_pos) {
/* send new pts */
_x_demux_control_newpts(this->stream, 0, 0);
@@ -394,28 +410,39 @@ static int demux_flac_seek (demux_plugin_t *this_gen,
this->status = DEMUX_OK;
} else {
- if (this->seekpoints == NULL) {
+ if (this->seekpoints == NULL && !start_pos) {
/* cannot seek if there is no seekpoints */
this->status = DEMUX_OK;
return this->status;
}
- /* do a lazy, linear seek based on the assumption that there are not
- * that many seek points */
+ /* Don't use seekpoints if start_pos != 0. This allows smooth seeking */
if (start_pos) {
/* offset-based seek */
- if (start_pos < this->seekpoints[0].offset)
- seekpoint_index = 0;
- else {
- for (seekpoint_index = 0; seekpoint_index < this->seekpoint_count - 1;
- seekpoint_index++) {
- if (start_pos < this->seekpoints[seekpoint_index + 1].offset) {
- break;
- }
- }
+ this->status = DEMUX_OK;
+ start_pos += this->data_start;
+ this->input->seek(this->input, start_pos, SEEK_SET);
+ while(1){ /* here we try to find something that resembles a frame header */
+
+ if (this->input->read(this->input, buf, 2) != 2){
+ this->status = DEMUX_FINISHED; /* we sought past the end of stream ? */
+ break;
+ }
+
+ if (buf[0] == 0xff && buf[1] == 0xf8)
+ break; /* this might be the frame header... or it may be not. We pass it to the decoder
+ * to decide, but this way we reduce the number of warnings */
+ start_pos +=2;
}
+
+ _x_demux_flush_engine(this->stream);
+ this->input->seek(this->input, start_pos, SEEK_SET);
+ _x_demux_control_newpts(this->stream, 0, BUF_FLAG_SEEK);
+ return this->status;
+
} else {
- /* time-based seek */
+ /* do a lazy, linear seek based on the assumption that there are not
+ * that many seek points; time-based seek */
start_pts = start_time;
start_pts *= 90;
if (start_pts < this->seekpoints[0].pts)
@@ -431,9 +458,9 @@ static int demux_flac_seek (demux_plugin_t *this_gen,
}
_x_demux_flush_engine(this->stream);
- this->input->seek(this->input, this->seekpoints[seekpoint_index].offset,
+ this->input->seek(this->input, this->seekpoints[seekpoint_index].offset,
SEEK_SET);
- _x_demux_control_newpts(this->stream,
+ _x_demux_control_newpts(this->stream,
this->seekpoints[seekpoint_index].pts, BUF_FLAG_SEEK);
}
@@ -444,6 +471,7 @@ static void demux_flac_dispose (demux_plugin_t *this_gen) {
demux_flac_t *this = (demux_flac_t *) this_gen;
free(this->seekpoints);
+ free(this);
}
static int demux_flac_get_status (demux_plugin_t *this_gen) {
@@ -482,7 +510,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_flac_t));
+ this = calloc(1, sizeof(demux_flac_t));
this->stream = stream;
this->input = input;
@@ -544,7 +572,8 @@ static const char *get_extensions (demux_class_t *this_gen) {
}
static const char *get_mimetypes (demux_class_t *this_gen) {
- return NULL;
+ return "audio/x-flac: flac: FLAC Audio;"
+ "audio/flac: flac: FLAC Audio;";
}
static void class_dispose (demux_class_t *this_gen) {
@@ -556,7 +585,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_flac_init_plugin (xine_t *xine, void *data) {
demux_flac_class_t *this;
- this = xine_xmalloc (sizeof (demux_flac_class_t));
+ this = calloc(1, sizeof(demux_flac_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_fli.c b/src/demuxers/demux_fli.c
index 99843a68c..7735671b9 100644
--- a/src/demuxers/demux_fli.c
+++ b/src/demuxers/demux_fli.c
@@ -112,7 +112,7 @@ static int open_fli_file(demux_fli_t *this) {
this->speed = _X_LE_32(&this->fli_header[16]);
if (this->magic_number == FLI_FILE_MAGIC_1) {
- /*
+ /*
* in this case, the speed (n) is number of 1/70s ticks between frames:
*
* xine pts n * frame #
@@ -123,7 +123,7 @@ static int open_fli_file(demux_fli_t *this) {
*/
this->frame_pts_inc = this->speed * 1285.7;
} else if (this->magic_number == FLI_FILE_MAGIC_2) {
- /*
+ /*
* in this case, the speed (n) is number of milliseconds between frames:
*
* xine pts n * frame #
@@ -244,7 +244,7 @@ static void demux_fli_send_headers(demux_plugin_t *this_gen) {
BUF_FLAG_FRAME_END;
buf->decoder_info[0] = this->frame_pts_inc; /* initial video_step */
buf->size = this->bih.biSize;
- memcpy(buf->content, &this->bih, sizeof(xine_bmiheader) + this->bih.biSize);
+ memcpy(buf->content, &this->bih, this->bih.biSize);
buf->type = BUF_VIDEO_FLI;
this->video_fifo->put (this->video_fifo, buf);
}
@@ -303,7 +303,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_fli_t *this;
- this = xine_xmalloc (sizeof (demux_fli_t));
+ this = calloc(1, sizeof(demux_fli_t));
this->stream = stream;
this->input = input;
@@ -377,7 +377,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_fli_class_t *this;
- this = xine_xmalloc (sizeof (demux_fli_class_t));
+ this = calloc(1, sizeof(demux_fli_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_flv.c b/src/demuxers/demux_flv.c
index bdb33d21d..813f33086 100644
--- a/src/demuxers/demux_flv.c
+++ b/src/demuxers/demux_flv.c
@@ -20,11 +20,11 @@
/*
* Flash Video (.flv) File Demuxer
- * by Mike Melanson (melanson@pcisys.net) and
- * Claudio Ciccani (klan@directfb.org)
+ * by Mike Melanson (melanson@pcisys.net) and
+ * Claudio Ciccani (klan@users.sf.net)
*
* For more information on the FLV file format, visit:
- * http://download.macromedia.com/pub/flash/flash_file_format_specification.pdf
+ * http://www.adobe.com/devnet/flv/pdf/video_file_format_spec_v9.pdf
*/
#ifdef HAVE_CONFIG_H
@@ -67,28 +67,28 @@ typedef struct {
unsigned char flags;
off_t start; /* in bytes */
off_t size; /* in bytes */
-
+
unsigned char got_video_header;
unsigned char got_audio_header;
-
+
unsigned int length; /* in ms */
int width;
int height;
int duration;
int videocodec;
-
+
int samplerate;
int samplesize;
int stereo;
int audiocodec;
-
+
off_t filesize;
-
+
flv_index_entry_t *index;
- int num_indices;
-
+ unsigned int num_indices;
+
unsigned int cur_pts;
-
+
int64_t last_pts[2];
int send_newpts;
int buf_flag_seek;
@@ -110,14 +110,20 @@ typedef struct {
#define FLV_SOUND_FORMAT_ADPCM 0x01
#define FLV_SOUND_FORMAT_MP3 0x02
#define FLV_SOUND_FORMAT_PCM_LE 0x03
+#define FLV_SOUND_FORMAT_NELLY16 0x04 /* Nellymoser 16KHz */
#define FLV_SOUND_FORMAT_NELLY8 0x05 /* Nellymoser 8KHz */
#define FLV_SOUND_FORMAT_NELLY 0x06 /* Nellymoser */
+#define FLV_SOUND_FORMAT_ALAW 0x07 /* G.711 A-LAW */
+#define FLV_SOUND_FORMAT_MULAW 0x08 /* G.711 MU-LAW */
+#define FLV_SOUND_FORMAT_AAC 0x0a
+#define FLV_SOUND_FORMAT_MP38 0x0e /* MP3 8KHz */
#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_VIDEO_FORMAT_H264 0x07
#define FLV_DATA_TYPE_NUMBER 0x00
#define FLV_DATA_TYPE_BOOL 0x01
@@ -172,7 +178,7 @@ static int open_flv_file(demux_flv_t *this) {
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]);
@@ -188,10 +194,10 @@ static int open_flv_file(demux_flv_t *this) {
this->start = _X_BE_32(&buffer[5]);
this->size = this->input->get_length(this->input);
-
+
this->input->seek(this->input, this->start, SEEK_SET);
-
- lprintf(" qualified FLV file, repositioned @ offset 0x%" PRIxMAX "\n",
+
+ lprintf(" qualified FLV file, repositioned @ offset 0x%" PRIxMAX "\n",
(intmax_t)this->start);
return 1;
@@ -203,19 +209,19 @@ static int open_flv_file(demux_flv_t *this) {
_tmp.d;\
})\
-static int parse_flv_var(demux_flv_t *this,
+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;
-
+ unsigned 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));
@@ -283,6 +289,8 @@ static int parse_flv_var(demux_flv_t *this,
str = tmp + 2;
tmp += len + 2;
len = parse_flv_var(this, tmp, end-tmp, str, len);
+ if (!len)
+ return 0;
tmp += len;
}
if (*tmp++ != FLV_DATA_TYPE_ENDOBJECT)
@@ -298,6 +306,8 @@ static int parse_flv_var(demux_flv_t *this,
str = tmp + 2;
tmp += len + 2;
len = parse_flv_var(this, tmp, end-tmp, str, len);
+ if (!len)
+ return 0;
tmp += len;
}
break;
@@ -306,10 +316,14 @@ static int parse_flv_var(demux_flv_t *this,
num = _X_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;
+ if (!this->index || this->num_indices != num) {
+ if (this->index)
+ free(this->index);
+ this->index = calloc(num, sizeof(flv_index_entry_t));
+ if (!this->index)
+ return 0;
+ 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));
@@ -320,19 +334,27 @@ static int parse_flv_var(demux_flv_t *this,
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;
- }
+ if (!this->index || this->num_indices != num) {
+ if (this->index)
+ free(this->index);
+ this->index = calloc(num, sizeof(flv_index_entry_t));
+ if (!this->index)
+ return 0;
+ 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;
}
+ break;
}
while (num-- && tmp < end) {
len = parse_flv_var(this, tmp, end-tmp, NULL, 0);
+ if (!len)
+ return 0;
tmp += len;
}
break;
@@ -344,17 +366,17 @@ static int parse_flv_var(demux_flv_t *this,
lprintf(" got type %d\n", type);
break;
}
-
+
return (tmp - buf);
}
static void parse_flv_script(demux_flv_t *this, int size) {
- unsigned char *buf = xine_xmalloc(size);
+ unsigned char *buf = malloc(size);
unsigned char *tmp = buf;
unsigned char *end = buf + size;
int len;
-
- if (this->input->read(this->input, buf, size ) != size) {
+
+ if (!buf || this->input->read(this->input, buf, size ) != size) {
this->status = DEMUX_FINISHED;
free(buf);
return;
@@ -366,7 +388,7 @@ static void parse_flv_script(demux_flv_t *this, int size) {
break;
tmp += len;
}
-
+
free(buf);
}
@@ -379,7 +401,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
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);
@@ -391,7 +413,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
tag_type = buffer[0];
remaining_bytes = _X_BE_24(&buffer[1]);
pts = _X_BE_24(&buffer[4]) | (buffer[7] << 24);
-
+
lprintf(" tag_type = 0x%02X, 0x%X bytes, pts %u\n",
tag_type, remaining_bytes, pts/90);
@@ -400,10 +422,10 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
lprintf(" got audio tag..\n");
if (this->input->read(this->input, buffer, 1) != 1) {
this->status = DEMUX_FINISHED;
- return this->status;
+ return this->status;
}
remaining_bytes--;
-
+
this->audiocodec = buffer[0] >> 4; /* override */
switch (this->audiocodec) {
case FLV_SOUND_FORMAT_PCM_BE:
@@ -413,17 +435,30 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
buf_type = BUF_AUDIO_FLVADPCM;
break;
case FLV_SOUND_FORMAT_MP3:
+ case FLV_SOUND_FORMAT_MP38:
buf_type = BUF_AUDIO_MPEG;
break;
case FLV_SOUND_FORMAT_PCM_LE:
buf_type = BUF_AUDIO_LPCM_LE;
break;
+ case FLV_SOUND_FORMAT_ALAW:
+ buf_type = BUF_AUDIO_ALAW;
+ break;
+ case FLV_SOUND_FORMAT_MULAW:
+ buf_type = BUF_AUDIO_MULAW;
+ break;
+ case FLV_SOUND_FORMAT_AAC:
+ buf_type = BUF_AUDIO_AAC;
+ /* AAC extra header */
+ this->input->read(this->input, buffer, 1 );
+ remaining_bytes--;
+ break;
default:
lprintf(" unsupported audio format (%d)...\n", buffer[0] >> 4);
buf_type = BUF_AUDIO_UNKNOWN;
break;
}
-
+
fifo = this->audio_fifo;
if (preview && !this->got_audio_header) {
/* send init info to audio decoder */
@@ -439,7 +474,7 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
this->got_audio_header = 1;
}
break;
-
+
case FLV_TAG_TYPE_VIDEO:
lprintf(" got video tag..\n");
if (this->input->read(this->input, buffer, 1) != 1) {
@@ -447,10 +482,19 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
return this->status;
}
remaining_bytes--;
-
- if ((buffer[0] >> 4) == 0x01)
- buf_flags = BUF_FLAG_KEYFRAME;
-
+
+ switch ((buffer[0] >> 4)) {
+ case 0x01:
+ buf_flags = BUF_FLAG_KEYFRAME;
+ break;
+ case 0x05:
+ /* skip server command */
+ this->input->seek(this->input, remaining_bytes, SEEK_CUR);
+ continue;
+ default:
+ break;
+ }
+
this->videocodec = buffer[0] & 0x0F; /* override */
switch (this->videocodec) {
case FLV_VIDEO_FORMAT_FLV1:
@@ -468,17 +512,23 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
this->input->read(this->input, buffer, 4);
remaining_bytes -= 4;
break;
+ case FLV_VIDEO_FORMAT_H264:
+ buf_type = BUF_VIDEO_H264;
+ /* AVC 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 (preview && !this->got_video_header) {
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 */
+ * 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;
@@ -495,16 +545,33 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
bih->biSize++;
buf->size++;
}
+ else if (buf_type == BUF_VIDEO_H264 && buffer[0] == 0) {
+ /* AVC sequence header */
+ if (remaining_bytes > buf->max_size-buf->size) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("sequence header too big (%u bytes)!\n"), remaining_bytes);
+ this->input->read(this->input, buf->content+buf->size, buf->max_size-buf->size);
+ this->input->seek(this->input, remaining_bytes-buf->max_size-buf->size, SEEK_CUR);
+ bih->biSize = buf->max_size;
+ buf->size = buf->max_size;
+ }
+ else {
+ this->input->read(this->input, buf->content+buf->size, remaining_bytes);
+ bih->biSize += remaining_bytes;
+ buf->size += remaining_bytes;
+ }
+ remaining_bytes = 0;
+ }
fifo->put(fifo, buf);
this->got_video_header = 1;
}
break;
-
+
case FLV_TAG_TYPE_SCRIPT:
lprintf(" got script tag...\n");
- parse_flv_script(this, remaining_bytes);
-
if (preview) {
+ parse_flv_script(this, remaining_bytes);
+
/* send init info to decoders using script information as reference */
if (!this->got_audio_header && this->audiocodec) {
buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
@@ -521,11 +588,21 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
buf->type = BUF_AUDIO_FLVADPCM;
break;
case FLV_SOUND_FORMAT_MP3:
+ case FLV_SOUND_FORMAT_MP38:
buf->type = BUF_AUDIO_MPEG;
break;
case FLV_SOUND_FORMAT_PCM_LE:
buf->type = BUF_AUDIO_LPCM_LE;
break;
+ case FLV_SOUND_FORMAT_ALAW:
+ buf->type = BUF_AUDIO_ALAW;
+ break;
+ case FLV_SOUND_FORMAT_MULAW:
+ buf->type = BUF_AUDIO_MULAW;
+ break;
+ case FLV_SOUND_FORMAT_AAC:
+ buf->type = BUF_AUDIO_AAC;
+ break;
default:
buf->type = BUF_AUDIO_UNKNOWN;
break;
@@ -533,9 +610,10 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
buf->size = 0;
this->audio_fifo->put(this->audio_fifo, buf);
this->got_audio_header = 1;
+ lprintf(" got audio header from metadata...\n");
}
-
- if (!this->got_video_header && this->videocodec) {
+
+ if (!this->got_video_header && this->videocodec && this->videocodec != FLV_VIDEO_FORMAT_H264) {
xine_bmiheader *bih;
buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_STDHEADER |
@@ -567,57 +645,88 @@ static int read_flv_packet(demux_flv_t *this, int preview) {
}
this->video_fifo->put(this->video_fifo, buf);
this->got_video_header = 1;
+ lprintf(" got video header from metadata...\n");
}
-
+
return this->status;
- }
+ }
+ /* no preview */
+ this->input->seek(this->input, remaining_bytes, SEEK_CUR);
continue;
-
+
default:
lprintf(" skipping packet...\n");
this->input->seek(this->input, remaining_bytes, SEEK_CUR);
continue;
}
-
+
while (remaining_bytes) {
buf = fifo->buffer_pool_alloc(fifo);
buf->type = buf_type;
- buf->pts = (int64_t) pts * 90;
-
- if (!preview)
- 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 =
+ 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;
- else
- buf->size = remaining_bytes;
- remaining_bytes -= buf->size;
+ if ((buf_type == BUF_VIDEO_H264 || buf_type == BUF_AUDIO_AAC) && buffer[0] == 0) {
+ /* AVC/AAC sequence header */
+ buf->pts = 0;
+ buf->size = 0;
- buf->decoder_flags = buf_flags;
- if (preview)
- buf->decoder_flags |= BUF_FLAG_PREVIEW;
- if (!remaining_bytes)
- buf->decoder_flags |= BUF_FLAG_FRAME_END;
+ buf->decoder_flags = BUF_FLAG_SPECIAL | BUF_FLAG_HEADER;
+ if (preview)
+ buf->decoder_flags |= BUF_FLAG_PREVIEW;
- if (this->input->read(this->input, buf->content, buf->size) != buf->size) {
- buf->free_buffer(buf);
- this->status = DEMUX_FINISHED;
- break;
+ buf->decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG;
+ buf->decoder_info[2] = MIN(remaining_bytes, buf->max_size);
+ buf->decoder_info_ptr[2] = buf->mem;
+
+ if (this->input->read(this->input, buf->mem, buf->decoder_info[2]) != buf->decoder_info[2]) {
+ buf->free_buffer(buf);
+ this->status = DEMUX_FINISHED;
+ break;
+ }
+
+ if (remaining_bytes > buf->max_size) {
+ xprintf(this->xine, XINE_VERBOSITY_LOG,
+ _("sequence header too big (%u bytes)!\n"), remaining_bytes);
+ this->input->seek(this->input, remaining_bytes-buf->max_size, SEEK_CUR);
+ }
+ remaining_bytes = 0;
+ }
+ else {
+ buf->pts = (int64_t) pts * 90;
+ if (!preview)
+ check_newpts(this, buf->pts, (tag_type == FLV_TAG_TYPE_VIDEO));
+
+ if (remaining_bytes > buf->max_size)
+ buf->size = buf->max_size;
+ else
+ buf->size = remaining_bytes;
+ remaining_bytes -= buf->size;
+
+ buf->decoder_flags = buf_flags;
+ if (preview)
+ buf->decoder_flags |= BUF_FLAG_PREVIEW;
+ if (!remaining_bytes)
+ buf->decoder_flags |= BUF_FLAG_FRAME_END;
+
+ if (this->input->read(this->input, buf->content, buf->size) != buf->size) {
+ buf->free_buffer(buf);
+ this->status = DEMUX_FINISHED;
+ break;
+ }
}
fifo->put(fifo, buf);
}
-
+
this->cur_pts = pts;
break;
}
-
+
return this->status;
}
@@ -628,52 +737,50 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) {
int next_tag = 0;
int do_rewind = (seek_pts < this->cur_pts);
int i;
-
- lprintf(" seeking %s to %d...\n",
+
+ lprintf(" seeking %s to %d...\n",
do_rewind ? "backward" : "forward", seek_pts);
-
- if (seek_pts == 0) {
+
+ if (seek_pos == 0 && seek_pts == 0) {
this->input->seek(this->input, this->start, SEEK_SET);
this->cur_pts = 0;
return;
}
-
+
if (this->index) {
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",
+ 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;
}
}
-
- if (seek_pos && this->videocodec) {
+ else if (seek_pos && this->videocodec && abs(seek_pts-this->cur_pts) > 300000) {
off_t pos, size;
-
+
pos = this->input->get_current_pos(this->input);
size = this->filesize ? : this->input->get_length(this->input);
this->input->seek(this->input, (uint64_t)size * seek_pos / 65535, SEEK_SET);
lprintf(" resyncing...\n");
-
+
/* resync */
for (i = 0; i < 200000; i++) {
uint8_t buf[4];
-
+
if (this->input->read(this->input, buf, 1) < 1) {
this->status = DEMUX_FINISHED;
return;
@@ -694,58 +801,59 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) {
this->input->seek(this->input, -11, SEEK_CUR);
}
}
-
+
lprintf(" ...resync failed!\n");
this->input->seek(this->input, pos, SEEK_SET);
- 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 = _X_BE_32(&buffer[0]);
- tag_type = buffer[4];
- data_size = _X_BE_24(&buffer[5]);
- pts = _X_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);
+ }
+ else if (seek_pts) {
+ 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 = _X_BE_32(&buffer[0]);
+ tag_type = buffer[4];
+ data_size = _X_BE_24(&buffer[5]);
+ pts = _X_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;
}
- 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);
}
-
- /* 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, 0);
}
@@ -757,11 +865,11 @@ static void demux_flv_send_headers(demux_plugin_t *this_gen) {
this->audio_fifo = this->stream->audio_fifo;
this->status = DEMUX_OK;
-
+
this->buf_flag_seek = 1;
/* load stream information */
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO,
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO,
(this->flags & FLV_FLAG_HAS_VIDEO) ? 1 : 0);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO,
(this->flags & FLV_FLAG_HAS_AUDIO) ? 1 : 0);
@@ -789,18 +897,22 @@ static int demux_flv_seek (demux_plugin_t *this_gen,
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 (start_pos && !start_time) {
+ if (this->length)
+ start_time = (int64_t) this->length * start_pos / 65535;
+ else if (this->index)
+ start_time = this->index[(int)(start_pos * (this->num_indices-1) / 65535)].pts;
+ }
if (!this->length || start_time < this->length) {
seek_flv_file(this, start_pos, start_time);
-
+
if (playing) {
this->buf_flag_seek = 1;
_x_demux_flush_engine(this->stream);
}
}
- }
+ }
return this->status;
}
@@ -838,7 +950,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
input_plugin_t *input) {
demux_flv_t *this;
- this = xine_xmalloc(sizeof (demux_flv_t));
+ this = calloc(1, sizeof(demux_flv_t));
this->xine = stream->xine;
this->stream = stream;
this->input = input;
@@ -857,12 +969,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
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)) {
@@ -906,7 +1012,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_flv_class_t *this;
- this = xine_xmalloc (sizeof (demux_flv_class_t));
+ this = calloc(1, sizeof(demux_flv_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_idcin.c b/src/demuxers/demux_idcin.c
index 99754c797..46d4c284b 100644
--- a/src/demuxers/demux_idcin.c
+++ b/src/demuxers/demux_idcin.c
@@ -328,7 +328,7 @@ static int open_idcin_file(demux_idcin_t *this) {
this->input->seek(this->input, IDCIN_HEADER_SIZE, SEEK_SET);
/* read the Huffman table */
- if (this->input->read(this->input, huffman_table, HUFFMAN_TABLE_SIZE) !=
+ if (this->input->read(this->input, huffman_table, HUFFMAN_TABLE_SIZE) !=
HUFFMAN_TABLE_SIZE)
return 0;
@@ -347,7 +347,7 @@ static int open_idcin_file(demux_idcin_t *this) {
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS,
this->wave.wBitsPerSample);
- this->filesize = this->input->get_length(this->input) -
+ this->filesize = this->input->get_length(this->input) -
IDCIN_HEADER_SIZE - HUFFMAN_TABLE_SIZE;
return 1;
@@ -433,7 +433,7 @@ static int demux_idcin_seek (demux_plugin_t *this_gen, off_t start_pos, int star
this->status = DEMUX_OK;
/* reposition stream past the Huffman tables */
- this->input->seek(this->input, IDCIN_HEADER_SIZE + HUFFMAN_TABLE_SIZE,
+ this->input->seek(this->input, IDCIN_HEADER_SIZE + HUFFMAN_TABLE_SIZE,
SEEK_SET);
this->pts_counter = 0;
@@ -472,7 +472,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_idcin_t *this;
- this = xine_xmalloc (sizeof (demux_idcin_t));
+ this = calloc(1, sizeof(demux_idcin_t));
this->stream = stream;
this->input = input;
@@ -547,7 +547,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_idcin_init_plugin (xine_t *xine, void *data) {
demux_idcin_class_t *this;
- this = xine_xmalloc (sizeof (demux_idcin_class_t));
+ this = calloc(1, sizeof(demux_idcin_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_iff.c b/src/demuxers/demux_iff.c
index d914405db..1785e86d7 100644
--- a/src/demuxers/demux_iff.c
+++ b/src/demuxers/demux_iff.c
@@ -212,7 +212,7 @@ static int read_iff_chunk(demux_iff_t *this) {
break;
case IFF_VHDR_CHUNK:
if( this->vhdr == NULL )
- this->vhdr = (Voice8Header *)xine_xmalloc(sizeof(Voice8Header));
+ this->vhdr = (Voice8Header *)calloc(1, sizeof(Voice8Header));
this->vhdr->oneShotHiSamples = _X_BE_32(&buffer[0]);
this->vhdr->repeatHiSamples = _X_BE_32(&buffer[4]);
this->vhdr->samplesPerHiCycle = _X_BE_32(&buffer[8]);
@@ -330,7 +330,7 @@ static int read_iff_chunk(demux_iff_t *this) {
break;
case IFF_BMHD_CHUNK:
if( this->bmhd == NULL )
- this->bmhd = (BitMapHeader *)xine_xmalloc(sizeof(BitMapHeader));
+ this->bmhd = (BitMapHeader *)calloc(1, sizeof(BitMapHeader));
this->bmhd->w = _X_BE_16(&buffer[0]);
this->bmhd->h = _X_BE_16(&buffer[2]);
this->bmhd->x = _X_BE_16(&buffer[4]);
@@ -399,20 +399,20 @@ static int read_iff_chunk(demux_iff_t *this) {
case IFF_CMAP_CHUNK:
/* every color contains red, green and blue componente using 8Bit */
this->cmap_num = junk_size / PIC_SIZE_OF_COLOR_REGISTER;
- this->cmap = (ColorRegister *)xine_xmalloc(junk_size);
+ this->cmap = (ColorRegister *)malloc(junk_size);
this->video_send_palette = 1;
- if (this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size)
+ if (!this->cmap || this->input->read(this->input, (char *)this->cmap, junk_size) != junk_size)
return 0;
break;
case IFF_GRAB_CHUNK:
if( this->grab == NULL )
- this->grab = (Point2D *)xine_xmalloc(sizeof(Point2D));
+ this->grab = (Point2D *)calloc(1, sizeof(Point2D));
this->grab->x = _X_BE_16(&buffer[0]);
this->grab->y = _X_BE_16(&buffer[2]);
break;
case IFF_DEST_CHUNK:
if( this->dest == NULL )
- this->dest = (DestMerge *)xine_xmalloc(sizeof(DestMerge));
+ this->dest = (DestMerge *)calloc(1, sizeof(DestMerge));
this->dest->depth = buffer[0];
this->dest->pad1 = buffer[1];
this->dest->plane_pick = _X_BE_16(&buffer[2]);
@@ -424,7 +424,7 @@ static int read_iff_chunk(demux_iff_t *this) {
break;
case IFF_CAMG_CHUNK:
if( this->camg == NULL )
- this->camg = (CamgChunk *)xine_xmalloc(sizeof(CamgChunk));
+ this->camg = (CamgChunk *)calloc(1, sizeof(CamgChunk));
this->camg->view_modes = _X_BE_32(&buffer[0]);
this->bih.biCompression = this->camg->view_modes;
if( this->camg->view_modes & CAMG_PAL &&
@@ -443,7 +443,7 @@ static int read_iff_chunk(demux_iff_t *this) {
break;
case IFF_CCRT_CHUNK:
if( this->ccrt == NULL )
- this->ccrt = (CcrtChunk *)xine_xmalloc(sizeof(CcrtChunk));
+ this->ccrt = (CcrtChunk *)calloc(1, sizeof(CcrtChunk));
this->ccrt->direction = _X_BE_16(&buffer[0]);
this->ccrt->start = buffer[2];
this->ccrt->end = buffer[3];
@@ -453,13 +453,13 @@ static int read_iff_chunk(demux_iff_t *this) {
break;
case IFF_DPI_CHUNK:
if( this->dpi == NULL )
- this->dpi = (DPIHeader *)xine_xmalloc(sizeof(DPIHeader));
+ this->dpi = (DPIHeader *)calloc(1, sizeof(DPIHeader));
this->dpi->x = _X_BE_16(&buffer[0]);
this->dpi->y = _X_BE_16(&buffer[0]);
break;
case IFF_ANHD_CHUNK:
if( this->anhd == NULL )
- this->anhd = (AnimHeader *)xine_xmalloc(sizeof(AnimHeader));
+ this->anhd = (AnimHeader *)calloc(1, sizeof(AnimHeader));
this->anhd->operation = buffer[0];
this->anhd->mask = buffer[1];
this->anhd->w = _X_BE_16(&buffer[2]);
@@ -500,7 +500,7 @@ static int read_iff_chunk(demux_iff_t *this) {
break;
case IFF_DPAN_CHUNK:
if( this->dpan == NULL )
- this->dpan = (DPAnimChunk *)xine_xmalloc(sizeof(DPAnimChunk));
+ this->dpan = (DPAnimChunk *)calloc(1, sizeof(DPAnimChunk));
this->dpan->version = _X_BE_16(&buffer[0]);
this->dpan->nframes = _X_BE_16(&buffer[2]);
this->dpan->fps = buffer[4];
@@ -709,11 +709,19 @@ static int demux_iff_send_chunk(demux_plugin_t *this_gen) {
/* load the whole chunk into the buffer */
if (this->audio_buffer_filled == 0) {
if (this->audio_interleave_buffer_size > 0)
+ {
this->audio_interleave_buffer =
- xine_xmalloc(this->audio_interleave_buffer_size);
+ calloc(1, this->audio_interleave_buffer_size);
+ if (!this->audio_interleave_buffer)
+ return this->status = DEMUX_FINISHED;
+ }
if (this->audio_read_buffer_size > 0)
+ {
this->audio_read_buffer =
- xine_xmalloc(this->audio_read_buffer_size);
+ calloc(1, this->audio_read_buffer_size);
+ if (!this->audio_read_buffer)
+ return this->status = DEMUX_FINISHED;
+ }
if (this->audio_read_buffer) {
if (this->input->read(this->input, this->audio_read_buffer,
this->data_size) != this->data_size) {
@@ -1234,7 +1242,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_iff_t *this;
- this = xine_xmalloc (sizeof (demux_iff_t));
+ this = calloc(1, sizeof(demux_iff_t));
this->stream = stream;
this->input = input;
@@ -1315,7 +1323,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_iff_class_t *this;
- this = xine_xmalloc (sizeof (demux_iff_class_t));
+ this = calloc(1, sizeof(demux_iff_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_image.c b/src/demuxers/demux_image.c
index 9f53e4173..08136edba 100644
--- a/src/demuxers/demux_image.c
+++ b/src/demuxers/demux_image.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2003-2005 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -82,7 +82,7 @@ static int demux_image_next (demux_plugin_t *this_gen, int preview) {
} else {
this->status = DEMUX_OK;
}
-
+
if (preview)
buf->decoder_flags = BUF_FLAG_PREVIEW;
@@ -198,7 +198,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
* if we reach this point, the input has been accepted.
*/
- this = xine_xmalloc (sizeof (demux_image_t));
+ this = calloc(1, sizeof(demux_image_t));
this->stream = stream;
this->input = input;
@@ -211,7 +211,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->demux_plugin.get_capabilities = demux_image_get_capabilities;
this->demux_plugin.get_optional_data = demux_image_get_optional_data;
this->demux_plugin.demux_class = class_gen;
-
+
this->status = DEMUX_FINISHED;
this->buf_type = buf_type;
@@ -226,7 +226,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
static const char *get_description (demux_class_t *this_gen) {
return "image demux plugin";
}
-
+
static const char *get_identifier (demux_class_t *this_gen) {
return "imagedmx";
}
@@ -249,7 +249,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_class (xine_t *xine, void *data) {
demux_image_class_t *this;
- this = xine_xmalloc (sizeof (demux_image_class_t));
+ this = calloc(1, sizeof(demux_image_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_ipmovie.c b/src/demuxers/demux_ipmovie.c
index cd21896c0..5b4e12ef8 100644
--- a/src/demuxers/demux_ipmovie.c
+++ b/src/demuxers/demux_ipmovie.c
@@ -183,7 +183,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
while ((chunk_size > 0) && (chunk_type != CHUNK_BAD)) {
/* read the next chunk, wherever the file happens to be pointing */
- if (this->input->read(this->input, opcode_preamble,
+ if (this->input->read(this->input, opcode_preamble,
OPCODE_PREAMBLE_SIZE) != OPCODE_PREAMBLE_SIZE) {
chunk_type = CHUNK_BAD;
break;
@@ -221,7 +221,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
chunk_type = CHUNK_BAD;
break;
}
- if (this->input->read(this->input, scratch, opcode_size) !=
+ if (this->input->read(this->input, scratch, opcode_size) !=
opcode_size) {
chunk_type = CHUNK_BAD;
break;
@@ -239,7 +239,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
chunk_type = CHUNK_BAD;
break;
}
- if (this->input->read(this->input, scratch, opcode_size) !=
+ if (this->input->read(this->input, scratch, opcode_size) !=
opcode_size) {
chunk_type = CHUNK_BAD;
break;
@@ -275,7 +275,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
chunk_type = CHUNK_BAD;
break;
}
- if (this->input->read(this->input, scratch, opcode_size) !=
+ if (this->input->read(this->input, scratch, opcode_size) !=
opcode_size) {
chunk_type = CHUNK_BAD;
break;
@@ -283,9 +283,10 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
this->bih.biWidth = _X_LE_16(&scratch[0]) * 8;
this->bih.biHeight = _X_LE_16(&scratch[2]) * 8;
/* set up staging area for decode map */
- this->decode_map_size = (this->bih.biWidth * this->bih.biHeight) /
- (8 * 8) / 2;
+ this->decode_map_size = (this->bih.biWidth / 8) * (this->bih.biHeight / 8) / 2;
this->decode_map = xine_xmalloc(this->decode_map_size);
+ if (!this->decode_map)
+ this->status = DEMUX_FINISHED;
lprintf("video resolution: %d x %d\n",
this->bih.biWidth, this->bih.biHeight);
break;
@@ -335,23 +336,23 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->data_size);
buf->extra_info->input_time = audio_pts / 90;
buf->pts = audio_pts;
-
+
if (opcode_size > buf->max_size)
buf->size = buf->max_size;
else
buf->size = opcode_size;
opcode_size -= buf->size;
-
+
if (this->input->read(this->input, buf->content, buf->size) !=
buf->size) {
buf->free_buffer(buf);
chunk_type = CHUNK_BAD;
break;
}
-
+
if (!opcode_size)
buf->decoder_flags |= BUF_FLAG_FRAME_END;
-
+
this->audio_fifo->put (this->audio_fifo, buf);
}
}else{
@@ -376,7 +377,7 @@ static int process_ipmovie_chunk(demux_ipmovie_t *this) {
case OPCODE_SET_PALETTE:
lprintf("set palette\n");
- /* check for the logical maximum palette size
+ /* check for the logical maximum palette size
* (3 * 256 + 4 bytes) */
if (opcode_size > 0x304) {
lprintf("set_palette opcode too large\n");
@@ -671,7 +672,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_ipmovie_t *this;
- this = xine_xmalloc (sizeof (demux_ipmovie_t));
+ this = calloc(1, sizeof(demux_ipmovie_t));
this->stream = stream;
this->input = input;
@@ -746,7 +747,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_ipmovie_init_plugin (xine_t *xine, void *data) {
demux_ipmovie_class_t *this;
- this = xine_xmalloc (sizeof (demux_ipmovie_class_t));
+ this = calloc(1, sizeof(demux_ipmovie_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_matroska-chapters.c b/src/demuxers/demux_matroska-chapters.c
new file mode 100644
index 000000000..4bfafe0da
--- /dev/null
+++ b/src/demuxers/demux_matroska-chapters.c
@@ -0,0 +1,433 @@
+/*
+ * Copyright (C) 2009 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * demultiplexer for matroska streams: chapter handling
+ *
+ * TODO:
+ * - nested chapters
+ *
+ * Authors:
+ * Nicos Gollan <gtdev@spearhead.de>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#define LOG_MODULE "demux_matroska_chapters"
+#define LOG_VERBOSE
+/*
+#define LOG
+*/
+
+#include "xine_internal.h"
+#include "xineutils.h"
+#include "demux.h"
+
+#include "ebml.h"
+#include "matroska.h"
+#include "demux_matroska.h"
+
+/* TODO: this only handles one single (title, language, country) tuple.
+ * See the header for information. */
+static int parse_chapter_display(demux_matroska_t *this, matroska_chapter_t *chap, int level) {
+ ebml_parser_t *ebml = this->ebml;
+ int next_level = level+1;
+ char* tmp_name = NULL;
+ char* tmp_lang = NULL;
+ char* tmp_country = NULL;
+
+ while (next_level == level+1) {
+ ebml_elem_t elem;
+
+ if (!ebml_read_elem_head(ebml, &elem))
+ return 0;
+
+ switch (elem.id) {
+
+ case MATROSKA_ID_CH_STRING:
+ tmp_name = ebml_alloc_read_ascii(ebml, &elem);
+ break;
+
+ case MATROSKA_ID_CH_LANGUAGE:
+ tmp_lang = ebml_alloc_read_ascii(ebml, &elem);
+ break;
+
+ case MATROSKA_ID_CH_COUNTRY:
+ tmp_country = ebml_alloc_read_ascii(ebml, &elem);
+ break;
+
+ default:
+ lprintf("Unhandled ID (inside ChapterDisplay): 0x%x\n", elem.id);
+ if (!ebml_skip(ebml, &elem))
+ return 0;
+ }
+
+ next_level = ebml_get_next_level(ebml, &elem);
+ }
+
+ if (NULL != chap->title) {
+ chap->title = tmp_name;
+
+ free(chap->language);
+ chap->language = tmp_lang;
+
+ free(chap->country);
+ chap->country = tmp_country;
+ } else if (tmp_lang != NULL && !strcmp("eng", tmp_lang) && (chap->language == NULL || strcmp("eng", chap->language))) {
+ free(chap->title);
+ chap->title = tmp_name;
+
+ free(chap->language);
+ chap->language = tmp_lang;
+
+ free(chap->country);
+ chap->country = tmp_country;
+ } else {
+ free(tmp_name);
+ free(tmp_lang);
+ free(tmp_country);
+ }
+
+ return 1;
+}
+
+static int parse_chapter_atom(demux_matroska_t *this, matroska_chapter_t *chap, int level) {
+ ebml_parser_t *ebml = this->ebml;
+ int next_level = level+1;
+ uint64_t num;
+
+ chap->time_start = 0;
+ chap->time_end = 0;
+ chap->hidden = 0;
+ chap->enabled = 1;
+
+ while (next_level == level+1) {
+ ebml_elem_t elem;
+
+ if (!ebml_read_elem_head(ebml, &elem)) {
+ lprintf("invalid head\n");
+ return 0;
+ }
+
+ switch (elem.id) {
+ case MATROSKA_ID_CH_UID:
+ if (!ebml_read_uint(ebml, &elem, &chap->uid)) {
+ lprintf("invalid UID\n");
+ return 0;
+ }
+ break;
+
+ case MATROSKA_ID_CH_TIMESTART:
+ if (!ebml_read_uint(ebml, &elem, &chap->time_start)) {
+ lprintf("invalid start time\n");
+ return 0;
+ }
+ /* convert to xine timing: Matroska timestamps are in nanoseconds,
+ * xine's PTS are in 1/90,000s */
+ chap->time_start /= 100000;
+ chap->time_start *= 9;
+ break;
+
+ case MATROSKA_ID_CH_TIMEEND:
+ if (!ebml_read_uint(ebml, &elem, &chap->time_end)) {
+ lprintf("invalid end time\n");
+ return 0;
+ }
+ /* convert to xine timing */
+ chap->time_end /= 100000;
+ chap->time_end *= 9;
+ break;
+
+ case MATROSKA_ID_CH_DISPLAY:
+ if (!ebml_read_master(ebml, &elem))
+ return 0;
+
+ lprintf("ChapterDisplay\n");
+ if(!parse_chapter_display(this, chap, level+1)) {
+ lprintf("invalid display information\n");
+ return 0;
+ }
+ break;
+
+ case MATROSKA_ID_CH_HIDDEN:
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ chap->hidden = (int)num;
+ break;
+
+ case MATROSKA_ID_CH_ENABLED:
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ chap->enabled = (int)num;
+ break;
+
+ case MATROSKA_ID_CH_ATOM: /* TODO */
+ xprintf(this->stream->xine, XINE_VERBOSITY_NONE,
+ LOG_MODULE ": Warning: Nested chapters are not supported, playback may suffer!\n");
+ if (!ebml_skip(ebml, &elem))
+ return 0;
+ break;
+
+ case MATROSKA_ID_CH_TRACK: /* TODO */
+ xprintf(this->stream->xine, XINE_VERBOSITY_NONE,
+ LOG_MODULE ": Warning: Specific track information in chapters is not supported, playback may suffer!\n");
+ if (!ebml_skip(ebml, &elem))
+ return 0;
+ break;
+
+ default:
+ lprintf("Unhandled ID (inside ChapterAtom): 0x%x\n", elem.id);
+ if (!ebml_skip(ebml, &elem))
+ return 0;
+ }
+
+ next_level = ebml_get_next_level(ebml, &elem);
+ }
+
+ /* fallback information */
+ /* FIXME: check allocations! */
+ if (NULL == chap->title) {
+ chap->title = malloc(9);
+ if (chap->title != NULL)
+ strncpy(chap->title, "No title", 9);
+ }
+
+ if (NULL == chap->language) {
+ chap->language = malloc(4);
+ if (chap->language != NULL)
+ strncpy(chap->language, "unk", 4);
+ }
+
+ if (NULL == chap->country) {
+ chap->country = malloc(3);
+ if (chap->country != NULL)
+ strncpy(chap->country, "XX", 3);
+ }
+
+ lprintf( "Chapter 0x%" PRIx64 ": %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n",
+ chap->uid, chap->time_start, chap->time_end,
+ chap->title, chap->language,
+ (chap->hidden ? "" : "not "),
+ (chap->enabled ? "" : "not "));
+
+ return 1;
+}
+
+static void free_chapter(demux_matroska_t *this, matroska_chapter_t *chap) {
+ free(chap->title);
+ free(chap->language);
+ free(chap->country);
+
+ free(chap);
+}
+
+static int parse_edition_entry(demux_matroska_t *this, matroska_edition_t *ed) {
+ ebml_parser_t *ebml = this->ebml;
+ int next_level = 3;
+ uint64_t num;
+ int i;
+
+ ed->hidden = 0;
+ ed->is_default = 0;
+ ed->ordered = 0;
+
+ while (next_level == 3) {
+ ebml_elem_t elem;
+
+ if (!ebml_read_elem_head(ebml, &elem))
+ return 0;
+
+ switch (elem.id) {
+ case MATROSKA_ID_CH_ED_UID:
+ if (!ebml_read_uint(ebml, &elem, &ed->uid))
+ return 0;
+ break;
+
+ case MATROSKA_ID_CH_ED_HIDDEN:
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ ed->hidden = (int)num;
+ break;
+
+ case MATROSKA_ID_CH_ED_DEFAULT:
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ ed->is_default = (int)num;
+ break;
+
+ case MATROSKA_ID_CH_ED_ORDERED:
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ ed->ordered = (int)num;
+ break;
+
+ case MATROSKA_ID_CH_ATOM:
+ {
+ matroska_chapter_t *chapter = calloc(1, sizeof(matroska_chapter_t));
+ if (NULL == chapter)
+ return 0;
+
+ lprintf("ChapterAtom\n");
+ if (!ebml_read_master(ebml, &elem))
+ return 0;
+
+ if (!parse_chapter_atom(this, chapter, next_level))
+ return 0;
+
+ /* resize chapters array if necessary */
+ if (ed->num_chapters >= ed->cap_chapters) {
+ matroska_chapter_t** old_chapters = ed->chapters;
+ ed->cap_chapters += 10;
+ ed->chapters = realloc(ed->chapters, ed->cap_chapters * sizeof(matroska_chapter_t*));
+
+ if (NULL == ed->chapters) {
+ ed->chapters = old_chapters;
+ ed->cap_chapters -= 10;
+ return 0;
+ }
+ }
+
+ ed->chapters[ed->num_chapters] = chapter;
+ ++ed->num_chapters;
+
+ break;
+ }
+
+ default:
+ lprintf("Unhandled ID (inside EditionEntry): 0x%x\n", elem.id);
+ if (!ebml_skip(ebml, &elem))
+ return 0;
+ }
+
+ next_level = ebml_get_next_level(ebml, &elem);
+ }
+
+ xprintf( this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": Edition 0x%" PRIx64 ": %shidden, %sdefault, %sordered. %d chapters:\n",
+ ed->uid,
+ (ed->hidden ? "" : "not "),
+ (ed->is_default ? "" : "not "),
+ (ed->ordered ? "" : "not "),
+ ed->num_chapters );
+
+ for (i=0; i<ed->num_chapters; ++i) {
+ matroska_chapter_t* chap = ed->chapters[i];
+ xprintf( this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": Chapter %d: %" PRIu64 "-%" PRIu64 "(pts), %s (%s). %shidden, %senabled.\n",
+ i+1, chap->time_start, chap->time_end,
+ chap->title, chap->language,
+ (chap->hidden ? "" : "not "),
+ (chap->enabled ? "" : "not "));
+ }
+
+ return 1;
+}
+
+static void free_edition(demux_matroska_t *this, matroska_edition_t *ed) {
+ int i;
+
+ for(i=0; i<ed->num_chapters; ++i) {
+ free_chapter(this, ed->chapters[i]);
+ }
+ free(ed->chapters);
+ free(ed);
+}
+
+int matroska_parse_chapters(demux_matroska_t *this) {
+ ebml_parser_t *ebml = this->ebml;
+ int next_level = 2;
+
+ while (next_level == 2) {
+ ebml_elem_t elem;
+
+ if (!ebml_read_elem_head(ebml, &elem))
+ return 0;
+
+ switch (elem.id) {
+ case MATROSKA_ID_CH_EDITIONENTRY:
+ {
+ matroska_edition_t *edition = calloc(1, sizeof(matroska_edition_t));
+ if (NULL == edition)
+ return 0;
+
+ lprintf("EditionEntry\n");
+ if (!ebml_read_master(ebml, &elem))
+ return 0;
+
+ if (!parse_edition_entry(this, edition))
+ return 0;
+
+ /* resize editions array if necessary */
+ if (this->num_editions >= this->cap_editions) {
+ matroska_edition_t** old_editions = this->editions;
+ this->cap_editions += 10;
+ this->editions = realloc(this->editions, this->cap_editions * sizeof(matroska_edition_t*));
+
+ if (NULL == this->editions) {
+ this->editions = old_editions;
+ this->cap_editions -= 10;
+ return 0;
+ }
+ }
+
+ this->editions[this->num_editions] = edition;
+ ++this->num_editions;
+
+ 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;
+}
+
+void matroska_free_editions(demux_matroska_t *this) {
+ int i;
+
+ for(i=0; i<this->num_editions; ++i) {
+ free_edition(this, this->editions[i]);
+ }
+ free(this->editions);
+ this->num_editions = 0;
+ this->cap_editions = 0;
+}
+
+int matroska_get_chapter(demux_matroska_t *this, uint64_t tc, matroska_edition_t** ed) {
+ uint64_t block_pts = (tc * this->timecode_scale) / 100000 * 9;
+ int chapter_idx = 0;
+
+ if (this->num_editions < 1)
+ return -1;
+
+ while (chapter_idx < (*ed)->num_chapters && block_pts > (*ed)->chapters[chapter_idx]->time_start)
+ ++chapter_idx;
+
+ if (chapter_idx > 0)
+ --chapter_idx;
+
+ return chapter_idx;
+}
diff --git a/src/demuxers/demux_matroska.c b/src/demuxers/demux_matroska.c
index b973c1caf..94f47db44 100644
--- a/src/demuxers/demux_matroska.c
+++ b/src/demuxers/demux_matroska.c
@@ -1,18 +1,18 @@
/*
- * Copyright (C) 2000-2007 the xine project
- *
+ * Copyright (C) 2000-2008 the xine project
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -42,6 +42,7 @@
/*
#define LOG
*/
+
#include "xine_internal.h"
#include "xineutils.h"
#include "demux.h"
@@ -50,96 +51,7 @@
#include "ebml.h"
#include "matroska.h"
-
-#define NUM_PREVIEW_BUFFERS 10
-
-#define MAX_STREAMS 128
-#define MAX_FRAMES 32
-
-#define WRAP_THRESHOLD 90000
-
-#if !defined(MIN)
-#define MIN(a, b) ((a)<(b)?(a):(b))
-#endif
-#if !defined(MAX)
-#define MAX(a, b) ((a)>(b)?(a):(b))
-#endif
-
-typedef struct {
- int track_num;
- off_t *pos;
- uint64_t *timecode;
- int num_entries;
-
-} matroska_index_t;
-
-typedef struct {
-
- demux_plugin_t demux_plugin;
-
- xine_stream_t *stream;
-
- input_plugin_t *input;
-
- int status;
-
- ebml_parser_t *ebml;
-
- /* segment element */
- ebml_elem_t segment;
- uint64_t timecode_scale;
- int duration; /* in millis */
- int preview_sent;
- int preview_mode;
-
- /* meta seek info */
- int has_seekhead;
- int seekhead_handled;
-
- /* seek info */
- matroska_index_t *indexes;
- int num_indexes;
- int first_cluster_found;
- int skip_to_timecode;
- int skip_for_track;
-
- /* tracks */
- int num_tracks;
- int num_video_tracks;
- int num_audio_tracks;
- int num_sub_tracks;
-
- matroska_track_t *tracks[MAX_STREAMS];
-
- /* block */
- uint8_t *block_data;
- int block_data_size;
-
- /* current tracks */
- matroska_track_t *video_track; /* to remove */
- matroska_track_t *audio_track; /* to remove */
- matroska_track_t *sub_track; /* to remove */
-
- int send_newpts;
- int buf_flag_seek;
-
- /* seekhead parsing */
- int top_level_list_size;
- int top_level_list_max_size;
- off_t *top_level_list;
-
-} demux_matroska_t ;
-
-typedef struct {
-
- demux_class_t demux_class;
-
- /* class-wide, global variables here */
-
- xine_t *xine;
-
-} demux_matroska_class_t;
-
+#include "demux_matroska.h"
static void check_newpts (demux_matroska_t *this, int64_t pts,
matroska_track_t *track) {
@@ -147,7 +59,7 @@ static void check_newpts (demux_matroska_t *this, int64_t pts,
if ((track->track_type == MATROSKA_TRACK_VIDEO) ||
(track->track_type == MATROSKA_TRACK_AUDIO)) {
-
+
diff = pts - track->last_pts;
if (pts && (this->send_newpts || (track->last_pts && abs(diff)>WRAP_THRESHOLD)) ) {
@@ -213,10 +125,10 @@ static int parse_info(demux_matroska_t *this) {
ebml_parser_t *ebml = this->ebml;
int next_level = 2;
double duration = 0.0; /* in matroska unit */
-
+
while (next_level == 2) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -226,14 +138,22 @@ static int parse_info(demux_matroska_t *this) {
if (!ebml_read_uint(ebml, &elem, &this->timecode_scale))
return 0;
break;
- case MATROSKA_ID_I_DURATION: {
-
+
+ case MATROSKA_ID_I_DURATION:
lprintf("duration\n");
if (!ebml_read_float(ebml, &elem, &duration))
return 0;
- }
- break;
-
+ break;
+
+ case MATROSKA_ID_I_TITLE:
+ lprintf("title\n");
+ if (NULL != this->title)
+ free(this->title);
+
+ this->title = ebml_alloc_read_ascii(ebml, &elem);
+ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->title);
+ break;
+
default:
lprintf("Unhandled ID: 0x%x\n", elem.id);
if (!ebml_skip(ebml, &elem))
@@ -247,6 +167,8 @@ static int parse_info(demux_matroska_t *this) {
this->duration = (int)(duration * (double)this->timecode_scale / 1000000.0);
lprintf("timecode_scale: %" PRId64 "\n", this->timecode_scale);
lprintf("duration: %d\n", this->duration);
+ lprintf("title: %s\n", (NULL != this->title ? this->title : "(none)"));
+
return 1;
}
@@ -488,9 +410,9 @@ static int parse_content_encodings (demux_matroska_t *this, matroska_track_t *tr
static void init_codec_video(demux_matroska_t *this, matroska_track_t *track) {
buf_element_t *buf;
-
+
buf = track->fifo->buffer_pool_alloc (track->fifo);
-
+
if (track->codec_private_len > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_matroska: private decoder data length (%d) is greater than fifo buffer length (%" PRId32 ")\n",
@@ -507,20 +429,20 @@ static void init_codec_video(demux_matroska_t *this, matroska_track_t *track) {
xine_fast_memcpy (buf->content, track->codec_private, buf->size);
else
buf->content = NULL;
-
+
if(track->default_duration) {
buf->decoder_flags |= BUF_FLAG_FRAMERATE;
- buf->decoder_info[0] = (int64_t)track->default_duration *
+ buf->decoder_info[0] = (int64_t)track->default_duration *
(int64_t)90 / (int64_t)1000000;
}
-
- if(track->video_track && track->video_track->display_width &&
+
+ if(track->video_track && track->video_track->display_width &&
track->video_track->display_height) {
buf->decoder_flags |= BUF_FLAG_ASPECT;
buf->decoder_info[1] = track->video_track->display_width;
buf->decoder_info[2] = track->video_track->display_height;
}
-
+
track->fifo->put (track->fifo, buf);
}
@@ -538,7 +460,7 @@ static void init_codec_audio(demux_matroska_t *this, matroska_track_t *track) {
return;
}
buf->size = track->codec_private_len;
-
+
/* default param */
buf->decoder_info[0] = 0;
buf->decoder_info[1] = 44100;
@@ -570,9 +492,9 @@ static void init_codec_audio(demux_matroska_t *this, matroska_track_t *track) {
static void init_codec_real(demux_matroska_t *this, matroska_track_t * track) {
buf_element_t *buf;
-
+
buf = track->fifo->buffer_pool_alloc (track->fifo);
-
+
if (track->codec_private_len > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_matroska: private decoder data length (%d) is greater than fifo buffer length (%" PRId32 ")\n",
@@ -580,30 +502,30 @@ static void init_codec_real(demux_matroska_t *this, matroska_track_t * track) {
buf->free_buffer(buf);
return;
}
-
+
buf->size = track->codec_private_len;
buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_END;
buf->type = track->buf_type;
buf->pts = 0;
-
+
if (buf->size)
xine_fast_memcpy (buf->content, track->codec_private, buf->size);
else
buf->content = NULL;
-
+
if(track->default_duration) {
buf->decoder_flags |= BUF_FLAG_FRAMERATE;
- buf->decoder_info[0] = (int64_t)track->default_duration *
+ buf->decoder_info[0] = (int64_t)track->default_duration *
(int64_t)90 / (int64_t)1000000;
}
-
- if(track->video_track && track->video_track->display_width &&
+
+ if(track->video_track && track->video_track->display_width &&
track->video_track->display_height) {
buf->decoder_flags |= BUF_FLAG_ASPECT;
buf->decoder_info[1] = track->video_track->display_width;
buf->decoder_info[2] = track->video_track->display_height;
}
-
+
track->fifo->put (track->fifo, buf);
}
@@ -614,6 +536,8 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) {
int i;
uint8_t *data;
+ if (track->codec_private_len < 3)
+ return;
nb_lace = track->codec_private[0];
if (nb_lace != 2)
return;
@@ -621,11 +545,13 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) {
frame[0] = track->codec_private[1];
frame[1] = track->codec_private[2];
frame[2] = track->codec_private_len - frame[0] - frame[1] - 3;
+ if (frame[2] < 0)
+ return;
data = track->codec_private + 3;
for (i = 0; i < 3; i++) {
buf = track->fifo->buffer_pool_alloc (track->fifo);
-
+
if (frame[i] > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_matroska: private decoder data length (%d) is greater than fifo buffer length (%" PRId32 ")\n",
@@ -634,10 +560,8 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) {
return;
}
buf->size = frame[i];
-
- buf->decoder_flags = BUF_FLAG_HEADER;
- if (i == 2)
- buf->decoder_flags |= BUF_FLAG_FRAME_END;
+
+ buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_START | BUF_FLAG_FRAME_END;
buf->type = track->buf_type;
buf->pts = 0;
@@ -685,7 +609,11 @@ static void init_codec_aac(demux_matroska_t *this, matroska_track_t *track) {
/* Create a DecoderSpecificInfo for initialising libfaad */
sr_index = aac_get_sr_index(atrack->sampling_freq);
- if (!strncmp (&track->codec_id[12], "MAIN", 4))
+ /* newer specification with appended CodecPrivate */
+ if (strlen(track->codec_id) <= 12)
+ profile = 3;
+ /* older specification */
+ else if (!strncmp (&track->codec_id[12], "MAIN", 4))
profile = 0;
else if (!strncmp (&track->codec_id[12], "LC", 2))
profile = 1;
@@ -884,7 +812,7 @@ static void init_codec_vobsub(demux_matroska_t *this,
static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track,
int decoder_flags,
- uint8_t *data, int data_len,
+ uint8_t *data, size_t data_len,
int64_t data_pts, int data_duration,
int input_normpos, int input_time) {
demux_matroska_t *this = (demux_matroska_t *) this_gen;
@@ -921,7 +849,7 @@ static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track,
buf->decoder_info[1] = BUF_SPECIAL_RV_CHUNK_TABLE;
buf->decoder_info[2] = chunks;
buf->decoder_info_ptr[2] = buf->content;
-
+
buf->size = 0;
buf->type = track->buf_type;
@@ -933,7 +861,7 @@ static void handle_realvideo (demux_plugin_t *this_gen, matroska_track_t *track,
static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track,
int decoder_flags,
- uint8_t *data, int data_len,
+ uint8_t *data, size_t data_len,
int64_t data_pts, int data_duration,
int input_normpos, int input_time) {
buf_element_t *buf;
@@ -988,7 +916,7 @@ static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track,
}
}
}
-
+
last_char = *data;
data++; data_len--;
}
@@ -999,16 +927,16 @@ static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track,
buf->size = dest - (char *)buf->content;
buf->extra_info->input_normpos = input_normpos;
buf->extra_info->input_time = input_time;
-
+
track->fifo->put(track->fifo, buf);
} else {
buf->free_buffer(buf);
- }
+ }
}
static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track,
int decoder_flags,
- uint8_t *data, int data_len,
+ uint8_t *data, size_t data_len,
int64_t data_pts, int data_duration,
int input_normpos, int input_time) {
demux_matroska_t *this = (demux_matroska_t *) this_gen;
@@ -1018,7 +946,7 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track,
buf = track->fifo->buffer_pool_alloc(track->fifo);
buf->size = data_len + 9; /* 2 uint32_t + '\0' */
-
+
if (buf->max_size >= buf->size) {
buf->decoder_flags = decoder_flags;
@@ -1027,7 +955,7 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track,
buf->decoder_info[1] = BUF_SPECIAL_CHARSET_ENCODING;
buf->decoder_info_ptr[2] = "utf-8";
buf->decoder_info[2] = strlen(buf->decoder_info_ptr[2]);
-
+
val = (uint32_t *)buf->content;
*val++ = data_pts / 90; /* start time */
*val++ = (data_pts + data_duration) / 90; /* end time */
@@ -1055,7 +983,7 @@ static void handle_sub_utf8 (demux_plugin_t *this_gen, matroska_track_t *track,
*/
static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track,
int decoder_flags,
- uint8_t *data, int data_len,
+ uint8_t *data, size_t data_len,
int64_t data_pts, int data_duration,
int input_normpos, int input_time) {
demux_matroska_t *this = (demux_matroska_t *) this_gen;
@@ -1092,7 +1020,7 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track,
(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;
@@ -1105,11 +1033,11 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track,
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",
@@ -1152,120 +1080,140 @@ static void handle_vobsub (demux_plugin_t *this_gen, matroska_track_t *track,
static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
ebml_parser_t *ebml = this->ebml;
int next_level = 3;
-
+
while (next_level == 3) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
switch (elem.id) {
- case MATROSKA_ID_TR_NUMBER: {
- uint64_t num;
- lprintf("TrackNumber\n");
- if (!ebml_read_uint(ebml, &elem, &num))
- return 0;
- track->track_num = num;
- }
- break;
-
- case MATROSKA_ID_TR_TYPE: {
- uint64_t num;
- lprintf("TrackType\n");
- if (!ebml_read_uint(ebml, &elem, &num))
- return 0;
- track->track_type = num;
- }
- break;
-
- case MATROSKA_ID_TR_CODECID: {
- char *codec_id = malloc (elem.len + 1);
- lprintf("CodecID\n");
- if (!ebml_read_ascii(ebml, &elem, codec_id)) {
- free(codec_id);
- return 0;
- }
- codec_id[elem.len] = '\0';
- track->codec_id = codec_id;
- }
- break;
-
- case MATROSKA_ID_TR_CODECPRIVATE: {
- char *codec_private = malloc (elem.len);
- lprintf("CodecPrivate\n");
- if (!ebml_read_binary(ebml, &elem, codec_private)) {
- free(codec_private);
- return 0;
- }
- track->codec_private = codec_private;
- track->codec_private_len = elem.len;
- }
- break;
-
- case MATROSKA_ID_TR_LANGUAGE: {
- char *language = malloc (elem.len + 1);
- lprintf("Language\n");
- if (!ebml_read_ascii(ebml, &elem, language)) {
- free(language);
- return 0;
- }
- language[elem.len] = '\0';
- track->language = language;
- }
- break;
-
+ case MATROSKA_ID_TR_NUMBER:
+ {
+ uint64_t num;
+ lprintf("TrackNumber\n");
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ track->track_num = num;
+ }
+ break;
+
+ case MATROSKA_ID_TR_TYPE:
+ {
+ uint64_t num;
+ lprintf("TrackType\n");
+ if (!ebml_read_uint(ebml, &elem, &num))
+ return 0;
+ track->track_type = num;
+ }
+ break;
+
+ case MATROSKA_ID_TR_CODECID:
+ {
+ char *codec_id = ebml_alloc_read_ascii (ebml, &elem);
+ lprintf("CodecID\n");
+ if (!codec_id)
+ return 0;
+ track->codec_id = codec_id;
+ }
+ break;
+
+ case MATROSKA_ID_TR_CODECPRIVATE:
+ {
+ char *codec_private;
+ if (elem.len >= 0x80000000)
+ return 0;
+ codec_private = malloc (elem.len);
+ if (! codec_private)
+ return 0;
+ lprintf("CodecPrivate\n");
+ if (!ebml_read_binary(ebml, &elem, codec_private)) {
+ free(codec_private);
+ return 0;
+ }
+ track->codec_private = codec_private;
+ track->codec_private_len = elem.len;
+ }
+ break;
+
+ case MATROSKA_ID_TR_LANGUAGE:
+ {
+ char *language = ebml_alloc_read_ascii (ebml, &elem);
+ lprintf("Language\n");
+ if (!language)
+ return 0;
+ track->language = language;
+ }
+ break;
+
case MATROSKA_ID_TV:
lprintf("Video\n");
if (track->video_track)
return 1;
- track->video_track = (matroska_video_track_t *)xine_xmalloc(sizeof(matroska_video_track_t));
+ track->video_track = (matroska_video_track_t *)calloc(1, sizeof(matroska_video_track_t));
if (!ebml_read_master (ebml, &elem))
return 0;
if ((elem.len > 0) && !parse_video_track(this, track->video_track))
return 0;
- break;
-
+ break;
+
case MATROSKA_ID_TA:
lprintf("Audio\n");
if (track->audio_track)
return 1;
- track->audio_track = (matroska_audio_track_t *)xine_xmalloc(sizeof(matroska_audio_track_t));
+ track->audio_track = (matroska_audio_track_t *)calloc(1, sizeof(matroska_audio_track_t));
if (!ebml_read_master (ebml, &elem))
return 0;
if ((elem.len > 0) && !parse_audio_track(this, track->audio_track))
return 0;
- break;
-
- case MATROSKA_ID_TR_FLAGDEFAULT: {
- uint64_t val;
-
- lprintf("Default\n");
- if (!ebml_read_uint(ebml, &elem, &val))
- return 0;
- track->default_flag = (int)val;
- }
- break;
+ break;
- case MATROSKA_ID_TR_DEFAULTDURATION: {
- uint64_t val;
+ case MATROSKA_ID_TR_FLAGDEFAULT:
+ {
+ uint64_t val;
- if (!ebml_read_uint(ebml, &elem, &val))
- return 0;
- track->default_duration = val;
- lprintf("Default Duration: %"PRIu64"\n", track->default_duration);
- }
- break;
+ lprintf("Default\n");
+ if (!ebml_read_uint(ebml, &elem, &val))
+ return 0;
+ track->default_flag = (int)val;
+ }
+ 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;
+ case MATROSKA_ID_TR_DEFAULTDURATION:
+ {
+ uint64_t val;
+
+ if (!ebml_read_uint(ebml, &elem, &val))
+ return 0;
+ track->default_duration = val;
+ 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;
case MATROSKA_ID_TR_UID:
+ {
+ uint64_t val;
+
+ if (!ebml_read_uint(ebml, &elem, &val)) {
+ lprintf("Track UID (invalid)\n");
+ return 0;
+ }
+
+ track->uid = val;
+ lprintf("Track UID: 0x%" PRIx64 "\n", track->uid);
+ }
+ break;
+
case MATROSKA_ID_TR_FLAGENABLED:
case MATROSKA_ID_TR_FLAGLACING:
case MATROSKA_ID_TR_MINCACHE:
@@ -1286,68 +1234,76 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
}
next_level = ebml_get_next_level(ebml, &elem);
}
-
+
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "demux_matroska: Track %d, %s %s\n",
- track->track_num,
- (track->codec_id ? track->codec_id : ""),
- (track->language ? track->language : ""));
+ "demux_matroska: Track %d, %s %s\n",
+ track->track_num,
+ (track->codec_id ? track->codec_id : ""),
+ (track->language ? track->language : ""));
if (track->codec_id) {
void (*init_codec)(demux_matroska_t *, matroska_track_t *) = NULL;
if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_VFW_FOURCC)) {
xine_bmiheader *bih;
- lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n");
- bih = (xine_bmiheader*)track->codec_private;
- _x_bmiheader_le2me(bih);
+ if (track->codec_private_len >= sizeof(xine_bmiheader)) {
+ lprintf("MATROSKA_CODEC_ID_V_VFW_FOURCC\n");
+ bih = (xine_bmiheader*)track->codec_private;
+ _x_bmiheader_le2me(bih);
- track->buf_type = _x_fourcc_to_buf_video(bih->biCompression);
- init_codec = init_codec_video;
+ track->buf_type = _x_fourcc_to_buf_video(bih->biCompression);
+ init_codec = init_codec_video;
+ }
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_UNCOMPRESSED)) {
} else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_SP)) ||
- (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_ASP)) ||
- (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AP))) {
+ (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_ASP)) ||
+ (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AP))) {
xine_bmiheader *bih;
-
+
lprintf("MATROSKA_CODEC_ID_V_MPEG4_*\n");
+ if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader))
+ track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader);
+
/* create a bitmap info header struct for MPEG 4 */
- bih = malloc(sizeof(xine_bmiheader) + track->codec_private_len);
+ bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len);
bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len;
bih->biCompression = ME_FOURCC('M', 'P', '4', 'S');
bih->biWidth = track->video_track->pixel_width;
bih->biHeight = track->video_track->pixel_height;
_x_bmiheader_le2me(bih);
-
+
/* add bih extra data */
memcpy(bih + 1, track->codec_private, track->codec_private_len);
free(track->codec_private);
track->codec_private = (uint8_t *)bih;
track->codec_private_len = bih->biSize;
track->buf_type = BUF_VIDEO_MPEG4;
-
+
/* init as a vfw decoder */
init_codec = init_codec_video;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MPEG4_AVC)) {
xine_bmiheader *bih;
-
+
lprintf("MATROSKA_CODEC_ID_V_MPEG4_AVC\n");
+ if (track->codec_private_len > 0x7fffffff - sizeof(xine_bmiheader))
+ track->codec_private_len = 0x7fffffff - sizeof(xine_bmiheader);
+
/* create a bitmap info header struct for h264 */
- bih = malloc(sizeof(xine_bmiheader) + track->codec_private_len);
+ bih = calloc(1, sizeof(xine_bmiheader) + track->codec_private_len);
bih->biSize = sizeof(xine_bmiheader) + track->codec_private_len;
bih->biCompression = ME_FOURCC('a', 'v', 'c', '1');
bih->biWidth = track->video_track->pixel_width;
bih->biHeight = track->video_track->pixel_height;
_x_bmiheader_le2me(bih);
-
+
/* add bih extra data */
memcpy(bih + 1, track->codec_private, track->codec_private_len);
free(track->codec_private);
track->codec_private = (uint8_t *)bih;
track->codec_private_len = bih->biSize;
track->buf_type = BUF_VIDEO_H264;
-
+
/* init as a vfw decoder */
init_codec = init_codec_video;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_MSMPEG4V3)) {
@@ -1368,7 +1324,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
track->handle_content = handle_realvideo;
init_codec = init_codec_real;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_V_REAL_RV40)) {
-
+
lprintf("MATROSKA_CODEC_ID_V_REAL_RV40\n");
track->buf_type = BUF_VIDEO_RV40;
track->handle_content = handle_realvideo;
@@ -1380,8 +1336,8 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
track->buf_type = BUF_VIDEO_THEORA_RAW;
init_codec = init_codec_xiph;
} else if ((!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L1)) ||
- (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L2)) ||
- (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L3))) {
+ (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L2)) ||
+ (!strcmp(track->codec_id, MATROSKA_CODEC_ID_A_MPEG1_L3))) {
lprintf("MATROSKA_CODEC_ID_A_MPEG1\n");
track->buf_type = BUF_AUDIO_MPEG;
init_codec = init_codec_audio;
@@ -1393,7 +1349,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
lprintf("MATROSKA_CODEC_ID_A_AC3\n");
track->buf_type = BUF_AUDIO_A52;
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;
@@ -1409,13 +1365,15 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
xine_waveformatex *wfh;
lprintf("MATROSKA_CODEC_ID_A_ACM\n");
- wfh = (xine_waveformatex*)track->codec_private;
- _x_waveformatex_le2me(wfh);
+ if (track->codec_private_len >= sizeof(xine_waveformatex)) {
+ wfh = (xine_waveformatex*)track->codec_private;
+ _x_waveformatex_le2me(wfh);
- track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag);
- init_codec = init_codec_audio;
+ track->buf_type = _x_formattag_to_buf_audio(wfh->wFormatTag);
+ init_codec = init_codec_audio;
+ }
} else if (!strncmp(track->codec_id, MATROSKA_CODEC_ID_A_AAC,
- sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) {
+ sizeof(MATROSKA_CODEC_ID_A_AAC) - 1)) {
lprintf("MATROSKA_CODEC_ID_A_AAC\n");
track->buf_type = BUF_AUDIO_AAC;
init_codec = init_codec_aac;
@@ -1435,17 +1393,17 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
track->buf_type = BUF_AUDIO_ATRK;
init_codec = init_codec_real;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_UTF8) ||
- !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_UTF8)) {
+ !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_UTF8)) {
lprintf("MATROSKA_CODEC_ID_S_TEXT_UTF8\n");
track->buf_type = BUF_SPU_OGM;
track->handle_content = handle_sub_utf8;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_SSA) ||
- !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_SSA)) {
+ !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_SSA)) {
lprintf("MATROSKA_CODEC_ID_S_TEXT_SSA\n");
track->buf_type = BUF_SPU_OGM;
track->handle_content = handle_sub_ssa;
} else if (!strcmp(track->codec_id, MATROSKA_CODEC_ID_S_TEXT_ASS) ||
- !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_ASS)) {
+ !strcmp(track->codec_id, MATROSKA_CODEC_ID_S_ASS)) {
lprintf("MATROSKA_CODEC_ID_S_TEXT_ASS\n");
track->buf_type = BUF_SPU_OGM;
track->handle_content = handle_sub_ssa;
@@ -1458,7 +1416,7 @@ 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.
@@ -1494,12 +1452,17 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
break;
}
- if (init_codec)
+ if (init_codec) {
+ if (! track->fifo) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: Error: fifo not set up for track of type type %" PRIu32 "\n", track->track_type);
+ return 0;
+ }
init_codec(this, track);
-
+ }
}
}
-
+
return 1;
}
@@ -1507,10 +1470,10 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) {
static int parse_tracks(demux_matroska_t *this) {
ebml_parser_t *ebml = this->ebml;
int next_level = 2;
-
+
while (next_level == 2) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -1518,8 +1481,14 @@ static int parse_tracks(demux_matroska_t *this) {
case MATROSKA_ID_TR_ENTRY: {
matroska_track_t *track;
+ /* bail out early if no more tracks can be handled! */
+ if (this->num_tracks >= MAX_STREAMS) {
+ lprintf("Too many tracks!\n");
+ return 0;
+ }
+
/* alloc and initialize a track with 0 */
- track = xine_xmalloc(sizeof(matroska_track_t));
+ track = calloc(1, sizeof(matroska_track_t));
track->compress_algo = MATROSKA_COMPRESS_NONE;
this->tracks[this->num_tracks] = track;
@@ -1531,29 +1500,7 @@ static int parse_tracks(demux_matroska_t *this) {
this->num_tracks++;
}
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_chapters(demux_matroska_t *this) {
- ebml_parser_t *ebml = this->ebml;
- int next_level = 2;
-
- while (next_level == 2) {
- ebml_elem_t elem;
-
- if (!ebml_read_elem_head(ebml, &elem))
- return 0;
-
- switch (elem.id) {
default:
lprintf("Unhandled ID: 0x%x\n", elem.id);
if (!ebml_skip(ebml, &elem))
@@ -1564,15 +1511,14 @@ static int parse_chapters(demux_matroska_t *this) {
return 1;
}
-
static int parse_cue_trackposition(demux_matroska_t *this, int *track_num,
int64_t *pos) {
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;
@@ -1609,10 +1555,10 @@ static int parse_cue_point(demux_matroska_t *this) {
int next_level = 3;
int64_t timecode = -1, pos = -1;
int track_num = -1;
-
+
while (next_level == 3) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -1677,10 +1623,10 @@ static int parse_cue_point(demux_matroska_t *this) {
static int parse_cues(demux_matroska_t *this) {
ebml_parser_t *ebml = this->ebml;
int next_level = 2;
-
+
while (next_level == 2) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -1706,10 +1652,10 @@ static int parse_cues(demux_matroska_t *this) {
static int parse_attachments(demux_matroska_t *this) {
ebml_parser_t *ebml = this->ebml;
int next_level = 2;
-
+
while (next_level == 2) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -1728,10 +1674,10 @@ static int parse_attachments(demux_matroska_t *this) {
static int parse_tags(demux_matroska_t *this) {
ebml_parser_t *ebml = this->ebml;
int next_level = 2;
-
+
while (next_level == 2) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -1746,7 +1692,7 @@ static int parse_tags(demux_matroska_t *this) {
return 1;
}
-static void alloc_block_data (demux_matroska_t *this, int len) {
+static void alloc_block_data (demux_matroska_t *this, size_t len) {
/* memory management */
if (this->block_data_size < len) {
if (this->block_data)
@@ -1770,7 +1716,7 @@ static int parse_ebml_uint(demux_matroska_t *this, uint8_t *data, uint64_t *num)
}
if (size > 8) {
off_t pos = this->input->get_current_pos(this->input);
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
"demux_matroska: Invalid Track Number at position %" PRIdMAX "\n",
(intmax_t)pos);
return 0;
@@ -1799,7 +1745,7 @@ static int parse_ebml_sint(demux_matroska_t *this, uint8_t *data, int64_t *num)
*num = -1;
else
*num = unum - ((1 << ((7 * size) - 1)) - 1);
-
+
return size;
}
@@ -1818,10 +1764,15 @@ static int find_track_by_id(demux_matroska_t *this, int track_num,
}
-static int read_block_data (demux_matroska_t *this, int len) {
+static int read_block_data (demux_matroska_t *this, size_t len) {
alloc_block_data(this, len);
/* block datas */
+ if (! this->block_data) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: memory allocation error\n");
+ return 0;
+ }
if (this->input->read(this->input, this->block_data, len) != len) {
off_t pos = this->input->get_current_pos(this->input);
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
@@ -1832,15 +1783,24 @@ static int read_block_data (demux_matroska_t *this, int len) {
return 1;
}
-static int parse_block (demux_matroska_t *this, uint64_t block_size,
+static int parse_int16(uint8_t *data) {
+ int value = (int)_X_BE_16(data);
+ if (value & 1<<15)
+ {
+ value -= 1<<16;
+ }
+ return value;
+}
+
+static int parse_block (demux_matroska_t *this, size_t block_size,
uint64_t cluster_timecode, uint64_t block_duration,
int normpos, int is_key) {
matroska_track_t *track;
- int64_t track_num;
+ uint64_t track_num;
uint8_t *data;
uint8_t flags;
int gap, lacing, num_len;
- int timecode_diff;
+ int16_t timecode_diff;
int64_t pts, xduration;
int decoder_flags = 0;
@@ -1848,14 +1808,15 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
if (!(num_len = parse_ebml_uint(this, data, &track_num)))
return 0;
data += num_len;
-
- timecode_diff = (int)_X_BE_16(data);
+
+ /* timecode_diff is signed */
+ timecode_diff = (int16_t)parse_int16(data);
data += 2;
flags = *data;
data += 1;
-
- lprintf("track_num: %" PRId64 ", timecode_diff: %d, flags: 0x%x\n", track_num, timecode_diff, flags);
+
+ lprintf("track_num: %" PRIu64 ", timecode_diff: %d, flags: 0x%x\n", track_num, timecode_diff, flags);
gap = flags & 1;
lacing = (flags >> 1) & 0x3;
@@ -1863,7 +1824,7 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
if (!find_track_by_id(this, (int)track_num, &track)) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "demux_matroska: invalid track id: %" PRId64 "\n", track_num);
+ "demux_matroska: invalid track id: %" PRIu64 "\n", track_num);
return 0;
}
@@ -1897,11 +1858,11 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
}
if (lacing == MATROSKA_NO_LACING) {
- int block_size_left;
+ size_t block_size_left;
lprintf("no lacing\n");
block_size_left = (this->block_data + block_size) - data;
- lprintf("size: %d, block_size: %" PRIu64 "\n", block_size_left, block_size);
+ lprintf("size: %d, block_size: %u\n", block_size_left, block_size);
if (track->handle_content != NULL) {
track->handle_content((demux_plugin_t *)this, track,
@@ -1917,9 +1878,9 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
}
} else {
- int block_size_left;
+ size_t block_size_left;
uint8_t lace_num;
- int frame[MAX_FRAMES];
+ size_t frame[MAX_FRAMES];
int i;
/* number of laced frames */
@@ -1961,7 +1922,7 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
int frame_size;
lprintf("fixed size lacing\n");
-
+
frame_size = block_size_left / (lace_num + 1);
for (i = 0; i < lace_num; i++) {
frame[i] = frame_size;
@@ -1972,24 +1933,51 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
break;
case MATROSKA_EBML_LACING: {
- int64_t tmp;
+ uint64_t first_frame_size;
lprintf("ebml lacing\n");
/* size of each frame */
- if (!(num_len = parse_ebml_uint(this, data, &tmp)))
+ if (!(num_len = parse_ebml_uint(this, data, &first_frame_size)))
+ return 0;
+ if (num_len > block_size_left) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: block too small\n");
return 0;
+ }
+ if (first_frame_size > INT_MAX) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: invalid first frame size (%" PRId64 ")\n",
+ first_frame_size);
+ return 0;
+ }
data += num_len; block_size_left -= num_len;
- frame[0] = (int) tmp;
+ frame[0] = (int) first_frame_size;
lprintf("first frame len: %d\n", frame[0]);
block_size_left -= frame[0];
for (i = 1; i < lace_num; i++) {
- if (!(num_len = parse_ebml_sint(this, data, &tmp)))
+ int64_t frame_size_diff;
+ int64_t frame_size;
+
+ if (!(num_len = parse_ebml_sint(this, data, &frame_size_diff)))
return 0;
+ if (num_len > block_size_left) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: block too small\n");
+ return 0;
+ }
data += num_len; block_size_left -= num_len;
- frame[i] = frame[i-1] + tmp;
+
+ frame_size = frame[i-1] + frame_size_diff;
+ if (frame_size > INT_MAX || frame_size < 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_matroska: invalid frame size (%" PRId64 ")\n",
+ frame_size);
+ return 0;
+ }
+ frame[i] = frame_size;
block_size_left -= frame[i];
}
@@ -2023,6 +2011,31 @@ static int parse_block (demux_matroska_t *this, uint64_t block_size,
return 1;
}
+static int parse_simpleblock(demux_matroska_t *this, size_t block_len, uint64_t cluster_timecode, uint64_t block_duration)
+{
+ int has_block = 0;
+ off_t block_pos = 0;
+ off_t file_len = 0;
+ int normpos = 0;
+ int is_key = 1;
+
+ lprintf("simpleblock\n");
+ block_pos = this->input->get_current_pos(this->input);
+ file_len = this->input->get_length(this->input);
+ if( file_len )
+ normpos = (int) ( (double) block_pos * 65535 / file_len );
+
+ if (!read_block_data(this, block_len))
+ return 0;
+
+ has_block = 1;
+ /* we have the duration, we can parse the block now */
+ if (!parse_block(this, block_len, cluster_timecode, block_duration,
+ normpos, is_key))
+ return 0;
+ return 1;
+}
+
static int parse_block_group(demux_matroska_t *this,
uint64_t cluster_timecode,
uint64_t cluster_duration) {
@@ -2033,7 +2046,7 @@ static int parse_block_group(demux_matroska_t *this,
off_t block_pos = 0;
off_t file_len = 0;
int normpos = 0;
- int block_len = 0;
+ size_t block_len = 0;
int is_key = 1;
while (next_level == 3) {
@@ -2085,9 +2098,52 @@ static int parse_block_group(demux_matroska_t *this,
return 1;
}
+static int demux_matroska_seek (demux_plugin_t*, off_t, int, int);
+
+static void handle_events(demux_matroska_t *this) {
+ xine_event_t* event;
+
+ while ((event = xine_event_get(this->event_queue))) {
+ if (this->num_editions > 0) {
+ matroska_edition_t* ed = this->editions[0];
+ int chapter_idx = matroska_get_chapter(this, this->last_timecode, &ed);
+ uint64_t next_time;
+
+ if (chapter_idx < 0) {
+ xine_event_free(event);
+ continue;
+ }
+
+ switch(event->type) {
+ case XINE_EVENT_INPUT_NEXT:
+ if (chapter_idx < ed->num_chapters-1) {
+ next_time = ed->chapters[chapter_idx+1]->time_start / 90;
+ demux_matroska_seek((demux_plugin_t*)this, 0, next_time, 1);
+ }
+ break;
+
+ /* TODO: should this try to implement common "start of chapter"
+ * functionality? */
+ case XINE_EVENT_INPUT_PREVIOUS:
+ if (chapter_idx > 0) {
+ next_time = ed->chapters[chapter_idx-1]->time_start / 90;
+ demux_matroska_seek((demux_plugin_t*)this, 0, next_time, 1);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ xine_event_free(event);
+ }
+}
+
static int parse_cluster(demux_matroska_t *this) {
ebml_parser_t *ebml = this->ebml;
- int next_level = 2;
+ int this_level = ebml->level;
+ int next_level = this_level;
uint64_t timecode = 0;
uint64_t duration = 0;
@@ -2104,7 +2160,9 @@ static int parse_cluster(demux_matroska_t *this) {
this->first_cluster_found = 1;
}
- while (next_level == 2) {
+ handle_events(this);
+
+ while (next_level == this_level) {
ebml_elem_t elem;
if (!ebml_read_elem_head(ebml, &elem))
@@ -2128,6 +2186,11 @@ static int parse_cluster(demux_matroska_t *this) {
if ((elem.len > 0) && !parse_block_group(this, timecode, duration))
return 0;
break;
+ case MATROSKA_ID_CL_SIMPLEBLOCK:
+ lprintf("simpleblock\n");
+ if (!parse_simpleblock(this, elem.len, timecode, duration))
+ return 0;
+ break;
case MATROSKA_ID_CL_BLOCK:
lprintf("block\n");
if (!ebml_skip(ebml, &elem))
@@ -2140,6 +2203,49 @@ static int parse_cluster(demux_matroska_t *this) {
}
next_level = ebml_get_next_level(ebml, &elem);
}
+
+ /* at this point, we MUST have a timecode (according to format spec).
+ * Use that to find the chapter we are in, and adjust the title.
+ *
+ * TODO: this only looks at the chapters in the first edition.
+ */
+
+ this->last_timecode = timecode;
+
+ if (this->num_editions <= 0)
+ return 1;
+ matroska_edition_t *ed = this->editions[0];
+
+ if (ed->num_chapters <= 0)
+ return 1;
+
+ /* fix up a makeshift title if none has been set yet (e.g. filename) */
+ if (NULL == this->title && NULL != _x_meta_info_get(this->stream, XINE_META_INFO_TITLE))
+ this->title = strdup(_x_meta_info_get(this->stream, XINE_META_INFO_TITLE));
+
+ if (NULL == this->title)
+ this->title = strdup("(No title)");
+
+ if (NULL == this->title) {
+ lprintf("Failed to determine a valid stream title!\n");
+ return 1;
+ }
+
+ int chapter_idx = matroska_get_chapter(this, timecode, &ed);
+ if (chapter_idx < 0) {
+ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, this->title);
+ return 1;
+ }
+
+ xine_ui_data_t uidata = {
+ .str = {0, },
+ .str_len = 0,
+ };
+
+ uidata.str_len = snprintf(uidata.str, sizeof(uidata.str), "%s / (%d) %s",
+ this->title, chapter_idx+1, ed->chapters[chapter_idx]->title);
+ _x_meta_info_set_utf8(this->stream, XINE_META_INFO_TITLE, uidata.str);
+
return 1;
}
@@ -2152,10 +2258,10 @@ static int parse_seek_entry(demux_matroska_t *this) {
int has_position = 0;
uint64_t id = 0;
uint64_t pos;
-
+
while (next_level == 3) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -2179,26 +2285,26 @@ static int parse_seek_entry(demux_matroska_t *this) {
}
next_level = ebml_get_next_level(ebml, &elem);
}
-
+
/* do not parse clusters */
if (id == MATROSKA_ID_CLUSTER) {
lprintf("skip cluster\n");
return 1;
}
-
- /* parse the referenced element */
+
+ /* parse the referenced element */
if (has_id && has_position) {
off_t current_pos, seek_pos;
-
+
seek_pos = this->segment.start + pos;
-
+
if ((seek_pos > 0) && (seek_pos < this->input->get_length(this->input))) {
ebml_parser_t ebml_bak;
/* backup current state */
current_pos = this->input->get_current_pos(this->input);
memcpy(&ebml_bak, this->ebml, sizeof(ebml_parser_t)); /* FIXME */
-
+
/* seek and parse the top_level element */
this->ebml->level = 1;
if (this->input->seek(this->input, seek_pos, SEEK_SET) < 0) {
@@ -2237,7 +2343,7 @@ static int parse_seekhead(demux_matroska_t *this) {
while (next_level == 2) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -2274,18 +2380,19 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) {
ebml_elem_t elem;
int ret_value = 1;
off_t current_pos;
-
+
+
current_pos = this->input->get_current_pos(this->input);
lprintf("current_pos: %" PRIdMAX "\n", (intmax_t)current_pos);
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
-
+
if (!find_top_level_entry(this, current_pos)) {
if (!add_top_level_entry(this, current_pos))
return 0;
-
+
switch (elem.id) {
case MATROSKA_ID_SEEKHEAD:
lprintf("SeekHead\n");
@@ -2312,7 +2419,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) {
lprintf("Chapters\n");
if (!ebml_read_master (ebml, &elem))
return 0;
- if ((elem.len > 0) && !parse_chapters(this))
+ if ((elem.len > 0) && !matroska_parse_chapters(this))
return 0;
break;
case MATROSKA_ID_CLUSTER:
@@ -2352,7 +2459,7 @@ static int parse_top_level_head(demux_matroska_t *this, int *next_level) {
if (!ebml_skip(ebml, &elem))
return 0;
}
-
+
if (next_level)
*next_level = ebml_get_next_level(ebml, &elem);
@@ -2439,12 +2546,12 @@ static int parse_segment(demux_matroska_t *this) {
if (this->segment.id == MATROSKA_ID_SEGMENT) {
int res;
int next_level;
-
+
lprintf("Segment detected\n");
if (!ebml_read_master (ebml, &this->segment))
return 0;
-
+
res = 1;
next_level = 1;
/* stop the loop on the first cluster */
@@ -2496,14 +2603,14 @@ static void demux_matroska_send_headers (demux_plugin_t *this_gen) {
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, (this->num_video_tracks != 0));
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, (this->num_audio_tracks != 0));
-
+
/*
* send preview buffers
*/
/* enter in the segment */
ebml_read_master (this->ebml, &this->segment);
-
+
/* seek back to the beginning of the segment */
next_level = 1;
if (this->input->seek(this->input, this->segment.start, SEEK_SET) < 0) {
@@ -2513,7 +2620,7 @@ static void demux_matroska_send_headers (demux_plugin_t *this_gen) {
this->status = DEMUX_FINISHED;
return;
}
-
+
this->preview_sent = 0;
this->preview_mode = 1;
@@ -2599,7 +2706,7 @@ static int demux_matroska_seek (demux_plugin_t *this_gen,
matroska_index_t *index;
matroska_track_t *track;
int i, entry;
-
+
start_pos = (off_t) ( (double) start_pos / 65535 *
this->input->get_length (this->input) );
@@ -2655,10 +2762,10 @@ static int demux_matroska_seek (demux_plugin_t *this_gen,
index->track_num, start_pos ? "pos" : "time",
start_pos ? (intmax_t)start_pos : (intmax_t)start_time,
index->track_num, index->timecode[entry], (intmax_t)index->pos[entry]);
-
+
if (this->input->seek(this->input, index->pos[entry], SEEK_SET) < 0)
this->status = DEMUX_FINISHED;
-
+
/* we always seek to the ebml level 1 */
this->ebml->level = 1;
@@ -2672,10 +2779,12 @@ static int demux_matroska_seek (demux_plugin_t *this_gen,
static void demux_matroska_dispose (demux_plugin_t *this_gen) {
-
+
demux_matroska_t *this = (demux_matroska_t *) this_gen;
int i;
+ free(this->block_data);
+
/* free tracks */
for (i = 0; i < this->num_tracks; i++) {
matroska_track_t *track;
@@ -2693,7 +2802,7 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) {
free (track->audio_track);
if (track->sub_track)
free (track->sub_track);
-
+
free (track);
}
/* Free the cues. */
@@ -2705,12 +2814,17 @@ static void demux_matroska_dispose (demux_plugin_t *this_gen) {
}
if (this->indexes)
free(this->indexes);
-
- /* Free the top_level elem list */
+
+ /* Free the top_level elem list */
if (this->top_level_list)
free(this->top_level_list);
+ free(this->title);
+
+ matroska_free_editions(this);
+
dispose_ebml_parser(this->ebml);
+ xine_event_dispose_queue(this->event_queue);
free (this);
}
@@ -2724,7 +2838,13 @@ static int demux_matroska_get_stream_length (demux_plugin_t *this_gen) {
static uint32_t demux_matroska_get_capabilities (demux_plugin_t *this_gen) {
- return DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG;
+ demux_matroska_t* this = (demux_matroska_t*)this_gen;
+ uint32_t caps = DEMUX_CAP_SPULANG | DEMUX_CAP_AUDIOLANG;
+
+ if(this->num_editions > 0 && this->editions[0]->num_chapters > 0)
+ caps |= DEMUX_CAP_CHAPTERS;
+
+ return caps;
}
@@ -2741,7 +2861,7 @@ static int demux_matroska_get_optional_data (demux_plugin_t *this_gen,
if ((channel >= 0) && (channel < this->num_sub_tracks)) {
for (track_num = 0; track_num < this->num_tracks; track_num++) {
matroska_track_t *track = this->tracks[track_num];
-
+
if ((track->buf_type & 0xFF00001F) == (BUF_SPU_BASE + channel)) {
if (track->language) {
strncpy (str, track->language, XINE_LANG_MAX);
@@ -2757,13 +2877,13 @@ static int demux_matroska_get_optional_data (demux_plugin_t *this_gen,
}
}
return DEMUX_OPTIONAL_UNSUPPORTED;
-
+
case DEMUX_OPTIONAL_DATA_AUDIOLANG:
lprintf ("DEMUX_OPTIONAL_DATA_AUDIOLANG channel = %d\n",channel);
if ((channel >= 0) && (channel < this->num_audio_tracks)) {
for (track_num = 0; track_num < this->num_tracks; track_num++) {
matroska_track_t *track = this->tracks[track_num];
-
+
if ((track->buf_type & 0xFF00001F) == (BUF_AUDIO_BASE + channel)) {
if (track->language) {
strncpy (str, track->language, XINE_LANG_MAX);
@@ -2824,7 +2944,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_matroska_t));
+ this = calloc(1, sizeof(demux_matroska_t));
this->demux_plugin.send_headers = demux_matroska_send_headers;
this->demux_plugin.send_chunk = demux_matroska_send_chunk;
@@ -2855,11 +2975,18 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
if (strcmp(ebml->doctype, "matroska"))
goto error;
+ this->event_queue = xine_event_new_queue(this->stream);
+
return &this->demux_plugin;
error:
dispose_ebml_parser(ebml);
- free(this);
+
+ if (NULL != this) {
+ xine_event_dispose_queue(this->event_queue);
+ free(this);
+ }
+
return NULL;
}
@@ -2884,7 +3011,8 @@ static const char *get_extensions (demux_class_t *this_gen) {
static const char *get_mimetypes (demux_class_t *this_gen) {
- return "video/mkv: mkv: matroska;";
+ return "video/mkv: mkv: matroska;"
+ "video/x-matroska: mkv: matroska;";
}
@@ -2899,7 +3027,7 @@ static void *init_class (xine_t *xine, void *data) {
demux_matroska_class_t *this;
- this = xine_xmalloc (sizeof (demux_matroska_class_t));
+ this = calloc(1, sizeof(demux_matroska_class_t));
this->xine = xine;
this->demux_class.open_plugin = open_plugin;
diff --git a/src/demuxers/demux_matroska.h b/src/demuxers/demux_matroska.h
new file mode 100644
index 000000000..e1611f397
--- /dev/null
+++ b/src/demuxers/demux_matroska.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2000-2008 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * demultiplexer for matroska streams: shared header
+ */
+
+#ifndef _DEMUX_MATROSKA_H_
+#define _DEMUX_MATROSKA_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <zlib.h>
+
+#include "xine_internal.h"
+#include "demux.h"
+#include "buffer.h"
+#include "bswap.h"
+
+#include "ebml.h"
+#include "matroska.h"
+
+#define NUM_PREVIEW_BUFFERS 10
+
+#define MAX_STREAMS 128
+#define MAX_FRAMES 32
+
+#define WRAP_THRESHOLD 90000
+
+typedef struct {
+ int track_num;
+ off_t *pos;
+ uint64_t *timecode;
+ int num_entries;
+
+} matroska_index_t;
+
+typedef struct {
+
+ demux_plugin_t demux_plugin;
+
+ xine_stream_t *stream;
+
+ input_plugin_t *input;
+
+ int status;
+
+ ebml_parser_t *ebml;
+
+ /* segment element */
+ ebml_elem_t segment;
+ uint64_t timecode_scale;
+ int duration; /* in millis */
+ int preview_sent;
+ int preview_mode;
+ char *title;
+
+ /* meta seek info */
+ int has_seekhead;
+ int seekhead_handled;
+
+ /* seek info */
+ matroska_index_t *indexes;
+ int num_indexes;
+ int first_cluster_found;
+ int skip_to_timecode;
+ int skip_for_track;
+
+ /* tracks */
+ int num_tracks;
+ int num_video_tracks;
+ int num_audio_tracks;
+ int num_sub_tracks;
+
+ matroska_track_t *tracks[MAX_STREAMS];
+
+ /* maintain editions, number and capacity */
+ int num_editions, cap_editions;
+ matroska_edition_t **editions;
+
+ /* block */
+ uint8_t *block_data;
+ size_t block_data_size;
+
+ /* current tracks */
+ matroska_track_t *video_track; /* to remove */
+ matroska_track_t *audio_track; /* to remove */
+ matroska_track_t *sub_track; /* to remove */
+ uint64_t last_timecode;
+
+ int send_newpts;
+ int buf_flag_seek;
+
+ /* seekhead parsing */
+ int top_level_list_size;
+ int top_level_list_max_size;
+ off_t *top_level_list;
+
+ /* event handling (chapter navigation) */
+ xine_event_queue_t *event_queue;
+} demux_matroska_t ;
+
+typedef struct {
+
+ demux_class_t demux_class;
+
+ /* class-wide, global variables here */
+
+ xine_t *xine;
+
+} demux_matroska_class_t;
+
+/* "entry points" for chapter handling.
+ * The parser descends into "Chapters" elements at the _parse_ function,
+ * and editions care about cleanup internally. */
+int matroska_parse_chapters(demux_matroska_t*);
+void matroska_free_editions(demux_matroska_t*);
+
+/* Search an edition for the chapter matching a given timecode.
+ *
+ * Return: chapter index, or -1 if none is found.
+ *
+ * TODO: does not handle chapter end times yet.
+ */
+int matroska_get_chapter(demux_matroska_t*, uint64_t, matroska_edition_t**);
+
+#endif /* _DEMUX_MATROSKA_H_ */
diff --git a/src/demuxers/demux_mng.c b/src/demuxers/demux_mng.c
index 12da8ca86..2fccd0b9e 100644
--- a/src/demuxers/demux_mng.c
+++ b/src/demuxers/demux_mng.c
@@ -104,7 +104,12 @@ static mng_bool mymng_close_stream(mng_handle mngh){
static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread){
demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
- *bytesread = this->input->read(this->input, buffer, size);
+ off_t n = this->input->read(this->input, buffer, size);
+ if (n < 0) {
+ *bytesread = 0;
+ return MNG_FALSE;
+ }
+ *bytesread = n;
return MNG_TRUE;
}
@@ -112,11 +117,16 @@ static mng_bool mymng_read_stream(mng_handle mngh, mng_ptr buffer, mng_uint32 si
static mng_bool mymng_process_header(mng_handle mngh, mng_uint32 width, mng_uint32 height){
demux_mng_t *this = (demux_mng_t*)mng_get_userdata(mngh);
+ if (width > 0x8000 || height > 0x8000)
+ return MNG_FALSE;
+
this->bih.biWidth = (width + 7) & ~7;
this->bih.biHeight = height;
this->left_edge = (this->bih.biWidth - width) / 2;
- this->image = malloc(this->bih.biWidth * height * 3);
+ this->image = malloc((mng_size_t)this->bih.biWidth * (mng_size_t)height * 3);
+ if (!this->image)
+ return MNG_FALSE;
mng_set_canvasstyle(mngh, MNG_CANVAS_RGB8);
@@ -171,7 +181,7 @@ static int demux_mng_send_chunk(demux_mng_t *this){
buf->decoder_flags = BUF_FLAG_FRAMERATE;
buf->decoder_info[0] = 90 * this->timer_count;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = this->tick_count;
buf->pts = 90 * this->tick_count;
@@ -260,7 +270,7 @@ static demux_plugin_t* open_plugin(demux_class_t *class_gen, xine_stream_t *stre
demux_mng_t *this;
- this = xine_xmalloc (sizeof (demux_mng_t));
+ this = calloc(1, sizeof(demux_mng_t));
this->stream = stream;
this->input = input;
@@ -360,7 +370,7 @@ static void class_dispose(demux_class_t *this){
static void *init_plugin(xine_t *xine, void *data){
demux_mng_class_t *this;
- this = xine_xmalloc (sizeof (demux_mng_class_t));
+ this = calloc(1, sizeof(demux_mng_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_mod.c b/src/demuxers/demux_mod.c
index e7c6f86b3..0439be7ee 100644
--- a/src/demuxers/demux_mod.c
+++ b/src/demuxers/demux_mod.c
@@ -73,17 +73,17 @@ typedef struct {
char *title;
char *artist;
char *copyright;
- off_t filesize;
-
+ size_t filesize;
+
char *buffer;
int64_t current_pts;
-
+
ModPlug_Settings settings;
ModPlugFile *mpfile;
int mod_length;
int seek_flag; /* this is set when a seek just occurred */
-
+
} demux_mod_t;
typedef struct {
@@ -130,30 +130,41 @@ static int probe_mod_file(demux_mod_t *this) {
/* returns 1 if the MOD file was opened successfully, 0 otherwise */
static int open_mod_file(demux_mod_t *this) {
int total_read;
-
+ off_t input_length;
+
/* Get size and create buffer */
- this->filesize = this->input->get_length(this->input);
+ input_length = this->input->get_length(this->input);
+ /* Avoid potential issues with signed variables and e.g. read() returning -1 */
+ if (input_length > 0x7FFFFFFF || input_length < 0) {
+ xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - size overflow\n");
+ return 0;
+ }
+ this->filesize = input_length;
this->buffer = (char *)malloc(this->filesize);
-
+ if(!this->buffer) {
+ xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - allocation failure\n");
+ return 0;
+ }
+
/* Seek to beginning */
this->input->seek(this->input, 0, SEEK_SET);
-
+
/* Read data */
total_read = this->input->read(this->input, this->buffer, this->filesize);
-
+
if(total_read != this->filesize) {
xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - filesize error\n");
free(this->buffer);
return 0;
}
-
+
this->mpfile = ModPlug_Load(this->buffer, this->filesize);
if (this->mpfile==NULL) {
xine_log(this->stream->xine, XINE_LOG_PLUGIN, "modplug - load error\n");
free(this->buffer);
return 0;
}
-
+
/* Set up modplug engine */
ModPlug_GetSettings(&this->settings);
this->settings.mResamplingMode = MODPLUG_RESAMPLE_FIR; /* RESAMP */
@@ -161,13 +172,15 @@ static int open_mod_file(demux_mod_t *this) {
this->settings.mBits = MOD_BITS;
this->settings.mFrequency = MOD_SAMPLERATE;
ModPlug_SetSettings(&this->settings);
-
+
this->title = strdup(ModPlug_GetName(this->mpfile));
this->artist = strdup("");
this->copyright = strdup("");
-
+
this->mod_length = ModPlug_GetLength(this->mpfile);
-
+ if (this->mod_length < 1)
+ this->mod_length = 1; /* avoids -ve & div-by-0 */
+
return 1;
}
@@ -188,20 +201,20 @@ static int demux_mod_send_chunk(demux_plugin_t *this_gen) {
buf->size = mlen;
buf->pts = this->current_pts;
buf->extra_info->input_time = buf->pts / 90;
-
+
buf->extra_info->input_normpos = buf->extra_info->input_time * 65535 / this->mod_length;
buf->decoder_flags = BUF_FLAG_FRAME_END;
-
+
if (this->seek_flag) {
_x_demux_control_newpts(this->stream, buf->pts, BUF_FLAG_SEEK);
this->seek_flag = 0;
}
this->audio_fifo->put (this->audio_fifo, buf);
-
+
this->current_pts += 90000 * mlen / OUT_BYTES_PER_SECOND;
}
-
+
return this->status;
}
@@ -247,9 +260,9 @@ static int demux_mod_seek (demux_plugin_t *this_gen,
demux_mod_t *this = (demux_mod_t *) this_gen;
int64_t seek_millis;
-
+
if (start_pos) {
- seek_millis = this->mod_length;
+ seek_millis = this->mod_length;
seek_millis *= start_pos;
seek_millis /= 65535;
} else {
@@ -259,14 +272,14 @@ static int demux_mod_seek (demux_plugin_t *this_gen,
_x_demux_flush_engine(this->stream);
ModPlug_Seek(this->mpfile, seek_millis);
this->current_pts = seek_millis * 90;
-
+
this->seek_flag = 1;
return this->status;
}
static void demux_mod_dispose (demux_plugin_t *this_gen) {
demux_mod_t *this = (demux_mod_t *) this_gen;
-
+
ModPlug_Unload(this->mpfile);
free(this->buffer);
free(this->title);
@@ -305,7 +318,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_mod_t));
+ this = calloc(1, sizeof(demux_mod_t));
this->stream = stream;
this->input = input;
@@ -322,7 +335,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->status = DEMUX_FINISHED;
xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "TEST mod decode\n");
-
+
switch (stream->content_detection_method) {
case METHOD_EXPLICIT:
@@ -368,7 +381,19 @@ static const char *get_extensions (demux_class_t *this_gen) {
}
static const char *get_mimetypes (demux_class_t *this_gen) {
- return NULL;
+ return "audio/x-mod: mod: SoundTracker/NoiseTracker/ProTracker Module;"
+ "audio/mod: mod: SoundTracker/NoiseTracker/ProTracker Module;"
+ "audio/it: it: ImpulseTracker Module;"
+ "audio/x-it: it: ImpulseTracker Module;"
+ "audio/x-stm: stm: ScreamTracker 2 Module;"
+ "audio/x-s3m: s3m: ScreamTracker 3 Module;"
+ "audio/s3m: s3m: ScreamTracker 3 Module;"
+ "application/playerpro: 669: 669 Tracker Module;"
+ "application/adrift: amf: ADRIFT Module File;"
+ "audio/med: med: Amiga MED/OctaMED Tracker Module Sound File;"
+ "audio/x-amf: amf: ADRIFT Module File;"
+ "audio/x-xm: xm: FastTracker II Audio;"
+ "audio/xm: xm: FastTracker II Audio;";
}
static void class_dispose (demux_class_t *this_gen) {
@@ -380,7 +405,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_mod_init_plugin (xine_t *xine, void *data) {
demux_mod_class_t *this;
- this = xine_xmalloc (sizeof (demux_mod_class_t));
+ this = calloc(1, sizeof(demux_mod_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_mpc.c b/src/demuxers/demux_mpc.c
index 346f0c2e6..04b25eeb5 100644
--- a/src/demuxers/demux_mpc.c
+++ b/src/demuxers/demux_mpc.c
@@ -24,7 +24,7 @@
* APE tag reading
* Seeking??
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -47,6 +47,7 @@
#include "buffer.h"
#include "bswap.h"
#include "group_audio.h"
+#include "id3.h"
/* Note that the header is actually 25 bytes long, so we'd only read 28
* (because of byte swapping we have to round up to nearest multiple of 4)
@@ -65,7 +66,7 @@ typedef struct {
unsigned int frames;
double samplerate;
unsigned int length;
-
+
unsigned int current_frame;
unsigned int next_frame_bits;
} demux_mpc_t;
@@ -81,7 +82,7 @@ typedef struct {
static int open_mpc_file(demux_mpc_t *this) {
unsigned int first_frame_size;
unsigned int id3v2_size = 0;
-
+
/* Read the file header */
if (_x_demux_read_header(this->input, this->header, HEADER_SIZE) != HEADER_SIZE)
return 0;
@@ -89,46 +90,40 @@ static int open_mpc_file(demux_mpc_t *this) {
/* TODO: non-seeking version */
if (INPUT_IS_SEEKABLE(this->input)) {
/* Check for id3v2 tag */
- if ((this->header[0] == 'I') ||
- (this->header[1] == 'D') ||
- (this->header[2] == '3')) {
-
+ if (id3v2_istag(this->header)) {
+
lprintf("found id3v2 header\n");
-
+
/* Read tag size */
- id3v2_size = (this->header[6] << 21) +
- (this->header[7] << 14) +
- (this->header[8] << 7) +
- this->header[9] + 10;
-
+
+ id3v2_size = _X_BE_32_synchsafe(&this->header[6]) + 10;
+
/* Add footer size if one is present */
if (this->header[5] & 0x10)
id3v2_size += 10;
-
+
lprintf("id3v2 size: %u\n", id3v2_size);
-
+
/* Seek past tag */
if (this->input->seek(this->input, id3v2_size, SEEK_SET) < 0)
return 0;
-
+
/* Read musepack header */
if (this->input->read(this->input, this->header, HEADER_SIZE) != HEADER_SIZE)
return 0;
}
}
-
+
/* Validate signature - We only support SV 7.x at the moment */
- if ((this->header[0] != 'M') ||
- (this->header[1] != 'P') ||
- (this->header[2] != '+') ||
+ if ( memcmp(this->header, "MP+", 3) != 0 ||
((this->header[3]&0x0f) != 0x07))
return 0;
-
+
/* Get frame count */
this->current_frame = 0;
this->frames = _X_LE_32(&this->header[4]);
lprintf("number of frames: %u\n", this->frames);
-
+
/* Get sample rate */
switch ((_X_LE_32(&this->header[8]) >> 16) & 0x3) {
case 0:
@@ -147,7 +142,7 @@ static int open_mpc_file(demux_mpc_t *this) {
break;
}
lprintf("samplerate: %f kHz\n", this->samplerate);
-
+
/* Calculate stream length */
this->length = (int) ((double) this->frames * 1152 / this->samplerate);
lprintf("stream length: %d ms\n", this->length);
@@ -156,14 +151,14 @@ static int open_mpc_file(demux_mpc_t *this) {
first_frame_size = (_X_LE_32(&this->header[24]) >> 4) & 0xFFFFF;
this->next_frame_bits = first_frame_size - 4;
lprintf("first frame size: %u\n", first_frame_size);
-
+
/* Move input to start of data (to nearest multiple of 4) */
this->input->seek(this->input, 28+id3v2_size, SEEK_SET);
-
+
/* Set stream info */
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, _X_ME_32(this->header));
-
+
return 1;
}
@@ -173,30 +168,30 @@ static int demux_mpc_send_chunk(demux_plugin_t *this_gen) {
off_t bytes_read;
buf_element_t *buf = NULL;
-
+
/* Check if we've finished */
if (this->current_frame++ == this->frames) {
lprintf("all frames read\n");
this->status = DEMUX_FINISHED;
- return this->status;
+ return this->status;
}
lprintf("current frame: %u\n", this->current_frame);
-
- /* Get a buffer */
+
+ /* Get a buffer */
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_MPC;
buf->pts = 0;
buf->extra_info->total_time = this->length;
-
+
/* Set normalised position */
- buf->extra_info->input_normpos =
- (int) ((double) this->input->get_current_pos(this->input) * 65535 /
+ buf->extra_info->input_normpos =
+ (int) ((double) this->input->get_current_pos(this->input) * 65535 /
this->input->get_length(this->input));
-
+
/* Set time based on there being 1152 audio frames per frame */
- buf->extra_info->input_time =
+ buf->extra_info->input_time =
(int) ((double) this->current_frame * 1152 / this->samplerate);
-
+
/* Calculate the number of bits that need to be read to finish reading
* the current frame and read the size of the next frame. This number
* has to be rounded up to the nearest 4 bytes on account of the
@@ -209,35 +204,35 @@ static int demux_mpc_send_chunk(demux_plugin_t *this_gen) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("demux_mpc: frame too big for buffer"));
this->status = DEMUX_FINISHED;
- return this->status;
+ return this->status;
}
-
+
/* Read data */
bytes_read = this->input->read(this->input, buf->content, bytes_to_read);
- if(bytes_read == 0) {
+ if(bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
- } else
+ } else
buf->size = bytes_read;
-
+
/* Read the size of the next frame */
if (this->current_frame < this->frames) {
- /* The number of bits of the next frame we've read */
+ /* The number of bits of the next frame we've read */
extra_bits_read = bits_to_read - (this->next_frame_bits+20);
-
+
if(extra_bits_read <= 12)
next_frame_size = (_X_LE_32(&buf->content[bytes_to_read-4]) >> extra_bits_read) & 0xFFFFF;
else
next_frame_size = ((_X_LE_32(&buf->content[bytes_to_read-8]) << (32-extra_bits_read)) |
(_X_LE_32(&buf->content[bytes_to_read-4]) >> extra_bits_read)) & 0xFFFFF;
-
+
lprintf("next frame size: %u\n", next_frame_size);
-
+
/* The number of bits of the next frame still to read */
- this->next_frame_bits = next_frame_size - extra_bits_read;
+ this->next_frame_bits = next_frame_size - extra_bits_read;
}
-
+
/* Each buffer contains at least one frame */
buf->decoder_flags |= BUF_FLAG_FRAME_END;
@@ -260,14 +255,14 @@ static void demux_mpc_send_headers(demux_plugin_t *this_gen) {
/* Send header to decoder */
if (this->audio_fifo) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
-
+
buf->type = BUF_AUDIO_MPC;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END;
buf->decoder_info[0] = this->input->get_length(this->input);
buf->decoder_info[1] = 0;
buf->decoder_info[2] = 0;
buf->decoder_info[3] = 0;
-
+
/* Copy the header */
buf->size = HEADER_SIZE;
memcpy(buf->content, this->header, buf->size);
@@ -324,7 +319,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_mpc_t *this;
- this = xine_xmalloc (sizeof (demux_mpc_t));
+ this = calloc(1, sizeof(demux_mpc_t));
this->stream = stream;
this->input = input;
@@ -356,12 +351,12 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
case METHOD_BY_CONTENT:
case METHOD_EXPLICIT:
-
+
if (!open_mpc_file(this)) {
free (this);
return NULL;
}
-
+
break;
default:
@@ -381,11 +376,12 @@ static const char *get_identifier (demux_class_t *this_gen) {
}
static const char *get_extensions (demux_class_t *this_gen) {
- return "mpc mp+";
+ return "mpc mp+ mpp";
}
static const char *get_mimetypes (demux_class_t *this_gen) {
- return NULL;
+ return "audio/musepack: mpc, mp+, mpp: Musepack audio;"
+ "audio/x-musepack: mpc, mp+, mpp: Musepack audio;";
}
static void class_dispose (demux_class_t *this_gen) {
@@ -397,7 +393,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_mpc_init_plugin (xine_t *xine, void *data) {
demux_mpc_class_t *this;
- this = xine_xmalloc (sizeof (demux_mpc_class_t));
+ this = calloc(1, sizeof(demux_mpc_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_mpeg.c b/src/demuxers/demux_mpeg.c
index 4419f8404..dbaae108d 100644
--- a/src/demuxers/demux_mpeg.c
+++ b/src/demuxers/demux_mpeg.c
@@ -170,7 +170,7 @@ static void find_mdat_atom(input_plugin_t *input, off_t *mdat_offset,
} else
atom_size -= ATOM_PREAMBLE_SIZE;
-
+
input->seek(input, atom_size, SEEK_CUR);
}
}
@@ -279,6 +279,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
if((this->dummy_space[0] & 0xE0) == 0x20) {
buf = this->input->read_block (this->input, this->video_fifo, len-1);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
track = (this->dummy_space[0] & 0x1f);
@@ -298,17 +302,21 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
int spu_id = this->dummy_space[1] & 0x03;
buf = this->input->read_block (this->input, this->video_fifo, len-1);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
buf->type = BUF_SPU_SVCD + spu_id;
buf->pts = pts;
- /* There is a bug in WinSubMux doesn't redo PACK headers in
+ /* There is a bug in WinSubMux doesn't redo PACK headers in
the private stream 1. This might cause the below to mess up.
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
*/
this->video_fifo->put (this->video_fifo, buf);
- lprintf ("SPU SVCD PACK (pts: %"PRId64", 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;
@@ -318,6 +326,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
if((this->dummy_space[0] & 0xfc) == 0x00) {
buf = this->input->read_block (this->input, this->video_fifo, len-1);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
buf->type = BUF_SPU_CVD + (this->dummy_space[0] & 0x03);
buf->pts = pts;
@@ -330,7 +342,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
if((this->dummy_space[0] & 0xf0) == 0x80) {
/* read rest of header - AC3 */
- i = this->input->read (this->input, this->dummy_space+1, 3);
+ this->input->read (this->input, this->dummy_space+1, 3);
/* contents */
for (i = len - 4; i > 0; i -= (this->audio_fifo)
@@ -356,10 +368,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
buf->decoder_flags = BUF_FLAG_PREVIEW;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos =
- (int)( ((int64_t)this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos =
+ (int)( ((int64_t)this->input->get_current_pos (this->input) *
65535) / this->input->get_length (this->input) );
-
+
if (this->rate)
buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
* 1000 / (this->rate * 50));
@@ -376,6 +388,10 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
i = this->input->read (this->input, this->dummy_space+1, 6);
buf = this->input->read_block (this->input, this->video_fifo, len-7);
+ if (! buf) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
buf->type = BUF_AUDIO_LPCM_BE + track;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
@@ -389,8 +405,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
buf->decoder_flags |= BUF_FLAG_PREVIEW;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos =
- (int)( ((int64_t)this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos =
+ (int)( ((int64_t)this->input->get_current_pos (this->input) *
65535) / this->input->get_length (this->input) );
if (this->rate)
buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -431,9 +447,9 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
header_len -= 5 ;
}
- i = this->input->read (this->input, this->dummy_space, header_len);
+ this->input->read (this->input, this->dummy_space, header_len);
- for (i = len; i > 0; i -= (this->audio_fifo)
+ for (i = len; i > 0; i -= (this->audio_fifo)
? this->audio_fifo->buffer_pool_buf_size : this->video_fifo->buffer_pool_buf_size) {
if(this->audio_fifo) {
buf = this->input->read_block (this->input, this->audio_fifo,
@@ -453,8 +469,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
buf->decoder_flags = BUF_FLAG_PREVIEW;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos =
- (int)( ((int64_t)this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos =
+ (int)( ((int64_t)this->input->get_current_pos (this->input) *
65535) / this->input->get_length (this->input) );
if (this->rate)
buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -489,21 +505,21 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
header_len -= 5 ;
}
-
+
if ((flags & 0x40) == 0x40) {
-
+
w = read_bytes(this, 1);
dts = (int64_t)(w & 0x0e) << 29 ;
w = read_bytes(this, 2);
dts |= (w & 0xFFFE) << 14;
w = read_bytes(this, 2);
dts |= (w & 0xFFFE) >> 1;
-
+
header_len -= 5 ;
- }
+ }
/* read rest of header */
- i = this->input->read (this->input, this->dummy_space, header_len);
+ this->input->read (this->input, this->dummy_space, header_len);
/* contents */
@@ -526,8 +542,8 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
buf->decoder_flags = BUF_FLAG_PREVIEW;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos =
- (int)( ((int64_t)this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos =
+ (int)( ((int64_t)this->input->get_current_pos (this->input) *
65535) / this->input->get_length (this->input) );
if (this->rate)
buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -538,7 +554,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
} else {
- for (i = len; i > 0; i -= 10000)
+ for (i = len; i > 0; i -= 10000)
this->input->read (this->input, this->dummy_space, (i > 10000) ? 10000 : i);
}
@@ -606,7 +622,7 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
pts |= (w & 0xFFFE) << 14;
w = read_bytes(this, 2); len -= 2;
-
+
pts |= (w & 0xFFFE) >> 1;
w = read_bytes(this, 1); len -= 1;
@@ -633,11 +649,11 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
lprintf("use scr\n");
pts = scr;
}
-
+
if ((stream_id & 0xe0) == 0xc0) {
int track = stream_id & 0x1f;
- for (i = len; i > 0; i -= (this->audio_fifo)
+ for (i = len; i > 0; i -= (this->audio_fifo)
? this->audio_fifo->buffer_pool_buf_size : this->video_fifo->buffer_pool_buf_size) {
if(this->audio_fifo) {
buf = this->input->read_block (this->input, this->audio_fifo,
@@ -657,8 +673,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
buf->decoder_flags = BUF_FLAG_PREVIEW;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos =
- (int)( ((int64_t)this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos =
+ (int)( ((int64_t)this->input->get_current_pos (this->input) *
65535) / this->input->get_length (this->input) );
if (this->rate)
buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -692,8 +708,8 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
buf->decoder_flags = BUF_FLAG_PREVIEW;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos =
- (int)( ((int64_t)this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos =
+ (int)( ((int64_t)this->input->get_current_pos (this->input) *
65535) / this->input->get_length (this->input) );
if (this->rate)
buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -704,12 +720,12 @@ static void parse_mpeg1_packet (demux_mpeg_t *this, int stream_id, int64_t scr)
} else if (stream_id == 0xbd) {
- for (i = len; i > 0; i -= 10000)
+ for (i = len; i > 0; i -= 10000)
this->input->read (this->input, this->dummy_space, (i > 10000) ? 10000 : i);
} else {
- for (i = len; i > 0; i -= 10000)
+ for (i = len; i > 0; i -= 10000)
this->input->read (this->input, this->dummy_space, (i > 10000) ? 10000 : i);
}
}
@@ -920,7 +936,7 @@ static void demux_mpeg_resync (demux_mpeg_t *this, uint32_t buf) {
if (pos == len) {
len = this->input->read(this->input, dummy_buf, sizeof(dummy_buf));
pos = 0;
- if (len == 0) {
+ if (len <= 0) {
this->status = DEMUX_FINISHED;
break;
}
@@ -962,40 +978,40 @@ static void demux_mpeg_send_headers (demux_plugin_t *this_gen) {
demux_mpeg_t *this = (demux_mpeg_t *) this_gen;
uint32_t w;
int num_buffers = NUM_PREVIEW_BUFFERS;
-
+
this->video_fifo = this->stream->video_fifo;
this->audio_fifo = this->stream->audio_fifo;
this->rate = 0; /* fixme */
this->last_pts[0] = 0;
this->last_pts[1] = 0;
-
+
_x_demux_control_start(this->stream);
/*
* send preview buffers for stream/meta_info
*/
-
+
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
this->preview_mode = 1;
-
+
this->input->seek (this->input, 4, SEEK_SET);
-
+
this->status = DEMUX_OK ;
-
+
do {
w = parse_pack_preview (this, &num_buffers);
-
+
if (w != 0x000001ba)
demux_mpeg_resync (this, w);
-
+
num_buffers --;
-
+
} while ( (this->status == DEMUX_OK) && (num_buffers > 0));
-
+
this->status = DEMUX_OK ;
_x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE, this->rate * 50 * 8);
@@ -1067,7 +1083,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
input_plugin_t *input) {
demux_mpeg_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_t));
+ this = calloc(1, sizeof(demux_mpeg_t));
this->stream = stream;
this->input = input;
@@ -1139,7 +1155,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
/* go through the same MPEG detection song and dance */
if (input->read(input, buf, 4) == 4) {
- if (!buf[0] && !buf[1] && (buf[2] == 0x01)
+ if (!buf[0] && !buf[1] && (buf[2] == 0x01)
&& (buf[3] == 0xba)) /* if so, take it */
break;
}
@@ -1147,7 +1163,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
free (this);
return NULL;
}
-
+
/* reset position for next check */
if (input->seek(input, 0, SEEK_SET) != 0) {
free (this);
@@ -1158,7 +1174,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
fourcc_tag = _X_BE_32(&buf[0]);
if (fourcc_tag == RIFF_TAG) {
uint8_t large_buf[1024];
-
+
if (input->read(input, large_buf, 12) != 12) {
free(this);
return NULL;
@@ -1177,7 +1193,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
* MPEG video marker. No, it's not a very efficient approach, but
* if execution has reached this special case, this is currently
* the best chance for detecting the file automatically. Also,
- * be extra lazy and do not bother skipping over the data
+ * be extra lazy and do not bother skipping over the data
* header. */
for (i = 0; i < RIFF_CHECK_KILOBYTES && !ok; i++) {
if (input->read(input, large_buf, 1024) != 1024)
@@ -1246,7 +1262,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_mpeg_class_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_class_t));
+ this = calloc(1, sizeof(demux_mpeg_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
@@ -1266,7 +1282,7 @@ static const demuxer_info_t demux_info_mpeg = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "mpeg", XINE_VERSION_CODE, &demux_info_mpeg, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c
index 32638129d..aa5294e8b 100644
--- a/src/demuxers/demux_mpeg_block.c
+++ b/src/demuxers/demux_mpeg_block.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2000-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., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -20,7 +20,7 @@
* demultiplexer for mpeg 1/2 program streams
* used with fixed blocksize devices (like dvd/vcd)
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -44,7 +44,7 @@
#define NUM_PREVIEW_BUFFERS 250
#define DISC_TRESHOLD 90000
-#define WRAP_THRESHOLD 120000
+#define WRAP_THRESHOLD 120000
#define PTS_AUDIO 0
#define PTS_VIDEO 1
@@ -56,22 +56,19 @@
typedef struct demux_mpeg_block_s {
demux_plugin_t demux_plugin;
- xine_stream_t *stream;
+ xine_stream_t *stream;
fifo_buffer_t *audio_fifo;
fifo_buffer_t *video_fifo;
input_plugin_t *input;
int status;
-
+
int blocksize;
int rate;
char cur_mrl[256];
- uint8_t *scratch;
- void *scratch_base;
-
int64_t nav_last_end_pts;
int64_t nav_last_start_pts;
int64_t last_pts[2];
@@ -126,30 +123,30 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_
/* OK, i think demux_mpeg_block discontinuity handling demands some
explanation:
-
+
- The preferred discontinuity handling/detection for DVD is based on
NAV packets information. Most of the time it will provide us very
accurate and reliable information.
-
+
- Has been shown that sometimes a DVD discontinuity may happen before
a new NAV packet arrives (seeking?). To avoid sending wrong PTS to
decoders we _used_ to check for SCR discontinuities. Unfortunately
some VCDs have very broken SCR values causing false triggering.
-
+
- To fix the above problem (also note that VCDs don't have NAV
packets) we fallback to the same PTS-based wrap detection as used
in demux_mpeg. The only trick is to not send discontinuity information
if NAV packets have already done the job.
-
+
[Miguel 02-05-2002]
*/
static void check_newpts( demux_mpeg_block_t *this, int64_t pts, int video )
{
int64_t diff;
-
+
diff = pts - this->last_pts[video];
-
+
if( pts && (this->send_newpts || (this->last_pts[video] && abs(diff)>WRAP_THRESHOLD) ) ) {
/* check if pts is outside nav pts range. any stream without nav must enter here. */
@@ -167,10 +164,10 @@ static void check_newpts( demux_mpeg_block_t *this, int64_t pts, int video )
} else {
lprintf("no wrap detected\n" );
}
-
+
this->last_pts[1-video] = 0;
}
-
+
if( pts )
this->last_pts[video] = pts;
}
@@ -223,9 +220,9 @@ static void demux_mpeg_block_parse_pack (demux_mpeg_block_t *this, int preview_m
buf->decoder_flags = BUF_FLAG_PREVIEW;
else
buf->decoder_flags = 0;
-
+
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
while(p < (buf->content + this->blocksize)) {
@@ -438,7 +435,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_block_t *this, uint8_
return 12;
} else { /* mpeg2 */
-
+
int num_stuffing_bytes;
/* system_clock_reference */
@@ -502,7 +499,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_
* the NAV packet for a much more accurate timing */
if (buf->extra_info->input_time) {
int64_t cell_time, frames;
-
+
cell_time = (p[7+0x18] >> 4 ) * 10 * 60 * 60 * 1000;
cell_time += (p[7+0x18] & 0x0f) * 60 * 60 * 1000;
cell_time += (p[7+0x19] >> 4 ) * 10 * 60 * 1000;
@@ -511,7 +508,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_
cell_time += (p[7+0x1a] & 0x0f) * 1000;
frames = ((p[7+0x1b] & 0x30) >> 4) * 10;
frames += ((p[7+0x1b] & 0x0f) ) ;
-
+
if (p[7+0x1b] & 0x80)
cell_time += (frames * 1000)/25;
else
@@ -521,7 +518,7 @@ static int32_t parse_private_stream_2(demux_mpeg_block_t *this, uint8_t *p, buf_
this->last_cell_pos = this->input->get_current_pos (this->input);
this->last_begin_time = buf->extra_info->input_time;
}
-
+
lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n",
start_pts, end_pts);
@@ -572,14 +569,14 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
}
if (this->rate && !buf->extra_info->input_time)
- buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
+ buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
* 1000 / (this->rate * 50));
if (this->mpeg1) {
header_len = 6;
p += 6; /* packet_len -= 6; */
while ((p[0] & 0x80) == 0x80) {
- p++;
+ p++;
header_len++;
this->packet_len--;
/* printf ("stuffing\n");*/
@@ -592,9 +589,9 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
this->packet_len -= 2;
}
- this->pts = 0;
+ this->pts = 0;
this->dts = 0;
-
+
if ((p[0] & 0xf0) == 0x20) {
this->pts = (int64_t)(p[ 0] & 0x0E) << 29 ;
this->pts |= p[ 1] << 22 ;
@@ -611,19 +608,19 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
this->pts |= (p[ 2] & 0xFE) << 14 ;
this->pts |= p[ 3] << 7 ;
this->pts |= (p[ 4] & 0xFE) >> 1 ;
-
+
this->dts = (int64_t)(p[ 5] & 0x0E) << 29 ;
this->dts |= p[ 6] << 22 ;
this->dts |= (p[ 7] & 0xFE) << 14 ;
this->dts |= p[ 8] << 7 ;
this->dts |= (p[ 9] & 0xFE) >> 1 ;
-
+
p += 10;
header_len += 10;
this->packet_len -= 10;
return header_len;
} else {
- p++;
+ p++;
header_len++;
this->packet_len--;
return header_len;
@@ -667,13 +664,13 @@ static int32_t parse_pes_for_pts(demux_mpeg_block_t *this, uint8_t *p, buf_eleme
this->pts = 0;
if (p[7] & 0x40) { /* dts avail */
-
+
this->dts = (int64_t)(p[14] & 0x0E) << 29 ;
this->dts |= p[15] << 22 ;
this->dts |= (p[16] & 0xFE) << 14 ;
this->dts |= p[17] << 7 ;
this->dts |= (p[18] & 0xFE) >> 1 ;
-
+
} else
this->dts = 0;
@@ -702,16 +699,16 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->content = p+1;
buf->size = this->packet_len-1;
-
+
buf->type = BUF_SPU_DVD + spu_id;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE;
buf->pts = this->pts;
-
- this->video_fifo->put (this->video_fifo, buf);
+
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU PACK put on fifo\n");
-
+
return -1;
}
@@ -727,9 +724,9 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
*/
- this->video_fifo->put (this->video_fifo, buf);
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id);
-
+
return -1;
}
@@ -744,29 +741,29 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
/* this is probably wrong:
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
- */
- this->video_fifo->put (this->video_fifo, buf);
+ */
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id);
-
+
return -1;
}
if ((p[0]&0xF0) == 0x80) {
-
+
track = p[0] & 0x0F; /* hack : ac3 track */
- /* Number of frame headers
+ /* Number of frame headers
*
* Describes the number of a52 frame headers that start in this pack (One pack per DVD sector).
*
* Likely values: 1 or 2.
*/
buf->decoder_info[1] = p[1];
- /* First access unit pointer.
+ /* First access unit pointer.
*
* Describes the byte offset within this pack to the beginning of the first A52 frame header.
* The PTS from this pack applies to the beginning of the first A52 frame that starts in this pack.
- * Any bytes before this offset should be considered to belong to the previous A52 frame.
+ * Any bytes before this offset should be considered to belong to the previous A52 frame.
* and therefore be tagged with a PTS value derived from the previous pack.
*
* Likely values: Anything from 1 to the size of an A52 frame.
@@ -867,7 +864,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->free_buffer(buf);
return -1;
}
-
+
} else if ((p[0]&0xf0) == 0xa0) {
int pcm_offset;
@@ -914,7 +911,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
buf->decoder_info[2] = p[5];
-
+
pcm_offset = 7;
buf->content = p+pcm_offset;
@@ -933,7 +930,7 @@ static int32_t parse_private_stream_1(demux_mpeg_block_t *this, uint8_t *p, buf_
buf->free_buffer(buf);
return -1;
}
-
+
}
/* Some new streams have been encountered.
1) DVD+RW disc recorded with a Philips DVD recorder: - new unknown sub-stream id of 0xff
@@ -1006,10 +1003,10 @@ static int demux_mpeg_block_send_chunk (demux_plugin_t *this_gen) {
}
#ifdef ESTIMATE_RATE_FIXED
-/*!
- Estimate bitrate by looking inside the MPEG file for presentation
- time stamps (PTS) and computing how far apart these are
- in bytes and in time.
+/*!
+ Estimate bitrate by looking inside the MPEG file for presentation
+ time stamps (PTS) and computing how far apart these are
+ in bytes and in time.
On failure return 0.
@@ -1040,23 +1037,23 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
int rate=0; /* The return rate value */
int stream_id;
- /* We can't estimate by sampling if we don't thave the ability to
+ /* We can't estimate by sampling if we don't thave the ability to
randomly access the and more importantly reset after accessessing. */
if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE))
return 0;
mpeg_length= this->input->get_length (this->input);
- step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize);
+ step = TRUNC((mpeg_length/MAX_SAMPLES), blocksize);
if (step <= 0) step = blocksize; /* avoid endless loop for tiny files */
pos = step;
/* At this point "pos", and "step" are a multiple of blocksize and
they should continue to be so throughout.
*/
-
+
this->input->seek (this->input, pos, SEEK_SET);
- while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize))
+ while ( (buf = this->input->read_block (this->input, this->video_fifo, blocksize))
&& count < MAX_SAMPLES && reads++ < MAX_READS ) {
p = buf->content; /* len = this->mnBlocksize; */
@@ -1065,9 +1062,9 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
is_mpeg1 = (p[4] & 0x40) == 0;
- if (is_mpeg1)
+ if (is_mpeg1)
p += 12;
- else
+ else
p += 14 + (p[0xD] & 0x07);
}
@@ -1084,7 +1081,7 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
}
stream_id = p[3];
- pts = 0;
+ pts = 0;
if ((stream_id < 0xbc) || ((stream_id & 0xf0) != 0xe0)) {
pos += (off_t) blocksize;
@@ -1114,18 +1111,18 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
pts |= (p[ 2] & 0xFE) << 14 ;
pts |= p[ 3] << 7 ;
pts |= (p[ 4] & 0xFE) >> 1 ;
- }
+ }
}
} else { /* mpeg 2 */
-
+
if (p[7] & 0x80) { /* pts avail */
-
+
pts = (int64_t)(p[ 9] & 0x0E) << 29 ;
pts |= p[10] << 22 ;
pts |= (p[11] & 0xFE) << 14 ;
pts |= p[12] << 7 ;
pts |= (p[13] & 0xFE) >> 1 ;
-
+
} else
pts = 0;
}
@@ -1135,16 +1132,16 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
if ( (pos>last_pos) && (pts>last_pts) ) {
int cur_rate;
-
+
cur_rate = ((pos - last_pos)*90000) / ((pts - last_pts) * 50);
-
+
rate = (count * rate + cur_rate) / (count+1);
count ++;
-
+
/*
- 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);
+ 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);
*/
}
@@ -1168,15 +1165,14 @@ static int demux_mpeg_block_estimate_rate (demux_mpeg_block_t *this) {
lprintf("est_rate=%d\n",rate);
return rate;
-
+
}
#endif /*ESTIMATE_RATE_FIXED*/
static void demux_mpeg_block_dispose (demux_plugin_t *this_gen) {
demux_mpeg_block_t *this = (demux_mpeg_block_t *) this_gen;
-
- free (this->scratch_base);
+
free (this);
}
@@ -1186,23 +1182,24 @@ static int demux_mpeg_block_get_status (demux_plugin_t *this_gen) {
return this->status;
}
-static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this,
+static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this,
input_plugin_t *input)
{
+ uint8_t scratch[4];
input->seek(input, 2048, SEEK_SET);
- if (!input->read(input, this->scratch, 4))
+ if (input->read(input, scratch, 4) != 4)
return 0;
- if (this->scratch[0] || this->scratch[1]
- || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) {
+ if (scratch[0] || scratch[1]
+ || (scratch[2] != 0x01) || (scratch[3] != 0xba)) {
input->seek(input, 2324, SEEK_SET);
- if (!input->read(input, this->scratch, 4))
+ if (input->read(input, scratch, 4) != 4)
return 0;
- if (this->scratch[0] || this->scratch[1]
- || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba))
+ if (scratch[0] || scratch[1]
+ || (scratch[2] != 0x01) || (scratch[3] != 0xba))
return 0;
-
+
return 2324;
} else
return 2048;
@@ -1222,34 +1219,34 @@ static void demux_mpeg_block_send_headers (demux_plugin_t *this_gen) {
if (!this->blocksize)
return;
}
-
- /*
+
+ /*
* send start buffer
*/
-
+
_x_demux_control_start(this->stream);
-
+
#ifdef USE_ILL_ADVISED_ESTIMATE_RATE_INITIALLY
- if (!this->rate)
+ if (!this->rate)
this->rate = demux_mpeg_block_estimate_rate (this);
-#else
+#else
/* Set to Use rate given in by stream initially. */
- this->rate = 0;
+ this->rate = 0;
#endif
-
+
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
-
+
int num_buffers = NUM_PREVIEW_BUFFERS;
-
+
this->input->seek (this->input, 0, SEEK_SET);
-
+
this->status = DEMUX_OK ;
while ( (num_buffers>0) && (this->status == DEMUX_OK) ) {
-
+
demux_mpeg_block_parse_pack(this, 1);
num_buffers --;
}
- }
+ }
/* else FIXME: implement preview generation from PREVIEW data */
this->status = DEMUX_OK;
@@ -1268,19 +1265,19 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen,
this->input->get_length (this->input) );
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
-
+
if (start_pos) {
start_pos /= (off_t) this->blocksize;
start_pos *= (off_t) this->blocksize;
-
+
this->input->seek (this->input, start_pos, SEEK_SET);
} else if (start_time) {
-
+
if( this->input->seek_time ) {
this->input->seek_time (this->input, start_time, SEEK_SET);
} else {
start_time /= 1000;
-
+
if (this->last_cell_time) {
start_pos = start_time - (this->last_cell_time + this->last_begin_time)/1000;
start_pos *= this->rate;
@@ -1293,20 +1290,20 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen,
}
start_pos /= (off_t) this->blocksize;
start_pos *= (off_t) this->blocksize;
-
+
this->input->seek (this->input, start_pos, SEEK_SET);
}
} else
this->input->seek (this->input, 0, SEEK_SET);
}
-
+
/*
* now start demuxing
*/
this->last_cell_time = 0;
this->send_newpts = 1;
if( !playing ) {
-
+
this->buf_flag_seek = 0;
this->nav_last_end_pts = this->nav_last_start_pts = 0;
this->status = DEMUX_OK ;
@@ -1317,7 +1314,7 @@ static int demux_mpeg_block_seek (demux_plugin_t *this_gen,
this->nav_last_end_pts = this->nav_last_start_pts = 0;
_x_demux_flush_engine(this->stream);
}
-
+
return this->status;
}
@@ -1335,7 +1332,7 @@ static void demux_mpeg_block_accept_input (demux_mpeg_block_t *this,
lprintf ("mrl %s is new\n", this->cur_mrl);
- }
+ }
else {
lprintf ("mrl %s is known, bitrate: %d\n",
this->cur_mrl, this->rate * 50 * 8);
@@ -1349,7 +1346,7 @@ static int demux_mpeg_block_get_stream_length (demux_plugin_t *this_gen) {
* find input plugin
*/
- if (this->rate)
+ if (this->rate)
return (int)((int64_t) 1000 * this->input->get_length (this->input) /
(this->rate * 50));
else
@@ -1371,10 +1368,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
input_plugin_t *input = (input_plugin_t *) input_gen;
demux_mpeg_block_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_block_t));
+ this = calloc(1, sizeof(demux_mpeg_block_t));
this->stream = stream;
this->input = input;
-
+
this->demux_plugin.send_headers = demux_mpeg_block_send_headers;
this->demux_plugin.send_chunk = demux_mpeg_block_send_chunk;
this->demux_plugin.seek = demux_mpeg_block_seek;
@@ -1385,25 +1382,25 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->demux_plugin.get_optional_data = demux_mpeg_block_get_optional_data;
this->demux_plugin.demux_class = class_gen;
- this->scratch = xine_xmalloc_aligned (512, 4096, &this->scratch_base);
this->status = DEMUX_FINISHED;
lprintf ("open_plugin:detection_method=%d\n",
stream->content_detection_method);
-
+
switch (stream->content_detection_method) {
-
+
case METHOD_BY_CONTENT: {
/* use demux_mpeg for non-block devices */
if (!(input->get_capabilities(input) & INPUT_CAP_BLOCK)) {
- free (this->scratch_base);
free (this);
return NULL;
}
if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) {
+ uint8_t scratch[5] = {0xff, 0xff, 0xff, 0xff, 0xff}; /* result of input->read() won't matter */
+
this->blocksize = input->get_blocksize(input);
lprintf("open_plugin:blocksize=%d\n",this->blocksize);
@@ -1411,28 +1408,25 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->blocksize = demux_mpeg_detect_blocksize( this, input );
if (!this->blocksize) {
- free (this->scratch_base);
free (this);
return NULL;
}
input->seek(input, 0, SEEK_SET);
- if (input->read(input, this->scratch, this->blocksize)) {
+ if (input->read(input, scratch, 5)) {
lprintf("open_plugin:read worked\n");
- if (this->scratch[0] || this->scratch[1]
- || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) {
+ if (scratch[0] || scratch[1]
+ || (scratch[2] != 0x01) || (scratch[3] != 0xba)) {
lprintf("open_plugin:scratch failed\n");
- free (this->scratch_base);
free (this);
return NULL;
}
/* if it's a file then make sure it's mpeg-2 */
if ( !input->get_blocksize(input)
- && ((this->scratch[4]>>4) != 4) ) {
- free (this->scratch_base);
+ && ((scratch[4]>>4) != 4) ) {
free (this);
return NULL;
}
@@ -1446,7 +1440,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
break;
}
}
- free (this->scratch_base);
free (this);
return NULL;
}
@@ -1467,7 +1460,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
ending = strrchr(mrl, '.');
if (!ending) {
- free (this->scratch_base);
free (this);
return NULL;
}
@@ -1477,7 +1469,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->blocksize = 2048;
demux_mpeg_block_accept_input(this, input);
} else {
- free (this->scratch_base);
free (this);
return NULL;
}
@@ -1495,7 +1486,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->blocksize = demux_mpeg_detect_blocksize( this, input );
if (!this->blocksize) {
- free (this->scratch_base);
free (this);
return NULL;
}
@@ -1505,7 +1495,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
break;
default:
- free (this->scratch_base);
free (this);
return NULL;
}
@@ -1540,7 +1529,7 @@ static void *init_plugin (xine_t *xine, void *data) {
demux_mpeg_block_class_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_block_class_t));
+ this = calloc(1, sizeof(demux_mpeg_block_class_t));
this->config = xine->config;
this->xine = xine;
@@ -1562,7 +1551,7 @@ static const demuxer_info_t demux_info_mpeg_block = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "mpeg_block", XINE_VERSION_CODE, &demux_info_mpeg_block, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c
index 423da5e24..0fe97fb93 100644
--- a/src/demuxers/demux_mpeg_pes.c
+++ b/src/demuxers/demux_mpeg_pes.c
@@ -1,18 +1,18 @@
/*
- * Copyright (C) 2000-2006 the xine project
- *
+ * Copyright (C) 2000-2008 the xine project
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -24,7 +24,7 @@
* (c) 2003 James Courtier-Dutton James@superbug.demon.co.uk
* This code might also decode normal MPG files.
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -48,7 +48,7 @@
#define NUM_PREVIEW_BUFFERS 250
#define DISC_TRESHOLD 90000
-#define WRAP_THRESHOLD 270000
+#define WRAP_THRESHOLD 270000
#define PTS_AUDIO 0
#define PTS_VIDEO 1
@@ -60,14 +60,14 @@
typedef struct demux_mpeg_pes_s {
demux_plugin_t demux_plugin;
- xine_stream_t *stream;
+ xine_stream_t *stream;
fifo_buffer_t *audio_fifo;
fifo_buffer_t *video_fifo;
input_plugin_t *input;
int status;
-
+
int rate;
char cur_mrl[256];
@@ -91,7 +91,7 @@ typedef struct demux_mpeg_pes_s {
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;
@@ -202,7 +202,7 @@ static int detect_pts_discontinuity( demux_mpeg_pes_t *this, int64_t pts, int vi
/* no discontinuity detected */
return 0;
}
-
+
static void check_newpts( demux_mpeg_pes_t *this, int64_t pts, int video )
{
if( pts && (this->send_newpts || detect_pts_discontinuity(this, pts, video) ) ) {
@@ -226,7 +226,7 @@ static void check_newpts( demux_mpeg_pes_t *this, int64_t pts, int video )
/* clear pts on the other track to avoid detecting the same discontinuity again */
this->last_pts[1-video] = 0;
}
-
+
if( pts )
this->last_pts[video] = pts;
}
@@ -257,9 +257,8 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode)
uint8_t *p;
int32_t result;
off_t i;
- int32_t n;
uint8_t buf6[ 6 ];
-
+
this->scr = 0;
this->preview_mode = preview_mode;
@@ -274,16 +273,16 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode)
while ((p[2] != 1) || p[0] || p[1]) {
/* resync code */
- for(n=0;n<5;n++) p[n]=p[n+1];
+ memmove(p, p+1, 5);
i = read_data(this, p+5, (off_t) 1);
if (i != 1) {
this->status = DEMUX_FINISHED;
return;
}
}
-
+
/* FIXME: buf must be allocated from somewhere before calling here. */
-
+
/* these streams should be allocated on the audio_fifo, if available. */
if ((0xC0 <= p[ 3 ] && p[ 3 ] <= 0xDF) /* audio_stream */
|| 0xBD == p[ 3 ]) /* private_sream_1 */
@@ -302,20 +301,19 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode)
return;
}
}
-
+
p = buf->mem;
/* copy local buffer to fifo element. */
- for (n = 0; n < sizeof (buf6); n++)
- p[ n ] = buf6[ n ];
-
+ memcpy(p, buf6, sizeof(buf6));
+
if (preview_mode)
buf->decoder_flags = BUF_FLAG_PREVIEW;
else
buf->decoder_flags = 0;
-
+
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
this->stream_id = p[3];
@@ -414,7 +412,7 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode)
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("xine-lib:demux_mpeg_pes: Unrecognised stream_id 0x%02x. "
"Please report this to xine developers.\n"), this->stream_id);
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: packet_len=%d\n", this->packet_len);
buf->free_buffer (buf);
return;
@@ -437,11 +435,11 @@ static int32_t parse_padding_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elem
{
/* Handle Jumbo frames from VDR. */
int i;
-
+
int size = buf->max_size;
if ((todo - done) < size)
size = todo - done;
-
+
i = read_data(this, buf->mem, (off_t)size);
if (i != size)
break;
@@ -458,98 +456,98 @@ static int32_t parse_padding_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elem
static int32_t parse_program_stream_map(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x.\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_ecm_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_emm_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_dsmcc_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_iec_13522_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_h222_typeA_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_h222_typeB_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_h222_typeC_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_h222_typeD_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_h222_typeE_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_IEC14496_SL_packetized_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_IEC14496_FlexMux_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_program_stream_directory(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
}
static int32_t parse_ancillary_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_element_t *buf) {
/* FIXME: Implement */
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"xine-lib:demux_mpeg_pes: Unhandled stream_id 0x%02x\n", this->stream_id);
buf->free_buffer (buf);
return -1;
@@ -590,7 +588,7 @@ static int32_t parse_program_stream_pack_header(demux_mpeg_pes_t *this, uint8_t
return 12;
} else { /* mpeg2 */
-
+
int num_stuffing_bytes;
/* system_clock_reference */
@@ -664,7 +662,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el
* the NAV packet for a much more accurate timing */
if (buf->extra_info->input_time) {
int64_t cell_time, frames;
-
+
cell_time = (p[7+0x18] >> 4 ) * 10 * 60 * 60 * 1000;
cell_time += (p[7+0x18] & 0x0f) * 60 * 60 * 1000;
cell_time += (p[7+0x19] >> 4 ) * 10 * 60 * 1000;
@@ -673,7 +671,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el
cell_time += (p[7+0x1a] & 0x0f) * 1000;
frames = ((p[7+0x1b] & 0x30) >> 4) * 10;
frames += ((p[7+0x1b] & 0x0f) ) ;
-
+
if (p[7+0x1b] & 0x80)
cell_time += (frames * 1000)/25;
else
@@ -683,7 +681,7 @@ static int32_t parse_private_stream_2(demux_mpeg_pes_t *this, uint8_t *p, buf_el
this->last_cell_pos = this->input->get_current_pos (this->input);
this->last_begin_time = buf->extra_info->input_time;
}
-
+
lprintf ("NAV packet, start pts = %"PRId64", end_pts = %"PRId64"\n",
start_pts, end_pts);
@@ -733,7 +731,7 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element
}
if (this->rate && !buf->extra_info->input_time)
- buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
+ buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
* 1000 / (this->rate * 50));
/* FIXME: This was determined by comparing a single MPEG1 and a single MPEG2 stream */
@@ -748,7 +746,7 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element
p += 6; /* packet_len -= 6; */
while ((p[0] & 0x80) == 0x80) {
- p++;
+ p++;
header_len++;
this->packet_len--;
/* printf ("stuffing\n");*/
@@ -761,9 +759,9 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element
this->packet_len -= 2;
}
- this->pts = 0;
+ this->pts = 0;
this->dts = 0;
-
+
if ((p[0] & 0xf0) == 0x20) {
this->pts = (int64_t) (p[ 0] & 0x0E) << 29 ;
this->pts |= (int64_t) p[ 1] << 22 ;
@@ -780,19 +778,19 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element
this->pts |= (int64_t) (p[ 2] & 0xFE) << 14 ;
this->pts |= (int64_t) p[ 3] << 7 ;
this->pts |= (int64_t) (p[ 4] & 0xFE) >> 1 ;
-
+
this->dts = (int64_t) (p[ 5] & 0x0E) << 29 ;
this->dts |= (int64_t) p[ 6] << 22 ;
this->dts |= (int64_t) (p[ 7] & 0xFE) << 14 ;
this->dts |= (int64_t) p[ 8] << 7 ;
this->dts |= (int64_t) (p[ 9] & 0xFE) >> 1 ;
-
+
p += 10;
header_len += 10;
this->packet_len -= 10;
return header_len;
} else {
- p++;
+ p++;
header_len++;
this->packet_len--;
return header_len;
@@ -836,13 +834,13 @@ static int32_t parse_pes_for_pts(demux_mpeg_pes_t *this, uint8_t *p, buf_element
this->pts = 0;
if (p[7] & 0x40) { /* dts avail */
-
+
this->dts = (int64_t) (p[14] & 0x0E) << 29 ;
this->dts |= (int64_t) p[15] << 22 ;
this->dts |= (int64_t) (p[16] & 0xFE) << 14 ;
this->dts |= (int64_t) p[17] << 7 ;
this->dts |= (int64_t) (p[18] & 0xFE) >> 1 ;
-
+
} else
this->dts = 0;
@@ -871,16 +869,16 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
buf->content = p+1;
buf->size = this->packet_len-1;
-
+
buf->type = BUF_SPU_DVD + spu_id;
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_SPU_DVD_SUBTYPE;
buf->decoder_info[2] = SPU_DVD_SUBTYPE_PACKAGE;
buf->pts = this->pts;
-
- this->video_fifo->put (this->video_fifo, buf);
+
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU PACK put on fifo\n");
-
+
return this->packet_len + result;
}
@@ -896,9 +894,9 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
*/
- this->video_fifo->put (this->video_fifo, buf);
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU SVCD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id);
-
+
return this->packet_len + result;
}
@@ -913,15 +911,15 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
/* this is probably wrong:
if( !preview_mode )
check_newpts( this, this->pts, PTS_VIDEO );
- */
- this->video_fifo->put (this->video_fifo, buf);
+ */
+ this->video_fifo->put (this->video_fifo, buf);
lprintf ("SPU CVD PACK (%"PRId64", %d) put on fifo\n", this->pts, spu_id);
-
+
return this->packet_len + result;
}
if ((p[0]&0xF0) == 0x80) {
-
+
track = p[0] & 0x0F; /* hack : ac3 track */
buf->decoder_info[1] = p[1]; /* Number of frame headers */
buf->decoder_info[2] = p[2] << 8 | p[3]; /* First access unit pointer */
@@ -945,7 +943,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
buf->free_buffer(buf);
}
return this->packet_len + result;
-
+
} else if ((p[0]&0xf0) == 0xa0) {
int pcm_offset;
@@ -985,7 +983,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
switch ((p[5]>>6) & 3) {
case 3: /* illegal, use 16-bits? */
default:
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"illegal lpcm sample format (%d), assume 16-bit samples\n",
(p[5]>>6) & 3 );
case 0: bits_per_sample = 16; break;
@@ -998,7 +996,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
buf->decoder_flags |= BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
buf->decoder_info[2] = p[5];
-
+
pcm_offset = 7;
buf->content = p+pcm_offset;
@@ -1022,7 +1020,7 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
int size;
/*
- * A52/AC3 streams in some DVB-S recordings made with VDR.
+ * A52/AC3 streams in some DVB-S recordings made with VDR.
* It is broadcast by a german tv-station called PRO7.
* PRO7 uses dolby 5.1 (A52 5.1) in some of the movies they broadcast,
* (and they would switch it to stereo-sound(A52 2.0) during commercials.)
@@ -1075,18 +1073,18 @@ static int32_t parse_private_stream_1(demux_mpeg_pes_t *this, uint8_t *p, buf_el
lprintf ("A52 PACK put on fifo\n");
} else {
buf->free_buffer(buf);
- }
+ }
}
return this->packet_len + result;
}
-
+
/* Some new streams have been encountered.
1) DVD+RW disc recorded with a Philips DVD recorder: - new unknown sub-stream id of 0xff
*/
- xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
_("demux_mpeg_pes:Unrecognised private stream 1 0x%02x. Please report this to xine developers.\n"), p[0]);
buf->free_buffer(buf);
return this->packet_len + result;
@@ -1168,14 +1166,14 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen
if (this->mpeg12_h264_detected > 2) {
int nal_type_code = -1;
if (payload_size >= 4 && p[2] == 0x01 && p[1] == 0x00 && p[0] == 0x00)
- nal_type_code = p[3] & 0x1f;
+ 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;
+ b->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0);
this->video_fifo->put (this->video_fifo, b);
}
}
@@ -1189,7 +1187,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen
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;
+ buf->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0);
}
} else {
buf->size = buf->max_size - result;
@@ -1227,7 +1225,7 @@ static int32_t parse_video_stream(demux_mpeg_pes_t *this, uint8_t *p, buf_elemen
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;
+ buf->decoder_flags = BUF_FLAG_FRAME_END | (this->preview_mode ? BUF_FLAG_PREVIEW : 0);
}
this->video_fifo->put (this->video_fifo, buf);
@@ -1277,10 +1275,10 @@ static int demux_mpeg_pes_send_chunk (demux_plugin_t *this_gen) {
}
#ifdef ESTIMATE_RATE_FIXED
-/*!
- Estimate bitrate by looking inside the MPEG file for presentation
- time stamps (PTS) and computing how far apart these are
- in bytes and in time.
+/*!
+ Estimate bitrate by looking inside the MPEG file for presentation
+ time stamps (PTS) and computing how far apart these are
+ in bytes and in time.
On failure return 0.
@@ -1310,23 +1308,23 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) {
int rate=0; /* The return rate value */
int stream_id;
- /* We can't estimate by sampling if we don't thave the ability to
+ /* We can't estimate by sampling if we don't thave the ability to
randomly access the and more importantly reset after accessessing. */
if (!(this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE))
return 0;
mpeg_length= this->input->get_length (this->input);
- step = TRUNC((mpeg_length/MAX_SAMPLES), 2048);
+ step = TRUNC((mpeg_length/MAX_SAMPLES), 2048);
if (step <= 0) step = 2048; /* avoid endless loop for tiny files */
pos = step;
/* At this point "pos", and "step" are a multiple of blocksize and
they should continue to be so throughout.
*/
-
+
this->input->seek (this->input, pos, SEEK_SET);
- while ( (buf = this->input->read_block (this->input, this->video_fifo, 2048))
+ while ( (buf = this->input->read_block (this->input, this->video_fifo, 2048))
&& count < MAX_SAMPLES && reads++ < MAX_READS ) {
p = buf->content; /* len = this->mnBlocksize; */
@@ -1335,9 +1333,9 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) {
is_mpeg1 = (p[4] & 0x40) == 0;
- if (is_mpeg1)
+ if (is_mpeg1)
p += 12;
- else
+ else
p += 14 + (p[0xD] & 0x07);
}
@@ -1347,14 +1345,14 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) {
/* we should now have a PES packet here */
if (p[0] || p[1] || (p[2] != 1)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_mpeg_pes: error %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]);
buf->free_buffer (buf);
return rate;
}
stream_id = p[3];
- pts = 0;
+ pts = 0;
if ((stream_id < 0xbc) || ((stream_id & 0xf0) != 0xe0)) {
pos += (off_t) 2048;
@@ -1383,18 +1381,18 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) {
pts |= (p[ 2] & 0xFE) << 14 ;
pts |= p[ 3] << 7 ;
pts |= (p[ 4] & 0xFE) >> 1 ;
- }
+ }
}
} else { /* mpeg 2 */
-
+
if (p[7] & 0x80) { /* pts avail */
-
+
pts = (int64_t)(p[ 9] & 0x0E) << 29 ;
pts |= p[10] << 22 ;
pts |= (p[11] & 0xFE) << 14 ;
pts |= p[12] << 7 ;
pts |= (p[13] & 0xFE) >> 1 ;
-
+
} else
pts = 0;
}
@@ -1404,16 +1402,16 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) {
if ( (pos>last_pos) && (pts>last_pts) ) {
int cur_rate;
-
+
cur_rate = ((pos - last_pos)*90000) / ((pts - last_pts) * 50);
-
+
rate = (count * rate + cur_rate) / (count+1);
count ++;
-
+
/*
- 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);
+ 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);
*/
}
@@ -1433,14 +1431,14 @@ static int demux_mpeg_pes_estimate_rate (demux_mpeg_pes_t *this) {
lprintf("est_rate=%d\n",rate);
return rate;
-
+
}
#endif /*ESTIMATE_RATE_FIXED*/
static void demux_mpeg_pes_dispose (demux_plugin_t *this_gen) {
demux_mpeg_pes_t *this = (demux_mpeg_pes_t *) this_gen;
-
+
free (this->scratch_base);
free (this);
}
@@ -1458,35 +1456,35 @@ static void demux_mpeg_pes_send_headers (demux_plugin_t *this_gen) {
this->video_fifo = this->stream->video_fifo;
this->audio_fifo = this->stream->audio_fifo;
- /*
+ /*
* send start buffer
*/
-
+
_x_demux_control_start(this->stream);
-
+
#ifdef USE_ILL_ADVISED_ESTIMATE_RATE_INITIALLY
- if (!this->rate)
+ if (!this->rate)
this->rate = demux_mpeg_pes_estimate_rate (this);
-#else
+#else
/* Set to Use rate given in by stream initially. */
- this->rate = 0;
+ this->rate = 0;
#endif
-
+
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
-
+
int num_buffers = NUM_PREVIEW_BUFFERS;
-
+
this->input->seek (this->input, 0, SEEK_SET);
-
+
this->status = DEMUX_OK ;
while ( (num_buffers>0) && (this->status == DEMUX_OK) ) {
-
+
demux_mpeg_pes_parse_pack(this, 1);
num_buffers --;
}
- }
+ }
else if((this->input->get_capabilities(this->input) & INPUT_CAP_PREVIEW) != 0) {
-
+
this->preview_size = this->input->get_optional_data(this->input, &this->preview_data, INPUT_OPTIONAL_DATA_PREVIEW);
this->preview_done = 0;
@@ -1514,14 +1512,14 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen,
this->input->get_length (this->input) );
if((this->input->get_capabilities(this->input) & INPUT_CAP_SEEKABLE) != 0) {
-
+
if (start_pos) {
start_pos /= (off_t) 2048;
start_pos *= (off_t) 2048;
-
+
this->input->seek (this->input, start_pos, SEEK_SET);
} else if (start_time) {
-
+
if (this->last_cell_time) {
start_pos = start_time - (this->last_cell_time + this->last_begin_time)/1000;
start_pos *= this->rate;
@@ -1534,19 +1532,19 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen,
}
start_pos /= (off_t) 2048;
start_pos *= (off_t) 2048;
-
+
this->input->seek (this->input, start_pos, SEEK_SET);
} else
this->input->seek (this->input, 0, SEEK_SET);
}
-
+
/*
* now start demuxing
*/
this->last_cell_time = 0;
this->send_newpts = 1;
if( !playing ) {
-
+
this->buf_flag_seek = 0;
this->nav_last_end_pts = this->nav_last_start_pts = 0;
this->status = DEMUX_OK ;
@@ -1559,7 +1557,7 @@ static int demux_mpeg_pes_seek (demux_plugin_t *this_gen,
this->mpeg12_h264_detected = 0;
_x_demux_flush_engine(this->stream);
}
-
+
return this->status;
}
@@ -1577,7 +1575,7 @@ static void demux_mpeg_pes_accept_input (demux_mpeg_pes_t *this,
lprintf ("mrl %s is new\n", this->cur_mrl);
- }
+ }
else {
lprintf ("mrl %s is known, bitrate: %d\n",
this->cur_mrl, this->rate * 50 * 8);
@@ -1591,7 +1589,7 @@ static int demux_mpeg_pes_get_stream_length (demux_plugin_t *this_gen) {
* find input plugin
*/
- if (this->rate)
+ if (this->rate)
return (int)((int64_t) 1000 * this->input->get_length (this->input) /
(this->rate * 50));
else
@@ -1613,10 +1611,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
input_plugin_t *input = (input_plugin_t *) input_gen;
demux_mpeg_pes_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_pes_t));
+ this = calloc(1, sizeof(demux_mpeg_pes_t));
this->stream = stream;
this->input = input;
-
+
this->demux_plugin.send_headers = demux_mpeg_pes_send_headers;
this->demux_plugin.send_chunk = demux_mpeg_pes_send_chunk;
this->demux_plugin.seek = demux_mpeg_pes_seek;
@@ -1639,9 +1637,9 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
lprintf ("open_plugin:detection_method=%d\n",
stream->content_detection_method);
-
+
switch (stream->content_detection_method) {
-
+
case METHOD_BY_CONTENT: {
/* use demux_mpeg_block for block devices */
@@ -1688,7 +1686,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
if (((input->get_capabilities(input) & INPUT_CAP_SEEKABLE) != 0) ) {
input->seek(input, 0, SEEK_SET);
- if (input->read(input, (char *)this->scratch, 6)) {
+ if (input->read(input, (char *)this->scratch, 6) == 6) {
lprintf("open_plugin:read worked\n");
if (this->scratch[0] || this->scratch[1]
@@ -1786,7 +1784,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_mpeg_pes_class_t *this;
- this = xine_xmalloc (sizeof (demux_mpeg_pes_class_t));
+ this = calloc(1, sizeof(demux_mpeg_pes_class_t));
this->config = xine->config;
this->xine = xine;
@@ -1808,7 +1806,7 @@ static const demuxer_info_t demux_info_mpeg_pes = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "mpeg_pes", XINE_VERSION_CODE, &demux_info_mpeg_pes, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c
index 17916f837..6205f9a08 100644
--- a/src/demuxers/demux_mpgaudio.c
+++ b/src/demuxers/demux_mpgaudio.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2000-2007 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -33,7 +33,7 @@
#include <string.h>
#include <stdlib.h>
-#define LOG_MODULE "demux_mpeg_audio"
+#define LOG_MODULE "demux_mpgaudio"
#define LOG_VERBOSE
/*
#define LOG
@@ -51,8 +51,8 @@
* the second mp3 frame is sent to the decoder
*/
#define NUM_PREVIEW_BUFFERS 2
+#define NUM_VALID_FRAMES 3
-#define WRAP_THRESHOLD 120000
#define FOURCC_TAG BE_FOURCC
#define RIFF_CHECK_BYTES 1024
@@ -79,16 +79,16 @@
/* mp3 frame struct */
typedef struct {
/* header */
- double duration;
- uint32_t size; /* in bytes */
+ double duration; /* in milliseconds */
+ uint32_t size; /* in bytes; including padding */
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;
+ uint8_t padding:3; /* in bytes */
+ uint8_t is_free_bitrate:1;
} mpg_audio_frame_t;
/* Xing Vbr Header struct */
@@ -98,7 +98,7 @@ typedef struct {
uint32_t stream_size;
uint8_t toc[XING_TOC_LENGTH];
uint32_t vbr_scale;
-
+
/* Lame extension */
uint16_t start_delay;
uint16_t end_delay;
@@ -131,7 +131,13 @@ typedef struct {
int br; /* bitrate in bits/second */
uint32_t blocksize;
+ /* current mp3 frame */
mpg_audio_frame_t cur_frame;
+
+ /* next mp3 frame, used when the frame size cannot be computed from the
+ * current frame header */
+ mpg_audio_frame_t next_frame;
+
double cur_time; /* in milliseconds */
off_t mpg_frame_start; /* offset */
@@ -141,7 +147,15 @@ typedef struct {
int check_vbr_header;
xing_header_t *xing_header;
vbri_header_t *vbri_header;
-
+
+ int found_next_frame:1;
+ int free_bitrate_count;
+ off_t free_bitrate_size; /* use this size if 3 free bitrate frames are encountered */
+ uint8_t next_header[4];
+ int mpg_version;
+ int mpg_layer;
+ int valid_frames;
+
} demux_mpgaudio_t ;
/* demuxer class struct */
@@ -212,14 +226,14 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con
const uint32_t head = _X_BE_32(buf);
const uint16_t frame_sync = head >> 21;
- lprintf("header: %08X\n", head);
if (frame_sync != 0x7ff) {
- lprintf("invalid frame sync\n");
+ lprintf("invalid frame sync %08X\n", head);
return 0;
}
+ lprintf("header: %08X\n", head);
frame_header.mpeg25_bit = (head >> 20) & 0x1;
- frame->lsf_bit = (head >> 19) & 0x1;
+ frame->lsf_bit = (head >> 19) & 0x1;
if (!frame_header.mpeg25_bit) {
if (frame->lsf_bit) {
lprintf("reserved mpeg25 lsf combination\n");
@@ -240,14 +254,14 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con
}
frame_header.bitrate_idx = (head >> 12) & 0xf;
- if ((frame_header.bitrate_idx == 0) || (frame_header.bitrate_idx == 15)) {
- lprintf("invalid bitrate index\n");
+ if (frame_header.bitrate_idx == 15) {
+ lprintf("invalid bitrate index: %d\n", frame_header.bitrate_idx);
return 0;
}
frame_header.freq_idx = (head >> 10) & 0x3;
if (frame_header.freq_idx == 3) {
- lprintf("invalid frequence index\n");
+ lprintf("invalid frequence index: %d\n", frame_header.freq_idx);
return 0;
}
@@ -275,24 +289,32 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con
return 0;
}
#endif
-
+
{
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 = 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)samples / (double)frame->freq;
+ frame->padding = ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 );
+ frame->channel_mode = frame_header.channel_mode;
+
+ if (frame->bitrate > 0) {
+ 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->padding;
+ } else {
+ /* Free bitrate frame, the size of the frame cannot be computed from the header. */
+ frame->is_free_bitrate = 1;
+ frame->size = 0;
+ }
}
- 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("mpeg %d, layer %d, channel_mode: %d\n", frame->version_idx + 1,
+ frame->layer, frame->channel_mode);
+ lprintf("bitrate: %d bps, output freq: %d Hz\n", frame->bitrate, frame->freq);
lprintf("length: %d bytes, %f ms\n", frame->size, frame->duration);
- lprintf("padding: %d bytes\n", ( frame_header.padding_bit ? ( frame->layer == 1 ? 4 : 1 ) : 0 ));
+ lprintf("padding: %d bytes\n", frame->padding);
return 1;
}
@@ -300,8 +322,8 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con
* Parse a Xing header
* return the Xing header or NULL on error
*/
-static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame,
- uint8_t *buf, int bufsize) {
+static xing_header_t *XINE_MALLOC parse_xing_header(mpg_audio_frame_t *frame,
+ uint8_t *buf, int bufsize) {
uint8_t *ptr = buf;
xing_header_t *xing = NULL;
@@ -317,21 +339,21 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame,
else
ptr += (9 + 4);
}
-
+
if (ptr >= (buf + bufsize - 4)) goto exit_error;
lprintf("checking %08X\n", *ptr);
-
+
if (_X_BE_32(ptr) == XING_TAG) {
int has_frames_flag = 0;
int has_bytes_flag = 0;
-
- xing = xine_xmalloc (sizeof (xing_header_t));
+
+ xing = calloc(1, sizeof(xing_header_t));
if (!xing)
goto exit_error;
-
- lprintf("Xing header found\n");
+
+ lprintf("found Xing header\n");
ptr += 4;
-
+
if (ptr >= (buf + bufsize - 4)) goto exit_error;
xing->flags = _X_BE_32(ptr); ptr += 4;
@@ -347,7 +369,7 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame,
lprintf("stream size: %d\n", xing->stream_size);
has_bytes_flag = 1;
}
-
+
/* check if it's a useful Xing header */
if (!has_frames_flag || !has_bytes_flag) {
lprintf("Stupid Xing tag, cannot do anything with it !\n");
@@ -405,7 +427,7 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame,
lprintf("Xing header not found\n");
}
return xing;
-
+
exit_error:
lprintf("Xing header parse error\n");
free(xing);
@@ -416,25 +438,25 @@ exit_error:
* Parse a Vbri header
* return the Vbri header or NULL on error
*/
-static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame,
- uint8_t *buf, int bufsize) {
+static vbri_header_t *XINE_MALLOC parse_vbri_header(mpg_audio_frame_t *frame,
+ uint8_t *buf, int bufsize) {
int i;
uint8_t *ptr = buf;
vbri_header_t *vbri;
- vbri = xine_xmalloc (sizeof (vbri_header_t));
+ vbri = calloc(1, sizeof(vbri_header_t));
if (!vbri)
return NULL;
ptr += (32 + 4);
-
+
if ((ptr + 4) >= (buf + bufsize)) return 0;
lprintf("Checking %08X\n", *ptr);
if (_X_BE_32(ptr) == VBRI_TAG) {
- lprintf("Vbri header found\n");
+ lprintf("found Vbri header\n");
ptr += 4;
-
+
if ((ptr + 22) >= (buf + bufsize)) return 0;
vbri->version = _X_BE_16(ptr); ptr += 2;
vbri->delai = _X_BE_16(ptr); ptr += 2;
@@ -456,7 +478,7 @@ static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame,
lprintf("entry_frames: %d\n", vbri->entry_frames);
if ((ptr + (vbri->toc_entries + 1) * vbri->entry_size) >= (buf + bufsize)) return 0;
- vbri->toc = xine_xmalloc (sizeof(int) * (vbri->toc_entries + 1));
+ vbri->toc = calloc (vbri->toc_entries + 1, sizeof (int));
if (!vbri->toc) {
free (vbri);
return NULL;
@@ -496,6 +518,7 @@ static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame,
}
}
+
/*
* Parse a mp3 frame paylod
* return 1 on success, 0 on error
@@ -506,43 +529,97 @@ static int parse_frame_payload(demux_mpgaudio_t *this,
buf_element_t *buf;
off_t frame_pos, len;
uint64_t pts = 0;
+ int payload_size = 0;
frame_pos = this->input->get_current_pos(this->input) - 4;
- lprintf("frame_pos = %"PRId64"\n", frame_pos);
+ lprintf("frame_pos = %"PRId64", header: %08X\n", frame_pos, _X_BE_32(frame_header));
buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
if (this->cur_frame.size > buf->max_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
- "demux_mpgaudio: frame size is greater than fifo buffer size\n");
+ LOG_MODULE ": frame size is greater than fifo buffer size\n");
buf->free_buffer(buf);
return 0;
}
-
- /* the decoder needs the frame header */
- memcpy(buf->mem, frame_header, 4);
- len = this->input->read(this->input, buf->mem + 4, this->cur_frame.size - 4);
- if (len != (this->cur_frame.size - 4)) {
- buf->free_buffer(buf);
- return 0;
+ memcpy(buf->content, frame_header, 4);
+
+ /* compute the payload size */
+ if (this->cur_frame.size > 0) {
+ payload_size = this->cur_frame.size - 4;
+ this->free_bitrate_count = 0;
+ } else if (this->free_bitrate_count >= NUM_VALID_FRAMES) {
+ payload_size = this->free_bitrate_size + this->cur_frame.padding - 4;
+ this->cur_frame.size = payload_size + 4;
+ } else {
+ this->free_bitrate_count++;
+ payload_size = 0;
+ }
+
+ /* Read the payload data. */
+ if (payload_size > 0) {
+ off_t len;
+
+ /* If we know the payload size, it's easy */
+ this->found_next_frame = 0;
+ len = this->input->read(this->input, buf->content + 4, payload_size);
+ if (len != payload_size) {
+ buf->free_buffer(buf);
+ return 0;
+ }
+ } else {
+ /* Search for the beginning of the next frame and deduce the size of the
+ * current frame from the position of the next one. */
+ int payload_size = 0;
+ int max_size = buf->max_size - 4;
+
+ while (payload_size < max_size) {
+ len = this->input->read(this->input, &buf->content[4 + payload_size], 1);
+ if (len != 1) {
+ lprintf("EOF\n");
+ buf->free_buffer(buf);
+ return 0;
+ }
+ payload_size += len;
+
+ if (parse_frame_header(&this->next_frame, &buf->content[payload_size])) {
+ lprintf("found next frame header\n");
+
+ if (this->free_bitrate_size == 0) {
+ this->free_bitrate_size = payload_size - this->cur_frame.padding;
+ }
+
+ /* don't read the frame header twice */
+ this->found_next_frame = 1;
+ memcpy(&this->next_header[0], &buf->content[payload_size], 4);
+ payload_size -= 4;
+ break;
+ }
+ }
+ this->cur_frame.size = payload_size + 4;
+ this->cur_frame.bitrate = 8000 * this->cur_frame.size / this->cur_frame.duration;
+ lprintf("free bitrate: bitrate: %d, frame size: %d\n", this->br, this->cur_frame.size);
}
if (this->check_vbr_header) {
this->check_vbr_header = 0;
this->mpg_frame_start = frame_pos;
- this->xing_header = parse_xing_header(&this->cur_frame, buf->mem, this->cur_frame.size);
+ this->xing_header = parse_xing_header(&this->cur_frame, buf->content, this->cur_frame.size);
if (this->xing_header) {
buf->free_buffer(buf);
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": found Xing header at offset %"PRId64"\n", frame_pos);
return 1;
}
- this->vbri_header = parse_vbri_header(&this->cur_frame, buf->mem, this->cur_frame.size);
+ this->vbri_header = parse_vbri_header(&this->cur_frame, buf->content, this->cur_frame.size);
if (this->vbri_header) {
buf->free_buffer(buf);
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": found Vbri header at offset %"PRId64"\n", frame_pos);
return 1;
}
}
-
pts = (int64_t)(this->cur_time * 90.0f);
@@ -551,8 +628,7 @@ static int parse_frame_payload(demux_mpgaudio_t *this,
buf->extra_info->input_time = this->cur_time;
buf->pts = pts;
- buf->size = len + 4;
- buf->content = buf->mem;
+ buf->size = this->cur_frame.size;
buf->type = BUF_AUDIO_MPEG;
buf->decoder_info[0] = 1;
buf->decoder_flags = decoder_flags | BUF_FLAG_FRAME_END;
@@ -572,8 +648,8 @@ static int parse_frame_payload(demux_mpgaudio_t *this,
}
}
+ lprintf("send buffer: size=%d, pts=%"PRId64"\n", buf->size, pts);
this->audio_fifo->put(this->audio_fifo, buf);
- lprintf("send buffer: pts=%"PRId64"\n", pts);
this->cur_time += this->cur_frame.duration;
return 1;
}
@@ -583,11 +659,12 @@ static int parse_frame_payload(demux_mpgaudio_t *this,
* 32-bit MP3 frame header.
* return 1 if found, 0 if not found
*/
-static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen)
+static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen, int *version, int *layer)
{
int offset;
mpg_audio_frame_t frame;
+ *version = *layer = 0;
if (buf == NULL)
return 0;
@@ -596,20 +673,21 @@ static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen)
if (parse_frame_header(&frame, buf + offset)) {
size_t size = frame.size;
- /* Since one frame is available, is there another frame
- * just to be sure this is more likely to be a real MP3
- * buffer? */
- offset += size;
-
- if (offset + 4 >= buflen) {
- return 0;
- }
+ if (size > 0) {
+ /* Since one frame is available, is there another frame
+ * just to be sure this is more likely to be a real MP3
+ * buffer? */
+ if (offset + size + 4 >= buflen) {
+ return 0;
+ }
- if (parse_frame_header(&frame, buf + offset)) {
- lprintf("mpeg audio frame detected\n");
- return 1;
+ if (parse_frame_header(&frame, buf + offset + size)) {
+ *version = frame.version_idx + 1;
+ *layer = frame.layer;
+ lprintf("frame detected, mpeg %d layer %d\n", *version, *layer);
+ return 1;
+ }
}
- break;
}
}
return 0;
@@ -621,7 +699,7 @@ static int sniff_buffer_looks_like_mp3 (uint8_t *buf, int buflen)
static int read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int bytes) {
off_t len;
int i;
-
+
for (i = 0; i < (4 - bytes); i++) {
header_buf[i] = header_buf[i + bytes];
}
@@ -637,40 +715,51 @@ static int read_frame_header(demux_mpgaudio_t *this, uint8_t *header_buf, int by
* Parse next mp3 frame
*/
static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags, int send_header) {
- uint8_t header_buf[4];
- int bytes = 4;
-
- for (;;) {
-
- if (read_frame_header(this, header_buf, bytes)) {
-
- if (parse_frame_header(&this->cur_frame, header_buf)) {
-
- /* send header buffer */
- if ( send_header ) {
- buf_element_t *buf;
-
- buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
-
- buf->type = BUF_AUDIO_MPEG;
- buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
-
- buf->decoder_info[0] = 0;
- buf->decoder_info[1] = this->cur_frame.freq;
- buf->decoder_info[2] = 0; /* bits_per_sample */
-
- /* Only for channel_mode == 3 (mono) there is one channel, for any other case, there are 2 */
- buf->decoder_info[3] = ( this->cur_frame.channel_mode == 3 ) ? 1 : 2;
-
- buf->size = 0; /* No extra header data */
-
- this->audio_fifo->put(this->audio_fifo, buf);
+ uint8_t buffer[4];
+ uint8_t *header = buffer;
+
+ if (this->found_next_frame) {
+ lprintf("skip header reading\n");
+ header = this->next_header;
+ memcpy(&this->cur_frame, &this->next_frame, sizeof(mpg_audio_frame_t));
+ } else {
+ int bytes = 4;
+ int loose_sync = 0;
+
+ for (;;) {
+ if (!read_frame_header(this, header, bytes))
+ return 0;
+ if (parse_frame_header(&this->cur_frame, header)) {
+ lprintf("frame found\n");
+
+ /* additionnal checks */
+ if ((this->mpg_version == (this->cur_frame.version_idx + 1)) &&
+ (this->mpg_layer == this->cur_frame.layer)) {
+ this->valid_frames++;
+ break;
+ } else {
+ if (this->valid_frames >= NUM_VALID_FRAMES) {
+ lprintf("invalid frame. expected mpeg %d, layer %d\n", this->mpg_version, this->mpg_layer);
+ } else {
+ this->mpg_version = this->cur_frame.version_idx + 1;
+ this->mpg_layer = this->cur_frame.layer;
+ this->valid_frames = 0;
+ break;
+ }
}
-
- return parse_frame_payload(this, header_buf, decoder_flags);
-
- } else if ( id3v2_istag(header_buf) ) {
- if (!id3v2_parse_tag(this->input, this->stream, header_buf)) {
+ }
+
+ if (!loose_sync) {
+ off_t frame_pos = this->input->get_current_pos(this->input) - 4;
+ loose_sync = 1;
+ xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
+ LOG_MODULE ": loose mp3 sync at offset %"PRId64"\n", frame_pos);
+ }
+ /* the stream is broken, don't keep info about previous frames */
+ this->free_bitrate_size = 0;
+
+ if ( id3v2_istag(header) ) {
+ if (!id3v2_parse_tag(this->input, this->stream, header)) {
xprintf(this->stream->xine, XINE_VERBOSITY_LOG,
LOG_MODULE ": ID3V2 tag parsing error\n");
bytes = 1; /* resync */
@@ -681,12 +770,31 @@ static int demux_mpgaudio_next (demux_mpgaudio_t *this, int decoder_flags, int s
/* skip */
bytes = 1;
}
-
- } else {
- lprintf("read error\n");
- return 0;
}
}
+
+ /* send header buffer */
+ if ( send_header ) {
+ buf_element_t *buf;
+
+ buf = this->audio_fifo->buffer_pool_alloc(this->audio_fifo);
+
+ buf->type = BUF_AUDIO_MPEG;
+ buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
+
+ buf->decoder_info[0] = 0;
+ buf->decoder_info[1] = this->cur_frame.freq;
+ buf->decoder_info[2] = 0; /* bits_per_sample */
+
+ /* Only for channel_mode == 3 (mono) there is one channel, for any other case, there are 2 */
+ buf->decoder_info[3] = ( this->cur_frame.channel_mode == 3 ) ? 1 : 2;
+
+ buf->size = 0; /* No extra header data */
+
+ this->audio_fifo->put(this->audio_fifo, buf);
+ }
+
+ return parse_frame_payload(this, header, decoder_flags);
}
static int demux_mpgaudio_send_chunk (demux_plugin_t *this_gen) {
@@ -742,12 +850,13 @@ static int demux_mpgaudio_read_head(input_plugin_t *input, uint8_t *buf) {
* mp3 stream detection
* return 1 if detected, 0 otherwise
*/
-static int detect_mpgaudio_file(input_plugin_t *input) {
- mpg_audio_frame_t frame;
+static int detect_mpgaudio_file(input_plugin_t *input,
+ int *version, int *layer) {
uint8_t buf[MAX_PREVIEW_SIZE];
int preview_len;
uint32_t head;
+ *version = *layer = 0;
preview_len = demux_mpgaudio_read_head(input, buf);
if (preview_len < 4)
return 0;
@@ -774,15 +883,15 @@ static int detect_mpgaudio_file(input_plugin_t *input) {
lprintf("cannot read mp3 frame header\n");
return 0;
}
- if (!parse_frame_header(&frame, &buf[10 + tag_size])) {
- lprintf ("invalid mp3 frame header\n");
+ if (!sniff_buffer_looks_like_mp3(&buf[10 + tag_size], preview_len - 10 - tag_size, version, layer)) {
+ lprintf ("sniff_buffer_looks_like_mp3 failed\n");
return 0;
} else {
lprintf ("a valid mp3 frame follows the id3v2 tag\n");
}
} else if (head == MPEG_MARKER) {
return 0;
- } else if (!sniff_buffer_looks_like_mp3(buf, preview_len)) {
+ } else if (!sniff_buffer_looks_like_mp3(buf, preview_len, version, layer)) {
lprintf ("sniff_buffer_looks_like_mp3 failed\n");
return 0;
}
@@ -821,11 +930,12 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) {
*/
this->check_vbr_header = 1;
for (i = 0; i < NUM_PREVIEW_BUFFERS; i++) {
+ lprintf("preview buffer number %d / %d\n", i + 1, NUM_PREVIEW_BUFFERS);
if (!demux_mpgaudio_next (this, BUF_FLAG_PREVIEW, i == 0)) {
break;
}
}
-
+
if (this->xing_header) {
xing_header_t *xing = this->xing_header;
@@ -836,7 +946,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) {
if (this->stream_length) {
this->br = ((uint64_t)xing->stream_size * 8 * 1000) / this->stream_length;
}
-
+
} else if (this->vbri_header) {
vbri_header_t *vbri = this->vbri_header;
@@ -848,7 +958,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) {
this->br = ((uint64_t)vbri->stream_size * 8 * 1000) / this->stream_length;
}
}
-
+
/* Set to default if Vbr header is incomplete or not present */
if (!this->br) {
/* assume CBR */
@@ -879,7 +989,7 @@ static void demux_mpgaudio_send_headers (demux_plugin_t *this_gen) {
{
char scratch_buf[256];
char *mpeg_ver[3] = {"1", "2", "2.5"};
-
+
snprintf(scratch_buf, 256, "MPEG %s Layer %1d%s",
mpeg_ver[this->cur_frame.version_idx], this->cur_frame.layer,
(this->xing_header)? " VBR" : " CBR" );
@@ -1007,7 +1117,8 @@ static int demux_mpgaudio_seek (demux_plugin_t *this_gen,
/* assume seeking is always perfect... */
this->cur_time = start_time;
this->input->seek (this->input, seek_pos, SEEK_SET);
-
+ this->found_next_frame = 0;
+
if (playing) {
_x_demux_flush_engine(this->stream);
}
@@ -1039,21 +1150,23 @@ static uint32_t demux_mpgaudio_get_capabilities(demux_plugin_t *this_gen) {
}
static int demux_mpgaudio_get_optional_data(demux_plugin_t *this_gen,
- void *data, int data_type) {
+ 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_mpgaudio_t *this;
+ int version = 0;
+ int layer = 0;
lprintf("trying to open %s...\n", input->get_mrl(input));
switch (stream->content_detection_method) {
case METHOD_BY_CONTENT: {
- if (!detect_mpgaudio_file(input))
+ if (!detect_mpgaudio_file(input, &version, &layer))
return NULL;
}
break;
@@ -1061,23 +1174,23 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
case METHOD_BY_EXTENSION: {
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);
-
+
if (!_x_demux_check_extension (mrl, extensions))
return NULL;
-
+
}
break;
case METHOD_EXPLICIT:
break;
-
+
default:
return NULL;
}
-
- this = xine_xmalloc (sizeof (demux_mpgaudio_t));
+
+ this = calloc(1, sizeof(demux_mpgaudio_t));
this->demux_plugin.send_headers = demux_mpgaudio_send_headers;
this->demux_plugin.send_chunk = demux_mpgaudio_send_chunk;
@@ -1088,12 +1201,17 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
this->demux_plugin.get_capabilities = demux_mpgaudio_get_capabilities;
this->demux_plugin.get_optional_data = demux_mpgaudio_get_optional_data;
this->demux_plugin.demux_class = class_gen;
-
- this->input = input;
- this->audio_fifo = stream->audio_fifo;
- this->status = DEMUX_FINISHED;
- this->stream = stream;
-
+
+ this->input = input;
+ this->audio_fifo = stream->audio_fifo;
+ this->status = DEMUX_FINISHED;
+ this->stream = stream;
+
+ this->mpg_version = version;
+ this->mpg_layer = layer;
+ if (version || layer) {
+ this->valid_frames = NUM_VALID_FRAMES;
+ }
return &this->demux_plugin;
}
@@ -1111,7 +1229,7 @@ static const char *get_identifier (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) )
return "mp3 mp2 mpa mpega";
else
@@ -1144,10 +1262,10 @@ static void class_dispose (demux_class_t *this_gen) {
}
void *demux_mpgaudio_init_class (xine_t *xine, void *data) {
-
+
demux_mpgaudio_class_t *this;
-
- this = xine_xmalloc (sizeof (demux_mpgaudio_class_t));
+
+ this = calloc(1, sizeof(demux_mpgaudio_class_t));
this->xine = xine;
this->demux_class.open_plugin = open_plugin;
diff --git a/src/demuxers/demux_nsf.c b/src/demuxers/demux_nsf.c
index 81f42044f..40aeae9da 100644
--- a/src/demuxers/demux_nsf.c
+++ b/src/demuxers/demux_nsf.c
@@ -22,7 +22,7 @@
* NSF File "Demuxer" by Mike Melanson (melanson@pcisys.net)
* This is really just a loader for NES Music File Format (extension NSF)
* which loads an entire NSF file and passes it over to the NSF audio
- * decoder.
+ * decoder.
*
* After the file is sent over, the demuxer controls the playback by
* sending empty buffers with incrementing pts values.
@@ -97,18 +97,14 @@ static int open_nsf_file(demux_nsf_t *this) {
return 0;
/* check for the signature */
- if ((header[0] != 'N') ||
- (header[1] != 'E') ||
- (header[2] != 'S') ||
- (header[3] != 'M') ||
- (header[4] != 0x1A))
+ if (memcmp(header, "NESM\x1A", 5) != 0)
return 0;
this->total_songs = header[6];
this->current_song = header[7];
- this->title = strdup(&header[0x0E]);
- this->artist = strdup(&header[0x2E]);
- this->copyright = strdup(&header[0x4E]);
+ this->title = strndup((char*)&header[0x0E], 0x20);
+ this->artist = strndup((char*)&header[0x2E], 0x20);
+ this->copyright = strndup((char*)&header[0x4E], 0x20);
this->filesize = this->input->get_length(this->input);
@@ -128,7 +124,7 @@ static int demux_nsf_send_chunk(demux_plugin_t *this_gen) {
buf->type = BUF_AUDIO_NSF;
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
/* the file has been completely loaded, free the buffer and start
* sending control buffers */
buf->free_buffer(buf);
@@ -170,7 +166,7 @@ static int demux_nsf_send_chunk(demux_plugin_t *this_gen) {
buf->decoder_info[1] = 0;
buf->type = BUF_AUDIO_NSF;
- if(this->total_songs)
+ if(this->total_songs)
buf->extra_info->input_normpos = (this->current_song - 1) * 65535 / this->total_songs;
buf->extra_info->input_time = this->current_pts / 90;
buf->pts = this->current_pts;
@@ -303,7 +299,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_nsf_t));
+ this = calloc(1, sizeof(demux_nsf_t));
this->stream = stream;
this->input = input;
@@ -377,7 +373,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_nsf_init_plugin (xine_t *xine, void *data) {
demux_nsf_class_t *this;
- this = xine_xmalloc (sizeof (demux_nsf_class_t));
+ this = calloc(1, sizeof(demux_nsf_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_nsv.c b/src/demuxers/demux_nsv.c
index 44bb18c79..8017d3d3f 100644
--- a/src/demuxers/demux_nsv.c
+++ b/src/demuxers/demux_nsv.c
@@ -50,7 +50,6 @@
#define FOURCC_TAG BE_FOURCC
#define NSVf_TAG FOURCC_TAG('N', 'S', 'V', 'f')
#define NSVs_TAG FOURCC_TAG('N', 'S', 'V', 's')
-#define NONE_TAG FOURCC_TAG('N', 'O', 'N', 'E')
#define BEEF 0xEFBE
@@ -107,17 +106,17 @@ static void nsv_parse_framerate(demux_nsv_t *this, uint8_t framerate)
/* 29.97 fps */
this->frame_pts_inc = 3003;
break;
-
+
case 3:
/* 23.976 fps */
this->frame_pts_inc = 3753;
break;
-
+
case 5:
/* 14.98 fps */
this->frame_pts_inc = 6006;
break;
-
+
default:
lprintf("unknown framerate: 0x%02X\n", this->fps);
this->frame_pts_inc = 90000;
@@ -125,7 +124,7 @@ static void nsv_parse_framerate(demux_nsv_t *this, uint8_t framerate)
}
} else
this->frame_pts_inc = 90000 / this->fps;
-
+
lprintf("frame_pts_inc=%d\n", this->frame_pts_inc);
}
@@ -139,7 +138,7 @@ static off_t nsv_read(demux_nsv_t *this, uint8_t *buffer, off_t len) {
int ultravox_rest;
int buffer_pos = 0;
-
+
/* ultravox stuff */
while (len) {
ultravox_rest = this->ultravox_size - this->ultravox_pos;
@@ -195,7 +194,7 @@ static off_t nsv_seek(demux_nsv_t *this, off_t offset, int origin) {
/* ultravox stuff */
if (origin == SEEK_CUR) {
uint8_t buffer[1024];
-
+
while (offset) {
if (offset > sizeof(buffer)) {
if (nsv_read(this, buffer, sizeof(buffer)) != sizeof(buffer))
@@ -222,7 +221,7 @@ static int nsv_resync(demux_nsv_t *this) {
for (i = 0; i < NSV_MAX_RESYNC; i++) {
uint8_t byte;
-
+
if (nsv_read(this, &byte, 1) != 1)
return NSV_RESYNC_ERROR;
@@ -256,17 +255,11 @@ static int open_nsv_file(demux_nsv_t *this) {
return 0;
/* check for a 'NSV' signature */
- if ((preview[0] != 'N') ||
- (preview[1] != 'S') ||
- (preview[2] != 'V'))
- {
- if ((preview[0] != 'Z') ||
- (preview[1] != 0) ||
- (preview[2] != '9'))
- return 0;
+ if ( memcmp(preview, "Z\09", 3) == 0) {
this->is_ultravox = preview[3];
this->ultravox_first = 1;
- }
+ } else if ( memcmp(preview, "NSV", 3) != 0 )
+ return 0;
lprintf("NSV file detected, ultravox=%d\n", this->is_ultravox);
@@ -274,11 +267,11 @@ static int open_nsv_file(demux_nsv_t *this) {
while (!NSVs_found) {
switch (nsv_resync(this)) {
-
+
case NSV_RESYNC_NSVf:
{
uint32_t chunk_size;
-
+
/* if there is a NSVs tag, load 24 more header bytes; load starting at
* offset 4 in buffer to keep header data in line with document */
if (nsv_read(this, &preview[4], 24) != 24)
@@ -287,41 +280,41 @@ static int open_nsv_file(demux_nsv_t *this) {
lprintf("found NSVf chunk\n");
/* this->data_size = _X_LE_32(&preview[8]);*/
/*lprintf("data_size: %lld\n", this->data_size);*/
-
+
/* skip the rest of the data */
chunk_size = _X_LE_32(&preview[4]);
nsv_seek(this, chunk_size - 28, SEEK_CUR);
}
break;
-
+
case NSV_RESYNC_NSVs:
-
- /* fetch the remaining 15 header bytes of the first chunk to get the
+
+ /* fetch the remaining 15 header bytes of the first chunk to get the
* relevant information */
if (nsv_read(this, &preview[4], 15) != 15)
return 0;
-
+
this->video_fourcc = _X_ME_32(&preview[4]);
- if (_X_BE_32(&preview[4]) == NONE_TAG)
+ if (_x_is_fourcc(&preview[4], "NONE"))
this->video_type = 0;
else
this->video_type = _x_fourcc_to_buf_video(this->video_fourcc);
-
+
this->audio_fourcc = _X_ME_32(&preview[8]);
- if (_X_BE_32(&preview[8]) == NONE_TAG)
+ if (_x_is_fourcc(&preview[8], "NONE"))
this->audio_type = 0;
else
this->audio_type = _x_formattag_to_buf_audio(this->audio_fourcc);
-
+
this->bih.biSize = sizeof(this->bih);
this->bih.biWidth = _X_LE_16(&preview[12]);
this->bih.biHeight = _X_LE_16(&preview[14]);
this->bih.biCompression = this->video_fourcc;
this->video_pts = 0;
-
+
/* may not be true, but set it for the time being */
this->frame_pts_inc = 3003;
-
+
lprintf("video: %c%c%c%c, buffer type %08X, %dx%d\n",
preview[4],
preview[5],
@@ -340,10 +333,10 @@ static int open_nsv_file(demux_nsv_t *this) {
nsv_parse_framerate(this, preview[16]);
NSVs_found = 1;
break;
-
+
case NSV_RESYNC_ERROR:
return 0;
-
+
}
}
@@ -465,27 +458,27 @@ static int demux_nsv_send_chunk(demux_plugin_t *this_gen) {
current_file_pos = this->input->get_current_pos(this->input);
lprintf("dispatching video & audio chunks...\n");
-
+
if (this->is_first_chunk) {
chunk_type = NSV_RESYNC_BEEF;
this->is_first_chunk = 0;
} else {
chunk_type = nsv_resync(this);
}
-
+
switch (chunk_type) {
case NSV_RESYNC_NSVf:
/* do nothing */
break;
-
+
case NSV_RESYNC_NSVs:
/* skip header */
if (nsv_read(this, buffer, 15) != 15)
return 0;
nsv_parse_framerate(this, buffer[12]);
-
+
/* fall thru */
-
+
case NSV_RESYNC_BEEF:
if (nsv_read(this, buffer, 5) != 5) {
this->status = DEMUX_FINISHED;
@@ -495,15 +488,15 @@ static int demux_nsv_send_chunk(demux_plugin_t *this_gen) {
video_size >>= 4;
video_size &= 0xFFFFF;
audio_size = _X_LE_16(&buffer[3]);
-
+
nsv_parse_payload(this, video_size, audio_size);
break;
-
+
case NSV_RESYNC_ERROR:
this->status = DEMUX_FINISHED;
break;
}
-
+
return this->status;
}
@@ -594,7 +587,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_nsv_t *this;
- this = xine_xmalloc (sizeof (demux_nsv_t));
+ this = calloc(1, sizeof(demux_nsv_t));
this->stream = stream;
this->input = input;
@@ -668,7 +661,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *demux_nsv_init_plugin (xine_t *xine, void *data) {
demux_nsv_class_t *this;
- this = xine_xmalloc (sizeof (demux_nsv_class_t));
+ this = calloc(1, sizeof(demux_nsv_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_ogg.c b/src/demuxers/demux_ogg.c
index 9ed39f12d..3fc5ec9e1 100644
--- a/src/demuxers/demux_ogg.c
+++ b/src/demuxers/demux_ogg.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2000-2004 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -194,7 +194,7 @@ static int get_stream (demux_ogg_t *this, int serno) {
static int new_stream_info (demux_ogg_t *this, const int cur_serno) {
int stream_num;
- this->si[this->num_streams] = (stream_info_t *)xine_xmalloc(sizeof(stream_info_t));
+ this->si[this->num_streams] = (stream_info_t *)calloc(1, sizeof(stream_info_t));
ogg_stream_init(&this->si[this->num_streams]->oss, cur_serno);
stream_num = this->num_streams;
this->si[stream_num]->buf_types = 0;
@@ -237,7 +237,7 @@ static int read_ogg_packet (demux_ogg_t *this) {
while (ogg_sync_pageout(&this->oy,&this->og)!=1) {
buffer = ogg_sync_buffer(&this->oy, CHUNKSIZE);
bytes = this->input->read(this->input, buffer, CHUNKSIZE);
- if (bytes == 0) {
+ if (bytes <= 0) {
if (total == 0) {
lprintf("read_ogg_packet read nothing\n");
return 0;
@@ -304,10 +304,10 @@ static void send_ogg_packet (demux_ogg_t *this,
buf_element_t *buf;
int done=0,todo=op->bytes;
- int op_size = sizeof(ogg_packet);
+ const size_t op_size = sizeof(ogg_packet);
while (done<todo) {
- int offset=0;
+ size_t offset=0;
buf = fifo->buffer_pool_alloc (fifo);
buf->decoder_flags = decoder_flags;
if (done==0) {
@@ -329,7 +329,7 @@ static void send_ogg_packet (demux_ogg_t *this,
buf->pts = pts;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = buf->pts / 90 ;
buf->type = this->si[stream_num]->buf_types;
@@ -498,7 +498,7 @@ static void read_chapter_comment (demux_ogg_t *this, ogg_packet *op) {
lprintf("time: %d %d %d %d\n", hour, min,sec,msec);
if (!this->chapter_info) {
- this->chapter_info = (chapter_info_t *)xine_xmalloc(sizeof(chapter_info_t));
+ this->chapter_info = (chapter_info_t *)calloc(1, sizeof(chapter_info_t));
this->chapter_info->current_chapter = -1;
}
this->chapter_info->max_chapter = chapter_no;
@@ -531,34 +531,34 @@ static void update_chapter_display (demux_ogg_t *this, int stream_num, ogg_packe
chapter--;
if (chapter != this->chapter_info->current_chapter){
- xine_event_t uevent;
- xine_ui_data_t data;
- int title_len;
- char *title;
+ xine_ui_data_t data = {
+ .str = { 0, },
+ .str_len = 0
+ };
+ xine_event_t uevent = {
+ .type = XINE_EVENT_UI_SET_TITLE,
+ .stream = this->stream,
+ .data = &data,
+ .data_length = sizeof(data)
+ };
this->chapter_info->current_chapter = chapter;
- if (chapter >= 0) {
- char t_title[256];
+ if (chapter >= 0) {
if (this->title) {
- snprintf(t_title, sizeof (t_title), "%s / %s", this->title, this->chapter_info->entries[chapter].name);
+ data.str_len = snprintf(data.str, sizeof(data.str), "%s / %s", this->title, this->chapter_info->entries[chapter].name);
} else {
- snprintf(t_title, sizeof (t_title), "%s", this->chapter_info->entries[chapter].name);
+ strncpy(data.str, this->chapter_info->entries[chapter].name, sizeof(data.str)-1);
}
- title = t_title;
} else {
- title = this->title;
+ strncpy(data.str, this->title, sizeof(data.str));
}
- _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, title);
- lprintf("new TITLE: %s\n", title);
-
- uevent.type = XINE_EVENT_UI_SET_TITLE;
- uevent.stream = this->stream;
- uevent.data = &data;
- uevent.data_length = sizeof(data);
- title_len = strlen(title) + 1;
- memcpy(data.str, title, title_len);
- data.str_len = title_len;
+ if ( data.str_len == 0 )
+ data.str_len = strlen(data.str);
+
+ _x_meta_info_set(this->stream, XINE_META_INFO_TITLE, data.str);
+ lprintf("new TITLE: %s\n", data.str);
+
xine_event_send(this->stream, &uevent);
}
}
@@ -578,10 +578,10 @@ static void send_ogg_buf (demux_ogg_t *this,
int normpos = 0;
if( this->input->get_length (this->input) )
- normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
-
+
hdrlen = (*op->packet & PACKET_LEN_BITS01) >> 6;
hdrlen |= (*op->packet & PACKET_LEN_BITS2) << 1;
@@ -686,7 +686,7 @@ static void send_ogg_buf (demux_ogg_t *this,
check_newpts( this, pts, PTS_VIDEO, decoder_flags );
} else
pts = 0;
-
+
llprintf(DEBUG_VIDEO_PACKETS,
"videostream %d op-gpos %" PRId64 " hdr-gpos %" PRId64 " pts %" PRId64 " \n",
stream_num,
@@ -1020,7 +1020,7 @@ static void decode_dshow_header (demux_ogg_t *this, const int stream_num, ogg_pa
this->si[stream_num]->headers = 0; /* header is sent below */
- if ( (_X_LE_32(&op->packet[96]) == 0x05589f80) && (op->bytes >= 184)) {
+ if ( _x_is_fourcc(&op->packet[96], "\x05\x58\x9f\x80") && (op->bytes >= 184)) {
buf_element_t *buf;
xine_bmiheader bih;
@@ -1079,7 +1079,7 @@ static void decode_dshow_header (demux_ogg_t *this, const int stream_num, ogg_pa
this->ignore_keyframes = 1;
- } else if (_X_LE_32(&op->packet[96]) == 0x05589F81) {
+ } else if (_x_is_fourcc(&op->packet[96], "\x05\x58\x9f\x81")) {
#if 0
/* FIXME: no test streams */
@@ -1194,27 +1194,27 @@ static void decode_theora_header (demux_ogg_t *this, const int stream_num, ogg_p
static void decode_flac_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) {
xine_flac_metadata_header header;
- xine_flac_streaminfo_block streaminfo;
+ xine_flac_streaminfo_block streaminfo = {};
buf_element_t *buf;
xine_waveformatex wave;
- /* Packet type */
- _x_assert(op->packet[0] == 0x7F);
-
- /* OggFLAC signature */
- _x_assert(op->packet[1] == 'F'); _x_assert(op->packet[2] == 'L');
- _x_assert(op->packet[3] == 'A'); _x_assert(op->packet[4] == 'C');
+ static const uint8_t flac_signature_1[] =
+ {
+ /* Packet type */
+ 0x7F,
+ /* OggFLAC signature */
+ 'F', 'L', 'A', 'C',
+ /* Version: only 1.0 supported */
+ 1, 0
+ };
+ static const uint8_t flac_signature_2[] = "fLaC";
- /* Version: supported only 1.0 */
- _x_assert(op->packet[5] == 1); _x_assert(op->packet[6] == 0);
+ _x_assert(memcmp(&op->packet[0], flac_signature_1, sizeof(flac_signature_1)) == 0);
+ _x_assert(memcmp(&op->packet[9], flac_signature_2, sizeof(flac_signature_2)) == 0);
/* Header count */
this->si[stream_num]->headers = 0/*_X_BE_16(&op->packet[7]) +1*/;
- /* fLaC signature */
- _x_assert(op->packet[9] == 'f'); _x_assert(op->packet[10] == 'L');
- _x_assert(op->packet[11] == 'a'); _x_assert(op->packet[12] == 'C');
-
_x_parse_flac_metadata_header(&op->packet[13], &header);
switch ( header.blocktype ) {
@@ -1267,8 +1267,8 @@ static void decode_annodex_header (demux_ogg_t *this, const int stream_num, ogg_
static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) {
int64_t granule_rate_n, granule_rate_d;
uint32_t secondary_headers;
- char content_type[1024];
- int content_type_length;
+ const char *content_type = "";
+ size_t content_type_length = 0;
lprintf("AnxData stream detected\n");
@@ -1280,11 +1280,16 @@ static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_
lprintf("granule_rate %" PRId64 "/%" PRId64 ", %d secondary headers\n",
granule_rate_n, granule_rate_d, secondary_headers);
- /* read "Content-Tyoe" MIME header */
- sscanf(&op->packet[28], "Content-Type: %1023s\r\n", content_type);
- content_type_length = strlen(content_type);
+ /* read "Content-Type" MIME header */
+ const char *startline = &op->packet[28];
+ const char *endline;
+ if ( strcmp(&op->packet[28], "Content-Type: ") == 0 &&
+ (endline = strstr(startline, "\r\n")) ) {
+ content_type = startline + sizeof("Content-Type: ");
+ content_type_length = startline - endline;
+ }
- lprintf("Content-Type: %s (length:%d)\n", content_type, content_type_length);
+ lprintf("Content-Type: %s (length:%td)\n", content_type, content_type_length);
/* how many header packets in the AnxData stream? */
this->si[stream_num]->headers = secondary_headers + 1;
@@ -1323,7 +1328,7 @@ static void decode_anxdata_header (demux_ogg_t *this, const int stream_num, ogg_
} else {
this->si[stream_num]->buf_types = BUF_CONTROL_NOP;
}
-
+
}
static void decode_cmml_header (demux_ogg_t *this, const int stream_num, ogg_packet *op) {
@@ -1352,7 +1357,7 @@ static void send_header (demux_ogg_t *this) {
this->ignore_keyframes = 0;
while (!done) {
- if (!read_ogg_packet(this)) {
+ if (!read_ogg_packet(this) || !this->og.header || !this->og.body) {
return;
}
/* now we've got at least one new page */
@@ -1478,6 +1483,12 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) {
return this->status;
}
+ if (!this->og.header || !this->og.body) {
+ this->status = DEMUX_FINISHED;
+ lprintf ("EOF\n");
+ return this->status;
+ }
+
/* now we've got one new page */
cur_serno = ogg_page_serialno (&this->og);
@@ -1592,10 +1603,10 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) {
if (ogg_page_eos(&this->og)) {
int i;
int finished_streams = 0;
-
+
lprintf("end of stream, serialnumber %d\n", cur_serno);
this->si[stream_num]->delivered_eos = 1;
-
+
/* check if all logical streams are finished */
for (i = 0; i < this->num_streams; i++) {
finished_streams += this->si[i]->delivered_eos;
@@ -1617,12 +1628,12 @@ static int demux_ogg_send_chunk (demux_plugin_t *this_gen) {
this->unhandled_video_streams = 0;
this->num_spu_streams = 0;
this->avg_bitrate = 1;
-
+
/* try to read a chained stream */
this->send_newpts = 1;
this->last_pts[0] = 0;
this->last_pts[1] = 0;
-
+
/* send control buffer to avoid buffer leak */
_x_demux_control_end(this->stream, 0);
_x_demux_control_start(this->stream);
@@ -1751,7 +1762,7 @@ static int demux_ogg_seek (demux_plugin_t *this_gen,
hasn` changed its length, otherwise no seek to "new" data is possible*/
lprintf ("seek to time %d called\n",start_time);
- lprintf ("current time is %d\n",current_time);
+ lprintf ("current time is %d\n",current_time);
if (current_time > start_time) {
/*seek between beginning and current_pos*/
@@ -1771,7 +1782,7 @@ static int demux_ogg_seek (demux_plugin_t *this_gen,
}
lprintf ("current_pos is %" PRId64 "\n",current_pos);
- lprintf ("new_pos is %" PRId64 "\n",start_pos);
+ lprintf ("new_pos is %" PRId64 "\n",start_pos);
} else {
/*seek using avg_bitrate*/
@@ -1790,9 +1801,9 @@ static int demux_ogg_seek (demux_plugin_t *this_gen,
ogg_stream_reset(&this->si[i]->oss);
}
- /*some strange streams have no syncpoint flag set at the beginning*/
- if (start_pos == 0)
- this->keyframe_needed = 0;
+ /*some strange streams have no syncpoint flag set at the beginning*/
+ if (start_pos == 0)
+ this->keyframe_needed = 0;
lprintf ("seek to %" PRId64 " called\n",start_pos);
@@ -1803,7 +1814,7 @@ static int demux_ogg_seek (demux_plugin_t *this_gen,
/* fixme - this would be a nice position to do the following tasks
1. adjust an ogg videostream to a keyframe
2. compare the keyframe_pts with start_time. if the difference is to
- high (e.g. larger than max keyframe_intervall, do a new seek or
+ high (e.g. larger than max keyframe_intervall, do a new seek or
continue reading
3. adjust the audiostreams in such a way, that the
difference is not to high.
@@ -1811,12 +1822,12 @@ static int demux_ogg_seek (demux_plugin_t *this_gen,
In short words, do all the cleanups necessary to continue playback
without further actions
*/
-
+
this->send_newpts = 1;
this->status = DEMUX_OK;
-
+
if( !playing ) {
-
+
this->buf_flag_seek = 0;
} else {
@@ -1833,13 +1844,13 @@ static int demux_ogg_seek (demux_plugin_t *this_gen,
_x_demux_flush_engine(this->stream);
}
-
+
return this->status;
}
static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) {
- demux_ogg_t *this = (demux_ogg_t *) this_gen;
+ demux_ogg_t *this = (demux_ogg_t *) this_gen;
if (this->time_length==-1){
if (this->avg_bitrate) {
@@ -1854,7 +1865,7 @@ static int demux_ogg_get_stream_length (demux_plugin_t *this_gen) {
}
static uint32_t demux_ogg_get_capabilities(demux_plugin_t *this_gen) {
- demux_ogg_t *this = (demux_ogg_t *) this_gen;
+ demux_ogg_t *this = (demux_ogg_t *) this_gen;
int cap_chapter = 0;
if (this->chapter_info)
@@ -1884,8 +1895,8 @@ static int format_lang_string (demux_ogg_t * this, uint32_t buf_mask, uint32_t b
static int demux_ogg_get_optional_data(demux_plugin_t *this_gen,
void *data, int data_type) {
-
- demux_ogg_t *this = (demux_ogg_t *) this_gen;
+
+ demux_ogg_t *this = (demux_ogg_t *) this_gen;
char *str=(char *) data;
int channel = *((int *)data);
@@ -1924,11 +1935,7 @@ static int detect_ogg_content (int detection_method, demux_class_t *class_gen,
if (_x_demux_read_header(input, buf, 4) != 4)
return 0;
- if ((buf[0] == 'O') && (buf[1] == 'g') && (buf[2] == 'g') &&
- (buf[3] == 'S'))
- return 1;
- else
- return 0;
+ return _x_is_fourcc(buf, "OggS");
}
case METHOD_BY_EXTENSION: {
@@ -2014,7 +2021,7 @@ static int detect_anx_content (int detection_method, demux_class_t *class_gen,
}
static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen,
- xine_stream_t *stream,
+ xine_stream_t *stream,
input_plugin_t *input) {
demux_ogg_t *this;
@@ -2026,8 +2033,7 @@ static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen,
* if we reach this point, the input has been accepted.
*/
- this = xine_xmalloc (sizeof (demux_ogg_t));
- memset (this, 0, sizeof(demux_ogg_t));
+ this = calloc(1, sizeof(demux_ogg_t));
this->stream = stream;
this->input = input;
@@ -2044,13 +2050,13 @@ static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen,
this->demux_plugin.get_capabilities = demux_ogg_get_capabilities;
this->demux_plugin.get_optional_data = demux_ogg_get_optional_data;
this->demux_plugin.demux_class = class_gen;
-
+
this->status = DEMUX_FINISHED;
#ifdef HAVE_THEORA
theora_info_init (&this->t_info);
theora_comment_init (&this->t_comment);
-#endif
+#endif
this->chapter_info = 0;
this->title = 0;
@@ -2060,7 +2066,7 @@ static demux_plugin_t *anx_open_plugin (demux_class_t *class_gen,
}
static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen,
- xine_stream_t *stream,
+ xine_stream_t *stream,
input_plugin_t *input) {
demux_ogg_t *this;
@@ -2072,8 +2078,7 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen,
* if we reach this point, the input has been accepted.
*/
- this = xine_xmalloc (sizeof (demux_ogg_t));
- memset (this, 0, sizeof(demux_ogg_t));
+ this = calloc(1, sizeof(demux_ogg_t));
this->stream = stream;
this->input = input;
@@ -2086,13 +2091,13 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen,
this->demux_plugin.get_capabilities = demux_ogg_get_capabilities;
this->demux_plugin.get_optional_data = demux_ogg_get_optional_data;
this->demux_plugin.demux_class = class_gen;
-
+
this->status = DEMUX_FINISHED;
#ifdef HAVE_THEORA
theora_info_init (&this->t_info);
theora_comment_init (&this->t_comment);
-#endif
+#endif
this->chapter_info = 0;
this->title = 0;
@@ -2108,7 +2113,7 @@ static demux_plugin_t *ogg_open_plugin (demux_class_t *class_gen,
static const char *anx_get_description (demux_class_t *this_gen) {
return "Annodex demux plugin";
}
-
+
static const char *anx_get_identifier (demux_class_t *this_gen) {
return "Annodex";
}
@@ -2118,7 +2123,12 @@ static const char *anx_get_extensions (demux_class_t *this_gen) {
}
static const char *anx_get_mimetypes (demux_class_t *this_gen) {
- return "application/x-annodex: ogg: Annodex media;";
+ return "application/annodex: anx: Annodex media;"
+ "application/x-annodex: anx: Annodex media;"
+ "audio/annodex: axa: Annodex audio;"
+ "audio/x-annodex: axa: Annodex audio;"
+ "video/annodex: axv: Annodex video;"
+ "video/x-annodex: axv: Annodex video;";
}
static void anx_class_dispose (demux_class_t *this_gen) {
@@ -2130,7 +2140,7 @@ static void anx_class_dispose (demux_class_t *this_gen) {
static void *anx_init_class (xine_t *xine, void *data) {
demux_anx_class_t *this;
- this = xine_xmalloc (sizeof (demux_anx_class_t));
+ this = calloc(1, sizeof(demux_anx_class_t));
this->demux_class.open_plugin = anx_open_plugin;
this->demux_class.get_description = anx_get_description;
@@ -2149,20 +2159,25 @@ static void *anx_init_class (xine_t *xine, void *data) {
static const char *ogg_get_description (demux_class_t *this_gen) {
return "OGG demux plugin";
}
-
+
static const char *ogg_get_identifier (demux_class_t *this_gen) {
return "OGG";
}
static const char *ogg_get_extensions (demux_class_t *this_gen) {
- return "ogg ogm spx";
+ return "ogx ogv oga ogg spx ogm";
}
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: Ogg Stream;"
- "application/ogg: ogg: Ogg Stream;";
+ return "application/ogg: ogx: Ogg Stream;"
+ "application/x-ogg: ogx: Ogg Stream;"
+ "application/x-ogm: ogx: Ogg Stream;"
+ "application/x-ogm-audio: oga: Ogg Audio;"
+ "application/x-ogm-video: ogv: Ogg Video;"
+ "audio/ogg: oga: Ogg Audio;"
+ "audio/x-ogg: oga: Ogg Audio;"
+ "video/ogg: ogv: Ogg Video;"
+ "video/x-ogg: ogv: Ogg Video;";
}
static void ogg_class_dispose (demux_class_t *this_gen) {
@@ -2174,7 +2189,7 @@ static void ogg_class_dispose (demux_class_t *this_gen) {
static void *ogg_init_class (xine_t *xine, void *data) {
demux_ogg_class_t *this;
- this = xine_xmalloc (sizeof (demux_ogg_class_t));
+ this = calloc(1, sizeof(demux_ogg_class_t));
this->demux_class.open_plugin = ogg_open_plugin;
this->demux_class.get_description = ogg_get_description;
@@ -2198,7 +2213,7 @@ static const demuxer_info_t demux_info_ogg = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "ogg", XINE_VERSION_CODE, &demux_info_ogg, ogg_init_class },
{ PLUGIN_DEMUX, 26, "anx", XINE_VERSION_CODE, &demux_info_anx, anx_init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
diff --git a/src/demuxers/demux_pva.c b/src/demuxers/demux_pva.c
index 298d936b5..e2b61dcf0 100644
--- a/src/demuxers/demux_pva.c
+++ b/src/demuxers/demux_pva.c
@@ -148,7 +148,7 @@ static int demux_pva_send_chunk(demux_plugin_t *this_gen) {
current_file_pos = this->input->get_current_pos(this->input);
if (preamble[2] == 1) {
-
+
/* video */
/* load the pts if it is the first thing in the chunk */
@@ -253,7 +253,7 @@ static int demux_pva_send_chunk(demux_plugin_t *this_gen) {
buf->pts = pts;
if( this->data_size )
- buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) *
+ buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) *
65535 / this->data_size);
this->audio_fifo->put (this->audio_fifo, buf);
@@ -302,7 +302,7 @@ static void demux_pva_send_headers(demux_plugin_t *this_gen) {
buf->pts = 0;
if( this->data_size )
- buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) *
+ buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) *
65535 / this->data_size);
buf->type = BUF_VIDEO_MPEG;
@@ -329,7 +329,7 @@ static void demux_pva_send_headers(demux_plugin_t *this_gen) {
buf->pts = 0;
if( this->data_size )
- buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) *
+ buf->extra_info->input_normpos = (int) ((double) this->input->get_current_pos(this->input) *
65535 / this->data_size);
buf->type = BUF_AUDIO_MPEG;
@@ -347,7 +347,7 @@ static int demux_pva_seek (demux_plugin_t *this_gen,
unsigned char seek_buffer[SEEK_BUFFER_SIZE];
int found = 0;
int i;
-
+
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
@@ -430,7 +430,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_pva_t));
+ this = calloc(1, sizeof(demux_pva_t));
this->stream = stream;
this->input = input;
@@ -503,7 +503,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_pva_class_t *this;
- this = xine_xmalloc (sizeof (demux_pva_class_t));
+ this = calloc(1, sizeof(demux_pva_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_qt.c b/src/demuxers/demux_qt.c
index a55a0aef3..8e00d73a4 100644
--- a/src/demuxers/demux_qt.c
+++ b/src/demuxers/demux_qt.c
@@ -134,7 +134,7 @@ typedef unsigned int qt_atom;
#define MAX_PTS_DIFF 100000
/* network bandwidth, cribbed from src/input/input_mms.c */
-const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600,
+static const int64_t bandwidths[]={14400,19200,28800,33600,34430,57600,
115200,262200,393216,524300,1544000,10485800};
/* these are things that can go wrong */
@@ -262,10 +262,10 @@ typedef struct {
/* flags that indicate how a trak is supposed to be used */
unsigned int flags;
-
+
/* formattag-like field that specifies codec in mp4 files */
unsigned int object_type_id;
-
+
/* decoder data pass information to the decoder */
void *decoder_config;
int decoder_config_len;
@@ -307,7 +307,7 @@ typedef struct {
unsigned int modification_time;
unsigned int timescale; /* base clock frequency is Hz */
unsigned int duration;
-
+
int64_t moov_first_offset;
int trak_count;
@@ -381,7 +381,7 @@ typedef struct {
* lazyqt special debugging functions
**********************************************************************/
-/* define DEBUG_ATOM_LOAD as 1 to get a verbose parsing of the relevant
+/* define DEBUG_ATOM_LOAD as 1 to get a verbose parsing of the relevant
* atoms */
#define DEBUG_ATOM_LOAD 0
@@ -403,7 +403,7 @@ typedef struct {
/* Define DEBUG_DUMP_MOOV as 1 to dump the raw moov atom to disk. This is
* particularly useful in debugging a file with a compressed moov (cmov)
- * atom. The atom will be dumped to the filename specified as
+ * atom. The atom will be dumped to the filename specified as
* RAW_MOOV_FILENAME. */
#define DEBUG_DUMP_MOOV 0
#define RAW_MOOV_FILENAME "moovatom.raw"
@@ -502,7 +502,7 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset,
atom = _X_BE_32(&atom_preamble[4]);
/* Special case alert: 'free' atoms sometimes masquerade as 'moov'
- * atoms. If this is a free atom, check for 'cmov' or 'mvhd' immediately
+ * atoms. If this is a free atom, check for 'cmov' or 'mvhd' immediately
* following. QT Player can handle it, so xine should too. */
if (atom == FREE_ATOM) {
@@ -533,7 +533,7 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset,
/* if this atom is not the moov atom, make sure that it is at least one
* of the other top-level QT atom.
- * However, allow a configurable amount ( currently 1 ) atom be a
+ * However, allow a configurable amount ( currently 1 ) atom be a
* non known atom, in hopes a known atom will be found */
if ((atom != FREE_ATOM) &&
(atom != JUNK_ATOM) &&
@@ -581,7 +581,7 @@ static void find_moov_atom(input_plugin_t *input, off_t *moov_offset,
static qt_info *create_qt_info(void) {
qt_info *info;
- info = (qt_info *)xine_xmalloc(sizeof(qt_info));
+ info = (qt_info *)calloc(1, sizeof(qt_info));
if (!info)
return NULL;
@@ -712,7 +712,7 @@ static int is_qt_file(input_plugin_t *qt_file) {
return 0;
} else {
/* check that the next atom in the chunk contains alphanumeric
- * characters in the atom type field; if not, disqualify the file
+ * characters in the atom type field; if not, disqualify the file
* as a QT file */
qt_file->seek(qt_file, moov_atom_offset + ATOM_PREAMBLE_SIZE, SEEK_SET);
if (qt_file->read(qt_file, atom_preamble, ATOM_PREAMBLE_SIZE) !=
@@ -738,39 +738,67 @@ static void parse_meta_atom(qt_info *info, unsigned char *meta_atom) {
if (current_atom == ART_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->artist = xine_xmalloc(string_size);
- strncpy(info->artist, &meta_atom[i + 20], string_size - 1);
- info->artist[string_size - 1] = 0;
+ if (info->artist) {
+ strncpy(info->artist, &meta_atom[i + 20], string_size - 1);
+ info->artist[string_size - 1] = 0;
+ }
} else if (current_atom == NAM_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->name = xine_xmalloc(string_size);
- strncpy(info->name, &meta_atom[i + 20], string_size - 1);
- info->name[string_size - 1] = 0;
+ if (info->name) {
+ strncpy(info->name, &meta_atom[i + 20], string_size - 1);
+ info->name[string_size - 1] = 0;
+ }
} else if (current_atom == ALB_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->album = xine_xmalloc(string_size);
- strncpy(info->album, &meta_atom[i + 20], string_size - 1);
- info->album[string_size - 1] = 0;
+ if (info->album) {
+ strncpy(info->album, &meta_atom[i + 20], string_size - 1);
+ info->album[string_size - 1] = 0;
+ }
} else if (current_atom == GEN_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->genre = xine_xmalloc(string_size);
- strncpy(info->genre, &meta_atom[i + 20], string_size - 1);
- info->genre[string_size - 1] = 0;
+ if (info->genre) {
+ strncpy(info->genre, &meta_atom[i + 20], string_size - 1);
+ info->genre[string_size - 1] = 0;
+ }
} else if (current_atom == TOO_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->comment = xine_xmalloc(string_size);
- strncpy(info->comment, &meta_atom[i + 20], string_size - 1);
- info->comment[string_size - 1] = 0;
+ if (info->comment) {
+ strncpy(info->comment, &meta_atom[i + 20], string_size - 1);
+ info->comment[string_size - 1] = 0;
+ }
} else if (current_atom == WRT_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->composer = xine_xmalloc(string_size);
- strncpy(info->composer, &meta_atom[i + 20], string_size - 1);
- info->composer[string_size - 1] = 0;
+ if (info->composer) {
+ strncpy(info->composer, &meta_atom[i + 20], string_size - 1);
+ info->composer[string_size - 1] = 0;
+ }
} else if (current_atom == DAY_ATOM) {
string_size = _X_BE_32(&meta_atom[i + 4]) - 16 + 1;
+ if (string_size <= 0)
+ continue;
info->year = xine_xmalloc(string_size);
- strncpy(info->year, &meta_atom[i + 20], string_size - 1);
- info->year[string_size - 1] = 0;
+ if (info->year) {
+ strncpy(info->year, &meta_atom[i + 20], string_size - 1);
+ info->year[string_size - 1] = 0;
+ }
}
}
@@ -793,7 +821,7 @@ static void parse_mvhd_atom(qt_info *info, unsigned char *mvhd_atom) {
static int mp4_read_descr_len(unsigned char *s, uint32_t *length) {
uint8_t b;
uint8_t numBytes = 0;
-
+
*length = 0;
do {
@@ -872,14 +900,14 @@ static qt_error parse_trak_atom (qt_trak *trak,
break;
}
}
-
+
debug_atom_load(" qt: parsing %s trak atom\n",
(trak->type == MEDIA_VIDEO) ? "video" :
(trak->type == MEDIA_AUDIO) ? "audio" : "other");
/* search for the useful atoms */
for (i = ATOM_PREAMBLE_SIZE; i < trak_atom_size - 4; i++) {
- current_atom_size = _X_BE_32(&trak_atom[i - 4]);
+ current_atom_size = _X_BE_32(&trak_atom[i - 4]);
current_atom = _X_BE_32(&trak_atom[i]);
if (current_atom == TKHD_ATOM) {
@@ -897,8 +925,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt elst atom (edit list atom): %d entries\n",
trak->edit_list_count);
- trak->edit_list_table = (edit_list_table_t *)xine_xmalloc(
- trak->edit_list_count * sizeof(edit_list_table_t));
+ trak->edit_list_table = (edit_list_table_t *)calloc(
+ trak->edit_list_count, sizeof(edit_list_table_t));
if (!trak->edit_list_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -919,7 +947,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
} else if (current_atom == MDHD_ATOM) {
int version;
debug_atom_load ("demux_qt: mdhd atom\n");
-
+
version = trak_atom[i+4];
if ( version > 1 ) continue; /* unsupported, undocumented */
@@ -933,18 +961,25 @@ static qt_error parse_trak_atom (qt_trak *trak,
/* allocate space for each of the properties unions */
trak->stsd_atoms_count = _X_BE_32(&trak_atom[i + 8]);
- trak->stsd_atoms = xine_xmalloc(trak->stsd_atoms_count * sizeof(properties_t));
+ if (trak->stsd_atoms_count <= 0) {
+ last_error = QT_HEADER_TROUBLE;
+ goto free_trak;
+ }
+ trak->stsd_atoms = calloc(trak->stsd_atoms_count, sizeof(properties_t));
if (!trak->stsd_atoms) {
last_error = QT_NO_MEMORY;
goto free_trak;
}
- memset(trak->stsd_atoms, 0, trak->stsd_atoms_count * sizeof(properties_t));
atom_pos = i + 0x10;
properties_offset = 0x0C;
for (k = 0; k < trak->stsd_atoms_count; k++) {
- current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]);
+ current_stsd_atom_size = _X_BE_32(&trak_atom[atom_pos - 4]);
+ if (current_stsd_atom_size < 4) {
+ last_error = QT_HEADER_TROUBLE;
+ goto free_trak;
+ }
if (trak->type == MEDIA_VIDEO) {
@@ -953,8 +988,12 @@ static qt_error parse_trak_atom (qt_trak *trak,
/* copy the properties atom */
trak->stsd_atoms[k].video.properties_atom_size = current_stsd_atom_size - 4;
- trak->stsd_atoms[k].video.properties_atom =
+ trak->stsd_atoms[k].video.properties_atom =
xine_xmalloc(trak->stsd_atoms[k].video.properties_atom_size);
+ if (!trak->stsd_atoms[k].video.properties_atom) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].video.properties_atom, &trak_atom[atom_pos],
trak->stsd_atoms[k].video.properties_atom_size);
@@ -967,7 +1006,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
trak->stsd_atoms[k].video.palette_count = 0;
/* fetch video parameters */
- if( _X_BE_16(&trak_atom[atom_pos + 0x1C]) &&
+ if( _X_BE_16(&trak_atom[atom_pos + 0x1C]) &&
_X_BE_16(&trak_atom[atom_pos + 0x1E]) ) {
trak->stsd_atoms[k].video.width =
_X_BE_16(&trak_atom[atom_pos + 0x1C]);
@@ -995,9 +1034,9 @@ static qt_error parse_trak_atom (qt_trak *trak,
/* compute the greyscale palette */
color_index = 255;
- color_dec = 256 /
+ color_dec = 256 /
(trak->stsd_atoms[k].video.palette_count - 1);
- for (j = 0;
+ for (j = 0;
j < trak->stsd_atoms[k].video.palette_count;
j++) {
@@ -1022,7 +1061,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
else
color_table = qt_default_palette_256;
- for (j = 0;
+ for (j = 0;
j < trak->stsd_atoms[k].video.palette_count;
j++) {
@@ -1049,7 +1088,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
color_index = _X_BE_16(&trak_atom[atom_pos + 0x5A + j * 8]);
if (color_count & 0x8000)
color_index = j;
- if (color_index <
+ if (color_index <
trak->stsd_atoms[k].video.palette_count) {
trak->stsd_atoms[k].video.palette[color_index].r =
trak_atom[atom_pos + 0x5A + j * 8 + 2];
@@ -1092,8 +1131,12 @@ static qt_error parse_trak_atom (qt_trak *trak,
/* copy the properties atom */
trak->stsd_atoms[k].audio.properties_atom_size = current_stsd_atom_size - 4;
- trak->stsd_atoms[k].audio.properties_atom =
+ trak->stsd_atoms[k].audio.properties_atom =
xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size);
+ if (!trak->stsd_atoms[k].audio.properties_atom) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].audio.properties_atom, &trak_atom[atom_pos],
trak->stsd_atoms[k].audio.properties_atom_size);
@@ -1110,12 +1153,12 @@ static qt_error parse_trak_atom (qt_trak *trak,
trak->stsd_atoms[k].audio.bits / 8;
trak->stsd_atoms[k].audio.samples_per_frame =
trak->stsd_atoms[k].audio.channels;
- trak->stsd_atoms[k].audio.bytes_per_frame =
- trak->stsd_atoms[k].audio.bytes_per_sample *
+ trak->stsd_atoms[k].audio.bytes_per_frame =
+ trak->stsd_atoms[k].audio.bytes_per_sample *
trak->stsd_atoms[k].audio.samples_per_frame;
- trak->stsd_atoms[k].audio.samples_per_packet =
+ trak->stsd_atoms[k].audio.samples_per_packet =
trak->stsd_atoms[k].audio.samples_per_frame;
- trak->stsd_atoms[k].audio.bytes_per_packet =
+ trak->stsd_atoms[k].audio.bytes_per_packet =
trak->stsd_atoms[k].audio.bytes_per_sample;
/* special case time: A lot of CBR audio codecs stored in the
@@ -1123,7 +1166,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
if (trak->stsd_atoms[k].audio.codec_fourcc == IMA4_FOURCC) {
trak->stsd_atoms[k].audio.samples_per_packet = 64;
trak->stsd_atoms[k].audio.bytes_per_packet = 34;
- trak->stsd_atoms[k].audio.bytes_per_frame = 34 *
+ trak->stsd_atoms[k].audio.bytes_per_frame = 34 *
trak->stsd_atoms[k].audio.channels;
trak->stsd_atoms[k].audio.bytes_per_sample = 2;
trak->stsd_atoms[k].audio.samples_per_frame = 64 *
@@ -1139,7 +1182,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
} else if (trak->stsd_atoms[k].audio.codec_fourcc == MAC6_FOURCC) {
trak->stsd_atoms[k].audio.samples_per_packet = 6;
trak->stsd_atoms[k].audio.bytes_per_packet = 1;
- trak->stsd_atoms[k].audio.bytes_per_frame = 1 *
+ trak->stsd_atoms[k].audio.bytes_per_frame = 1 *
trak->stsd_atoms[k].audio.channels;
trak->stsd_atoms[k].audio.bytes_per_sample = 1;
trak->stsd_atoms[k].audio.samples_per_frame = 6 *
@@ -1147,7 +1190,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
} else if (trak->stsd_atoms[k].audio.codec_fourcc == ALAW_FOURCC) {
trak->stsd_atoms[k].audio.samples_per_packet = 1;
trak->stsd_atoms[k].audio.bytes_per_packet = 1;
- trak->stsd_atoms[k].audio.bytes_per_frame = 1 *
+ trak->stsd_atoms[k].audio.bytes_per_frame = 1 *
trak->stsd_atoms[k].audio.channels;
trak->stsd_atoms[k].audio.bytes_per_sample = 2;
trak->stsd_atoms[k].audio.samples_per_frame = 2 *
@@ -1155,7 +1198,7 @@ static qt_error parse_trak_atom (qt_trak *trak,
} else if (trak->stsd_atoms[k].audio.codec_fourcc == ULAW_FOURCC) {
trak->stsd_atoms[k].audio.samples_per_packet = 1;
trak->stsd_atoms[k].audio.bytes_per_packet = 1;
- trak->stsd_atoms[k].audio.bytes_per_frame = 1 *
+ trak->stsd_atoms[k].audio.bytes_per_frame = 1 *
trak->stsd_atoms[k].audio.channels;
trak->stsd_atoms[k].audio.bytes_per_sample = 2;
trak->stsd_atoms[k].audio.samples_per_frame = 2 *
@@ -1174,21 +1217,22 @@ static qt_error parse_trak_atom (qt_trak *trak,
(trak->stsd_atoms[k].audio.codec_fourcc != RAW_FOURCC)) {
if (_X_BE_32(&trak_atom[atom_pos + 0x20]))
- trak->stsd_atoms[k].audio.samples_per_packet =
+ trak->stsd_atoms[k].audio.samples_per_packet =
_X_BE_32(&trak_atom[atom_pos + 0x20]);
if (_X_BE_32(&trak_atom[atom_pos + 0x24]))
- trak->stsd_atoms[k].audio.bytes_per_packet =
+ trak->stsd_atoms[k].audio.bytes_per_packet =
_X_BE_32(&trak_atom[atom_pos + 0x24]);
if (_X_BE_32(&trak_atom[atom_pos + 0x28]))
- trak->stsd_atoms[k].audio.bytes_per_frame =
+ trak->stsd_atoms[k].audio.bytes_per_frame =
_X_BE_32(&trak_atom[atom_pos + 0x28]);
if (_X_BE_32(&trak_atom[atom_pos + 0x2C]))
- trak->stsd_atoms[k].audio.bytes_per_sample =
+ trak->stsd_atoms[k].audio.bytes_per_sample =
_X_BE_32(&trak_atom[atom_pos + 0x2C]);
- trak->stsd_atoms[k].audio.samples_per_frame =
- (trak->stsd_atoms[k].audio.bytes_per_frame /
- trak->stsd_atoms[k].audio.bytes_per_packet) *
- trak->stsd_atoms[k].audio.samples_per_packet;
+ if (trak->stsd_atoms[k].audio.bytes_per_packet)
+ trak->stsd_atoms[k].audio.samples_per_frame =
+ (trak->stsd_atoms[k].audio.bytes_per_frame /
+ trak->stsd_atoms[k].audio.bytes_per_packet) *
+ trak->stsd_atoms[k].audio.samples_per_packet;
}
/* see if the trak deserves a promotion to VBR */
@@ -1208,9 +1252,13 @@ static qt_error parse_trak_atom (qt_trak *trak,
trak->stsd_atoms[k].audio.vbr = 1;
/* further, FFmpeg's ALAC decoder requires 36 out-of-band bytes */
trak->stsd_atoms[k].audio.properties_atom_size = 36;
- trak->stsd_atoms[k].audio.properties_atom =
+ trak->stsd_atoms[k].audio.properties_atom =
xine_xmalloc(trak->stsd_atoms[k].audio.properties_atom_size);
- memcpy(trak->stsd_atoms[k].audio.properties_atom,
+ if (!trak->stsd_atoms[k].audio.properties_atom) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
+ memcpy(trak->stsd_atoms[k].audio.properties_atom,
&trak_atom[atom_pos + 0x20],
trak->stsd_atoms[k].audio.properties_atom_size);
}
@@ -1226,11 +1274,15 @@ static qt_error parse_trak_atom (qt_trak *trak,
(_X_BE_32(&trak_atom[atom_pos + 0x3C]) == FRMA_ATOM) &&
(_X_ME_32(&trak_atom[atom_pos + 0x48]) == trak->stsd_atoms[k].audio.codec_fourcc)) {
int wave_size = _X_BE_32(&trak_atom[atom_pos + 0x44]) - 8;
-
+
if ((wave_size >= sizeof(xine_waveformatex)) &&
(current_atom_size >= (0x4C + wave_size))) {
trak->stsd_atoms[k].audio.wave_size = wave_size;
trak->stsd_atoms[k].audio.wave = xine_xmalloc(wave_size);
+ if (!trak->stsd_atoms[k].audio.wave) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->stsd_atoms[k].audio.wave, &trak_atom[atom_pos + 0x4C],
wave_size);
_x_waveformatex_le2me(trak->stsd_atoms[k].audio.wave);
@@ -1279,12 +1331,12 @@ static qt_error parse_trak_atom (qt_trak *trak,
} else if (current_atom == ESDS_ATOM) {
uint32_t len;
-
+
debug_atom_load(" qt/mpeg-4 esds atom\n");
- if ((trak->type == MEDIA_VIDEO) ||
+ if ((trak->type == MEDIA_VIDEO) ||
(trak->type == MEDIA_AUDIO)) {
-
+
j = i + 8;
if( trak_atom[j++] == 0x03 ) {
j += mp4_read_descr_len( &trak_atom[j], &len );
@@ -1300,21 +1352,29 @@ static qt_error parse_trak_atom (qt_trak *trak,
j += mp4_read_descr_len( &trak_atom[j], &len );
debug_atom_load(" decoder config is %d (0x%X) bytes long\n",
len, len);
+ if (len > current_atom_size - (j - i)) {
+ last_error = QT_NOT_A_VALID_FILE;
+ goto free_trak;
+ }
trak->decoder_config = realloc(trak->decoder_config, len);
trak->decoder_config_len = len;
+ if (!trak->decoder_config) {
+ last_error = QT_NO_MEMORY;
+ goto free_trak;
+ }
memcpy(trak->decoder_config,&trak_atom[j],len);
}
}
}
} else if (current_atom == AVCC_ATOM) {
-
+
debug_atom_load(" avcC atom\n");
-
+
trak->decoder_config_len = current_atom_size - 8;
trak->decoder_config = realloc(trak->decoder_config, trak->decoder_config_len);
memcpy(trak->decoder_config, &trak_atom[i + 4], trak->decoder_config_len);
-
+
} else if (current_atom == STSZ_ATOM) {
/* there should only be one of these atoms */
@@ -1331,8 +1391,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
/* allocate space and load table only if sample size is 0 */
if (trak->sample_size == 0) {
- trak->sample_size_table = (unsigned int *)malloc(
- trak->sample_size_count * sizeof(unsigned int));
+ trak->sample_size_table = (unsigned int *)calloc(
+ trak->sample_size_count, sizeof(unsigned int));
if (!trak->sample_size_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1362,8 +1422,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt stss atom (sample sync atom): %d sync samples\n",
trak->sync_sample_count);
- trak->sync_sample_table = (unsigned int *)malloc(
- trak->sync_sample_count * sizeof(unsigned int));
+ trak->sync_sample_table = (unsigned int *)calloc(
+ trak->sync_sample_count, sizeof(unsigned int));
if (!trak->sync_sample_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1391,8 +1451,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt stco atom (32-bit chunk offset atom): %d chunk offsets\n",
trak->chunk_offset_count);
- trak->chunk_offset_table = (int64_t *)malloc(
- trak->chunk_offset_count * sizeof(int64_t));
+ trak->chunk_offset_table = (int64_t *)calloc(
+ trak->chunk_offset_count, sizeof(int64_t));
if (!trak->chunk_offset_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1419,8 +1479,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt co64 atom (64-bit chunk offset atom): %d chunk offsets\n",
trak->chunk_offset_count);
- trak->chunk_offset_table = (int64_t *)malloc(
- trak->chunk_offset_count * sizeof(int64_t));
+ trak->chunk_offset_table = (int64_t *)calloc(
+ trak->chunk_offset_count, sizeof(int64_t));
if (!trak->chunk_offset_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1450,8 +1510,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt stsc atom (sample-to-chunk atom): %d entries\n",
trak->sample_to_chunk_count);
- trak->sample_to_chunk_table = (sample_to_chunk_table_t *)malloc(
- trak->sample_to_chunk_count * sizeof(sample_to_chunk_table_t));
+ trak->sample_to_chunk_table = (sample_to_chunk_table_t *)calloc(
+ trak->sample_to_chunk_count, sizeof(sample_to_chunk_table_t));
if (!trak->sample_to_chunk_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1475,7 +1535,8 @@ static qt_error parse_trak_atom (qt_trak *trak,
} else if (current_atom == STTS_ATOM) {
/* there should only be one of these atoms */
- if (trak->time_to_sample_table) {
+ if (trak->time_to_sample_table
+ || current_atom_size < 12 || current_atom_size >= UINT_MAX) {
last_error = QT_HEADER_TROUBLE;
goto free_trak;
}
@@ -1485,8 +1546,13 @@ static qt_error parse_trak_atom (qt_trak *trak,
debug_atom_load(" qt stts atom (time-to-sample atom): %d entries\n",
trak->time_to_sample_count);
- trak->time_to_sample_table = (time_to_sample_table_t *)malloc(
- (trak->time_to_sample_count+1) * sizeof(time_to_sample_table_t));
+ if (trak->time_to_sample_count > (current_atom_size - 12) / 8) {
+ last_error = QT_HEADER_TROUBLE;
+ goto free_trak;
+ }
+
+ trak->time_to_sample_table = (time_to_sample_table_t *)calloc(
+ trak->time_to_sample_count+1, sizeof(time_to_sample_table_t));
if (!trak->time_to_sample_table) {
last_error = QT_NO_MEMORY;
goto free_trak;
@@ -1537,44 +1603,51 @@ static qt_error parse_reference_atom (reference_t *ref,
qt_atom current_atom;
unsigned int current_atom_size;
+ if (ref_atom_size >= 0x80000000)
+ return QT_NOT_A_VALID_FILE;
+
/* initialize reference atom */
ref->url = NULL;
ref->data_rate = 0;
ref->qtim_version = 0;
/* traverse through the atom looking for the key atoms */
- for (i = ATOM_PREAMBLE_SIZE; i < ref_atom_size - 4; i++) {
+ for (i = ATOM_PREAMBLE_SIZE; i + 4 < ref_atom_size; i++) {
current_atom_size = _X_BE_32(&ref_atom[i - 4]);
current_atom = _X_BE_32(&ref_atom[i]);
if (current_atom == RDRF_ATOM) {
+ size_t string_size = _X_BE_32(&ref_atom[i + 12]);
+ size_t url_offset = 0;
+ int http = 0;
+
+ if (string_size >= current_atom_size || string_size >= ref_atom_size - i)
+ return QT_NOT_A_VALID_FILE;
/* if the URL starts with "http://", copy it */
- if (strncmp(&ref_atom[i + 16], "http://", 7) == 0
- || strncmp(&ref_atom[i + 16], "rtsp://", 7) == 0) {
+ if ( memcmp(&ref_atom[i + 16], "http://", 7) &&
+ memcmp(&ref_atom[i + 16], "rtsp://", 7) &&
+ base_mrl )
+ {
+ /* We need a "qt" prefix hack for Apple trailers */
+ http = !strncasecmp (base_mrl, "http://", 7);
+ url_offset = strlen(base_mrl) + 2 * http;
+ }
+ if (url_offset >= 0x80000000)
+ return QT_NOT_A_VALID_FILE;
- /* URL is spec'd to terminate with a NULL; don't trust it */
- ref->url = xine_xmalloc(_X_BE_32(&ref_atom[i + 12]) + 1);
- strncpy(ref->url, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12]));
- ref->url[_X_BE_32(&ref_atom[i + 12]) - 1] = '\0';
+ /* otherwise, append relative URL to base MRL */
+ string_size += url_offset;
- } else {
+ ref->url = xine_xmalloc(string_size + 1);
- int string_size;
+ if ( url_offset )
+ sprintf (ref->url, "%s%s", http ? "qt" : "", base_mrl);
- if (base_mrl)
- string_size = strlen(base_mrl) + _X_BE_32(&ref_atom[i + 12]) + 1;
- else
- string_size = _X_BE_32(&ref_atom[i + 12]) + 1;
+ memcpy(ref->url + url_offset, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12]));
- /* otherwise, append relative URL to base MRL */
- ref->url = xine_xmalloc(string_size);
- if (base_mrl)
- strcpy(ref->url, base_mrl);
- strncat(ref->url, &ref_atom[i + 16], _X_BE_32(&ref_atom[i + 12]));
- ref->url[string_size - 1] = '\0';
- }
+ ref->url[string_size] = '\0';
debug_atom_load(" qt rdrf URL reference:\n %s\n", ref->url);
@@ -1609,9 +1682,9 @@ static qt_error parse_reference_atom (reference_t *ref,
/* This is a little support function used to process the edit list when
* building a frame table. */
#define MAX_DURATION 0x7FFFFFFFFFFFFFFFLL
-static void get_next_edit_list_entry(qt_trak *trak,
+static void get_next_edit_list_entry(qt_trak *trak,
int *edit_list_index,
- unsigned int *edit_list_media_time,
+ unsigned int *edit_list_media_time,
int64_t *edit_list_duration,
unsigned int global_timescale) {
@@ -1628,9 +1701,9 @@ static void get_next_edit_list_entry(qt_trak *trak,
/* otherwise, find an edit list entries whose media time != -1 */
if (trak->edit_list_table[*edit_list_index].media_time != -1) {
- *edit_list_media_time =
+ *edit_list_media_time =
trak->edit_list_table[*edit_list_index].media_time;
- *edit_list_duration =
+ *edit_list_duration =
trak->edit_list_table[*edit_list_index].track_duration;
/* duration is in global timescale units; convert to trak timescale */
@@ -1644,8 +1717,8 @@ static void get_next_edit_list_entry(qt_trak *trak,
*edit_list_index = *edit_list_index + 1;
}
- /* on the way out, check if this is the last edit list entry; if so,
- * don't let the duration expire (so set it to an absurdly large value)
+ /* on the way out, check if this is the last edit list entry; if so,
+ * don't let the duration expire (so set it to an absurdly large value)
*/
if (*edit_list_index == trak->edit_list_count)
*edit_list_duration = MAX_DURATION;
@@ -1680,14 +1753,13 @@ static qt_error build_frame_table(qt_trak *trak,
/* AUDIO and OTHER frame types follow the same rules; VIDEO and vbr audio
* frame types follow a different set */
- if ((trak->type == MEDIA_VIDEO) ||
+ if ((trak->type == MEDIA_VIDEO) ||
(trak->properties->audio.vbr)) {
/* in this case, the total number of frames is equal to the number of
* entries in the sample size table */
trak->frame_count = trak->sample_size_count;
- trak->frames = (qt_frame *)malloc(
- trak->frame_count * sizeof(qt_frame));
+ trak->frames = (qt_frame *)calloc(trak->frame_count, sizeof(qt_frame));
if (!trak->frames)
return QT_NO_MEMORY;
trak->current_frame = 0;
@@ -1699,10 +1771,9 @@ static qt_error build_frame_table(qt_trak *trak,
pts_index_countdown =
trak->time_to_sample_table[pts_index].count;
- media_id_counts = xine_xmalloc(trak->stsd_atoms_count * sizeof(int));
+ media_id_counts = calloc(trak->stsd_atoms_count, sizeof(int));
if (!media_id_counts)
return QT_NO_MEMORY;
- memset(media_id_counts, 0, trak->stsd_atoms_count * sizeof(int));
/* iterate through each start chunk in the stsc table */
for (i = 0; i < trak->sample_to_chunk_count; i++) {
@@ -1732,7 +1803,7 @@ static qt_error build_frame_table(qt_trak *trak,
trak->stsd_atoms_count);
trak->frames[frame_counter].media_id = 0;
} else {
- trak->frames[frame_counter].media_id =
+ trak->frames[frame_counter].media_id =
trak->sample_to_chunk_table[i].media_id;
media_id_counts[trak->sample_to_chunk_table[i].media_id - 1]++;
}
@@ -1792,11 +1863,11 @@ static qt_error build_frame_table(qt_trak *trak,
debug_edit_list(" %d: (before) pts = %"PRId64"...", i, trak->frames[i].pts);
- if (trak->frames[i].pts < edit_list_media_time)
+ if (trak->frames[i].pts < edit_list_media_time)
trak->frames[i].pts = edit_list_pts_counter;
else {
if (i < trak->frame_count - 1)
- frame_duration =
+ frame_duration =
(trak->frames[i + 1].pts - trak->frames[i].pts);
debug_edit_list("duration = %"PRId64"...", frame_duration);
@@ -1837,8 +1908,7 @@ static qt_error build_frame_table(qt_trak *trak,
/* in this case, the total number of frames is equal to the number of
* chunks */
trak->frame_count = trak->chunk_offset_count;
- trak->frames = (qt_frame *)malloc(
- trak->frame_count * sizeof(qt_frame));
+ trak->frames = (qt_frame *)calloc(trak->frame_count, sizeof(qt_frame));
if (!trak->frames)
return QT_NO_MEMORY;
@@ -1876,7 +1946,7 @@ static qt_error build_frame_table(qt_trak *trak,
trak->stsd_atoms_count);
trak->frames[j].media_id = 0;
} else {
- trak->frames[j].media_id =
+ trak->frames[j].media_id =
trak->sample_to_chunk_table[i].media_id;
}
@@ -1941,10 +2011,10 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom,
/* create a new trak structure */
info->trak_count++;
- info->traks = (qt_trak *)realloc(info->traks,
+ info->traks = (qt_trak *)realloc(info->traks,
info->trak_count * sizeof(qt_trak));
- info->last_error = parse_trak_atom (&info->traks[info->trak_count - 1],
+ info->last_error = parse_trak_atom (&info->traks[info->trak_count - 1],
&moov_atom[i - 4]);
if (info->last_error != QT_OK) {
info->trak_count--;
@@ -1993,8 +2063,12 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom,
info->references = (reference_t *)realloc(info->references,
info->reference_count * sizeof(reference_t));
- parse_reference_atom(&info->references[info->reference_count - 1],
- &moov_atom[i - 4], info->base_mrl);
+ error = parse_reference_atom(&info->references[info->reference_count - 1],
+ &moov_atom[i - 4], info->base_mrl);
+ if (error != QT_OK) {
+ info->last_error = error;
+ return;
+ }
} else {
debug_atom_load(" qt: unknown atom into the moov atom (0x%08X)\n", current_atom);
@@ -2049,11 +2123,11 @@ static void parse_moov_atom(qt_info *info, unsigned char *moov_atom,
/* iterate through 1..n-1 reference entries and decide on the right one */
for (i = 1; i < info->reference_count; i++) {
- if (info->references[i].qtim_version >
+ if (info->references[i].qtim_version >
info->references[info->chosen_reference].qtim_version)
info->chosen_reference = i;
else if ((info->references[i].data_rate <= bandwidth) &&
- (info->references[i].data_rate >
+ (info->references[i].data_rate >
info->references[info->chosen_reference].data_rate))
info->chosen_reference = i;
}
@@ -2137,7 +2211,7 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input,
info->last_error = QT_FILE_READ_ERROR;
return info->last_error;
}
- if (input->read(input, moov_atom, moov_atom_size) !=
+ if (input->read(input, moov_atom, moov_atom_size) !=
moov_atom_size) {
free(moov_atom);
info->last_error = QT_FILE_READ_ERROR;
@@ -2145,7 +2219,7 @@ static qt_error open_qt_file(qt_info *info, input_plugin_t *input,
}
/* check if moov is compressed */
- if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM) {
+ if (_X_BE_32(&moov_atom[12]) == CMOV_ATOM && moov_atom_size >= 0x28) {
info->compressed_header = 1;
@@ -2268,12 +2342,12 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) {
/* if audio is present, send pts of current audio frame, otherwise
* send current video frame pts */
if (audio_trak)
- _x_demux_control_newpts(this->stream,
- audio_trak->frames[audio_trak->current_frame].pts,
+ _x_demux_control_newpts(this->stream,
+ audio_trak->frames[audio_trak->current_frame].pts,
BUF_FLAG_SEEK);
else
- _x_demux_control_newpts(this->stream,
- video_trak->frames[video_trak->current_frame].pts,
+ _x_demux_control_newpts(this->stream,
+ video_trak->frames[video_trak->current_frame].pts,
BUF_FLAG_SEEK);
}
@@ -2380,7 +2454,7 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) {
frame_duration);
debug_video_demux(" qt: sending off video frame %d from offset 0x%"PRIX64", %d bytes, media id %d, %"PRId64" pts\n",
- i,
+ i,
video_trak->frames[i].offset,
video_trak->frames[i].size,
video_trak->frames[i].media_id,
@@ -2438,7 +2512,7 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) {
SEEK_SET);
debug_audio_demux(" qt: sending off audio frame %d from offset 0x%"PRIX64", %d bytes, media id %d, %"PRId64" pts\n",
- i,
+ i,
audio_trak->frames[i].offset,
audio_trak->frames[i].size,
audio_trak->frames[i].media_id,
@@ -2457,8 +2531,8 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) {
* turns around and sends out audio buffers as soon as they are
* received. If 2 or more consecutive audio buffers are dispatched to
* the audio out unit, the engine will compensate with pops. */
- if ((buf->type == BUF_AUDIO_LPCM_BE) ||
- (buf->type == BUF_AUDIO_LPCM_LE)) {
+ if ((buf->type == BUF_AUDIO_LPCM_BE) ||
+ (buf->type == BUF_AUDIO_LPCM_LE)) {
if (first_buf) {
buf->extra_info->input_time = audio_trak->frames[i].pts / 90;
buf->pts = audio_trak->frames[i].pts;
@@ -2487,7 +2561,7 @@ static int demux_qt_send_chunk(demux_plugin_t *this_gen) {
/* Special case alert: If this is signed, 8-bit data, transform
* the data to unsigned. */
- if ((audio_trak->properties->audio.bits == 8) &&
+ if ((audio_trak->properties->audio.bits == 8) &&
((audio_trak->properties->audio.codec_fourcc == TWOS_FOURCC) ||
(audio_trak->properties->audio.codec_fourcc == SOWT_FOURCC)))
for (j = 0; j < buf->size; j++)
@@ -2556,7 +2630,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
this->bih.biBitCount = video_trak->properties->video.depth;
this->bih.biCompression = video_trak->properties->video.codec_fourcc;
- video_trak->properties->video.codec_buftype =
+ video_trak->properties->video.codec_buftype =
_x_fourcc_to_buf_video(this->bih.biCompression);
/* hack: workaround a fourcc clash! 'mpg4' is used by MS and Sorenson
@@ -2564,13 +2638,13 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
*/
if( video_trak->properties->video.codec_buftype == BUF_VIDEO_MSMPEG4_V1 )
video_trak->properties->video.codec_buftype = BUF_VIDEO_MPEG4;
-
- if( !video_trak->properties->video.codec_buftype &&
+
+ if( !video_trak->properties->video.codec_buftype &&
video_trak->properties->video.codec_fourcc )
video_trak->properties->video.codec_buftype = BUF_VIDEO_UNKNOWN;
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,
this->bih.biWidth);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_HEIGHT,
this->bih.biHeight);
@@ -2603,7 +2677,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
break;
}
} else {
- audio_trak->properties->audio.codec_buftype =
+ audio_trak->properties->audio.codec_buftype =
_x_formattag_to_buf_audio(audio_trak->properties->audio.codec_fourcc);
}
@@ -2618,7 +2692,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
audio_trak->properties->audio.sample_rate);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_BITS,
audio_trak->properties->audio.bits);
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC,
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC,
audio_trak->properties->audio.codec_fourcc);
} else {
@@ -2659,17 +2733,17 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
(video_trak->properties->video.codec_buftype)) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER|BUF_FLAG_FRAME_END;
-
+
memcpy(buf->content, &this->bih, sizeof(this->bih));
buf->size = sizeof(this->bih);
buf->type = video_trak->properties->video.codec_buftype;
this->video_fifo->put (this->video_fifo, buf);
-
+
/* send header info to decoder. some mpeg4 streams need this */
if( video_trak->decoder_config ) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = video_trak->properties->video.codec_buftype;
-
+
if (video_trak->properties->video.codec_fourcc == AVC1_FOURCC) {
buf->size = 0;
buf->decoder_flags = BUF_FLAG_SPECIAL|BUF_FLAG_HEADER;
@@ -2713,9 +2787,9 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
/* set the audio bitrate field (only for CBR audio) */
if (!audio_trak->properties->audio.vbr) {
- audio_bitrate =
+ audio_bitrate =
audio_trak->properties->audio.sample_rate /
- audio_trak->properties->audio.samples_per_frame *
+ audio_trak->properties->audio.samples_per_frame *
audio_trak->properties->audio.bytes_per_frame *
audio_trak->properties->audio.channels *
8;
@@ -2730,7 +2804,7 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
buf->decoder_info[1] = audio_trak->properties->audio.sample_rate;
buf->decoder_info[2] = audio_trak->properties->audio.bits;
buf->decoder_info[3] = audio_trak->properties->audio.channels;
-
+
if( audio_trak->properties->audio.wave_size ) {
if( audio_trak->properties->audio.wave_size > buf->max_size )
buf->size = buf->max_size;
@@ -2741,9 +2815,9 @@ static void demux_qt_send_headers(demux_plugin_t *this_gen) {
buf->size = 0;
buf->content = NULL;
}
-
+
this->audio_fifo->put (this->audio_fifo, buf);
-
+
if( audio_trak->decoder_config ) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = audio_trak->properties->audio.codec_buftype;
@@ -2836,7 +2910,7 @@ static int demux_qt_seek (demux_plugin_t *this_gen,
qt_trak *video_trak = NULL;
qt_trak *audio_trak = NULL;
int64_t keyframe_pts;
-
+
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
@@ -2944,7 +3018,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_qt_t));
+ this = calloc(1, sizeof(demux_qt_t));
this->stream = stream;
this->input = input;
@@ -3059,7 +3133,9 @@ 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;"
- "application/x-quicktimeplayer: qtl: Quicktime list;";
+ "application/x-quicktimeplayer: qtl: Quicktime list;"
+ "video/mp4: mp4,mpg4: MPEG-4 video;"
+ "audio/mp4: mp4,mpg4: MPEG-4 audio;";
}
static void class_dispose (demux_class_t *this_gen) {
@@ -3073,7 +3149,7 @@ static void *init_plugin (xine_t *xine, void *data) {
demux_qt_class_t *this;
- this = xine_xmalloc (sizeof (demux_qt_class_t));
+ this = calloc(1, sizeof(demux_qt_class_t));
this->config = xine->config;
this->xine = xine;
@@ -3095,7 +3171,7 @@ static const demuxer_info_t demux_info_qt = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "quicktime", XINE_VERSION_CODE, &demux_info_qt, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_rawdv.c b/src/demuxers/demux_rawdv.c
index 2d21f080d..968542057 100644
--- a/src/demuxers/demux_rawdv.c
+++ b/src/demuxers/demux_rawdv.c
@@ -1,18 +1,18 @@
/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -89,17 +89,17 @@ static int demux_raw_dv_next (demux_raw_dv_t *this) {
/* TODO: duplicate data and send to audio fifo.
* however we don't have dvaudio decoder yet.
*/
-
+
buf->pts = this->pts;
buf->extra_info->input_time = this->pts/90;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->extra_info->frame_number = this->cur_frame;
buf->type = BUF_VIDEO_DV;
-
+
this->video_fifo->put(this->video_fifo, buf);
-
+
if (this->audio_fifo) {
abuf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
abuf->content = abuf->mem;
@@ -213,11 +213,11 @@ static void demux_raw_dv_send_headers (demux_plugin_t *this_gen) {
bih->biSizeImage = bih->biWidth*bih->biHeight;
this->video_fifo->put(this->video_fifo, buf);
-
+
this->pts = 0;
this->cur_frame = 0;
this->bytes_left = this->frame_size;
-
+
this->status = DEMUX_OK;
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
@@ -302,20 +302,21 @@ static int demux_raw_dv_seek (demux_plugin_t *this_gen,
}
if( !start_pos && start_time ) {
- start_pos = (start_time * 90 / this->duration) * this->frame_size;
+ /* Upcast start_time in case sizeof(off_t) > sizeof(int) */
+ start_pos = ((off_t) start_time * 90 / this->duration) * this->frame_size;
}
-
- start_pos = start_pos - (start_pos % this->frame_size);
+
+ start_pos = start_pos - (start_pos % this->frame_size);
this->input->seek(this->input, start_pos, SEEK_SET);
this->cur_frame = start_pos / this->frame_size;
this->pts = this->cur_frame * this->duration;
this->bytes_left = this->frame_size;
-
+
_x_demux_flush_engine (this->stream);
_x_demux_control_newpts (this->stream, this->pts, BUF_FLAG_SEEK);
-
+
this->status = DEMUX_OK;
return this->status;
}
@@ -347,7 +348,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_raw_dv_t *this;
- this = xine_xmalloc (sizeof (demux_raw_dv_t));
+ this = calloc(1, sizeof(demux_raw_dv_t));
this->stream = stream;
this->input = input;
@@ -367,15 +368,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
case METHOD_BY_CONTENT: {
uint8_t buf[8];
-
+
if (_x_demux_read_header(input, buf, 8) != 8) {
free (this);
return NULL;
}
/* DIF (DV) movie file */
- if (!((buf[0] == 0x1f) && (buf[1] == 0x07) && (buf[2] == 00) &&
- (buf[4] ^ 0x01))) {
+ if (memcmp(buf, "\x1F\x07\x00", 3) != 0 || !(buf[4] ^ 0x01)) {
free (this);
return NULL;
}
@@ -436,7 +436,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_raw_dv_class_t *this;
- this = xine_xmalloc (sizeof (demux_raw_dv_class_t));
+ this = calloc(1, sizeof(demux_raw_dv_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_real.c b/src/demuxers/demux_real.c
index 85d7dc5a3..340083221 100644
--- a/src/demuxers/demux_real.c
+++ b/src/demuxers/demux_real.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2005 the xine project
+ * Copyright (C) 2000-2008 the xine project
*
* This file is part of xine, a free video player.
*
@@ -26,9 +26,9 @@
*
* video packet sub-demuxer ported from mplayer code (www.mplayerhq.hu):
* Real parser & demuxer
- *
+ *
* (C) Alex Beregszaszi <alex@naxine.org>
- *
+ *
* Based on FFmpeg's libav/rm.c.
*/
@@ -42,6 +42,9 @@
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
+#ifdef HAVE_MALLOC_H
+#include <malloc.h>
+#endif
#define LOG_MODULE "demux_real"
#define LOG_VERBOSE
@@ -55,13 +58,13 @@
#include "demux.h"
#include "bswap.h"
+#include "real_common.h"
+
#define FOURCC_TAG BE_FOURCC
-#define RMF_TAG FOURCC_TAG('.', 'R', 'M', 'F')
#define PROP_TAG FOURCC_TAG('P', 'R', 'O', 'P')
#define MDPR_TAG FOURCC_TAG('M', 'D', 'P', 'R')
#define CONT_TAG FOURCC_TAG('C', 'O', 'N', 'T')
#define DATA_TAG FOURCC_TAG('D', 'A', 'T', 'A')
-#define INDX_TAG FOURCC_TAG('I', 'N', 'D', 'X')
#define RA_TAG FOURCC_TAG('.', 'r', 'a', 0xfd)
#define VIDO_TAG FOURCC_TAG('V', 'I', 'D', 'O')
@@ -90,11 +93,11 @@ typedef struct {
uint32_t start_time;
uint32_t preroll;
uint32_t duration;
- char stream_name_size;
+ size_t stream_name_size;
char *stream_name;
- char mime_type_size;
+ size_t mime_type_size;
char *mime_type;
- uint32_t type_specific_len;
+ size_t type_specific_len;
char *type_specific_data;
} mdpr_t;
@@ -108,11 +111,17 @@ typedef struct {
uint32_t fourcc;
uint32_t buf_type;
uint32_t format;
-
+
real_index_entry_t *index;
int index_entries;
-
+
mdpr_t *mdpr;
+ int sps, cfs, w, h;
+ int block_align;
+ size_t frame_size;
+ uint8_t *frame_buffer;
+ uint32_t frame_num_bytes;
+ uint32_t sub_packet_cnt;
} real_stream_t;
typedef struct {
@@ -150,7 +159,7 @@ typedef struct {
int64_t last_pts[2];
int send_newpts;
int buf_flag_seek;
-
+
uint32_t last_ts;
uint32_t next_ts;
int last_seq;
@@ -168,16 +177,14 @@ typedef struct {
demux_class_t demux_class;
} demux_real_class_t;
-
static void real_parse_index(demux_real_t *this) {
off_t next_index_chunk = this->index_start;
off_t original_pos = this->input->get_current_pos(this->input);
unsigned char index_chunk_header[INDEX_CHUNK_HEADER_SIZE];
unsigned char index_record[INDEX_RECORD_SIZE];
- int i, entries, stream_num;
- real_index_entry_t **index;
-
+ int i;
+
while(next_index_chunk) {
lprintf("reading index chunk at %"PRIX64"\n", next_index_chunk);
@@ -192,69 +199,68 @@ static void real_parse_index(demux_real_t *this) {
}
/* Check chunk is actually an index chunk */
- if(_X_BE_32(&index_chunk_header[0]) == INDX_TAG) {
- unsigned short version;
+ if(!_x_is_fourcc(&index_chunk_header[0], "INDX")) {
+ lprintf("expected index chunk found chunk type: %.4s\n", &index_chunk_header[0]);
+ break;
+ }
- /* Check version */
- version = _X_BE_16(&index_chunk_header[8]);
- if(version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: unknown object version in INDX: 0x%04x\n", version);
- break;
- }
+ /* Check version */
+ const uint16_t version = _X_BE_16(&index_chunk_header[8]);
+ if(version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: unknown object version in INDX: 0x%04x\n", version);
+ break;
+ }
- /* Read data from header */
- entries = _X_BE_32(&index_chunk_header[10]);
- stream_num = _X_BE_16(&index_chunk_header[14]);
- next_index_chunk = _X_BE_32(&index_chunk_header[16]);
-
- /* Find which stream this index is for */
- index = NULL;
- for(i = 0; i < this->num_video_streams; i++) {
- if(stream_num == this->video_streams[i].mdpr->stream_number) {
- index = &this->video_streams[i].index;
- this->video_streams[i].index_entries = entries;
- lprintf("found index chunk for video stream with num %d\n", stream_num);
- break;
- }
+ /* Read data from header */
+ const uint32_t entries = _X_BE_32(&index_chunk_header[10]);
+ const uint16_t stream_num = _X_BE_16(&index_chunk_header[14]);
+ next_index_chunk = _X_BE_32(&index_chunk_header[16]);
+
+ /* Find which stream this index is for */
+ real_index_entry_t **index = NULL;
+ for(i = 0; i < this->num_video_streams; i++) {
+ if(stream_num == this->video_streams[i].mdpr->stream_number) {
+ index = &this->video_streams[i].index;
+ this->video_streams[i].index_entries = entries;
+ lprintf("found index chunk for video stream with num %d\n", stream_num);
+ break;
}
+ }
- if(!index) {
- for(i = 0; i < this->num_audio_streams; i++) {
- if(stream_num == this->audio_streams[i].mdpr->stream_number) {
- index = &this->audio_streams[i].index;
- this->audio_streams[i].index_entries = entries;
- lprintf("found index chunk for audio stream with num %d\n", stream_num);
- break;
- }
- }
+ if(!index) {
+ for(i = 0; i < this->num_audio_streams; i++) {
+ if(stream_num == this->audio_streams[i].mdpr->stream_number) {
+ index = &this->audio_streams[i].index;
+ this->audio_streams[i].index_entries = entries;
+ lprintf("found index chunk for audio stream with num %d\n", stream_num);
+ break;
+ }
}
+ }
- if(index && entries) {
- /* Allocate memory for index */
- *index = xine_xmalloc(entries * sizeof(real_index_entry_t));
-
- /* Read index */
- for(i = 0; i < entries; i++) {
- if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE)
- != INDEX_RECORD_SIZE) {
- lprintf("index record not read\n");
- free(*index);
- *index = NULL;
- break;
- }
-
- (*index)[i].timestamp = _X_BE_32(&index_record[2]);
- (*index)[i].offset = _X_BE_32(&index_record[6]);
- (*index)[i].packetno = _X_BE_32(&index_record[10]);
- }
- } else {
- lprintf("unused index chunk with %d entries for stream num %d\n",
- entries, stream_num);
+ if(index && entries)
+ /* Allocate memory for index */
+ *index = calloc(entries, sizeof(real_index_entry_t));
+
+ if(index && entries && *index) {
+ /* Read index */
+ for(i = 0; i < entries; i++) {
+ if(this->input->read(this->input, index_record, INDEX_RECORD_SIZE)
+ != INDEX_RECORD_SIZE) {
+ lprintf("index record not read\n");
+ free(*index);
+ *index = NULL;
+ break;
+ }
+
+ (*index)[i].timestamp = _X_BE_32(&index_record[2]);
+ (*index)[i].offset = _X_BE_32(&index_record[6]);
+ (*index)[i].packetno = _X_BE_32(&index_record[10]);
}
} else {
- lprintf("expected index chunk found chunk type: %.4s\n", &index_chunk_header[0]);
- break;
+ lprintf("unused index chunk with %d entries for stream num %d\n",
+ entries, stream_num);
}
}
@@ -262,8 +268,12 @@ static void real_parse_index(demux_real_t *this) {
this->input->seek(this->input, original_pos, SEEK_SET);
}
-static mdpr_t *real_parse_mdpr(const char *data) {
- mdpr_t *mdpr=malloc(sizeof(mdpr_t));
+static mdpr_t *real_parse_mdpr(const char *data, const unsigned int size)
+{
+ if (size < 38)
+ return NULL;
+
+ mdpr_t *mdpr=calloc(sizeof(mdpr_t), 1);
mdpr->stream_number=_X_BE_16(&data[2]);
mdpr->max_bit_rate=_X_BE_32(&data[4]);
@@ -275,17 +285,29 @@ static mdpr_t *real_parse_mdpr(const char *data) {
mdpr->duration=_X_BE_32(&data[28]);
mdpr->stream_name_size=data[32];
- mdpr->stream_name=malloc(sizeof(char)*(mdpr->stream_name_size+1));
+ if (size < 38 + mdpr->stream_name_size)
+ goto fail;
+ mdpr->stream_name=malloc(mdpr->stream_name_size+1);
+ if (!mdpr->stream_name)
+ goto fail;
memcpy(mdpr->stream_name, &data[33], mdpr->stream_name_size);
mdpr->stream_name[(int)mdpr->stream_name_size]=0;
mdpr->mime_type_size=data[33+mdpr->stream_name_size];
- mdpr->mime_type=malloc(sizeof(char)*(mdpr->mime_type_size+1));
+ if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size)
+ goto fail;
+ mdpr->mime_type=malloc(mdpr->mime_type_size+1);
+ if (!mdpr->mime_type)
+ goto fail;
memcpy(mdpr->mime_type, &data[34+mdpr->stream_name_size], mdpr->mime_type_size);
mdpr->mime_type[(int)mdpr->mime_type_size]=0;
mdpr->type_specific_len=_X_BE_32(&data[34+mdpr->stream_name_size+mdpr->mime_type_size]);
- mdpr->type_specific_data=malloc(sizeof(char)*(mdpr->type_specific_len));
+ if (size < 38 + mdpr->stream_name_size + mdpr->mime_type_size + mdpr->type_specific_data)
+ goto fail;
+ mdpr->type_specific_data=malloc(mdpr->type_specific_len);
+ if (!mdpr->type_specific_data)
+ goto fail;
memcpy(mdpr->type_specific_data,
&data[38+mdpr->stream_name_size+mdpr->mime_type_size], mdpr->type_specific_len);
@@ -305,6 +327,13 @@ static mdpr_t *real_parse_mdpr(const char *data) {
#endif
return mdpr;
+
+fail:
+ free (mdpr->stream_name);
+ free (mdpr->mime_type);
+ free (mdpr->type_specific_data);
+ free (mdpr);
+ return NULL;
}
static void real_free_mdpr (mdpr_t *mdpr) {
@@ -314,43 +343,109 @@ static void real_free_mdpr (mdpr_t *mdpr) {
free (mdpr);
}
+static void real_parse_audio_specific_data (demux_real_t *this,
+ real_stream_t * stream)
+{
+ if (stream->mdpr->type_specific_len < 46) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_real: audio data size smaller than header length!\n");
+ return;
+ }
+
+ uint8_t * data = stream->mdpr->type_specific_data;
+ const uint32_t coded_frame_size = _X_BE_32 (data+24);
+ const uint16_t codec_data_length = _X_BE_16 (data+40);
+ const uint16_t coded_frame_size2 = _X_BE_16 (data+42);
+ const uint16_t subpacket_size = _X_BE_16 (data+44);
+
+ stream->sps = subpacket_size;
+ stream->w = coded_frame_size2;
+ stream->h = codec_data_length;
+ stream->block_align = coded_frame_size2;
+ stream->cfs = coded_frame_size;
+
+ switch (stream->buf_type) {
+ case BUF_AUDIO_COOK:
+ case BUF_AUDIO_ATRK:
+ stream->block_align = subpacket_size;
+ break;
+
+ case BUF_AUDIO_14_4:
+ break;
+
+ case BUF_AUDIO_28_8:
+ stream->block_align = stream->cfs;
+ break;
+
+ case BUF_AUDIO_SIPRO:
+ /* this->block_align = 19; */
+ break;
+
+ default:
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: error, i don't handle buf type 0x%08x\n", stream->buf_type);
+ }
+
+ /*
+ * when stream->sps is set it used to do this:
+ * stream->frame_size = stream->w / stream->sps * stream->h * stream->sps;
+ * but it looks pointless? the compiler will probably optimise it away, I suppose?
+ */
+ if (stream->w < 32768 && stream->h < 32768) {
+ stream->frame_size = stream->w * stream->h;
+ stream->frame_buffer = calloc(stream->frame_size, 1);
+ } else {
+ stream->frame_size = 0;
+ stream->frame_buffer = NULL;
+ }
+
+ stream->frame_num_bytes = 0;
+ stream->sub_packet_cnt = 0;
+
+ if (!stream->frame_buffer)
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_real: failed to allocate the audio frame buffer!\n");
+
+ xprintf (this->stream->xine, XINE_VERBOSITY_LOG,
+ "demux_real: buf type 0x%08x frame size %zu block align %d\n", stream->buf_type,
+ stream->frame_size, stream->block_align);
+
+}
static void real_parse_headers (demux_real_t *this) {
char preamble[PREAMBLE_SIZE];
unsigned int chunk_type = 0;
unsigned int chunk_size;
- unsigned short version;
- unsigned char *chunk_buffer;
- int field_size;
- int stream_ptr;
- unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
- unsigned char signature[REAL_SIGNATURE_SIZE];
-
- this->data_start = 0;
- this->data_size = 0;
- this->num_video_streams = 0;
- this->num_audio_streams = 0;
if (INPUT_IS_SEEKABLE(this->input))
this->input->seek (this->input, 0, SEEK_SET);
- if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) !=
- REAL_SIGNATURE_SIZE) {
+ {
+ uint8_t signature[REAL_SIGNATURE_SIZE];
+ if (this->input->read(this->input, signature, REAL_SIGNATURE_SIZE) !=
+ REAL_SIGNATURE_SIZE) {
- lprintf ("signature not read\n");
- this->status = DEMUX_FINISHED;
- return;
- }
+ lprintf ("signature not read\n");
+ this->status = DEMUX_FINISHED;
+ return;
+ }
- if (_X_BE_32(signature) != RMF_TAG) {
- this->status = DEMUX_FINISHED;
- lprintf ("signature not found '%.4s'\n", signature);
- return;
+ if ( !_x_is_fourcc(signature, ".RMF") ) {
+ this->status = DEMUX_FINISHED;
+ lprintf ("signature not found '%.4s'\n", signature);
+ return;
+ }
+
+ /* skip to the start of the first chunk and start traversing */
+ chunk_size = _X_BE_32(&signature[4]);
}
- /* skip to the start of the first chunk and start traversing */
- chunk_size = _X_BE_32(&signature[4]);
+ this->data_start = 0;
+ this->data_size = 0;
+ this->num_video_streams = 0;
+ this->num_audio_streams = 0;
+
this->input->seek(this->input, chunk_size-8, SEEK_CUR);
/* iterate through chunks and gather information until the first DATA
@@ -371,179 +466,198 @@ static void real_parse_headers (demux_real_t *this) {
case PROP_TAG:
case MDPR_TAG:
case CONT_TAG:
+ {
+ if (chunk_size < PREAMBLE_SIZE+1) {
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+ chunk_size -= PREAMBLE_SIZE;
+ uint8_t *const chunk_buffer = malloc(chunk_size);
+ if (! chunk_buffer ||
+ this->input->read(this->input, chunk_buffer, chunk_size) !=
+ chunk_size) {
+ free (chunk_buffer);
+ this->status = DEMUX_FINISHED;
+ return;
+ }
- chunk_size -= PREAMBLE_SIZE;
- chunk_buffer = xine_xmalloc(chunk_size);
- if (this->input->read(this->input, chunk_buffer, chunk_size) !=
- chunk_size) {
- free (chunk_buffer);
- this->status = DEMUX_FINISHED;
- return;
- }
-
- version = _X_BE_16(&chunk_buffer[0]);
-
- if (chunk_type == PROP_TAG) {
-
- if(version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demuxe_real: unknown object version in PROP: 0x%04x\n", version);
- free(chunk_buffer);
- this->status = DEMUX_FINISHED;
- return;
- }
-
- this->duration = _X_BE_32(&chunk_buffer[22]);
- this->index_start = _X_BE_32(&chunk_buffer[30]);
- this->data_start = _X_BE_32(&chunk_buffer[34]);
- this->avg_bitrate = _X_BE_32(&chunk_buffer[6]);
-
- lprintf("PROP: duration: %d ms\n", this->duration);
- 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;
-
- _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE,
- this->avg_bitrate);
-
- } else if (chunk_type == MDPR_TAG) {
+ uint16_t version = _X_BE_16(&chunk_buffer[0]);
- mdpr_t *mdpr;
- uint32_t fourcc;
+ if (chunk_type == PROP_TAG) {
- if (version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: unknown object version in MDPR: 0x%04x\n", version);
- free(chunk_buffer);
- continue;
- }
-
- mdpr = real_parse_mdpr (chunk_buffer);
+ if(version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demuxe_real: unknown object version in PROP: 0x%04x\n", version);
+ free(chunk_buffer);
+ this->status = DEMUX_FINISHED;
+ return;
+ }
- lprintf ("parsing type specific data...\n");
+ this->duration = _X_BE_32(&chunk_buffer[22]);
+ this->index_start = _X_BE_32(&chunk_buffer[30]);
+ this->data_start = _X_BE_32(&chunk_buffer[34]);
+ this->avg_bitrate = _X_BE_32(&chunk_buffer[6]);
- if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) {
- int version, len;
+ lprintf("PROP: duration: %d ms\n", this->duration);
+ 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->num_audio_streams == MAX_AUDIO_STREAMS) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: maximum number of audio stream exceeded\n");
- goto unknown;
- }
-
- version = _X_BE_16(mdpr->type_specific_data + 4);
+ if (this->avg_bitrate<1)
+ this->avg_bitrate = 1;
- lprintf("audio version %d detected\n", version);
+ _x_stream_info_set(this->stream, XINE_STREAM_INFO_BITRATE,
+ this->avg_bitrate);
- switch(version) {
+ } else if (chunk_type == MDPR_TAG) {
+ if (version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: unknown object version in MDPR: 0x%04x\n", version);
+ free(chunk_buffer);
+ continue;
+ }
+
+ mdpr_t *const mdpr = real_parse_mdpr (chunk_buffer, chunk_size);
+
+ lprintf ("parsing type specific data...\n");
+ if (!mdpr) {
+ free (chunk_buffer);
+ this->status = DEMUX_FINISHED;
+ return;
+ }
+ if(!strcmp(mdpr->mime_type, "audio/X-MP3-draft-00")) {
+ lprintf ("mpeg layer 3 audio detected...\n");
+
+ static const uint32_t fourcc = ME_FOURCC('a', 'd', 'u', 0x55);
+ this->audio_streams[this->num_audio_streams].fourcc = fourcc;
+ this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
+ this->audio_streams[this->num_audio_streams].index = NULL;
+ this->audio_streams[this->num_audio_streams].mdpr = mdpr;
+ this->num_audio_streams++;
+ } else if(_X_BE_32(mdpr->type_specific_data) == RA_TAG &&
+ mdpr->type_specific_len >= 6) {
+ if(this->num_audio_streams == MAX_AUDIO_STREAMS) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: maximum number of audio stream exceeded\n");
+ goto unknown;
+ }
+
+ const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4);
+
+ lprintf("audio version %d detected\n", version);
+
+ char *fourcc_ptr = "\0\0\0";
+ switch(version) {
case 3:
- /* Version 3 header stores fourcc after meta info - cheat by reading backwards from the
+ /* Version 3 header stores fourcc after meta info - cheat by reading backwards from the
* end of the header instead of having to parse it all */
- fourcc = _X_ME_32(mdpr->type_specific_data + mdpr->type_specific_len - 5);
+ if (mdpr->type_specific_len >= 5)
+ fourcc_ptr = mdpr->type_specific_data + mdpr->type_specific_len - 5;
break;
- case 4:
- len = *(mdpr->type_specific_data + 56);
- fourcc = _X_ME_32(mdpr->type_specific_data + 58 + len);
+ case 4: {
+ if (mdpr->type_specific_len >= 57) {
+ const uint8_t len = *(mdpr->type_specific_data + 56);
+ if (mdpr->type_specific_len >= 62 + len)
+ fourcc_ptr = mdpr->type_specific_data + 58 + len;
+ }
+ }
break;
case 5:
- fourcc = _X_ME_32(mdpr->type_specific_data + 66);
+ if (mdpr->type_specific_len >= 70)
+ fourcc_ptr = mdpr->type_specific_data + 66;
break;
default:
lprintf("unsupported audio header version %d\n", version);
goto unknown;
- }
-
- lprintf("fourcc = %.4s\n", (char *) &fourcc);
-
- this->audio_streams[this->num_audio_streams].fourcc = fourcc;
- this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
- this->audio_streams[this->num_audio_streams].index = NULL;
- this->audio_streams[this->num_audio_streams].mdpr = mdpr;
-
- this->num_audio_streams++;
-
- } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG) {
-
- if(this->num_video_streams == MAX_VIDEO_STREAMS) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: maximum number of video stream exceeded\n");
- goto unknown;
- }
-
- lprintf ("video detected\n");
- fourcc = _X_ME_32(mdpr->type_specific_data + 8);
- lprintf("fourcc = %.4s\n", (char *) &fourcc);
-
- this->video_streams[this->num_video_streams].fourcc = fourcc;
- this->video_streams[this->num_video_streams].buf_type = _x_fourcc_to_buf_video(fourcc);
- this->video_streams[this->num_video_streams].format = _X_BE_32(mdpr->type_specific_data + 30);
- this->video_streams[this->num_video_streams].index = NULL;
- this->video_streams[this->num_video_streams].mdpr = mdpr;
-
- this->num_video_streams++;
-
- } else {
- lprintf("unrecognised type specific data\n");
-
-unknown:
- real_free_mdpr(mdpr);
- }
-
- } else if (chunk_type == CONT_TAG) {
-
- if(version != 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: unknown object version in CONT: 0x%04x\n", version);
- free(chunk_buffer);
- continue;
- }
+ }
+ lprintf("fourcc = %.4s\n", fourcc_ptr);
+
+ const uint32_t fourcc = _X_ME_32(fourcc_ptr);
+
+ this->audio_streams[this->num_audio_streams].fourcc = fourcc;
+ this->audio_streams[this->num_audio_streams].buf_type = _x_formattag_to_buf_audio(fourcc);
+ this->audio_streams[this->num_audio_streams].index = NULL;
+ this->audio_streams[this->num_audio_streams].mdpr = mdpr;
+
+ real_parse_audio_specific_data (this,
+ &this->audio_streams[this->num_audio_streams]);
+ this->num_audio_streams++;
+
+ } else if(_X_BE_32(mdpr->type_specific_data + 4) == VIDO_TAG &&
+ mdpr->type_specific_len >= 34) {
+
+ if(this->num_video_streams == MAX_VIDEO_STREAMS) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: maximum number of video stream exceeded\n");
+ goto unknown;
+ }
+
+ lprintf ("video detected\n");
+ const uint32_t fourcc = _X_ME_32(mdpr->type_specific_data + 8);
+ lprintf("fourcc = %.4s\n", (char *) &fourcc);
+
+ this->video_streams[this->num_video_streams].fourcc = fourcc;
+ this->video_streams[this->num_video_streams].buf_type = _x_fourcc_to_buf_video(fourcc);
+ this->video_streams[this->num_video_streams].format = _X_BE_32(mdpr->type_specific_data + 30);
+ this->video_streams[this->num_video_streams].index = NULL;
+ this->video_streams[this->num_video_streams].mdpr = mdpr;
+
+ this->num_video_streams++;
+
+ } else {
+ lprintf("unrecognised type specific data\n");
+
+ unknown:
+ real_free_mdpr(mdpr);
+ }
+
+ } else if (chunk_type == CONT_TAG) {
+
+ if(version != 0) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: unknown object version in CONT: 0x%04x\n", version);
+ free(chunk_buffer);
+ continue;
+ }
+
+ int stream_ptr = 2;
+#define SET_METADATA_STRING(type) \
+ do { \
+ const uint16_t field_size = _X_BE_16(&chunk_buffer[stream_ptr]); \
+ stream_ptr += 2; \
+ _x_meta_info_n_set(this->stream, type, \
+ &chunk_buffer[stream_ptr], field_size); \
+ stream_ptr += field_size; \
+ } while(0)
+
+ /* load the title string */
+ SET_METADATA_STRING(XINE_META_INFO_TITLE);
+
+ /* load the author string */
+ SET_METADATA_STRING(XINE_META_INFO_ARTIST);
+
+ /* load the copyright string as the year */
+ SET_METADATA_STRING(XINE_META_INFO_YEAR);
+
+ /* load the comment string */
+ SET_METADATA_STRING(XINE_META_INFO_COMMENT);
+ }
- stream_ptr = 2;
-
- /* load the title string */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
-
- /* load the author string */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
-
- /* load the copyright string as the year */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
-
- /* load the comment string */
- field_size = _X_BE_16(&chunk_buffer[stream_ptr]);
- stream_ptr += 2;
- _x_meta_info_n_set(this->stream, XINE_META_INFO_COMMENT,
- &chunk_buffer[stream_ptr], field_size);
- stream_ptr += field_size;
+ free(chunk_buffer);
}
-
- free(chunk_buffer);
break;
- case DATA_TAG:
- if (this->input->read(this->input, data_chunk_header,
+ case DATA_TAG: {
+ uint8_t data_chunk_header[DATA_CHUNK_HEADER_SIZE];
+
+ if (this->input->read(this->input, data_chunk_header,
DATA_CHUNK_HEADER_SIZE) != DATA_CHUNK_HEADER_SIZE) {
this->status = DEMUX_FINISHED;
return ;
}
-
+
/* check version */
- version = _X_BE_16(&data_chunk_header[0]);
+ const uint16_t version = _X_BE_16(&data_chunk_header[0]);
if(version != 0) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: unknown object version in DATA: 0x%04x\n", version);
@@ -554,7 +668,8 @@ unknown:
this->current_data_chunk_packet_count = _X_BE_32(&data_chunk_header[2]);
this->next_data_chunk_offset = _X_BE_32(&data_chunk_header[6]);
this->data_chunk_size = chunk_size;
- break;
+ }
+ break;
default:
/* this should not occur, but in case it does, skip the chunk */
@@ -568,17 +683,10 @@ unknown:
/* Read index tables */
if(INPUT_IS_SEEKABLE(this->input))
real_parse_index(this);
-
+
/* Simple stream selection case - 0/1 audio/video streams */
- if(this->num_video_streams == 1)
- this->video_stream = &this->video_streams[0];
- else
- this->video_stream = NULL;
-
- if(this->num_audio_streams == 1)
- this->audio_stream = &this->audio_streams[0];
- else
- this->audio_stream = NULL;
+ this->video_stream = (this->num_video_streams == 1) ? &this->video_streams[0] : NULL;
+ this->audio_stream = (this->num_audio_streams == 1) ? &this->audio_streams[0] : NULL;
/* In the case of multiple audio/video streams select the first
streams found in the file */
@@ -590,23 +698,23 @@ unknown:
/* Get data to search through for stream chunks */
if(INPUT_IS_SEEKABLE(this->input)) {
original_pos = this->input->get_current_pos(this->input);
-
+
if((len = this->input->read(this->input, search_buffer, MAX_PREVIEW_SIZE)) <= 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: failed to read header\n");
this->status = DEMUX_FINISHED;
return;
}
-
+
offset = 0;
} else if((this->input->get_capabilities(this->input) & INPUT_CAP_PREVIEW) != 0) {
if((len = this->input->get_optional_data(this->input, search_buffer, INPUT_OPTIONAL_DATA_PREVIEW)) <= 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: failed to read header\n");
this->status = DEMUX_FINISHED;
return;
}
-
+
/* Preview data starts at the beginning of the file */
offset = this->data_start + 18;
} else {
@@ -615,19 +723,17 @@ unknown:
this->status = DEMUX_FINISHED;
return;
}
-
+
while((offset < len) &&
((!this->video_stream && (this->num_video_streams > 0)) ||
(!this->audio_stream && (this->num_audio_streams > 0)))) {
- uint32_t id;
- int i, stream;
-
+ int i;
+
/* Check for end of the data chunk */
- if(((id = _X_BE_32(&search_buffer[offset])) == DATA_TAG) ||
- (id == INDX_TAG))
- break;
-
- stream = _X_BE_16(&search_buffer[offset + 4]);
+ if (_x_is_fourcc(&search_buffer[offset], "INDX") || _x_is_fourcc(&search_buffer[offset], "DATA"))
+ break;
+
+ const int stream = _X_BE_16(&search_buffer[offset + 4]);
for(i = 0; !this->video_stream && (i < this->num_video_streams); i++) {
if(stream == this->video_streams[i].mdpr->stream_number) {
@@ -635,7 +741,7 @@ unknown:
lprintf("selecting video stream: %d\n", stream);
}
}
-
+
for(i = 0; !this->audio_stream && (i < this->num_audio_streams); i++) {
if(stream == this->audio_streams[i].mdpr->stream_number) {
this->audio_stream = &this->audio_streams[i];
@@ -645,11 +751,11 @@ unknown:
offset += _X_BE_16(&search_buffer[offset + 2]);
}
-
+
if(INPUT_IS_SEEKABLE(this->input))
this->input->seek(this->input, original_pos, SEEK_SET);
}
-
+
/* Let the user know if we haven't managed to detect what streams to play */
if((!this->video_stream && this->num_video_streams) ||
(!this->audio_stream && this->num_audio_streams)) {
@@ -658,19 +764,17 @@ unknown:
this->status = DEMUX_FINISHED;
return;
}
-
+
/* Send headers and set meta info */
if(this->video_stream) {
- buf_element_t *buf;
-
/* Check for recognised codec*/
if(!this->video_stream->buf_type)
this->video_stream->buf_type = BUF_VIDEO_UNKNOWN;
-
+
/* Send header */
- buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
+ buf_element_t *const buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
buf->content = buf->mem;
-
+
memcpy(buf->content, this->video_stream->mdpr->type_specific_data,
this->video_stream->mdpr->type_specific_len);
@@ -688,9 +792,9 @@ unknown:
this->video_stream->fourcc);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_BITRATE,
this->video_stream->mdpr->avg_bit_rate);
-
+
/* Allocate fragment offset table */
- this->fragment_tab = xine_xmalloc(FRAGMENT_TAB_SIZE*sizeof(uint32_t));
+ this->fragment_tab = calloc(FRAGMENT_TAB_SIZE, sizeof(uint32_t));
this->fragment_tab_max = FRAGMENT_TAB_SIZE;
}
@@ -698,31 +802,30 @@ unknown:
/* Check for recognised codec */
if(!this->audio_stream->buf_type)
this->audio_stream->buf_type = BUF_AUDIO_UNKNOWN;
-
+
/* Send headers */
if(this->audio_fifo) {
- mdpr_t *mdpr = this->audio_stream->mdpr;
- buf_element_t *buf;
+ mdpr_t *const mdpr = this->audio_stream->mdpr;
- buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf_element_t *buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = this->audio_stream->buf_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END;
-
+
/* For AAC we send two header buffers, the first is a standard audio
* header giving bits per sample, sample rate and number of channels.
* The second is the codec initialisation data found at the end of
* the type specific data for the audio stream */
if(buf->type == BUF_AUDIO_AAC) {
- int version = _X_BE_16(mdpr->type_specific_data + 4);
-
+ const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4);
+
if(version != 5) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: unsupported audio header version for AAC: %d\n", version);
buf->free_buffer(buf);
goto unsupported;
}
-
+
buf->decoder_info[1] = _X_BE_16(mdpr->type_specific_data + 54);
buf->decoder_info[2] = _X_BE_16(mdpr->type_specific_data + 58);
buf->decoder_info[3] = _X_BE_16(mdpr->type_specific_data + 60);
@@ -730,21 +833,28 @@ unknown:
buf->decoder_flags |= BUF_FLAG_STDHEADER;
buf->content = NULL;
buf->size = 0;
-
+
this->audio_fifo->put (this->audio_fifo, buf);
-
+
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
-
+
buf->type = this->audio_stream->buf_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END|BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_DECODER_CONFIG;
buf->decoder_info[2] = _X_BE_32(mdpr->type_specific_data + 74) - 1;
buf->decoder_info_ptr[2] = buf->content;
buf->size = 0;
-
+
memcpy(buf->content, mdpr->type_specific_data + 79,
buf->decoder_info[2]);
+ } else if(buf->type == BUF_AUDIO_MP3ADU) {
+ buf->decoder_flags |= BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END;
+ buf->size = 0;
+ buf->decoder_info[0] = 0;
+ buf->decoder_info[1] = 0;
+ buf->decoder_info[2] = 0;
+ buf->decoder_info[3] = 0;
} else {
memcpy(buf->content, mdpr->type_specific_data,
mdpr->type_specific_len);
@@ -782,7 +892,7 @@ static int demux_real_parse_references( demux_real_t *this) {
lprintf("parsing references\n");
-
+
/* read file to memory.
* warning: dumb code, but hopefuly ok since reference file is small */
do {
@@ -801,17 +911,27 @@ static int demux_real_parse_references( demux_real_t *this) {
if(buf_used)
buf[buf_used] = '\0';
-
+
lprintf("received %d bytes [%s]\n", buf_used, buf);
if (!strncmp(buf,"http://",7))
{
- for (i = 0; buf[i] && !isspace(buf[i]); ++i)
- /**/;
- buf[i] = 0;
- lprintf("reference [%s] found\n", buf);
-
- _x_demux_send_mrl_reference (this->stream, 0, buf, NULL, 0, 0);
+ i = 0;
+ while (buf[i])
+ {
+ j = i;
+ while (buf[i] && !isspace(buf[i]))
+ ++i; /* skip non-space */
+ len = buf[i];
+ buf[i] = 0;
+ if (strncmp (buf + j, "http://", 7) || (i - j) < 8)
+ break; /* stop at the first non-http reference */
+ lprintf("reference [%s] found\n", buf + j);
+ _x_demux_send_mrl_reference (this->stream, 0, buf + j, NULL, 0, 0);
+ buf[i] = (char) len;
+ while (buf[i] && isspace(buf[i]))
+ ++i; /* skip spaces */
+ }
}
else for (i = 0; i < buf_used; ++i)
{
@@ -825,10 +945,10 @@ static int demux_real_parse_references( demux_real_t *this) {
/* rpm files can contain comments which should be skipped */
if( !strncmp(&buf[i],"<!--",4) )
comment = 1;
-
+
if( !strncmp(&buf[i],"-->",3) )
comment = 0;
-
+
if( (!strncmp(&buf[i],"pnm://",6) || !strncmp(&buf[i],"rtsp://",7)) &&
!comment ) {
for(j=i; buf[j] && buf[j] != '"' && !isspace(buf[j]); j++ )
@@ -841,14 +961,14 @@ static int demux_real_parse_references( demux_real_t *this) {
i = j;
}
- }
-
+ }
+
free(buf);
-
+
this->status = DEMUX_FINISHED;
return this->status;
}
-
+
/* redefine abs as macro to handle 64-bit diffs.
i guess llabs may not be available everywhere */
#define abs(x) ( ((x)<0) ? -(x) : (x) )
@@ -858,9 +978,7 @@ static int demux_real_parse_references( demux_real_t *this) {
#define PTS_VIDEO 1
static void check_newpts (demux_real_t *this, int64_t pts, int video, int preview) {
- int64_t diff;
-
- diff = pts - this->last_pts[video];
+ const int64_t diff = pts - this->last_pts[video];
lprintf ("check_newpts %"PRId64"\n", pts);
if (!preview && pts &&
@@ -886,7 +1004,7 @@ static uint32_t real_fix_timestamp (demux_real_t *this, uint8_t *hdr, uint32_t t
int pict_type;
int seq;
uint32_t ts_out;
-
+
switch(this->video_stream->buf_type) {
case BUF_VIDEO_RV20:
pict_type = (hdr[0] & 0xC0) >> 6;
@@ -901,35 +1019,35 @@ static uint32_t real_fix_timestamp (demux_real_t *this, uint8_t *hdr, uint32_t t
seq = ((hdr[1] & 0x07) << 10) + (hdr[2] << 2) + ((hdr[3] & 0xC0) >> 6);
break;
default:
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_real: can't fix timestamp for buf type 0x%08x\n",
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: can't fix timestamp for buf type 0x%08x\n",
this->video_stream->buf_type);
return ts_in;
break;
}
-
+
switch (pict_type) {
case 0:
- case 1:
+ case 1:
/* I frame */
ts_out = this->next_ts;
-
+
this->last_ts = this->next_ts;
this->next_ts = ts_in;
-
+
this->last_seq = this->next_seq;
this->next_seq = seq;
break;
case 2:
/* P frame */
ts_out = this->next_ts;
-
+
this->last_ts = this->next_ts;
if (seq < this->next_seq)
this->next_ts += seq + 8192 - this->next_seq;
else
this->next_ts += seq - this->next_seq;
-
+
this->last_seq = this->next_seq;
this->next_seq = seq;
break;
@@ -946,8 +1064,8 @@ static uint32_t real_fix_timestamp (demux_real_t *this, uint8_t *hdr, uint32_t t
ts_out = 0;
break;
}
-
- return ts_out;
+
+ return ts_out;
}
static int stream_read_char (demux_real_t *this) {
@@ -966,18 +1084,14 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
demux_real_t *this = (demux_real_t *) this_gen;
char header[DATA_PACKET_HEADER_SIZE];
- int stream, size, keyframe, input_time = 0;
- unsigned short version;
- uint32_t id, timestamp;
- int64_t pts;
- off_t offset, input_length = 0;
+ int keyframe, input_time = 0;
int normpos = 0;
if(this->reference_mode)
return demux_real_parse_references(this);
-
+
/* load a header from wherever the stream happens to be pointing */
- if ( (size=this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE)) !=
+ if ( this->input->read(this->input, header, DATA_PACKET_HEADER_SIZE) !=
DATA_PACKET_HEADER_SIZE) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
@@ -988,29 +1102,28 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
}
/* Check to see if we've gone past the end of the data chunk */
- if(((id = _X_BE_32(&header[0])) == DATA_TAG) ||
- (id == INDX_TAG)) {
+ if (_x_is_fourcc(&header[0], "INDX") || _x_is_fourcc(&header[0], "DATA")) {
lprintf("finished reading data chunk\n");
this->status = DEMUX_FINISHED;
return this->status;
}
/* check version */
- version = _X_BE_16(&header[0]);
+ const uint16_t version = _X_BE_16(&header[0]);
if(version > 1) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: unknown object version in data packet: 0x%04x\n", version);
this->status = DEMUX_FINISHED;
return this->status;
}
-
+
/* read the packet information */
- stream = _X_BE_16(&header[4]);
- offset = this->input->get_current_pos(this->input);
- size = _X_BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE;
- timestamp= _X_BE_32(&header[6]);
- pts = (int64_t) timestamp * 90;
-
+ const uint16_t stream = _X_BE_16(&header[4]);
+ const off_t offset __attr_unused = this->input->get_current_pos(this->input);
+ uint16_t size = _X_BE_16(&header[2]) - DATA_PACKET_HEADER_SIZE;
+ const uint32_t timestamp= _X_BE_32(&header[6]);
+ int64_t pts = (int64_t) timestamp * 90;
+
/* Data packet header with version 1 contains 1 extra byte */
if(version == 0)
keyframe = header[11] & PN_KEYFRAME_FLAG;
@@ -1024,11 +1137,9 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
if (this->video_stream && (stream == this->video_stream->mdpr->stream_number)) {
- int vpkg_header, vpkg_length, vpkg_offset;
int vpkg_seqnum = -1;
int vpkg_subseq = 0;
buf_element_t *buf;
- int n, fragment_size;
uint32_t decoder_flags;
lprintf ("video chunk detected.\n");
@@ -1043,21 +1154,20 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
* bit 6: 1=short header (only one block?)
*/
- vpkg_header = stream_read_char (this); size--;
+ const int vpkg_header = stream_read_char (this); size--;
lprintf ("vpkg_hdr: %02x (size=%d)\n", vpkg_header, size);
+ int vpkg_length, vpkg_offset;
if (0x40==(vpkg_header&0xc0)) {
/*
* seems to be a very short header
* 2 bytes, purpose of the second byte yet unknown
*/
- int bummer;
-
- bummer = stream_read_char (this); size--;
+ const int bummer __attr_unused = stream_read_char (this);
lprintf ("bummer == %02X\n",bummer);
vpkg_offset = 0;
- vpkg_length = size;
+ vpkg_length = --size;
} else {
@@ -1115,23 +1225,22 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
if(this->video_stream->index)
input_time = timestamp;
else
- input_time = (int)((int64_t) this->input->get_current_pos(this->input)
+ input_time = (int)((int64_t) this->input->get_current_pos(this->input)
* 8 * 1000 / this->avg_bitrate);
- if(this->data_start && this->data_chunk_size)
- input_length = this->data_start + 18 + this->data_chunk_size;
- if( input_length )
+ const off_t input_length = this->data_start + 18 + this->data_chunk_size;
+ if( input_length > 18 )
normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length);
-
+
check_newpts (this, pts, PTS_VIDEO, 0);
if (this->fragment_size == 0) {
lprintf ("new packet starting\n");
-
+
/* send fragment offset table */
if(this->fragment_count) {
lprintf("sending fragment offset table\n");
-
+
buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
buf->decoder_flags = BUF_FLAG_SPECIAL | BUF_FLAG_FRAME_END;
@@ -1144,18 +1253,18 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
xine_fast_memcpy(buf->decoder_info_ptr[2], this->fragment_tab,
this->fragment_count*8);
-
+
this->video_fifo->put(this->video_fifo, buf);
-
+
this->fragment_count = 0;
}
-
+
decoder_flags = BUF_FLAG_FRAME_START;
} else {
lprintf ("continuing packet \n");
decoder_flags = 0;
}
-
+
/* add entry to fragment offset table */
this->fragment_tab[2*this->fragment_count] = 1;
this->fragment_tab[2*this->fragment_count+1] = this->fragment_size;
@@ -1165,46 +1274,47 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
* calc size of fragment
*/
- if ((vpkg_header & 0xc0) == 0x080)
+ int fragment_size;
+ switch(vpkg_header & 0xc0) {
+ case 0x80:
fragment_size = vpkg_offset;
- else {
- if (0x00 == (vpkg_header&0xc0))
- fragment_size = size;
- else
- fragment_size = vpkg_length;
+ break;
+ case 0x00:
+ fragment_size = size;
+ break;
+ default:
+ fragment_size = vpkg_length;
+ break;
}
lprintf ("fragment size is %d\n", fragment_size);
/*
* read fragment_size bytes of data
*/
-
- n = fragment_size;
+
+ int n = fragment_size;
while(n) {
buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
-
- if(n>buf->max_size)
- buf->size = buf->max_size;
- else
- buf->size = n;
+
+ buf->size = MIN(n, buf->max_size);
buf->decoder_flags = decoder_flags;
decoder_flags &= ~BUF_FLAG_FRAME_START;
-
+
buf->type = this->video_stream->buf_type;
-
+
if(this->input->read(this->input, buf->content, buf->size) < buf->size) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: failed to read video fragment");
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
}
-
- /* RV30 and RV40 streams contain some fragments that shouldn't be passed
- * to the decoder. The purpose of these fragments is unknown, but
- * realplayer doesn't appear to pass them to the decoder either */
- if((n == fragment_size) &&
+
+ /* RV30 and RV40 streams contain some fragments that shouldn't be passed
+ * to the decoder. The purpose of these fragments is unknown, but
+ * realplayer doesn't appear to pass them to the decoder either */
+ if((n == fragment_size) &&
(((buf->type == BUF_VIDEO_RV30) && (buf->content[0] & 0x20)) ||
((buf->type == BUF_VIDEO_RV40) && (buf->content[0] & 0x80)))) {
lprintf("ignoring fragment\n");
@@ -1216,12 +1326,12 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
break;
}
-
+
/* if the video stream has b-frames fix the timestamps */
if((this->video_stream->format >= 0x20200002) &&
(buf->decoder_flags & BUF_FLAG_FRAME_START))
pts = (int64_t) real_fix_timestamp(this, buf->content, timestamp) * 90;
-
+
/* this test was moved from ffmpeg video decoder.
* fixme: is pts only valid on frame start? */
if( buf->decoder_flags & BUF_FLAG_FRAME_START )
@@ -1229,13 +1339,13 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
else
buf->pts = 0;
pts = 0;
-
+
buf->extra_info->input_normpos = normpos;
buf->extra_info->input_time = input_time;
buf->extra_info->total_time = this->duration;
-
+
this->video_fifo->put(this->video_fifo, buf);
-
+
n -= buf->size;
}
@@ -1260,71 +1370,131 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) {
goto discard;
else
this->audio_need_keyframe = 0;
-
+
/* if we have a seekable stream then use the timestamp for the data
* packet for more accurate seeking - if not then estimate time using
* average bitrate */
if(this->audio_stream->index)
input_time = timestamp;
else
- input_time = (int)((int64_t) this->input->get_current_pos(this->input)
- * 8 * 1000 / this->avg_bitrate);
-
- if(this->data_start && this->data_chunk_size)
- input_length = this->data_start + 18 + this->data_chunk_size;
- else
- input_length = 0;
-
- if( input_length )
+ input_time = (int)((int64_t) this->input->get_current_pos(this->input)
+ * 8 * 1000 / this->avg_bitrate);
+
+ const off_t input_length = this->data_start + 18 + this->data_chunk_size;
+
+ if( input_length > 18 )
normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length);
-
+
check_newpts (this, pts, PTS_AUDIO, 0);
-
+
/* Each packet of AAC is made up of several AAC frames preceded by a
* header defining the size of the frames */
if(this->audio_stream->buf_type == BUF_AUDIO_AAC) {
- int i, frames, *sizes;
-
+ int i;
+
/* Upper 4 bits of second byte is frame count */
- frames = (stream_read_word(this) & 0xf0) >> 4;
-
+ const int frames = (stream_read_word(this) & 0xf0) >> 4;
+
/* 2 bytes per frame size */
- sizes = xine_xmalloc(frames*sizeof(int));
+ int sizes[frames];
+
for(i = 0; i < frames; i++)
sizes[i] = stream_read_word(this);
-
+
for(i = 0; i < frames; i++) {
- if(_x_demux_read_send_data(this->audio_fifo, this->input, sizes[i], pts,
- this->audio_stream->buf_type, 0, normpos,
+ if(_x_demux_read_send_data(this->audio_fifo, this->input, sizes[i], pts,
+ this->audio_stream->buf_type, 0, normpos,
input_time, this->duration, 0) < 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: failed to read AAC frame\n");
- free(sizes);
this->status = DEMUX_FINISHED;
return this->status;
}
-
+
pts = 0; /* Only set pts on first frame */
}
-
- free(sizes);
+ } else if (this->audio_stream->buf_type == BUF_AUDIO_COOK ||
+ this->audio_stream->buf_type == BUF_AUDIO_ATRK ||
+ this->audio_stream->buf_type == BUF_AUDIO_28_8 ||
+ this->audio_stream->buf_type == BUF_AUDIO_SIPRO) {
+ /* reorder */
+ uint8_t * buffer = this->audio_stream->frame_buffer;
+ int sps = this->audio_stream->sps;
+ int sph = this->audio_stream->h;
+ int cfs = this->audio_stream->cfs;
+ int w = this->audio_stream->w;
+ int spc = this->audio_stream->sub_packet_cnt;
+ int x;
+ off_t pos;
+ const size_t fs = this->audio_stream->frame_size;
+
+ if (!buffer) {
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+
+ switch (this->audio_stream->buf_type) {
+ case BUF_AUDIO_28_8:
+ for (x = 0; x < sph / 2; x++) {
+ pos = x * 2 * w + spc * cfs;
+ if(pos + cfs > fs || this->input->read(this->input, buffer + pos, cfs) < cfs) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ }
+ break;
+ case BUF_AUDIO_COOK:
+ case BUF_AUDIO_ATRK:
+ for (x = 0; x < w / sps; x++) {
+ pos = sps * (sph * x + ((sph + 1) / 2) * (spc & 1) + (spc >> 1));
+ if(pos + sps > fs || this->input->read(this->input, buffer + pos, sps) < sps) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ }
+ break;
+ case BUF_AUDIO_SIPRO:
+ pos = spc * w;
+ if(pos + w > fs || this->input->read(this->input, buffer + pos, w) < w) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_real: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ if (spc == sph - 1)
+ demux_real_sipro_swap (buffer, sph * w * 2 / 96);
+ break;
+ }
+ if(++this->audio_stream->sub_packet_cnt == sph) {
+ this->audio_stream->sub_packet_cnt = 0;
+ _x_demux_send_data(this->audio_fifo, buffer, this->audio_stream->frame_size,
+ pts, this->audio_stream->buf_type, 0, normpos, input_time,
+ this->duration, 0);
+ }
} else {
- if(_x_demux_read_send_data(this->audio_fifo, this->input, size, pts,
+ if(_x_demux_read_send_data(this->audio_fifo, this->input, size, pts,
this->audio_stream->buf_type, 0, normpos,
input_time, this->duration, 0) < 0) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_real: failed to read audio chunk\n");
this->status = DEMUX_FINISHED;
return this->status;
}
-
+
/* FIXME: dp->flags = (flags & 0x2) ? 0x10 : 0; */
}
-
+
} else {
/* discard */
@@ -1342,18 +1512,10 @@ discard:
/* check if it's time to reload */
if (!this->current_data_chunk_packet_count &&
this->next_data_chunk_offset) {
- char preamble[PREAMBLE_SIZE];
unsigned char data_chunk_header[DATA_CHUNK_HEADER_SIZE];
/* seek to the next DATA chunk offset */
- this->input->seek(this->input, this->next_data_chunk_offset, SEEK_SET);
-
- /* load the DATA chunk preamble */
- if (this->input->read(this->input, preamble, PREAMBLE_SIZE) !=
- PREAMBLE_SIZE) {
- this->status = DEMUX_FINISHED;
- return this->status;
- }
+ this->input->seek(this->input, this->next_data_chunk_offset + PREAMBLE_SIZE, SEEK_SET);
/* load the rest of the DATA chunk header */
if (this->input->read(this->input, data_chunk_header,
@@ -1415,14 +1577,14 @@ static int demux_real_seek (demux_plugin_t *this_gen,
demux_real_t *this = (demux_real_t *) this_gen;
real_index_entry_t *index, *other_index = NULL;
int i = 0, entries;
-
+
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) );
@@ -1459,6 +1621,9 @@ static int demux_real_seek (demux_plugin_t *this_gen,
this->input->seek(this->input, index[i].offset, SEEK_SET);
if(playing) {
+ if(this->audio_stream)
+ this->audio_stream->sub_packet_cnt = 0;
+
this->buf_flag_seek = 1;
_x_demux_flush_engine(this->stream);
}
@@ -1467,14 +1632,14 @@ static int demux_real_seek (demux_plugin_t *this_gen,
/* 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;
this->fragment_size = 0;
-
+
this->next_ts = 0;
this->next_seq = 0;
@@ -1489,19 +1654,16 @@ static void demux_real_dispose (demux_plugin_t *this_gen) {
for(i = 0; i < this->num_video_streams; i++) {
real_free_mdpr(this->video_streams[i].mdpr);
- if(this->video_streams[i].index)
- free(this->video_streams[i].index);
+ free(this->video_streams[i].index);
}
-
+
for(i = 0; i < this->num_audio_streams; i++) {
real_free_mdpr(this->audio_streams[i].mdpr);
- if(this->audio_streams[i].index)
- free(this->audio_streams[i].index);
+ free(this->audio_streams[i].index);
+ free(this->audio_streams[i].frame_buffer);
}
-
- if(this->fragment_tab)
- free(this->fragment_tab);
-
+
+ free(this->fragment_tab);
free(this);
}
@@ -1528,21 +1690,27 @@ static int demux_real_get_optional_data(demux_plugin_t *this_gen,
}
/* help function to discover stream type. returns:
+ * -1 if couldn't read
* 0 if not known.
* 1 if normal stream.
* 2 if reference stream.
*/
-static int real_check_stream_type(uint8_t *buf, int len)
+static int real_check_stream_type(input_plugin_t *input)
{
- if ((buf[0] == 0x2e)
- && (buf[1] == 'R')
- && (buf[2] == 'M')
- && (buf[3] == 'F'))
+ uint8_t buf[1024];
+ off_t len = _x_demux_read_header(input, buf, sizeof(buf));
+
+ if ( len < 4 )
+ return -1;
+
+ if ( memcmp(buf, "\x2eRMF", 4) == 0 )
return 1;
- buf[len] = '\0';
- if( strstr(buf,"pnm://") || strstr(buf,"rtsp://") || strstr(buf,"<smil>") ||
- !strncmp(buf,"http://",7) )
+#define my_strnstr(haystack, haystacklen, needle) \
+ memmem(haystack, haystacklen, needle, sizeof(needle))
+
+ if( my_strnstr(buf, len, "pnm://") || my_strnstr(buf, len, "rtsp://") ||
+ my_strnstr(buf, len, "<smil>") || !strncmp(buf, "http://", MIN(7, len)) )
return 2;
return 0;
@@ -1551,32 +1719,24 @@ static int real_check_stream_type(uint8_t *buf, int len)
static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *stream,
input_plugin_t *input) {
- demux_real_t *this;
- uint8_t buf[1024+1];
- int len, stream_type=0;
-
- switch (stream->content_detection_method) {
-
- case METHOD_BY_CONTENT:{
+ /* discover stream type */
+ const int stream_type = real_check_stream_type(input);
- if (! (len = _x_demux_read_header(input, buf, 1024)) )
- return NULL;
+ if ( stream_type < 0 )
+ return NULL;
- lprintf ("read 4 bytes: %02x %02x %02x %02x\n",
- buf[0], buf[1], buf[2], buf[3]);
+ switch (stream->content_detection_method) {
- if (!(stream_type = real_check_stream_type(buf,len)))
+ case METHOD_BY_CONTENT:
+ if ( stream_type < 1 )
return NULL;
- }
- lprintf ("by content accepted.\n");
- break;
+ lprintf ("by content accepted.\n");
+ break;
case METHOD_BY_EXTENSION: {
- const char *extensions, *mrl;
-
- mrl = input->get_mrl (input);
- 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 ("by extension '%s'\n", mrl);
@@ -1595,17 +1755,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
-
- this = xine_xmalloc (sizeof (demux_real_t));
+ demux_real_t *this = calloc(1, sizeof(demux_real_t));
this->stream = stream;
this->input = input;
- /* discover stream type */
- if(!stream_type)
- if ( (len = _x_demux_read_header(this->input, buf, 1024)) )
- stream_type = real_check_stream_type(buf,len);
-
if(stream_type == 2){
this->reference_mode = 1;
lprintf("reference stream detected\n");
@@ -1642,7 +1796,7 @@ 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;"
- "application/vnd.rn-realmedia: ra, rm, ram: Real Media file;";
+ "application/vnd.rn-realmedia: ra, rm, ram: Real Media file;";
}
static void class_dispose (demux_class_t *this_gen) {
@@ -1652,9 +1806,7 @@ static void class_dispose (demux_class_t *this_gen) {
}
static void *init_class (xine_t *xine, void *data) {
- demux_real_class_t *this;
-
- this = xine_xmalloc (sizeof (demux_real_class_t));
+ demux_real_class_t *const this = calloc(1, sizeof(demux_real_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_realaudio.c b/src/demuxers/demux_realaudio.c
index 70c9b310a..3c18f7ec3 100644
--- a/src/demuxers/demux_realaudio.c
+++ b/src/demuxers/demux_realaudio.c
@@ -41,6 +41,8 @@
#include "bswap.h"
#include "group_audio.h"
+#include "real_common.h"
+
#define RA_FILE_HEADER_PREV_SIZE 22
typedef struct {
@@ -61,7 +63,13 @@ typedef struct {
off_t data_start;
off_t data_size;
-
+
+ uint32_t cfs;
+ uint16_t w, h;
+ int frame_len;
+ size_t frame_size;
+ uint8_t *frame_buffer;
+
unsigned char *header;
unsigned int header_size;
} demux_ra_t;
@@ -70,26 +78,24 @@ typedef struct {
demux_class_t demux_class;
} demux_ra_class_t;
+/* Map flavour to bytes per second */
+static const int sipr_fl2bps[4] = {813, 1062, 625, 2000}; // 6.5, 8.5, 5, 16 kbit per second
+
/* returns 1 if the RealAudio file was opened successfully, 0 otherwise */
static int open_ra_file(demux_ra_t *this) {
- unsigned char file_header[RA_FILE_HEADER_PREV_SIZE], len;
- unsigned short version;
- off_t offset;
-
+ uint8_t file_header[RA_FILE_HEADER_PREV_SIZE];
/* check the signature */
if (_x_demux_read_header(this->input, file_header, RA_FILE_HEADER_PREV_SIZE) !=
RA_FILE_HEADER_PREV_SIZE)
return 0;
- if ((file_header[0] != '.') ||
- (file_header[1] != 'r') ||
- (file_header[2] != 'a'))
+ if ( memcmp(file_header, ".ra", 3) != 0 )
return 0;
/* read version */
- version = _X_BE_16(&file_header[0x04]);
-
+ const uint16_t version = _X_BE_16(&file_header[0x04]);
+
/* read header size according to version */
if (version == 3)
this->header_size = _X_BE_16(&file_header[0x06]) + 8;
@@ -99,86 +105,121 @@ static int open_ra_file(demux_ra_t *this) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unknown version number %d\n", version);
return 0;
}
-
+
/* allocate for and read header data */
- this->header = xine_xmalloc(this->header_size);
-
- if (_x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) {
+ this->header = malloc(this->header_size);
+
+ if (!this->header || _x_demux_read_header(this->input, this->header, this->header_size) != this->header_size) {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: unable to read header\n");
free(this->header);
return 0;
}
-
+
+ off_t offset;
/* read header data according to version */
if((version == 3) && (this->header_size >= 32)) {
this->data_size = _X_BE_32(&this->header[0x12]);
-
+
this->block_align = 240;
-
+
offset = 0x16;
} else if(this->header_size >= 72) {
- this->data_size = _X_BE_32(&this->header[0x1C]);
-
+ this->data_size = _X_BE_32(&this->header[0x1C]);
+
this->block_align = _X_BE_16(&this->header[0x2A]);
-
+
if(this->header[0x3D] == 4)
this->fourcc = _X_ME_32(&this->header[0x3E]);
else {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_realaudio: invalid fourcc size %d\n", this->header[0x3D]);
free(this->header);
return 0;
}
-
+
offset = 0x45;
} else {
xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: header too small\n");
free(this->header);
return 0;
}
-
+
/* Read title */
- len = this->header[offset];
- if(len && ((offset+len+2) < this->header_size)) {
- _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE,
- &this->header[offset+1], len);
- offset += len+1;
- } else
- offset++;
-
+ {
+ const uint8_t len = this->header[offset];
+ if(len && ((offset+len+2) < this->header_size)) {
+ _x_meta_info_n_set(this->stream, XINE_META_INFO_TITLE,
+ &this->header[offset+1], len);
+ offset += len+1;
+ } else
+ offset++;
+ }
+
/* Author */
- len = this->header[offset];
- if(len && ((offset+len+1) < this->header_size)) {
- _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST,
- &this->header[offset+1], len);
- offset += len+1;
- } else
- offset++;
-
+ {
+ const uint8_t len = this->header[offset];
+ if(len && ((offset+len+1) < this->header_size)) {
+ _x_meta_info_n_set(this->stream, XINE_META_INFO_ARTIST,
+ &this->header[offset+1], len);
+ offset += len+1;
+ } else
+ offset++;
+ }
+
/* Copyright/Date */
- len = this->header[offset];
- if(len && ((offset+len) <= this->header_size)) {
- _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR,
- &this->header[offset+1], len);
- offset += len+1;
- } else
- offset++;
-
+ {
+ const uint8_t len = this->header[offset];
+ if(len && ((offset+len) <= this->header_size)) {
+ _x_meta_info_n_set(this->stream, XINE_META_INFO_YEAR,
+ &this->header[offset+1], len);
+ offset += len+1;
+ } else
+ offset++;
+ }
+
/* Fourcc for version 3 comes after meta info */
- if((version == 3) && ((offset+7) <= this->header_size)) {
- if(this->header[offset+2] == 4)
- this->fourcc = _X_ME_32(&this->header[offset+3]);
- else {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
- "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]);
- free(this->header);
- return 0;
+ if(version == 3) {
+ if (((offset+7) <= this->header_size)) {
+ if(this->header[offset+2] == 4)
+ this->fourcc = _X_ME_32(&this->header[offset+3]);
+ else {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_realaudio: invalid fourcc size %d\n", this->header[offset+2]);
+ free(this->header);
+ return 0;
+ }
+ } else {
+ this->fourcc = ME_FOURCC('l', 'p', 'c', 'J');
}
}
-
+
_x_stream_info_set(this->stream, XINE_STREAM_INFO_AUDIO_FOURCC, this->fourcc);
this->audio_type = _x_formattag_to_buf_audio(this->fourcc);
+ if (version == 4) {
+ const uint16_t sps = _X_BE_16 (this->header+44) ? : 1;
+ this->w = _X_BE_16 (this->header+42);
+ this->h = _X_BE_16 (this->header+40);
+ this->cfs = _X_BE_32 (this->header+24);
+
+ if (this->w < 0x8000 && this->h < 0x8000) {
+ uint64_t fs;
+ this->frame_len = this->w * this->h;
+ fs = (uint64_t) this->frame_len * sps;
+ if (fs < 0x80000000) {
+ this->frame_size = fs;
+ this->frame_buffer = calloc(this->frame_size, 1);
+ }
+ }
+ if (! this->frame_buffer) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_realaudio: malloc failed\n");
+ return 0;
+ }
+
+ if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO)
+ this->block_align = this->cfs;
+ }
+
/* seek to start of data */
this->data_start = this->header_size;
if (this->input->seek(this->input, this->data_start, SEEK_SET) !=
@@ -197,27 +238,57 @@ static int demux_ra_send_chunk(demux_plugin_t *this_gen) {
demux_ra_t *this = (demux_ra_t *) this_gen;
off_t current_normpos = 0;
- int64_t current_pts;
/* just load data chunks from wherever the stream happens to be
* pointing; issue a DEMUX_FINISHED status if EOF is reached */
if( this->input->get_length (this->input) )
- current_normpos = (int)( (double) (this->input->get_current_pos (this->input) - this->data_start) *
+ current_normpos = (int)( (double) (this->input->get_current_pos (this->input) - this->data_start) *
65535 / this->data_size );
- current_pts = 0; /* let the engine sort out the pts for now */
+ const int64_t current_pts = 0; /* let the engine sort out the pts for now */
if (this->seek_flag) {
_x_demux_control_newpts(this->stream, current_pts, BUF_FLAG_SEEK);
this->seek_flag = 0;
}
- if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align,
- current_pts, this->audio_type, 0, current_normpos,
+ if (this->audio_type == BUF_AUDIO_28_8 || this->audio_type == BUF_AUDIO_SIPRO) {
+ if (this->audio_type == BUF_AUDIO_SIPRO) {
+ if(this->input->read(this->input, this->frame_buffer, this->frame_len) < this->frame_len) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_realaudio: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ demux_real_sipro_swap (this->frame_buffer, this->frame_len * 2 / 96);
+ } else {
+ int x, y;
+
+ for (y = 0; y < this->h; y++)
+ for (x = 0; x < this->h / 2; x++) {
+ const int pos = x * 2 * this->w + y * this->cfs;
+ if(this->input->read(this->input, this->frame_buffer + pos,
+ this->cfs) < this->cfs) {
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_realaudio: failed to read audio chunk\n");
+
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ }
+ }
+
+ _x_demux_send_data(this->audio_fifo,
+ this->frame_buffer, this->frame_size,
+ current_pts, this->audio_type, 0,
+ current_normpos, current_pts / 90, 0, 0);
+ } else if(_x_demux_read_send_data(this->audio_fifo, this->input, this->block_align,
+ current_pts, this->audio_type, 0, current_normpos,
current_pts / 90, 0, 0) < 0) {
- this->status = DEMUX_FINISHED;
+ this->status = DEMUX_FINISHED;
}
-
+
return this->status;
}
@@ -243,12 +314,9 @@ static void demux_ra_send_headers(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = this->audio_type;
buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_FRAME_END;
-
- if(this->header_size > buf->max_size)
- buf->size = buf->max_size;
- else
- buf->size = this->header_size;
-
+
+ buf->size = MIN(this->header_size, buf->max_size);
+
memcpy(buf->content, this->header, buf->size);
this->audio_fifo->put (this->audio_fifo, buf);
@@ -296,9 +364,11 @@ static int demux_ra_seek (demux_plugin_t *this_gen,
static void demux_ra_dispose (demux_plugin_t *this_gen) {
demux_ra_t *this = (demux_ra_t *) this_gen;
-
+
if(this->header)
free(this->header);
+ if (this->frame_buffer)
+ free(this->frame_buffer);
free(this);
}
@@ -311,8 +381,6 @@ static int demux_ra_get_status (demux_plugin_t *this_gen) {
/* return the approximate length in miliseconds */
static int demux_ra_get_stream_length (demux_plugin_t *this_gen) {
- demux_ra_t *this = (demux_ra_t *) this_gen;
-
return 0;
}
@@ -330,9 +398,10 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_ra_t *this;
- this = xine_xmalloc (sizeof (demux_ra_t));
+ this = calloc(1, sizeof(demux_ra_t));
this->stream = stream;
this->input = input;
+ this->frame_buffer = NULL;
this->demux_plugin.send_headers = demux_ra_send_headers;
this->demux_plugin.send_chunk = demux_ra_send_chunk;
@@ -370,7 +439,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
}
break;
-
+
default:
free (this);
return NULL;
@@ -404,7 +473,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_realaudio_init_plugin (xine_t *xine, void *data) {
demux_ra_class_t *this;
- this = xine_xmalloc (sizeof (demux_ra_class_t));
+ this = calloc(1, sizeof(demux_ra_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_roq.c b/src/demuxers/demux_roq.c
index 18edaea87..346d487aa 100644
--- a/src/demuxers/demux_roq.c
+++ b/src/demuxers/demux_roq.c
@@ -47,7 +47,6 @@
#include "bswap.h"
#include "group_games.h"
-#define RoQ_MAGIC_NUMBER 0x1084
#define RoQ_CHUNK_PREAMBLE_SIZE 8
#define RoQ_AUDIO_SAMPLE_RATE 22050
@@ -93,10 +92,11 @@ static int open_roq_file(demux_roq_t *this) {
return 0;
/* check for the RoQ magic numbers */
- if ((_X_LE_16(&preamble[0]) != RoQ_MAGIC_NUMBER) ||
- (_X_LE_32(&preamble[2]) != 0xFFFFFFFF))
+ static const uint8_t RoQ_MAGIC_STRING[] =
+ { 0x10, 0x84, 0xFF, 0xFF, 0xFF, 0xFF };
+ if( memcmp(preamble, RoQ_MAGIC_STRING, sizeof(RoQ_MAGIC_STRING)) != 0 )
return 0;
-
+
this->bih.biSize = sizeof(xine_bmiheader);
this->bih.biWidth = this->bih.biHeight = 0;
this->wave.nChannels = 0; /* assume no audio at first */
@@ -119,7 +119,7 @@ static int open_roq_file(demux_roq_t *this) {
while (i-- > 0) {
/* if this read fails, then maybe it's just a really small RoQ file
* (even less than 2 seconds) */
- if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
RoQ_CHUNK_PREAMBLE_SIZE)
break;
chunk_type = _X_LE_16(&preamble[0]);
@@ -181,7 +181,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) {
off_t current_file_pos;
/* fetch the next preamble */
- if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
+ if (this->input->read(this->input, preamble, RoQ_CHUNK_PREAMBLE_SIZE) !=
RoQ_CHUNK_PREAMBLE_SIZE) {
this->status = DEMUX_FINISHED;
return this->status;
@@ -193,21 +193,21 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) {
if ((chunk_type == RoQ_SOUND_MONO) || (chunk_type == RoQ_SOUND_STEREO)) {
if( this->audio_fifo ) {
-
+
/* do this calculation carefully because I can't trust the
* 64-bit numerical manipulation */
audio_pts = this->audio_byte_count;
audio_pts *= 90000;
audio_pts /= (RoQ_AUDIO_SAMPLE_RATE * this->wave.nChannels);
this->audio_byte_count += chunk_size - 8; /* do not count the preamble */
-
+
current_file_pos = this->input->get_current_pos(this->input);
/* send out the preamble */
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_ROQ;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) *
+ buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) *
65535 / this->input->get_length (this->input) );
buf->pts = 0;
buf->size = RoQ_CHUNK_PREAMBLE_SIZE;
@@ -219,7 +219,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_ROQ;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) current_file_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_file_pos *
65535 / this->input->get_length (this->input) );
buf->pts = audio_pts;
@@ -256,7 +256,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_ROQ;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) *
+ buf->extra_info->input_normpos = (int)( (double) (current_file_pos - RoQ_CHUNK_PREAMBLE_SIZE) *
65535 / this->input->get_length (this->input) );
buf->pts = this->video_pts_counter;
buf->size = RoQ_CHUNK_PREAMBLE_SIZE;
@@ -267,7 +267,7 @@ static int demux_roq_send_chunk(demux_plugin_t *this_gen) {
buf = this->video_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_VIDEO_ROQ;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) current_file_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_file_pos *
65535 / this->input->get_length (this->input) );
buf->pts = this->video_pts_counter;
@@ -411,7 +411,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_roq_t));
+ this = calloc(1, sizeof(demux_roq_t));
this->stream = stream;
this->input = input;
@@ -485,7 +485,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_roq_init_plugin (xine_t *xine, void *data) {
demux_roq_class_t *this;
- this = xine_xmalloc (sizeof (demux_roq_class_t));
+ this = calloc(1, sizeof(demux_roq_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_shn.c b/src/demuxers/demux_shn.c
index 87324ab45..b4f7c764b 100644
--- a/src/demuxers/demux_shn.c
+++ b/src/demuxers/demux_shn.c
@@ -83,16 +83,16 @@ static int demux_shn_send_chunk(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_SHORTEN;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
buf->pts = 0;
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
- } else
+ } else
buf->size = bytes_read;
/* each buffer stands on its own */
@@ -182,7 +182,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_shn_t *this;
- this = xine_xmalloc (sizeof (demux_shn_t));
+ this = calloc(1, sizeof(demux_shn_t));
this->stream = stream;
this->input = input;
@@ -253,7 +253,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_shn_init_plugin (xine_t *xine, void *data) {
demux_shn_class_t *this;
- this = xine_xmalloc (sizeof (demux_shn_class_t));
+ this = calloc(1, sizeof(demux_shn_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_slave.c b/src/demuxers/demux_slave.c
index 436d37579..de530f224 100644
--- a/src/demuxers/demux_slave.c
+++ b/src/demuxers/demux_slave.c
@@ -2,19 +2,19 @@
* Copyright (C) 2000-2003 the xine project
* May 2003 - Miguel Freitas
* This plugin was sponsored by 1Control
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -51,7 +51,7 @@
#define CHECK_VPTS_INTERVAL 2*90000
#define NETWORK_PREBUFFER 90000
-typedef struct {
+typedef struct {
demux_plugin_t demux_plugin;
xine_stream_t *stream;
@@ -86,14 +86,15 @@ static int demux_slave_next (demux_slave_t *this) {
char fifo_name[11];
uint8_t *p, *s;
int64_t curvpts;
-
+
/* fill the scratch buffer */
n = this->input->read(this->input, &this->scratch[this->scratch_used],
SCRATCH_SIZE - this->scratch_used);
- this->scratch_used += n;
+ if (n > 0)
+ this->scratch_used += n;
this->scratch[this->scratch_used] = '\0';
- if( !n ) {
+ if (n <= 0) {
lprintf("connection closed\n");
this->status = DEMUX_FINISHED;
return 0;
@@ -186,10 +187,8 @@ static int demux_slave_next (demux_slave_t *this) {
buf->decoder_flags = decoder_flags;
/* set decoder info */
- for( i = 0; i < BUF_NUM_DEC_INFO; i++ ) {
- buf->decoder_info[i] = this->decoder_info[i];
- buf->decoder_info_ptr[i] = this->decoder_info_ptr[i];
- }
+ memcpy(buf->decoder_info, this->decoder_info, sizeof(this->decoder_info));
+ memcpy(buf->decoder_info_ptr, this->decoder_info_ptr, sizeof(this->decoder_info));
memset(this->decoder_info, 0, sizeof(this->decoder_info));
memset(this->decoder_info_ptr, 0, sizeof(this->decoder_info_ptr));
@@ -331,7 +330,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_slave_t *this;
static char slave_id_str[] = "master xine v1\n";
- this = xine_xmalloc (sizeof (demux_slave_t));
+ this = calloc(1, sizeof(demux_slave_t));
switch (stream->content_detection_method) {
@@ -414,7 +413,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_slave_class_t *this;
- this = xine_xmalloc (sizeof (demux_slave_class_t));
+ this = calloc(1, sizeof(demux_slave_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
@@ -434,7 +433,7 @@ static const demuxer_info_t demux_info_slave = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "slave", XINE_VERSION_CODE, &demux_info_slave, init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_smjpeg.c b/src/demuxers/demux_smjpeg.c
index 899fbf7e3..04a46fa78 100644
--- a/src/demuxers/demux_smjpeg.c
+++ b/src/demuxers/demux_smjpeg.c
@@ -55,7 +55,6 @@
#define vidD_TAG FOURCC_TAG('v', 'i', 'd', 'D')
#define APCM_TAG FOURCC_TAG('A', 'P', 'C', 'M')
-#define SMJPEG_SIGNATURE_SIZE 8
/* 16 is the max size of a header chunk (the video header) */
#define SMJPEG_VIDEO_HEADER_SIZE 16
#define SMJPEG_AUDIO_HEADER_SIZE 12
@@ -98,27 +97,22 @@ static int open_smjpeg_file(demux_smjpeg_t *this) {
unsigned char header_chunk[SMJPEG_HEADER_CHUNK_MAX_SIZE];
unsigned int audio_codec = 0;
- if (_x_demux_read_header(this->input, signature, SMJPEG_SIGNATURE_SIZE) !=
- SMJPEG_SIGNATURE_SIZE)
+ static const uint8_t SMJPEG_SIGNATURE[8] =
+ { 0x00, 0x0A, 'S', 'M', 'J', 'P', 'E', 'G' };
+
+ if (_x_demux_read_header(this->input, signature, sizeof(SMJPEG_SIGNATURE)) !=
+ sizeof(SMJPEG_SIGNATURE))
return 0;
- /* check for the SMJPEG signature */
- if ((signature[0] != 0x00) ||
- (signature[1] != 0x0A) ||
- (signature[2] != 'S') ||
- (signature[3] != 'M') ||
- (signature[4] != 'J') ||
- (signature[5] != 'P') ||
- (signature[6] != 'E') ||
- (signature[7] != 'G'))
+ if (memcmp(signature, SMJPEG_SIGNATURE, sizeof(SMJPEG_SIGNATURE)) != 0)
return 0;
/* file is qualified; jump over the header + version to the duration */
- this->input->seek(this->input, SMJPEG_SIGNATURE_SIZE + 4, SEEK_SET);
+ this->input->seek(this->input, sizeof(SMJPEG_SIGNATURE) + 4, SEEK_SET);
if (this->input->read(this->input, header_chunk, 4) != 4)
return 0;
this->duration = _X_BE_32(&header_chunk[0]);
-
+
/* initial state: no video and no audio (until headers found) */
this->video_type = this->audio_type = 0;
this->input_length = this->input->get_length (this->input);
@@ -400,7 +394,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_smjpeg_t));
+ this = calloc(1, sizeof(demux_smjpeg_t));
this->stream = stream;
this->input = input;
@@ -474,7 +468,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_smjpeg_init_plugin (xine_t *xine, void *data) {
demux_smjpeg_class_t *this;
- this = xine_xmalloc (sizeof (demux_smjpeg_class_t));
+ this = calloc(1, sizeof(demux_smjpeg_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_snd.c b/src/demuxers/demux_snd.c
index 0965a75ae..66e2bd543 100644
--- a/src/demuxers/demux_snd.c
+++ b/src/demuxers/demux_snd.c
@@ -42,8 +42,6 @@
#define SND_HEADER_SIZE 24
#define PCM_BLOCK_ALIGN 1024
-/* this is the big-endian hex value '.snd' */
-#define snd_TAG 0x2E736E64
typedef struct {
demux_plugin_t demux_plugin;
@@ -83,7 +81,7 @@ static int open_snd_file(demux_snd_t *this) {
return 0;
/* check the signature */
- if (_X_BE_32(&header[0]) != snd_TAG)
+ if ( !_x_is_fourcc(&header[0], ".snd") )
return 0;
/* file is qualified; skip over the header bytes in the stream */
@@ -112,11 +110,11 @@ static int open_snd_file(demux_snd_t *this) {
this->audio_bytes_per_second = this->audio_channels *
this->audio_sample_rate;
break;
-
+
case 2:
this->audio_type = BUF_AUDIO_LPCM_BE;
this->audio_bits = 8;
- this->audio_frames = this->data_size /
+ this->audio_frames = this->data_size /
(this->audio_channels * this->audio_bits / 8);
this->audio_block_align = PCM_BLOCK_ALIGN;
this->audio_bytes_per_second = this->audio_channels *
@@ -126,7 +124,7 @@ static int open_snd_file(demux_snd_t *this) {
case 3:
this->audio_type = BUF_AUDIO_LPCM_BE;
this->audio_bits = 16;
- this->audio_frames = this->data_size /
+ this->audio_frames = this->data_size /
(this->audio_channels * this->audio_bits / 8);
this->audio_block_align = PCM_BLOCK_ALIGN;
this->audio_bytes_per_second = this->audio_channels *
@@ -165,7 +163,7 @@ static int demux_snd_send_chunk(demux_plugin_t *this_gen) {
/* just load data chunks from wherever the stream happens to be
* pointing; issue a DEMUX_FINISHED status if EOF is reached */
remaining_sample_bytes = this->audio_block_align;
- current_file_pos =
+ current_file_pos =
this->input->get_current_pos(this->input) - this->data_start;
current_pts = current_file_pos;
@@ -207,7 +205,7 @@ static int demux_snd_send_chunk(demux_plugin_t *this_gen) {
for (i = 0; i < buf->size; i++)
buf->content[i] += 0x80;
}
-
+
this->audio_fifo->put (this->audio_fifo, buf);
}
return this->status;
@@ -253,11 +251,11 @@ static int demux_snd_seek (demux_plugin_t *this_gen, off_t start_pos, int start_
demux_snd_t *this = (demux_snd_t *) this_gen;
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
-
+
this->seek_flag = 1;
this->status = DEMUX_OK;
_x_demux_flush_engine (this->stream);
-
+
/* if input is non-seekable, do not proceed with the rest of this
* seek function */
if (!INPUT_IS_SEEKABLE(this->input))
@@ -318,7 +316,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_snd_t *this;
- this = xine_xmalloc (sizeof (demux_snd_t));
+ this = calloc(1, sizeof(demux_snd_t));
this->stream = stream;
this->input = input;
@@ -348,7 +346,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
}
}
/* falling through is intended */
-
+
case METHOD_BY_CONTENT:
case METHOD_EXPLICIT:
@@ -382,7 +380,7 @@ static const char *get_extensions (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;";
+ "audio/x-pn-au: snd,au: ULAW (Sun) audio;";
}
@@ -395,7 +393,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_snd_init_plugin (xine_t *xine, void *data) {
demux_snd_class_t *this;
- this = xine_xmalloc (sizeof (demux_snd_class_t));
+ this = calloc(1, sizeof(demux_snd_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_str.c b/src/demuxers/demux_str.c
index 2cf542014..d88432817 100644
--- a/src/demuxers/demux_str.c
+++ b/src/demuxers/demux_str.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2003 the xine project
+ * Copyright (C) 2000-2008 the xine project
*
* This file is part of xine, a free video player.
*
@@ -102,7 +102,7 @@
* - then follows 16-bit RLE data until the EOD
* - RLE format: bits 15-10: # of 0s preceding this value (unsigned)
* bits 9-0: this value (signed)
- * - e.g. 3 bytes (2,10)(0,20)(3,30) -> 0 0 10 20 0 0 0 30
+ * - e.g. 3 bytes (2,10)(0,20)(3,30) -> 0 0 10 20 0 0 0 30
* - 16 bits: EOD (0xFE00)
* - 16 bits: 0xFE00 end-of-data footer
*/
@@ -139,20 +139,15 @@
#define CD_RAW_SECTOR_SIZE 2352
+#define STR_MAGIC "\x60\x01\x01\x80"
#define STR_MAX_CHANNELS 32
-#define STR_MAGIC (0x80010160)
-
#define CDXA_TYPE_MASK 0x0E
#define CDXA_TYPE_DATA 0x08
#define CDXA_TYPE_AUDIO 0x04
#define CDXA_TYPE_VIDEO 0x02
#define CDXA_SUBMODE_EOF 0x80 /* set if EOF */
-#define FOURCC_TAG BE_FOURCC
-#define RIFF_TAG FOURCC_TAG('R', 'I', 'F', 'F')
-#define CDXA_TAG FOURCC_TAG('C', 'D', 'X', 'A')
-
/* FIXME */
#define FRAME_DURATION 45000
@@ -188,9 +183,7 @@ static int open_str_file(demux_str_t *this) {
unsigned char check_bytes[STR_CHECK_BYTES];
int local_offset, sector, channel;
- for (channel = 0; channel < STR_MAX_CHANNELS; channel++) {
- this->channel_type[channel] = 0;
- }
+ memset(this->channel_type, 0, sizeof(this->channel_type));
this->input->seek(this->input, 0, SEEK_SET);
if (this->input->read(this->input, check_bytes, STR_CHECK_BYTES) !=
@@ -200,8 +193,8 @@ static int open_str_file(demux_str_t *this) {
}
/* check for STR with a RIFF header */
- if ((_X_BE_32(&check_bytes[0]) == RIFF_TAG) &&
- (_X_BE_32(&check_bytes[8]) == CDXA_TAG))
+ if ( _x_is_fourcc(&check_bytes[0], "RIFF") &&
+ _x_is_fourcc(&check_bytes[8], "CDXA") )
local_offset = 0x2C;
else
local_offset = 0;
@@ -218,16 +211,20 @@ static int open_str_file(demux_str_t *this) {
check_bytes[local_offset + 0x13]);
/* check for 12-byte sync marker */
- if ((_X_BE_32(&check_bytes[local_offset + 0]) != 0x00FFFFFF) ||
- (_X_BE_32(&check_bytes[local_offset + 4]) != 0xFFFFFFFF) ||
- (_X_BE_32(&check_bytes[local_offset + 8]) != 0xFFFFFF00)) {
+ static const uint8_t sync_marker[12] =
+ { 0x00, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0xFF, 0xFF, 0X00
+ };
+ if ( memcmp(&check_bytes[local_offset],
+ sync_marker, sizeof(sync_marker)) != 0 ) {
lprintf("sector %d sync error\n", sector);
return 0;
}
/* the 32 bits starting at 0x10 and at 0x14 should be the same */
- if (_X_BE_32(&check_bytes[local_offset + 0x10]) !=
- _X_BE_32(&check_bytes[local_offset + 0x14])) {
+ if (memcmp(&check_bytes[local_offset + 0x10],
+ &check_bytes[local_offset + 0x14], 4) != 0) {
lprintf("sector %d control bits copy error\n", sector);
return 0;
}
@@ -246,7 +243,7 @@ static int open_str_file(demux_str_t *this) {
case CDXA_TYPE_VIDEO:
/* first time we have seen video/data in this channel? */
if ((!(this->channel_type[channel] & CDXA_TYPE_DATA)) &&
- (_X_LE_32(&check_bytes[local_offset + 0x18]) == STR_MAGIC)) {
+ (_x_is_fourcc(&check_bytes[local_offset + 0x18], STR_MAGIC))) {
/* mark this channel as having video data */
this->channel_type[channel] |= CDXA_TYPE_VIDEO;
@@ -347,7 +344,7 @@ static int demux_str_send_chunk(demux_plugin_t *this_gen) {
case CDXA_TYPE_DATA:
/* video chunk */
- if (_X_LE_32(&sector[0x18]) != STR_MAGIC ||
+ if (!_x_is_fourcc(&sector[0x18], STR_MAGIC) ||
channel != this->default_video_channel) {
return 0;
}
@@ -370,7 +367,7 @@ static int demux_str_send_chunk(demux_plugin_t *this_gen) {
*/
if( this->data_size )
- buf->extra_info->input_normpos = (int)( (double) current_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_pos *
65535 / this->data_size );
buf->extra_info->input_time = (current_pos*1000)/(CD_RAW_SECTOR_SIZE*75);
@@ -408,7 +405,7 @@ static int demux_str_send_chunk(demux_plugin_t *this_gen) {
}
if( this->data_size )
- buf->extra_info->input_normpos = (int)( (double) current_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_pos *
65535 / this->data_size );
buf->extra_info->input_time = (current_pos*1000)/(CD_RAW_SECTOR_SIZE*75);
@@ -532,7 +529,7 @@ static int demux_str_get_status (demux_plugin_t *this_gen) {
static int demux_str_get_stream_length (demux_plugin_t *this_gen) {
demux_str_t *this = (demux_str_t *) this_gen;
- return (int)((int64_t) this->input->get_length(this->input)
+ return (int)((int64_t) this->input->get_length(this->input)
* 1000 / (CD_RAW_SECTOR_SIZE * 75));
}
@@ -555,7 +552,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_str_t));
+ this = calloc(1, sizeof(demux_str_t));
this->stream = stream;
this->input = input;
@@ -578,7 +575,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
mrl = input->get_mrl (input);
extensions = class_gen->get_extensions (class_gen);
-
+
if (!_x_demux_check_extension (mrl, extensions)) {
free (this);
return NULL;
@@ -628,7 +625,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_str_init_plugin (xine_t *xine, void *data) {
demux_str_class_t *this;
- this = xine_xmalloc (sizeof (demux_str_class_t));
+ this = calloc(1, sizeof(demux_str_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_ts.c b/src/demuxers/demux_ts.c
index 86a14f019..1a19340f3 100644
--- a/src/demuxers/demux_ts.c
+++ b/src/demuxers/demux_ts.c
@@ -1,3 +1,4 @@
+
/*
* Copyright (C) 2000-2003 the xine project
*
@@ -33,8 +34,13 @@
* Date Author
* ---- ------
*
+ * 8-Apr-2009 Petri Hintukainen <phi@sdf-eu.org>
+ * - support for 192-byte packets (HDMV/BluRay)
+ * - support for audio inside PES PID 0xfd (HDMV/BluRay)
+ * - demux HDMV/BluRay bitmap subtitles
+ *
* 28-Nov-2004 Mike Lampard <mlampard>
- * - Added support for PMT sections larger than 1 ts packet
+ * - Added support for PMT sections larger than 1 ts packet
*
* 28-Aug-2004 James Courtier-Dutton <jcdutton>
* - Improve PAT and PMT handling. Added some FIXME comments.
@@ -52,7 +58,7 @@
* - dynamic allocation leaks fixes
*
* 27-May-2002 Giovanni Baronetti and Mauro Borghi <mauro.borghi@tilab.com>
- * - fill buffers before putting them in fifos
+ * - fill buffers before putting them in fifos
* - force PMT reparsing when PMT PID changes
* - accept non seekable input plugins -- FIX?
* - accept dvb as input plugin
@@ -167,14 +173,14 @@
#define PKT_SIZE 188
#define BODY_SIZE (188 - 4)
/* more PIDS are needed due "auto-detection". 40 spare media entries */
-#define MAX_PIDS ((BODY_SIZE - 1 - 13) / 4) + 40
+#define MAX_PIDS ((BODY_SIZE - 1 - 13) / 4) + 40
#define MAX_PMTS ((BODY_SIZE - 1 - 13) / 4) + 10
#define SYNC_BYTE 0x47
#define MIN_SYNCS 3
-#define NPKT_PER_READ 100
+#define NPKT_PER_READ 96 // 96*188 = 94*192
-#define BUF_SIZE (NPKT_PER_READ * PKT_SIZE)
+#define BUF_SIZE (NPKT_PER_READ * (PKT_SIZE + 4))
#define MAX_PES_BUF_SIZE 2048
@@ -185,9 +191,6 @@
#define INVALID_PROGRAM ((unsigned int)(-1))
#define INVALID_CC ((unsigned int)(-1))
-#define MIN(a,b) (((a)<(b))?(a):(b))
-#define MAX(a,b) (((a)>(b))?(a):(b))
-
#define PROG_STREAM_MAP 0xBC
#define PRIVATE_STREAM1 0xBD
#define PADDING_STREAM 0xBE
@@ -220,7 +223,23 @@
ISO_13818_PART7_AUDIO = 0x0f, /* ISO/IEC 13818-7 Audio with ADTS transport sytax */
ISO_14496_PART2_VIDEO = 0x10, /* ISO/IEC 14496-2 Visual (MPEG-4) */
ISO_14496_PART3_AUDIO = 0x11, /* ISO/IEC 14496-3 Audio with LATM transport syntax */
- ISO_14496_PART10_VIDEO = 0x1b /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */
+ ISO_14496_PART10_VIDEO = 0x1b, /* ISO/IEC 14496-10 Video (MPEG-4 part 10/AVC, aka H.264) */
+ STREAM_VIDEO_MPEG = 0x80,
+ STREAM_AUDIO_AC3 = 0x81,
+
+ STREAM_VIDEO_VC1 = 0xea, /* VC-1 Video */
+
+ HDMV_AUDIO_80_PCM = 0x80, /* BluRay PCM */
+ HDMV_AUDIO_82_DTS = 0x82, /* DTS */
+ HDMV_AUDIO_83_TRUEHD = 0x83, /* Dolby TrueHD, primary audio */
+ HDMV_AUDIO_84_EAC3 = 0x84, /* Dolby Digital plus, primary audio */
+ HDMV_AUDIO_85_DTS_HRA = 0x85, /* DTS-HRA */
+ HDMV_AUDIO_86_DTS_HD_MA = 0x86, /* DTS-HD Master audio */
+
+ HDMV_SPU_BITMAP = 0x90,
+ HDMV_SPU_INTERACTIVE = 0x91,
+ HDMV_SPU_TEXT = 0x92,
+
} streamType;
#define WRAP_THRESHOLD 270000
@@ -228,6 +247,11 @@
#define PTS_AUDIO 0
#define PTS_VIDEO 1
+#undef MIN
+#define MIN(a,b) ((a)<(b)?(a):(b))
+#undef MAX
+#define MAX(a,b) ((a)>(b)?(a):(b))
+
/*
**
** DATA STRUCTURES
@@ -246,24 +270,25 @@ typedef struct {
int64_t pts;
buf_element_t *buf;
unsigned int counter;
- uint8_t descriptor_tag;
+ uint16_t descriptor_tag; /* +0x100 for PES stream IDs (no available TS descriptor tag?) */
int64_t packet_count;
int corrupted_pes;
uint32_t buffered_bytes;
+ int autodetected;
} demux_ts_media;
/* DVBSUB */
-#define MAX_SPU_LANGS 16
+#define MAX_SPU_LANGS 32
typedef struct {
spu_dvb_descriptor_t desc;
int pid;
int media_index;
} demux_ts_spu_lang;
-
+
/* Audio Channels */
-#define MAX_AUDIO_TRACKS 16
+#define MAX_AUDIO_TRACKS 32
typedef struct {
int pid;
@@ -288,6 +313,10 @@ typedef struct {
int status;
+ int hdmv; /* -1 = unknown, 0 = mpeg-ts, 1 = hdmv/m2ts */
+ int pkt_size; /* TS packet size */
+ int pkt_offset; /* TS packet offset */
+
int blockSize;
int rate;
int media_num;
@@ -309,10 +338,10 @@ typedef struct {
unsigned int pid_count;
unsigned int videoPid;
unsigned int videoMedia;
-
+
demux_ts_audio_track audio_tracks[MAX_AUDIO_TRACKS];
int audio_tracks_count;
-
+
int send_end_buffers;
int64_t last_pts[2];
int send_newpts;
@@ -340,7 +369,7 @@ typedef struct {
int32_t npkt_read;
uint8_t buf[BUF_SIZE]; /* == PKT_SIZE * NPKT_PER_READ */
-
+
int numPreview;
} demux_ts_t;
@@ -368,7 +397,7 @@ static void demux_ts_build_crc32_table(demux_ts_t*this) {
}
}
-static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data,
+static uint32_t demux_ts_compute_crc32(demux_ts_t*this, uint8_t *data,
int32_t length, uint32_t crc32) {
int32_t i;
@@ -413,7 +442,7 @@ static void check_newpts( demux_ts_t *this, int64_t pts, int video )
The original code worked well when the wrap happend like this:
V7 A7 V8 V9 A9 Dv V0 V1 da A1 V2 V3 A3 V4
-
+
Legend:
Vn = video packet with timestamp n
An = audio packet with timestamp n
@@ -431,27 +460,27 @@ static void check_newpts( demux_ts_t *this, int64_t pts, int video )
a delay of almoust 26.5 hours!
The new code gives the following sequences for the above examples:
-
+
V7 A7 V8 V9 A9 Dv V0 V1 A1 V2 V3 A3 V4
V7 V8 A7 V9 Dv V0 Da A9 Dv V1 V2 A1 V3 V4 A3
After proving this code it should be cleaned up to use just a single variable "last_pts". */
-
+
/*
this->last_pts[video] = pts;
-*/
+*/
this->last_pts[video] = this->last_pts[1-video] = pts;
}
}
/* Send a BUF_SPU_DVB to let xine know of that channel. */
-static void demux_send_special_spu_buf( demux_ts_t *this, int spu_channel )
+static void demux_send_special_spu_buf( demux_ts_t *this, uint32_t spu_type, int spu_channel )
{
buf_element_t *buf;
buf = this->video_fifo->buffer_pool_alloc( this->video_fifo );
- buf->type = BUF_SPU_DVB|spu_channel;
+ buf->type = spu_type|spu_channel;
buf->content = buf->mem;
buf->size = 0;
this->video_fifo->put( this->video_fifo, buf );
@@ -466,7 +495,7 @@ static void demux_send_special_spu_buf( demux_ts_t *this, int spu_channel )
static void demux_ts_update_spu_channel(demux_ts_t *this)
{
buf_element_t *buf;
-
+
this->current_spu_channel = this->stream->spu_channel;
buf = this->video_fifo->buffer_pool_alloc(this->video_fifo);
@@ -475,7 +504,7 @@ static void demux_ts_update_spu_channel(demux_ts_t *this)
buf->decoder_flags = BUF_FLAG_SPECIAL;
buf->decoder_info[1] = BUF_SPECIAL_SPU_DVB_DESCRIPTOR;
buf->size = 0;
-
+
if (this->current_spu_channel >= 0
&& this->current_spu_channel < this->spu_langs_count)
{
@@ -504,6 +533,10 @@ static void demux_ts_update_spu_channel(demux_ts_t *this)
#endif
}
+ if ((this->media[this->spu_media].type & BUF_MAJOR_MASK) == BUF_SPU_HDMV) {
+ buf->type = BUF_SPU_HDMV;
+ }
+
this->video_fifo->put(this->video_fifo, buf);
}
@@ -540,7 +573,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
* indicator set.
*/
if (!pusi) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: demux error! PAT without payload unit start indicator\n");
return;
}
@@ -550,7 +583,7 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
*/
pkt += pkt[4];
if (pkt - original_pkt > PKT_SIZE) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: demux error! PAT with invalid pointer\n");
return;
}
@@ -584,13 +617,13 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
}
if (pkt - original_pkt > BODY_SIZE - 1 - 3 - section_length) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: FIXME: (unsupported )PAT spans multiple TS packets\n");
return;
}
if ((section_number != 0) || (last_section_number != 0)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: FIXME: (unsupported) PAT consists of multiple (%d) sections\n", last_section_number);
return;
}
@@ -599,11 +632,11 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
calc_crc32 = demux_ts_compute_crc32 (this, pkt+5, section_length+3-4,
0xffffffff);
if (crc32 != calc_crc32) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: demux error! PAT with invalid CRC32: packet_crc32: %.8x calc_crc32: %.8x\n",
crc32,calc_crc32);
return;
- }
+ }
#ifdef TS_PAT_LOG
else {
printf ("demux_ts: PAT CRC32 ok.\n");
@@ -647,13 +680,12 @@ static void demux_ts_parse_pat (demux_ts_t*this, unsigned char *original_pkt,
this->last_pmt_crc = 0;
this->videoPid = INVALID_PID;
this->spu_pid = INVALID_PID;
- }
- this->pmt_pid[program_count] = pmt_pid;
- if (this->pmt[program_count] != NULL) {
- free(this->pmt[program_count]);
- this->pmt[program_count] = NULL;
- this->pmt_write_ptr[program_count] = NULL;
+ if (this->pmt[program_count] != NULL) {
+ free(this->pmt[program_count]);
+ this->pmt[program_count] = NULL;
+ this->pmt_write_ptr[program_count] = NULL;
+ }
}
#ifdef TS_PAT_LOG
if (this->program_number[program_count] != INVALID_PROGRAM)
@@ -682,7 +714,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
/* we should have a PES packet here */
if (p[0] || p[1] || (p[2] != 1)) {
- xprintf (xine, XINE_VERBOSITY_DEBUG,
+ xprintf (xine, XINE_VERBOSITY_DEBUG,
"demux_ts: error %02x %02x %02x (should be 0x000001) \n", p[0], p[1], p[2]);
return 0 ;
}
@@ -733,7 +765,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
/* sometimes corruption on header_len causes segfault in memcpy below */
if (header_len + 9 > pkt_len) {
- xprintf (xine, XINE_VERBOSITY_DEBUG,
+ xprintf (xine, XINE_VERBOSITY_DEBUG,
"demux_ts: illegal value for PES_header_data_length (0x%x)\n", header_len);
return 0;
}
@@ -741,10 +773,28 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
p += header_len + 9;
packet_len -= header_len + 3;
- if (stream_id == 0xbd) {
+ if (m->descriptor_tag == STREAM_VIDEO_VC1) {
+ m->content = p;
+ m->size = packet_len;
+ m->type = BUF_VIDEO_VC1;
+ return 1;
+ }
+
+ if (m->descriptor_tag == HDMV_SPU_BITMAP) {
+ long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3;
+
+ m->content = p;
+ m->size = packet_len;
+ m->type |= BUF_SPU_HDMV;
+ m->buf->decoder_info[2] = payload_len;
+ return 1;
+
+ } else
+
+ if (stream_id == 0xbd || stream_id == 0xfd /* HDMV */) {
int spu_id;
-
+
lprintf ("audio buf = %02X %02X %02X %02X %02X %02X %02X %02X\n",
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
@@ -752,15 +802,42 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
* we check the descriptor tag first because some stations
* do not include any of the ac3 header info in their audio tracks
* these "raw" streams may begin with a byte that looks like a stream type.
+ * For audio streams, m->type already contains the stream no.
*/
- if((m->descriptor_tag == 0x81) || /* ac3 - raw */
+ if((m->descriptor_tag == STREAM_AUDIO_AC3) || /* ac3 - raw */
(p[0] == 0x0B && p[1] == 0x77)) { /* ac3 - syncword */
m->content = p;
m->size = packet_len;
m->type |= BUF_AUDIO_A52;
return 1;
- } else if (m->descriptor_tag == 0x06
+ } else if (m->descriptor_tag == HDMV_AUDIO_83_TRUEHD) {
+ /* TODO: separate AC3 and TrueHD streams ... */
+ m->content = p;
+ m->size = packet_len;
+ m->type |= BUF_AUDIO_A52;
+ return 1;
+
+ } else if (m->descriptor_tag == HDMV_AUDIO_82_DTS ||
+ m->descriptor_tag == HDMV_AUDIO_86_DTS_HD_MA ) {
+ m->content = p;
+ m->size = packet_len;
+ m->type |= BUF_AUDIO_DTS;
+ return 1;
+
+ } else if (m->descriptor_tag == HDMV_AUDIO_80_PCM) {
+
+ m->content = p + 4;
+ m->size = packet_len - 4;
+ m->type |= BUF_AUDIO_LPCM_BE;
+
+ m->buf->decoder_flags |= BUF_FLAG_SPECIAL;
+ m->buf->decoder_info[1] = BUF_SPECIAL_LPCM_CONFIG;
+ m->buf->decoder_info[2] = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];
+
+ return 1;
+
+ } else if (m->descriptor_tag == ISO_13818_PES_PRIVATE
&& p[0] == 0x20 && p[1] == 0x00) {
/* DVBSUB */
long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3;
@@ -808,6 +885,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
switch (m->descriptor_tag) {
case ISO_11172_VIDEO:
case ISO_13818_VIDEO:
+ case STREAM_VIDEO_MPEG:
lprintf ("demux_ts: found MPEG video type.\n");
m->type = BUF_VIDEO_MPEG;
break;
@@ -831,7 +909,7 @@ static int demux_ts_parse_pes_header (xine_t *xine, demux_ts_media *m,
m->content = p;
m->size = packet_len;
switch (m->descriptor_tag) {
- case ISO_11172_AUDIO:
+ case ISO_11172_AUDIO:
case ISO_13818_AUDIO:
lprintf ("demux_ts: found MPEG audio track.\n");
m->type |= BUF_AUDIO_MPEG;
@@ -880,7 +958,7 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
case (i.e. adaptation field only) when it does not get bumped. */
if (m->counter != INVALID_CC) {
if ((m->counter & 0x0f) != cc) {
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: PID 0x%.4x: unexpected cc %d (expected %d)\n", m->pid, cc, m->counter);
}
}
@@ -906,13 +984,13 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
else if ( this->numPreview<5 )
m->buf->decoder_flags=BUF_FLAG_PREVIEW;
else
- m->buf->decoder_flags=BUF_FLAG_FRAME_END;
+ m->buf->decoder_flags |= BUF_FLAG_FRAME_END;
}
m->buf->pts = m->pts;
m->buf->decoder_info[0] = 1;
-
+
if( this->input->get_length (this->input) )
- m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
if (this->rate)
m->buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -930,13 +1008,15 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
if (!demux_ts_parse_pes_header(this->stream->xine, m, ts, len, this->stream)) {
m->buf->free_buffer(m->buf);
m->buf = NULL;
-
- if (m->corrupted_pes > CORRUPT_PES_THRESHOLD) {
- if (this->videoPid == m->pid)
+
+ if (m->corrupted_pes > CORRUPT_PES_THRESHOLD && m->autodetected) {
+ if (this->videoPid == m->pid) {
this->videoPid = INVALID_PID;
+ this->last_pmt_crc = 0;
+ }
} else {
m->corrupted_pes++;
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: PID 0x%.4x: corrupted pes encountered\n", m->pid);
}
} else {
@@ -955,7 +1035,7 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts,
m->buf->pts = m->pts;
m->buf->decoder_info[0] = 1;
if( this->input->get_length (this->input) )
- m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
+ m->buf->extra_info->input_normpos = (int)( (double) this->input->get_current_pos (this->input) *
65535 / this->input->get_length (this->input) );
if (this->rate)
m->buf->extra_info->input_time = (int)((int64_t)this->input->get_current_pos (this->input)
@@ -982,7 +1062,7 @@ static void demux_ts_pes_new(demux_ts_t*this,
unsigned int mediaIndex,
unsigned int pid,
fifo_buffer_t *fifo,
- uint8_t descriptor) {
+ uint16_t descriptor) {
demux_ts_media *m = &this->media[mediaIndex];
@@ -1040,7 +1120,7 @@ static void demux_ts_get_reg_desc(demux_ts_t *this, uint32_t *dest,
{
*dest = (d[2] << 24) | (d[3] << 16) | (d[4] << 8) | d[5];
- xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf(this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: found registration format identifier: 0x%.4x\n", *dest);
return;
}
@@ -1062,7 +1142,7 @@ static inline int ts_payloadsize(unsigned char * tsp)
}
return 184;
}
-
+
/*
* NAME demux_ts_parse_pmt
@@ -1092,14 +1172,14 @@ static void demux_ts_parse_pmt (demux_ts_t *this,
uint32_t crc32;
uint32_t calc_crc32;
uint32_t coded_length;
- unsigned int pid;
+ unsigned int pid;
unsigned char *stream;
- unsigned int i;
- int count;
- char *ptr = NULL;
+ unsigned int i;
+ int count;
+ char *ptr = NULL;
unsigned char len;
- unsigned int offset=0;
-
+ unsigned int offset=0;
+
/*
* A new section should start with the payload unit start
* indicator set. We allocate some mem (max. allowed for a PM section)
@@ -1108,7 +1188,7 @@ static void demux_ts_parse_pmt (demux_ts_t *this,
if (pusi) {
pkt+=pkt[4]; /* pointer to start of section */
offset=1;
-
+
if (this->pmt[program_count] != NULL) free(this->pmt[program_count]);
this->pmt[program_count] = (uint8_t *) calloc(4096, sizeof(unsigned char));
this->pmt_write_ptr[program_count] = this->pmt[program_count];
@@ -1152,7 +1232,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
}
if ((section_number != 0) || (last_section_number != 0)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: FIXME (unsupported) PMT consists of multiple (%d) sections\n", last_section_number);
return;
}
@@ -1178,7 +1258,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
len = count-offset;
memcpy (this->pmt_write_ptr[program_count], ptr, len);
this->pmt_write_ptr[program_count] +=len;
-
+
#ifdef TS_PMT_LOG
printf ("ts_demux: wr_ptr: %p, will be %p when finished\n",
this->pmt_write_ptr[program_count],
@@ -1193,6 +1273,15 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
return;
}
+ if (!section_length) {
+ free (this->pmt[program_count]);
+ this->pmt[program_count] = NULL;
+#ifdef TS_PMT_LOG
+ printf ("ts_demux: eek, zero-length section?\n");
+#endif
+ return;
+ }
+
#ifdef TS_PMT_LOG
printf ("ts_demux: have all TS packets for the PMT section\n");
#endif
@@ -1207,9 +1296,9 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
this->pmt[program_count],
section_length+3-4, 0xffffffff);
if (crc32 != calc_crc32) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: demux error! PMT with invalid CRC32: packet_crc32: %#.8x calc_crc32: %#.8x\n",
- crc32,calc_crc32);
+ crc32,calc_crc32);
return;
}
else {
@@ -1230,6 +1319,15 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
}
}
+ /*
+ * Forget the current video, audio and subtitle PIDs; if the PMT has not
+ * changed, we'll pick them up again when we parse this PMT, while if the
+ * PMT has changed (e.g. an IPTV streamer that's just changed its source),
+ * we'll get new PIDs that we should follow.
+ */
+ this->audio_tracks_count = 0;
+ this->videoPid = INVALID_PID;
+ this->spu_pid = INVALID_PID;
/*
* ES definitions start here...we are going to learn upto one video
@@ -1247,7 +1345,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
stream = &this->pmt[program_count][12] + program_info_length;
coded_length = 13 + program_info_length;
if (coded_length > section_length) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux error! PMT with inconsistent progInfo length\n");
return;
}
@@ -1264,7 +1362,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
stream_info_length = ((stream[3] << 8) | stream[4]) & 0x0fff;
coded_length = 5 + stream_info_length;
if (coded_length > section_length) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux error! PMT with inconsistent streamInfo length\n");
return;
}
@@ -1278,6 +1376,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
case ISO_13818_VIDEO:
case ISO_14496_PART2_VIDEO:
case ISO_14496_PART10_VIDEO:
+ case STREAM_VIDEO_VC1:
if (this->videoPid == INVALID_PID) {
#ifdef TS_PMT_LOG
printf ("demux_ts: PMT video pid 0x%.4x type %2.2x\n", pid, stream[0]);
@@ -1331,7 +1430,6 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
case ISO_13818_PES_PRIVATE:
for (i = 5; i < coded_length; i += stream[i+1] + 2) {
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) {
@@ -1344,7 +1442,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
printf ("demux_ts: PMT AC3 audio pid 0x%.4x type %2.2x\n", pid, stream[0]);
#endif
demux_ts_pes_new(this, this->media_num, pid,
- this->audio_fifo, 0x81);
+ this->audio_fifo, STREAM_AUDIO_AC3);
this->audio_tracks[this->audio_tracks_count].pid = pid;
this->audio_tracks[this->audio_tracks_count].media_index = this->media_num;
@@ -1379,9 +1477,9 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
{
int no = this->spu_langs_count;
demux_ts_spu_lang *lang = &this->spu_langs[no];
-
+
this->spu_langs_count++;
-
+
memcpy(lang->desc.lang, &stream[pos], 3);
lang->desc.lang[3] = 0;
lang->desc.comp_page_id =
@@ -1392,7 +1490,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
lang->media_index = this->media_num;
this->media[this->media_num].type = no;
demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]);
- demux_send_special_spu_buf( this, no );
+ demux_send_special_spu_buf( this, BUF_SPU_DVB, no );
#ifdef TS_LOG
printf("demux_ts: DVBSUB: pid 0x%.4x: %s page %ld %ld type %2.2x\n",
pid, lang->desc.lang,
@@ -1405,6 +1503,46 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
}
break;
+ case HDMV_SPU_INTERACTIVE:
+ case HDMV_SPU_TEXT:
+ if (this->hdmv > 0) {
+ printf("demux_ts: Skipping unsupported HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n",
+ stream[0], pid);
+ break;
+ }
+ /* fall thru */
+
+ case HDMV_SPU_BITMAP:
+ if (this->hdmv > 0) {
+ if (pid >= 0x1200 && pid < 0x1300) {
+ /* HDMV Presentation Graphics / SPU */
+
+ if (this->spu_langs_count >= MAX_SPU_LANGS) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ "demux_ts: too many SPU tracks! ignoring pid 0x%.4x\n",
+ pid);
+ break;
+ }
+
+ demux_ts_spu_lang *lang = &this->spu_langs[this->spu_langs_count];
+
+ memset(lang->desc.lang, 0, sizeof(lang->desc.lang));
+ /*memcpy(lang->desc.lang, &stream[pos], 3);*/
+ /*lang->desc.lang[3] = 0;*/
+ lang->pid = pid;
+ lang->media_index = this->media_num;
+ this->media[this->media_num].type = this->spu_langs_count;
+ demux_ts_pes_new(this, this->media_num, pid, this->video_fifo, stream[0]);
+ demux_send_special_spu_buf( this, BUF_SPU_HDMV, this->spu_langs_count );
+ this->spu_langs_count++;
+#ifdef TS_PMT_LOG
+ printf("demux_ts: HDMV subtitle stream_type: 0x%.2x pid: 0x%.4x\n",
+ stream[0], pid);
+#endif
+ break;
+ }
+ }
+ /* fall thru */
default:
/* This following section handles all the cases where the audio track info is stored in PMT user info with stream id >= 0x80
@@ -1412,7 +1550,7 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
* then we check the registration format identifier to see if it holds "AC-3" (0x41432d33) and
* 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->audio_tracks_count < MAX_AUDIO_TRACKS) && (stream[0] >= 0x80) ) {
int i, found = 0;
for(i = 0; i < this->audio_tracks_count; i++) {
@@ -1426,7 +1564,10 @@ printf("Program Number is %i, looking for %i\n",program_number,this->program_num
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)) {
+ if (( format_identifier == 0x41432d33) ||
+ ( format_identifier == 0) ||
+ ((format_identifier == 0x48444d56 || this->hdmv>0) && stream[0] == HDMV_AUDIO_80_PCM) /* BluRay PCM */) {
+
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;
@@ -1491,10 +1632,10 @@ static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG, "demux_ts: about to resync!\n");
for (p=0; p < npkt_read; p++) {
- for(n=0; n < PKT_SIZE; n++) {
+ for(n=0; n < this->pkt_size; n++) {
sync_ok = 1;
for (i=0; i < MIN(MIN_SYNCS, npkt_read - p); i++) {
- if (buf[n + ((i+p) * PKT_SIZE)] != SYNC_BYTE) {
+ if (buf[this->pkt_offset + n + ((i+p) * this->pkt_size)] != SYNC_BYTE) {
sync_ok = 0;
break;
}
@@ -1506,14 +1647,14 @@ static int sync_correct(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) {
if (sync_ok) {
/* Found sync, fill in */
- memmove(&buf[0], &buf[n + p * PKT_SIZE],
- ((PKT_SIZE * (npkt_read - p)) - n));
+ memmove(&buf[0], &buf[n + p * this->pkt_size],
+ ((this->pkt_size * (npkt_read - p)) - n));
read_length = this->input->read(this->input,
- &buf[(PKT_SIZE * (npkt_read - p)) - n],
- n + p * PKT_SIZE);
+ &buf[(this->pkt_size * (npkt_read - p)) - n],
+ n + p * this->pkt_size);
/* FIXME: when read_length is not as required... we now stop demuxing */
- if (read_length != (n + p * PKT_SIZE)) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ if (read_length != (n + p * this->pkt_size)) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts_tsync_correct: sync found, but read failed\n");
return 0;
}
@@ -1531,6 +1672,32 @@ static int sync_detect(demux_ts_t*this, uint8_t *buf, int32_t npkt_read) {
sync_ok = 1;
+ if (this->hdmv) {
+ this->pkt_size = PKT_SIZE + 4;
+ this->pkt_offset = 4;
+ for (i=0; i < MIN(MIN_SYNCS, npkt_read - 3); i++) {
+ if (buf[this->pkt_offset + i * this->pkt_size] != SYNC_BYTE) {
+ sync_ok = 0;
+ break;
+ }
+ }
+ if (sync_ok) {
+ if (this->hdmv < 0) {
+ /* fix npkt_read (packet size is 192, not 188) */
+ this->npkt_read = npkt_read * PKT_SIZE / this->pkt_size;
+ }
+ this->hdmv = 1;
+ return sync_ok;
+ }
+ if (this->hdmv > 0)
+ return sync_correct(this, buf, npkt_read);
+
+ /* plain ts */
+ this->hdmv = 0;
+ this->pkt_size = PKT_SIZE;
+ this->pkt_offset = 0;
+ }
+
for (i=0; i < MIN(MIN_SYNCS, npkt_read); i++) {
if (buf[i * PKT_SIZE] != SYNC_BYTE) {
sync_ok = 0;
@@ -1554,15 +1721,15 @@ static unsigned char * demux_synchronise(demux_ts_t* this) {
/* NEW: handle read returning less packets than NPKT_PER_READ... */
do {
read_length = this->input->read(this->input, this->buf,
- PKT_SIZE * NPKT_PER_READ);
- if (read_length % PKT_SIZE) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ this->pkt_size * NPKT_PER_READ);
+ if (read_length < 0 || read_length % this->pkt_size) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: read returned %d bytes (not a multiple of %d!)\n",
- read_length, PKT_SIZE);
+ read_length, this->pkt_size);
this->status = DEMUX_FINISHED;
return NULL;
}
- this->npkt_read = read_length / PKT_SIZE;
+ this->npkt_read = read_length / this->pkt_size;
#ifdef TS_READ_STATS
this->rstat[this->npkt_read]++;
@@ -1589,13 +1756,13 @@ static unsigned char * demux_synchronise(demux_ts_t* this) {
return NULL;
}
}
- return_pointer = &(this->buf)[PKT_SIZE * this->packet_number];
+ return_pointer = &(this->buf)[this->pkt_offset + this->pkt_size * this->packet_number];
this->packet_number++;
return return_pointer;
}
-static int64_t demux_ts_adaptation_field_parse(uint8_t *data,
+static int64_t demux_ts_adaptation_field_parse(uint8_t *data,
uint32_t adaptation_field_length) {
uint32_t discontinuity_indicator=0;
@@ -1717,7 +1884,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
transport_error_indicator = (originalPkt[1] >> 7) & 0x01;
payload_unit_start_indicator = (originalPkt[1] >> 6) & 0x01;
transport_priority = (originalPkt[1] >> 5) & 0x01;
- pid = ((originalPkt[1] << 8) |
+ pid = ((originalPkt[1] << 8) |
originalPkt[2]) & 0x1fff;
transport_scrambling_control = (originalPkt[3] >> 6) & 0x03;
adaptation_field_control = (originalPkt[3] >> 4) & 0x03;
@@ -1737,8 +1904,8 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
/*
* Discard packets that are obviously bad.
*/
- if (sync_byte != 0x47) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ if (sync_byte != SYNC_BYTE) {
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux error! invalid ts sync byte %.2x\n", sync_byte);
return;
}
@@ -1753,7 +1920,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
if (transport_scrambling_control) {
if (this->videoPid == pid) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: selected videoPid is scrambled; skipping...\n");
}
for (i=0; i < this->scrambled_npids; i++) {
@@ -1778,7 +1945,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
*/
data_offset += adaptation_field_length + 1;
}
-
+
if (! (adaptation_field_control & 0x1)) {
return;
}
@@ -1790,10 +1957,10 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
*/
program_count=0;
if(this->media_num<MAX_PMTS)
- while ((this->program_number[program_count] != INVALID_PROGRAM) &&
- (program_count < MAX_PMTS)) {
+ while ((this->program_number[program_count] != INVALID_PROGRAM) &&
+ (program_count < MAX_PMTS)) {
if (pid == this->pmt_pid[program_count]) {
-
+
#ifdef TS_LOG
printf ("demux_ts: PMT prog: 0x%.4x pid: 0x%.4x\n",
this->program_number[program_count],
@@ -1806,7 +1973,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
}
program_count++;
}
-
+
if (payload_unit_start_indicator && this->media_num < MAX_PIDS){
int pes_stream_id;
if (pid == 0) {
@@ -1820,7 +1987,7 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
#ifdef TS_HEADER_LOG
printf("demux_ts:ts_pes_header:stream_id=0x%.2x\n",pes_stream_id);
#endif
-
+
if ( (pes_stream_id >= VIDEO_STREAM_S) && (pes_stream_id <= VIDEO_STREAM_E) ) {
if ( this->videoPid == INVALID_PID) {
int i, found = 0;
@@ -1830,20 +1997,21 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
break;
}
}
-
+
if (found && (this->media[i].corrupted_pes == 0)) {
this->videoPid = pid;
this->videoMedia = i;
} else if (!found) {
this->videoPid = pid;
this->videoMedia = this->media_num;
- demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, pes_stream_id);
+ this->media[this->videoMedia].autodetected = 1;
+ demux_ts_pes_new(this, this->media_num++, pid, this->video_fifo, 0x100 + pes_stream_id);
}
-
+
if (this->videoPid != INVALID_PID) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: auto-detected video pid 0x%.4x\n", pid);
- }
+ }
}
} else if ( (pes_stream_id >= AUDIO_STREAM_S) && (pes_stream_id <= AUDIO_STREAM_E) ) {
if (this->audio_tracks_count < MAX_AUDIO_TRACKS) {
@@ -1859,20 +2027,21 @@ static void demux_ts_parse_packet (demux_ts_t*this) {
xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: auto-detected audio pid 0x%.4x\n", pid);
#endif
+ /* store PID, index and stream no. */
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_fifo, 0x100 + pes_stream_id);
this->audio_tracks_count++;
}
}
}
}
-
+
if (data_len > PKT_SIZE) {
- xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
+ xprintf (this->stream->xine, XINE_VERBOSITY_DEBUG,
"demux_ts: demux error! invalid payload size %d\n", data_len);
} else {
@@ -1946,7 +2115,7 @@ static void demux_ts_event_handler (demux_ts_t *this) {
this->last_pmt_crc = 0;
_x_demux_control_start (this->stream);
break;
-
+
}
xine_event_free (event);
@@ -1985,7 +2154,7 @@ static void demux_ts_dispose (demux_plugin_t *this_gen) {
}
}
for (i=0; i < MAX_PIDS; i++) {
- if (this->media[i].buf != NULL) {
+ if (this->media[i].buf != NULL) {
this->media[i].buf->free_buffer(this->media[i].buf);
this->media[i].buf = NULL;
}
@@ -2022,23 +2191,23 @@ static void demux_ts_send_headers (demux_plugin_t *this_gen) {
this->last_pmt_crc = 0;
_x_demux_control_start (this->stream);
-
+
this->input->seek (this->input, 0, SEEK_SET);
this->send_newpts = 1;
-
+
demux_ts_build_crc32_table (this);
-
+
this->status = DEMUX_OK ;
this->send_end_buffers = 1;
this->scrambled_npids = 0;
-
+
/* DVBSUB */
this->spu_pid = INVALID_PID;
this->spu_langs_count = 0;
this->current_spu_channel = -1;
-
+
/* FIXME ? */
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
@@ -2065,11 +2234,11 @@ static int demux_ts_seek (demux_plugin_t *this_gen,
}
this->send_newpts = 1;
-
+
for (i=0; i<MAX_PIDS; i++) {
demux_ts_media *m = &this->media[i];
- if (m->buf != NULL)
+ if (m->buf != NULL)
m->buf->free_buffer(m->buf);
m->buf = NULL;
m->counter = INVALID_CC;
@@ -2078,7 +2247,7 @@ static int demux_ts_seek (demux_plugin_t *this_gen,
}
if( !playing ) {
-
+
this->status = DEMUX_OK;
this->buf_flag_seek = 0;
@@ -2088,7 +2257,7 @@ static int demux_ts_seek (demux_plugin_t *this_gen,
_x_demux_flush_engine(this->stream);
}
-
+
return this->status;
}
@@ -2097,7 +2266,7 @@ static int demux_ts_get_stream_length (demux_plugin_t *this_gen) {
demux_ts_t*this = (demux_ts_t*)this_gen;
if (this->rate)
- return (int)((int64_t) this->input->get_length (this->input)
+ return (int)((int64_t) this->input->get_length (this->input)
* 1000 / (this->rate * 50));
else
return 0;
@@ -2119,7 +2288,7 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen,
/* be a bit paranoid */
if (this == NULL || this->stream == NULL)
return DEMUX_OPTIONAL_UNSUPPORTED;
-
+
switch (data_type)
{
case DEMUX_OPTIONAL_DATA_AUDIOLANG:
@@ -2138,7 +2307,7 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen,
if (channel>=0 && channel<this->spu_langs_count) {
memcpy(str, this->spu_langs[channel].desc.lang, 3);
str[3] = 0;}
- else
+ else
strcpy(str, "none");
return DEMUX_OPTIONAL_SUCCESS;
@@ -2147,45 +2316,54 @@ static int demux_ts_get_optional_data(demux_plugin_t *this_gen,
}
}
+static int detect_ts(uint8_t *buf, size_t len, int ts_size)
+{
+ int i, j;
+ int try_again, ts_detected = 0;
+ size_t packs = len / ts_size - 2;
+
+ for (i = 0; i < ts_size; i++) {
+ try_again = 0;
+ if (buf[i] == SYNC_BYTE) {
+ for (j = 1; j < packs; j++) {
+ if (buf[i + j*ts_size] != SYNC_BYTE) {
+ try_again = 1;
+ break;
+ }
+ }
+ if (try_again == 0) {
+#ifdef TS_LOG
+ printf ("demux_ts: found 0x47 pattern at offset %d\n", i);
+#endif
+ ts_detected = 1;
+ }
+ }
+ }
-static demux_plugin_t *open_plugin (demux_class_t *class_gen,
- xine_stream_t *stream,
+ return ts_detected;
+}
+
+static demux_plugin_t *open_plugin (demux_class_t *class_gen,
+ xine_stream_t *stream,
input_plugin_t *input) {
-
+
demux_ts_t *this;
int i;
+ int hdmv = -1;
switch (stream->content_detection_method) {
case METHOD_BY_CONTENT: {
uint8_t buf[2069];
- int i, j;
- int try_again, ts_detected;
- if (!_x_demux_read_header(input, buf, 2069))
+ if (!_x_demux_read_header(input, buf, sizeof(buf)))
return NULL;
- ts_detected = 0;
-
- for (i = 0; i < 188; i++) {
- try_again = 0;
- if (buf[i] == 0x47) {
- for (j = 1; j <= 10; j++) {
- if (buf[i + j*188] != 0x47) {
- try_again = 1;
- break;
- }
- }
- if (try_again == 0) {
-#ifdef TS_LOG
- printf ("demux_ts: found 0x47 pattern at offset %d\n", i);
-#endif
- ts_detected = 1;
- }
- }
- }
-
- if (!ts_detected)
+ if (detect_ts(buf, sizeof(buf), PKT_SIZE))
+ hdmv = 0;
+ else if (detect_ts(buf, sizeof(buf), PKT_SIZE+4))
+ hdmv = 1;
+ else
return NULL;
}
break;
@@ -2193,6 +2371,11 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
case METHOD_BY_EXTENSION: {
const char *const mrl = input->get_mrl (input);
+ if (_x_demux_check_extension (mrl, "m2ts mts"))
+ hdmv = 1;
+ else
+ hdmv = 0;
+
/* check extension */
const char *const extensions = class_gen->get_extensions (class_gen);
@@ -2229,7 +2412,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
* if we reach this point, the input has been accepted.
*/
- this = xine_xmalloc(sizeof(*this));
+ this = calloc(1, sizeof(*this));
this->stream = stream;
this->input = input;
this->blockSize = PKT_SIZE;
@@ -2243,13 +2426,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->demux_plugin.get_capabilities = demux_ts_get_capabilities;
this->demux_plugin.get_optional_data = demux_ts_get_optional_data;
this->demux_plugin.demux_class = class_gen;
-
+
/*
* Initialise our specialised data.
*/
for (i = 0; i < MAX_PIDS; i++) {
this->media[i].pid = INVALID_PID;
this->media[i].buf = NULL;
+ this->media[i].autodetected = 0;
}
for (i = 0; i < MAX_PMTS; i++) {
@@ -2267,14 +2451,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
this->last_pmt_crc = 0;
this->rate = 16000; /* FIXME */
-
- this->status = DEMUX_FINISHED;
-#ifdef TS_READ_STATS
- for (i=0; i<=NPKT_PER_READ; i++) {
- this->rstat[i] = 0;
- }
-#endif
+ this->status = DEMUX_FINISHED;
/* DVBSUB */
this->spu_pid = INVALID_PID;
@@ -2283,9 +2461,14 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
/* dvb */
this->event_queue = xine_event_new_queue (this->stream);
-
+
+ /* HDMV */
+ this->hdmv = hdmv;
+ this->pkt_offset = (hdmv > 0) ? 4 : 0;
+ this->pkt_size = PKT_SIZE + this->pkt_offset;
+
this->numPreview=0;
-
+
return &this->demux_plugin;
}
@@ -2296,7 +2479,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
static const char *get_description (demux_class_t *this_gen) {
return "MPEG Transport Stream demuxer";
}
-
+
static const char *get_identifier (demux_class_t *this_gen) {
return "MPEG_TS";
}
@@ -2317,10 +2500,10 @@ static void class_dispose (demux_class_t *this_gen) {
}
static void *init_class (xine_t *xine, void *data) {
-
+
demux_ts_class_t *this;
-
- this = xine_xmalloc (sizeof (demux_ts_class_t));
+
+ this = calloc(1, sizeof(demux_ts_class_t));
this->config = xine->config;
this->xine = xine;
@@ -2343,7 +2526,7 @@ static const demuxer_info_t demux_info_ts = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "mpeg-ts", XINE_VERSION_CODE, &demux_info_ts, init_class },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c
index f6eadd652..7462cd874 100644
--- a/src/demuxers/demux_tta.c
+++ b/src/demuxers/demux_tta.c
@@ -19,11 +19,21 @@
*
* True Audio demuxer by Diego Pettenò <flameeyes@gentoo.org>
* Inspired by tta libavformat demuxer by Alex Beregszaszi
+ *
+ * Seek + time support added by Kelvie Wong <kelvie@ieee.org>
*/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
#define LOG_MODULE "demux_tta"
#define LOG_VERBOSE
+// This is from the TTA spec, the length (in seconds) of a frame
+// http://www.true-audio.com/TTA_Lossless_Audio_Codec_-_Format_Description
+#define FRAME_TIME 1.04489795918367346939
+
#include "xine_internal.h"
#include "xineutils.h"
#include "demux.h"
@@ -43,6 +53,8 @@ typedef struct {
uint32_t totalframes;
uint32_t currentframe;
+ off_t datastart;
+
int status;
union {
@@ -52,9 +64,9 @@ typedef struct {
uint16_t channels;
uint16_t bits_per_sample;
uint32_t samplerate;
- uint32_t data_length;
+ uint32_t data_length; /* Number of samples */
uint32_t crc32;
- } __attribute__((__packed__)) tta;
+ } XINE_PACKED tta;
uint8_t buffer[22]; /* This is the size of the header */
} header;
} demux_tta_t;
@@ -72,13 +84,13 @@ static int open_tta_file(demux_tta_t *this) {
if (_x_demux_read_header(this->input, peek, 4) != 4)
return 0;
- if ( _X_BE_32(peek) != FOURCC_32('T', 'T', 'A', '1') )
+ if ( !_x_is_fourcc(peek, "TTA1") )
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);
+ framelen = (uint32_t)(FRAME_TIME * 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;
@@ -87,12 +99,15 @@ static int open_tta_file(demux_tta_t *this) {
return 0;
}
- this->seektable = xine_xmalloc(sizeof(uint32_t)*this->totalframes);
+ this->seektable = calloc(this->totalframes, sizeof(uint32_t));
this->input->read(this->input, this->seektable, sizeof(uint32_t)*this->totalframes);
/* Skip the CRC32 */
this->input->seek(this->input, 4, SEEK_CUR);
+ /* Store the offset after the header for seeking */
+ this->datastart = this->input->get_current_pos(this->input);
+
return 1;
}
@@ -100,7 +115,7 @@ 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 ) {
+ if ( this->currentframe >= this->totalframes ) {
this->status = DEMUX_FINISHED;
return this->status;
}
@@ -115,7 +130,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
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->extra_info->total_time = (int)(le2me_32(this->header.tta.data_length) * 1000.0 / le2me_32(this->header.tta.samplerate)); /* milliseconds */
buf->decoder_flags = 0;
/* Set normalised position */
@@ -123,9 +138,13 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
(int) ((double) this->currentframe * 65535 / this->totalframes);
/* Set time */
- /* buf->extra_info->input_time = this->current_sample / this->samplerate; */
+ buf->extra_info->input_time = (int)(FRAME_TIME * this->currentframe)*1000;
bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read);
+ if (bytes_read < 0) {
+ this->status = DEMUX_FINISHED;
+ break;
+ }
buf->size = bytes_read;
@@ -133,7 +152,7 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
if ( bytes_to_read <= 0 )
buf->decoder_flags |= BUF_FLAG_FRAME_END;
-
+
this->audio_fifo->put(this->audio_fifo, buf);
}
@@ -145,6 +164,12 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) {
static void demux_tta_send_headers(demux_plugin_t *this_gen) {
demux_tta_t *this = (demux_tta_t *) this_gen;
buf_element_t *buf;
+ xine_waveformatex wave;
+ uint32_t total_size = sizeof(xine_waveformatex) + sizeof(this->header) +
+ sizeof(uint32_t)*this->totalframes;
+ unsigned char *header;
+
+ header = malloc(total_size);
this->audio_fifo = this->stream->audio_fifo;
@@ -162,32 +187,51 @@ static void demux_tta_send_headers(demux_plugin_t *this_gen) {
/* 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);
+ /* create header */
+ wave.cbSize = total_size - sizeof(xine_waveformatex);
- wave.cbSize = buf->size - sizeof(xine_waveformatex);
- memcpy(buf->content, &wave, sizeof(wave));
+ memcpy(header, &wave, sizeof(wave));
+ memcpy(header+sizeof(xine_waveformatex), this->header.buffer, sizeof(this->header));
+ memcpy(header+sizeof(xine_waveformatex)+sizeof(this->header), this->seektable, sizeof(uint32_t)*this->totalframes);
- this->audio_fifo->put (this->audio_fifo, buf);
+ /* send init info to decoders */
+ if (this->audio_fifo) {
+ uint32_t bytes_left = total_size;
+
+ /* We are sending the seektable as well, and this may be larger than
+ buf->max_size */
+ while (bytes_left) {
+ buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
+ buf->decoder_flags = BUF_FLAG_HEADER|BUF_FLAG_STDHEADER;
+ buf->type = BUF_AUDIO_TTA;
+
+ /* Copy min(bytes_left, max_size) bytes */
+ buf->size = bytes_left < buf->max_size ? bytes_left : buf->max_size;
+ memcpy(buf->content, header+(total_size-bytes_left), buf->size);
+
+ bytes_left -= buf->size;
+
+ /* The decoder information only needs the decoder information on the last
+ buffer element. */
+ if (!bytes_left) {
+ buf->decoder_flags |= 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);
+ }
+ this->audio_fifo->put (this->audio_fifo, buf);
+ }
}
+ free(header);
}
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;
+ uint32_t start_frame;
+ uint32_t frame_index;
+ off_t start_off = this->datastart;
/* if thread is not running, initialize demuxer */
if( !playing ) {
@@ -196,6 +240,27 @@ static int demux_tta_seek (demux_plugin_t *this_gen,
_x_demux_control_newpts(this->stream, 0, 0);
this->status = DEMUX_OK;
+
+ } else {
+
+ /* Get the starting frame */
+ if( start_pos )
+ start_frame = start_pos * this->totalframes / 65535;
+ else
+ start_frame = (uint32_t)((double)start_time/ 1000.0 / FRAME_TIME);
+
+ /* Now we find the offset */
+ for( frame_index = 0; frame_index < start_frame; frame_index++ )
+ start_off += le2me_32(this->seektable[frame_index]);
+
+ /* Let's seek! We store the current frame internally, so let's update that
+ * as well */
+ _x_demux_flush_engine(this->stream);
+ this->input->seek(this->input, start_off, SEEK_SET);
+ this->currentframe = start_frame;
+ _x_demux_control_newpts(this->stream, (int)(FRAME_TIME * start_frame) * 90000, BUF_FLAG_SEEK);
+
+ this->status = DEMUX_OK;
}
return this->status;
@@ -204,6 +269,7 @@ static int demux_tta_seek (demux_plugin_t *this_gen,
static void demux_tta_dispose (demux_plugin_t *this_gen) {
demux_tta_t *this = (demux_tta_t *) this_gen;
+ free(this->seektable);
free(this);
}
@@ -214,9 +280,8 @@ static int demux_tta_get_status (demux_plugin_t *this_gen) {
}
static int demux_tta_get_stream_length (demux_plugin_t *this_gen) {
-// demux_tta_t *this = (demux_tta_t *) this_gen;
-
- return 0;
+ demux_tta_t *this = (demux_tta_t *) this_gen;
+ return le2me_32(this->header.tta.data_length) * 1000.0 / le2me_32(this->header.tta.samplerate); /* milliseconds */
}
static uint32_t demux_tta_get_capabilities(demux_plugin_t *this_gen) {
@@ -233,7 +298,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_tta_t *this;
- this = xine_xmalloc (sizeof (demux_tta_t));
+ this = calloc(1, sizeof(demux_tta_t));
this->stream = stream;
this->input = input;
@@ -295,7 +360,8 @@ static const char *get_extensions (demux_class_t *this_gen) {
}
static const char *get_mimetypes (demux_class_t *this_gen) {
- return NULL;
+ return "audio/x-tta: tta: True Audio;"
+ "audio/tta: tta: True Audio;";
}
static void class_dispose (demux_class_t *this_gen) {
@@ -307,7 +373,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_tta_init_plugin (xine_t *xine, void *data) {
demux_tta_class_t *this;
- this = xine_xmalloc (sizeof (demux_tta_class_t));
+ this = calloc(1, sizeof(demux_tta_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_vmd.c b/src/demuxers/demux_vmd.c
index 8b0087417..6aec12580 100644
--- a/src/demuxers/demux_vmd.c
+++ b/src/demuxers/demux_vmd.c
@@ -19,7 +19,7 @@
*/
/*
- * Sierra Video and Music Data (.vmd) File Demuxer
+ * Sierra Video and Music Data (.vmd) File Demuxer
* by Mike Melanson (melanson@pcisys.net)
* For more information on the VMD file format, visit:
* http://www.pcisys.net/~melanson/codecs/
@@ -109,7 +109,7 @@ static int open_vmd_file(demux_vmd_t *this) {
unsigned int total_frames;
int64_t current_video_pts = 0;
- if (_x_demux_read_header(this->input, vmd_header, VMD_HEADER_SIZE) !=
+ if (_x_demux_read_header(this->input, vmd_header, VMD_HEADER_SIZE) !=
VMD_HEADER_SIZE)
return 0;
@@ -168,7 +168,7 @@ static int open_vmd_file(demux_vmd_t *this) {
return 0;
}
- this->frame_table = xine_xmalloc(this->frame_count * sizeof(vmd_frame_t));
+ this->frame_table = calloc(this->frame_count, sizeof(vmd_frame_t));
current_offset = this->data_start = _X_LE_32(&vmd_header[20]);
this->data_size = toc_offset - this->data_start;
@@ -234,7 +234,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_VMD;
if( this->data_size )
- buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
+ buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
65535 / this->data_size);
memcpy(buf->content, frame->frame_record, BYTES_PER_FRAME_RECORD);
buf->size = BYTES_PER_FRAME_RECORD;
@@ -246,7 +246,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) {
buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_VMD;
if( this->data_size )
- buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
+ buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
65535 / this->data_size);
if (remaining_bytes > buf->max_size)
@@ -277,7 +277,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_VMD;
if( this->data_size )
- buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
+ buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
65535 / this->data_size);
memcpy(buf->content, frame->frame_record, BYTES_PER_FRAME_RECORD);
buf->size = BYTES_PER_FRAME_RECORD;
@@ -289,7 +289,7 @@ static int demux_vmd_send_chunk(demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_VMD;
if( this->data_size )
- buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
+ buf->extra_info->input_normpos = (int)( (double) (frame->frame_offset - this->data_start) *
65535 / this->data_size);
if (remaining_bytes > buf->max_size)
@@ -421,7 +421,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_vmd_t *this;
- this = xine_xmalloc (sizeof (demux_vmd_t));
+ this = calloc(1, sizeof(demux_vmd_t));
this->stream = stream;
this->input = input;
@@ -495,7 +495,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_vmd_init_plugin (xine_t *xine, void *data) {
demux_vmd_class_t *this;
- this = xine_xmalloc (sizeof (demux_vmd_class_t));
+ this = calloc(1, sizeof(demux_vmd_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_voc.c b/src/demuxers/demux_voc.c
index 0439980f8..1ddbc1727 100644
--- a/src/demuxers/demux_voc.c
+++ b/src/demuxers/demux_voc.c
@@ -85,7 +85,7 @@ static int open_voc_file(demux_voc_t *this) {
return 0;
/* check the signature */
- if (strncmp(header, VOC_SIGNATURE, strlen(VOC_SIGNATURE)) != 0)
+ if (memcmp(header, VOC_SIGNATURE, sizeof(VOC_SIGNATURE)-1) != 0)
return 0;
/* file is qualified */
@@ -93,7 +93,7 @@ static int open_voc_file(demux_voc_t *this) {
this->input->seek(this->input, first_block_offset, SEEK_SET);
/* load the block preamble */
- if (this->input->read(this->input, preamble, BLOCK_PREAMBLE_SIZE) !=
+ if (this->input->read(this->input, preamble, BLOCK_PREAMBLE_SIZE) !=
BLOCK_PREAMBLE_SIZE)
return 0;
@@ -106,7 +106,7 @@ static int open_voc_file(demux_voc_t *this) {
}
/* assemble 24-bit, little endian length */
- this->data_size = preamble[1] | (preamble[2] << 8) | (preamble[3] << 16);
+ this->data_size = _X_LE_24(&preamble[1]);
/* get the next 2 bytes (re-use preamble bytes) */
if (this->input->read(this->input, preamble, 2) != 2)
@@ -142,7 +142,7 @@ static int demux_voc_send_chunk(demux_plugin_t *this_gen) {
/* just load data chunks from wherever the stream happens to be
* pointing; issue a DEMUX_FINISHED status if EOF is reached */
remaining_sample_bytes = PCM_BLOCK_ALIGN;
- current_file_pos =
+ current_file_pos =
this->input->get_current_pos(this->input) - this->data_start;
current_pts = current_file_pos;
@@ -231,7 +231,7 @@ static int demux_voc_seek (demux_plugin_t *this_gen, off_t start_pos, int start_
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
-
+
this->seek_flag = 1;
this->status = DEMUX_OK;
_x_demux_flush_engine (this->stream);
@@ -296,7 +296,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_voc_t *this;
- this = xine_xmalloc (sizeof (demux_voc_t));
+ this = calloc(1, sizeof(demux_voc_t));
this->stream = stream;
this->input = input;
@@ -370,7 +370,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_voc_init_plugin (xine_t *xine, void *data) {
demux_voc_class_t *this;
- this = xine_xmalloc (sizeof (demux_voc_class_t));
+ this = calloc(1, sizeof(demux_voc_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_vox.c b/src/demuxers/demux_vox.c
index 3ce2ad705..ccf9bf877 100644
--- a/src/demuxers/demux_vox.c
+++ b/src/demuxers/demux_vox.c
@@ -77,7 +77,7 @@ static int demux_vox_send_chunk (demux_plugin_t *this_gen) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_DIALOGIC_IMA;
bytes_read = this->input->read(this->input, buf->content, buf->max_size);
- if (bytes_read == 0) {
+ if (bytes_read <= 0) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
return this->status;
@@ -87,7 +87,7 @@ static int demux_vox_send_chunk (demux_plugin_t *this_gen) {
buf->size = buf->max_size;
if( this->input->get_length (this->input) )
- buf->extra_info->input_normpos = (int)( (double) current_file_pos *
+ buf->extra_info->input_normpos = (int)( (double) current_file_pos *
65535 / this->input->get_length (this->input) );
buf->extra_info->input_time = audio_pts / 90;
buf->pts = audio_pts;
@@ -166,7 +166,7 @@ static int demux_vox_get_status (demux_plugin_t *this_gen) {
static int demux_vox_get_stream_length (demux_plugin_t *this_gen) {
demux_vox_t *this = (demux_vox_t *) this_gen;
- return (int)((int64_t)this->input->get_length(this->input)
+ return (int)((int64_t)this->input->get_length(this->input)
* 2 * 1000 / DIALOGIC_SAMPLERATE);
}
@@ -203,7 +203,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
return NULL;
}
- this = xine_xmalloc (sizeof (demux_vox_t));
+ this = calloc(1, sizeof(demux_vox_t));
this->stream = stream;
this->input = input;
@@ -247,7 +247,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_vox_init_plugin (xine_t *xine, void *data) {
demux_vox_class_t *this;
- this = xine_xmalloc (sizeof (demux_vox_class_t));
+ this = calloc(1, sizeof(demux_vox_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_vqa.c b/src/demuxers/demux_vqa.c
index 40242476b..578be14ee 100644
--- a/src/demuxers/demux_vqa.c
+++ b/src/demuxers/demux_vqa.c
@@ -25,7 +25,7 @@
*
* Quick technical note: VQA files begin with a header that includes a
* frame index. This ought to be useful for seeking within a VQA file.
- * However, seeking is infeasible due to the audio encoding: Each audio
+ * However, seeking is infeasible due to the audio encoding: Each audio
* block needs information from the previous audio block in order to be
* decoded, thus making random seeking difficult.
*/
@@ -96,8 +96,8 @@ static int open_vqa_file(demux_vqa_t *this) {
return 0;
/* check for the VQA signatures */
- if ((_X_BE_32(&scratch[0]) != FORM_TAG) ||
- (_X_BE_32(&scratch[8]) != WVQA_TAG))
+ if (!_x_is_fourcc(&scratch[0], "FORM") ||
+ !_x_is_fourcc(&scratch[8], "WVQA") )
return 0;
/* file is qualified; skip to the start of the VQA header */
@@ -108,7 +108,7 @@ static int open_vqa_file(demux_vqa_t *this) {
this->filesize = 1;
/* load the VQA header */
- if (this->input->read(this->input, vqa_header, VQA_HEADER_SIZE) !=
+ if (this->input->read(this->input, vqa_header, VQA_HEADER_SIZE) !=
VQA_HEADER_SIZE)
return 0;
@@ -334,7 +334,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_vqa_t *this;
- this = xine_xmalloc (sizeof (demux_vqa_t));
+ this = calloc(1, sizeof(demux_vqa_t));
this->stream = stream;
this->input = input;
@@ -408,7 +408,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_vqa_init_plugin (xine_t *xine, void *data) {
demux_vqa_class_t *this;
- this = xine_xmalloc (sizeof (demux_vqa_class_t));
+ this = calloc(1, sizeof(demux_vqa_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_wav.c b/src/demuxers/demux_wav.c
index 33baaf973..99c50ad67 100644
--- a/src/demuxers/demux_wav.c
+++ b/src/demuxers/demux_wav.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2001-2005 the xine project
+ * Copyright (C) 2001-2008 the xine project
*
* This file is part of xine, a free video player.
*
@@ -41,9 +41,11 @@
#include "bswap.h"
#include "group_audio.h"
-#define WAV_SIGNATURE_SIZE 16
+#define WAV_SIGNATURE_SIZE 12
/* this is the hex value for 'data' */
#define data_TAG 0x61746164
+/* this is the hex value for 'fmt ' */
+#define fmt_TAG 0x20746D66
#define PCM_BLOCK_ALIGN 1024
#define PREFERED_BLOCK_SIZE 4096
@@ -74,31 +76,62 @@ typedef struct {
static int demux_wav_get_stream_length (demux_plugin_t *this_gen);
-/* returns 1 if the WAV file was opened successfully, 0 otherwise */
-static int open_wav_file(demux_wav_t *this) {
- uint8_t signature[WAV_SIGNATURE_SIZE];
+/* searches for the chunk with the given tag from the beginning of WAV file
+ * returns 1 if chunk was found, 0 otherwise,
+ * fills chunk_size and chunk_pos if chunk was found
+ * NOTE: chunk_pos is set to the position of the first byte of chunk data */
+static int find_chunk_by_tag(demux_wav_t *this, const uint32_t given_chunk_tag,
+ uint32_t *found_chunk_size, off_t *found_chunk_pos) {
uint32_t chunk_tag;
uint32_t chunk_size;
uint8_t chunk_preamble[8];
+ /* search for the chunks from the start of the WAV file */
+ this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET);
+
+ while (1) {
+ if (this->input->read(this->input, chunk_preamble, 8) != 8) {
+ return 0;
+ }
+
+ chunk_tag = _X_LE_32(&chunk_preamble[0]);
+ chunk_size = _X_LE_32(&chunk_preamble[4]);
+
+ if (chunk_tag == given_chunk_tag) {
+ if (found_chunk_size)
+ *found_chunk_size = _X_LE_32(&chunk_preamble[4]);
+ if (found_chunk_pos)
+ *found_chunk_pos = this->input->get_current_pos(this->input);
+ return 1;
+ } else {
+ this->input->seek(this->input, chunk_size, SEEK_CUR);
+ }
+ }
+}
+
+/* returns 1 if the WAV file was opened successfully, 0 otherwise */
+static int open_wav_file(demux_wav_t *this) {
+ uint8_t signature[WAV_SIGNATURE_SIZE];
+ off_t wave_pos;
+ uint32_t wave_size;
+
/* check the signature */
if (_x_demux_read_header(this->input, signature, WAV_SIGNATURE_SIZE) != WAV_SIGNATURE_SIZE)
return 0;
- if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVEfmt ", 8) )
+ if (memcmp(signature, "RIFF", 4) || memcmp(&signature[8], "WAVE", 4) )
return 0;
- /* file is qualified; skip over the header bytes in the stream */
- this->input->seek(this->input, WAV_SIGNATURE_SIZE, SEEK_SET);
-
- /* go after the format structure */
- if (this->input->read(this->input,
- (unsigned char *)&this->wave_size, 4) != 4)
+ /* search for the 'fmt ' chunk first */
+ wave_pos = 0;
+ if (find_chunk_by_tag(this, fmt_TAG, &wave_size, &wave_pos)==0)
return 0;
- this->wave_size = le2me_32(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 = wave_size;
+
+ this->input->seek(this->input, wave_pos, SEEK_SET);
+ this->wave = malloc( this->wave_size );
+
+ if (!this->wave || this->input->read(this->input, (void *)this->wave, this->wave_size) !=
this->wave_size) {
free (this->wave);
return 0;
@@ -114,28 +147,21 @@ static int open_wav_file(demux_wav_t *this) {
return 0;
}
- /* traverse through the chunks to find the 'data' chunk */
+ /* search for the 'data' chunk */
this->data_start = this->data_size = 0;
- while (this->data_start == 0) {
-
- if (this->input->read(this->input, chunk_preamble, 8) != 8) {
- free (this->wave);
- return 0;
- }
- chunk_tag = _X_LE_32(&chunk_preamble[0]);
- chunk_size = _X_LE_32(&chunk_preamble[4]);
-
- if (chunk_tag == data_TAG) {
- this->data_start = this->input->get_current_pos(this->input);
- /* Get the data length from the file itself, instead of the data
- * TAG, for broken files */
- this->data_size = this->input->get_length(this->input);
- } else {
- this->input->seek(this->input, chunk_size, SEEK_CUR);
- }
+ if (find_chunk_by_tag(this, data_TAG, NULL, &this->data_start)==0)
+ {
+ free (this->wave);
+ return 0;
+ }
+ else
+ {
+ /* Get the data length from the file itself, instead of the data
+ * TAG, for broken files */
+ this->input->seek(this->input, this->data_start, SEEK_SET);
+ this->data_size = this->input->get_length(this->input);
+ return 1;
}
-
- return 1;
}
static int demux_wav_send_chunk(demux_plugin_t *this_gen) {
@@ -184,11 +210,16 @@ static int demux_wav_send_chunk(demux_plugin_t *this_gen) {
buf->size = remaining_sample_bytes;
remaining_sample_bytes -= buf->size;
- if (this->input->read(this->input, buf->content, buf->size) !=
+ off_t read;
+ if ((read = this->input->read(this->input, buf->content, buf->size)) !=
buf->size) {
- buf->free_buffer(buf);
- this->status = DEMUX_FINISHED;
- break;
+ if (read == 0) {
+ buf->free_buffer(buf);
+ this->status = DEMUX_FINISHED;
+ break;
+ } else {
+ buf->size = read;
+ }
}
#if 0
@@ -337,7 +368,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_wav_t *this;
uint32_t align;
- this = xine_xmalloc (sizeof (demux_wav_t));
+ this = calloc(1, sizeof(demux_wav_t));
this->stream = stream;
this->input = input;
@@ -423,7 +454,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_wav_init_plugin (xine_t *xine, void *data) {
demux_wav_class_t *this;
- this = xine_xmalloc (sizeof (demux_wav_class_t));
+ this = calloc(1, sizeof(demux_wav_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_wc3movie.c b/src/demuxers/demux_wc3movie.c
index 596d47f4a..36cc4eabb 100644
--- a/src/demuxers/demux_wc3movie.c
+++ b/src/demuxers/demux_wc3movie.c
@@ -102,7 +102,7 @@ typedef struct {
} demux_mve_class_t;
/* bizarre palette lookup table */
-const unsigned char wc3_pal_lookup[] = {
+static const unsigned char wc3_pal_lookup[] = {
0x00, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0E, 0x10, 0x12, 0x13, 0x15, 0x16,
0x18, 0x19, 0x1A,
0x1C, 0x1D, 0x1F, 0x20, 0x21, 0x23, 0x24, 0x25, 0x27, 0x28, 0x29, 0x2A, 0x2C,
@@ -177,7 +177,7 @@ static int demux_mve_send_chunk(demux_plugin_t *this_gen) {
}
}
this->current_shot++;
-
+
/* this is the start of a new shot; send a new palette */
if (this->input->read(this->input, preamble, 4) != 4) {
this->status = DEMUX_FINISHED;
@@ -205,7 +205,7 @@ static int demux_mve_send_chunk(demux_plugin_t *this_gen) {
} else if (chunk_tag == AUDI_TAG) {
if( this->audio_fifo ) {
audio_pts = this->video_pts - WC3_PTS_INC;
-
+
while (chunk_size) {
buf = this->audio_fifo->buffer_pool_alloc (this->audio_fifo);
buf->type = BUF_AUDIO_LPCM_LE;
@@ -213,23 +213,23 @@ static int demux_mve_send_chunk(demux_plugin_t *this_gen) {
buf->extra_info->input_normpos = (int)( (double) current_file_pos * 65535 / this->data_size);
buf->extra_info->input_time = audio_pts / 90;
buf->pts = audio_pts;
-
+
if (chunk_size > buf->max_size)
buf->size = buf->max_size;
else
buf->size = chunk_size;
chunk_size -= buf->size;
-
+
if (this->input->read(this->input, buf->content, buf->size) !=
buf->size) {
buf->free_buffer(buf);
this->status = DEMUX_FINISHED;
break;
}
-
+
if (!chunk_size)
buf->decoder_flags |= BUF_FLAG_FRAME_END;
-
+
this->audio_fifo->put (this->audio_fifo, buf);
}
}else{
@@ -293,7 +293,7 @@ static void demux_mve_send_headers(demux_plugin_t *this_gen) {
/* load stream information */
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_VIDEO, 1);
- /* this is not strictly correct-- some WC3 MVE files do not contain
+ /* this is not strictly correct-- some WC3 MVE files do not contain
* audio, but I'm too lazy to check if that is the case */
_x_stream_info_set(this->stream, XINE_STREAM_INFO_HAS_AUDIO, 1);
_x_stream_info_set(this->stream, XINE_STREAM_INFO_VIDEO_WIDTH,
@@ -357,9 +357,9 @@ static int open_mve_file(demux_mve_t *this) {
if (_x_demux_read_header(this->input, header, WC3_HEADER_SIZE) != WC3_HEADER_SIZE)
return 0;
- if ((_X_BE_32(&header[0]) != FORM_TAG) ||
- (_X_BE_32(&header[8]) != MOVE_TAG) ||
- (_X_BE_32(&header[12]) != PC_TAG))
+ if ( !_x_is_fourcc(&header[0], "FORM") ||
+ !_x_is_fourcc(&header[8], "MOVE") ||
+ !_x_is_fourcc(&header[12], "_PC_") )
return 0;
/* file is qualified */
@@ -376,19 +376,23 @@ static int open_mve_file(demux_mve_t *this) {
if (this->input->read(this->input, preamble, 4) != 4)
return 0;
this->number_of_shots = _X_LE_32(&preamble[0]);
-
+
/* allocate space for the shot offset index and set offsets to 0 */
- this->shot_offsets = xine_xmalloc(this->number_of_shots * sizeof(off_t));
+ this->shot_offsets = calloc(this->number_of_shots, sizeof(off_t));
this->current_shot = 0;
- for (i = 0; i < this->number_of_shots; i++)
- this->shot_offsets[i] = 0;
/* skip the SOND chunk */
this->input->seek(this->input, 12, SEEK_CUR);
/* load the palette chunks */
- this->palettes = xine_xmalloc(this->number_of_shots * PALETTE_SIZE *
+ this->palettes = calloc(this->number_of_shots, PALETTE_SIZE *
sizeof(palette_entry_t));
+
+ if (!this->shot_offsets || !this->palettes) {
+ free (this->shot_offsets);
+ return 0;
+ }
+
for (i = 0; i < this->number_of_shots; i++) {
/* make sure there was a valid palette chunk preamble */
if (this->input->read(this->input, preamble, PREAMBLE_SIZE) !=
@@ -398,8 +402,8 @@ static int open_mve_file(demux_mve_t *this) {
return 0;
}
- if ((_X_BE_32(&preamble[0]) != PALT_TAG) ||
- (_X_BE_32(&preamble[4]) != PALETTE_CHUNK_SIZE)) {
+ if ( !_x_is_fourcc(&preamble[0], "PALT") ||
+ (_X_BE_32(&preamble[4]) != PALETTE_CHUNK_SIZE)) {
xine_log(this->stream->xine, XINE_LOG_MSG,
_("demux_wc3movie: There was a problem while loading palette chunks\n"));
free (this->palettes);
@@ -460,8 +464,9 @@ static int open_mve_file(demux_mve_t *this) {
case BNAM_TAG:
/* load the name into the stream attributes */
- title = realloc (title, chunk_size);
- if (this->input->read(this->input, title, chunk_size) != chunk_size) {
+ free (title);
+ title = malloc (chunk_size);
+ if (!title || this->input->read(this->input, title, chunk_size) != chunk_size) {
free (title);
free (this->palettes);
free (this->shot_offsets);
@@ -535,13 +540,13 @@ static int demux_mve_seek (demux_plugin_t *this_gen,
start_time /= 1000;
start_pos = (off_t) ( (double) start_pos / 65535 *
this->data_size );
-
+
this->status = DEMUX_OK;
_x_demux_flush_engine(this->stream);
this->seek_flag = 1;
/* if input is non-seekable, do not proceed with the rest of this
- * seek function */
+ * seek function */
if (!INPUT_IS_SEEKABLE(this->input))
return this->status;
@@ -561,7 +566,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen,
chunk_size = (_X_BE_32(&preamble[4]) + 1) & (~1);
if (chunk_tag == SHOT_TAG) {
- this->shot_offsets[0] =
+ this->shot_offsets[0] =
this->input->get_current_pos(this->input) - PREAMBLE_SIZE;
/* skip the four SHOT data bytes (palette index) */
this->input->seek(this->input, 4, SEEK_CUR);
@@ -576,7 +581,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen,
start_pos += this->data_start;
for (i = 0; i < this->number_of_shots - 1; i++) {
- /* if the next shot offset has not been recorded, traverse through the
+ /* if the next shot offset has not been recorded, traverse through the
* file until it is found */
if (this->shot_offsets[i + 1] == 0) {
off_t current_pos;
@@ -602,7 +607,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen,
chunk_size = (_X_BE_32(&preamble[4]) + 1) & (~1);
if (chunk_tag == SHOT_TAG) {
- this->shot_offsets[i + 1] =
+ this->shot_offsets[i + 1] =
this->input->get_current_pos(this->input) - PREAMBLE_SIZE;
/* skip the four SHOT data bytes (palette index) */
this->input->seek(this->input, 4, SEEK_CUR);
@@ -615,7 +620,7 @@ static int demux_mve_seek (demux_plugin_t *this_gen,
/* check if the seek-to offset falls in between this shot offset and
* the next one */
- if ((start_pos >= this->shot_offsets[i]) &&
+ if ((start_pos >= this->shot_offsets[i]) &&
(start_pos < this->shot_offsets[i + 1])) {
new_shot = i;
@@ -667,7 +672,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
demux_mve_t *this;
- this = xine_xmalloc (sizeof (demux_mve_t));
+ this = calloc(1, sizeof(demux_mve_t));
this->stream = stream;
this->input = input;
@@ -741,7 +746,7 @@ static void class_dispose (demux_class_t *this_gen) {
void *demux_wc3movie_init_plugin (xine_t *xine, void *data) {
demux_mve_class_t *this;
- this = xine_xmalloc (sizeof (demux_mve_class_t));
+ this = calloc(1, sizeof(demux_mve_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_yuv4mpeg2.c b/src/demuxers/demux_yuv4mpeg2.c
index 9c5856710..aa1a4dff6 100644
--- a/src/demuxers/demux_yuv4mpeg2.c
+++ b/src/demuxers/demux_yuv4mpeg2.c
@@ -69,7 +69,7 @@ typedef struct {
int aspect_d;
int progressive;
int top_field_first;
-
+
unsigned int frame_pts_inc;
unsigned int frame_size;
@@ -86,7 +86,7 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
char *header_ptr, *header_endptr, *header_end;
this->bih.biWidth = this->bih.biHeight = this->fps_n = this->fps_d =
- this->aspect_n = this->aspect_d = this->progressive =
+ this->aspect_n = this->aspect_d = this->progressive =
this->top_field_first = this->data_start = 0;
if (_x_demux_read_header(this->input, header, Y4M_HEADER_BYTES) != Y4M_HEADER_BYTES)
@@ -98,11 +98,11 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
/* null terminate the read data */
header[Y4M_HEADER_BYTES] = '\0';
-
+
/* check for stream header terminator */
if ((header_end = strchr(header, '\n')) == NULL)
return 0;
-
+
/* read tagged fields in stream header */
header_ptr = &header[Y4M_SIGNATURE_SIZE];
while (header_ptr < header_end) {
@@ -111,7 +111,7 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
break;
else
header_ptr++;
-
+
switch (*header_ptr) {
case 'W':
/* read the width */
@@ -153,31 +153,31 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
return 0;
else
header_ptr = header_endptr;
-
+
/* denominator */
this->fps_d = strtol(header_ptr + 1, &header_endptr, 10);
if (header_endptr == header_ptr + 1)
return 0;
else
header_ptr = header_endptr;
-
+
break;
case 'A':
- /* read aspect ratio - stored as a ratio(!)
+ /* read aspect ratio - stored as a ratio(!)
* numerator */
this->aspect_n = strtol(header_ptr + 1, &header_endptr, 10);
if ((header_endptr == header_ptr + 1) || (*header_endptr != ':'))
return 0;
else
header_ptr = header_endptr;
-
+
/* denominator */
this->aspect_d = strtol(header_ptr + 1, &header_endptr, 10);
if (header_endptr == header_ptr + 1)
return 0;
else
header_ptr = header_endptr;
-
+
break;
default:
/* skip whatever this is */
@@ -185,7 +185,7 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
header_ptr++;
}
}
-
+
/* make sure all the data was found */
if (!this->bih.biWidth || !this->bih.biHeight || !this->fps_n || !this->fps_d)
return 0;
@@ -194,25 +194,17 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
this->frame_size = this->bih.biWidth * this->bih.biHeight * 3 / 2;
/* pts difference between frames */
- this->frame_pts_inc = (90000 * this->fps_d) / this->fps_n;
-
+ this->frame_pts_inc = (90000 * this->fps_d) / this->fps_n;
+
/* finally, look for the first frame */
- while ((header_ptr - header) < (Y4M_HEADER_BYTES - 4)) {
- if((header_ptr[0] == 'F') &&
- (header_ptr[1] == 'R') &&
- (header_ptr[2] == 'A') &&
- (header_ptr[3] == 'M') &&
- (header_ptr[4] == 'E')) {
- this->data_start = header_ptr - header;
- break;
- } else
- header_ptr++;
- }
-
+ char *data_start_ptr = memmem(header_ptr, Y4M_HEADER_BYTES, "FRAME", 5);
+
/* make sure the first frame was found */
- if(!this->data_start)
+ if ( !data_start_ptr )
return 0;
-
+
+ this->data_start = data_start_ptr - header;
+
/* compute size of all frames */
if (INPUT_IS_SEEKABLE(this->input)) {
this->data_size = this->input->get_length(this->input) -
@@ -228,29 +220,26 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) {
static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) {
demux_yuv4mpeg2_t *this = (demux_yuv4mpeg2_t *) this_gen;
- buf_element_t *buf = NULL;
- unsigned char preamble[Y4M_FRAME_SIGNATURE_SIZE];
- int bytes_remaining;
- off_t current_file_pos;
- int64_t pts;
-
/* validate that this is an actual frame boundary */
- if (this->input->read(this->input, preamble, Y4M_FRAME_SIGNATURE_SIZE) !=
- Y4M_FRAME_SIGNATURE_SIZE) {
- this->status = DEMUX_FINISHED;
- return this->status;
- }
- if (memcmp(preamble, Y4M_FRAME_SIGNATURE, Y4M_FRAME_SIGNATURE_SIZE) !=
- 0) {
- this->status = DEMUX_FINISHED;
- return this->status;
+ {
+ uint8_t preamble[Y4M_FRAME_SIGNATURE_SIZE];
+ if (this->input->read(this->input, preamble, Y4M_FRAME_SIGNATURE_SIZE) !=
+ Y4M_FRAME_SIGNATURE_SIZE) {
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
+ if (memcmp(preamble, Y4M_FRAME_SIGNATURE, Y4M_FRAME_SIGNATURE_SIZE) !=
+ 0) {
+ this->status = DEMUX_FINISHED;
+ return this->status;
+ }
}
/* load and dispatch the raw frame */
- bytes_remaining = this->frame_size;
- current_file_pos =
+ int bytes_remaining = this->frame_size;
+ off_t current_file_pos =
this->input->get_current_pos(this->input) - this->data_start;
- pts = current_file_pos;
+ int64_t pts = current_file_pos;
pts /= (this->frame_size + Y4M_FRAME_SIGNATURE_SIZE);
pts *= this->frame_pts_inc;
@@ -261,17 +250,14 @@ static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) {
}
while(bytes_remaining) {
- buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+ buf_element_t *buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
buf->type = BUF_VIDEO_I420;
if( this->data_size )
buf->extra_info->input_normpos = (int)((double) current_file_pos * 65535 / this->data_size);
buf->extra_info->input_time = pts / 90;
buf->pts = pts;
- if (bytes_remaining > buf->max_size)
- buf->size = buf->max_size;
- else
- buf->size = bytes_remaining;
+ buf->size = MIN(bytes_remaining, buf->max_size);
bytes_remaining -= buf->size;
if (this->input->read(this->input, buf->content, buf->size) !=
@@ -285,13 +271,12 @@ static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) {
buf->decoder_flags |= BUF_FLAG_FRAME_END;
this->video_fifo->put(this->video_fifo, buf);
}
-
+
return this->status;
-}
+}
static void demux_yuv4mpeg2_send_headers(demux_plugin_t *this_gen) {
demux_yuv4mpeg2_t *this = (demux_yuv4mpeg2_t *) this_gen;
- buf_element_t *buf;
this->video_fifo = this->stream->video_fifo;
this->audio_fifo = this->stream->audio_fifo;
@@ -310,17 +295,17 @@ static void demux_yuv4mpeg2_send_headers(demux_plugin_t *this_gen) {
_x_demux_control_start(this->stream);
/* send init info to decoders */
- buf = this->video_fifo->buffer_pool_alloc (this->video_fifo);
+ buf_element_t *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] = this->frame_pts_inc; /* initial video step */
-
+
if(this->aspect_n && this->aspect_d) {
buf->decoder_flags |= BUF_FLAG_ASPECT;
buf->decoder_info[1] = this->bih.biWidth * this->aspect_n;
buf->decoder_info[2] = this->bih.biHeight * this->aspect_d;
}
-
+
buf->decoder_info[3] = this->progressive;
buf->decoder_info[4] = this->top_field_first;
@@ -342,7 +327,7 @@ static int demux_yuv4mpeg2_seek (demux_plugin_t *this_gen,
/* YUV4MPEG2 files are essentially constant bit-rate video. Seek along
* the calculated frame boundaries. Divide the requested seek offset
- * by the frame size integer-wise to obtain the desired frame number
+ * by the frame size integer-wise to obtain the desired frame number
* and then multiply the frame number by the frame size to get the
* starting offset. Add the data_start offset to obtain the final
* offset. */
@@ -385,7 +370,7 @@ static int demux_yuv4mpeg2_get_status (demux_plugin_t *this_gen) {
static int demux_yuv4mpeg2_get_stream_length (demux_plugin_t *this_gen) {
demux_yuv4mpeg2_t *this = (demux_yuv4mpeg2_t *) this_gen;
- return (int)(((int64_t) this->data_size * 1000 * this->fps_d) /
+ return (int)(((int64_t) this->data_size * 1000 * this->fps_d) /
((this->frame_size + Y4M_FRAME_SIGNATURE_SIZE) * this->fps_n));
}
@@ -400,10 +385,7 @@ static int demux_yuv4mpeg2_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_yuv4mpeg2_t *this;
-
- this = xine_xmalloc (sizeof (demux_yuv4mpeg2_t));
+ demux_yuv4mpeg2_t *this = calloc(1, sizeof(demux_yuv4mpeg2_t));
this->stream = stream;
this->input = input;
@@ -422,10 +404,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str
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);
+ const char *const mrl = input->get_mrl (input);
+ const char *const extensions = class_gen->get_extensions (class_gen);
if (!_x_demux_check_extension (mrl, extensions)) {
free (this);
@@ -477,7 +457,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_plugin (xine_t *xine, void *data) {
demux_yuv4mpeg2_class_t *this;
- this = xine_xmalloc (sizeof (demux_yuv4mpeg2_class_t));
+ this = calloc(1, sizeof(demux_yuv4mpeg2_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/demux_yuv_frames.c b/src/demuxers/demux_yuv_frames.c
index 774329c05..81dd2b03a 100644
--- a/src/demuxers/demux_yuv_frames.c
+++ b/src/demuxers/demux_yuv_frames.c
@@ -1,19 +1,19 @@
/*
* Copyright (C) 2003-2004 the xine project
* Copyright (C) 2003 Jeroen Asselman <j.asselman@itsec-ps.nl>
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
@@ -70,8 +70,6 @@ static int demux_yuv_frames_get_status (demux_plugin_t *this_gen) {
}
static int switch_buf(demux_yuv_frames_t *this , buf_element_t *buf){
- int result = 0;
-
if (!buf)
return 0;
@@ -88,8 +86,7 @@ static int switch_buf(demux_yuv_frames_t *this , buf_element_t *buf){
case BUF_VIDEO_I420:
case BUF_VIDEO_YUY2:
this->video_fifo->put(this->video_fifo, buf);
- result = 1; /* 1, we still should read audio */
- break;
+ return 1; /* 1, we still should read audio */
case BUF_AUDIO_LPCM_LE:
if (!_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO))
_x_demux_control_newpts(this->stream, buf->pts, 0);
@@ -100,7 +97,7 @@ static int switch_buf(demux_yuv_frames_t *this , buf_element_t *buf){
buf->free_buffer(buf);
}
- return result;
+ return 0;
}
static int demux_yuv_frames_send_chunk (demux_plugin_t *this_gen){
@@ -123,21 +120,27 @@ static void demux_yuv_frames_send_headers (demux_plugin_t *this_gen){
this->video_fifo = this->stream->video_fifo;
this->audio_fifo = this->stream->audio_fifo;
-
+
_x_demux_control_start(this->stream);
if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_AUDIO)) {
buf = this->input->read_block(this->input, this->audio_fifo, 0);
-
- this->audio_fifo->put(this->audio_fifo, buf);
+
+ if (buf)
+ this->audio_fifo->put(this->audio_fifo, buf);
+ else
+ this->status = DEMUX_FINISHED;
}
-
+
if(_x_stream_info_get(this->stream, XINE_STREAM_INFO_HAS_VIDEO)) {
buf = this->input->read_block(this->input, this->video_fifo, 0);
-
- this->video_fifo->put(this->video_fifo, buf);
+
+ if (buf)
+ this->video_fifo->put(this->video_fifo, buf);
+ else
+ this->status = DEMUX_FINISHED;
}
-
+
this->status = DEMUX_OK;
}
@@ -203,7 +206,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen,
* if we reach this point, the input has been accepted.
*/
- this = xine_xmalloc (sizeof (demux_yuv_frames_t));
+ this = calloc(1, sizeof(demux_yuv_frames_t));
this->stream = stream;
this->input = input;
@@ -253,7 +256,7 @@ static void class_dispose (demux_class_t *this_gen) {
static void *init_class (xine_t *xine, void *data) {
demux_yuv_frames_class_t *this;
- this = xine_xmalloc (sizeof (demux_yuv_frames_class_t));
+ this = calloc(1, sizeof(demux_yuv_frames_class_t));
this->demux_class.open_plugin = open_plugin;
this->demux_class.get_description = get_description;
diff --git a/src/demuxers/ebml.c b/src/demuxers/ebml.c
index ac44aecd7..75fbfde75 100644
--- a/src/demuxers/ebml.c
+++ b/src/demuxers/ebml.c
@@ -40,7 +40,7 @@
ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input) {
ebml_parser_t *ebml;
-
+
ebml = malloc(sizeof(ebml_parser_t));
ebml->xine = xine;
ebml->input = input;
@@ -52,15 +52,15 @@ ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input) {
ebml->doctype = NULL;
ebml->doctype_version = 0;
ebml->doctype_read_version = 0;
-
+
ebml->level = 0;
-
+
return ebml;
}
void dispose_ebml_parser(ebml_parser_t *ebml) {
- free(ebml);
+ free(ebml);
}
@@ -132,7 +132,7 @@ static int ebml_read_elem_len(ebml_parser_t *ebml, uint64_t *len) {
int ff_bytes;
uint64_t value;
int i;
-
+
if (ebml->input->read(ebml->input, data, 1) != 1) {
off_t pos = ebml->input->get_current_pos(ebml->input);
xprintf(ebml->xine, XINE_VERBOSITY_LOG,
@@ -162,7 +162,7 @@ static int ebml_read_elem_len(ebml_parser_t *ebml, uint64_t *len) {
ff_bytes = 1;
else
ff_bytes = 0;
-
+
/* read the rest of the len */
if (ebml->input->read(ebml->input, data + 1, size - 1) != (size - 1)) {
off_t pos = ebml->input->get_current_pos(ebml->input);
@@ -231,7 +231,7 @@ int ebml_read_uint(ebml_parser_t *ebml, ebml_elem_t *elem, uint64_t *num) {
"ebml: Invalid integer element size %" PRIu64 "\n", size);
return 0;
}
-
+
if (!ebml_read_elem_data (ebml, data, size))
return 0;
@@ -253,7 +253,7 @@ int ebml_read_sint (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *num) {
"ebml: Invalid integer element size %" PRIu64 "\n", size);
return 0;
}
-
+
if (!ebml_read_elem_data(ebml, data, size))
return 0;
@@ -262,7 +262,7 @@ int ebml_read_sint (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *num) {
*num = -1;
else
*num = 0;
-
+
while (size > 0) {
*num = (*num << 8) | data[elem->len - size];
size--;
@@ -310,7 +310,7 @@ int ebml_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem, char *str) {
if (!ebml_read_elem_data(ebml, str, size))
return 0;
-
+
return 1;
}
@@ -318,6 +318,22 @@ int ebml_read_utf8 (ebml_parser_t *ebml, ebml_elem_t *elem, char *str) {
return ebml_read_ascii (ebml, elem, str);
}
+char *ebml_alloc_read_ascii (ebml_parser_t *ebml, ebml_elem_t *elem)
+{
+ char *text;
+ if (elem->len >= 4096)
+ return NULL;
+ text = malloc(elem->len + 1);
+ if (text)
+ {
+ text[elem->len] = '\0';
+ if (ebml_read_ascii (ebml, elem, text))
+ return text;
+ free (text);
+ }
+ return NULL;
+}
+
int ebml_read_date (ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *date) {
return ebml_read_sint (ebml, elem, date);
}
@@ -330,7 +346,7 @@ int ebml_read_master (ebml_parser_t *ebml, ebml_elem_t *elem) {
top_elem->start = elem->start;
top_elem->len = elem->len;
top_elem->id = elem->id;
-
+
ebml->level++;
lprintf("id: 0x%x, len: %" PRIu64 ", level: %d\n", elem->id, elem->len, ebml->level);
if (ebml->level >= EBML_STACK_SIZE) {
@@ -362,20 +378,20 @@ int ebml_check_header(ebml_parser_t *ebml) {
"ebml: invalid master element\n");
return 0;
}
-
+
if (master.id != EBML_ID_EBML) {
xprintf(ebml->xine, XINE_VERBOSITY_LOG,
"ebml: invalid master element\n");
return 0;
}
-
+
if (!ebml_read_master (ebml, &master))
return 0;
next_level = 1;
while (next_level == 1) {
ebml_elem_t elem;
-
+
if (!ebml_read_elem_head(ebml, &elem))
return 0;
@@ -389,7 +405,7 @@ int ebml_check_header(ebml_parser_t *ebml) {
ebml->version = num;
break;
}
-
+
case EBML_ID_EBMLREADVERSION: {
uint64_t num;
@@ -423,10 +439,8 @@ int ebml_check_header(ebml_parser_t *ebml) {
}
case EBML_ID_DOCTYPE: {
- char *text = malloc(elem.len + 1);
-
- text[elem.len] = '\0';
- if (!ebml_read_ascii (ebml, &elem, text))
+ char *text = ebml_alloc_read_ascii (ebml, &elem);
+ if (!text)
return 0;
lprintf("doctype: %s\n", text);
diff --git a/src/demuxers/ebml.h b/src/demuxers/ebml.h
index 35078c502..6d750a98c 100644
--- a/src/demuxers/ebml.h
+++ b/src/demuxers/ebml.h
@@ -48,7 +48,7 @@ typedef struct ebml_parser_s {
/* xine stuff */
xine_t *xine;
input_plugin_t *input;
-
+
/* EBML Parser Stack Management */
ebml_elem_t elem_stack[EBML_STACK_SIZE];
int level;
@@ -61,11 +61,11 @@ typedef struct ebml_parser_s {
char *doctype;
uint64_t doctype_version;
uint64_t doctype_read_version;
-
+
} ebml_parser_t;
-ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input);
+ebml_parser_t *new_ebml_parser (xine_t *xine, input_plugin_t *input) XINE_MALLOC;
void dispose_ebml_parser (ebml_parser_t *ebml);
@@ -91,6 +91,8 @@ int ebml_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem, char *str);
int ebml_read_utf8(ebml_parser_t *ebml, ebml_elem_t *elem, char *str);
+char *ebml_alloc_read_ascii(ebml_parser_t *ebml, ebml_elem_t *elem);
+
int ebml_read_date(ebml_parser_t *ebml, ebml_elem_t *elem, int64_t *date);
int ebml_read_master(ebml_parser_t *ebml, ebml_elem_t *elem);
diff --git a/src/demuxers/group_audio.c b/src/demuxers/group_audio.c
index 2643a8b80..f405d0292 100644
--- a/src/demuxers/group_audio.c
+++ b/src/demuxers/group_audio.c
@@ -110,7 +110,7 @@ static const demuxer_info_t demux_info_mod = {
#endif
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "aac", XINE_VERSION_CODE, &demux_info_aac, demux_aac_init_plugin },
{ PLUGIN_DEMUX, 26, "ac3", XINE_VERSION_CODE, &demux_info_ac3, demux_ac3_init_plugin },
{ PLUGIN_DEMUX, 26, "aud", XINE_VERSION_CODE, &demux_info_aud, demux_aud_init_plugin },
diff --git a/src/demuxers/group_audio.h b/src/demuxers/group_audio.h
index 424e5c8e0..d2cd91875 100644
--- a/src/demuxers/group_audio.h
+++ b/src/demuxers/group_audio.h
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2005 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
diff --git a/src/demuxers/group_games.c b/src/demuxers/group_games.c
index ad257c2fb..f08e8477d 100644
--- a/src/demuxers/group_games.c
+++ b/src/demuxers/group_games.c
@@ -78,7 +78,7 @@ static const demuxer_info_t demux_info_vmd = {
};
const plugin_info_t xine_plugin_info[] EXPORTED = {
- /* type, API, "name", version, special_info, init_function */
+ /* type, API, "name", version, special_info, init_function */
{ PLUGIN_DEMUX, 26, "wve", XINE_VERSION_CODE, &demux_info_eawve, demux_eawve_init_plugin},
{ PLUGIN_DEMUX, 26, "idcin", XINE_VERSION_CODE, &demux_info_idcin, demux_idcin_init_plugin },
{ PLUGIN_DEMUX, 26, "ipmovie", XINE_VERSION_CODE, &demux_info_ipmovie, demux_ipmovie_init_plugin },
diff --git a/src/demuxers/group_games.h b/src/demuxers/group_games.h
index f93d4bb07..ea6b00e75 100644
--- a/src/demuxers/group_games.h
+++ b/src/demuxers/group_games.h
@@ -1,18 +1,18 @@
-/*
+/*
* Copyright (C) 2000-2003 the xine project
- *
+ *
* This file is part of xine, a free video player.
- *
+ *
* xine is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
- *
+ *
* xine is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
diff --git a/src/demuxers/id3.c b/src/demuxers/id3.c
index 6b36cc666..15599ffea 100644
--- a/src/demuxers/id3.c
+++ b/src/demuxers/id3.c
@@ -29,7 +29,7 @@
*
* ID3v2 specs: http://www.id3.org/
*/
-
+
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
@@ -84,7 +84,7 @@ static const char* const id3_encoding[] = {
"UTF-16", /* 0x01 */
"UTF-16BE", /* 0x02 */
"UTF-8"}; /* 0x03 */
-
+
int id3v1_parse_tag (input_plugin_t *input, xine_stream_t *stream) {
off_t len;
@@ -113,7 +113,7 @@ int id3v1_parse_tag (input_plugin_t *input, xine_stream_t *stream) {
if (tag.genre < ID3_GENRE_COUNT) {
_x_meta_info_set(stream, XINE_META_INFO_GENRE, id3_genre[tag.genre]);
}
-
+
}
return 1;
} else {
@@ -126,12 +126,12 @@ static int id3v2_parse_genre(char* dest, char *src, int len) {
int state = 0;
char *buf = dest;
unsigned int index = 0;
-
+
while (*src) {
lprintf("state=%d\n", state);
if ((buf - dest) >= len)
return 0;
-
+
switch (state) {
case 0:
/* initial state */
@@ -241,7 +241,7 @@ static int id3v2_parse_header(input_plugin_t *input, uint8_t *mp3_frame_header,
lprintf("tag: ID3 v2.%d.%d\n", mp3_frame_header[3], tag_header->revision);
lprintf("flags: %d\n", tag_header->flags);
- lprintf("size: %d\n", tag_header->size);
+ lprintf("size: %zu\n", tag_header->size);
return 1;
} else {
return 0;
@@ -259,9 +259,9 @@ static int id3v22_parse_frame_header(input_plugin_t *input,
if (len == ID3V22_FRAME_HEADER_SIZE) {
frame_header->id = (buf[0] << 16) + (buf[1] << 8) + buf[2];
- frame_header->size = _X_BE_24_synchsafe(&buf[3]);
+ frame_header->size = _X_BE_24(&buf[3]);
- lprintf("frame: %c%c%c: size: %d\n", buf[0], buf[1], buf[2],
+ lprintf("frame: %c%c%c: size: %zu\n", buf[0], buf[1], buf[2],
frame_header->size);
return 1;
@@ -275,8 +275,11 @@ static int id3v22_interp_frame(input_plugin_t *input,
id3v22_frame_header_t *frame_header) {
char *buf;
int enc;
-
- buf = malloc(frame_header->size + 1);
+ const size_t bufsize = frame_header->size + 2;
+ if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */
+ return 0;
+
+ buf = malloc(bufsize);
if (buf == NULL) {
lprintf("malloc error");
return 0;
@@ -284,6 +287,7 @@ static int id3v22_interp_frame(input_plugin_t *input,
if (input->read (input, buf, frame_header->size) == frame_header->size) {
buf[frame_header->size] = 0;
+ buf[frame_header->size + 1] = 0;
enc = buf[0];
if( enc >= ID3_ENCODING_COUNT )
enc = 0;
@@ -292,7 +296,7 @@ static int id3v22_interp_frame(input_plugin_t *input,
case ( FOURCC_TAG(0, 'T', 'C', 'O') ):
{
char tmp[1024];
-
+
if (id3v2_parse_genre(tmp, buf + 1, 1024)) {
_x_meta_info_set(stream, XINE_META_INFO_GENRE, tmp);
}
@@ -337,9 +341,9 @@ static int id3v22_interp_frame(input_plugin_t *input,
}
-int id3v22_parse_tag(input_plugin_t *input,
- xine_stream_t *stream,
- int8_t *mp3_frame_header) {
+static int id3v22_parse_tag(input_plugin_t *input,
+ xine_stream_t *stream,
+ int8_t *mp3_frame_header) {
id3v2_header_t tag_header;
id3v22_frame_header_t tag_frame_header;
int pos = 0;
@@ -348,22 +352,22 @@ int id3v22_parse_tag(input_plugin_t *input,
if (tag_header.flags & ID3V22_ZERO_FLAG) {
/* invalid flags */
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid header flags (%02x)\n", tag_header.flags);
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid header flags (%02x)\n", tag_header.flags);
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 0;
}
if (tag_header.flags & ID3V22_COMPRESS_FLAG) {
/* compressed tag: not supported */
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: compressed tags are not supported\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": compressed tags are not supported\n");
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 0;
}
if (tag_header.flags & ID3V22_UNSYNCH_FLAG) {
/* unsynchronized tag: not supported */
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: unsynchronized tags are not supported\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": unsynchronized tags are not supported\n");
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 0;
}
@@ -371,15 +375,15 @@ int id3v22_parse_tag(input_plugin_t *input,
while ((pos + ID3V22_FRAME_HEADER_SIZE) <= tag_header.size) {
if (id3v22_parse_frame_header(input, &tag_frame_header)) {
pos += ID3V22_FRAME_HEADER_SIZE;
- if (tag_frame_header.id && tag_frame_header.size) {
+ if (tag_frame_header.id) {
if ((pos + tag_frame_header.size) <= tag_header.size) {
if (!id3v22_interp_frame(input, stream, &tag_frame_header)) {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid frame content\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid frame content\n");
}
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid frame header\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid frame header\n");
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 1;
}
@@ -390,14 +394,14 @@ int id3v22_parse_tag(input_plugin_t *input,
return 1;
}
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: id3v2_parse_frame_header problem\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": id3v2_parse_frame_header problem\n");
return 0;
}
}
return 1;
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "id3: id3v2_parse_header problem\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": id3v2_parse_header problem\n");
return 0;
}
}
@@ -415,7 +419,7 @@ static int id3v23_parse_frame_header(input_plugin_t *input,
frame_header->size = _X_BE_32(&buf[4]);
frame_header->flags = _X_BE_16(buf + 8);
- lprintf("frame: %c%c%c%c, size: %d, flags: %X\n", buf[0], buf[1], buf[2], buf[3],
+ lprintf("frame: %c%c%c%c, size: %zu, flags: %X\n", buf[0], buf[1], buf[2], buf[3],
frame_header->size, frame_header->flags);
return 1;
@@ -429,9 +433,9 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input,
uint8_t buf[14];
if (input->read (input, buf, 4) == 4) {
-
- frame_ext_header->size = _X_BE_32_synchsafe(&buf[0]);
-
+
+ frame_ext_header->size = _X_BE_32(&buf[0]);
+
if (frame_ext_header->size == 6) {
if (input->read (input, buf + 4, 6) == 6) {
frame_ext_header->flags = _X_BE_16(buf + 4);
@@ -439,7 +443,7 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input,
frame_ext_header->crc = 0;
} else {
return 0;
- }
+ }
} else if (frame_ext_header->size == 10) {
if (input->read (input, buf + 4, 10) == 10) {
@@ -451,11 +455,11 @@ static int id3v23_parse_frame_ext_header(input_plugin_t *input,
}
} else {
- lprintf("invalid ext header size: %d\n", frame_ext_header->size);
+ lprintf("invalid ext header size: %zu\n", frame_ext_header->size);
return 0;
}
- lprintf("ext header: size: %d, flags: %X, padding_size: %d, crc: %d\n",
+ lprintf("ext header: size: %zu, flags: %X, padding_size: %d, crc: %d\n",
frame_ext_header->size, frame_ext_header->flags,
frame_ext_header->padding_size, frame_ext_header->crc);
return 1;
@@ -469,8 +473,11 @@ static int id3v23_interp_frame(input_plugin_t *input,
id3v23_frame_header_t *frame_header) {
char *buf;
int enc;
+ const size_t bufsize = frame_header->size + 2;
+ if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */
+ return 0;
- buf = malloc(frame_header->size + 1);
+ buf = malloc(bufsize);
if (buf == NULL) {
lprintf("malloc error");
return 0;
@@ -478,6 +485,7 @@ static int id3v23_interp_frame(input_plugin_t *input,
if (input->read (input, buf, frame_header->size) == frame_header->size) {
buf[frame_header->size] = 0;
+ buf[frame_header->size + 1] = 0;
enc = buf[0];
if( enc >= ID3_ENCODING_COUNT )
enc = 0;
@@ -486,7 +494,7 @@ static int id3v23_interp_frame(input_plugin_t *input,
case ( FOURCC_TAG('T', 'C', 'O', 'N') ):
{
char tmp[1024];
-
+
if (id3v2_parse_genre(tmp, buf + 1, 1024)) {
_x_meta_info_set(stream, XINE_META_INFO_GENRE, tmp);
}
@@ -530,9 +538,9 @@ static int id3v23_interp_frame(input_plugin_t *input,
}
}
-int id3v23_parse_tag(input_plugin_t *input,
- xine_stream_t *stream,
- int8_t *mp3_frame_header) {
+static int id3v23_parse_tag(input_plugin_t *input,
+ xine_stream_t *stream,
+ int8_t *mp3_frame_header) {
id3v2_header_t tag_header;
id3v23_frame_header_t tag_frame_header;
id3v23_frame_ext_header_t tag_frame_ext_header;
@@ -542,15 +550,15 @@ int id3v23_parse_tag(input_plugin_t *input,
if (tag_header.flags & ID3V23_ZERO_FLAG) {
/* invalid flags */
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid header flags (%02x)\n", tag_header.flags);
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid header flags (%02x)\n", tag_header.flags);
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 0;
}
if (tag_header.flags & ID3V23_UNSYNCH_FLAG) {
/* unsynchronized tag: not supported */
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: unsynchronized tags are not supported\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": unsynchronized tags are not supported\n");
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 0;
}
@@ -559,38 +567,40 @@ int id3v23_parse_tag(input_plugin_t *input,
if (!id3v23_parse_frame_ext_header(input, &tag_frame_ext_header)) {
return 0;
}
+ pos += tag_frame_ext_header.size;
}
/* frame parsing */
while ((pos + ID3V23_FRAME_HEADER_SIZE) <= tag_header.size) {
if (id3v23_parse_frame_header(input, &tag_frame_header)) {
pos += ID3V23_FRAME_HEADER_SIZE;
- if (tag_frame_header.id && tag_frame_header.size) {
+ if (tag_frame_header.id) {
if ((pos + tag_frame_header.size) <= tag_header.size) {
if (!id3v23_interp_frame(input, stream, &tag_frame_header)) {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid frame content\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid frame content\n");
}
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid frame header\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid frame header\n");
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 1;
}
pos += tag_frame_header.size;
} else {
/* end of frames, the rest is padding */
- input->seek (input, tag_header.size - pos, SEEK_CUR);
+ lprintf("skipping padding %zu bytes\n", tag_header.size - pos);
+ input->seek (input, tag_header.size - pos, SEEK_CUR);
return 1;
}
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: id3v2_parse_frame_header problem\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": id3v2_parse_frame_header problem\n");
return 0;
}
}
return 1;
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "id3v23: id3v2_parse_header problem\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": id3v2_parse_header problem\n");
return 0;
}
}
@@ -600,7 +610,7 @@ int id3v23_parse_tag(input_plugin_t *input,
/* id3v2 "genre" parsing code. what a ugly format ! */
static int id3v24_parse_genre(char* dest, char *src, int len) {
unsigned int index = 0;
-
+
dest[0] = '\0';
if (sscanf(src, "%u", &index) == 1) {
if (index < ID3_GENRE_COUNT) {
@@ -621,10 +631,10 @@ static int id3v24_parse_frame_header(input_plugin_t *input,
len = input->read (input, buf, ID3V24_FRAME_HEADER_SIZE);
if (len == ID3V24_FRAME_HEADER_SIZE) {
frame_header->id = _X_BE_32(buf);
- frame_header->size = _X_BE_32_synchsafe(&buf[4]);
+ frame_header->size = _X_BE_32(&buf[4]);
frame_header->flags = _X_BE_16(&buf[8]);
- lprintf("frame: %c%c%c%c, size: %d, flags: %X\n", buf[0], buf[1], buf[2], buf[3],
+ lprintf("frame: %c%c%c%c, size: %zu, flags: %X\n", buf[0], buf[1], buf[2], buf[3],
frame_header->size, frame_header->flags);
return 1;
@@ -638,8 +648,8 @@ static int id3v24_parse_ext_header(input_plugin_t *input,
uint8_t buf[5];
if (input->read (input, buf, 4) == 4) {
-
- frame_ext_header->size = _X_BE_32_synchsafe(&buf[0]);
+
+ frame_ext_header->size = _X_BE_32(&buf[0]);
if (input->read (input, buf, 2) == 2) {
uint8_t flags_size = buf[0];
@@ -704,7 +714,7 @@ static int id3v24_parse_ext_header(input_plugin_t *input,
} else {
return 0;
}
- lprintf("ext header: size: %d, flags: %X, crc: %d, restrictions: %8X\n",
+ lprintf("ext header: size: %zu, flags: %X, crc: %d, restrictions: %8X\n",
frame_ext_header->size, frame_ext_header->flags,
frame_ext_header->crc, frame_ext_header->restrictions);
return 1;
@@ -718,8 +728,11 @@ static int id3v24_interp_frame(input_plugin_t *input,
id3v24_frame_header_t *frame_header) {
char *buf;
int enc;
+ const size_t bufsize = frame_header->size + 2;
+ if ( bufsize < 3 ) /* frames has to be _at least_ 1 byte */
+ return 0;
- buf = malloc(frame_header->size + 1);
+ buf = malloc(bufsize);
if (buf == NULL) {
lprintf("malloc error");
return 0;
@@ -727,17 +740,18 @@ static int id3v24_interp_frame(input_plugin_t *input,
if (input->read (input, buf, frame_header->size) == frame_header->size) {
buf[frame_header->size] = 0;
+ buf[frame_header->size + 1] = 0;
enc = buf[0];
if( enc >= ID3_ENCODING_COUNT )
enc = 0;
-
+
lprintf("data: %s\n", buf+1);
switch (frame_header->id) {
case ( FOURCC_TAG('T', 'C', 'O', 'N') ):
{
char tmp[1024];
-
+
if (id3v24_parse_genre(tmp, buf + 1, 1024)) {
_x_meta_info_set(stream, XINE_META_INFO_GENRE, tmp);
}
@@ -757,6 +771,7 @@ static int id3v24_interp_frame(input_plugin_t *input,
break;
case ( FOURCC_TAG('T', 'Y', 'E', 'R') ):
+ case ( FOURCC_TAG('T', 'D', 'R', 'C') ):
_x_meta_info_set_generic(stream, XINE_META_INFO_YEAR, buf + 1, id3_encoding[enc]);
break;
@@ -781,9 +796,9 @@ static int id3v24_interp_frame(input_plugin_t *input,
}
}
-int id3v24_parse_tag(input_plugin_t *input,
- xine_stream_t *stream,
- int8_t *mp3_frame_header) {
+static int id3v24_parse_tag(input_plugin_t *input,
+ xine_stream_t *stream,
+ int8_t *mp3_frame_header) {
id3v2_header_t tag_header;
id3v24_frame_header_t tag_frame_header;
id3v24_frame_ext_header_t tag_frame_ext_header;
@@ -793,8 +808,8 @@ int id3v24_parse_tag(input_plugin_t *input,
if (tag_header.flags & ID3V24_ZERO_FLAG) {
/* invalid flags */
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid header flags (%02x)\n", tag_header.flags);
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid header flags (%02x)\n", tag_header.flags);
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 0;
}
@@ -809,20 +824,21 @@ int id3v24_parse_tag(input_plugin_t *input,
if (!id3v24_parse_ext_header(input, &tag_frame_ext_header)) {
return 0;
}
+ pos += tag_frame_ext_header.size;
}
/* frame parsing */
while ((pos + ID3V24_FRAME_HEADER_SIZE) <= tag_header.size) {
if (id3v24_parse_frame_header(input, &tag_frame_header)) {
pos += ID3V24_FRAME_HEADER_SIZE;
- if (tag_frame_header.id && tag_frame_header.size) {
+ if (tag_frame_header.id) {
if ((pos + tag_frame_header.size) <= tag_header.size) {
if (!id3v24_interp_frame(input, stream, &tag_frame_header)) {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid frame content\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid frame content\n");
}
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: invalid frame header\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": invalid frame header\n");
input->seek (input, tag_header.size - pos, SEEK_CUR);
return 1;
}
@@ -833,8 +849,8 @@ int id3v24_parse_tag(input_plugin_t *input,
return 1;
}
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "id3: id3v2_parse_frame_header problem\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
+ LOG_MODULE ": id3v2_parse_frame_header problem\n");
return 0;
}
}
@@ -844,7 +860,7 @@ int id3v24_parse_tag(input_plugin_t *input,
}
return 1;
} else {
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG, "id3v23: id3v2_parse_header problem\n");
+ xprintf(stream->xine, XINE_VERBOSITY_DEBUG, LOG_MODULE ": id3v2_parse_header problem\n");
return 0;
}
}
@@ -858,22 +874,22 @@ int id3v2_parse_tag(input_plugin_t *input,
switch(mp3_frame_header[3]) {
case 2:
- xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.2 tag\n");
+ xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": 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");
+ xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": ID3V2.3 tag\n");
result = id3v23_parse_tag(input, stream, mp3_frame_header);
break;
case 4:
- xprintf(stream->xine, XINE_VERBOSITY_LOG, "ID3V2.4 tag\n");
+ xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": ID3V2.4 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]);
+ xprintf(stream->xine, XINE_VERBOSITY_LOG, LOG_MODULE ": 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 b4ea4b6be..41babe2b4 100644
--- a/src/demuxers/id3.h
+++ b/src/demuxers/id3.h
@@ -103,22 +103,22 @@ typedef struct {
uint32_t id;
uint8_t revision;
uint8_t flags;
- uint32_t size;
+ size_t size;
} id3v2_header_t;
typedef struct {
uint32_t id;
- uint32_t size;
+ size_t size;
} id3v22_frame_header_t;
typedef struct {
uint32_t id;
- uint32_t size;
+ size_t size;
uint16_t flags;
} id3v23_frame_header_t;
typedef struct {
- uint32_t size;
+ size_t size;
uint16_t flags;
uint32_t padding_size;
uint32_t crc;
@@ -128,12 +128,12 @@ typedef id3v2_header_t id3v24_footer_t;
typedef struct {
uint32_t id;
- uint32_t size;
+ size_t size;
uint16_t flags;
} id3v24_frame_header_t;
typedef struct {
- uint32_t size;
+ size_t size;
uint8_t flags;
uint32_t crc;
uint8_t restrictions;
@@ -151,19 +151,16 @@ typedef struct {
int id3v1_parse_tag (input_plugin_t *input, xine_stream_t *stream);
-int id3v22_parse_tag(input_plugin_t *input,
- xine_stream_t *stream,
- int8_t *mp3_frame_header);
-
-int id3v23_parse_tag(input_plugin_t *input,
- xine_stream_t *stream,
- int8_t *mp3_frame_header);
-
-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 */
+/**
+ * @brief Generic function for ID3v2 tags parsing.
+ * @param input Pointer to the input plugin used by the demuxer, used
+ * to access the tag's data.
+ * @param stream Pointer to the xine stream currently being read.
+ * @param mp3_frame_header Header of the MP3 frame carrying the tag.
+ *
+ * @note This function will take care of calling the proper function for
+ * parsing ID3v2.2, ID3v2.3 or ID3v2.4 tags.
+ */
int id3v2_parse_tag(input_plugin_t *input,
xine_stream_t *stream,
int8_t *mp3_frame_header);
diff --git a/src/demuxers/iff.h b/src/demuxers/iff.h
index 94830f69c..8ac24a697 100644
--- a/src/demuxers/iff.h
+++ b/src/demuxers/iff.h
@@ -27,8 +27,8 @@
#define IFFP_IFF_H
#define IFF_OKAY 0L
-#define CLIENT_ERROR 1L
-#define NOFILE 5L
+#define IFF_CLIENT_ERROR 1L
+#define IFF_NOFILE 5L
#define FOURCC_CHUNK BE_FOURCC
#define IFF_16SV_CHUNK FOURCC_CHUNK('1', '6', 'S', 'V')
diff --git a/src/demuxers/matroska.h b/src/demuxers/matroska.h
index 6806c207d..0a8226319 100644
--- a/src/demuxers/matroska.h
+++ b/src/demuxers/matroska.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2000-2007 the xine project
+ * Copyright (C) 2000-2009 the xine project
*
* This file is part of xine, a free video player.
*
@@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ *
+ * Matroska EBML stream handling
*/
#ifndef MATROSKA_H
#define MATROSKA_H
@@ -62,6 +64,7 @@
#define MATROSKA_ID_CL_BLOCKGROUP 0xA0
#define MATROSKA_ID_CL_BLOCK 0xA1
#define MATROSKA_ID_CL_BLOCKVIRTUAL 0xA2
+#define MATROSKA_ID_CL_SIMPLEBLOCK 0xA3
#define MATROSKA_ID_CL_BLOCKADDITIONS 0x75A1
#define MATROSKA_ID_CL_BLOCKMORE 0xA6
#define MATROSKA_ID_CL_BLOCKADDID 0xEE
@@ -168,10 +171,16 @@
/* Chapters */
#define MATROSKA_ID_CHAPTERS 0x1043A770
#define MATROSKA_ID_CH_EDITIONENTRY 0x45B9
+#define MATROSKA_ID_CH_ED_UID 0x45BC
+#define MATROSKA_ID_CH_ED_HIDDEN 0x45BD
+#define MATROSKA_ID_CH_ED_DEFAULT 0x45DB
+#define MATROSKA_ID_CH_ED_ORDERED 0x45DD
#define MATROSKA_ID_CH_ATOM 0xB6
#define MATROSKA_ID_CH_UID 0x73C4
#define MATROSKA_ID_CH_TIMESTART 0x91
#define MATROSKA_ID_CH_TIMEEND 0x92
+#define MATROSKA_ID_CH_HIDDEN 0x98
+#define MATROSKA_ID_CH_ENABLED 0x4598
#define MATROSKA_ID_CH_TRACK 0x8F
#define MATROSKA_ID_CH_TRACKNUMBER 0x89
#define MATROSKA_ID_CH_DISPLAY 0x80
@@ -182,6 +191,46 @@
/* Tags */
#define MATROSKA_ID_TAGS 0x1254C367
+/* Chapter (used in tracks) */
+typedef struct {
+ uint64_t uid;
+ uint64_t time_start;
+ uint64_t time_end;
+ /* if not 0, the chapter could e.g. be used for skipping, but not
+ * be shown in the chapter list */
+ int hidden;
+ /* disabled chapters should be skipped during playback (using this
+ * would require parsing control blocks) */
+ int enabled;
+ /* Tracks this chapter belongs to.
+ * Remember that elements can occur in any order, so in theory the
+ * chapters could become available before the tracks do.
+ * TODO: currently unused
+ */
+ /* uint64_t* tracks; */
+ /* Chapter titles and locale information
+ * TODO: chapters can have multiple sets of those, i.e. several tuples
+ * (title, language, country). The current implementation picks from
+ * those by the following rules:
+ * 1) remember the first element
+ * 2) overwrite with an element where language=="eng"
+ */
+ char* title;
+ char* language;
+ char* country;
+} matroska_chapter_t;
+
+/* Edition */
+typedef struct {
+ uint64_t uid;
+ unsigned int hidden;
+ unsigned int is_default;
+ unsigned int ordered;
+
+ int num_chapters, cap_chapters;
+ matroska_chapter_t** chapters;
+} matroska_edition_t;
+
/* Matroska Track */
typedef struct {
int flag_interlaced;
@@ -213,7 +262,8 @@ typedef struct {
typedef struct matroska_track_s matroska_track_t;
struct matroska_track_s {
int track_num;
-
+ uint64_t uid;
+
uint32_t track_type;
uint64_t default_duration;
char *language;
@@ -222,7 +272,7 @@ struct matroska_track_s {
uint32_t codec_private_len;
int default_flag;
uint32_t compress_algo;
-
+
uint32_t buf_type;
fifo_buffer_t *fifo;
@@ -235,7 +285,7 @@ struct matroska_track_s {
void (*handle_content) (demux_plugin_t *this_gen,
matroska_track_t *track,
int decoder_flags,
- uint8_t *data, int data_len,
+ uint8_t *data, size_t data_len,
int64_t data_pts, int data_duration,
int input_normpos, int input_time);
};
diff --git a/src/demuxers/qtpalette.h b/src/demuxers/qtpalette.h
index a8a44e916..422b570a9 100644
--- a/src/demuxers/qtpalette.h
+++ b/src/demuxers/qtpalette.h
@@ -11,7 +11,7 @@ static const unsigned char qt_default_palette_4[4 * 4] = {
0x93, 0x65, 0x5E, 0x00,
0xFF, 0xFF, 0xFF, 0x00,
0xDF, 0xD0, 0xAB, 0x00,
- 0x00, 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
};
static const unsigned char qt_default_palette_16[16 * 4] = {
@@ -30,7 +30,7 @@ static const unsigned char qt_default_palette_16[16 * 4] = {
0xFF, 0xFB, 0xF9, 0x00,
0xE8, 0xCA, 0xC5, 0x00,
0x8A, 0x7C, 0x77, 0x00,
- 0x00, 0x00, 0x00, 0x00
+ 0x00, 0x00, 0x00, 0x00
};
static const unsigned char qt_default_palette_256[256 * 4] = {
diff --git a/src/demuxers/real_common.h b/src/demuxers/real_common.h
new file mode 100644
index 000000000..4945a65ff
--- /dev/null
+++ b/src/demuxers/real_common.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ */
+
+static inline void demux_real_sipro_swap (char buffer[], int bs)
+{
+ /* bs = nybbles per subpacket */
+ static const unsigned char sipr_swaps[38][2] = {
+ {0, 63}, {1, 22}, {2, 44}, {3, 90}, {5, 81}, {7, 31}, {8, 86}, {9, 58},
+ {10, 36}, {12, 68}, {13, 39}, {14, 73}, {15, 53}, {16, 69}, {17, 57},
+ {19, 88}, {20, 34}, {21, 71}, {24, 46}, {25, 94}, {26, 54}, {28, 75},
+ {29, 50}, {32, 70}, {33, 92}, {35, 74}, {38, 85}, {40, 56}, {42, 87},
+ {43, 65}, {45, 59}, {48, 79}, {49, 93}, {51, 89}, {55, 95}, {61, 76},
+ {67, 83}, {77, 80}
+ };
+ int n;
+
+ for (n = 0; n < 38; ++n)
+ {
+ int j;
+ int i = bs * sipr_swaps[n][0];
+ int o = bs * sipr_swaps[n][1];
+ /* swap nibbles of block 'i' with 'o' TODO: optimize */
+ for (j = 0; j < bs; ++j)
+ {
+ int x = (i & 1) ? (buffer[i >> 1] >> 4) : (buffer[i >> 1] & 0x0F);
+ int y = (o & 1) ? (buffer[o >> 1] >> 4) : (buffer[o >> 1] & 0x0F);
+ if (o & 1)
+ buffer[o >> 1] = (buffer[o >> 1] & 0x0F) | (x << 4);
+ else
+ buffer[o >> 1] = (buffer[o >> 1] & 0xF0) | x;
+ if (i & 1)
+ buffer[i >> 1] = (buffer[i >> 1] & 0x0F) | (y << 4);
+ else
+ buffer[i >> 1] = (buffer[i >> 1] & 0xF0) | y;
+ ++i;
+ ++o;
+ }
+ }
+}