2009-08-04 15:13:11 +00:00
|
|
|
/* GStreamer Editing Services
|
2009-11-30 14:14:25 +00:00
|
|
|
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
|
|
|
|
* 2009 Nokia Corporation
|
2009-08-04 15:13:11 +00:00
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
|
2009-09-10 16:40:51 +00:00
|
|
|
/**
|
|
|
|
* SECTION:ges-timeline-pipeline
|
|
|
|
* @short_description: Convenience #GstPipeline for editing.
|
2009-08-04 15:13:11 +00:00
|
|
|
*
|
2009-09-10 16:40:51 +00:00
|
|
|
* #GESTimelinePipeline allows developers to view and render #GESTimeline
|
|
|
|
* in a simple fashion.
|
|
|
|
* Its usage is inspired by the 'playbin' element from gst-plugins-base.
|
2009-08-04 15:13:11 +00:00
|
|
|
*/
|
|
|
|
|
2009-09-10 16:40:51 +00:00
|
|
|
#include "ges-internal.h"
|
|
|
|
#include "ges-timeline-pipeline.h"
|
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
#define DEFAULT_TIMELINE_MODE TIMELINE_MODE_PREVIEW
|
|
|
|
|
2009-09-08 17:45:08 +00:00
|
|
|
/* Structure corresponding to a timeline - sink link */
|
|
|
|
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GESTimelinePipeline *pipeline;
|
2009-12-09 11:22:34 +00:00
|
|
|
GstElement *tee;
|
|
|
|
GstPad *srcpad; /* Timeline source pad */
|
2009-12-04 09:49:32 +00:00
|
|
|
GstPad *playsinkpad;
|
|
|
|
GstPad *encodebinpad;
|
2009-09-08 17:45:08 +00:00
|
|
|
} OutputChain;
|
|
|
|
|
2009-08-06 15:38:43 +00:00
|
|
|
G_DEFINE_TYPE (GESTimelinePipeline, ges_timeline_pipeline, GST_TYPE_PIPELINE);
|
|
|
|
|
2009-09-08 17:45:08 +00:00
|
|
|
static GstStateChangeReturn ges_timeline_pipeline_change_state (GstElement *
|
|
|
|
element, GstStateChange transition);
|
2009-08-06 15:38:43 +00:00
|
|
|
static void
|
|
|
|
ges_timeline_pipeline_get_property (GObject * object,
|
2009-08-04 15:16:31 +00:00
|
|
|
guint property_id, GValue * value, GParamSpec * pspec)
|
2009-08-04 15:13:11 +00:00
|
|
|
{
|
|
|
|
switch (property_id) {
|
2009-08-04 15:16:31 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
2009-08-04 15:13:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-08-04 15:16:31 +00:00
|
|
|
ges_timeline_pipeline_set_property (GObject * object, guint property_id,
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
2009-08-04 15:13:11 +00:00
|
|
|
{
|
|
|
|
switch (property_id) {
|
2009-08-04 15:16:31 +00:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
|
2009-08-04 15:13:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-08-04 15:16:31 +00:00
|
|
|
ges_timeline_pipeline_dispose (GObject * object)
|
2009-08-04 15:13:11 +00:00
|
|
|
{
|
|
|
|
G_OBJECT_CLASS (ges_timeline_pipeline_parent_class)->dispose (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-08-04 15:16:31 +00:00
|
|
|
ges_timeline_pipeline_finalize (GObject * object)
|
2009-08-04 15:13:11 +00:00
|
|
|
{
|
2009-09-08 17:45:08 +00:00
|
|
|
GESTimelinePipeline *self = GES_TIMELINE_PIPELINE (object);
|
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
if (self->playsink) {
|
|
|
|
gst_bin_remove (GST_BIN (object), self->playsink);
|
|
|
|
gst_object_unref (self->playsink);
|
|
|
|
self->playsink = NULL;
|
2009-09-08 17:45:08 +00:00
|
|
|
}
|
2009-08-04 15:13:11 +00:00
|
|
|
G_OBJECT_CLASS (ges_timeline_pipeline_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-08-04 15:16:31 +00:00
|
|
|
ges_timeline_pipeline_class_init (GESTimelinePipelineClass * klass)
|
2009-08-04 15:13:11 +00:00
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
2009-09-08 17:45:08 +00:00
|
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
2009-08-04 15:13:11 +00:00
|
|
|
|
|
|
|
object_class->get_property = ges_timeline_pipeline_get_property;
|
|
|
|
object_class->set_property = ges_timeline_pipeline_set_property;
|
|
|
|
object_class->dispose = ges_timeline_pipeline_dispose;
|
|
|
|
object_class->finalize = ges_timeline_pipeline_finalize;
|
2009-09-08 17:45:08 +00:00
|
|
|
|
|
|
|
element_class->change_state =
|
|
|
|
GST_DEBUG_FUNCPTR (ges_timeline_pipeline_change_state);
|
|
|
|
|
|
|
|
/* TODO : Add state_change handlers
|
|
|
|
* Don't change state if we don't have a timeline */
|
2009-08-04 15:13:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2009-08-04 15:16:31 +00:00
|
|
|
ges_timeline_pipeline_init (GESTimelinePipeline * self)
|
2009-08-04 15:13:11 +00:00
|
|
|
{
|
2009-09-08 17:45:08 +00:00
|
|
|
GST_INFO_OBJECT (self, "Creating new 'playsink'");
|
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
self->playsink = gst_element_factory_make ("playsink", "internal-sinks");
|
|
|
|
self->encodebin =
|
|
|
|
gst_element_factory_make ("encodebin", "internal-encodebin");
|
2009-09-08 17:45:08 +00:00
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
if (G_UNLIKELY (self->playsink == NULL))
|
2009-09-08 17:45:08 +00:00
|
|
|
GST_ERROR_OBJECT (self, "Can't create playsink instance !");
|
2009-12-04 09:49:32 +00:00
|
|
|
if (G_UNLIKELY (self->encodebin == NULL))
|
|
|
|
GST_ERROR_OBJECT (self, "Can't create encodebin instance !");
|
2009-09-08 17:45:08 +00:00
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
ges_timeline_pipeline_set_mode (self, DEFAULT_TIMELINE_MODE);
|
2009-08-04 15:13:11 +00:00
|
|
|
}
|
|
|
|
|
2009-09-16 10:37:45 +00:00
|
|
|
/**
|
|
|
|
* ges_timeline_pipeline_new:
|
|
|
|
*
|
|
|
|
* Creates a new conveninence #GESTimelinePipeline.
|
|
|
|
*
|
|
|
|
* Returns: the new #GESTimelinePipeline.
|
|
|
|
*/
|
2009-08-04 15:16:31 +00:00
|
|
|
GESTimelinePipeline *
|
2009-08-04 15:13:11 +00:00
|
|
|
ges_timeline_pipeline_new (void)
|
|
|
|
{
|
2009-09-07 13:46:44 +00:00
|
|
|
return g_object_new (GES_TYPE_TIMELINE_PIPELINE, NULL);
|
2009-08-04 15:13:11 +00:00
|
|
|
}
|
2009-09-08 17:45:08 +00:00
|
|
|
|
|
|
|
static GstStateChangeReturn
|
|
|
|
ges_timeline_pipeline_change_state (GstElement * element,
|
|
|
|
GstStateChange transition)
|
|
|
|
{
|
|
|
|
GESTimelinePipeline *self;
|
|
|
|
GstStateChangeReturn ret;
|
|
|
|
|
|
|
|
self = GES_TIMELINE_PIPELINE (element);
|
|
|
|
|
|
|
|
switch (transition) {
|
|
|
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
|
|
|
case GST_STATE_CHANGE_READY_TO_PAUSED:
|
|
|
|
if (G_UNLIKELY (self->timeline == NULL)) {
|
|
|
|
GST_ERROR_OBJECT (element,
|
|
|
|
"No GESTimeline set on the pipeline, cannot play !");
|
|
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
ret =
|
2009-11-30 14:14:25 +00:00
|
|
|
GST_ELEMENT_CLASS (ges_timeline_pipeline_parent_class)->change_state
|
|
|
|
(element, transition);
|
2009-09-08 17:45:08 +00:00
|
|
|
|
|
|
|
done:
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
|
|
|
{
|
|
|
|
OutputChain *chain;
|
|
|
|
GESTrack *track;
|
|
|
|
GstPad *sinkpad;
|
2009-09-09 10:42:29 +00:00
|
|
|
gboolean reconfigured = FALSE;
|
2009-09-08 17:45:08 +00:00
|
|
|
|
|
|
|
GST_DEBUG_OBJECT (self, "new pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
/* FIXME : Adapt for usage of render sink */
|
|
|
|
|
2009-09-08 17:45:08 +00:00
|
|
|
if (G_UNLIKELY (!(track =
|
|
|
|
ges_timeline_get_track_for_pad (self->timeline, pad)))) {
|
|
|
|
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-12-09 11:22:34 +00:00
|
|
|
/* Don't connect track if it's not going to be used */
|
|
|
|
if (track->type == GES_TRACK_TYPE_VIDEO &&
|
|
|
|
!(self->mode & TIMELINE_MODE_PREVIEW_VIDEO) &&
|
|
|
|
!(self->mode & TIMELINE_MODE_RENDER)) {
|
|
|
|
GST_DEBUG_OBJECT (self, "Video track... but we don't need it. Not linking");
|
2009-09-08 17:45:08 +00:00
|
|
|
}
|
2009-12-09 11:22:34 +00:00
|
|
|
if (track->type == GES_TRACK_TYPE_AUDIO &&
|
|
|
|
!(self->mode & TIMELINE_MODE_PREVIEW_AUDIO) &&
|
|
|
|
!(self->mode & TIMELINE_MODE_RENDER)) {
|
|
|
|
GST_DEBUG_OBJECT (self, "Audio track... but we don't need it. Not linking");
|
2009-09-08 17:45:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Create a new chain */
|
|
|
|
chain = g_new0 (OutputChain, 1);
|
|
|
|
chain->pipeline = self;
|
|
|
|
chain->srcpad = pad;
|
2009-12-09 11:22:34 +00:00
|
|
|
|
|
|
|
/* Adding tee */
|
|
|
|
chain->tee = gst_element_factory_make ("tee", NULL);
|
|
|
|
gst_bin_add (GST_BIN_CAST (self), chain->tee);
|
2009-12-11 14:17:25 +00:00
|
|
|
gst_element_sync_state_with_parent (chain->tee);
|
2009-12-09 11:22:34 +00:00
|
|
|
|
|
|
|
/* Linking pad to tee */
|
|
|
|
sinkpad = gst_element_get_pad (chain->tee, "sink");
|
|
|
|
gst_pad_link (pad, sinkpad);
|
|
|
|
|
|
|
|
/* Connect playsink */
|
|
|
|
if (self->mode & TIMELINE_MODE_PREVIEW) {
|
|
|
|
const gchar *sinkpad_name;
|
|
|
|
|
|
|
|
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->playsink, sinkpad_name)))) {
|
|
|
|
GST_WARNING_OBJECT (self, "Couldn't get a pad from the playsink !");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_UNLIKELY (gst_pad_link (gst_element_get_request_pad (chain->tee,
|
|
|
|
"src%d"), sinkpad) != GST_PAD_LINK_OK)) {
|
|
|
|
GST_WARNING_OBJECT (self, "Couldn't link track pad to playsink");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_DEBUG ("Reconfiguring playsink");
|
|
|
|
|
|
|
|
/* reconfigure playsink */
|
|
|
|
g_signal_emit_by_name (self->playsink, "reconfigure", &reconfigured);
|
|
|
|
GST_DEBUG ("'reconfigure' returned %d", reconfigured);
|
|
|
|
|
|
|
|
chain->playsinkpad = sinkpad;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Connect to encodebin */
|
|
|
|
if (self->mode & TIMELINE_MODE_RENDER) {
|
|
|
|
GST_DEBUG_OBJECT (self, "Connecting to encodebin");
|
|
|
|
|
|
|
|
sinkpad = NULL;
|
|
|
|
g_signal_emit_by_name (self->encodebin, "request-pad",
|
|
|
|
gst_pad_get_caps (pad), &sinkpad);
|
|
|
|
if (G_UNLIKELY (sinkpad == NULL)) {
|
|
|
|
GST_WARNING_OBJECT (self, "Couldn't get a pad from encodebin !");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (G_UNLIKELY (gst_pad_link (gst_element_get_request_pad (chain->tee,
|
|
|
|
"src%d"), sinkpad) != GST_PAD_LINK_OK)) {
|
|
|
|
GST_WARNING_OBJECT (self, "Couldn't link track pad to playsink");
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
chain->encodebinpad = sinkpad;
|
|
|
|
}
|
2009-09-08 17:45:08 +00:00
|
|
|
|
|
|
|
self->chains = g_list_append (self->chains, chain);
|
|
|
|
|
|
|
|
GST_DEBUG ("done");
|
2009-12-09 11:22:34 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
error:
|
|
|
|
{
|
|
|
|
if (chain->tee) {
|
|
|
|
gst_bin_remove (GST_BIN_CAST (self), chain->tee);
|
|
|
|
gst_object_unref (chain->tee);
|
|
|
|
}
|
|
|
|
if (sinkpad)
|
|
|
|
gst_object_unref (sinkpad);
|
|
|
|
g_free (chain);
|
|
|
|
}
|
2009-09-08 17:45:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
|
|
|
{
|
2009-12-04 09:49:32 +00:00
|
|
|
GST_DEBUG_OBJECT (self, "pad removed %s:%s", GST_DEBUG_PAD_NAME (pad));
|
|
|
|
|
|
|
|
/* FIXME : IMPLEMENT ! */
|
2009-12-09 11:22:34 +00:00
|
|
|
GST_WARNING_OBJECT (self, "IMPLEMENTE ME !");
|
2009-09-08 17:45:08 +00:00
|
|
|
|
|
|
|
GST_DEBUG ("done");
|
|
|
|
}
|
|
|
|
|
2009-09-16 10:37:45 +00:00
|
|
|
/**
|
|
|
|
* ges_timeline_pipeline_add_timeline:
|
|
|
|
* @pipeline: a #GESTimelinePipeline
|
|
|
|
* @timeline: the #GESTimeline to set on the @pipeline.
|
|
|
|
*
|
|
|
|
* Sets the timeline to use in this pipeline.
|
|
|
|
*
|
|
|
|
* The reference to the @timeline will be stolen by the @pipeline.
|
|
|
|
*
|
|
|
|
* Returns: TRUE if the @timeline could be successfully set on the @pipeline,
|
|
|
|
* else FALSE.
|
|
|
|
*/
|
2009-09-08 17:45:08 +00:00
|
|
|
gboolean
|
|
|
|
ges_timeline_pipeline_add_timeline (GESTimelinePipeline * pipeline,
|
|
|
|
GESTimeline * timeline)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (pipeline->timeline == NULL, FALSE);
|
|
|
|
g_return_val_if_fail (timeline != NULL, FALSE);
|
|
|
|
|
|
|
|
GST_DEBUG ("pipeline:%p, timeline:%p", timeline, pipeline);
|
|
|
|
|
2009-12-09 11:22:34 +00:00
|
|
|
if (G_UNLIKELY (!gst_bin_add (GST_BIN_CAST (pipeline),
|
|
|
|
GST_ELEMENT (timeline)))) {
|
2009-09-08 17:45:08 +00:00
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
pipeline->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);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
2009-12-04 09:49:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* ges_timeline_pipeline_set_render_settings:
|
|
|
|
* @pipeline: a #GESTimelinePipeline
|
|
|
|
* @output_uri: the %URI to which the timeline will be rendered
|
|
|
|
* @profile: the #GstEncodingProfile to use to render the timeline
|
|
|
|
*
|
|
|
|
* Specify where the pipeline shall be rendered and with what settings.
|
|
|
|
*
|
|
|
|
* Returns: %TRUE if the settings were aknowledged properly, else %FALSE
|
|
|
|
*/
|
|
|
|
gboolean
|
|
|
|
ges_timeline_pipeline_set_render_settings (GESTimelinePipeline * pipeline,
|
|
|
|
gchar * output_uri, GstEncodingProfile * profile)
|
|
|
|
{
|
|
|
|
/* Clear previous URI sink if it existed */
|
|
|
|
/* FIXME : We should figure out if it was added to the pipeline,
|
|
|
|
* and if so, remove it. */
|
|
|
|
if (pipeline->urisink) {
|
|
|
|
g_object_unref (pipeline->urisink);
|
|
|
|
pipeline->urisink = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pipeline->urisink =
|
|
|
|
gst_element_make_from_uri (GST_URI_SINK, output_uri, "urisink");
|
|
|
|
if (G_UNLIKELY (pipeline->urisink == NULL)) {
|
|
|
|
GST_ERROR_OBJECT (pipeline, "Couldn't not create sink for URI %s",
|
|
|
|
output_uri);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_object_set (pipeline->encodebin, "profile", profile, NULL);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* ges_timeline_pipeline_set_mode:
|
|
|
|
* @pipeline: a #GESTimelinePipeline
|
|
|
|
* @mode: the #GESPipelineFlags to use
|
|
|
|
*
|
|
|
|
* switches the @pipeline to the specified @mode. The default mode when
|
|
|
|
* creating a #GESTimelinePipeline is #TIMELINE_MODE_PREVIEW.
|
|
|
|
*
|
|
|
|
* Note: The @pipeline will be set to #GST_STATE_NULL during this call due to
|
|
|
|
* the internal changes that happen. The caller will therefore have to
|
|
|
|
* set the @pipeline to the requested state after calling this method.
|
2009-12-11 14:24:56 +00:00
|
|
|
*
|
|
|
|
* Returns: %TRUE if the mode was properly set, else %FALSE.
|
2009-12-04 09:49:32 +00:00
|
|
|
**/
|
|
|
|
gboolean
|
|
|
|
ges_timeline_pipeline_set_mode (GESTimelinePipeline * pipeline,
|
|
|
|
GESPipelineFlags mode)
|
|
|
|
{
|
|
|
|
GST_DEBUG_OBJECT (pipeline, "current mode : %d, mode : %d", pipeline->mode,
|
|
|
|
mode);
|
|
|
|
|
|
|
|
/* fast-path, nothing to change */
|
|
|
|
if (mode == pipeline->mode)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
/* FIXME: It would be nice if we are only (de)activating preview
|
|
|
|
* modes to not set the whole pipeline to NULL, but instead just
|
|
|
|
* do the proper (un)linking to playsink. */
|
|
|
|
|
|
|
|
/* Switch pipeline to NULL since we're changing the configuration */
|
|
|
|
gst_element_set_state (GST_ELEMENT_CAST (pipeline), GST_STATE_NULL);
|
|
|
|
|
|
|
|
/* remove no-longer needed components */
|
|
|
|
if (pipeline->mode & TIMELINE_MODE_PREVIEW && !(mode & TIMELINE_MODE_PREVIEW)) {
|
|
|
|
/* Disable playsink */
|
|
|
|
GST_DEBUG ("Disabling playsink");
|
|
|
|
g_object_ref (pipeline->playsink);
|
|
|
|
gst_bin_remove (GST_BIN_CAST (pipeline), pipeline->playsink);
|
|
|
|
}
|
|
|
|
if ((pipeline->mode & TIMELINE_MODE_RENDER) && !(mode & TIMELINE_MODE_RENDER)) {
|
|
|
|
/* Disable render bin */
|
|
|
|
GST_DEBUG ("Disabling rendering bin");
|
|
|
|
g_object_ref (pipeline->encodebin);
|
|
|
|
g_object_ref (pipeline->urisink);
|
|
|
|
gst_bin_remove_many (GST_BIN_CAST (pipeline),
|
|
|
|
pipeline->encodebin, pipeline->urisink, NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Add new elements */
|
|
|
|
if (!(pipeline->mode & TIMELINE_MODE_PREVIEW) &&
|
|
|
|
(mode & TIMELINE_MODE_PREVIEW)) {
|
|
|
|
/* Add playsink */
|
|
|
|
GST_DEBUG ("Adding playsink");
|
|
|
|
|
|
|
|
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->playsink)) {
|
|
|
|
GST_ERROR_OBJECT (pipeline, "Couldn't add playsink");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!(pipeline->mode & TIMELINE_MODE_RENDER) && (mode & TIMELINE_MODE_RENDER)) {
|
|
|
|
/* Adding render bin */
|
|
|
|
GST_DEBUG ("Adding render bin");
|
|
|
|
|
|
|
|
if (G_UNLIKELY (pipeline->urisink == NULL)) {
|
|
|
|
GST_ERROR_OBJECT (pipeline, "Output URI not set !");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->encodebin)) {
|
|
|
|
GST_ERROR_OBJECT (pipeline, "Couldn't add encodebin");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
if (!gst_bin_add (GST_BIN_CAST (pipeline), pipeline->urisink)) {
|
|
|
|
GST_ERROR_OBJECT (pipeline, "Couldn't add URI sink");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
gst_element_link (pipeline->encodebin, pipeline->urisink);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXUPS */
|
|
|
|
/* FIXME
|
|
|
|
* If we are rendering, set playsink to sync=False,
|
|
|
|
* If we are NOT rendering, set playsink to sync=TRUE */
|
|
|
|
|
2009-12-09 14:03:30 +00:00
|
|
|
pipeline->mode = mode;
|
|
|
|
|
2009-12-04 09:49:32 +00:00
|
|
|
return TRUE;
|
|
|
|
}
|