playsink: handle after-the-fact changes in converters/volume booleans

The playsink was nastily poking a boolean in the structure.
Make those booleans properties, so we are told when they change,
and rebuild the conversion bin when they do.

Some cleanup to go with it too.

https://bugzilla.gnome.org/show_bug.cgi?id=661262
This commit is contained in:
Vincent Penquerc'h 2011-10-17 21:05:30 +00:00 committed by Sebastian Dröge
parent c08a23169d
commit ae3ba53391
7 changed files with 143 additions and 57 deletions

View file

@ -1799,9 +1799,15 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_AUDIO) || (!have_volume if (!(playsink->flags & GST_PLAY_FLAG_NATIVE_AUDIO) || (!have_volume
&& playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME)) { && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME)) {
GST_DEBUG_OBJECT (playsink, "creating audioconvert"); gboolean use_converters = !(playsink->flags & GST_PLAY_FLAG_NATIVE_AUDIO);
gboolean use_volume =
!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME;
GST_DEBUG_OBJECT (playsink,
"creating audioconvert with use-converters %d, use-volume %d",
use_converters, use_volume);
chain->conv = chain->conv =
g_object_new (GST_TYPE_PLAY_SINK_AUDIO_CONVERT, "name", "aconv", NULL); g_object_new (GST_TYPE_PLAY_SINK_AUDIO_CONVERT, "name", "aconv",
"use-converters", use_converters, "use-volume", use_volume, NULL);
gst_bin_add (bin, chain->conv); gst_bin_add (bin, chain->conv);
if (prev) { if (prev) {
if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink", if (!gst_element_link_pads_full (prev, "src", chain->conv, "sink",
@ -1812,11 +1818,6 @@ gen_audio_chain (GstPlaySink * playsink, gboolean raw)
} }
prev = chain->conv; prev = chain->conv;
GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv)->use_converters =
!(playsink->flags & GST_PLAY_FLAG_NATIVE_AUDIO);
GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv)->use_volume = (!have_volume
&& playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME);
if (!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) { if (!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) {
GstPlaySinkAudioConvert *conv = GstPlaySinkAudioConvert *conv =
GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv); GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv);
@ -1964,13 +1965,13 @@ setup_audio_chain (GstPlaySink * playsink, gboolean raw)
G_CALLBACK (notify_mute_cb), playsink); G_CALLBACK (notify_mute_cb), playsink);
} }
GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv)->use_volume = FALSE; g_object_set (chain->conv, "use-volume", FALSE, NULL);
} else { } else {
GstPlaySinkAudioConvert *conv = GstPlaySinkAudioConvert *conv =
GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv); GST_PLAY_SINK_AUDIO_CONVERT_CAST (chain->conv);
/* no volume, we need to add a volume element when we can */ /* no volume, we need to add a volume element when we can */
conv->use_volume = TRUE; g_object_set (chain->conv, "use-volume", TRUE, NULL);
GST_DEBUG_OBJECT (playsink, "the sink has no volume property"); GST_DEBUG_OBJECT (playsink, "the sink has no volume property");
/* Disconnect signals */ /* Disconnect signals */
@ -3028,14 +3029,14 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink)
if (pad == playsink->audio_pad) { if (pad == playsink->audio_pad) {
raw = is_raw_pad (pad); raw = is_raw_pad (pad);
reconfigure = (! !playsink->audio_pad_raw != ! !raw) reconfigure = (!!playsink->audio_pad_raw != !!raw)
&& playsink->audiochain; && playsink->audiochain;
GST_DEBUG_OBJECT (pad, GST_DEBUG_OBJECT (pad,
"Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, "Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,
reconfigure, caps); reconfigure, caps);
} else if (pad == playsink->video_pad) { } else if (pad == playsink->video_pad) {
raw = is_raw_pad (pad); raw = is_raw_pad (pad);
reconfigure = (! !playsink->video_pad_raw != ! !raw) reconfigure = (!!playsink->video_pad_raw != !!raw)
&& playsink->videochain; && playsink->videochain;
GST_DEBUG_OBJECT (pad, GST_DEBUG_OBJECT (pad,
"Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, "Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,

View file

@ -34,15 +34,26 @@ GST_DEBUG_CATEGORY_STATIC (gst_play_sink_audio_convert_debug);
G_DEFINE_TYPE (GstPlaySinkAudioConvert, gst_play_sink_audio_convert, G_DEFINE_TYPE (GstPlaySinkAudioConvert, gst_play_sink_audio_convert,
GST_TYPE_PLAY_SINK_CONVERT_BIN); GST_TYPE_PLAY_SINK_CONVERT_BIN);
static gboolean enum
gst_play_sink_audio_convert_add_conversion_elements (GstPlaySinkConvertBin *
cbin)
{ {
GstPlaySinkAudioConvert *self = GST_PLAY_SINK_AUDIO_CONVERT (cbin); PROP_0,
PROP_USE_CONVERTERS,
PROP_USE_VOLUME,
};
static gboolean
gst_play_sink_audio_convert_add_conversion_elements (GstPlaySinkAudioConvert *
self)
{
GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self);
GstElement *el, *prev = NULL; GstElement *el, *prev = NULL;
g_assert (cbin->conversion_elements == NULL); g_assert (cbin->conversion_elements == NULL);
GST_DEBUG_OBJECT (self,
"Building audio conversion with use-converters %d, use-volume %d",
self->use_converters, self->use_volume);
if (self->use_converters) { if (self->use_converters) {
el = gst_play_sink_convert_bin_add_conversion_element_factory (cbin, el = gst_play_sink_convert_bin_add_conversion_element_factory (cbin,
"audioconvert", "conv"); "audioconvert", "conv");
@ -73,6 +84,7 @@ gst_play_sink_audio_convert_add_conversion_elements (GstPlaySinkConvertBin *
} }
prev = el; prev = el;
} }
return TRUE; return TRUE;
link_failed: link_failed:
@ -90,6 +102,59 @@ gst_play_sink_audio_convert_finalize (GObject * object)
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static void
gst_play_sink_audio_convert_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstPlaySinkAudioConvert *self = GST_PLAY_SINK_AUDIO_CONVERT_CAST (object);
gboolean v, changed = FALSE;
switch (prop_id) {
case PROP_USE_CONVERTERS:
v = g_value_get_boolean (value);
if (v != self->use_converters) {
self->use_converters = v;
changed = TRUE;
}
break;
case PROP_USE_VOLUME:
v = g_value_get_boolean (value);
if (v != self->use_volume) {
self->use_volume = v;
changed = TRUE;
}
break;
default:
break;
}
if (changed) {
GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self);
GST_DEBUG_OBJECT (self, "Rebuilding converter bin");
gst_play_sink_convert_bin_remove_elements (cbin);
gst_play_sink_audio_convert_add_conversion_elements (self);
gst_play_sink_convert_bin_cache_converter_caps (cbin);
}
}
static void
gst_play_sink_audio_convert_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstPlaySinkAudioConvert *self = GST_PLAY_SINK_AUDIO_CONVERT_CAST (object);
switch (prop_id) {
case PROP_USE_CONVERTERS:
g_value_set_boolean (value, self->use_converters);
break;
case PROP_USE_VOLUME:
g_value_set_boolean (value, self->use_volume);
break;
default:
break;
}
}
static void static void
gst_play_sink_audio_convert_class_init (GstPlaySinkAudioConvertClass * klass) gst_play_sink_audio_convert_class_init (GstPlaySinkAudioConvertClass * klass)
{ {
@ -103,6 +168,18 @@ gst_play_sink_audio_convert_class_init (GstPlaySinkAudioConvertClass * klass)
gstelement_class = (GstElementClass *) klass; gstelement_class = (GstElementClass *) klass;
gobject_class->finalize = gst_play_sink_audio_convert_finalize; gobject_class->finalize = gst_play_sink_audio_convert_finalize;
gobject_class->set_property = gst_play_sink_audio_convert_set_property;
gobject_class->get_property = gst_play_sink_audio_convert_get_property;
g_object_class_install_property (gobject_class, PROP_USE_CONVERTERS,
g_param_spec_boolean ("use-converters", "Use converters",
"Whether to use conversion elements", FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_USE_VOLUME,
g_param_spec_boolean ("use-volume", "Use volume",
"Whether to use a volume element", FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
gst_element_class_set_details_simple (gstelement_class, gst_element_class_set_details_simple (gstelement_class,
"Player Sink Audio Converter", "Audio/Bin/Converter", "Player Sink Audio Converter", "Audio/Bin/Converter",
@ -116,8 +193,6 @@ gst_play_sink_audio_convert_init (GstPlaySinkAudioConvert * self)
GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self); GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self);
cbin->audio = TRUE; cbin->audio = TRUE;
cbin->add_conversion_elements =
gst_play_sink_audio_convert_add_conversion_elements;
/* FIXME: Only create this on demand but for now we need /* FIXME: Only create this on demand but for now we need
* it to always exist because of playsink's volume proxying * it to always exist because of playsink's volume proxying
@ -126,4 +201,7 @@ gst_play_sink_audio_convert_init (GstPlaySinkAudioConvert * self)
self->volume = gst_element_factory_make ("volume", "volume"); self->volume = gst_element_factory_make ("volume", "volume");
if (self->volume) if (self->volume)
gst_object_ref_sink (self->volume); gst_object_ref_sink (self->volume);
gst_play_sink_audio_convert_add_conversion_elements (self);
gst_play_sink_convert_bin_cache_converter_caps (cbin);
} }

View file

@ -36,7 +36,6 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAY_SINK_AUDIO_CONVERT)) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAY_SINK_AUDIO_CONVERT))
#define GST_IS_PLAY_SINK_AUDIO_CONVERT_CLASS(klass) \ #define GST_IS_PLAY_SINK_AUDIO_CONVERT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK_AUDIO_CONVERT)) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK_AUDIO_CONVERT))
typedef struct _GstPlaySinkAudioConvert GstPlaySinkAudioConvert; typedef struct _GstPlaySinkAudioConvert GstPlaySinkAudioConvert;
typedef struct _GstPlaySinkAudioConvertClass GstPlaySinkAudioConvertClass; typedef struct _GstPlaySinkAudioConvertClass GstPlaySinkAudioConvertClass;
@ -46,8 +45,8 @@ struct _GstPlaySinkAudioConvert
/* < pseudo public > */ /* < pseudo public > */
GstElement *volume; GstElement *volume;
gboolean use_volume;
gboolean use_converters; gboolean use_converters;
gboolean use_volume;
}; };
struct _GstPlaySinkAudioConvertClass struct _GstPlaySinkAudioConvertClass

View file

@ -147,6 +147,8 @@ gst_play_sink_convert_bin_set_targets (GstPlaySinkConvertBin * self,
GstPad *pad; GstPad *pad;
GstElement *head, *tail; GstElement *head, *tail;
GST_DEBUG_OBJECT (self, "Setting pad targets with passthrough %d",
passthrough);
if (self->conversion_elements == NULL || passthrough) { if (self->conversion_elements == NULL || passthrough) {
if (!passthrough) { if (!passthrough) {
GST_WARNING_OBJECT (self, GST_WARNING_OBJECT (self,
@ -159,10 +161,12 @@ gst_play_sink_convert_bin_set_targets (GstPlaySinkConvertBin * self,
} }
pad = gst_element_get_static_pad (head, "sink"); pad = gst_element_get_static_pad (head, "sink");
GST_DEBUG_OBJECT (self, "Ghosting bin sink pad to %" GST_PTR_FORMAT, pad);
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), pad); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->sinkpad), pad);
gst_object_unref (pad); gst_object_unref (pad);
pad = gst_element_get_static_pad (tail, "src"); pad = gst_element_get_static_pad (tail, "src");
GST_DEBUG_OBJECT (self, "Ghosting bin src pad to %" GST_PTR_FORMAT, pad);
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), pad); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (self->srcpad), pad);
gst_object_unref (pad); gst_object_unref (pad);
} }
@ -289,6 +293,7 @@ gst_play_sink_convert_bin_sink_setcaps (GstPad * pad, GstCaps * caps)
gboolean reconfigure = FALSE; gboolean reconfigure = FALSE;
gboolean raw; gboolean raw;
GST_DEBUG_OBJECT (pad, "setcaps: %" GST_PTR_FORMAT, caps);
GST_PLAY_SINK_CONVERT_BIN_LOCK (self); GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
name = gst_structure_get_name (s); name = gst_structure_get_name (s);
@ -299,6 +304,8 @@ gst_play_sink_convert_bin_sink_setcaps (GstPad * pad, GstCaps * caps)
raw = g_str_has_prefix (name, "video/x-raw-"); raw = g_str_has_prefix (name, "video/x-raw-");
} }
GST_DEBUG_OBJECT (self, "raw %d, self->raw %d, blocked %d",
raw, self->raw, gst_pad_is_blocked (self->sink_proxypad));
if (raw) { if (raw) {
if (!self->raw && !gst_pad_is_blocked (self->sink_proxypad)) { if (!self->raw && !gst_pad_is_blocked (self->sink_proxypad)) {
GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw"); GST_DEBUG_OBJECT (self, "Changing caps from non-raw to raw");
@ -376,24 +383,49 @@ gst_play_sink_convert_bin_getcaps (GstPad * pad)
return ret; return ret;
} }
void
gst_play_sink_convert_bin_remove_elements (GstPlaySinkConvertBin * self)
{
if (self->conversion_elements) {
g_list_foreach (self->conversion_elements,
(GFunc) gst_play_sink_convert_bin_remove_element, self);
g_list_free (self->conversion_elements);
self->conversion_elements = NULL;
}
if (self->identity) {
gst_element_set_state (self->identity, GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (self), self->identity);
self->identity = NULL;
}
if (self->converter_caps) {
gst_caps_unref (self->converter_caps);
self->converter_caps = NULL;
}
}
static void static void
gst_play_sink_convert_bin_finalize (GObject * object) gst_play_sink_convert_bin_finalize (GObject * object)
{ {
GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (object); GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (object);
gst_play_sink_convert_bin_remove_elements (self);
gst_object_unref (self->sink_proxypad); gst_object_unref (self->sink_proxypad);
g_mutex_free (self->lock); g_mutex_free (self->lock);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
static void void
gst_play_sink_convert_bin_cache_converter_caps (GstPlaySinkConvertBin * self) gst_play_sink_convert_bin_cache_converter_caps (GstPlaySinkConvertBin * self)
{ {
GstElement *head; GstElement *head;
GstPad *pad; GstPad *pad;
self->converter_caps = NULL; if (self->converter_caps) {
gst_caps_unref (self->converter_caps);
self->converter_caps = NULL;
}
if (!self->conversion_elements) { if (!self->conversion_elements) {
GST_WARNING_OBJECT (self, "No conversion elements"); GST_WARNING_OBJECT (self, "No conversion elements");
@ -422,17 +454,6 @@ gst_play_sink_convert_bin_change_state (GstElement * element,
GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (element); GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (element);
switch (transition) { switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
g_assert (self->add_conversion_elements);
if (!(*self->add_conversion_elements) (self)) {
GST_ELEMENT_ERROR (self, CORE, PAD,
(NULL), ("Failed to configure the converter bin."));
}
gst_play_sink_convert_bin_cache_converter_caps (self);
gst_play_sink_convert_bin_add_identity (self);
GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
break;
case GST_STATE_CHANGE_PAUSED_TO_READY: case GST_STATE_CHANGE_PAUSED_TO_READY:
GST_PLAY_SINK_CONVERT_BIN_LOCK (self); GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
if (gst_pad_is_blocked (self->sink_proxypad)) if (gst_pad_is_blocked (self->sink_proxypad))
@ -465,25 +486,6 @@ gst_play_sink_convert_bin_change_state (GstElement * element,
(GDestroyNotify) gst_object_unref); (GDestroyNotify) gst_object_unref);
GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self); GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
break; break;
case GST_STATE_CHANGE_READY_TO_NULL:
GST_PLAY_SINK_CONVERT_BIN_LOCK (self);
if (self->conversion_elements) {
g_list_foreach (self->conversion_elements,
(GFunc) gst_play_sink_convert_bin_remove_element, self);
g_list_free (self->conversion_elements);
self->conversion_elements = NULL;
}
if (self->identity) {
gst_element_set_state (self->identity, GST_STATE_NULL);
gst_bin_remove (GST_BIN_CAST (self), self->identity);
self->identity = NULL;
}
if (self->converter_caps) {
gst_caps_unref (self->converter_caps);
self->converter_caps = NULL;
}
GST_PLAY_SINK_CONVERT_BIN_UNLOCK (self);
break;
default: default:
break; break;
} }
@ -547,4 +549,6 @@ gst_play_sink_convert_bin_init (GstPlaySinkConvertBin * self)
GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_getcaps)); GST_DEBUG_FUNCPTR (gst_play_sink_convert_bin_getcaps));
gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad); gst_element_add_pad (GST_ELEMENT_CAST (self), self->srcpad);
gst_object_unref (templ); gst_object_unref (templ);
gst_play_sink_convert_bin_add_identity (self);
} }

