static void pad_removed_cb (GstElement * timeline, GstPad * pad, GESPipeline * self) { OutputChain *chain; GESTrack *track; GstPad *peer; GST_DEBUG_OBJECT (self, "pad removed %s:%s", GST_DEBUG_PAD_NAME (pad)); if (G_UNLIKELY (!(track = ges_timeline_get_track_for_pad (self->priv->timeline, pad)))) { GST_WARNING_OBJECT (self, "Couldn't find coresponding track !"); return; } if (G_UNLIKELY (!(chain = get_output_chain_for_track (self, track)))) { GST_DEBUG_OBJECT (self, "Pad wasn't used"); return; } /* Unlink encodebin */ if (chain->encodebinpad) { peer = gst_pad_get_peer (chain->encodebinpad); gst_pad_unlink (peer, chain->encodebinpad); gst_object_unref (peer); gst_element_release_request_pad (self->priv->encodebin, chain->encodebinpad); } /* Unlink playsink */ if (chain->playsinkpad) { peer = gst_pad_get_peer (chain->playsinkpad); gst_pad_unlink (peer, chain->playsinkpad); gst_object_unref (peer); gst_element_release_request_pad (self->priv->playsink, chain->playsinkpad); gst_object_unref (chain->playsinkpad); } if (chain->blocked_pad) { GST_DEBUG_OBJECT (chain->blocked_pad, "unblocking pad"); gst_pad_remove_probe (chain->blocked_pad, chain->probe_id); gst_object_unref (chain->blocked_pad); chain->blocked_pad = NULL; chain->probe_id = 0; } /* Unlike/remove tee */ peer = gst_element_get_static_pad (chain->tee, "sink"); gst_pad_unlink (pad, peer); gst_object_unref (peer); gst_element_set_state (chain->tee, GST_STATE_NULL); gst_bin_remove (GST_BIN (self), chain->tee); self->priv->chains = g_list_remove (self->priv->chains, chain); g_free (chain); GST_DEBUG ("done"); }
static void _unlink_track (GESPipeline * self, GESTrack * track) { OutputChain *chain; GST_DEBUG_OBJECT (self, "Unlinking removed %" GST_PTR_FORMAT, track); if (G_UNLIKELY (!(chain = get_output_chain_for_track (self, track)))) { GST_DEBUG_OBJECT (self, "Track wasn't used"); return; } /* Unlink encodebin */ if (chain->encodebinpad) { GstPad *peer = gst_pad_get_peer (chain->encodebinpad); gst_pad_unlink (peer, chain->encodebinpad); gst_object_unref (peer); gst_element_release_request_pad (self->priv->encodebin, chain->encodebinpad); gst_object_unref (chain->encodebinpad); } /* Unlink playsink */ if (chain->playsinkpad) { GstPad *peer = gst_pad_get_peer (chain->playsinkpad); gst_pad_unlink (peer, chain->playsinkpad); gst_object_unref (peer); gst_element_release_request_pad (self->priv->playsink, chain->playsinkpad); gst_object_unref (chain->playsinkpad); } gst_element_set_state (chain->tee, GST_STATE_NULL); gst_bin_remove (GST_BIN (self), chain->tee); if (chain->query_position_id) { g_signal_handler_disconnect (ges_track_get_composition (track), chain->query_position_id); chain->query_position_id = 0; } self->priv->chains = g_list_remove (self->priv->chains, chain); g_free (chain); GST_DEBUG ("done"); }
static void pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self) { OutputChain *chain; GESTrack *track; GstPad *sinkpad; gboolean reconfigured = FALSE; GST_DEBUG_OBJECT (self, "new pad %s:%s , caps:%" GST_PTR_FORMAT, GST_DEBUG_PAD_NAME (pad), GST_PAD_CAPS (pad)); if (G_UNLIKELY (!(track = ges_timeline_get_track_for_pad (self->priv->timeline, pad)))) { GST_WARNING_OBJECT (self, "Couldn't find coresponding track !"); return; } /* Don't connect track if it's not going to be used */ if (track->type == GES_TRACK_TYPE_VIDEO && !(self->priv->mode & TIMELINE_MODE_PREVIEW_VIDEO) && !(self->priv->mode & TIMELINE_MODE_RENDER) && !(self->priv->mode & TIMELINE_MODE_SMART_RENDER)) { GST_DEBUG_OBJECT (self, "Video track... but we don't need it. Not linking"); } if (track->type == GES_TRACK_TYPE_AUDIO && !(self->priv->mode & TIMELINE_MODE_PREVIEW_AUDIO) && !(self->priv->mode & TIMELINE_MODE_RENDER) && !(self->priv->mode & TIMELINE_MODE_SMART_RENDER)) { GST_DEBUG_OBJECT (self, "Audio track... but we don't need it. Not linking"); } /* Get an existing chain or create it */ if (!(chain = get_output_chain_for_track (self, track))) chain = new_output_chain_for_track (self, track); chain->srcpad = pad; /* Adding tee */ chain->tee = gst_element_factory_make ("tee", NULL); gst_bin_add (GST_BIN_CAST (self), chain->tee); gst_element_sync_state_with_parent (chain->tee); /* Linking pad to tee */ sinkpad = gst_element_get_static_pad (chain->tee, "sink"); gst_pad_link_full (pad, sinkpad, GST_PAD_LINK_CHECK_NOTHING); gst_object_unref (sinkpad); /* Connect playsink */ if (self->priv->mode & TIMELINE_MODE_PREVIEW) { const gchar *sinkpad_name; GstPad *tmppad; GST_DEBUG_OBJECT (self, "Connecting to playsink"); switch (track->type) { case GES_TRACK_TYPE_VIDEO: sinkpad_name = "video_sink"; break; case GES_TRACK_TYPE_AUDIO: sinkpad_name = "audio_sink"; break; case GES_TRACK_TYPE_TEXT: sinkpad_name = "text_sink"; break; default: GST_WARNING_OBJECT (self, "Can't handle tracks of type %d yet", track->type); goto error; } /* Request a sinkpad from playsink */ if (G_UNLIKELY (!(sinkpad = gst_element_get_request_pad (self->priv->playsink, sinkpad_name)))) { GST_ERROR_OBJECT (self, "Couldn't get a pad from the playsink !"); goto error; } tmppad = gst_element_get_request_pad (chain->tee, "src%d"); if (G_UNLIKELY (gst_pad_link_full (tmppad, sinkpad, GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) { GST_ERROR_OBJECT (self, "Couldn't link track pad to playsink"); gst_object_unref (tmppad); goto error; } gst_object_unref (tmppad); GST_DEBUG ("Reconfiguring playsink"); /* reconfigure playsink */ g_signal_emit_by_name (self->priv->playsink, "reconfigure", &reconfigured); GST_DEBUG ("'reconfigure' returned %d", reconfigured); /* We still hold a reference on the sinkpad */ chain->playsinkpad = sinkpad; } /* Connect to encodebin */ if (self->priv->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) { GstPad *tmppad; GST_DEBUG_OBJECT (self, "Connecting to encodebin"); if (!chain->encodebinpad) { /* Check for unused static pads */ sinkpad = get_compatible_unlinked_pad (self->priv->encodebin, pad); if (sinkpad == NULL) { GstCaps *caps = gst_pad_get_caps_reffed (pad); /* If no compatible static pad is available, request a pad */ g_signal_emit_by_name (self->priv->encodebin, "request-pad", caps, &sinkpad); gst_caps_unref (caps); if (G_UNLIKELY (sinkpad == NULL)) { GST_ERROR_OBJECT (self, "Couldn't get a pad from encodebin !"); goto error; } } chain->encodebinpad = sinkpad; } tmppad = gst_element_get_request_pad (chain->tee, "src%d"); if (G_UNLIKELY (gst_pad_link_full (tmppad, chain->encodebinpad, GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) { GST_WARNING_OBJECT (self, "Couldn't link track pad to playsink"); goto error; } gst_object_unref (tmppad); } /* If chain wasn't already present, insert it in list */ if (!get_output_chain_for_track (self, track)) self->priv->chains = g_list_append (self->priv->chains, chain); GST_DEBUG ("done"); return; error: { if (chain->tee) { gst_bin_remove (GST_BIN_CAST (self), chain->tee); } if (sinkpad) gst_object_unref (sinkpad); g_free (chain); } }