From 25e0da562be42ebd2e16511e93fcba383b0cd3af Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Sun, 5 Jun 2011 02:00:08 +0530 Subject: [PATCH 01/11] matroskaparse: Use ARTIST tag instead of AUTHOR for GST_TAG_ARTIST AUTHOR only existed in an old version of the spec and ARTIST is the new replacement for this. We are still reading both to still be compatible with old files. Fixes bug #644875. --- gst/matroska/matroska-parse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 177a619434..f141ff5b65 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -1702,6 +1702,7 @@ gst_matroska_parse_parse_metadata_id_simple_tag (GstMatroskaParse * parse, tag_conv[] = { { GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, { + GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, { GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, { GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { From 6d8d08eac7af2ff57a1e75e5c56313f26c5d0311 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 4 Jun 2011 13:43:00 -0700 Subject: [PATCH 02/11] souphttpsink: code cleanup --- ext/soup/gstsouphttpsink.c | 88 ++++++++++++++++++++++++++++++-------- ext/soup/gstsouphttpsink.h | 2 + 2 files changed, 72 insertions(+), 18 deletions(-) diff --git a/ext/soup/gstsouphttpsink.c b/ext/soup/gstsouphttpsink.c index 04af372bf9..2de51d867f 100644 --- a/ext/soup/gstsouphttpsink.c +++ b/ext/soup/gstsouphttpsink.c @@ -74,6 +74,9 @@ static void authenticate (SoupSession * session, SoupMessage * msg, SoupAuth * auth, gboolean retrying, gpointer user_data); static void callback (SoupSession * session, SoupMessage * msg, gpointer user_data); +static gboolean +gst_soup_http_sink_set_proxy (GstSoupHttpSink * souphttpsink, + const gchar * uri); enum { @@ -87,7 +90,7 @@ enum PROP_PROXY_ID, PROP_PROXY_PW, PROP_COOKIES, - PROP_SESSION, + PROP_SESSION }; #define DEFAULT_USER_AGENT "GStreamer souphttpsink " @@ -159,13 +162,11 @@ gst_soup_http_sink_class_init (GstSoupHttpSinkClass * klass) g_param_spec_boolean ("automatic-redirect", "automatic-redirect", "Automatically follow HTTP redirects (HTTP Status Code 3xx)", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -#if 0 g_object_class_install_property (gobject_class, PROP_PROXY, g_param_spec_string ("proxy", "Proxy", "HTTP proxy server URI", "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -#endif g_object_class_install_property (gobject_class, PROP_USER_ID, g_param_spec_string ("user-id", "user-id", @@ -187,7 +188,9 @@ gst_soup_http_sink_class_init (GstSoupHttpSinkClass * klass) g_param_spec_object ("session", "session", "SoupSession object to use for communication", SOUP_TYPE_SESSION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - + g_object_class_install_property (gobject_class, PROP_COOKIES, + g_param_spec_boxed ("cookies", "Cookies", "HTTP request cookies", + G_TYPE_STRV, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } @@ -195,9 +198,7 @@ static void gst_soup_http_sink_init (GstSoupHttpSink * souphttpsink, GstSoupHttpSinkClass * souphttpsink_class) { -#if 0 const char *proxy; -#endif souphttpsink->sinkpad = gst_pad_new_from_static_template (&gst_soup_http_sink_sink_template, @@ -215,14 +216,12 @@ gst_soup_http_sink_init (GstSoupHttpSink * souphttpsink, souphttpsink->proxy_pw = NULL; souphttpsink->prop_session = NULL; souphttpsink->timeout = 1; -#if 0 proxy = g_getenv ("http_proxy"); if (proxy && !gst_soup_http_sink_set_proxy (souphttpsink, proxy)) { GST_WARNING_OBJECT (souphttpsink, "The proxy in the http_proxy env var (\"%s\") cannot be parsed.", proxy); } -#endif gst_soup_http_sink_reset (souphttpsink); } @@ -237,6 +236,25 @@ gst_soup_http_sink_reset (GstSoupHttpSink * souphttpsink) } +static gboolean +gst_soup_http_sink_set_proxy (GstSoupHttpSink * souphttpsink, const gchar * uri) +{ + if (souphttpsink->proxy) { + soup_uri_free (souphttpsink->proxy); + souphttpsink->proxy = NULL; + } + if (g_str_has_prefix (uri, "http://")) { + souphttpsink->proxy = soup_uri_new (uri); + } else { + gchar *new_uri = g_strconcat ("http://", uri, NULL); + + souphttpsink->proxy = soup_uri_new (new_uri); + g_free (new_uri); + } + + return TRUE; +} + void gst_soup_http_sink_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) @@ -279,10 +297,31 @@ gst_soup_http_sink_set_property (GObject * object, guint property_id, g_free (souphttpsink->proxy_pw); souphttpsink->proxy_pw = g_value_dup_string (value); break; + case PROP_PROXY: + { + const gchar *proxy; + + proxy = g_value_get_string (value); + + if (proxy == NULL) { + GST_WARNING ("proxy property cannot be NULL"); + goto done; + } + if (!gst_soup_http_sink_set_proxy (souphttpsink, proxy)) { + GST_WARNING ("badly formatted proxy URI"); + goto done; + } + break; + } + case PROP_COOKIES: + g_strfreev (souphttpsink->cookies); + souphttpsink->cookies = g_strdupv (g_value_get_boxed (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; } +done: g_mutex_unlock (souphttpsink->mutex); } @@ -317,7 +356,19 @@ gst_soup_http_sink_get_property (GObject * object, guint property_id, case PROP_PROXY_PW: g_value_set_string (value, souphttpsink->proxy_pw); break; + case PROP_PROXY: + if (souphttpsink->proxy == NULL) + g_value_set_static_string (value, ""); + else { + char *proxy = soup_uri_to_string (souphttpsink->proxy, FALSE); + g_value_set_string (value, proxy); + g_free (proxy); + } + break; + case PROP_COOKIES: + g_value_set_boxed (value, g_strdupv (souphttpsink->cookies)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -349,6 +400,8 @@ gst_soup_http_sink_finalize (GObject * object) g_free (souphttpsink->user_pw); g_free (souphttpsink->proxy_id); g_free (souphttpsink->proxy_pw); + if (souphttpsink->proxy) + soup_uri_free (souphttpsink->proxy); g_free (souphttpsink->location); g_cond_free (souphttpsink->cond); @@ -482,17 +535,17 @@ gst_soup_http_sink_event (GstBaseSink * sink, GstEvent * event) { GstSoupHttpSink *souphttpsink = GST_SOUP_HTTP_SINK (sink); - GST_DEBUG ("event"); + GST_DEBUG_OBJECT (souphttpsink, "event"); if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - GST_DEBUG ("got eos"); + GST_DEBUG_OBJECT (souphttpsink, "got eos"); g_mutex_lock (souphttpsink->mutex); while (souphttpsink->message) { - GST_DEBUG ("waiting"); + GST_DEBUG_OBJECT (souphttpsink, "waiting"); g_cond_wait (souphttpsink->cond, souphttpsink->mutex); } g_mutex_unlock (souphttpsink->mutex); - GST_DEBUG ("finished eos"); + GST_DEBUG_OBJECT (souphttpsink, "finished eos"); } return TRUE; @@ -536,8 +589,6 @@ send_message_locked (GstSoupHttpSink * souphttpsink) souphttpsink->message = soup_message_new ("PUT", souphttpsink->location); - //soup_message_body_set_accumulate (souphttpsink->message->request_body, TRUE); - n = 0; if (souphttpsink->offset == 0) { for (g = souphttpsink->streamheader_buffers; g; g = g_list_next (g)) { @@ -579,10 +630,11 @@ send_message_locked (GstSoupHttpSink * souphttpsink) souphttpsink->sent_buffers = souphttpsink->queued_buffers; souphttpsink->queued_buffers = NULL; - GST_DEBUG ("queue message %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, + GST_DEBUG_OBJECT (souphttpsink, + "queue message %" G_GUINT64_FORMAT " %" G_GUINT64_FORMAT, souphttpsink->offset, n); - soup_session_queue_message (souphttpsink->session, - souphttpsink->message, callback, souphttpsink); + soup_session_queue_message (souphttpsink->session, souphttpsink->message, + callback, souphttpsink); souphttpsink->offset += n; } @@ -631,6 +683,7 @@ gst_soup_http_sink_render (GstBaseSink * sink, GstBuffer * buffer) gboolean wake; if (souphttpsink->status_code != 0) { + /* FIXME we should allow a moderate amount of retries. */ GST_ELEMENT_ERROR (souphttpsink, RESOURCE, WRITE, ("Could not write to HTTP URI"), ("error: %d %s", souphttpsink->status_code, @@ -646,7 +699,6 @@ gst_soup_http_sink_render (GstBaseSink * sink, GstBuffer * buffer) if (wake) { source = g_idle_source_new (); - //g_source_set_priority (source, G_PRIORITY_DEFAULT); g_source_set_callback (source, (GSourceFunc) (send_message), souphttpsink, NULL); g_source_attach (source, souphttpsink->context); diff --git a/ext/soup/gstsouphttpsink.h b/ext/soup/gstsouphttpsink.h index c7d4e49b82..f78272946e 100644 --- a/ext/soup/gstsouphttpsink.h +++ b/ext/soup/gstsouphttpsink.h @@ -62,10 +62,12 @@ struct _GstSoupHttpSink char *location; char *user_id; char *user_pw; + SoupURI *proxy; char *proxy_id; char *proxy_pw; char *user_agent; gboolean automatic_redirect; + gchar **cookies; }; From f6c348430e4eacdf7d8f22aed3772f2195c2dc05 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 4 Jun 2011 13:49:52 -0700 Subject: [PATCH 03/11] interleave: Work around changes in g_atomic API See #651514 for details. --- gst/interleave/interleave.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gst/interleave/interleave.c b/gst/interleave/interleave.c index 96a43c8d61..f8e4392889 100644 --- a/gst/interleave/interleave.c +++ b/gst/interleave/interleave.c @@ -479,8 +479,13 @@ gst_interleave_request_new_pad (GstElement * element, GstPadTemplate * templ, if (templ->direction != GST_PAD_SINK) goto not_sink_pad; +#if GLIB_CHECK_VERSION(2,29,5) + channels = g_atomic_int_add (&self->channels, 1); + padnumber = g_atomic_int_add (&self->padcounter, 1); +#else channels = g_atomic_int_exchange_and_add (&self->channels, 1); padnumber = g_atomic_int_exchange_and_add (&self->padcounter, 1); +#endif pad_name = g_strdup_printf ("sink%d", padnumber); new_pad = GST_PAD_CAST (g_object_new (GST_TYPE_INTERLEAVE_PAD, From 785247cfb315bcdaa989114497464de7189a08d1 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 6 Jun 2011 12:42:53 +0200 Subject: [PATCH 04/11] rtspsrc: reset state tracking variable when appropriate ... so we don't end up interrupting an operation that should not be interrupted based on the indication of a previous interruptable operation. --- gst/rtsp/gstrtspsrc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/rtsp/gstrtspsrc.c b/gst/rtsp/gstrtspsrc.c index 7ae7097859..78b968ff6e 100644 --- a/gst/rtsp/gstrtspsrc.c +++ b/gst/rtsp/gstrtspsrc.c @@ -6457,6 +6457,8 @@ gst_rtspsrc_thread (GstRTSPSrc * src) else if (src->task) gst_task_pause (src->task); } + /* reset waiting */ + src->waiting = FALSE; GST_OBJECT_UNLOCK (src); } From febfcce0fda8b33744bec48aec7bd3d3e39ba32d Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Sun, 5 Jun 2011 02:24:41 +0530 Subject: [PATCH 05/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_metadata_id_simple_tag https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 128 +--------------------------- gst/matroska/matroska-parse.c | 128 +--------------------------- gst/matroska/matroska-read-common.c | 123 ++++++++++++++++++++++++++ gst/matroska/matroska-read-common.h | 3 + 4 files changed, 132 insertions(+), 250 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 853e899674..6e9683cd40 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -2387,129 +2387,6 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_metadata_id_simple_tag (GstMatroskaDemux * demux, - GstEbmlRead * ebml, GstTagList ** p_taglist) -{ - /* FIXME: check if there are more useful mappings */ - static const struct - { - const gchar *matroska_tagname; - const gchar *gstreamer_tagname; - } - tag_conv[] = { - { - GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, { - GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, { - GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, { - GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { - GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { - GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { - GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, { - GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, { - GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { - GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, { - GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, { - GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, { - GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, { - GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, { - GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, { - GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE} - }; - GstFlowReturn ret; - guint32 id; - gchar *value = NULL; - gchar *tag = NULL; - - 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 && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - /* read all sub-entries */ - - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_TAGNAME: - 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: - ret = gst_matroska_read_common_parse_skip (&demux->common, ebml, - "SimpleTag", id); - break; - /* fall-through */ - - case GST_MATROSKA_ID_TAGLANGUAGE: - case GST_MATROSKA_ID_TAGDEFAULT: - case GST_MATROSKA_ID_TAGBINARY: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (demux, ebml, "SimpleTag", ret); - - if (tag && value) { - guint i; - - for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) { - const gchar *tagname_gst = tag_conv[i].gstreamer_tagname; - - const gchar *tagname_mkv = tag_conv[i].matroska_tagname; - - if (strcmp (tagname_mkv, tag) == 0) { - GValue dest = { 0, }; - GType dest_type = gst_tag_get_type (tagname_gst); - - /* Ensure that any date string is complete */ - if (dest_type == GST_TYPE_DATE) { - guint year = 1901, month = 1, day = 1; - - /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need - * the first type */ - if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) { - g_free (value); - value = g_strdup_printf ("%04u-%02u-%02u", year, month, day); - } - } - - g_value_init (&dest, dest_type); - if (gst_value_deserialize (&dest, value)) { - gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND, - tagname_gst, &dest, NULL); - } else { - GST_WARNING_OBJECT (demux, "Can't transform tag '%s' with " - "value '%s' to target type '%s'", tag, value, - g_type_name (dest_type)); - } - g_value_unset (&dest); - break; - } - } - } - - g_free (tag); - g_free (value); - - return ret; -} - static GstFlowReturn gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux, GstEbmlRead * ebml, GstTagList ** p_taglist) @@ -2532,8 +2409,9 @@ 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, ebml, - p_taglist); + ret = + gst_matroska_read_common_parse_metadata_id_simple_tag + (&demux->common, ebml, p_taglist); break; default: diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index f141ff5b65..8da2d22ad6 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -1689,129 +1689,6 @@ gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_metadata_id_simple_tag (GstMatroskaParse * parse, - GstEbmlRead * ebml, GstTagList ** p_taglist) -{ - /* FIXME: check if there are more useful mappings */ - struct - { - const gchar *matroska_tagname; - const gchar *gstreamer_tagname; - } - tag_conv[] = { - { - GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, { - GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, { - GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, { - GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { - GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { - GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { - GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, { - GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, { - GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { - GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, { - GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, { - GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, { - GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, { - GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, { - GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, { - GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE} - }; - GstFlowReturn ret; - guint32 id; - gchar *value = NULL; - gchar *tag = NULL; - - DEBUG_ELEMENT_START (parse, ebml, "SimpleTag"); - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret); - return ret; - } - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - /* read all sub-entries */ - - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_TAGNAME: - g_free (tag); - tag = NULL; - ret = gst_ebml_read_ascii (ebml, &id, &tag); - GST_DEBUG_OBJECT (parse, "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 (parse, "TagString: %s", GST_STR_NULL (value)); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&parse->common, ebml, - "SimpleTag", id); - break; - /* fall-through */ - - case GST_MATROSKA_ID_TAGLANGUAGE: - case GST_MATROSKA_ID_TAGDEFAULT: - case GST_MATROSKA_ID_TAGBINARY: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (parse, ebml, "SimpleTag", ret); - - if (tag && value) { - guint i; - - for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) { - const gchar *tagname_gst = tag_conv[i].gstreamer_tagname; - - const gchar *tagname_mkv = tag_conv[i].matroska_tagname; - - if (strcmp (tagname_mkv, tag) == 0) { - GValue dest = { 0, }; - GType dest_type = gst_tag_get_type (tagname_gst); - - /* Ensure that any date string is complete */ - if (dest_type == GST_TYPE_DATE) { - guint year = 1901, month = 1, day = 1; - - /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need - * the first type */ - if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) { - g_free (value); - value = g_strdup_printf ("%04u-%02u-%02u", year, month, day); - } - } - - g_value_init (&dest, dest_type); - if (gst_value_deserialize (&dest, value)) { - gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND, - tagname_gst, &dest, NULL); - } else { - GST_WARNING_OBJECT (parse, "Can't transform tag '%s' with " - "value '%s' to target type '%s'", tag, value, - g_type_name (dest_type)); - } - g_value_unset (&dest); - break; - } - } - } - - g_free (tag); - g_free (value); - - return ret; -} - static GstFlowReturn gst_matroska_parse_parse_metadata_id_tag (GstMatroskaParse * parse, GstEbmlRead * ebml, GstTagList ** p_taglist) @@ -1834,8 +1711,9 @@ gst_matroska_parse_parse_metadata_id_tag (GstMatroskaParse * parse, switch (id) { case GST_MATROSKA_ID_SIMPLETAG: - ret = gst_matroska_parse_parse_metadata_id_simple_tag (parse, ebml, - p_taglist); + ret = + gst_matroska_read_common_parse_metadata_id_simple_tag + (&parse->common, ebml, p_taglist); break; default: diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index bc4200b593..73c7f43905 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -953,6 +953,129 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, return ret; } +GstFlowReturn +gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon * + common, GstEbmlRead * ebml, GstTagList ** p_taglist) +{ + /* FIXME: check if there are more useful mappings */ + static const struct + { + const gchar *matroska_tagname; + const gchar *gstreamer_tagname; + } + tag_conv[] = { + { + GST_MATROSKA_TAG_ID_TITLE, GST_TAG_TITLE}, { + GST_MATROSKA_TAG_ID_ARTIST, GST_TAG_ARTIST}, { + GST_MATROSKA_TAG_ID_AUTHOR, GST_TAG_ARTIST}, { + GST_MATROSKA_TAG_ID_ALBUM, GST_TAG_ALBUM}, { + GST_MATROSKA_TAG_ID_COMMENTS, GST_TAG_COMMENT}, { + GST_MATROSKA_TAG_ID_BITSPS, GST_TAG_BITRATE}, { + GST_MATROSKA_TAG_ID_BPS, GST_TAG_BITRATE}, { + GST_MATROSKA_TAG_ID_ENCODER, GST_TAG_ENCODER}, { + GST_MATROSKA_TAG_ID_DATE, GST_TAG_DATE}, { + GST_MATROSKA_TAG_ID_ISRC, GST_TAG_ISRC}, { + GST_MATROSKA_TAG_ID_COPYRIGHT, GST_TAG_COPYRIGHT}, { + GST_MATROSKA_TAG_ID_BPM, GST_TAG_BEATS_PER_MINUTE}, { + GST_MATROSKA_TAG_ID_TERMS_OF_USE, GST_TAG_LICENSE}, { + GST_MATROSKA_TAG_ID_COMPOSER, GST_TAG_COMPOSER}, { + GST_MATROSKA_TAG_ID_LEAD_PERFORMER, GST_TAG_PERFORMER}, { + GST_MATROSKA_TAG_ID_GENRE, GST_TAG_GENRE} + }; + GstFlowReturn ret; + guint32 id; + gchar *value = NULL; + gchar *tag = NULL; + + DEBUG_ELEMENT_START (common, ebml, "SimpleTag"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret); + return ret; + } + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + /* read all sub-entries */ + + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + case GST_MATROSKA_ID_TAGNAME: + g_free (tag); + tag = NULL; + ret = gst_ebml_read_ascii (ebml, &id, &tag); + GST_DEBUG_OBJECT (common, "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 (common, "TagString: %s", GST_STR_NULL (value)); + break; + + default: + ret = gst_matroska_read_common_parse_skip (common, ebml, "SimpleTag", + id); + break; + /* fall-through */ + + case GST_MATROSKA_ID_TAGLANGUAGE: + case GST_MATROSKA_ID_TAGDEFAULT: + case GST_MATROSKA_ID_TAGBINARY: + ret = gst_ebml_read_skip (ebml); + break; + } + } + + DEBUG_ELEMENT_STOP (common, ebml, "SimpleTag", ret); + + if (tag && value) { + guint i; + + for (i = 0; i < G_N_ELEMENTS (tag_conv); i++) { + const gchar *tagname_gst = tag_conv[i].gstreamer_tagname; + + const gchar *tagname_mkv = tag_conv[i].matroska_tagname; + + if (strcmp (tagname_mkv, tag) == 0) { + GValue dest = { 0, }; + GType dest_type = gst_tag_get_type (tagname_gst); + + /* Ensure that any date string is complete */ + if (dest_type == GST_TYPE_DATE) { + guint year = 1901, month = 1, day = 1; + + /* Dates can be yyyy-MM-dd, yyyy-MM or yyyy, but we need + * the first type */ + if (sscanf (value, "%04u-%02u-%02u", &year, &month, &day) != 0) { + g_free (value); + value = g_strdup_printf ("%04u-%02u-%02u", year, month, day); + } + } + + g_value_init (&dest, dest_type); + if (gst_value_deserialize (&dest, value)) { + gst_tag_list_add_values (*p_taglist, GST_TAG_MERGE_APPEND, + tagname_gst, &dest, NULL); + } else { + GST_WARNING_OBJECT (common, "Can't transform tag '%s' with " + "value '%s' to target type '%s'", tag, value, + g_type_name (dest_type)); + } + g_value_unset (&dest); + break; + } + } + } + + g_free (tag); + g_free (value); + + return ret; +} + static const guint8 * gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint peek) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index 7525772d94..2927d96cee 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -93,6 +93,9 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); +GstFlowReturn gst_matroska_read_common_parse_metadata_id_simple_tag ( + GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList ** + p_taglist); GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common, GstEbmlRead * ebml, const gchar * parent_name, guint id); GstFlowReturn gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * From 493e197588909706edf671738200b1ba53bea0eb Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Sun, 5 Jun 2011 09:54:42 +0530 Subject: [PATCH 06/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_metadata_id_tag https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 42 ++--------------------------- gst/matroska/matroska-parse.c | 42 ++--------------------------- gst/matroska/matroska-read-common.c | 39 ++++++++++++++++++++++++++- gst/matroska/matroska-read-common.h | 2 +- 4 files changed, 43 insertions(+), 82 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 6e9683cd40..d294eccb7a 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -2387,45 +2387,6 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_metadata_id_tag (GstMatroskaDemux * demux, - GstEbmlRead * ebml, GstTagList ** p_taglist) -{ - guint32 id; - GstFlowReturn ret; - - 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 && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - /* read all sub-entries */ - - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_SIMPLETAG: - ret = - gst_matroska_read_common_parse_metadata_id_simple_tag - (&demux->common, ebml, p_taglist); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&demux->common, ebml, - "Tag", id); - break; - } - } - - DEBUG_ELEMENT_STOP (demux, ebml, "Tag", ret); - - return ret; -} - static GstFlowReturn gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, GstEbmlRead * ebml) { @@ -2468,7 +2429,8 @@ gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, GstEbmlRead * ebml) switch (id) { case GST_MATROSKA_ID_TAG: - ret = gst_matroska_demux_parse_metadata_id_tag (demux, ebml, &taglist); + ret = gst_matroska_read_common_parse_metadata_id_tag (&demux->common, + ebml, &taglist); break; default: diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 8da2d22ad6..43c87cabda 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -1689,45 +1689,6 @@ gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_metadata_id_tag (GstMatroskaParse * parse, - GstEbmlRead * ebml, GstTagList ** p_taglist) -{ - guint32 id; - GstFlowReturn ret; - - DEBUG_ELEMENT_START (parse, ebml, "Tag"); - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret); - return ret; - } - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - /* read all sub-entries */ - - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_SIMPLETAG: - ret = - gst_matroska_read_common_parse_metadata_id_simple_tag - (&parse->common, ebml, p_taglist); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&parse->common, ebml, - "Tag", id); - break; - } - } - - DEBUG_ELEMENT_STOP (parse, ebml, "Tag", ret); - - return ret; -} - static GstFlowReturn gst_matroska_parse_parse_metadata (GstMatroskaParse * parse, GstEbmlRead * ebml) { @@ -1770,7 +1731,8 @@ gst_matroska_parse_parse_metadata (GstMatroskaParse * parse, GstEbmlRead * ebml) switch (id) { case GST_MATROSKA_ID_TAG: - ret = gst_matroska_parse_parse_metadata_id_tag (parse, ebml, &taglist); + ret = gst_matroska_read_common_parse_metadata_id_tag (&parse->common, + ebml, &taglist); break; default: diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index 73c7f43905..e58f981673 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -953,7 +953,7 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, return ret; } -GstFlowReturn +static GstFlowReturn gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList ** p_taglist) { @@ -1076,6 +1076,43 @@ gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon * return ret; } +GstFlowReturn +gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common, + GstEbmlRead * ebml, GstTagList ** p_taglist) +{ + guint32 id; + GstFlowReturn ret; + + DEBUG_ELEMENT_START (common, ebml, "Tag"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret); + return ret; + } + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + /* read all sub-entries */ + + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + case GST_MATROSKA_ID_SIMPLETAG: + ret = gst_matroska_read_common_parse_metadata_id_simple_tag (common, + ebml, p_taglist); + break; + + default: + ret = gst_matroska_read_common_parse_skip (common, ebml, "Tag", id); + break; + } + } + + DEBUG_ELEMENT_STOP (common, ebml, "Tag", ret); + + return ret; +} + static const guint8 * gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint peek) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index 2927d96cee..7feb6b0692 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -93,7 +93,7 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); -GstFlowReturn gst_matroska_read_common_parse_metadata_id_simple_tag ( +GstFlowReturn gst_matroska_read_common_parse_metadata_id_tag ( GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList ** p_taglist); GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * From 2d282a6c7956dee8a6ee6760ccc13fc0394026ed Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Sun, 5 Jun 2011 10:15:23 +0530 Subject: [PATCH 07/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_metadata https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 74 ++--------------------------- gst/matroska/matroska-demux.h | 1 - gst/matroska/matroska-parse.c | 74 ++--------------------------- gst/matroska/matroska-parse.h | 1 - gst/matroska/matroska-read-common.c | 66 ++++++++++++++++++++++++- gst/matroska/matroska-read-common.h | 6 +-- 6 files changed, 78 insertions(+), 144 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index d294eccb7a..423cdcd17e 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -404,10 +404,10 @@ gst_matroska_demux_reset (GstElement * element) demux->segmentinfo_parsed = FALSE; demux->attachments_parsed = FALSE; - g_list_foreach (demux->tags_parsed, + g_list_foreach (demux->common.tags_parsed, (GFunc) gst_matroska_demux_free_parsed_el, NULL); - g_list_free (demux->tags_parsed); - demux->tags_parsed = NULL; + g_list_free (demux->common.tags_parsed); + demux->common.tags_parsed = NULL; g_list_foreach (demux->seek_parsed, (GFunc) gst_matroska_demux_free_parsed_el, NULL); @@ -2387,71 +2387,6 @@ gst_matroska_demux_parse_info (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_metadata (GstMatroskaDemux * demux, GstEbmlRead * ebml) -{ - GstTagList *taglist; - GstFlowReturn ret = GST_FLOW_OK; - guint32 id; - GList *l; - guint64 curpos; - - curpos = gst_ebml_read_get_pos (ebml); - - /* Make sure we don't parse a tags element twice and - * post it's tags twice */ - curpos = gst_ebml_read_get_pos (ebml); - for (l = demux->tags_parsed; l; l = l->next) { - guint64 *pos = l->data; - - if (*pos == curpos) { - GST_DEBUG_OBJECT (demux, "Skipping already parsed Tags at offset %" - G_GUINT64_FORMAT, curpos); - return GST_FLOW_OK; - } - } - - demux->tags_parsed = - g_list_prepend (demux->tags_parsed, g_slice_new (guint64)); - *((guint64 *) demux->tags_parsed->data) = curpos; - /* fall-through */ - - 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 (); - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_TAG: - ret = gst_matroska_read_common_parse_metadata_id_tag (&demux->common, - ebml, &taglist); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&demux->common, ebml, - "Tags", id); - break; - /* FIXME: Use to limit the tags to specific pads */ - case GST_MATROSKA_ID_TARGETS: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (demux, ebml, "Tags", ret); - - gst_matroska_read_common_found_global_tag (&demux->common, - GST_ELEMENT_CAST (demux), taglist); - - return ret; -} - static GstFlowReturn gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, GstEbmlRead * ebml, GstTagList * taglist) @@ -4556,7 +4491,8 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, break; case GST_MATROSKA_ID_TAGS: GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); - ret = gst_matroska_demux_parse_metadata (demux, &ebml); + ret = gst_matroska_read_common_parse_metadata (&demux->common, + GST_ELEMENT_CAST (demux), &ebml); break; case GST_MATROSKA_ID_CHAPTERS: GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index 109f301736..e9637f5ecc 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -70,7 +70,6 @@ typedef struct _GstMatroskaDemux { gboolean tracks_parsed; gboolean segmentinfo_parsed; gboolean attachments_parsed; - GList *tags_parsed; GList *seek_parsed; /* cluster positions (optional) */ diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 43c87cabda..ef60d67f37 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -327,10 +327,10 @@ gst_matroska_parse_reset (GstElement * element) parse->segmentinfo_parsed = FALSE; parse->attachments_parsed = FALSE; - g_list_foreach (parse->tags_parsed, + g_list_foreach (parse->common.tags_parsed, (GFunc) gst_matroska_parse_free_parsed_el, NULL); - g_list_free (parse->tags_parsed); - parse->tags_parsed = NULL; + g_list_free (parse->common.tags_parsed); + parse->common.tags_parsed = NULL; g_list_foreach (parse->seek_parsed, (GFunc) gst_matroska_parse_free_parsed_el, NULL); @@ -1689,71 +1689,6 @@ gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_metadata (GstMatroskaParse * parse, GstEbmlRead * ebml) -{ - GstTagList *taglist; - GstFlowReturn ret = GST_FLOW_OK; - guint32 id; - GList *l; - guint64 curpos; - - curpos = gst_ebml_read_get_pos (ebml); - - /* Make sure we don't parse a tags element twice and - * post it's tags twice */ - curpos = gst_ebml_read_get_pos (ebml); - for (l = parse->tags_parsed; l; l = l->next) { - guint64 *pos = l->data; - - if (*pos == curpos) { - GST_DEBUG_OBJECT (parse, "Skipping already parsed Tags at offset %" - G_GUINT64_FORMAT, curpos); - return GST_FLOW_OK; - } - } - - parse->tags_parsed = - g_list_prepend (parse->tags_parsed, g_slice_new (guint64)); - *((guint64 *) parse->tags_parsed->data) = curpos; - /* fall-through */ - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret); - return ret; - } - - taglist = gst_tag_list_new (); - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_TAG: - ret = gst_matroska_read_common_parse_metadata_id_tag (&parse->common, - ebml, &taglist); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&parse->common, ebml, - "Tags", id); - break; - /* FIXME: Use to limit the tags to specific pads */ - case GST_MATROSKA_ID_TARGETS: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (parse, ebml, "Tags", ret); - - gst_matroska_read_common_found_global_tag (&parse->common, - GST_ELEMENT_CAST (parse), taglist); - - return ret; -} - static GstFlowReturn gst_matroska_parse_parse_attached_file (GstMatroskaParse * parse, GstEbmlRead * ebml, GstTagList * taglist) @@ -3176,7 +3111,8 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id, break; case GST_MATROSKA_ID_TAGS: GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml)); - ret = gst_matroska_parse_parse_metadata (parse, &ebml); + ret = gst_matroska_read_common_parse_metadata (&parse->common, + GST_ELEMENT_CAST (parse), &ebml); gst_matroska_parse_output (parse, ebml.buf, FALSE); break; case GST_MATROSKA_ID_CHAPTERS: diff --git a/gst/matroska/matroska-parse.h b/gst/matroska/matroska-parse.h index 14c9129525..453510aeba 100644 --- a/gst/matroska/matroska-parse.h +++ b/gst/matroska/matroska-parse.h @@ -75,7 +75,6 @@ typedef struct _GstMatroskaParse { gboolean tracks_parsed; gboolean segmentinfo_parsed; gboolean attachments_parsed; - GList *tags_parsed; GList *seek_parsed; /* keeping track of playback position */ diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index e58f981673..f7cc0cf834 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -1076,7 +1076,7 @@ gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon * return ret; } -GstFlowReturn +static GstFlowReturn gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList ** p_taglist) { @@ -1113,6 +1113,70 @@ gst_matroska_read_common_parse_metadata_id_tag (GstMatroskaReadCommon * common, return ret; } +GstFlowReturn +gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * common, + GstElement * el, GstEbmlRead * ebml) +{ + GstTagList *taglist; + GstFlowReturn ret = GST_FLOW_OK; + guint32 id; + GList *l; + guint64 curpos; + + curpos = gst_ebml_read_get_pos (ebml); + + /* Make sure we don't parse a tags element twice and + * post it's tags twice */ + curpos = gst_ebml_read_get_pos (ebml); + for (l = common->tags_parsed; l; l = l->next) { + guint64 *pos = l->data; + + if (*pos == curpos) { + GST_DEBUG_OBJECT (common, "Skipping already parsed Tags at offset %" + G_GUINT64_FORMAT, curpos); + return GST_FLOW_OK; + } + } + + common->tags_parsed = + g_list_prepend (common->tags_parsed, g_slice_new (guint64)); + *((guint64 *) common->tags_parsed->data) = curpos; + /* fall-through */ + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret); + return ret; + } + + taglist = gst_tag_list_new (); + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + case GST_MATROSKA_ID_TAG: + ret = gst_matroska_read_common_parse_metadata_id_tag (common, ebml, + &taglist); + break; + + default: + ret = gst_matroska_read_common_parse_skip (common, ebml, "Tags", id); + break; + /* FIXME: Use to limit the tags to specific pads */ + case GST_MATROSKA_ID_TARGETS: + ret = gst_ebml_read_skip (ebml); + break; + } + } + + DEBUG_ELEMENT_STOP (common, ebml, "Tags", ret); + + gst_matroska_read_common_found_global_tag (common, el, taglist); + + return ret; +} + static const guint8 * gst_matroska_read_common_peek_adapter (GstMatroskaReadCommon * common, guint peek) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index 7feb6b0692..f1b96840d6 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -54,6 +54,7 @@ typedef struct _GstMatroskaReadCommon { /* did we parse cues/tracks/segmentinfo already? */ gboolean index_parsed; + GList *tags_parsed; /* start-of-segment */ guint64 ebml_segment_start; @@ -93,9 +94,8 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); -GstFlowReturn gst_matroska_read_common_parse_metadata_id_tag ( - GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList ** - p_taglist); +GstFlowReturn gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * + common, GstElement * el, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common, GstEbmlRead * ebml, const gchar * parent_name, guint id); GstFlowReturn gst_matroska_read_common_peek_bytes (GstMatroskaReadCommon * From 366f064e73b07a59f9fb4ae5a423f9d9f2146154 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Sun, 5 Jun 2011 22:45:55 +0530 Subject: [PATCH 08/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_info https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 304 +++++++++------------------- gst/matroska/matroska-demux.h | 7 - gst/matroska/matroska-parse.c | 186 +++-------------- gst/matroska/matroska-parse.h | 7 - gst/matroska/matroska-read-common.c | 130 ++++++++++++ gst/matroska/matroska-read-common.h | 11 + 6 files changed, 262 insertions(+), 383 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 423cdcd17e..4b2f1604fb 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -257,8 +257,8 @@ gst_matroska_demux_init (GstMatroskaDemux * demux, /* initial stream no. */ demux->common.src = NULL; - demux->writing_app = NULL; - demux->muxing_app = NULL; + demux->common.writing_app = NULL; + demux->common.muxing_app = NULL; demux->common.index = NULL; demux->common.global_tags = NULL; @@ -378,10 +378,10 @@ gst_matroska_demux_reset (GstElement * element) demux->num_v_streams = 0; /* reset media info */ - g_free (demux->writing_app); - demux->writing_app = NULL; - g_free (demux->muxing_app); - demux->muxing_app = NULL; + g_free (demux->common.writing_app); + demux->common.writing_app = NULL; + g_free (demux->common.muxing_app); + demux->common.muxing_app = NULL; /* reset indexes */ if (demux->common.index) { @@ -397,11 +397,11 @@ gst_matroska_demux_reset (GstElement * element) /* reset timers */ demux->clock = NULL; demux->common.time_scale = 1000000; - demux->created = G_MININT64; + demux->common.created = G_MININT64; demux->common.index_parsed = FALSE; demux->tracks_parsed = FALSE; - demux->segmentinfo_parsed = FALSE; + demux->common.segmentinfo_parsed = FALSE; demux->attachments_parsed = FALSE; g_list_foreach (demux->common.tags_parsed, @@ -414,7 +414,7 @@ gst_matroska_demux_reset (GstElement * element) g_list_free (demux->seek_parsed); demux->seek_parsed = NULL; - gst_segment_init (&demux->segment, GST_FORMAT_TIME); + gst_segment_init (&demux->common.segment, GST_FORMAT_TIME); demux->last_stop_end = GST_CLOCK_TIME_NONE; demux->seek_block = 0; @@ -1353,7 +1353,7 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad, gst_query_set_position (query, GST_FORMAT_TIME, context->pos); else gst_query_set_position (query, GST_FORMAT_TIME, - demux->segment.last_stop); + demux->common.segment.last_stop); GST_OBJECT_UNLOCK (demux); } else if (format == GST_FORMAT_DEFAULT && context && context->default_duration) { @@ -1378,13 +1378,13 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad, if (format == GST_FORMAT_TIME) { GST_OBJECT_LOCK (demux); gst_query_set_duration (query, GST_FORMAT_TIME, - demux->segment.duration); + demux->common.segment.duration); GST_OBJECT_UNLOCK (demux); } else if (format == GST_FORMAT_DEFAULT && context && context->default_duration) { GST_OBJECT_LOCK (demux); gst_query_set_duration (query, GST_FORMAT_DEFAULT, - demux->segment.duration / context->default_duration); + demux->common.segment.duration / context->default_duration); GST_OBJECT_UNLOCK (demux); } else { GST_DEBUG_OBJECT (demux, @@ -1412,7 +1412,7 @@ gst_matroska_demux_query (GstMatroskaDemux * demux, GstPad * pad, } gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, - 0, demux->segment.duration); + 0, demux->common.segment.duration); res = TRUE; } GST_OBJECT_UNLOCK (demux); @@ -1532,7 +1532,7 @@ gst_matroska_demux_move_to_entry (GstMatroskaDemux * demux, /* update the time */ gst_matroska_read_common_reset_streams (&demux->common, entry->time, TRUE); - demux->segment.last_stop = entry->time; + demux->common.segment.last_stop = entry->time; demux->seek_block = entry->block; demux->seek_first = TRUE; demux->last_stop_end = GST_CLOCK_TIME_NONE; @@ -1715,7 +1715,7 @@ gst_matroska_demux_search_pos (GstMatroskaDemux * demux, GstClockTime time) /* estimate using start and current position */ GST_OBJECT_LOCK (demux); opos = demux->common.offset - demux->common.ebml_segment_start; - otime = demux->segment.last_stop; + otime = demux->common.segment.last_stop; GST_OBJECT_UNLOCK (demux); retry: @@ -1884,7 +1884,7 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, /* copy segment, we need this because we still need the old * segment when we close the current segment. */ - memcpy (&seeksegment, &demux->segment, sizeof (GstSegment)); + memcpy (&seeksegment, &demux->common.segment, sizeof (GstSegment)); if (event) { GST_DEBUG_OBJECT (demux, "configuring seek"); @@ -1975,15 +1975,16 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, gst_event_unref (demux->close_segment); demux->close_segment = gst_event_new_new_segment (TRUE, - demux->segment.rate, GST_FORMAT_TIME, demux->segment.start, - demux->segment.last_stop, demux->segment.time); + demux->common.segment.rate, GST_FORMAT_TIME, + demux->common.segment.start, demux->common.segment.last_stop, + demux->common.segment.time); GST_OBJECT_UNLOCK (demux); } GST_OBJECT_LOCK (demux); /* now update the real segment info */ GST_DEBUG_OBJECT (demux, "Committing new seek segment"); - memcpy (&demux->segment, &seeksegment, sizeof (GstSegment)); + memcpy (&demux->common.segment, &seeksegment, sizeof (GstSegment)); GST_OBJECT_UNLOCK (demux); /* update some (segment) state */ @@ -1991,11 +1992,11 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, goto seek_error; /* notify start of new segment */ - if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) { + if (demux->common.segment.flags & GST_SEEK_FLAG_SEGMENT) { GstMessage *msg; msg = gst_message_new_segment_start (GST_OBJECT (demux), - GST_FORMAT_TIME, demux->segment.start); + GST_FORMAT_TIME, demux->common.segment.start); gst_element_post_message (GST_ELEMENT (demux), msg); } @@ -2003,8 +2004,9 @@ gst_matroska_demux_handle_seek_event (GstMatroskaDemux * demux, if (demux->new_segment) gst_event_unref (demux->new_segment); demux->new_segment = gst_event_new_new_segment_full (FALSE, - demux->segment.rate, demux->segment.applied_rate, demux->segment.format, - demux->segment.start, demux->segment.stop, demux->segment.time); + demux->common.segment.rate, demux->common.segment.applied_rate, + demux->common.segment.format, demux->common.segment.start, + demux->common.segment.stop, demux->common.segment.time); GST_OBJECT_UNLOCK (demux); /* restart our task since it might have been stopped when we did the @@ -2191,10 +2193,10 @@ gst_matroska_demux_seek_to_previous_keyframe (GstMatroskaDemux * demux) GST_DEBUG_OBJECT (demux, "segment start %" GST_TIME_FORMAT ", stream %d at %" GST_TIME_FORMAT, - GST_TIME_ARGS (demux->segment.start), stream->index, + GST_TIME_ARGS (demux->common.segment.start), stream->index, GST_TIME_ARGS (stream->from_time)); if (GST_CLOCK_TIME_IS_VALID (stream->from_time)) { - if (stream->from_time > demux->segment.start) { + if (stream->from_time > demux->common.segment.start) { GST_DEBUG_OBJECT (demux, "stream %d not finished yet", stream->index); done = FALSE; } @@ -2257,136 +2259,6 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_info (GstMatroskaDemux * demux, GstEbmlRead * ebml) -{ - GstFlowReturn ret = GST_FLOW_OK; - gdouble dur_f = -1.0; - 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 && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - /* cluster timecode */ - case GST_MATROSKA_ID_TIMECODESCALE:{ - guint64 num; - - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) - break; - - - GST_DEBUG_OBJECT (demux, "TimeCodeScale: %" G_GUINT64_FORMAT, num); - demux->common.time_scale = num; - break; - } - - case GST_MATROSKA_ID_DURATION:{ - if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK) - break; - - if (dur_f <= 0.0) { - GST_WARNING_OBJECT (demux, "Invalid duration %lf", dur_f); - break; - } - - GST_DEBUG_OBJECT (demux, "Duration: %lf", dur_f); - break; - } - - case GST_MATROSKA_ID_WRITINGAPP:{ - gchar *text; - - 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; - } - - case GST_MATROSKA_ID_MUXINGAPP:{ - gchar *text; - - 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; - } - - case GST_MATROSKA_ID_DATEUTC:{ - gint64 time; - - 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; - } - - case GST_MATROSKA_ID_TITLE:{ - gchar *text; - GstTagList *taglist; - - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) - break; - - GST_DEBUG_OBJECT (demux, "Title: %s", GST_STR_NULL (text)); - taglist = gst_tag_list_new (); - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, - NULL); - gst_matroska_read_common_found_global_tag (&demux->common, - GST_ELEMENT_CAST (demux), taglist); - g_free (text); - break; - } - - default: - ret = gst_matroska_read_common_parse_skip (&demux->common, ebml, - "SegmentInfo", id); - break; - - /* fall through */ - case GST_MATROSKA_ID_SEGMENTUID: - case GST_MATROSKA_ID_SEGMENTFILENAME: - case GST_MATROSKA_ID_PREVUID: - case GST_MATROSKA_ID_PREVFILENAME: - case GST_MATROSKA_ID_NEXTUID: - case GST_MATROSKA_ID_NEXTFILENAME: - case GST_MATROSKA_ID_SEGMENTFAMILY: - case GST_MATROSKA_ID_CHAPTERTRANSLATE: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - if (dur_f > 0.0) { - GstClockTime dur_u; - - dur_u = gst_gdouble_to_guint64 (dur_f * - gst_guint64_to_gdouble (demux->common.time_scale)); - if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64) - gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME, dur_u); - } - - DEBUG_ELEMENT_STOP (demux, ebml, "SegmentInfo", ret); - - demux->segmentinfo_parsed = TRUE; - - return ret; -} - static GstFlowReturn gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, GstEbmlRead * ebml, GstTagList * taglist) @@ -2695,7 +2567,7 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) GST_OBJECT_LOCK (demux); GST_LOG_OBJECT (demux, "Sync to %" GST_TIME_FORMAT, - GST_TIME_ARGS (demux->segment.last_stop)); + GST_TIME_ARGS (demux->common.segment.last_stop)); g_assert (demux->common.num_streams == demux->common.src->len); for (stream_nr = 0; stream_nr < demux->common.src->len; stream_nr++) { @@ -2715,15 +2587,15 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) /* does it lag? 0.5 seconds is a random threshold... * lag need only be considered if we have advanced into requested segment */ if (GST_CLOCK_TIME_IS_VALID (context->pos) && - GST_CLOCK_TIME_IS_VALID (demux->segment.last_stop) && - demux->segment.last_stop > demux->segment.start && - context->pos + (GST_SECOND / 2) < demux->segment.last_stop) { + GST_CLOCK_TIME_IS_VALID (demux->common.segment.last_stop) && + demux->common.segment.last_stop > demux->common.segment.start && + context->pos + (GST_SECOND / 2) < demux->common.segment.last_stop) { gint64 new_start; GstEvent *event; - new_start = demux->segment.last_stop - (GST_SECOND / 2); - if (GST_CLOCK_TIME_IS_VALID (demux->segment.stop)) - new_start = MIN (new_start, demux->segment.stop); + new_start = demux->common.segment.last_stop - (GST_SECOND / 2); + if (GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) + new_start = MIN (new_start, demux->common.segment.stop); GST_DEBUG_OBJECT (demux, "Synchronizing stream %d with others by advancing time " "from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT, stream_nr, @@ -2732,8 +2604,9 @@ gst_matroska_demux_sync_streams (GstMatroskaDemux * demux) context->pos = new_start; /* advance stream time */ - event = gst_event_new_new_segment (TRUE, demux->segment.rate, - demux->segment.format, new_start, demux->segment.stop, new_start); + event = gst_event_new_new_segment (TRUE, demux->common.segment.rate, + demux->common.segment.format, new_start, demux->common.segment.stop, + new_start); GST_OBJECT_UNLOCK (demux); gst_pad_push_event (context->pad, event); GST_OBJECT_LOCK (demux); @@ -3593,13 +3466,14 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, "generating segment starting at %" GST_TIME_FORMAT, GST_TIME_ARGS (lace_time)); /* pretend we seeked here */ - gst_segment_set_seek (&demux->segment, demux->segment.rate, + gst_segment_set_seek (&demux->common.segment, demux->common.segment.rate, GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL); /* now convey our segment notion downstream */ gst_matroska_demux_send_event (demux, gst_event_new_new_segment (FALSE, - demux->segment.rate, demux->segment.format, demux->segment.start, - demux->segment.stop, demux->segment.start)); + demux->common.segment.rate, demux->common.segment.format, + demux->common.segment.start, demux->common.segment.stop, + demux->common.segment.start)); demux->need_newsegment = FALSE; } @@ -3643,7 +3517,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, will instad skip until the next keyframe. */ if (GST_CLOCK_TIME_IS_VALID (lace_time) && stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && - stream->index_table && demux->segment.rate > 0.0) { + stream->index_table && demux->common.segment.rate > 0.0) { GstMatroskaTrackVideoContext *videocontext = (GstMatroskaTrackVideoContext *) stream; GstClockTime earliest_time; @@ -3652,7 +3526,7 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, GST_OBJECT_LOCK (demux); earliest_time = videocontext->earliest_time; GST_OBJECT_UNLOCK (demux); - earliest_stream_time = gst_segment_to_position (&demux->segment, + earliest_stream_time = gst_segment_to_position (&demux->common.segment, GST_FORMAT_TIME, earliest_time); if (GST_CLOCK_TIME_IS_VALID (lace_time) && @@ -3700,11 +3574,11 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, GstClockTime last_stop_end; /* Check if this stream is after segment stop */ - if (GST_CLOCK_TIME_IS_VALID (demux->segment.stop) && - lace_time >= demux->segment.stop) { + if (GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) && + lace_time >= demux->common.segment.stop) { GST_DEBUG_OBJECT (demux, "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index, - GST_TIME_ARGS (demux->segment.stop)); + GST_TIME_ARGS (demux->common.segment.stop)); gst_buffer_unref (sub); goto eos; } @@ -3718,18 +3592,18 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, /* handle gaps, e.g. non-zero start-time, or an cue index entry * that landed us with timestamps not quite intended */ GST_OBJECT_LOCK (demux); - if (GST_CLOCK_TIME_IS_VALID (demux->segment.last_stop) && - demux->segment.rate > 0.0) { + if (GST_CLOCK_TIME_IS_VALID (demux->common.segment.last_stop) && + demux->common.segment.rate > 0.0) { GstClockTimeDiff diff; GstEvent *event1, *event2; /* only send newsegments with increasing start times, * otherwise if these go back and forth downstream (sinks) increase * accumulated time and running_time */ - diff = GST_CLOCK_DIFF (demux->segment.last_stop, lace_time); - if (diff > 2 * GST_SECOND && lace_time > demux->segment.start && - (!GST_CLOCK_TIME_IS_VALID (demux->segment.stop) || - lace_time < demux->segment.stop)) { + diff = GST_CLOCK_DIFF (demux->common.segment.last_stop, lace_time); + if (diff > 2 * GST_SECOND && lace_time > demux->common.segment.start + && (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop) + || lace_time < demux->common.segment.stop)) { GST_DEBUG_OBJECT (demux, "Gap of %" G_GINT64_FORMAT " ns detected in" "stream %d (%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). " @@ -3739,29 +3613,33 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, /* send newsegment events such that the gap is not accounted in * accum time, hence running_time */ /* close ahead of gap */ - event1 = gst_event_new_new_segment (TRUE, demux->segment.rate, - demux->segment.format, demux->segment.last_stop, - demux->segment.last_stop, demux->segment.last_stop); + event1 = gst_event_new_new_segment (TRUE, + demux->common.segment.rate, + demux->common.segment.format, + demux->common.segment.last_stop, + demux->common.segment.last_stop, + demux->common.segment.last_stop); /* skip gap */ - event2 = gst_event_new_new_segment (FALSE, demux->segment.rate, - demux->segment.format, lace_time, demux->segment.stop, - lace_time); + event2 = gst_event_new_new_segment (FALSE, + demux->common.segment.rate, + demux->common.segment.format, lace_time, + demux->common.segment.stop, lace_time); GST_OBJECT_UNLOCK (demux); gst_matroska_demux_send_event (demux, event1); gst_matroska_demux_send_event (demux, event2); GST_OBJECT_LOCK (demux); /* align segment view with downstream, * prevents double-counting accum when closing segment */ - gst_segment_set_newsegment (&demux->segment, FALSE, - demux->segment.rate, demux->segment.format, lace_time, - demux->segment.stop, lace_time); - demux->segment.last_stop = lace_time; + gst_segment_set_newsegment (&demux->common.segment, FALSE, + demux->common.segment.rate, demux->common.segment.format, + lace_time, demux->common.segment.stop, lace_time); + demux->common.segment.last_stop = lace_time; } } - if (!GST_CLOCK_TIME_IS_VALID (demux->segment.last_stop) - || demux->segment.last_stop < lace_time) { - demux->segment.last_stop = lace_time; + if (!GST_CLOCK_TIME_IS_VALID (demux->common.segment.last_stop) + || demux->common.segment.last_stop < lace_time) { + demux->common.segment.last_stop = lace_time; } GST_OBJECT_UNLOCK (demux); @@ -3776,9 +3654,9 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, demux->last_stop_end = last_stop_end; GST_OBJECT_LOCK (demux); - if (demux->segment.duration == -1 || - demux->segment.duration < lace_time) { - gst_segment_set_duration (&demux->segment, GST_FORMAT_TIME, + if (demux->common.segment.duration == -1 || + demux->common.segment.duration < lace_time) { + gst_segment_set_duration (&demux->common.segment, GST_FORMAT_TIME, last_stop_end); GST_OBJECT_UNLOCK (demux); gst_element_post_message (GST_ELEMENT_CAST (demux), @@ -3837,8 +3715,9 @@ gst_matroska_demux_parse_blockgroup_or_simpleblock (GstMatroskaDemux * demux, } ret = gst_pad_push (stream->pad, sub); - if (demux->segment.rate < 0) { - if (lace_time > demux->segment.stop && ret == GST_FLOW_UNEXPECTED) { + if (demux->common.segment.rate < 0) { + if (lace_time > demux->common.segment.stop + && ret == GST_FLOW_UNEXPECTED) { /* In reverse playback we can get a GST_FLOW_UNEXPECTED when * we are at the end of the segment, so we just need to jump * back to the previous section. */ @@ -4382,9 +4261,10 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, case GST_MATROSKA_READ_STATE_SEEK: switch (id) { case GST_MATROSKA_ID_SEGMENTINFO: - if (!demux->segmentinfo_parsed) { + if (!demux->common.segmentinfo_parsed) { GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); - ret = gst_matroska_demux_parse_info (demux, &ebml); + ret = gst_matroska_read_common_parse_info (&demux->common, + GST_ELEMENT_CAST (demux), &ebml); } else { GST_READ_CHECK (gst_matroska_demux_flush (demux, read)); } @@ -4418,8 +4298,8 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, gst_matroska_demux_send_event (demux, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, 0, - (demux->segment.duration > - 0) ? demux->segment.duration : -1, 0)); + (demux->common.segment.duration > + 0) ? demux->common.segment.duration : -1, 0)); } demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = demux->common.offset; @@ -4668,7 +4548,7 @@ next: /* ERRORS */ eos: { - if (demux->segment.rate < 0.0) { + if (demux->common.segment.rate < 0.0) { ret = gst_matroska_demux_seek_to_previous_keyframe (demux); if (ret == GST_FLOW_OK) return; @@ -4690,22 +4570,22 @@ pause: /* Close the segment, i.e. update segment stop with the duration * if no stop was set */ if (GST_CLOCK_TIME_IS_VALID (demux->last_stop_end) && - !GST_CLOCK_TIME_IS_VALID (demux->segment.stop)) { + !GST_CLOCK_TIME_IS_VALID (demux->common.segment.stop)) { GstEvent *event = - gst_event_new_new_segment_full (TRUE, demux->segment.rate, - demux->segment.applied_rate, demux->segment.format, - demux->segment.start, - MAX (demux->last_stop_end, demux->segment.start), - demux->segment.time); + gst_event_new_new_segment_full (TRUE, demux->common.segment.rate, + demux->common.segment.applied_rate, demux->common.segment.format, + demux->common.segment.start, + MAX (demux->last_stop_end, demux->common.segment.start), + demux->common.segment.time); gst_matroska_demux_send_event (demux, event); } - if (demux->segment.flags & GST_SEEK_FLAG_SEGMENT) { + if (demux->common.segment.flags & GST_SEEK_FLAG_SEGMENT) { gint64 stop; /* for segment playback we need to post when (in stream time) * we stopped, this is either stop (when set) or the duration. */ - if ((stop = demux->segment.stop) == -1) + if ((stop = demux->common.segment.stop) == -1) stop = demux->last_stop_end; GST_LOG_OBJECT (demux, "Sending segment done, at end of segment"); @@ -4850,12 +4730,12 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) demux->common.offset = start; /* do not know where we are; * need to come across a cluster and generate newsegment */ - demux->segment.last_stop = GST_CLOCK_TIME_NONE; + demux->common.segment.last_stop = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; demux->need_newsegment = TRUE; /* but keep some of the upstream segment */ - demux->segment.rate = rate; + demux->common.segment.rate = rate; GST_OBJECT_UNLOCK (demux); exit: /* chain will send initial newsegment after pads have been added, @@ -4885,7 +4765,7 @@ gst_matroska_demux_handle_sink_event (GstPad * pad, GstEvent * event) GST_OBJECT_LOCK (demux); gst_matroska_read_common_reset_streams (&demux->common, GST_CLOCK_TIME_NONE, TRUE); - demux->segment.last_stop = GST_CLOCK_TIME_NONE; + demux->common.segment.last_stop = GST_CLOCK_TIME_NONE; demux->cluster_time = GST_CLOCK_TIME_NONE; demux->cluster_offset = 0; GST_OBJECT_UNLOCK (demux); diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index e9637f5ecc..8980918f1b 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -55,11 +55,6 @@ typedef struct _GstMatroskaDemux { guint num_a_streams; guint num_t_streams; - /* metadata */ - gchar *muxing_app; - gchar *writing_app; - gint64 created; - /* state */ gboolean streaming; guint level_up; @@ -68,7 +63,6 @@ typedef struct _GstMatroskaDemux { /* did we parse cues/tracks/segmentinfo already? */ gboolean tracks_parsed; - gboolean segmentinfo_parsed; gboolean attachments_parsed; GList *seek_parsed; @@ -76,7 +70,6 @@ typedef struct _GstMatroskaDemux { GArray *clusters; /* keeping track of playback position */ - GstSegment segment; gboolean segment_running; GstClockTime last_stop_end; diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index ef60d67f37..30f862b37c 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -226,8 +226,8 @@ gst_matroska_parse_init (GstMatroskaParse * parse, /* initial stream no. */ parse->common.src = NULL; - parse->writing_app = NULL; - parse->muxing_app = NULL; + parse->common.writing_app = NULL; + parse->common.muxing_app = NULL; parse->common.index = NULL; parse->common.global_tags = NULL; @@ -306,10 +306,10 @@ gst_matroska_parse_reset (GstElement * element) parse->num_v_streams = 0; /* reset media info */ - g_free (parse->writing_app); - parse->writing_app = NULL; - g_free (parse->muxing_app); - parse->muxing_app = NULL; + g_free (parse->common.writing_app); + parse->common.writing_app = NULL; + g_free (parse->common.muxing_app); + parse->common.muxing_app = NULL; /* reset indexes */ if (parse->common.index) { @@ -320,11 +320,11 @@ gst_matroska_parse_reset (GstElement * element) /* reset timers */ parse->clock = NULL; parse->common.time_scale = 1000000; - parse->created = G_MININT64; + parse->common.created = G_MININT64; parse->common.index_parsed = FALSE; parse->tracks_parsed = FALSE; - parse->segmentinfo_parsed = FALSE; + parse->common.segmentinfo_parsed = FALSE; parse->attachments_parsed = FALSE; g_list_foreach (parse->common.tags_parsed, @@ -337,7 +337,7 @@ gst_matroska_parse_reset (GstElement * element) g_list_free (parse->seek_parsed); parse->seek_parsed = NULL; - gst_segment_init (&parse->segment, GST_FORMAT_TIME); + gst_segment_init (&parse->common.segment, GST_FORMAT_TIME); parse->last_stop_end = GST_CLOCK_TIME_NONE; parse->seek_block = 0; @@ -1111,7 +1111,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, gst_query_set_position (query, GST_FORMAT_TIME, context->pos); else gst_query_set_position (query, GST_FORMAT_TIME, - parse->segment.last_stop); + parse->common.segment.last_stop); GST_OBJECT_UNLOCK (parse); } else if (format == GST_FORMAT_DEFAULT && context && context->default_duration) { @@ -1136,13 +1136,13 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, if (format == GST_FORMAT_TIME) { GST_OBJECT_LOCK (parse); gst_query_set_duration (query, GST_FORMAT_TIME, - parse->segment.duration); + parse->common.segment.duration); GST_OBJECT_UNLOCK (parse); } else if (format == GST_FORMAT_DEFAULT && context && context->default_duration) { GST_OBJECT_LOCK (parse); gst_query_set_duration (query, GST_FORMAT_DEFAULT, - parse->segment.duration / context->default_duration); + parse->common.segment.duration / context->default_duration); GST_OBJECT_UNLOCK (parse); } else { GST_DEBUG_OBJECT (parse, @@ -1165,7 +1165,7 @@ gst_matroska_parse_query (GstMatroskaParse * parse, GstPad * pad, seekable = parse->seekable; gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, - 0, parse->segment.duration); + 0, parse->common.segment.duration); res = TRUE; } break; @@ -1354,7 +1354,7 @@ gst_matroska_parse_handle_seek_event (GstMatroskaParse * parse, /* copy segment, we need this because we still need the old * segment when we close the current segment. */ - memcpy (&seeksegment, &parse->segment, sizeof (GstSegment)); + memcpy (&seeksegment, &parse->common.segment, sizeof (GstSegment)); if (event) { GST_DEBUG_OBJECT (parse, "configuring seek"); @@ -1559,136 +1559,6 @@ gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_info (GstMatroskaParse * parse, GstEbmlRead * ebml) -{ - GstFlowReturn ret = GST_FLOW_OK; - gdouble dur_f = -1.0; - guint32 id; - - DEBUG_ELEMENT_START (parse, ebml, "SegmentInfo"); - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret); - return ret; - } - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - /* cluster timecode */ - case GST_MATROSKA_ID_TIMECODESCALE:{ - guint64 num; - - if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) - break; - - - GST_DEBUG_OBJECT (parse, "TimeCodeScale: %" G_GUINT64_FORMAT, num); - parse->common.time_scale = num; - break; - } - - case GST_MATROSKA_ID_DURATION:{ - if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK) - break; - - if (dur_f <= 0.0) { - GST_WARNING_OBJECT (parse, "Invalid duration %lf", dur_f); - break; - } - - GST_DEBUG_OBJECT (parse, "Duration: %lf", dur_f); - break; - } - - case GST_MATROSKA_ID_WRITINGAPP:{ - gchar *text; - - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) - break; - - GST_DEBUG_OBJECT (parse, "WritingApp: %s", GST_STR_NULL (text)); - parse->writing_app = text; - break; - } - - case GST_MATROSKA_ID_MUXINGAPP:{ - gchar *text; - - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) - break; - - GST_DEBUG_OBJECT (parse, "MuxingApp: %s", GST_STR_NULL (text)); - parse->muxing_app = text; - break; - } - - case GST_MATROSKA_ID_DATEUTC:{ - gint64 time; - - if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK) - break; - - GST_DEBUG_OBJECT (parse, "DateUTC: %" G_GINT64_FORMAT, time); - parse->created = time; - break; - } - - case GST_MATROSKA_ID_TITLE:{ - gchar *text; - GstTagList *taglist; - - if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) - break; - - GST_DEBUG_OBJECT (parse, "Title: %s", GST_STR_NULL (text)); - taglist = gst_tag_list_new (); - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, - NULL); - gst_matroska_read_common_found_global_tag (&parse->common, - GST_ELEMENT_CAST (parse), taglist); - g_free (text); - break; - } - - default: - ret = gst_matroska_read_common_parse_skip (&parse->common, ebml, - "SegmentInfo", id); - break; - - /* fall through */ - case GST_MATROSKA_ID_SEGMENTUID: - case GST_MATROSKA_ID_SEGMENTFILENAME: - case GST_MATROSKA_ID_PREVUID: - case GST_MATROSKA_ID_PREVFILENAME: - case GST_MATROSKA_ID_NEXTUID: - case GST_MATROSKA_ID_NEXTFILENAME: - case GST_MATROSKA_ID_SEGMENTFAMILY: - case GST_MATROSKA_ID_CHAPTERTRANSLATE: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - if (dur_f > 0.0) { - GstClockTime dur_u; - - dur_u = gst_gdouble_to_guint64 (dur_f * - gst_guint64_to_gdouble (parse->common.time_scale)); - if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64) - gst_segment_set_duration (&parse->segment, GST_FORMAT_TIME, dur_u); - } - - DEBUG_ELEMENT_STOP (parse, ebml, "SegmentInfo", ret); - - parse->segmentinfo_parsed = TRUE; - - return ret; -} - static GstFlowReturn gst_matroska_parse_parse_attached_file (GstMatroskaParse * parse, GstEbmlRead * ebml, GstTagList * taglist) @@ -2237,13 +2107,14 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, "generating segment starting at %" GST_TIME_FORMAT, GST_TIME_ARGS (lace_time)); /* pretend we seeked here */ - gst_segment_set_seek (&parse->segment, parse->segment.rate, + gst_segment_set_seek (&parse->common.segment, parse->common.segment.rate, GST_FORMAT_TIME, 0, GST_SEEK_TYPE_SET, lace_time, GST_SEEK_TYPE_SET, GST_CLOCK_TIME_NONE, NULL); /* now convey our segment notion downstream */ gst_matroska_parse_send_event (parse, gst_event_new_new_segment (FALSE, - parse->segment.rate, parse->segment.format, parse->segment.start, - parse->segment.stop, parse->segment.start)); + parse->common.segment.rate, parse->common.segment.format, + parse->common.segment.start, parse->common.segment.stop, + parse->common.segment.start)); parse->need_newsegment = FALSE; } @@ -2285,7 +2156,7 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, will instad skip until the next keyframe. */ if (GST_CLOCK_TIME_IS_VALID (lace_time) && stream->type == GST_MATROSKA_TRACK_TYPE_VIDEO && - stream->index_table && parse->segment.rate > 0.0) { + stream->index_table && parse->common.segment.rate > 0.0) { GstMatroskaTrackVideoContext *videocontext = (GstMatroskaTrackVideoContext *) stream; GstClockTime earliest_time; @@ -2294,7 +2165,7 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, GST_OBJECT_LOCK (parse); earliest_time = videocontext->earliest_time; GST_OBJECT_UNLOCK (parse); - earliest_stream_time = gst_segment_to_position (&parse->segment, + earliest_stream_time = gst_segment_to_position (&parse->common.segment, GST_FORMAT_TIME, earliest_time); if (GST_CLOCK_TIME_IS_VALID (lace_time) && @@ -2342,11 +2213,11 @@ gst_matroska_parse_parse_blockgroup_or_simpleblock (GstMatroskaParse * parse, GstClockTime last_stop_end; /* Check if this stream is after segment stop */ - if (GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && - lace_time >= parse->segment.stop) { + if (GST_CLOCK_TIME_IS_VALID (parse->common.segment.stop) && + lace_time >= parse->common.segment.stop) { GST_DEBUG_OBJECT (parse, "Stream %d after segment stop %" GST_TIME_FORMAT, stream->index, - GST_TIME_ARGS (parse->segment.stop)); + GST_TIME_ARGS (parse->common.segment.stop)); gst_buffer_unref (sub); goto eos; } @@ -3014,8 +2885,9 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id, switch (id) { case GST_MATROSKA_ID_SEGMENTINFO: GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml)); - if (!parse->segmentinfo_parsed) { - ret = gst_matroska_parse_parse_info (parse, &ebml); + if (!parse->common.segmentinfo_parsed) { + ret = gst_matroska_read_common_parse_info (&parse->common, + GST_ELEMENT_CAST (parse), &ebml); } gst_matroska_parse_accumulate_streamheader (parse, ebml.buf); break; @@ -3475,12 +3347,12 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) parse->common.offset = start; /* do not know where we are; * need to come across a cluster and generate newsegment */ - parse->segment.last_stop = GST_CLOCK_TIME_NONE; + parse->common.segment.last_stop = GST_CLOCK_TIME_NONE; parse->cluster_time = GST_CLOCK_TIME_NONE; parse->cluster_offset = 0; parse->need_newsegment = TRUE; /* but keep some of the upstream segment */ - parse->segment.rate = rate; + parse->common.segment.rate = rate; exit: /* chain will send initial newsegment after pads have been added, * or otherwise come up with one */ @@ -3510,7 +3382,7 @@ gst_matroska_parse_handle_sink_event (GstPad * pad, GstEvent * event) gst_matroska_read_common_reset_streams (&parse->common, GST_CLOCK_TIME_NONE, TRUE); GST_OBJECT_UNLOCK (parse); - parse->segment.last_stop = GST_CLOCK_TIME_NONE; + parse->common.segment.last_stop = GST_CLOCK_TIME_NONE; parse->cluster_time = GST_CLOCK_TIME_NONE; parse->cluster_offset = 0; /* fall-through */ diff --git a/gst/matroska/matroska-parse.h b/gst/matroska/matroska-parse.h index 453510aeba..db62a8a8d6 100644 --- a/gst/matroska/matroska-parse.h +++ b/gst/matroska/matroska-parse.h @@ -60,11 +60,6 @@ typedef struct _GstMatroskaParse { gboolean pushed_headers; GstClockTime last_timestamp; - /* metadata */ - gchar *muxing_app; - gchar *writing_app; - gint64 created; - /* state */ //gboolean streaming; guint level_up; @@ -73,12 +68,10 @@ typedef struct _GstMatroskaParse { /* did we parse cues/tracks/segmentinfo already? */ gboolean tracks_parsed; - gboolean segmentinfo_parsed; gboolean attachments_parsed; GList *seek_parsed; /* keeping track of playback position */ - GstSegment segment; gboolean segment_running; GstClockTime last_stop_end; diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index f7cc0cf834..af6b696cdf 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -953,6 +953,136 @@ gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, return ret; } +GstFlowReturn +gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common, + GstElement * el, GstEbmlRead * ebml) +{ + GstFlowReturn ret = GST_FLOW_OK; + gdouble dur_f = -1.0; + guint32 id; + + DEBUG_ELEMENT_START (common, ebml, "SegmentInfo"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret); + return ret; + } + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + /* cluster timecode */ + case GST_MATROSKA_ID_TIMECODESCALE:{ + guint64 num; + + if ((ret = gst_ebml_read_uint (ebml, &id, &num)) != GST_FLOW_OK) + break; + + + GST_DEBUG_OBJECT (common, "TimeCodeScale: %" G_GUINT64_FORMAT, num); + common->time_scale = num; + break; + } + + case GST_MATROSKA_ID_DURATION:{ + if ((ret = gst_ebml_read_float (ebml, &id, &dur_f)) != GST_FLOW_OK) + break; + + if (dur_f <= 0.0) { + GST_WARNING_OBJECT (common, "Invalid duration %lf", dur_f); + break; + } + + GST_DEBUG_OBJECT (common, "Duration: %lf", dur_f); + break; + } + + case GST_MATROSKA_ID_WRITINGAPP:{ + gchar *text; + + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (common, "WritingApp: %s", GST_STR_NULL (text)); + common->writing_app = text; + break; + } + + case GST_MATROSKA_ID_MUXINGAPP:{ + gchar *text; + + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (common, "MuxingApp: %s", GST_STR_NULL (text)); + common->muxing_app = text; + break; + } + + case GST_MATROSKA_ID_DATEUTC:{ + gint64 time; + + if ((ret = gst_ebml_read_date (ebml, &id, &time)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (common, "DateUTC: %" G_GINT64_FORMAT, time); + common->created = time; + break; + } + + case GST_MATROSKA_ID_TITLE:{ + gchar *text; + GstTagList *taglist; + + if ((ret = gst_ebml_read_utf8 (ebml, &id, &text)) != GST_FLOW_OK) + break; + + GST_DEBUG_OBJECT (common, "Title: %s", GST_STR_NULL (text)); + taglist = gst_tag_list_new (); + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_TITLE, text, + NULL); + gst_matroska_read_common_found_global_tag (common, el, taglist); + g_free (text); + break; + } + + default: + ret = gst_matroska_read_common_parse_skip (common, ebml, + "SegmentInfo", id); + break; + + /* fall through */ + case GST_MATROSKA_ID_SEGMENTUID: + case GST_MATROSKA_ID_SEGMENTFILENAME: + case GST_MATROSKA_ID_PREVUID: + case GST_MATROSKA_ID_PREVFILENAME: + case GST_MATROSKA_ID_NEXTUID: + case GST_MATROSKA_ID_NEXTFILENAME: + case GST_MATROSKA_ID_SEGMENTFAMILY: + case GST_MATROSKA_ID_CHAPTERTRANSLATE: + ret = gst_ebml_read_skip (ebml); + break; + } + } + + if (dur_f > 0.0) { + GstClockTime dur_u; + + dur_u = gst_gdouble_to_guint64 (dur_f * + gst_guint64_to_gdouble (common->time_scale)); + if (GST_CLOCK_TIME_IS_VALID (dur_u) && dur_u <= G_MAXINT64) + gst_segment_set_duration (&common->segment, GST_FORMAT_TIME, dur_u); + } + + DEBUG_ELEMENT_STOP (common, ebml, "SegmentInfo", ret); + + common->segmentinfo_parsed = TRUE; + + return ret; +} + static GstFlowReturn gst_matroska_read_common_parse_metadata_id_simple_tag (GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList ** p_taglist) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index f1b96840d6..bdfdd35b68 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -49,11 +49,17 @@ typedef struct _GstMatroskaReadCommon { GPtrArray *src; guint num_streams; + /* metadata */ + gchar *muxing_app; + gchar *writing_app; + gint64 created; + /* state */ GstMatroskaReadState state; /* did we parse cues/tracks/segmentinfo already? */ gboolean index_parsed; + gboolean segmentinfo_parsed; GList *tags_parsed; /* start-of-segment */ @@ -65,6 +71,9 @@ typedef struct _GstMatroskaReadCommon { /* timescale in the file */ guint64 time_scale; + /* keeping track of playback position */ + GstSegment segment; + GstTagList *global_tags; /* pull mode caching */ @@ -92,6 +101,8 @@ GstMatroskaTrackContext * gst_matroska_read_common_get_seek_track ( GstMatroskaReadCommon * common, GstMatroskaTrackContext * track); GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); +GstFlowReturn gst_matroska_read_common_parse_info (GstMatroskaReadCommon * + common, GstElement * el, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * From d8a8326d7c5fe3fb3041d3916494b482e1b6a47d Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Mon, 6 Jun 2011 12:43:14 +0530 Subject: [PATCH 09/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_attached_file https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 159 +--------------------------- gst/matroska/matroska-parse.c | 159 +--------------------------- gst/matroska/matroska-read-common.c | 158 +++++++++++++++++++++++++++ gst/matroska/matroska-read-common.h | 2 + 4 files changed, 164 insertions(+), 314 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 4b2f1604fb..0d08a1c4f4 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -61,8 +61,6 @@ #include -#include - #include #include "matroska-demux.h" @@ -2259,160 +2257,6 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_attached_file (GstMatroskaDemux * demux, - GstEbmlRead * ebml, GstTagList * taglist) -{ - guint32 id; - GstFlowReturn ret; - gchar *description = NULL; - gchar *filename = NULL; - gchar *mimetype = NULL; - guint8 *data = NULL; - guint64 datalen = 0; - - DEBUG_ELEMENT_START (demux, ebml, "AttachedFile"); - - 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 && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - /* read all sub-entries */ - - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_FILEDESCRIPTION: - if (description) { - GST_WARNING_OBJECT (demux, "FileDescription can only appear once"); - break; - } - - 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) { - GST_WARNING_OBJECT (demux, "FileName can only appear once"); - break; - } - - 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) { - GST_WARNING_OBJECT (demux, "FileMimeType can only appear once"); - break; - } - - 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) { - GST_WARNING_OBJECT (demux, "FileData can only appear once"); - break; - } - - ret = gst_ebml_read_binary (ebml, &id, &data, &datalen); - GST_DEBUG_OBJECT (demux, "FileData of size %" G_GUINT64_FORMAT, - datalen); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&demux->common, ebml, - "AttachedFile", id); - break; - case GST_MATROSKA_ID_FILEUID: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (demux, ebml, "AttachedFile", ret); - - if (filename && mimetype && data && datalen > 0) { - GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; - GstBuffer *tagbuffer = NULL; - GstCaps *caps; - gchar *filename_lc = g_utf8_strdown (filename, -1); - - GST_DEBUG_OBJECT (demux, "Creating tag for attachment with filename '%s', " - "mimetype '%s', description '%s', size %" G_GUINT64_FORMAT, filename, - mimetype, GST_STR_NULL (description), datalen); - - /* TODO: better heuristics for different image types */ - if (strstr (filename_lc, "cover")) { - if (strstr (filename_lc, "back")) - 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/") || - 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); - - /* First try to create an image tag buffer from this */ - if (image_type != GST_TAG_IMAGE_TYPE_NONE) { - tagbuffer = - gst_tag_image_data_to_image_buffer (data, datalen, image_type); - - if (!tagbuffer) - image_type = GST_TAG_IMAGE_TYPE_NONE; - } - - /* if this failed create an attachment buffer */ - if (!tagbuffer) { - tagbuffer = gst_buffer_new_and_alloc (datalen); - - memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen); - GST_BUFFER_SIZE (tagbuffer) = datalen; - - caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); - if (caps == NULL) - caps = gst_caps_new_simple (mimetype, NULL); - gst_buffer_set_caps (tagbuffer, caps); - gst_caps_unref (caps); - } - - /* Set filename and description on the caps */ - caps = GST_BUFFER_CAPS (tagbuffer); - gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); - if (description) - gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, - NULL); - - 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) - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer, - NULL); - else - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT, - tagbuffer, NULL); - } - - g_free (filename); - g_free (mimetype); - g_free (data); - g_free (description); - - return ret; -} - static GstFlowReturn gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, GstEbmlRead * ebml) @@ -2436,7 +2280,8 @@ gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, switch (id) { case GST_MATROSKA_ID_ATTACHEDFILE: - ret = gst_matroska_demux_parse_attached_file (demux, ebml, taglist); + ret = gst_matroska_read_common_parse_attached_file (&demux->common, + ebml, taglist); break; default: diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 30f862b37c..7534ed0ed7 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -61,8 +61,6 @@ #include -#include - #include #include "matroska-parse.h" @@ -1559,160 +1557,6 @@ gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_attached_file (GstMatroskaParse * parse, - GstEbmlRead * ebml, GstTagList * taglist) -{ - guint32 id; - GstFlowReturn ret; - gchar *description = NULL; - gchar *filename = NULL; - gchar *mimetype = NULL; - guint8 *data = NULL; - guint64 datalen = 0; - - DEBUG_ELEMENT_START (parse, ebml, "AttachedFile"); - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret); - return ret; - } - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - /* read all sub-entries */ - - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_FILEDESCRIPTION: - if (description) { - GST_WARNING_OBJECT (parse, "FileDescription can only appear once"); - break; - } - - ret = gst_ebml_read_utf8 (ebml, &id, &description); - GST_DEBUG_OBJECT (parse, "FileDescription: %s", - GST_STR_NULL (description)); - break; - case GST_MATROSKA_ID_FILENAME: - if (filename) { - GST_WARNING_OBJECT (parse, "FileName can only appear once"); - break; - } - - ret = gst_ebml_read_utf8 (ebml, &id, &filename); - - GST_DEBUG_OBJECT (parse, "FileName: %s", GST_STR_NULL (filename)); - break; - case GST_MATROSKA_ID_FILEMIMETYPE: - if (mimetype) { - GST_WARNING_OBJECT (parse, "FileMimeType can only appear once"); - break; - } - - ret = gst_ebml_read_ascii (ebml, &id, &mimetype); - GST_DEBUG_OBJECT (parse, "FileMimeType: %s", GST_STR_NULL (mimetype)); - break; - case GST_MATROSKA_ID_FILEDATA: - if (data) { - GST_WARNING_OBJECT (parse, "FileData can only appear once"); - break; - } - - ret = gst_ebml_read_binary (ebml, &id, &data, &datalen); - GST_DEBUG_OBJECT (parse, "FileData of size %" G_GUINT64_FORMAT, - datalen); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&parse->common, ebml, - "AttachedFile", id); - break; - case GST_MATROSKA_ID_FILEUID: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (parse, ebml, "AttachedFile", ret); - - if (filename && mimetype && data && datalen > 0) { - GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; - GstBuffer *tagbuffer = NULL; - GstCaps *caps; - gchar *filename_lc = g_utf8_strdown (filename, -1); - - GST_DEBUG_OBJECT (parse, "Creating tag for attachment with filename '%s', " - "mimetype '%s', description '%s', size %" G_GUINT64_FORMAT, filename, - mimetype, GST_STR_NULL (description), datalen); - - /* TODO: better heuristics for different image types */ - if (strstr (filename_lc, "cover")) { - if (strstr (filename_lc, "back")) - 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/") || - 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); - - /* First try to create an image tag buffer from this */ - if (image_type != GST_TAG_IMAGE_TYPE_NONE) { - tagbuffer = - gst_tag_image_data_to_image_buffer (data, datalen, image_type); - - if (!tagbuffer) - image_type = GST_TAG_IMAGE_TYPE_NONE; - } - - /* if this failed create an attachment buffer */ - if (!tagbuffer) { - tagbuffer = gst_buffer_new_and_alloc (datalen); - - memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen); - GST_BUFFER_SIZE (tagbuffer) = datalen; - - caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); - if (caps == NULL) - caps = gst_caps_new_simple (mimetype, NULL); - gst_buffer_set_caps (tagbuffer, caps); - gst_caps_unref (caps); - } - - /* Set filename and description on the caps */ - caps = GST_BUFFER_CAPS (tagbuffer); - gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); - if (description) - gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, - NULL); - - GST_DEBUG_OBJECT (parse, - "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); - - /* and append to the tag list */ - if (image_type != GST_TAG_IMAGE_TYPE_NONE) - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer, - NULL); - else - gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT, - tagbuffer, NULL); - } - - g_free (filename); - g_free (mimetype); - g_free (data); - g_free (description); - - return ret; -} - static GstFlowReturn gst_matroska_parse_parse_attachments (GstMatroskaParse * parse, GstEbmlRead * ebml) @@ -1736,7 +1580,8 @@ gst_matroska_parse_parse_attachments (GstMatroskaParse * parse, switch (id) { case GST_MATROSKA_ID_ATTACHEDFILE: - ret = gst_matroska_parse_parse_attached_file (parse, ebml, taglist); + ret = gst_matroska_read_common_parse_attached_file (&parse->common, + ebml, taglist); break; default: diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index af6b696cdf..bbe3e74014 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -36,6 +36,9 @@ #include #endif +#include +#include + #include "lzo.h" #include "ebml-read.h" @@ -484,6 +487,161 @@ gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common, return gst_ebml_read_skip (ebml); } +GstFlowReturn +gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common, + GstEbmlRead * ebml, GstTagList * taglist) +{ + guint32 id; + GstFlowReturn ret; + gchar *description = NULL; + gchar *filename = NULL; + gchar *mimetype = NULL; + guint8 *data = NULL; + guint64 datalen = 0; + + DEBUG_ELEMENT_START (common, ebml, "AttachedFile"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret); + return ret; + } + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + /* read all sub-entries */ + + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + case GST_MATROSKA_ID_FILEDESCRIPTION: + if (description) { + GST_WARNING_OBJECT (common, "FileDescription can only appear once"); + break; + } + + ret = gst_ebml_read_utf8 (ebml, &id, &description); + GST_DEBUG_OBJECT (common, "FileDescription: %s", + GST_STR_NULL (description)); + break; + case GST_MATROSKA_ID_FILENAME: + if (filename) { + GST_WARNING_OBJECT (common, "FileName can only appear once"); + break; + } + + ret = gst_ebml_read_utf8 (ebml, &id, &filename); + + GST_DEBUG_OBJECT (common, "FileName: %s", GST_STR_NULL (filename)); + break; + case GST_MATROSKA_ID_FILEMIMETYPE: + if (mimetype) { + GST_WARNING_OBJECT (common, "FileMimeType can only appear once"); + break; + } + + ret = gst_ebml_read_ascii (ebml, &id, &mimetype); + GST_DEBUG_OBJECT (common, "FileMimeType: %s", GST_STR_NULL (mimetype)); + break; + case GST_MATROSKA_ID_FILEDATA: + if (data) { + GST_WARNING_OBJECT (common, "FileData can only appear once"); + break; + } + + ret = gst_ebml_read_binary (ebml, &id, &data, &datalen); + GST_DEBUG_OBJECT (common, "FileData of size %" G_GUINT64_FORMAT, + datalen); + break; + + default: + ret = gst_matroska_read_common_parse_skip (common, ebml, + "AttachedFile", id); + break; + case GST_MATROSKA_ID_FILEUID: + ret = gst_ebml_read_skip (ebml); + break; + } + } + + DEBUG_ELEMENT_STOP (common, ebml, "AttachedFile", ret); + + if (filename && mimetype && data && datalen > 0) { + GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE; + GstBuffer *tagbuffer = NULL; + GstCaps *caps; + gchar *filename_lc = g_utf8_strdown (filename, -1); + + GST_DEBUG_OBJECT (common, "Creating tag for attachment with " + "filename '%s', mimetype '%s', description '%s', " + "size %" G_GUINT64_FORMAT, filename, mimetype, + GST_STR_NULL (description), datalen); + + /* TODO: better heuristics for different image types */ + if (strstr (filename_lc, "cover")) { + if (strstr (filename_lc, "back")) + 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/") || + 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); + + /* First try to create an image tag buffer from this */ + if (image_type != GST_TAG_IMAGE_TYPE_NONE) { + tagbuffer = + gst_tag_image_data_to_image_buffer (data, datalen, image_type); + + if (!tagbuffer) + image_type = GST_TAG_IMAGE_TYPE_NONE; + } + + /* if this failed create an attachment buffer */ + if (!tagbuffer) { + tagbuffer = gst_buffer_new_and_alloc (datalen); + + memcpy (GST_BUFFER_DATA (tagbuffer), data, datalen); + GST_BUFFER_SIZE (tagbuffer) = datalen; + + caps = gst_type_find_helper_for_buffer (NULL, tagbuffer, NULL); + if (caps == NULL) + caps = gst_caps_new_simple (mimetype, NULL); + gst_buffer_set_caps (tagbuffer, caps); + gst_caps_unref (caps); + } + + /* Set filename and description on the caps */ + caps = GST_BUFFER_CAPS (tagbuffer); + gst_caps_set_simple (caps, "filename", G_TYPE_STRING, filename, NULL); + if (description) + gst_caps_set_simple (caps, "description", G_TYPE_STRING, description, + NULL); + + GST_DEBUG_OBJECT (common, + "Created attachment buffer with caps: %" GST_PTR_FORMAT, caps); + + /* and append to the tag list */ + if (image_type != GST_TAG_IMAGE_TYPE_NONE) + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_IMAGE, tagbuffer, + NULL); + else + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_TAG_ATTACHMENT, + tagbuffer, NULL); + } + + g_free (filename); + g_free (mimetype); + g_free (data); + g_free (description); + + return ret; +} + GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index bdfdd35b68..4fb489c613 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -103,6 +103,8 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common, GstElement * el, GstEbmlRead * ebml); +GstFlowReturn gst_matroska_read_common_parse_attached_file ( + GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList * taglist); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * From 05778b85d59acbb8c90f0d9926ad19918dd5a426 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Mon, 6 Jun 2011 14:47:27 +0530 Subject: [PATCH 10/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_attachments https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 56 +++-------------------------- gst/matroska/matroska-demux.h | 1 - gst/matroska/matroska-parse.c | 56 +++-------------------------- gst/matroska/matroska-parse.h | 1 - gst/matroska/matroska-read-common.c | 50 +++++++++++++++++++++++++- gst/matroska/matroska-read-common.h | 5 +-- 6 files changed, 60 insertions(+), 109 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 0d08a1c4f4..30767bf8ac 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -400,7 +400,7 @@ gst_matroska_demux_reset (GstElement * element) demux->common.index_parsed = FALSE; demux->tracks_parsed = FALSE; demux->common.segmentinfo_parsed = FALSE; - demux->attachments_parsed = FALSE; + demux->common.attachments_parsed = FALSE; g_list_foreach (demux->common.tags_parsed, (GFunc) gst_matroska_demux_free_parsed_el, NULL); @@ -2257,55 +2257,6 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_attachments (GstMatroskaDemux * demux, - GstEbmlRead * ebml) -{ - guint32 id; - GstFlowReturn ret = GST_FLOW_OK; - GstTagList *taglist; - - DEBUG_ELEMENT_START (demux, ebml, "Attachments"); - - 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 && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_ATTACHEDFILE: - ret = gst_matroska_read_common_parse_attached_file (&demux->common, - ebml, taglist); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&demux->common, ebml, - "Attachments", id); - break; - } - } - DEBUG_ELEMENT_STOP (demux, ebml, "Attachments", ret); - - if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) { - GST_DEBUG_OBJECT (demux, "Storing attachment tags"); - gst_matroska_read_common_found_global_tag (&demux->common, - GST_ELEMENT_CAST (demux), taglist); - } else { - GST_DEBUG_OBJECT (demux, "No valid attachments found"); - gst_tag_list_free (taglist); - } - - demux->attachments_parsed = TRUE; - - return ret; -} - static GstFlowReturn gst_matroska_demux_parse_chapters (GstMatroskaDemux * demux, GstEbmlRead * ebml) { @@ -4207,9 +4158,10 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, DEBUG_ELEMENT_STOP (demux, &ebml, "SimpleBlock", ret); break; case GST_MATROSKA_ID_ATTACHMENTS: - if (!demux->attachments_parsed) { + if (!demux->common.attachments_parsed) { GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); - ret = gst_matroska_demux_parse_attachments (demux, &ebml); + ret = gst_matroska_read_common_parse_attachments (&demux->common, + GST_ELEMENT_CAST (demux), &ebml); } else { GST_READ_CHECK (gst_matroska_demux_flush (demux, read)); } diff --git a/gst/matroska/matroska-demux.h b/gst/matroska/matroska-demux.h index 8980918f1b..c9ab2fc8e1 100644 --- a/gst/matroska/matroska-demux.h +++ b/gst/matroska/matroska-demux.h @@ -63,7 +63,6 @@ typedef struct _GstMatroskaDemux { /* did we parse cues/tracks/segmentinfo already? */ gboolean tracks_parsed; - gboolean attachments_parsed; GList *seek_parsed; /* cluster positions (optional) */ diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 7534ed0ed7..20e1248282 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -323,7 +323,7 @@ gst_matroska_parse_reset (GstElement * element) parse->common.index_parsed = FALSE; parse->tracks_parsed = FALSE; parse->common.segmentinfo_parsed = FALSE; - parse->attachments_parsed = FALSE; + parse->common.attachments_parsed = FALSE; g_list_foreach (parse->common.tags_parsed, (GFunc) gst_matroska_parse_free_parsed_el, NULL); @@ -1557,55 +1557,6 @@ gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_attachments (GstMatroskaParse * parse, - GstEbmlRead * ebml) -{ - guint32 id; - GstFlowReturn ret = GST_FLOW_OK; - GstTagList *taglist; - - DEBUG_ELEMENT_START (parse, ebml, "Attachments"); - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret); - return ret; - } - - taglist = gst_tag_list_new (); - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - case GST_MATROSKA_ID_ATTACHEDFILE: - ret = gst_matroska_read_common_parse_attached_file (&parse->common, - ebml, taglist); - break; - - default: - ret = gst_matroska_read_common_parse_skip (&parse->common, ebml, - "Attachments", id); - break; - } - } - DEBUG_ELEMENT_STOP (parse, ebml, "Attachments", ret); - - if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) { - GST_DEBUG_OBJECT (parse, "Storing attachment tags"); - gst_matroska_read_common_found_global_tag (&parse->common, - GST_ELEMENT_CAST (parse), taglist); - } else { - GST_DEBUG_OBJECT (parse, "No valid attachments found"); - gst_tag_list_free (taglist); - } - - parse->attachments_parsed = TRUE; - - return ret; -} - static GstFlowReturn gst_matroska_parse_parse_chapters (GstMatroskaParse * parse, GstEbmlRead * ebml) { @@ -2821,8 +2772,9 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id, break; case GST_MATROSKA_ID_ATTACHMENTS: GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml)); - if (!parse->attachments_parsed) { - ret = gst_matroska_parse_parse_attachments (parse, &ebml); + if (!parse->common.attachments_parsed) { + ret = gst_matroska_read_common_parse_attachments (&parse->common, + GST_ELEMENT_CAST (parse), &ebml); } gst_matroska_parse_output (parse, ebml.buf, FALSE); break; diff --git a/gst/matroska/matroska-parse.h b/gst/matroska/matroska-parse.h index db62a8a8d6..a447e776cd 100644 --- a/gst/matroska/matroska-parse.h +++ b/gst/matroska/matroska-parse.h @@ -68,7 +68,6 @@ typedef struct _GstMatroskaParse { /* did we parse cues/tracks/segmentinfo already? */ gboolean tracks_parsed; - gboolean attachments_parsed; GList *seek_parsed; /* keeping track of playback position */ diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index bbe3e74014..abf9e068c3 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -487,7 +487,7 @@ gst_matroska_read_common_parse_skip (GstMatroskaReadCommon * common, return gst_ebml_read_skip (ebml); } -GstFlowReturn +static GstFlowReturn gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList * taglist) { @@ -642,6 +642,54 @@ gst_matroska_read_common_parse_attached_file (GstMatroskaReadCommon * common, return ret; } +GstFlowReturn +gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common, + GstElement * el, GstEbmlRead * ebml) +{ + guint32 id; + GstFlowReturn ret = GST_FLOW_OK; + GstTagList *taglist; + + DEBUG_ELEMENT_START (common, ebml, "Attachments"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret); + return ret; + } + + taglist = gst_tag_list_new (); + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + case GST_MATROSKA_ID_ATTACHEDFILE: + ret = gst_matroska_read_common_parse_attached_file (common, ebml, + taglist); + break; + + default: + ret = gst_matroska_read_common_parse_skip (common, ebml, + "Attachments", id); + break; + } + } + DEBUG_ELEMENT_STOP (common, ebml, "Attachments", ret); + + if (gst_structure_n_fields (GST_STRUCTURE (taglist)) > 0) { + GST_DEBUG_OBJECT (common, "Storing attachment tags"); + gst_matroska_read_common_found_global_tag (common, el, taglist); + } else { + GST_DEBUG_OBJECT (common, "No valid attachments found"); + gst_tag_list_free (taglist); + } + + common->attachments_parsed = TRUE; + + return ret; +} + GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index 4fb489c613..ef1e19f63d 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -60,6 +60,7 @@ typedef struct _GstMatroskaReadCommon { /* did we parse cues/tracks/segmentinfo already? */ gboolean index_parsed; gboolean segmentinfo_parsed; + gboolean attachments_parsed; GList *tags_parsed; /* start-of-segment */ @@ -103,8 +104,8 @@ GstFlowReturn gst_matroska_read_common_parse_index (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common, GstElement * el, GstEbmlRead * ebml); -GstFlowReturn gst_matroska_read_common_parse_attached_file ( - GstMatroskaReadCommon * common, GstEbmlRead * ebml, GstTagList * taglist); +GstFlowReturn gst_matroska_read_common_parse_attachments ( + GstMatroskaReadCommon * common, GstElement * el, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon * From 9175a903fb201cb74f996d7a2c28b1dc497cc720 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Mon, 6 Jun 2011 18:21:04 +0530 Subject: [PATCH 11/11] matroska: refactor code common to matroskademux and matroskaparse Move the following function to matroska-read-common.[ch] from matroska-demux.c and matroska-parse.c: - gst_matroska_{demux,parse}_parse_chapters https://bugzilla.gnome.org/show_bug.cgi?id=650877 --- gst/matroska/matroska-demux.c | 34 +---------------------------- gst/matroska/matroska-parse.c | 34 +---------------------------- gst/matroska/matroska-read-common.c | 33 ++++++++++++++++++++++++++++ gst/matroska/matroska-read-common.h | 2 ++ 4 files changed, 37 insertions(+), 66 deletions(-) diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index 30767bf8ac..a6fb32f138 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -2257,38 +2257,6 @@ gst_matroska_demux_parse_tracks (GstMatroskaDemux * demux, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_demux_parse_chapters (GstMatroskaDemux * demux, GstEbmlRead * ebml) -{ - guint32 id; - GstFlowReturn ret = GST_FLOW_OK; - - GST_WARNING_OBJECT (demux, "Parsing of chapters not implemented yet"); - - /* TODO: implement parsing of chapters */ - - 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 && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - default: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (demux, ebml, "Chapters", ret); - return ret; -} - /* * Read signed/unsigned "EBML" numbers. * Return: number of bytes processed. @@ -4173,7 +4141,7 @@ gst_matroska_demux_parse_id (GstMatroskaDemux * demux, guint32 id, break; case GST_MATROSKA_ID_CHAPTERS: GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); - ret = gst_matroska_demux_parse_chapters (demux, &ebml); + ret = gst_matroska_read_common_parse_chapters (&demux->common, &ebml); break; case GST_MATROSKA_ID_SEEKHEAD: GST_READ_CHECK (gst_matroska_demux_take (demux, read, &ebml)); diff --git a/gst/matroska/matroska-parse.c b/gst/matroska/matroska-parse.c index 20e1248282..8f8da64fcc 100644 --- a/gst/matroska/matroska-parse.c +++ b/gst/matroska/matroska-parse.c @@ -1557,38 +1557,6 @@ gst_matroska_parse_parse_tracks (GstMatroskaParse * parse, GstEbmlRead * ebml) return ret; } -static GstFlowReturn -gst_matroska_parse_parse_chapters (GstMatroskaParse * parse, GstEbmlRead * ebml) -{ - guint32 id; - GstFlowReturn ret = GST_FLOW_OK; - - GST_WARNING_OBJECT (parse, "Parsing of chapters not implemented yet"); - - /* TODO: implement parsing of chapters */ - - DEBUG_ELEMENT_START (parse, ebml, "Chapters"); - - if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { - DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret); - return ret; - } - - while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { - if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) - break; - - switch (id) { - default: - ret = gst_ebml_read_skip (ebml); - break; - } - } - - DEBUG_ELEMENT_STOP (parse, ebml, "Chapters", ret); - return ret; -} - /* * Read signed/unsigned "EBML" numbers. * Return: number of bytes processed. @@ -2786,7 +2754,7 @@ gst_matroska_parse_parse_id (GstMatroskaParse * parse, guint32 id, break; case GST_MATROSKA_ID_CHAPTERS: GST_READ_CHECK (gst_matroska_parse_take (parse, read, &ebml)); - ret = gst_matroska_parse_parse_chapters (parse, &ebml); + ret = gst_matroska_read_common_parse_chapters (&parse->common, &ebml); gst_matroska_parse_output (parse, ebml.buf, FALSE); break; case GST_MATROSKA_ID_SEEKHEAD: diff --git a/gst/matroska/matroska-read-common.c b/gst/matroska/matroska-read-common.c index abf9e068c3..fa678fdb0e 100644 --- a/gst/matroska/matroska-read-common.c +++ b/gst/matroska/matroska-read-common.c @@ -690,6 +690,39 @@ gst_matroska_read_common_parse_attachments (GstMatroskaReadCommon * common, return ret; } +GstFlowReturn +gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * common, + GstEbmlRead * ebml) +{ + guint32 id; + GstFlowReturn ret = GST_FLOW_OK; + + GST_WARNING_OBJECT (common, "Parsing of chapters not implemented yet"); + + /* TODO: implement parsing of chapters */ + + DEBUG_ELEMENT_START (common, ebml, "Chapters"); + + if ((ret = gst_ebml_read_master (ebml, &id)) != GST_FLOW_OK) { + DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret); + return ret; + } + + while (ret == GST_FLOW_OK && gst_ebml_read_has_remaining (ebml, 1, TRUE)) { + if ((ret = gst_ebml_peek_id (ebml, &id)) != GST_FLOW_OK) + break; + + switch (id) { + default: + ret = gst_ebml_read_skip (ebml); + break; + } + } + + DEBUG_ELEMENT_STOP (common, ebml, "Chapters", ret); + return ret; +} + GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml) diff --git a/gst/matroska/matroska-read-common.h b/gst/matroska/matroska-read-common.h index ef1e19f63d..68b0f6c34f 100644 --- a/gst/matroska/matroska-read-common.h +++ b/gst/matroska/matroska-read-common.h @@ -106,6 +106,8 @@ GstFlowReturn gst_matroska_read_common_parse_info (GstMatroskaReadCommon * common, GstElement * el, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_attachments ( GstMatroskaReadCommon * common, GstElement * el, GstEbmlRead * ebml); +GstFlowReturn gst_matroska_read_common_parse_chapters (GstMatroskaReadCommon * + common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_header (GstMatroskaReadCommon * common, GstEbmlRead * ebml); GstFlowReturn gst_matroska_read_common_parse_metadata (GstMatroskaReadCommon *