mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 19:51:11 +00:00
GESTimelinePipeline: add a private structure
This commit is contained in:
parent
a66d8eaf16
commit
8d19b737d8
2 changed files with 110 additions and 94 deletions
|
@ -48,6 +48,21 @@ typedef struct
|
||||||
|
|
||||||
G_DEFINE_TYPE (GESTimelinePipeline, ges_timeline_pipeline, GST_TYPE_PIPELINE);
|
G_DEFINE_TYPE (GESTimelinePipeline, ges_timeline_pipeline, GST_TYPE_PIPELINE);
|
||||||
|
|
||||||
|
struct _GESTimelinePipelinePrivate
|
||||||
|
{
|
||||||
|
GESTimeline *timeline;
|
||||||
|
GstElement *playsink;
|
||||||
|
GstElement *encodebin;
|
||||||
|
/* Note : urisink is only created when a URI has been provided */
|
||||||
|
GstElement *urisink;
|
||||||
|
|
||||||
|
GESPipelineFlags mode;
|
||||||
|
|
||||||
|
GList *chains;
|
||||||
|
|
||||||
|
GstEncodingProfile *profile;
|
||||||
|
};
|
||||||
|
|
||||||
static GstStateChangeReturn ges_timeline_pipeline_change_state (GstElement *
|
static GstStateChangeReturn ges_timeline_pipeline_change_state (GstElement *
|
||||||
element, GstStateChange transition);
|
element, GstStateChange transition);
|
||||||
|
|
||||||
|
@ -63,25 +78,25 @@ ges_timeline_pipeline_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GESTimelinePipeline *self = GES_TIMELINE_PIPELINE (object);
|
GESTimelinePipeline *self = GES_TIMELINE_PIPELINE (object);
|
||||||
|
|
||||||
if (self->playsink) {
|
if (self->priv->playsink) {
|
||||||
if (self->mode & (TIMELINE_MODE_PREVIEW))
|
if (self->priv->mode & (TIMELINE_MODE_PREVIEW))
|
||||||
gst_bin_remove (GST_BIN (object), self->playsink);
|
gst_bin_remove (GST_BIN (object), self->priv->playsink);
|
||||||
else
|
else
|
||||||
gst_object_unref (self->playsink);
|
gst_object_unref (self->priv->playsink);
|
||||||
self->playsink = NULL;
|
self->priv->playsink = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->encodebin) {
|
if (self->priv->encodebin) {
|
||||||
if (self->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))
|
if (self->priv->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))
|
||||||
gst_bin_remove (GST_BIN (object), self->encodebin);
|
gst_bin_remove (GST_BIN (object), self->priv->encodebin);
|
||||||
else
|
else
|
||||||
gst_object_unref (self->encodebin);
|
gst_object_unref (self->priv->encodebin);
|
||||||
self->encodebin = NULL;
|
self->priv->encodebin = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (self->profile) {
|
if (self->priv->profile) {
|
||||||
gst_encoding_profile_free (self->profile);
|
gst_encoding_profile_free (self->priv->profile);
|
||||||
self->profile = NULL;
|
self->priv->profile = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
G_OBJECT_CLASS (ges_timeline_pipeline_parent_class)->dispose (object);
|
G_OBJECT_CLASS (ges_timeline_pipeline_parent_class)->dispose (object);
|
||||||
|
@ -93,6 +108,8 @@ ges_timeline_pipeline_class_init (GESTimelinePipelineClass * klass)
|
||||||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||||
|
|
||||||
|
g_type_class_add_private (klass, sizeof (GESTimelinePipelinePrivate));
|
||||||
|
|
||||||
object_class->dispose = ges_timeline_pipeline_dispose;
|
object_class->dispose = ges_timeline_pipeline_dispose;
|
||||||
|
|
||||||
element_class->change_state =
|
element_class->change_state =
|
||||||
|
@ -108,27 +125,27 @@ ges_timeline_pipeline_init (GESTimelinePipeline * self)
|
||||||
GstElementClass *playsinkclass;
|
GstElementClass *playsinkclass;
|
||||||
|
|
||||||
GST_INFO_OBJECT (self, "Creating new 'playsink'");
|
GST_INFO_OBJECT (self, "Creating new 'playsink'");
|
||||||
|
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
|
||||||
|
GES_TYPE_TIMELINE_PIPELINE, GESTimelinePipelinePrivate);
|
||||||
|
|
||||||
self->playsink = gst_element_factory_make ("playsink", "internal-sinks");
|
self->priv->playsink =
|
||||||
self->encodebin =
|
gst_element_factory_make ("playsink", "internal-sinks");
|
||||||
|
self->priv->encodebin =
|
||||||
gst_element_factory_make ("encodebin", "internal-encodebin");
|
gst_element_factory_make ("encodebin", "internal-encodebin");
|
||||||
/* Limit encodebin buffering to 1 buffer since we know the various
|
/* Limit encodebin buffering to 1 buffer since we know the various
|
||||||
* stream fed to it are decoupled already */
|
* stream fed to it are decoupled already */
|
||||||
g_object_set (self->encodebin, "queue-buffers-max", (guint32) 1,
|
g_object_set (self->priv->encodebin, "queue-buffers-max", (guint32) 1,
|
||||||
"queue-bytes-max", (guint32) 0, "queue-time-max", (guint64) 0,
|
"queue-bytes-max", (guint32) 0, "queue-time-max", (guint64) 0,
|
||||||
"use-smartencoder", TRUE, NULL);
|
"use-smartencoder", TRUE, NULL);
|
||||||
|
|
||||||
if (G_UNLIKELY (self->playsink == NULL)) {
|
if (G_UNLIKELY (self->priv->playsink == NULL))
|
||||||
GST_ERROR_OBJECT (self, "Can't create playsink instance !");
|
GST_ERROR_OBJECT (self, "Can't create playsink instance !");
|
||||||
return;
|
if (G_UNLIKELY (self->priv->encodebin == NULL))
|
||||||
}
|
|
||||||
if (G_UNLIKELY (self->encodebin == NULL)) {
|
|
||||||
GST_ERROR_OBJECT (self, "Can't create encodebin instance !");
|
GST_ERROR_OBJECT (self, "Can't create encodebin instance !");
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
/* HACK : Intercept events going through playsink */
|
/* HACK : Intercept events going through playsink */
|
||||||
playsinkclass = GST_ELEMENT_GET_CLASS (self->playsink);
|
playsinkclass = GST_ELEMENT_GET_CLASS (self->priv->playsink);
|
||||||
/* Replace playsink's GstBin::send_event with our own */
|
/* Replace playsink's GstBin::send_event with our own */
|
||||||
playsinkclass->send_event = play_sink_multiple_seeks_send_event;
|
playsinkclass->send_event = play_sink_multiple_seeks_send_event;
|
||||||
|
|
||||||
|
@ -158,12 +175,12 @@ ges_timeline_pipeline_update_caps (GESTimelinePipeline * self)
|
||||||
{
|
{
|
||||||
GList *ltrack, *tracks, *lstream;
|
GList *ltrack, *tracks, *lstream;
|
||||||
|
|
||||||
if (!self->profile)
|
if (!self->priv->profile)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
GST_DEBUG ("Updating track caps");
|
GST_DEBUG ("Updating track caps");
|
||||||
|
|
||||||
tracks = ges_timeline_get_tracks (self->timeline);
|
tracks = ges_timeline_get_tracks (self->priv->timeline);
|
||||||
|
|
||||||
/* Take each stream of the encoding profile and find a matching
|
/* Take each stream of the encoding profile and find a matching
|
||||||
* track to set the caps on */
|
* track to set the caps on */
|
||||||
|
@ -171,13 +188,13 @@ ges_timeline_pipeline_update_caps (GESTimelinePipeline * self)
|
||||||
GESTrack *track = (GESTrack *) ltrack->data;
|
GESTrack *track = (GESTrack *) ltrack->data;
|
||||||
|
|
||||||
/* Find a matching stream setting */
|
/* Find a matching stream setting */
|
||||||
for (lstream = self->profile->encodingprofiles; lstream;
|
for (lstream = self->priv->profile->encodingprofiles; lstream;
|
||||||
lstream = lstream->next) {
|
lstream = lstream->next) {
|
||||||
GstStreamEncodingProfile *prof =
|
GstStreamEncodingProfile *prof =
|
||||||
(GstStreamEncodingProfile *) lstream->data;
|
(GstStreamEncodingProfile *) lstream->data;
|
||||||
|
|
||||||
if (TRACK_COMPATIBLE_PROFILE (track->type, prof->type)) {
|
if (TRACK_COMPATIBLE_PROFILE (track->type, prof->type)) {
|
||||||
if (self->mode == TIMELINE_MODE_SMART_RENDER) {
|
if (self->priv->mode == TIMELINE_MODE_SMART_RENDER) {
|
||||||
GstCaps *ocaps, *rcaps;
|
GstCaps *ocaps, *rcaps;
|
||||||
|
|
||||||
GST_DEBUG ("Smart Render mode, setting output caps");
|
GST_DEBUG ("Smart Render mode, setting output caps");
|
||||||
|
@ -228,13 +245,14 @@ ges_timeline_pipeline_change_state (GstElement * element,
|
||||||
|
|
||||||
switch (transition) {
|
switch (transition) {
|
||||||
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
||||||
if (G_UNLIKELY (self->timeline == NULL)) {
|
if (G_UNLIKELY (self->priv->timeline == NULL)) {
|
||||||
GST_ERROR_OBJECT (element,
|
GST_ERROR_OBJECT (element,
|
||||||
"No GESTimeline set on the pipeline, cannot play !");
|
"No GESTimeline set on the pipeline, cannot play !");
|
||||||
ret = GST_STATE_CHANGE_FAILURE;
|
ret = GST_STATE_CHANGE_FAILURE;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (self->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))
|
if (self->
|
||||||
|
priv->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))
|
||||||
GST_DEBUG ("rendering => Updating pipeline caps");
|
GST_DEBUG ("rendering => Updating pipeline caps");
|
||||||
if (!ges_timeline_pipeline_update_caps (self)) {
|
if (!ges_timeline_pipeline_update_caps (self)) {
|
||||||
GST_ERROR_OBJECT (element, "Error setting the caps for rendering");
|
GST_ERROR_OBJECT (element, "Error setting the caps for rendering");
|
||||||
|
@ -272,7 +290,7 @@ get_output_chain_for_track (GESTimelinePipeline * self, GESTrack * track)
|
||||||
{
|
{
|
||||||
GList *tmp;
|
GList *tmp;
|
||||||
|
|
||||||
for (tmp = self->chains; tmp; tmp = tmp->next) {
|
for (tmp = self->priv->chains; tmp; tmp = tmp->next) {
|
||||||
OutputChain *chain = (OutputChain *) tmp->data;
|
OutputChain *chain = (OutputChain *) tmp->data;
|
||||||
if (chain->track == track)
|
if (chain->track == track)
|
||||||
return chain;
|
return chain;
|
||||||
|
@ -353,22 +371,22 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
GST_DEBUG_PAD_NAME (pad), GST_PAD_CAPS (pad));
|
GST_DEBUG_PAD_NAME (pad), GST_PAD_CAPS (pad));
|
||||||
|
|
||||||
if (G_UNLIKELY (!(track =
|
if (G_UNLIKELY (!(track =
|
||||||
ges_timeline_get_track_for_pad (self->timeline, pad)))) {
|
ges_timeline_get_track_for_pad (self->priv->timeline, pad)))) {
|
||||||
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't connect track if it's not going to be used */
|
/* Don't connect track if it's not going to be used */
|
||||||
if (track->type == GES_TRACK_TYPE_VIDEO &&
|
if (track->type == GES_TRACK_TYPE_VIDEO &&
|
||||||
!(self->mode & TIMELINE_MODE_PREVIEW_VIDEO) &&
|
!(self->priv->mode & TIMELINE_MODE_PREVIEW_VIDEO) &&
|
||||||
!(self->mode & TIMELINE_MODE_RENDER) &&
|
!(self->priv->mode & TIMELINE_MODE_RENDER) &&
|
||||||
!(self->mode & TIMELINE_MODE_SMART_RENDER)) {
|
!(self->priv->mode & TIMELINE_MODE_SMART_RENDER)) {
|
||||||
GST_DEBUG_OBJECT (self, "Video track... but we don't need it. Not linking");
|
GST_DEBUG_OBJECT (self, "Video track... but we don't need it. Not linking");
|
||||||
}
|
}
|
||||||
if (track->type == GES_TRACK_TYPE_AUDIO &&
|
if (track->type == GES_TRACK_TYPE_AUDIO &&
|
||||||
!(self->mode & TIMELINE_MODE_PREVIEW_AUDIO) &&
|
!(self->priv->mode & TIMELINE_MODE_PREVIEW_AUDIO) &&
|
||||||
!(self->mode & TIMELINE_MODE_RENDER) &&
|
!(self->priv->mode & TIMELINE_MODE_RENDER) &&
|
||||||
!(self->mode & TIMELINE_MODE_SMART_RENDER)) {
|
!(self->priv->mode & TIMELINE_MODE_SMART_RENDER)) {
|
||||||
GST_DEBUG_OBJECT (self, "Audio track... but we don't need it. Not linking");
|
GST_DEBUG_OBJECT (self, "Audio track... but we don't need it. Not linking");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,7 +406,7 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
gst_object_unref (sinkpad);
|
gst_object_unref (sinkpad);
|
||||||
|
|
||||||
/* Connect playsink */
|
/* Connect playsink */
|
||||||
if (self->mode & TIMELINE_MODE_PREVIEW) {
|
if (self->priv->mode & TIMELINE_MODE_PREVIEW) {
|
||||||
const gchar *sinkpad_name;
|
const gchar *sinkpad_name;
|
||||||
GstPad *tmppad;
|
GstPad *tmppad;
|
||||||
|
|
||||||
|
@ -412,7 +430,8 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
|
|
||||||
/* Request a sinkpad from playsink */
|
/* Request a sinkpad from playsink */
|
||||||
if (G_UNLIKELY (!(sinkpad =
|
if (G_UNLIKELY (!(sinkpad =
|
||||||
gst_element_get_request_pad (self->playsink, sinkpad_name)))) {
|
gst_element_get_request_pad (self->priv->playsink,
|
||||||
|
sinkpad_name)))) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't get a pad from the playsink !");
|
GST_ERROR_OBJECT (self, "Couldn't get a pad from the playsink !");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -429,7 +448,7 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
GST_DEBUG ("Reconfiguring playsink");
|
GST_DEBUG ("Reconfiguring playsink");
|
||||||
|
|
||||||
/* reconfigure playsink */
|
/* reconfigure playsink */
|
||||||
g_signal_emit_by_name (self->playsink, "reconfigure", &reconfigured);
|
g_signal_emit_by_name (self->priv->playsink, "reconfigure", &reconfigured);
|
||||||
GST_DEBUG ("'reconfigure' returned %d", reconfigured);
|
GST_DEBUG ("'reconfigure' returned %d", reconfigured);
|
||||||
|
|
||||||
/* We still hold a reference on the sinkpad */
|
/* We still hold a reference on the sinkpad */
|
||||||
|
@ -437,18 +456,19 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Connect to encodebin */
|
/* Connect to encodebin */
|
||||||
if (self->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) {
|
if (self->priv->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) {
|
||||||
GstPad *tmppad;
|
GstPad *tmppad;
|
||||||
GST_DEBUG_OBJECT (self, "Connecting to encodebin");
|
GST_DEBUG_OBJECT (self, "Connecting to encodebin");
|
||||||
|
|
||||||
if (!chain->encodebinpad) {
|
if (!chain->encodebinpad) {
|
||||||
/* Check for unused static pads */
|
/* Check for unused static pads */
|
||||||
sinkpad = get_compatible_unlinked_pad (self->encodebin, pad);
|
sinkpad = get_compatible_unlinked_pad (self->priv->encodebin, pad);
|
||||||
|
|
||||||
if (sinkpad == NULL) {
|
if (sinkpad == NULL) {
|
||||||
GstCaps *caps = gst_pad_get_caps_reffed (pad);
|
GstCaps *caps = gst_pad_get_caps_reffed (pad);
|
||||||
/* If no compatible static pad is available, request a pad */
|
/* If no compatible static pad is available, request a pad */
|
||||||
g_signal_emit_by_name (self->encodebin, "request-pad", caps, &sinkpad);
|
g_signal_emit_by_name (self->priv->encodebin, "request-pad", caps,
|
||||||
|
&sinkpad);
|
||||||
gst_caps_unref (caps);
|
gst_caps_unref (caps);
|
||||||
if (G_UNLIKELY (sinkpad == NULL)) {
|
if (G_UNLIKELY (sinkpad == NULL)) {
|
||||||
GST_ERROR_OBJECT (self, "Couldn't get a pad from encodebin !");
|
GST_ERROR_OBJECT (self, "Couldn't get a pad from encodebin !");
|
||||||
|
@ -471,7 +491,7 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
|
|
||||||
/* If chain wasn't already present, insert it in list */
|
/* If chain wasn't already present, insert it in list */
|
||||||
if (!get_output_chain_for_track (self, track))
|
if (!get_output_chain_for_track (self, track))
|
||||||
self->chains = g_list_append (self->chains, chain);
|
self->priv->chains = g_list_append (self->priv->chains, chain);
|
||||||
|
|
||||||
GST_DEBUG ("done");
|
GST_DEBUG ("done");
|
||||||
return;
|
return;
|
||||||
|
@ -497,7 +517,7 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
GST_DEBUG_OBJECT (self, "pad removed %s:%s", GST_DEBUG_PAD_NAME (pad));
|
GST_DEBUG_OBJECT (self, "pad removed %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
if (G_UNLIKELY (!(track =
|
if (G_UNLIKELY (!(track =
|
||||||
ges_timeline_get_track_for_pad (self->timeline, pad)))) {
|
ges_timeline_get_track_for_pad (self->priv->timeline, pad)))) {
|
||||||
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -512,7 +532,8 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
peer = gst_pad_get_peer (chain->encodebinpad);
|
peer = gst_pad_get_peer (chain->encodebinpad);
|
||||||
gst_pad_unlink (peer, chain->encodebinpad);
|
gst_pad_unlink (peer, chain->encodebinpad);
|
||||||
gst_object_unref (peer);
|
gst_object_unref (peer);
|
||||||
gst_element_release_request_pad (self->encodebin, chain->encodebinpad);
|
gst_element_release_request_pad (self->priv->encodebin,
|
||||||
|
chain->encodebinpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Unlink playsink */
|
/* Unlink playsink */
|
||||||
|
@ -520,7 +541,7 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
peer = gst_pad_get_peer (chain->playsinkpad);
|
peer = gst_pad_get_peer (chain->playsinkpad);
|
||||||
gst_pad_unlink (peer, chain->playsinkpad);
|
gst_pad_unlink (peer, chain->playsinkpad);
|
||||||
gst_object_unref (peer);
|
gst_object_unref (peer);
|
||||||
gst_element_release_request_pad (self->playsink, chain->playsinkpad);
|
gst_element_release_request_pad (self->priv->playsink, chain->playsinkpad);
|
||||||
gst_object_unref (chain->playsinkpad);
|
gst_object_unref (chain->playsinkpad);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,7 +552,7 @@ pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
gst_element_set_state (chain->tee, GST_STATE_NULL);
|
gst_element_set_state (chain->tee, GST_STATE_NULL);
|
||||||
gst_bin_remove (GST_BIN (self), chain->tee);
|
gst_bin_remove (GST_BIN (self), chain->tee);
|
||||||
|
|
||||||
self->chains = g_list_remove (self->chains, chain);
|
self->priv->chains = g_list_remove (self->priv->chains, chain);
|
||||||
g_free (chain);
|
g_free (chain);
|
||||||
|
|
||||||
GST_DEBUG ("done");
|
GST_DEBUG ("done");
|
||||||
|
@ -553,7 +574,7 @@ gboolean
|
||||||
ges_timeline_pipeline_add_timeline (GESTimelinePipeline * pipeline,
|
ges_timeline_pipeline_add_timeline (GESTimelinePipeline * pipeline,
|
||||||
GESTimeline * timeline)
|
GESTimeline * timeline)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail (pipeline->timeline == NULL, FALSE);
|
g_return_val_if_fail (pipeline->priv->timeline == NULL, FALSE);
|
||||||
g_return_val_if_fail (timeline != NULL, FALSE);
|
g_return_val_if_fail (timeline != NULL, FALSE);
|
||||||
|
|
||||||
GST_DEBUG ("pipeline:%p, timeline:%p", timeline, pipeline);
|
GST_DEBUG ("pipeline:%p, timeline:%p", timeline, pipeline);
|
||||||
|
@ -562,7 +583,7 @@ ges_timeline_pipeline_add_timeline (GESTimelinePipeline * pipeline,
|
||||||
GST_ELEMENT (timeline)))) {
|
GST_ELEMENT (timeline)))) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
pipeline->timeline = timeline;
|
pipeline->priv->timeline = timeline;
|
||||||
|
|
||||||
/* Connect to pipeline */
|
/* Connect to pipeline */
|
||||||
g_signal_connect (timeline, "pad-added", (GCallback) pad_added_cb, pipeline);
|
g_signal_connect (timeline, "pad-added", (GCallback) pad_added_cb, pipeline);
|
||||||
|
@ -595,25 +616,25 @@ ges_timeline_pipeline_set_render_settings (GESTimelinePipeline * pipeline,
|
||||||
/* Clear previous URI sink if it existed */
|
/* Clear previous URI sink if it existed */
|
||||||
/* FIXME : We should figure out if it was added to the pipeline,
|
/* FIXME : We should figure out if it was added to the pipeline,
|
||||||
* and if so, remove it. */
|
* and if so, remove it. */
|
||||||
if (pipeline->urisink) {
|
if (pipeline->priv->urisink) {
|
||||||
g_object_unref (pipeline->urisink);
|
g_object_unref (pipeline->priv->urisink);
|
||||||
pipeline->urisink = NULL;
|
pipeline->priv->urisink = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline->urisink =
|
pipeline->priv->urisink =
|
||||||
gst_element_make_from_uri (GST_URI_SINK, output_uri, "urisink");
|
gst_element_make_from_uri (GST_URI_SINK, output_uri, "urisink");
|
||||||
if (G_UNLIKELY (pipeline->urisink == NULL)) {
|
if (G_UNLIKELY (pipeline->priv->urisink == NULL)) {
|
||||||
GST_ERROR_OBJECT (pipeline, "Couldn't not create sink for URI %s",
|
GST_ERROR_OBJECT (pipeline, "Couldn't not create sink for URI %s",
|
||||||
output_uri);
|
output_uri);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipeline->profile)
|
if (pipeline->priv->profile)
|
||||||
gst_encoding_profile_free (pipeline->profile);
|
gst_encoding_profile_free (pipeline->priv->profile);
|
||||||
g_object_set (pipeline->encodebin, "use-smartencoder",
|
g_object_set (pipeline->priv->encodebin, "use-smartencoder",
|
||||||
!(!(pipeline->mode & TIMELINE_MODE_SMART_RENDER)), NULL);
|
!(!(pipeline->priv->mode & TIMELINE_MODE_SMART_RENDER)), NULL);
|
||||||
g_object_set (pipeline->encodebin, "profile", profile, NULL);
|
g_object_set (pipeline->priv->encodebin, "profile", profile, NULL);
|
||||||
pipeline->profile = gst_encoding_profile_copy (profile);
|
pipeline->priv->profile = gst_encoding_profile_copy (profile);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -636,11 +657,11 @@ gboolean
|
||||||
ges_timeline_pipeline_set_mode (GESTimelinePipeline * pipeline,
|
ges_timeline_pipeline_set_mode (GESTimelinePipeline * pipeline,
|
||||||
GESPipelineFlags mode)
|
GESPipelineFlags mode)
|
||||||
{
|
{
|
||||||
GST_DEBUG_OBJECT (pipeline, "current mode : %d, mode : %d", pipeline->mode,
|
GST_DEBUG_OBJECT (pipeline, "current mode : %d, mode : %d",
|
||||||
mode);
|
pipeline->priv->mode, mode);
|
||||||
|
|
||||||
/* fast-path, nothing to change */
|
/* fast-path, nothing to change */
|
||||||
if (mode == pipeline->mode)
|
if (mode == pipeline->priv->mode)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* FIXME: It would be nice if we are only (de)activating preview
|
/* FIXME: It would be nice if we are only (de)activating preview
|
||||||
|
@ -651,55 +672,58 @@ ges_timeline_pipeline_set_mode (GESTimelinePipeline * pipeline,
|
||||||
gst_element_set_state (GST_ELEMENT_CAST (pipeline), GST_STATE_NULL);
|
gst_element_set_state (GST_ELEMENT_CAST (pipeline), GST_STATE_NULL);
|
||||||
|
|
||||||
/* remove no-longer needed components */
|
/* remove no-longer needed components */
|
||||||
if (pipeline->mode & TIMELINE_MODE_PREVIEW && !(mode & TIMELINE_MODE_PREVIEW)) {
|
if (pipeline->priv->mode & TIMELINE_MODE_PREVIEW &&
|
||||||
|
!(mode & TIMELINE_MODE_PREVIEW)) {
|
||||||
/* Disable playsink */
|
/* Disable playsink */
|
||||||
GST_DEBUG ("Disabling playsink");
|
GST_DEBUG ("Disabling playsink");
|
||||||
g_object_ref (pipeline->playsink);
|
g_object_ref (pipeline->priv->playsink);
|
||||||
gst_bin_remove (GST_BIN_CAST (pipeline), pipeline->playsink);
|
gst_bin_remove (GST_BIN_CAST (pipeline), pipeline->priv->playsink);
|
||||||
}
|
}
|
||||||
if ((pipeline->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) &&
|
if ((pipeline->priv->mode &
|
||||||
|
(TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) &&
|
||||||
!(mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))) {
|
!(mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))) {
|
||||||
/* Disable render bin */
|
/* Disable render bin */
|
||||||
GST_DEBUG ("Disabling rendering bin");
|
GST_DEBUG ("Disabling rendering bin");
|
||||||
g_object_ref (pipeline->encodebin);
|
g_object_ref (pipeline->priv->encodebin);
|
||||||
g_object_ref (pipeline->urisink);
|
g_object_ref (pipeline->priv->urisink);
|
||||||
gst_bin_remove_many (GST_BIN_CAST (pipeline),
|
gst_bin_remove_many (GST_BIN_CAST (pipeline),
|
||||||
pipeline->encodebin, pipeline->urisink, NULL);
|
pipeline->priv->encodebin, pipeline->priv->urisink, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add new elements */
|
/* Add new elements */
|
||||||
if (!(pipeline->mode & TIMELINE_MODE_PREVIEW) &&
|
if (!(pipeline->priv->mode & TIMELINE_MODE_PREVIEW) &&
|
||||||
(mode & TIMELINE_MODE_PREVIEW)) {
|
(mode & TIMELINE_MODE_PREVIEW)) {
|
||||||
/* Add playsink */
|
/* Add playsink */
|
||||||
GST_DEBUG ("Adding playsink");
|
GST_DEBUG ("Adding playsink");
|
||||||
|
|
||||||
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->playsink)) {
|
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->playsink)) {
|
||||||
GST_ERROR_OBJECT (pipeline, "Couldn't add playsink");
|
GST_ERROR_OBJECT (pipeline, "Couldn't add playsink");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!(pipeline->mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) &&
|
if (!(pipeline->priv->mode &
|
||||||
|
(TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER)) &&
|
||||||
(mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))) {
|
(mode & (TIMELINE_MODE_RENDER | TIMELINE_MODE_SMART_RENDER))) {
|
||||||
/* Adding render bin */
|
/* Adding render bin */
|
||||||
GST_DEBUG ("Adding render bin");
|
GST_DEBUG ("Adding render bin");
|
||||||
|
|
||||||
if (G_UNLIKELY (pipeline->urisink == NULL)) {
|
if (G_UNLIKELY (pipeline->priv->urisink == NULL)) {
|
||||||
GST_ERROR_OBJECT (pipeline, "Output URI not set !");
|
GST_ERROR_OBJECT (pipeline, "Output URI not set !");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->encodebin)) {
|
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->encodebin)) {
|
||||||
GST_ERROR_OBJECT (pipeline, "Couldn't add encodebin");
|
GST_ERROR_OBJECT (pipeline, "Couldn't add encodebin");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->urisink)) {
|
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->priv->urisink)) {
|
||||||
GST_ERROR_OBJECT (pipeline, "Couldn't add URI sink");
|
GST_ERROR_OBJECT (pipeline, "Couldn't add URI sink");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
g_object_set (pipeline->encodebin, "use-smartencoder",
|
g_object_set (pipeline->priv->encodebin, "use-smartencoder",
|
||||||
!(!(mode & TIMELINE_MODE_SMART_RENDER)), NULL);
|
!(!(mode & TIMELINE_MODE_SMART_RENDER)), NULL);
|
||||||
|
|
||||||
gst_element_link_pads_full (pipeline->encodebin, "src", pipeline->urisink,
|
gst_element_link_pads_full (pipeline->priv->encodebin, "src",
|
||||||
"sink", GST_PAD_LINK_CHECK_NOTHING);
|
pipeline->priv->urisink, "sink", GST_PAD_LINK_CHECK_NOTHING);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXUPS */
|
/* FIXUPS */
|
||||||
|
@ -707,7 +731,7 @@ ges_timeline_pipeline_set_mode (GESTimelinePipeline * pipeline,
|
||||||
* If we are rendering, set playsink to sync=False,
|
* If we are rendering, set playsink to sync=False,
|
||||||
* If we are NOT rendering, set playsink to sync=TRUE */
|
* If we are NOT rendering, set playsink to sync=TRUE */
|
||||||
|
|
||||||
pipeline->mode = mode;
|
pipeline->priv->mode = mode;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -733,7 +757,7 @@ ges_timeline_pipeline_get_thumbnail_buffer (GESTimelinePipeline * self,
|
||||||
GstElement *sink;
|
GstElement *sink;
|
||||||
GstBuffer *buf;
|
GstBuffer *buf;
|
||||||
|
|
||||||
sink = self->playsink;
|
sink = self->priv->playsink;
|
||||||
if (!sink) {
|
if (!sink) {
|
||||||
GST_WARNING ("thumbnailing can only be done if we have a playsink");
|
GST_WARNING ("thumbnailing can only be done if we have a playsink");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -44,6 +44,8 @@ G_BEGIN_DECLS
|
||||||
#define GES_TIMELINE_PIPELINE_GET_CLASS(obj) \
|
#define GES_TIMELINE_PIPELINE_GET_CLASS(obj) \
|
||||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), GES_TYPE_TIMELINE_PIPELINE, GESTimelinePipelineClass))
|
(G_TYPE_INSTANCE_GET_CLASS ((obj), GES_TYPE_TIMELINE_PIPELINE, GESTimelinePipelineClass))
|
||||||
|
|
||||||
|
typedef struct _GESTimelinePipelinePrivate GESTimelinePipelinePrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GESPipelineFlags:
|
* GESPipelineFlags:
|
||||||
* @TIMELINE_MODE_PREVIEW_AUDIO: output audio to the soundcard
|
* @TIMELINE_MODE_PREVIEW_AUDIO: output audio to the soundcard
|
||||||
|
@ -70,18 +72,8 @@ typedef enum {
|
||||||
struct _GESTimelinePipeline {
|
struct _GESTimelinePipeline {
|
||||||
GstPipeline parent;
|
GstPipeline parent;
|
||||||
|
|
||||||
/*< private >*/
|
/* <private> */
|
||||||
GESTimeline * timeline;
|
GESTimelinePipelinePrivate *priv;
|
||||||
GstElement * playsink;
|
|
||||||
GstElement * encodebin;
|
|
||||||
/* Note : urisink is only created when a URI has been provided */
|
|
||||||
GstElement * urisink;
|
|
||||||
|
|
||||||
GESPipelineFlags mode;
|
|
||||||
|
|
||||||
GList *chains;
|
|
||||||
|
|
||||||
GstEncodingProfile *profile;
|
|
||||||
|
|
||||||
/* Padding for API extension */
|
/* Padding for API extension */
|
||||||
gpointer _ges_reserved[GES_PADDING];
|
gpointer _ges_reserved[GES_PADDING];
|
||||||
|
|
Loading…
Reference in a new issue