diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 24a7294851..0e2157a15f 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -592,21 +592,16 @@ beach: } static GstFlowReturn -gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) +gst_matroska_demux_parse_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml, + GstMatroskaTrackContext ** dest_context) { - GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux); GstMatroskaTrackContext *context; - GstPadTemplate *templ = NULL; - GstStreamFlags stream_flags; GstCaps *caps = NULL; GstTagList *cached_taglist; - gchar *padname = NULL; GstFlowReturn ret; guint32 id, riff_fourcc = 0; guint16 riff_audio_fmt = 0; - GstEvent *stream_start; gchar *codec = NULL; - gchar *stream_id; DEBUG_ELEMENT_START (demux, ebml, "TrackEntry"); @@ -619,8 +614,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) /* allocate generic... if we know the type, we'll g_renew() * with the precise type */ context = g_new0 (GstMatroskaTrackContext, 1); - g_ptr_array_add (demux->common.src, context); - context->index = demux->common.num_streams; context->index_writer_id = -1; context->type = 0; /* no type yet */ context->default_duration = 0; @@ -637,10 +630,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) context->dts_only = FALSE; context->intra_only = FALSE; context->tags = gst_tag_list_new_empty (); - demux->common.num_streams++; - g_assert (demux->common.src->len == demux->common.num_streams); - GST_DEBUG_OBJECT (demux, "Stream number %d", context->index); + GST_DEBUG_OBJECT (demux, "Parsing a TrackEntry (%d tracks parsed so far)", + demux->common.num_streams); /* try reading the trackentry headers */ while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { @@ -659,12 +651,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) GST_ERROR_OBJECT (demux, "Invalid TrackNumber 0"); ret = GST_FLOW_ERROR; break; - } else if (!gst_matroska_read_common_tracknumber_unique (&demux->common, - 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); @@ -731,8 +717,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) context->type = 0; break; } - g_ptr_array_index (demux->common.src, demux->common.num_streams - 1) - = context; break; } @@ -751,8 +735,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) break; } videocontext = (GstMatroskaTrackVideoContext *) context; - g_ptr_array_index (demux->common.src, demux->common.num_streams - 1) - = context; while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { @@ -1033,8 +1015,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) break; audiocontext = (GstMatroskaTrackAudioContext *) context; - g_ptr_array_index (demux->common.src, demux->common.num_streams - 1) - = context; while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { @@ -1363,11 +1343,9 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) if (ret == GST_FLOW_OK || ret == GST_FLOW_EOS) GST_WARNING_OBJECT (ebml, "Unknown stream/codec in track entry header"); - demux->common.num_streams--; - g_ptr_array_remove_index (demux->common.src, demux->common.num_streams); - g_assert (demux->common.src->len == demux->common.num_streams); gst_matroska_track_free (context); - + context = NULL; + *dest_context = NULL; return ret; } @@ -1378,21 +1356,16 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) if (cached_taglist) gst_tag_list_insert (context->tags, cached_taglist, GST_TAG_MERGE_APPEND); - /* now create the GStreamer connectivity */ + /* compute caps */ switch (context->type) { case GST_MATROSKA_TRACK_TYPE_VIDEO:{ GstMatroskaTrackVideoContext *videocontext = (GstMatroskaTrackVideoContext *) context; - padname = g_strdup_printf ("video_%u", demux->num_v_streams++); - templ = gst_element_class_get_pad_template (klass, "video_%u"); caps = gst_matroska_demux_video_caps (videocontext, context->codec_id, context->codec_priv, context->codec_priv_size, &codec, &riff_fourcc); - if (!context->intra_only) - demux->have_nonintraonly_v_streams = TRUE; - if (codec) { gst_tag_list_add (context->tags, GST_TAG_MERGE_REPLACE, GST_TAG_VIDEO_CODEC, codec, NULL); @@ -1406,8 +1379,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) GstMatroskaTrackAudioContext *audiocontext = (GstMatroskaTrackAudioContext *) context; - padname = g_strdup_printf ("audio_%u", demux->num_a_streams++); - templ = gst_element_class_get_pad_template (klass, "audio_%u"); caps = gst_matroska_demux_audio_caps (audiocontext, context->codec_id, context->codec_priv, context->codec_priv_size, &codec, &riff_audio_fmt); @@ -1425,8 +1396,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) GstMatroskaTrackSubtitleContext *subtitlecontext = (GstMatroskaTrackSubtitleContext *) context; - padname = g_strdup_printf ("subtitle_%u", demux->num_t_streams++); - templ = gst_element_class_get_pad_template (klass, "subtitle_%u"); caps = gst_matroska_demux_subtitle_caps (subtitlecontext, context->codec_id, context->codec_priv, context->codec_priv_size); break; @@ -1498,9 +1467,59 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) context->stream_headers, caps); } + context->caps = caps; + + /* tadaah! */ + *dest_context = context; + return ret; +} + +static void +gst_matroska_demux_add_stream (GstMatroskaDemux * demux, + GstMatroskaTrackContext * context) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (demux); + gchar *padname = NULL; + GstPadTemplate *templ = NULL; + GstStreamFlags stream_flags; + + GstEvent *stream_start; + + gchar *stream_id; + + g_ptr_array_add (demux->common.src, context); + context->index = demux->common.num_streams++; + g_assert (demux->common.src->len == demux->common.num_streams); + g_ptr_array_index (demux->common.src, demux->common.num_streams - 1) = + context; + + /* now create the GStreamer connectivity */ + switch (context->type) { + case GST_MATROSKA_TRACK_TYPE_VIDEO: + padname = g_strdup_printf ("video_%u", demux->num_v_streams++); + templ = gst_element_class_get_pad_template (klass, "video_%u"); + + if (!context->intra_only) + demux->have_nonintraonly_v_streams = TRUE; + break; + + case GST_MATROSKA_TRACK_TYPE_AUDIO: + padname = g_strdup_printf ("audio_%u", demux->num_a_streams++); + templ = gst_element_class_get_pad_template (klass, "audio_%u"); + break; + + case GST_MATROSKA_TRACK_TYPE_SUBTITLE: + padname = g_strdup_printf ("subtitle_%u", demux->num_t_streams++); + templ = gst_element_class_get_pad_template (klass, "subtitle_%u"); + break; + + default: + /* we should already have quit by now */ + g_assert_not_reached (); + } + /* the pad in here */ context->pad = gst_pad_new_from_template (templ, padname); - context->caps = caps; gst_pad_set_event_function (context->pad, GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_event)); @@ -1508,7 +1527,7 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) GST_DEBUG_FUNCPTR (gst_matroska_demux_handle_src_query)); GST_INFO_OBJECT (demux, "Adding pad '%s' with caps %" GST_PTR_FORMAT, - padname, caps); + padname, context->caps); gst_pad_set_element_private (context->pad, context); @@ -1576,9 +1595,6 @@ gst_matroska_demux_add_stream (GstMatroskaDemux * demux, GstEbmlRead * ebml) gst_flow_combiner_add_pad (demux->flowcombiner, context->pad); g_free (padname); - - /* tadaah! */ - return ret; } static gboolean @@ -3085,9 +3101,23 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux, GstEbmlRead * ebml) switch (id) { /* one track within the "all-tracks" header */ - case GST_MATROSKA_ID_TRACKENTRY: - ret = gst_matroska_demux_add_stream (demux, ebml); + case GST_MATROSKA_ID_TRACKENTRY:{ + GstMatroskaTrackContext *track; + ret = gst_matroska_demux_parse_stream (demux, ebml, &track); + if (track != NULL) { + if (gst_matroska_read_common_tracknumber_unique (&demux->common, + track->num)) { + gst_matroska_demux_add_stream (demux, track); + } else { + GST_ERROR_OBJECT (demux, + "TrackNumber %" G_GUINT64_FORMAT " is not unique", track->num); + ret = GST_FLOW_ERROR; + gst_matroska_track_free (track); + track = NULL; + } + } break; + } default: ret = gst_matroska_read_common_parse_skip (&demux->common, ebml,