diff options
author | Edgard Lima <edgard.lima@indt.org.br> | 2007-11-23 17:35:21 +0000 |
---|---|---|
committer | Edgard Lima <edgard.lima@indt.org.br> | 2007-11-23 17:35:21 +0000 |
commit | 1cb35c75741314f40f098250108b1b0e7db643cc (patch) | |
tree | 6aac146d2ba54a9bdd7e7c720d39d4e92a9d496c /ext/metadata | |
parent | db93cd7461e32ce9e4261309e6d972758c0de8db (diff) | |
download | gst-plugins-bad-1cb35c75741314f40f098250108b1b0e7db643cc.tar.gz gst-plugins-bad-1cb35c75741314f40f098250108b1b0e7db643cc.tar.bz2 gst-plugins-bad-1cb35c75741314f40f098250108b1b0e7db643cc.zip |
Now parser is generic (just add/remove a list of chunks). And a template of muxer has been created.
Original commit message from CVS:
Now parser is generic (just add/remove a list of chunks). And a template of muxer has been created.
Diffstat (limited to 'ext/metadata')
-rw-r--r-- | ext/metadata/Makefile.am | 22 | ||||
-rw-r--r-- | ext/metadata/gstmetadata.c | 14 | ||||
-rw-r--r-- | ext/metadata/gstmetadatamux.c | 243 | ||||
-rw-r--r-- | ext/metadata/gstmetadatamux.h (renamed from ext/metadata/metadataparsetypes.h) | 45 | ||||
-rw-r--r-- | ext/metadata/gstmetadataparse.c | 669 | ||||
-rw-r--r-- | ext/metadata/gstmetadataparse.h | 24 | ||||
-rw-r--r-- | ext/metadata/metadataparse.c | 68 | ||||
-rw-r--r-- | ext/metadata/metadataparse.h | 14 | ||||
-rw-r--r-- | ext/metadata/metadataparsejpeg.c | 136 | ||||
-rw-r--r-- | ext/metadata/metadataparsejpeg.h | 20 | ||||
-rw-r--r-- | ext/metadata/metadataparsepng.c | 31 | ||||
-rw-r--r-- | ext/metadata/metadataparsepng.h | 16 | ||||
-rw-r--r-- | ext/metadata/metadatatypes.c | 115 | ||||
-rw-r--r-- | ext/metadata/metadatatypes.h | 85 |
14 files changed, 1150 insertions, 352 deletions
diff --git a/ext/metadata/Makefile.am b/ext/metadata/Makefile.am index 095a3996..950f9ff4 100644 --- a/ext/metadata/Makefile.am +++ b/ext/metadata/Makefile.am @@ -8,18 +8,22 @@ libgstmetadata_la_SOURCES = gstmetadata.c \ metadataparseexif.c \ metadataparseiptc.c \ metadataparsexmp.c \ - metadataparseutil.c + metadataparseutil.c \ + metadatatypes.c \ + gstmetadatamux.c libgstmetadata_la_CFLAGS = $(METADATA_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) libgstmetadata_la_LIBADD = $(METADATA_LIBS) -lgsttag-@GST_MAJORMINOR@ $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) libgstmetadata_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -noinst_HEADERS = gstmetadataparse.h \ - metadataparse.h \ - metadataparsejpeg.h \ - metadataparsepng.h \ - metadataparseexif.h \ - metadataparseiptc.h \ - metadataparsexmp.h \ - metadataparseutil.h +noinst_HEADERS = gstmetadataparse.h \ + metadataparse.h \ + metadataparsejpeg.h \ + metadataparsepng.h \ + metadataparseexif.h \ + metadataparseiptc.h \ + metadataparsexmp.h \ + metadataparseutil.h \ + metadatatypes.h \ + gstmetadatamux.h diff --git a/ext/metadata/gstmetadata.c b/ext/metadata/gstmetadata.c index 263c8b37..858f33db 100644 --- a/ext/metadata/gstmetadata.c +++ b/ext/metadata/gstmetadata.c @@ -45,14 +45,22 @@ #include "config.h" #endif -#include "gstmetadataparse.h" -/* #include "gstmetadatamux.h" ...soon.. */ +#include <gst/gst.h> + +extern gboolean gst_metadata_parse_plugin_init (GstPlugin * plugin); +extern gboolean gst_metadata_mux_plugin_init (GstPlugin * plugin); static gboolean plugin_init (GstPlugin * plugin) { - return gst_metadata_parse_plugin_init (plugin); + gboolean ret = TRUE; + + ret = gst_metadata_parse_plugin_init (plugin); + + ret = ret && gst_metadata_mux_plugin_init (plugin); + + return ret; } diff --git a/ext/metadata/gstmetadatamux.c b/ext/metadata/gstmetadatamux.c new file mode 100644 index 00000000..556191b7 --- /dev/null +++ b/ext/metadata/gstmetadatamux.c @@ -0,0 +1,243 @@ +/* + * GStreamer + * Copyright 2007 Edgard Lima <edgard.lima@indt.org.br> + * + * 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. + */ + +/** + * SECTION:element-plugin + * + * <refsect2> + * <title>Example launch line</title> + * <para> + * <programlisting> + * gst-launch -v -m filesrc location=./test.jpeg ! metadatamux ! filesink location=meta.jpeg + * </programlisting> + * </para> + * </refsect2> + */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gst/gst.h> + +#include "gstmetadatamux.h" + +GST_DEBUG_CATEGORY_STATIC (gst_metadata_mux_debug); +#define GST_CAT_DEFAULT gst_metadata_mux_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + ARG_0, +}; + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/jpeg, tags-extracted = (bool) true;" + "image/png, tags-extracted = (bool) true") + ); + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/jpeg; " "image/png") + ); + +GST_BOILERPLATE (GstMetadataMux, gst_metadata_mux, GstElement, + GST_TYPE_ELEMENT); + +static void gst_metadata_mux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_metadata_mux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_metadata_mux_set_caps (GstPad * pad, GstCaps * caps); +static GstFlowReturn gst_metadata_mux_chain (GstPad * pad, GstBuffer * buf); + +static void +gst_metadata_mux_base_init (gpointer gclass) +{ + static GstElementDetails element_details = { + "PluginTemplate", + "Generic/PluginTemplate", + "Generic Template Element", + "Thomas Vander Stichele <thomas@apestaart.org>" + }; + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); + gst_element_class_set_details (element_class, &element_details); +} + +/* initialize the plugin's class */ +static void +gst_metadata_mux_class_init (GstMetadataMuxClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_metadata_mux_set_property; + gobject_class->get_property = gst_metadata_mux_get_property; + + +} + +/* initialize the new element + * instantiate pads and add them to element + * set functions + * initialize structure + */ +static void +gst_metadata_mux_init (GstMetadataMux * filter, GstMetadataMuxClass * gclass) +{ + GstElementClass *klass = GST_ELEMENT_GET_CLASS (filter); + + filter->sinkpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "sink"), "sink"); + gst_pad_set_setcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_metadata_mux_set_caps)); + gst_pad_set_getcaps_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); + + filter->srcpad = + gst_pad_new_from_template (gst_element_class_get_pad_template (klass, + "src"), "src"); + gst_pad_set_getcaps_function (filter->srcpad, + GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); + + gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); + gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad); + gst_pad_set_chain_function (filter->sinkpad, + GST_DEBUG_FUNCPTR (gst_metadata_mux_chain)); + +} + +static void +gst_metadata_mux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstMetadataMux *filter = GST_METADATA_MUX (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_metadata_mux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstMetadataMux *filter = GST_METADATA_MUX (object); + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* GstElement vmethod implementations */ + +/* this function handles the link with other elements */ +static gboolean +gst_metadata_mux_set_caps (GstPad * pad, GstCaps * caps) +{ + GstMetadataMux *filter; + GstPad *otherpad; + + filter = GST_METADATA_MUX (gst_pad_get_parent (pad)); + otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad; + + return gst_pad_set_caps (pad, caps); +} + +/* chain function + * this function does the actual processing + */ + +static GstFlowReturn +gst_metadata_mux_chain (GstPad * pad, GstBuffer * buf) +{ + GstMetadataMux *filter; + + filter = GST_METADATA_MUX (GST_OBJECT_PARENT (pad)); + + /* just push out the incoming buffer without touching it */ + return gst_pad_push (filter->srcpad, buf); +} + + +/* entry point to initialize the plug-in + * initialize the plug-in itself + * register the element factories and pad templates + * register the features + * + * exchange the string 'plugin' with your elemnt name + */ +gboolean +gst_metadata_mux_plugin_init (GstPlugin * plugin) +{ + /* exchange the strings 'plugin' and 'Template plugin' with your + * plugin name and description */ + GST_DEBUG_CATEGORY_INIT (gst_metadata_mux_debug, "metadatamux", + 0, "Metadata muxer"); + + return gst_element_register (plugin, "metadatamux", + GST_RANK_NONE, GST_TYPE_METADATA_MUX); +} diff --git a/ext/metadata/metadataparsetypes.h b/ext/metadata/gstmetadatamux.h index 7fd74fb4..8deb0f5f 100644 --- a/ext/metadata/metadataparsetypes.h +++ b/ext/metadata/gstmetadatamux.h @@ -41,24 +41,43 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __METADATAPARSETYPES_H__ -#define __METADATAPARSETYPES_H__ +#ifndef __GST_METADATA_MUX_H__ +#define __GST_METADATA_MUX_H__ -#include <gst/base/gstadapter.h> +#include <gst/gst.h> G_BEGIN_DECLS -typedef struct _tag_MetadataChunk +/* #defines don't like whitespacey bits */ +#define GST_TYPE_METADATA_MUX \ + (gst_metadata_mux_get_type()) +#define GST_METADATA_MUX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_METADATA_MUX,GstMetadataMux)) +#define GST_METADATA_MUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_METADATA_MUX,GstMetadataMuxClass)) +#define GST_IS_METADATAMUX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_METADATA_MUX)) +#define GST_IS_METADATAMUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_METADATA_MUX)) + +typedef struct _GstMetadataMux GstMetadataMux; +typedef struct _GstMetadataMuxClass GstMetadataMuxClass; + +struct _GstMetadataMux { - gint64 offset; /* from the beginning of file */ - guint32 size; /* size of bytes in chunk (same as adapter size) */ - GstAdapter *adapter; - /* in some cases, when there is JPEG/EXIF, and no JIF as first chunk - is is need to add a chunk data back to the file */ - guint32 size_inject; /* same as buffer size */ - guint8 * buffer; -} MetadataChunk; + GstElement element; + GstPad *sinkpad, *srcpad; + +}; + +struct _GstMetadataMuxClass +{ + GstElementClass parent_class; +}; + +GType gst_metadata_mux_get_type (void); G_END_DECLS -#endif /* __METADATAPARSETYPES_H__ */ + +#endif /* __GST_METADATA_MUX_H__ */ diff --git a/ext/metadata/gstmetadataparse.c b/ext/metadata/gstmetadataparse.c index f5afb477..dfe7502e 100644 --- a/ext/metadata/gstmetadataparse.c +++ b/ext/metadata/gstmetadataparse.c @@ -138,13 +138,13 @@ static gboolean gst_metadata_parse_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_metadata_parse_chain (GstPad * pad, GstBuffer * buf); static gboolean -gst_metadata_parse_get_range (GstPad * pad, guint64 offset, guint size, +gst_metadata_parse_get_range (GstPad * pad, guint64 offset_orig, guint size, GstBuffer ** buf); -static gboolean gst_metadata_parse_activate (GstPad * pad); +static gboolean gst_metadata_parse_sink_activate (GstPad * pad); static gboolean -gst_metadata_parse_element_activate_src_pull (GstPad * pad, gboolean active); +gst_metadata_parse_src_activate_pull (GstPad * pad, gboolean active); static gboolean gst_metadata_parse_pull_range_parse (GstMetadataParse * filter); @@ -161,19 +161,20 @@ gst_metadata_parse_parse (GstMetadataParse * filter, const guint8 * buf, static void gst_metadata_parse_send_tags (GstMetadataParse * filter); -static gboolean gst_metadata_parse_activate (GstPad * pad); + static int gst_metadata_parse_get_strip_seg (const gint64 offset, guint32 size, const gint64 seg_offset, const guint32 seg_size, - guint32 * boffset, guint32 * bsize, guint32 * seg_binter); + gint64 * boffset, guint32 * bsize, guint32 * seg_binter); + static gboolean -gst_metadata_parse_strip_buffer (GstMetadataParse * filter, gint64 offset, - GstBuffer ** buf); +gst_metadata_parse_strip_push_buffer (GstMetadataParse * filter, + gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf); -static void -gst_metadata_parse_translate_pos (GstMetadataParse * filter, gint64 pos, - gint64 * orig_pos); +static gboolean +gst_metadata_parse_translate_pos_to_orig (GstMetadataParse * filter, gint64 pos, + gint64 * orig_pos, GstBuffer ** buf); static const GstQueryType *gst_metadata_parse_get_query_types (GstPad * pad); @@ -254,7 +255,8 @@ gst_metadata_parse_init (GstMetadataParse * filter, gst_pad_set_event_function (filter->sinkpad, gst_metadata_parse_sink_event); gst_pad_set_chain_function (filter->sinkpad, GST_DEBUG_FUNCPTR (gst_metadata_parse_chain)); - gst_pad_set_activate_function (filter->sinkpad, gst_metadata_parse_activate); + gst_pad_set_activate_function (filter->sinkpad, + gst_metadata_parse_sink_activate); /* source pad */ @@ -269,9 +271,11 @@ gst_metadata_parse_init (GstMetadataParse * filter, gst_pad_set_query_type_function (filter->srcpad, GST_DEBUG_FUNCPTR (gst_metadata_parse_get_query_types)); gst_pad_use_fixed_caps (filter->srcpad); + gst_pad_set_getrange_function (filter->srcpad, gst_metadata_parse_get_range); + gst_pad_set_activatepull_function (filter->srcpad, - GST_DEBUG_FUNCPTR (gst_metadata_parse_element_activate_src_pull)); + GST_DEBUG_FUNCPTR (gst_metadata_parse_src_activate_pull)); /* addind pads */ gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad); @@ -460,7 +464,13 @@ gst_metadata_parse_src_event (GstPad * pad, GstEvent * event) } start_type == GST_SEEK_TYPE_SET; - gst_metadata_parse_translate_pos (filter, start, &start); + if (filter->prepend_buffer) { + gst_buffer_unref (filter->prepend_buffer); + filter->prepend_buffer = NULL; + } + + gst_metadata_parse_translate_pos_to_orig (filter, start, &start, + &filter->prepend_buffer); if (stop_type == GST_SEEK_TYPE_CUR) stop = filter->offset + stop; @@ -471,7 +481,7 @@ gst_metadata_parse_src_event (GstPad * pad, GstEvent * event) } stop_type == GST_SEEK_TYPE_SET; - gst_metadata_parse_translate_pos (filter, stop, &stop); + gst_metadata_parse_translate_pos_to_orig (filter, stop, &stop, NULL); gst_event_unref (event); event = gst_event_new_seek (rate, format, flags, @@ -549,14 +559,31 @@ static void gst_metadata_parse_dispose_members (GstMetadataParse * filter) { metadataparse_dispose (&filter->parse_data); - if (filter->adapter) { - gst_object_unref (filter->adapter); - filter->adapter = NULL; + + if (filter->adapter_parsing) { + gst_object_unref (filter->adapter_parsing); + filter->adapter_parsing = NULL; + } + + if (filter->adapter_holding) { + gst_object_unref (filter->adapter_holding); + filter->adapter_holding = NULL; } + if (filter->taglist) { gst_tag_list_free (filter->taglist); filter->taglist = NULL; } + + if (filter->append_buffer) { + gst_buffer_unref (filter->append_buffer); + filter->append_buffer = NULL; + } + + if (filter->prepend_buffer) { + gst_buffer_unref (filter->prepend_buffer); + filter->prepend_buffer = NULL; + } } static void @@ -567,30 +594,23 @@ gst_metadata_parse_init_members (GstMetadataParse * filter) filter->iptc = TRUE; filter->xmp = TRUE; - memset (filter->seg_offset_orig, 0x00, - sizeof (filter->seg_offset_orig[0]) * 3); - memset (filter->seg_size, 0x00, sizeof (filter->seg_size[0]) * 3); - - memset (filter->seg_inject_offset, 0x00, - sizeof (filter->seg_inject_offset[0]) * 3); - memset (filter->seg_inject_data, 0x00, - sizeof (filter->seg_inject_data[0]) * 3); - memset (filter->seg_inject_size, 0x00, - sizeof (filter->seg_inject_size[0]) * 3); - - filter->num_segs = 0; - filter->taglist = NULL; - filter->adapter = NULL; + filter->adapter_parsing = NULL; + filter->adapter_holding = NULL; filter->next_offset = 0; filter->next_size = 0; filter->img_type = IMG_NONE; - filter->duration = -1; filter->offset_orig = 0; + filter->duration_orig = 0; filter->offset = 0; + filter->duration = 0; filter->state = MT_STATE_NULL; filter->need_more_data = FALSE; - metadataparse_init (&filter->parse_data); + + filter->append_buffer = NULL; + filter->prepend_buffer = NULL; + + memset (&filter->parse_data, 0x00, sizeof (ParseData)); } static gboolean @@ -745,13 +765,13 @@ gst_metadata_parse_send_tags (GstMetadataParse * filter) if (PARSE_DATA_OPTION (filter->parse_data) & PARSE_OPT_EXIF) metadataparse_exif_tag_list_add (filter->taglist, GST_TAG_MERGE_KEEP, - filter->parse_data.exif.adapter); + filter->parse_data.exif_adapter); if (PARSE_DATA_OPTION (filter->parse_data) & PARSE_OPT_IPTC) metadataparse_iptc_tag_list_add (filter->taglist, GST_TAG_MERGE_KEEP, - filter->parse_data.iptc.adapter); + filter->parse_data.iptc_adapter); if (PARSE_DATA_OPTION (filter->parse_data) & PARSE_OPT_XMP) metadataparse_xmp_tag_list_add (filter->taglist, GST_TAG_MERGE_KEEP, - filter->parse_data.xmp.adapter); + filter->parse_data.xmp_adapter); if (!gst_tag_list_is_empty (filter->taglist)) { @@ -853,77 +873,50 @@ gst_metadata_parse_parse (GstMetadataParse * filter, const guint8 * buf, filter->need_more_data = TRUE; } else { int i, j; - guint32 bytes_striped; - - filter->num_segs = 0; - - /* FIXME: better design for segments */ - - filter->seg_size[0] = filter->parse_data.exif.size; - filter->seg_offset_orig[0] = filter->parse_data.exif.offset; - filter->seg_inject_size[0] = filter->parse_data.exif.size_inject; - filter->seg_inject_data[0] = filter->parse_data.exif.buffer; - - filter->seg_size[1] = filter->parse_data.iptc.size; - filter->seg_offset_orig[1] = filter->parse_data.iptc.offset; - filter->seg_inject_size[1] = filter->parse_data.iptc.size_inject; - filter->seg_inject_data[1] = filter->parse_data.iptc.buffer; - - filter->seg_size[2] = filter->parse_data.xmp.size; - filter->seg_offset_orig[2] = filter->parse_data.xmp.offset; - filter->seg_inject_size[2] = filter->parse_data.xmp.size_inject; - filter->seg_inject_data[2] = filter->parse_data.xmp.buffer; - - for (i = 0; i < 3; ++i) { - if (filter->seg_size[i]) { - filter->num_segs++; + guint32 append_size; + guint32 bytes_striped, bytes_inject; + MetadataChunk *strip = filter->parse_data.strip_chunks.chunk; + MetadataChunk *inject = filter->parse_data.inject_chunks.chunk; + const gsize strip_len = filter->parse_data.strip_chunks.len; + const gsize inject_len = filter->parse_data.inject_chunks.len; + + bytes_striped = 0; + bytes_inject = 0; + + /* calculate the new position off injected chunks */ + for (i = 0; i < inject_len; ++i) { + for (j = 0; j < strip_len; ++i) { + if (strip[j].offset_orig >= inject[i].offset_orig) { + break; + } + inject[i].offset = inject[i].offset_orig - bytes_striped + bytes_inject; + bytes_striped += strip[j].size; } + bytes_inject += inject[i].size; } - if (filter->num_segs) { - - for (i = 0; i < 3; ++i) { - int j, min = i; - - for (j = i + 1; j < 3; ++j) { - if (filter->seg_size[j]) - if (filter->seg_size[min] == 0 - || filter->seg_offset_orig[j] < filter->seg_offset_orig[min]) - min = j; - } - if (min != i) { - gint64 aux_offset; - guint32 aux_size; - guint8 *aux_data; - - aux_offset = filter->seg_offset_orig[i]; - aux_size = filter->seg_size[i]; - - filter->seg_offset_orig[i] = filter->seg_offset_orig[min]; - filter->seg_size[i] = filter->seg_size[min]; - - filter->seg_offset_orig[min] = aux_offset; - filter->seg_size[min] = aux_size; - - aux_size = filter->seg_inject_size[i]; - filter->seg_inject_size[i] = filter->seg_inject_size[min]; - filter->seg_inject_size[min] = aux_size; - - aux_data = filter->seg_inject_data[i]; - filter->seg_inject_data[i] = filter->seg_inject_data[min]; - filter->seg_inject_data[min] = aux_data; + /* calculate append (doesnt make much sense, but, anyway..) */ + append_size = 0; + for (i = inject_len - 1; i >= 0; --i) { + if (inject[i].offset_orig == filter->duration_orig) + append_size += inject[i].size; + else + break; + } + if (append_size) { + guint8 *data; + + filter->append_buffer = gst_buffer_new_and_alloc (append_size); + GST_BUFFER_FLAG_SET (filter->append_buffer, GST_BUFFER_FLAG_READONLY); + data = GST_BUFFER_DATA (filter->append_buffer); + for (i = inject_len - 1; i >= 0; --i) { + if (inject[i].offset_orig == filter->duration_orig) { + memcpy (data, inject[i].data, inject[i].size); + data += inject[i].size; + } else { + break; } } - - bytes_striped = 0; - - /* calculate the new position off injected chunks */ - for (i = 0; i < filter->num_segs; ++i) { - filter->seg_inject_offset[i] = - filter->seg_offset_orig[i] - bytes_striped; - bytes_striped += filter->seg_size[i] - filter->seg_inject_size[i]; - } - } filter->state = MT_STATE_PARSED; @@ -965,18 +958,19 @@ gst_metadata_parse_chain (GstPad * pad, GstBuffer * buf) GstFlowReturn ret = GST_FLOW_ERROR; guint32 buf_size = 0; guint32 new_buf_size = 0; + gboolean append = FALSE; filter = GST_METADATA_PARSE (gst_pad_get_parent (pad)); /* commented until I figure out how to strip if it wasn't parsed yet */ -#if 0 + if (filter->state != MT_STATE_PARSED) { - guint32 adpt_size = gst_adapter_available (filter->adapter); + guint32 adpt_size = gst_adapter_available (filter->adapter_parsing); if (filter->next_offset) { if (filter->next_offset >= adpt_size) { /* clean adapter */ - gst_adapter_clear (filter->adapter); + gst_adapter_clear (filter->adapter_parsing); filter->next_offset -= adpt_size; if (filter->next_offset >= GST_BUFFER_SIZE (buf)) { /* we don't need data in this buffer */ @@ -991,51 +985,87 @@ gst_metadata_parse_chain (GstPad * pad, GstBuffer * buf) memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf) - filter->next_offset); filter->next_offset = 0; - gst_adapter_push (filter->adapter, new_buf); + gst_adapter_push (filter->adapter_parsing, new_buf); } } else { /* remove first bytes and add buffer */ - gst_adapter_flush (filter->adapter, filter->next_offset); + gst_adapter_flush (filter->adapter_parsing, filter->next_offset); filter->next_offset = 0; - gst_adapter_push (filter->adapter, gst_buffer_copy (buf)); + gst_adapter_push (filter->adapter_parsing, gst_buffer_copy (buf)); } } else { /* just push buffer */ - gst_adapter_push (filter->adapter, gst_buffer_copy (buf)); + gst_adapter_push (filter->adapter_parsing, gst_buffer_copy (buf)); } - adpt_size = gst_adapter_available (filter->adapter); + adpt_size = gst_adapter_available (filter->adapter_parsing); if (adpt_size && filter->next_size <= adpt_size) { - const guint8 *new_buf = gst_adapter_peek (filter->adapter, adpt_size); + const guint8 *new_buf = + gst_adapter_peek (filter->adapter_parsing, adpt_size); if (gst_metadata_parse_parse (filter, new_buf, adpt_size) < 0) goto done; } } -#endif - if (filter->need_send_tag) { - gst_metadata_parse_send_tags (filter); - } + if (filter->state == MT_STATE_PARSED) { + + if (filter->adapter_holding) { + gst_adapter_push (filter->adapter_holding, buf); + buf = gst_adapter_take_buffer (filter->adapter_holding, + gst_adapter_available (filter->adapter_holding)); + g_object_unref (filter->adapter_holding); + filter->adapter_holding = NULL; + } - buf_size = GST_BUFFER_SIZE (buf); - gst_metadata_parse_strip_buffer (filter, filter->offset_orig, &buf); + if (filter->need_send_tag) { + gst_metadata_parse_send_tags (filter); + } + + if (filter->offset_orig + GST_BUFFER_SIZE (buf) == filter->duration_orig) + append = TRUE; + + buf_size = GST_BUFFER_SIZE (buf); - if (buf) { /* may be all buffer has been striped */ - gst_buffer_set_caps (buf, GST_PAD_CAPS (filter->srcpad)); - new_buf_size = GST_BUFFER_SIZE (buf); + gst_metadata_parse_strip_push_buffer (filter, filter->offset_orig, + &filter->prepend_buffer, &buf); + + if (buf) { /* may be all buffer has been striped */ + gst_buffer_set_caps (buf, GST_PAD_CAPS (filter->srcpad)); + new_buf_size = GST_BUFFER_SIZE (buf); + + ret = gst_pad_push (filter->srcpad, buf); + buf = NULL; /* this function don't owner it anymore */ + if (ret != GST_FLOW_OK) + goto done; + } else { + ret = GST_FLOW_OK; + } + + if (append && filter->append_buffer) { + gst_buffer_set_caps (filter->append_buffer, + GST_PAD_CAPS (filter->srcpad)); + gst_buffer_ref (filter->append_buffer); + ret = gst_pad_push (filter->srcpad, filter->append_buffer); + if (ret != GST_FLOW_OK) + goto done; + } + + filter->offset_orig += buf_size; + filter->offset += new_buf_size; - ret = gst_pad_push (filter->srcpad, buf); - buf = NULL; /* this function don't owner it anymore */ } else { + /* just store while still not parsed */ + if (!filter->adapter_holding) + filter->adapter_holding = gst_adapter_new (); + gst_adapter_push (filter->adapter_holding, buf); + buf = NULL; ret = GST_FLOW_OK; } done: - filter->offset_orig += buf_size; - filter->offset += new_buf_size; if (buf) { /* there was an error and buffer wasn't pushed */ @@ -1106,13 +1136,19 @@ gst_metadata_parse_pull_range_parse (GstMetadataParse * filter) if (res == 0) { int i; + MetadataChunk *strip = filter->parse_data.strip_chunks.chunk; + MetadataChunk *inject = filter->parse_data.inject_chunks.chunk; + const gsize strip_len = filter->parse_data.strip_chunks.len; + const gsize inject_len = filter->parse_data.inject_chunks.len; filter->duration = duration; + filter->duration_orig = duration; - for (i = 0; i < filter->num_segs; ++i) { - - filter->duration -= (filter->seg_size[i] - filter->seg_inject_size[i]); - + for (i = 0; i < inject_len; ++i) { + filter->duration += inject[i].size; + } + for (i = 0; i < strip_len; ++i) { + filter->duration -= strip[i].size; } } @@ -1124,7 +1160,7 @@ done: } static gboolean -gst_metadata_parse_activate (GstPad * pad) +gst_metadata_parse_sink_activate (GstPad * pad) { GstMetadataParse *filter = NULL; gboolean ret = TRUE; @@ -1178,7 +1214,7 @@ done: static int gst_metadata_parse_get_strip_seg (const gint64 offset, guint32 size, const gint64 seg_offset, const guint32 seg_size, - guint32 * boffset, guint32 * bsize, guint32 * seg_binter) + gint64 * boffset, guint32 * bsize, guint32 * seg_binter) { int ret = -1; @@ -1239,119 +1275,320 @@ done: } /* - * TRUE -> buffer striped (or injeted) + * TRUE -> buffer striped or injeted * FALSE -> buffer unmodified */ static gboolean -gst_metadata_parse_strip_buffer (GstMetadataParse * filter, gint64 offset, - GstBuffer ** buf) +gst_metadata_parse_strip_push_buffer (GstMetadataParse * filter, + gint64 offset_orig, GstBuffer ** prepend, GstBuffer ** buf) { + MetadataChunk *strip = filter->parse_data.strip_chunks.chunk; + MetadataChunk *inject = filter->parse_data.inject_chunks.chunk; + const gsize strip_len = filter->parse_data.strip_chunks.len; + const gsize inject_len = filter->parse_data.inject_chunks.len; - const gint64 *seg_offset = filter->seg_offset_orig; - const guint32 *seg_size = filter->seg_size; - const guint32 *seg_inject_size = filter->seg_inject_size; - const guint8 **seg_inject_data = filter->seg_inject_data; + guint32 size_buf_in = GST_BUFFER_SIZE (*buf); - const size = GST_BUFFER_SIZE (*buf); + gint64 *boffset_strip = NULL; + guint32 *bsize_strip = NULL; + guint32 *seg_binter_strip = NULL; - gint64 boffset[3]; - guint32 bsize[3]; - guint32 seg_binter[3]; + int i, j; + gboolean need_free_strip = FALSE; - int i; - gboolean ret = FALSE; + guint32 striped_bytes = 0; + guint32 injected_bytes = 0; - if (filter->num_segs == 0) - goto done; + guint32 prepend_size = prepend && *prepend ? GST_BUFFER_SIZE (*prepend) : 0; + + if (inject_len) { + + for (i = 0; i < inject_len; ++i) { + 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; + } + } + } + + } - memset (bsize, 0x00, sizeof (bsize)); + /* + * strip segments + */ - for (i = 0; i < filter->num_segs; ++i) { + if (strip_len == 0) + goto inject; + + if (G_UNLIKELY (strip_len > 16)) { + boffset_strip = g_new (gint64, strip_len); + bsize_strip = g_new (guint32, strip_len); + seg_binter_strip = g_new (guint32, strip_len); + need_free_strip = TRUE; + } else { + boffset_strip = g_alloca (sizeof (boffset_strip[0]) * strip_len); + bsize_strip = g_alloca (sizeof (bsize_strip[0]) * strip_len); + seg_binter_strip = g_alloca (sizeof (seg_binter_strip[0]) * strip_len); + } + + memset (bsize_strip, 0x00, sizeof (bsize_strip[0]) * strip_len); + + for (i = 0; i < strip_len; ++i) { int res; - res = gst_metadata_parse_get_strip_seg (offset, size, - seg_offset[i], seg_size[i], &boffset[i], &bsize[i], &seg_binter[i]); + res = gst_metadata_parse_get_strip_seg (offset_orig, size_buf_in, + strip[i].offset_orig, strip[i].size, &boffset_strip[i], &bsize_strip[i], + &seg_binter_strip[i]); /* segment is after size (segments are sorted) */ - if (res > 0) + striped_bytes += bsize_strip[i]; + if (res > 0) { break; - if (res == 0) - ret = TRUE; + } } - /* segments must be sorted by offset to make this copy */ - if (ret) { + if (striped_bytes) { guint8 *data; - guint32 moved = 0; - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { + if (injected_bytes + prepend_size > striped_bytes) { + GstBuffer *new_buf = + gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + injected_bytes + + prepend_size - striped_bytes); + + memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (*buf), + GST_BUFFER_SIZE (*buf)); + + gst_buffer_unref (*buf); + *buf = new_buf; + + } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { GstBuffer *new_buf = gst_buffer_copy (*buf); gst_buffer_unref (*buf); *buf = new_buf; GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); + GST_BUFFER_SIZE (*buf) += injected_bytes + prepend_size - striped_bytes; } data = GST_BUFFER_DATA (*buf); - for (i = 0; i < filter->num_segs; ++i) { - + striped_bytes = 0; + for (i = 0; i < strip_len; ++i) { /* intersect */ - if (bsize[i]) { - /* has data to inject */ - if (seg_inject_size[i]) { - /* has data to inject here */ - if (seg_binter[i] < seg_inject_size[i]) { - const guint32 inject_size = seg_inject_size[i] - seg_binter[i]; - - memcpy (data + boffset[i], seg_inject_data[i] + seg_binter[i], - inject_size); - boffset[i] += inject_size; - bsize[i] -= inject_size; - } - } - if (bsize[i]) { - /* if even inject there is still thing to remove */ - memmove (data + boffset[i] - moved, - data + boffset[i] + bsize[i] - moved, - size - boffset[i] - bsize[i] + moved); - moved += bsize[i]; - } + if (bsize_strip[i]) { + memmove (data + boffset_strip[i] - striped_bytes, + data + boffset_strip[i] + bsize_strip[i] - striped_bytes, + size_buf_in - boffset_strip[i] - bsize_strip[i]); + striped_bytes += bsize_strip[i]; } + } + size_buf_in -= striped_bytes; + + } + +inject: + + /* + * inject segments + */ + + if (inject_len) { + + guint8 *data; + guint32 striped_so_far; + + if (injected_bytes + prepend_size > striped_bytes) { + GstBuffer *new_buf = + gst_buffer_new_and_alloc (GST_BUFFER_SIZE (*buf) + injected_bytes + + prepend_size - striped_bytes); + + memcpy (GST_BUFFER_DATA (new_buf), GST_BUFFER_DATA (*buf), + GST_BUFFER_SIZE (*buf)); + + gst_buffer_unref (*buf); + *buf = new_buf; + } else if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_READONLY)) { + GstBuffer *new_buf = gst_buffer_copy (*buf); + + gst_buffer_unref (*buf); + *buf = new_buf; + GST_BUFFER_FLAG_UNSET (*buf, GST_BUFFER_FLAG_READONLY); + GST_BUFFER_SIZE (*buf) += injected_bytes + prepend_size - striped_bytes; } - GST_BUFFER_SIZE (*buf) -= moved; + data = GST_BUFFER_DATA (*buf); + + injected_bytes = 0; + striped_so_far = 0; + j = 0; + for (i = 0; i < inject_len; ++i) { + int res; + + while (j < strip_len) { + if (strip[j].offset_orig < inject[i].offset_orig) + striped_so_far += bsize_strip[j++]; + else + break; + } + + if (inject[i].offset_orig >= offset_orig) { + if (inject[i].offset_orig < offset_orig + size_buf_in + striped_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 += injected_bytes; + } else { + /* segment is after size (segments are sorted) */ + break; + } + } + } } + done: - return ret; + if (prepend_size) { + if (injected_bytes == 0 && striped_bytes == 0) { + GstBuffer *new_buf = + gst_buffer_new_and_alloc (size_buf_in + prepend_size); + + memcpy (GST_BUFFER_DATA (new_buf) + prepend_size, GST_BUFFER_DATA (*buf), + size_buf_in); + + gst_buffer_unref (*buf); + *buf = new_buf; + } else { + memmove (GST_BUFFER_DATA (*buf) + prepend_size, GST_BUFFER_DATA (*buf), + size_buf_in); + } + memcpy (GST_BUFFER_DATA (*buf), GST_BUFFER_DATA (*prepend), prepend_size); + gst_buffer_unref (*prepend); + *prepend = NULL; + } + + GST_BUFFER_SIZE (*buf) = size_buf_in + prepend_size; + + if (need_free_strip) { + g_free (boffset_strip); + g_free (bsize_strip); + g_free (seg_binter_strip); + } + + return injected_bytes || striped_bytes; } /* * pos - position in stream striped * orig_pos - position in original stream + * return TRUE - position in original buffer + * FALSE - position in inserted chunk */ -static void -gst_metadata_parse_translate_pos (GstMetadataParse * filter, gint64 pos, - gint64 * orig_pos) +static gboolean +gst_metadata_parse_translate_pos_to_orig (GstMetadataParse * filter, gint64 pos, + gint64 * orig_pos, GstBuffer ** buf) { int i; + MetadataChunk *strip = filter->parse_data.strip_chunks.chunk; + MetadataChunk *inject = filter->parse_data.inject_chunks.chunk; + const gsize strip_len = filter->parse_data.strip_chunks.len; + const gsize inject_len = filter->parse_data.inject_chunks.len; + gboolean ret = TRUE; + guint64 new_buf_size = 0; + guint64 injected_before = 0; + + if (G_UNLIKELY (pos == -1)) { + *orig_pos = -1; + return TRUE; + } else if (G_UNLIKELY (pos >= filter->duration)) { + /* this should never happen */ + *orig_pos = filter->duration_orig; + return TRUE; + } + + /* 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 + 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; + ret = FALSE; + } else { + /* in case pos is not inside a injected chunk */ + injected_before += inject[i].size; + } + } else { + break; + } + } + + /* alloc buffer and calcute original pos */ + if (buf && ret == FALSE) { + guint8 *data; + + 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; + } + } + } + + if (ret == FALSE) { + /* if it inside a injected is already done */ + goto done; + } - *orig_pos = 0; - for (i = 0; i < filter->num_segs; ++i) { - if (filter->seg_offset_orig[i] > pos) { + /* calculate for striped */ + + *orig_pos = pos - injected_before; + for (i = 0; i < strip_len; ++i) { + if (strip[i].offset_orig > pos) { break; } - *orig_pos += filter->seg_size[i] - filter->seg_inject_size[i]; + *orig_pos += strip[i].size; + } + +done: + + if (G_UNLIKELY (*orig_pos >= filter->duration_orig)) { + *orig_pos = filter->duration_orig - 1; } - *orig_pos += pos; + + return ret; } @@ -1360,33 +1597,64 @@ gst_metadata_parse_get_range (GstPad * pad, guint64 offset, guint size, GstBuffer ** buf) { GstMetadataParse *filter = NULL; - gboolean ret; - gint64 pos; - const gint64 saved_offset = offset + size; + gboolean ret = TRUE; + const gint64 offset_orig = 0; + guint size_orig; + GstBuffer *prepend = NULL; + gboolean need_append = FALSE; filter = GST_METADATA_PARSE (GST_PAD_PARENT (pad)); + if (offset + size > filter->duration) { + /* this should never happen */ + return FALSE; + } + + size_orig = size; + if (filter->need_send_tag) { gst_metadata_parse_send_tags (filter); } - gst_metadata_parse_translate_pos (filter, offset + size - 1, &pos); - gst_metadata_parse_translate_pos (filter, offset, &offset); + gst_metadata_parse_translate_pos_to_orig (filter, offset, &offset_orig, + &prepend); - ret = gst_pad_pull_range (filter->sinkpad, offset, 1 + pos - offset, buf); + if (size > 1) { + gint64 pos; - if (ret == GST_FLOW_OK && *buf) { - gst_metadata_parse_strip_buffer (filter, offset, buf); - filter->offset_orig = pos; - filter->offset = saved_offset; + pos = offset + size - 1; + gst_metadata_parse_translate_pos_to_orig (filter, pos, &pos, NULL); + size_orig = pos + 1 - offset_orig; } + if (size_orig) { + + ret = gst_pad_pull_range (filter->sinkpad, offset_orig, size_orig, buf); + + if (ret == GST_FLOW_OK && *buf) { + /* FIXEME: put prepend here */ + gst_metadata_parse_strip_push_buffer (filter, offset_orig, &prepend, buf); + filter->offset_orig = offset; + filter->offset = offset; + + if (GST_BUFFER_SIZE (*buf) < size) { + /* need append */ + need_append = TRUE; + } + + } + } else { + *buf = prepend; + } + +done: + return ret; } static gboolean -gst_metadata_parse_element_activate_src_pull (GstPad * pad, gboolean active) +gst_metadata_parse_src_activate_pull (GstPad * pad, gboolean active) { GstMetadataParse *filter = NULL; gboolean ret; @@ -1415,8 +1683,9 @@ gst_metadata_parse_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: gst_metadata_parse_init_members (filter); - filter->adapter = gst_adapter_new (); + filter->adapter_parsing = gst_adapter_new (); filter->taglist = gst_tag_list_new (); + metadataparse_init (&filter->parse_data); break; default: break; diff --git a/ext/metadata/gstmetadataparse.h b/ext/metadata/gstmetadataparse.h index 17d0fcb3..0243261e 100644 --- a/ext/metadata/gstmetadataparse.h +++ b/ext/metadata/gstmetadataparse.h @@ -79,30 +79,26 @@ struct _GstMetadataParse gboolean iptc; gboolean xmp; - gint64 seg_offset_orig[3]; /* offset in chunk in original stream */ - guint32 seg_size[3]; - - gint64 seg_inject_offset[3]; /* offset of chunk in resulting stream */ - guint32 seg_inject_size[3]; - guint8 * seg_inject_data[3]; - - gint8 num_segs; - gboolean need_send_tag; GstTagList *taglist; ParseData parse_data; - GstAdapter *adapter; + GstAdapter *adapter_parsing; + GstAdapter *adapter_holding; guint32 next_offset; guint32 next_size; ImageType img_type; - gint64 offset_orig; - gint64 duration; - gint64 offset; + gint64 offset_orig; /* offset in original stream */ + gint64 duration_orig; /* durarion of stream */ + gint64 offset; /* offset in current stream */ + gint64 duration; /* durarion of modified stream */ MetadataState state; + GstBuffer * prepend_buffer; + GstBuffer * append_buffer; + gboolean need_more_data; @@ -116,7 +112,5 @@ struct _GstMetadataParseClass extern GType gst_metadata_parse_get_type (void); -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 410ae847..cb22c795 100644 --- a/ext/metadata/metadataparse.c +++ b/ext/metadata/metadataparse.c @@ -63,10 +63,12 @@ metadataparse_init (ParseData * parse_data) parse_data->state = STATE_NULL; parse_data->img_type = IMG_NONE; parse_data->option = PARSE_OPT_ALL; - parse_data->offset = 0; - memset (&parse_data->exif, 0x00, sizeof (MetadataChunk)); - memset (&parse_data->iptc, 0x00, sizeof (MetadataChunk)); - memset (&parse_data->xmp, 0x00, sizeof (MetadataChunk)); + parse_data->offset_orig = 0; + parse_data->exif_adapter = NULL; + parse_data->iptc_adapter = NULL; + parse_data->xmp_adapter = NULL; + metadata_chunk_array_init (&parse_data->strip_chunks, 4); + metadata_chunk_array_init (&parse_data->inject_chunks, 1); } /* @@ -100,12 +102,14 @@ metadataparse_parse (ParseData * parse_data, const guint8 * buf, case IMG_JPEG: ret = metadataparse_jpeg_parse (&parse_data->format_data.jpeg, - (guint8 *) buf, &bufsize, parse_data->offset, &next_start, next_size); + (guint8 *) buf, &bufsize, parse_data->offset_orig, &next_start, + next_size); break; case IMG_PNG: ret = metadataparse_png_parse (&parse_data->format_data.png, - (guint8 *) buf, &bufsize, parse_data->offset, &next_start, next_size); + (guint8 *) buf, &bufsize, parse_data->offset_orig, &next_start, + next_size); break; default: /* unexpected */ @@ -115,7 +119,7 @@ metadataparse_parse (ParseData * parse_data, const guint8 * buf, } *next_offset = next_start - buf; - parse_data->offset += *next_offset; + parse_data->offset_orig += *next_offset; done: @@ -139,34 +143,24 @@ metadataparse_dispose (ParseData * parse_data) break; } - if (parse_data->xmp.adapter) { - gst_object_unref (parse_data->xmp.adapter); - } - - if (parse_data->iptc.adapter) { - gst_object_unref (parse_data->iptc.adapter); - } + metadata_chunk_array_free (&parse_data->strip_chunks); + metadata_chunk_array_free (&parse_data->inject_chunks); - if (parse_data->exif.adapter) { - gst_object_unref (parse_data->exif.adapter); + if (parse_data->xmp_adapter) { + gst_object_unref (parse_data->xmp_adapter); + parse_data->xmp_adapter = NULL; } - if (parse_data->xmp.buffer) { - free (parse_data->xmp.buffer); + if (parse_data->iptc_adapter) { + gst_object_unref (parse_data->iptc_adapter); + parse_data->iptc_adapter = NULL; } - if (parse_data->iptc.buffer) { - free (parse_data->iptc.buffer); + if (parse_data->exif_adapter) { + gst_object_unref (parse_data->exif_adapter); + parse_data->exif_adapter = NULL; } - if (parse_data->exif.buffer) { - free (parse_data->exif.buffer); - } - - memset (&parse_data->xmp, 0x00, sizeof (MetadataChunk)); - memset (&parse_data->iptc, 0x00, sizeof (MetadataChunk)); - memset (&parse_data->exif, 0x00, sizeof (MetadataChunk)); - } /* @@ -180,9 +174,9 @@ metadataparse_parse_none (ParseData * parse_data, const guint8 * buf, { int ret = -1; - MetadataChunk *exif = NULL; - MetadataChunk *iptc = NULL; - MetadataChunk *xmp = NULL; + GstAdapter **exif = NULL; + GstAdapter **iptc = NULL; + GstAdapter **xmp = NULL; *next_start = (guint8 *) buf; @@ -195,14 +189,15 @@ metadataparse_parse_none (ParseData * parse_data, const guint8 * buf, } if (parse_data->option & PARSE_OPT_EXIF) - exif = &parse_data->exif; + exif = &parse_data->exif_adapter; if (parse_data->option & PARSE_OPT_IPTC) - iptc = &parse_data->iptc; + iptc = &parse_data->iptc_adapter; if (parse_data->option & PARSE_OPT_XMP) - xmp = &parse_data->xmp; + xmp = &parse_data->xmp_adapter; if (buf[0] == 0xFF && buf[1] == 0xD8 && buf[2] == 0xFF) { - metadataparse_jpeg_init (&parse_data->format_data.jpeg, exif, iptc, xmp); + metadataparse_jpeg_init (&parse_data->format_data.jpeg, exif, iptc, xmp, + &parse_data->strip_chunks, &parse_data->inject_chunks); ret = 0; parse_data->img_type = IMG_JPEG; goto done; @@ -216,7 +211,8 @@ metadataparse_parse_none (ParseData * parse_data, const guint8 * buf, 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, exif, iptc, xmp); + metadataparse_png_init (&parse_data->format_data.png, exif, iptc, xmp, + &parse_data->strip_chunks, &parse_data->inject_chunks); ret = 0; parse_data->img_type = IMG_PNG; goto done; diff --git a/ext/metadata/metadataparse.h b/ext/metadata/metadataparse.h index 98c1714d..c0b82aa1 100644 --- a/ext/metadata/metadataparse.h +++ b/ext/metadata/metadataparse.h @@ -45,7 +45,7 @@ #define __METADATAPARSE_H__ #include <gst/base/gstadapter.h> -#include "metadataparsetypes.h" +#include "metadatatypes.h" #include "metadataparsejpeg.h" #include "metadataparsepng.h" @@ -79,15 +79,19 @@ typedef struct _tag_ParseData ParseState state; ImageType img_type; ParseOption option; - guint32 offset; /* offset since begining of stream */ + guint32 offset_orig; /* offset since begining of stream */ union { JpegData jpeg; PngData png; } format_data; - MetadataChunk exif; - MetadataChunk iptc; - MetadataChunk xmp; + GstAdapter * exif_adapter; + GstAdapter * iptc_adapter; + GstAdapter * xmp_adapter; + + MetadataChunkArray strip_chunks; + MetadataChunkArray inject_chunks; + } ParseData; #define PARSE_DATA_IMG_TYPE(p) (p).img_type diff --git a/ext/metadata/metadataparsejpeg.c b/ext/metadata/metadataparsejpeg.c index daf7ad27..4b81d1ec 100644 --- a/ext/metadata/metadataparsejpeg.c +++ b/ext/metadata/metadataparsejpeg.c @@ -71,16 +71,20 @@ metadataparse_jpeg_jump (JpegData * jpeg_data, guint8 ** buf, #define READ(buf, size) ( (size)--, *((buf)++) ) void -metadataparse_jpeg_init (JpegData * jpeg_data, MetadataChunk * exif, - MetadataChunk * iptc, MetadataChunk * xmp) +metadataparse_jpeg_init (JpegData * jpeg_data, GstAdapter ** exif_adpt, + GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks) { jpeg_data->state = JPEG_NULL; - jpeg_data->exif = exif; - jpeg_data->iptc = iptc; - jpeg_data->xmp = xmp; + jpeg_data->exif_adapter = exif_adpt; + jpeg_data->iptc_adapter = iptc_adpt; + jpeg_data->xmp_adapter = xmp_adpt; jpeg_data->read = 0; jpeg_data->jfif_found = FALSE; + jpeg_data->strip_chunks = strip_chunks; + jpeg_data->inject_chunks = inject_chunks; + metadataparse_xmp_init (); } @@ -89,9 +93,9 @@ metadataparse_jpeg_dispose (JpegData * jpeg_data) { metadataparse_xmp_dispose (); - jpeg_data->exif = NULL; - jpeg_data->iptc = NULL; - jpeg_data->xmp = NULL; + jpeg_data->exif_adapter = NULL; + jpeg_data->iptc_adapter = NULL; + jpeg_data->xmp_adapter = NULL; } int @@ -242,28 +246,42 @@ metadataparse_jpeg_reading (JpegData * jpeg_data, guint8 ** buf, goto done; } - if (jpeg_data->exif) { - if (0 == memcmp (ExifHeader, *buf, 6)) { - jpeg_data->exif->offset = (*buf - step_buf) + offset - 4; /* maker + size */ - jpeg_data->exif->size = chunk_size + 2; /* chunk size plus app marker */ - jpeg_data->read = chunk_size - 2; - ret = 0; + if (0 == memcmp (ExifHeader, *buf, 6)) { + MetadataChunk chunk; - if (!jpeg_data->jfif_found) { - static const guint8 chunk[] = { 0xff, 0xe0, 0x00, 0x10, - 0x4a, 0x46, 0x49, 0x46, 0x00, - 0x01, 0x02, - 0x00, 0x00, 0x01, 0x00, 0x01, - 0x00, 0x00 - }; - - /* only inject if no JFIF has been found */ - jpeg_data->exif->size_inject = 18; - jpeg_data->exif->buffer = malloc (18); - memcpy (jpeg_data->exif->buffer, chunk, 18); - } + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ + chunk.size = chunk_size + 2; /* chunk size plus app marker */ + + metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, &chunk); + + if (!jpeg_data->jfif_found) { + /* only inject if no JFIF has been found */ + + static const guint8 segment[] = { 0xff, 0xe0, 0x00, 0x10, + 0x4a, 0x46, 0x49, 0x46, 0x00, + 0x01, 0x02, + 0x00, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00 + }; + + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = 2; + chunk.size = 18; + chunk.data = g_new (guint8, 18); + memcpy (chunk.data, segment, 18); + + metadata_chunk_array_append_sorted (jpeg_data->inject_chunks, + &chunk); + + } + + if (jpeg_data->exif_adapter) { + jpeg_data->read = chunk_size - 2; jpeg_data->state = JPEG_EXIF; + ret = 0; goto done; } } @@ -274,15 +292,23 @@ metadataparse_jpeg_reading (JpegData * jpeg_data, guint8 ** buf, goto done; } - if (jpeg_data->xmp) { - if (0 == memcmp (XmpHeader, *buf, 29)) { - jpeg_data->xmp->offset = (*buf - step_buf) + offset - 4; /* maker + size */ - jpeg_data->xmp->size = chunk_size + 2; /* chunk size plus app marker */ + if (0 == memcmp (XmpHeader, *buf, 29)) { + MetadataChunk chunk; + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ + chunk.size = chunk_size + 2; /* chunk size plus app marker */ + + metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, + &chunk); + + /* if adapter has been provided, prepare to hold chunk */ + if (jpeg_data->xmp_adapter) { *buf += 29; *bufsize -= 29; jpeg_data->read = chunk_size - 2 - 29; - ret = 0; jpeg_data->state = JPEG_XMP; + ret = 0; goto done; } } @@ -297,13 +323,21 @@ metadataparse_jpeg_reading (JpegData * jpeg_data, guint8 ** buf, goto done; } - if (jpeg_data->iptc) { - if (0 == memcmp (IptcHeader, *buf, 14)) { - jpeg_data->iptc->offset = (*buf - step_buf) + offset - 4; /* maker + size */ - jpeg_data->iptc->size = chunk_size + 2; /* chunk size plus app marker */ + + if (0 == memcmp (IptcHeader, *buf, 14)) { + MetadataChunk chunk; + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 4; /* maker + size */ + chunk.size = chunk_size + 2; /* chunk size plus app marker */ + + metadata_chunk_array_append_sorted (jpeg_data->strip_chunks, &chunk); + + /* if adapter has been provided, prepare to hold chunk */ + if (jpeg_data->iptc_adapter) { jpeg_data->read = chunk_size - 2; - ret = 0; jpeg_data->state = JPEG_IPTC; + ret = 0; goto done; } } @@ -335,13 +369,13 @@ metadataparse_jpeg_exif (JpegData * jpeg_data, guint8 ** buf, int ret; ret = metadataparse_util_hold_chunk (&jpeg_data->read, buf, - bufsize, next_start, next_size, &jpeg_data->exif->adapter); + bufsize, next_start, next_size, jpeg_data->exif_adapter); if (ret == 0) { jpeg_data->state = JPEG_READING; /* if there is a second Exif chunk in the file it will be jumped */ - jpeg_data->exif = NULL; + jpeg_data->exif_adapter = NULL; } return ret; @@ -355,7 +389,7 @@ metadataparse_jpeg_iptc (JpegData * jpeg_data, guint8 ** buf, int ret; ret = metadataparse_util_hold_chunk (&jpeg_data->read, buf, - bufsize, next_start, next_size, &jpeg_data->iptc->adapter); + bufsize, next_start, next_size, jpeg_data->iptc_adapter); if (ret == 0) { @@ -367,8 +401,8 @@ metadataparse_jpeg_iptc (JpegData * jpeg_data, guint8 ** buf, jpeg_data->state = JPEG_READING; - size = gst_adapter_available (jpeg_data->iptc->adapter); - buf = gst_adapter_peek (jpeg_data->iptc->adapter, size); + size = gst_adapter_available (*jpeg_data->iptc_adapter); + buf = gst_adapter_peek (*jpeg_data->iptc_adapter, size); res = iptc_jpeg_ps3_find_iptc (buf, size, &iptc_len); @@ -377,21 +411,21 @@ metadataparse_jpeg_iptc (JpegData * jpeg_data, guint8 ** buf, ret = -1; } else if (res == 0) { /* no iptc data found */ - gst_adapter_clear (jpeg_data->iptc->adapter); + gst_adapter_clear (*jpeg_data->iptc_adapter); } else { - gst_adapter_flush (jpeg_data->iptc->adapter, res); - size = gst_adapter_available (jpeg_data->iptc->adapter); + gst_adapter_flush (*jpeg_data->iptc_adapter, res); + size = gst_adapter_available (*jpeg_data->iptc_adapter); if (size > iptc_len) { GstBuffer *buf; - buf = gst_adapter_take_buffer (jpeg_data->iptc->adapter, iptc_len); - gst_adapter_clear (jpeg_data->iptc->adapter); - gst_adapter_push (jpeg_data->iptc->adapter, buf); + buf = gst_adapter_take_buffer (*jpeg_data->iptc_adapter, iptc_len); + gst_adapter_clear (*jpeg_data->iptc_adapter); + gst_adapter_push (*jpeg_data->iptc_adapter, buf); } } /* if there is a second Iptc chunk in the file it will be jumped */ - jpeg_data->iptc = NULL; + jpeg_data->iptc_adapter = NULL; } @@ -406,12 +440,12 @@ metadataparse_jpeg_xmp (JpegData * jpeg_data, guint8 ** buf, int ret; ret = metadataparse_util_hold_chunk (&jpeg_data->read, buf, - bufsize, next_start, next_size, &jpeg_data->xmp->adapter); + bufsize, next_start, next_size, jpeg_data->xmp_adapter); if (ret == 0) { jpeg_data->state = JPEG_READING; /* if there is a second XMP chunk in the file it will be jumped */ - jpeg_data->xmp = NULL; + jpeg_data->xmp_adapter = NULL; } return ret; } diff --git a/ext/metadata/metadataparsejpeg.h b/ext/metadata/metadataparsejpeg.h index cc7cd6e2..4d1d57c6 100644 --- a/ext/metadata/metadataparsejpeg.h +++ b/ext/metadata/metadataparsejpeg.h @@ -44,7 +44,9 @@ #ifndef __METADATAPARSE_JPEG_H__ #define __METADATAPARSE_JPEG_H__ -#include "metadataparsetypes.h" +#include <gst/base/gstadapter.h> + +#include "metadatatypes.h" G_BEGIN_DECLS @@ -63,17 +65,23 @@ typedef enum _tag_JpegState typedef struct _tag_JpegData { JpegState state; - MetadataChunk *exif; - MetadataChunk *iptc; - MetadataChunk *xmp; + + GstAdapter ** exif_adapter; + GstAdapter ** iptc_adapter; + GstAdapter ** xmp_adapter; + + MetadataChunkArray * strip_chunks; + MetadataChunkArray * inject_chunks; + guint32 read; gboolean jfif_found; } JpegData; extern void -metadataparse_jpeg_init (JpegData * jpeg_data, MetadataChunk * adpt_exif, - MetadataChunk * adpt_iptc, MetadataChunk * adpt_xmp); +metadataparse_jpeg_init (JpegData * jpeg_data, GstAdapter ** exif_adpt, + GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks); extern void metadataparse_jpeg_dispose (JpegData * jpeg_data); diff --git a/ext/metadata/metadataparsepng.c b/ext/metadata/metadataparsepng.c index 829ad65e..e007e9ed 100644 --- a/ext/metadata/metadataparsepng.c +++ b/ext/metadata/metadataparsepng.c @@ -61,13 +61,17 @@ metadataparse_png_jump (PngData * png_data, guint8 ** buf, #define READ(buf, size) ( (size)--, *((buf)++) ) void -metadataparse_png_init (PngData * png_data, MetadataChunk * exif, - MetadataChunk * iptc, MetadataChunk * xmp) +metadataparse_png_init (PngData * png_data, GstAdapter ** exif_adpt, + GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks) { png_data->state = PNG_NULL; - png_data->xmp = xmp; + png_data->xmp_adapter = xmp_adpt; png_data->read = 0; + png_data->strip_chunks = strip_chunks; + png_data->inject_chunks = inject_chunks; + metadataparse_xmp_init (); } @@ -76,7 +80,7 @@ metadataparse_png_dispose (PngData * png_data) { metadataparse_xmp_dispose (); - png_data->xmp = NULL; + png_data->xmp_adapter = NULL; } int @@ -197,10 +201,17 @@ metadataparse_png_reading (PngData * png_data, guint8 ** buf, goto done; } - if (png_data->xmp) { - if (0 == memcmp (XmpHeader, *buf, 18)) { - png_data->xmp->offset = (*buf - step_buf) + offset - 8; /* maker + size */ - png_data->xmp->size = chunk_size + 12; /* chunk size plus app marker plus crc */ + if (0 == memcmp (XmpHeader, *buf, 18)) { + MetadataChunk chunk; + + memset (&chunk, 0x00, sizeof (MetadataChunk)); + chunk.offset_orig = (*buf - step_buf) + offset - 8; /* maker + size */ + chunk.size = chunk_size + 12; /* chunk size plus app marker plus crc */ + + metadata_chunk_array_append_sorted (png_data->strip_chunks, &chunk); + + /* if adapter has been provided, prepare to hold chunk */ + if (png_data->xmp_adapter) { *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 */ @@ -240,13 +251,13 @@ metadataparse_png_xmp (PngData * png_data, guint8 ** buf, int ret; ret = metadataparse_util_hold_chunk (&png_data->read, buf, - bufsize, next_start, next_size, &png_data->xmp->adapter); + bufsize, next_start, next_size, png_data->xmp_adapter); if (ret == 0) { /* jump four CRC bytes at the end of chunk */ png_data->read = 4; png_data->state = PNG_JUMPING; /* if there is a second XMP chunk in the file it will be jumped */ - png_data->xmp = NULL; + png_data->xmp_adapter = NULL; } return ret; diff --git a/ext/metadata/metadataparsepng.h b/ext/metadata/metadataparsepng.h index c059450f..568e8494 100644 --- a/ext/metadata/metadataparsepng.h +++ b/ext/metadata/metadataparsepng.h @@ -44,7 +44,9 @@ #ifndef __METADATAPARSE_PNG_H__ #define __METADATAPARSE_PNG_H__ -#include "metadataparsetypes.h" +#include <gst/base/gstadapter.h> + +#include "metadatatypes.h" G_BEGIN_DECLS @@ -61,14 +63,20 @@ typedef enum _tag_PngState typedef struct _tag_PngData { PngState state; - MetadataChunk *xmp; + + GstAdapter ** xmp_adapter; + + MetadataChunkArray * strip_chunks; + MetadataChunkArray * inject_chunks; + guint32 read; } PngData; extern void -metadataparse_png_init (PngData * png_data, MetadataChunk *exif, - MetadataChunk * iptc, MetadataChunk *xmp); +metadataparse_png_init (PngData * png_data, GstAdapter ** exif_adpt, + GstAdapter ** iptc_adpt, GstAdapter ** xmp_adpt, + MetadataChunkArray * strip_chunks, MetadataChunkArray * inject_chunks); extern void metadataparse_png_dispose (PngData * png_data); diff --git a/ext/metadata/metadatatypes.c b/ext/metadata/metadatatypes.c new file mode 100644 index 00000000..a3aee807 --- /dev/null +++ b/ext/metadata/metadatatypes.c @@ -0,0 +1,115 @@ +/* + * GStreamer + * Copyright 2007 Edgard Lima <edgard.lima@indt.org.br> + * + * 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 "metadatatypes.h" + +#include <string.h> + +void +metadata_chunk_array_init (MetadataChunkArray * array, gsize alloc_size) +{ + array->len = 0; + array->chunk = g_new0 (MetadataChunk, alloc_size); + array->allocated_len = alloc_size; +} + +void +metadata_chunk_array_free (MetadataChunkArray * array) +{ + metadata_chunk_array_clear (array); + array->allocated_len = 0; + if (array->chunk) { + g_free (array->chunk); + array->chunk = NULL; + } +} + +void +metadata_chunk_array_clear (MetadataChunkArray * array) +{ + while (array->len) { + array->len--; + if (array->chunk[array->len].data) { + g_free (array->chunk[array->len].data); + } + } +} + +void +metadata_chunk_array_append (MetadataChunkArray * array, MetadataChunk * chunk) +{ + if (array->len == array->allocated_len) { + array->allocated_len += 2; + array->chunk = g_realloc (array->chunk, array->allocated_len); + } + memcpy (&array->chunk[array->len], chunk, sizeof (MetadataChunk)); + ++array->len; +} + +void +metadata_chunk_array_append_sorted (MetadataChunkArray * array, + MetadataChunk * chunk) +{ + gint32 i, pos; + + if (array->len == array->allocated_len) { + array->allocated_len += 2; + array->chunk = g_realloc (array->chunk, array->allocated_len); + } + pos = array->len; + for (i = array->len - 1; i >= 0; --i) { + if (chunk->offset_orig > array->chunk[i].offset_orig) { + break; + } + } + pos = i + 1; + if (pos < array->len) { + memmove (&array->chunk[pos + 1], &array->chunk[pos], + sizeof (MetadataChunk) * (array->len - pos)); + } + memcpy (&array->chunk[pos], chunk, sizeof (MetadataChunk)); + ++array->len; + + return; + +} diff --git a/ext/metadata/metadatatypes.h b/ext/metadata/metadatatypes.h new file mode 100644 index 00000000..2c4bc169 --- /dev/null +++ b/ext/metadata/metadatatypes.h @@ -0,0 +1,85 @@ +/* + * GStreamer + * Copyright 2007 Edgard Lima <edgard.lima@indt.org.br> + * + * 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 __METADATATYPES_H__ +#define __METADATATYPES_H__ + +#include <glib.h> + +G_BEGIN_DECLS + +typedef struct _tag_MetadataChunk +{ + gint64 offset_orig; /* from the beginning of original file */ + gint64 offset; /*here just for convinience (filled by element) offset in new stream */ + guint32 size; /* chunk or buffer size*/ + guint8 * data; +} MetadataChunk; + +typedef struct _tag_MetadataChunkArray +{ + MetadataChunk * chunk; + gsize len; + gsize allocated_len; +} MetadataChunkArray; + +extern void +metadata_chunk_array_init(MetadataChunkArray * array, gsize alloc_size); + +extern void +metadata_chunk_array_free(MetadataChunkArray * array); + +extern void +metadata_chunk_array_clear(MetadataChunkArray * array); + +extern void +metadata_chunk_array_append(MetadataChunkArray * array, MetadataChunk * chunk); + +/* sorted by offset (chunk supposed to be already sorted + * returns false if chunks are inserted in same offset + */ +extern void +metadata_chunk_array_append_sorted(MetadataChunkArray * array, MetadataChunk * chunk); + +G_END_DECLS +#endif /* __METADATATYPES_H__ */ |