2 * Copyright (C) <2006> Wim Taymans <wim@fluendo.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
17 * Boston, MA 02110-1335, USA.
20 * SECTION:element-videoanalyse
21 * @title: videoanalyse
23 * This plugin analyses every video frame and if the #GstVideoAnalyse:message
24 * property is %TRUE, posts an element message with video statistics called
27 * The message's structure contains these fields:
29 * * #GstClockTime `timestamp`: the timestamp of the buffer that triggered the message.
31 * * #GstClockTime `stream-time`: the stream time of the buffer.
33 * * #GstClockTime `running-time`: the running_time of the buffer.
35 * * #GstClockTime`duration`:the duration of the buffer.
37 * * #gdouble`luma-average`: the average brightness of the frame. Range: 0.0-1.0
39 * * #gdouble`luma-variance`: the brightness variance of the frame.
41 * ## Example launch line
43 * gst-launch-1.0 -m videotestsrc ! videoanalyse ! videoconvert ! ximagesink
44 * ]| This pipeline emits messages to the console for each frame that has been analysed.
53 #include <gst/video/video.h>
54 #include <gst/video/gstvideofilter.h>
55 #include "gstvideoanalyse.h"
57 GST_DEBUG_CATEGORY_STATIC (gst_video_analyse_debug_category);
58 #define GST_CAT_DEFAULT gst_video_analyse_debug_category
63 static void gst_video_analyse_set_property (GObject * object,
64 guint property_id, const GValue * value, GParamSpec * pspec);
65 static void gst_video_analyse_get_property (GObject * object,
66 guint property_id, GValue * value, GParamSpec * pspec);
67 static void gst_video_analyse_finalize (GObject * object);
69 static GstFlowReturn gst_video_analyse_transform_frame_ip (GstVideoFilter *
70 filter, GstVideoFrame * frame);
78 #define DEFAULT_MESSAGE TRUE
81 GST_VIDEO_CAPS_MAKE("{ I420, YV12, Y444, Y42B, Y41B }")
84 /* class initialization */
86 G_DEFINE_TYPE_WITH_CODE (GstVideoAnalyse, gst_video_analyse,
87 GST_TYPE_VIDEO_FILTER,
88 GST_DEBUG_CATEGORY_INIT (gst_video_analyse_debug_category, "videoanalyse",
89 0, "debug category for videoanalyse element"));
90 GST_ELEMENT_REGISTER_DEFINE (videoanalyse, "videoanalyse",
91 GST_RANK_NONE, GST_TYPE_VIDEO_ANALYSE);
94 gst_video_analyse_class_init (GstVideoAnalyseClass * klass)
96 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
98 GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);
100 gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
101 gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
102 tmp = gst_caps_from_string (VIDEO_CAPS)));
103 gst_caps_unref (tmp);
104 gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
105 gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
106 tmp = gst_caps_from_string (VIDEO_CAPS)));
107 gst_caps_unref (tmp);
109 gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
110 "Video analyser", "Filter/Analyzer/Video",
111 "Analyse video signal", "Wim Taymans <wim@fluendo.com>");
113 gobject_class->set_property = gst_video_analyse_set_property;
114 gobject_class->get_property = gst_video_analyse_get_property;
115 gobject_class->finalize = gst_video_analyse_finalize;
116 video_filter_class->transform_frame_ip =
117 GST_DEBUG_FUNCPTR (gst_video_analyse_transform_frame_ip);
119 g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MESSAGE,
120 g_param_spec_boolean ("message", "Message",
121 "Post statics messages",
123 G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
124 //trans_class->passthrough_on_same_caps = TRUE;
128 gst_video_analyse_init (GstVideoAnalyse * videoanalyse)
133 gst_video_analyse_set_property (GObject * object, guint property_id,
134 const GValue * value, GParamSpec * pspec)
136 GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (object);
138 GST_DEBUG_OBJECT (videoanalyse, "set_property");
140 switch (property_id) {
142 videoanalyse->message = g_value_get_boolean (value);
145 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
151 gst_video_analyse_get_property (GObject * object, guint property_id,
152 GValue * value, GParamSpec * pspec)
154 GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (object);
156 GST_DEBUG_OBJECT (videoanalyse, "get_property");
158 switch (property_id) {
160 g_value_set_boolean (value, videoanalyse->message);
163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
169 gst_video_analyse_finalize (GObject * object)
171 GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (object);
173 GST_DEBUG_OBJECT (videoanalyse, "finalize");
175 /* clean up object here */
177 G_OBJECT_CLASS (gst_video_analyse_parent_class)->finalize (object);
181 gst_video_analyse_post_message (GstVideoAnalyse * videoanalyse,
182 GstVideoFrame * frame)
184 GstBaseTransform *trans;
186 guint64 duration, timestamp, running_time, stream_time;
188 trans = GST_BASE_TRANSFORM_CAST (videoanalyse);
191 timestamp = GST_BUFFER_TIMESTAMP (frame->buffer);
192 duration = GST_BUFFER_DURATION (frame->buffer);
193 running_time = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
195 stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
198 m = gst_message_new_element (GST_OBJECT_CAST (videoanalyse),
199 gst_structure_new ("GstVideoAnalyse",
200 "timestamp", G_TYPE_UINT64, timestamp,
201 "stream-time", G_TYPE_UINT64, stream_time,
202 "running-time", G_TYPE_UINT64, running_time,
203 "duration", G_TYPE_UINT64, duration,
204 "luma-average", G_TYPE_DOUBLE, videoanalyse->luma_average,
205 "luma-variance", G_TYPE_DOUBLE, videoanalyse->luma_variance, NULL));
207 gst_element_post_message (GST_ELEMENT_CAST (videoanalyse), m);
211 gst_video_analyse_planar (GstVideoAnalyse * videoanalyse, GstVideoFrame * frame)
217 gint width = frame->info.width;
218 gint height = frame->info.height;
222 stride = frame->info.stride[0];
224 /* do brightness as average of pixel brightness in 0.0 to 1.0 */
225 for (i = 0; i < height; i++) {
226 for (j = 0; j < width; j++) {
231 avg = sum / (width * height);
232 videoanalyse->luma_average = sum / (255.0 * width * height);
235 stride = frame->info.stride[0];
238 for (i = 0; i < height; i++) {
239 for (j = 0; j < width; j++) {
245 videoanalyse->luma_variance = sum / (255.0 * 255.0 * width * height);
249 gst_video_analyse_transform_frame_ip (GstVideoFilter * filter,
250 GstVideoFrame * frame)
252 GstVideoAnalyse *videoanalyse = GST_VIDEO_ANALYSE (filter);
254 GST_DEBUG_OBJECT (videoanalyse, "transform_frame_ip");
256 gst_video_analyse_planar (videoanalyse, frame);
258 if (videoanalyse->message)
259 gst_video_analyse_post_message (videoanalyse, frame);