mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-30 05:31:15 +00:00
Port to the new NLE API
Port the timeline, track and pipeline to the new NLE API where all objects have static src pads.
This commit is contained in:
parent
11f9c6e108
commit
b3336fe26e
3 changed files with 110 additions and 145 deletions
|
@ -37,6 +37,10 @@
|
||||||
#include "ges-audio-track.h"
|
#include "ges-audio-track.h"
|
||||||
#include "ges-video-track.h"
|
#include "ges-video-track.h"
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_STATIC (ges_pipeline_debug);
|
||||||
|
#undef GST_CAT_DEFAULT
|
||||||
|
#define GST_CAT_DEFAULT ges_pipeline_debug
|
||||||
|
|
||||||
#define DEFAULT_TIMELINE_MODE GES_PIPELINE_MODE_PREVIEW
|
#define DEFAULT_TIMELINE_MODE GES_PIPELINE_MODE_PREVIEW
|
||||||
|
|
||||||
/* Structure corresponding to a timeline - sink link */
|
/* Structure corresponding to a timeline - sink link */
|
||||||
|
@ -48,8 +52,6 @@ typedef struct
|
||||||
GstPad *srcpad; /* Timeline source pad */
|
GstPad *srcpad; /* Timeline source pad */
|
||||||
GstPad *playsinkpad;
|
GstPad *playsinkpad;
|
||||||
GstPad *encodebinpad;
|
GstPad *encodebinpad;
|
||||||
GstPad *blocked_pad;
|
|
||||||
gulong probe_id;
|
|
||||||
} OutputChain;
|
} OutputChain;
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,6 +90,8 @@ static OutputChain *get_output_chain_for_track (GESPipeline * self,
|
||||||
GESTrack * track);
|
GESTrack * track);
|
||||||
static OutputChain *new_output_chain_for_track (GESPipeline * self,
|
static OutputChain *new_output_chain_for_track (GESPipeline * self,
|
||||||
GESTrack * track);
|
GESTrack * track);
|
||||||
|
static void _link_track (GESPipeline * self, GESTrack * track);
|
||||||
|
static void _unlink_track (GESPipeline * self, GESTrack * track);
|
||||||
|
|
||||||
/****************************************************
|
/****************************************************
|
||||||
* Video Overlay vmethods implementation *
|
* Video Overlay vmethods implementation *
|
||||||
|
@ -234,6 +238,9 @@ ges_pipeline_class_init (GESPipelineClass * klass)
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GESPipelinePrivate));
|
g_type_class_add_private (klass, sizeof (GESPipelinePrivate));
|
||||||
|
|
||||||
|
GST_DEBUG_CATEGORY_INIT (ges_pipeline_debug, "gespipeline",
|
||||||
|
GST_DEBUG_FG_YELLOW, "ges pipeline");
|
||||||
|
|
||||||
object_class->dispose = ges_pipeline_dispose;
|
object_class->dispose = ges_pipeline_dispose;
|
||||||
object_class->get_property = ges_pipeline_get_property;
|
object_class->get_property = ges_pipeline_get_property;
|
||||||
object_class->set_property = ges_pipeline_set_property;
|
object_class->set_property = ges_pipeline_set_property;
|
||||||
|
@ -434,6 +441,39 @@ done:
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_link_tracks (GESPipeline * pipeline)
|
||||||
|
{
|
||||||
|
GList *tmp;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pipeline, "Linking tracks");
|
||||||
|
|
||||||
|
if (!pipeline->priv->timeline) {
|
||||||
|
GST_INFO_OBJECT (pipeline, "Not timeline set yet, doing nothing");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tmp = pipeline->priv->timeline->tracks; tmp; tmp = tmp->next)
|
||||||
|
_link_track (pipeline, tmp->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_unlink_tracks (GESPipeline * pipeline)
|
||||||
|
{
|
||||||
|
GList *tmp;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (pipeline, "Disconnecting all tracks");
|
||||||
|
if (!pipeline->priv->timeline) {
|
||||||
|
GST_INFO_OBJECT (pipeline, "Not timeline set yet, doing nothing");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (tmp = pipeline->priv->timeline->tracks; tmp; tmp = tmp->next)
|
||||||
|
_unlink_track (pipeline, tmp->data);
|
||||||
|
}
|
||||||
|
|
||||||
static GstStateChangeReturn
|
static GstStateChangeReturn
|
||||||
ges_pipeline_change_state (GstElement * element, GstStateChange transition)
|
ges_pipeline_change_state (GstElement * element, GstStateChange transition)
|
||||||
{
|
{
|
||||||
|
@ -453,12 +493,13 @@ ges_pipeline_change_state (GstElement * element, GstStateChange transition)
|
||||||
if (self->priv->mode & (GES_PIPELINE_MODE_RENDER |
|
if (self->priv->mode & (GES_PIPELINE_MODE_RENDER |
|
||||||
GES_PIPELINE_MODE_SMART_RENDER))
|
GES_PIPELINE_MODE_SMART_RENDER))
|
||||||
GST_DEBUG ("rendering => Updating pipeline caps");
|
GST_DEBUG ("rendering => Updating pipeline caps");
|
||||||
|
/* Set caps on all tracks according to profile if present */
|
||||||
if (!ges_pipeline_update_caps (self)) {
|
if (!ges_pipeline_update_caps (self)) {
|
||||||
GST_ERROR_OBJECT (element, "Error setting the caps for rendering");
|
GST_ERROR_OBJECT (element, "Error setting the caps for rendering");
|
||||||
ret = GST_STATE_CHANGE_FAILURE;
|
ret = GST_STATE_CHANGE_FAILURE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
/* Set caps on all tracks according to profile if present */
|
_link_tracks (self);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -468,6 +509,14 @@ ges_pipeline_change_state (GstElement * element, GstStateChange transition)
|
||||||
GST_ELEMENT_CLASS (ges_pipeline_parent_class)->change_state
|
GST_ELEMENT_CLASS (ges_pipeline_parent_class)->change_state
|
||||||
(element, transition);
|
(element, transition);
|
||||||
|
|
||||||
|
switch (transition) {
|
||||||
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
||||||
|
_unlink_tracks (self);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -500,25 +549,21 @@ get_output_chain_for_track (GESPipeline * self, GESTrack * track)
|
||||||
/* Fetches a compatible pad on the target element which isn't already
|
/* Fetches a compatible pad on the target element which isn't already
|
||||||
* linked */
|
* linked */
|
||||||
static GstPad *
|
static GstPad *
|
||||||
get_compatible_unlinked_pad (GstElement * element, GstPad * pad)
|
get_compatible_unlinked_pad (GstElement * element, GESTrack * track)
|
||||||
{
|
{
|
||||||
GstPad *res = NULL;
|
GstPad *res = NULL;
|
||||||
GstIterator *pads;
|
GstIterator *pads;
|
||||||
gboolean done = FALSE;
|
gboolean done = FALSE;
|
||||||
GstCaps *srccaps;
|
const GstCaps *srccaps;
|
||||||
GValue paditem = { 0, };
|
GValue paditem = { 0, };
|
||||||
|
|
||||||
if (G_UNLIKELY (pad == NULL))
|
if (G_UNLIKELY (track == NULL))
|
||||||
goto no_pad;
|
goto no_track;
|
||||||
|
|
||||||
GST_DEBUG ("element : %s, pad %s:%s",
|
GST_DEBUG_OBJECT (element, " track %" GST_PTR_FORMAT, track);
|
||||||
GST_ELEMENT_NAME (element), GST_DEBUG_PAD_NAME (pad));
|
|
||||||
|
|
||||||
if (GST_PAD_DIRECTION (pad) == GST_PAD_SRC)
|
pads = gst_element_iterate_sink_pads (element);
|
||||||
pads = gst_element_iterate_sink_pads (element);
|
srccaps = ges_track_get_caps (track);
|
||||||
else
|
|
||||||
pads = gst_element_iterate_src_pads (element);
|
|
||||||
srccaps = gst_pad_query_caps (pad, NULL);
|
|
||||||
|
|
||||||
GST_DEBUG ("srccaps %" GST_PTR_FORMAT, srccaps);
|
GST_DEBUG ("srccaps %" GST_PTR_FORMAT, srccaps);
|
||||||
|
|
||||||
|
@ -553,34 +598,27 @@ get_compatible_unlinked_pad (GstElement * element, GstPad * pad)
|
||||||
}
|
}
|
||||||
g_value_reset (&paditem);
|
g_value_reset (&paditem);
|
||||||
gst_iterator_free (pads);
|
gst_iterator_free (pads);
|
||||||
gst_caps_unref (srccaps);
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
no_pad:
|
no_track:
|
||||||
{
|
{
|
||||||
GST_ERROR ("No pad to check against");
|
GST_ERROR ("No track to check against");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstPadProbeReturn
|
|
||||||
pad_blocked (GstPad * pad, GstPadProbeInfo * info, gpointer user_data)
|
|
||||||
{
|
|
||||||
/* no nothing */
|
|
||||||
GST_DEBUG_OBJECT (pad, "blocked callback, blocked");
|
|
||||||
return GST_PAD_PROBE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pad_added_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
_link_track (GESPipeline * self, GESTrack * track)
|
||||||
{
|
{
|
||||||
|
GstPad *pad;
|
||||||
OutputChain *chain;
|
OutputChain *chain;
|
||||||
GESTrack *track;
|
|
||||||
GstPad *sinkpad;
|
GstPad *sinkpad;
|
||||||
GstCaps *caps;
|
GstCaps *caps;
|
||||||
|
GstPadLinkReturn lret;
|
||||||
gboolean reconfigured = FALSE;
|
gboolean reconfigured = FALSE;
|
||||||
|
|
||||||
|
pad = ges_timeline_get_pad_for_track (self->priv->timeline, track);
|
||||||
caps = gst_pad_query_caps (pad, NULL);
|
caps = gst_pad_query_caps (pad, NULL);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "new pad %s:%s , caps:%" GST_PTR_FORMAT,
|
GST_DEBUG_OBJECT (self, "new pad %s:%s , caps:%" GST_PTR_FORMAT,
|
||||||
|
@ -588,8 +626,6 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
|
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
|
|
||||||
track = ges_timeline_get_track_for_pad (self->priv->timeline, pad);
|
|
||||||
|
|
||||||
if (G_UNLIKELY (!track)) {
|
if (G_UNLIKELY (!track)) {
|
||||||
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
||||||
return;
|
return;
|
||||||
|
@ -613,15 +649,23 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
if (!(chain = get_output_chain_for_track (self, track)))
|
if (!(chain = get_output_chain_for_track (self, track)))
|
||||||
chain = new_output_chain_for_track (self, track);
|
chain = new_output_chain_for_track (self, track);
|
||||||
chain->srcpad = pad;
|
chain->srcpad = pad;
|
||||||
|
gst_object_unref (pad);
|
||||||
|
|
||||||
/* Adding tee */
|
/* Adding tee */
|
||||||
chain->tee = gst_element_factory_make ("tee", NULL);
|
if (!chain->tee) {
|
||||||
gst_bin_add (GST_BIN_CAST (self), chain->tee);
|
chain->tee = gst_element_factory_make ("tee", NULL);
|
||||||
gst_element_sync_state_with_parent (chain->tee);
|
gst_bin_add (GST_BIN_CAST (self), chain->tee);
|
||||||
|
gst_element_sync_state_with_parent (chain->tee);
|
||||||
|
}
|
||||||
|
|
||||||
/* Linking pad to tee */
|
/* Linking pad to tee */
|
||||||
sinkpad = gst_element_get_static_pad (chain->tee, "sink");
|
sinkpad = gst_element_get_static_pad (chain->tee, "sink");
|
||||||
gst_pad_link_full (pad, sinkpad, GST_PAD_LINK_CHECK_NOTHING);
|
lret = gst_pad_link (pad, sinkpad);
|
||||||
|
if (lret != GST_PAD_LINK_OK) {
|
||||||
|
GST_ERROR_OBJECT (self, "Could not link the tee (%i)", lret);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
|
|
||||||
/* Connect playsink */
|
/* Connect playsink */
|
||||||
|
@ -658,14 +702,10 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
tmppad = gst_element_get_request_pad (chain->tee, "src_%u");
|
tmppad = gst_element_get_request_pad (chain->tee, "src_%u");
|
||||||
if (G_UNLIKELY (gst_pad_link_full (tmppad, sinkpad,
|
if (G_UNLIKELY (gst_pad_link_full (tmppad, sinkpad,
|
||||||
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) {
|
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't link track pad to playsink");
|
GST_ERROR_OBJECT (self, "Couldn't link track pad to encodebin");
|
||||||
gst_object_unref (tmppad);
|
gst_object_unref (tmppad);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
chain->blocked_pad = tmppad;
|
|
||||||
GST_DEBUG_OBJECT (tmppad, "blocking pad");
|
|
||||||
chain->probe_id = gst_pad_add_probe (tmppad,
|
|
||||||
GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, pad_blocked, NULL, NULL);
|
|
||||||
|
|
||||||
GST_DEBUG ("Reconfiguring playsink");
|
GST_DEBUG ("Reconfiguring playsink");
|
||||||
|
|
||||||
|
@ -685,7 +725,7 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
|
|
||||||
if (!chain->encodebinpad) {
|
if (!chain->encodebinpad) {
|
||||||
/* Check for unused static pads */
|
/* Check for unused static pads */
|
||||||
sinkpad = get_compatible_unlinked_pad (self->priv->encodebin, pad);
|
sinkpad = get_compatible_unlinked_pad (self->priv->encodebin, track);
|
||||||
|
|
||||||
if (sinkpad == NULL) {
|
if (sinkpad == NULL) {
|
||||||
GstCaps *caps = gst_pad_query_caps (pad, NULL);
|
GstCaps *caps = gst_pad_query_caps (pad, NULL);
|
||||||
|
@ -704,10 +744,9 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmppad = gst_element_get_request_pad (chain->tee, "src_%u");
|
tmppad = gst_element_get_request_pad (chain->tee, "src_%u");
|
||||||
if (G_UNLIKELY (gst_pad_link_full (tmppad,
|
if (G_UNLIKELY (gst_pad_link_full (tmppad, chain->encodebinpad,
|
||||||
chain->encodebinpad,
|
|
||||||
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) {
|
GST_PAD_LINK_CHECK_NOTHING) != GST_PAD_LINK_OK)) {
|
||||||
GST_WARNING_OBJECT (self, "Couldn't link track pad to playsink");
|
GST_ERROR_OBJECT (self, "Couldn't link track pad to encodebin");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
gst_object_unref (tmppad);
|
gst_object_unref (tmppad);
|
||||||
|
@ -733,25 +772,19 @@ error:
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pad_removed_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
_unlink_track (GESPipeline * self, GESTrack * track)
|
||||||
{
|
{
|
||||||
OutputChain *chain;
|
OutputChain *chain;
|
||||||
GESTrack *track;
|
GstPad *pad, *peer;
|
||||||
GstPad *peer;
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (self, "pad removed %s:%s", GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG_OBJECT (self, "Unlinking removed %" GST_PTR_FORMAT, track);
|
||||||
|
|
||||||
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)))) {
|
if (G_UNLIKELY (!(chain = get_output_chain_for_track (self, track)))) {
|
||||||
GST_DEBUG_OBJECT (self, "Pad wasn't used");
|
GST_DEBUG_OBJECT (self, "Track wasn't used");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pad = ges_timeline_get_pad_for_track (self->priv->timeline, track);
|
||||||
/* Unlink encodebin */
|
/* Unlink encodebin */
|
||||||
if (chain->encodebinpad) {
|
if (chain->encodebinpad) {
|
||||||
peer = gst_pad_get_peer (chain->encodebinpad);
|
peer = gst_pad_get_peer (chain->encodebinpad);
|
||||||
|
@ -771,14 +804,6 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
gst_object_unref (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 */
|
/* Unlike/remove tee */
|
||||||
peer = gst_element_get_static_pad (chain->tee, "sink");
|
peer = gst_element_get_static_pad (chain->tee, "sink");
|
||||||
gst_pad_unlink (pad, peer);
|
gst_pad_unlink (pad, peer);
|
||||||
|
@ -788,29 +813,11 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESPipeline * self)
|
||||||
|
|
||||||
self->priv->chains = g_list_remove (self->priv->chains, chain);
|
self->priv->chains = g_list_remove (self->priv->chains, chain);
|
||||||
g_free (chain);
|
g_free (chain);
|
||||||
|
gst_object_unref (pad);
|
||||||
|
|
||||||
GST_DEBUG ("done");
|
GST_DEBUG ("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
no_more_pads_cb (GstElement * timeline, GESPipeline * self)
|
|
||||||
{
|
|
||||||
GList *tmp;
|
|
||||||
|
|
||||||
GST_DEBUG ("received no-more-pads");
|
|
||||||
for (tmp = self->priv->chains; tmp; tmp = g_list_next (tmp)) {
|
|
||||||
OutputChain *chain = (OutputChain *) tmp->data;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ges_pipeline_set_timeline:
|
* ges_pipeline_set_timeline:
|
||||||
* @pipeline: a #GESPipeline
|
* @pipeline: a #GESPipeline
|
||||||
|
@ -826,6 +833,7 @@ no_more_pads_cb (GstElement * timeline, GESPipeline * self)
|
||||||
gboolean
|
gboolean
|
||||||
ges_pipeline_set_timeline (GESPipeline * pipeline, GESTimeline * timeline)
|
ges_pipeline_set_timeline (GESPipeline * pipeline, GESTimeline * timeline)
|
||||||
{
|
{
|
||||||
|
|
||||||
g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE);
|
g_return_val_if_fail (GES_IS_PIPELINE (pipeline), FALSE);
|
||||||
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
|
g_return_val_if_fail (GES_IS_TIMELINE (timeline), FALSE);
|
||||||
g_return_val_if_fail (pipeline->priv->timeline == NULL, FALSE);
|
g_return_val_if_fail (pipeline->priv->timeline == NULL, FALSE);
|
||||||
|
@ -838,13 +846,6 @@ ges_pipeline_set_timeline (GESPipeline * pipeline, GESTimeline * timeline)
|
||||||
}
|
}
|
||||||
pipeline->priv->timeline = timeline;
|
pipeline->priv->timeline = timeline;
|
||||||
|
|
||||||
/* Connect to pipeline */
|
|
||||||
g_signal_connect (timeline, "pad-added", (GCallback) pad_added_cb, pipeline);
|
|
||||||
g_signal_connect (timeline, "pad-removed", (GCallback) pad_removed_cb,
|
|
||||||
pipeline);
|
|
||||||
g_signal_connect (timeline, "no-more-pads", (GCallback) no_more_pads_cb,
|
|
||||||
pipeline);
|
|
||||||
|
|
||||||
/* FIXME Check if we should rollback if we can't sync state */
|
/* FIXME Check if we should rollback if we can't sync state */
|
||||||
gst_element_sync_state_with_parent (GST_ELEMENT (timeline));
|
gst_element_sync_state_with_parent (GST_ELEMENT (timeline));
|
||||||
|
|
||||||
|
|
|
@ -2400,19 +2400,18 @@ _pad_probe_cb (GstPad * mixer_pad, GstPadProbeInfo * info,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pad_added_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
|
_ghost_track_srcpad (TrackPrivate * tr_priv)
|
||||||
{
|
{
|
||||||
|
GstPad *pad;
|
||||||
gchar *padname;
|
gchar *padname;
|
||||||
gboolean no_more;
|
gboolean no_more;
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
|
GESTrack *track = tr_priv->track;
|
||||||
|
|
||||||
|
pad = gst_element_get_static_pad (GST_ELEMENT (track), "src");
|
||||||
|
|
||||||
GST_DEBUG ("track:%p, pad:%s:%s", track, GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG ("track:%p, pad:%s:%s", track, GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
if (G_UNLIKELY (tr_priv->pad)) {
|
|
||||||
GST_WARNING ("We are already controlling a pad for this track");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Remember the pad */
|
/* Remember the pad */
|
||||||
LOCK_DYN (tr_priv->timeline);
|
LOCK_DYN (tr_priv->timeline);
|
||||||
GST_OBJECT_LOCK (track);
|
GST_OBJECT_LOCK (track);
|
||||||
|
@ -2449,28 +2448,6 @@ pad_added_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
|
||||||
UNLOCK_DYN (tr_priv->timeline);
|
UNLOCK_DYN (tr_priv->timeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pad_removed_cb (GESTrack * track, GstPad * pad, TrackPrivate * tr_priv)
|
|
||||||
{
|
|
||||||
GST_DEBUG ("track:%p, pad:%s:%s", track, GST_DEBUG_PAD_NAME (pad));
|
|
||||||
|
|
||||||
if (G_UNLIKELY (tr_priv->pad != pad)) {
|
|
||||||
GST_WARNING ("Not the pad we're controlling");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (G_UNLIKELY (tr_priv->ghostpad == NULL)) {
|
|
||||||
GST_WARNING ("We don't have a ghostpad for this pad !");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("Removing ghostpad");
|
|
||||||
gst_pad_set_active (tr_priv->ghostpad, FALSE);
|
|
||||||
gst_element_remove_pad (GST_ELEMENT (tr_priv->timeline), tr_priv->ghostpad);
|
|
||||||
tr_priv->ghostpad = NULL;
|
|
||||||
tr_priv->pad = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
timeline_add_element (GESTimeline * timeline, GESTimelineElement * element)
|
timeline_add_element (GESTimeline * timeline, GESTimelineElement * element)
|
||||||
{
|
{
|
||||||
|
@ -2809,10 +2786,6 @@ ges_timeline_add_track (GESTimeline * timeline, GESTrack * track)
|
||||||
UNLOCK_DYN (timeline);
|
UNLOCK_DYN (timeline);
|
||||||
timeline->tracks = g_list_append (timeline->tracks, track);
|
timeline->tracks = g_list_append (timeline->tracks, track);
|
||||||
|
|
||||||
/* Listen to pad-added/-removed */
|
|
||||||
g_signal_connect (track, "pad-added", (GCallback) pad_added_cb, tr_priv);
|
|
||||||
g_signal_connect (track, "pad-removed", (GCallback) pad_removed_cb, tr_priv);
|
|
||||||
|
|
||||||
/* Inform the track that it's currently being used by ourself */
|
/* Inform the track that it's currently being used by ourself */
|
||||||
ges_track_set_timeline (track, timeline);
|
ges_track_set_timeline (track, timeline);
|
||||||
|
|
||||||
|
@ -2843,6 +2816,8 @@ ges_timeline_add_track (GESTimeline * timeline, GESTrack * track)
|
||||||
g_list_free (objects);
|
g_list_free (objects);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_ghost_track_srcpad (tr_priv);
|
||||||
|
|
||||||
/* FIXME Check if we should rollback if we can't sync state */
|
/* FIXME Check if we should rollback if we can't sync state */
|
||||||
gst_element_sync_state_with_parent (GST_ELEMENT (track));
|
gst_element_sync_state_with_parent (GST_ELEMENT (track));
|
||||||
g_object_set (track, "message-forward", TRUE, NULL);
|
g_object_set (track, "message-forward", TRUE, NULL);
|
||||||
|
@ -2904,8 +2879,6 @@ ges_timeline_remove_track (GESTimeline * timeline, GESTrack * track)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Remove pad-added/-removed handlers */
|
/* Remove pad-added/-removed handlers */
|
||||||
g_signal_handlers_disconnect_by_func (track, pad_added_cb, tr_priv);
|
|
||||||
g_signal_handlers_disconnect_by_func (track, pad_removed_cb, tr_priv);
|
|
||||||
g_signal_handlers_disconnect_by_func (track, track_element_added_cb,
|
g_signal_handlers_disconnect_by_func (track, track_element_added_cb,
|
||||||
timeline);
|
timeline);
|
||||||
g_signal_handlers_disconnect_by_func (track, track_element_removed_cb,
|
g_signal_handlers_disconnect_by_func (track, track_element_removed_cb,
|
||||||
|
|
|
@ -37,6 +37,12 @@
|
||||||
G_DEFINE_TYPE_WITH_CODE (GESTrack, ges_track, GST_TYPE_BIN,
|
G_DEFINE_TYPE_WITH_CODE (GESTrack, ges_track, GST_TYPE_BIN,
|
||||||
G_IMPLEMENT_INTERFACE (GES_TYPE_META_CONTAINER, NULL));
|
G_IMPLEMENT_INTERFACE (GES_TYPE_META_CONTAINER, NULL));
|
||||||
|
|
||||||
|
static GstStaticPadTemplate ges_track_src_pad_template =
|
||||||
|
GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
|
GST_PAD_SRC,
|
||||||
|
GST_PAD_ALWAYS,
|
||||||
|
GST_STATIC_CAPS_ANY);
|
||||||
|
|
||||||
/* Structure that represents gaps and keep knowledge
|
/* Structure that represents gaps and keep knowledge
|
||||||
* of the gaps filled in the track */
|
* of the gaps filled in the track */
|
||||||
typedef struct
|
typedef struct
|
||||||
|
@ -92,9 +98,6 @@ static guint ges_track_signals[LAST_SIGNAL] = { 0 };
|
||||||
|
|
||||||
static GParamSpec *properties[ARG_LAST];
|
static GParamSpec *properties[ARG_LAST];
|
||||||
|
|
||||||
static void pad_added_cb (GstElement * element, GstPad * pad, GESTrack * track);
|
|
||||||
static void
|
|
||||||
pad_removed_cb (GstElement * element, GstPad * pad, GESTrack * track);
|
|
||||||
static void composition_duration_cb (GstElement * composition, GParamSpec * arg
|
static void composition_duration_cb (GstElement * composition, GParamSpec * arg
|
||||||
G_GNUC_UNUSED, GESTrack * obj);
|
G_GNUC_UNUSED, GESTrack * obj);
|
||||||
|
|
||||||
|
@ -256,9 +259,10 @@ sort_track_elements_cb (GESTrackElement * child,
|
||||||
static void
|
static void
|
||||||
_ghost_nlecomposition_srcpad (GESTrack * track)
|
_ghost_nlecomposition_srcpad (GESTrack * track)
|
||||||
{
|
{
|
||||||
GESTrackPrivate *priv = track->priv;
|
|
||||||
GstPad *capsfilter_sink;
|
GstPad *capsfilter_sink;
|
||||||
GstPad *capsfilter_src;
|
GstPad *capsfilter_src;
|
||||||
|
GESTrackPrivate *priv = track->priv;
|
||||||
|
GstPad *pad = gst_element_get_static_pad (priv->composition, "src");
|
||||||
|
|
||||||
capsfilter_sink = gst_element_get_static_pad (priv->capsfilter, "sink");
|
capsfilter_sink = gst_element_get_static_pad (priv->capsfilter, "sink");
|
||||||
|
|
||||||
|
@ -277,22 +281,6 @@ _ghost_nlecomposition_srcpad (GESTrack * track)
|
||||||
GST_DEBUG ("done");
|
GST_DEBUG ("done");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
pad_removed_cb (GstElement * element, GstPad * pad, GESTrack * track)
|
|
||||||
{
|
|
||||||
GESTrackPrivate *priv = track->priv;
|
|
||||||
|
|
||||||
GST_DEBUG ("track:%p, pad %s:%s", track, GST_DEBUG_PAD_NAME (pad));
|
|
||||||
|
|
||||||
if (G_LIKELY (priv->srcpad)) {
|
|
||||||
gst_pad_set_active (priv->srcpad, FALSE);
|
|
||||||
gst_element_remove_pad (GST_ELEMENT (track), priv->srcpad);
|
|
||||||
priv->srcpad = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG ("done");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
composition_duration_cb (GstElement * composition,
|
composition_duration_cb (GstElement * composition,
|
||||||
GParamSpec * arg G_GNUC_UNUSED, GESTrack * track)
|
GParamSpec * arg G_GNUC_UNUSED, GESTrack * track)
|
||||||
|
@ -423,6 +411,7 @@ ges_track_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GESTrack *track = (GESTrack *) object;
|
GESTrack *track = (GESTrack *) object;
|
||||||
GESTrackPrivate *priv = track->priv;
|
GESTrackPrivate *priv = track->priv;
|
||||||
|
gboolean ret;
|
||||||
|
|
||||||
/* Remove all TrackElements and drop our reference */
|
/* Remove all TrackElements and drop our reference */
|
||||||
g_hash_table_unref (priv->trackelements_iter);
|
g_hash_table_unref (priv->trackelements_iter);
|
||||||
|
@ -430,11 +419,13 @@ ges_track_dispose (GObject * object)
|
||||||
(GFunc) dispose_trackelements_foreach, track);
|
(GFunc) dispose_trackelements_foreach, track);
|
||||||
g_sequence_free (priv->trackelements_by_start);
|
g_sequence_free (priv->trackelements_by_start);
|
||||||
g_list_free_full (priv->gaps, (GDestroyNotify) free_gap);
|
g_list_free_full (priv->gaps, (GDestroyNotify) free_gap);
|
||||||
|
g_signal_emit_by_name (track->priv->composition, "commit", TRUE, &ret);
|
||||||
|
|
||||||
if (priv->mixing_operation)
|
if (priv->mixing_operation)
|
||||||
gst_object_unref (priv->mixing_operation);
|
gst_object_unref (priv->mixing_operation);
|
||||||
|
|
||||||
if (priv->composition) {
|
if (priv->composition) {
|
||||||
|
gst_element_remove_pad (GST_ELEMENT (track), priv->srcpad);
|
||||||
gst_bin_remove (GST_BIN (object), priv->composition);
|
gst_bin_remove (GST_BIN (object), priv->composition);
|
||||||
priv->composition = NULL;
|
priv->composition = NULL;
|
||||||
}
|
}
|
||||||
|
@ -508,6 +499,7 @@ static void
|
||||||
ges_track_class_init (GESTrackClass * klass)
|
ges_track_class_init (GESTrackClass * klass)
|
||||||
{
|
{
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
|
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
g_type_class_add_private (klass, sizeof (GESTrackPrivate));
|
g_type_class_add_private (klass, sizeof (GESTrackPrivate));
|
||||||
|
|
||||||
|
@ -586,6 +578,9 @@ ges_track_class_init (GESTrackClass * klass)
|
||||||
g_object_class_install_property (object_class, ARG_MIXING,
|
g_object_class_install_property (object_class, ARG_MIXING,
|
||||||
properties[ARG_MIXING]);
|
properties[ARG_MIXING]);
|
||||||
|
|
||||||
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
gst_static_pad_template_get (&ges_track_src_pad_template));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GESTrack::track-element-added:
|
* GESTrack::track-element-added:
|
||||||
* @object: the #GESTrack
|
* @object: the #GESTrack
|
||||||
|
@ -632,10 +627,6 @@ ges_track_init (GESTrack * self)
|
||||||
|
|
||||||
g_signal_connect (G_OBJECT (self->priv->composition), "notify::duration",
|
g_signal_connect (G_OBJECT (self->priv->composition), "notify::duration",
|
||||||
G_CALLBACK (composition_duration_cb), self);
|
G_CALLBACK (composition_duration_cb), self);
|
||||||
g_signal_connect (self->priv->composition, "pad-added",
|
|
||||||
(GCallback) pad_added_cb, self);
|
|
||||||
g_signal_connect (self->priv->composition, "pad-removed",
|
|
||||||
(GCallback) pad_removed_cb, self);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue