mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-24 01:00:37 +00:00
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:
parent
fe1f3e3595
commit
7ebbfbd3a5
2 changed files with 242 additions and 0 deletions
|
@ -157,6 +157,130 @@ _xmp_tag_get_mapping_reverse (const gchar * xmp_tag, XmpTag ** _xmp_tag)
|
||||||
return ret;
|
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
|
/* look at this page for addtional schemas
|
||||||
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/XMP.html
|
* 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 */
|
/* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */
|
||||||
_xmp_tag_add_simple_mapping (GST_TAG_VIDEO_CODEC, "dc:format", NULL, NULL);
|
_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 */
|
/* photoshop schema */
|
||||||
_xmp_tag_add_simple_mapping (GST_TAG_GEO_LOCATION_COUNTRY,
|
_xmp_tag_add_simple_mapping (GST_TAG_GEO_LOCATION_COUNTRY,
|
||||||
"photoshop:Country", NULL, NULL);
|
"photoshop:Country", NULL, NULL);
|
||||||
|
|
|
@ -852,6 +852,116 @@ GST_START_TEST (test_xmp_parsing)
|
||||||
|
|
||||||
GST_END_TEST;
|
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 *
|
static Suite *
|
||||||
tag_suite (void)
|
tag_suite (void)
|
||||||
|
@ -868,6 +978,7 @@ tag_suite (void)
|
||||||
tcase_add_test (tc_chain, test_language_utils);
|
tcase_add_test (tc_chain, test_language_utils);
|
||||||
tcase_add_test (tc_chain, test_xmp_formatting);
|
tcase_add_test (tc_chain, test_xmp_formatting);
|
||||||
tcase_add_test (tc_chain, test_xmp_parsing);
|
tcase_add_test (tc_chain, test_xmp_parsing);
|
||||||
|
tcase_add_test (tc_chain, test_xmp_tags_serialization_deserialization);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue