gst/playback/: More fixes on reusing of the element.

Original commit message from CVS:
* gst/playback/gstdecodebin.c: (gst_decode_bin_get_type),
(gst_decode_bin_class_init), (gst_decode_bin_factory_filter),
(compare_ranks), (print_feature), (gst_decode_bin_init),
(gst_decode_bin_dispose), (find_compatibles), (close_pad_link),
(try_to_link_1), (new_pad), (close_link), (type_found),
(gst_decode_bin_set_property), (gst_decode_bin_get_property),
(gst_decode_bin_change_state), (plugin_init):
* gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type),
(gst_play_base_bin_class_init), (gst_play_base_bin_init),
(gst_play_base_bin_dispose), (queue_overrun),
(gen_preroll_element), (remove_prerolls), (no_more_pads),
(new_stream), (setup_source), (gst_play_base_bin_set_property),
(gst_play_base_bin_get_property), (play_base_eos),
(gst_play_base_bin_change_state), (gst_play_base_bin_add_element),
(gst_play_base_bin_remove_element),
(gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream),
(gst_play_base_bin_unlink_stream),
(gst_play_base_bin_get_streaminfo):
* gst/playback/gstplaybasebin.h:
* gst/playback/gstplaybin.c: (gst_play_bin_get_type),
(gst_play_bin_class_init), (gst_play_bin_init),
(gst_play_bin_dispose), (gst_play_bin_set_property),
(gst_play_bin_get_property), (gen_video_element),
(gen_audio_element), (remove_sinks), (setup_sinks),
(gst_play_bin_change_state), (gst_play_bin_get_event_masks),
(gst_play_bin_send_event), (gst_play_bin_get_formats),
(gst_play_bin_convert), (gst_play_bin_get_query_types),
(gst_play_bin_query), (plugin_init):
* gst/playback/test4.c: (main):
More fixes on reusing of the element.
This commit is contained in:
Wim Taymans 2004-07-12 09:11:41 +00:00
parent 83358169b7
commit 467c454d75
6 changed files with 239 additions and 46 deletions

View file

@ -1,3 +1,36 @@
2004-07-12 Wim Taymans <wim@fluendo.com>
* gst/playback/gstdecodebin.c: (gst_decode_bin_get_type),
(gst_decode_bin_class_init), (gst_decode_bin_factory_filter),
(compare_ranks), (print_feature), (gst_decode_bin_init),
(gst_decode_bin_dispose), (find_compatibles), (close_pad_link),
(try_to_link_1), (new_pad), (close_link), (type_found),
(gst_decode_bin_set_property), (gst_decode_bin_get_property),
(gst_decode_bin_change_state), (plugin_init):
* gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type),
(gst_play_base_bin_class_init), (gst_play_base_bin_init),
(gst_play_base_bin_dispose), (queue_overrun),
(gen_preroll_element), (remove_prerolls), (no_more_pads),
(new_stream), (setup_source), (gst_play_base_bin_set_property),
(gst_play_base_bin_get_property), (play_base_eos),
(gst_play_base_bin_change_state), (gst_play_base_bin_add_element),
(gst_play_base_bin_remove_element),
(gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream),
(gst_play_base_bin_unlink_stream),
(gst_play_base_bin_get_streaminfo):
* gst/playback/gstplaybasebin.h:
* gst/playback/gstplaybin.c: (gst_play_bin_get_type),
(gst_play_bin_class_init), (gst_play_bin_init),
(gst_play_bin_dispose), (gst_play_bin_set_property),
(gst_play_bin_get_property), (gen_video_element),
(gen_audio_element), (remove_sinks), (setup_sinks),
(gst_play_bin_change_state), (gst_play_bin_get_event_masks),
(gst_play_bin_send_event), (gst_play_bin_get_formats),
(gst_play_bin_convert), (gst_play_bin_get_query_types),
(gst_play_bin_query), (plugin_init):
* gst/playback/test4.c: (main):
More fixes on reusing of the element.
2004-07-11 Benjamin Otte <otte@gnome.org>
* ext/mad/gstmad.c: (normal_seek):
@ -13,6 +46,39 @@
ourselves.
(interleave_buffered_loop): Use g_newa instead of malloc/free.
2004-07-09 Wim Taymans <wim@fluendo.com>
* gst/playback/gstdecodebin.c: (gst_decode_bin_get_type),
(gst_decode_bin_class_init), (gst_decode_bin_factory_filter),
(compare_ranks), (print_feature), (gst_decode_bin_init),
(gst_decode_bin_dispose), (find_compatibles), (close_pad_link),
(try_to_link_1), (new_pad), (close_link), (type_found),
(gst_decode_bin_set_property), (gst_decode_bin_get_property),
(gst_decode_bin_change_state), (plugin_init):
* gst/playback/gstplaybasebin.c: (gst_play_base_bin_get_type),
(gst_play_base_bin_class_init), (gst_play_base_bin_init),
(gst_play_base_bin_dispose), (queue_overrun),
(gen_preroll_element), (remove_prerolls), (no_more_pads),
(new_stream), (setup_source), (gst_play_base_bin_set_property),
(gst_play_base_bin_get_property), (play_base_eos),
(gst_play_base_bin_change_state), (gst_play_base_bin_add_element),
(gst_play_base_bin_remove_element),
(gst_play_base_bin_mute_stream), (gst_play_base_bin_link_stream),
(gst_play_base_bin_unlink_stream),
(gst_play_base_bin_get_streaminfo):
* gst/playback/gstplaybasebin.h:
* gst/playback/gstplaybin.c: (gst_play_bin_get_type),
(gst_play_bin_class_init), (gst_play_bin_init),
(gst_play_bin_dispose), (gst_play_bin_set_property),
(gst_play_bin_get_property), (gen_video_element),
(gen_audio_element), (remove_sinks), (setup_sinks),
(gst_play_bin_change_state), (gst_play_bin_get_event_masks),
(gst_play_bin_send_event), (gst_play_bin_get_formats),
(gst_play_bin_convert), (gst_play_bin_get_query_types),
(gst_play_bin_query), (plugin_init):
* gst/playback/test4.c: (main):
Work on object reuse and seeking.
2004-07-09 Wim Taymans <wim@fluendo.com>
* examples/seeking/seek.c: (iterate):

View file

