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.
This commit is contained in:
Wim Taymans 2004-10-08 11:30:32 +00:00
parent 18fff8755d
commit a85131e7ca
7 changed files with 155 additions and 89 deletions

View file

@ -1,3 +1,24 @@
2004-10-08 Wim Taymans <wim@fluendo.com>
* 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 <julien@moutte.net>
* sys/ximage/ximagesink.c: (gst_ximagesink_sink_link),

View file

@ -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

View file

@ -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");

View file

@ -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);

View file

@ -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);
}
}
}

View file

@ -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;

View file

@ -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__ */