From e16f2f891a4e83f9a7a13b5131ee576d18f3e9df Mon Sep 17 00:00:00 2001 From: Michael Smith Date: Thu, 28 Jul 2011 23:31:03 +0100 Subject: [PATCH] tagmux: add support for end tags Originally "id3tag: Add new id3 tagging plugin, supports v1, v2.3, and v2.4." from gst-plugins-bad. This is an artificial bridge commit. --- gst-libs/gst/tag/gsttagmux.c | 304 ++++++++++++++++++++++------------- gst-libs/gst/tag/gsttagmux.h | 56 ++++--- 2 files changed, 228 insertions(+), 132 deletions(-) diff --git a/gst-libs/gst/tag/gsttagmux.c b/gst-libs/gst/tag/gsttagmux.c index 7e8cf6e250..bfa4e1bcc7 100644 --- a/gst-libs/gst/tag/gsttagmux.c +++ b/gst-libs/gst/tag/gsttagmux.c @@ -1,8 +1,10 @@ -/* GStreamer taglib-based muxer base class +/* GStreamer tag muxer base class + * * Copyright (C) 2006 Christophe Fergeau * Copyright (C) 2006 Tim-Philipp Müller * Copyright (C) 2006 Sebastian Dröge - + * Copyright (C) 2009 Pioneers of the Inevitable + * * 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 @@ -27,19 +29,22 @@ #include #include -#include "gsttaglibmux.h" +#include "gsttagmux.h" -GST_DEBUG_CATEGORY_STATIC (gst_tag_lib_mux_debug); -#define GST_CAT_DEFAULT gst_tag_lib_mux_debug +GST_DEBUG_CATEGORY_STATIC (gst_tag_mux_debug); +#define GST_CAT_DEFAULT gst_tag_mux_debug -static GstStaticPadTemplate gst_tag_lib_mux_sink_template = +/* Subclass provides a src template and pad. We accept anything as input here, + however. */ + +static GstStaticPadTemplate gst_tag_mux_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY")); static void -gst_tag_lib_mux_iface_init (GType taglib_type) +gst_tag_mux_iface_init (GType tag_type) { static const GInterfaceInfo tag_setter_info = { NULL, @@ -47,23 +52,22 @@ gst_tag_lib_mux_iface_init (GType taglib_type) NULL }; - g_type_add_interface_static (taglib_type, GST_TYPE_TAG_SETTER, - &tag_setter_info); + g_type_add_interface_static (tag_type, GST_TYPE_TAG_SETTER, &tag_setter_info); } -GST_BOILERPLATE_FULL (GstTagLibMux, gst_tag_lib_mux, - GstElement, GST_TYPE_ELEMENT, gst_tag_lib_mux_iface_init); +GST_BOILERPLATE_FULL (GstTagMux, gst_tag_mux, + GstElement, GST_TYPE_ELEMENT, gst_tag_mux_iface_init); static GstStateChangeReturn -gst_tag_lib_mux_change_state (GstElement * element, GstStateChange transition); -static GstFlowReturn gst_tag_lib_mux_chain (GstPad * pad, GstBuffer * buffer); -static gboolean gst_tag_lib_mux_sink_event (GstPad * pad, GstEvent * event); +gst_tag_mux_change_state (GstElement * element, GstStateChange transition); +static GstFlowReturn gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_tag_mux_sink_event (GstPad * pad, GstEvent * event); static void -gst_tag_lib_mux_finalize (GObject * obj) +gst_tag_mux_finalize (GObject * obj) { - GstTagLibMux *mux = GST_TAG_LIB_MUX (obj); + GstTagMux *mux = GST_TAG_MUX (obj); if (mux->newsegment_ev) { gst_event_unref (mux->newsegment_ev); @@ -75,23 +79,28 @@ gst_tag_lib_mux_finalize (GObject * obj) mux->event_tags = NULL; } + if (mux->final_tags) { + gst_tag_list_free (mux->final_tags); + mux->final_tags = NULL; + } + G_OBJECT_CLASS (parent_class)->finalize (obj); } static void -gst_tag_lib_mux_base_init (gpointer g_class) +gst_tag_mux_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_tag_lib_mux_sink_template)); + gst_static_pad_template_get (&gst_tag_mux_sink_template)); - GST_DEBUG_CATEGORY_INIT (gst_tag_lib_mux_debug, "taglibmux", 0, - "taglib-based muxer"); + GST_DEBUG_CATEGORY_INIT (gst_tag_mux_debug, "tagmux", 0, + "tag muxer base class"); } static void -gst_tag_lib_mux_class_init (GstTagLibMuxClass * klass) +gst_tag_mux_class_init (GstTagMuxClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -99,24 +108,23 @@ gst_tag_lib_mux_class_init (GstTagLibMuxClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - gobject_class->finalize = gst_tag_lib_mux_finalize; - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_tag_lib_mux_change_state); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_tag_mux_finalize); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_tag_mux_change_state); } static void -gst_tag_lib_mux_init (GstTagLibMux * mux, GstTagLibMuxClass * mux_class) +gst_tag_mux_init (GstTagMux * mux, GstTagMuxClass * mux_class) { GstElementClass *element_klass = GST_ELEMENT_CLASS (mux_class); GstPadTemplate *tmpl; /* pad through which data comes in to the element */ mux->sinkpad = - gst_pad_new_from_static_template (&gst_tag_lib_mux_sink_template, "sink"); + gst_pad_new_from_static_template (&gst_tag_mux_sink_template, "sink"); gst_pad_set_chain_function (mux->sinkpad, - GST_DEBUG_FUNCPTR (gst_tag_lib_mux_chain)); + GST_DEBUG_FUNCPTR (gst_tag_mux_chain)); gst_pad_set_event_function (mux->sinkpad, - GST_DEBUG_FUNCPTR (gst_tag_lib_mux_sink_event)); + GST_DEBUG_FUNCPTR (gst_tag_mux_sink_event)); gst_element_add_pad (GST_ELEMENT (mux), mux->sinkpad); /* pad through which data goes out of the element */ @@ -128,21 +136,19 @@ gst_tag_lib_mux_init (GstTagLibMux * mux, GstTagLibMuxClass * mux_class) gst_element_add_pad (GST_ELEMENT (mux), mux->srcpad); } - mux->render_tag = TRUE; + mux->render_start_tag = TRUE; + mux->render_end_tag = TRUE; } -static GstBuffer * -gst_tag_lib_mux_render_tag (GstTagLibMux * mux) +static GstTagList * +gst_tag_mux_get_tags (GstTagMux * mux) { - GstTagLibMuxClass *klass; - GstTagMergeMode merge_mode; - GstTagSetter *tagsetter; - GstBuffer *buffer; + GstTagSetter *tagsetter = GST_TAG_SETTER (mux); const GstTagList *tagsetter_tags; - GstTagList *taglist; - GstEvent *event; + GstTagMergeMode merge_mode; - tagsetter = GST_TAG_SETTER (mux); + if (mux->final_tags) + return mux->final_tags; tagsetter_tags = gst_tag_setter_get_tag_list (tagsetter); merge_mode = gst_tag_setter_get_tag_merge_mode (tagsetter); @@ -151,22 +157,42 @@ gst_tag_lib_mux_render_tag (GstTagLibMux * mux) GST_LOG_OBJECT (mux, "event tags: %" GST_PTR_FORMAT, mux->event_tags); GST_LOG_OBJECT (mux, "set tags: %" GST_PTR_FORMAT, tagsetter_tags); - taglist = gst_tag_list_merge (tagsetter_tags, mux->event_tags, merge_mode); + mux->final_tags = + gst_tag_list_merge (tagsetter_tags, mux->event_tags, merge_mode); - GST_LOG_OBJECT (mux, "final tags: %" GST_PTR_FORMAT, taglist); + GST_LOG_OBJECT (mux, "final tags: %" GST_PTR_FORMAT, mux->final_tags); - klass = GST_TAG_LIB_MUX_CLASS (G_OBJECT_GET_CLASS (mux)); + return mux->final_tags; +} - if (klass->render_tag == NULL) +static GstFlowReturn +gst_tag_mux_render_start_tag (GstTagMux * mux) +{ + GstTagMuxClass *klass; + GstBuffer *buffer; + GstTagList *taglist; + GstEvent *event; + GstFlowReturn ret; + + taglist = gst_tag_mux_get_tags (mux); + + klass = GST_TAG_MUX_CLASS (G_OBJECT_GET_CLASS (mux)); + + if (klass->render_start_tag == NULL) goto no_vfunc; - buffer = klass->render_tag (mux, taglist); + buffer = klass->render_start_tag (mux, taglist); - if (buffer == NULL) - goto render_error; + /* Null buffer is ok, just means we're not outputting anything */ + if (buffer == NULL) { + GST_INFO_OBJECT (mux, "No start tag generated"); + mux->start_tag_size = 0; + return GST_FLOW_OK; + } - mux->tag_size = GST_BUFFER_SIZE (buffer); - GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes", mux->tag_size); + mux->start_tag_size = GST_BUFFER_SIZE (buffer); + GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes", + mux->start_tag_size); /* Send newsegment event from byte position 0, so the tag really gets * written to the start of the file, independent of the upstream segment */ @@ -174,31 +200,74 @@ gst_tag_lib_mux_render_tag (GstTagLibMux * mux) gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0)); /* Send an event about the new tags to downstream elements */ - /* gst_event_new_tag takes ownership of the list, so no need to unref it */ - event = gst_event_new_tag (taglist); + /* gst_event_new_tag takes ownership of the list, so use a copy */ + event = gst_event_new_tag (gst_tag_list_copy (taglist)); gst_pad_push_event (mux->srcpad, event); GST_BUFFER_OFFSET (buffer) = 0; + ret = gst_pad_push (mux->srcpad, buffer); - return buffer; + mux->current_offset = mux->start_tag_size; + mux->max_offset = MAX (mux->max_offset, mux->current_offset); + + return ret; no_vfunc: { - GST_ERROR_OBJECT (mux, "Subclass does not implement render_tag vfunc!"); - gst_tag_list_free (taglist); - return NULL; + GST_ERROR_OBJECT (mux, "Subclass does not implement " + "render_start_tag vfunc!"); + return GST_FLOW_ERROR; + } +} + +static GstFlowReturn +gst_tag_mux_render_end_tag (GstTagMux * mux) +{ + GstTagMuxClass *klass; + GstBuffer *buffer; + GstTagList *taglist; + GstFlowReturn ret; + + taglist = gst_tag_mux_get_tags (mux); + + klass = GST_TAG_MUX_CLASS (G_OBJECT_GET_CLASS (mux)); + + if (klass->render_end_tag == NULL) + goto no_vfunc; + + buffer = klass->render_end_tag (mux, taglist); + + if (buffer == NULL) { + GST_INFO_OBJECT (mux, "No end tag generated"); + mux->end_tag_size = 0; + return GST_FLOW_OK; } -render_error: + mux->end_tag_size = GST_BUFFER_SIZE (buffer); + GST_LOG_OBJECT (mux, "tag size = %" G_GSIZE_FORMAT " bytes", + mux->end_tag_size); + + /* Send newsegment event from the end of the file, so it gets written there, + independent of whatever new segment events upstream has sent us */ + gst_pad_push_event (mux->srcpad, + gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, mux->max_offset, + -1, 0)); + + GST_BUFFER_OFFSET (buffer) = mux->max_offset; + ret = gst_pad_push (mux->srcpad, buffer); + + return ret; + +no_vfunc: { - GST_ERROR_OBJECT (mux, "Failed to render tag"); - gst_tag_list_free (taglist); - return NULL; + GST_ERROR_OBJECT (mux, "Subclass does not implement " + "render_end_tag vfunc!"); + return GST_FLOW_ERROR; } } static GstEvent * -gst_tag_lib_mux_adjust_event_offsets (GstTagLibMux * mux, +gst_tag_mux_adjust_event_offsets (GstTagMux * mux, const GstEvent * newsegment_event) { GstFormat format; @@ -210,33 +279,30 @@ gst_tag_lib_mux_adjust_event_offsets (GstTagLibMux * mux, g_assert (format == GST_FORMAT_BYTES); if (start != -1) - start += mux->tag_size; + start += mux->start_tag_size; if (stop != -1) - stop += mux->tag_size; + stop += mux->start_tag_size; if (cur != -1) - cur += mux->tag_size; + cur += mux->start_tag_size; GST_DEBUG_OBJECT (mux, "adjusting newsegment event offsets to start=%" G_GINT64_FORMAT ", stop=%" G_GINT64_FORMAT ", cur=%" G_GINT64_FORMAT - " (delta = +%" G_GSIZE_FORMAT ")", start, stop, cur, mux->tag_size); + " (delta = +%" G_GSIZE_FORMAT ")", start, stop, cur, mux->start_tag_size); return gst_event_new_new_segment (TRUE, 1.0, format, start, stop, cur); } static GstFlowReturn -gst_tag_lib_mux_chain (GstPad * pad, GstBuffer * buffer) +gst_tag_mux_chain (GstPad * pad, GstBuffer * buffer) { - GstTagLibMux *mux = GST_TAG_LIB_MUX (GST_OBJECT_PARENT (pad)); + GstTagMux *mux = GST_TAG_MUX (GST_OBJECT_PARENT (pad)); + GstFlowReturn ret; + int length; - if (mux->render_tag) { - GstFlowReturn ret; - GstBuffer *tag_buffer; + if (mux->render_start_tag) { GST_INFO_OBJECT (mux, "Adding tags to stream"); - tag_buffer = gst_tag_lib_mux_render_tag (mux); - if (tag_buffer == NULL) - goto no_tag_buffer; - ret = gst_pad_push (mux->srcpad, tag_buffer); + ret = gst_tag_mux_render_start_tag (mux); if (ret != GST_FLOW_OK) { GST_DEBUG_OBJECT (mux, "flow: %s", gst_flow_get_name (ret)); gst_buffer_unref (buffer); @@ -245,16 +311,25 @@ gst_tag_lib_mux_chain (GstPad * pad, GstBuffer * buffer) /* Now send the cached newsegment event that we got from upstream */ if (mux->newsegment_ev) { + gint64 start; + GstEvent *newseg; + GST_DEBUG_OBJECT (mux, "sending cached newsegment event"); - gst_pad_push_event (mux->srcpad, - gst_tag_lib_mux_adjust_event_offsets (mux, mux->newsegment_ev)); + newseg = gst_tag_mux_adjust_event_offsets (mux, mux->newsegment_ev); gst_event_unref (mux->newsegment_ev); mux->newsegment_ev = NULL; + + gst_event_parse_new_segment (newseg, NULL, NULL, NULL, &start, NULL, + NULL); + + gst_pad_push_event (mux->srcpad, newseg); + mux->current_offset = start; + mux->max_offset = MAX (mux->max_offset, mux->current_offset); } else { /* upstream sent no newsegment event or only one in a non-BYTE format */ } - mux->render_tag = FALSE; + mux->render_start_tag = FALSE; } buffer = gst_buffer_make_metadata_writable (buffer); @@ -262,28 +337,28 @@ gst_tag_lib_mux_chain (GstPad * pad, GstBuffer * buffer) if (GST_BUFFER_OFFSET (buffer) != GST_BUFFER_OFFSET_NONE) { GST_LOG_OBJECT (mux, "Adjusting buffer offset from %" G_GINT64_FORMAT " to %" G_GINT64_FORMAT, GST_BUFFER_OFFSET (buffer), - GST_BUFFER_OFFSET (buffer) + mux->tag_size); - GST_BUFFER_OFFSET (buffer) += mux->tag_size; + GST_BUFFER_OFFSET (buffer) + mux->start_tag_size); + GST_BUFFER_OFFSET (buffer) += mux->start_tag_size; } + length = GST_BUFFER_SIZE (buffer); + gst_buffer_set_caps (buffer, GST_PAD_CAPS (mux->srcpad)); - return gst_pad_push (mux->srcpad, buffer); + ret = gst_pad_push (mux->srcpad, buffer); -/* ERRORS */ -no_tag_buffer: - { - GST_ELEMENT_ERROR (mux, LIBRARY, ENCODE, (NULL), (NULL)); - return GST_FLOW_ERROR; - } + mux->current_offset += length; + mux->max_offset = MAX (mux->max_offset, mux->current_offset); + + return ret; } static gboolean -gst_tag_lib_mux_sink_event (GstPad * pad, GstEvent * event) +gst_tag_mux_sink_event (GstPad * pad, GstEvent * event) { - GstTagLibMux *mux; + GstTagMux *mux; gboolean result; - mux = GST_TAG_LIB_MUX (gst_pad_get_parent (pad)); + mux = GST_TAG_MUX (gst_pad_get_parent (pad)); result = FALSE; switch (GST_EVENT_TYPE (event)) { @@ -303,15 +378,16 @@ gst_tag_lib_mux_sink_event (GstPad * pad, GstEvent * event) GST_INFO_OBJECT (mux, "Event tags are now: %" GST_PTR_FORMAT, mux->event_tags); - /* just drop the event, we'll push a new tag event in render_tag */ + /* just drop the event, we'll push a new tag event in render_start_tag */ gst_event_unref (event); result = TRUE; break; } case GST_EVENT_NEWSEGMENT:{ GstFormat fmt; + gint64 start; - gst_event_parse_new_segment (event, NULL, NULL, &fmt, NULL, NULL, NULL); + gst_event_parse_new_segment (event, NULL, NULL, &fmt, &start, NULL, NULL); if (fmt != GST_FORMAT_BYTES) { GST_WARNING_OBJECT (mux, "dropping newsegment event in %s format", @@ -320,7 +396,7 @@ gst_tag_lib_mux_sink_event (GstPad * pad, GstEvent * event) break; } - if (mux->render_tag) { + if (mux->render_start_tag) { /* we have not rendered the tag yet, which means that we don't know * how large it is going to be yet, so we can't adjust the offsets * here at this point and need to cache the newsegment event for now @@ -336,13 +412,34 @@ gst_tag_lib_mux_sink_event (GstPad * pad, GstEvent * event) } else { GST_DEBUG_OBJECT (mux, "got newsegment event, adjusting offsets"); gst_pad_push_event (mux->srcpad, - gst_tag_lib_mux_adjust_event_offsets (mux, event)); + gst_tag_mux_adjust_event_offsets (mux, event)); gst_event_unref (event); + + mux->current_offset = start; + mux->max_offset = MAX (mux->max_offset, mux->current_offset); } event = NULL; result = TRUE; break; } + case GST_EVENT_EOS:{ + if (mux->render_end_tag) { + GstFlowReturn ret; + + GST_INFO_OBJECT (mux, "Adding tags to stream"); + ret = gst_tag_mux_render_end_tag (mux); + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (mux, "flow: %s", gst_flow_get_name (ret)); + return ret; + } + + mux->render_end_tag = FALSE; + } + + /* Now forward EOS */ + result = gst_pad_event_default (pad, event); + break; + } default: result = gst_pad_event_default (pad, event); break; @@ -355,12 +452,12 @@ gst_tag_lib_mux_sink_event (GstPad * pad, GstEvent * event) static GstStateChangeReturn -gst_tag_lib_mux_change_state (GstElement * element, GstStateChange transition) +gst_tag_mux_change_state (GstElement * element, GstStateChange transition) { - GstTagLibMux *mux; + GstTagMux *mux; GstStateChangeReturn result; - mux = GST_TAG_LIB_MUX (element); + mux = GST_TAG_MUX (element); result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); if (result != GST_STATE_CHANGE_SUCCESS) { @@ -377,8 +474,12 @@ gst_tag_lib_mux_change_state (GstElement * element, GstStateChange transition) gst_tag_list_free (mux->event_tags); mux->event_tags = NULL; } - mux->tag_size = 0; - mux->render_tag = TRUE; + mux->start_tag_size = 0; + mux->end_tag_size = 0; + mux->render_start_tag = TRUE; + mux->render_end_tag = TRUE; + mux->current_offset = 0; + mux->max_offset = 0; break; } default: @@ -387,16 +488,3 @@ gst_tag_lib_mux_change_state (GstElement * element, GstStateChange transition) return result; } - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return (gst_id3v2_mux_plugin_init (plugin) - && gst_apev2_mux_plugin_init (plugin)); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "taglib", - "Tag writing plug-in based on taglib", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst-libs/gst/tag/gsttagmux.h b/gst-libs/gst/tag/gsttagmux.h index d26ff30867..c13a7326d2 100644 --- a/gst-libs/gst/tag/gsttagmux.h +++ b/gst-libs/gst/tag/gsttagmux.h @@ -1,7 +1,9 @@ -/* GStreamer taglib-based muxer base class +/* GStreamer tag muxer base class + * * Copyright (C) 2006 Christophe Fergeau * Copyright (C) 2006 Tim-Philipp Müller - + * Copyright (C) 2009 Pioneers of the Inevitable + * * 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 @@ -18,54 +20,60 @@ * Boston, MA 02111-1307, USA. */ -#ifndef GST_TAG_LIB_MUX_H -#define GST_TAG_LIB_MUX_H +#ifndef GST_TAG_MUX_H +#define GST_TAG_MUX_H #include G_BEGIN_DECLS -typedef struct _GstTagLibMux GstTagLibMux; -typedef struct _GstTagLibMuxClass GstTagLibMuxClass; +typedef struct _GstTagMux GstTagMux; +typedef struct _GstTagMuxClass GstTagMuxClass; /* Definition of structure storing data for this element. */ -struct _GstTagLibMux { +struct _GstTagMux { GstElement element; GstPad *srcpad; GstPad *sinkpad; GstTagList *event_tags; /* tags received from upstream elements */ - gsize tag_size; - gboolean render_tag; + GstTagList *final_tags; /* Final set of tags used for muxing */ + gsize start_tag_size; + gsize end_tag_size; + gboolean render_start_tag; + gboolean render_end_tag; + + gint64 current_offset; + gint64 max_offset; GstEvent *newsegment_ev; /* cached newsegment event from upstream */ }; /* Standard definition defining a class for this element. */ -struct _GstTagLibMuxClass { +struct _GstTagMuxClass { GstElementClass parent_class; /* vfuncs */ - GstBuffer * (*render_tag) (GstTagLibMux * mux, GstTagList * tag_list); + GstBuffer * (*render_start_tag) (GstTagMux * mux, GstTagList * tag_list); + GstBuffer * (*render_end_tag) (GstTagMux * mux, GstTagList * tag_list); }; /* Standard macros for defining types for this element. */ -#define GST_TYPE_TAG_LIB_MUX \ - (gst_tag_lib_mux_get_type()) -#define GST_TAG_LIB_MUX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_LIB_MUX,GstTagLibMux)) -#define GST_TAG_LIB_MUX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_LIB_MUX,GstTagLibMuxClass)) -#define GST_IS_TAG_LIB_MUX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_LIB_MUX)) -#define GST_IS_TAG_LIB_MUX_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_LIB_MUX)) +#define GST_TYPE_TAG_MUX \ + (gst_tag_mux_get_type()) +#define GST_TAG_MUX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TAG_MUX,GstTagMux)) +#define GST_TAG_MUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TAG_MUX,GstTagMuxClass)) +#define GST_IS_TAG_MUX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TAG_MUX)) +#define GST_IS_TAG_MUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TAG_MUX)) /* Standard function returning type information. */ -GType gst_tag_lib_mux_get_type (void); -gboolean gst_apev2_mux_plugin_init (GstPlugin * plugin); -gboolean gst_id3v2_mux_plugin_init (GstPlugin * plugin); +GType gst_tag_mux_get_type (void); G_END_DECLS #endif +