From 8d6cabf9c358579c9e61688a81151147140cd9f4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 15 Sep 2010 22:13:43 -0300 Subject: [PATCH] qtdemux: Parse xmp packet in uuid atom xmp packet is placed into a top-level uuid atom for isom/mp4 variants. This patch makes qtdemux parse all top-level atoms in pull-mode before starting to push data, making it able to find those tags. https://bugzilla.gnome.org/show_bug.cgi?id=629839 --- gst/qtdemux/qtdemux.c | 97 ++++++++++++++++++++++++++++++------ gst/qtdemux/qtdemux_fourcc.h | 1 + 2 files changed, 82 insertions(+), 16 deletions(-) diff --git a/gst/qtdemux/qtdemux.c b/gst/qtdemux/qtdemux.c index 3997457847..f310fdaddf 100644 --- a/gst/qtdemux/qtdemux.c +++ b/gst/qtdemux/qtdemux.c @@ -1733,6 +1733,59 @@ qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length) } } +static void +qtdemux_handle_xmp_taglist (GstQTDemux * qtdemux, GstTagList * taglist) +{ + /* Strip out bogus fields */ + if (taglist) { + gst_tag_list_remove_tag (taglist, GST_TAG_VIDEO_CODEC); + + GST_DEBUG_OBJECT (qtdemux, "Found XMP tags %" GST_PTR_FORMAT, taglist); + + 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_free (taglist); + } else + qtdemux->tag_list = taglist; + } +} + +static void +qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length) +{ + static guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB, + 0x97, 0xA9, 0x42, 0xE8, + 0x9C, 0x71, 0x99, 0x94, + 0x91, 0xE3, 0xAF, 0xAC + }; + guint offset; + + offset = (QT_UINT32 (buffer) == 0) ? 16 : 8; + + if (length <= offset + 16) { + GST_DEBUG_OBJECT (qtdemux, "uuid atom is too short, skipping"); + return; + } + + if (memcmp (buffer + offset, xmp_uuid, 16) == 0) { + GstBuffer *buf; + GstTagList *taglist; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) buffer + offset + 16; + GST_BUFFER_SIZE (buf) = length - offset - 16; + + taglist = gst_tag_list_from_xmp_buffer (buf); + gst_buffer_unref (buf); + + qtdemux_handle_xmp_taglist (qtdemux, taglist); + + } else { + GST_DEBUG_OBJECT (qtdemux, "Ignoring unknown uuid"); + } +} + static void extract_initial_length_and_fourcc (const guint8 * data, guint64 * plength, guint32 * pfourcc) @@ -1802,6 +1855,12 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux) { GstBuffer *moov; + if (qtdemux->got_moov) { + GST_DEBUG_OBJECT (qtdemux, "Skipping moov atom as we have one already"); + qtdemux->offset += length; + goto beach; + } + ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov); if (ret != GST_FLOW_OK) goto beach; @@ -1851,9 +1910,7 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux) g_node_destroy (qtdemux->moov_node); gst_buffer_unref (moov); qtdemux->moov_node = NULL; - qtdemux->state = QTDEMUX_STATE_MOVIE; - GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)", - qtdemux->state); + qtdemux->got_moov = TRUE; break; } case FOURCC_ftyp: @@ -1870,6 +1927,20 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux) gst_buffer_unref (ftyp); break; } + case FOURCC_uuid: + { + GstBuffer *uuid; + + /* uuid are extension atoms */ + ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &uuid); + if (ret != GST_FLOW_OK) + goto beach; + qtdemux->offset += length; + qtdemux_parse_uuid (qtdemux, GST_BUFFER_DATA (uuid), + GST_BUFFER_SIZE (uuid)); + gst_buffer_unref (uuid); + break; + } default: { GstBuffer *unknown; @@ -1890,6 +1961,12 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux) } beach: + if (ret == GST_FLOW_UNEXPECTED && qtdemux->got_moov) { + qtdemux->state = QTDEMUX_STATE_MOVIE; + GST_DEBUG_OBJECT (qtdemux, "switching state to STATE_MOVIE (%d)", + qtdemux->state); + return GST_FLOW_OK; + } return ret; } @@ -7003,19 +7080,7 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta) taglist = gst_tag_list_from_xmp_buffer (buf); gst_buffer_unref (buf); - /* Strip out bogus fields */ - - if (taglist) { - gst_tag_list_remove_tag (taglist, GST_TAG_VIDEO_CODEC); - if (qtdemux->tag_list) { - GST_DEBUG_OBJECT (qtdemux, "Found XMP tags"); - - /* prioritize native tags using _KEEP mode */ - gst_tag_list_insert (qtdemux->tag_list, taglist, GST_TAG_MERGE_KEEP); - gst_tag_list_free (taglist); - } else - qtdemux->tag_list = taglist; - } + qtdemux_handle_xmp_taglist (qtdemux, taglist); } else { GST_DEBUG_OBJECT (qtdemux, "No XMP_ node found"); } diff --git a/gst/qtdemux/qtdemux_fourcc.h b/gst/qtdemux/qtdemux_fourcc.h index 345fe5ed1a..c4c0841b8f 100644 --- a/gst/qtdemux/qtdemux_fourcc.h +++ b/gst/qtdemux/qtdemux_fourcc.h @@ -205,6 +205,7 @@ G_BEGIN_DECLS #define FOURCC_tCtC GST_MAKE_FOURCC('t','C','t','C') #define FOURCC_XMP_ GST_MAKE_FOURCC('X','M','P','_') +#define FOURCC_uuid GST_MAKE_FOURCC('u','u','i','d') G_END_DECLS