@ -60,6 +60,10 @@ struct _GstDecodeBin
GList *factories;
gint numpads;
GList *elements;
guint have_type_id;
};
struct _GstDecodeBinClass
@ -176,7 +180,6 @@ gst_decode_bin_class_init (GstDecodeBinClass * klass)
GST_DEBUG_FUNCPTR (gst_decode_bin_change_state);
}
static gboolean
gst_decode_bin_factory_filter (GstPluginFeature * feature,
GstDecodeBin * decode_bin)
@ -208,7 +211,7 @@ compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
static void
print_feature (GstPluginFeature * feature)
{
g_print ("%s\n", gst_plugin_feature_get_name (feature));
GST_DEBUG ("%s\n", gst_plugin_feature_get_name (feature));
}
static void
@ -231,11 +234,10 @@ gst_decode_bin_init (GstDecodeBin * decode_bin)
gst_element_add_ghost_pad (GST_ELEMENT (decode_bin),
gst_element_get_pad (decode_bin->typefind, "sink"), "sink");
g_signal_connect (G_OBJECT (decode_bin->typefind), "have_type",
decode_bin->have_type_id =
g_signal_connect (G_OBJECT (decode_bin->typefind), "have_type",
G_CALLBACK (type_found), decode_bin);
decode_bin->numpads = 0;
decode_bin->threaded = FALSE;
}
static void
@ -245,6 +247,13 @@ gst_decode_bin_dispose (GObject * object)
decode_bin = GST_DECODE_BIN (object);
g_signal_handlers_disconnect_matched (G_OBJECT (decode_bin->typefind),
G_SIGNAL_MATCH_ID, decode_bin->have_type_id, 0, NULL, NULL, NULL);
gst_bin_remove (GST_BIN (decode_bin), decode_bin->typefind);
g_list_free (decode_bin->factories);
if (G_OBJECT_CLASS (parent_class)->dispose) {
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@ -305,6 +314,7 @@ close_pad_link (GstElement * element, GstPad * pad, GstCaps * caps,
ghost = gst_element_get_pad (GST_ELEMENT (decode_bin), padname);
/* our own signal with an extra flag that this is the only pad */
g_signal_emit (G_OBJECT (decode_bin),
gst_decode_bin_signals[SIGNAL_NEW_STREAM], 0,
ghost, !decode_bin->dynamic);
@ -336,7 +346,7 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories)
GstElement *element;
gboolean ret;
g_print ("trying to link %s\n",
GST_DEBUG ("trying to link %s\n",
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
element = gst_element_factory_create (factory, NULL);
@ -344,6 +354,7 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories)
continue;
gst_bin_add (GST_BIN (decode_bin), element);
decode_bin->elements = g_list_prepend (decode_bin->elements, element);
ret = gst_pad_link (pad, gst_element_get_pad (element, "sink"));
if (ret) {
@ -486,13 +497,24 @@ gst_decode_bin_get_property (GObject * object, guint prop_id, GValue * value,
static GstElementStateReturn
gst_decode_bin_change_state (GstElement * element)
{
GstElementStateReturn ret = GST_STATE_SUCCESS;
GstElementStateReturn ret;
GstDecodeBin *decode_bin;
gint transition;
decode_bin = GST_DECODE_BIN (element);
switch (GST_STATE_TRANSITION (element)) {
transition = GST_STATE_TRANSITION (element);
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
if (ret != GST_STATE_SUCCESS) {
return ret;
}
switch (transition) {
case GST_STATE_NULL_TO_READY:
decode_bin->numpads = 0;
decode_bin->threaded = FALSE;
break;
case GST_STATE_READY_TO_PAUSED:
case GST_STATE_PAUSED_TO_PLAYING:
case GST_STATE_PLAYING_TO_PAUSED:
@ -503,10 +525,6 @@ gst_decode_bin_change_state (GstElement * element)
break;
}
if (ret == GST_STATE_SUCCESS) {
return GST_ELEMENT_CLASS (parent_class)->change_state (element);
}
return ret;
}

View file

@ -117,6 +117,9 @@ gst_play_base_bin_class_init (GstPlayBaseBinClass * klass)
g_param_spec_pointer ("stream-info", "Stream info", "List of streaminfo",
G_PARAM_READABLE));
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),
@ -151,9 +154,13 @@ gst_play_base_bin_init (GstPlayBaseBin * play_base_bin)
{
play_base_bin->uri = NULL;
play_base_bin->threaded = FALSE;
play_base_bin->need_rebuild = TRUE;
play_base_bin->source = NULL;
play_base_bin->decoder = NULL;
play_base_bin->preroll_lock = g_mutex_new ();
play_base_bin->preroll_cond = g_cond_new ();
play_base_bin->preroll_elems = NULL;
GST_FLAG_SET (play_base_bin, GST_BIN_SELF_SCHEDULABLE);
}
@ -171,23 +178,6 @@ gst_play_base_bin_dispose (GObject * object)
}
}
static void
rebuild_pipeline (GstPlayBaseBin * play_base_bin)
{
GstElementState oldstate;
if (play_base_bin->thread == NULL)
return;
oldstate = gst_element_get_state (play_base_bin->thread);
gst_element_set_state (play_base_bin->thread, GST_STATE_NULL);
/* remove old elements */
/* set to old state again */
gst_element_set_state (play_base_bin->thread, oldstate);
}
static void
queue_overrun (GstElement * element, GstPlayBaseBin * play_base_bin)
{
@ -213,6 +203,31 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, GstPad * pad)
return element;
}
static void
remove_prerolls (GstPlayBaseBin * play_base_bin)
{
GList *prerolls, *infos;
for (prerolls = play_base_bin->preroll_elems; prerolls;
prerolls = g_list_next (prerolls)) {
GstElement *element = GST_ELEMENT (prerolls->data);
GST_LOG ("removing preroll element %s", gst_element_get_name (element));
gst_bin_remove (GST_BIN (play_base_bin->thread), element);
}
g_list_free (play_base_bin->preroll_elems);
play_base_bin->preroll_elems = NULL;
for (infos = play_base_bin->streaminfo; infos; infos = g_list_next (infos)) {
GstStreamInfo *info = GST_STREAM_INFO (infos->data);
g_object_unref (info);
}
g_list_free (play_base_bin->streaminfo);
play_base_bin->streaminfo = NULL;
play_base_bin->nstreams = 0;
}
static void
no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin)
{
@ -257,6 +272,9 @@ new_stream (GstElement * element, GstPad * pad, gboolean last,
gst_bin_add (GST_BIN (play_base_bin->thread), new_element);
play_base_bin->threaded = TRUE;
play_base_bin->preroll_elems =
g_list_prepend (play_base_bin->preroll_elems, new_element);
gst_pad_link (pad, gst_element_get_pad (new_element, "sink"));
gst_element_sync_state_with_parent (new_element);
}
@ -269,46 +287,73 @@ new_stream (GstElement * element, GstPad * pad, gboolean last,
static gboolean
setup_source (GstPlayBaseBin * play_base_bin)
{
if (play_base_bin->source) {
gst_bin_remove (GST_BIN (play_base_bin->thread), play_base_bin->source);
gst_object_unref (GST_OBJECT (play_base_bin->source));
}
GstElement *old_src;
if (!play_base_bin->need_rebuild)
return TRUE;
old_src = play_base_bin->source;
play_base_bin->source =
gst_element_make_from_uri (GST_URI_SRC, play_base_bin->uri, "source");
if (!play_base_bin->source) {
g_warning ("don't know how to read %s", play_base_bin->uri);
play_base_bin->source = old_src;
return FALSE;
} else {
if (old_src) {
GST_LOG ("removing old src element %s", gst_element_get_name (old_src));
gst_bin_remove (GST_BIN (play_base_bin->thread), old_src);
}
gst_bin_add (GST_BIN (play_base_bin->thread), play_base_bin->source);
}
{
GstElement *decoder;
gboolean res;
gint sig1, sig2;
GstElement *old_dec;
gst_bin_add (GST_BIN (play_base_bin->thread), play_base_bin->source);
old_dec = play_base_bin->decoder;
decoder = gst_element_factory_make ("decodebin", "decoder");
if (!decoder) {
play_base_bin->decoder = gst_element_factory_make ("decodebin", "decoder");
if (!play_base_bin->decoder) {
g_warning ("can't find decoder element");
play_base_bin->decoder = old_dec;
return FALSE;
} else {
if (old_dec) {
GST_LOG ("removing old decoder element %s",
gst_element_get_name (old_dec));
gst_bin_remove (GST_BIN (play_base_bin->thread), old_dec);
}
gst_bin_add (GST_BIN (play_base_bin->thread), play_base_bin->decoder);
}
remove_prerolls (play_base_bin);
gst_bin_add (GST_BIN (play_base_bin->thread), decoder);
res = gst_element_link_pads (play_base_bin->source, "src", decoder, "sink");
res =
gst_element_link_pads (play_base_bin->source, "src",
play_base_bin->decoder, "sink");
if (!res) {
g_warning ("can't link source to typefind element");
return FALSE;
}
g_signal_connect (G_OBJECT (decoder), "new_stream",
sig1 = g_signal_connect (G_OBJECT (play_base_bin->decoder), "new_stream",
G_CALLBACK (new_stream), play_base_bin);
g_signal_connect (G_OBJECT (decoder), "no-more-pads",
sig2 = g_signal_connect (G_OBJECT (play_base_bin->decoder), "no-more-pads",
G_CALLBACK (no_more_pads), play_base_bin);
g_mutex_lock (play_base_bin->preroll_lock);
gst_element_set_state (play_base_bin->thread, GST_STATE_PLAYING);
g_cond_wait (play_base_bin->preroll_cond, play_base_bin->preroll_lock);
g_mutex_unlock (play_base_bin->preroll_lock);
g_signal_handlers_disconnect_matched (G_OBJECT (play_base_bin->decoder),
G_SIGNAL_MATCH_ID, sig1, 0, NULL, NULL, NULL);
g_signal_handlers_disconnect_matched (G_OBJECT (play_base_bin->decoder),
G_SIGNAL_MATCH_ID, sig2, 0, NULL, NULL, NULL);
play_base_bin->need_rebuild = FALSE;
}
return TRUE;
@ -337,7 +382,7 @@ gst_play_base_bin_set_property (GObject * object, guint prop_id,
g_free (play_base_bin->uri);
play_base_bin->uri = g_strdup (uri);
rebuild_pipeline (play_base_bin);
play_base_bin->need_rebuild = TRUE;
}
break;
}
@ -373,6 +418,13 @@ gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value,
}
}
static void
play_base_eos (GstBin * bin, GstPlayBaseBin * play_base_bin)
{
g_print ("eos\n");
gst_element_set_eos (GST_ELEMENT (play_base_bin));
}
static GstElementStateReturn
gst_play_base_bin_change_state (GstElement * element)
{
@ -395,6 +447,9 @@ gst_play_base_bin_change_state (GstElement * element)
GST_OBJECT (play_base_bin));
gst_element_set_state (play_base_bin->thread, GST_STATE_READY);
g_signal_connect (G_OBJECT (play_base_bin->thread), "eos",
G_CALLBACK (play_base_eos), play_base_bin);
} else {
g_warning ("could not get 'opt' scheduler");
gst_object_unref (GST_OBJECT (play_base_bin->thread));
@ -423,10 +478,9 @@ gst_play_base_bin_change_state (GstElement * element)
break;
case GST_STATE_PAUSED_TO_READY:
ret = gst_element_set_state (play_base_bin->thread, GST_STATE_READY);
play_base_bin->need_rebuild = TRUE;
break;
case GST_STATE_READY_TO_NULL:
ret = gst_element_set_state (play_base_bin->thread, GST_STATE_NULL);
gst_object_unref (GST_OBJECT (play_base_bin->thread));
break;
default:
@ -468,7 +522,7 @@ gst_play_base_bin_add_element (GstBin * bin, GstElement * element)
clock = gst_scheduler_get_clock (sched);
gst_scheduler_set_clock (sched, clock);
gst_element_sync_state_with_parent (element);
//gst_element_sync_state_with_parent (element);
} else {
g_warning ("adding elements is not allowed in NULL");
}
@ -482,6 +536,21 @@ gst_play_base_bin_remove_element (GstBin * bin, GstElement * element)
play_base_bin = GST_PLAY_BASE_BIN (bin);
if (play_base_bin->thread) {
if (play_base_bin->threaded) {
gchar *name;
GstElement *thread;
name = g_strdup_printf ("thread_%s", gst_element_get_name (element));
thread = gst_bin_get_by_name (GST_BIN (play_base_bin->thread), name);
g_free (name);
if (!thread) {
g_warning ("cannot find element to remove");
} else {
element = thread;
}
}
GST_LOG ("removing element %s", gst_element_get_name (element));
gst_bin_remove (GST_BIN (play_base_bin->thread), element);
} else {
g_warning ("removing elements is not allowed in NULL");

View file

@ -42,11 +42,14 @@ struct _GstPlayBaseBin {
gboolean threaded;
GMutex *preroll_lock;
GCond *preroll_cond;
GList *preroll_elems;
/* internal thread */
GstElement *thread;
gchar *uri;
GstElement *source;
GstElement *decoder;
gboolean need_rebuild;
gint nstreams;
GList *streaminfo;

View file

@ -46,6 +46,8 @@ struct _GstPlayBin
GstElement *video_sink;
GstElement *visualisation;
GList *sinks;
GList *seekables;
};
@ -181,6 +183,7 @@ gst_play_bin_init (GstPlayBin * play_bin)
play_bin->audio_sink = NULL;
play_bin->visualisation = NULL;
play_bin->seekables = NULL;
play_bin->sinks = NULL;
GST_FLAG_SET (play_bin, GST_BIN_SELF_SCHEDULABLE);
}
@ -259,7 +262,7 @@ gen_video_element (GstPlayBin * play_bin)
sink = gst_element_factory_make ("ximagesink", "sink");
}
play_bin->seekables = g_list_prepend (play_bin->seekables, sink);
play_bin->seekables = g_list_append (play_bin->seekables, sink);
gst_bin_add (GST_BIN (element), conv);
gst_bin_add (GST_BIN (element), sink);
@ -298,6 +301,23 @@ gen_audio_element (GstPlayBin * play_bin)
return element;
}
static void
remove_sinks (GstPlayBin * play_bin)
{
GList *sinks;
for (sinks = play_bin->sinks; sinks; sinks = g_list_next (sinks)) {
GstElement *element = GST_ELEMENT (sinks->data);
GST_LOG ("removing sink %p", element);
gst_bin_remove (GST_BIN (play_bin), element);
}
g_list_free (play_bin->sinks);
g_list_free (play_bin->seekables);
play_bin->sinks = NULL;
play_bin->seekables = NULL;
}
static void
setup_sinks (GstPlayBin * play_bin)
{
@ -317,6 +337,9 @@ setup_sinks (GstPlayBin * play_bin)
g_object_get (obj, "type", &type, NULL);
g_object_get (obj, "pad", &srcpad, NULL);
if (gst_pad_is_linked (srcpad))
continue;
if (type == 1) {
sink = gen_audio_element (play_bin);
} else if (type == 2) {
@ -335,6 +358,10 @@ setup_sinks (GstPlayBin * play_bin)
capsstr = gst_caps_to_string (gst_pad_get_caps (srcpad));
g_warning ("could not link %s", capsstr);
g_free (capsstr);
GST_LOG ("removing sink %p", sink);
gst_bin_remove (GST_BIN (play_bin), sink);
} else {
play_bin->sinks = g_list_prepend (play_bin->sinks, sink);
}
}
}
@ -360,7 +387,10 @@ gst_play_bin_change_state (GstElement * element)
break;
case GST_STATE_PAUSED_TO_PLAYING:
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
remove_sinks (play_bin);
break;
case GST_STATE_READY_TO_NULL:
break;
default:
@ -392,9 +422,11 @@ gst_play_bin_send_event (GstElement * element, GstEvent * event)
GstElement *element = GST_ELEMENT (s->data);
gboolean ok;
gst_event_ref (event);
ok = gst_element_send_event (element, event);
res |= ok;
}
gst_event_unref (event);
return res;
}

View file

@ -31,6 +31,11 @@ main (gint argc, gchar * argv[])
player = gst_element_factory_make ("playbin", "player");
g_assert (player);
if (argc < 2) {
g_print ("usage: %s <uri>\n", argv[0]);
exit (-1);
}
g_object_set (G_OBJECT (player), "uri", argv[1], NULL);
g_print ("play...\n");