summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThiago Santos <thiago.sousa.santos@collabora.co.uk>2010-03-22 15:18:28 -0300
committerThiago Santos <thiago.sousa.santos@collabora.co.uk>2010-03-24 15:33:16 -0300
commit7ebbfbd3a5571c0e7518c5de9e710b9b9915f91e (patch)
tree2640bc625aa314bdfdf13e2bdaccae7ba4b2ac8f
parentfe1f3e35957ddae12ae662e8e950bd8eb2358520 (diff)
tag: xmp: Adds mappings for LATITUDE and LONGITUDE
Adds the mappings for those tags and tests for tags serialization. Fixes #613690
-rw-r--r--gst-libs/gst/tag/gstxmptag.c131
-rw-r--r--tests/check/libs/tag.c111
2 files changed, 242 insertions, 0 deletions
diff --git a/gst-libs/gst/tag/gstxmptag.c b/gst-libs/gst/tag/gstxmptag.c
index b1d9108e3..5ede2877f 100644
--- a/gst-libs/gst/tag/gstxmptag.c
+++ b/gst-libs/gst/tag/gstxmptag.c
@@ -157,6 +157,130 @@ _xmp_tag_get_mapping_reverse (const gchar * xmp_tag, XmpTag ** _xmp_tag)
return ret;
}
+/* (de)serialize functions */
+static gchar *
+serialize_exif_gps_coordinate (const GValue * value, gchar pos, gchar neg)
+{
+ gdouble num;
+ gchar c;
+ gint integer;
+ gchar fraction[G_ASCII_DTOSTR_BUF_SIZE];
+
+ g_return_val_if_fail (G_VALUE_TYPE (value) == G_TYPE_DOUBLE, NULL);
+
+ num = g_value_get_double (value);
+ if (num < 0) {
+ c = neg;
+ num *= -1;
+ } else {
+ c = pos;
+ }
+ integer = (gint) num;
+
+ g_ascii_dtostr (fraction, sizeof (fraction), (num - integer) * 60);
+
+ /* FIXME review GPSCoordinate serialization spec for the .mm or ,ss
+ * decision. Couldn't understand it clearly */
+ return g_strdup_printf ("%d,%s%c", integer, fraction, c);
+}
+
+static gchar *
+serialize_exif_latitude (const GValue * value)
+{
+ return serialize_exif_gps_coordinate (value, 'N', 'S');
+}
+
+static gchar *
+serialize_exif_longitude (const GValue * value)
+{
+ return serialize_exif_gps_coordinate (value, 'E', 'W');
+}
+
+static void
+deserialize_exif_gps_coordinate (GstTagList * taglist, const gchar * gst_tag,
+ const gchar * str, gchar pos, gchar neg)
+{
+ gdouble value = 0;
+ gint d = 0, m = 0, s = 0;
+ gdouble m2 = 0;
+ gchar c;
+ const gchar *current;
+
+ /* get the degrees */
+ if (sscanf (str, "%d", &d) != 1)
+ goto error;
+
+ /* find the beginning of the minutes */
+ current = strchr (str, ',');
+ if (current == NULL)
+ goto end;
+ current += 1;
+
+ /* check if it uses ,SS or .mm */
+ if (strchr (current, ',') != NULL) {
+ sscanf (current, "%d,%d%c", &m, &s, &c);
+ } else {
+ gchar *copy = g_strdup (current);
+ gint len = strlen (copy);
+ gint i;
+
+ /* check the last letter */
+ for (i = len - 1; len >= 0; len--) {
+ if (g_ascii_isspace (copy[i]))
+ continue;
+
+ if (g_ascii_isalpha (copy[i])) {
+ /* found it */
+ c = copy[i];
+ copy[i] = '\0';
+ break;
+
+ } else {
+ /* something is wrong */
+ g_free (copy);
+ goto error;
+ }
+ }
+
+ /* use a copy so we can change the last letter as E can cause
+ * problems here */
+ m2 = g_ascii_strtod (copy, NULL);
+ g_free (copy);
+ }
+
+end:
+ /* we can add them all as those that aren't parsed are 0 */
+ value = d + (m / 60.0) + (s / (60.0 * 60.0)) + (m2 / 60.0);
+
+ if (c == pos) {
+ //NOP
+ } else if (c == neg) {
+ value *= -1;
+ } else {
+ goto error;
+ }
+
+ gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, gst_tag, value, NULL);
+ return;
+
+error:
+ GST_WARNING ("Failed to deserialize gps coordinate: %s", str);
+}
+
+static void
+deserialize_exif_latitude (GstTagList * taglist, const gchar * gst_tag,
+ const gchar * str)
+{
+ deserialize_exif_gps_coordinate (taglist, gst_tag, str, 'N', 'S');
+}
+
+static void
+deserialize_exif_longitude (GstTagList * taglist, const gchar * gst_tag,
+ const gchar * str)
+{
+ deserialize_exif_gps_coordinate (taglist, gst_tag, str, 'E', 'W');
+}
+
/* look at this page for addtional schemas
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/XMP.html
*/
@@ -182,6 +306,13 @@ _init_xmp_tag_map ()
/* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */
_xmp_tag_add_simple_mapping (GST_TAG_VIDEO_CODEC, "dc:format", NULL, NULL);
+ /* exif schema */
+ _xmp_tag_add_simple_mapping (GST_TAG_GEO_LOCATION_LATITUDE,
+ "exif:GPSLatitude", serialize_exif_latitude, deserialize_exif_latitude);
+ _xmp_tag_add_simple_mapping (GST_TAG_GEO_LOCATION_LONGITUDE,
+ "exif:GPSLongitude", serialize_exif_longitude,
+ deserialize_exif_longitude);
+
/* photoshop schema */
_xmp_tag_add_simple_mapping (GST_TAG_GEO_LOCATION_COUNTRY,
"photoshop:Country", NULL, NULL);
diff --git a/tests/check/libs/tag.c b/tests/check/libs/tag.c
index bfe738dc9..619487608 100644
--- a/tests/check/libs/tag.c
+++ b/tests/check/libs/tag.c
@@ -852,6 +852,116 @@ GST_START_TEST (test_xmp_parsing)
GST_END_TEST;
+static void
+do_xmp_tag_serialization_deserialization (const gchar * gsttag, GValue * value)
+{
+ GstTagList *taglist = gst_tag_list_new ();
+ GstTagList *taglist2;
+ GstBuffer *buf;
+ const gchar *name_sent, *name_recv;
+ const GValue *value_sent, *value_recv;
+ gboolean found;
+ gint comparison;
+ gint n_recv;
+ gint n_sent;
+ gint i, j;
+
+ fail_if (FALSE);
+
+ gst_tag_list_add_value (taglist, GST_TAG_MERGE_REPLACE, gsttag, value);
+
+ buf = gst_tag_list_to_xmp_buffer (taglist, TRUE);
+ taglist2 = gst_tag_list_from_xmp_buffer (buf);
+
+ /* verify tags */
+ fail_unless (taglist2 != NULL);
+ n_recv = gst_structure_n_fields (taglist2);
+ n_sent = gst_structure_n_fields (taglist);
+ fail_unless (n_recv == n_sent);
+
+ /* FIXME: compare taglist values */
+ for (i = 0; i < n_sent; i++) {
+ name_sent = gst_structure_nth_field_name (taglist, i);
+ value_sent = gst_structure_get_value (taglist, name_sent);
+ found = FALSE;
+ for (j = 0; j < n_recv; j++) {
+ name_recv = gst_structure_nth_field_name (taglist2, j);
+ if (!strcmp (name_sent, name_recv)) {
+ value_recv = gst_structure_get_value (taglist2, name_recv);
+ comparison = gst_value_compare (value_sent, value_recv);
+ if (comparison != GST_VALUE_EQUAL) {
+ gchar *vs = g_strdup_value_contents (value_sent);
+ gchar *vr = g_strdup_value_contents (value_recv);
+ GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'",
+ G_VALUE_TYPE_NAME (value_sent), vs,
+ G_VALUE_TYPE_NAME (value_recv), vr);
+ g_free (vs);
+ g_free (vr);
+ }
+ fail_unless (comparison == GST_VALUE_EQUAL,
+ "tag item %s has been received with different type or value",
+ name_sent);
+ found = TRUE;
+ break;
+ }
+ }
+ fail_unless (found, "tag item %s is lost", name_sent);
+ }
+
+ gst_buffer_unref (buf);
+ gst_tag_list_free (taglist);
+ gst_tag_list_free (taglist2);
+}
+
+GST_START_TEST (test_xmp_tags_serialization_deserialization)
+{
+ GValue value = { 0 };
+ GDate *date;
+
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_static_string (&value, "my string");
+ do_xmp_tag_serialization_deserialization (GST_TAG_ARTIST, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_COPYRIGHT, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DESCRIPTION, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_KEYWORDS, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_TITLE, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_VIDEO_CODEC, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_COUNTRY,
+ &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_CITY, &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_SUBLOCATION,
+ &value);
+
+ g_value_unset (&value);
+ g_value_init (&value, G_TYPE_DOUBLE);
+
+ g_value_set_double (&value, 0.0);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LATITUDE,
+ &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LONGITUDE,
+ &value);
+ g_value_set_double (&value, 10.5);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LATITUDE,
+ &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LONGITUDE,
+ &value);
+ g_value_set_double (&value, -32.375);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LATITUDE,
+ &value);
+ do_xmp_tag_serialization_deserialization (GST_TAG_GEO_LOCATION_LONGITUDE,
+ &value);
+ g_value_unset (&value);
+
+ g_value_init (&value, GST_TYPE_DATE);
+ date = g_date_new_dmy (22, 3, 2010);
+ gst_value_set_date (&value, date);
+ g_date_free (date);
+ do_xmp_tag_serialization_deserialization (GST_TAG_DATE, &value);
+ g_value_unset (&value);
+}
+
+GST_END_TEST;
+
static Suite *
tag_suite (void)
@@ -868,6 +978,7 @@ tag_suite (void)
tcase_add_test (tc_chain, test_language_utils);
tcase_add_test (tc_chain, test_xmp_formatting);
tcase_add_test (tc_chain, test_xmp_parsing);
+ tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization);
return s;
}