tag: xmp: Adds mappings for LATITUDE and LONGITUDE

Adds the mappings for those tags and tests
for tags serialization.

Fixes #613690
This commit is contained in:
Thiago Santos 2010-03-22 15:18:28 -03:00
parent fe1f3e3595
commit 7ebbfbd3a5
2 changed files with 242 additions and 0 deletions

View file

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

View file

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