GESTimelinePipeline: add a private structure

This commit is contained in:
Thibault Saunier 2010-11-28 16:40:15 +01:00 committed by Edward Hervey
parent a66d8eaf16
commit 8d19b737d8
2 changed files with 110 additions and 94 deletions

View file

@ -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;

View file

@ -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];