mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 00:36:51 +00:00
tag: xmp: Add struct xmp tag type support
Adds support for writing the xmp struct tag type, it is a compound tag that has inner tags.
This commit is contained in:
parent
d764676583
commit
1b29009bb3
1 changed files with 204 additions and 171 deletions
|
@ -112,14 +112,31 @@ xmp_serialization_data_use_schema (XmpSerializationData * serdata,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
GstXmpTagTypeSimple = 0,
|
||||||
|
GstXmpTagTypeBag,
|
||||||
|
GstXmpTagTypeSeq,
|
||||||
|
GstXmpTagTypeStruct,
|
||||||
|
|
||||||
|
/* Not really a xmp type, this is a tag that in gst is represented with
|
||||||
|
* a single value and on xmp it needs 2 (or more) simple values
|
||||||
|
*
|
||||||
|
* e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary
|
||||||
|
* tags in the exif's schema. One of them stores the absolute elevation,
|
||||||
|
* and the other one stores if it is above of below sea level.
|
||||||
|
*/
|
||||||
|
GstXmpTagTypeCompound
|
||||||
|
} GstXmpTagType;
|
||||||
|
|
||||||
#define GST_XMP_TAG_TYPE_SIMPLE 0
|
|
||||||
#define GST_XMP_TAG_TYPE_BAG 1
|
|
||||||
#define GST_XMP_TAG_TYPE_SEQ 2
|
|
||||||
struct _XmpTag
|
struct _XmpTag
|
||||||
{
|
{
|
||||||
|
const gchar *gst_tag;
|
||||||
const gchar *tag_name;
|
const gchar *tag_name;
|
||||||
gint type;
|
GstXmpTagType type;
|
||||||
|
|
||||||
|
/* Used for struct and compound types */
|
||||||
|
GSList *children;
|
||||||
|
|
||||||
XmpSerializationFunc serialize;
|
XmpSerializationFunc serialize;
|
||||||
XmpDeserializationFunc deserialize;
|
XmpDeserializationFunc deserialize;
|
||||||
|
@ -129,10 +146,10 @@ static GstTagMergeMode
|
||||||
xmp_tag_get_merge_mode (XmpTag * xmptag)
|
xmp_tag_get_merge_mode (XmpTag * xmptag)
|
||||||
{
|
{
|
||||||
switch (xmptag->type) {
|
switch (xmptag->type) {
|
||||||
case GST_XMP_TAG_TYPE_BAG:
|
case GstXmpTagTypeBag:
|
||||||
case GST_XMP_TAG_TYPE_SEQ:
|
case GstXmpTagTypeSeq:
|
||||||
return GST_TAG_MERGE_APPEND;
|
return GST_TAG_MERGE_APPEND;
|
||||||
case GST_XMP_TAG_TYPE_SIMPLE:
|
case GstXmpTagTypeSimple:
|
||||||
default:
|
default:
|
||||||
return GST_TAG_MERGE_KEEP;
|
return GST_TAG_MERGE_KEEP;
|
||||||
}
|
}
|
||||||
|
@ -142,11 +159,11 @@ static const gchar *
|
||||||
xmp_tag_get_type_name (XmpTag * xmptag)
|
xmp_tag_get_type_name (XmpTag * xmptag)
|
||||||
{
|
{
|
||||||
switch (xmptag->type) {
|
switch (xmptag->type) {
|
||||||
case GST_XMP_TAG_TYPE_SEQ:
|
case GstXmpTagTypeSeq:
|
||||||
return "rdf:Seq";
|
return "rdf:Seq";
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
case GST_XMP_TAG_TYPE_BAG:
|
case GstXmpTagTypeBag:
|
||||||
return "rdf:Bag";
|
return "rdf:Bag";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -159,14 +176,9 @@ struct _PendingXmpTag
|
||||||
};
|
};
|
||||||
typedef struct _PendingXmpTag PendingXmpTag;
|
typedef struct _PendingXmpTag PendingXmpTag;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A schema is a mapping of strings (the tag name in gstreamer) to a list of
|
* A schema is a mapping of strings (the tag name in gstreamer) to a list of
|
||||||
* tags in xmp (XmpTag). We need a list because some tags are split into 2
|
* tags in xmp (XmpTag).
|
||||||
* when serialized into xmp.
|
|
||||||
* e.g. GST_TAG_GEO_LOCATION_ELEVATION needs to be mapped into 2 complementary
|
|
||||||
* tags in the exif's schema. One of them stores the absolute elevation,
|
|
||||||
* and the other one stores if it is above of below sea level.
|
|
||||||
*/
|
*/
|
||||||
typedef GHashTable GstXmpSchema;
|
typedef GHashTable GstXmpSchema;
|
||||||
#define gst_xmp_schema_lookup g_hash_table_lookup
|
#define gst_xmp_schema_lookup g_hash_table_lookup
|
||||||
|
@ -214,19 +226,59 @@ _gst_xmp_add_schema (const gchar * name, GstXmpSchema * schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_gst_xmp_schema_add_mapping (GstXmpSchema * schema, const gchar * gst_tag,
|
_gst_xmp_schema_add_mapping (GstXmpSchema * schema, XmpTag * tag)
|
||||||
GPtrArray * array)
|
|
||||||
{
|
{
|
||||||
GQuark key;
|
GQuark key;
|
||||||
|
|
||||||
key = g_quark_from_string (gst_tag);
|
key = g_quark_from_string (tag->gst_tag);
|
||||||
|
|
||||||
if (gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key))) {
|
if (gst_xmp_schema_lookup (schema, GUINT_TO_POINTER (key))) {
|
||||||
GST_WARNING ("Tag %s already present for the schema", gst_tag);
|
GST_WARNING ("Tag %s already present for the schema", tag->gst_tag);
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), array);
|
gst_xmp_schema_insert (schema, GUINT_TO_POINTER (key), tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
static XmpTag *
|
||||||
|
gst_xmp_tag_create (const gchar * gst_tag, const gchar * xmp_tag,
|
||||||
|
gint xmp_type, XmpSerializationFunc serialization_func,
|
||||||
|
XmpDeserializationFunc deserialization_func)
|
||||||
|
{
|
||||||
|
XmpTag *xmpinfo;
|
||||||
|
|
||||||
|
xmpinfo = g_slice_new (XmpTag);
|
||||||
|
xmpinfo->gst_tag = gst_tag;
|
||||||
|
xmpinfo->tag_name = xmp_tag;
|
||||||
|
xmpinfo->type = xmp_type;
|
||||||
|
xmpinfo->serialize = serialization_func;
|
||||||
|
xmpinfo->deserialize = deserialization_func;
|
||||||
|
xmpinfo->children = NULL;
|
||||||
|
|
||||||
|
return xmpinfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
static XmpTag *
|
||||||
|
gst_xmp_tag_create_compound (const gchar * gst_tag, const gchar * xmp_tag_a,
|
||||||
|
const gchar * xmp_tag_b, XmpSerializationFunc serialization_func_a,
|
||||||
|
XmpSerializationFunc serialization_func_b,
|
||||||
|
XmpDeserializationFunc deserialization_func)
|
||||||
|
{
|
||||||
|
XmpTag *xmptag;
|
||||||
|
XmpTag *xmptag_a =
|
||||||
|
gst_xmp_tag_create (gst_tag, xmp_tag_a, GstXmpTagTypeSimple,
|
||||||
|
serialization_func_a, deserialization_func);
|
||||||
|
XmpTag *xmptag_b =
|
||||||
|
gst_xmp_tag_create (gst_tag, xmp_tag_b, GstXmpTagTypeSimple,
|
||||||
|
serialization_func_b, deserialization_func);
|
||||||
|
|
||||||
|
xmptag =
|
||||||
|
gst_xmp_tag_create (gst_tag, NULL, GstXmpTagTypeCompound, NULL, NULL);
|
||||||
|
|
||||||
|
xmptag->children = g_slist_prepend (xmptag->children, xmptag_b);
|
||||||
|
xmptag->children = g_slist_prepend (xmptag->children, xmptag_a);
|
||||||
|
|
||||||
|
return xmptag;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -235,19 +287,9 @@ _gst_xmp_schema_add_simple_mapping (GstXmpSchema * schema,
|
||||||
XmpSerializationFunc serialization_func,
|
XmpSerializationFunc serialization_func,
|
||||||
XmpDeserializationFunc deserialization_func)
|
XmpDeserializationFunc deserialization_func)
|
||||||
{
|
{
|
||||||
XmpTag *xmpinfo;
|
_gst_xmp_schema_add_mapping (schema,
|
||||||
GPtrArray *array;
|
gst_xmp_tag_create (gst_tag, xmp_tag, xmp_type, serialization_func,
|
||||||
|
deserialization_func));
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
|
||||||
xmpinfo->tag_name = xmp_tag;
|
|
||||||
xmpinfo->type = xmp_type;
|
|
||||||
xmpinfo->serialize = serialization_func;
|
|
||||||
xmpinfo->deserialize = deserialization_func;
|
|
||||||
|
|
||||||
array = g_ptr_array_sized_new (1);
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
|
|
||||||
_gst_xmp_schema_add_mapping (schema, gst_tag, array);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -286,22 +328,30 @@ _gst_xmp_schema_get_mapping_reverse (GstXmpSchema * schema,
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
gpointer key, value;
|
gpointer key, value;
|
||||||
const gchar *ret = NULL;
|
const gchar *ret = NULL;
|
||||||
gint index;
|
|
||||||
|
|
||||||
/* Iterate over the hashtable */
|
/* Iterate over the hashtable */
|
||||||
g_hash_table_iter_init (&iter, schema);
|
g_hash_table_iter_init (&iter, schema);
|
||||||
while (!ret && g_hash_table_iter_next (&iter, &key, &value)) {
|
while (!ret && g_hash_table_iter_next (&iter, &key, &value)) {
|
||||||
GPtrArray *array = (GPtrArray *) value;
|
XmpTag *xmpinfo = (XmpTag *) value;
|
||||||
|
|
||||||
/* each mapping might contain complementary tags */
|
|
||||||
for (index = 0; index < array->len; index++) {
|
|
||||||
XmpTag *xmpinfo = (XmpTag *) g_ptr_array_index (array, index);
|
|
||||||
|
|
||||||
|
if (xmpinfo->tag_name) {
|
||||||
if (strcmp (xmpinfo->tag_name, xmp_tag) == 0) {
|
if (strcmp (xmpinfo->tag_name, xmp_tag) == 0) {
|
||||||
*_xmp_tag = xmpinfo;
|
*_xmp_tag = xmpinfo;
|
||||||
ret = g_quark_to_string (GPOINTER_TO_UINT (key));
|
ret = g_quark_to_string (GPOINTER_TO_UINT (key));
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
} else if (xmpinfo->children) {
|
||||||
|
GSList *iter;
|
||||||
|
for (iter = xmpinfo->children; iter; iter = g_slist_next (iter)) {
|
||||||
|
XmpTag *child = iter->data;
|
||||||
|
if (strcmp (child->tag_name, xmp_tag) == 0) {
|
||||||
|
*_xmp_tag = child;
|
||||||
|
ret = g_quark_to_string (GPOINTER_TO_UINT (key));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -856,7 +906,6 @@ deserialize_tiff_orientation (XmpTag * xmptag, GstTagList * taglist,
|
||||||
static gpointer
|
static gpointer
|
||||||
_init_xmp_tag_map (gpointer user_data)
|
_init_xmp_tag_map (gpointer user_data)
|
||||||
{
|
{
|
||||||
GPtrArray *array;
|
|
||||||
XmpTag *xmpinfo;
|
XmpTag *xmpinfo;
|
||||||
GstXmpSchema *schema;
|
GstXmpSchema *schema;
|
||||||
|
|
||||||
|
@ -868,136 +917,95 @@ _init_xmp_tag_map (gpointer user_data)
|
||||||
*/
|
*/
|
||||||
schema = gst_xmp_schema_new ();
|
schema = gst_xmp_schema_new ();
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_ARTIST,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_ARTIST,
|
||||||
"dc:creator", GST_XMP_TAG_TYPE_SEQ, NULL, NULL);
|
"dc:creator", GstXmpTagTypeSeq, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_COPYRIGHT,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_COPYRIGHT,
|
||||||
"dc:rights", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"dc:rights", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE, "dc:date",
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE, "dc:date",
|
||||||
GST_XMP_TAG_TYPE_SEQ, NULL, NULL);
|
GstXmpTagTypeSeq, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DESCRIPTION,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DESCRIPTION,
|
||||||
"dc:description", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"dc:description", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_KEYWORDS,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_KEYWORDS,
|
||||||
"dc:subject", GST_XMP_TAG_TYPE_BAG, NULL, NULL);
|
"dc:subject", GstXmpTagTypeBag, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_TITLE, "dc:title",
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_TITLE, "dc:title",
|
||||||
GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
GstXmpTagTypeSimple, NULL, NULL);
|
||||||
/* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */
|
/* FIXME: we probably want GST_TAG_{,AUDIO_,VIDEO_}MIME_TYPE */
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_VIDEO_CODEC,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_VIDEO_CODEC,
|
||||||
"dc:format", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"dc:format", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_add_schema ("dc", schema);
|
_gst_xmp_add_schema ("dc", schema);
|
||||||
|
|
||||||
/* xap (xmp) schema */
|
/* xap (xmp) schema */
|
||||||
schema = gst_xmp_schema_new ();
|
schema = gst_xmp_schema_new ();
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_USER_RATING,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_USER_RATING,
|
||||||
"xmp:Rating", GST_XMP_TAG_TYPE_SIMPLE, NULL, deserialize_xmp_rating);
|
"xmp:Rating", GstXmpTagTypeSimple, NULL, deserialize_xmp_rating);
|
||||||
_gst_xmp_add_schema ("xap", schema);
|
_gst_xmp_add_schema ("xap", schema);
|
||||||
|
|
||||||
/* tiff */
|
/* tiff */
|
||||||
schema = gst_xmp_schema_new ();
|
schema = gst_xmp_schema_new ();
|
||||||
_gst_xmp_schema_add_simple_mapping (schema,
|
_gst_xmp_schema_add_simple_mapping (schema,
|
||||||
GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GST_XMP_TAG_TYPE_SIMPLE, NULL,
|
GST_TAG_DEVICE_MANUFACTURER, "tiff:Make", GstXmpTagTypeSimple, NULL,
|
||||||
NULL);
|
NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DEVICE_MODEL,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DEVICE_MODEL,
|
||||||
"tiff:Model", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"tiff:Model", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_APPLICATION_NAME,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_APPLICATION_NAME,
|
||||||
"tiff:Software", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"tiff:Software", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_IMAGE_ORIENTATION,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_IMAGE_ORIENTATION,
|
||||||
"tiff:Orientation", GST_XMP_TAG_TYPE_SIMPLE, serialize_tiff_orientation,
|
"tiff:Orientation", GstXmpTagTypeSimple, serialize_tiff_orientation,
|
||||||
deserialize_tiff_orientation);
|
deserialize_tiff_orientation);
|
||||||
_gst_xmp_add_schema ("tiff", schema);
|
_gst_xmp_add_schema ("tiff", schema);
|
||||||
|
|
||||||
/* exif schema */
|
/* exif schema */
|
||||||
schema = gst_xmp_schema_new ();
|
schema = gst_xmp_schema_new ();
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE_TIME,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_DATE_TIME,
|
||||||
"exif:DateTimeOriginal", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"exif:DateTimeOriginal", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema,
|
_gst_xmp_schema_add_simple_mapping (schema,
|
||||||
GST_TAG_GEO_LOCATION_LATITUDE, "exif:GPSLatitude",
|
GST_TAG_GEO_LOCATION_LATITUDE, "exif:GPSLatitude",
|
||||||
GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_latitude,
|
GstXmpTagTypeSimple, serialize_exif_latitude, deserialize_exif_latitude);
|
||||||
deserialize_exif_latitude);
|
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_LONGITUDE,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_LONGITUDE,
|
||||||
"exif:GPSLongitude", GST_XMP_TAG_TYPE_SIMPLE, serialize_exif_longitude,
|
"exif:GPSLongitude", GstXmpTagTypeSimple, serialize_exif_longitude,
|
||||||
deserialize_exif_longitude);
|
deserialize_exif_longitude);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema,
|
_gst_xmp_schema_add_simple_mapping (schema,
|
||||||
GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, "exif:ExposureBiasValue",
|
GST_TAG_CAPTURING_EXPOSURE_COMPENSATION, "exif:ExposureBiasValue",
|
||||||
GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
GstXmpTagTypeSimple, NULL, NULL);
|
||||||
|
|
||||||
/* compound exif tags */
|
/* compound exif tags */
|
||||||
array = g_ptr_array_sized_new (2);
|
xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_ELEVATION,
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
"exif:GPSAltitude", "exif:GPSAltitudeRef", serialize_exif_altitude,
|
||||||
xmpinfo->tag_name = "exif:GPSAltitude";
|
serialize_exif_altituderef, deserialize_exif_altitude);
|
||||||
xmpinfo->serialize = serialize_exif_altitude;
|
_gst_xmp_schema_add_mapping (schema, xmpinfo);
|
||||||
xmpinfo->deserialize = deserialize_exif_altitude;
|
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
|
||||||
xmpinfo->tag_name = "exif:GPSAltitudeRef";
|
|
||||||
xmpinfo->serialize = serialize_exif_altituderef;
|
|
||||||
xmpinfo->deserialize = deserialize_exif_altitude;
|
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
_gst_xmp_schema_add_mapping (schema, GST_TAG_GEO_LOCATION_ELEVATION, array);
|
|
||||||
|
|
||||||
array = g_ptr_array_sized_new (2);
|
xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_MOVEMENT_SPEED,
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
"exif:GPSSpeed", "exif:GPSSpeedRef", serialize_exif_gps_speed,
|
||||||
xmpinfo->tag_name = "exif:GPSSpeed";
|
serialize_exif_gps_speedref, deserialize_exif_gps_speed);
|
||||||
xmpinfo->serialize = serialize_exif_gps_speed;
|
_gst_xmp_schema_add_mapping (schema, xmpinfo);
|
||||||
xmpinfo->deserialize = deserialize_exif_gps_speed;
|
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
|
||||||
xmpinfo->tag_name = "exif:GPSSpeedRef";
|
|
||||||
xmpinfo->serialize = serialize_exif_gps_speedref;
|
|
||||||
xmpinfo->deserialize = deserialize_exif_gps_speed;
|
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
_gst_xmp_schema_add_mapping (schema,
|
|
||||||
GST_TAG_GEO_LOCATION_MOVEMENT_SPEED, array);
|
|
||||||
|
|
||||||
array = g_ptr_array_sized_new (2);
|
xmpinfo =
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION,
|
||||||
xmpinfo->tag_name = "exif:GPSTrack";
|
"exif:GPSTrack", "exif:GPSTrackRef", serialize_exif_gps_direction,
|
||||||
xmpinfo->serialize = serialize_exif_gps_direction;
|
serialize_exif_gps_directionref, deserialize_exif_gps_track);
|
||||||
xmpinfo->deserialize = deserialize_exif_gps_track;
|
_gst_xmp_schema_add_mapping (schema, xmpinfo);
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
xmpinfo = gst_xmp_tag_create_compound (GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION,
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
"exif:GPSImgDirection", "exif:GPSImgDirectionRef",
|
||||||
xmpinfo->tag_name = "exif:GPSTrackRef";
|
serialize_exif_gps_direction, serialize_exif_gps_directionref,
|
||||||
xmpinfo->serialize = serialize_exif_gps_directionref;
|
deserialize_exif_gps_img_direction);
|
||||||
xmpinfo->deserialize = deserialize_exif_gps_track;
|
_gst_xmp_schema_add_mapping (schema, xmpinfo);
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
_gst_xmp_schema_add_mapping (schema,
|
|
||||||
GST_TAG_GEO_LOCATION_MOVEMENT_DIRECTION, array);
|
|
||||||
|
|
||||||
array = g_ptr_array_sized_new (2);
|
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
|
||||||
xmpinfo->tag_name = "exif:GPSImgDirection";
|
|
||||||
xmpinfo->serialize = serialize_exif_gps_direction;
|
|
||||||
xmpinfo->deserialize = deserialize_exif_gps_img_direction;
|
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
xmpinfo = g_slice_new (XmpTag);
|
|
||||||
xmpinfo->tag_name = "exif:GPSImgDirectionRef";
|
|
||||||
xmpinfo->serialize = serialize_exif_gps_directionref;
|
|
||||||
xmpinfo->deserialize = deserialize_exif_gps_img_direction;
|
|
||||||
xmpinfo->type = GST_XMP_TAG_TYPE_SIMPLE;
|
|
||||||
g_ptr_array_add (array, xmpinfo);
|
|
||||||
_gst_xmp_schema_add_mapping (schema,
|
|
||||||
GST_TAG_GEO_LOCATION_CAPTURE_DIRECTION, array);
|
|
||||||
_gst_xmp_add_schema ("exif", schema);
|
_gst_xmp_add_schema ("exif", schema);
|
||||||
|
|
||||||
/* photoshop schema */
|
/* photoshop schema */
|
||||||
schema = gst_xmp_schema_new ();
|
schema = gst_xmp_schema_new ();
|
||||||
_gst_xmp_schema_add_simple_mapping (schema,
|
_gst_xmp_schema_add_simple_mapping (schema,
|
||||||
GST_TAG_GEO_LOCATION_COUNTRY, "photoshop:Country",
|
GST_TAG_GEO_LOCATION_COUNTRY, "photoshop:Country",
|
||||||
GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_CITY,
|
_gst_xmp_schema_add_simple_mapping (schema, GST_TAG_GEO_LOCATION_CITY,
|
||||||
"photoshop:City", GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
"photoshop:City", GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_add_schema ("photoshop", schema);
|
_gst_xmp_add_schema ("photoshop", schema);
|
||||||
|
|
||||||
/* iptc4xmpcore schema */
|
/* iptc4xmpcore schema */
|
||||||
schema = gst_xmp_schema_new ();
|
schema = gst_xmp_schema_new ();
|
||||||
_gst_xmp_schema_add_simple_mapping (schema,
|
_gst_xmp_schema_add_simple_mapping (schema,
|
||||||
GST_TAG_GEO_LOCATION_SUBLOCATION, "Iptc4xmpCore:Location",
|
GST_TAG_GEO_LOCATION_SUBLOCATION, "Iptc4xmpCore:Location",
|
||||||
GST_XMP_TAG_TYPE_SIMPLE, NULL, NULL);
|
GstXmpTagTypeSimple, NULL, NULL);
|
||||||
_gst_xmp_add_schema ("Iptc4xmpCore", schema);
|
_gst_xmp_add_schema ("Iptc4xmpCore", schema);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1540,33 +1548,64 @@ gst_value_serialize_xmp (const GValue * value)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
write_one_tag (const GstTagList * list, const gchar * tag,
|
write_one_tag (const GstTagList * list, XmpTag * xmp_tag, gpointer user_data)
|
||||||
GPtrArray * xmp_tag_array, gpointer user_data)
|
|
||||||
{
|
{
|
||||||
guint i = 0, ct = gst_tag_list_get_tag_size (list, tag), tag_index;
|
guint i = 0, ct;
|
||||||
XmpSerializationData *serialization_data = user_data;
|
XmpSerializationData *serialization_data = user_data;
|
||||||
GString *data = serialization_data->data;
|
GString *data = serialization_data->data;
|
||||||
char *s;
|
char *s;
|
||||||
|
|
||||||
for (tag_index = 0; tag_index < xmp_tag_array->len; tag_index++) {
|
/* struct type handled differently */
|
||||||
XmpTag *xmp_tag;
|
if (xmp_tag->type == GstXmpTagTypeStruct ||
|
||||||
|
xmp_tag->type == GstXmpTagTypeCompound) {
|
||||||
|
GSList *iter;
|
||||||
|
gboolean use_it = FALSE;
|
||||||
|
|
||||||
xmp_tag = g_ptr_array_index (xmp_tag_array, tag_index);
|
/* check if any of the inner tags are present on the taglist */
|
||||||
|
for (iter = xmp_tag->children; iter && !use_it; iter = g_slist_next (iter)) {
|
||||||
|
XmpTag *child_tag = iter->data;
|
||||||
|
|
||||||
|
if (gst_tag_list_get_value_index (list, child_tag->gst_tag, 0) != NULL) {
|
||||||
|
use_it = TRUE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (use_it) {
|
||||||
|
if (xmp_tag->tag_name)
|
||||||
|
string_open_tag (data, xmp_tag->tag_name);
|
||||||
|
/* now write it */
|
||||||
|
for (iter = xmp_tag->children; iter; iter = g_slist_next (iter)) {
|
||||||
|
write_one_tag (list, iter->data, user_data);
|
||||||
|
}
|
||||||
|
if (xmp_tag->tag_name)
|
||||||
|
string_close_tag (data, xmp_tag->tag_name);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* at this point we must have a gst_tag */
|
||||||
|
g_assert (xmp_tag->gst_tag);
|
||||||
|
if (gst_tag_list_get_value_index (list, xmp_tag->gst_tag, 0) == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ct = gst_tag_list_get_tag_size (list, xmp_tag->gst_tag);
|
||||||
string_open_tag (data, xmp_tag->tag_name);
|
string_open_tag (data, xmp_tag->tag_name);
|
||||||
|
|
||||||
/* fast path for single valued tag */
|
/* fast path for single valued tag */
|
||||||
if (ct == 1 || xmp_tag->type == GST_XMP_TAG_TYPE_SIMPLE) {
|
if (ct == 1 || xmp_tag->type == GstXmpTagTypeSimple) {
|
||||||
if (xmp_tag->serialize) {
|
if (xmp_tag->serialize) {
|
||||||
s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, 0));
|
s = xmp_tag->serialize (gst_tag_list_get_value_index (list,
|
||||||
|
xmp_tag->gst_tag, 0));
|
||||||
} else {
|
} else {
|
||||||
s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag,
|
s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list,
|
||||||
0));
|
xmp_tag->gst_tag, 0));
|
||||||
}
|
}
|
||||||
if (s) {
|
if (s) {
|
||||||
g_string_append (data, s);
|
g_string_append (data, s);
|
||||||
g_free (s);
|
g_free (s);
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("unhandled type for %s to xmp", tag);
|
GST_WARNING ("unhandled type for %s to xmp", xmp_tag->gst_tag);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const gchar *typename;
|
const gchar *typename;
|
||||||
|
@ -1575,12 +1614,13 @@ write_one_tag (const GstTagList * list, const gchar * tag,
|
||||||
|
|
||||||
string_open_tag (data, typename);
|
string_open_tag (data, typename);
|
||||||
for (i = 0; i < ct; i++) {
|
for (i = 0; i < ct; i++) {
|
||||||
GST_DEBUG ("mapping %s[%u/%u] to xmp", tag, i, ct);
|
GST_DEBUG ("mapping %s[%u/%u] to xmp", xmp_tag->gst_tag, i, ct);
|
||||||
if (xmp_tag->serialize) {
|
if (xmp_tag->serialize) {
|
||||||
s = xmp_tag->serialize (gst_tag_list_get_value_index (list, tag, i));
|
s = xmp_tag->serialize (gst_tag_list_get_value_index (list,
|
||||||
|
xmp_tag->gst_tag, i));
|
||||||
} else {
|
} else {
|
||||||
s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list, tag,
|
s = gst_value_serialize_xmp (gst_tag_list_get_value_index (list,
|
||||||
i));
|
xmp_tag->gst_tag, i));
|
||||||
}
|
}
|
||||||
if (s) {
|
if (s) {
|
||||||
string_open_tag (data, "rdf:li");
|
string_open_tag (data, "rdf:li");
|
||||||
|
@ -1588,7 +1628,7 @@ write_one_tag (const GstTagList * list, const gchar * tag,
|
||||||
string_close_tag (data, "rdf:li");
|
string_close_tag (data, "rdf:li");
|
||||||
g_free (s);
|
g_free (s);
|
||||||
} else {
|
} else {
|
||||||
GST_WARNING ("unhandled type for %s to xmp", tag);
|
GST_WARNING ("unhandled type for %s to xmp", xmp_tag->gst_tag);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
string_close_tag (data, typename);
|
string_close_tag (data, typename);
|
||||||
|
@ -1596,7 +1636,6 @@ write_one_tag (const GstTagList * list, const gchar * tag,
|
||||||
|
|
||||||
string_close_tag (data, xmp_tag->tag_name);
|
string_close_tag (data, xmp_tag->tag_name);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_tag_list_to_xmp_buffer_full:
|
* gst_tag_list_to_xmp_buffer_full:
|
||||||
|
@ -1652,7 +1691,6 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only,
|
||||||
/* use all schemas */
|
/* use all schemas */
|
||||||
schemas = gst_tag_xmp_list_schemas ();
|
schemas = gst_tag_xmp_list_schemas ();
|
||||||
}
|
}
|
||||||
i = 0;
|
|
||||||
for (i = 0; schemas[i] != NULL; i++) {
|
for (i = 0; schemas[i] != NULL; i++) {
|
||||||
GstXmpSchema *schema = _gst_xmp_get_schema (schemas[i]);
|
GstXmpSchema *schema = _gst_xmp_get_schema (schemas[i]);
|
||||||
GHashTableIter iter;
|
GHashTableIter iter;
|
||||||
|
@ -1664,12 +1702,7 @@ gst_tag_list_to_xmp_buffer_full (const GstTagList * list, gboolean read_only,
|
||||||
/* Iterate over the hashtable */
|
/* Iterate over the hashtable */
|
||||||
g_hash_table_iter_init (&iter, schema);
|
g_hash_table_iter_init (&iter, schema);
|
||||||
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
while (g_hash_table_iter_next (&iter, &key, &value)) {
|
||||||
const gchar *tag = g_quark_to_string (GPOINTER_TO_UINT (key));
|
write_one_tag (list, value, (gpointer) & serialization_data);
|
||||||
|
|
||||||
if (gst_tag_list_get_value_index (list, tag, 0) != NULL) {
|
|
||||||
write_one_tag (list, tag, value, (gpointer) & serialization_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue