From a85131e7ca4f737a5b8fb7d276ebf87e18fcbc04 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 8 Oct 2004 11:30:32 +0000 Subject: [PATCH] gst/playback/: Reuse the audio and video bins. Original commit message from CVS: * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), (gst_decode_bin_init), (find_compatibles), (close_pad_link), (try_to_link_1), (no_more_pads), (close_link), (type_found): * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), (unknown_type), (gst_play_base_bin_remove_element), (gst_play_base_bin_link_stream): * gst/playback/gstplaybasebin.h: * gst/playback/gstplaybin.c: (gst_play_bin_init), (gst_play_bin_set_property), (gen_video_element), (gen_audio_element), (setup_sinks): * gst/playback/gststreaminfo.c: (gst_stream_type_get_type), (gst_stream_info_get_type), (gst_stream_info_class_init), (gst_stream_info_init), (gst_stream_info_new), (gst_stream_info_dispose), (stream_info_mute_pad), (gst_stream_info_set_property), (gst_stream_info_get_property): * gst/playback/gststreaminfo.h: Reuse the audio and video bins. Some internal cleanups in the stream selection code. --- ChangeLog | 21 ++++++++++ gst/playback/gstdecodebin.c | 13 +++--- gst/playback/gstplaybasebin.c | 78 ++++++----------------------------- gst/playback/gstplaybasebin.h | 6 --- gst/playback/gstplaybin.c | 61 +++++++++++++++++++++++---- gst/playback/gststreaminfo.c | 60 ++++++++++++++++++++++++++- gst/playback/gststreaminfo.h | 5 ++- 7 files changed, 155 insertions(+), 89 deletions(-) diff --git a/ChangeLog b/ChangeLog index b82f2ca5d3..79741d96db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,24 @@ +2004-10-08 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_class_init), + (gst_decode_bin_init), (find_compatibles), (close_pad_link), + (try_to_link_1), (no_more_pads), (close_link), (type_found): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_class_init), + (unknown_type), (gst_play_base_bin_remove_element), + (gst_play_base_bin_link_stream): + * gst/playback/gstplaybasebin.h: + * gst/playback/gstplaybin.c: (gst_play_bin_init), + (gst_play_bin_set_property), (gen_video_element), + (gen_audio_element), (setup_sinks): + * gst/playback/gststreaminfo.c: (gst_stream_type_get_type), + (gst_stream_info_get_type), (gst_stream_info_class_init), + (gst_stream_info_init), (gst_stream_info_new), + (gst_stream_info_dispose), (stream_info_mute_pad), + (gst_stream_info_set_property), (gst_stream_info_get_property): + * gst/playback/gststreaminfo.h: + Reuse the audio and video bins. + Some internal cleanups in the stream selection code. + 2004-10-08 Julien MOUTTE * sys/ximage/ximagesink.c: (gst_ximagesink_sink_link), diff --git a/gst/playback/gstdecodebin.c b/gst/playback/gstdecodebin.c index e7253019d5..8da8a1257e 100644 --- a/gst/playback/gstdecodebin.c +++ b/gst/playback/gstdecodebin.c @@ -73,7 +73,7 @@ struct _GstDecodeBinClass /* signal we fire when a new pad has been decoded into raw audio/video */ void (*new_decoded_pad) (GstElement * element, GstPad * pad, gboolean last); /* signal fired when we found a pad that we cannot decode */ - void (*unknown_type) (GstElement * element, GstCaps * caps); + void (*unknown_type) (GstElement * element, GstPad * pad, GstCaps * caps); }; /* props */ @@ -187,7 +187,8 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass) gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE] = g_signal_new ("unknown-type", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstDecodeBinClass, unknown_type), - NULL, NULL, gst_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GST_TYPE_CAPS); + NULL, NULL, gst_marshal_VOID__POINTER_OBJECT, G_TYPE_NONE, 2, + GST_TYPE_PAD, GST_TYPE_CAPS); gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_decode_bin_dispose); @@ -374,9 +375,9 @@ close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps, /* the caps is empty, this means the pad has no type, we can only * decide to fire the unknown_type signal. */ - if (gst_caps_is_empty (caps)) { + if (caps == NULL || gst_caps_is_empty (caps)) { g_signal_emit (G_OBJECT (decode_bin), - gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, caps); + gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); return; } @@ -423,15 +424,13 @@ close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps, /* no compatible elements, fire the unknown_type signal, we cannot go * on */ g_signal_emit (G_OBJECT (decode_bin), - gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, caps); + gst_decode_bin_signals[SIGNAL_UNKNOWN_TYPE], 0, pad, caps); return; } try_to_link_1 (decode_bin, pad, to_try); } else { GST_LOG_OBJECT (element, "multiple possibilities, delaying"); - g_warning ("multiple possibilities, delaying"); } - } /* given a list of element factories, try to link one of the factories diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c index 1ce48cbbfc..e5a3cfc6f5 100644 --- a/gst/playback/gstplaybasebin.c +++ b/gst/playback/gstplaybasebin.c @@ -136,11 +136,6 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass) GST_DEBUG_CATEGORY_INIT (gst_play_base_bin_debug, "playbasebin", 0, "playbasebin"); - gst_play_base_bin_signals[MUTE_STREAM_SIGNAL] = - g_signal_new ("mute-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstPlayBaseBinClass, mute_stream), - NULL, NULL, gst_marshal_VOID__OBJECT_POINTER, G_TYPE_NONE, 2, - G_TYPE_OBJECT, G_TYPE_BOOLEAN); gst_play_base_bin_signals[LINK_STREAM_SIGNAL] = g_signal_new ("link-stream", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (GstPlayBaseBinClass, link_stream), @@ -162,7 +157,6 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass) gstbin_klass->remove_element = GST_DEBUG_FUNCPTR (gst_play_base_bin_remove_element); - klass->mute_stream = gst_play_base_bin_mute_stream; klass->link_stream = gst_play_base_bin_link_stream; klass->unlink_stream = gst_play_base_bin_unlink_stream; } @@ -256,13 +250,19 @@ remove_prerolls (GstPlayBaseBin * play_base_bin) } static void -unknown_type (GstElement * element, GstCaps * caps, +unknown_type (GstElement * element, GstPad * pad, GstCaps * caps, GstPlayBaseBin * play_base_bin) { - gchar *capsstr = gst_caps_to_string (caps); + gchar *capsstr; + GstStreamInfo *info; + capsstr = gst_caps_to_string (caps); g_warning ("don't know how to handle %s", capsstr); + /* add the stream to the list */ + info = gst_stream_info_new (pad, GST_STREAM_TYPE_UNKNOWN, NULL); + play_base_bin->streaminfo = g_list_append (play_base_bin->streaminfo, info); + g_free (capsstr); } @@ -683,6 +683,9 @@ gst_play_base_bin_remove_element (GstBin * bin, GstElement * element) if (!thread) { g_warning ("cannot find element to remove"); } else { + /* we remove the element from the thread first so that the + * state is not affected when someone holds a reference to it */ + gst_bin_remove (GST_BIN (thread), element); element = thread; } } @@ -739,63 +742,6 @@ gst_play_base_bin_found_tag (GstElement * element, gst_object_unref (parent); } -static void -play_base_bin_mute_pad (GstPlayBaseBin * play_base_bin, - GstPad * pad, gboolean mute) -{ - GList *int_links; - gboolean activate = !mute; - gchar *debug_str = (activate ? "activate" : "inactivate"); - - GST_DEBUG_OBJECT (play_base_bin, "%s %s:%s", debug_str, - GST_DEBUG_PAD_NAME (pad)); - gst_pad_set_active (pad, activate); - - for (int_links = gst_pad_get_internal_links (pad); - int_links; int_links = g_list_next (int_links)) { - GstPad *pad = GST_PAD (int_links->data); - GstPad *peer = gst_pad_get_peer (pad); - GstElement *peer_elem = gst_pad_get_parent (peer); - - GST_DEBUG_OBJECT (play_base_bin, "%s internal pad %s:%s", - debug_str, GST_DEBUG_PAD_NAME (pad)); - - gst_pad_set_active (pad, activate); - - if (peer_elem->numsrcpads == 1) { - GST_DEBUG_OBJECT (play_base_bin, "recursing element %s on pad %s:%s", - gst_element_get_name (peer_elem), GST_DEBUG_PAD_NAME (peer)); - play_base_bin_mute_pad (play_base_bin, peer, mute); - } else { - GST_DEBUG_OBJECT (play_base_bin, "%s final pad %s:%s", - debug_str, GST_DEBUG_PAD_NAME (peer)); - gst_pad_set_active (peer, activate); - } - } -} - -/* muting a stream follows the flow downstream and dis/enables all - * pads it encounters until an element with more than one source pad - * (a demuxer or equivalent) is met. - */ -void -gst_play_base_bin_mute_stream (GstPlayBaseBin * play_base_bin, - GstStreamInfo * info, gboolean mute) -{ - GST_DEBUG ("mute stream"); - - g_return_if_fail (play_base_bin != NULL); - g_return_if_fail (GST_IS_PLAY_BASE_BIN (play_base_bin)); - g_return_if_fail (info != NULL); - g_return_if_fail (GST_IS_STREAM_INFO (info)); - - /* check if info contains a pad */ - if (info->pad == NULL) - return; - - play_base_bin_mute_pad (play_base_bin, info->pad, mute); -} - void gst_play_base_bin_link_stream (GstPlayBaseBin * play_base_bin, GstStreamInfo * info, GstPad * pad) @@ -821,7 +767,7 @@ gst_play_base_bin_link_stream (GstPlayBaseBin * play_base_bin, if (info) { if (!gst_pad_link (info->pad, pad)) { GST_DEBUG ("could not link"); - gst_play_base_bin_mute_stream (play_base_bin, info, TRUE); + g_object_set (G_OBJECT (info), "mute", TRUE, NULL); } } else { GST_DEBUG ("could not find pad to link"); diff --git a/gst/playback/gstplaybasebin.h b/gst/playback/gstplaybasebin.h index 405e5a7806..5ab688ce68 100644 --- a/gst/playback/gstplaybasebin.h +++ b/gst/playback/gstplaybasebin.h @@ -66,9 +66,6 @@ struct _GstPlayBaseBin { struct _GstPlayBaseBinClass { GstBinClass parent_class; - void (*mute_stream) (GstPlayBaseBin *play_base_bin, - GstStreamInfo *info, - gboolean mute); void (*link_stream) (GstPlayBaseBin *play_base_bin, GstStreamInfo *info, GstPad *pad); @@ -83,9 +80,6 @@ const GList* gst_play_base_bin_get_streaminfo (GstPlayBaseBin *play_base_bin); gint gst_play_base_bin_get_nstreams_of_type (GstPlayBaseBin *play_base_bin, GstStreamType type); -void gst_play_base_bin_mute_stream (GstPlayBaseBin *play_base_bin, - GstStreamInfo *info, - gboolean mute); void gst_play_base_bin_link_stream (GstPlayBaseBin *play_base_bin, GstStreamInfo *info, GstPad *pad); diff --git a/gst/playback/gstplaybin.c b/gst/playback/gstplaybin.c index d38363ecdb..38fe300b25 100644 --- a/gst/playback/gstplaybin.c +++ b/gst/playback/gstplaybin.c @@ -48,11 +48,13 @@ struct _GstPlayBin GstElement *video_sink; GstElement *visualisation; GstElement *volume_element; - float volume; + gfloat volume; GList *sinks; GList *seekables; + + GHashTable *cache; }; struct _GstPlayBinClass @@ -194,6 +196,7 @@ gst_play_bin_init (GstPlayBin * play_bin) play_bin->volume = 1.0; play_bin->seekables = NULL; play_bin->sinks = NULL; + play_bin->cache = g_hash_table_new (g_str_hash, g_str_equal); GST_FLAG_SET (play_bin, GST_BIN_SELF_SCHEDULABLE); } @@ -222,11 +225,31 @@ gst_play_bin_set_property (GObject * object, guint prop_id, switch (prop_id) { case ARG_VIDEO_SINK: + { + GstElement *element; + play_bin->video_sink = g_value_get_object (value); + + element = g_hash_table_lookup (play_bin->cache, "vbin"); + if (element != NULL) { + g_hash_table_remove (play_bin->cache, "vbin"); + g_object_unref (G_OBJECT (element)); + } break; + } case ARG_AUDIO_SINK: + { + GstElement *element; + play_bin->audio_sink = g_value_get_object (value); + + element = g_hash_table_lookup (play_bin->cache, "abin"); + if (element != NULL) { + g_hash_table_remove (play_bin->cache, "abin"); + g_object_unref (G_OBJECT (element)); + } break; + } case ARG_VIS_PLUGIN: play_bin->visualisation = g_value_get_object (value); break; @@ -281,6 +304,13 @@ gen_video_element (GstPlayBin * play_bin) GstElement *scale; GstElement *sink; + element = g_hash_table_lookup (play_bin->cache, "vbin"); + if (element != NULL) { + g_object_ref (G_OBJECT (element)); + sink = gst_bin_get_by_name (GST_BIN (element), "sink"); + goto done; + } + element = gst_bin_new ("vbin"); conv = gst_element_factory_make ("ffmpegcolorspace", "vconv"); scale = gst_element_factory_make ("videoscale", "vscale"); @@ -291,8 +321,6 @@ gen_video_element (GstPlayBin * play_bin) sink = gst_element_factory_make ("ximagesink", "sink"); } - play_bin->seekables = g_list_append (play_bin->seekables, sink); - gst_bin_add (GST_BIN (element), conv); gst_bin_add (GST_BIN (element), scale); gst_bin_add (GST_BIN (element), sink); @@ -304,6 +332,13 @@ gen_video_element (GstPlayBin * play_bin) gst_element_set_state (element, GST_STATE_READY); + /* ref before adding to the cache */ + g_object_ref (G_OBJECT (element)); + g_hash_table_insert (play_bin->cache, "vbin", element); + +done: + play_bin->seekables = g_list_append (play_bin->seekables, sink); + return element; } @@ -316,6 +351,12 @@ gen_audio_element (GstPlayBin * play_bin) GstElement *volume; GstElement *scale; + element = g_hash_table_lookup (play_bin->cache, "abin"); + if (element != NULL) { + g_object_ref (G_OBJECT (element)); + sink = gst_bin_get_by_name (GST_BIN (element), "sink"); + goto done; + } element = gst_bin_new ("abin"); conv = gst_element_factory_make ("audioconvert", "aconv"); scale = gst_element_factory_make ("audioscale", "ascale"); @@ -331,8 +372,6 @@ gen_audio_element (GstPlayBin * play_bin) sink = gst_element_factory_make ("osssink", "sink"); } - play_bin->seekables = g_list_prepend (play_bin->seekables, sink); - gst_bin_add (GST_BIN (element), conv); gst_bin_add (GST_BIN (element), scale); gst_bin_add (GST_BIN (element), volume); @@ -347,6 +386,13 @@ gen_audio_element (GstPlayBin * play_bin) gst_element_set_state (element, GST_STATE_READY); + /* ref before adding to the cache */ + g_object_ref (G_OBJECT (element)); + g_hash_table_insert (play_bin->cache, "abin", element); + +done: + play_bin->seekables = g_list_prepend (play_bin->seekables, sink); + return element; } @@ -380,7 +426,7 @@ setup_sinks (GstPlayBin * play_bin) for (s = streaminfo; s; s = g_list_next (s)) { GObject *obj = G_OBJECT (s->data); - int type; + gint type; GstPad *srcpad, *sinkpad; GstElement *sink = NULL; gboolean res; @@ -431,8 +477,7 @@ setup_sinks (GstPlayBin * play_bin) } } if (mute) { - gst_play_base_bin_mute_stream (GST_PLAY_BASE_BIN (play_bin), - GST_STREAM_INFO (obj), TRUE); + g_object_set (G_OBJECT (obj), "mute", TRUE, NULL); } } } diff --git a/gst/playback/gststreaminfo.c b/gst/playback/gststreaminfo.c index 16483c1373..d38a76f9b5 100644 --- a/gst/playback/gststreaminfo.c +++ b/gst/playback/gststreaminfo.c @@ -32,14 +32,18 @@ enum ARG_PAD, ARG_TYPE, ARG_DECODER, + ARG_MUTE, }; /* signals */ enum { + SIGNAL_MUTED, LAST_SIGNAL }; +static guint gst_stream_info_signals[LAST_SIGNAL] = { 0 }; + #define GST_TYPE_STREAM_TYPE (gst_stream_type_get_type()) static GType gst_stream_type_get_type (void) @@ -89,7 +93,6 @@ gst_stream_info_get_type (void) (GInstanceInitFunc) gst_stream_info_init, NULL }; - gst_stream_info_type = g_type_register_static (G_TYPE_OBJECT, "GstStreamInfo", &gst_stream_info_info, 0); } @@ -118,6 +121,14 @@ gst_stream_info_class_init (GstStreamInfoClass * klass) g_object_class_install_property (gobject_klass, ARG_DECODER, g_param_spec_string ("decoder", "Decoder", "The decoder used to decode the stream", NULL, G_PARAM_READABLE)); + g_object_class_install_property (gobject_klass, ARG_MUTE, + g_param_spec_boolean ("mute", "Mute", "Mute or unmute this stream", FALSE, + G_PARAM_READWRITE)); + + gst_stream_info_signals[SIGNAL_MUTED] = + g_signal_new ("muted", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstStreamInfoClass, muted), NULL, NULL, + gst_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); gobject_klass->dispose = GST_DEBUG_FUNCPTR (gst_stream_info_dispose); } @@ -129,6 +140,7 @@ gst_stream_info_init (GstStreamInfo * stream_info) stream_info->pad = NULL; stream_info->type = GST_STREAM_TYPE_UNKNOWN; stream_info->decoder = NULL; + stream_info->mute = FALSE; } GstStreamInfo * @@ -163,6 +175,39 @@ gst_stream_info_dispose (GObject * object) } } +static void +stream_info_mute_pad (GstStreamInfo * stream_info, GstPad * pad, gboolean mute) +{ + GList *int_links; + gboolean activate = !mute; + gchar *debug_str = (activate ? "activate" : "inactivate"); + + GST_DEBUG_OBJECT (stream_info, "%s %s:%s", debug_str, + GST_DEBUG_PAD_NAME (pad)); + gst_pad_set_active (pad, activate); + + for (int_links = gst_pad_get_internal_links (pad); + int_links; int_links = g_list_next (int_links)) { + GstPad *pad = GST_PAD (int_links->data); + GstPad *peer = gst_pad_get_peer (pad); + GstElement *peer_elem = gst_pad_get_parent (peer); + + GST_DEBUG_OBJECT (stream_info, "%s internal pad %s:%s", + debug_str, GST_DEBUG_PAD_NAME (pad)); + + gst_pad_set_active (pad, activate); + + if (peer_elem->numsrcpads == 1) { + GST_DEBUG_OBJECT (stream_info, "recursing element %s on pad %s:%s", + gst_element_get_name (peer_elem), GST_DEBUG_PAD_NAME (peer)); + stream_info_mute_pad (stream_info, peer, mute); + } else { + GST_DEBUG_OBJECT (stream_info, "%s final pad %s:%s", + debug_str, GST_DEBUG_PAD_NAME (peer)); + gst_pad_set_active (peer, activate); + } + } +} static void gst_stream_info_set_property (GObject * object, guint prop_id, @@ -175,6 +220,16 @@ gst_stream_info_set_property (GObject * object, guint prop_id, stream_info = GST_STREAM_INFO (object); switch (prop_id) { + case ARG_MUTE: + { + gboolean new_mute = g_value_get_boolean (value); + + if (new_mute != stream_info->mute) { + stream_info->mute = new_mute; + stream_info_mute_pad (stream_info, stream_info->pad, new_mute); + } + break; + } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -201,6 +256,9 @@ gst_stream_info_get_property (GObject * object, guint prop_id, GValue * value, case ARG_DECODER: g_value_set_string (value, stream_info->decoder); break; + case ARG_MUTE: + g_value_set_boolean (value, stream_info->mute); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/playback/gststreaminfo.h b/gst/playback/gststreaminfo.h index d0d186d1de..22d34dd0e3 100644 --- a/gst/playback/gststreaminfo.h +++ b/gst/playback/gststreaminfo.h @@ -47,17 +47,20 @@ struct _GstStreamInfo { GstPad *pad; GstStreamType type; gchar *decoder; + gboolean mute; }; struct _GstStreamInfoClass { GObjectClass parent_class; + + /* signals */ + void (*muted) (GstStreamInfo *info, gboolean mute); }; GType gst_stream_info_get_type (void); GstStreamInfo* gst_stream_info_new (GstPad *pad, GstStreamType type, gchar *decoder); - G_END_DECLS #endif /* __GST_STREAMINFO_H__ */