diff options
author | Edgard Lima <edgard.lima@indt.org.br> | 2007-12-21 19:01:00 +0000 |
---|---|---|
committer | Edgard Lima <edgard.lima@indt.org.br> | 2007-12-21 19:01:00 +0000 |
commit | 21962cbffe8d7255726b34bfc3a773ffcc3fa43b (patch) | |
tree | 9aba4437a94b989a7fd091c380135bb818d30f49 /ext/metadata | |
parent | 0f2ac9fe8b5c7f37e61f3eef95299098ce953f1e (diff) | |
download | gst-plugins-bad-21962cbffe8d7255726b34bfc3a773ffcc3fa43b.tar.gz gst-plugins-bad-21962cbffe8d7255726b34bfc3a773ffcc3fa43b.tar.bz2 gst-plugins-bad-21962cbffe8d7255726b34bfc3a773ffcc3fa43b.zip |
Some IPTC tags mapped.
Original commit message from CVS:
Some IPTC tags mapped.
Diffstat (limited to 'ext/metadata')
-rw-r--r-- | ext/metadata/TODO | 10 | ||||
-rw-r--r-- | ext/metadata/gstbasemetadata.c | 46 | ||||
-rw-r--r-- | ext/metadata/gstbasemetadata.h | 10 | ||||
-rw-r--r-- | ext/metadata/metadata.h | 3 | ||||
-rw-r--r-- | ext/metadata/metadataiptc.c | 150 | ||||
-rw-r--r-- | ext/metadata/metadatamuxjpeg.c | 43 | ||||
-rw-r--r-- | ext/metadata/metadataparsejpeg.c | 4 | ||||
-rw-r--r-- | ext/metadata/metadataparseutil.c | 1 |
8 files changed, 215 insertions, 52 deletions
diff --git a/ext/metadata/TODO b/ext/metadata/TODO index 1cb063ec..77245761 100644 --- a/ext/metadata/TODO +++ b/ext/metadata/TODO @@ -1,11 +1,14 @@ This file contains a list of things to be done as well some open issues (questions) related to design/implementation. -* I (Edgard Lima - alima - edgard.lima@indt.org.br) will be on vacation until 05-Jan-2008. After that I will be back on it. +INFO: + +1- I (Edgard Lima - alima - edgard.lima@indt.org.br) will be on vacation until 05-Jan-2008. After that I will be back on it. +2- to see what tags are mapped so far run 'grep -n GST_TAG *.[ch]' into this folder. TODO: -1- Add individual tags IPTC and XMP (and more for EXIF) +1- Add individual XMP tags (and more for EXIF and IPTC) 2- Get properties like 'width' and 'height' from caps 3- Review the code (in order to move to gst-plugins-good) 4- Document how the plugin works (atchitecture and interaction beteween modules) @@ -17,8 +20,9 @@ OPEN ISSUES: ex: file.jpeg has XMP, then we do filesrc ! metadataparse ! jpegdec ! pngenc ! metadatamux ! files is the metadata still valid? which fields are no valid anymore? 3- Add GST_TYPE_FRACTION support for GStreamer TAGS +4- currently, in JPEG files, if there is a Photoshop segment, everything inside it but IPTC will be lost. From the point of view of implementation it is easy, but I still don't now how to solve from the point of view of "designing". Anyway I think it is not so important. KNOWN BUGS 1- exposure-time, exposure-program and fnumber can't be read from a file saved from scratch (whithout WHOLE_CHUNK from previous file) - I believe it is a bu in libexif + I believe it is a bug in libexif diff --git a/ext/metadata/gstbasemetadata.c b/ext/metadata/gstbasemetadata.c index 858145fe..75b515fd 100644 --- a/ext/metadata/gstbasemetadata.c +++ b/ext/metadata/gstbasemetadata.c @@ -263,10 +263,10 @@ gboolean gst_base_metadata_strip_push_buffer (GstBaseMetadata * base, gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf) { - MetadataChunk *strip = base->metadata->strip_chunks.chunk; - MetadataChunk *inject = base->metadata->inject_chunks.chunk; - const gsize strip_len = base->metadata->strip_chunks.len; - const gsize inject_len = base->metadata->inject_chunks.len; + MetadataChunk *strip = META_DATA_STRIP_CHUNKS (base->metadata).chunk; + MetadataChunk *inject = META_DATA_INJECT_CHUNKS (base->metadata).chunk; + const gsize strip_len = META_DATA_STRIP_CHUNKS (base->metadata).len; + const gsize inject_len = META_DATA_INJECT_CHUNKS (base->metadata).len; gboolean buffer_reallocated = FALSE; @@ -493,10 +493,10 @@ gboolean gst_base_metadata_translate_pos_to_orig (GstBaseMetadata * base, gint64 pos, gint64 * orig_pos, GstBuffer ** buf) { - MetadataChunk *strip = base->metadata->strip_chunks.chunk; - MetadataChunk *inject = base->metadata->inject_chunks.chunk; - const gsize strip_len = base->metadata->strip_chunks.len; - const gsize inject_len = base->metadata->inject_chunks.len; + MetadataChunk *strip = META_DATA_STRIP_CHUNKS (base->metadata).chunk; + MetadataChunk *inject = META_DATA_INJECT_CHUNKS (base->metadata).chunk; + const gsize strip_len = META_DATA_STRIP_CHUNKS (base->metadata).len; + const gsize inject_len = META_DATA_INJECT_CHUNKS (base->metadata).len; const gint64 duration_orig = base->duration_orig; const gint64 duration = base->duration; @@ -597,8 +597,8 @@ gst_base_metadata_calculate_offsets (GstBaseMetadata * base) int i, j; guint32 append_size; guint32 bytes_striped, bytes_inject; - MetadataChunk *strip = base->metadata->strip_chunks.chunk; - MetadataChunk *inject = base->metadata->inject_chunks.chunk; + MetadataChunk *strip = META_DATA_STRIP_CHUNKS (base->metadata).chunk; + MetadataChunk *inject = META_DATA_INJECT_CHUNKS (base->metadata).chunk; gsize strip_len; gsize inject_len; @@ -607,8 +607,8 @@ gst_base_metadata_calculate_offsets (GstBaseMetadata * base) metadata_lazy_update (base->metadata); - strip_len = base->metadata->strip_chunks.len; - inject_len = base->metadata->inject_chunks.len; + strip_len = META_DATA_STRIP_CHUNKS (base->metadata).len; + inject_len = META_DATA_INJECT_CHUNKS (base->metadata).len; bytes_striped = 0; bytes_inject = 0; @@ -1661,23 +1661,22 @@ done: } void -gst_base_metadata_set_option_flag (GstBaseMetadata * metadata, - MetaOptions options) +gst_base_metadata_set_option_flag (GstBaseMetadata * base, MetaOptions options) { - metadata->options |= options; + base->options |= options; } void -gst_base_metadata_unset_option_flag (GstBaseMetadata * metadata, +gst_base_metadata_unset_option_flag (GstBaseMetadata * base, MetaOptions options) { - metadata->options &= ~options; + base->options &= ~options; } MetaOptions -gst_base_metadata_get_option_flag (const GstBaseMetadata * metadata) +gst_base_metadata_get_option_flag (const GstBaseMetadata * base) { - return metadata->options; + return base->options; } void @@ -1685,8 +1684,8 @@ gst_base_metadata_update_segment_with_new_buffer (GstBaseMetadata * base, guint8 ** buf, guint32 * size, MetadataChunkType type) { int i; - MetadataChunk *inject = base->metadata->inject_chunks.chunk; - const gsize inject_len = base->metadata->inject_chunks.len; + MetadataChunk *inject = META_DATA_INJECT_CHUNKS (base->metadata).chunk; + const gsize inject_len = META_DATA_INJECT_CHUNKS (base->metadata).len; if (!(buf && size)) goto done; @@ -1714,7 +1713,8 @@ done: } void -gst_base_metadata_chunk_array_remove_zero_size (GstBaseMetadata * metadata) +gst_base_metadata_chunk_array_remove_zero_size (GstBaseMetadata * base) { - metadata_chunk_array_remove_zero_size (&metadata->metadata->inject_chunks); + metadata_chunk_array_remove_zero_size (&META_DATA_INJECT_CHUNKS (base-> + metadata)); } diff --git a/ext/metadata/gstbasemetadata.h b/ext/metadata/gstbasemetadata.h index cb304406..1e49f8bc 100644 --- a/ext/metadata/gstbasemetadata.h +++ b/ext/metadata/gstbasemetadata.h @@ -156,20 +156,20 @@ extern GType gst_base_metadata_get_type (void); extern void -gst_base_metadata_set_option_flag(GstBaseMetadata *metadata, const MetaOptions options); +gst_base_metadata_set_option_flag(GstBaseMetadata *base, const MetaOptions options); extern void -gst_base_metadata_unset_option_flag(GstBaseMetadata *metadata, const MetaOptions options); +gst_base_metadata_unset_option_flag(GstBaseMetadata *base, const MetaOptions options); extern MetaOptions -gst_base_metadata_get_option_flag(const GstBaseMetadata *metadata); +gst_base_metadata_get_option_flag(const GstBaseMetadata *base); extern void -gst_base_metadata_update_segment_with_new_buffer (GstBaseMetadata *metadata, +gst_base_metadata_update_segment_with_new_buffer (GstBaseMetadata *base, guint8 ** buf, guint32 * size, MetadataChunkType type); extern void -gst_base_metadata_chunk_array_remove_zero_size (GstBaseMetadata *metadata); +gst_base_metadata_chunk_array_remove_zero_size (GstBaseMetadata *base); G_END_DECLS #endif /* __GST_BASE_METADATA_H__ */ diff --git a/ext/metadata/metadata.h b/ext/metadata/metadata.h index 63e9ec90..2f14471a 100644 --- a/ext/metadata/metadata.h +++ b/ext/metadata/metadata.h @@ -106,6 +106,9 @@ typedef struct _tag_MetaData #define META_DATA_IMG_TYPE(p) (p)->img_type +#define META_DATA_STRIP_CHUNKS(p) (p)->strip_chunks +#define META_DATA_INJECT_CHUNKS(p) (p)->inject_chunks + extern void metadata_init (MetaData ** meta_data, const MetaOptions options); extern void metadata_dispose (MetaData ** meta_data); diff --git a/ext/metadata/metadataiptc.c b/ext/metadata/metadataiptc.c index b052d329..0b040ede 100644 --- a/ext/metadata/metadataiptc.c +++ b/ext/metadata/metadataiptc.c @@ -75,11 +75,74 @@ metadatamux_iptc_create_chunk_from_tag_list (guint8 ** buf, guint32 * size, #else /* ifndef HAVE_IPTC */ #include <iptc-data.h> +#include <iptc-tag.h> #include <string.h> +#include <gst/gsttaglist.h> + +typedef struct _tag_MEUserData +{ + GstTagList *taglist; + GstTagMergeMode mode; +} MEUserData; + +typedef struct _tag_MapIntStr +{ + IptcRecord record; + IptcTag iptc; + const gchar *str; +} MapIntStr; static void iptc_data_foreach_dataset_func (IptcDataSet * dataset, void *user_data); +/* *INDENT-OFF* */ +static MapIntStr mappedTags[] = { + {IPTC_RECORD_APP_2, IPTC_TAG_OBJECT_NAME, /*ASCII*/ GST_TAG_TITLE /*STRING*/}, + {IPTC_RECORD_APP_2, IPTC_TAG_BYLINE, /*ASCII*/ GST_TAG_COMPOSER /*STRING*/}, + {IPTC_RECORD_APP_2, IPTC_TAG_CAPTION, /*ASCII*/ GST_TAG_DESCRIPTION /*STRING*/}, + {IPTC_RECORD_APP_2, IPTC_TAG_COPYRIGHT_NOTICE, /*ASCII*/ GST_TAG_COPYRIGHT /*STRING*/}, + {0, 0, NULL} +}; +/* *INDENT-ON* */ + +static const gchar * +metadataparse_iptc_get_tag_from_iptc (IptcTag iptc, GType * type, + IptcRecord * record) +{ + int i = 0; + + while (mappedTags[i].iptc) { + if (iptc == mappedTags[i].iptc) { + *type = gst_tag_get_type (mappedTags[i].str); + *record = mappedTags[i].record; + break; + } + ++i; + } + + return mappedTags[i].str; + +} + +static IptcTag +metadataparse_iptc_get_iptc_from_tag (const gchar * tag, GType * type, + IptcRecord * record) +{ + int i = 0; + + while (mappedTags[i].iptc) { + if (0 == strcmp (mappedTags[i].str, tag)) { + *type = gst_tag_get_type (tag); + *record = mappedTags[i].record; + break; + } + ++i; + } + + return mappedTags[i].iptc; + +} + void metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, GstAdapter * adapter, MetadataTagMapping mapping) @@ -87,6 +150,7 @@ metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, const guint8 *buf; guint32 size; IptcData *iptc = NULL; + MEUserData user_data = { taglist, mode }; if (adapter == NULL || (size = gst_adapter_available (adapter)) == 0) { goto done; @@ -108,7 +172,7 @@ metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, } iptc_data_foreach_dataset (iptc, iptc_data_foreach_dataset_func, - (void *) taglist); + (void *) &user_data); done: @@ -123,20 +187,81 @@ static void iptc_data_foreach_dataset_func (IptcDataSet * dataset, void *user_data) { - char buf[256]; - GstTagList *taglist = (GstTagList *) user_data; + char buf[1024]; + MEUserData *meudata = (MEUserData *) user_data; + GType type; + IptcRecord record; + const gchar *tag = + metadataparse_iptc_get_tag_from_iptc (dataset->tag, &type, &record); + const gchar *value = iptc_dataset_get_as_str (dataset, buf, 1024); + + if (!tag) + goto done; + + gst_tag_list_add (meudata->taglist, meudata->mode, tag, value, NULL); + +done: GST_LOG ("name -> %s", iptc_tag_get_name (dataset->record, dataset->tag)); GST_LOG ("title -> %s", iptc_tag_get_title (dataset->record, dataset->tag)); GST_LOG ("description -> %s", iptc_tag_get_description (dataset->record, dataset->tag)); - GST_LOG ("value = %s", iptc_dataset_get_as_str (dataset, buf, 256)); + GST_LOG ("value = %s", value); + GST_LOG ("record = %d", dataset->record); + + return; + +} + + +static void +metadataiptc_for_each_tag_in_list (const GstTagList * list, const gchar * tag, + gpointer user_data) +{ + IptcData *iptc = (IptcData *) user_data; + IptcTag iptc_tag; + IptcRecord record; + GType type; + IptcDataSet *dataset = NULL; + gboolean new_dataset = FALSE; + gchar *tag_value = NULL; + + iptc_tag = metadataparse_iptc_get_iptc_from_tag (tag, &type, &record); + + if (!iptc_tag) + goto done; + + dataset = iptc_data_get_dataset (iptc, record, iptc_tag); + + if (!dataset) { + dataset = iptc_dataset_new (); + new_dataset = TRUE; + } + + iptc_dataset_set_tag (dataset, record, iptc_tag); + + if (gst_tag_list_get_string (list, tag, &tag_value)) { + iptc_dataset_set_data (dataset, tag_value, strlen (tag_value), + IPTC_DONT_VALIDATE); + g_free (tag_value); + tag_value = NULL; + } + + + if (new_dataset) + iptc_data_add_dataset (iptc, dataset); + +done: + + if (dataset) + iptc_dataset_unref (dataset); } void metadatamux_iptc_create_chunk_from_tag_list (guint8 ** buf, guint32 * size, const GstTagList * taglist) { + IptcData *iptc = NULL; GstBuffer *iptc_chunk = NULL; const GValue *val = NULL; @@ -152,14 +277,25 @@ metadatamux_iptc_create_chunk_from_tag_list (guint8 ** buf, guint32 * size, if (val) { iptc_chunk = gst_value_get_buffer (val); if (iptc_chunk) { - *size = GST_BUFFER_SIZE (iptc_chunk); - *buf = g_new (guint8, *size); - memcpy (*buf, GST_BUFFER_DATA (iptc_chunk), *size); + iptc = iptc_data_new_from_data (GST_BUFFER_DATA (iptc_chunk), + GST_BUFFER_SIZE (iptc_chunk)); } } + if (!iptc) { + iptc = iptc_data_new (); + } + + gst_tag_list_foreach (taglist, metadataiptc_for_each_tag_in_list, iptc); + + iptc_data_save (iptc, buf, size); + + done: + if (iptc) + iptc_data_unref (iptc); + return; } diff --git a/ext/metadata/metadatamuxjpeg.c b/ext/metadata/metadatamuxjpeg.c index ffcefcf0..5384f30a 100644 --- a/ext/metadata/metadatamuxjpeg.c +++ b/ext/metadata/metadatamuxjpeg.c @@ -75,6 +75,35 @@ metadatamux_wrap_chunk (MetadataChunk * chunk, const guint8 * buf, } } +#ifdef HAVE_IPTC +static gboolean +metadatamux_wrap_iptc_with_ps3 (unsigned char **buf, unsigned int *buf_size) +{ + unsigned int out_size = *buf_size + 4096; + unsigned char *outbuf = g_new (unsigned char, out_size); + int size_written; + gboolean ret = TRUE; + + size_written = + iptc_jpeg_ps3_save_iptc (NULL, 0, *buf, *buf_size, outbuf, out_size); + + g_free (*buf); + *buf = NULL; + *buf_size = 0; + + if (size_written < 0) { + g_free (outbuf); + ret = FALSE; + } else { + *buf_size = size_written; + *buf = outbuf; + } + + return ret; + +} +#endif /* #ifdef HAVE_IPTC */ + void metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data) { @@ -93,21 +122,12 @@ metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data) case MD_CHUNK_IPTC: #ifdef HAVE_IPTC { - unsigned int size = jpeg_data->inject_chunks->chunk[i].size + 256; - unsigned char *buf = g_new (guint8, size); - - size = iptc_jpeg_ps3_save_iptc (NULL, 0, - jpeg_data->inject_chunks->chunk[i].data, - jpeg_data->inject_chunks->chunk[i].size, buf, size); - if (size > 0) { - g_free (jpeg_data->inject_chunks->chunk[i].data); - jpeg_data->inject_chunks->chunk[i].data = buf; - jpeg_data->inject_chunks->chunk[i].size = size; + if (metadatamux_wrap_iptc_with_ps3 (&jpeg_data->inject_chunks-> + chunk[i].data, &jpeg_data->inject_chunks->chunk[i].size)) { metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i], NULL, 0, 0xFF, 0xED); } else { GST_ERROR ("Invalid IPTC chunk\n"); - g_free (buf); /* FIXME: remove entry from list */ } } @@ -225,7 +245,6 @@ metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf, static const char JfifHeader[] = "JFIF"; static const unsigned char ExifHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; - static const char IptcHeader[] = "Photoshop 3.0"; static const char XmpHeader[] = "http://ns.adobe.com/xap/1.0/"; *next_start = *buf; diff --git a/ext/metadata/metadataparsejpeg.c b/ext/metadata/metadataparsejpeg.c index f2482c72..3c2719da 100644 --- a/ext/metadata/metadataparsejpeg.c +++ b/ext/metadata/metadataparsejpeg.c @@ -199,7 +199,7 @@ metadataparse_jpeg_reading (JpegParseData * jpeg_data, guint8 ** buf, static const char JfifHeader[] = "JFIF"; static const unsigned char ExifHeader[] = { 0x45, 0x78, 0x69, 0x66, 0x00, 0x00 }; - static const char IptcHeader[] = "Photoshop 3.0"; + static const char PhotoshopHeader[] = "Photoshop 3.0"; static const char XmpHeader[] = "http://ns.adobe.com/xap/1.0/"; *next_start = *buf; @@ -354,7 +354,7 @@ metadataparse_jpeg_reading (JpegParseData * jpeg_data, guint8 ** buf, } - if (0 == memcmp (IptcHeader, *buf, 14)) { + if (0 == memcmp (PhotoshopHeader, *buf, 14)) { if (!jpeg_data->parse_only) { diff --git a/ext/metadata/metadataparseutil.c b/ext/metadata/metadataparseutil.c index 845c125b..dbb1618d 100644 --- a/ext/metadata/metadataparseutil.c +++ b/ext/metadata/metadataparseutil.c @@ -42,6 +42,7 @@ */ #include "metadataparseutil.h" +#include <string.h> void metadataparse_util_tag_list_add_chunk (GstTagList * taglist, |