diff --git a/ges/ges-audio-test-source.c b/ges/ges-audio-test-source.c index 4d0f9dde17..82b443cbd5 100644 --- a/ges/ges-audio-test-source.c +++ b/ges/ges-audio-test-source.c @@ -51,21 +51,20 @@ static void ges_audio_test_source_get_property (GObject * object, guint static void ges_audio_test_source_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); -static GstElement *ges_audio_test_source_create_element (GESTrackElement * - self); +static GstElement *ges_audio_test_source_create_source (GESTrackElement * self); static void ges_audio_test_source_class_init (GESAudioTestSourceClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - GESTrackElementClass *bg_class = GES_TRACK_ELEMENT_CLASS (klass); + GESSourceClass *source_class = GES_SOURCE_CLASS (klass); g_type_class_add_private (klass, sizeof (GESAudioTestSourcePrivate)); object_class->get_property = ges_audio_test_source_get_property; object_class->set_property = ges_audio_test_source_set_property; - bg_class->create_element = ges_audio_test_source_create_element; + source_class->create_source = ges_audio_test_source_create_source; } static void @@ -99,7 +98,7 @@ ges_audio_test_source_set_property (GObject * object, } static GstElement * -ges_audio_test_source_create_element (GESTrackElement * trksrc) +ges_audio_test_source_create_source (GESTrackElement * trksrc) { GESAudioTestSource *self; GstElement *ret; diff --git a/ges/ges-image-source.c b/ges/ges-image-source.c index cdc28522e6..f2089f39a0 100644 --- a/ges/ges-image-source.c +++ b/ges/ges-image-source.c @@ -110,7 +110,7 @@ pad_added_cb (GstElement * timeline, GstPad * pad, GstElement * scale) } static GstElement * -ges_image_source_create_element (GESTrackElement * track_element) +ges_image_source_create_source (GESTrackElement * track_element) { GstElement *bin, *source, *scale, *freeze, *iconv; GstPad *src, *target; @@ -150,7 +150,7 @@ static void ges_image_source_class_init (GESImageSourceClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - GESTrackElementClass *gesobj_class = GES_TRACK_ELEMENT_CLASS (klass); + GESSourceClass *source_class = GES_SOURCE_CLASS (klass); g_type_class_add_private (klass, sizeof (GESImageSourcePrivate)); @@ -166,7 +166,7 @@ ges_image_source_class_init (GESImageSourceClass * klass) g_object_class_install_property (object_class, PROP_URI, g_param_spec_string ("uri", "URI", "uri of the resource", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - gesobj_class->create_element = ges_image_source_create_element; + source_class->create_source = ges_image_source_create_source; } static void diff --git a/ges/ges-source.c b/ges/ges-source.c index 1cbb4d8964..f1373e9e6e 100644 --- a/ges/ges-source.c +++ b/ges/ges-source.c @@ -23,27 +23,222 @@ * @short_description: Base Class for single-media sources */ -#include "ges-internal.h" +#include "ges/ges-meta-container.h" #include "ges-track-element.h" #include "ges-source.h" +#include "ges-layer.h" +#include "gstframepositionner.h" G_DEFINE_TYPE (GESSource, ges_source, GES_TYPE_TRACK_ELEMENT); struct _GESSourcePrivate { /* Dummy variable */ - void *nothing; + GstFramePositionner *positionner; }; +static void +_pad_added_cb (GstElement * element, GstPad * srcpad, GstPad * sinkpad) +{ + gst_element_no_more_pads (element); + gst_pad_link (srcpad, sinkpad); +} + +static void +_ghost_pad_added_cb (GstElement * element, GstPad * srcpad, GstElement * bin) +{ + GstPad *ghost; + + ghost = gst_ghost_pad_new ("src", srcpad); + gst_pad_set_active (ghost, TRUE); + gst_element_add_pad (bin, ghost); + gst_element_no_more_pads (element); +} + +static GstElement * +_create_bin (const gchar * bin_name, GstElement * sub_element, ...) +{ + va_list argp; + + GstElement *element; + GstElement *prev = NULL; + GstElement *first = NULL; + GstElement *bin; + GstPad *sub_srcpad; + + va_start (argp, sub_element); + bin = gst_bin_new (bin_name); + gst_bin_add (GST_BIN (bin), sub_element); + + while ((element = va_arg (argp, GstElement *)) != NULL) { + gst_bin_add (GST_BIN (bin), element); + if (prev) + gst_element_link (prev, element); + prev = element; + if (first == NULL) + first = element; + } + + va_end (argp); + + sub_srcpad = gst_element_get_static_pad (sub_element, "src"); + + if (prev != NULL) { + GstPad *srcpad, *sinkpad, *ghost; + + srcpad = gst_element_get_static_pad (prev, "src"); + ghost = gst_ghost_pad_new ("src", srcpad); + gst_pad_set_active (ghost, TRUE); + gst_element_add_pad (bin, ghost); + + sinkpad = gst_element_get_static_pad (first, "sink"); + if (sub_srcpad) + gst_pad_link (sub_srcpad, sinkpad); + else + g_signal_connect (sub_element, "pad-added", G_CALLBACK (_pad_added_cb), + sinkpad); + + gst_object_unref (srcpad); + gst_object_unref (sinkpad); + + } else if (sub_srcpad) { + GstPad *ghost; + + ghost = gst_ghost_pad_new ("src", sub_srcpad); + gst_pad_set_active (ghost, TRUE); + gst_element_add_pad (bin, ghost); + } else { + g_signal_connect (sub_element, "pad-added", + G_CALLBACK (_ghost_pad_added_cb), bin); + } + + return bin; +} + +static void +_sync_element_to_layer_property_float (GESTrackElement * trksrc, + GstElement * element, const gchar * meta, const gchar * propname) +{ + GESTimelineElement *parent; + GESLayer *layer; + gfloat value; + + parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc)); + layer = ges_clip_get_layer (GES_CLIP (parent)); + + gst_object_unref (parent); + + if (layer != NULL) { + + ges_meta_container_get_float (GES_META_CONTAINER (layer), meta, &value); + g_object_set (element, propname, value, NULL); + GST_DEBUG_OBJECT (trksrc, "Setting %s to %f", propname, value); + + } else { + + GST_DEBUG_OBJECT (trksrc, "NOT setting the %s", propname); + } + + gst_object_unref (layer); +} + +static void +update_z_order_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED, + GESSource * self) +{ + GESLayer *layer = ges_clip_get_layer (clip); + + if (layer == NULL) + return; + + /* 10000 is the max value of zorder on videomixerpad, hardcoded */ + + g_object_set (self->priv->positionner, "zorder", + 10000 - ges_layer_get_priority (layer), NULL); + + gst_object_unref (layer); +} + +static GstElement * +ges_source_create_element (GESTrackElement * trksrc) +{ + GstElement *topbin; + GstElement *sub_element; + GESSourceClass *source_class = GES_SOURCE_GET_CLASS (trksrc); + GESTrack *track; + GESSource *self; + + if (!source_class->create_source) + return NULL; + + sub_element = source_class->create_source (trksrc); + + track = ges_track_element_get_track (trksrc); + + self = (GESSource *) trksrc; + + switch (track->type) { + case GES_TRACK_TYPE_AUDIO: + { + const gchar *props[] = { "volume", "mute", NULL }; + GstElement *volume; + + GST_DEBUG_OBJECT (trksrc, "Creating a bin sub_element ! volume"); + + volume = gst_element_factory_make ("volume", NULL); + + topbin = _create_bin ("audio-src-bin", sub_element, volume, NULL); + + _sync_element_to_layer_property_float (trksrc, volume, GES_META_VOLUME, + "volume"); + ges_track_element_add_children_props (trksrc, volume, NULL, NULL, props); + break; + } + case GES_TRACK_TYPE_VIDEO: + { + GstElement *positionner; + const gchar *props[] = { "alpha", "posx", "posy", NULL }; + GESTimelineElement *parent; + + /* That positionner will add metadata to buffers according to its + properties, acting like a proxy for our smart-mixer dynamic pads. */ + positionner = + gst_element_factory_make ("framepositionner", "frame_tagger"); + + ges_track_element_add_children_props (trksrc, positionner, NULL, NULL, + props); + topbin = _create_bin ("video-src-bin", sub_element, positionner, NULL); + parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc)); + if (parent) { + self->priv->positionner = GST_FRAME_POSITIONNER (positionner); + g_signal_connect (parent, "notify::layer", + (GCallback) update_z_order_cb, trksrc); + update_z_order_cb (GES_CLIP (parent), NULL, self); + gst_object_unref (parent); + } else { + GST_WARNING ("No parent timeline element, SHOULD NOT HAPPEN"); + } + break; + } + default: + topbin = _create_bin ("a-questionable-name", sub_element, NULL); + break; + } + + return topbin; +} + static void ges_source_class_init (GESSourceClass * klass) { GESTrackElementClass *track_class = GES_TRACK_ELEMENT_CLASS (klass); + GESSourceClass *source_class = GES_SOURCE_CLASS (klass); g_type_class_add_private (klass, sizeof (GESSourcePrivate)); track_class->gnlobject_factorytype = "gnlsource"; - track_class->create_element = NULL; + track_class->create_element = ges_source_create_element; + source_class->create_source = NULL; } static void @@ -51,4 +246,5 @@ ges_source_init (GESSource * self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GES_TYPE_SOURCE, GESSourcePrivate); + self->priv->positionner = NULL; } diff --git a/ges/ges-source.h b/ges/ges-source.h index 9ab8022d98..73339c2658 100644 --- a/ges/ges-source.h +++ b/ges/ges-source.h @@ -65,6 +65,7 @@ struct _GESSource { /** * GESSourceClass: + * @create_source: method to return the GstElement to put in the source topbin. */ struct _GESSourceClass { @@ -73,6 +74,7 @@ struct _GESSourceClass { /*< private >*/ /* Padding for API extension */ + GstElement* (*create_source) (GESTrackElement * object); gpointer _ges_reserved[GES_PADDING]; }; diff --git a/ges/ges-title-source.c b/ges/ges-title-source.c index 13b5ee513a..1fd8ac8a53 100644 --- a/ges/ges-title-source.c +++ b/ges/ges-title-source.c @@ -58,13 +58,13 @@ static void ges_title_source_get_property (GObject * object, guint static void ges_title_source_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec); -static GstElement *ges_title_source_create_element (GESTrackElement * self); +static GstElement *ges_title_source_create_source (GESTrackElement * self); static void ges_title_source_class_init (GESTitleSourceClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - GESTrackElementClass *bg_class = GES_TRACK_ELEMENT_CLASS (klass); + GESSourceClass *source_class = GES_SOURCE_CLASS (klass); g_type_class_add_private (klass, sizeof (GESTitleSourcePrivate)); @@ -72,7 +72,7 @@ ges_title_source_class_init (GESTitleSourceClass * klass) object_class->set_property = ges_title_source_set_property; object_class->dispose = ges_title_source_dispose; - bg_class->create_element = ges_title_source_create_element; + source_class->create_source = ges_title_source_create_source; } static void @@ -139,7 +139,7 @@ ges_title_source_set_property (GObject * object, } static GstElement * -ges_title_source_create_element (GESTrackElement * object) +ges_title_source_create_source (GESTrackElement * object) { GESTitleSource *self = GES_TITLE_SOURCE (object); GESTitleSourcePrivate *priv = self->priv; diff --git a/ges/ges-uri-source.c b/ges/ges-uri-source.c index a339681f99..671b7d844a 100644 --- a/ges/ges-uri-source.c +++ b/ges/ges-uri-source.c @@ -32,12 +32,10 @@ #include "ges-uri-source.h" #include "ges-uri-asset.h" #include "ges-extractable.h" -#include "ges-layer.h" -#include "gstframepositionner.h" struct _GESUriSourcePrivate { - GstFramePositionner *positionner; + void *nothing; }; enum @@ -46,190 +44,24 @@ enum PROP_URI }; -/* Callbacks */ - -static void -_pad_added_cb (GstElement * element, GstPad * srcpad, GstPad * sinkpad) -{ - gst_element_no_more_pads (element); - gst_pad_link (srcpad, sinkpad); -} - -static void -_ghost_pad_added_cb (GstElement * element, GstPad * srcpad, GstElement * bin) -{ - GstPad *ghost; - - ghost = gst_ghost_pad_new ("src", srcpad); - gst_pad_set_active (ghost, TRUE); - gst_element_add_pad (bin, ghost); - gst_element_no_more_pads (element); -} - -/* Internal methods */ - +/* GESSource VMethod */ static GstElement * -_create_bin (const gchar * bin_name, GstElement * decodebin, ...) -{ - va_list argp; - - GstElement *element; - GstElement *prev = NULL; - GstElement *first = NULL; - GstElement *bin; - - va_start (argp, decodebin); - bin = gst_bin_new (bin_name); - gst_bin_add (GST_BIN (bin), decodebin); - - while ((element = va_arg (argp, GstElement *)) != NULL) { - gst_bin_add (GST_BIN (bin), element); - if (prev) - gst_element_link (prev, element); - prev = element; - if (first == NULL) - first = element; - } - - va_end (argp); - - if (prev != NULL) { - GstPad *srcpad, *sinkpad, *ghost; - - srcpad = gst_element_get_static_pad (prev, "src"); - ghost = gst_ghost_pad_new ("src", srcpad); - gst_pad_set_active (ghost, TRUE); - gst_element_add_pad (bin, ghost); - - sinkpad = gst_element_get_static_pad (first, "sink"); - g_signal_connect (decodebin, "pad-added", G_CALLBACK (_pad_added_cb), - sinkpad); - - gst_object_unref (srcpad); - gst_object_unref (sinkpad); - - } else { - /* Our decodebin is alone in the bin, we need to ghost its source when it appears */ - - g_signal_connect (decodebin, "pad-added", G_CALLBACK (_ghost_pad_added_cb), - bin); - } - - return bin; -} - -static void -_sync_element_to_layer_property_float (GESTrackElement * trksrc, - GstElement * element, const gchar * meta, const gchar * propname) -{ - GESTimelineElement *parent; - GESLayer *layer; - gfloat value; - - parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc)); - layer = ges_clip_get_layer (GES_CLIP (parent)); - - gst_object_unref (parent); - - if (layer != NULL) { - - ges_meta_container_get_float (GES_META_CONTAINER (layer), meta, &value); - g_object_set (element, propname, value, NULL); - GST_DEBUG_OBJECT (trksrc, "Setting %s to %f", propname, value); - - } else { - - GST_DEBUG_OBJECT (trksrc, "NOT setting the %s", propname); - } - - gst_object_unref (layer); -} - -/* TrackElement VMethods */ - -static void -update_z_order_cb (GESClip * clip, GParamSpec * arg G_GNUC_UNUSED, - GESUriSource * self) -{ - GESLayer *layer = ges_clip_get_layer (clip); - - if (layer == NULL) - return; - - /* 10000 is the max value of zorder on videomixerpad, hardcoded */ - - g_object_set (self->priv->positionner, "zorder", - 10000 - ges_layer_get_priority (layer), NULL); - - gst_object_unref (layer); -} - -static GstElement * -ges_uri_source_create_element (GESTrackElement * trksrc) +ges_uri_source_create_source (GESTrackElement * trksrc) { GESUriSource *self; GESTrack *track; GstElement *decodebin; - GstElement *topbin, *volume; - GstElement *positionner; - GESTimelineElement *parent; self = (GESUriSource *) trksrc; + track = ges_track_element_get_track (trksrc); - switch (track->type) { - case GES_TRACK_TYPE_AUDIO: - { - const gchar *props[] = { "volume", "mute", NULL }; - - GST_DEBUG_OBJECT (trksrc, "Creating a bin uridecodebin ! volume"); - - decodebin = gst_element_factory_make ("uridecodebin", NULL); - volume = gst_element_factory_make ("volume", NULL); - - topbin = _create_bin ("audio-src-bin", decodebin, volume, NULL); - - _sync_element_to_layer_property_float (trksrc, volume, GES_META_VOLUME, - "volume"); - ges_track_element_add_children_props (trksrc, volume, NULL, NULL, props); - break; - } - case GES_TRACK_TYPE_VIDEO: - { - const gchar *props[] = { "alpha", "posx", "posy", NULL }; - - decodebin = gst_element_factory_make ("uridecodebin", NULL); - - /* That positionner will add metadata to buffers according to its - properties, acting like a proxy for our smart-mixer dynamic pads. */ - positionner = - gst_element_factory_make ("framepositionner", "frame_tagger"); - - ges_track_element_add_children_props (trksrc, positionner, NULL, NULL, - props); - topbin = _create_bin ("video-src-bin", decodebin, positionner, NULL); - parent = ges_timeline_element_get_parent (GES_TIMELINE_ELEMENT (trksrc)); - if (parent) { - self->priv->positionner = GST_FRAME_POSITIONNER (positionner); - g_signal_connect (parent, "notify::layer", - (GCallback) update_z_order_cb, trksrc); - update_z_order_cb (GES_CLIP (parent), NULL, self); - gst_object_unref (parent); - } else { - GST_WARNING ("No parent timeline element, SHOULD NOT HAPPEN"); - } - break; - } - default: - decodebin = gst_element_factory_make ("uridecodebin", NULL); - topbin = _create_bin ("video-src-bin", decodebin, NULL); - break; - } + decodebin = gst_element_factory_make ("uridecodebin", NULL); g_object_set (decodebin, "caps", ges_track_get_caps (track), "expose-all-streams", FALSE, "uri", self->uri, NULL); - return topbin; + return decodebin; } /* Extractable interface implementation */ @@ -319,7 +151,7 @@ static void ges_track_filesource_class_init (GESUriSourceClass * klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); - GESTrackElementClass *track_class = GES_TRACK_ELEMENT_CLASS (klass); + GESSourceClass *source_class = GES_SOURCE_CLASS (klass); g_type_class_add_private (klass, sizeof (GESUriSourcePrivate)); @@ -336,7 +168,7 @@ ges_track_filesource_class_init (GESUriSourceClass * klass) g_param_spec_string ("uri", "URI", "uri of the resource", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - track_class->create_element = ges_uri_source_create_element; + source_class->create_source = ges_uri_source_create_source; } static void @@ -344,7 +176,6 @@ ges_track_filesource_init (GESUriSource * self) { self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GES_TYPE_URI_SOURCE, GESUriSourcePrivate); - self->priv->positionner = NULL; } /** diff --git a/ges/ges-uri-source.h b/ges/ges-uri-source.h index b2c1143ec8..1401684d91 100644 --- a/ges/ges-uri-source.h +++ b/ges/ges-uri-source.h @@ -24,7 +24,6 @@ #include #include #include -#include G_BEGIN_DECLS diff --git a/ges/ges-video-test-source.c b/ges/ges-video-test-source.c index f71eca8bb1..4a4dbe1b0f 100644 --- a/ges/ges-video-test-source.c +++ b/ges/ges-video-test-source.c @@ -36,17 +36,16 @@ struct _GESVideoTestSourcePrivate GESVideoTestPattern pattern; }; -static GstElement *ges_video_test_source_create_element (GESTrackElement * - self); +static GstElement *ges_video_test_source_create_source (GESTrackElement * self); static void ges_video_test_source_class_init (GESVideoTestSourceClass * klass) { - GESTrackElementClass *track_element_class = GES_TRACK_ELEMENT_CLASS (klass); + GESSourceClass *source_class = GES_SOURCE_CLASS (klass); g_type_class_add_private (klass, sizeof (GESVideoTestSourcePrivate)); - track_element_class->create_element = ges_video_test_source_create_element; + source_class->create_source = ges_video_test_source_create_source; } static void @@ -59,7 +58,7 @@ ges_video_test_source_init (GESVideoTestSource * self) } static GstElement * -ges_video_test_source_create_element (GESTrackElement * self) +ges_video_test_source_create_source (GESTrackElement * self) { gint pattern; GstElement *ret;