blob: a5e78fe9aa6e8d87f8e739d1b4917135029ef555 [file] [log] [blame]
Stefan Kostb3cfa352008-06-11 14:28:44 +00001/* GStreamer
2 * Copyright (C) 2008 Stefan Kost <ensonic@users.sf.net>
3 *
4 * gsttaginject.c:
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21/**
22 * SECTION:element-taginject
23 *
Stefan Kostda2d6b62008-07-22 06:32:03 +000024 * Element that injects new metadata tags, but passes incomming data through
Stefan Kostb3cfa352008-06-11 14:28:44 +000025 * unmodified.
Stefan Kosta99d3f82009-01-28 12:29:42 +020026 *
27 * <refsect2>
28 * <title>Example launch lines</title>
Stefan Kostb3cfa352008-06-11 14:28:44 +000029 * |[
30 * gst-launch audiotestsrc num-buffers=100 ! taginject tags="title=testsrc,artist=gstreamer" ! vorbisenc ! oggmux ! filesink location=test.ogg
Stefan Kostd64815f2008-09-03 11:10:25 +000031 * ]| set title and artist
32 * |[
Stefan Kostf003fef2010-02-05 13:28:53 +020033 * gst-launch audiotestsrc num-buffers=100 ! taginject tags="keywords=\{\"testone\",\"audio\"\},title=\"audio testtone\"" ! vorbisenc ! oggmux ! filesink location=test.ogg
34 * ]| set keywords and title demonstrating quoting of special chars and handling lists
Stefan Kosta99d3f82009-01-28 12:29:42 +020035 * </refsect2>
Stefan Kostb3cfa352008-06-11 14:28:44 +000036 */
37
38#ifdef HAVE_CONFIG_H
39# include "config.h"
40#endif
41
42#include <stdlib.h>
43
44#include "gsttaginject.h"
45
46static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
47 GST_PAD_SINK,
48 GST_PAD_ALWAYS,
49 GST_STATIC_CAPS_ANY);
50
51static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
52 GST_PAD_SRC,
53 GST_PAD_ALWAYS,
54 GST_STATIC_CAPS_ANY);
55
56GST_DEBUG_CATEGORY_STATIC (gst_tag_inject_debug);
57#define GST_CAT_DEFAULT gst_tag_inject_debug
58
59enum
60{
Tim-Philipp Müller7a118612008-06-13 21:13:46 +000061 PROP_TAGS = 1
Stefan Kostb3cfa352008-06-11 14:28:44 +000062};
63
64
65#define DEBUG_INIT(bla) \
66 GST_DEBUG_CATEGORY_INIT (gst_tag_inject_debug, "taginject", 0, "tag inject element");
67
68GST_BOILERPLATE_FULL (GstTagInject, gst_tag_inject, GstBaseTransform,
69 GST_TYPE_BASE_TRANSFORM, DEBUG_INIT);
70
71static void gst_tag_inject_finalize (GObject * object);
72static void gst_tag_inject_set_property (GObject * object, guint prop_id,
73 const GValue * value, GParamSpec * pspec);
74static void gst_tag_inject_get_property (GObject * object, guint prop_id,
75 GValue * value, GParamSpec * pspec);
76
Stefan Kostda2d6b62008-07-22 06:32:03 +000077static GstFlowReturn gst_tag_inject_transform_ip (GstBaseTransform * trans,
78 GstBuffer * buf);
Stefan Kostb3cfa352008-06-11 14:28:44 +000079static gboolean gst_tag_inject_start (GstBaseTransform * trans);
80
81
82static void
83gst_tag_inject_base_init (gpointer g_class)
84{
85 GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
86
87 gst_element_class_set_details_simple (gstelement_class,
88 "TagInject",
89 "Generic", "inject metadata tags", "Stefan Kost <ensonic@users.sf.net>");
90 gst_element_class_add_pad_template (gstelement_class,
91 gst_static_pad_template_get (&srctemplate));
92 gst_element_class_add_pad_template (gstelement_class,
93 gst_static_pad_template_get (&sinktemplate));
94}
95
96static void
97gst_tag_inject_finalize (GObject * object)
98{
99 GstTagInject *self = GST_TAG_INJECT (object);
100
Tim-Philipp Müller7a118612008-06-13 21:13:46 +0000101 if (self->tags) {
102 gst_tag_list_free (self->tags);
103 self->tags = NULL;
104 }
Stefan Kostb3cfa352008-06-11 14:28:44 +0000105
106 G_OBJECT_CLASS (parent_class)->finalize (object);
107}
108
109static void
110gst_tag_inject_class_init (GstTagInjectClass * klass)
111{
112 GObjectClass *gobject_class;
Stefan Kostb3cfa352008-06-11 14:28:44 +0000113 GstBaseTransformClass *gstbasetrans_class;
114
115 gobject_class = G_OBJECT_CLASS (klass);
Stefan Kostb3cfa352008-06-11 14:28:44 +0000116 gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
117
Sebastian Drögef16ed4a2010-06-06 17:52:40 +0200118 gobject_class->set_property = gst_tag_inject_set_property;
119 gobject_class->get_property = gst_tag_inject_get_property;
Stefan Kostb3cfa352008-06-11 14:28:44 +0000120
121 g_object_class_install_property (gobject_class, PROP_TAGS,
122 g_param_spec_string ("tags", "taglist",
123 "List of tags to inject into the target file",
124 NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
125
Sebastian Drögef16ed4a2010-06-06 17:52:40 +0200126 gobject_class->finalize = gst_tag_inject_finalize;
Stefan Kostb3cfa352008-06-11 14:28:44 +0000127
Stefan Kostda2d6b62008-07-22 06:32:03 +0000128 gstbasetrans_class->transform_ip =
129 GST_DEBUG_FUNCPTR (gst_tag_inject_transform_ip);
Tim-Philipp Müller7a118612008-06-13 21:13:46 +0000130
Stefan Kostb3cfa352008-06-11 14:28:44 +0000131 gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_tag_inject_start);
132}
133
134static void
135gst_tag_inject_init (GstTagInject * self, GstTagInjectClass * g_class)
136{
137 self->tags = NULL;
138}
139
Stefan Kostb3cfa352008-06-11 14:28:44 +0000140static GstFlowReturn
141gst_tag_inject_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
142{
Tim-Philipp Müller7a118612008-06-13 21:13:46 +0000143 GstTagInject *self = GST_TAG_INJECT (trans);
Stefan Kostb3cfa352008-06-11 14:28:44 +0000144
Stefan Kostda2d6b62008-07-22 06:32:03 +0000145 if (G_UNLIKELY (!self->tags_sent)) {
146 self->tags_sent = TRUE;
147 /* send tags */
148 if (self->tags && !gst_tag_list_is_empty (self->tags)) {
Stefan Kostd64815f2008-09-03 11:10:25 +0000149 GST_DEBUG ("tag event :%" GST_PTR_FORMAT, self->tags);
Stefan Kostda2d6b62008-07-22 06:32:03 +0000150 gst_element_found_tags (GST_ELEMENT (trans),
151 gst_tag_list_copy (self->tags));
152 }
153 }
154
Stefan Kostb3cfa352008-06-11 14:28:44 +0000155 return GST_FLOW_OK;
156}
Stefan Kostb3cfa352008-06-11 14:28:44 +0000157
158static void
159gst_tag_inject_set_property (GObject * object, guint prop_id,
160 const GValue * value, GParamSpec * pspec)
161{
162 GstTagInject *self = GST_TAG_INJECT (object);
Stefan Kostb3cfa352008-06-11 14:28:44 +0000163
164 switch (prop_id) {
Stefan Kostd64815f2008-09-03 11:10:25 +0000165 case PROP_TAGS:{
166 gchar *structure =
167 g_strdup_printf ("taglist,%s", g_value_get_string (value));
168 if (!(self->tags = gst_structure_from_string (structure, NULL))) {
169 GST_WARNING ("unparsable taglist = '%s'", structure);
170 }
Tuukka Pasanend203b1e2011-02-14 15:21:29 +0200171
172 /* make sure that tags will be send */
173 self->tags_sent = FALSE;
Stefan Kostb3cfa352008-06-11 14:28:44 +0000174 g_free (structure);
175 break;
Stefan Kostd64815f2008-09-03 11:10:25 +0000176 }
Stefan Kostb3cfa352008-06-11 14:28:44 +0000177 default:
178 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
179 break;
180 }
181}
182
183static void
184gst_tag_inject_get_property (GObject * object, guint prop_id, GValue * value,
185 GParamSpec * pspec)
186{
187 /*GstTagInject *self = GST_TAG_INJECT (object); */
188
189 switch (prop_id) {
190 default:
191 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
192 break;
193 }
194}
195
196static gboolean
197gst_tag_inject_start (GstBaseTransform * trans)
198{
199 GstTagInject *self = GST_TAG_INJECT (trans);
200
Stefan Kostda2d6b62008-07-22 06:32:03 +0000201 /* we need to sent tags _transform_ip() once */
202 self->tags_sent = FALSE;
Stefan Kostb3cfa352008-06-11 14:28:44 +0000203
204 return TRUE;
205}