mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-26 09:08:14 +00:00
gst/videomixer/videomixer.c: Fix memleak by unref'ing collectpads instance (when finalizing)
Original commit message from CVS: Patch by: Mark Nauwelaerts <manauw at skynet be> * gst/videomixer/videomixer.c: (gst_videomixer_set_master_geometry), (gst_videomixer_pad_sink_setcaps), (gst_videomixer_class_init), (gst_videomixer_collect_free), (gst_videomixer_reset), (gst_videomixer_init), (gst_videomixer_finalize), (gst_videomixer_request_new_pad), (gst_videomixer_release_pad), (gst_videomixer_collected), (gst_videomixer_change_state): Fix memleak by unref'ing collectpads instance (when finalizing) Implement releasing a request pad. Fixes #374479.
This commit is contained in:
parent
6093ab0332
commit
27d42165b7
2 changed files with 157 additions and 26 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
2006-11-13 Wim Taymans <wim@fluendo.com>
|
||||||
|
|
||||||
|
Patch by: Mark Nauwelaerts <manauw at skynet be>
|
||||||
|
|
||||||
|
* gst/videomixer/videomixer.c:
|
||||||
|
(gst_videomixer_set_master_geometry),
|
||||||
|
(gst_videomixer_pad_sink_setcaps), (gst_videomixer_class_init),
|
||||||
|
(gst_videomixer_collect_free), (gst_videomixer_reset),
|
||||||
|
(gst_videomixer_init), (gst_videomixer_finalize),
|
||||||
|
(gst_videomixer_request_new_pad), (gst_videomixer_release_pad),
|
||||||
|
(gst_videomixer_collected), (gst_videomixer_change_state):
|
||||||
|
Fix memleak by unref'ing collectpads instance (when finalizing)
|
||||||
|
Implement releasing a request pad. Fixes #374479.
|
||||||
|
|
||||||
2006-11-10 Tim-Philipp Müller <tim at centricular dot net>
|
2006-11-10 Tim-Philipp Müller <tim at centricular dot net>
|
||||||
|
|
||||||
Patch by: Sergey Scobich <sergey.scobich at gmail com>
|
Patch by: Sergey Scobich <sergey.scobich at gmail com>
|
||||||
|
|
|
@ -296,6 +296,7 @@ struct _GstVideoMixer
|
||||||
|
|
||||||
gint in_width, in_height;
|
gint in_width, in_height;
|
||||||
gint out_width, out_height;
|
gint out_width, out_height;
|
||||||
|
gboolean setcaps;
|
||||||
|
|
||||||
GstVideoMixerBackground background;
|
GstVideoMixerBackground background;
|
||||||
|
|
||||||
|
@ -308,6 +309,48 @@ struct _GstVideoMixerClass
|
||||||
GstElementClass parent_class;
|
GstElementClass parent_class;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_videomixer_set_master_geometry (GstVideoMixer * mix)
|
||||||
|
{
|
||||||
|
GSList *walk;
|
||||||
|
gint width = 0, height = 0, fps_n = 0, fps_d = 0;
|
||||||
|
GstVideoMixerPad *master = NULL;
|
||||||
|
|
||||||
|
walk = mix->sinkpads;
|
||||||
|
while (walk) {
|
||||||
|
GstVideoMixerPad *mixpad = GST_VIDEO_MIXER_PAD (walk->data);
|
||||||
|
|
||||||
|
walk = g_slist_next (walk);
|
||||||
|
|
||||||
|
/* Biggest input geometry will be our output geometry */
|
||||||
|
width = MAX (width, mixpad->in_width);
|
||||||
|
height = MAX (height, mixpad->in_height);
|
||||||
|
|
||||||
|
/* If mix framerate < mixpad framerate, using fractions */
|
||||||
|
GST_DEBUG_OBJECT (mix, "comparing framerate %d/%d to mixpad's %d/%d",
|
||||||
|
fps_n, fps_d, mixpad->fps_n, mixpad->fps_d);
|
||||||
|
if ((!fps_n && !fps_d) ||
|
||||||
|
((gint64) fps_n * mixpad->fps_d < (gint64) mixpad->fps_n * fps_d)) {
|
||||||
|
fps_n = mixpad->fps_n;
|
||||||
|
fps_d = mixpad->fps_d;
|
||||||
|
GST_DEBUG_OBJECT (mixpad, "becomes the master pad");
|
||||||
|
master = mixpad;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* set results */
|
||||||
|
if (mix->master != master || mix->in_width != width
|
||||||
|
|| mix->in_height != height || mix->fps_n != fps_n
|
||||||
|
|| mix->fps_d != fps_d) {
|
||||||
|
mix->setcaps = TRUE;
|
||||||
|
mix->master = master;
|
||||||
|
mix->in_width = width;
|
||||||
|
mix->in_height = height;
|
||||||
|
mix->fps_n = fps_n;
|
||||||
|
mix->fps_d = fps_d;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_videomixer_pad_sink_setcaps (GstPad * pad, GstCaps * vscaps)
|
gst_videomixer_pad_sink_setcaps (GstPad * pad, GstCaps * vscaps)
|
||||||
{
|
{
|
||||||
|
@ -343,21 +386,7 @@ gst_videomixer_pad_sink_setcaps (GstPad * pad, GstCaps * vscaps)
|
||||||
mixpad->xpos = 0;
|
mixpad->xpos = 0;
|
||||||
mixpad->ypos = 0;
|
mixpad->ypos = 0;
|
||||||
|
|
||||||
/* Biggest input geometry will be our output geometry */
|
gst_videomixer_set_master_geometry (mix);
|
||||||
mix->in_width = MAX (mix->in_width, mixpad->in_width);
|
|
||||||
mix->in_height = MAX (mix->in_height, mixpad->in_height);
|
|
||||||
|
|
||||||
/* If mix framerate < mixpad framerate, using fractions */
|
|
||||||
GST_DEBUG_OBJECT (mix, "comparing mix framerate %d/%d to mixpad's %d/%d",
|
|
||||||
mix->fps_n, mix->fps_d, mixpad->fps_n, mixpad->fps_d);
|
|
||||||
if ((!mix->fps_n && !mix->fps_d) ||
|
|
||||||
((gint64) mix->fps_n * mixpad->fps_d <
|
|
||||||
(gint64) mixpad->fps_n * mix->fps_d)) {
|
|
||||||
mix->fps_n = mixpad->fps_n;
|
|
||||||
mix->fps_d = mixpad->fps_d;
|
|
||||||
GST_DEBUG_OBJECT (mixpad, "becomes the master pad");
|
|
||||||
mix->master = mixpad;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = TRUE;
|
ret = TRUE;
|
||||||
|
|
||||||
|
@ -460,6 +489,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink_%d",
|
||||||
static void gst_videomixer_base_init (gpointer g_class);
|
static void gst_videomixer_base_init (gpointer g_class);
|
||||||
static void gst_videomixer_class_init (GstVideoMixerClass * klass);
|
static void gst_videomixer_class_init (GstVideoMixerClass * klass);
|
||||||
static void gst_videomixer_init (GstVideoMixer * videomixer);
|
static void gst_videomixer_init (GstVideoMixer * videomixer);
|
||||||
|
static void gst_videomixer_finalize (GObject * object);
|
||||||
|
|
||||||
static GstCaps *gst_videomixer_getcaps (GstPad * pad);
|
static GstCaps *gst_videomixer_getcaps (GstPad * pad);
|
||||||
|
|
||||||
|
@ -467,6 +497,7 @@ static GstFlowReturn gst_videomixer_collected (GstCollectPads * pads,
|
||||||
GstVideoMixer * mix);
|
GstVideoMixer * mix);
|
||||||
static GstPad *gst_videomixer_request_new_pad (GstElement * element,
|
static GstPad *gst_videomixer_request_new_pad (GstElement * element,
|
||||||
GstPadTemplate * templ, const gchar * name);
|
GstPadTemplate * templ, const gchar * name);
|
||||||
|
static void gst_videomixer_release_pad (GstElement * element, GstPad * pad);
|
||||||
static void gst_videomixer_set_property (GObject * object, guint prop_id,
|
static void gst_videomixer_set_property (GObject * object, guint prop_id,
|
||||||
const GValue * value, GParamSpec * pspec);
|
const GValue * value, GParamSpec * pspec);
|
||||||
static void gst_videomixer_get_property (GObject * object, guint prop_id,
|
static void gst_videomixer_get_property (GObject * object, guint prop_id,
|
||||||
|
@ -527,6 +558,8 @@ gst_videomixer_class_init (GstVideoMixerClass * klass)
|
||||||
|
|
||||||
parent_class = g_type_class_peek_parent (klass);
|
parent_class = g_type_class_peek_parent (klass);
|
||||||
|
|
||||||
|
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_videomixer_finalize);
|
||||||
|
|
||||||
gobject_class->get_property = gst_videomixer_get_property;
|
gobject_class->get_property = gst_videomixer_get_property;
|
||||||
gobject_class->set_property = gst_videomixer_set_property;
|
gobject_class->set_property = gst_videomixer_set_property;
|
||||||
|
|
||||||
|
@ -535,8 +568,47 @@ gst_videomixer_class_init (GstVideoMixerClass * klass)
|
||||||
GST_TYPE_VIDEO_MIXER_BACKGROUND,
|
GST_TYPE_VIDEO_MIXER_BACKGROUND,
|
||||||
DEFAULT_BACKGROUND, G_PARAM_READWRITE));
|
DEFAULT_BACKGROUND, G_PARAM_READWRITE));
|
||||||
|
|
||||||
gstelement_class->request_new_pad = gst_videomixer_request_new_pad;
|
gstelement_class->request_new_pad =
|
||||||
gstelement_class->change_state = gst_videomixer_change_state;
|
GST_DEBUG_FUNCPTR (gst_videomixer_request_new_pad);
|
||||||
|
gstelement_class->release_pad =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_videomixer_release_pad);
|
||||||
|
gstelement_class->change_state =
|
||||||
|
GST_DEBUG_FUNCPTR (gst_videomixer_change_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_videomixer_collect_free (GstCollectData * collect)
|
||||||
|
{
|
||||||
|
GstVideoMixerCollect *mixcol;
|
||||||
|
|
||||||
|
mixcol = (GstVideoMixerCollect *) collect;
|
||||||
|
|
||||||
|
if (mixcol->buffer) {
|
||||||
|
gst_buffer_unref (mixcol->buffer);
|
||||||
|
mixcol->buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_videomixer_reset (GstVideoMixer * mix)
|
||||||
|
{
|
||||||
|
GSList *walk;
|
||||||
|
|
||||||
|
mix->in_width = 0;
|
||||||
|
mix->in_height = 0;
|
||||||
|
mix->out_width = 0;
|
||||||
|
mix->out_height = 0;
|
||||||
|
mix->fps_n = mix->fps_d = 0;
|
||||||
|
mix->setcaps = FALSE;
|
||||||
|
|
||||||
|
/* clean up collect data */
|
||||||
|
walk = mix->collect->data;
|
||||||
|
while (walk) {
|
||||||
|
GstCollectData *data = (GstCollectData *) walk->data;
|
||||||
|
|
||||||
|
gst_videomixer_collect_free (data);
|
||||||
|
walk = g_slist_next (walk);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -547,20 +619,30 @@ gst_videomixer_init (GstVideoMixer * mix)
|
||||||
mix->srcpad =
|
mix->srcpad =
|
||||||
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
|
gst_pad_new_from_template (gst_element_class_get_pad_template (klass,
|
||||||
"src"), "src");
|
"src"), "src");
|
||||||
gst_pad_set_getcaps_function (GST_PAD (mix->srcpad), gst_videomixer_getcaps);
|
gst_pad_set_getcaps_function (GST_PAD (mix->srcpad),
|
||||||
|
GST_DEBUG_FUNCPTR (gst_videomixer_getcaps));
|
||||||
gst_element_add_pad (GST_ELEMENT (mix), mix->srcpad);
|
gst_element_add_pad (GST_ELEMENT (mix), mix->srcpad);
|
||||||
|
|
||||||
mix->collect = gst_collect_pads_new ();
|
mix->collect = gst_collect_pads_new ();
|
||||||
mix->background = DEFAULT_BACKGROUND;
|
mix->background = DEFAULT_BACKGROUND;
|
||||||
mix->in_width = 0;
|
|
||||||
mix->in_height = 0;
|
|
||||||
mix->out_width = 0;
|
|
||||||
mix->out_height = 0;
|
|
||||||
mix->fps_n = mix->fps_d = 0;
|
|
||||||
|
|
||||||
gst_collect_pads_set_function (mix->collect,
|
gst_collect_pads_set_function (mix->collect,
|
||||||
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_videomixer_collected),
|
(GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_videomixer_collected),
|
||||||
mix);
|
mix);
|
||||||
|
|
||||||
|
/* initialize variables */
|
||||||
|
gst_videomixer_reset (mix);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_videomixer_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstVideoMixer *mix = GST_VIDEO_MIXER (object);
|
||||||
|
|
||||||
|
gst_object_unref (mix->collect);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
static GstCaps *
|
||||||
|
@ -649,12 +731,44 @@ gst_videomixer_request_new_pad (GstElement * element,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dd the pad to the element */
|
/* add the pad to the element */
|
||||||
gst_element_add_pad (element, GST_PAD (mixpad));
|
gst_element_add_pad (element, GST_PAD (mixpad));
|
||||||
|
|
||||||
return GST_PAD (mixpad);
|
return GST_PAD (mixpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_videomixer_release_pad (GstElement * element, GstPad * pad)
|
||||||
|
{
|
||||||
|
GstVideoMixer *mix = NULL;
|
||||||
|
GSList *walk = NULL;
|
||||||
|
|
||||||
|
mix = GST_VIDEO_MIXER (element);
|
||||||
|
|
||||||
|
walk = mix->collect->data;
|
||||||
|
while (walk) {
|
||||||
|
GstCollectData *data = (GstCollectData *) walk->data;
|
||||||
|
GstVideoMixerCollect *mixcol = (GstVideoMixerCollect *) data;
|
||||||
|
GstVideoMixerPad *mixpad = mixcol->mixpad;
|
||||||
|
|
||||||
|
walk = g_slist_next (walk);
|
||||||
|
|
||||||
|
if (mixpad == GST_VIDEO_MIXER_PAD (pad)) {
|
||||||
|
/* found it, remove from all sorts of lists */
|
||||||
|
mix->sinkpads = g_slist_remove (mix->sinkpads, pad);
|
||||||
|
gst_videomixer_collect_free (data);
|
||||||
|
gst_collect_pads_remove_pad (mix->collect, pad);
|
||||||
|
gst_element_remove_pad (element, pad);
|
||||||
|
/* determine possibly new geometry and master */
|
||||||
|
gst_videomixer_set_master_geometry (mix);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_warning ("Unknown pad %s", GST_PAD_NAME (pad));
|
||||||
|
}
|
||||||
|
|
||||||
#define BLEND_NORMAL(Y1,U1,V1,Y2,U2,V2,alpha,Y,U,V) \
|
#define BLEND_NORMAL(Y1,U1,V1,Y2,U2,V2,alpha,Y,U,V) \
|
||||||
Y = ((Y1*(255-alpha))+(Y2*alpha))>>8; \
|
Y = ((Y1*(255-alpha))+(Y2*alpha))>>8; \
|
||||||
U = ((U1*(255-alpha))+(U2*alpha))>>8; \
|
U = ((U1*(255-alpha))+(U2*alpha))>>8; \
|
||||||
|
@ -1141,7 +1255,8 @@ gst_videomixer_collected (GstCollectPads * pads, GstVideoMixer * mix)
|
||||||
outsize = ROUND_UP_2 (mix->in_width) * ROUND_UP_2 (mix->in_height) * 4;
|
outsize = ROUND_UP_2 (mix->in_width) * ROUND_UP_2 (mix->in_height) * 4;
|
||||||
|
|
||||||
/* If geometry has changed we need to set new caps on the buffer */
|
/* If geometry has changed we need to set new caps on the buffer */
|
||||||
if (mix->in_width != mix->out_width || mix->in_height != mix->out_height) {
|
if (mix->in_width != mix->out_width || mix->in_height != mix->out_height
|
||||||
|
|| mix->setcaps) {
|
||||||
GstCaps *newcaps = NULL;
|
GstCaps *newcaps = NULL;
|
||||||
|
|
||||||
newcaps = gst_caps_make_writable
|
newcaps = gst_caps_make_writable
|
||||||
|
@ -1153,6 +1268,7 @@ gst_videomixer_collected (GstCollectPads * pads, GstVideoMixer * mix)
|
||||||
|
|
||||||
mix->out_width = mix->in_width;
|
mix->out_width = mix->in_width;
|
||||||
mix->out_height = mix->in_height;
|
mix->out_height = mix->in_height;
|
||||||
|
mix->setcaps = FALSE;
|
||||||
|
|
||||||
ret =
|
ret =
|
||||||
gst_pad_alloc_buffer_and_set_caps (mix->srcpad, GST_BUFFER_OFFSET_NONE,
|
gst_pad_alloc_buffer_and_set_caps (mix->srcpad, GST_BUFFER_OFFSET_NONE,
|
||||||
|
@ -1237,6 +1353,7 @@ gst_videomixer_change_state (GstElement * element, GstStateChange transition)
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
|
gst_videomixer_reset (mix);
|
||||||
GST_LOG ("starting collectpads");
|
GST_LOG ("starting collectpads");
|
||||||
gst_collect_pads_start (mix->collect);
|
gst_collect_pads_start (mix->collect);
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue