From 6cf110c1e38db7612df9e86bad61e23471107477 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 18 Jun 2008 10:28:20 +0000 Subject: [PATCH] gst/matroska/matroska-demux.c: Improve debug output everywhere and fix the EOS logic. Original commit message from CVS: * gst/matroska/matroska-demux.c: (gst_matroska_demux_reset), (gst_matroska_demux_stream_from_num), (gst_matroska_demux_encoding_cmp), (gst_matroska_demux_encoding_order_unique), (gst_matroska_demux_read_track_encoding), (gst_matroska_demux_read_track_encodings), (gst_matroska_demux_tracknumber_unique), (gst_matroska_demux_add_stream), (gst_matroska_demux_init_stream), (gst_matroska_demux_parse_tracks), (gst_matroska_demux_parse_index_cuetrack), (gst_matroska_demux_parse_index_pointentry), (gst_matroska_demux_parse_index), (gst_matroska_demux_parse_info), (gst_matroska_demux_parse_metadata_id_simple_tag), (gst_matroska_demux_parse_metadata_id_tag), (gst_matroska_demux_parse_metadata), (gst_matroska_demux_parse_attached_file), (gst_matroska_demux_parse_attachments), (gst_matroska_demux_parse_chapters), (gst_matroska_demux_sync_streams), (gst_matroska_decode_buffer), (gst_matroska_demux_parse_blockgroup_or_simpleblock), (gst_matroska_demux_parse_cluster), (gst_matroska_demux_parse_contents_seekentry), (gst_matroska_demux_parse_contents), (gst_matroska_demux_loop_stream_parse_id), (gst_matroska_demux_loop): Improve debug output everywhere and fix the EOS logic. Check the values of the ContentEncoding elements more strictly and don't use tracks for which it's invalid. Check that the track number is unique for this stream. Check that seek positions are below G_MAXINT64 as our seeks are int64-based and overflows will fail badly. After seeks also don't push SimpleBlocks until the first one containing a keyframe is found. Before this was done only for normal Blocks. Update some FIXME/TODOs. * gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes), (gst_ebml_read_utf8), (gst_ebml_read_header): Improve debug output. * gst/matroska/matroska-ids.c: (gst_matroska_track_init_video_context): * gst/matroska/matroska-ids.h: * gst/matroska/matroska-mux.c: (gst_matroska_mux_video_pad_setcaps): Remove eye mode and don't parse it anymore. We can't use that information in GStreamer yet so it's useless. --- ChangeLog | 56 ++ gst/matroska/ebml-read.c | 16 +- gst/matroska/matroska-demux.c | 1291 +++++++++++++++++++++++------------------ gst/matroska/matroska-ids.c | 1 - gst/matroska/matroska-ids.h | 8 - gst/matroska/matroska-mux.c | 1 - 6 files changed, 799 insertions(+), 574 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b63b48..94ece96 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,59 @@ +2008-06-18 Sebastian Dröge + + * gst/matroska/matroska-demux.c: (gst_matroska_demux_reset), + (gst_matroska_demux_stream_from_num), + (gst_matroska_demux_encoding_cmp), + (gst_matroska_demux_encoding_order_unique), + (gst_matroska_demux_read_track_encoding), + (gst_matroska_demux_read_track_encodings), + (gst_matroska_demux_tracknumber_unique), + (gst_matroska_demux_add_stream), (gst_matroska_demux_init_stream), + (gst_matroska_demux_parse_tracks), + (gst_matroska_demux_parse_index_cuetrack), + (gst_matroska_demux_parse_index_pointentry), + (gst_matroska_demux_parse_index), (gst_matroska_demux_parse_info), + (gst_matroska_demux_parse_metadata_id_simple_tag), + (gst_matroska_demux_parse_metadata_id_tag), + (gst_matroska_demux_parse_metadata), + (gst_matroska_demux_parse_attached_file), + (gst_matroska_demux_parse_attachments), + (gst_matroska_demux_parse_chapters), + (gst_matroska_demux_sync_streams), (gst_matroska_decode_buffer), + (gst_matroska_demux_parse_blockgroup_or_simpleblock), + (gst_matroska_demux_parse_cluster), + (gst_matroska_demux_parse_contents_seekentry), + (gst_matroska_demux_parse_contents), + (gst_matroska_demux_loop_stream_parse_id), + (gst_matroska_demux_loop): + Improve debug output everywhere and fix the EOS logic. + + Check the values of the ContentEncoding elements more strictly and + don't use tracks for which it's invalid. + + Check that the track number is unique for this stream. + + Check that seek positions are below G_MAXINT64 as our seeks are + int64-based and overflows will fail badly. + + After seeks also don't push SimpleBlocks until the first one + containing a keyframe is found. Before this was done only for normal + Blocks. + + Update some FIXME/TODOs. + + * gst/matroska/ebml-read.c: (gst_ebml_read_peek_bytes), + (gst_ebml_read_utf8), (gst_ebml_read_header): + Improve debug output. + + * gst/matroska/matroska-ids.c: + (gst_matroska_track_init_video_context): + * gst/matroska/matroska-ids.h: + * gst/matroska/matroska-mux.c: + (gst_matroska_mux_video_pad_setcaps): + Remove eye mode and don't parse it anymore. We can't use that + information in GStreamer yet so it's useless. + + 2008-06-18 Wim Taymans Patch by: mersad diff --git a/gst/matroska/ebml-read.c b/gst/matroska/ebml-read.c index 82d8217..6ce679d 100644 --- a/gst/matroska/ebml-read.c +++ b/gst/matroska/ebml-read.c @@ -247,7 +247,7 @@ gst_ebml_read_peek_bytes (GstEbmlRead * ebml, guint size, GstBuffer ** p_buf, gst_pad_pull_range (ebml->sinkpad, ebml->offset, size, &ebml->cached_buffer); if (ret != GST_FLOW_OK) { - GST_DEBUG ("pull_range returned %d", ret); + GST_DEBUG_OBJECT (ebml, "pull_range returned %d", ret); if (p_buf) *p_buf = NULL; if (bytes) @@ -804,7 +804,8 @@ gst_ebml_read_utf8 (GstEbmlRead * ebml, guint32 * id, gchar ** str) if (str != NULL && *str != NULL && **str != '\0' && !g_utf8_validate (*str, -1, NULL)) { - GST_WARNING ("Invalid UTF-8 string at offset %" G_GUINT64_FORMAT, oldoff); + GST_WARNING_OBJECT (ebml, + "Invalid UTF-8 string at offset %" G_GUINT64_FORMAT, oldoff); } return ret; @@ -942,6 +943,8 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); return GST_FLOW_ERROR; } + + GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num); break; } @@ -957,6 +960,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); return GST_FLOW_ERROR; } + GST_DEBUG_OBJECT (ebml, "EbmlMaxSizeLength: %" G_GUINT64_FORMAT, num); break; } @@ -972,6 +976,7 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) GST_ELEMENT_ERROR (ebml, STREAM, WRONG_TYPE, (NULL), (NULL)); return GST_FLOW_ERROR; } + GST_DEBUG_OBJECT (ebml, "EbmlMaxIdLength: %" G_GUINT64_FORMAT, num); break; } @@ -982,6 +987,9 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) if (ret != GST_FLOW_OK) return ret; g_assert (id == GST_EBML_ID_DOCTYPE); + + GST_DEBUG_OBJECT (ebml, "EbmlDocType: %s", GST_STR_NULL (text)); + if (doctype) { g_free (*doctype); *doctype = text; @@ -999,11 +1007,13 @@ gst_ebml_read_header (GstEbmlRead * ebml, gchar ** doctype, guint * version) g_assert (id == GST_EBML_ID_DOCTYPEREADVERSION); if (version) *version = num; + GST_DEBUG_OBJECT (ebml, "EbmlReadVersion: %" G_GUINT64_FORMAT, num); break; } default: - GST_WARNING ("Unknown data type 0x%x in EBML header (ignored)", id); + GST_WARNING_OBJECT (ebml, + "Unknown data type 0x%x in EBML header (ignored)", id); /* pass-through */ /* we ignore these two, as they don't tell us anything we care about */ diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 890d297..e70ecc3 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -65,6 +65,15 @@ GST_DEBUG_CATEGORY_STATIC (matroskademux_debug); #define GST_CAT_DEFAULT matroskademux_debug +#define DEBUG_ELEMENT_START(demux, ebml, element) \ + GST_DEBUG_OBJECT (demux, "Parsing " element " element at offset %" \ + G_GUINT64_FORMAT, ebml->offset) + +#define DEBUG_ELEMENT_STOP(demux, ebml, element, ret) \ + GST_DEBUG_OBJECT (demux, "Parsing " element " element at offset %" \ + G_GUINT64_FORMAT " finished with '%s'", ebml->offset, \ + gst_flow_get_name (ret)) + enum { ARG_0, @@ -104,7 +113,7 @@ static GstStaticPadTemplate subtitle_src_templ = ); static GstFlowReturn gst_matroska_demux_parse_contents (GstMatroskaDemux * - demux, gboolean * p_run_loop); + demux); /* element functions */ static void gst_matroska_demux_loop (GstPad * pad); @@ -278,6 +287,8 @@ gst_matroska_demux_reset (GstElement * element) guint i; + GST_DEBUG_OBJECT (demux, "Resetting state"); + /* reset input */ demux->state = GST_MATROSKA_DEMUX_STATE_START; @@ -337,182 +348,194 @@ gst_matroska_demux_stream_from_num (GstMatroskaDemux * demux, guint track_num) } } - if (n == demux->num_streams) { - GST_WARNING ("Failed to find corresponding pad for tracknum %d", track_num); - } + if (n == demux->num_streams) + GST_WARNING_OBJECT (demux, + "Failed to find corresponding pad for tracknum %d", track_num); return -1; } static gint -gst_matroska_demux_encoding_cmp (gconstpointer a, gconstpointer b) +gst_matroska_demux_encoding_cmp (GstMatroskaTrackEncoding * a, + GstMatroskaTrackEncoding * b) { - const GstMatroskaTrackEncoding *enc_a; + if (b->order > a->order) + return 1; + else if (b->order < a->order) + return -1; + else + return 0; +} - const GstMatroskaTrackEncoding *enc_b; +static gboolean +gst_matroska_demux_encoding_order_unique (GArray * encodings, guint64 order) +{ + gint i; - enc_a = (const GstMatroskaTrackEncoding *) a; - enc_b = (const GstMatroskaTrackEncoding *) b; + if (encodings == NULL || encodings->len == 0) + return TRUE; - /* FIXME: give warning if diff == 0, should be unique! */ + for (i = 0; i < encodings->len; i++) + if (g_array_index (encodings, GstMatroskaTrackEncoding, i).order == order) + return FALSE; - return (gint) enc_b->order - (gint) enc_a->order; + return TRUE; } static GstFlowReturn -gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml, - GstMatroskaDemux * demux, GstMatroskaTrackContext * context) +gst_matroska_demux_read_track_encoding (GstMatroskaDemux * demux, + GstMatroskaTrackContext * context) { + GstMatroskaTrackEncoding enc = { 0, }; + GstEbmlRead *ebml = GST_EBML_READ (demux); + GstFlowReturn ret; guint32 id; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; + DEBUG_ELEMENT_START (demux, ebml, "ContentEncoding"); + /* Set default values */ + enc.scope = 1; + /* All other default values are 0 */ - context->encodings = - g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1); + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "ContentEncoding", ret); + return ret; + } while (ret == GST_FLOW_OK) { - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) { + if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) break; - } else if (demux->level_up > 0) { + + if (demux->level_up) { demux->level_up--; break; } switch (id) { - case GST_MATROSKA_ID_CONTENTENCODING:{ - GstMatroskaTrackEncoding enc = { 0, }; + case GST_MATROSKA_ID_CONTENTENCODINGORDER:{ + guint64 num; - /* Set default values */ - enc.scope = 1; + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) + break; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + if (!gst_matroska_demux_encoding_order_unique (context->encodings, num)) { + GST_ERROR_OBJECT (demux, "ContentEncodingOrder %" G_GUINT64_FORMAT + "is not unique for track %d", num, context->num); + ret = GST_FLOW_ERROR; break; } + GST_DEBUG_OBJECT (demux, "ContentEncodingOrder: %" G_GUINT64_FORMAT, + num); + enc.order = num; + break; + } + case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{ + guint64 num; + + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) + break; + + if (num > 7 && num == 0) { + GST_ERROR_OBJECT (demux, "Invalid ContentEncodingScope %", + G_GUINT64_FORMAT, num); + ret = GST_FLOW_ERROR; + break; + } else if (num & 0x4) { + GST_ERROR_OBJECT (demux, "Unsupported ContentEncodingScope %", + G_GUINT64_FORMAT, num); + ret = GST_FLOW_ERROR; + } + + GST_DEBUG_OBJECT (demux, "ContentEncodingScope: %" G_GUINT64_FORMAT, + num); + enc.scope = num; + + break; + } + case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{ + guint64 num; + + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) + break; + + if (num > 1) { + GST_ERROR_OBJECT (demux, "Invalid ContentEncodingType %" + G_GUINT64_FORMAT, num); + ret = GST_FLOW_ERROR; + break; + } else if (num != 0) { + GST_ERROR_OBJECT (demux, "Encrypted tracks are not supported yet"); + ret = GST_FLOW_ERROR; + break; + } + GST_DEBUG_OBJECT (demux, "ContentEncodingType: %" G_GUINT64_FORMAT, + num); + enc.type = num; + break; + } + case GST_MATROSKA_ID_CONTENTCOMPRESSION:{ + + DEBUG_ELEMENT_START (demux, ebml, "ContentCompression"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + break; + while (ret == GST_FLOW_OK) { - if ((ret = - gst_ebml_peek_id (ebml, &demux->level_up, - &id)) != GST_FLOW_OK) { + if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, + &id)) != GST_FLOW_OK) break; - } else if (demux->level_up > 0) { + + if (demux->level_up) { demux->level_up--; break; } switch (id) { - case GST_MATROSKA_ID_CONTENTENCODINGORDER:{ + case GST_MATROSKA_ID_CONTENTCOMPALGO:{ guint64 num; if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { break; } - /* FIXME: must be unique, check this! */ - enc.order = num; - break; - } - case GST_MATROSKA_ID_CONTENTENCODINGSCOPE:{ - guint64 num; - - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if (num > 3) { + GST_ERROR_OBJECT (demux, "Invalid ContentCompAlgo %" + G_GUINT64_FORMAT, num); + ret = GST_FLOW_ERROR; break; - } - if (num > 7 && num == 0) - GST_WARNING ("Unknown scope value in contents encoding."); - else - enc.scope = num; - break; - } - case GST_MATROSKA_ID_CONTENTENCODINGTYPE:{ - guint64 num; - - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + } else if (num != 0) { + GST_ERROR_OBJECT (demux, "Unsupported ContentCompAlgo %" + G_GUINT64_FORMAT, num); + ret = GST_FLOW_ERROR; break; } - if (num > 1) - GST_WARNING ("Unknown type value in contents encoding."); - else - enc.type = num; + GST_DEBUG_OBJECT (demux, "ContentCompAlgo: %" G_GUINT64_FORMAT, + num); + enc.comp_algo = num; + break; } - case GST_MATROSKA_ID_CONTENTCOMPRESSION:{ - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - break; - } - - /* FIXME: Might be compressed or encrypted, depending on ContentEncodingScope & 0x4 - * and the previous ContentEncodingOrder */ - while (ret == GST_FLOW_OK) { - - if ((ret = - gst_ebml_peek_id (ebml, &demux->level_up, - &id)) != GST_FLOW_OK) { - break; - } else if (demux->level_up > 0) { - demux->level_up--; - break; - } - - switch (id) { - case GST_MATROSKA_ID_CONTENTCOMPALGO:{ - guint64 num; - - if ((ret = - gst_ebml_read_uint (ebml, &id, - &num)) != GST_FLOW_OK) { - break; - } - /* FIXME: maybe don't add tracks at all for which we don't - * support the compression algorithm */ - if (num > 3) - GST_WARNING ("Unknown value in encoding compalgo."); - else - enc.comp_algo = num; - break; - } - case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{ - guint8 *data; - - guint64 size; + case GST_MATROSKA_ID_CONTENTCOMPSETTINGS:{ + guint8 *data; + guint64 size; - if ((ret = - gst_ebml_read_binary (ebml, &id, &data, - &size)) != GST_FLOW_OK) { - break; - } - enc.comp_settings = data; - enc.comp_settings_length = size; - break; - } - default: - GST_WARNING ("Unknown track compression header entry 0x%x" - " - ignoring", id); - ret = gst_ebml_read_skip (ebml); - break; - } - if (demux->level_up) { - demux->level_up--; - break; - } + if ((ret = + gst_ebml_read_binary (ebml, &id, &data, + &size)) != GST_FLOW_OK) { + break; } + enc.comp_settings = data; + enc.comp_settings_length = size; + GST_DEBUG_OBJECT (demux, + "ContentCompSettings of size %" G_GUINT64_FORMAT, size); break; } - - case GST_MATROSKA_ID_CONTENTENCRYPTION: - GST_WARNING ("Encrypted tracks not yet supported"); - /* FIXME: Might be compressed, depending on ContentEncodingScope & 0x4 - * and the previous ContentEncodingOrder */ - /* FIXME: don't add encrypted tracks at all */ - ret = gst_ebml_read_skip (ebml); - break; default: - GST_WARNING - ("Unknown track encoding header entry 0x%x - ignoring", id); + GST_WARNING_OBJECT (demux, + "Unknown ContentCompression subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -522,14 +545,75 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml, break; } } - - g_array_append_val (context->encodings, enc); break; + DEBUG_ELEMENT_STOP (demux, ebml, "ContentCompression", ret); } + case GST_MATROSKA_ID_CONTENTENCRYPTION: + GST_ERROR_OBJECT (demux, "Encrypted tracks not yet supported"); + gst_ebml_read_skip (ebml); + ret = GST_FLOW_ERROR; + break; default: - GST_WARNING ("Unknown track encodings header entry 0x%x - ignoring", - id); + GST_WARNING_OBJECT (demux, + "Unknown ContentEncoding subelement 0x%x - ignoring", id); + ret = gst_ebml_read_skip (ebml); + break; + } + + if (demux->level_up) { + demux->level_up--; + break; + } + } + + DEBUG_ELEMENT_STOP (demux, ebml, "ContentEncoding", ret); + if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED) + return ret; + + /* TODO: Check if the combination of values is valid */ + + g_array_append_val (context->encodings, enc); + + return ret; +} + +static GstFlowReturn +gst_matroska_demux_read_track_encodings (GstMatroskaDemux * demux, + GstMatroskaTrackContext * context) +{ + GstFlowReturn ret; + + GstEbmlRead *ebml = GST_EBML_READ (demux); + + guint32 id; + + DEBUG_ELEMENT_START (demux, ebml, "ContentEncodings"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "ContentEncodings", ret); + return ret; + } + + context->encodings = + g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaTrackEncoding), 1); + + while (ret == GST_FLOW_OK) { + if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) + break; + + if (demux->level_up) { + demux->level_up--; + break; + } + + switch (id) { + case GST_MATROSKA_ID_CONTENTENCODING: + ret = gst_matroska_demux_read_track_encoding (demux, context); + break; + default: + GST_WARNING_OBJECT (demux, + "Unknown ContentEncodings subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -540,12 +624,31 @@ gst_matroska_demux_read_track_encodings (GstEbmlRead * ebml, } } + DEBUG_ELEMENT_STOP (demux, ebml, "ContentEncodings", ret); + if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED) + return ret; + /* Sort encodings according to their order */ - g_array_sort (context->encodings, gst_matroska_demux_encoding_cmp); + g_array_sort (context->encodings, + (GCompareFunc) gst_matroska_demux_encoding_cmp); + + /* TODO: Decompress & decrypt ContentEncodings if necessary */ return ret; } +static gboolean +gst_matroska_demux_tracknumber_unique (GstMatroskaDemux * demux, guint64 num) +{ + gint i; + + for (i = 0; i <= demux->num_streams; i++) + if (demux->src[i] && demux->src[i]->num == num) + return FALSE; + + return TRUE; +} + static GstFlowReturn gst_matroska_demux_add_stream (GstMatroskaDemux * demux) { @@ -570,11 +673,20 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) gchar *codec = NULL; if (demux->num_streams >= GST_MATROSKA_DEMUX_MAX_STREAMS) { - GST_WARNING ("Maximum number of streams (%d) exceeded, skipping", + GST_WARNING_OBJECT (demux, + "Maximum number of streams (%d) exceeded, skipping", GST_MATROSKA_DEMUX_MAX_STREAMS); return gst_ebml_read_skip (ebml); /* skip-and-continue */ } + DEBUG_ELEMENT_START (demux, ebml, "TrackEntry"); + + /* start with the master */ + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "TrackEntry", ret); + return ret; + } + /* allocate generic... if we know the type, we'll g_renew() * with the precise type */ context = g_new0 (GstMatroskaTrackContext, 1); @@ -591,34 +703,38 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) context->last_flow = GST_FLOW_OK; demux->num_streams++; - /* start with the master */ - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; + GST_DEBUG_OBJECT (demux, "Stream number %d", context->index); /* try reading the trackentry headers */ while (ret == GST_FLOW_OK) { - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) { + if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) break; - } else if (demux->level_up > 0) { + + if (demux->level_up) { demux->level_up--; break; } switch (id) { - /* FIXME: check unique */ /* track number (unique stream ID) */ case GST_MATROSKA_ID_TRACKNUMBER:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num == 0) { - GST_WARNING ("Invalid track number (0) - skipping"); + GST_ERROR_OBJECT (demux, "Invalid TrackNumber 0"); + ret = GST_FLOW_ERROR; + break; + } else if (!gst_matroska_demux_tracknumber_unique (demux, num)) { + GST_ERROR_OBJECT (demux, "TrackNumber %" G_GUINT64_FORMAT + " is not unique", num); ret = GST_FLOW_ERROR; break; } + GST_DEBUG_OBJECT (demux, "TrackNumber: %" G_GUINT64_FORMAT, num); context->num = num; break; } @@ -626,15 +742,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKUID:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num == 0) { - GST_WARNING ("Invalid track UID (0) - skipping"); + GST_ERROR_OBJECT (demux, "Invalid TrackUID 0"); ret = GST_FLOW_ERROR; break; } + GST_DEBUG_OBJECT (demux, "TrackUID: %" G_GUINT64_FORMAT, num); context->uid = num; break; } @@ -648,15 +765,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) } if (context->type != 0 && context->type != track_type) { - GST_WARNING - ("More than one tracktype defined in a trackentry - skipping"); + GST_WARNING_OBJECT (demux, + "More than one tracktype defined in a TrackEntry - skipping"); break; } else if (track_type < 1 || track_type > 254) { - GST_WARNING ("Invalid track type (%u) - skipping", - (guint) track_type); + GST_WARNING_OBJECT (demux, "Invalid TrackType %" G_GUINT64_FORMAT, + track_type); break; } + GST_DEBUG_OBJECT (demux, "TrackType: %" G_GUINT64_FORMAT, track_type); + /* ok, so we're actually going to reallocate this thing */ switch (track_type) { case GST_MATROSKA_TRACK_TYPE_VIDEO: @@ -673,8 +792,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_TRACK_TYPE_BUTTONS: case GST_MATROSKA_TRACK_TYPE_CONTROL: default: - GST_WARNING ("Unknown or unsupported track type %" - G_GUINT64_FORMAT, track_type); + GST_WARNING_OBJECT (demux, + "Unknown or unsupported TrackType %" G_GUINT64_FORMAT, + track_type); context->type = 0; break; } @@ -686,9 +806,11 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKVIDEO:{ GstMatroskaTrackVideoContext *videocontext; + DEBUG_ELEMENT_START (demux, ebml, "TrackVideo"); + if (!gst_matroska_track_init_video_context (&context)) { - GST_WARNING - ("trackvideo EBML entry in non-video track - ignoring track"); + GST_WARNING_OBJECT (demux, + "TrackVideo element in non-video track - ignoring track"); ret = GST_FLOW_ERROR; break; } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { @@ -700,9 +822,10 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, - &id)) != GST_FLOW_OK) { + &id)) != GST_FLOW_OK) break; - } else if (demux->level_up > 0) { + + if (demux->level_up) { demux->level_up--; break; } @@ -712,15 +835,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING ("Invalid track default duration (0) - ignoring"); + GST_WARNING_OBJECT (demux, "Invalid TrackDefaultDuration 0"); break; } + GST_DEBUG_OBJECT (demux, + "TrackDefaultDuration: %" G_GUINT64_FORMAT, num); context->default_duration = num; break; } @@ -731,16 +855,15 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEOFRAMERATE:{ gdouble num; - if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num <= 0.0) { - GST_WARNING ("Invalid video framerate (%lf fps) - ignoring", - num); + GST_WARNING_OBJECT (demux, "Invalid TrackVideoFPS %lf", num); break; } + GST_DEBUG_OBJECT (demux, "TrackVideoFrameRate: %lf", num); if (context->default_duration == 0) context->default_duration = gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num)); @@ -752,17 +875,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEODISPLAYWIDTH:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING ("Invalid display width (0) - ignoring"); + GST_WARNING_OBJECT (demux, "Invalid TrackVideoDisplayWidth 0"); break; } + GST_DEBUG_OBJECT (demux, + "TrackVideoDisplayWidth: %" G_GUINT64_FORMAT, num); videocontext->display_width = num; - GST_DEBUG ("display_width %" G_GUINT64_FORMAT, num); break; } @@ -770,17 +893,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEODISPLAYHEIGHT:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING ("Invalid display height (0) - ignoring"); + GST_WARNING_OBJECT (demux, "Invalid TrackVideoDisplayHeight 0"); break; } + GST_DEBUG_OBJECT (demux, + "TrackVideoDisplayHeight: %" G_GUINT64_FORMAT, num); videocontext->display_height = num; - GST_DEBUG ("display_height %" G_GUINT64_FORMAT, num); break; } @@ -788,17 +911,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEOPIXELWIDTH:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING ("Invalid pixel width (0) - ignoring"); + GST_WARNING_OBJECT (demux, "Invalid TrackVideoPixelWidth 0"); break; } + GST_DEBUG_OBJECT (demux, + "TrackVideoPixelWidth: %" G_GUINT64_FORMAT, num); videocontext->pixel_width = num; - GST_DEBUG ("pixel_width %" G_GUINT64_FORMAT, num); break; } @@ -806,17 +929,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEOPIXELHEIGHT:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING ("Invalid pixel height (0) - ignoring"); + GST_WARNING_OBJECT (demux, "Invalid TrackVideoPixelHeight 0"); break; } + GST_DEBUG_OBJECT (demux, + "TrackVideoPixelHeight: %" G_GUINT64_FORMAT, num); videocontext->pixel_height = num; - GST_DEBUG ("pixel_height %" G_GUINT64_FORMAT, num); break; } @@ -824,33 +947,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEOFLAGINTERLACED:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num) context->flags |= GST_MATROSKA_VIDEOTRACK_INTERLACED; else context->flags &= ~GST_MATROSKA_VIDEOTRACK_INTERLACED; - break; - } - - /* stereo mode (whether the video has two streams, where - * one is for the left eye and the other for the right eye, - * which creates a 3D-like effect) */ - case GST_MATROSKA_ID_VIDEOSTEREOMODE:{ - guint64 num; - - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { - break; - } - if (num != GST_MATROSKA_EYE_MODE_MONO && - num != GST_MATROSKA_EYE_MODE_LEFT && - num != GST_MATROSKA_EYE_MODE_RIGHT && - num != GST_MATROSKA_EYE_MODE_BOTH) { - GST_WARNING ("Unknown eye mode 0x%x - ignoring", (guint) num); - break; - } - videocontext->eye_mode = num; + GST_DEBUG_OBJECT (demux, "TrackVideoInterlaced: %d", + (context-> + flags & GST_MATROSKA_VIDEOTRACK_INTERLACED) ? 1 : 0); break; } @@ -858,46 +964,58 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_VIDEOASPECTRATIOTYPE:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num != GST_MATROSKA_ASPECT_RATIO_MODE_FREE && num != GST_MATROSKA_ASPECT_RATIO_MODE_KEEP && num != GST_MATROSKA_ASPECT_RATIO_MODE_FIXED) { - GST_WARNING ("Unknown aspect ratio mode 0x%x - ignoring", - (guint) num); + GST_WARNING_OBJECT (demux, + "Unknown TrackVideoAspectRatioType 0x%x", (guint) num); break; } + GST_DEBUG_OBJECT (demux, + "TrackVideoAspectRatioType: %" G_GUINT64_FORMAT, num); videocontext->asr_mode = num; break; } /* colourspace (only matters for raw video) fourcc */ case GST_MATROSKA_ID_VIDEOCOLOURSPACE:{ - guint64 num; + guint8 *data; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + guint64 datalen; + + if ((ret = + gst_ebml_read_binary (ebml, &id, &data, + &datalen)) != GST_FLOW_OK) break; - } - if (num > G_MAXUINT32) { - GST_WARNING ("Invalid video colourspace (%" G_GUINT64_FORMAT - ") - ignoring", num); + if (datalen != 4) { + GST_WARNING_OBJECT (demux, + "Invalid TrackVideoColourSpace length %" G_GUINT64_FORMAT, + datalen); break; } - videocontext->fourcc = num; + + memcpy (&videocontext->fourcc, data, 4); + GST_DEBUG_OBJECT (demux, + "TrackVideoColourSpace: %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (videocontext->fourcc)); break; } + default: + GST_WARNING_OBJECT (demux, + "Unknown TrackVideo subelement 0x%x - ignoring", id); + /* fall through */ + case GST_MATROSKA_ID_VIDEOSTEREOMODE: case GST_MATROSKA_ID_VIDEODISPLAYUNIT: case GST_MATROSKA_ID_VIDEOPIXELCROPBOTTOM: case GST_MATROSKA_ID_VIDEOPIXELCROPTOP: case GST_MATROSKA_ID_VIDEOPIXELCROPLEFT: case GST_MATROSKA_ID_VIDEOPIXELCROPRIGHT: case GST_MATROSKA_ID_VIDEOGAMMAVALUE: - default: - GST_WARNING ("Unknown video track header entry 0x%x - ignoring", - id); ret = gst_ebml_read_skip (ebml); break; } @@ -907,6 +1025,8 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) break; } } + + DEBUG_ELEMENT_STOP (demux, ebml, "TrackVideo", ret); break; } @@ -914,23 +1034,28 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKAUDIO:{ GstMatroskaTrackAudioContext *audiocontext; + DEBUG_ELEMENT_START (demux, ebml, "TrackAudio"); + if (!gst_matroska_track_init_audio_context (&context)) { - GST_WARNING - ("trackaudio EBML entry in non-audio track - ignoring track"); + GST_WARNING_OBJECT (demux, + "TrackAudio element in non-audio track - ignoring track"); ret = GST_FLOW_ERROR; break; - } else if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - break; } + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + break; + audiocontext = (GstMatroskaTrackAudioContext *) context; demux->src[demux->num_streams - 1] = context; while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, - &id)) != GST_FLOW_OK) { + &id)) != GST_FLOW_OK) break; - } else if (demux->level_up > 0) { + + if (demux->level_up) { demux->level_up--; break; } @@ -940,13 +1065,13 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_AUDIOSAMPLINGFREQ:{ gdouble num; - if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num <= 0.0) { - GST_WARNING ("Invalid audio sample rate (%lf) - ignoring)", - num); + GST_WARNING_OBJECT (demux, + "Invalid TrackAudioSamplingFrequency %lf", num); break; } @@ -954,6 +1079,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) context->default_duration = gst_gdouble_to_guint64 ((gdouble) GST_SECOND * (1.0 / num)); + GST_DEBUG_OBJECT (demux, "TrackAudioSamplingFrequency: %lf", num); audiocontext->samplerate = num; break; } @@ -962,15 +1088,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_AUDIOBITDEPTH:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING ("Invalid audio bit depth (0) - ignoring)"); + GST_WARNING_OBJECT (demux, "Invalid TrackAudioBitDepth 0"); break; } + GST_DEBUG_OBJECT (demux, "TrackAudioBitDepth: %" G_GUINT64_FORMAT, + num); audiocontext->bitdepth = num; break; } @@ -979,25 +1106,26 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_AUDIOCHANNELS:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num == 0) { - GST_WARNING - ("Invalid number of audio channels (0) - ignoring)"); + GST_WARNING_OBJECT (demux, "Invalid TrackAudioChannels 0"); break; } + GST_DEBUG_OBJECT (demux, "TrackAudioChannels: %" G_GUINT64_FORMAT, + num); audiocontext->channels = num; break; } + default: + GST_WARNING_OBJECT (demux, + "Unknown TrackAudio subelement 0x%x - ignoring", id); + /* fall through */ case GST_MATROSKA_ID_AUDIOCHANNELPOSITIONS: case GST_MATROSKA_ID_AUDIOOUTPUTSAMPLINGFREQ: - default: - GST_WARNING ("Unknown audio track header entry 0x%x - ignoring", - id); ret = gst_ebml_read_skip (ebml); break; } @@ -1007,6 +1135,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) break; } } + + DEBUG_ELEMENT_STOP (demux, ebml, "TrackAudio", ret); + break; } @@ -1014,9 +1145,10 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_CODECID:{ gchar *text; - if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_ascii (ebml, &id, &text)) != GST_FLOW_OK) break; - } + + GST_DEBUG_OBJECT (demux, "CodecID: %s", GST_STR_NULL (text)); context->codec_id = text; break; } @@ -1028,14 +1160,14 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) guint64 size; if ((ret = - gst_ebml_read_binary (ebml, &id, &data, - &size)) != GST_FLOW_OK) { + gst_ebml_read_binary (ebml, &id, &data, &size)) != GST_FLOW_OK) break; - } - /* TODO: might be compressed or encrypted */ + context->codec_priv = data; context->codec_priv_size = size; - GST_LOG_OBJECT (demux, "%u bytes of codec private data", (guint) size); + + GST_DEBUG_OBJECT (demux, "CodecPrivate of size %" G_GUINT64_FORMAT, + size); break; } @@ -1043,9 +1175,10 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_CODECNAME:{ gchar *text; - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) break; - } + + GST_DEBUG_OBJECT (demux, "CodecName: %s", GST_STR_NULL (text)); context->codec_name = text; break; } @@ -1054,11 +1187,11 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKNAME:{ gchar *text; - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) break; - } + context->name = text; - GST_LOG ("stream %d: trackname=%s", context->index, text); + GST_DEBUG_OBJECT (demux, "TrackName: %s", GST_STR_NULL (text)); break; } @@ -1066,16 +1199,18 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKLANGUAGE:{ gchar *text; - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) break; - } + context->language = text; - GST_LOG ("stream %d: language=%s", context->index, text); /* fre-ca => fre */ if (strlen (context->language) >= 4 && context->language[3] == '-') context->language[3] = '\0'; + + GST_DEBUG_OBJECT (demux, "TrackLanguage: %s", + GST_STR_NULL (context->language)); break; } @@ -1083,13 +1218,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKFLAGENABLED:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num) context->flags |= GST_MATROSKA_TRACK_ENABLED; else context->flags &= ~GST_MATROSKA_TRACK_ENABLED; + + GST_DEBUG_OBJECT (demux, "TrackEnabled: %d", + (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0); break; } @@ -1097,13 +1235,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKFLAGDEFAULT:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num) context->flags |= GST_MATROSKA_TRACK_DEFAULT; else context->flags &= ~GST_MATROSKA_TRACK_DEFAULT; + + GST_DEBUG_OBJECT (demux, "TrackDefault: %d", + (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0); break; } @@ -1118,6 +1259,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) context->flags |= GST_MATROSKA_TRACK_FORCED; else context->flags &= ~GST_MATROSKA_TRACK_FORCED; + + GST_DEBUG_OBJECT (demux, "TrackForced: %d", + (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0); break; } @@ -1126,13 +1270,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKFLAGLACING:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num) context->flags |= GST_MATROSKA_TRACK_LACING; else context->flags &= ~GST_MATROSKA_TRACK_LACING; + + GST_DEBUG_OBJECT (demux, "TrackLacing: %d", + (context->flags & GST_MATROSKA_TRACK_ENABLED) ? 1 : 0); break; } @@ -1140,21 +1287,23 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TRACKDEFAULTDURATION:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + if (num == 0) { - GST_WARNING ("Invalid track default duration (0) - ignoring"); + GST_WARNING_OBJECT (demux, "Invalid TrackDefaultDuration 0"); break; } + GST_DEBUG_OBJECT (demux, "TrackDefaultDuration: %" G_GUINT64_FORMAT, + num); context->default_duration = num; break; } case GST_MATROSKA_ID_CONTENTENCODINGS:{ - ret = gst_matroska_demux_read_track_encodings (ebml, demux, context); + ret = gst_matroska_demux_read_track_encodings (demux, context); break; } @@ -1165,16 +1314,17 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) break; if (num <= 0.0) { - GST_WARNING ("Invalid track time code scale (%lf) - ignoring", num); + GST_WARNING_OBJECT (demux, "Invalid TrackTimeCodeScale %lf", num); break; } + GST_DEBUG_OBJECT (demux, "TrackTimeCodeScale: %lf", num); context->timecodescale = num; break; } default: - GST_WARNING ("Unknown track header entry 0x%x - ignoring", id); + GST_WARNING ("Unknown TrackEntry subelement 0x%x - ignoring", id); /* pass-through */ /* we ignore these because they're nothing useful (i.e. crap) @@ -1200,9 +1350,14 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux) } } - if (context->type == 0 || context->codec_id == NULL || ret != GST_FLOW_OK) { - if (ret == GST_FLOW_OK) - GST_WARNING ("Unknown stream/codec in track entry header"); + DEBUG_ELEMENT_STOP (demux, ebml, "TrackEntry", ret); + + /* TODO: decompress/decrypt codec private if necessary */ + + if (context->type == 0 || context->codec_id == NULL || (ret != GST_FLOW_OK + && ret != GST_FLOW_UNEXPECTED)) { + if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) + GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header"); demux->num_streams--; demux->src[demux->num_streams] = NULL; @@ -1734,6 +1889,8 @@ gst_matroska_demux_init_stream (GstMatroskaDemux * demux) GstFlowReturn ret; + GST_DEBUG_OBJECT (demux, "Init stream"); + if ((ret = gst_ebml_read_header (ebml, &doctype, &version)) != GST_FLOW_OK) return ret; @@ -1765,7 +1922,8 @@ gst_matroska_demux_init_stream (GstMatroskaDemux * demux) break; /* oi! */ - GST_WARNING ("Expected a Segment ID (0x%x), but received 0x%x!", + GST_WARNING_OBJECT (demux, + "Expected a Segment ID (0x%x), but received 0x%x!", GST_MATROSKA_ID_SEGMENT, id); if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK) @@ -1778,6 +1936,8 @@ gst_matroska_demux_init_stream (GstMatroskaDemux * demux) return ret; } + GST_DEBUG_OBJECT (demux, "Found Segment start at offset %" G_GUINT64_FORMAT, + ebml->offset); /* seeks are from the beginning of the segment, * after the segment ID/length */ demux->ebml_segment_start = ebml->offset; @@ -1794,10 +1954,18 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux) guint32 id; + DEBUG_ELEMENT_START (demux, ebml, "Tracks"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Tracks", ret); + return ret; + } + while (ret == GST_FLOW_OK) { - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) { + if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) break; - } else if (demux->level_up) { + + if (demux->level_up) { demux->level_up--; break; } @@ -1809,7 +1977,7 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux) break; default: - GST_WARNING ("Unknown entry 0x%x in track header", id); + GST_WARNING ("Unknown Track subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -1819,6 +1987,7 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux) break; } } + DEBUG_ELEMENT_STOP (demux, ebml, "Tracks", ret); demux->tracks_parsed = TRUE; @@ -1827,7 +1996,7 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux) static GstFlowReturn gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux, - gboolean prevent_eos, guint * nentries, guint64 length) + guint * nentries) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -1842,15 +2011,16 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux, idx.time = GST_CLOCK_TIME_NONE; idx.block = 1; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; + DEBUG_ELEMENT_START (demux, ebml, "CueTrackPositions"); - while (TRUE) { - if (prevent_eos && length == ebml->offset) - break; + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "CueTrackPositions", ret); + return ret; + } + while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -1864,14 +2034,15 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux, guint64 num; if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) - goto error; + break; + if (num == 0) { idx.track = 0; - GST_WARNING ("Invalid cue track number (0)"); - goto error; + GST_WARNING_OBJECT (demux, "Invalid CueTrack 0"); break; } + GST_DEBUG_OBJECT (demux, "CueTrack: %" G_GUINT64_FORMAT, num); idx.track = num; break; } @@ -1882,9 +2053,13 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux, guint64 num; if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) - goto error; + break; - /* FIXME: may overflow, our seeks, etc are int64 based */ + if (num > G_MAXINT64) { + GST_WARNING_OBJECT (demux, "CueClusterPosition %" G_GUINT64_FORMAT + " too large", num); + break; + } idx.pos = num; break; @@ -1896,24 +2071,27 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux, guint64 num; if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) - goto error; + break; if (num == 0) { - GST_WARNING_OBJECT (demux, "Invalid CueBlockNumber (0)"); - } else { - idx.block = num; + GST_WARNING_OBJECT (demux, "Invalid CueBlockNumber 0"); + break; } + + GST_DEBUG_OBJECT (demux, "CueBlockNumber: %" G_GUINT64_FORMAT, num); + idx.block = num; break; } default: - GST_WARNING ("Unknown entry 0x%x in CuesTrackPositions", id); + GST_WARNING ("Unknown CueTrackPositions subelement 0x%x - ignoring", + id); /* fall-through */ case GST_MATROSKA_ID_CUECODECSTATE: case GST_MATROSKA_ID_CUEREFERENCE: if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK) - goto error; + break; break; } @@ -1923,25 +2101,21 @@ gst_matroska_demux_parse_index_cuetrack (GstMatroskaDemux * demux, } } - if (ret == GST_FLOW_OK && idx.pos != (guint64) - 1 && idx.track > 0) { + DEBUG_ELEMENT_STOP (demux, ebml, "CueTrackPositions", ret); + + if ((ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) + && idx.pos != (guint64) - 1 && idx.track > 0) { g_array_append_val (demux->index, idx); (*nentries)++; - } else { + } else if (ret == GST_FLOW_OK || ret == GST_FLOW_UNEXPECTED) { GST_DEBUG_OBJECT (demux, "CueTrackPositions without valid content"); } return ret; - -error: - if (demux->level_up) - demux->level_up--; - - return ret; } static GstFlowReturn -gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux, - gboolean prevent_eos, guint64 length) +gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -1953,15 +2127,16 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux, guint nentries = 0; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + DEBUG_ELEMENT_START (demux, ebml, "CuePoint"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "CuePoint", ret); return ret; + } while (ret == GST_FLOW_OK) { - if (prevent_eos && length == ebml->offset) - break; - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -1973,8 +2148,9 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux, case GST_MATROSKA_ID_CUETIME: { if ((ret = gst_ebml_read_uint (ebml, &id, &time)) != GST_FLOW_OK) - return ret; + break; + GST_DEBUG_OBJECT (demux, "CueTime: %" G_GUINT64_FORMAT, time); time = time * demux->time_scale; break; } @@ -1983,16 +2159,17 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux, case GST_MATROSKA_ID_CUETRACKPOSITIONS: { if ((ret = - gst_matroska_demux_parse_index_cuetrack (demux, prevent_eos, - &nentries, length)) != GST_FLOW_OK) - return ret; + gst_matroska_demux_parse_index_cuetrack (demux, + &nentries)) != GST_FLOW_OK) + break; break; } default: - GST_WARNING ("Unknown entry 0x%x in cuespoint index", id); + GST_WARNING_OBJECT (demux, + "Unknown CuePoint subelement 0x%x - ignoring", id); if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK) - return ret; + break; break; } @@ -2002,6 +2179,8 @@ gst_matroska_demux_parse_index_pointentry (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_STOP (demux, ebml, "CuePoint", ret); + if (nentries > 0) { if (time == GST_CLOCK_TIME_NONE) { GST_WARNING_OBJECT (demux, "CuePoint without valid time"); @@ -2043,34 +2222,29 @@ gst_matroska_index_compare (GstMatroskaIndex * i1, GstMatroskaIndex * i2) } static GstFlowReturn -gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos) +gst_matroska_demux_parse_index (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); guint32 id; - guint64 length = 0; - GstFlowReturn ret = GST_FLOW_OK; - if (prevent_eos) { - length = gst_ebml_read_get_length (ebml); - } - if (demux->index) g_array_free (demux->index, TRUE); demux->index = g_array_sized_new (FALSE, FALSE, sizeof (GstMatroskaIndex), 128); - while (ret == GST_FLOW_OK) { - /* We're an element that can be seeked to. If we are, then - * we want to prevent EOS, since that'll kill us. So we cache - * file size and seek until there, and don't call EOS upon os. */ - if (prevent_eos && length == ebml->offset) - break; + DEBUG_ELEMENT_START (demux, ebml, "Cues"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Cues", ret); + return ret; + } + while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2080,12 +2254,11 @@ gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos) switch (id) { /* one single index entry ('point') */ case GST_MATROSKA_ID_POINTENTRY: - ret = gst_matroska_demux_parse_index_pointentry (demux, prevent_eos, - length); + ret = gst_matroska_demux_parse_index_pointentry (demux); break; default: - GST_WARNING ("Unknown entry 0x%x in cues header", id); + GST_WARNING ("Unknown Cues subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -2095,6 +2268,7 @@ gst_matroska_demux_parse_index (GstMatroskaDemux * demux, gboolean prevent_eos) break; } } + DEBUG_ELEMENT_STOP (demux, ebml, "Cues", ret); /* Sort index by time, smallest time first, for easier searching */ g_array_sort (demux->index, (GCompareFunc) gst_matroska_index_compare); @@ -2113,10 +2287,18 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) guint32 id; + DEBUG_ELEMENT_START (demux, ebml, "SegmentInfo"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "SegmentInfo", ret); + return ret; + } + while (ret == GST_FLOW_OK) { - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) { + if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) break; - } else if (demux->level_up) { + + if (demux->level_up) { demux->level_up--; break; } @@ -2126,9 +2308,11 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) case GST_MATROSKA_ID_TIMECODESCALE:{ guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) break; - } + + + GST_DEBUG_OBJECT (demux, "TimeCodeScale: %" G_GUINT64_FORMAT, num); demux->time_scale = num; break; } @@ -2138,15 +2322,16 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) GstClockTime dur; - if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_float (ebml, &id, &num)) != GST_FLOW_OK) break; - } if (num <= 0.0) { - GST_WARNING ("Invalid duration (%lf) - skipping", num); + GST_WARNING_OBJECT (demux, "Invalid duration %lf", num); break; } + GST_DEBUG_OBJECT (demux, "Duration: %lf", num); + dur = gst_gdouble_to_guint64 (num * gst_guint64_to_gdouble (demux->time_scale)); if (GST_CLOCK_TIME_IS_VALID (dur) && dur <= G_MAXINT64) @@ -2157,9 +2342,10 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) case GST_MATROSKA_ID_WRITINGAPP:{ gchar *text; - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) break; - } + + GST_DEBUG_OBJECT (demux, "WritingApp: %s", GST_STR_NULL (text)); demux->writing_app = text; break; } @@ -2167,9 +2353,10 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) case GST_MATROSKA_ID_MUXINGAPP:{ gchar *text; - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) break; - } + + GST_DEBUG_OBJECT (demux, "MuxingApp: %s", GST_STR_NULL (text)); demux->muxing_app = text; break; } @@ -2177,13 +2364,19 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) case GST_MATROSKA_ID_DATEUTC:{ gint64 time; - if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK) { + if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK) break; - } + + GST_DEBUG_OBJECT (demux, "DateUTC: %" G_GINT64_FORMAT, time); demux->created = time; break; } + default: + GST_WARNING_OBJECT (demux, + "Unknown SegmentInfo subelement 0x%x - ignoring", id); + + /* fall through */ case GST_MATROSKA_ID_SEGMENTUID: case GST_MATROSKA_ID_SEGMENTFILENAME: case GST_MATROSKA_ID_PREVUID: @@ -2192,14 +2385,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) case GST_MATROSKA_ID_NEXTFILENAME: case GST_MATROSKA_ID_TITLE: case GST_MATROSKA_ID_SEGMENTFAMILY: - case GST_MATROSKA_ID_CHAPTERTRANSLATE:{ - /* TODO not yet implemented. */ - ret = gst_ebml_read_skip (ebml); - break; - } - - default: - GST_WARNING ("Unknown entry 0x%x in info header", id); + case GST_MATROSKA_ID_CHAPTERTRANSLATE: ret = gst_ebml_read_skip (ebml); break; } @@ -2210,6 +2396,8 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) } } + DEBUG_ELEMENT_STOP (demux, ebml, "SegmentInfo", ret); + demux->segmentinfo_parsed = TRUE; return ret; @@ -2217,7 +2405,7 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux) static GstFlowReturn gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux, - gboolean prevent_eos, guint64 length, GstTagList ** p_taglist) + GstTagList ** p_taglist) { /* FIXME: check if there are more useful mappings */ struct @@ -2253,16 +2441,18 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux, gchar *tag = NULL; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + DEBUG_ELEMENT_START (demux, ebml, "SimpleTag"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "SimpleTag", ret); return ret; + } while (ret == GST_FLOW_OK) { /* read all sub-entries */ - if (prevent_eos && length == ebml->offset) - break; if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2274,16 +2464,19 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux, g_free (tag); tag = NULL; ret = gst_ebml_read_ascii (ebml, &id, &tag); + GST_DEBUG_OBJECT (demux, "TagName: %s", GST_STR_NULL (tag)); break; case GST_MATROSKA_ID_TAGSTRING: g_free (value); value = NULL; ret = gst_ebml_read_utf8 (ebml, &id, &value); + GST_DEBUG_OBJECT (demux, "TagString: %s", GST_STR_NULL (value)); break; default: - GST_WARNING ("Unknown entry 0x%x in metadata collection", id); + GST_WARNING_OBJECT (demux, + "Unknown SimpleTag subelement 0x%x - ignoring", id); /* fall-through */ case GST_MATROSKA_ID_TAGLANGUAGE: @@ -2299,6 +2492,8 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_STOP (demux, ebml, "SimpleTag", ret); + if (tag && value) { guint i; @@ -2334,7 +2529,7 @@ gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux, static GstFlowReturn gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux, - gboolean prevent_eos, guint64 length, GstTagList ** p_taglist) + GstTagList ** p_taglist) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -2342,16 +2537,18 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux, GstFlowReturn ret; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + DEBUG_ELEMENT_START (demux, ebml, "Tag"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Tag", ret); return ret; + } while (ret == GST_FLOW_OK) { /* read all sub-entries */ - if (prevent_eos && length == ebml->offset) - break; if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2360,12 +2557,13 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux, switch (id) { case GST_MATROSKA_ID_SIMPLETAG: - ret = gst_matroska_demux_parse_metadata_id_simple_tag (demux, - prevent_eos, length, p_taglist); + ret = + gst_matroska_demux_parse_metadata_id_simple_tag (demux, p_taglist); break; default: - GST_WARNING ("Unknown entry 0x%x in metadata collection", id); + GST_WARNING_OBJECT (demux, "Unknown Tag subelement 0x%x - ignoring", + id); ret = gst_ebml_read_skip (ebml); break; } @@ -2376,12 +2574,13 @@ gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_STOP (demux, ebml, "Tag", ret); + return ret; } static GstFlowReturn -gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, - gboolean prevent_eos) +gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -2389,8 +2588,6 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, GstFlowReturn ret = GST_FLOW_OK; - guint64 length = 0; - guint32 id; GList *l; @@ -2419,29 +2616,23 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_START (demux, ebml, "Tags"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Tags", ret); + return ret; + } + taglist = gst_tag_list_new (); - GST_DEBUG_OBJECT (demux, "Parsing Tags at offset %" G_GUINT64_FORMAT, - ebml->offset); /* TODO: g_slice_dup() if we depend on GLib 2.14 */ curlevel = g_slice_new (GstEbmlLevel); memcpy (curlevel, ebml->level->data, sizeof (GstEbmlLevel)); demux->tags_parsed = g_list_prepend (demux->tags_parsed, curlevel); - /* TODO: review length/eos logic */ - if (prevent_eos) { - length = gst_ebml_read_get_length (ebml); - } - while (ret == GST_FLOW_OK) { - /* We're an element that can be seeked to. If we are, then - * we want to prevent EOS, since that'll kill us. So we cache - * file size and seek until there, and don't call EOS upon os. */ - if (prevent_eos && length == ebml->offset) - break; - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2450,12 +2641,12 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, switch (id) { case GST_MATROSKA_ID_TAG: - ret = gst_matroska_demux_parse_metadata_id_tag (demux, prevent_eos, - length, &taglist); + ret = gst_matroska_demux_parse_metadata_id_tag (demux, &taglist); break; default: - GST_WARNING ("Unknown entry 0x%x in metadata header", id); + GST_WARNING_OBJECT (demux, "Unknown Tags subelement 0x%x - ignoring", + id); /* FIXME: Use to limit the tags to specific pads */ case GST_MATROSKA_ID_TARGETS: ret = gst_ebml_read_skip (ebml); @@ -2468,6 +2659,8 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_STOP (demux, ebml, "Tags", ret); + if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) { gst_element_found_tags (GST_ELEMENT (ebml), taglist); } else { @@ -2479,7 +2672,7 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, static GstFlowReturn gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, - gboolean prevent_eos, guint64 length, GstTagList * taglist) + GstTagList * taglist) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -2497,19 +2690,18 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, guint64 datalen = 0; - GST_DEBUG_OBJECT (demux, "Parsing AttachedFile at offset %" G_GUINT64_FORMAT, - ebml->offset); + DEBUG_ELEMENT_START (demux, ebml, "AttachedFile"); - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "AttachedFile", ret); return ret; + } while (ret == GST_FLOW_OK) { /* read all sub-entries */ - if (prevent_eos && length == ebml->offset) - break; if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2523,8 +2715,9 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, break; } - if ((ret = gst_ebml_read_utf8 (ebml, &id, &description)) != GST_FLOW_OK) - return ret; + ret = gst_ebml_read_utf8 (ebml, &id, &description); + GST_DEBUG_OBJECT (demux, "FileDescription: %s", + GST_STR_NULL (description)); break; case GST_MATROSKA_ID_FILENAME: if (filename) { @@ -2532,8 +2725,9 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, break; } - if ((ret = gst_ebml_read_utf8 (ebml, &id, &filename)) != GST_FLOW_OK) - return ret; + ret = gst_ebml_read_utf8 (ebml, &id, &filename); + + GST_DEBUG_OBJECT (demux, "FileName: %s", GST_STR_NULL (filename)); break; case GST_MATROSKA_ID_FILEMIMETYPE: if (mimetype) { @@ -2541,8 +2735,8 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, break; } - if ((ret = gst_ebml_read_ascii (ebml, &id, &mimetype)) != GST_FLOW_OK) - return ret; + ret = gst_ebml_read_ascii (ebml, &id, &mimetype); + GST_DEBUG_OBJECT (demux, "FileMimeType: %s", GST_STR_NULL (mimetype)); break; case GST_MATROSKA_ID_FILEDATA: if (data) { @@ -2550,14 +2744,13 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, break; } - if ((ret = - gst_ebml_read_binary (ebml, &id, &data, - &datalen)) != GST_FLOW_OK) - return ret; + ret = gst_ebml_read_binary (ebml, &id, &data, &datalen); + GST_DEBUG_OBJECT (demux, "FileData of size %" G_GUINT64_FORMAT, + datalen); break; default: - GST_WARNING ("Unknown entry 0x%x in AttachedFile", id); + GST_WARNING ("Unknown AttachedFile subelement 0x%x - ignoring", id); /* fall through */ case GST_MATROSKA_ID_FILEUID: ret = gst_ebml_read_skip (ebml); @@ -2570,6 +2763,8 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_STOP (demux, ebml, "AttachedFile", ret); + if (filename && mimetype && data && datalen > 0) { GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; @@ -2589,7 +2784,12 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, image_type = GST_TAG_IMAGE_TYPE_BACK_COVER; else image_type = GST_TAG_IMAGE_TYPE_FRONT_COVER; - } else if (g_str_has_prefix (mimetype, "image/")) { + } else if (g_str_has_prefix (mimetype, "image/") || + g_str_has_suffix (filename_lc, "png") || + g_str_has_suffix (filename_lc, "jpg") || + g_str_has_suffix (filename_lc, "jpeg") || + g_str_has_suffix (filename_lc, "gif") || + g_str_has_suffix (filename_lc, "bmp")) { image_type = GST_TAG_IMAGE_TYPE_UNDEFINED; } g_free (filename_lc); @@ -2624,8 +2824,8 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, NULL); - GST_DEBUG_OBJECT (demux, "Created tag buffer with caps: %" GST_PTR_FORMAT, - caps); + GST_DEBUG_OBJECT (demux, + "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); /* and append to the tag list */ if (image_type != GST_TAG_IMAGE_TYPE_NONE) @@ -2645,37 +2845,28 @@ gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, } static GstFlowReturn -gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, - gboolean prevent_eos) +gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); - guint64 length = 0; - guint32 id; GstFlowReturn ret = GST_FLOW_OK; GstTagList *taglist; - if (prevent_eos) { - length = gst_ebml_read_get_length (ebml); - } + DEBUG_ELEMENT_START (demux, ebml, "Attachments"); - GST_DEBUG_OBJECT (demux, "Parsing Attachments at offset %" G_GUINT64_FORMAT, - ebml->offset); + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Attachments", ret); + return ret; + } taglist = gst_tag_list_new (); while (ret == GST_FLOW_OK) { - /* We're an element that can be seeked to. If we are, then - * we want to prevent EOS, since that'll kill us. So we cache - * file size and seek until there, and don't call EOS upon os. */ - if (prevent_eos && length == ebml->offset) - break; - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2684,13 +2875,11 @@ gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, switch (id) { case GST_MATROSKA_ID_ATTACHEDFILE: - ret = - gst_matroska_demux_parse_attached_file (demux, prevent_eos, length, - taglist); + ret = gst_matroska_demux_parse_attached_file (demux, taglist); break; default: - GST_WARNING ("Unknown entry 0x%x in Attachments", id); + GST_WARNING ("Unknown Attachments subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -2700,6 +2889,7 @@ gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, break; } } + DEBUG_ELEMENT_STOP (demux, ebml, "Attachments", ret); if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) { GST_DEBUG_OBJECT (demux, "Posting attachment tags"); @@ -2715,13 +2905,10 @@ gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, } static GstFlowReturn -gst_matroska_demux_parse_chapters (GstMatroskaDemux * demux, - gboolean prevent_eos) +gst_matroska_demux_parse_chapters (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); - guint64 length = 0; - guint32 id; GstFlowReturn ret = GST_FLOW_OK; @@ -2729,19 +2916,17 @@ gst_matroska_demux_parse_chapters (GstMatroskaDemux * demux, GST_WARNING_OBJECT (demux, "Parsing of chapters not implemented yet"); /* TODO: implement parsing of chapters */ - if (prevent_eos) { - length = gst_ebml_read_get_length (ebml); + + DEBUG_ELEMENT_START (demux, ebml, "Chapters"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Chapters", ret); + return ret; } while (ret == GST_FLOW_OK) { - /* We're an element that can be seeked to. If we are, then - * we want to prevent EOS, since that'll kill us. So we cache - * file size and seek until there, and don't call EOS upon os. */ - if (prevent_eos && length == ebml->offset) - break; - if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -2760,6 +2945,7 @@ gst_matroska_demux_parse_chapters (GstMatroskaDemux * demux, } } + DEBUG_ELEMENT_STOP (demux, ebml, "Chapters", ret); return ret; } @@ -2836,7 +3022,7 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) { gint stream_nr; - GST_LOG ("Sync to %" GST_TIME_FORMAT, + GST_LOG_OBJECT (demux, "Sync to %" GST_TIME_FORMAT, GST_TIME_ARGS (demux->segment.last_stop)); for (stream_nr = 0; stream_nr < demux->num_streams; stream_nr++) { @@ -2846,13 +3032,15 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) if (context->type != GST_MATROSKA_TRACK_TYPE_SUBTITLE) continue; - GST_LOG ("Checking for resync on stream %d (%" GST_TIME_FORMAT ")", - stream_nr, GST_TIME_ARGS (context->pos)); + GST_LOG_OBJECT (demux, + "Checking for resync on stream %d (%" GST_TIME_FORMAT ")", stream_nr, + GST_TIME_ARGS (context->pos)); /* does it lag? 0.5 seconds is a random treshold... */ if (context->pos + (GST_SECOND / 2) < demux->segment.last_stop) { - GST_DEBUG ("Synchronizing stream %d with others by advancing time " - "from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, stream_nr, + GST_DEBUG_OBJECT (demux, + "Synchronizing stream %d with others by advancing time " "from %" + GST_TIME_FORMAT " to %" GST_TIME_FORMAT, stream_nr, GST_TIME_ARGS (context->pos), GST_TIME_ARGS (demux->segment.last_stop)); @@ -3276,7 +3464,7 @@ gst_matroska_decode_buffer (GstMatroskaTrackContext * context, GstBuffer * buf) new_size = zstream.total_out; inflateEnd (&zstream); #else - GST_WARNING ("GZIP encoded tracks not supported."); + GST_WARNING ("zlib encoded tracks not supported."); break; #endif /* FIXME: add bzip/lzo support, what is header stripped? @@ -3343,7 +3531,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, while (ret == GST_FLOW_OK) { if (!is_simpleblock) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - goto done; + break; if (demux->level_up) { demux->level_up--; @@ -3386,7 +3574,8 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, if (size <= 3 || stream_num < 0 || stream_num >= demux->num_streams) { gst_buffer_unref (buf); buf = NULL; - GST_WARNING ("Invalid stream %d or size %u", stream_num, size); + GST_WARNING_OBJECT (demux, "Invalid stream %d or size %u", stream_num, + size); ret = GST_FLOW_ERROR; break; } @@ -3513,16 +3702,21 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, case GST_MATROSKA_ID_BLOCKDURATION:{ ret = gst_ebml_read_uint (ebml, &id, &block_duration); + GST_DEBUG_OBJECT (demux, "BlockDuration: %" G_GUINT64_FORMAT, + &block_duration); break; } case GST_MATROSKA_ID_REFERENCEBLOCK:{ ret = gst_ebml_read_sint (ebml, &id, &referenceblock); + GST_DEBUG_OBJECT (demux, "ReferenceBlock: %" G_GINT64_FORMAT, + &referenceblock); break; } default: - GST_WARNING ("Unknown entry 0x%x in blockgroup data", id); + GST_WARNING_OBJECT (demux, + "Unknown BlockGroup subelement 0x%x - ignoring", id); /* fall-through */ case GST_MATROSKA_ID_BLOCKVIRTUAL: @@ -3544,14 +3738,6 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, } } - if (referenceblock && readblock && demux->src[stream_num]->set_discont) { - /* When doing seeks or such, we need to restart on key frames or - decoders might choke. */ - readblock = FALSE; - gst_buffer_unref (buf); - buf = NULL; - } - if (ret == GST_FLOW_OK && readblock) { guint64 duration = 0; @@ -3632,12 +3818,21 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, } } + if (GST_BUFFER_FLAG_IS_SET (sub, GST_BUFFER_FLAG_DELTA_UNIT) + && demux->src[stream_num]->set_discont) { + /* When doing seeks or such, we need to restart on key frames or + * decoders might choke. */ + goto done; + } + + if (stream->set_discont) { GST_BUFFER_FLAG_SET (sub, GST_BUFFER_FLAG_DISCONT); stream->set_discont = FALSE; } - GST_DEBUG ("Pushing lace %d, data of size %d for stream %d, time=%" + GST_DEBUG_OBJECT (demux, + "Pushing lace %d, data of size %d for stream %d, time=%" GST_TIME_FORMAT " and duration=%" GST_TIME_FORMAT, n, GST_BUFFER_SIZE (sub), stream_num, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (sub)), @@ -3679,9 +3874,16 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux) guint32 id; + DEBUG_ELEMENT_START (demux, ebml, "Cluster"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Cluster", ret); + return ret; + } + while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -3694,29 +3896,35 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux) { guint64 num; - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) == GST_FLOW_OK) { - cluster_time = num; - } + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (demux, "ClusterTimeCode: %" G_GUINT64_FORMAT, num); + cluster_time = num; break; } /* a group of blocks inside a cluster */ case GST_MATROSKA_ID_BLOCKGROUP: + DEBUG_ELEMENT_START (demux, ebml, "BlockGroup"); if ((ret = gst_ebml_read_master (ebml, &id)) == GST_FLOW_OK) { ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux, cluster_time, FALSE); } + DEBUG_ELEMENT_STOP (demux, ebml, "BlockGroup", ret); break; case GST_MATROSKA_ID_SIMPLEBLOCK: { + DEBUG_ELEMENT_START (demux, ebml, "SimpleBlock"); ret = gst_matroska_demux_parse_blockgroup_or_simpleblock (demux, cluster_time, TRUE); + DEBUG_ELEMENT_STOP (demux, ebml, "SimpleBlock", ret); break; } default: - GST_WARNING ("Unknown entry 0x%x in cluster data", id); + GST_WARNING ("Unknown Cluster subelement 0x%x - ignoring", id); /* fall-through */ case GST_MATROSKA_ID_POSITION: @@ -3732,13 +3940,13 @@ gst_matroska_demux_parse_cluster (GstMatroskaDemux * demux) break; } } + DEBUG_ELEMENT_STOP (demux, ebml, "Cluster", ret); return ret; } static GstFlowReturn -gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, - gboolean * p_run_loop) +gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -3750,12 +3958,16 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, guint32 id; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) + DEBUG_ELEMENT_START (demux, ebml, "Seek"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (demux, ebml, "Seek", ret); return ret; + } while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -3767,9 +3979,11 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, { guint64 t; - if ((ret = gst_ebml_read_uint (ebml, &id, &t)) == GST_FLOW_OK) { - seek_id = t; - } + if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (demux, "SeekID: %" G_GUINT64_FORMAT, t); + seek_id = t; break; } @@ -3777,14 +3991,23 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, { guint64 t; - if ((ret = gst_ebml_read_uint (ebml, &id, &t)) == GST_FLOW_OK) { - seek_pos = t; + if ((ret = gst_ebml_read_uint (ebml, &id, &t)) != GST_FLOW_OK) + break; + + if (t > G_MAXINT64) { + GST_WARNING_OBJECT (demux, + "Too large SeekPosition %" G_GUINT64_FORMAT, t); + break; } + + GST_DEBUG_OBJECT (demux, "SeekPosition: %" G_GUINT64_FORMAT, t); + seek_pos = t; break; } default: - GST_WARNING ("Unknown seekhead ID 0x%x", id); + GST_WARNING_OBJECT (demux, + "Unknown SeekHead subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -3795,11 +4018,11 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, } } - if (ret != GST_FLOW_OK) + if (ret != GST_FLOW_OK && ret != GST_FLOW_UNEXPECTED) return ret; if (!seek_id || seek_pos == (guint64) - 1) { - GST_WARNING ("Incomplete seekhead entry (0x%x/%" + GST_WARNING_OBJECT (demux, "Incomplete seekhead entry (0x%x/%" G_GUINT64_FORMAT ")", seek_id, seek_pos); return GST_FLOW_OK; } @@ -3826,7 +4049,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, /* check for validity */ if (seek_pos + demux->ebml_segment_start + 12 >= length) { GST_WARNING_OBJECT (demux, - "Seekhead reference lies outside file!" " (%" + "SeekHead reference lies outside file!" " (%" G_GUINT64_FORMAT "+%" G_GUINT64_FORMAT "+12 >= %" G_GUINT64_FORMAT ")", seek_pos, demux->ebml_segment_start, length); break; @@ -3835,7 +4058,7 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, /* seek */ if (gst_ebml_read_seek (ebml, seek_pos + demux->ebml_segment_start) != GST_FLOW_OK) - return GST_FLOW_ERROR; + break; /* we don't want to lose our seekhead level, so we add * a dummy. This is a crude hack. */ @@ -3846,12 +4069,12 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, /* check ID */ if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + goto finish; if (id != seek_id) { - g_warning ("We looked for ID=0x%x but got ID=0x%x (pos=%" - G_GUINT64_FORMAT ")", seek_id, id, - seek_pos + demux->ebml_segment_start); + GST_WARNING_OBJECT (demux, + "We looked for ID=0x%x but got ID=0x%x (pos=%" G_GUINT64_FORMAT ")", + seek_id, id, seek_pos + demux->ebml_segment_start); goto finish; } @@ -3859,53 +4082,34 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, switch (id) { case GST_MATROSKA_ID_CUES: if (!demux->index_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_index (demux, - TRUE)) != GST_FLOW_OK) - return ret; + ret = gst_matroska_demux_parse_index (demux); } - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; break; case GST_MATROSKA_ID_TAGS: - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_metadata (demux, - TRUE)) != GST_FLOW_OK) - return ret; - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; + ret = gst_matroska_demux_parse_metadata (demux); break; case GST_MATROSKA_ID_TRACKS: if (!demux->tracks_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = gst_matroska_demux_parse_tracks (demux)) != GST_FLOW_OK) - return ret; + ret = gst_matroska_demux_parse_tracks (demux); } - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; break; case GST_MATROSKA_ID_SEGMENTINFO: if (!demux->segmentinfo_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = gst_matroska_demux_parse_info (demux)) != GST_FLOW_OK) - return ret; + ret = gst_matroska_demux_parse_info (demux); } - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; break; case GST_MATROSKA_ID_SEEKHEAD: { GList *l; - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; + DEBUG_ELEMENT_START (demux, ebml, "SeekHead"); + ret = gst_ebml_read_master (ebml, &id); + if (ret == GST_FLOW_UNEXPECTED) + ret = GST_FLOW_OK; + + if (ret != GST_FLOW_OK) + break; /* Prevent infinite recursion if there's a cycle from * one seekhead to the same again. Simply break if @@ -3918,42 +4122,22 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, goto finish; } - if ((ret = - gst_matroska_demux_parse_contents (demux, - p_run_loop)) != GST_FLOW_OK) - return ret; - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; + ret = gst_matroska_demux_parse_contents (demux); + + if (ret == GST_FLOW_UNEXPECTED) + ret = GST_FLOW_OK; break; } case GST_MATROSKA_ID_ATTACHMENTS: if (!demux->attachments_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_attachments (demux, - TRUE)) != GST_FLOW_OK) - return ret; + ret = gst_matroska_demux_parse_attachments (demux); } - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; break; case GST_MATROSKA_ID_CHAPTERS: - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_chapters (demux, - TRUE)) != GST_FLOW_OK) - return ret; - if (gst_ebml_read_get_length (ebml) == ebml->offset) - *p_run_loop = FALSE; + ret = gst_matroska_demux_parse_chapters (demux); break; } - /* FIXME: - * used to be here in 0.8 version, but makes mewmew sample not work */ - /* if (*p_run_loop == FALSE) break; */ - finish: /* remove dummy level */ while (ebml->level) { @@ -3974,16 +4158,16 @@ gst_matroska_demux_parse_contents_seekentry (GstMatroskaDemux * demux, } default: - GST_INFO ("Ignoring seekhead entry for ID=0x%x", seek_id); + GST_DEBUG_OBJECT (demux, "Ignoring Seek entry for ID=0x%x", seek_id); break; } + DEBUG_ELEMENT_STOP (demux, ebml, "Seek", ret); return ret; } static GstFlowReturn -gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, - gboolean * p_run_loop) +gst_matroska_demux_parse_contents (GstMatroskaDemux * demux) { GstEbmlRead *ebml = GST_EBML_READ (demux); @@ -3993,7 +4177,7 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, while (ret == GST_FLOW_OK) { if ((ret = gst_ebml_peek_id (ebml, &demux->level_up, &id)) != GST_FLOW_OK) - return ret; + break; if (demux->level_up) { demux->level_up--; @@ -4003,12 +4187,17 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, switch (id) { case GST_MATROSKA_ID_SEEKENTRY: { - ret = gst_matroska_demux_parse_contents_seekentry (demux, p_run_loop); + ret = gst_matroska_demux_parse_contents_seekentry (demux); + /* Ignore EOS here */ + if (ret == GST_FLOW_UNEXPECTED) { + GST_DEBUG_OBJECT (demux, "Ignoring EOS"); + ret = GST_FLOW_OK; + } break; } default: - GST_WARNING ("Unknown seekhead ID 0x%x", id); + GST_WARNING ("Unknown SeekHead subelement 0x%x - ignoring", id); ret = gst_ebml_read_skip (ebml); break; } @@ -4018,6 +4207,7 @@ gst_matroska_demux_parse_contents (GstMatroskaDemux * demux, break; } } + DEBUG_ELEMENT_STOP (demux, ebml, "SeekHead", ret); return ret; } @@ -4037,8 +4227,6 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, * must have the same content so ignore them */ case GST_MATROSKA_ID_SEGMENTINFO: if (!demux->segmentinfo_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; if ((ret = gst_matroska_demux_parse_info (demux)) != GST_FLOW_OK) return ret; } else { @@ -4053,8 +4241,6 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, case GST_MATROSKA_ID_TRACKS: { if (!demux->tracks_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; if ((ret = gst_matroska_demux_parse_tracks (demux)) != GST_FLOW_OK) return ret; } else { @@ -4070,10 +4256,7 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, case GST_MATROSKA_ID_CUES: { if (!demux->index_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_index (demux, FALSE)) != GST_FLOW_OK) + if ((ret = gst_matroska_demux_parse_index (demux)) != GST_FLOW_OK) return ret; } else { if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK) @@ -4086,10 +4269,7 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, * can exist more than one time with different content */ case GST_MATROSKA_ID_TAGS: { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_metadata (demux, FALSE)) != GST_FLOW_OK) + if ((ret = gst_matroska_demux_parse_metadata (demux)) != GST_FLOW_OK) return ret; break; } @@ -4097,11 +4277,10 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, /* file index (if seekable, seek to Cues/Tags/etc to parse it) */ case GST_MATROSKA_ID_SEEKHEAD: { + DEBUG_ELEMENT_START (demux, ebml, "SeekHead"); if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) return ret; - if ((ret = - gst_matroska_demux_parse_contents (demux, - p_run_loop)) != GST_FLOW_OK) + if ((ret = gst_matroska_demux_parse_contents (demux)) != GST_FLOW_OK) return ret; break; } @@ -4123,9 +4302,6 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, GST_DEBUG_OBJECT (demux, "signaling no more pads"); gst_element_no_more_pads (GST_ELEMENT (demux)); } else { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - /* The idea is that we parse one cluster per loop and * then break out of the loop here. In the next call * of the loopfunc, we will get back here with the @@ -4145,11 +4321,7 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, case GST_MATROSKA_ID_ATTACHMENTS:{ if (!demux->attachments_parsed) { - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_attachments (demux, - FALSE)) != GST_FLOW_OK) + if ((ret = gst_matroska_demux_parse_attachments (demux)) != GST_FLOW_OK) return ret; } else { if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK) @@ -4161,17 +4333,14 @@ gst_matroska_demux_loop_stream_parse_id (GstMatroskaDemux * demux, /* chapters - contains meta information about how to group * the file into chapters, similar to DVD */ case GST_MATROSKA_ID_CHAPTERS:{ - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) - return ret; - if ((ret = - gst_matroska_demux_parse_chapters (demux, FALSE)) != GST_FLOW_OK) + if ((ret = gst_matroska_demux_parse_chapters (demux)) != GST_FLOW_OK) return ret; break; } default: - GST_WARNING ("Unknown matroska file header ID 0x%x at %" - G_GUINT64_FORMAT, id, GST_EBML_READ (demux)->offset); + GST_WARNING_OBJECT (demux, "Unknown Segment subelement 0x%x at %" + G_GUINT64_FORMAT " - ignoring", id, GST_EBML_READ (demux)->offset); if ((ret = gst_ebml_read_skip (ebml)) != GST_FLOW_OK) return ret; break; @@ -4249,7 +4418,7 @@ gst_matroska_demux_loop (GstPad * pad) } if (ebml->offset == gst_ebml_read_get_length (ebml)) { - GST_LOG ("Reached end of stream, sending EOS"); + GST_LOG_OBJECT (demux, "Reached end of stream, sending EOS"); ret = GST_FLOW_UNEXPECTED; goto pause; } diff --git a/gst/matroska/matroska-ids.c b/gst/matroska/matroska-ids.c index 056dbf4..9d68617 100644 --- a/gst/matroska/matroska-ids.c +++ b/gst/matroska/matroska-ids.c @@ -53,7 +53,6 @@ gst_matroska_track_init_video_context (GstMatroskaTrackContext ** p_context) video_context->display_height = 0; video_context->pixel_width = 0; video_context->pixel_height = 0; - video_context->eye_mode = 0; video_context->asr_mode = 0; video_context->fourcc = 0; video_context->default_fps = 0.0; diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index 987cbbb..6ad2060 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -430,13 +430,6 @@ typedef enum { } GstMatroskaTrackType; typedef enum { - GST_MATROSKA_EYE_MODE_MONO = 0x0, - GST_MATROSKA_EYE_MODE_RIGHT = 0x1, - GST_MATROSKA_EYE_MODE_LEFT = 0x2, - GST_MATROSKA_EYE_MODE_BOTH = 0x3, -} GstMatroskaEyeMode; - -typedef enum { GST_MATROSKA_ASPECT_RATIO_MODE_FREE = 0x0, GST_MATROSKA_ASPECT_RATIO_MODE_KEEP = 0x1, GST_MATROSKA_ASPECT_RATIO_MODE_FIXED = 0x2, @@ -512,7 +505,6 @@ typedef struct _GstMatroskaTrackVideoContext { guint pixel_width, pixel_height; guint display_width, display_height; gdouble default_fps; - GstMatroskaEyeMode eye_mode; GstMatroskaAspectRatioMode asr_mode; guint32 fourcc; } GstMatroskaTrackVideoContext; diff --git a/gst/matroska/matroska-mux.c b/gst/matroska/matroska-mux.c index 9b5ba25..1582b67 100644 --- a/gst/matroska/matroska-mux.c +++ b/gst/matroska/matroska-mux.c @@ -589,7 +589,6 @@ gst_matroska_mux_video_pad_setcaps (GstPad * pad, GstCaps * caps) skip_details: videocontext->asr_mode = GST_MATROSKA_ASPECT_RATIO_MODE_FREE; - videocontext->eye_mode = GST_MATROSKA_EYE_MODE_MONO; videocontext->fourcc = 0; /* TODO: - check if we handle all codecs by the spec, i.e. codec private -- 2.7.4