• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* 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., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 /**
22  * SECTION:element-taginject
23  * @title: taginject
24  *
25  * Element that injects new metadata tags, but passes incoming data through
26  * unmodified.
27  *
28  * ## Example launch lines
29  * |[
30  * gst-launch-1.0 audiotestsrc num-buffers=100 ! taginject tags="title=testsrc,artist=gstreamer" ! vorbisenc ! oggmux ! filesink location=test.ogg
31  * ]| set title and artist
32  * |[
33  * gst-launch-1.0 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
35  *
36  */
37 
38 #ifdef HAVE_CONFIG_H
39 #  include "config.h"
40 #endif
41 
42 #include <stdlib.h>
43 
44 #include "gstdebugutilselements.h"
45 #include "gsttaginject.h"
46 
47 static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
48     GST_PAD_SINK,
49     GST_PAD_ALWAYS,
50     GST_STATIC_CAPS_ANY);
51 
52 static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
53     GST_PAD_SRC,
54     GST_PAD_ALWAYS,
55     GST_STATIC_CAPS_ANY);
56 
57 GST_DEBUG_CATEGORY_STATIC (gst_tag_inject_debug);
58 #define GST_CAT_DEFAULT gst_tag_inject_debug
59 
60 enum
61 {
62   PROP_TAGS = 1
63 };
64 
65 
66 #define gst_tag_inject_parent_class parent_class
67 G_DEFINE_TYPE (GstTagInject, gst_tag_inject, GST_TYPE_BASE_TRANSFORM);
68 GST_ELEMENT_REGISTER_DEFINE (taginject, "taginject",
69     GST_RANK_NONE, gst_tag_inject_get_type ());
70 
71 static void gst_tag_inject_finalize (GObject * object);
72 static void gst_tag_inject_set_property (GObject * object, guint prop_id,
73     const GValue * value, GParamSpec * pspec);
74 static void gst_tag_inject_get_property (GObject * object, guint prop_id,
75     GValue * value, GParamSpec * pspec);
76 
77 static GstFlowReturn gst_tag_inject_transform_ip (GstBaseTransform * trans,
78     GstBuffer * buf);
79 static gboolean gst_tag_inject_start (GstBaseTransform * trans);
80 
81 
82 static void
gst_tag_inject_finalize(GObject * object)83 gst_tag_inject_finalize (GObject * object)
84 {
85   GstTagInject *self = GST_TAG_INJECT (object);
86 
87   if (self->tags) {
88     gst_tag_list_unref (self->tags);
89     self->tags = NULL;
90   }
91 
92   G_OBJECT_CLASS (parent_class)->finalize (object);
93 }
94 
95 static void
gst_tag_inject_class_init(GstTagInjectClass * klass)96 gst_tag_inject_class_init (GstTagInjectClass * klass)
97 {
98   GObjectClass *gobject_class;
99   GstElementClass *gstelement_class;
100   GstBaseTransformClass *gstbasetrans_class;
101 
102   gobject_class = G_OBJECT_CLASS (klass);
103   gstelement_class = GST_ELEMENT_CLASS (klass);
104   gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
105 
106   GST_DEBUG_CATEGORY_INIT (gst_tag_inject_debug, "taginject", 0,
107       "tag inject element");
108 
109   gobject_class->set_property = gst_tag_inject_set_property;
110   gobject_class->get_property = gst_tag_inject_get_property;
111 
112   g_object_class_install_property (gobject_class, PROP_TAGS,
113       g_param_spec_string ("tags", "taglist",
114           "List of tags to inject into the target file",
115           NULL, G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS));
116 
117   gobject_class->finalize = gst_tag_inject_finalize;
118 
119   gst_element_class_set_static_metadata (gstelement_class,
120       "TagInject",
121       "Generic", "inject metadata tags", "Stefan Kost <ensonic@users.sf.net>");
122   gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
123   gst_element_class_add_static_pad_template (gstelement_class, &sinktemplate);
124 
125   gstbasetrans_class->transform_ip =
126       GST_DEBUG_FUNCPTR (gst_tag_inject_transform_ip);
127 
128   gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_tag_inject_start);
129 }
130 
131 static void
gst_tag_inject_init(GstTagInject * self)132 gst_tag_inject_init (GstTagInject * self)
133 {
134   GstBaseTransform *trans = GST_BASE_TRANSFORM (self);
135 
136   gst_base_transform_set_gap_aware (trans, TRUE);
137 
138   self->tags = NULL;
139 }
140 
141 static GstFlowReturn
gst_tag_inject_transform_ip(GstBaseTransform * trans,GstBuffer * buf)142 gst_tag_inject_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
143 {
144   GstTagInject *self = GST_TAG_INJECT (trans);
145 
146   if (G_UNLIKELY (!self->tags_sent)) {
147     self->tags_sent = TRUE;
148     /* send tags */
149     if (self->tags && !gst_tag_list_is_empty (self->tags)) {
150       GST_DEBUG ("tag event :%" GST_PTR_FORMAT, self->tags);
151       gst_pad_push_event (GST_BASE_TRANSFORM_SRC_PAD (trans),
152           gst_event_new_tag (gst_tag_list_ref (self->tags)));
153     }
154   }
155 
156   return GST_FLOW_OK;
157 }
158 
159 static void
gst_tag_inject_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)160 gst_tag_inject_set_property (GObject * object, guint prop_id,
161     const GValue * value, GParamSpec * pspec)
162 {
163   GstTagInject *self = GST_TAG_INJECT (object);
164 
165   switch (prop_id) {
166     case PROP_TAGS:{
167       gchar *structure =
168           g_strdup_printf ("taglist,%s", g_value_get_string (value));
169       if (!(self->tags = gst_tag_list_new_from_string (structure))) {
170         GST_WARNING ("unparsable taglist = '%s'", structure);
171       }
172 
173       /* make sure that tags will be send */
174       self->tags_sent = FALSE;
175       g_free (structure);
176       break;
177     }
178     default:
179       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
180       break;
181   }
182 }
183 
184 static void
gst_tag_inject_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)185 gst_tag_inject_get_property (GObject * object, guint prop_id, GValue * value,
186     GParamSpec * pspec)
187 {
188   /*GstTagInject *self = GST_TAG_INJECT (object); */
189 
190   switch (prop_id) {
191     default:
192       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
193       break;
194   }
195 }
196 
197 static gboolean
gst_tag_inject_start(GstBaseTransform * trans)198 gst_tag_inject_start (GstBaseTransform * trans)
199 {
200   GstTagInject *self = GST_TAG_INJECT (trans);
201 
202   /* we need to sent tags _transform_ip() once */
203   self->tags_sent = FALSE;
204 
205   return TRUE;
206 }
207