mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-18 22:36:33 +00:00
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
This commit is contained in:
parent
2c8b725591
commit
8d6cabf9c3
2 changed files with 82 additions and 16 deletions
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue