From: <wt...@ke...> - 2008-12-10 17:39:57
|
CVS Root: /cvs/gstreamer Module: gst-plugins-base Changes by: wtay Date: Wed Dec 10 2008 17:39:47 UTC Log message: * gst/playback/gstplaysink.c: (gst_play_sink_class_init), (gst_play_sink_dispose), (gst_play_sink_finalize), (try_element), (gen_video_chain), (gen_audio_chain), (gst_play_sink_reconfigure), (gst_play_sink_send_event), (gst_play_sink_change_state): Use G_DEFINE_TYPE. Try to set the selected sink to READY before using it. This will allow for detection of incompatible formats sooner. Don't cause a fatal error when conversion elements are missing but post a missing-element message and a warning instead because things might still link and run fine. Simplyfy the construction of audio and video sink chains. Modified files: . : ChangeLog gst/playback : gstplaysink.c Links: http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/ChangeLog.diff?r1=1.4239&r2=1.4240 http://freedesktop.org/cgi-bin/viewcvs.cgi/gstreamer/gst-plugins-base/gst/playback/gstplaysink.c.diff?r1=1.20&r2=1.21 ====Begin Diffs==== Index: ChangeLog =================================================================== RCS file: /cvs/gstreamer/gst-plugins-base/ChangeLog,v retrieving revision 1.4239 retrieving revision 1.4240 diff -u -d -r1.4239 -r1.4240 --- ChangeLog 10 Dec 2008 14:55:08 -0000 1.4239 +++ ChangeLog 10 Dec 2008 17:39:31 -0000 1.4240 @@ -1,5 +1,19 @@ 2008-12-10 Wim Taymans <wim...@co...> + * gst/playback/gstplaysink.c: (gst_play_sink_class_init), + (gst_play_sink_dispose), (gst_play_sink_finalize), (try_element), + (gen_video_chain), (gen_audio_chain), (gst_play_sink_reconfigure), + (gst_play_sink_send_event), (gst_play_sink_change_state): + Use G_DEFINE_TYPE. + Try to set the selected sink to READY before using it. This will allow + for detection of incompatible formats sooner. + Don't cause a fatal error when conversion elements are missing but post + a missing-element message and a warning instead because things might + still link and run fine. + Simplyfy the construction of audio and video sink chains. + +2008-12-10 Wim Taymans <wim...@co...> * ext/ogg/gstoggdemux.c: (gst_ogg_pad_class_init), (gst_ogg_pad_dispose), (gst_ogg_pad_finalize): Use G_DEFINE_TYPE for the OggPad to get some threadsafe type Index: gstplaysink.c RCS file: /cvs/gstreamer/gst-plugins-base/gst/playback/gstplaysink.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- gstplaysink.c 22 Nov 2008 14:31:43 -0000 1.20 +++ gstplaysink.c 10 Dec 2008 17:39:32 -0000 1.21 @@ -170,8 +170,6 @@ static GstStateChangeReturn gst_play_sink_change_state (GstElement * element, GstStateChange transition); -static GstElementClass *parent_class; - /* static guint gst_play_sink_signals[LAST_SIGNAL] = { 0 }; */ static const GstElementDetails gst_play_sink_details = @@ -180,31 +178,7 @@ "Autoplug and play media from an uri", "Wim Taymans <wim...@gm...>"); -GType -gst_play_sink_get_type (void) -{ - static GType gst_play_sink_type = 0; - if (!gst_play_sink_type) { - static const GTypeInfo gst_play_sink_info = { - sizeof (GstPlaySinkClass), - NULL, - (GClassInitFunc) gst_play_sink_class_init, - sizeof (GstPlaySink), - 0, - (GInstanceInitFunc) gst_play_sink_init, - NULL - }; - gst_play_sink_type = g_type_register_static (GST_TYPE_BIN, - "GstPlaySink", &gst_play_sink_info, 0); - } - return gst_play_sink_type; -} +G_DEFINE_TYPE (GstPlaySink, gst_play_sink, GST_TYPE_BIN); static void gst_play_sink_class_init (GstPlaySinkClass * klass) @@ -217,8 +191,6 @@ gstelement_klass = (GstElementClass *) klass; gstbin_klass = (GstBinClass *) klass; - parent_class = g_type_class_peek_parent (klass); gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_play_sink_dispose); gobject_klass->finalize = GST_DEBUG_FUNCPTR (gst_play_sink_finalize); @@ -270,7 +242,7 @@ g_free (playsink->font_desc); playsink->font_desc = NULL; - G_OBJECT_CLASS (parent_class)->dispose (object); + G_OBJECT_CLASS (gst_play_sink_parent_class)->dispose (object); } @@ -282,7 +254,7 @@ g_mutex_free (playsink->lock); - G_OBJECT_CLASS (parent_class)->finalize (object); + G_OBJECT_CLASS (gst_play_sink_parent_class)->finalize (object); void @@ -636,6 +608,26 @@ return result; +/* try to change the state of an element. This function returns the element when + * the state change could be performed. When this function returns NULL an error + * occured and the element is unreffed. */ +static GstElement * +try_element (GstPlaySink * playsink, GstElement * element) +{ + GstStateChangeReturn ret; + if (element) { + ret = gst_element_set_state (element, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) { + GST_DEBUG_OBJECT (playsink, "failed state change.."); + gst_element_set_state (element, GST_STATE_NULL); + gst_object_unref (element); + element = NULL; + } + } + return element; +} /* make the element (bin) that contains the elements needed to perform * video display. * @@ -655,6 +647,7 @@ GstPlayVideoChain *chain; GstBin *bin; GstPad *pad; + GstElement *prev, *elem; chain = g_new0 (GstPlayVideoChain, 1); chain->chain.playsink = gst_object_ref (playsink); @@ -662,15 +655,22 @@ GST_DEBUG_OBJECT (playsink, "making video chain %p", chain); if (playsink->video_sink) { - chain->sink = gst_object_ref (playsink->video_sink); - } else { - chain->sink = gst_element_factory_make ("autovideosink", "videosink"); - if (chain->sink == NULL) { - chain->sink = gst_element_factory_make ("xvimagesink", "videosink"); - } - if (chain->sink == NULL) - goto no_sinks; + GST_DEBUG_OBJECT (playsink, "trying configured videosink"); + elem = gst_object_ref (playsink->video_sink); + chain->sink = try_element (playsink, elem); + if (chain->sink == NULL) { + GST_DEBUG_OBJECT (playsink, "trying autovideosink"); + elem = gst_element_factory_make ("autovideosink", "videosink"); + GST_DEBUG_OBJECT (playsink, "trying xvimagesink"); + elem = gst_element_factory_make ("xvimagesink", "videosink"); } + if (chain->sink == NULL) + goto no_sinks; /* if we can disable async behaviour of the sink, we can avoid adding a * queue for the audio chain. We can't use the deep property here because the @@ -680,8 +680,10 @@ async); g_object_set (chain->sink, "async", async, NULL); chain->async = async; - } else + } else { + GST_DEBUG_OBJECT (playsink, "no async property on the sink"); chain->async = TRUE; /* create a bin to hold objects, as we create them we add them to this bin so * that when something goes wrong we only need to unref the bin */ @@ -691,18 +693,6 @@ gst_object_sink (bin); gst_bin_add (bin, chain->sink); - if (raw) { - chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); - if (chain->conv == NULL) - goto no_colorspace; - gst_bin_add (bin, chain->conv); - chain->scale = gst_element_factory_make ("videoscale", "vscale"); - if (chain->scale == NULL) - goto no_videoscale; - gst_bin_add (bin, chain->scale); /* decouple decoder from sink, this improves playback quite a lot since the * decoder can continue while the sink blocks for synchronisation. We don't * need a lot of buffers as this consumes a lot of memory and we don't want @@ -711,24 +701,49 @@ g_object_set (G_OBJECT (chain->queue), "max-size-buffers", 3, "max-size-bytes", 0, "max-size-time", (gint64) 0, NULL); gst_bin_add (bin, chain->queue); + prev = chain->queue; if (raw) { - gst_element_link_pads (chain->queue, "src", chain->conv, "sink"); - gst_element_link_pads (chain->conv, "src", chain->scale, "sink"); - /* be more careful with the pad from the custom sink element, it might not - * be named 'sink' */ - if (!gst_element_link_pads (chain->scale, "src", chain->sink, NULL)) - goto link_failed; + GST_DEBUG_OBJECT (playsink, "creating ffmpegcolorspace"); + chain->conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); + if (chain->conv == NULL) { + post_missing_element_message (playsink, "ffmpegcolorspace"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "ffmpegcolorspace"), (NULL)); + } else { + gst_bin_add (bin, chain->conv); + if (!gst_element_link_pads (prev, "src", chain->conv, "sink")) + goto link_failed; - pad = gst_element_get_static_pad (chain->queue, "sink"); - if (!gst_element_link_pads (chain->queue, "src", chain->sink, NULL)) + prev = chain->conv; + GST_DEBUG_OBJECT (playsink, "creating videoscale"); + chain->scale = gst_element_factory_make ("videoscale", "vscale"); + if (chain->scale == NULL) { + post_missing_element_message (playsink, "videoscale"); + "videoscale"), ("possibly a liboil version mismatch?")); + gst_bin_add (bin, chain->scale); + if (!gst_element_link_pads (prev, "src", chain->scale, "sink")) + prev = chain->scale; + /* be more careful with the pad from the custom sink element, it might not + * be named 'sink' */ + if (!gst_element_link_pads (prev, "src", chain->sink, NULL)) + goto link_failed; + pad = gst_element_get_static_pad (chain->queue, "sink"); chain->sinkpad = gst_ghost_pad_new ("sink", pad); gst_object_unref (pad); gst_element_add_pad (chain->chain.bin, chain->sinkpad); return chain; @@ -743,24 +758,6 @@ free_chain ((GstPlayChain *) chain); return NULL; -no_colorspace: - { - post_missing_element_message (playsink, "ffmpegcolorspace"); - GST_ELEMENT_ERROR (playsink, CORE, MISSING_PLUGIN, - (_("Missing element '%s' - check your GStreamer installation."), - "ffmpegcolorspace"), (NULL)); - free_chain ((GstPlayChain *) chain); - return NULL; -no_videoscale: - post_missing_element_message (playsink, "videoscale"); - "videoscale"), ("possibly a liboil version mismatch?")); link_failed: { GST_ELEMENT_ERROR (playsink, CORE, PAD, @@ -879,8 +876,9 @@ { GstPlayAudioChain *chain; - gboolean res, have_volume; + gboolean have_volume; + GstElement *head, *prev, *elem; chain = g_new0 (GstPlayAudioChain, 1); @@ -888,15 +886,24 @@ GST_DEBUG_OBJECT (playsink, "making audio chain %p", chain); if (playsink->audio_sink) { - chain->sink = gst_object_ref (playsink->audio_sink); - chain->sink = gst_element_factory_make ("autoaudiosink", "audiosink"); - chain->sink = gst_element_factory_make ("alsasink", "audiosink"); + GST_DEBUG_OBJECT (playsink, "trying configured audiosink"); + elem = gst_object_ref (playsink->audio_sink); + GST_DEBUG_OBJECT (playsink, "trying autoaudiosink"); + elem = gst_element_factory_make ("autoaudiosink", "audiosink"); + GST_DEBUG_OBJECT (playsink, "trying alsasink"); + elem = gst_element_factory_make ("alsasink", "audiosink"); chain->chain.bin = gst_bin_new ("abin"); bin = GST_BIN_CAST (chain->chain.bin); gst_object_ref (bin); @@ -909,6 +916,10 @@ GST_DEBUG_OBJECT (playsink, "adding audio queue"); chain->queue = gst_element_factory_make ("queue", "aqueue"); gst_bin_add (bin, chain->queue); + prev = head = chain->queue; + head = chain->sink; + prev = NULL; /* check if the sink has the volume property, if it does we don't need to @@ -934,60 +945,80 @@ chain->conv = gst_element_factory_make ("audioconvert", "aconv"); - goto no_audioconvert; + post_missing_element_message (playsink, "audioconvert"); + "audioconvert"), ("possibly a liboil version mismatch?")); + if (prev) { + if (!gst_element_link_pads (prev, "src", chain->conv, "sink")) + goto link_failed; + } else { + head = chain->conv; + } chain->resample = gst_element_factory_make ("audioresample", "aresample"); - if (chain->resample == NULL) - goto no_audioresample; - gst_bin_add (bin, chain->resample); - res = gst_element_link_pads (chain->conv, "src", chain->resample, "sink"); + if (chain->resample == NULL) { + post_missing_element_message (playsink, "audioresample"); + "audioresample"), ("possibly a liboil version mismatch?")); + gst_bin_add (bin, chain->resample); + if (!gst_element_link_pads (prev, "src", chain->resample, "sink")) + head = chain->resample; + prev = chain->resample; if (!have_volume && playsink->flags & GST_PLAY_FLAG_SOFT_VOLUME) { chain->volume = gst_element_factory_make ("volume", "volume"); - if (chain->volume == NULL) - goto no_volume; - have_volume = TRUE; - /* volume also has the mute property */ - chain->mute = gst_object_ref (chain->volume); + if (chain->volume == NULL) { + post_missing_element_message (playsink, "volume"); + GST_ELEMENT_WARNING (playsink, CORE, MISSING_PLUGIN, + (_("Missing element '%s' - check your GStreamer installation."), + "volume"), ("possibly a liboil version mismatch?")); + have_volume = TRUE; - /* configure with the latest volume and mute */ - g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, NULL); - g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL); - gst_bin_add (bin, chain->volume); + /* volume also has the mute property */ + chain->mute = gst_object_ref (chain->volume); - res &= - gst_element_link_pads (chain->resample, "src", chain->volume, "sink"); - res &= gst_element_link_pads (chain->volume, "src", chain->sink, NULL); - } else { - res &= gst_element_link_pads (chain->resample, "src", chain->sink, NULL); - if (!res) + /* configure with the latest volume and mute */ + g_object_set (G_OBJECT (chain->volume), "volume", playsink->volume, + NULL); + g_object_set (G_OBJECT (chain->mute), "mute", playsink->mute, NULL); + gst_bin_add (bin, chain->volume); - if (queue) { - res = gst_element_link_pads (chain->queue, "src", chain->conv, "sink"); - pad = gst_element_get_static_pad (chain->queue, "sink"); - pad = gst_element_get_static_pad (chain->conv, "sink"); - res = gst_element_link_pads (chain->queue, "src", chain->sink, "sink"); - pad = gst_element_get_static_pad (chain->sink, "sink"); + if (prev) { + if (!gst_element_link_pads (prev, "src", chain->volume, "sink")) + goto link_failed; + } else { + head = chain->volume; + } + prev = chain->volume; } /* post a warning if we have no way to configure the volume */ if (!have_volume) { GST_ELEMENT_WARNING (playsink, STREAM, NOT_IMPLEMENTED, (_("No volume control found")), ("No volume control found")); + /* and ghost the sinkpad of the headmost element */ + pad = gst_element_get_static_pad (head, "sink"); @@ -1003,33 +1034,6 @@ -no_audioconvert: - post_missing_element_message (playsink, "audioconvert"); - "audioconvert"), ("possibly a liboil version mismatch?")); -no_audioresample: - post_missing_element_message (playsink, "audioresample"); - "audioresample"), ("possibly a liboil version mismatch?")); -no_volume: - post_missing_element_message (playsink, "volume"); - "volume"), ("possibly a liboil version mismatch?")); @@ -1175,7 +1179,8 @@ /* figure out which components we need */ if (flags & GST_PLAY_FLAG_TEXT && playsink->text_pad) { - /* we need video too */ + /* we have a text_pad and we need text rendering, in this case we need a + * video_pad to combine the video with the text */ if (!playsink->video_pad) goto subs_but_no_video; @@ -1593,7 +1598,9 @@ res = gst_play_sink_send_event_to_sink (GST_PLAY_SINK (element), event); break; default: - res = parent_class->send_event (element, event); + res = + GST_ELEMENT_CLASS (gst_play_sink_parent_class)->send_event (element, + event); return res; @@ -1614,7 +1621,9 @@ - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + ret = + GST_ELEMENT_CLASS (gst_play_sink_parent_class)->change_state (element, + transition); if (ret == GST_STATE_CHANGE_FAILURE) return ret; |