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