diff --git a/ChangeLog b/ChangeLog index f0da419872..6e51f30f23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,25 @@ +2007-11-02 Edgard Lima + + * ext/metadata/Makefile.am: + * ext/metadata/gstmetadataparse.c: + * ext/metadata/gstmetadataparse.h: + * ext/metadata/metadataparse.c: + * ext/metadata/metadataparse.h: + * ext/metadata/metadataparseexif.c: + * ext/metadata/metadataparseexif.h: + * ext/metadata/metadataparseiptc.c: + * ext/metadata/metadataparseiptc.h: + * ext/metadata/metadataparsejpeg.c: + * ext/metadata/metadataparsejpeg.h: + * ext/metadata/metadataparsepng.c: + * ext/metadata/metadataparsepng.h: + * ext/metadata/metadataparseutil.c: + * ext/metadata/metadataparseutil.h: + * ext/metadata/metadataparsexmp.c: + * ext/metadata/metadataparsexmp.h: + Added support for PNG/XMP. Indentation. And fixed pull mode to parse + the file. + 2007-11-02 Edgard Lima * ext/metadata/gstmetadataparse.c: (gst_metadata_parse_init), diff --git a/ext/metadata/Makefile.am b/ext/metadata/Makefile.am index 88596b4266..095a399663 100644 --- a/ext/metadata/Makefile.am +++ b/ext/metadata/Makefile.am @@ -4,6 +4,7 @@ libgstmetadata_la_SOURCES = gstmetadata.c \ gstmetadataparse.c \ metadataparse.c \ metadataparsejpeg.c \ + metadataparsepng.c \ metadataparseexif.c \ metadataparseiptc.c \ metadataparsexmp.c \ @@ -16,6 +17,7 @@ libgstmetadata_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = gstmetadataparse.h \ metadataparse.h \ metadataparsejpeg.h \ + metadataparsepng.h \ metadataparseexif.h \ metadataparseiptc.h \ metadataparsexmp.h \ diff --git a/ext/metadata/gstmetadataparse.c b/ext/metadata/gstmetadataparse.c index cb828f29fd..be1e0d43b9 100644 --- a/ext/metadata/gstmetadataparse.c +++ b/ext/metadata/gstmetadataparse.c @@ -146,6 +146,8 @@ static gboolean gst_metadata_parse_activate (GstPad * pad); static gboolean gst_metadata_parse_element_activate_src_pull (GstPad * pad, gboolean active); +static gboolean gst_metadata_parse_pull_range_parse (GstMetadataParse * filter); + static void gst_metadata_parse_init_members (GstMetadataParse * filter); static void gst_metadata_parse_dispose_members (GstMetadataParse * filter); @@ -486,7 +488,7 @@ gst_metadata_parse_dispose_members (GstMetadataParse * filter) static void gst_metadata_parse_init_members (GstMetadataParse * filter) { - filter->need_send_tag = TRUE; + filter->need_send_tag = FALSE; filter->exif = TRUE; filter->iptc = TRUE; filter->xmp = TRUE; @@ -708,6 +710,7 @@ gst_metadata_parse_parse (GstMetadataParse * filter, const guint8 * buf, } else { filter->state = MT_STATE_PARSED; filter->need_more_data = FALSE; + filter->need_send_tag = TRUE; } if (filter->img_type != PARSE_DATA_IMG_TYPE (filter->parse_data)) { @@ -807,22 +810,14 @@ done: } static gboolean -gst_metadata_parse_activate (GstPad * pad) +gst_metadata_parse_pull_range_parse (GstMetadataParse * filter) { - GstMetadataParse *filter = NULL; + + int res; gboolean ret = TRUE; + guint32 offset = 0; gint64 duration = 0; GstFormat format = GST_FORMAT_BYTES; - int res; - guint32 offset = 0; - - filter = GST_METADATA_PARSE (GST_PAD_PARENT (pad)); - - if (!gst_pad_check_pull_range (pad) || - !gst_pad_activate_pull (filter->sinkpad, TRUE)) { - /* nothing to be done by now, activate push mode */ - return gst_pad_activate_push (pad, TRUE); - } if (!(ret = gst_pad_query_peer_duration (filter->sinkpad, &format, &duration))) { @@ -836,7 +831,6 @@ gst_metadata_parse_activate (GstPad * pad) goto done; } - /* try to parse */ do { GstFlowReturn flow; GstBuffer *buf = NULL; @@ -870,6 +864,32 @@ gst_metadata_parse_activate (GstPad * pad) } while (res > 0); +done: + + return ret; + +} + +static gboolean +gst_metadata_parse_activate (GstPad * pad) +{ + GstMetadataParse *filter = NULL; + gboolean ret = TRUE; + + + filter = GST_METADATA_PARSE (GST_PAD_PARENT (pad)); + + if (!gst_pad_check_pull_range (pad) || + !gst_pad_activate_pull (filter->sinkpad, TRUE)) { + /* nothing to be done by now, activate push mode */ + return gst_pad_activate_push (pad, TRUE); + } + + /* try to parse */ + if (filter->state == MT_STATE_NULL) { + ret = gst_metadata_parse_pull_range_parse (filter); + } + done: if (ret) { @@ -911,6 +931,10 @@ gst_metadata_parse_element_activate_src_pull (GstPad * pad, gboolean active) ret = gst_pad_activate_pull (filter->sinkpad, active); + if (ret && filter->state == MT_STATE_NULL) { + ret = gst_metadata_parse_pull_range_parse (filter); + } + gst_object_unref (filter); return ret; diff --git a/ext/metadata/gstmetadataparse.h b/ext/metadata/gstmetadataparse.h index 5ae49cb379..eb1f802d7d 100644 --- a/ext/metadata/gstmetadataparse.h +++ b/ext/metadata/gstmetadataparse.h @@ -49,7 +49,6 @@ #include "metadataparse.h" G_BEGIN_DECLS - /* #defines don't like whitespacey bits */ #define GST_TYPE_METADATA_PARSE \ (gst_metadata_parse_get_type()) @@ -61,13 +60,12 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_METADATA_PARSE)) #define GST_IS_METADATA_PARSE_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_METADATA_PARSE)) - -typedef struct _GstMetadataParse GstMetadataParse; +typedef struct _GstMetadataParse GstMetadataParse; typedef struct _GstMetadataParseClass GstMetadataParseClass; -typedef enum _tag_MetadataState { - MT_STATE_NULL, /* still need to check media type */ - MT_STATE_READING, +typedef enum _tag_MetadataState +{ + MT_STATE_NULL, /* still need to check media type */ MT_STATE_PARSED } MetadataState; @@ -85,7 +83,7 @@ struct _GstMetadataParse GstTagList *taglist; ParseData parse_data; - GstAdapter * adapter; + GstAdapter *adapter; guint32 next_offset; guint32 next_size; ImageType img_type; @@ -98,17 +96,14 @@ struct _GstMetadataParse }; -struct _GstMetadataParseClass +struct _GstMetadataParseClass { GstElementClass parent_class; }; -extern GType -gst_metadata_parse_get_type (void); +extern GType gst_metadata_parse_get_type (void); -extern gboolean -gst_metadata_parse_plugin_init (GstPlugin * plugin); +extern gboolean gst_metadata_parse_plugin_init (GstPlugin * plugin); G_END_DECLS - #endif /* __GST_METADATA_PARSE_H__ */ diff --git a/ext/metadata/metadataparse.c b/ext/metadata/metadataparse.c index 9c7dfa8402..8a16bcf3e6 100644 --- a/ext/metadata/metadataparse.c +++ b/ext/metadata/metadataparse.c @@ -43,9 +43,6 @@ #include "metadataparse.h" -#include "metadataparsejpeg.h" - - /* *static declarations */ @@ -103,7 +100,9 @@ metadataparse_parse (ParseData * parse_data, const guint8 * buf, (guint8 *) buf, &bufsize, &next_start, next_size); break; case IMG_PNG: - ret = 0; + ret = + metadataparse_png_parse (&parse_data->format_data.png, + (guint8 *) buf, &bufsize, &next_start, next_size); break; default: /* unexpected */ @@ -131,6 +130,9 @@ metadataparse_dispose (ParseData * parse_data) case IMG_JPEG: metadataparse_jpeg_dispose (&parse_data->format_data.jpeg); break; + case IMG_PNG: + metadataparse_png_dispose (&parse_data->format_data.png); + break; } if (parse_data->adpt_xmp) { @@ -169,13 +171,12 @@ metadataparse_parse_none (ParseData * parse_data, const guint8 * buf, parse_data->img_type = IMG_NONE; - if (*bufsize < 4) { - *next_size = 4; + if (*bufsize < 3) { + *next_size = 3; ret = 1; goto done; } - ret = 0; if (parse_data->option & PARSE_OPT_EXIF) adpt_exif = &parse_data->adpt_exif; if (parse_data->option & PARSE_OPT_IPTC) @@ -186,12 +187,25 @@ metadataparse_parse_none (ParseData * parse_data, const guint8 * buf, if (buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF) { metadataparse_jpeg_init (&parse_data->format_data.jpeg, adpt_exif, adpt_iptc, adpt_xmp); + ret = 0; parse_data->img_type = IMG_JPEG; - } else if (buf[0] == 0x89 && buf[1] == 0x50 && buf[2] == 0x4e - && buf[3] == 0x47) { + goto done; + } + + if (*bufsize < 8) { + *next_size = 8; + ret = 1; + goto done; + } + + if (buf[0] == 0x89 && buf[1] == 0x50 && buf[2] == 0x4E && buf[3] == 0x47 && + buf[4] == 0x0D && buf[5] == 0x0A && buf[6] == 0x1A && buf[7] == 0x0A) { + metadataparse_png_init (&parse_data->format_data.png, adpt_exif, + adpt_iptc, adpt_xmp); + ret = 0; parse_data->img_type = IMG_PNG; - } else - ret = -1; + goto done; + } done: diff --git a/ext/metadata/metadataparse.h b/ext/metadata/metadataparse.h index fde0a8b8b5..4534f12a85 100644 --- a/ext/metadata/metadataparse.h +++ b/ext/metadata/metadataparse.h @@ -47,35 +47,41 @@ #include #include "metadataparsejpeg.h" +#include "metadataparsepng.h" G_BEGIN_DECLS -typedef enum _tag_ParseOption { +typedef enum _tag_ParseOption +{ PARSE_OPT_EXIF = (1 << 0), PARSE_OPT_IPTC = (1 << 1), - PARSE_OPT_XMP = (1 << 2), - PARSE_OPT_ALL = (1 << 3) -1 + PARSE_OPT_XMP = (1 << 2), + PARSE_OPT_ALL = (1 << 3) - 1 } ParseOption; -typedef enum _tag_ParseState { +typedef enum _tag_ParseState +{ STATE_NULL, STATE_READING, STATE_DONE } ParseState; -typedef enum _tag_ImageType { +typedef enum _tag_ImageType +{ IMG_NONE, IMG_JPEG, IMG_PNG } ImageType; - -typedef struct _tag_ParseData { +typedef struct _tag_ParseData +{ ParseState state; - ImageType img_type; + ImageType img_type; ParseOption option; - union { + union + { JpegData jpeg; + PngData png; } format_data; GstAdapter *adpt_exif; GstAdapter *adpt_iptc; @@ -87,8 +93,7 @@ typedef struct _tag_ParseData { #define set_parse_option(p, m) do { (p).option = (p).option | (m); } while(FALSE) #define unset_parse_option(p, m) do { (p).option = (p).option & ~(m); } while(FALSE) -extern void -metadataparse_init(ParseData *parse_data); +extern void metadataparse_init (ParseData * parse_data); /* * offset: number of bytes to jump (just a hint to jump a chunk) @@ -98,12 +103,11 @@ metadataparse_init(ParseData *parse_data); * 1 -> need more data */ extern int -metadataparse_parse(ParseData *parse_data, const guint8 *buf, guint32 bufsize, guint32 * next_offset, guint32 * next_size); +metadataparse_parse (ParseData * parse_data, const guint8 * buf, + guint32 bufsize, guint32 * next_offset, guint32 * next_size); -extern void -metadataparse_dispose(ParseData *parse_data); +extern void metadataparse_dispose (ParseData * parse_data); G_END_DECLS - #endif /* __METADATAPARSE_H__ */ diff --git a/ext/metadata/metadataparseexif.c b/ext/metadata/metadataparseexif.c index 204319ac46..4b7fd4f1de 100644 --- a/ext/metadata/metadataparseexif.c +++ b/ext/metadata/metadataparseexif.c @@ -65,7 +65,7 @@ metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, GST_LOG ("EXIF not defined, here I should send just one tag as whole chunk"); - metadataparse_tag_list_add_chunk (taglist, mode, GST_TAG_EXIF, adapter); + metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_EXIF, adapter); } @@ -91,7 +91,7 @@ metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, } /* add chunk tag */ - metadataparse_tag_list_add_chunk (taglist, mode, GST_TAG_EXIF, adapter); + metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_EXIF, adapter); buf = gst_adapter_peek (adapter, size); diff --git a/ext/metadata/metadataparseexif.h b/ext/metadata/metadataparseexif.h index 4830e5a35b..8c6ecb2cde 100644 --- a/ext/metadata/metadataparseexif.h +++ b/ext/metadata/metadataparseexif.h @@ -48,13 +48,11 @@ #include G_BEGIN_DECLS + extern void +metadataparse_exif_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, + GstAdapter * adapter); -extern void -metadataparse_exif_tag_list_add (GstTagList *taglist, GstTagMergeMode mode, GstAdapter * adapter); - -extern void -metadataparse_exif_tags_register (void); +extern void metadataparse_exif_tags_register (void); G_END_DECLS - #endif /* __GST_METADATAPARSE_EXIF_H__ */ diff --git a/ext/metadata/metadataparseiptc.c b/ext/metadata/metadataparseiptc.c index 3f3e5eab3e..ed4f803eae 100644 --- a/ext/metadata/metadataparseiptc.c +++ b/ext/metadata/metadataparseiptc.c @@ -65,7 +65,7 @@ metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, GST_LOG ("IPTC not defined, here I should send just one tag as whole chunk"); - metadataparse_tag_list_add_chunk (taglist, mode, GST_TAG_IPTC, adapter); + metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_IPTC, adapter); } @@ -89,7 +89,7 @@ metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, } /* add chunk tag */ - metadataparse_tag_list_add_chunk (taglist, mode, GST_TAG_IPTC, adapter); + metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_IPTC, adapter); buf = gst_adapter_peek (adapter, size); diff --git a/ext/metadata/metadataparseiptc.h b/ext/metadata/metadataparseiptc.h index 29bb559c04..e45d350fbe 100644 --- a/ext/metadata/metadataparseiptc.h +++ b/ext/metadata/metadataparseiptc.h @@ -50,11 +50,10 @@ G_BEGIN_DECLS extern void -metadataparse_iptc_tag_list_add (GstTagList *taglist, GstTagMergeMode mode, GstAdapter * adapter); +metadataparse_iptc_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, + GstAdapter * adapter); -extern void -metadataparse_iptc_tags_register (void); +extern void metadataparse_iptc_tags_register (void); G_END_DECLS - #endif /* __GST_METADATAPARSE_IPTC_H__ */ diff --git a/ext/metadata/metadataparsejpeg.c b/ext/metadata/metadataparsejpeg.c index 753d436a6b..1a3acb4b65 100644 --- a/ext/metadata/metadataparsejpeg.c +++ b/ext/metadata/metadataparsejpeg.c @@ -51,12 +51,6 @@ static int metadataparse_jpeg_reading (JpegData * jpeg_data, guint8 ** buf, guint32 * bufsize, guint8 ** next_start, guint32 * next_size); - -static int -metadataparse_jpeg_hold_chunk (JpegData * jpeg_data, guint8 ** buf, - guint32 * bufsize, guint8 ** next_start, - guint32 * next_size, GstAdapter ** adapter); - static int metadataparse_jpeg_exif (JpegData * jpeg_data, guint8 ** buf, guint32 * bufsize, guint8 ** next_start, guint32 * next_size); @@ -245,7 +239,9 @@ metadataparse_jpeg_reading (JpegData * jpeg_data, guint8 ** buf, if (jpeg_data->adpt_xmp) { if (0 == memcmp (XmpHeader, *buf, 29)) { - jpeg_data->read = chunk_size - 2; + *buf += 29; + *bufsize -= 29; + jpeg_data->read = chunk_size - 2 - 29; ret = 0; jpeg_data->state = JPEG_XMP; goto done; @@ -291,44 +287,18 @@ done: } -static int -metadataparse_jpeg_hold_chunk (JpegData * jpeg_data, guint8 ** buf, - guint32 * bufsize, guint8 ** next_start, - guint32 * next_size, GstAdapter ** adapter) -{ - int ret; - - if (jpeg_data->read > *bufsize) { - *next_start = *buf; - *next_size = jpeg_data->read; - ret = 1; - } else { - GstBuffer *gst_buf; - - if (NULL == *adapter) { - *adapter = gst_adapter_new (); - } - gst_buf = gst_buffer_new_and_alloc (jpeg_data->read); - memcpy (GST_BUFFER_DATA (gst_buf), *buf, jpeg_data->read); - gst_adapter_push (*adapter, gst_buf); - - *next_start = *buf + jpeg_data->read; - *buf += jpeg_data->read; - *bufsize -= jpeg_data->read; - jpeg_data->state = JPEG_READING; - ret = 0; - } - - return ret; -} - static int metadataparse_jpeg_exif (JpegData * jpeg_data, guint8 ** buf, guint32 * bufsize, guint8 ** next_start, guint32 * next_size) { + int ret; - return metadataparse_jpeg_hold_chunk (jpeg_data, buf, + ret = metadataparse_util_hold_chunk (&jpeg_data->read, buf, bufsize, next_start, next_size, jpeg_data->adpt_exif); + if (ret == 0) { + jpeg_data->state = JPEG_READING; + } + return ret; } @@ -339,7 +309,7 @@ metadataparse_jpeg_iptc (JpegData * jpeg_data, guint8 ** buf, int ret; - ret = metadataparse_jpeg_hold_chunk (jpeg_data, buf, + ret = metadataparse_util_hold_chunk (&jpeg_data->read, buf, bufsize, next_start, next_size, jpeg_data->adpt_iptc); @@ -350,6 +320,8 @@ metadataparse_jpeg_iptc (JpegData * jpeg_data, guint8 ** buf, unsigned int iptc_len; int res; + jpeg_data->state = JPEG_READING; + size = gst_adapter_available (*jpeg_data->adpt_iptc); buf = gst_adapter_peek (*jpeg_data->adpt_iptc, size); @@ -383,32 +355,22 @@ static int metadataparse_jpeg_xmp (JpegData * jpeg_data, guint8 ** buf, guint32 * bufsize, guint8 ** next_start, guint32 * next_size) { + int ret; - return metadataparse_jpeg_hold_chunk (jpeg_data, buf, + ret = metadataparse_util_hold_chunk (&jpeg_data->read, buf, bufsize, next_start, next_size, jpeg_data->adpt_xmp); + if (ret == 0) { + jpeg_data->state = JPEG_READING; + } + return ret; } static int metadataparse_jpeg_jump (JpegData * jpeg_data, guint8 ** buf, guint32 * bufsize, guint8 ** next_start, guint32 * next_size) { - int ret; - - if (jpeg_data->read > *bufsize) { - jpeg_data->read -= *bufsize; - *next_size = 2; - *next_start = *buf + *bufsize + jpeg_data->read; - jpeg_data->read = 0; - *bufsize = 0; - jpeg_data->state = JPEG_READING; - ret = 1; - } else { - *next_start = *buf + jpeg_data->read; - *buf += jpeg_data->read; - *bufsize -= jpeg_data->read; - jpeg_data->state = JPEG_READING; - ret = 0; - } - return ret; + jpeg_data->state = JPEG_READING; + return metadataparse_util_jump_chunk (&jpeg_data->read, buf, + bufsize, next_start, next_size); } diff --git a/ext/metadata/metadataparsejpeg.h b/ext/metadata/metadataparsejpeg.h index 67e5ac0e62..d7f1660d76 100644 --- a/ext/metadata/metadataparsejpeg.h +++ b/ext/metadata/metadataparsejpeg.h @@ -48,7 +48,8 @@ G_BEGIN_DECLS -typedef enum _tag_JpegState { +typedef enum _tag_JpegState +{ JPEG_NULL, JPEG_READING, JPEG_JUMPING, @@ -59,7 +60,8 @@ typedef enum _tag_JpegState { } JpegState; -typedef struct _tag_JpegData { +typedef struct _tag_JpegData +{ JpegState state; GstAdapter **adpt_exif; GstAdapter **adpt_iptc; @@ -69,17 +71,15 @@ typedef struct _tag_JpegData { extern void -metadataparse_jpeg_init(JpegData *jpeg_data, GstAdapter **adpt_exif, GstAdapter **adpt_iptc, GstAdapter **adpt_xmp); +metadataparse_jpeg_init (JpegData * jpeg_data, GstAdapter ** adpt_exif, + GstAdapter ** adpt_iptc, GstAdapter ** adpt_xmp); -extern void -metadataparse_jpeg_dispose(JpegData *jpeg_data); +extern void metadataparse_jpeg_dispose (JpegData * jpeg_data); int -metadataparse_jpeg_parse(JpegData *jpeg_data, guint8 *buf, - guint32 *bufsize, guint8 ** next_start, - guint32 * next_size); +metadataparse_jpeg_parse (JpegData * jpeg_data, guint8 * buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size); G_END_DECLS - #endif /* __METADATAPARSE_JPEG_H__ */ diff --git a/ext/metadata/metadataparsepng.c b/ext/metadata/metadataparsepng.c new file mode 100644 index 0000000000..9c3241cfcf --- /dev/null +++ b/ext/metadata/metadataparsepng.c @@ -0,0 +1,245 @@ +/* + * GStreamer + * Copyright 2007 Edgard Lima + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "metadataparsepng.h" + +#include + +static int +metadataparse_png_reading (PngData * png_data, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size); + +static int +metadataparse_png_xmp (PngData * png_data, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size); + +static int +metadataparse_png_jump (PngData * png_data, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size); + +#define READ(buf, size) ( (size)--, *((buf)++) ) + +void +metadataparse_png_init (PngData * png_data, GstAdapter ** adpt_exif, + GstAdapter ** adpt_iptc, GstAdapter ** adpt_xmp) +{ + png_data->state = PNG_NULL; + png_data->adpt_xmp = adpt_xmp; + png_data->read = 0; + + metadataparse_xmp_init (); +} + +void +metadataparse_png_dispose (PngData * png_data) +{ + metadataparse_xmp_dispose (); + + png_data->adpt_xmp = NULL; +} + +int +metadataparse_png_parse (PngData * png_data, guint8 * buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size) +{ + + int ret = 0; + guint8 mark[8]; + + *next_start = buf; + + if (png_data->state == PNG_NULL) { + + if (*bufsize < 8) { + *next_size = (buf - *next_start) + 8; + ret = 1; + goto done; + } + + mark[0] = READ (buf, *bufsize); + mark[1] = READ (buf, *bufsize); + mark[2] = READ (buf, *bufsize); + mark[3] = READ (buf, *bufsize); + mark[4] = READ (buf, *bufsize); + mark[5] = READ (buf, *bufsize); + mark[6] = READ (buf, *bufsize); + mark[7] = READ (buf, *bufsize); + + if (mark[0] != 0x89 || mark[1] != 0x50 || mark[2] != 0x4E || mark[3] != 0x47 + || mark[4] != 0x0D || mark[5] != 0x0A || mark[6] != 0x1A + || mark[7] != 0x0A) { + ret = -1; + goto done; + } + + png_data->state = PNG_READING; + + } + + while (ret == 0) { + switch (png_data->state) { + case PNG_READING: + ret = + metadataparse_png_reading (png_data, &buf, bufsize, next_start, + next_size); + break; + case PNG_JUMPING: + ret = + metadataparse_png_jump (png_data, &buf, bufsize, next_start, + next_size); + break; + case PNG_XMP: + ret = + metadataparse_png_xmp (png_data, &buf, bufsize, next_start, + next_size); + break; + case PNG_DONE: + goto done; + break; + default: + ret = -1; + break; + } + } + +done: + + return ret; + +} + + +/* look for markers */ +static int +metadataparse_png_reading (PngData * png_data, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size) +{ + + int ret = -1; + guint8 mark[4]; + guint32 chunk_size = 0; + + static const char XmpHeader[] = "XML:com.adobe.xmp"; + + *next_start = *buf; + + if (*bufsize < 8) { + *next_size = (*buf - *next_start) + 8; + ret = 1; + goto done; + } + + chunk_size = READ (*buf, *bufsize) << 24; + chunk_size += READ (*buf, *bufsize) << 16; + chunk_size += READ (*buf, *bufsize) << 8; + chunk_size += READ (*buf, *bufsize); + + mark[0] = READ (*buf, *bufsize); + mark[1] = READ (*buf, *bufsize); + mark[2] = READ (*buf, *bufsize); + mark[3] = READ (*buf, *bufsize); + + if (mark[0] == 'I' && mark[1] == 'E' && mark[2] == 'N' && mark[3] == 'D') { + ret = 0; + png_data->state = PNG_DONE; + goto done; + } + + if (mark[0] == 'i' && mark[1] == 'T' && mark[2] == 'X' && mark[3] == 't') { + if (chunk_size >= 22) { /* "XML:com.adobe.xmp" plus some flags */ + if (*bufsize < 22) { + *next_size = (*buf - *next_start) + 22; + ret = 1; + goto done; + } + + if (png_data->adpt_xmp) { + if (0 == memcmp (XmpHeader, *buf, 18)) { + *buf += 22; /* jump "XML:com.adobe.xmp" plus some flags */ + *bufsize -= 22; + png_data->read = chunk_size - 22; /* four CRC bytes at the end will be jumped after */ + png_data->state = PNG_XMP; + ret = 0; + goto done; + } + } + } + } + + /* just set jump sise */ + png_data->read = chunk_size + 4; /* four CRC bytes at the end */ + png_data->state = PNG_JUMPING; + ret = 0; + +done: + + return ret; + + +} + +static int +metadataparse_png_jump (PngData * png_data, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size) +{ + png_data->state = PNG_READING; + return metadataparse_util_jump_chunk (&png_data->read, buf, + bufsize, next_start, next_size); +} + +static int +metadataparse_png_xmp (PngData * png_data, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size) +{ + int ret; + + ret = metadataparse_util_hold_chunk (&png_data->read, buf, + bufsize, next_start, next_size, png_data->adpt_xmp); + if (ret == 0) { + /* jump four CRC bytes at the end of chunk */ + png_data->read = 4; + png_data->state = PNG_JUMPING; + } + return ret; + +} diff --git a/ext/metadata/metadataparsepng.h b/ext/metadata/metadataparsepng.h new file mode 100644 index 0000000000..99f0f7ea9b --- /dev/null +++ b/ext/metadata/metadataparsepng.h @@ -0,0 +1,81 @@ +/* + * GStreamer + * Copyright 2007 Edgard Lima + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __METADATAPARSE_PNG_H__ +#define __METADATAPARSE_PNG_H__ + +#include + +G_BEGIN_DECLS + +typedef enum _tag_PngState +{ + PNG_NULL, + PNG_READING, + PNG_JUMPING, + PNG_XMP, + PNG_DONE +} PngState; + + +typedef struct _tag_PngData +{ + PngState state; + GstAdapter **adpt_xmp; + guint32 read; +} PngData; + + +extern void +metadataparse_png_init (PngData * png_data, GstAdapter ** adpt_exif, + GstAdapter ** adpt_iptc, GstAdapter ** adpt_xmp); + +extern void metadataparse_png_dispose (PngData * png_data); + + +int +metadataparse_png_parse (PngData * png_data, guint8 * buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size); + +G_END_DECLS +#endif /* __METADATAPARSE_PNG_H__ */ diff --git a/ext/metadata/metadataparseutil.c b/ext/metadata/metadataparseutil.c index dfab579f75..ff1b882634 100644 --- a/ext/metadata/metadataparseutil.c +++ b/ext/metadata/metadataparseutil.c @@ -44,8 +44,8 @@ #include "metadataparseutil.h" void -metadataparse_tag_list_add_chunk (GstTagList * taglist, GstTagMergeMode mode, - const gchar * name, GstAdapter * adapter) +metadataparse_util_tag_list_add_chunk (GstTagList * taglist, + GstTagMergeMode mode, const gchar * name, GstAdapter * adapter) { GstBuffer *buf; guint size; @@ -62,3 +62,57 @@ metadataparse_tag_list_add_chunk (GstTagList * taglist, GstTagMergeMode mode, } } + +int +metadataparse_util_hold_chunk (guint32 * read, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, + guint32 * next_size, GstAdapter ** adapter) +{ + int ret; + + if (*read > *bufsize) { + *next_start = *buf; + *next_size = *read; + ret = 1; + } else { + GstBuffer *gst_buf; + + if (NULL == *adapter) { + *adapter = gst_adapter_new (); + } + gst_buf = gst_buffer_new_and_alloc (*read); + memcpy (GST_BUFFER_DATA (gst_buf), *buf, *read); + gst_adapter_push (*adapter, gst_buf); + + *next_start = *buf + *read; + *buf += *read; + *bufsize -= *read; + *read = 0; + ret = 0; + } + + return ret; +} + +int +metadataparse_util_jump_chunk (guint32 * read, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size) +{ + int ret; + + if (*read > *bufsize) { + *read -= *bufsize; + *next_size = 2; + *next_start = *buf + *bufsize + *read; + *read = 0; + *bufsize = 0; + ret = 1; + } else { + *next_start = *buf + *read; + *buf += *read; + *bufsize -= *read; + *read = 0; + ret = 0; + } + return ret; +} diff --git a/ext/metadata/metadataparseutil.h b/ext/metadata/metadataparseutil.h index 7512984378..5d49b54b5c 100644 --- a/ext/metadata/metadataparseutil.h +++ b/ext/metadata/metadataparseutil.h @@ -50,9 +50,15 @@ G_BEGIN_DECLS extern void -metadataparse_tag_list_add_chunk (GstTagList * taglist, GstTagMergeMode mode, - const gchar * name, GstAdapter * adapter); +metadataparse_util_tag_list_add_chunk (GstTagList * taglist, + GstTagMergeMode mode, const gchar * name, GstAdapter * adapter); +extern int metadataparse_util_hold_chunk (guint32 * read, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size, + GstAdapter ** adapter); + +extern int +metadataparse_util_jump_chunk (guint32 * read, guint8 ** buf, + guint32 * bufsize, guint8 ** next_start, guint32 * next_size); G_END_DECLS - #endif /* __GST_METADATAPARSE_UTIL_H__ */ diff --git a/ext/metadata/metadataparsexmp.c b/ext/metadata/metadataparsexmp.c index 9b58300257..aa503d3518 100644 --- a/ext/metadata/metadataparsexmp.c +++ b/ext/metadata/metadataparsexmp.c @@ -65,7 +65,7 @@ metadataparse_xmp_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, GST_LOG ("XMP not defined, here I should send just one tag as whole chunk"); - metadataparse_tag_list_add_chunk (taglist, mode, GST_TAG_XMP, adapter); + metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_XMP, adapter); } @@ -111,13 +111,10 @@ metadataparse_xmp_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, } /* add chunk tag */ - metadataparse_tag_list_add_chunk (taglist, mode, GST_TAG_XMP, adapter); + metadataparse_util_tag_list_add_chunk (taglist, mode, GST_TAG_XMP, adapter); buf = gst_adapter_peek (adapter, size); - buf += 29; /* jump "http://ns.adobe.com/xap/1.0/" */ - size -= 29; - xmp = xmp_new (buf, size); if (!xmp) goto done; @@ -128,7 +125,6 @@ metadataparse_xmp_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, xmp_serialize (xmp, xmp_str, XMP_SERIAL_ENCODEUTF8, 2); - GST_LOG (xmp_string_cstr (xmp_str)); done: diff --git a/ext/metadata/metadataparsexmp.h b/ext/metadata/metadataparsexmp.h index 07e34a95cd..80b93a3981 100644 --- a/ext/metadata/metadataparsexmp.h +++ b/ext/metadata/metadataparsexmp.h @@ -50,17 +50,14 @@ G_BEGIN_DECLS extern void -metadataparse_xmp_tag_list_add (GstTagList *taglist, GstTagMergeMode mode, GstAdapter * adapter); +metadataparse_xmp_tag_list_add (GstTagList * taglist, GstTagMergeMode mode, + GstAdapter * adapter); -extern gboolean -metadataparse_xmp_init(void); +extern gboolean metadataparse_xmp_init (void); -extern void -metadataparse_xmp_dispose(void); +extern void metadataparse_xmp_dispose (void); -extern void -metadataparse_xmp_tags_register (void); +extern void metadataparse_xmp_tags_register (void); G_END_DECLS - #endif /* __GST_METADATAPARSE_XMP_H__ */