From 1159638102e1669bbf0e5f81fb89069b032a2410 Mon Sep 17 00:00:00 2001 From: Edgard Lima Date: Wed, 30 Jan 2008 12:56:51 +0000 Subject: Add documentation. Fix test app compilation. Fix pull mode. Original commit message from CVS: Add documentation. Fix test app compilation. Fix pull mode. --- ext/Makefile.am | 15 +- ext/metadata/TODO | 8 - ext/metadata/gstbasemetadata.c | 177 ++++++++++------- ext/metadata/gstbasemetadata.h | 54 ++++-- ext/metadata/metadatamuxjpeg.c | 371 ++++++++++++++++++++++++++--------- ext/metadata/metadatamuxjpeg.h | 18 +- ext/metadata/metadatamuxpng.c | 403 ++++++++++++++++++++++++++++++--------- ext/metadata/metadatamuxpng.h | 14 +- ext/metadata/metadataparsejpeg.c | 4 +- ext/metadata/metadataparsepng.c | 4 +- 10 files changed, 779 insertions(+), 289 deletions(-) (limited to 'ext') diff --git a/ext/Makefile.am b/ext/Makefile.am index db2fe1bc..0bf562e7 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -76,12 +76,6 @@ else DTS_DIR= endif -if USE_METADATA -METADATA_DIR=metadata -else -METADATA_DIR= -endif - if USE_FAAC FAAC_DIR=faac else @@ -160,6 +154,12 @@ else MPEG2ENC_DIR= endif +if USE_METADATA +METADATA_DIR=metadata +else +METADATA_DIR= +endif + # if USE_MPLEX # MPLEX_DIR=mplex # else @@ -313,6 +313,7 @@ SUBDIRS=\ $(LIBFAME_DIR) \ $(LIBMMS_DIR) \ $(MPEG2ENC_DIR) \ + $(METADATA_DIR) \ $(MPLEX_DIR) \ $(MUSEPACK_DIR) \ $(MUSICBRAINZ_DIR) \ @@ -342,7 +343,6 @@ DIST_SUBDIRS = \ cdaudio \ dc1394 \ directfb \ - metadata \ faac \ faad \ gio \ @@ -353,6 +353,7 @@ DIST_SUBDIRS = \ libmms \ dts \ divx \ + metadata \ mpeg2enc \ musepack \ musicbrainz \ diff --git a/ext/metadata/TODO b/ext/metadata/TODO index 5aa15169..aa7169fb 100644 --- a/ext/metadata/TODO +++ b/ext/metadata/TODO @@ -26,12 +26,4 @@ OPEN ISSUES: KNOWN BUGS -1- gst-launch-0.10 filesrc location=BlueSquare.png ! metadatademux ! metadatamux ! pngdec ! ffmpegcolorspace ! freeze ! xvimagesink - -the following pipelines work fine: - -gst-launch-0.10 filesrc location=BlueSquare.png ! metadatamux ! metadatademux ! pngdec ! ffmpegcolorspace ! freeze ! xvimagesink -gst-launch-0.10 filesrc location=BlueSquare.png ! metadatademux ! metadatamux ! queue ! pngdec ! ffmpegcolorspace ! freeze ! xvimagesink -gst-launch-0.10 filesrc location=BlueSquare.png ! ! metadatamux ! pngdec ! ffmpegcolorspace ! freeze ! xvimagesink -gst-launch-0.10 filesrc location=BlueSquare.png ! metadatademux ! ! pngdec ! ffmpegcolorspace ! freeze ! xvimagesink diff --git a/ext/metadata/gstbasemetadata.c b/ext/metadata/gstbasemetadata.c index 6d826607..92a13fa8 100644 --- a/ext/metadata/gstbasemetadata.c +++ b/ext/metadata/gstbasemetadata.c @@ -159,7 +159,8 @@ gst_base_metadata_parse (GstBaseMetadata * filter, const guint8 * buf, static gboolean gst_base_metadata_strip_push_buffer (GstBaseMetadata * base, - gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf); + const gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf, + gboolean inject_begin); static int gst_base_metadata_buf_get_intersection_seg (const gint64 offset, guint32 size, @@ -168,7 +169,7 @@ gst_base_metadata_buf_get_intersection_seg (const gint64 offset, guint32 size, static gboolean gst_base_metadata_translate_pos_to_orig (GstBaseMetadata * base, - gint64 pos, gint64 * orig_pos, GstBuffer ** buf); + gint64 pos, gint64 * orig_pos, GstBuffer ** buf, guint32 max_size); static gboolean gst_base_metadata_calculate_offsets (GstBaseMetadata * base); @@ -639,6 +640,7 @@ done: * beginning og @buf * @buf: a pointer to a buffer that will be modified (data striped/injected or * prepended) + * @inject_begin: is TRUE can inject a chunk start exactly in @offset_orig * * Strip bytes from @buf that are part of some chunk that will be striped. Add * a whole injected chunk if some inject chunk starts into the buffer. Prepend @@ -658,7 +660,8 @@ done: static gboolean gst_base_metadata_strip_push_buffer (GstBaseMetadata * base, - gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf) + const gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf, + gboolean inject_begin) { MetadataChunk *strip = META_DATA_STRIP_CHUNKS (base->metadata).chunk; MetadataChunk *inject = META_DATA_INJECT_CHUNKS (base->metadata).chunk; @@ -692,11 +695,13 @@ gst_base_metadata_strip_push_buffer (GstBaseMetadata * base, int res; if (inject[i].offset_orig >= offset_orig) { - if (inject[i].offset_orig < offset_orig + size_buf_in) { - injected_bytes += inject[i].size; - } else { - /* segment is after size (segments are sorted) */ - break; + if (G_LIKELY (inject_begin || inject[i].offset_orig > offset_orig)) { + if (inject[i].offset_orig < offset_orig + size_buf_in) { + injected_bytes += inject[i].size; + } else { + /* segment is after size (segments are sorted) */ + break; + } } } } @@ -846,20 +851,22 @@ inject: original buffer */ if (inject[i].offset_orig >= offset_orig) { - if (inject[i].offset_orig < - offset_orig + size_buf_in + striped_bytes - injected_bytes) { - /* insert */ - guint32 buf_off = - inject[i].offset_orig - offset_orig - striped_so_far + - injected_bytes; - memmove (data + buf_off + inject[i].size, data + buf_off, - size_buf_in - buf_off); - memcpy (data + buf_off, inject[i].data, inject[i].size); - injected_bytes += inject[i].size; - size_buf_in += inject[i].size; - } else { - /* segment is after size (segments are sorted) */ - break; + if (G_LIKELY (inject_begin || inject[i].offset_orig > offset_orig)) { + if (inject[i].offset_orig < + offset_orig + size_buf_in + striped_bytes - injected_bytes) { + /* insert */ + guint32 buf_off = + inject[i].offset_orig - offset_orig - striped_so_far + + injected_bytes; + memmove (data + buf_off + inject[i].size, data + buf_off, + size_buf_in - buf_off); + memcpy (data + buf_off, inject[i].data, inject[i].size); + injected_bytes += inject[i].size; + size_buf_in += inject[i].size; + } else { + /* segment is after size (segments are sorted) */ + break; + } } } } @@ -988,6 +995,7 @@ done: * @orig_pos: position in original stream * @buf: if not NULL, will have data that starts at some point into a injected * chunk + * @max_size: the maximum size to allocate to @buf. pass 0 if don't care * * Given a position in output stream (@pos), returns the position in original * stream (@orig_pos) that contains the same data. If @pos is into a injected @@ -1006,7 +1014,7 @@ done: static gboolean gst_base_metadata_translate_pos_to_orig (GstBaseMetadata * base, - gint64 pos, gint64 * orig_pos, GstBuffer ** buf) + gint64 pos, gint64 * orig_pos, GstBuffer ** buf, guint32 max_size) { MetadataChunk *strip = META_DATA_STRIP_CHUNKS (base->metadata).chunk; MetadataChunk *inject = META_DATA_INJECT_CHUNKS (base->metadata).chunk; @@ -1014,9 +1022,11 @@ gst_base_metadata_translate_pos_to_orig (GstBaseMetadata * base, const gsize inject_len = META_DATA_INJECT_CHUNKS (base->metadata).len; const gint64 duration_orig = base->duration_orig; const gint64 duration = base->duration; + gboolean ret = TRUE; + const gint64 saved_pos = pos; int i; - gboolean ret = TRUE; + guint64 new_buf_size = 0; guint64 injected_before = 0; @@ -1032,56 +1042,67 @@ gst_base_metadata_translate_pos_to_orig (GstBaseMetadata * base, /* calculate for injected */ /* just calculate size */ - *orig_pos = pos; /* save pos */ for (i = 0; i < inject_len; ++i) { - /* check if pos in inside chunk */ - if (inject[i].offset <= pos) { + if (pos >= inject[i].offset) { if (pos < inject[i].offset + inject[i].size) { - /* orig pos points after insert chunk */ - new_buf_size += inject[i].size; - /* put pos after current chunk */ - pos = inject[i].offset + inject[i].size; + /* pos is inside the chunk */ + const guint32 offset_in_chunk = pos - inject[i].offset; + ret = FALSE; + pos = inject[i].offset + inject[i].size; /* put pos just after chunk */ + new_buf_size += inject[i].size - offset_in_chunk; + /* we still continue, 'cause the next chunk could be just after this */ } else { /* in case pos is not inside a injected chunk */ injected_before += inject[i].size; } } else { + /* pos is before the chunk */ break; } } /* alloc buffer and calcute original pos */ - if (buf && ret == FALSE) { - guint8 *data; + if (ret == FALSE) { - if (*buf) - gst_buffer_unref (*buf); - *buf = gst_buffer_new_and_alloc (new_buf_size); - data = GST_BUFFER_DATA (*buf); - pos = *orig_pos; /* recover saved pos */ - for (i = 0; i < inject_len; ++i) { - if (inject[i].offset > pos) { - break; - } - if (inject[i].offset <= pos && pos < inject[i].offset + inject[i].size) { - memcpy (data, inject[i].data, inject[i].size); - data += inject[i].size; - pos = inject[i].offset + inject[i].size; - /* out position after insert chunk orig */ - *orig_pos = inject[i].offset_orig + inject[i].size; + *orig_pos = pos; + + if (buf) { + guint8 *data; + + if (max_size > 0) + if (new_buf_size > max_size) + new_buf_size = max_size; + + if (*buf) + gst_buffer_unref (*buf); + *buf = gst_buffer_new_and_alloc (new_buf_size); + data = GST_BUFFER_DATA (*buf); + pos = saved_pos; + for (i = 0; i < inject_len && new_buf_size > 0; ++i) { + if (inject[i].offset > pos) { + break; + } + if (pos < inject[i].offset + inject[i].size) { + const guint32 offset = pos - inject[i].offset; + guint32 size = inject[i].size - offset; + + if (size > new_buf_size) + size = new_buf_size; + memcpy (data, inject[i].data + offset, size); + data += size; + pos = inject[i].offset + inject[i].size; + new_buf_size -= size; + } } } - } - if (ret == FALSE) { - /* if it inside a injected is already done */ goto done; } /* calculate for striped */ - *orig_pos = pos - injected_before; + *orig_pos = saved_pos - injected_before; for (i = 0; i < strip_len; ++i) { if (strip[i].offset_orig > pos) { break; @@ -1479,7 +1500,7 @@ gst_base_metadata_src_event (GstPad * pad, GstEvent * event) striped/injected buffer in next 'chain' calling */ filter->offset = start; gst_base_metadata_translate_pos_to_orig (filter, start, &start, - &filter->prepend_buffer); + &filter->prepend_buffer, 0); filter->offset_orig = start; if (stop_type == GST_SEEK_TYPE_CUR) @@ -1491,7 +1512,7 @@ gst_base_metadata_src_event (GstPad * pad, GstEvent * event) } stop_type == GST_SEEK_TYPE_SET; - gst_base_metadata_translate_pos_to_orig (filter, stop, &stop, NULL); + gst_base_metadata_translate_pos_to_orig (filter, stop, &stop, NULL, 0); gst_event_unref (event); event = gst_event_new_seek (rate, format, flags, @@ -1569,6 +1590,7 @@ gst_base_metadata_get_range (GstPad * pad, guint size_orig; GstBuffer *prepend = NULL; gboolean need_append = FALSE; + gboolean into_inject; filter = GST_BASE_METADATA (GST_PAD_PARENT (pad)); @@ -1583,34 +1605,45 @@ gst_base_metadata_get_range (GstPad * pad, size_orig = size; - gst_base_metadata_translate_pos_to_orig (filter, offset, - &offset_orig, &prepend); + into_inject = !gst_base_metadata_translate_pos_to_orig (filter, offset, + &offset_orig, &prepend, size); + + if (into_inject) { + size_orig = GST_BUFFER_SIZE (prepend) < size_orig ? + size_orig - GST_BUFFER_SIZE (prepend) : 0; + } + + if (size_orig == 0) { + /* enough data in prepend */ + *buf = prepend; + goto done; + } - if (size > 1) { + if (size_orig > 1) { gint64 pos; pos = offset + size - 1; - gst_base_metadata_translate_pos_to_orig (filter, pos, &pos, NULL); + into_inject = gst_base_metadata_translate_pos_to_orig (filter, pos, &pos, + NULL, 0); size_orig = pos + 1 - offset_orig; } - if (size_orig) { - - ret = gst_pad_pull_range (filter->sinkpad, offset_orig, size_orig, buf); + ret = gst_pad_pull_range (filter->sinkpad, offset_orig, size_orig, buf); - if (ret == GST_FLOW_OK && *buf) { - gst_base_metadata_strip_push_buffer (filter, offset_orig, &prepend, buf); - - if (GST_BUFFER_SIZE (*buf) < size) { - /* need append */ - need_append = TRUE; - } + if (ret == GST_FLOW_OK && *buf) { + gst_base_metadata_strip_push_buffer (filter, offset_orig, &prepend, buf, + FALSE); + if (GST_BUFFER_SIZE (*buf) < size) { + /* need append */ + need_append = TRUE; + } else { + /* hide extra bytes */ + GST_BUFFER_SIZE (*buf) = size; } - } else { - *buf = prepend; } + done: if (need_append) { @@ -1715,7 +1748,7 @@ gst_base_metadata_chain (GstPad * pad, GstBuffer * buf) buf_size = GST_BUFFER_SIZE (buf); gst_base_metadata_strip_push_buffer (filter, filter->offset_orig, - &filter->prepend_buffer, &buf); + &filter->prepend_buffer, &buf, TRUE); if (buf) { /* may be all buffer has been striped */ gst_buffer_set_caps (buf, GST_PAD_CAPS (filter->srcpad)); @@ -1848,6 +1881,7 @@ gst_base_metadata_src_query (GstPad * pad, GstQuery * query) gst_query_set_position (query, GST_FORMAT_BYTES, filter->offset); ret = TRUE; } + break; case GST_QUERY_DURATION: @@ -1864,6 +1898,7 @@ gst_base_metadata_src_query (GstPad * pad, GstQuery * query) ret = TRUE; } } + break; case GST_QUERY_FORMATS: gst_query_set_formats (query, 1, GST_FORMAT_BYTES); diff --git a/ext/metadata/gstbasemetadata.h b/ext/metadata/gstbasemetadata.h index 9a3c08ce..427496c0 100644 --- a/ext/metadata/gstbasemetadata.h +++ b/ext/metadata/gstbasemetadata.h @@ -73,27 +73,57 @@ typedef enum _tag_BaseMetadataType { } BaseMetadataType; -/** +/* * GST_BASE_METADATA_SRC_PAD: * @obj: base metadata instance * * Gives the pointer to the #GstPad object of the element. */ -#define GST_BASE_METADATA_SRC_PAD(obj) (GST_BASE_METADATA_CAST (obj)->srcpad) +#define GST_BASE_METADATA_SRC_PAD(obj) (GST_BASE_METADATA_CAST (obj)->srcpad) -/** +/* * GST_BASE_METADATA_SINK_PAD: * @obj: base metadata instance * * Gives the pointer to the #GstPad object of the element. */ -#define GST_BASE_METADATA_SINK_PAD(obj) (GST_BASE_METADATA_CAST (obj)->sinkpad) +#define GST_BASE_METADATA_SINK_PAD(obj) (GST_BASE_METADATA_CAST (obj)->sinkpad) + +/* + * GST_BASE_METADATA_EXIF_ADAPTER + * @obj: base metadata instance + * + * Gives the pointer to the EXIF #GstAdapter of the element. + */ +#define GST_BASE_METADATA_EXIF_ADAPTER(obj) \ + (GST_BASE_METADATA_CAST (obj)->metadata->exif_adapter) + +/* + * GST_BASE_METADATA_IPTC_ADAPTER + * @obj: base metadata instance + * + * Gives the pointer to the IPTC #GstAdapter of the element. + */ +#define GST_BASE_METADATA_IPTC_ADAPTER(obj) \ + (GST_BASE_METADATA_CAST (obj)->metadata->iptc_adapter) -#define GST_BASE_METADATA_EXIF_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->metadata->exif_adapter) -#define GST_BASE_METADATA_IPTC_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->metadata->iptc_adapter) -#define GST_BASE_METADATA_XMP_ADAPTER(obj) (GST_BASE_METADATA_CAST (obj)->metadata->xmp_adapter) +/* + * GST_BASE_METADATA_XMP_ADAPTER + * @obj: base metadata instance + * + * Gives the pointer to the XMP #GstAdapter of the element. + */ +#define GST_BASE_METADATA_XMP_ADAPTER(obj) \ + (GST_BASE_METADATA_CAST (obj)->metadata->xmp_adapter) -#define GST_BASE_METADATA_IMG_TYPE(obj) (GST_BASE_METADATA_CAST (obj)->img_type) +/* + * GST_BASE_METADATA_IMG_TYPE + * @obj: base metadata instance + * + * Gives the type indentified by the parser of the element. + */ +#define GST_BASE_METADATA_IMG_TYPE(obj) \ + (GST_BASE_METADATA_CAST (obj)->img_type) typedef enum _tag_MetadataState @@ -127,7 +157,7 @@ struct _GstBaseMetadata MetaOptions options; - gboolean need_processing; /* still need some action before send first buffer */ + gboolean need_processing; /* still need a action before send first buffer */ GstAdapter *adapter_parsing; GstAdapter *adapter_holding; @@ -161,10 +191,12 @@ extern GType gst_base_metadata_get_type (void); extern void -gst_base_metadata_set_option_flag(GstBaseMetadata *base, const MetaOptions options); +gst_base_metadata_set_option_flag(GstBaseMetadata *base, + const MetaOptions options); extern void -gst_base_metadata_unset_option_flag(GstBaseMetadata *base, const MetaOptions options); +gst_base_metadata_unset_option_flag(GstBaseMetadata *base, + const MetaOptions options); extern MetaOptions gst_base_metadata_get_option_flag(const GstBaseMetadata *base); diff --git a/ext/metadata/metadatamuxjpeg.c b/ext/metadata/metadatamuxjpeg.c index 5384f30a..d8aa2cdd 100644 --- a/ext/metadata/metadatamuxjpeg.c +++ b/ext/metadata/metadatamuxjpeg.c @@ -41,6 +41,41 @@ * Boston, MA 02111-1307, USA. */ +/* + * SECTION: metadatamuxjpeg + * @short_description: This module provides functions to parse JPEG files in + * order to write metadata to it. + * + * This module parses a JPEG stream to find the places in which metadata (EXIF, + * IPTC, XMP) chunks would be written. It also wraps metadata chunks with JPEG + * marks according to the specification. + * + * + * + * #metadatamux_jpeg_init must be called before any other function in this + * module and must be paired with a call to #metadatamux_jpeg_dispose. + * #metadatamux_jpeg_parse is used to parse the stream (find the place + * metadata chunks should be written to). + * #metadatamux_jpeg_lazy_update do nothing. + * + * + * EXIF chunks will always be the first chunk (replaces JFIF). IPTC and XMP + * chunks will be placed or second chunk (after JFIF or EXIF) or third chunk + * if both (IPTC and XMP) are written to the file. + * + * + * When a EXIF chunk is written to the JPEG stream, if there is a JFIF chunk + * as the first chunk, it will be stripped out. + * + * + * + * Last reviewed on 2008-01-24 (0.10.15) + */ + +/* + * includes + */ + #include "metadatamuxjpeg.h" #include @@ -49,109 +84,51 @@ #include #endif +/* + * defines and macros + */ + +#define READ(buf, size) ( (size)--, *((buf)++) ) + +/* + * static helper functions declaration + */ + static MetadataParsingReturn metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf, guint32 * bufsize, const guint32 offset, const guint8 * step_buf, guint8 ** next_start, guint32 * next_size); -#define READ(buf, size) ( (size)--, *((buf)++) ) - static void metadatamux_wrap_chunk (MetadataChunk * chunk, const guint8 * buf, - guint32 buf_size, guint8 a, guint8 b) -{ - guint8 *data = g_new (guint8, 4 + buf_size + chunk->size); - - memcpy (data + 4 + buf_size, chunk->data, chunk->size); - g_free (chunk->data); - chunk->data = data; - chunk->size += 4 + buf_size; - data[0] = a; - data[1] = b; - data[2] = ((chunk->size - 2) >> 8) & 0xFF; - data[3] = (chunk->size - 2) & 0xFF; - if (buf && buf_size) { - memcpy (data + 4, buf, buf_size); - } -} + guint32 buf_size, guint8 a, guint8 b); #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; - -} +metadatamux_wrap_iptc_with_ps3 (unsigned char **buf, unsigned int *buf_size); #endif /* #ifdef HAVE_IPTC */ -void -metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data) -{ - gsize i; - gboolean has_exif = FALSE; - for (i = 0; i < jpeg_data->inject_chunks->len; ++i) { - if (jpeg_data->inject_chunks->chunk[i].size > 0 && - jpeg_data->inject_chunks->chunk[i].data) { - switch (jpeg_data->inject_chunks->chunk[i].type) { - case MD_CHUNK_EXIF: - metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i], NULL, 0, - 0xFF, 0xE1); - has_exif = TRUE; - break; - case MD_CHUNK_IPTC: -#ifdef HAVE_IPTC - { - 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"); - /* FIXME: remove entry from list */ - } - } -#endif /* #ifdef HAVE_IPTC */ - break; - case MD_CHUNK_XMP: - { - static const char XmpHeader[] = "http://ns.adobe.com/xap/1.0/"; - - metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i], - XmpHeader, sizeof (XmpHeader), 0xFF, 0xE1); - } - break; - default: - break; - } - } - } - if (!has_exif) { - /* EXIF not injected so not strip JFIF anymore */ - metadata_chunk_array_clear (jpeg_data->strip_chunks); - } +/* + * extern functions implementations + */ -} +/* + * metadatamux_jpeg_init: + * @jpeg_data: [in] jpeg data handler to be inited + * @strip_chunks: Array of chunks (offset and size) marked for removal + * @inject_chunks: Array of chunks (offset, data, size) marked for injection + * adapter (@exif_adpt, @iptc_adpt, @xmp_adpt). Or FALSE if should also put + * them on @strip_chunks. + * + * Init jpeg data handle. + * This function must be called before any other function from this module. + * This function must not be called twice without call to + * #metadatamux_jpeg_dispose beteween them. + * @see_also: #metadatamux_jpeg_dispose #metadatamux_jpeg_parse + * + * Returns: nothing + */ void metadatamux_jpeg_init (JpegMuxData * jpeg_data, @@ -164,6 +141,16 @@ metadatamux_jpeg_init (JpegMuxData * jpeg_data, } +/* + * metadatamux_jpeg_dispose: + * @jpeg_data: [in] jpeg data handler to be freed + * + * Call this function to free any resource allocated by #metadatamux_jpeg_init + * @see_also: #metadatamux_jpeg_init + * + * Returns: nothing + */ + void metadatamux_jpeg_dispose (JpegMuxData * jpeg_data) { @@ -173,6 +160,42 @@ metadatamux_jpeg_dispose (JpegMuxData * jpeg_data) jpeg_data->state = JPEG_MUX_NULL; } +/* + * metadatamux_jpeg_parse: + * @jpeg_data: [in] jpeg data handle + * @buf: [in] data to be parsed + * @bufsize: [in] size of @buf in bytes + * @offset: is the offset where @buf starts from the beginnig of the whole + * stream + * @next_start: is a pointer after @buf which indicates where @buf should start + * on the next call to this function. It means, that after returning, this + * function has consumed *@next_start - @buf bytes. Which also means + * that @offset should also be incremanted by (*@next_start - @buf) for the + * next time. + * @next_size: [out] number of minimal bytes in @buf for the next call to this + * function + * + * This function is used to parse a JPEG stream step-by-step incrementally. + * Basically this function works like a state machine, that will run in a loop + * while there is still bytes in @buf to be read or it has finished parsing. + * If the it hasn't parsed yet and there is no more data in @buf, then the + * current state is saved and a indication will be make about the buffer to + * be passed by the caller function. + * @see_also: #metadatamux_jpeg_init + * + * Returns: + * + * %META_PARSING_ERROR + * + * %META_PARSING_DONE if parse has finished. Now strip and + * inject chunks has been found + * + * %META_PARSING_NEED_MORE_DATA if this function should be + * called again (look @next_start and @next_size) + * + * + */ + MetadataParsingReturn metadatamux_jpeg_parse (JpegMuxData * jpeg_data, guint8 * buf, guint32 * bufsize, const guint32 offset, guint8 ** next_start, @@ -227,8 +250,114 @@ done: } +/* + * metadatamux_jpeg_lazy_update: + * @jpeg_data: [in] jpeg data handle + * + * This function wrap metadata chunk with proper JPEG marks. In case of IPTC + * it will be wrapped by PhotoShop and then by JPEG mark. + * @see_also: #metadata_lazy_update + * + * Returns: nothing + */ + +void +metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data) +{ + gsize i; + gboolean has_exif = FALSE; + + for (i = 0; i < jpeg_data->inject_chunks->len; ++i) { + if (jpeg_data->inject_chunks->chunk[i].size > 0 && + jpeg_data->inject_chunks->chunk[i].data) { + switch (jpeg_data->inject_chunks->chunk[i].type) { + case MD_CHUNK_EXIF: + metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i], NULL, 0, + 0xFF, 0xE1); + has_exif = TRUE; + break; + case MD_CHUNK_IPTC: +#ifdef HAVE_IPTC + { + 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"); + /* FIXME: remove entry from list */ + } + } +#endif /* #ifdef HAVE_IPTC */ + break; + case MD_CHUNK_XMP: + { + static const char XmpHeader[] = "http://ns.adobe.com/xap/1.0/"; + + metadatamux_wrap_chunk (&jpeg_data->inject_chunks->chunk[i], + XmpHeader, sizeof (XmpHeader), 0xFF, 0xE1); + } + break; + default: + break; + } + } + } + if (!has_exif) { + /* EXIF not injected so not strip JFIF anymore */ + metadata_chunk_array_clear (jpeg_data->strip_chunks); + } + +} + + + +/* + * static helper functions implementation + */ + +/* + * metadatamux_jpeg_reading: + * @jpeg_data: [in] jpeg data handle + * @buf: [in] data to be parsed. @buf will increment during the parsing step. + * So it will hold the next byte to be read inside a parsing function or on + * the next nested parsing function. And so, @bufsize will decrement. + * @bufsize: [in] size of @buf in bytes. This value will decrement during the + * parsing for the same reason that @buf will advance. + * @offset: is the offset where @step_buf starts from the beginnig of the + * stream + * @step_buf: holds the pointer to the buffer passed to + * #metadatamux_jpeg_parse. It means that any point inside this function + * the offset (related to the beginning of the whole stream) after the last + * byte read so far is "(*buf - step_buf) + offset" + * @next_start: is a pointer after @step_buf which indicates where the next + * call to #metadatamux_jpeg_parse should start on the next call to this + * function. It means, that after return, this function has + * consumed *@next_start - @buf bytes. Which also means that @offset should + * also be incremanted by (*@next_start - @buf) for the next time. + * @next_size: [out] number of minimal bytes in @buf for the next call to this + * function + * + * This function is used to parse a JPEG stream step-by-step incrementally. + * If this function quickly finds the place (offset) in which EXIF, IPTC and + * XMP chunk should be written to. + * The found places are written to @jpeg_data->inject_chunks + * @see_also: #metadatamux_jpeg_init + * + * Returns: + * + * %META_PARSING_ERROR + * + * %META_PARSING_DONE if parse has finished. Now strip and + * inject chunks has been found. Or some chunk has been found and should be + * held or jumped. + * + * %META_PARSING_NEED_MORE_DATA if this function should be + * called again (look @next_start and @next_size) + * + * + */ -/* look for markers */ static MetadataParsingReturn metadatamux_jpeg_reading (JpegMuxData * jpeg_data, guint8 ** buf, guint32 * bufsize, const guint32 offset, const guint8 * step_buf, @@ -338,3 +467,65 @@ done: } + +/* + * metadatamux_wrap_chunk: + * @chunk: chunk to be wrapped + * @buf: data to inject in the beginning of @chunk->data and after @a and @b + * @buf_size: size in bytes of @buf + * @a: together with @b forms the JPEG mark to be injected in the beginning + * @b: look at @a + * + * Wraps a chunk if a JPEG mark (@a@b) and, if @buf_size > 0, with some data + * (@buf) + * + * Returns: nothing + */ + +static void +metadatamux_wrap_chunk (MetadataChunk * chunk, const guint8 * buf, + guint32 buf_size, guint8 a, guint8 b) +{ + guint8 *data = g_new (guint8, 4 + buf_size + chunk->size); + + memcpy (data + 4 + buf_size, chunk->data, chunk->size); + g_free (chunk->data); + chunk->data = data; + chunk->size += 4 + buf_size; + data[0] = a; + data[1] = b; + data[2] = ((chunk->size - 2) >> 8) & 0xFF; + data[3] = (chunk->size - 2) & 0xFF; + if (buf && buf_size) { + memcpy (data + 4, buf, buf_size); + } +} + +#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 */ diff --git a/ext/metadata/metadatamuxjpeg.h b/ext/metadata/metadatamuxjpeg.h index f57b7df6..01858328 100644 --- a/ext/metadata/metadatamuxjpeg.h +++ b/ext/metadata/metadatamuxjpeg.h @@ -44,10 +44,18 @@ #ifndef __METADATAMUX_JPEG_H__ #define __METADATAMUX_JPEG_H__ +/* + * includes + */ + #include #include "metadatatypes.h" +/* + * enum and types + */ + G_BEGIN_DECLS typedef enum _tag_JpegMuxState @@ -67,6 +75,9 @@ typedef struct _tag_JpegMuxData } JpegMuxData; +/* + * external function prototypes + */ extern void metadatamux_jpeg_init (JpegMuxData * jpeg_data, @@ -74,11 +85,12 @@ metadatamux_jpeg_init (JpegMuxData * jpeg_data, extern void metadatamux_jpeg_dispose (JpegMuxData * jpeg_data); -extern void metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data); - extern MetadataParsingReturn metadatamux_jpeg_parse (JpegMuxData * jpeg_data, guint8 * buf, - guint32 * bufsize, const guint32 offset, guint8 ** next_start, guint32 * next_size); + guint32 * bufsize, const guint32 offset, guint8 ** next_start, + guint32 * next_size); + +extern void metadatamux_jpeg_lazy_update (JpegMuxData * jpeg_data); G_END_DECLS #endif /* __METADATAMUX_JPEG_H__ */ diff --git a/ext/metadata/metadatamuxpng.c b/ext/metadata/metadatamuxpng.c index ac8e86bb..dd3828cd 100644 --- a/ext/metadata/metadatamuxpng.c +++ b/ext/metadata/metadatamuxpng.c @@ -41,113 +41,88 @@ * Boston, MA 02111-1307, USA. */ +/* + * SECTION: metadatamuxpng + * @short_description: This module provides functions to parse PNG files in + * order to write metadata to it. + * + * This module parses a PNG stream to find the places in which XMP metadata + * chunks would be written. It also wraps metadata chunks with PNG marks + * according to the specification. + * + * + * + * #metadatamux_png_init must be called before any other function in this + * module and must be paired with a call to #metadatamux_png_dispose. + * #metadatamux_png_parse is used to parse the stream (find the place + * metadata chunks should be written to). + * #metadatamux_png_lazy_update do nothing. + * + * + * EXIF chunks will always be the first chunk (replaces JFIF). IPTC and XMP + * chunks will be placed or second chunk (after JFIF or EXIF) or third chunk + * if both (IPTC and XMP) are written to the file. + * + * + * When a EXIF chunk is written to the PNG stream, if there is a JFIF chunk + * as the first chunk, it will be stripped out. + * + * + * + * Last reviewed on 2008-01-24 (0.10.15) + */ + +/* + * includes + */ + #include "metadatamuxpng.h" #include -static MetadataParsingReturn -metadatamux_png_reading (PngMuxData * png_data, guint8 ** buf, - guint32 * bufsize, const guint32 offset, const guint8 * step_buf, - guint8 ** next_start, guint32 * next_size); +/* + * defines and macros + */ #define READ(buf, size) ( (size)--, *((buf)++) ) -static void -make_crc_table (guint32 crc_table[]) -{ - guint32 c; - guint16 n, k; - - for (n = 0; n < 256; n++) { - c = (guint32) n; - for (k = 0; k < 8; k++) { - if (c & 1) - c = 0xedb88320L ^ (c >> 1); - else - c = c >> 1; - } - crc_table[n] = c; - } -} - -static guint32 -update_crc (guint32 crc, guint8 * buf, guint32 len) -{ - guint32 c = crc; - guint32 n; - guint32 crc_table[256]; - - /* FIXME: make_crc_table should be done once in life - for speed up */ - make_crc_table (crc_table); +/* + * static helper functions declaration + */ - for (n = 0; n < len; n++) { - c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); - } - return c; -} +static MetadataParsingReturn +metadatamux_png_reading (PngMuxData * png_data, guint8 ** buf, + guint32 * bufsize, const guint32 offset, const guint8 * step_buf, + guint8 ** next_start, guint32 * next_size); -/* Return the CRC of the bytes buf[0..len-1]. */ -static guint32 -calc_crc (guint8 * buf, guint32 len) -{ - return update_crc (0xffffffffL, buf, len) ^ 0xffffffffL; -} +static void metadatamux_make_crc_table (guint32 crc_table[]); +static guint32 metadatamux_update_crc (guint32 crc, guint8 * buf, guint32 len); -static void -metadatamux_wrap_xmp_chunk (MetadataChunk * chunk) -{ - static const char XmpHeader[] = "XML:com.adobe.xmp"; - guint8 *data = NULL; - guint32 crc; +static guint32 metadatamux_calc_crc (guint8 * buf, guint32 len); - data = g_new (guint8, 12 + 18 + 4 + chunk->size); +static void metadatamux_wrap_xmp_chunk (MetadataChunk * chunk); - memcpy (data + 8, XmpHeader, 18); - memset (data + 8 + 18, 0x00, 4); - memcpy (data + 8 + 18 + 4, chunk->data, chunk->size); - g_free (chunk->data); - chunk->data = data; - chunk->size += 18 + 4; - data[0] = (chunk->size >> 24) & 0xFF; - data[1] = (chunk->size >> 16) & 0xFF; - data[2] = (chunk->size >> 8) & 0xFF; - data[3] = chunk->size & 0xFF; - data[4] = 'i'; - data[5] = 'T'; - data[6] = 'X'; - data[7] = 't'; - crc = calc_crc (data + 4, chunk->size + 4 + 18); - data[chunk->size + 8] = (crc >> 24) & 0xFF; - data[chunk->size + 9] = (crc >> 16) & 0xFF; - data[chunk->size + 10] = (crc >> 8) & 0xFF; - data[chunk->size + 11] = crc & 0xFF; - chunk->size += 12; - -} - -void -metadatamux_png_lazy_update (PngMuxData * png_data) -{ - gsize i; +/* + * extern functions implementations + */ - for (i = 0; i < png_data->inject_chunks->len; ++i) { - if (png_data->inject_chunks->chunk[i].size > 0 && - png_data->inject_chunks->chunk[i].data) { - switch (png_data->inject_chunks->chunk[i].type) { - case MD_CHUNK_XMP: - { - metadatamux_wrap_xmp_chunk (&png_data->inject_chunks->chunk[i]); - } - break; - default: - GST_ERROR ("Unexpected chunk for PNG muxer."); - break; - } - } - } -} +/* + * metadatamux_png_init: + * @png_data: [in] png data handler to be inited + * @strip_chunks: Array of chunks (offset and size) marked for removal + * @inject_chunks: Array of chunks (offset, data, size) marked for injection + * adapter (@exif_adpt, @iptc_adpt, @xmp_adpt). Or FALSE if should also put + * them on @strip_chunks. + * + * Init png data handle. + * This function must be called before any other function from this module. + * This function must not be called twice without call to + * #metadatamux_png_dispose beteween them. + * @see_also: #metadatamux_png_dispose #metadatamux_png_parse + * + * Returns: nothing + */ void metadatamux_png_init (PngMuxData * png_data, @@ -159,6 +134,16 @@ metadatamux_png_init (PngMuxData * png_data, png_data->inject_chunks = inject_chunks; } +/* + * metadatamux_png_dispose: + * png_data: [in] png data handler to be freed + * + * Call this function to free any resource allocated by #metadatamux_png_init + * @see_also: #metadatamux_png_init + * + * Returns: nothing + */ + void metadatamux_png_dispose (PngMuxData * png_data) { @@ -168,6 +153,42 @@ metadatamux_png_dispose (PngMuxData * png_data) png_data->state = PNG_MUX_NULL; } +/* + * metadatamux_png_parse: + * @png_data: [in] png data handle + * @buf: [in] data to be parsed + * @bufsize: [in] size of @buf in bytes + * @offset: is the offset where @buf starts from the beginnig of the whole + * stream + * @next_start: is a pointer after @buf which indicates where @buf should start + * on the next call to this function. It means, that after returning, this + * function has consumed *@next_start - @buf bytes. Which also means + * that @offset should also be incremanted by (*@next_start - @buf) for the + * next time. + * @next_size: [out] number of minimal bytes in @buf for the next call to this + * function + * + * This function is used to parse a PNG stream step-by-step incrementally. + * Basically this function works like a state machine, that will run in a loop + * while there is still bytes in @buf to be read or it has finished parsing. + * If the it hasn't parsed yet and there is no more data in @buf, then the + * current state is saved and a indication will be make about the buffer to + * be passed by the caller function. + * @see_also: #metadatamux_png_init + * + * Returns: + * + * %META_PARSING_ERROR + * + * %META_PARSING_DONE if parse has finished. Now strip and + * inject chunks has been found + * + * %META_PARSING_NEED_MORE_DATA if this function should be + * called again (look @next_start and @next_size) + * + * + */ + MetadataParsingReturn metadatamux_png_parse (PngMuxData * png_data, guint8 * buf, guint32 * bufsize, const guint32 offset, guint8 ** next_start, @@ -230,8 +251,86 @@ done: } +/* + * metadatamux_png_lazy_update: + * @png_data: [in] png data handle + * + * This function wrap metadata chunk with proper PNG bytes. + * @see_also: #metadata_lazy_update + * + * Returns: nothing + */ + +void +metadatamux_png_lazy_update (PngMuxData * png_data) +{ + gsize i; + + for (i = 0; i < png_data->inject_chunks->len; ++i) { + if (png_data->inject_chunks->chunk[i].size > 0 && + png_data->inject_chunks->chunk[i].data) { + switch (png_data->inject_chunks->chunk[i].type) { + case MD_CHUNK_XMP: + { + metadatamux_wrap_xmp_chunk (&png_data->inject_chunks->chunk[i]); + } + break; + default: + GST_ERROR ("Unexpected chunk for PNG muxer."); + break; + } + } + } +} + + +/* + * static helper functions implementation + */ + +/* + * metadatamux_png_reading: + * @png_data: [in] png data handle + * @buf: [in] data to be parsed. @buf will increment during the parsing step. + * So it will hold the next byte to be read inside a parsing function or on + * the next nested parsing function. And so, @bufsize will decrement. + * @bufsize: [in] size of @buf in bytes. This value will decrement during the + * parsing for the same reason that @buf will advance. + * @offset: is the offset where @step_buf starts from the beginnig of the + * stream + * @step_buf: holds the pointer to the buffer passed to + * #metadatamux_png_parse. It means that any point inside this function + * the offset (related to the beginning of the whole stream) after the last + * byte read so far is "(*buf - step_buf) + offset" + * @next_start: is a pointer after @step_buf which indicates where the next + * call to #metadatamux_png_parse should start on the next call to this + * function. It means, that after return, this function has + * consumed *@next_start - @buf bytes. Which also means that @offset should + * also be incremanted by (*@next_start - @buf) for the next time. + * @next_size: [out] number of minimal bytes in @buf for the next call to this + * function + * + * This function is used to parse a PNG stream step-by-step incrementally. + * If this function quickly finds the place (offset) in which EXIF, IPTC and + * XMP chunk should be written to. + * The found places are written to @png_data->inject_chunks + * @see_also: #metadatamux_png_init + * + * Returns: + * + * %META_PARSING_ERROR + * + * %META_PARSING_DONE if parse has finished. Now strip and + * inject chunks has been found. Or some chunk has been found and should be + * held or jumped. + * + * %META_PARSING_NEED_MORE_DATA if this function should be + * called again (look @next_start and @next_size) + * + * + */ + -/* look for markers */ static MetadataParsingReturn metadatamux_png_reading (PngMuxData * png_data, guint8 ** buf, guint32 * bufsize, const guint32 offset, const guint8 * step_buf, @@ -287,3 +386,119 @@ done: } + +/* + * metadatamux_make_crc_table: + * @crc_table: table to be written to. + * + * Creates a startup CRC table. For optimization it should be done only once. + * @see_also: #metadatamux_update_crc + * + * Returns: nothing. + */ + +static void +metadatamux_make_crc_table (guint32 crc_table[]) +{ + guint32 c; + guint16 n, k; + + for (n = 0; n < 256; n++) { + c = (guint32) n; + for (k = 0; k < 8; k++) { + if (c & 1) + c = 0xedb88320L ^ (c >> 1); + else + c = c >> 1; + } + crc_table[n] = c; + } +} + +/* + * metadatamux_update_crc: + * @crc: seed to calculate the CRC + * @buf: data to calculate the CRC for + * @len: size in bytes of @buf + * + * Calculates the CRC of a data buffer for a seed @crc. + * @see_also: #metadatamux_make_crc_table #metadatamux_calc_crc + * + * Returns: the CRC of the bytes buf[0..len-1]. + */ + +static guint32 +metadatamux_update_crc (guint32 crc, guint8 * buf, guint32 len) +{ + guint32 c = crc; + guint32 n; + guint32 crc_table[256]; + + /* FIXME: make_crc_table should be done once in life + for speed up. It could be written hard coded to a file */ + metadatamux_make_crc_table (crc_table); + + for (n = 0; n < len; n++) { + c = crc_table[(c ^ buf[n]) & 0xff] ^ (c >> 8); + } + return c; +} + +/* + * metadatamux_calc_crc: + * @buf: data to calculate the CRC for + * @len: size in bytes of @buf + * + * Calculates the CRC of a data buffer. + * + * Returns: the CRC of the bytes buf[0..len-1]. + */ + +static guint32 +metadatamux_calc_crc (guint8 * buf, guint32 len) +{ + return metadatamux_update_crc (0xffffffffL, buf, len) ^ 0xffffffffL; +} + + +/* + * metadatamux_wrap_xmp_chunk: + * @chunk: chunk to be wrapped + * + * Wraps a XMP chunk with proper PNG bytes (mark, size and crc in the end) + * + * Returns: nothing + */ + +static void +metadatamux_wrap_xmp_chunk (MetadataChunk * chunk) +{ + static const char XmpHeader[] = "XML:com.adobe.xmp"; + guint8 *data = NULL; + guint32 crc; + + data = g_new (guint8, 12 + 18 + 4 + chunk->size); + + memcpy (data + 8, XmpHeader, 18); + memset (data + 8 + 18, 0x00, 4); + memcpy (data + 8 + 18 + 4, chunk->data, chunk->size); + g_free (chunk->data); + chunk->data = data; + chunk->size += 18 + 4; + data[0] = (chunk->size >> 24) & 0xFF; + data[1] = (chunk->size >> 16) & 0xFF; + data[2] = (chunk->size >> 8) & 0xFF; + data[3] = chunk->size & 0xFF; + data[4] = 'i'; + data[5] = 'T'; + data[6] = 'X'; + data[7] = 't'; + crc = metadatamux_calc_crc (data + 4, chunk->size + 4); + data[chunk->size + 8] = (crc >> 24) & 0xFF; + data[chunk->size + 9] = (crc >> 16) & 0xFF; + data[chunk->size + 10] = (crc >> 8) & 0xFF; + data[chunk->size + 11] = crc & 0xFF; + + chunk->size += 12; + +} diff --git a/ext/metadata/metadatamuxpng.h b/ext/metadata/metadatamuxpng.h index 96eb7bd2..8680ca57 100644 --- a/ext/metadata/metadatamuxpng.h +++ b/ext/metadata/metadatamuxpng.h @@ -44,12 +44,20 @@ #ifndef __METADATAMUX_PNG_H__ #define __METADATAMUX_PNG_H__ +/* + * includes + */ + #include #include "metadatatypes.h" G_BEGIN_DECLS +/* + * enum and types + */ + typedef enum _tag_PngMuxState { PNG_MUX_NULL, @@ -69,6 +77,9 @@ typedef struct _tag_PngMuxData } PngMuxData; +/* + * external function prototypes + */ extern void metadatamux_png_init (PngMuxData * png_data, @@ -80,7 +91,8 @@ extern void metadatamux_png_lazy_update (PngMuxData * png_data); extern MetadataParsingReturn metadatamux_png_parse (PngMuxData * png_data, guint8 * buf, - guint32 * bufsize, const guint32 offset, guint8 ** next_start, guint32 * next_size); + guint32 * bufsize, const guint32 offset, guint8 ** next_start, + guint32 * next_size); G_END_DECLS #endif /* __METADATAMUX_PNG_H__ */ diff --git a/ext/metadata/metadataparsejpeg.c b/ext/metadata/metadataparsejpeg.c index ce6a161c..fb950b3b 100644 --- a/ext/metadata/metadataparsejpeg.c +++ b/ext/metadata/metadataparsejpeg.c @@ -185,7 +185,7 @@ metadataparse_jpeg_dispose (JpegParseData * jpeg_data) } /* - * metadata_parse: + * metadataparse_jpeg_parse: * @jpeg_data: [in] jpeg data handle * @buf: [in] data to be parsed * @bufsize: [in] size of @buf in bytes @@ -310,7 +310,7 @@ done: * @jpeg_data: [in] jpeg data handle * * This function do nothing - * @see_also: metadata_lazy_update + * @see_also: #metadata_lazy_update * * Returns: nothing */ diff --git a/ext/metadata/metadataparsepng.c b/ext/metadata/metadataparsepng.c index b5a8e775..3999d590 100644 --- a/ext/metadata/metadataparsepng.c +++ b/ext/metadata/metadataparsepng.c @@ -152,7 +152,7 @@ metadataparse_png_dispose (PngParseData * png_data) } /* - * metadata_parse: + * metadataparse_png_parse: * @png_data: [in] png data handle * @buf: [in] data to be parsed * @bufsize: [in] size of @buf in bytes @@ -273,7 +273,7 @@ done: * @png_data: [in] png data handle * * This function do nothing - * @see_also: metadata_lazy_update + * @see_also: #metadata_lazy_update * * Returns: nothing */ -- cgit v1.2.1