diff --git a/ChangeLog b/ChangeLog index d0af3d2fde..e82a75166f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +2005-05-25 Wim Taymans + + * gst/playback/gstdecodebin.c: (gst_decode_bin_init), + (gst_decode_bin_dispose), (try_to_link_1), (get_our_ghost_pad), + (remove_element_chain), (no_more_pads), (unlinked), (close_link), + (type_found): + * gst/playback/gstplaybasebin.c: (gst_play_base_bin_dispose), + (group_destroy), (group_commit), (queue_overrun), + (gen_preroll_element), (no_more_pads), (preroll_unlinked), + (mute_stream), (new_decoded_pad), (setup_substreams), + (setup_source), (mute_group_type), (set_active_source), + (gst_play_base_bin_change_state): + * gst/playback/gstplaybin.c: (gst_play_bin_dispose), + (gen_video_element), (gen_text_element), (gen_audio_element), + (gen_vis_element), (remove_sinks), (add_sink), (setup_sinks): + * gst/playback/gststreaminfo.c: (gst_stream_info_new), + (gst_stream_info_dispose), (gst_stream_info_set_mute): + * gst/playback/gststreamselector.c: (gst_stream_selector_chain): + Some playbin cleanups mostly refcounting sloppyness. + 2005-05-25 Ronald S. Bultje * ext/ogg/gstoggdemux.c: (gst_ogg_pad_submit_packet): diff --git a/gst/playback/gstdecodebin.c b/gst/playback/gstdecodebin.c index 0b0b2ca3ed..26f3d06538 100644 --- a/gst/playback/gstdecodebin.c +++ b/gst/playback/gstdecodebin.c @@ -309,11 +309,18 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) if (!decode_bin->typefind) { g_warning ("can't find typefind element, decodebin will not work"); } else { + GstPad *pad; + /* add the typefind element */ gst_bin_add (GST_BIN (decode_bin), decode_bin->typefind); + + /* get the sinkpad */ + pad = gst_element_get_pad (decode_bin->typefind, "sink"); + /* ghost the sink pad to ourself */ - gst_element_add_ghost_pad (GST_ELEMENT (decode_bin), - gst_element_get_pad (decode_bin->typefind, "sink"), "sink"); + gst_element_add_ghost_pad (GST_ELEMENT (decode_bin), pad, "sink"); + + gst_object_unref (GST_OBJECT_CAST (pad)); /* connect a signal to find out when the typefind element found * a type */ @@ -326,6 +333,8 @@ gst_decode_bin_init (GstDecodeBin * decode_bin) decode_bin->dynamics = NULL; } +static void dynamic_free (GstDynamic * dyn); + static void gst_decode_bin_dispose (GObject * object) { @@ -344,14 +353,12 @@ gst_decode_bin_dispose (GObject * object) for (dyns = decode_bin->dynamics; dyns; dyns = g_list_next (dyns)) { GstDynamic *dynamic = (GstDynamic *) dyns->data; - g_free (dynamic); + dynamic_free (dynamic); } g_list_free (decode_bin->dynamics); decode_bin->dynamics = NULL; - if (G_OBJECT_CLASS (parent_class)->dispose) { - G_OBJECT_CLASS (parent_class)->dispose (object); - } + G_OBJECT_CLASS (parent_class)->dispose (object); } static GstDynamic * @@ -553,27 +560,37 @@ static GstElement * try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories) { GList *walk; + GstElement *result = NULL; /* loop over the factories */ for (walk = factories; walk; walk = g_list_next (walk)) { GstElementFactory *factory = GST_ELEMENT_FACTORY (walk->data); GstElement *element; GstPadLinkReturn ret; + GstPad *sinkpad; GST_DEBUG_OBJECT (decode_bin, "trying to link %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); /* make an element from the factory first */ - element = gst_element_factory_create (factory, NULL); - if (element == NULL) { + if ((element = gst_element_factory_create (factory, NULL)) == NULL) { /* hmm, strange. Like with all things in live, let's move on.. */ GST_WARNING_OBJECT (decode_bin, "could not create an element from %s", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory))); continue; } + /* try to link the given pad to a sinkpad */ + /* FIXME, find the sinkpad by looping over the pads instead of + * looking it up by name */ + if ((sinkpad = gst_element_get_pad (element, "sink")) == NULL) { + /* if no pad is found we can't do anything */ + GST_WARNING_OBJECT (decode_bin, "could not find sinkpad in element"); + continue; + } + /* now add the element to the bin first */ - GST_DEBUG_OBJECT (decode_bin, "adding %s", gst_element_get_name (element)); + GST_DEBUG_OBJECT (decode_bin, "adding %s", GST_OBJECT_NAME (element)); gst_bin_add (GST_BIN (decode_bin), element); /* set to ready first so it is ready */ @@ -582,11 +599,15 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories) /* keep our own list of elements */ decode_bin->elements = g_list_prepend (decode_bin->elements, element); - /* try to link the given pad to a sinkpad */ - /* FIXME, find the sinkpad by looping over the pads instead of - * looking it up by name */ - ret = gst_pad_link (pad, gst_element_get_pad (element, "sink")); - if (ret == GST_PAD_LINK_OK) { + if ((ret = gst_pad_link (pad, sinkpad)) != GST_PAD_LINK_OK) { + GST_DEBUG_OBJECT (decode_bin, "link failed on pad %s:%s, reason %d", + GST_DEBUG_PAD_NAME (pad), ret); + /* get rid of the sinkpad */ + gst_object_unref (GST_OBJECT_CAST (sinkpad)); + /* this element did not work, remove it again and continue trying + * other elements, the element will be disposed. */ + gst_bin_remove (GST_BIN (decode_bin), element); + } else { const gchar *klass; GstElementFactory *factory; guint sig; @@ -597,6 +618,7 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories) /* The link worked, now figure out what it was that we connected */ factory = gst_element_get_factory (element); klass = gst_element_factory_get_klass (factory); + /* check if we can use threads */ if (decode_bin->threaded) { if (strstr (klass, "Demux") != NULL) { @@ -608,8 +630,9 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories) } /* make sure we catch unlink signals */ - sig = g_signal_connect (G_OBJECT (GST_PAD_REALIZE (pad)), "unlinked", + sig = g_signal_connect (G_OBJECT (pad), "unlinked", G_CALLBACK (unlinked), decode_bin); + /* keep a ref to the signal id so that we can disconnect the signal callback */ g_object_set_data (G_OBJECT (pad), "unlinked_id", GINT_TO_POINTER (sig)); @@ -618,21 +641,24 @@ try_to_link_1 (GstDecodeBin * decode_bin, GstPad * pad, GList * factories) close_link (element, decode_bin); /* change the state of the element to that of the parent */ gst_element_set_state (element, GST_STATE_PAUSED); - return element; - } else { - GST_DEBUG_OBJECT (decode_bin, "link failed on pad %s:%s", - GST_DEBUG_PAD_NAME (pad)); - /* this element did not work, remove it again and continue trying - * other elements */ - gst_bin_remove (GST_BIN (decode_bin), element); + + result = element; + + /* get rid of the sinkpad now */ + gst_object_unref (GST_OBJECT_CAST (sinkpad)); + + /* and exit */ + goto done; } } - return NULL; +done: + return result; } static GstPad * get_our_ghost_pad (GstDecodeBin * decode_bin, GstPad * pad) { +#if 0 GList *ghostpads; if (pad == NULL || !GST_PAD_IS_SRC (pad)) { @@ -643,8 +669,7 @@ get_our_ghost_pad (GstDecodeBin * decode_bin, GstPad * pad) if (GST_IS_GHOST_PAD (pad)) { GstElement *parent = gst_pad_get_parent (pad); - GST_DEBUG_OBJECT (decode_bin, "pad parent %s", - gst_element_get_name (parent)); + GST_DEBUG_OBJECT (decode_bin, "pad parent %s", GST_ELEMENT_NAME (parent)); if (parent == GST_ELEMENT (decode_bin)) { GST_DEBUG_OBJECT (decode_bin, "pad is our ghostpad"); @@ -669,6 +694,7 @@ get_our_ghost_pad (GstDecodeBin * decode_bin, GstPad * pad) ghostpads = g_list_next (ghostpads); } GST_DEBUG_OBJECT (decode_bin, "done looping over ghostpads, nothing found"); +#endif return NULL; } @@ -680,7 +706,7 @@ get_our_ghost_pad (GstDecodeBin * decode_bin, GstPad * pad) static void remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) { - GList *int_links; + GList *int_links, *walk; GstElement *elem = GST_ELEMENT (GST_OBJECT_PARENT (pad)); while (GST_OBJECT_PARENT (elem) && @@ -688,16 +714,16 @@ remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) elem = GST_ELEMENT (GST_OBJECT_PARENT (elem)); GST_DEBUG_OBJECT (decode_bin, "%s:%s", GST_DEBUG_PAD_NAME (pad)); + int_links = gst_pad_get_internal_links (pad); /* remove all elements linked to this pad up to the ghostpad * that we created for this stream */ - for (int_links = gst_pad_get_internal_links (pad); - int_links; int_links = g_list_next (int_links)) { + for (walk = int_links; walk; walk = g_list_next (walk)) { GstPad *pad; GstPad *ghostpad; GstPad *peer; - pad = GST_PAD (int_links->data); + pad = GST_PAD (walk->data); GST_DEBUG_OBJECT (decode_bin, "inspecting internal pad %s:%s", GST_DEBUG_PAD_NAME (pad)); @@ -723,20 +749,24 @@ remove_element_chain (GstDecodeBin * decode_bin, GstPad * pad) GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (peer)); { - GstElement *parent = gst_pad_get_real_parent (peer); + GstElement *parent = gst_pad_get_parent (peer); if (parent != GST_ELEMENT (decode_bin)) { GST_DEBUG_OBJECT (decode_bin, "dead end pad %s:%s", GST_DEBUG_PAD_NAME (peer)); } else { GST_DEBUG_OBJECT (decode_bin, "recursing element %s on pad %s:%s", - gst_element_get_name (elem), GST_DEBUG_PAD_NAME (pad)); + GST_ELEMENT_NAME (elem), GST_DEBUG_PAD_NAME (pad)); remove_element_chain (decode_bin, peer); } gst_object_unref (GST_OBJECT_CAST (parent)); } + gst_object_unref (GST_OBJECT_CAST (peer)); } - GST_DEBUG_OBJECT (decode_bin, "removing %s", gst_element_get_name (elem)); + GST_DEBUG_OBJECT (decode_bin, "removing %s", GST_ELEMENT_NAME (elem)); + + g_list_free (int_links); + gst_bin_remove (GST_BIN (decode_bin), elem); } @@ -768,7 +798,7 @@ no_more_pads (GstElement * element, GstDynamic * dynamic) GstDecodeBin *decode_bin = dynamic->decode_bin; GST_DEBUG_OBJECT (decode_bin, "no more pads on element %s", - gst_element_get_name (element)); + GST_ELEMENT_NAME (element)); /* remove the element from the list of dynamic elements */ decode_bin->dynamics = g_list_remove (decode_bin->dynamics, dynamic); @@ -793,7 +823,7 @@ unlinked (GstPad * pad, GstPad * peerpad, GstDecodeBin * decode_bin) GstElement *element; /* inactivate pad */ - gst_pad_set_active (pad, FALSE); + gst_pad_set_active (pad, GST_ACTIVATE_NONE); /* remove all elements linked to the peerpad */ remove_element_chain (decode_bin, peerpad); @@ -825,7 +855,7 @@ close_link (GstElement * element, GstDecodeBin * decode_bin) gboolean more; GST_DEBUG_OBJECT (decode_bin, "closing links with element %s", - gst_element_get_name (element)); + GST_ELEMENT_NAME (element)); /* loop over all the padtemplates */ for (pads = GST_ELEMENT_GET_CLASS (element)->padtemplates; pads; @@ -905,7 +935,7 @@ close_link (GstElement * element, GstDecodeBin * decode_bin) /* now loop over all the pads we need to connect */ for (pads = to_connect; pads; pads = g_list_next (pads)) { - GstPad *pad = GST_PAD (pads->data); + GstPad *pad = GST_PAD_CAST (pads->data); GstCaps *caps; /* we have more pads if we have more than 1 pad to connect or @@ -915,15 +945,16 @@ close_link (GstElement * element, GstDecodeBin * decode_bin) more |= gst_decode_bin_is_dynamic (decode_bin); GST_DEBUG_OBJECT (decode_bin, "closing pad link for %s", - gst_pad_get_name (pad)); + GST_OBJECT_NAME (pad)); /* continue autoplugging on the pads */ caps = gst_pad_get_caps (pad); close_pad_link (element, pad, caps, decode_bin, more); if (caps) gst_caps_unref (caps); - } + gst_object_unref (GST_OBJECT_CAST (pad)); + } g_list_free (to_connect); } @@ -941,7 +972,7 @@ type_found (GstElement * typefind, guint probability, GstCaps * caps, /* autoplug the new pad with the caps that the signal gave us. */ pad = gst_element_get_pad (typefind, "src"); close_pad_link (typefind, pad, caps, decode_bin, FALSE); - gst_object_unref (GST_OBJECT (pad)); + gst_object_unref (GST_OBJECT_CAST (pad)); dynamic = gst_decode_bin_is_dynamic (decode_bin); if (dynamic == FALSE) { diff --git a/gst/playback/gstplaybasebin.c b/gst/playback/gstplaybasebin.c index dba17a5935..9fbfdcfb1d 100644 --- a/gst/playback/gstplaybasebin.c +++ b/gst/playback/gstplaybasebin.c @@ -202,9 +202,7 @@ gst_play_base_bin_dispose (GObject * object) g_free (play_base_bin->suburi); play_base_bin->suburi = NULL; - if (G_OBJECT_CLASS (parent_class)->dispose) { - G_OBJECT_CLASS (parent_class)->dispose (object); - } + G_OBJECT_CLASS (parent_class)->dispose (object); } static void @@ -312,8 +310,7 @@ group_destroy (GstPlayBaseGroup * group) fakesrc = (GstElement *) g_object_get_data (G_OBJECT (pad), "fakesrc"); if (fakesrc != NULL) { GST_LOG ("removing fakesrc from %s:%s", - gst_pad_get_name (pad), - GST_ELEMENT_NAME (gst_pad_get_parent (pad))); + GST_PAD_NAME (pad), GST_ELEMENT_NAME (gst_pad_get_parent (pad))); gst_bin_remove (GST_BIN (play_base_bin), fakesrc); } } @@ -321,7 +318,7 @@ group_destroy (GstPlayBaseGroup * group) /* if the group is currently being played, we have to remove the element * from the thread */ if (get_active_group (play_base_bin) == group) { - GST_LOG ("removing preroll element %s", gst_element_get_name (element)); + GST_LOG ("removing preroll element %s", GST_ELEMENT_NAME (element)); gst_bin_remove (group->type[n].bin, element); gst_bin_remove (group->type[n].bin, group->type[n].selector); } else { @@ -388,7 +385,7 @@ group_commit (GstPlayBaseBin * play_base_bin, gboolean fatal, gboolean subtitle) sig_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (element), "signal_id")); - GST_LOG ("removing preroll signal %s", gst_element_get_name (element)); + GST_LOG ("removing preroll signal %s", GST_ELEMENT_NAME (element)); g_signal_handler_disconnect (G_OBJECT (element), sig_id); } } @@ -469,7 +466,7 @@ check_queue (GstProbe * probe, GstMiniObject ** data, gpointer user_data) static void queue_overrun (GstElement * element, GstPlayBaseBin * play_base_bin) { - GST_DEBUG ("queue %s overrun", gst_element_get_name (element)); + GST_DEBUG ("queue %s overrun", GST_ELEMENT_NAME (element)); group_commit (play_base_bin, FALSE, FALSE); @@ -550,7 +547,7 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, GstStreamInfo * info) { GstElement *selector, *preroll; - gchar *name; + gchar *name, *padname; const gchar *prename; guint sig; GstPad *preroll_pad; @@ -566,20 +563,26 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, g_return_if_reached (); /* create stream selector */ - name = g_strdup_printf ("selector_%s_%s", prename, gst_pad_get_name (pad)); + padname = gst_pad_get_name (pad); + name = g_strdup_printf ("selector_%s_%s", prename, padname); selector = g_object_new (GST_TYPE_STREAM_SELECTOR, NULL); gst_object_set_name (GST_OBJECT (selector), name); g_free (name); /* create preroll queue */ - name = g_strdup_printf ("preroll_%s_%s", prename, gst_pad_get_name (pad)); + name = g_strdup_printf ("preroll_%s_%s", prename, padname); preroll = gst_element_factory_make ("queue", name); + g_free (padname); + g_free (name); + g_object_set (G_OBJECT (preroll), "max-size-buffers", 0, "max-size-bytes", ((type == GST_STREAM_TYPE_VIDEO) ? 25 : 1) * 1024 * 1024, "max-size-time", play_base_bin->queue_size, NULL); + sig = g_signal_connect (G_OBJECT (preroll), "overrun", G_CALLBACK (queue_overrun), play_base_bin); + if (play_base_bin->is_stream && ((type == GST_STREAM_TYPE_VIDEO && group->type[GST_STREAM_TYPE_AUDIO - 1].npads == 0) || @@ -609,34 +612,32 @@ gen_preroll_element (GstPlayBaseBin * play_base_bin, /* keep a ref to the signal id so that we can disconnect the signal callback * when we are done with the preroll */ g_object_set_data (G_OBJECT (preroll), "signal_id", GINT_TO_POINTER (sig)); - g_free (name); /* listen for EOS */ preroll_pad = gst_element_get_pad (preroll, "src"); probe = gst_probe_new (FALSE, probe_triggered, info); /* have to REALIZE the pad as we cannot attach a padprobe to a ghostpad */ gst_pad_add_probe (preroll_pad, probe); + gst_object_unref (GST_OBJECT_CAST (preroll_pad)); /* add to group list */ - gst_element_link (selector, preroll); + /* FIXME refcount elements */ group->type[type - 1].selector = selector; group->type[type - 1].preroll = preroll; if (type == GST_STREAM_TYPE_TEXT && play_base_bin->subtitle) { group->type[type - 1].bin = GST_BIN (play_base_bin->subtitle); gst_bin_add (GST_BIN (play_base_bin->subtitle), selector); gst_bin_add (GST_BIN (play_base_bin->subtitle), preroll); - gst_element_set_state (selector, - GST_STATE (play_base_bin) == GST_STATE_PLAYING ? - GST_STATE_PLAYING : GST_STATE_PAUSED); } else { group->type[type - 1].bin = GST_BIN (play_base_bin); gst_bin_add (GST_BIN (play_base_bin), selector); gst_bin_add (GST_BIN (play_base_bin), preroll); - gst_element_set_state (selector, - GST_STATE (play_base_bin) == GST_STATE_PLAYING ? - GST_STATE_PLAYING : GST_STATE_PAUSED); } + gst_element_link (selector, preroll); + gst_element_set_state (selector, + GST_STATE (play_base_bin) == GST_STATE_PLAYING ? + GST_STATE_PLAYING : GST_STATE_PAUSED); gst_element_set_state (preroll, GST_STATE (play_base_bin) == GST_STATE_PLAYING ? GST_STATE_PLAYING : GST_STATE_PAUSED); @@ -754,7 +755,7 @@ no_more_pads (GstElement * element, GstPlayBaseBin * play_base_bin) /* we can commit this group for playback now */ group_commit (play_base_bin, play_base_bin->is_stream, - gst_object_get_parent (GST_OBJECT (element)) == + GST_OBJECT_PARENT (GST_OBJECT_CAST (element)) == GST_OBJECT (play_base_bin->subtitle)); } @@ -848,6 +849,7 @@ preroll_unlinked (GstPad * pad, GstPad * peerpad, { GstElement *fakesrc; guint sig_id; + GstPad *srcpad; /* make a fakesrc that will just emit one EOS */ fakesrc = gst_element_factory_make ("fakesrc", NULL); @@ -855,8 +857,10 @@ preroll_unlinked (GstPad * pad, GstPad * peerpad, GST_DEBUG ("patching unlinked pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - gst_pad_link (gst_element_get_pad (fakesrc, "src"), pad); + srcpad = gst_element_get_pad (fakesrc, "src"); gst_bin_add (GST_BIN (play_base_bin), fakesrc); + gst_pad_link (srcpad, pad); + gst_object_unref (GST_OBJECT_CAST (srcpad)); /* keep track of these patch elements */ g_object_set_data (G_OBJECT (pad), "fakesrc", fakesrc); @@ -879,7 +883,7 @@ mute_stream (GstProbe * probe, GstMiniObject ** d, gpointer data) if (GST_IS_BUFFER (*d)) { g_object_set (G_OBJECT (info), "mute", TRUE, NULL); - gst_pad_remove_probe ((GstPad *) GST_PAD_REALIZE (info->object), probe); + gst_pad_remove_probe (GST_PAD_CAST (info->object), probe); gst_probe_destroy (probe); } @@ -911,18 +915,14 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last, GstPlayBaseGroup *group; GstProbe *probe; guint sig; + GstObject *parent; GST_DEBUG ("play base: new decoded pad %d", last); /* first see if this pad has interesting caps */ caps = gst_pad_get_caps (pad); - if (caps == NULL || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) { - g_warning ("no type on pad %s:%s", - GST_DEBUG_PAD_NAME (GST_PAD_REALIZE (pad))); - if (caps) - gst_caps_unref (caps); - return; - } + if (caps == NULL || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) + goto no_type; /* get the mime type */ structure = gst_caps_get_structure (caps, 0); @@ -934,19 +934,19 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last, group->nstreams++; + parent = gst_object_get_parent (GST_OBJECT (element)); if (g_str_has_prefix (mimetype, "audio/") && - gst_object_get_parent (GST_OBJECT (element)) != - GST_OBJECT (play_base_bin->subtitle)) { + parent != GST_OBJECT_CAST (play_base_bin->subtitle)) { type = GST_STREAM_TYPE_AUDIO; } else if (g_str_has_prefix (mimetype, "video/") && - gst_object_get_parent (GST_OBJECT (element)) != - GST_OBJECT (play_base_bin->subtitle)) { + parent != GST_OBJECT_CAST (play_base_bin->subtitle)) { type = GST_STREAM_TYPE_VIDEO; } else if (g_str_has_prefix (mimetype, "text/")) { type = GST_STREAM_TYPE_TEXT; } else { type = GST_STREAM_TYPE_UNKNOWN; } + gst_object_unref (parent); info = gst_stream_info_new (GST_OBJECT (pad), type, NULL, caps); if (type > 0 && type <= NUM_TYPES) { @@ -974,7 +974,7 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last, /* select 1st for now - we'll select a preferred one after preroll */ if (type == GST_STREAM_TYPE_UNKNOWN || group->type[type - 1].npads > 0) { probe = gst_probe_new (FALSE, silence_stream, info); - gst_pad_add_probe (GST_PAD_REALIZE (pad), probe); + gst_pad_add_probe (GST_PAD_CAST (pad), probe); g_object_set_data (G_OBJECT (pad), "eat_probe", probe); } @@ -985,6 +985,16 @@ new_decoded_pad (GstElement * element, GstPad * pad, gboolean last, /* signal the no more pads after adding the stream */ if (last) no_more_pads (element, play_base_bin); + + return; + +no_type: + { + g_warning ("no type on pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + if (caps) + gst_caps_unref (caps); + return; + } } @@ -1066,7 +1076,7 @@ setup_substreams (GstPlayBaseBin * play_base_bin) probe = g_object_get_data (G_OBJECT (info->object), "eat_probe"); if (probe) { - gst_pad_remove_probe (GST_PAD_REALIZE (info->object), probe); + gst_pad_remove_probe (GST_PAD_CAST (info->object), probe); gst_probe_destroy (probe); } @@ -1075,7 +1085,7 @@ setup_substreams (GstPlayBaseBin * play_base_bin) GstProbe *probe; probe = gst_probe_new (FALSE, mute_stream, info); - gst_pad_add_probe (GST_PAD_REALIZE (info->object), probe); + gst_pad_add_probe (GST_PAD_CAST (info->object), probe); } } @@ -1115,24 +1125,12 @@ setup_source (GstPlayBaseBin * play_base_bin, } /* create and configure an element that can handle the uri */ - play_base_bin->source = gen_source_element (play_base_bin, &subbin); - if (!play_base_bin->source) { - gchar *prot; - - /* whoops, could not create the source element */ - prot = gst_uri_get_protocol (play_base_bin->uri); - if (prot) { - g_set_error (error, 0, 0, "No URI handler implemented for \"%s\"", prot); - g_free (prot); - } else { - g_set_error (error, 0, 0, "Invalid URI \"%s\"", play_base_bin->uri); - } - GST_WARNING ("don't know how to read %s", play_base_bin->uri); - return FALSE; - } + if (!(play_base_bin->source = gen_source_element (play_base_bin, &subbin))) + goto no_source; gst_bin_add (GST_BIN (play_base_bin), play_base_bin->source); g_object_notify (G_OBJECT (play_base_bin), "source"); + /* state will be merged later - if file is not found, error will be * handled by the application right after. */ @@ -1274,18 +1272,14 @@ setup_source (GstPlayBaseBin * play_base_bin, } /* now create the decoder element */ - play_base_bin->decoder = gst_element_factory_make ("decodebin", "decoder"); - if (!play_base_bin->decoder) { - g_set_error (error, 0, 0, "Could not create autoplugger element"); - GST_WARNING ("can't find decoder element"); - return FALSE; - } + if (!(play_base_bin->decoder = + gst_element_factory_make ("decodebin", "decoder"))) + goto no_decodebin; + gst_bin_add (GST_BIN (play_base_bin), play_base_bin->decoder); - if (!gst_element_link (play_base_bin->source, play_base_bin->decoder)) { - g_set_error (error, 0, 0, "Could not link source and autoplugger"); - GST_WARNING ("can't link source to decoder element"); - return FALSE; - } + + if (!gst_element_link (play_base_bin->source, play_base_bin->decoder)) + goto could_not_link; /* set up callbacks to create the links between decoded data * and video/audio/subtitle rendering/output. */ @@ -1299,6 +1293,35 @@ setup_source (GstPlayBaseBin * play_base_bin, play_base_bin->need_rebuild = FALSE; return TRUE; + + /* ERRORS */ +no_source: + { + gchar *prot; + + /* whoops, could not create the source element */ + prot = gst_uri_get_protocol (play_base_bin->uri); + if (prot) { + g_set_error (error, 0, 0, "No URI handler implemented for \"%s\"", prot); + g_free (prot); + } else { + g_set_error (error, 0, 0, "Invalid URI \"%s\"", play_base_bin->uri); + } + GST_WARNING ("don't know how to read %s", play_base_bin->uri); + return FALSE; + } +no_decodebin: + { + g_set_error (error, 0, 0, "Could not create autoplugger element"); + GST_WARNING ("can't find decoder element"); + return FALSE; + } +could_not_link: + { + g_set_error (error, 0, 0, "Could not link source and autoplugger"); + GST_WARNING ("can't link source to decoder element"); + return FALSE; + } } static void @@ -1408,13 +1431,17 @@ static void mute_group_type (GstPlayBaseGroup * group, GstStreamType type, gboolean mute) { gboolean active = !mute; + GstPad *pad; - gst_pad_set_active (gst_element_get_pad (group->type[type - 1].preroll, - "src"), active); - gst_pad_set_active (gst_element_get_pad (group->type[type - 1].preroll, - "sink"), active); - gst_pad_set_active (gst_element_get_pad (group->type[type - 1].selector, - "src"), active); + pad = gst_element_get_pad (group->type[type - 1].preroll, "src"); + gst_pad_set_active (pad, active); + gst_object_unref (GST_OBJECT_CAST (pad)); + pad = gst_element_get_pad (group->type[type - 1].preroll, "sink"); + gst_pad_set_active (pad, active); + gst_object_unref (GST_OBJECT_CAST (pad)); + pad = gst_element_get_pad (group->type[type - 1].selector, "src"); + gst_pad_set_active (pad, active); + gst_object_unref (GST_OBJECT_CAST (pad)); if (mute) { g_signal_connect (group->type[type - 1].preroll, "state-change", @@ -1477,7 +1504,7 @@ set_active_source (GstPlayBaseBin * play_base_bin, GstProbe *probe; probe = gst_probe_new (FALSE, mute_stream, info); - gst_pad_add_probe (GST_PAD_REALIZE (info->object), probe); + gst_pad_add_probe (GST_PAD_CAST (info->object), probe); } num++; } @@ -1632,44 +1659,24 @@ gst_play_base_bin_get_property (GObject * object, guint prop_id, GValue * value, static GstElementStateReturn gst_play_base_bin_change_state (GstElement * element) { - GstElementStateReturn ret = GST_STATE_SUCCESS; + GstElementStateReturn ret; GstPlayBaseBin *play_base_bin; gint transition = GST_STATE_TRANSITION (element); gchar *new_location = NULL; + GError *error = NULL; play_base_bin = GST_PLAY_BASE_BIN (element); switch (transition) { case GST_STATE_READY_TO_PAUSED: - { - GError *error = NULL; - - if (!setup_source (play_base_bin, &new_location, &error) || error != NULL) { - if (!error) { - /* opening failed but no error - hellup */ - GST_ELEMENT_ERROR (GST_ELEMENT (play_base_bin), STREAM, - NOT_IMPLEMENTED, - ("cannot open file \"%s\"", play_base_bin->uri), (NULL)); - } else { - /* just copy the cached error - type doesn't matter */ - GST_ELEMENT_ERROR (play_base_bin, STREAM, TOO_LAZY, - (error->message), (NULL)); - g_error_free (error); - } - ret = GST_STATE_FAILURE; - play_base_bin->need_rebuild = TRUE; - } + if (!setup_source (play_base_bin, &new_location, &error) || error != NULL) + goto source_failed; break; - } default: break; } - if (ret != GST_STATE_SUCCESS) { - return ret; - } else { - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); - } + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element); switch (transition) { case GST_STATE_READY_TO_PAUSED: @@ -1688,8 +1695,26 @@ gst_play_base_bin_change_state (GstElement * element) default: break; } - return ret; + + /* ERRORS */ +source_failed: + { + if (!error) { + /* opening failed but no error - hellup */ + GST_ELEMENT_ERROR (GST_ELEMENT (play_base_bin), STREAM, + NOT_IMPLEMENTED, + ("cannot open file \"%s\"", play_base_bin->uri), (NULL)); + } else { + /* just copy the cached error - type doesn't matter */ + GST_ELEMENT_ERROR (play_base_bin, STREAM, TOO_LAZY, + (error->message), (NULL)); + g_error_free (error); + } + play_base_bin->need_rebuild = TRUE; + + return GST_STATE_FAILURE; + } } const GList * diff --git a/gst/playback/gstplaybin.c b/gst/playback/gstplaybin.c index e7d5f1812d..653366fa7d 100644 --- a/gst/playback/gstplaybin.c +++ b/gst/playback/gstplaybin.c @@ -237,9 +237,7 @@ gst_play_bin_dispose (GObject * object) g_free (play_bin->font_desc); play_bin->font_desc = NULL; - if (G_OBJECT_CLASS (parent_class)->dispose) { - G_OBJECT_CLASS (parent_class)->dispose (object); - } + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -410,7 +408,7 @@ gen_video_element (GstPlayBin * play_bin) pad = gst_element_get_pad (identity, "sink"); gst_element_add_ghost_pad (element, pad, "sink"); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); gst_element_set_state (element, GST_STATE_READY); @@ -460,11 +458,11 @@ gen_text_element (GstPlayBin * play_bin) pad = gst_element_get_pad (overlay, "text_sink"); gst_element_add_ghost_pad (element, pad, "text_sink"); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); pad = gst_element_get_pad (csp, "sink"); gst_element_add_ghost_pad (element, pad, "sink"); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); return element; } @@ -525,7 +523,7 @@ gen_audio_element (GstPlayBin * play_bin) pad = gst_element_get_pad (conv, "sink"); gst_element_add_ghost_pad (element, pad, "sink"); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); gst_element_set_state (element, GST_STATE_READY); @@ -606,19 +604,19 @@ gen_vis_element (GstPlayBin * play_bin) pad = gst_element_get_pad (aqueue, "sink"); rpad = gst_element_get_request_pad (tee, "src%d"); gst_pad_link (rpad, pad); - g_object_unref (G_OBJECT (rpad)); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (rpad)); + gst_object_unref (GST_OBJECT (pad)); gst_element_link_pads (aqueue, "src", asink, "sink"); pad = gst_element_get_pad (conv, "sink"); rpad = gst_element_get_request_pad (tee, "src%d"); gst_pad_link (rpad, pad); - g_object_unref (G_OBJECT (rpad)); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (rpad)); + gst_object_unref (GST_OBJECT (pad)); pad = gst_element_get_pad (tee, "sink"); gst_element_add_ghost_pad (element, pad, "sink"); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); return element; } @@ -639,27 +637,37 @@ remove_sinks (GstPlayBin * play_bin) /* we remove the element from the parent so that * there is no unwanted state change when the parent * is disposed */ + play_bin->sinks = g_list_remove (play_bin->sinks, element); gst_bin_remove (GST_BIN (parent), element); - g_object_unref (G_OBJECT (parent)); + gst_object_unref (GST_OBJECT (parent)); } } element = g_hash_table_lookup (play_bin->cache, "vbin"); if (element != NULL) { parent = gst_element_get_parent (element); if (parent != NULL) { + play_bin->sinks = g_list_remove (play_bin->sinks, element); gst_bin_remove (GST_BIN (parent), element); - g_object_unref (G_OBJECT (parent)); + gst_object_unref (GST_OBJECT (parent)); } } for (sinks = play_bin->sinks; sinks; sinks = g_list_next (sinks)) { GstElement *element = GST_ELEMENT (sinks->data); - GstPad *pad = gst_element_get_pad (element, "sink"); + GstPad *pad; + GstPad *peer; + + pad = gst_element_get_pad (element, "sink"); GST_LOG ("removing sink %p", element); - if (GST_PAD_PEER (pad)) - gst_pad_unlink (GST_PAD_PEER (pad), pad); - g_object_unref (G_OBJECT (pad)); + + peer = gst_pad_get_peer (pad); + if (peer) { + gst_pad_unlink (peer, pad); + gst_object_unref (GST_OBJECT (peer)); + } + gst_object_unref (GST_OBJECT (pad)); + gst_bin_remove (GST_BIN (play_bin), element); } g_list_free (play_bin->sinks); @@ -694,12 +702,12 @@ add_sink (GstPlayBin * play_bin, GstElement * sink, GstPad * srcpad) /* we found a sink for this stream, now try to install it */ sinkpad = gst_element_get_pad (sink, "sink"); res = gst_pad_link (srcpad, sinkpad); - g_object_unref (G_OBJECT (sinkpad)); + gst_object_unref (GST_OBJECT (sinkpad)); parent = gst_pad_get_parent (srcpad); GST_DEBUG ("Adding sink with state %d (parent: %d, peer: %d)\n", GST_STATE (sink), GST_STATE (play_bin), GST_STATE (parent)); - g_object_unref (G_OBJECT (parent)); + gst_object_unref (GST_OBJECT (parent)); /* try to link the pad of the sink to the stream */ if (res < 0) { @@ -770,7 +778,7 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group) pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_AUDIO - 1].preroll, "src"); add_sink (play_bin, sink, pad); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); } /* link video */ @@ -783,15 +791,15 @@ setup_sinks (GstPlayBaseBin * play_base_bin, GstPlayBaseGroup * group) gst_element_get_pad (group->type[GST_STREAM_TYPE_TEXT - 1].preroll, "src"); gst_pad_link (textsrcpad, textsinkpad); - g_object_unref (G_OBJECT (textsinkpad)); - g_object_unref (G_OBJECT (textsrcpad)); + gst_object_unref (GST_OBJECT (textsinkpad)); + gst_object_unref (GST_OBJECT (textsrcpad)); } else { sink = gen_video_element (play_bin); } pad = gst_element_get_pad (group->type[GST_STREAM_TYPE_VIDEO - 1].preroll, "src"); add_sink (play_bin, sink, pad); - g_object_unref (G_OBJECT (pad)); + gst_object_unref (GST_OBJECT (pad)); } if (play_bin->fakesink) { diff --git a/gst/playback/gststreaminfo.c b/gst/playback/gststreaminfo.c index 22e236a1d2..f6de764344 100644 --- a/gst/playback/gststreaminfo.c +++ b/gst/playback/gststreaminfo.c @@ -219,7 +219,7 @@ gst_stream_info_new (GstObject * object, GstProbe *probe; probe = gst_probe_new (FALSE, cb_probe, info); - gst_pad_add_probe (GST_PAD_REALIZE (object), probe); + gst_pad_add_probe (GST_PAD_CAST (object), probe); } info->object = object; info->type = type; @@ -243,7 +243,7 @@ gst_stream_info_dispose (GObject * object) GstElement *parent; parent = gst_pad_get_parent ((GstPad *) - GST_PAD_REALIZE (stream_info->object)); + GST_PAD_CAST (stream_info->object)); if (parent != NULL) { g_signal_handlers_disconnect_by_func (parent, G_CALLBACK (stream_info_change_state), stream_info); @@ -301,11 +301,11 @@ gst_stream_info_set_mute (GstStreamInfo * stream_info, gboolean mute) stream_info->mute = mute; //gst_pad_set_active_recursive ((GstPad *) - //GST_PAD_REALIZE (stream_info->object), !mute); + //GST_PAD_CAST (stream_info->object), !mute); g_warning ("FIXME"); element = gst_pad_get_parent ((GstPad *) - GST_PAD_REALIZE (stream_info->object)); + GST_PAD_CAST (stream_info->object)); if (mute) { g_signal_connect (element, "state-change", G_CALLBACK (stream_info_change_state), stream_info); diff --git a/gst/playback/gststreamselector.c b/gst/playback/gststreamselector.c index eaf6d72f7f..a52431b5da 100644 --- a/gst/playback/gststreamselector.c +++ b/gst/playback/gststreamselector.c @@ -238,8 +238,6 @@ gst_stream_selector_chain (GstPad * pad, GstBuffer * buf) GstStreamSelector *sel = GST_STREAM_SELECTOR (gst_pad_get_parent (pad)); GstFlowReturn res; - GST_STREAM_LOCK (pad); - /* first, check if the active pad changed. If so, redo * negotiation and fail if that fails. */ if (pad != sel->last_active_sinkpad) { @@ -255,7 +253,5 @@ gst_stream_selector_chain (GstPad * pad, GstBuffer * buf) "buf", gst_pad_get_name (pad)); res = gst_pad_push (sel->srcpad, buf); - GST_STREAM_UNLOCK (pad); - return res; }