From 75dee31b0d8d04cb5f5565d5ee111974b6de44de Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 2 Feb 2015 13:35:59 -0300 Subject: [PATCH] qtdemux: parse stream tags Keep global and stream tags separately and parse the udta node that can be found under the trak atom. The udta will contain stream specific tags and will be pushed as such https://bugzilla.gnome.org/show_bug.cgi?id=692473 --- gst/isomp4/qtdemux.c | 253 ++++++++++++++++++++++--------------------- 1 file changed, 127 insertions(+), 126 deletions(-) diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index 7e20428e78..baffc76a2b 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -466,6 +466,8 @@ static gboolean qtdemux_parse_moov (GstQTDemux * qtdemux, static gboolean qtdemux_parse_node (GstQTDemux * qtdemux, GNode * node, const guint8 * buffer, guint length); static gboolean qtdemux_parse_tree (GstQTDemux * qtdemux); +static void qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, + GNode * udta); static void gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream, GNode * esds, GstTagList * list); @@ -2247,20 +2249,23 @@ qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length) } static void -qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist) +qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist, + GstTagList * xmptaglist) { /* Strip out bogus fields */ - if (taglist) { - gst_tag_list_remove_tag (taglist, GST_TAG_VIDEO_CODEC); + if (xmptaglist) { + if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL) { + gst_tag_list_remove_tag (xmptaglist, GST_TAG_VIDEO_CODEC); + gst_tag_list_remove_tag (xmptaglist, GST_TAG_AUDIO_CODEC); + } else { + gst_tag_list_remove_tag (xmptaglist, GST_TAG_CONTAINER_FORMAT); + } - GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, taglist); + GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, xmptaglist); - if (qtdemux->tag_list) { - /* prioritize native tags using _KEEP mode */ - gst_tag_list_insert (qtdemux->tag_list, taglist, GST_TAG_MERGE_KEEP); - gst_tag_list_unref (taglist); - } else - qtdemux->tag_list = taglist; + /* prioritize native tags using _KEEP mode */ + gst_tag_list_insert (taglist, xmptaglist, GST_TAG_MERGE_KEEP); + gst_tag_list_unref (xmptaglist); } } @@ -2297,7 +2302,7 @@ qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length) taglist = gst_tag_list_from_xmp_buffer (buf); gst_buffer_unref (buf); - qtdemux_handle_xmp_taglist (qtdemux, taglist); + qtdemux_handle_xmp_taglist (qtdemux, qtdemux->tag_list, taglist); } else if (memcmp (buffer + offset, playready_uuid, 16) == 0) { int len; @@ -7580,10 +7585,10 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) GNode *esds; GNode *pasp; GNode *tref; + GNode *udta; QtDemuxStream *stream = NULL; gboolean new_stream = FALSE; - GstTagList *list = NULL; gchar *codec = NULL; const guint8 *stsd_data; guint16 lang_code; /* quicktime lang code or packed iso code */ @@ -7621,6 +7626,9 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) } } + if (stream->pending_tags == NULL) + stream->pending_tags = gst_tag_list_new_empty (); + if ((tkhd_flags & 1) == 0) stream->disabled = TRUE; @@ -7789,7 +7797,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) stream->display_width = w >> 16; stream->display_height = h >> 16; - qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix, &list); + qtdemux_inspect_transformation_matrix (qtdemux, stream, matrix, + &stream->pending_tags); offset = 16; if (len < 86) @@ -7894,9 +7903,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) } if (codec) { - if (list == NULL) - list = gst_tag_list_new_empty (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_VIDEO_CODEC, codec, NULL); g_free (codec); codec = NULL; @@ -7955,7 +7962,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) } if (esds) { - gst_qtdemux_handle_esds (qtdemux, stream, esds, list); + gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags); } else { switch (fourcc) { case FOURCC_H264: @@ -8046,15 +8053,12 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) max_bitrate = temp; } - if (!list) - list = gst_tag_list_new_empty (); - if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) { - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE, max_bitrate, NULL); } if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32) { - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, avg_bitrate, NULL); } @@ -8821,9 +8825,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) GstStructure *s; gint bitrate = 0; - if (list == NULL) - list = gst_tag_list_new_empty (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, codec, NULL); g_free (codec); codec = NULL; @@ -8832,8 +8834,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) s = gst_caps_get_structure (stream->caps, 0); gst_structure_get_int (s, "bitrate", &bitrate); if (bitrate > 0) - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, - bitrate, NULL); + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, + GST_TAG_BITRATE, bitrate, NULL); } mp4a = qtdemux_tree_get_child_by_type (stsd, FOURCC_mp4a); @@ -8903,7 +8905,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) g_node_destroy (wavenode); } } else if (esds) { - gst_qtdemux_handle_esds (qtdemux, stream, esds, list); + gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags); } else { switch (fourcc) { #if 0 @@ -8990,9 +8992,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) * the 3GPP container spec (26.244) for more details. */ if ((len - 0x34) > 8 && (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) { - if (!list) - list = gst_tag_list_new_empty (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_MAXIMUM_BITRATE, bitrate, NULL); } @@ -9063,8 +9063,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) stream->caps = qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec); if (codec) { - list = gst_tag_list_new_empty (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_SUBTITLE_CODEC, codec, NULL); g_free (codec); codec = NULL; @@ -9087,7 +9086,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) break; } - gst_qtdemux_handle_esds (qtdemux, stream, esds, list); + gst_qtdemux_handle_esds (qtdemux, stream, esds, stream->pending_tags); break; } default: @@ -9109,8 +9108,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) goto unknown_stream; if (codec) { - list = gst_tag_list_new_empty (); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_SUBTITLE_CODEC, codec, NULL); g_free (codec); codec = NULL; @@ -9168,21 +9166,22 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak) strcmp (stream->lang_id, "und")) { const gchar *lang_code; - if (!list) - list = gst_tag_list_new_empty (); - /* convert ISO 639-2 code to ISO 639-1 */ lang_code = gst_tag_get_language_code (stream->lang_id); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE, GST_TAG_LANGUAGE_CODE, (lang_code) ? lang_code : stream->lang_id, NULL); } + /* Check for UDTA tags */ + if ((udta = qtdemux_tree_get_child_by_type (trak, FOURCC_udta))) { + qtdemux_parse_udta (qtdemux, stream->pending_tags, udta); + } + /* now we are ready to add the stream */ if (qtdemux->n_streams >= GST_QTDEMUX_MAX_STREAMS) goto too_many_streams; if (!qtdemux->got_moov) { - stream->pending_tags = list; qtdemux->streams[qtdemux->n_streams] = stream; qtdemux->n_streams++; GST_DEBUG_OBJECT (qtdemux, "n_streams is now %d", qtdemux->n_streams); @@ -9521,8 +9520,8 @@ qtdemux_is_string_tag_3gp (GstQTDemux * qtdemux, guint32 fourcc) } static void -qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag, - const char *dummy, GNode * node) +qtdemux_tag_add_location (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL }; int offset; @@ -9549,7 +9548,7 @@ qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag, "giving up", tag); } } else { - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_GEO_LOCATION_NAME, name, NULL); offset += strlen (name); g_free (name); @@ -9572,7 +9571,7 @@ qtdemux_tag_add_location (GstQTDemux * qtdemux, const char *tag, /* one invalid means all are invalid */ if (longitude >= -180.0 && longitude <= 180.0 && latitude >= -90.0 && latitude <= 90.0) { - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_GEO_LOCATION_LATITUDE, latitude, GST_TAG_GEO_LOCATION_LONGITUDE, longitude, GST_TAG_GEO_LOCATION_ELEVATION, altitude, NULL); @@ -9592,8 +9591,8 @@ short_read: static void -qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy, - GNode * node) +qtdemux_tag_add_year (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { guint16 y; GDate *date; @@ -9611,13 +9610,13 @@ qtdemux_tag_add_year (GstQTDemux * qtdemux, const char *tag, const char *dummy, GST_DEBUG_OBJECT (qtdemux, "year: %u", y); date = g_date_new_dmy (1, 1, y); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL); g_date_free (date); } static void -qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag, - const char *dummy, GNode * node) +qtdemux_tag_add_classification (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { int offset; char *tag_str = NULL; @@ -9656,8 +9655,7 @@ qtdemux_tag_add_classification (GstQTDemux * qtdemux, const char *tag, memcpy (tag_str, entity, 4); GST_DEBUG_OBJECT (qtdemux, "classification info: %s", tag_str); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_APPEND, tag, - tag_str, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, tag, tag_str, NULL); g_free (tag_str); @@ -9672,8 +9670,8 @@ short_read: } static gboolean -qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag, - const char *dummy, GNode * node) +qtdemux_tag_add_str_full (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL }; GNode *data; @@ -9693,8 +9691,7 @@ qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag, env_vars); if (s) { GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s)); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, - NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL); g_free (s); } else { GST_DEBUG_OBJECT (qtdemux, "failed to convert %s tag to UTF-8", tag); @@ -9766,7 +9763,7 @@ qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag, } if (s) { GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (s)); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, s, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, s, NULL); g_free (s); ret = TRUE; } else { @@ -9777,15 +9774,15 @@ qtdemux_tag_add_str_full (GstQTDemux * qtdemux, const char *tag, } static void -qtdemux_tag_add_str (GstQTDemux * qtdemux, const char *tag, - const char *dummy, GNode * node) +qtdemux_tag_add_str (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { - qtdemux_tag_add_str_full (qtdemux, tag, dummy, node); + qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node); } static void -qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag, - const char *dummy, GNode * node) +qtdemux_tag_add_keywords (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { const gchar *env_vars[] = { "GST_QT_TAG_ENCODING", "GST_TAG_ENCODING", NULL }; guint8 *data; @@ -9796,7 +9793,7 @@ qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag, /* first try normal string tag if major brand not 3GP */ if (!qtdemux_is_brand_3gp (qtdemux, TRUE)) { - if (!qtdemux_tag_add_str_full (qtdemux, tag, dummy, node)) { + if (!qtdemux_tag_add_str_full (qtdemux, taglist, tag, dummy, node)) { /* hm, that did not work, maybe 3gpp storage in non-3gpp major brand; * let's try it 3gpp way after minor safety check */ data = node->data; @@ -9846,7 +9843,7 @@ qtdemux_tag_add_keywords (GstQTDemux * qtdemux, const char *tag, done: if (k) { GST_DEBUG_OBJECT (qtdemux, "adding tag %s", GST_STR_NULL (k)); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, k, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, k, NULL); } g_free (k); @@ -9861,8 +9858,8 @@ short_read: } static void -qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1, - const char *tag2, GNode * node) +qtdemux_tag_add_num (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag1, const char *tag2, GNode * node) { GNode *data; int len; @@ -9878,21 +9875,19 @@ qtdemux_tag_add_num (GstQTDemux * qtdemux, const char *tag1, n2 = QT_UINT16 ((guint8 *) data->data + 20); if (n1 > 0) { GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag1, n1); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, - tag1, n1, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, n1, NULL); } if (n2 > 0) { GST_DEBUG_OBJECT (qtdemux, "adding tag %s=%d", tag2, n2); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, - tag2, n2, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag2, n2, NULL); } } } } static void -qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy, - GNode * node) +qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag1, const char *dummy, GNode * node) { GNode *data; int len; @@ -9910,16 +9905,16 @@ qtdemux_tag_add_tmpo (GstQTDemux * qtdemux, const char *tag1, const char *dummy, if (n1) { /* do not add bpm=0 */ GST_DEBUG_OBJECT (qtdemux, "adding tag %d", n1); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, - tag1, (gdouble) n1, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, (gdouble) n1, + NULL); } } } } static void -qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1, - const char *dummy, GNode * node) +qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag1, const char *dummy, GNode * node) { GNode *data; int len; @@ -9937,16 +9932,15 @@ qtdemux_tag_add_uint32 (GstQTDemux * qtdemux, const char *tag1, if (num) { /* do not add num=0 */ GST_DEBUG_OBJECT (qtdemux, "adding tag %d", num); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, - tag1, num, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, num, NULL); } } } } static void -qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy, - GNode * node) +qtdemux_tag_add_covr (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag1, const char *dummy, GNode * node) { GNode *data; int len; @@ -9963,8 +9957,7 @@ qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy, gst_tag_image_data_to_image_sample ((guint8 *) data->data + 16, len - 16, GST_TAG_IMAGE_TYPE_NONE))) { GST_DEBUG_OBJECT (qtdemux, "adding tag size %d", len - 16); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, - tag1, sample, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag1, sample, NULL); gst_sample_unref (sample); } } @@ -9972,8 +9965,8 @@ qtdemux_tag_add_covr (GstQTDemux * qtdemux, const char *tag1, const char *dummy, } static void -qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy, - GNode * node) +qtdemux_tag_add_date (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { GNode *data; char *s; @@ -9995,8 +9988,7 @@ qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy, GDate *date; date = g_date_new_dmy (d, m, y); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, tag, - date, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, date, NULL); g_date_free (date); } else { GST_DEBUG_OBJECT (qtdemux, "could not parse date string '%s'", s); @@ -10007,8 +9999,8 @@ qtdemux_tag_add_date (GstQTDemux * qtdemux, const char *tag, const char *dummy, } static void -qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy, - GNode * node) +qtdemux_tag_add_gnre (GstQTDemux * qtdemux, GstTagList * taglist, + const char *tag, const char *dummy, GNode * node) { GNode *data; @@ -10018,7 +10010,7 @@ qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy, * or no data atom and compatible brand suggests so */ if (qtdemux_is_brand_3gp (qtdemux, TRUE) || (qtdemux_is_brand_3gp (qtdemux, FALSE) && !data)) { - qtdemux_tag_add_str (qtdemux, tag, dummy, node); + qtdemux_tag_add_str (qtdemux, taglist, tag, dummy, node); return; } @@ -10035,8 +10027,7 @@ qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy, genre = gst_tag_id3_genre_get (n - 1); if (genre != NULL) { GST_DEBUG_OBJECT (qtdemux, "adding %d [%s]", n, genre); - gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_REPLACE, - tag, genre, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, genre, NULL); } } } @@ -10044,8 +10035,8 @@ qtdemux_tag_add_gnre (GstQTDemux * qtdemux, const char *tag, const char *dummy, } static void -qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag, - guint8 * data, guint32 datasize) +qtdemux_add_double_tag_from_str (GstQTDemux * demux, GstTagList * taglist, + const gchar * tag, guint8 * data, guint32 datasize) { gdouble value; gchar *datacopy; @@ -10056,7 +10047,7 @@ qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag, /* convert the str to double */ if (sscanf (datacopy, "%lf", &value) == 1) { GST_DEBUG_OBJECT (demux, "adding tag: %s [%s]", tag, datacopy); - gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_REPLACE, tag, value, NULL); + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, tag, value, NULL); } else { GST_WARNING_OBJECT (demux, "Failed to parse double from string: %s", datacopy); @@ -10066,8 +10057,8 @@ qtdemux_add_double_tag_from_str (GstQTDemux * demux, const gchar * tag, static void -qtdemux_tag_add_revdns (GstQTDemux * demux, const char *tag, - const char *tag_bis, GNode * node) +qtdemux_tag_add_revdns (GstQTDemux * demux, GstTagList * taglist, + const char *tag, const char *tag_bis, GNode * node) { GNode *mean; GNode *name; @@ -10157,11 +10148,11 @@ qtdemux_tag_add_revdns (GstQTDemux * demux, const char *tag, if (!g_ascii_strncasecmp (tags[i].name, namestr, namesize)) { switch (gst_tag_get_type (tags[i].tag)) { case G_TYPE_DOUBLE: - qtdemux_add_double_tag_from_str (demux, tags[i].tag, + qtdemux_add_double_tag_from_str (demux, taglist, tags[i].tag, ((guint8 *) data->data) + 16, datasize - 16); break; case G_TYPE_STRING: - qtdemux_tag_add_str (demux, tags[i].tag, NULL, node); + qtdemux_tag_add_str (demux, taglist, tags[i].tag, NULL, node); break; default: /* not reached */ @@ -10199,13 +10190,13 @@ unknown_tag: } static void -qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag, +qtdemux_tag_add_id32 (GstQTDemux * demux, GstTagList * taglist, const char *tag, const char *tag_bis, GNode * node) { guint8 *data; GstBuffer *buf; guint len; - GstTagList *taglist = NULL; + GstTagList *id32_taglist = NULL; GST_LOG_OBJECT (demux, "parsing ID32"); @@ -10219,21 +10210,19 @@ qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag, buf = gst_buffer_new_allocate (NULL, len - 14, NULL); gst_buffer_fill (buf, 0, data + 14, len - 14); - taglist = gst_tag_list_from_id3v2_tag (buf); - if (taglist) { + id32_taglist = gst_tag_list_from_id3v2_tag (buf); + if (id32_taglist) { GST_LOG_OBJECT (demux, "parsing ok"); - gst_tag_list_insert (demux->tag_list, taglist, GST_TAG_MERGE_KEEP); + gst_tag_list_insert (taglist, id32_taglist, GST_TAG_MERGE_KEEP); + gst_tag_list_unref (id32_taglist); } else { GST_LOG_OBJECT (demux, "parsing failed"); } - if (taglist) - gst_tag_list_unref (taglist); - gst_buffer_unref (buf); } -typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, +typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux, GstTagList * taglist, const char *tag, const char *tag_bis, GNode * node); /* unmapped tags @@ -10310,8 +10299,15 @@ static const struct FOURCC_ID32, "", NULL, qtdemux_tag_add_id32} }; +struct _GstQtDemuxTagList +{ + GstQTDemux *demux; + GstTagList *taglist; +}; +typedef struct _GstQtDemuxTagList GstQtDemuxTagList; + static void -qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux) +qtdemux_tag_add_blob (GNode * node, GstQtDemuxTagList * qtdemuxtaglist) { gint len; guint8 *data; @@ -10322,6 +10318,8 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux) GstStructure *s; guint i; guint8 ndata[4]; + GstQTDemux *demux = qtdemuxtaglist->demux; + GstTagList *taglist = qtdemuxtaglist->taglist; data = node->data; len = QT_UINT32 (data); @@ -10359,20 +10357,24 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux) GST_DEBUG_OBJECT (demux, "adding private tag; size %d, info %" GST_PTR_FORMAT, len, s); - gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND, + gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, GST_QT_DEMUX_PRIVATE_TAG, sample, NULL); gst_sample_unref (sample); } static void -qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta) +qtdemux_parse_udta (GstQTDemux * qtdemux, GstTagList * taglist, GNode * udta) { GNode *meta; GNode *ilst; GNode *xmp_; GNode *node; gint i; + GstQtDemuxTagList demuxtaglist; + + demuxtaglist.demux = qtdemux; + demuxtaglist.taglist = taglist; meta = qtdemux_tree_get_child_by_type (udta, FOURCC_meta); if (meta != NULL) { @@ -10386,14 +10388,6 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta) GST_LOG_OBJECT (qtdemux, "no meta so using udta itself"); } - GST_DEBUG_OBJECT (qtdemux, "new tag list"); - if (!qtdemux->tag_list) { - qtdemux->tag_list = gst_tag_list_new_empty (); - gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL); - } else { - qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list); - } - i = 0; while (i < G_N_ELEMENTS (add_funcs)) { node = qtdemux_tree_get_child_by_type (ilst, add_funcs[i].fourcc); @@ -10405,7 +10399,7 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta) GST_DEBUG_OBJECT (qtdemux, "too small tag atom %" GST_FOURCC_FORMAT, GST_FOURCC_ARGS (add_funcs[i].fourcc)); } else { - add_funcs[i].func (qtdemux, add_funcs[i].gst_tag, + add_funcs[i].func (qtdemux, taglist, add_funcs[i].gst_tag, add_funcs[i].gst_tag_bis, node); } g_node_destroy (node); @@ -10416,24 +10410,23 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta) /* parsed nodes have been removed, pass along remainder as blob */ g_node_children_foreach (ilst, G_TRAVERSE_ALL, - (GNodeForeachFunc) qtdemux_tag_add_blob, qtdemux); + (GNodeForeachFunc) qtdemux_tag_add_blob, &demuxtaglist); /* parse up XMP_ node if existing */ xmp_ = qtdemux_tree_get_child_by_type (udta, FOURCC_XMP_); if (xmp_ != NULL) { GstBuffer *buf; - GstTagList *taglist; + GstTagList *xmptaglist; buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8, QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL); - taglist = gst_tag_list_from_xmp_buffer (buf); + xmptaglist = gst_tag_list_from_xmp_buffer (buf); gst_buffer_unref (buf); - qtdemux_handle_xmp_taglist (qtdemux, taglist); + qtdemux_handle_xmp_taglist (qtdemux, taglist, xmptaglist); } else { GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found"); } - } typedef struct @@ -10747,10 +10740,18 @@ qtdemux_parse_tree (GstQTDemux * qtdemux) trak = qtdemux_tree_get_sibling_by_type (trak, FOURCC_trak); } + if (!qtdemux->tag_list) { + GST_DEBUG_OBJECT (qtdemux, "new tag list"); + qtdemux->tag_list = gst_tag_list_new_empty (); + gst_tag_list_set_scope (qtdemux->tag_list, GST_TAG_SCOPE_GLOBAL); + } else { + qtdemux->tag_list = gst_tag_list_make_writable (qtdemux->tag_list); + } + /* find tags */ udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_udta); if (udta) { - qtdemux_parse_udta (qtdemux, udta); + qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta); } else { GST_LOG_OBJECT (qtdemux, "No udta node found."); } @@ -10759,7 +10760,7 @@ qtdemux_parse_tree (GstQTDemux * qtdemux) udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta); if (udta) { GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags."); - qtdemux_parse_udta (qtdemux, udta); + qtdemux_parse_udta (qtdemux, qtdemux->tag_list, udta); } else { GST_LOG_OBJECT (qtdemux, "No meta node found."); }