From 00897e21a99011884c07c4def20a6d658cc0e97b Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 28 Apr 2010 23:52:12 -0300 Subject: [PATCH] jpegformat: Add exif support Adds exif writing support to jifmux. Adds parsing support to jpegparse. Fixes #614872 --- gst/jpegformat/gstjifmux.c | 68 +++++++++++++++++++++++++++++------ gst/jpegformat/gstjpegparse.c | 27 +++++++++++++- 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/gst/jpegformat/gstjifmux.c b/gst/jpegformat/gstjifmux.c index 15e26f9950..43e562323a 100644 --- a/gst/jpegformat/gstjifmux.c +++ b/gst/jpegformat/gstjifmux.c @@ -338,7 +338,8 @@ static gboolean gst_jif_mux_mangle_markers (GstJifMux * self) { gboolean modified = FALSE; - const GstTagList *tags; + GstTagList *tags = NULL; + gboolean cleanup_tags; GstJifMuxMarker *m; GList *node, *file_hdr = NULL, *frame_hdr = NULL, *scan_hdr = NULL; GList *app0_jfif = NULL, *app1_exif = NULL, *app1_xmp = NULL, *com = NULL; @@ -367,7 +368,8 @@ gst_jif_mux_mangle_markers (GstJifMux * self) } break; case APP1: - if (m->size > 6 && !memcmp (m->data, "EXIF\0\0", 6)) { + if (m->size > 6 && (!memcmp (m->data, "EXIF\0\0", 6) || + !memcmp (m->data, "Exif\0\0", 6))) { GST_DEBUG_OBJECT (self, "found APP1 EXIF"); if (!app1_exif) app1_exif = node; @@ -435,25 +437,66 @@ gst_jif_mux_mangle_markers (GstJifMux * self) /* else */ /* remove JFIF if exists */ - /* if we want combined or EXIF */ - /* check if we don't have EXIF APP1 */ - if (!app1_exif) { - /* exif_data = gst_tag_list_to_exif_buffer (tags); */ - /* insert into self->markers list */ + /* Existing exif tags will be removed and our own will be added */ + if (!tags) { + tags = (GstTagList *) gst_tag_setter_get_tag_list (GST_TAG_SETTER (self)); + cleanup_tags = FALSE; } - /* else */ - /* remove EXIF if exists */ - - tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (self)); if (!tags) { tags = gst_tag_list_new (); } + /* FIXME: not happy with those * - else where we would use VIDEO_CODEC = "Jpeg" gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_VIDEO_CODEC, "image/jpeg", NULL); */ + /* Add EXIF */ + { + GstBuffer *exif_data; + guint8 *data; + GstJifMuxMarker *m; + GList *pos; + + /* insert into self->markers list */ + exif_data = gst_tag_list_to_exif_buffer_with_tiff_header (tags); + if (exif_data && + GST_BUFFER_SIZE (exif_data) + 8 >= G_GUINT64_CONSTANT (65536)) { + GST_WARNING_OBJECT (self, "Exif tags data size exceed maximum size"); + gst_buffer_unref (exif_data); + exif_data = NULL; + } + if (exif_data) { + data = g_malloc0 (GST_BUFFER_SIZE (exif_data) + 6); + memcpy (data, "Exif", 4); + memcpy (data + 6, GST_BUFFER_DATA (exif_data), + GST_BUFFER_SIZE (exif_data)); + m = gst_jif_mux_new_marker (APP1, GST_BUFFER_SIZE (exif_data) + 6, data, + TRUE); + gst_buffer_unref (exif_data); + + if (app1_exif) { + gst_jif_mux_marker_free ((GstJifMuxMarker *) app1_exif->data); + app1_exif->data = m; + } else { + pos = file_hdr; + if (app0_jfif) + pos = app0_jfif; + pos = g_list_next (pos); + + self->priv->markers = + g_list_insert_before (self->priv->markers, pos, m); + if (pos) { + app1_exif = g_list_previous (pos); + } else { + app1_exif = g_list_last (self->priv->markers); + } + } + modified = TRUE; + } + } + /* add xmp */ xmp_data = gst_tag_list_to_xmp_buffer (tags, FALSE); if (xmp_data) { @@ -506,6 +549,9 @@ gst_jif_mux_mangle_markers (GstJifMux * self) modified = TRUE; } + + if (tags && cleanup_tags) + gst_tag_list_free (tags); return modified; } diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index 4217c6aff8..2653e7da7d 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -578,7 +578,32 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer) if (!gst_byte_reader_get_string_utf8 (&reader, &id_str)) goto error; - if (!strcmp (id_str, "http://ns.adobe.com/xap/1.0/")) { + if (!strcmp (id_str, "Exif")) { + const guint8 *exif_data = NULL; + guint exif_size = size - 2; + GstTagList *tags; + GstBuffer *buf; + + /* skip padding */ + gst_byte_reader_skip (&reader, 1); + + /* handle exif metadata */ + if (!gst_byte_reader_get_data (&reader, exif_size, &exif_data)) + goto error; + + buf = gst_buffer_new (); + GST_BUFFER_DATA (buf) = (guint8 *) exif_data; + GST_BUFFER_SIZE (buf) = exif_size; + tags = gst_tag_list_from_exif_buffer_with_tiff_header (buf); + gst_buffer_unref (buf); + if (tags) { + GST_INFO_OBJECT (parse, "post exif metadata"); + gst_element_found_tags_for_pad (GST_ELEMENT_CAST (parse), + parse->priv->srcpad, tags); + } + GST_LOG_OBJECT (parse, "parsed marker %x: '%s' %u bytes", + marker, id_str, size - 2); + } else if (!strcmp (id_str, "http://ns.adobe.com/xap/1.0/")) { const guint8 *xmp_data = NULL; guint xmp_size = size - 2 - 29; GstTagList *tags;