diff options
Diffstat (limited to 'src/demuxers')
61 files changed, 2350 insertions, 1376 deletions
diff --git a/src/demuxers/Makefile.am b/src/demuxers/Makefile.am index ffbfa0a8d..3bc1103ec 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) @@ -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 @@ -130,7 +131,7 @@ 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_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 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_4xm.c b/src/demuxers/demux_4xm.c index 24aee1ac4..397a271b8 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) { @@ -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..68a684ffa 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; } @@ -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,7 +173,7 @@ 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; @@ -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..711bb0b45 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 @@ -308,13 +311,7 @@ static int demux_ac3_send_chunk (demux_plugin_t *this_gen) { 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; @@ -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..273992f64 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 */ @@ -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); } @@ -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..d79782026 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; @@ -351,6 +352,14 @@ static void asf_send_video_header (demux_asf_t *this, int stream) { 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; @@ -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,7 +415,11 @@ 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"); @@ -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, @@ -703,7 +738,10 @@ 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]); @@ -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; } @@ -1657,6 +1697,7 @@ 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; @@ -2059,7 +2100,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; @@ -2134,7 +2175,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; diff --git a/src/demuxers/demux_aud.c b/src/demuxers/demux_aud.c index a6f88ff48..7730de1fa 100644 --- a/src/demuxers/demux_aud.c +++ b/src/demuxers/demux_aud.c @@ -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..0ab3448bb 100644 --- a/src/demuxers/demux_avi.c +++ b/src/demuxers/demux_avi.c @@ -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 @@ -719,7 +721,7 @@ static void reset_idx(demux_avi_t *this, avi_t *AVI) { } } -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; @@ -780,7 +782,7 @@ static avi_t *AVI_init(demux_avi_t *this) { 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; @@ -790,7 +792,7 @@ static avi_t *AVI_init(demux_avi_t *this) { 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 ) @@ -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]); @@ -877,12 +880,11 @@ static avi_t *AVI_init(demux_avi_t *this) { } 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; @@ -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; @@ -973,6 +975,10 @@ static avi_t *AVI_init(demux_avi_t *this) { 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 ) @@ -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); @@ -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); @@ -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..8e9ad3679 100644 --- a/src/demuxers/demux_cdda.c +++ b/src/demuxers/demux_cdda.c @@ -187,7 +187,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 +250,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..ed1f16d33 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); @@ -223,7 +278,7 @@ static int demux_dts_send_chunk (demux_plugin_t *this_gen) { this->frame_size); } - if (buf->size == 0) { + if (buf->size <= 0) { buf->free_buffer(buf); this->status = DEMUX_FINISHED; return this->status; @@ -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..7a21635cb 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; @@ -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..a66befe01 100644 --- a/src/demuxers/demux_elem.c +++ b/src/demuxers/demux_elem.c @@ -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; diff --git a/src/demuxers/demux_film.c b/src/demuxers/demux_film.c index 13036afc1..dcd57f76c 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); @@ -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); @@ -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..c14536040 100644 --- a/src/demuxers/demux_flac.c +++ b/src/demuxers/demux_flac.c @@ -164,8 +164,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; @@ -189,7 +191,7 @@ static int open_flac_file(demux_flac_t *flac) { 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,18 +204,25 @@ 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); @@ -223,6 +232,9 @@ static int open_flac_file(demux_flac_t *flac) { } 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 +260,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 +393,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 +407,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) @@ -482,7 +506,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 +568,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 +581,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..12ae81609 100644 --- a/src/demuxers/demux_fli.c +++ b/src/demuxers/demux_fli.c @@ -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..d3da20136 100644 --- a/src/demuxers/demux_flv.c +++ b/src/demuxers/demux_flv.c @@ -21,10 +21,10 @@ /* * Flash Video (.flv) File Demuxer * by Mike Melanson (melanson@pcisys.net) and - * Claudio Ciccani (klan@directfb.org) + * 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 @@ -85,7 +85,7 @@ typedef struct { off_t filesize; flv_index_entry_t *index; - int num_indices; + unsigned int num_indices; unsigned int cur_pts; @@ -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 @@ -209,7 +215,7 @@ static int parse_flv_var(demux_flv_t *this, unsigned char *end = buf + size; char *str; unsigned char type; - int len, num; + unsigned int len, num; if (size < 1) return 0; @@ -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; @@ -349,12 +371,12 @@ static int parse_flv_var(demux_flv_t *this, } 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; @@ -413,11 +435,24 @@ 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; @@ -448,8 +483,17 @@ static int read_flv_packet(demux_flv_t *this, int preview) { } 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) { @@ -468,6 +512,12 @@ 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; @@ -495,6 +545,23 @@ 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; } @@ -502,9 +569,9 @@ static int read_flv_packet(demux_flv_t *this, int preview) { 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,10 +645,13 @@ 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: @@ -582,33 +663,61 @@ static int read_flv_packet(demux_flv_t *this, int preview) { 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 = (int)((double)this->input->get_current_pos(this->input) * 65535.0 / this->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_FLAG_SPECIAL | BUF_FLAG_HEADER; + if (preview) + buf->decoder_flags |= BUF_FLAG_PREVIEW; - 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; + 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); @@ -631,8 +740,8 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) { 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; @@ -658,11 +767,9 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) { 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); @@ -697,49 +804,50 @@ static void seek_flv_file(demux_flv_t *this, off_t seek_pos, int seek_pts) { 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; + 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); + 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; - } + 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); + 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 (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); + 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); + /* seek back to the beginning of the tag */ + this->input->seek(this->input, -len, SEEK_CUR); - lprintf( " seeked to %d.\n", pts); + lprintf( " seeked to %d.\n", pts); + } } @@ -789,8 +897,12 @@ 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); @@ -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..d44f03ab3 100644 --- a/src/demuxers/demux_idcin.c +++ b/src/demuxers/demux_idcin.c @@ -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..feaf3ceaa 100644 --- a/src/demuxers/demux_image.c +++ b/src/demuxers/demux_image.c @@ -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; @@ -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..4ef877988 100644 --- a/src/demuxers/demux_ipmovie.c +++ b/src/demuxers/demux_ipmovie.c @@ -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; @@ -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.c b/src/demuxers/demux_matroska.c index b973c1caf..5cf783bf5 100644 --- a/src/demuxers/demux_matroska.c +++ b/src/demuxers/demux_matroska.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2007 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -58,13 +58,6 @@ #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; @@ -113,7 +106,7 @@ typedef struct { /* block */ uint8_t *block_data; - int block_data_size; + size_t block_data_size; /* current tracks */ matroska_track_t *video_track; /* to remove */ @@ -614,6 +607,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,6 +616,8 @@ 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++) { @@ -635,9 +632,7 @@ static void init_codec_xiph(demux_matroska_t *this, matroska_track_t *track) { } buf->size = frame[i]; - buf->decoder_flags = BUF_FLAG_HEADER; - if (i == 2) - buf->decoder_flags |= BUF_FLAG_FRAME_END; + buf->decoder_flags = BUF_FLAG_HEADER | BUF_FLAG_FRAME_START | BUF_FLAG_FRAME_END; buf->type = track->buf_type; buf->pts = 0; @@ -685,7 +680,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 +883,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; @@ -933,7 +932,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; @@ -1008,7 +1007,7 @@ static void handle_sub_ssa (demux_plugin_t *this_gen, matroska_track_t *track, 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; @@ -1055,7 +1054,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; @@ -1179,19 +1178,21 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { break; case MATROSKA_ID_TR_CODECID: { - char *codec_id = malloc (elem.len + 1); + char *codec_id = ebml_alloc_read_ascii (ebml, &elem); lprintf("CodecID\n"); - if (!ebml_read_ascii(ebml, &elem, codec_id)) { - free(codec_id); + if (!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); + 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); @@ -1203,13 +1204,10 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { break; case MATROSKA_ID_TR_LANGUAGE: { - char *language = malloc (elem.len + 1); + char *language = ebml_alloc_read_ascii (ebml, &elem); lprintf("Language\n"); - if (!ebml_read_ascii(ebml, &elem, language)) { - free(language); + if (!language) return 0; - } - language[elem.len] = '\0'; track->language = language; } break; @@ -1218,7 +1216,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { 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)) @@ -1229,7 +1227,7 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { 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)) @@ -1298,12 +1296,14 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { 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)) || @@ -1312,8 +1312,11 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { 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; @@ -1333,8 +1336,11 @@ static int parse_track_entry(demux_matroska_t *this, matroska_track_t *track) { 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; @@ -1409,11 +1415,13 @@ 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)) { lprintf("MATROSKA_CODEC_ID_A_AAC\n"); @@ -1494,9 +1502,14 @@ 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); - + } } } @@ -1519,7 +1532,7 @@ static int parse_tracks(demux_matroska_t *this) { matroska_track_t *track; /* 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; @@ -1746,7 +1759,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) @@ -1818,10 +1831,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 +1850,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 +1875,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 +1891,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 +1925,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 +1945,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 */ @@ -1972,24 +2000,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 +2078,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 +2113,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) { @@ -2087,7 +2167,8 @@ static int parse_block_group(demux_matroska_t *this, 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 +2185,7 @@ static int parse_cluster(demux_matroska_t *this) { this->first_cluster_found = 1; } - while (next_level == 2) { + while (next_level == this_level) { ebml_elem_t elem; if (!ebml_read_elem_head(ebml, &elem)) @@ -2128,6 +2209,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)) @@ -2274,6 +2360,7 @@ 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); @@ -2824,7 +2911,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; @@ -2884,7 +2971,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 +2987,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_mng.c b/src/demuxers/demux_mng.c index 12da8ca86..d0d83ff80 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); @@ -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..34b8ebabe 100644 --- a/src/demuxers/demux_mod.c +++ b/src/demuxers/demux_mod.c @@ -73,7 +73,7 @@ typedef struct { char *title; char *artist; char *copyright; - off_t filesize; + size_t filesize; char *buffer; @@ -130,11 +130,22 @@ 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); @@ -305,7 +316,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; @@ -368,7 +379,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 +403,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..220e1b8b6 100644 --- a/src/demuxers/demux_mpc.c +++ b/src/demuxers/demux_mpc.c @@ -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) @@ -89,17 +90,13 @@ 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) @@ -118,9 +115,7 @@ static int open_mpc_file(demux_mpc_t *this) { } /* 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; @@ -214,7 +209,7 @@ static int demux_mpc_send_chunk(demux_plugin_t *this_gen) { /* 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; @@ -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; @@ -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..85b62f48e 100644 --- a/src/demuxers/demux_mpeg.c +++ b/src/demuxers/demux_mpeg.c @@ -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,6 +302,10 @@ 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; @@ -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) @@ -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; @@ -431,7 +447,7 @@ 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) ? this->audio_fifo->buffer_pool_buf_size : this->video_fifo->buffer_pool_buf_size) { @@ -503,7 +519,7 @@ static void parse_mpeg2_packet (demux_mpeg_t *this, int stream_id, int64_t scr) } /* 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 */ @@ -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; } @@ -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; @@ -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; diff --git a/src/demuxers/demux_mpeg_block.c b/src/demuxers/demux_mpeg_block.c index 32638129d..ffbc63f3d 100644 --- a/src/demuxers/demux_mpeg_block.c +++ b/src/demuxers/demux_mpeg_block.c @@ -1190,14 +1190,14 @@ static int demux_mpeg_detect_blocksize(demux_mpeg_block_t *this, input_plugin_t *input) { input->seek(input, 2048, SEEK_SET); - if (!input->read(input, this->scratch, 4)) + if (input->read(input, this->scratch, 4) != 4) return 0; if (this->scratch[0] || this->scratch[1] || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) { input->seek(input, 2324, SEEK_SET); - if (!input->read(input, this->scratch, 4)) + if (input->read(input, this->scratch, 4) != 4) return 0; if (this->scratch[0] || this->scratch[1] || (this->scratch[2] != 0x01) || (this->scratch[3] != 0xba)) @@ -1371,7 +1371,7 @@ 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; @@ -1417,6 +1417,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str } input->seek(input, 0, SEEK_SET); + memset (this->scratch, 255, 5); /* result of input->read() won't matter */ if (input->read(input, this->scratch, this->blocksize)) { lprintf("open_plugin:read worked\n"); @@ -1540,7 +1541,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; diff --git a/src/demuxers/demux_mpeg_pes.c b/src/demuxers/demux_mpeg_pes.c index 423da5e24..b7c0e7e6d 100644 --- a/src/demuxers/demux_mpeg_pes.c +++ b/src/demuxers/demux_mpeg_pes.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2006 the xine project + * Copyright (C) 2000-2008 the xine project * * This file is part of xine, a free video player. * @@ -257,7 +257,6 @@ 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; @@ -274,7 +273,7 @@ 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; @@ -306,8 +305,7 @@ static void demux_mpeg_pes_parse_pack (demux_mpeg_pes_t *this, int preview_mode) 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; @@ -1613,7 +1611,7 @@ 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; @@ -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; diff --git a/src/demuxers/demux_mpgaudio.c b/src/demuxers/demux_mpgaudio.c index 3730da6e4..a87de5f97 100644 --- a/src/demuxers/demux_mpgaudio.c +++ b/src/demuxers/demux_mpgaudio.c @@ -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 */ @@ -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; } @@ -280,19 +294,27 @@ static int parse_frame_header(mpg_audio_frame_t *const frame, const uint8_t *con 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; @@ -325,11 +347,11 @@ static xing_header_t* parse_xing_header(mpg_audio_frame_t *frame, 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; @@ -416,14 +438,14 @@ 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; @@ -432,7 +454,7 @@ static vbri_header_t* parse_vbri_header(mpg_audio_frame_t *frame, 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; @@ -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; @@ -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); - } - - 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)) { + 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; + } + } + } + + 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; @@ -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); } @@ -1047,13 +1158,15 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str 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; @@ -1076,8 +1189,8 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str 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; } @@ -1147,7 +1265,7 @@ 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..926ea97e1 100644 --- a/src/demuxers/demux_nsf.c +++ b/src/demuxers/demux_nsf.c @@ -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); @@ -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..42d31ca14 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 @@ -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); @@ -302,13 +295,13 @@ static int open_nsv_file(demux_nsv_t *this) { 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); @@ -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..e3a9b20c4 100644 --- a/src/demuxers/demux_ogg.c +++ b/src/demuxers/demux_ogg.c @@ -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) { @@ -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); } } @@ -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); + 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"; - /* 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'); - - /* 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; @@ -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); @@ -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: { @@ -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; @@ -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; @@ -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; @@ -2155,14 +2165,19 @@ static const char *ogg_get_identifier (demux_class_t *this_gen) { } 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; diff --git a/src/demuxers/demux_pva.c b/src/demuxers/demux_pva.c index 298d936b5..ddd32b63c 100644 --- a/src/demuxers/demux_pva.c +++ b/src/demuxers/demux_pva.c @@ -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..5aba5b479 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 */ @@ -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; @@ -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; + } } } @@ -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; @@ -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]); + if (current_stsd_atom_size < 4) { + last_error = QT_HEADER_TROUBLE; + goto free_trak; + } if (trak->type == MEDIA_VIDEO) { @@ -955,6 +990,10 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].video.properties_atom_size = current_stsd_atom_size - 4; 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); @@ -1094,6 +1133,10 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].audio.properties_atom_size = current_stsd_atom_size - 4; 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); @@ -1185,10 +1228,11 @@ static qt_error parse_trak_atom (qt_trak *trak, if (_X_BE_32(&trak_atom[atom_pos + 0x2C])) 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 */ @@ -1210,6 +1254,10 @@ static qt_error parse_trak_atom (qt_trak *trak, trak->stsd_atoms[k].audio.properties_atom_size = 36; 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 + 0x20], trak->stsd_atoms[k].audio.properties_atom_size); @@ -1231,6 +1279,10 @@ static qt_error parse_trak_atom (qt_trak *trak, (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); @@ -1300,8 +1352,16 @@ 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); } } @@ -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,46 @@ 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; + + 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 ) + url_offset = strlen(base_mrl); + 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 ) + strcpy(ref->url, 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); @@ -1686,8 +1754,7 @@ static qt_error build_frame_table(qt_trak *trak, /* 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 +1766,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++) { @@ -1837,8 +1903,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; @@ -1993,8 +2058,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); @@ -2145,7 +2214,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; @@ -2944,7 +3013,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 +3128,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 +3144,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; diff --git a/src/demuxers/demux_rawdv.c b/src/demuxers/demux_rawdv.c index 2d21f080d..86f777ec6 100644 --- a/src/demuxers/demux_rawdv.c +++ b/src/demuxers/demux_rawdv.c @@ -347,7 +347,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; @@ -374,8 +374,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, xine_stream_t *str } /* 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 +435,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 9206bfc74..8f1e4f539 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. * @@ -55,13 +55,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 +90,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; @@ -113,6 +113,12 @@ typedef struct { 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 { @@ -168,15 +174,13 @@ 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 +196,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)); + if(index && entries) + /* Allocate memory for index */ + *index = calloc(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 && *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 +265,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 +282,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 +324,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 +340,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; + } + + if ( !_x_is_fourcc(signature, ".RMF") ) { + this->status = DEMUX_FINISHED; + lprintf ("signature not found '%.4s'\n", signature); + return; + } - lprintf ("signature not read\n"); - this->status = DEMUX_FINISHED; - return; + /* skip to the start of the first chunk and start traversing */ + chunk_size = _X_BE_32(&signature[4]); } - if (_X_BE_32(signature) != RMF_TAG) { - this->status = DEMUX_FINISHED; - lprintf ("signature not found '%.4s'\n", signature); - return; - } + this->data_start = 0; + this->data_size = 0; + this->num_video_streams = 0; + this->num_audio_streams = 0; - /* skip to the start of the first chunk and start traversing */ - chunk_size = _X_BE_32(&signature[4]); this->input->seek(this->input, chunk_size-8, SEEK_CUR); /* iterate through chunks and gather information until the first DATA @@ -371,171 +463,190 @@ static void real_parse_headers (demux_real_t *this) { case PROP_TAG: case MDPR_TAG: case CONT_TAG: - - 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; - } + { + 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; + } - version = _X_BE_16(&chunk_buffer[0]); + uint16_t version = _X_BE_16(&chunk_buffer[0]); - if (chunk_type == PROP_TAG) { + 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, + 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) { - - mdpr_t *mdpr; - uint32_t fourcc; - - 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; - } + } 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 = real_parse_mdpr (chunk_buffer); - - lprintf ("parsing type specific data...\n"); - - if(_X_BE_32(mdpr->type_specific_data) == RA_TAG) { - int version, len; - - 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; - } + 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; + } - version = _X_BE_16(mdpr->type_specific_data + 4); + const uint16_t version = _X_BE_16(mdpr->type_specific_data + 4); - lprintf("audio version %d detected\n", version); + lprintf("audio version %d detected\n", version); - switch(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 * 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", fourcc_ptr); - lprintf("fourcc = %.4s\n", (char *) &fourcc); + 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; + 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++; + 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) { + } 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; - } + 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 ("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: + 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; @@ -543,7 +654,7 @@ unknown: } /* 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 +665,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 */ @@ -570,16 +682,9 @@ unknown: 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; + 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; - if(this->num_audio_streams == 1) - this->audio_stream = &this->audio_streams[0]; - else - this->audio_stream = NULL; - /* In the case of multiple audio/video streams select the first streams found in the file */ if((this->num_video_streams > 1) || (this->num_audio_streams > 1)) { @@ -619,15 +724,13 @@ unknown: 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; + if (_x_is_fourcc(&search_buffer[offset], "INDX") || _x_is_fourcc(&search_buffer[offset], "DATA")) + break; - stream = _X_BE_16(&search_buffer[offset + 4]); + 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) { @@ -661,14 +764,12 @@ unknown: /* 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, @@ -690,7 +791,7 @@ unknown: 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; } @@ -701,10 +802,9 @@ 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; @@ -714,7 +814,7 @@ unknown: * 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, @@ -745,6 +845,13 @@ unknown: memcpy(buf->content, mdpr->type_specific_data + 79, buf->decoder_info[2]); + } else if(buf->type == BUF_AUDIO_MP3ADU) { + buf->decoder_flags |= BUF_FLAG_STDHEADER | BUF_FLAG_FRAME_END; + buf->size = 0; + buf->decoder_info[0] = 0; + buf->decoder_info[1] = 0; + buf->decoder_info[2] = 0; + buf->decoder_info[3] = 0; } else { memcpy(buf->content, mdpr->type_specific_data, mdpr->type_specific_len); @@ -868,9 +975,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 && @@ -976,18 +1081,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, @@ -998,15 +1099,14 @@ 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); @@ -1015,11 +1115,11 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { } /* 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) @@ -1034,11 +1134,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"); @@ -1053,21 +1151,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 { @@ -1128,9 +1225,8 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { 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); @@ -1175,13 +1271,17 @@ 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); @@ -1189,14 +1289,11 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { * 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; @@ -1280,12 +1377,9 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { 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; + const off_t input_length = this->data_start + 18 + this->data_chunk_size; - if( input_length ) + if( input_length > 18 ) normpos = (int)((double) this->input->get_current_pos(this->input) * 65535 / input_length); check_newpts (this, pts, PTS_AUDIO, 0); @@ -1293,13 +1387,14 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { /* 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); @@ -1311,15 +1406,77 @@ static int demux_real_send_chunk(demux_plugin_t *this_gen) { 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, this->audio_stream->buf_type, 0, normpos, @@ -1352,18 +1509,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, @@ -1469,6 +1618,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); } @@ -1499,19 +1651,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); } @@ -1538,21 +1687,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; @@ -1561,32 +1716,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); @@ -1605,17 +1752,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"); @@ -1662,9 +1803,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..44449667c 100644 --- a/src/demuxers/demux_realaudio.c +++ b/src/demuxers/demux_realaudio.c @@ -41,6 +41,8 @@ #include "bswap.h" #include "group_audio.h" +#include "real_common.h" + #define RA_FILE_HEADER_PREV_SIZE 22 typedef struct { @@ -62,6 +64,12 @@ 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,25 +78,23 @@ 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) @@ -101,14 +107,15 @@ static int open_ra_file(demux_ra_t *this) { } /* allocate for and read header data */ - this->header = xine_xmalloc(this->header_size); + this->header = malloc(this->header_size); - if (_x_demux_read_header(this->input, this->header, this->header_size) != 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]); @@ -138,47 +145,81 @@ static int open_ra_file(demux_ra_t *this) { } /* 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,7 +238,6 @@ 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 */ @@ -205,14 +245,45 @@ static int demux_ra_send_chunk(demux_plugin_t *this_gen) { 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, + 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; @@ -244,10 +315,7 @@ static void demux_ra_send_headers(demux_plugin_t *this_gen) { 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); @@ -299,6 +367,8 @@ static void demux_ra_dispose (demux_plugin_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; @@ -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..df2fb76a5 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,8 +92,9 @@ 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); @@ -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..ccc34b57f 100644 --- a/src/demuxers/demux_shn.c +++ b/src/demuxers/demux_shn.c @@ -88,7 +88,7 @@ static int demux_shn_send_chunk(demux_plugin_t *this_gen) { 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; @@ -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..abb4d01e5 100644 --- a/src/demuxers/demux_slave.c +++ b/src/demuxers/demux_slave.c @@ -90,10 +90,11 @@ static int demux_slave_next (demux_slave_t *this) { /* 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; diff --git a/src/demuxers/demux_smjpeg.c b/src/demuxers/demux_smjpeg.c index 899fbf7e3..aacd55503 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,23 +97,18 @@ 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]); @@ -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..b98b66758 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 */ @@ -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; @@ -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..442bffadc 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. * @@ -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(§or[0x18]) != STR_MAGIC || + if (!_x_is_fourcc(§or[0x18], STR_MAGIC) || channel != this->default_video_channel) { return 0; } @@ -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; @@ -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..98de1f9ea 100644 --- a/src/demuxers/demux_ts.c +++ b/src/demuxers/demux_ts.c @@ -185,9 +185,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 +217,9 @@ 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, } streamType; #define WRAP_THRESHOLD 270000 @@ -246,10 +245,11 @@ 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; @@ -752,15 +752,16 @@ 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 == ISO_13818_PES_PRIVATE && p[0] == 0x20 && p[1] == 0x00) { /* DVBSUB */ long payload_len = ((buf[4] << 8) | buf[5]) - header_len - 3; @@ -808,6 +809,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; @@ -931,9 +933,11 @@ static void demux_ts_buffer_pes(demux_ts_t*this, unsigned char *ts, 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, @@ -982,7 +986,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]; @@ -1193,6 +1197,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 @@ -1230,6 +1243,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 @@ -1331,7 +1353,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 +1365,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; @@ -1555,7 +1576,7 @@ static unsigned char * demux_synchronise(demux_ts_t* this) { do { read_length = this->input->read(this->input, this->buf, PKT_SIZE * NPKT_PER_READ); - if (read_length % PKT_SIZE) { + if (read_length < 0 || read_length % 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); @@ -1837,7 +1858,8 @@ static void demux_ts_parse_packet (demux_ts_t*this) { } 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) { @@ -1859,11 +1881,12 @@ 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++; } } @@ -2229,7 +2252,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; @@ -2250,6 +2273,7 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, 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++) { @@ -2270,12 +2294,6 @@ static demux_plugin_t *open_plugin (demux_class_t *class_gen, this->status = DEMUX_FINISHED; -#ifdef TS_READ_STATS - for (i=0; i<=NPKT_PER_READ; i++) { - this->rstat[i] = 0; - } -#endif - /* DVBSUB */ this->spu_pid = INVALID_PID; this->spu_langs_count = 0; @@ -2320,7 +2338,7 @@ 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; diff --git a/src/demuxers/demux_tta.c b/src/demuxers/demux_tta.c index f6eadd652..24a983157 100644 --- a/src/demuxers/demux_tta.c +++ b/src/demuxers/demux_tta.c @@ -21,6 +21,10 @@ * Inspired by tta libavformat demuxer by Alex Beregszaszi */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #define LOG_MODULE "demux_tta" #define LOG_VERBOSE @@ -72,7 +76,7 @@ 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) ) @@ -87,7 +91,7 @@ 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 */ @@ -126,6 +130,10 @@ static int demux_tta_send_chunk(demux_plugin_t *this_gen) { /* buf->extra_info->input_time = this->current_sample / this->samplerate; */ bytes_read = this->input->read(this->input, buf->content, ( bytes_to_read > buf->max_size ) ? buf->max_size : bytes_to_read); + if (bytes_read < 0) { + this->status = DEMUX_FINISHED; + break; + } buf->size = bytes_read; @@ -233,7 +241,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; @@ -307,7 +315,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..b81e4575e 100644 --- a/src/demuxers/demux_vmd.c +++ b/src/demuxers/demux_vmd.c @@ -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; @@ -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..e825f6869 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 */ @@ -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) @@ -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..1b34106ad 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; @@ -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..5fb8273dd 100644 --- a/src/demuxers/demux_vqa.c +++ b/src/demuxers/demux_vqa.c @@ -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 */ @@ -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..7750c3e0e 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, @@ -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 */ @@ -378,17 +378,21 @@ static int open_mve_file(demux_mve_t *this) { 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); @@ -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..2387fc7a7 100644 --- a/src/demuxers/demux_yuv4mpeg2.c +++ b/src/demuxers/demux_yuv4mpeg2.c @@ -197,21 +197,13 @@ static int open_yuv4mpeg2_file(demux_yuv4mpeg2_t *this) { 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)) { @@ -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) != @@ -291,7 +277,6 @@ static int demux_yuv4mpeg2_send_chunk(demux_plugin_t *this_gen) { 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,7 +295,7 @@ 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 */ @@ -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..089207f58 100644 --- a/src/demuxers/demux_yuv_frames.c +++ b/src/demuxers/demux_yuv_frames.c @@ -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){ @@ -129,13 +126,19 @@ static void demux_yuv_frames_send_headers (demux_plugin_t *this_gen){ 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..4ce8a549d 100644 --- a/src/demuxers/ebml.c +++ b/src/demuxers/ebml.c @@ -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); } @@ -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..9aa471c0b 100644 --- a/src/demuxers/ebml.h +++ b/src/demuxers/ebml.h @@ -65,7 +65,7 @@ typedef struct ebml_parser_s { } 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/id3.c b/src/demuxers/id3.c index 6b36cc666..39055a852 100644 --- a/src/demuxers/id3.c +++ b/src/demuxers/id3.c @@ -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; @@ -261,7 +261,7 @@ static int id3v22_parse_frame_header(input_plugin_t *input, frame_header->size = _X_BE_24_synchsafe(&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; + 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; @@ -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; @@ -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; @@ -349,21 +353,21 @@ 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); + 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"); + 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"); + 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"); + LOG_MODULE ": invalid frame content\n"); } } else { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame header\n"); + LOG_MODULE ": invalid frame header\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } @@ -391,13 +395,13 @@ int id3v22_parse_tag(input_plugin_t *input, } } else { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: id3v2_parse_frame_header problem\n"); + 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; @@ -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; - - 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; @@ -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; @@ -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; @@ -543,14 +551,14 @@ 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); + 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"); + 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"); + LOG_MODULE ": invalid frame content\n"); } } else { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame header\n"); + 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"); + 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; } } @@ -624,7 +634,7 @@ static int id3v24_parse_frame_header(input_plugin_t *input, frame_header->size = _X_BE_32_synchsafe(&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; @@ -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; - - 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; @@ -727,6 +740,7 @@ 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; @@ -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; @@ -794,7 +809,7 @@ 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); + 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"); + LOG_MODULE ": invalid frame content\n"); } } else { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: invalid frame header\n"); + LOG_MODULE ": invalid frame header\n"); input->seek (input, tag_header.size - pos, SEEK_CUR); return 1; } @@ -834,7 +850,7 @@ int id3v24_parse_tag(input_plugin_t *input, } } else { xprintf(stream->xine, XINE_VERBOSITY_DEBUG, - "id3: id3v2_parse_frame_header problem\n"); + 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..df6e8ad1b 100644 --- a/src/demuxers/matroska.h +++ b/src/demuxers/matroska.h @@ -62,6 +62,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 @@ -235,7 +236,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/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; + } + } +} |