mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-02 12:32:29 +00:00
GESTimelinePipeline: Use 'playsink', track added/removed pads.
Also add a method to set a GESTimeline on the pipeline.
This commit is contained in:
parent
416323c649
commit
de31b79ee4
2 changed files with 166 additions and 0 deletions
|
@ -24,8 +24,20 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* Structure corresponding to a timeline - sink link */
|
||||||
|
/* TODO : Don't forget we want to render also :) */
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
GESTimelinePipeline *pipeline;
|
||||||
|
GstPad *srcpad;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
} OutputChain;
|
||||||
|
|
||||||
G_DEFINE_TYPE (GESTimelinePipeline, ges_timeline_pipeline, GST_TYPE_PIPELINE);
|
G_DEFINE_TYPE (GESTimelinePipeline, ges_timeline_pipeline, GST_TYPE_PIPELINE);
|
||||||
|
|
||||||
|
static GstStateChangeReturn ges_timeline_pipeline_change_state (GstElement *
|
||||||
|
element, GstStateChange transition);
|
||||||
static void
|
static void
|
||||||
ges_timeline_pipeline_get_property (GObject * object,
|
ges_timeline_pipeline_get_property (GObject * object,
|
||||||
guint property_id, GValue * value, GParamSpec * pspec)
|
guint property_id, GValue * value, GParamSpec * pspec)
|
||||||
|
@ -55,6 +67,13 @@ ges_timeline_pipeline_dispose (GObject * object)
|
||||||
static void
|
static void
|
||||||
ges_timeline_pipeline_finalize (GObject * object)
|
ges_timeline_pipeline_finalize (GObject * object)
|
||||||
{
|
{
|
||||||
|
GESTimelinePipeline *self = GES_TIMELINE_PIPELINE (object);
|
||||||
|
|
||||||
|
if (self->sink) {
|
||||||
|
gst_bin_remove (GST_BIN (object), self->sink);
|
||||||
|
gst_object_unref (self->sink);
|
||||||
|
self->sink = NULL;
|
||||||
|
}
|
||||||
G_OBJECT_CLASS (ges_timeline_pipeline_parent_class)->finalize (object);
|
G_OBJECT_CLASS (ges_timeline_pipeline_parent_class)->finalize (object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,16 +81,36 @@ static void
|
||||||
ges_timeline_pipeline_class_init (GESTimelinePipelineClass * klass)
|
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);
|
||||||
|
|
||||||
object_class->get_property = ges_timeline_pipeline_get_property;
|
object_class->get_property = ges_timeline_pipeline_get_property;
|
||||||
object_class->set_property = ges_timeline_pipeline_set_property;
|
object_class->set_property = ges_timeline_pipeline_set_property;
|
||||||
object_class->dispose = ges_timeline_pipeline_dispose;
|
object_class->dispose = ges_timeline_pipeline_dispose;
|
||||||
object_class->finalize = ges_timeline_pipeline_finalize;
|
object_class->finalize = ges_timeline_pipeline_finalize;
|
||||||
|
|
||||||
|
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 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ges_timeline_pipeline_init (GESTimelinePipeline * self)
|
ges_timeline_pipeline_init (GESTimelinePipeline * self)
|
||||||
{
|
{
|
||||||
|
GST_INFO_OBJECT (self, "Creating new 'playsink'");
|
||||||
|
|
||||||
|
self->sink = gst_element_factory_make ("playsink", "internal-sinks");
|
||||||
|
|
||||||
|
if (G_UNLIKELY (self->sink == NULL))
|
||||||
|
GST_ERROR_OBJECT (self, "Can't create playsink instance !");
|
||||||
|
else {
|
||||||
|
GST_INFO_OBJECT (self, "Adding playsink to self");
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_bin_add (GST_BIN (self), self->sink))) {
|
||||||
|
GST_ERROR_OBJECT (self, "Can't add playsink to ourselves !");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GESTimelinePipeline *
|
GESTimelinePipeline *
|
||||||
|
@ -79,3 +118,121 @@ ges_timeline_pipeline_new (void)
|
||||||
{
|
{
|
||||||
return g_object_new (GES_TYPE_TIMELINE_PIPELINE, NULL);
|
return g_object_new (GES_TYPE_TIMELINE_PIPELINE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 =
|
||||||
|
GST_ELEMENT_CLASS (ges_timeline_pipeline_parent_class)->
|
||||||
|
change_state (element, transition);
|
||||||
|
|
||||||
|
done:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pad_added_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
|
{
|
||||||
|
OutputChain *chain;
|
||||||
|
GESTrack *track;
|
||||||
|
const gchar *sinkpad_name;
|
||||||
|
GstPad *sinkpad;
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (self, "new pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!(track =
|
||||||
|
ges_timeline_get_track_for_pad (self->timeline, pad)))) {
|
||||||
|
GST_WARNING_OBJECT (self, "Couldn't find coresponding track !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!(sinkpad =
|
||||||
|
gst_element_get_request_pad (self->sink, sinkpad_name)))) {
|
||||||
|
GST_WARNING_OBJECT (self, "Couldn't get a pad from the playsink !");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (G_UNLIKELY (gst_pad_link (pad, sinkpad) != GST_PAD_LINK_OK)) {
|
||||||
|
GST_WARNING_OBJECT (self, "Couldn't link track pad to playsink");
|
||||||
|
gst_object_unref (sinkpad);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create a new chain */
|
||||||
|
chain = g_new0 (OutputChain, 1);
|
||||||
|
chain->pipeline = self;
|
||||||
|
chain->srcpad = pad;
|
||||||
|
chain->sinkpad = sinkpad;
|
||||||
|
|
||||||
|
self->chains = g_list_append (self->chains, chain);
|
||||||
|
|
||||||
|
/* Request a sinkpad from playsink */
|
||||||
|
GST_DEBUG ("done");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
pad_removed_cb (GstElement * timeline, GstPad * pad, GESTimelinePipeline * self)
|
||||||
|
{
|
||||||
|
GST_DEBUG ("pad %s:%s", GST_DEBUG_PAD_NAME (pad));
|
||||||
|
|
||||||
|
GST_DEBUG ("done");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
if (G_UNLIKELY (!gst_bin_add (GST_BIN (pipeline), GST_ELEMENT (timeline)))) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -44,6 +44,12 @@ G_BEGIN_DECLS
|
||||||
|
|
||||||
struct _GESTimelinePipeline {
|
struct _GESTimelinePipeline {
|
||||||
GstPipeline parent;
|
GstPipeline parent;
|
||||||
|
|
||||||
|
/* <private> */
|
||||||
|
GESTimeline * timeline;
|
||||||
|
GstElement * sink;
|
||||||
|
|
||||||
|
GList *chains;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GESTimelinePipelineClass {
|
struct _GESTimelinePipelineClass {
|
||||||
|
@ -54,6 +60,9 @@ GType ges_timeline_pipeline_get_type (void);
|
||||||
|
|
||||||
GESTimelinePipeline* ges_timeline_pipeline_new (void);
|
GESTimelinePipeline* ges_timeline_pipeline_new (void);
|
||||||
|
|
||||||
|
gboolean ges_timeline_pipeline_add_timeline (GESTimelinePipeline * pipeline,
|
||||||
|
GESTimeline * timeline);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* _GES_TIMELINE_PIPELINE */
|
#endif /* _GES_TIMELINE_PIPELINE */
|
||||||
|
|
Loading…
Reference in a new issue