View file

@ -78,7 +78,6 @@ struct _GstPlaySinkConvertBin
/* configuration for derived classes */ /* configuration for derived classes */
gboolean audio; gboolean audio;
gboolean (*add_conversion_elements)(GstPlaySinkConvertBin *);
}; };
struct _GstPlaySinkConvertBinClass struct _GstPlaySinkConvertBinClass
@ -93,6 +92,10 @@ gst_play_sink_convert_bin_add_conversion_element_factory (GstPlaySinkConvertBin
void void
gst_play_sink_convert_bin_add_conversion_element (GstPlaySinkConvertBin *self, gst_play_sink_convert_bin_add_conversion_element (GstPlaySinkConvertBin *self,
GstElement *el); GstElement *el);
void
gst_play_sink_convert_bin_cache_converter_caps (GstPlaySinkConvertBin * self);
void
gst_play_sink_convert_bin_remove_elements (GstPlaySinkConvertBin * self);
G_END_DECLS G_END_DECLS
#endif /* __GST_PLAY_SINK_CONVERT_BIN_H__ */ #endif /* __GST_PLAY_SINK_CONVERT_BIN_H__ */

View file

@ -35,9 +35,10 @@ G_DEFINE_TYPE (GstPlaySinkVideoConvert, gst_play_sink_video_convert,
GST_TYPE_PLAY_SINK_CONVERT_BIN); GST_TYPE_PLAY_SINK_CONVERT_BIN);
static gboolean static gboolean
gst_play_sink_video_convert_add_conversion_elements (GstPlaySinkConvertBin * gst_play_sink_video_convert_add_conversion_elements (GstPlaySinkVideoConvert *
cbin) self)
{ {
GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self);
GstElement *el, *prev = NULL; GstElement *el, *prev = NULL;
el = gst_play_sink_convert_bin_add_conversion_element_factory (cbin, el = gst_play_sink_convert_bin_add_conversion_element_factory (cbin,
@ -87,6 +88,7 @@ gst_play_sink_video_convert_init (GstPlaySinkVideoConvert * self)
{ {
GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self); GstPlaySinkConvertBin *cbin = GST_PLAY_SINK_CONVERT_BIN (self);
cbin->audio = FALSE; cbin->audio = FALSE;
cbin->add_conversion_elements =
gst_play_sink_video_convert_add_conversion_elements; gst_play_sink_video_convert_add_conversion_elements (self);
gst_play_sink_convert_bin_cache_converter_caps (cbin);
} }

View file

@ -36,7 +36,6 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAY_SINK_VIDEO_CONVERT)) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_PLAY_SINK_VIDEO_CONVERT))
#define GST_IS_PLAY_SINK_VIDEO_CONVERT_CLASS(klass) \ #define GST_IS_PLAY_SINK_VIDEO_CONVERT_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK_VIDEO_CONVERT)) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_PLAY_SINK_VIDEO_CONVERT))
typedef struct _GstPlaySinkVideoConvert GstPlaySinkVideoConvert; typedef struct _GstPlaySinkVideoConvert GstPlaySinkVideoConvert;
typedef struct _GstPlaySinkVideoConvertClass GstPlaySinkVideoConvertClass; typedef struct _GstPlaySinkVideoConvertClass GstPlaySinkVideoConvertClass;