• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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