mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 16:50:47 +00:00
Use new ghostpad API; now they actually work in Totem, also.
Original commit message from CVS: * ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_reset), (gst_gconf_audio_sink_init), (do_toggle_element), (cb_toggle_element), (gst_gconf_audio_sink_change_state): * ext/gconf/gstgconfaudiosink.h: * ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_reset), (gst_gconf_video_sink_init), (do_toggle_element), (cb_toggle_element), (gst_gconf_video_sink_change_state): * ext/gconf/gstgconfvideosink.h: * gst/autodetect/gstautoaudiosink.c: (gst_auto_audio_sink_reset), (gst_auto_audio_sink_init), (gst_auto_audio_sink_detect), (gst_auto_audio_sink_change_state): * gst/autodetect/gstautoaudiosink.h: * gst/autodetect/gstautovideosink.c: (gst_auto_video_sink_reset), (gst_auto_video_sink_init), (gst_auto_video_sink_detect), (gst_auto_video_sink_change_state): * gst/autodetect/gstautovideosink.h: Use new ghostpad API; now they actually work in Totem, also.
This commit is contained in:
parent
1b23cf61a8
commit
7e8df65cc2
9 changed files with 225 additions and 170 deletions
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
2005-08-03 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* ext/gconf/gstgconfaudiosink.c: (gst_gconf_audio_sink_reset),
|
||||
(gst_gconf_audio_sink_init), (do_toggle_element),
|
||||
(cb_toggle_element), (gst_gconf_audio_sink_change_state):
|
||||
* ext/gconf/gstgconfaudiosink.h:
|
||||
* ext/gconf/gstgconfvideosink.c: (gst_gconf_video_sink_reset),
|
||||
(gst_gconf_video_sink_init), (do_toggle_element),
|
||||
(cb_toggle_element), (gst_gconf_video_sink_change_state):
|
||||
* ext/gconf/gstgconfvideosink.h:
|
||||
* gst/autodetect/gstautoaudiosink.c: (gst_auto_audio_sink_reset),
|
||||
(gst_auto_audio_sink_init), (gst_auto_audio_sink_detect),
|
||||
(gst_auto_audio_sink_change_state):
|
||||
* gst/autodetect/gstautoaudiosink.h:
|
||||
* gst/autodetect/gstautovideosink.c: (gst_auto_video_sink_reset),
|
||||
(gst_auto_video_sink_init), (gst_auto_video_sink_detect),
|
||||
(gst_auto_video_sink_change_state):
|
||||
* gst/autodetect/gstautovideosink.h:
|
||||
Use new ghostpad API; now they actually work in Totem, also.
|
||||
|
||||
2005-08-03 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
|
||||
|
||||
* ext/libpng/Makefile.am:
|
||||
|
|
|
@ -62,20 +62,40 @@ gst_gconf_audio_sink_class_init (GstGConfAudioSinkClass * klass)
|
|||
eklass->change_state = gst_gconf_audio_sink_change_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to make negotiation work.
|
||||
*/
|
||||
|
||||
static void
|
||||
gst_gconf_audio_sink_reset (GstGConfAudioSink * sink)
|
||||
{
|
||||
GstPad *targetpad;
|
||||
|
||||
/* fakesink */
|
||||
if (sink->kid) {
|
||||
gst_bin_remove (GST_BIN (sink), sink->kid);
|
||||
}
|
||||
sink->kid = gst_element_factory_make ("fakesink", "testsink");
|
||||
gst_bin_add (GST_BIN (sink), sink->kid);
|
||||
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gconf_audio_sink_init (GstGConfAudioSink * sink)
|
||||
{
|
||||
sink->pad = NULL;
|
||||
sink->kid = NULL;
|
||||
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
gst_gconf_audio_sink_reset (sink);
|
||||
|
||||
sink->client = gconf_client_get_default ();
|
||||
gconf_client_add_dir (sink->client, GST_GCONF_DIR,
|
||||
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
|
||||
gconf_client_notify_add (sink->client, GST_GCONF_DIR "/default/audiosink",
|
||||
cb_toggle_element, sink, NULL, NULL);
|
||||
cb_toggle_element (sink->client, 0, NULL, sink);
|
||||
|
||||
sink->init = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -91,23 +111,10 @@ gst_gconf_audio_sink_dispose (GObject * object)
|
|||
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
cb_toggle_element (GConfClient * client,
|
||||
guint connection_id, GConfEntry * entry, gpointer data)
|
||||
static gboolean
|
||||
do_toggle_element (GstGConfAudioSink * sink)
|
||||
{
|
||||
GstGConfAudioSink *sink = GST_GCONF_AUDIO_SINK (data);
|
||||
GstPad *peer = NULL, *targetpad;
|
||||
|
||||
/* save ghostpad */
|
||||
if (sink->pad) {
|
||||
peer = GST_PAD_PEER (sink->pad);
|
||||
if (peer) {
|
||||
gst_pad_unlink (peer, sink->pad);
|
||||
GST_DEBUG_OBJECT (sink, "Caching peer %p", peer);
|
||||
}
|
||||
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
|
||||
sink->pad = NULL;
|
||||
}
|
||||
GstPad *targetpad;
|
||||
|
||||
/* kill old element */
|
||||
if (sink->kid) {
|
||||
|
@ -116,31 +123,30 @@ cb_toggle_element (GConfClient * client,
|
|||
sink->kid = NULL;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)",
|
||||
entry ? "audio" : "fake");
|
||||
sink->kid = entry ? gst_gconf_get_default_audio_sink () :
|
||||
gst_element_factory_make ("fakesink", "temporary-element");
|
||||
if (!sink->kid) {
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid");
|
||||
if (!(sink->kid = gst_gconf_get_default_audio_sink ())) {
|
||||
GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
|
||||
("Failed to render audio sink from GConf"));
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
gst_element_set_state (sink->kid, GST_STATE (sink));
|
||||
gst_bin_add (GST_BIN (sink), sink->kid);
|
||||
|
||||
/* re-attach ghostpad */
|
||||
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
sink->pad = gst_ghost_pad_new ("sink", targetpad);
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
if (peer) {
|
||||
GST_DEBUG_OBJECT (sink, "Linking...");
|
||||
gst_pad_link (peer, sink->pad);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "done changing gconf audio sink");
|
||||
sink->init = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_toggle_element (GConfClient * client,
|
||||
guint connection_id, GConfEntry * entry, gpointer data)
|
||||
{
|
||||
do_toggle_element (GST_GCONF_AUDIO_SINK (data));
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -148,12 +154,16 @@ gst_gconf_audio_sink_change_state (GstElement * element)
|
|||
{
|
||||
GstGConfAudioSink *sink = GST_GCONF_AUDIO_SINK (element);
|
||||
|
||||
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
|
||||
cb_toggle_element (sink->client, 0,
|
||||
gconf_client_get_entry (sink->client,
|
||||
GST_GCONF_DIR "/default/audiosink", NULL, TRUE, NULL), sink);
|
||||
if (!sink->init)
|
||||
return GST_STATE_FAILURE;
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
if (!do_toggle_element (sink))
|
||||
return GST_STATE_FAILURE;
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
gst_gconf_audio_sink_reset (sink);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
|
||||
|
|
|
@ -45,7 +45,6 @@ typedef struct _GstGConfAudioSink {
|
|||
GConfClient *client;
|
||||
GstElement *kid;
|
||||
GstPad *pad;
|
||||
gboolean init;
|
||||
} GstGConfAudioSink;
|
||||
|
||||
typedef struct _GstGConfAudioSinkClass {
|
||||
|
|
|
@ -62,20 +62,40 @@ gst_gconf_video_sink_class_init (GstGConfVideoSinkClass * klass)
|
|||
eklass->change_state = gst_gconf_video_sink_change_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to make negotiation work.
|
||||
*/
|
||||
|
||||
static void
|
||||
gst_gconf_video_sink_reset (GstGConfVideoSink * sink)
|
||||
{
|
||||
GstPad *targetpad;
|
||||
|
||||
/* fakesink */
|
||||
if (sink->kid) {
|
||||
gst_bin_remove (GST_BIN (sink), sink->kid);
|
||||
}
|
||||
sink->kid = gst_element_factory_make ("fakesink", "testsink");
|
||||
gst_bin_add (GST_BIN (sink), sink->kid);
|
||||
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_gconf_video_sink_init (GstGConfVideoSink * sink)
|
||||
{
|
||||
sink->pad = NULL;
|
||||
sink->kid = NULL;
|
||||
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
gst_gconf_video_sink_reset (sink);
|
||||
|
||||
sink->client = gconf_client_get_default ();
|
||||
gconf_client_add_dir (sink->client, GST_GCONF_DIR,
|
||||
GCONF_CLIENT_PRELOAD_RECURSIVE, NULL);
|
||||
gconf_client_notify_add (sink->client, GST_GCONF_DIR "/default/videosink",
|
||||
cb_toggle_element, sink, NULL, NULL);
|
||||
cb_toggle_element (sink->client, 0, NULL, sink);
|
||||
|
||||
sink->init = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -91,23 +111,10 @@ gst_gconf_video_sink_dispose (GObject * object)
|
|||
GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object));
|
||||
}
|
||||
|
||||
static void
|
||||
cb_toggle_element (GConfClient * client,
|
||||
guint connection_id, GConfEntry * entry, gpointer data)
|
||||
static gboolean
|
||||
do_toggle_element (GstGConfVideoSink * sink)
|
||||
{
|
||||
GstGConfVideoSink *sink = GST_GCONF_VIDEO_SINK (data);
|
||||
GstPad *peer = NULL, *targetpad;
|
||||
|
||||
/* save ghostpad */
|
||||
if (sink->pad) {
|
||||
peer = GST_PAD_PEER (sink->pad);
|
||||
if (peer) {
|
||||
gst_pad_unlink (peer, sink->pad);
|
||||
GST_DEBUG_OBJECT (sink, "Caching peer %p", peer);
|
||||
}
|
||||
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
|
||||
sink->pad = NULL;
|
||||
}
|
||||
GstPad *targetpad;
|
||||
|
||||
/* kill old element */
|
||||
if (sink->kid) {
|
||||
|
@ -116,31 +123,30 @@ cb_toggle_element (GConfClient * client,
|
|||
sink->kid = NULL;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)",
|
||||
entry ? "video" : "fake");
|
||||
sink->kid = entry ? gst_gconf_get_default_video_sink () :
|
||||
gst_element_factory_make ("fakesink", "temporary-element");
|
||||
if (!sink->kid) {
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid");
|
||||
if (!(sink->kid = gst_gconf_get_default_video_sink ())) {
|
||||
GST_ELEMENT_ERROR (sink, LIBRARY, SETTINGS, (NULL),
|
||||
("Failed to render video sink from GConf"));
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
gst_element_set_state (sink->kid, GST_STATE (sink));
|
||||
gst_bin_add (GST_BIN (sink), sink->kid);
|
||||
|
||||
/* re-attach ghostpad */
|
||||
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
sink->pad = gst_ghost_pad_new ("sink", targetpad);
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
if (peer) {
|
||||
GST_DEBUG_OBJECT (sink, "Linking...");
|
||||
gst_pad_link (peer, sink->pad);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "done changing gconf video sink");
|
||||
sink->init = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
cb_toggle_element (GConfClient * client,
|
||||
guint connection_id, GConfEntry * entry, gpointer data)
|
||||
{
|
||||
do_toggle_element (GST_GCONF_VIDEO_SINK (data));
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -148,12 +154,16 @@ gst_gconf_video_sink_change_state (GstElement * element)
|
|||
{
|
||||
GstGConfVideoSink *sink = GST_GCONF_VIDEO_SINK (element);
|
||||
|
||||
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
|
||||
cb_toggle_element (sink->client, 0,
|
||||
gconf_client_get_entry (sink->client,
|
||||
GST_GCONF_DIR "/default/videosink", NULL, TRUE, NULL), sink);
|
||||
if (!sink->init)
|
||||
return GST_STATE_FAILURE;
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
if (!do_toggle_element (sink))
|
||||
return GST_STATE_FAILURE;
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
gst_gconf_video_sink_reset (sink);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
|
||||
|
|
|
@ -45,7 +45,6 @@ typedef struct _GstGConfVideoSink {
|
|||
GConfClient *client;
|
||||
GstElement *kid;
|
||||
GstPad *pad;
|
||||
gboolean init;
|
||||
} GstGConfVideoSink;
|
||||
|
||||
typedef struct _GstGConfVideoSinkClass {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "gstautoaudiosink.h"
|
||||
#include "gstautodetect.h"
|
||||
|
||||
static void gst_auto_audio_sink_detect (GstAutoAudioSink * sink, gboolean fake);
|
||||
static GstElementStateReturn
|
||||
gst_auto_audio_sink_change_state (GstElement * element);
|
||||
|
||||
|
@ -60,13 +59,36 @@ gst_auto_audio_sink_class_init (GstAutoAudioSinkClass * klass)
|
|||
eklass->change_state = gst_auto_audio_sink_change_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to make initial linking work; ideally, this'd work even when
|
||||
* no target has been assigned to the ghostpad yet.
|
||||
*/
|
||||
|
||||
static void
|
||||
gst_auto_audio_sink_reset (GstAutoAudioSink * sink)
|
||||
{
|
||||
GstPad *targetpad;
|
||||
|
||||
/* fakesink placeholder */
|
||||
if (sink->kid) {
|
||||
gst_bin_remove (GST_BIN (sink), sink->kid);
|
||||
}
|
||||
sink->kid = gst_element_factory_make ("fakesink", "tempsink");
|
||||
gst_bin_add (GST_BIN (sink), sink->kid);
|
||||
|
||||
/* pad */
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_audio_sink_init (GstAutoAudioSink * sink)
|
||||
{
|
||||
sink->pad = NULL;
|
||||
sink->kid = NULL;
|
||||
gst_auto_audio_sink_detect (sink, TRUE);
|
||||
sink->init = FALSE;
|
||||
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
gst_auto_audio_sink_reset (sink);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -171,56 +193,35 @@ done:
|
|||
return choice;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_audio_sink_detect (GstAutoAudioSink * sink, gboolean fake)
|
||||
static gboolean
|
||||
gst_auto_audio_sink_detect (GstAutoAudioSink * sink)
|
||||
{
|
||||
GstElement *esink;
|
||||
GstPad *targetpad, *peer = NULL;
|
||||
GstPad *targetpad;
|
||||
|
||||
/* save ghostpad */
|
||||
if (sink->pad) {
|
||||
peer = GST_PAD_PEER (sink->pad);
|
||||
if (peer) {
|
||||
gst_pad_unlink (peer, sink->pad);
|
||||
GST_DEBUG_OBJECT (sink, "Element was linked, caching peer %p", peer);
|
||||
}
|
||||
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
|
||||
sink->pad = NULL;
|
||||
}
|
||||
|
||||
/* kill old element */
|
||||
if (sink->kid) {
|
||||
GST_DEBUG_OBJECT (sink, "Removing old kid");
|
||||
gst_bin_remove (GST_BIN (sink), sink->kid);
|
||||
sink->kid = NULL;
|
||||
}
|
||||
|
||||
/* find element */
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)", fake ? "fake" : "audio");
|
||||
if (fake) {
|
||||
esink = gst_element_factory_make ("fakesink", "temporary-sink");
|
||||
} else if (!(esink = gst_auto_audio_sink_find_best (sink))) {
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid");
|
||||
if (!(esink = gst_auto_audio_sink_find_best (sink))) {
|
||||
GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
|
||||
("Failed to find a supported audio sink"));
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
sink->kid = esink;
|
||||
gst_bin_add (GST_BIN (sink), esink);
|
||||
|
||||
/* attach ghost pad */
|
||||
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
|
||||
GST_DEBUG_OBJECT (sink, "Re-assigning ghostpad");
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
sink->pad = gst_ghost_pad_new ("sink", targetpad);
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
if (peer) {
|
||||
GST_DEBUG_OBJECT (sink, "Linking...");
|
||||
gst_pad_link (peer, sink->pad);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "done changing auto audio sink");
|
||||
sink->init = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -228,12 +229,20 @@ gst_auto_audio_sink_change_state (GstElement * element)
|
|||
{
|
||||
GstAutoAudioSink *sink = GST_AUTO_AUDIO_SINK (element);
|
||||
|
||||
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
|
||||
gst_auto_audio_sink_detect (sink, FALSE);
|
||||
if (!sink->init)
|
||||
return GST_STATE_FAILURE;
|
||||
GST_DEBUG_OBJECT (element, "Change state 0x%x",
|
||||
GST_STATE_TRANSITION (element));
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
if (!gst_auto_audio_sink_detect (sink))
|
||||
return GST_STATE_FAILURE;
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
gst_auto_audio_sink_reset (sink);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS, change_state,
|
||||
(element), GST_STATE_SUCCESS);
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ typedef struct _GstAutoAudioSink {
|
|||
/* explicit pointers to stuff used */
|
||||
GstPad *pad;
|
||||
GstElement *kid;
|
||||
gboolean init;
|
||||
} GstAutoAudioSink;
|
||||
|
||||
typedef struct _GstAutoAudioSinkClass {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "gstautovideosink.h"
|
||||
#include "gstautodetect.h"
|
||||
|
||||
static void gst_auto_video_sink_detect (GstAutoVideoSink * sink, gboolean fake);
|
||||
static GstElementStateReturn
|
||||
gst_auto_video_sink_change_state (GstElement * element);
|
||||
|
||||
|
@ -60,13 +59,36 @@ gst_auto_video_sink_class_init (GstAutoVideoSinkClass * klass)
|
|||
eklass->change_state = gst_auto_video_sink_change_state;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to make initial linking work; ideally, this'd work even when
|
||||
* no target has been assigned to the ghostpad yet.
|
||||
*/
|
||||
|
||||
static void
|
||||
gst_auto_video_sink_reset (GstAutoVideoSink * sink)
|
||||
{
|
||||
GstPad *targetpad;
|
||||
|
||||
/* fakesink placeholder */
|
||||
if (sink->kid) {
|
||||
gst_bin_remove (GST_BIN (sink), sink->kid);
|
||||
}
|
||||
sink->kid = gst_element_factory_make ("fakesink", "tempsink");
|
||||
gst_bin_add (GST_BIN (sink), sink->kid);
|
||||
|
||||
/* pad */
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_video_sink_init (GstAutoVideoSink * sink)
|
||||
{
|
||||
sink->pad = NULL;
|
||||
sink->kid = NULL;
|
||||
gst_auto_video_sink_detect (sink, TRUE);
|
||||
sink->init = FALSE;
|
||||
sink->pad = gst_ghost_pad_new_notarget ("sink", GST_PAD_SINK);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
gst_auto_video_sink_reset (sink);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -132,56 +154,35 @@ gst_auto_video_sink_find_best (GstAutoVideoSink * sink)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_video_sink_detect (GstAutoVideoSink * sink, gboolean fake)
|
||||
static gboolean
|
||||
gst_auto_video_sink_detect (GstAutoVideoSink * sink)
|
||||
{
|
||||
GstElement *esink;
|
||||
GstPad *targetpad, *peer = NULL;
|
||||
GstPad *targetpad;
|
||||
|
||||
/* save ghostpad */
|
||||
if (sink->pad) {
|
||||
peer = GST_PAD_PEER (sink->pad);
|
||||
if (peer) {
|
||||
gst_pad_unlink (peer, sink->pad);
|
||||
GST_DEBUG_OBJECT (sink, "Element was linked, caching peer %p", peer);
|
||||
}
|
||||
gst_element_remove_pad (GST_ELEMENT (sink), sink->pad);
|
||||
sink->pad = NULL;
|
||||
}
|
||||
|
||||
/* kill old element */
|
||||
if (sink->kid) {
|
||||
GST_DEBUG_OBJECT (sink, "Removing old kid");
|
||||
gst_bin_remove (GST_BIN (sink), sink->kid);
|
||||
sink->kid = NULL;
|
||||
}
|
||||
|
||||
/* find element */
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid (%ssink)", fake ? "fake" : "video");
|
||||
if (fake) {
|
||||
esink = gst_element_factory_make ("fakesink", "temporary-sink");
|
||||
} else if (!(esink = gst_auto_video_sink_find_best (sink))) {
|
||||
GST_DEBUG_OBJECT (sink, "Creating new kid");
|
||||
if (!(esink = gst_auto_video_sink_find_best (sink))) {
|
||||
GST_ELEMENT_ERROR (sink, LIBRARY, INIT, (NULL),
|
||||
("Failed to find a supported video sink"));
|
||||
return;
|
||||
return FALSE;
|
||||
}
|
||||
sink->kid = esink;
|
||||
gst_bin_add (GST_BIN (sink), esink);
|
||||
|
||||
/* attach ghost pad */
|
||||
GST_DEBUG_OBJECT (sink, "Creating new ghostpad");
|
||||
GST_DEBUG_OBJECT (sink, "Re-assigning ghostpad");
|
||||
targetpad = gst_element_get_pad (sink->kid, "sink");
|
||||
sink->pad = gst_ghost_pad_new ("sink", targetpad);
|
||||
gst_ghost_pad_set_target (GST_GHOST_PAD (sink->pad), targetpad);
|
||||
gst_object_unref (targetpad);
|
||||
gst_element_add_pad (GST_ELEMENT (sink), sink->pad);
|
||||
|
||||
if (peer) {
|
||||
GST_DEBUG_OBJECT (sink, "Linking...");
|
||||
gst_pad_link (peer, sink->pad);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (sink, "done changing auto video sink");
|
||||
sink->init = TRUE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static GstElementStateReturn
|
||||
|
@ -189,10 +190,19 @@ gst_auto_video_sink_change_state (GstElement * element)
|
|||
{
|
||||
GstAutoVideoSink *sink = GST_AUTO_VIDEO_SINK (element);
|
||||
|
||||
if (GST_STATE_TRANSITION (element) == GST_STATE_NULL_TO_READY && !sink->init) {
|
||||
gst_auto_video_sink_detect (sink, FALSE);
|
||||
if (!sink->init)
|
||||
return GST_STATE_FAILURE;
|
||||
GST_DEBUG_OBJECT (element, "Change state 0x%x",
|
||||
GST_STATE_TRANSITION (element));
|
||||
|
||||
switch (GST_STATE_TRANSITION (element)) {
|
||||
case GST_STATE_NULL_TO_READY:
|
||||
if (!gst_auto_video_sink_detect (sink))
|
||||
return GST_STATE_FAILURE;
|
||||
break;
|
||||
case GST_STATE_READY_TO_NULL:
|
||||
gst_auto_video_sink_reset (sink);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
|
||||
|
|
|
@ -43,7 +43,6 @@ typedef struct _GstAutoVideoSink {
|
|||
/* explicit pointers to stuff used */
|
||||
GstPad *pad;
|
||||
GstElement *kid;
|
||||
gboolean init;
|
||||
} GstAutoVideoSink;
|
||||
|
||||
typedef struct _GstAutoVideoSinkClass {
|
||||
|
|
Loading…
Reference in a new issue