summaryrefslogtreecommitdiffstats
path: root/ext/metadata/metadataexif.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/metadata/metadataexif.c')
-rw-r--r--ext/metadata/metadataexif.c423
1 files changed, 254 insertions, 169 deletions
diff --git a/ext/metadata/metadataexif.c b/ext/metadata/metadataexif.c
index 76dee2a7..39948a6f 100644
--- a/ext/metadata/metadataexif.c
+++ b/ext/metadata/metadataexif.c
@@ -41,23 +41,52 @@
* Boston, MA 02111-1307, USA.
*/
+/*
+ * SECTION: metadataexif
+ * @short_description: This module provides functions to extract tags from
+ * EXIF metadata chunks and create EXIF chunks from metadata tags.
+ * @see_also: #metadatatags.[c/h]
+ *
+ * If libexif isn't available at compilation time, only the whole chunk
+ * (#METADATA_TAG_MAP_WHOLECHUNK) tags is created. It means that individual
+ * tags aren't mapped.
+ *
+ * Last reviewed on 2008-01-24 (0.10.15)
+ */
+
+/*
+ * includes
+ */
+
#include "metadataexif.h"
#include "metadataparseutil.h"
#include "metadatatags.h"
+/*
+ * defines
+ */
+
GST_DEBUG_CATEGORY (gst_metadata_exif_debug);
#define GST_CAT_DEFAULT gst_metadata_exif_debug
+/*
+ * Implementation when libexif isn't available at compilation time
+ */
+
#ifndef HAVE_EXIF
+/*
+ * extern functions implementations
+ */
+
+
void
metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
GstAdapter * adapter, MetadataTagMapping mapping)
{
if (mapping & METADATA_TAG_MAP_WHOLECHUNK) {
- GST_LOG
- ("EXIF not defined, here I should send just one tag as whole chunk");
+ GST_LOG ("EXIF not defined, sending just one tag as whole chunk");
metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_EXIF,
adapter);
}
@@ -73,11 +102,23 @@ metadatamux_exif_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
#else /* ifndef HAVE_EXIF */
+/*
+ * Implementation when libexif is available at compilation time
+ */
+
+/*
+ * includes
+ */
+
#include <libexif/exif-data.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
+/*
+ * enum and types
+ */
+
typedef struct _tag_MEUserData
{
GstTagList *taglist;
@@ -92,10 +133,9 @@ typedef struct _tag_MapIntStr
const gchar *str;
} MapIntStr;
-static void
-exif_data_foreach_content_func (ExifContent * content, void *callback_data);
-
-static void exif_content_foreach_entry_func (ExifEntry * entry, void *);
+/*
+ * defines and static global vars
+ */
/* *INDENT-OFF* */
static MapIntStr mappedTags[] = {
@@ -131,41 +171,47 @@ static MapIntStr mappedTags[] = {
};
/* *INDENT-ON* */
-static const gchar *
-metadataparse_exif_get_tag_from_exif (ExifTag exif, GType * type)
-{
- int i = 0;
+/*
+ * static helper functions declaration
+ */
- while (mappedTags[i].exif) {
- if (exif == mappedTags[i].exif) {
- *type = gst_tag_get_type (mappedTags[i].str);
- break;
- }
- ++i;
- }
+static const gchar *metadataparse_exif_get_tag_from_exif (ExifTag exif,
+ GType * type);
- return mappedTags[i].str;
+static ExifTag
+metadatamux_exif_get_exif_from_tag (const gchar * tag, GType * type,
+ ExifIfd * ifd);
-}
+static void
+metadataparse_exif_data_foreach_content_func (ExifContent * content,
+ void *callback_data);
-static ExifTag
-metadataparse_exif_get_exif_from_tag (const gchar * tag, GType * type,
- ExifIfd * ifd)
-{
- int i = 0;
+static void
+metadataparse_exif_content_foreach_entry_func (ExifEntry * entry,
+ void *user_data);
- while (mappedTags[i].exif) {
- if (0 == strcmp (mappedTags[i].str, tag)) {
- *type = gst_tag_get_type (tag);
- *ifd = mappedTags[i].ifd;
- break;
- }
- ++i;
- }
+static void
+metadatamux_exif_for_each_tag_in_list (const GstTagList * list,
+ const gchar * tag, gpointer user_data);
- return mappedTags[i].exif;
+/*
+ * extern functions implementations
+ */
-}
+/*
+ * metadataparse_exif_tag_list_add:
+ * @taglist: tag list in which extracted tags will be added
+ * @mode: tag list merge mode
+ * @adapter: contains the EXIF metadata chunk
+ * @mapping: if is to extract individual tags and/or the whole chunk.
+ *
+ * This function gets a EXIF chunk (@adapter) and extract tags from it
+ * and the add to @taglist.
+ * Note: The EXIF chunk (@adapetr) must NOT be wrapped by any bytes specific
+ * to any file format
+ *
+ * Returns: nothing
+ */
void
metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
@@ -195,8 +241,8 @@ metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode,
goto done;
}
- exif_data_foreach_content (exif, exif_data_foreach_content_func,
- (void *) &user_data);
+ exif_data_foreach_content (exif,
+ metadataparse_exif_data_foreach_content_func, (void *) &user_data);
done:
@@ -207,44 +253,178 @@ done:
}
-static void
-exif_data_foreach_content_func (ExifContent * content, void *user_data)
+/*
+ * metadatamux_exif_create_chunk_from_tag_list:
+ * @buf: buffer that will have the created EXIF chunk
+ * @size: size of the buffer that will be created
+ * @taglist: list of tags to be added to EXIF chunk
+ *
+ * Get tags from @taglist, create a EXIF chunk based on it and save to @buf.
+ * Note: The EXIF chunk is NOT wrapped by any bytes specific to any file format
+ *
+ * Returns: nothing
+ */
+
+void
+metadatamux_exif_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
+ const GstTagList * taglist)
{
- ExifIfd ifd = exif_content_get_ifd (content);
+ ExifData *ed = NULL;
+ GstBuffer *exif_chunk = NULL;
+ const GValue *val = NULL;
- GST_LOG ("\n Content %p: %s (ifd=%d)", content, exif_ifd_get_name (ifd),
- ifd);
- exif_content_foreach_entry (content, exif_content_foreach_entry_func,
- user_data);
+ if (!(buf && size))
+ goto done;
+ if (*buf) {
+ g_free (*buf);
+ *buf = NULL;
+ }
+ *size = 0;
+
+ val = gst_tag_list_get_value_index (taglist, GST_TAG_EXIF, 0);
+ if (val) {
+ exif_chunk = gst_value_get_buffer (val);
+ if (exif_chunk) {
+ ed = exif_data_new_from_data (GST_BUFFER_DATA (exif_chunk),
+ GST_BUFFER_SIZE (exif_chunk));
+ }
+ }
+
+ if (!ed) {
+ ed = exif_data_new ();
+ exif_data_set_data_type (ed, EXIF_DATA_TYPE_COMPRESSED);
+ exif_data_fix (ed);
+ }
+
+ gst_tag_list_foreach (taglist, metadatamux_exif_for_each_tag_in_list, ed);
+
+ exif_data_save_data (ed, buf, size);
+
+
+done:
+
+ if (ed)
+ exif_data_unref (ed);
+
+ return;
}
-#if 0
-static gboolean
-exif_fast_mdc (glong n, glong d, gulong * m)
-{
- gboolean ret = FALSE;
- static const int a[] =
- { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 39, 41, 43, 47, 49, 53, 0 };
+/*
+ * static helper functions implementation
+ */
+
+/*
+ * metadataparse_exif_get_tag_from_exif:
+ * @exif: EXIF tag to look for
+ * @type: the type of the GStreamer tag mapped to @exif
+ *
+ * This returns the GStreamer tag mapped to an EXIF tag.
+ *
+ * Returns:
+ * <itemizedlist>
+ * <listitem><para>The GStreamer tag mapped to the @exif
+ * </para></listitem>
+ * <listitem><para>%NULL if there is no mapped GST tag for @exif
+ * </para></listitem>
+ * </itemizedlist>
+ */
+
+static const gchar *
+metadataparse_exif_get_tag_from_exif (ExifTag exif, GType * type)
+{
int i = 0;
- *m = 1;
+ while (mappedTags[i].exif) {
+ if (exif == mappedTags[i].exif) {
+ *type = gst_tag_get_type (mappedTags[i].str);
+ break;
+ }
+ ++i;
+ }
+
+ return mappedTags[i].str;
- while (a[i] <= n && a[i] <= d) {
- while ((n % a[i] == 0) && (d % a[i]) == 0) {
- *m *= a[i];
- ret = TRUE;
+}
+
+/*
+ * metadatamux_exif_get_exif_from_tag:
+ * @tag: GST tag to look for
+ * @type: the type of the GStreamer @tag
+ * @ifd: the place into EXIF chunk @exif belongs to.
+ *
+ * This returns thet EXIF tag mapped to an GStreamer @tag.
+ *
+ * Returns:
+ * <itemizedlist>
+ * <listitem><para>The EXIF tag mapped to the GST @tag
+ * </para></listitem>
+ * <listitem><para>0 if there is no mapped EXIF tag for GST @tag
+ * </para></listitem>
+ * </itemizedlist>
+ */
+
+static ExifTag
+metadatamux_exif_get_exif_from_tag (const gchar * tag, GType * type,
+ ExifIfd * ifd)
+{
+ int i = 0;
+
+ while (mappedTags[i].exif) {
+ if (0 == strcmp (mappedTags[i].str, tag)) {
+ *type = gst_tag_get_type (tag);
+ *ifd = mappedTags[i].ifd;
+ break;
}
++i;
}
- return ret;
+ return mappedTags[i].exif;
}
-#endif
+
+/*
+ * metadataparse_exif_data_foreach_content_func:
+ * @content: EXIF structure from libexif containg a IFD
+ * @user_data: pointer to #MEUserData
+ *
+ * This function designed to be called for each EXIF IFD in a EXIF chunk. This
+ * function gets calls another function for each tag into @content. Then all
+ * tags into a EXIF chunk can be extracted to a tag list in @user_data.
+ * @see_also: #metadataparse_exif_tag_list_add
+ * #metadataparse_exif_content_foreach_entry_func
+ *
+ * Returns: nothing
+ */
static void
-exif_content_foreach_entry_func (ExifEntry * entry, void *user_data)
+metadataparse_exif_data_foreach_content_func (ExifContent * content,
+ void *user_data)
+{
+ ExifIfd ifd = exif_content_get_ifd (content);
+
+ GST_LOG ("\n Content %p: %s (ifd=%d)", content, exif_ifd_get_name (ifd),
+ ifd);
+ exif_content_foreach_entry (content,
+ metadataparse_exif_content_foreach_entry_func, user_data);
+}
+
+/*
+ * metadataparse_exif_content_foreach_entry_func:
+ * @entry: EXIF structure from libexif having a EXIF tag
+ * @user_data: pointer to #MEUserData
+ *
+ * This function designed to be called for each EXIF tag in a EXIF IFD. This
+ * function gets the EXIF tag from @entry and then add to the tag list
+ * in @user_data by using a merge mode also specified in @user_data
+ * @see_also: #metadataparse_exif_data_foreach_content_func
+ *
+ * Returns: nothing
+ */
+
+static void
+metadataparse_exif_content_foreach_entry_func (ExifEntry * entry,
+ void *user_data)
{
char buf[2048];
MEUserData *meudata = (MEUserData *) user_data;
@@ -390,76 +570,22 @@ done:
}
/*
+ * metadatamux_exif_for_each_tag_in_list:
+ * @list: GStreamer tag list from which @tag belongs to
+ * @tag: GStreamer tag to be added to the EXIF chunk
+ * @user_data: pointer to #ExifData in which the tag will be added
*
+ * This function designed to be called for each tag in GST tag list. This
+ * function adds get the tag value from tag @list and then add it to the EXIF
+ * chunk by using #ExifData and related functions from libexif
+ * @see_also: #metadatamux_exif_create_chunk_from_tag_list
+ *
+ * Returns: nothing
*/
-static ExifRational
-float_to_rational (gfloat f)
-{
- ExifRational r;
- int i = 6; /* precision */
-
- r.denominator = 1;
-
- while (i--) {
- if (f == floorf (f)) {
- break;
- }
- f *= 10.0f;
- r.denominator *= 10;
- }
-
- r.numerator = f;
-
- if (!(r.numerator & 0x1 || r.denominator & 0x1)) {
- /* divide both by 2 */
- r.numerator >>= 1;
- r.denominator >>= 1;
- }
- if (r.numerator % 5 == 0 && r.denominator % 5 == 0) {
- r.numerator /= 5;
- r.denominator /= 5;
- }
-
- return r;
-
-}
-
-static ExifSRational
-float_to_srational (gfloat f)
-{
- ExifSRational sr;
- int i = 6; /* precision */
-
- sr.denominator = 1;
-
- while (i--) {
- if (f == floorf (f)) {
- break;
- }
- f *= 10.0f;
- sr.denominator *= 10;
- }
-
- sr.numerator = f;
-
- if (!(sr.numerator & 0x1 || sr.denominator & 0x1)) {
- /* divide both by 2 */
- sr.numerator >>= 1;
- sr.denominator >>= 1;
- }
- if (sr.numerator % 5 == 0 && sr.denominator % 5 == 0) {
- sr.numerator /= 5;
- sr.denominator /= 5;
- }
-
- return sr;
-
-}
-
static void
-metadataexif_for_each_tag_in_list (const GstTagList * list, const gchar * tag,
- gpointer user_data)
+metadatamux_exif_for_each_tag_in_list (const GstTagList * list,
+ const gchar * tag, gpointer user_data)
{
ExifData *ed = (ExifData *) user_data;
ExifTag exif_tag;
@@ -468,7 +594,7 @@ metadataexif_for_each_tag_in_list (const GstTagList * list, const gchar * tag,
ExifIfd ifd;
const ExifByteOrder byte_order = exif_data_get_byte_order (ed);
- exif_tag = metadataparse_exif_get_exif_from_tag (tag, &type, &ifd);
+ exif_tag = metadatamux_exif_get_exif_from_tag (tag, &type, &ifd);
if (!exif_tag)
goto done;
@@ -505,7 +631,9 @@ metadataexif_for_each_tag_in_list (const GstTagList * list, const gchar * tag,
entry->tag == EXIF_TAG_Y_RESOLUTION) {
ExifEntry *unit_entry = NULL;
- if ((unit_entry = exif_data_get_entry (ed, EXIF_TAG_RESOLUTION_UNIT))) {
+ unit_entry = exif_data_get_entry (ed, EXIF_TAG_RESOLUTION_UNIT);
+
+ if (unit_entry) {
ExifShort vsh = exif_get_short (unit_entry->data, byte_order);
if (vsh != 2) /* inches */
@@ -568,48 +696,5 @@ done:
}
-void
-metadatamux_exif_create_chunk_from_tag_list (guint8 ** buf, guint32 * size,
- const GstTagList * taglist)
-{
- ExifData *ed = NULL;
- GstBuffer *exif_chunk = NULL;
- const GValue *val = NULL;
-
- if (!(buf && size))
- goto done;
- if (*buf) {
- g_free (*buf);
- *buf = NULL;
- }
- *size = 0;
-
- val = gst_tag_list_get_value_index (taglist, GST_TAG_EXIF, 0);
- if (val) {
- exif_chunk = gst_value_get_buffer (val);
- if (exif_chunk) {
- ed = exif_data_new_from_data (GST_BUFFER_DATA (exif_chunk),
- GST_BUFFER_SIZE (exif_chunk));
- }
- }
-
- if (!ed) {
- ed = exif_data_new ();
- exif_data_set_data_type (ed, EXIF_DATA_TYPE_COMPRESSED);
- exif_data_fix (ed);
- }
-
- gst_tag_list_foreach (taglist, metadataexif_for_each_tag_in_list, ed);
-
- exif_data_save_data (ed, buf, size);
-
-
-done:
-
- if (ed)
- exif_data_unref (ed);
-
- return;
-}
#endif /* else (ifndef HAVE_EXIF) */