mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 00:06:36 +00:00
tag: exif: Map GST_TAG_DATE_TIME
Adds mapping to the exif helper library for GST_TAG_DATE_TIME. Tests included. https://bugzilla.gnome.org/show_bug.cgi?id=594504
This commit is contained in:
parent
5e51a77df4
commit
93f97277da
2 changed files with 70 additions and 7 deletions
|
@ -38,6 +38,7 @@
|
||||||
#include <gst/base/gstbytewriter.h>
|
#include <gst/base/gstbytewriter.h>
|
||||||
#include "gsttageditingprivate.h"
|
#include "gsttageditingprivate.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
@ -163,6 +164,7 @@ static gint deserialize_speed (GstExifReader * exif_reader,
|
||||||
/* FIXME copyright tag has a weird "artist\0editor\0" format that is
|
/* FIXME copyright tag has a weird "artist\0editor\0" format that is
|
||||||
* not yet handled */
|
* not yet handled */
|
||||||
|
|
||||||
|
#define EXIF_IFD_TAG 0x8769
|
||||||
#define EXIF_GPS_IFD_TAG 0x8825
|
#define EXIF_GPS_IFD_TAG 0x8825
|
||||||
|
|
||||||
/* useful macros for speed tag */
|
/* useful macros for speed tag */
|
||||||
|
@ -180,10 +182,16 @@ static const GstExifTagMatch tag_map_ifd0[] = {
|
||||||
deserialize_orientation},
|
deserialize_orientation},
|
||||||
{GST_TAG_ARTIST, 0x13B, EXIF_TYPE_ASCII, 0, NULL, NULL},
|
{GST_TAG_ARTIST, 0x13B, EXIF_TYPE_ASCII, 0, NULL, NULL},
|
||||||
{GST_TAG_COPYRIGHT, 0x8298, EXIF_TYPE_ASCII, 0, NULL, NULL},
|
{GST_TAG_COPYRIGHT, 0x8298, EXIF_TYPE_ASCII, 0, NULL, NULL},
|
||||||
|
{NULL, EXIF_IFD_TAG, EXIF_TYPE_LONG, 0, NULL, NULL},
|
||||||
{NULL, EXIF_GPS_IFD_TAG, EXIF_TYPE_LONG, 0, NULL, NULL},
|
{NULL, EXIF_GPS_IFD_TAG, EXIF_TYPE_LONG, 0, NULL, NULL},
|
||||||
{NULL, 0, 0, 0, NULL, NULL}
|
{NULL, 0, 0, 0, NULL, NULL}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const GstExifTagMatch tag_map_exif[] = {
|
||||||
|
{GST_TAG_DATE_TIME, 0x9003, EXIF_TYPE_ASCII, 0, NULL, NULL},
|
||||||
|
{NULL, 0, 0, 0, NULL, NULL}
|
||||||
|
};
|
||||||
|
|
||||||
static const GstExifTagMatch tag_map_gps[] = {
|
static const GstExifTagMatch tag_map_gps[] = {
|
||||||
{GST_TAG_GEO_LOCATION_LATITUDE, 0x2, EXIF_TYPE_RATIONAL, 0x1,
|
{GST_TAG_GEO_LOCATION_LATITUDE, 0x2, EXIF_TYPE_RATIONAL, 0x1,
|
||||||
serialize_geo_coordinate, deserialize_geo_coordinate},
|
serialize_geo_coordinate, deserialize_geo_coordinate},
|
||||||
|
@ -280,6 +288,9 @@ gst_tag_list_has_ifd_tags (const GstTagList * taglist,
|
||||||
if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG &&
|
if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG &&
|
||||||
gst_tag_list_has_ifd_tags (taglist, tag_map_gps))
|
gst_tag_list_has_ifd_tags (taglist, tag_map_gps))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
if (tag_map[i].exif_tag == EXIF_IFD_TAG &&
|
||||||
|
gst_tag_list_has_ifd_tags (taglist, tag_map_exif))
|
||||||
|
return TRUE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -439,8 +450,24 @@ write_exif_ascii_tag_from_taglist (GstExifWriter * writer,
|
||||||
str = (gchar *) g_value_get_string (value);
|
str = (gchar *) g_value_get_string (value);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (G_VALUE_TYPE (value) == GST_TYPE_DATE_TIME) {
|
||||||
|
GstDateTime *dt = (GstDateTime *) g_value_get_boxed (value);
|
||||||
|
|
||||||
|
if (dt == NULL) {
|
||||||
|
GST_WARNING ("NULL datetime received");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
str = g_strdup_printf ("%04d:%02d:%02d %02d:%02d:%02d",
|
||||||
|
gst_date_time_get_year (dt), gst_date_time_get_month (dt),
|
||||||
|
gst_date_time_get_day (dt), gst_date_time_get_hour (dt),
|
||||||
|
gst_date_time_get_minute (dt), gst_date_time_get_second (dt));
|
||||||
|
|
||||||
|
cleanup = TRUE;
|
||||||
|
} else {
|
||||||
GST_WARNING ("Conversion from %s to ascii string not supported",
|
GST_WARNING ("Conversion from %s to ascii string not supported",
|
||||||
G_VALUE_TYPE_NAME (value));
|
G_VALUE_TYPE_NAME (value));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,7 +569,7 @@ gst_exif_tag_rewrite_offsets (GstExifWriter * writer, guint32 base_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* adjust the offset if needed */
|
/* adjust the offset if needed */
|
||||||
if (byte_size > 4 || tag_id == EXIF_GPS_IFD_TAG) {
|
if (byte_size > 4 || tag_id == EXIF_GPS_IFD_TAG || tag_id == EXIF_IFD_TAG) {
|
||||||
if (writer->byte_order == G_LITTLE_ENDIAN) {
|
if (writer->byte_order == G_LITTLE_ENDIAN) {
|
||||||
if (gst_byte_reader_peek_uint32_le (reader, &cur_offset)) {
|
if (gst_byte_reader_peek_uint32_le (reader, &cur_offset)) {
|
||||||
gst_byte_writer_put_uint32_le (&writer->tagwriter,
|
gst_byte_writer_put_uint32_le (&writer->tagwriter,
|
||||||
|
@ -565,9 +592,10 @@ gst_exif_tag_rewrite_offsets (GstExifWriter * writer, guint32 base_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
parse_exif_ascii_tag (GstExifReader * reader, const gchar * gst_tag,
|
parse_exif_ascii_tag (GstExifReader * reader, const GstExifTagMatch * tag,
|
||||||
guint32 count, guint32 offset, const guint8 * offset_as_data)
|
guint32 count, guint32 offset, const guint8 * offset_as_data)
|
||||||
{
|
{
|
||||||
|
GType tagtype;
|
||||||
gchar *str;
|
gchar *str;
|
||||||
guint32 real_offset;
|
guint32 real_offset;
|
||||||
|
|
||||||
|
@ -581,7 +609,7 @@ parse_exif_ascii_tag (GstExifReader * reader, const gchar * gst_tag,
|
||||||
real_offset = offset - reader->base_offset;
|
real_offset = offset - reader->base_offset;
|
||||||
if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) {
|
if (real_offset >= GST_BUFFER_SIZE (reader->buffer)) {
|
||||||
GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s",
|
GST_WARNING ("Invalid offset %u for buffer of size %u, not adding tag %s",
|
||||||
real_offset, GST_BUFFER_SIZE (reader->buffer), gst_tag);
|
real_offset, GST_BUFFER_SIZE (reader->buffer), tag->gst_tag);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +619,26 @@ parse_exif_ascii_tag (GstExifReader * reader, const gchar * gst_tag,
|
||||||
} else {
|
} else {
|
||||||
str = g_strndup ((gchar *) offset_as_data, count);
|
str = g_strndup ((gchar *) offset_as_data, count);
|
||||||
}
|
}
|
||||||
gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, gst_tag, str, NULL);
|
|
||||||
|
tagtype = gst_tag_get_type (tag->gst_tag);
|
||||||
|
if (tagtype == GST_TYPE_DATE_TIME) {
|
||||||
|
gint year = 0, month = 1, day = 1, hour = 0, minute = 0, second = 0;
|
||||||
|
|
||||||
|
if (sscanf (str, "%04d:%02d:%02d %02d:%02d:%02d", &year, &month, &day,
|
||||||
|
&hour, &minute, &second) > 0) {
|
||||||
|
gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, tag->gst_tag,
|
||||||
|
gst_date_time_new_local_time (year, month, day, hour, minute, second,
|
||||||
|
0), NULL);
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("Failed to parse %s into a datetime tag", str);
|
||||||
|
}
|
||||||
|
} else if (tagtype == G_TYPE_STRING) {
|
||||||
|
gst_tag_list_add (reader->taglist, GST_TAG_MERGE_REPLACE, tag->gst_tag, str,
|
||||||
|
NULL);
|
||||||
|
} else {
|
||||||
|
GST_WARNING ("No parsing function associated to %x(%s)", tag->exif_tag,
|
||||||
|
tag->gst_tag);
|
||||||
|
}
|
||||||
g_free (str);
|
g_free (str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -686,6 +733,8 @@ write_exif_ifd (const GstTagList * taglist, gboolean byte_order,
|
||||||
|
|
||||||
if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG) {
|
if (tag_map[i].exif_tag == EXIF_GPS_IFD_TAG) {
|
||||||
inner_tag_map = tag_map_gps;
|
inner_tag_map = tag_map_gps;
|
||||||
|
} else if (tag_map[i].exif_tag == EXIF_IFD_TAG) {
|
||||||
|
inner_tag_map = tag_map_exif;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inner_tag_map) {
|
if (inner_tag_map) {
|
||||||
|
@ -821,6 +870,12 @@ parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset,
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (tagdata.tag == EXIF_IFD_TAG) {
|
||||||
|
i += parse_exif_ifd (exif_reader,
|
||||||
|
tagdata.offset - exif_reader->base_offset, tag_map_exif);
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* tags that need specialized deserialization */
|
/* tags that need specialized deserialization */
|
||||||
if (tag_map[map_index].deserialize) {
|
if (tag_map[map_index].deserialize) {
|
||||||
|
@ -831,7 +886,7 @@ parse_exif_ifd (GstExifReader * exif_reader, gint buf_offset,
|
||||||
|
|
||||||
switch (tagdata.tag_type) {
|
switch (tagdata.tag_type) {
|
||||||
case EXIF_TYPE_ASCII:
|
case EXIF_TYPE_ASCII:
|
||||||
parse_exif_ascii_tag (exif_reader, tag_map[map_index].gst_tag,
|
parse_exif_ascii_tag (exif_reader, &tag_map[map_index],
|
||||||
tagdata.count, tagdata.offset, tagdata.offset_as_data);
|
tagdata.count, tagdata.offset, tagdata.offset_as_data);
|
||||||
break;
|
break;
|
||||||
case EXIF_TYPE_RATIONAL:
|
case EXIF_TYPE_RATIONAL:
|
||||||
|
|
|
@ -1170,6 +1170,7 @@ do_exif_tag_serialization_deserialization (const gchar * gsttag, GValue * value)
|
||||||
GST_START_TEST (test_exif_tags_serialization_deserialization)
|
GST_START_TEST (test_exif_tags_serialization_deserialization)
|
||||||
{
|
{
|
||||||
GValue value = { 0 };
|
GValue value = { 0 };
|
||||||
|
GstDateTime *datetime = NULL;
|
||||||
|
|
||||||
g_value_init (&value, G_TYPE_STRING);
|
g_value_init (&value, G_TYPE_STRING);
|
||||||
g_value_set_static_string (&value, "my string");
|
g_value_set_static_string (&value, "my string");
|
||||||
|
@ -1243,6 +1244,13 @@ GST_START_TEST (test_exif_tags_serialization_deserialization)
|
||||||
do_exif_tag_serialization_deserialization
|
do_exif_tag_serialization_deserialization
|
||||||
(GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
|
(GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, &value);
|
||||||
g_value_unset (&value);
|
g_value_unset (&value);
|
||||||
|
|
||||||
|
g_value_init (&value, GST_TYPE_DATE_TIME);
|
||||||
|
datetime = gst_date_time_new_local_time (2010, 6, 22, 12, 5, 10, 0);
|
||||||
|
g_value_set_boxed (&value, datetime);
|
||||||
|
gst_date_time_unref (datetime);
|
||||||
|
do_exif_tag_serialization_deserialization (GST_TAG_DATE_TIME, &value);
|
||||||
|
g_value_unset (&value);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
|
Loading…
Reference in a new issue