From 57013ae63e681057d7525d6e09532995177127ce Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 17 Aug 2010 15:05:32 -0300 Subject: [PATCH] tag: exif: Adds mapping for GST_TAG_APPLICATION_DATA Adds mapping for GST_TAG_APPLICATION_DATA to the exif 'maker-note' tag. --- gst-libs/gst/tag/gstexiftag.c | 100 ++++++++++++++++++++++++++++++++++ tests/check/libs/tag.c | 12 ++++ 2 files changed, 112 insertions(+) diff --git a/gst-libs/gst/tag/gstexiftag.c b/gst-libs/gst/tag/gstexiftag.c index 3e75b53b7d..a443ba722d 100644 --- a/gst-libs/gst/tag/gstexiftag.c +++ b/gst-libs/gst/tag/gstexiftag.c @@ -181,6 +181,7 @@ static const GstExifTagMatch tag_map_ifd0[] = { static const GstExifTagMatch tag_map_exif[] = { {NULL, EXIF_VERSION_TAG, EXIF_TYPE_UNDEFINED, 0, NULL, NULL}, {GST_TAG_DATE_TIME, 0x9003, EXIF_TYPE_ASCII, 0, NULL, NULL}, + {GST_TAG_APPLICATION_DATA, 0x927C, EXIF_TYPE_UNDEFINED, 0, NULL, NULL}, {NULL, 0, 0, 0, NULL, NULL} }; @@ -492,6 +493,47 @@ write_exif_ascii_tag_from_taglist (GstExifWriter * writer, g_free (str); } +static void +write_exif_undefined_tag_from_taglist (GstExifWriter * writer, + const GstTagList * taglist, const GstExifTagMatch * exiftag) +{ + const GValue *value; + const guint8 *data = NULL; + gint size = 0; + gint tag_size = gst_tag_list_get_tag_size (taglist, exiftag->gst_tag); + + if (tag_size != 1) { + GST_WARNING ("Only the first item in the taglist will be serialized"); + return; + } + + value = gst_tag_list_get_value_index (taglist, exiftag->gst_tag, 0); + + /* do some conversion if needed */ + switch (G_VALUE_TYPE (value)) { + case G_TYPE_STRING: + data = (guint8 *) g_value_get_string (value); + size = strlen ((gchar *) data); /* no need to +1, undefined doesn't require it */ + break; + default: + if (G_VALUE_TYPE (value) == GST_TYPE_BUFFER) { + GstBuffer *buf = gst_value_get_buffer (value); + + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + } else { + GST_WARNING ("Conversion from %s to raw data not supported", + G_VALUE_TYPE_NAME (value)); + } + break; + } + + if (size == 0) + return; + + write_exif_undefined_tag (writer, exiftag->exif_tag, data, size); +} + static void write_exif_tag_from_taglist (GstExifWriter * writer, const GstTagList * taglist, const GstExifTagMatch * exiftag) @@ -508,6 +550,9 @@ write_exif_tag_from_taglist (GstExifWriter * writer, const GstTagList * taglist, case EXIF_TYPE_ASCII: write_exif_ascii_tag_from_taglist (writer, taglist, exiftag); break; + case EXIF_TYPE_UNDEFINED: + write_exif_undefined_tag_from_taglist (writer, taglist, exiftag); + break; default: GST_WARNING ("Unhandled tag type %d", exiftag->exif_type); } @@ -688,6 +733,58 @@ parse_exif_ascii_tag (GstExifReader * reader, const GstExifTagMatch * tag, g_free (str); } +static void +parse_exif_undefined_tag (GstExifReader * reader, const GstExifTagMatch * tag, + guint32 count, guint32 offset, const guint8 * offset_as_data) +{ + GType tagtype; + guint8 *data; + guint32 real_offset; + + if (count > 4) { + if (offset < reader->base_offset) { + GST_WARNING ("Offset is smaller (%u) than base offset (%u)", offset, + reader->base_offset); + return; + } + + real_offset = offset - reader->base_offset; + if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) { + GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s", + real_offset, GST_BUFFER_SIZE (reader->buffer), tag->gst_tag); + return; + } + + /* +1 because it could be a string without the \0 */ + data = malloc (sizeof (guint8) * count + 1); + memcpy (data, GST_BUFFER_DATA (reader->buffer) + real_offset, count); + data[count] = 0; + } else { + data = malloc (sizeof (guint8) * count + 1); + memcpy (data, (guint8 *) offset_as_data, count); + data[count] = 0; + } + + tagtype = gst_tag_get_type (tag->gst_tag); + if (tagtype == GST_TYPE_BUFFER) { + GstBuffer *buf = gst_buffer_new (); + gst_buffer_set_data (buf, data, count); + data = NULL; + + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_APPEND, tag->gst_tag, + buf, NULL); + + gst_buffer_unref (buf); + } else if (tagtype == G_TYPE_STRING) { + gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, tag->gst_tag, + data, NULL); + } else { + GST_WARNING ("No parsing function associated to %x(%s)", tag->exif_tag, + tag->gst_tag); + } + g_free (data); +} + static void parse_exif_rational_tag (GstExifReader * exif_reader, const gchar * gst_tag, guint32 count, guint32 offset, gdouble multiplier) @@ -946,6 +1043,9 @@ parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset, parse_exif_rational_tag (exif_reader, tag_map[map_index].gst_tag, tagdata.count, tagdata.offset, 1); break; + case EXIF_TYPE_UNDEFINED: + parse_exif_undefined_tag (exif_reader, &tag_map[map_index], + tagdata.count, tagdata.offset, tagdata.offset_as_data); default: GST_WARNING ("Unhandled tag type: %u", tagdata.tag_type); break; diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c index e561dce47e..94c5978ad6 100644 --- a/tests/check/libs/tag.c +++ b/tests/check/libs/tag.c @@ -1243,6 +1243,8 @@ GST_START_TEST (test_exif_tags_serialization_deserialization) { GValue value = { 0 }; GstDateTime *datetime = NULL; + GstBuffer *buf = NULL; + gint i; g_value_init (&value, G_TYPE_STRING); g_value_set_static_string (&value, "my string"); @@ -1334,6 +1336,16 @@ GST_START_TEST (test_exif_tags_serialization_deserialization) gst_date_time_unref (datetime); do_simple_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value); g_value_unset (&value); + + g_value_init (&value, GST_TYPE_BUFFER); + buf = gst_buffer_new_and_alloc (1024); + for (i = 0; i < 1024; i++) + GST_BUFFER_DATA (buf)[i] = i % 255; + gst_value_set_buffer (&value, buf); + gst_buffer_unref (buf); + do_simple_exif_tag_serialization_deserialization (GST_TAG_APPLICATION_DATA, + &value); + g_value_unset (&value); } GST_END_TEST;