1 /*
2 * GStreamer
3 * Copyright (C) 2005 Thomas Vander Stichele <thomas@apestaart.org>
4 * Copyright (C) 2005 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
5 * Copyright (C) 2011 Igalia S.L.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 */
22
23 /**
24 * SECTION:element-debugspy
25 * @title: debugspy
26 *
27 * A spy element that can provide information on buffers going through it, with
28 * bus messages.
29 *
30 * ## Example launch line
31 * |[
32 * gst-launch-1.0 -m videotestsrc ! debugspy ! fakesink
33 * ]|
34 *
35 */
36
37 #ifdef HAVE_CONFIG_H
38 # include <config.h>
39 #endif
40
41 #include <gst/gst.h>
42
43 #include "gstdebugspy.h"
44
45 GST_DEBUG_CATEGORY_STATIC (gst_debug_spy_debug);
46 #define GST_CAT_DEFAULT gst_debug_spy_debug
47
48 /* Filter signals and args */
49 enum
50 {
51 /* FILL ME */
52 LAST_SIGNAL
53 };
54
55 enum
56 {
57 PROP_0,
58 PROP_SILENT,
59 PROP_CHECKSUM_TYPE
60 };
61
62 /* create a GType for GChecksumType */
63 #define GST_DEBUG_SPY_CHECKSUM_TYPE (gst_debug_spy_checksum_get_type())
64 static GType
gst_debug_spy_checksum_get_type(void)65 gst_debug_spy_checksum_get_type (void)
66 {
67 static GType checksum_type = 0;
68
69 static const GEnumValue checksum_values[] = {
70 {G_CHECKSUM_MD5, "Use the MD5 hashing algorithm", "md5"},
71 {G_CHECKSUM_SHA1, "Use the SHA-1 hashing algorithm", "sha1"},
72 {G_CHECKSUM_SHA256, "Use the SHA-256 hashing algorithm", "sha256"},
73 {0, NULL, NULL}
74 };
75
76 if (!checksum_type)
77 checksum_type = g_enum_register_static ("GChecksumType", checksum_values);
78
79 return checksum_type;
80 }
81
82 /* the capabilities of the inputs and outputs.
83 *
84 * describe the real formats here.
85 */
86 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
87 GST_PAD_SINK,
88 GST_PAD_ALWAYS,
89 GST_STATIC_CAPS ("ANY")
90 );
91
92 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
93 GST_PAD_SRC,
94 GST_PAD_ALWAYS,
95 GST_STATIC_CAPS ("ANY")
96 );
97
98 G_DEFINE_TYPE (GstDebugSpy, gst_debug_spy, GST_TYPE_BASE_TRANSFORM);
99
100 static void gst_debug_spy_set_property (GObject * object, guint prop_id,
101 const GValue * value, GParamSpec * pspec);
102 static void gst_debug_spy_get_property (GObject * object, guint prop_id,
103 GValue * value, GParamSpec * pspec);
104 static GstFlowReturn gst_debug_spy_transform_ip (GstBaseTransform * transform,
105 GstBuffer * buf);
106
107 /* GObject vmethod implementations */
108
109 /* initialize the debugspy's class */
110 static void
gst_debug_spy_class_init(GstDebugSpyClass * klass)111 gst_debug_spy_class_init (GstDebugSpyClass * klass)
112 {
113 GObjectClass *gobject_class;
114 GstElementClass *element_class;
115 GstBaseTransformClass *base_transform_class;
116
117 gobject_class = (GObjectClass *) klass;
118 element_class = (GstElementClass *) klass;
119 base_transform_class = (GstBaseTransformClass *) klass;
120
121 gobject_class->set_property = gst_debug_spy_set_property;
122 gobject_class->get_property = gst_debug_spy_get_property;
123
124 base_transform_class->passthrough_on_same_caps = TRUE;
125 base_transform_class->transform_ip = gst_debug_spy_transform_ip;
126
127 g_object_class_install_property (gobject_class, PROP_SILENT,
128 g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
129 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
130
131 g_object_class_install_property (gobject_class, PROP_CHECKSUM_TYPE,
132 g_param_spec_enum ("checksum-type", "Checksum TYpe",
133 "Checksum algorithm to use", GST_DEBUG_SPY_CHECKSUM_TYPE,
134 G_CHECKSUM_SHA1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
135
136 gst_element_class_set_static_metadata (element_class,
137 "DebugSpy",
138 "Filter/Analyzer/Debug",
139 "DebugSpy provides information on buffers with bus messages",
140 "Guillaume Emont <gemont@igalia.com>");
141
142 gst_element_class_add_static_pad_template (element_class, &src_factory);
143 gst_element_class_add_static_pad_template (element_class, &sink_factory);
144
145 GST_DEBUG_CATEGORY_INIT (gst_debug_spy_debug, "debugspy", 0, "debugspy");
146 }
147
148 /* initialize the new element
149 * instantiate pads and add them to element
150 * set pad calback functions
151 * initialize instance structure
152 */
153 static void
gst_debug_spy_init(GstDebugSpy * debugspy)154 gst_debug_spy_init (GstDebugSpy * debugspy)
155 {
156 debugspy->silent = FALSE;
157 debugspy->checksum_type = G_CHECKSUM_SHA1;
158 }
159
160 static void
gst_debug_spy_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)161 gst_debug_spy_set_property (GObject * object, guint prop_id,
162 const GValue * value, GParamSpec * pspec)
163 {
164 GstDebugSpy *debugspy = GST_DEBUGSPY (object);
165
166 switch (prop_id) {
167 case PROP_SILENT:
168 debugspy->silent = g_value_get_boolean (value);
169 break;
170 case PROP_CHECKSUM_TYPE:
171 debugspy->checksum_type = g_value_get_enum (value);
172 break;
173 default:
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
175 break;
176 }
177 }
178
179 static void
gst_debug_spy_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)180 gst_debug_spy_get_property (GObject * object, guint prop_id,
181 GValue * value, GParamSpec * pspec)
182 {
183 GstDebugSpy *debugspy = GST_DEBUGSPY (object);
184
185 switch (prop_id) {
186 case PROP_SILENT:
187 g_value_set_boolean (value, debugspy->silent);
188 break;
189 case PROP_CHECKSUM_TYPE:
190 g_value_set_enum (value, debugspy->checksum_type);
191 break;
192 default:
193 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
194 break;
195 }
196 }
197
198 /* GstBaseTransform vmethod implementations */
199
200 static GstFlowReturn
gst_debug_spy_transform_ip(GstBaseTransform * transform,GstBuffer * buf)201 gst_debug_spy_transform_ip (GstBaseTransform * transform, GstBuffer * buf)
202 {
203 GstDebugSpy *debugspy = GST_DEBUGSPY (transform);
204
205 if (debugspy->silent == FALSE) {
206 gchar *checksum;
207 GstMessage *message;
208 GstStructure *message_structure;
209 GstMapInfo map;
210 GstCaps *caps;
211
212 gst_buffer_map (buf, &map, GST_MAP_READ);
213 checksum = g_compute_checksum_for_data (debugspy->checksum_type,
214 map.data, map.size);
215
216 caps = gst_pad_get_current_caps (GST_BASE_TRANSFORM_SRC_PAD (transform));
217 message_structure = gst_structure_new ("buffer",
218 "checksum", G_TYPE_STRING, checksum,
219 "timestamp", GST_TYPE_CLOCK_TIME, GST_BUFFER_TIMESTAMP (buf),
220 "duration", GST_TYPE_CLOCK_TIME, GST_BUFFER_DURATION (buf),
221 "offset", G_TYPE_UINT64, GST_BUFFER_OFFSET (buf),
222 "offset_end", G_TYPE_UINT64, GST_BUFFER_OFFSET_END (buf),
223 "size", G_TYPE_UINT, map.size, "caps", GST_TYPE_CAPS, caps, NULL);
224 if (caps)
225 gst_caps_unref (caps);
226
227 g_free (checksum);
228 gst_buffer_unmap (buf, &map);
229
230 message =
231 gst_message_new_element (GST_OBJECT (transform), message_structure);
232
233 gst_element_post_message (GST_ELEMENT (transform), message);
234
235 }
236
237 return GST_FLOW_OK;
238 }
239