jpegformat: Add exif support

Adds exif writing support to jifmux.
Adds parsing support to jpegparse.

Fixes #614872
This commit is contained in:
Thiago Santos 2010-04-28 23:52:12 -03:00
parent eebe58a163
commit 00897e21a9
2 changed files with 83 additions and 12 deletions

View file

@ -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;
}

View file

@ -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;