mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
videomark/detect: port to 1.0
This commit is contained in:
parent
4cfa3f5af3
commit
b3ff0630e8
6 changed files with 649 additions and 691 deletions
|
@ -2,12 +2,11 @@ plugin_LTLIBRARIES = libgstvideosignal.la
|
||||||
|
|
||||||
libgstvideosignal_la_SOURCES = gstvideosignal.c \
|
libgstvideosignal_la_SOURCES = gstvideosignal.c \
|
||||||
gstvideoanalyse.c \
|
gstvideoanalyse.c \
|
||||||
gstvideoanalyse.h
|
gstvideoanalyse.h \
|
||||||
|
gstvideodetect.c \
|
||||||
# gstvideodetect.c \
|
gstvideodetect.h \
|
||||||
# gstvideodetect.h \
|
gstvideomark.c \
|
||||||
# gstvideomark.c \
|
gstvideomark.h
|
||||||
# gstvideomark.h
|
|
||||||
|
|
||||||
libgstvideosignal_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
|
libgstvideosignal_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) \
|
||||||
$(GST_PLUGINS_BASE_CFLAGS)
|
$(GST_PLUGINS_BASE_CFLAGS)
|
||||||
|
|
|
@ -13,10 +13,9 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the
|
* License along with this library; if not, write to the
|
||||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1335, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:element-videodetect
|
* SECTION:element-videodetect
|
||||||
* @see_also: #GstVideoMark
|
* @see_also: #GstVideoMark
|
||||||
|
@ -79,13 +78,6 @@
|
||||||
* <listitem>
|
* <listitem>
|
||||||
* <para>
|
* <para>
|
||||||
* #guint64
|
* #guint64
|
||||||
* <classname>"data-uint64"</classname>:
|
|
||||||
* the data-pattern found after the pattern or 0 when have-signal is #FALSE.
|
|
||||||
* </para>
|
|
||||||
* </listitem>
|
|
||||||
* <listitem>
|
|
||||||
* <para>
|
|
||||||
* #guint
|
|
||||||
* <classname>"data"</classname>:
|
* <classname>"data"</classname>:
|
||||||
* the data-pattern found after the pattern or 0 when have-signal is #FALSE.
|
* the data-pattern found after the pattern or 0 when have-signal is #FALSE.
|
||||||
* </para>
|
* </para>
|
||||||
|
@ -106,24 +98,31 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideofilter.h>
|
||||||
#include "gstvideodetect.h"
|
#include "gstvideodetect.h"
|
||||||
|
|
||||||
#include <string.h>
|
GST_DEBUG_CATEGORY_STATIC (gst_video_detect_debug_category);
|
||||||
#include <math.h>
|
#define GST_CAT_DEFAULT gst_video_detect_debug_category
|
||||||
|
|
||||||
#include <gst/video/video.h>
|
/* prototypes */
|
||||||
|
|
||||||
/* GstVideoDetect signals and args */
|
|
||||||
|
|
||||||
#define DEFAULT_MESSAGE TRUE
|
static void gst_video_detect_set_property (GObject * object,
|
||||||
#define DEFAULT_PATTERN_WIDTH 4
|
guint property_id, const GValue * value, GParamSpec * pspec);
|
||||||
#define DEFAULT_PATTERN_HEIGHT 16
|
static void gst_video_detect_get_property (GObject * object,
|
||||||
#define DEFAULT_PATTERN_COUNT 4
|
guint property_id, GValue * value, GParamSpec * pspec);
|
||||||
#define DEFAULT_PATTERN_DATA_COUNT 5
|
static void gst_video_detect_dispose (GObject * object);
|
||||||
#define DEFAULT_PATTERN_CENTER 0.5
|
static void gst_video_detect_finalize (GObject * object);
|
||||||
#define DEFAULT_PATTERN_SENSITIVITY 0.3
|
|
||||||
#define DEFAULT_LEFT_OFFSET 0
|
static gboolean gst_video_detect_start (GstBaseTransform * trans);
|
||||||
#define DEFAULT_BOTTOM_OFFSET 0
|
static gboolean gst_video_detect_stop (GstBaseTransform * trans);
|
||||||
|
static gboolean gst_video_detect_set_info (GstVideoFilter * filter,
|
||||||
|
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||||
|
GstVideoInfo * out_info);
|
||||||
|
static GstFlowReturn gst_video_detect_transform_frame_ip (GstVideoFilter *
|
||||||
|
filter, GstVideoFrame * frame);
|
||||||
|
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -139,328 +138,62 @@ enum
|
||||||
PROP_BOTTOM_OFFSET
|
PROP_BOTTOM_OFFSET
|
||||||
};
|
};
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (video_detect_debug);
|
#define DEFAULT_MESSAGE TRUE
|
||||||
#define GST_CAT_DEFAULT video_detect_debug
|
#define DEFAULT_PATTERN_WIDTH 4
|
||||||
|
#define DEFAULT_PATTERN_HEIGHT 16
|
||||||
|
#define DEFAULT_PATTERN_COUNT 4
|
||||||
|
#define DEFAULT_PATTERN_DATA_COUNT 5
|
||||||
|
#define DEFAULT_PATTERN_CENTER 0.5
|
||||||
|
#define DEFAULT_PATTERN_SENSITIVITY 0.3
|
||||||
|
#define DEFAULT_LEFT_OFFSET 0
|
||||||
|
#define DEFAULT_BOTTOM_OFFSET 0
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_video_detect_src_template =
|
/* pad templates */
|
||||||
GST_STATIC_PAD_TEMPLATE ("src",
|
|
||||||
GST_PAD_SRC,
|
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV
|
|
||||||
("{ I420, YV12, Y41B, Y42B, Y444, YUY2, UYVY, AYUV, YVYU }"))
|
|
||||||
);
|
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_video_detect_sink_template =
|
#define VIDEO_CAPS \
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
GST_VIDEO_CAPS_MAKE( \
|
||||||
GST_PAD_SINK,
|
"{ I420, YV12, Y41B, Y42B, Y444, YUY2, UYVY, AYUV, YVYU }")
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV
|
|
||||||
("{ I420, YV12, Y41B, Y42B, Y444, YUY2, UYVY, AYUV, YVYU }"))
|
|
||||||
);
|
|
||||||
|
|
||||||
static GstVideoFilterClass *parent_class = NULL;
|
|
||||||
|
|
||||||
static gboolean
|
/* class initialization */
|
||||||
gst_video_detect_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
|
|
||||||
GstCaps * outcaps)
|
|
||||||
{
|
|
||||||
GstVideoDetect *vf;
|
|
||||||
GstStructure *in_s;
|
|
||||||
guint32 fourcc;
|
|
||||||
gboolean ret;
|
|
||||||
|
|
||||||
vf = GST_VIDEO_DETECT (btrans);
|
G_DEFINE_TYPE_WITH_CODE (GstVideoDetect, gst_video_detect,
|
||||||
|
GST_TYPE_VIDEO_FILTER,
|
||||||
in_s = gst_caps_get_structure (incaps, 0);
|
GST_DEBUG_CATEGORY_INIT (gst_video_detect_debug_category, "videodetect", 0,
|
||||||
|
"debug category for videodetect element"));
|
||||||
ret = gst_structure_get_int (in_s, "width", &vf->width);
|
|
||||||
ret &= gst_structure_get_int (in_s, "height", &vf->height);
|
|
||||||
ret &= gst_structure_get_fourcc (in_s, "format", &fourcc);
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
vf->format = gst_video_format_from_fourcc (fourcc);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_video_detect_post_message (GstVideoDetect * videodetect, GstBuffer * buffer,
|
gst_video_detect_class_init (GstVideoDetectClass * klass)
|
||||||
guint64 data)
|
|
||||||
{
|
{
|
||||||
GstBaseTransform *trans;
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
GstMessage *m;
|
GstBaseTransformClass *base_transform_class =
|
||||||
guint64 duration, timestamp, running_time, stream_time;
|
GST_BASE_TRANSFORM_CLASS (klass);
|
||||||
|
GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);
|
||||||
|
|
||||||
trans = GST_BASE_TRANSFORM_CAST (videodetect);
|
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||||
|
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
gst_caps_from_string (VIDEO_CAPS)));
|
||||||
|
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||||
|
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
gst_caps_from_string (VIDEO_CAPS)));
|
||||||
|
|
||||||
/* get timestamps */
|
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
|
||||||
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
"Video detecter", "Filter/Effect/Video",
|
||||||
duration = GST_BUFFER_DURATION (buffer);
|
|
||||||
running_time = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
|
|
||||||
timestamp);
|
|
||||||
stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
|
|
||||||
timestamp);
|
|
||||||
|
|
||||||
/* post message */
|
|
||||||
m = gst_message_new_element (GST_OBJECT_CAST (videodetect),
|
|
||||||
gst_structure_new ("GstVideoDetect",
|
|
||||||
"have-pattern", G_TYPE_BOOLEAN, videodetect->in_pattern,
|
|
||||||
"timestamp", G_TYPE_UINT64, timestamp,
|
|
||||||
"stream-time", G_TYPE_UINT64, stream_time,
|
|
||||||
"running-time", G_TYPE_UINT64, running_time,
|
|
||||||
"duration", G_TYPE_UINT64, duration,
|
|
||||||
"data-uint64", G_TYPE_UINT64, data,
|
|
||||||
"data", G_TYPE_UINT, (guint) MIN (data, G_MAXINT), NULL));
|
|
||||||
gst_element_post_message (GST_ELEMENT_CAST (videodetect), m);
|
|
||||||
}
|
|
||||||
|
|
||||||
static gdouble
|
|
||||||
gst_video_detect_calc_brightness (GstVideoDetect * videodetect, guint8 * data,
|
|
||||||
gint width, gint height, gint row_stride, gint pixel_stride)
|
|
||||||
{
|
|
||||||
gint i, j;
|
|
||||||
guint64 sum;
|
|
||||||
|
|
||||||
sum = 0;
|
|
||||||
for (i = 0; i < height; i++) {
|
|
||||||
for (j = 0; j < width; j++) {
|
|
||||||
sum += data[pixel_stride * j];
|
|
||||||
}
|
|
||||||
data += row_stride;
|
|
||||||
}
|
|
||||||
return sum / (255.0 * width * height);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_detect_yuv (GstVideoDetect * videodetect, GstBuffer * buffer)
|
|
||||||
{
|
|
||||||
GstVideoFormat format;
|
|
||||||
gdouble brightness;
|
|
||||||
gint i, pw, ph, row_stride, pixel_stride, offset;
|
|
||||||
gint width, height, req_width, req_height;
|
|
||||||
guint8 *d, *data;
|
|
||||||
guint64 pattern_data;
|
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (buffer);
|
|
||||||
|
|
||||||
format = videodetect->format;
|
|
||||||
width = videodetect->width;
|
|
||||||
height = videodetect->height;
|
|
||||||
|
|
||||||
pw = videodetect->pattern_width;
|
|
||||||
ph = videodetect->pattern_height;
|
|
||||||
row_stride = gst_video_format_get_row_stride (format, 0, width);
|
|
||||||
pixel_stride = gst_video_format_get_pixel_stride (format, 0);
|
|
||||||
offset = gst_video_format_get_component_offset (format, 0, width, height);
|
|
||||||
|
|
||||||
req_width =
|
|
||||||
(videodetect->pattern_count + videodetect->pattern_data_count) * pw +
|
|
||||||
videodetect->left_offset;
|
|
||||||
req_height = videodetect->bottom_offset + ph;
|
|
||||||
if (req_width > width || req_height > height) {
|
|
||||||
goto no_pattern;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* analyse the bottom left pixels */
|
|
||||||
for (i = 0; i < videodetect->pattern_count; i++) {
|
|
||||||
d = data + offset;
|
|
||||||
/* move to start of bottom left, adjust for offsets */
|
|
||||||
d += row_stride * (height - ph - videodetect->bottom_offset) +
|
|
||||||
pixel_stride * videodetect->left_offset;
|
|
||||||
/* move to i-th pattern */
|
|
||||||
d += pixel_stride * pw * i;
|
|
||||||
|
|
||||||
/* calc brightness of width * height box */
|
|
||||||
brightness = gst_video_detect_calc_brightness (videodetect, d, pw, ph,
|
|
||||||
row_stride, pixel_stride);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videodetect, "brightness %f", brightness);
|
|
||||||
|
|
||||||
if (i & 1) {
|
|
||||||
/* odd pixels must be white, all pixels darker than the center +
|
|
||||||
* sensitivity are considered wrong. */
|
|
||||||
if (brightness <
|
|
||||||
(videodetect->pattern_center + videodetect->pattern_sensitivity))
|
|
||||||
goto no_pattern;
|
|
||||||
} else {
|
|
||||||
/* even pixels must be black, pixels lighter than the center - sensitivity
|
|
||||||
* are considered wrong. */
|
|
||||||
if (brightness >
|
|
||||||
(videodetect->pattern_center - videodetect->pattern_sensitivity))
|
|
||||||
goto no_pattern;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
GST_DEBUG_OBJECT (videodetect, "found pattern");
|
|
||||||
|
|
||||||
pattern_data = 0;
|
|
||||||
|
|
||||||
/* get the data of the pattern */
|
|
||||||
for (i = 0; i < videodetect->pattern_data_count; i++) {
|
|
||||||
d = data + offset;
|
|
||||||
/* move to start of bottom left, adjust for offsets */
|
|
||||||
d += row_stride * (height - ph - videodetect->bottom_offset) +
|
|
||||||
pixel_stride * videodetect->left_offset;
|
|
||||||
/* move after the fixed pattern */
|
|
||||||
d += pixel_stride * (videodetect->pattern_count * pw);
|
|
||||||
/* move to i-th pattern data */
|
|
||||||
d += pixel_stride * pw * i;
|
|
||||||
|
|
||||||
/* calc brightness of width * height box */
|
|
||||||
brightness = gst_video_detect_calc_brightness (videodetect, d, pw, ph,
|
|
||||||
row_stride, pixel_stride);
|
|
||||||
/* update pattern, we just use the center to decide between black and white. */
|
|
||||||
pattern_data <<= 1;
|
|
||||||
if (brightness > videodetect->pattern_center)
|
|
||||||
pattern_data |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videodetect, "have data %" G_GUINT64_FORMAT, pattern_data);
|
|
||||||
|
|
||||||
videodetect->in_pattern = TRUE;
|
|
||||||
gst_video_detect_post_message (videodetect, buffer, pattern_data);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
no_pattern:
|
|
||||||
{
|
|
||||||
GST_DEBUG_OBJECT (videodetect, "no pattern found");
|
|
||||||
if (videodetect->in_pattern) {
|
|
||||||
videodetect->in_pattern = FALSE;
|
|
||||||
gst_video_detect_post_message (videodetect, buffer, 0);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_video_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
|
||||||
{
|
|
||||||
GstVideoDetect *videodetect;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
videodetect = GST_VIDEO_DETECT (trans);
|
|
||||||
|
|
||||||
gst_video_detect_yuv (videodetect, buf);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_detect_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstVideoDetect *videodetect;
|
|
||||||
|
|
||||||
videodetect = GST_VIDEO_DETECT (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_MESSAGE:
|
|
||||||
videodetect->message = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_WIDTH:
|
|
||||||
videodetect->pattern_width = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_HEIGHT:
|
|
||||||
videodetect->pattern_height = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_COUNT:
|
|
||||||
videodetect->pattern_count = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA_COUNT:
|
|
||||||
videodetect->pattern_data_count = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_CENTER:
|
|
||||||
videodetect->pattern_center = g_value_get_double (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_SENSITIVITY:
|
|
||||||
videodetect->pattern_sensitivity = g_value_get_double (value);
|
|
||||||
break;
|
|
||||||
case PROP_LEFT_OFFSET:
|
|
||||||
videodetect->left_offset = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_BOTTOM_OFFSET:
|
|
||||||
videodetect->bottom_offset = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_detect_get_property (GObject * object, guint prop_id, GValue * value,
|
|
||||||
GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstVideoDetect *videodetect;
|
|
||||||
|
|
||||||
videodetect = GST_VIDEO_DETECT (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_MESSAGE:
|
|
||||||
g_value_set_boolean (value, videodetect->message);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_WIDTH:
|
|
||||||
g_value_set_int (value, videodetect->pattern_width);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_HEIGHT:
|
|
||||||
g_value_set_int (value, videodetect->pattern_height);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_COUNT:
|
|
||||||
g_value_set_int (value, videodetect->pattern_count);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA_COUNT:
|
|
||||||
g_value_set_int (value, videodetect->pattern_data_count);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_CENTER:
|
|
||||||
g_value_set_double (value, videodetect->pattern_center);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_SENSITIVITY:
|
|
||||||
g_value_set_double (value, videodetect->pattern_sensitivity);
|
|
||||||
break;
|
|
||||||
case PROP_LEFT_OFFSET:
|
|
||||||
g_value_set_int (value, videodetect->left_offset);
|
|
||||||
break;
|
|
||||||
case PROP_BOTTOM_OFFSET:
|
|
||||||
g_value_set_int (value, videodetect->bottom_offset);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_detect_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (element_class, "Video detecter",
|
|
||||||
"Filter/Effect/Video",
|
|
||||||
"Detect patterns in a video signal", "Wim Taymans <wim@fluendo.com>");
|
"Detect patterns in a video signal", "Wim Taymans <wim@fluendo.com>");
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_video_detect_sink_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_video_detect_src_template));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_detect_class_init (gpointer klass, gpointer class_data)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
GstBaseTransformClass *trans_class;
|
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
|
||||||
trans_class = (GstBaseTransformClass *) klass;
|
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_video_detect_set_property;
|
gobject_class->set_property = gst_video_detect_set_property;
|
||||||
gobject_class->get_property = gst_video_detect_get_property;
|
gobject_class->get_property = gst_video_detect_get_property;
|
||||||
|
gobject_class->dispose = gst_video_detect_dispose;
|
||||||
|
gobject_class->finalize = gst_video_detect_finalize;
|
||||||
|
base_transform_class->start = GST_DEBUG_FUNCPTR (gst_video_detect_start);
|
||||||
|
base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_video_detect_stop);
|
||||||
|
video_filter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_detect_set_info);
|
||||||
|
video_filter_class->transform_frame_ip =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_video_detect_transform_frame_ip);
|
||||||
|
|
||||||
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MESSAGE,
|
g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_MESSAGE,
|
||||||
g_param_spec_boolean ("message", "Message",
|
g_param_spec_boolean ("message", "Message",
|
||||||
"Post statics messages",
|
"Post detected data as bus messages",
|
||||||
DEFAULT_MESSAGE,
|
DEFAULT_MESSAGE,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_WIDTH,
|
g_object_class_install_property (gobject_class, PROP_PATTERN_WIDTH,
|
||||||
|
@ -503,47 +236,304 @@ gst_video_detect_class_init (gpointer klass, gpointer class_data)
|
||||||
"The offset from the bottom border where the pattern starts", 0,
|
"The offset from the bottom border where the pattern starts", 0,
|
||||||
G_MAXINT, DEFAULT_BOTTOM_OFFSET,
|
G_MAXINT, DEFAULT_BOTTOM_OFFSET,
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_detect_set_caps);
|
|
||||||
trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_video_detect_transform_ip);
|
|
||||||
trans_class->passthrough_on_same_caps = TRUE;
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (video_detect_debug, "videodetect", 0,
|
|
||||||
"Video detect");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_video_detect_init (GTypeInstance * instance, gpointer g_class)
|
gst_video_detect_init (GstVideoDetect * videodetect)
|
||||||
{
|
{
|
||||||
GstVideoDetect *videodetect;
|
}
|
||||||
|
|
||||||
videodetect = GST_VIDEO_DETECT (instance);
|
void
|
||||||
|
gst_video_detect_set_property (GObject * object, guint property_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (object);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videodetect, "gst_video_detect_init");
|
GST_DEBUG_OBJECT (videodetect, "set_property");
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_MESSAGE:
|
||||||
|
videodetect->message = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_WIDTH:
|
||||||
|
videodetect->pattern_width = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_HEIGHT:
|
||||||
|
videodetect->pattern_height = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_COUNT:
|
||||||
|
videodetect->pattern_count = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_DATA_COUNT:
|
||||||
|
videodetect->pattern_data_count = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_CENTER:
|
||||||
|
videodetect->pattern_center = g_value_get_double (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_SENSITIVITY:
|
||||||
|
videodetect->pattern_sensitivity = g_value_get_double (value);
|
||||||
|
break;
|
||||||
|
case PROP_LEFT_OFFSET:
|
||||||
|
videodetect->left_offset = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_BOTTOM_OFFSET:
|
||||||
|
videodetect->bottom_offset = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_detect_get_property (GObject * object, guint property_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "get_property");
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_MESSAGE:
|
||||||
|
g_value_set_boolean (value, videodetect->message);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_WIDTH:
|
||||||
|
g_value_set_int (value, videodetect->pattern_width);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_HEIGHT:
|
||||||
|
g_value_set_int (value, videodetect->pattern_height);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_COUNT:
|
||||||
|
g_value_set_int (value, videodetect->pattern_count);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_DATA_COUNT:
|
||||||
|
g_value_set_int (value, videodetect->pattern_data_count);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_CENTER:
|
||||||
|
g_value_set_double (value, videodetect->pattern_center);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_SENSITIVITY:
|
||||||
|
g_value_set_double (value, videodetect->pattern_sensitivity);
|
||||||
|
break;
|
||||||
|
case PROP_LEFT_OFFSET:
|
||||||
|
g_value_set_int (value, videodetect->left_offset);
|
||||||
|
break;
|
||||||
|
case PROP_BOTTOM_OFFSET:
|
||||||
|
g_value_set_int (value, videodetect->bottom_offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_detect_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "dispose");
|
||||||
|
|
||||||
|
/* clean up as possible. may be called multiple times */
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_video_detect_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_detect_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "finalize");
|
||||||
|
|
||||||
|
/* clean up object here */
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_video_detect_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_video_detect_start (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (trans);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "start");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_video_detect_stop (GstBaseTransform * trans)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (trans);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "stop");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_video_detect_set_info (GstVideoFilter * filter, GstCaps * incaps,
|
||||||
|
GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
|
||||||
|
{
|
||||||
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (filter);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "set_info");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_detect_post_message (GstVideoDetect * videodetect, GstBuffer * buffer,
|
||||||
|
guint64 data)
|
||||||
|
{
|
||||||
|
GstBaseTransform *trans;
|
||||||
|
GstMessage *m;
|
||||||
|
guint64 duration, timestamp, running_time, stream_time;
|
||||||
|
|
||||||
|
trans = GST_BASE_TRANSFORM_CAST (videodetect);
|
||||||
|
|
||||||
|
/* get timestamps */
|
||||||
|
timestamp = GST_BUFFER_TIMESTAMP (buffer);
|
||||||
|
duration = GST_BUFFER_DURATION (buffer);
|
||||||
|
running_time = gst_segment_to_running_time (&trans->segment, GST_FORMAT_TIME,
|
||||||
|
timestamp);
|
||||||
|
stream_time = gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME,
|
||||||
|
timestamp);
|
||||||
|
|
||||||
|
/* post message */
|
||||||
|
m = gst_message_new_element (GST_OBJECT_CAST (videodetect),
|
||||||
|
gst_structure_new ("GstVideoDetect",
|
||||||
|
"have-pattern", G_TYPE_BOOLEAN, videodetect->in_pattern,
|
||||||
|
"timestamp", G_TYPE_UINT64, timestamp,
|
||||||
|
"stream-time", G_TYPE_UINT64, stream_time,
|
||||||
|
"running-time", G_TYPE_UINT64, running_time,
|
||||||
|
"duration", G_TYPE_UINT64, duration,
|
||||||
|
"data", G_TYPE_UINT64, data, NULL));
|
||||||
|
gst_element_post_message (GST_ELEMENT_CAST (videodetect), m);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gdouble
|
||||||
|
gst_video_detect_calc_brightness (GstVideoDetect * videodetect, guint8 * data,
|
||||||
|
gint width, gint height, gint row_stride, gint pixel_stride)
|
||||||
|
{
|
||||||
|
gint i, j;
|
||||||
|
guint64 sum;
|
||||||
|
|
||||||
|
sum = 0;
|
||||||
|
for (i = 0; i < height; i++) {
|
||||||
|
for (j = 0; j < width; j++) {
|
||||||
|
sum += data[pixel_stride * j];
|
||||||
|
}
|
||||||
|
data += row_stride;
|
||||||
|
}
|
||||||
|
return sum / (255.0 * width * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_detect_yuv (GstVideoDetect * videodetect, GstVideoFrame * frame)
|
||||||
|
{
|
||||||
|
gdouble brightness;
|
||||||
|
gint i, pw, ph, row_stride, pixel_stride;
|
||||||
|
gint width, height, req_width, req_height;
|
||||||
|
guint8 *d;
|
||||||
|
guint64 pattern_data;
|
||||||
|
|
||||||
|
width = frame->info.width;
|
||||||
|
height = frame->info.height;
|
||||||
|
|
||||||
|
pw = videodetect->pattern_width;
|
||||||
|
ph = videodetect->pattern_height;
|
||||||
|
row_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
|
||||||
|
pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
|
||||||
|
|
||||||
|
req_width =
|
||||||
|
(videodetect->pattern_count + videodetect->pattern_data_count) * pw +
|
||||||
|
videodetect->left_offset;
|
||||||
|
req_height = videodetect->bottom_offset + ph;
|
||||||
|
if (req_width > width || req_height > height) {
|
||||||
|
goto no_pattern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* analyse the bottom left pixels */
|
||||||
|
for (i = 0; i < videodetect->pattern_count; i++) {
|
||||||
|
d = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
|
||||||
|
/* move to start of bottom left, adjust for offsets */
|
||||||
|
d += row_stride * (height - ph - videodetect->bottom_offset) +
|
||||||
|
pixel_stride * videodetect->left_offset;
|
||||||
|
/* move to i-th pattern */
|
||||||
|
d += pixel_stride * pw * i;
|
||||||
|
|
||||||
|
/* calc brightness of width * height box */
|
||||||
|
brightness = gst_video_detect_calc_brightness (videodetect, d, pw, ph,
|
||||||
|
row_stride, pixel_stride);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "brightness %f", brightness);
|
||||||
|
|
||||||
|
if (i & 1) {
|
||||||
|
/* odd pixels must be white, all pixels darker than the center +
|
||||||
|
* sensitivity are considered wrong. */
|
||||||
|
if (brightness <
|
||||||
|
(videodetect->pattern_center + videodetect->pattern_sensitivity))
|
||||||
|
goto no_pattern;
|
||||||
|
} else {
|
||||||
|
/* even pixels must be black, pixels lighter than the center - sensitivity
|
||||||
|
* are considered wrong. */
|
||||||
|
if (brightness >
|
||||||
|
(videodetect->pattern_center - videodetect->pattern_sensitivity))
|
||||||
|
goto no_pattern;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "found pattern");
|
||||||
|
|
||||||
|
pattern_data = 0;
|
||||||
|
|
||||||
|
/* get the data of the pattern */
|
||||||
|
for (i = 0; i < videodetect->pattern_data_count; i++) {
|
||||||
|
d = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
|
||||||
|
/* move to start of bottom left, adjust for offsets */
|
||||||
|
d += row_stride * (height - ph - videodetect->bottom_offset) +
|
||||||
|
pixel_stride * videodetect->left_offset;
|
||||||
|
/* move after the fixed pattern */
|
||||||
|
d += pixel_stride * (videodetect->pattern_count * pw);
|
||||||
|
/* move to i-th pattern data */
|
||||||
|
d += pixel_stride * pw * i;
|
||||||
|
|
||||||
|
/* calc brightness of width * height box */
|
||||||
|
brightness = gst_video_detect_calc_brightness (videodetect, d, pw, ph,
|
||||||
|
row_stride, pixel_stride);
|
||||||
|
/* update pattern, we just use the center to decide between black and white. */
|
||||||
|
pattern_data <<= 1;
|
||||||
|
if (brightness > videodetect->pattern_center)
|
||||||
|
pattern_data |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "have data %" G_GUINT64_FORMAT, pattern_data);
|
||||||
|
|
||||||
|
videodetect->in_pattern = TRUE;
|
||||||
|
gst_video_detect_post_message (videodetect, frame->buffer, pattern_data);
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
no_pattern:
|
||||||
|
{
|
||||||
|
GST_DEBUG_OBJECT (videodetect, "no pattern found");
|
||||||
|
if (videodetect->in_pattern) {
|
||||||
videodetect->in_pattern = FALSE;
|
videodetect->in_pattern = FALSE;
|
||||||
|
gst_video_detect_post_message (videodetect, frame->buffer, 0);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GType
|
static GstFlowReturn
|
||||||
gst_video_detect_get_type (void)
|
gst_video_detect_transform_frame_ip (GstVideoFilter * filter,
|
||||||
|
GstVideoFrame * frame)
|
||||||
{
|
{
|
||||||
static GType video_detect_type = 0;
|
GstVideoDetect *videodetect = GST_VIDEO_DETECT (filter);
|
||||||
|
|
||||||
if (!video_detect_type) {
|
GST_DEBUG_OBJECT (videodetect, "transform_frame_ip");
|
||||||
static const GTypeInfo video_detect_info = {
|
|
||||||
sizeof (GstVideoDetectClass),
|
|
||||||
gst_video_detect_base_init,
|
|
||||||
NULL,
|
|
||||||
gst_video_detect_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstVideoDetect),
|
|
||||||
0,
|
|
||||||
gst_video_detect_init,
|
|
||||||
};
|
|
||||||
|
|
||||||
video_detect_type = g_type_register_static (GST_TYPE_VIDEO_FILTER,
|
gst_video_detect_yuv (videodetect, frame);
|
||||||
"GstVideoDetect", &video_detect_info, 0);
|
|
||||||
}
|
return GST_FLOW_OK;
|
||||||
return video_detect_type;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,38 +17,26 @@
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __GST_VIDEO_DETECT_H__
|
#ifndef _GST_VIDEO_DETECT_H_
|
||||||
#define __GST_VIDEO_DETECT_H__
|
#define _GST_VIDEO_DETECT_H_
|
||||||
|
|
||||||
#include <gst/video/gstvideofilter.h>
|
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideofilter.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_TYPE_VIDEO_DETECT \
|
#define GST_TYPE_VIDEO_DETECT (gst_video_detect_get_type())
|
||||||
(gst_video_detect_get_type())
|
#define GST_VIDEO_DETECT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_DETECT,GstVideoDetect))
|
||||||
#define GST_VIDEO_DETECT(obj) \
|
#define GST_VIDEO_DETECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_DETECT,GstVideoDetectClass))
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_DETECT,GstVideoDetect))
|
#define GST_IS_VIDEO_DETECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_DETECT))
|
||||||
#define GST_VIDEO_DETECT_CLASS(klass) \
|
#define GST_IS_VIDEO_DETECT_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_DETECT))
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_DETECT,GstVideoDetectClass))
|
|
||||||
#define GST_IS_VIDEO_DETECT(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_DETECT))
|
|
||||||
#define GST_IS_VIDEO_DETECT_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_DETECT))
|
|
||||||
|
|
||||||
typedef struct _GstVideoDetect GstVideoDetect;
|
typedef struct _GstVideoDetect GstVideoDetect;
|
||||||
typedef struct _GstVideoDetectClass GstVideoDetectClass;
|
typedef struct _GstVideoDetectClass GstVideoDetectClass;
|
||||||
|
|
||||||
/**
|
struct _GstVideoDetect
|
||||||
* GstVideoDetect:
|
{
|
||||||
*
|
GstVideoFilter base_videodetect;
|
||||||
* Opaque datastructure.
|
|
||||||
*/
|
|
||||||
struct _GstVideoDetect {
|
|
||||||
GstVideoFilter videofilter;
|
|
||||||
|
|
||||||
gint width, height;
|
|
||||||
GstVideoFormat format;
|
|
||||||
|
|
||||||
gboolean message;
|
gboolean message;
|
||||||
gint pattern_width;
|
gint pattern_width;
|
||||||
|
@ -63,12 +51,13 @@ struct _GstVideoDetect {
|
||||||
gboolean in_pattern;
|
gboolean in_pattern;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVideoDetectClass {
|
struct _GstVideoDetectClass
|
||||||
GstVideoFilterClass parent_class;
|
{
|
||||||
|
GstVideoFilterClass base_videodetect_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_video_detect_get_type (void);
|
GType gst_video_detect_get_type (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_VIDEO_DETECT_H__ */
|
#endif
|
||||||
|
|
|
@ -13,10 +13,9 @@
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Library General Public
|
* You should have received a copy of the GNU Library General Public
|
||||||
* License along with this library; if not, write to the
|
* License along with this library; if not, write to the
|
||||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
* Free Software Foundation, Inc., 51 Franklin Street, Suite 500,
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1335, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:element-videomark
|
* SECTION:element-videomark
|
||||||
* @see_also: #GstVideoDetect
|
* @see_also: #GstVideoDetect
|
||||||
|
@ -48,14 +47,44 @@
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <gst/gst.h>
|
||||||
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideofilter.h>
|
||||||
#include "gstvideomark.h"
|
#include "gstvideomark.h"
|
||||||
|
|
||||||
#include <string.h>
|
GST_DEBUG_CATEGORY_STATIC (gst_video_mark_debug_category);
|
||||||
#include <math.h>
|
#define GST_CAT_DEFAULT gst_video_mark_debug_category
|
||||||
|
|
||||||
#include <gst/video/video.h>
|
/* prototypes */
|
||||||
|
|
||||||
/* GstVideoMark signals and args */
|
|
||||||
|
static void gst_video_mark_set_property (GObject * object,
|
||||||
|
guint property_id, const GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_video_mark_get_property (GObject * object,
|
||||||
|
guint property_id, GValue * value, GParamSpec * pspec);
|
||||||
|
static void gst_video_mark_dispose (GObject * object);
|
||||||
|
static void gst_video_mark_finalize (GObject * object);
|
||||||
|
|
||||||
|
static gboolean gst_video_mark_start (GstBaseTransform * trans);
|
||||||
|
static gboolean gst_video_mark_stop (GstBaseTransform * trans);
|
||||||
|
static gboolean gst_video_mark_set_info (GstVideoFilter * filter,
|
||||||
|
GstCaps * incaps, GstVideoInfo * in_info, GstCaps * outcaps,
|
||||||
|
GstVideoInfo * out_info);
|
||||||
|
static GstFlowReturn gst_video_mark_transform_frame_ip (GstVideoFilter * filter,
|
||||||
|
GstVideoFrame * frame);
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
PROP_0,
|
||||||
|
PROP_PATTERN_WIDTH,
|
||||||
|
PROP_PATTERN_HEIGHT,
|
||||||
|
PROP_PATTERN_COUNT,
|
||||||
|
PROP_PATTERN_DATA_COUNT,
|
||||||
|
PROP_PATTERN_DATA,
|
||||||
|
PROP_ENABLED,
|
||||||
|
PROP_LEFT_OFFSET,
|
||||||
|
PROP_BOTTOM_OFFSET
|
||||||
|
};
|
||||||
|
|
||||||
#define DEFAULT_PATTERN_WIDTH 4
|
#define DEFAULT_PATTERN_WIDTH 4
|
||||||
#define DEFAULT_PATTERN_HEIGHT 16
|
#define DEFAULT_PATTERN_HEIGHT 16
|
||||||
|
@ -66,62 +95,227 @@
|
||||||
#define DEFAULT_LEFT_OFFSET 0
|
#define DEFAULT_LEFT_OFFSET 0
|
||||||
#define DEFAULT_BOTTOM_OFFSET 0
|
#define DEFAULT_BOTTOM_OFFSET 0
|
||||||
|
|
||||||
enum
|
/* pad templates */
|
||||||
|
|
||||||
|
#define VIDEO_CAPS \
|
||||||
|
GST_VIDEO_CAPS_MAKE( \
|
||||||
|
"{ I420, YV12, Y41B, Y42B, Y444, YUY2, UYVY, AYUV, YVYU }")
|
||||||
|
|
||||||
|
|
||||||
|
/* class initialization */
|
||||||
|
|
||||||
|
G_DEFINE_TYPE_WITH_CODE (GstVideoMark, gst_video_mark, GST_TYPE_VIDEO_FILTER,
|
||||||
|
GST_DEBUG_CATEGORY_INIT (gst_video_mark_debug_category, "videomark", 0,
|
||||||
|
"debug category for videomark element"));
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_mark_class_init (GstVideoMarkClass * klass)
|
||||||
{
|
{
|
||||||
PROP_0,
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||||
PROP_PATTERN_WIDTH,
|
GstBaseTransformClass *base_transform_class =
|
||||||
PROP_PATTERN_HEIGHT,
|
GST_BASE_TRANSFORM_CLASS (klass);
|
||||||
PROP_PATTERN_COUNT,
|
GstVideoFilterClass *video_filter_class = GST_VIDEO_FILTER_CLASS (klass);
|
||||||
PROP_PATTERN_DATA_COUNT,
|
|
||||||
PROP_PATTERN_DATA,
|
|
||||||
PROP_PATTERN_DATA_64,
|
|
||||||
PROP_ENABLED,
|
|
||||||
PROP_LEFT_OFFSET,
|
|
||||||
PROP_BOTTOM_OFFSET
|
|
||||||
};
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_STATIC (video_mark_debug);
|
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||||
#define GST_CAT_DEFAULT video_mark_debug
|
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
|
||||||
|
gst_caps_from_string (VIDEO_CAPS)));
|
||||||
|
gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass),
|
||||||
|
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
|
||||||
|
gst_caps_from_string (VIDEO_CAPS)));
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_video_mark_src_template =
|
gst_element_class_set_static_metadata (GST_ELEMENT_CLASS (klass),
|
||||||
GST_STATIC_PAD_TEMPLATE ("src",
|
"Video marker", "Filter/Effect/Video",
|
||||||
GST_PAD_SRC,
|
"Marks a video signal with a pattern", "Wim Taymans <wim@fluendo.com>");
|
||||||
GST_PAD_ALWAYS,
|
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV
|
|
||||||
("{ I420, YV12, Y41B, Y42B, Y444, YUY2, UYVY, AYUV, YVYU }"))
|
|
||||||
);
|
|
||||||
|
|
||||||
static GstStaticPadTemplate gst_video_mark_sink_template =
|
gobject_class->set_property = gst_video_mark_set_property;
|
||||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
gobject_class->get_property = gst_video_mark_get_property;
|
||||||
GST_PAD_SINK,
|
gobject_class->dispose = gst_video_mark_dispose;
|
||||||
GST_PAD_ALWAYS,
|
gobject_class->finalize = gst_video_mark_finalize;
|
||||||
GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV
|
base_transform_class->start = GST_DEBUG_FUNCPTR (gst_video_mark_start);
|
||||||
("{ I420, YV12, Y41B, Y42B, Y444, YUY2, UYVY, AYUV, YVYU }"))
|
base_transform_class->stop = GST_DEBUG_FUNCPTR (gst_video_mark_stop);
|
||||||
);
|
video_filter_class->set_info = GST_DEBUG_FUNCPTR (gst_video_mark_set_info);
|
||||||
|
video_filter_class->transform_frame_ip =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_video_mark_transform_frame_ip);
|
||||||
|
|
||||||
static GstVideoFilterClass *parent_class = NULL;
|
g_object_class_install_property (gobject_class, PROP_PATTERN_WIDTH,
|
||||||
|
g_param_spec_int ("pattern-width", "Pattern width",
|
||||||
|
"The width of the pattern markers", 1, G_MAXINT,
|
||||||
|
DEFAULT_PATTERN_WIDTH,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PATTERN_HEIGHT,
|
||||||
|
g_param_spec_int ("pattern-height", "Pattern height",
|
||||||
|
"The height of the pattern markers", 1, G_MAXINT,
|
||||||
|
DEFAULT_PATTERN_HEIGHT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PATTERN_COUNT,
|
||||||
|
g_param_spec_int ("pattern-count", "Pattern count",
|
||||||
|
"The number of pattern markers", 0, G_MAXINT,
|
||||||
|
DEFAULT_PATTERN_COUNT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PATTERN_DATA_COUNT,
|
||||||
|
g_param_spec_int ("pattern-data-count", "Pattern data count",
|
||||||
|
"The number of extra data pattern markers", 0, 64,
|
||||||
|
DEFAULT_PATTERN_DATA_COUNT,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_PATTERN_DATA,
|
||||||
|
g_param_spec_uint64 ("pattern-data", "Pattern data",
|
||||||
|
"The extra data pattern markers", 0, G_MAXUINT64,
|
||||||
|
DEFAULT_PATTERN_DATA,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_ENABLED,
|
||||||
|
g_param_spec_boolean ("enabled", "Enabled",
|
||||||
|
"Enable or disable the filter",
|
||||||
|
DEFAULT_ENABLED,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_LEFT_OFFSET,
|
||||||
|
g_param_spec_int ("left-offset", "Left Offset",
|
||||||
|
"The offset from the left border where the pattern starts", 0,
|
||||||
|
G_MAXINT, DEFAULT_LEFT_OFFSET,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_BOTTOM_OFFSET,
|
||||||
|
g_param_spec_int ("bottom-offset", "Bottom Offset",
|
||||||
|
"The offset from the bottom border where the pattern starts", 0,
|
||||||
|
G_MAXINT, DEFAULT_BOTTOM_OFFSET,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_video_mark_init (GstVideoMark * videomark)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_mark_set_property (GObject * object, guint property_id,
|
||||||
|
const GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videomark, "set_property");
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_PATTERN_WIDTH:
|
||||||
|
videomark->pattern_width = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_HEIGHT:
|
||||||
|
videomark->pattern_height = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_COUNT:
|
||||||
|
videomark->pattern_count = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_DATA_COUNT:
|
||||||
|
videomark->pattern_data_count = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_DATA:
|
||||||
|
videomark->pattern_data = g_value_get_uint64 (value);
|
||||||
|
break;
|
||||||
|
case PROP_ENABLED:
|
||||||
|
videomark->enabled = g_value_get_boolean (value);
|
||||||
|
break;
|
||||||
|
case PROP_LEFT_OFFSET:
|
||||||
|
videomark->left_offset = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
case PROP_BOTTOM_OFFSET:
|
||||||
|
videomark->bottom_offset = g_value_get_int (value);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_mark_get_property (GObject * object, guint property_id,
|
||||||
|
GValue * value, GParamSpec * pspec)
|
||||||
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videomark, "get_property");
|
||||||
|
|
||||||
|
switch (property_id) {
|
||||||
|
case PROP_PATTERN_WIDTH:
|
||||||
|
g_value_set_int (value, videomark->pattern_width);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_HEIGHT:
|
||||||
|
g_value_set_int (value, videomark->pattern_height);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_COUNT:
|
||||||
|
g_value_set_int (value, videomark->pattern_count);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_DATA_COUNT:
|
||||||
|
g_value_set_int (value, videomark->pattern_data_count);
|
||||||
|
break;
|
||||||
|
case PROP_PATTERN_DATA:
|
||||||
|
g_value_set_uint64 (value, videomark->pattern_data);
|
||||||
|
break;
|
||||||
|
case PROP_ENABLED:
|
||||||
|
g_value_set_boolean (value, videomark->enabled);
|
||||||
|
break;
|
||||||
|
case PROP_LEFT_OFFSET:
|
||||||
|
g_value_set_int (value, videomark->left_offset);
|
||||||
|
break;
|
||||||
|
case PROP_BOTTOM_OFFSET:
|
||||||
|
g_value_set_int (value, videomark->bottom_offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_mark_dispose (GObject * object)
|
||||||
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videomark, "dispose");
|
||||||
|
|
||||||
|
/* clean up as possible. may be called multiple times */
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_video_mark_parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gst_video_mark_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (object);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videomark, "finalize");
|
||||||
|
|
||||||
|
/* clean up object here */
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (gst_video_mark_parent_class)->finalize (object);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_video_mark_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
|
gst_video_mark_start (GstBaseTransform * trans)
|
||||||
GstCaps * outcaps)
|
|
||||||
{
|
{
|
||||||
GstVideoMark *vf;
|
GstVideoMark *videomark = GST_VIDEO_MARK (trans);
|
||||||
GstStructure *in_s;
|
|
||||||
guint32 fourcc;
|
|
||||||
gboolean ret;
|
|
||||||
|
|
||||||
vf = GST_VIDEO_MARK (btrans);
|
GST_DEBUG_OBJECT (videomark, "start");
|
||||||
|
|
||||||
in_s = gst_caps_get_structure (incaps, 0);
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
ret = gst_structure_get_int (in_s, "width", &vf->width);
|
static gboolean
|
||||||
ret &= gst_structure_get_int (in_s, "height", &vf->height);
|
gst_video_mark_stop (GstBaseTransform * trans)
|
||||||
ret &= gst_structure_get_fourcc (in_s, "format", &fourcc);
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (trans);
|
||||||
|
|
||||||
if (ret)
|
GST_DEBUG_OBJECT (videomark, "stop");
|
||||||
vf->format = gst_video_format_from_fourcc (fourcc);
|
|
||||||
|
|
||||||
return ret;
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_video_mark_set_info (GstVideoFilter * filter, GstCaps * incaps,
|
||||||
|
GstVideoInfo * in_info, GstCaps * outcaps, GstVideoInfo * out_info)
|
||||||
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (filter);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videomark, "set_info");
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -139,26 +333,21 @@ gst_video_mark_draw_box (GstVideoMark * videomark, guint8 * data,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_video_mark_yuv (GstVideoMark * videomark, GstBuffer * buffer)
|
gst_video_mark_yuv (GstVideoMark * videomark, GstVideoFrame * frame)
|
||||||
{
|
{
|
||||||
GstVideoFormat format;
|
gint i, pw, ph, row_stride, pixel_stride;
|
||||||
gint i, pw, ph, row_stride, pixel_stride, offset;
|
|
||||||
gint width, height, req_width, req_height;
|
gint width, height, req_width, req_height;
|
||||||
guint8 *d, *data;
|
guint8 *d;
|
||||||
guint64 pattern_shift;
|
guint64 pattern_shift;
|
||||||
guint8 color;
|
guint8 color;
|
||||||
|
|
||||||
data = GST_BUFFER_DATA (buffer);
|
width = frame->info.width;
|
||||||
|
height = frame->info.height;
|
||||||
format = videomark->format;
|
|
||||||
width = videomark->width;
|
|
||||||
height = videomark->height;
|
|
||||||
|
|
||||||
pw = videomark->pattern_width;
|
pw = videomark->pattern_width;
|
||||||
ph = videomark->pattern_height;
|
ph = videomark->pattern_height;
|
||||||
row_stride = gst_video_format_get_row_stride (format, 0, width);
|
row_stride = GST_VIDEO_FRAME_COMP_STRIDE (frame, 0);
|
||||||
pixel_stride = gst_video_format_get_pixel_stride (format, 0);
|
pixel_stride = GST_VIDEO_FRAME_COMP_PSTRIDE (frame, 0);
|
||||||
offset = gst_video_format_get_component_offset (format, 0, width, height);
|
|
||||||
|
|
||||||
req_width =
|
req_width =
|
||||||
(videomark->pattern_count + videomark->pattern_data_count) * pw +
|
(videomark->pattern_count + videomark->pattern_data_count) * pw +
|
||||||
|
@ -173,7 +362,7 @@ gst_video_mark_yuv (GstVideoMark * videomark, GstBuffer * buffer)
|
||||||
|
|
||||||
/* draw the bottom left pixels */
|
/* draw the bottom left pixels */
|
||||||
for (i = 0; i < videomark->pattern_count; i++) {
|
for (i = 0; i < videomark->pattern_count; i++) {
|
||||||
d = data + offset;
|
d = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
|
||||||
/* move to start of bottom left */
|
/* move to start of bottom left */
|
||||||
d += row_stride * (height - ph - videomark->bottom_offset) +
|
d += row_stride * (height - ph - videomark->bottom_offset) +
|
||||||
pixel_stride * videomark->left_offset;
|
pixel_stride * videomark->left_offset;
|
||||||
|
@ -195,7 +384,7 @@ gst_video_mark_yuv (GstVideoMark * videomark, GstBuffer * buffer)
|
||||||
|
|
||||||
/* get the data of the pattern */
|
/* get the data of the pattern */
|
||||||
for (i = 0; i < videomark->pattern_data_count; i++) {
|
for (i = 0; i < videomark->pattern_data_count; i++) {
|
||||||
d = data + offset;
|
d = GST_VIDEO_FRAME_COMP_DATA (frame, 0);
|
||||||
/* move to start of bottom left, adjust for offsets */
|
/* move to start of bottom left, adjust for offsets */
|
||||||
d += row_stride * (height - ph - videomark->bottom_offset) +
|
d += row_stride * (height - ph - videomark->bottom_offset) +
|
||||||
pixel_stride * videomark->left_offset;
|
pixel_stride * videomark->left_offset;
|
||||||
|
@ -218,214 +407,17 @@ gst_video_mark_yuv (GstVideoMark * videomark, GstBuffer * buffer)
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
|
||||||
gst_video_mark_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
|
|
||||||
{
|
|
||||||
GstVideoMark *videomark;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
|
||||||
|
|
||||||
videomark = GST_VIDEO_MARK (trans);
|
static GstFlowReturn
|
||||||
|
gst_video_mark_transform_frame_ip (GstVideoFilter * filter,
|
||||||
|
GstVideoFrame * frame)
|
||||||
|
{
|
||||||
|
GstVideoMark *videomark = GST_VIDEO_MARK (filter);
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (videomark, "transform_frame_ip");
|
||||||
|
|
||||||
if (videomark->enabled)
|
if (videomark->enabled)
|
||||||
return gst_video_mark_yuv (videomark, buf);
|
return gst_video_mark_yuv (videomark, frame);
|
||||||
|
|
||||||
return ret;
|
return GST_FLOW_OK;
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_mark_set_property (GObject * object, guint prop_id,
|
|
||||||
const GValue * value, GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstVideoMark *videomark;
|
|
||||||
|
|
||||||
videomark = GST_VIDEO_MARK (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_PATTERN_WIDTH:
|
|
||||||
videomark->pattern_width = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_HEIGHT:
|
|
||||||
videomark->pattern_height = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_COUNT:
|
|
||||||
videomark->pattern_count = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA_COUNT:
|
|
||||||
videomark->pattern_data_count = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA_64:
|
|
||||||
videomark->pattern_data = g_value_get_uint64 (value);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA:
|
|
||||||
videomark->pattern_data = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_ENABLED:
|
|
||||||
videomark->enabled = g_value_get_boolean (value);
|
|
||||||
break;
|
|
||||||
case PROP_LEFT_OFFSET:
|
|
||||||
videomark->left_offset = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
case PROP_BOTTOM_OFFSET:
|
|
||||||
videomark->bottom_offset = g_value_get_int (value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_mark_get_property (GObject * object, guint prop_id, GValue * value,
|
|
||||||
GParamSpec * pspec)
|
|
||||||
{
|
|
||||||
GstVideoMark *videomark;
|
|
||||||
|
|
||||||
videomark = GST_VIDEO_MARK (object);
|
|
||||||
|
|
||||||
switch (prop_id) {
|
|
||||||
case PROP_PATTERN_WIDTH:
|
|
||||||
g_value_set_int (value, videomark->pattern_width);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_HEIGHT:
|
|
||||||
g_value_set_int (value, videomark->pattern_height);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_COUNT:
|
|
||||||
g_value_set_int (value, videomark->pattern_count);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA_COUNT:
|
|
||||||
g_value_set_int (value, videomark->pattern_data_count);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA_64:
|
|
||||||
g_value_set_uint64 (value, videomark->pattern_data);
|
|
||||||
break;
|
|
||||||
case PROP_PATTERN_DATA:
|
|
||||||
g_value_set_int (value, MIN (videomark->pattern_data, G_MAXINT));
|
|
||||||
break;
|
|
||||||
case PROP_ENABLED:
|
|
||||||
g_value_set_boolean (value, videomark->enabled);
|
|
||||||
break;
|
|
||||||
case PROP_LEFT_OFFSET:
|
|
||||||
g_value_set_int (value, videomark->left_offset);
|
|
||||||
break;
|
|
||||||
case PROP_BOTTOM_OFFSET:
|
|
||||||
g_value_set_int (value, videomark->bottom_offset);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_mark_base_init (gpointer g_class)
|
|
||||||
{
|
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
||||||
|
|
||||||
gst_element_class_set_static_metadata (element_class, "Video marker",
|
|
||||||
"Filter/Effect/Video",
|
|
||||||
"Marks a video signal with a pattern", "Wim Taymans <wim@fluendo.com>");
|
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_video_mark_sink_template));
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
|
||||||
gst_static_pad_template_get (&gst_video_mark_src_template));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_mark_class_init (gpointer klass, gpointer class_data)
|
|
||||||
{
|
|
||||||
GObjectClass *gobject_class;
|
|
||||||
GstBaseTransformClass *trans_class;
|
|
||||||
|
|
||||||
gobject_class = (GObjectClass *) klass;
|
|
||||||
trans_class = (GstBaseTransformClass *) klass;
|
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
|
||||||
|
|
||||||
gobject_class->set_property = gst_video_mark_set_property;
|
|
||||||
gobject_class->get_property = gst_video_mark_get_property;
|
|
||||||
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_WIDTH,
|
|
||||||
g_param_spec_int ("pattern-width", "Pattern width",
|
|
||||||
"The width of the pattern markers", 1, G_MAXINT,
|
|
||||||
DEFAULT_PATTERN_WIDTH,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_HEIGHT,
|
|
||||||
g_param_spec_int ("pattern-height", "Pattern height",
|
|
||||||
"The height of the pattern markers", 1, G_MAXINT,
|
|
||||||
DEFAULT_PATTERN_HEIGHT,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_COUNT,
|
|
||||||
g_param_spec_int ("pattern-count", "Pattern count",
|
|
||||||
"The number of pattern markers", 0, G_MAXINT,
|
|
||||||
DEFAULT_PATTERN_COUNT,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_DATA_COUNT,
|
|
||||||
g_param_spec_int ("pattern-data-count", "Pattern data count",
|
|
||||||
"The number of extra data pattern markers", 0, 64,
|
|
||||||
DEFAULT_PATTERN_DATA_COUNT,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_DATA_64,
|
|
||||||
g_param_spec_uint64 ("pattern-data-uint64", "Pattern data",
|
|
||||||
"The extra data pattern markers", 0, G_MAXUINT64,
|
|
||||||
DEFAULT_PATTERN_DATA,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_PATTERN_DATA,
|
|
||||||
g_param_spec_int ("pattern-data", "Pattern data",
|
|
||||||
"The extra data pattern markers", 0, G_MAXINT,
|
|
||||||
DEFAULT_PATTERN_DATA, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_ENABLED,
|
|
||||||
g_param_spec_boolean ("enabled", "Enabled",
|
|
||||||
"Enable or disable the filter",
|
|
||||||
DEFAULT_ENABLED,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_LEFT_OFFSET,
|
|
||||||
g_param_spec_int ("left-offset", "Left Offset",
|
|
||||||
"The offset from the left border where the pattern starts", 0,
|
|
||||||
G_MAXINT, DEFAULT_LEFT_OFFSET,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
g_object_class_install_property (gobject_class, PROP_BOTTOM_OFFSET,
|
|
||||||
g_param_spec_int ("bottom-offset", "Bottom Offset",
|
|
||||||
"The offset from the bottom border where the pattern starts", 0,
|
|
||||||
G_MAXINT, DEFAULT_BOTTOM_OFFSET,
|
|
||||||
G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
|
|
||||||
|
|
||||||
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_video_mark_set_caps);
|
|
||||||
trans_class->transform_ip = GST_DEBUG_FUNCPTR (gst_video_mark_transform_ip);
|
|
||||||
|
|
||||||
GST_DEBUG_CATEGORY_INIT (video_mark_debug, "videomark", 0, "Video mark");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gst_video_mark_init (GTypeInstance * instance, gpointer g_class)
|
|
||||||
{
|
|
||||||
GstVideoMark *videomark;
|
|
||||||
|
|
||||||
videomark = GST_VIDEO_MARK (instance);
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (videomark, "gst_video_mark_init");
|
|
||||||
}
|
|
||||||
|
|
||||||
GType
|
|
||||||
gst_video_mark_get_type (void)
|
|
||||||
{
|
|
||||||
static GType video_mark_type = 0;
|
|
||||||
|
|
||||||
if (!video_mark_type) {
|
|
||||||
static const GTypeInfo video_mark_info = {
|
|
||||||
sizeof (GstVideoMarkClass),
|
|
||||||
gst_video_mark_base_init,
|
|
||||||
NULL,
|
|
||||||
gst_video_mark_class_init,
|
|
||||||
NULL,
|
|
||||||
NULL,
|
|
||||||
sizeof (GstVideoMark),
|
|
||||||
0,
|
|
||||||
gst_video_mark_init,
|
|
||||||
};
|
|
||||||
|
|
||||||
video_mark_type = g_type_register_static (GST_TYPE_VIDEO_FILTER,
|
|
||||||
"GstVideoMark", &video_mark_info, 0);
|
|
||||||
}
|
|
||||||
return video_mark_type;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,39 +17,28 @@
|
||||||
* Boston, MA 02110-1301, USA.
|
* Boston, MA 02110-1301, USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __GST_VIDEO_MARK_H__
|
#ifndef _GST_VIDEO_MARK_H_
|
||||||
#define __GST_VIDEO_MARK_H__
|
#define _GST_VIDEO_MARK_H_
|
||||||
|
|
||||||
#include <gst/video/gstvideofilter.h>
|
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
#include <gst/video/gstvideofilter.h>
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
#define GST_TYPE_VIDEO_MARK \
|
#define GST_TYPE_VIDEO_MARK (gst_video_mark_get_type())
|
||||||
(gst_video_mark_get_type())
|
#define GST_VIDEO_MARK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_MARK,GstVideoMark))
|
||||||
#define GST_VIDEO_MARK(obj) \
|
#define GST_VIDEO_MARK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_MARK,GstVideoMarkClass))
|
||||||
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_MARK,GstVideoMark))
|
#define GST_IS_VIDEO_MARK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_MARK))
|
||||||
#define GST_VIDEO_MARK_CLASS(klass) \
|
#define GST_IS_VIDEO_MARK_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_MARK))
|
||||||
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_MARK,GstVideoMarkClass))
|
|
||||||
#define GST_IS_VIDEO_MARK(obj) \
|
|
||||||
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_MARK))
|
|
||||||
#define GST_IS_VIDEO_MARK_CLASS(klass) \
|
|
||||||
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_MARK))
|
|
||||||
|
|
||||||
typedef struct _GstVideoMark GstVideoMark;
|
typedef struct _GstVideoMark GstVideoMark;
|
||||||
typedef struct _GstVideoMarkClass GstVideoMarkClass;
|
typedef struct _GstVideoMarkClass GstVideoMarkClass;
|
||||||
|
|
||||||
/**
|
struct _GstVideoMark
|
||||||
* GstVideoMark:
|
{
|
||||||
*
|
GstVideoFilter base_videomark;
|
||||||
* Opaque datastructure.
|
|
||||||
*/
|
|
||||||
struct _GstVideoMark {
|
|
||||||
GstVideoFilter videofilter;
|
|
||||||
|
|
||||||
gint width, height;
|
|
||||||
GstVideoFormat format;
|
|
||||||
|
|
||||||
|
/* properties */
|
||||||
gint pattern_width;
|
gint pattern_width;
|
||||||
gint pattern_height;
|
gint pattern_height;
|
||||||
gint pattern_count;
|
gint pattern_count;
|
||||||
|
@ -60,12 +49,13 @@ struct _GstVideoMark {
|
||||||
gint bottom_offset;
|
gint bottom_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstVideoMarkClass {
|
struct _GstVideoMarkClass
|
||||||
GstVideoFilterClass parent_class;
|
{
|
||||||
|
GstVideoFilterClass base_videomark_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_video_mark_get_type (void);
|
GType gst_video_mark_get_type (void);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_VIDEO_MARK_H__ */
|
#endif
|
||||||
|
|
|
@ -33,7 +33,6 @@ plugin_init (GstPlugin * plugin)
|
||||||
res = gst_element_register (plugin, "videoanalyse", GST_RANK_NONE,
|
res = gst_element_register (plugin, "videoanalyse", GST_RANK_NONE,
|
||||||
GST_TYPE_VIDEO_ANALYSE);
|
GST_TYPE_VIDEO_ANALYSE);
|
||||||
|
|
||||||
#if 0
|
|
||||||
/* FIXME under no circumstances is anyone allowed to revive the
|
/* FIXME under no circumstances is anyone allowed to revive the
|
||||||
* element formerly known as videodetect without changing the name
|
* element formerly known as videodetect without changing the name
|
||||||
* first. XOXO --ds */
|
* first. XOXO --ds */
|
||||||
|
@ -43,7 +42,6 @@ plugin_init (GstPlugin * plugin)
|
||||||
|
|
||||||
res &= gst_element_register (plugin, "videomark", GST_RANK_NONE,
|
res &= gst_element_register (plugin, "videomark", GST_RANK_NONE,
|
||||||
GST_TYPE_VIDEO_MARK);
|
GST_TYPE_VIDEO_MARK);
|
||||||
#endif
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue