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 "gstdebugutilsbadelements.h"
44 #include "gstdebugspy.h"
45
46 GST_DEBUG_CATEGORY_STATIC (gst_debug_spy_debug);
47 #define GST_CAT_DEFAULT gst_debug_spy_debug
48
49 /* Filter signals and args */
50 enum
51 {
52 /* FILL ME */
53 LAST_SIGNAL
54 };
55
56 enum
57 {
58 PROP_0,
59 PROP_SILENT,
60 PROP_CHECKSUM_TYPE
61 };
62
63 /* create a GType for GChecksumType */
64 #define GST_DEBUG_SPY_CHECKSUM_TYPE (gst_debug_spy_checksum_get_type())
65 static GType
gst_debug_spy_checksum_get_type(void)66 gst_debug_spy_checksum_get_type (void)
67 {
68 static GType checksum_type = 0;
69
70 static const GEnumValue checksum_values[] = {
71 {G_CHECKSUM_MD5, "Use the MD5 hashing algorithm", "md5"},
72 {G_CHECKSUM_SHA1, "Use the SHA-1 hashing algorithm", "sha1"},
73 {G_CHECKSUM_SHA256, "Use the SHA-256 hashing algorithm", "sha256"},
74 {0, NULL, NULL}
75 };
76
77 if (!checksum_type)
78 checksum_type = g_enum_register_static ("GChecksumType", checksum_values);
79
80 return checksum_type;
81 }
82
83 /* the capabilities of the inputs and outputs.
84 *
85 * describe the real formats here.
86 */
87 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
88 GST_PAD_SINK,
89 GST_PAD_ALWAYS,
90 GST_STATIC_CAPS ("ANY")
91 );
92
93 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
94 GST_PAD_SRC,
95 GST_PAD_ALWAYS,
96 GST_STATIC_CAPS ("ANY")
97 );
98
99 G_DEFINE_TYPE (GstDebugSpy, gst_debug_spy, GST_TYPE_BASE_TRANSFORM);
100 GST_ELEMENT_REGISTER_DEFINE (debugspy, "debugspy",
101 GST_RANK_NONE, gst_debug_spy_get_type ());
102
103 static void gst_debug_spy_set_property (GObject * object, guint prop_id,
104 const GValue * value, GParamSpec * pspec);
105 static void gst_debug_spy_get_property (GObject * object, guint prop_id,
106 GValue * value, GParamSpec * pspec);
107 static GstFlowReturn gst_debug_spy_transform_ip (GstBaseTransform * transform,
108 GstBuffer * buf);
109
110 /* GObject vmethod implementations */
111
112 /* initialize the debugspy's class */
113 static void
gst_debug_spy_class_init(GstDebugSpyClass * klass)114 gst_debug_spy_class_init (GstDebugSpyClass * klass)
115 {
116 GObjectClass *gobject_class;
117 GstElementClass *element_class;
118 GstBaseTransformClass *base_transform_class;
119
120 gobject_class = (GObjectClass *) klass;
121 element_class = (GstElementClass *) klass;
122 base_transform_class = (GstBaseTransformClass *) klass;
123
124 gobject_class->set_property = gst_debug_spy_set_property;
125 gobject_class->get_property = gst_debug_spy_get_property;
126
127 base_transform_class->passthrough_on_same_caps = TRUE;
128 base_transform_class->transform_ip = gst_debug_spy_transform_ip;
129
130 g_object_class_install_property (gobject_class, PROP_SILENT,
131 g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?",
132 FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
133
134 g_object_class_install_property (gobject_class, PROP_CHECKSUM_TYPE,
135 g_param_spec_enum ("checksum-type", "Checksum TYpe",
136 "Checksum algorithm to use", GST_DEBUG_SPY_CHECKSUM_TYPE,
137 G_CHECKSUM_SHA1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
138
139 gst_element_class_set_static_metadata (element_class,
140 "DebugSpy",
141 "Filter/Analyzer/Debug",
142 "DebugSpy provides information on buffers with bus messages",
143 "Guillaume Emont <gemont@igalia.com>");
144
145 gst_element_class_add_static_pad_template (element_class, &src_factory);
146 gst_element_class_add_static_pad_template (element_class, &sink_factory);
147
148 GST_DEBUG_CATEGORY_INIT (gst_debug_spy_debug, "debugspy", 0, "debugspy");
149 }
150
151 /* initialize the new element
152 * instantiate pads and add them to element
153 * set pad callback functions
154 * initialize instance structure
155 */
156 static void
gst_debug_spy_init(GstDebugSpy * debugspy)157 gst_debug_spy_init (GstDebugSpy * debugspy)
158 {
159 debugspy->silent = FALSE;
160 debugspy->checksum_type = G_CHECKSUM_SHA1;
161 }
162
163 static void
gst_debug_spy_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)164 gst_debug_spy_set_property (GObject * object, guint prop_id,
165 const GValue * value, GParamSpec * pspec)
166 {
167 GstDebugSpy *debugspy = GST_DEBUGSPY (object);
168
169 switch (prop_id) {
170 case PROP_SILENT:
171 debugspy->silent = g_value_get_boolean (value);
172 break;
173 case PROP_CHECKSUM_TYPE:
174 debugspy->checksum_type = g_value_get_enum (value);
175 break;
176 default:
177 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
178 break;
179 }
180 }
181
182 static void
gst_debug_spy_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)183 gst_debug_spy_get_property (GObject * object, guint prop_id,
184 GValue * value, GParamSpec * pspec)
185 {
186 GstDebugSpy *debugspy = GST_DEBUGSPY (object);
187
188 switch (prop_id) {
189 case PROP_SILENT:
190 g_value_set_boolean (value, debugspy->silent);
191 break;
192 case PROP_CHECKSUM_TYPE:
193 g_value_set_enum (value, debugspy->checksum_type);
194 break;
195 default:
196 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
197 break;
198 }
199 }
200
201 /* GstBaseTransform vmethod implementations */
202
203 static GstFlowReturn
gst_debug_spy_transform_ip(GstBaseTransform * transform,GstBuffer * buf)204 gst_debug_spy_transform_ip (GstBaseTransform * transform, GstBuffer * buf)
205 {
206 GstDebugSpy *debugspy = GST_DEBUGSPY (transform);
207
208 if (debugspy->silent == FALSE) {
209 gchar *checksum;
210 GstMessage *message;
211 GstStructure *message_structure;
212 GstMapInfo map;
213 GstCaps *caps;
214
215 gst_buffer_map (buf, &map, GST_MAP_READ);
216 checksum = g_compute_checksum_for_data (debugspy->checksum_type,
217 map.data, map.size);
218
219 caps = gst_pad_get_current_caps (GST_BASE_TRANSFORM_SRC_PAD (transform));
220 message_structure = gst_structure_new ("buffer",
221 "checksum", G_TYPE_STRING, checksum,
222 "timestamp", GST_TYPE_CLOCK_TIME, GST_BUFFER_TIMESTAMP (buf),
223 "duration", GST_TYPE_CLOCK_TIME, GST_BUFFER_DURATION (buf),
224 "offset", G_TYPE_UINT64, GST_BUFFER_OFFSET (buf),
225 "offset_end", G_TYPE_UINT64, GST_BUFFER_OFFSET_END (buf),
226 "size", G_TYPE_UINT, map.size, "caps", GST_TYPE_CAPS, caps, NULL);
227 if (caps)
228 gst_caps_unref (caps);
229
230 g_free (checksum);
231 gst_buffer_unmap (buf, &map);
232
233 message =
234 gst_message_new_element (GST_OBJECT (transform), message_structure);
235
236 gst_element_post_message (GST_ELEMENT (transform), message);
237
238 }
239
240 return GST_FLOW_OK;
241 }
242