mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-06-05 15:08:53 +00:00
jpegformat: Add exif support
Adds exif writing support to jifmux. Adds parsing support to jpegparse. Fixes #614872
This commit is contained in:
parent
eebe58a163
commit
00897e21a9
2 changed files with 83 additions and 12 deletions
|
@ -338,7 +338,8 @@ static gboolean
|
||||||
gst_jif_mux_mangle_markers (GstJifMux * self)
|
gst_jif_mux_mangle_markers (GstJifMux * self)
|
||||||
{
|
{
|
||||||
gboolean modified = FALSE;
|
gboolean modified = FALSE;
|
||||||
const GstTagList *tags;
|
GstTagList *tags = NULL;
|
||||||
|
gboolean cleanup_tags;
|
||||||
GstJifMuxMarker *m;
|
GstJifMuxMarker *m;
|
||||||
GList *node, *file_hdr = NULL, *frame_hdr = NULL, *scan_hdr = NULL;
|
GList *node, *file_hdr = NULL, *frame_hdr = NULL, *scan_hdr = NULL;
|
||||||
GList *app0_jfif = NULL, *app1_exif = NULL, *app1_xmp = NULL, *com = 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;
|
break;
|
||||||
case APP1:
|
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");
|
GST_DEBUG_OBJECT (self, "found APP1 EXIF");
|
||||||
if (!app1_exif)
|
if (!app1_exif)
|
||||||
app1_exif = node;
|
app1_exif = node;
|
||||||
|
@ -435,25 +437,66 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
|
||||||
/* else */
|
/* else */
|
||||||
/* remove JFIF if exists */
|
/* remove JFIF if exists */
|
||||||
|
|
||||||
/* if we want combined or EXIF */
|
/* Existing exif tags will be removed and our own will be added */
|
||||||
/* check if we don't have EXIF APP1 */
|
if (!tags) {
|
||||||
if (!app1_exif) {
|
tags = (GstTagList *) gst_tag_setter_get_tag_list (GST_TAG_SETTER (self));
|
||||||
/* exif_data = gst_tag_list_to_exif_buffer (tags); */
|
cleanup_tags = FALSE;
|
||||||
/* insert into self->markers list */
|
|
||||||
}
|
}
|
||||||
/* else */
|
|
||||||
/* remove EXIF if exists */
|
|
||||||
|
|
||||||
tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (self));
|
|
||||||
if (!tags) {
|
if (!tags) {
|
||||||
tags = gst_tag_list_new ();
|
tags = gst_tag_list_new ();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: not happy with those
|
/* FIXME: not happy with those
|
||||||
* - else where we would use VIDEO_CODEC = "Jpeg"
|
* - else where we would use VIDEO_CODEC = "Jpeg"
|
||||||
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
|
gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
|
||||||
GST_TAG_VIDEO_CODEC, "image/jpeg", NULL);
|
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 */
|
/* add xmp */
|
||||||
xmp_data = gst_tag_list_to_xmp_buffer (tags, FALSE);
|
xmp_data = gst_tag_list_to_xmp_buffer (tags, FALSE);
|
||||||
if (xmp_data) {
|
if (xmp_data) {
|
||||||
|
@ -506,6 +549,9 @@ gst_jif_mux_mangle_markers (GstJifMux * self)
|
||||||
|
|
||||||
modified = TRUE;
|
modified = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tags && cleanup_tags)
|
||||||
|
gst_tag_list_free (tags);
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -578,7 +578,32 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer)
|
||||||
if (!gst_byte_reader_get_string_utf8 (&reader, &id_str))
|
if (!gst_byte_reader_get_string_utf8 (&reader, &id_str))
|
||||||
goto error;
|
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;
|
const guint8 *xmp_data = NULL;
|
||||||
guint xmp_size = size - 2 - 29;
|
guint xmp_size = size - 2 - 29;
|
||||||
GstTagList *tags;
|
GstTagList *tags;
|
||||||
|
|
Loading…
Reference in a new issue