dicetv: Clean up dicetv element and fix some smaller issues

This fixes a memory leak (the dice map) and a crash when
setting the square-bits property before caps are set.
This commit is contained in:
Sebastian Dröge 2009-06-15 17:21:58 +02:00
parent d1ad31b9b3
commit 0cbdfcbc22

View file

@ -1,5 +1,6 @@
/* GStreamer /* GStreamer
* Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu> * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
* *
* dice.c: a 'dicing' effect * dice.c: a 'dicing' effect
* copyright (c) 2001 Sam Mertens. This code is subject to the provisions of * copyright (c) 2001 Sam Mertens. This code is subject to the provisions of
@ -14,12 +15,13 @@
#include "config.h" #include "config.h"
#endif #endif
#include <gst/video/gstvideofilter.h>
#include <string.h> #include <string.h>
#include <gst/gst.h> #include <gst/gst.h>
#include <gst/video/video.h> #include <gst/video/video.h>
#include <gst/video/gstvideofilter.h>
#include <gst/controller/gstcontroller.h>
#define GST_TYPE_DICETV \ #define GST_TYPE_DICETV \
(gst_dicetv_get_type()) (gst_dicetv_get_type())
@ -66,16 +68,10 @@ struct _GstDiceTVClass
GstVideoFilterClass parent_class; GstVideoFilterClass parent_class;
}; };
GType gst_dicetv_get_type (void); GST_BOILERPLATE (GstDiceTV, gst_dicetv, GstVideoFilter, GST_TYPE_VIDEO_FILTER);
static void gst_dicetv_create_map (GstDiceTV * filter); static void gst_dicetv_create_map (GstDiceTV * filter);
static const GstElementDetails gst_dicetv_details =
GST_ELEMENT_DETAILS ("DiceTV effect",
"Filter/Effect/Video",
"'Dices' the screen up into many small squares",
"Wim Taymans <wim.taymans@chello.be>");
static GstStaticPadTemplate gst_dicetv_src_template = static GstStaticPadTemplate gst_dicetv_src_template =
GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC, GST_PAD_SRC,
@ -92,8 +88,6 @@ static GstStaticPadTemplate gst_dicetv_sink_template =
GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR) GST_VIDEO_CAPS_BGRx ";" GST_VIDEO_CAPS_xBGR)
); );
static GstVideoFilterClass *parent_class = NULL;
enum enum
{ {
ARG_0, ARG_0,
@ -114,7 +108,7 @@ gst_dicetv_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
gst_structure_get_int (structure, "height", &filter->height)) { gst_structure_get_int (structure, "height", &filter->height)) {
g_free (filter->dicemap); g_free (filter->dicemap);
filter->dicemap = filter->dicemap =
(gchar *) g_malloc (filter->height * filter->width * sizeof (char)); (gchar *) g_malloc (filter->height * filter->width * sizeof (gchar));
gst_dicetv_create_map (filter); gst_dicetv_create_map (filter);
ret = TRUE; ret = TRUE;
} }
@ -126,13 +120,11 @@ static gboolean
gst_dicetv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, gst_dicetv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
guint * size) guint * size)
{ {
GstDiceTV *filter; GstDiceTV *filter = GST_DICETV (btrans);
GstStructure *structure; GstStructure *structure;
gboolean ret = FALSE; gboolean ret = FALSE;
gint width, height; gint width, height;
filter = GST_DICETV (btrans);
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
if (gst_structure_get_int (structure, "width", &width) && if (gst_structure_get_int (structure, "width", &width) &&
@ -146,10 +138,10 @@ gst_dicetv_get_unit_size (GstBaseTransform * btrans, GstCaps * caps,
return ret; return ret;
} }
static unsigned int static inline guint
fastrand (void) fastrand (void)
{ {
static unsigned int fastrand_val; static guint fastrand_val;
return (fastrand_val = fastrand_val * 1103515245 + 12345); return (fastrand_val = fastrand_val * 1103515245 + 12345);
} }
@ -157,17 +149,25 @@ fastrand (void)
static GstFlowReturn static GstFlowReturn
gst_dicetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out) gst_dicetv_transform (GstBaseTransform * trans, GstBuffer * in, GstBuffer * out)
{ {
GstDiceTV *filter; GstDiceTV *filter = GST_DICETV (trans);
guint32 *src, *dest; guint32 *src, *dest;
gint i, map_x, map_y, map_i, base, dx, dy, di; gint i, map_x, map_y, map_i, base, dx, dy, di;
gint video_width, g_cube_bits, g_cube_size; gint video_width, g_cube_bits, g_cube_size;
GstFlowReturn ret = GST_FLOW_OK; GstFlowReturn ret = GST_FLOW_OK;
GstClockTime timestamp, stream_time;
filter = GST_DICETV (trans);
src = (guint32 *) GST_BUFFER_DATA (in); src = (guint32 *) GST_BUFFER_DATA (in);
dest = (guint32 *) GST_BUFFER_DATA (out); dest = (guint32 *) GST_BUFFER_DATA (out);
gst_buffer_copy_metadata (out, in, GST_BUFFER_COPY_TIMESTAMPS); timestamp = GST_BUFFER_TIMESTAMP (in);
stream_time =
gst_segment_to_stream_time (&trans->segment, GST_FORMAT_TIME, timestamp);
GST_DEBUG_OBJECT (filter, "sync to %" GST_TIME_FORMAT,
GST_TIME_ARGS (timestamp));
if (GST_CLOCK_TIME_IS_VALID (stream_time))
gst_object_sync_values (G_OBJECT (filter), stream_time);
video_width = filter->width; video_width = filter->width;
g_cube_bits = filter->g_cube_bits; g_cube_bits = filter->g_cube_bits;
@ -236,6 +236,9 @@ gst_dicetv_create_map (GstDiceTV * filter)
{ {
gint x, y, i; gint x, y, i;
if (filter->height <= 0 || filter->width <= 0)
return;
filter->g_map_height = filter->height >> filter->g_cube_bits; filter->g_map_height = filter->height >> filter->g_cube_bits;
filter->g_map_width = filter->width >> filter->g_cube_bits; filter->g_map_width = filter->width >> filter->g_cube_bits;
filter->g_cube_size = 1 << filter->g_cube_bits; filter->g_cube_size = 1 << filter->g_cube_bits;
@ -255,17 +258,15 @@ static void
gst_dicetv_set_property (GObject * object, guint prop_id, const GValue * value, gst_dicetv_set_property (GObject * object, guint prop_id, const GValue * value,
GParamSpec * pspec) GParamSpec * pspec)
{ {
GstDiceTV *filter; GstDiceTV *filter = GST_DICETV (object);
g_return_if_fail (GST_IS_DICETV (object));
filter = GST_DICETV (object);
switch (prop_id) { switch (prop_id) {
case ARG_CUBE_BITS: case ARG_CUBE_BITS:
filter->g_cube_bits = g_value_get_int (value); filter->g_cube_bits = g_value_get_int (value);
gst_dicetv_create_map (filter); gst_dicetv_create_map (filter);
break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
} }
@ -274,11 +275,7 @@ static void
gst_dicetv_get_property (GObject * object, guint prop_id, GValue * value, gst_dicetv_get_property (GObject * object, guint prop_id, GValue * value,
GParamSpec * pspec) GParamSpec * pspec)
{ {
GstDiceTV *filter; GstDiceTV *filter = GST_DICETV (object);
g_return_if_fail (GST_IS_DICETV (object));
filter = GST_DICETV (object);
switch (prop_id) { switch (prop_id) {
case ARG_CUBE_BITS: case ARG_CUBE_BITS:
@ -290,12 +287,26 @@ gst_dicetv_get_property (GObject * object, guint prop_id, GValue * value,
} }
} }
static void
gst_dicetv_finalize (GObject * object)
{
GstDiceTV *filter = GST_DICETV (object);
g_free (filter->dicemap);
filter->dicemap = NULL;
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void static void
gst_dicetv_base_init (gpointer g_class) gst_dicetv_base_init (gpointer g_class)
{ {
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
gst_element_class_set_details (element_class, &gst_dicetv_details); gst_element_class_set_details_simple (element_class, "DiceTV effect",
"Filter/Effect/Video",
"'Dices' the screen up into many small squares",
"Wim Taymans <wim.taymans@chello.be>");
gst_element_class_add_pad_template (element_class, gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_dicetv_sink_template)); gst_static_pad_template_get (&gst_dicetv_sink_template));
@ -304,22 +315,19 @@ gst_dicetv_base_init (gpointer g_class)
} }
static void static void
gst_dicetv_class_init (gpointer klass, gpointer class_data) gst_dicetv_class_init (GstDiceTVClass * klass)
{ {
GObjectClass *gobject_class; GObjectClass *gobject_class = (GObjectClass *) klass;
GstBaseTransformClass *trans_class; GstBaseTransformClass *trans_class = (GstBaseTransformClass *) klass;
gobject_class = (GObjectClass *) klass;
trans_class = (GstBaseTransformClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = gst_dicetv_set_property; gobject_class->set_property = gst_dicetv_set_property;
gobject_class->get_property = gst_dicetv_get_property; gobject_class->get_property = gst_dicetv_get_property;
gobject_class->finalize = gst_dicetv_finalize;
g_object_class_install_property (gobject_class, ARG_CUBE_BITS, g_object_class_install_property (gobject_class, ARG_CUBE_BITS,
g_param_spec_int ("square_bits", "Square Bits", "The size of the Squares", g_param_spec_int ("square-bits", "Square Bits", "The size of the Squares",
MIN_CUBE_BITS, MAX_CUBE_BITS, DEFAULT_CUBE_BITS, G_PARAM_READWRITE)); MIN_CUBE_BITS, MAX_CUBE_BITS, DEFAULT_CUBE_BITS,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | GST_PARAM_CONTROLLABLE));
trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_dicetv_set_caps); trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_dicetv_set_caps);
trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_dicetv_get_unit_size); trans_class->get_unit_size = GST_DEBUG_FUNCPTR (gst_dicetv_get_unit_size);
@ -327,38 +335,11 @@ gst_dicetv_class_init (gpointer klass, gpointer class_data)
} }
static void static void
gst_dicetv_init (GTypeInstance * instance, gpointer g_class) gst_dicetv_init (GstDiceTV * filter, GstDiceTVClass * klass)
{ {
GstDiceTV *filter = GST_DICETV (instance);
filter->dicemap = NULL; filter->dicemap = NULL;
filter->g_cube_bits = DEFAULT_CUBE_BITS; filter->g_cube_bits = DEFAULT_CUBE_BITS;
filter->g_cube_size = 0; filter->g_cube_size = 0;
filter->g_map_height = 0; filter->g_map_height = 0;
filter->g_map_width = 0; filter->g_map_width = 0;
} }
GType
gst_dicetv_get_type (void)
{
static GType dicetv_type = 0;
if (!dicetv_type) {
static const GTypeInfo dicetv_info = {
sizeof (GstDiceTVClass),
gst_dicetv_base_init,
NULL,
(GClassInitFunc) gst_dicetv_class_init,
NULL,
NULL,
sizeof (GstDiceTV),
0,
(GInstanceInitFunc) gst_dicetv_init,
};
dicetv_type =
g_type_register_static (GST_TYPE_VIDEO_FILTER, "GstDiceTV",
&dicetv_info, 0);
}
return dicetv_type;
}