video-transition: Port to the new 'operator' API in compositor

Now subclassing a ghostpad with an alpha property so that
we can multiply the alpha of the frame positioning meta
and the alpha of that pad, setting it on the compositor pad.

https://bugzilla.gnome.org/show_bug.cgi?id=797169
This commit is contained in:
Thibault Saunier 2018-10-28 15:55:23 +00:00
parent b64dd33661
commit 3c7f488fc2
3 changed files with 111 additions and 6 deletions

View file

@ -22,6 +22,76 @@
#include "ges-internal.h" #include "ges-internal.h"
#include "ges-smart-video-mixer.h" #include "ges-smart-video-mixer.h"
G_DECLARE_FINAL_TYPE (GESSmartMixerPad, ges_smart_mixer_pad, GES,
SMART_MIXER_PAD, GstGhostPad);
struct _GESSmartMixerPad
{
GstGhostPad parent;
gdouble alpha;
GstSegment segment;
};
enum
{
PROP_PAD_0,
PROP_PAD_ALPHA,
};
static void
ges_smart_mixer_pad_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GESSmartMixerPad *pad = GES_SMART_MIXER_PAD (object);
switch (prop_id) {
case PROP_PAD_ALPHA:
g_value_set_double (value, pad->alpha);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
ges_smart_mixer_pad_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GESSmartMixerPad *pad = GES_SMART_MIXER_PAD (object);
switch (prop_id) {
case PROP_PAD_ALPHA:
pad->alpha = g_value_get_double (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
G_DEFINE_TYPE (GESSmartMixerPad, ges_smart_mixer_pad, GST_TYPE_GHOST_PAD);
static void
ges_smart_mixer_pad_init (GESSmartMixerPad * self)
{
gst_segment_init (&self->segment, GST_FORMAT_UNDEFINED);
}
static void
ges_smart_mixer_pad_class_init (GESSmartMixerPadClass * klass)
{
GObjectClass *gobject_class = (GObjectClass *) klass;
gobject_class->get_property = ges_smart_mixer_pad_get_property;
gobject_class->set_property = ges_smart_mixer_pad_set_property;
g_object_class_install_property (gobject_class, PROP_PAD_ALPHA,
g_param_spec_double ("alpha", "Alpha", "Alpha of the picture", 0.0, 1.0,
1.0,
G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS));
}
G_DEFINE_TYPE (GESSmartMixer, ges_smart_mixer, GST_TYPE_BIN); G_DEFINE_TYPE (GESSmartMixer, ges_smart_mixer, GST_TYPE_BIN);
#define GET_LOCK(obj) (&((GESSmartMixer*)(obj))->lock) #define GET_LOCK(obj) (&((GESSmartMixer*)(obj))->lock)
@ -88,9 +158,10 @@ ges_smart_mixer_get_mixer_pad (GESSmartMixer * self, GstPad ** mixerpad)
added in the video sources' bin */ added in the video sources' bin */
static GstPadProbeReturn static GstPadProbeReturn
parse_metadata (GstPad * mixer_pad, GstPadProbeInfo * info, parse_metadata (GstPad * mixer_pad, GstPadProbeInfo * info,
GESSmartMixer * self) GESSmartMixerPad * ghost)
{ {
GstFramePositionerMeta *meta; GstFramePositionerMeta *meta;
GESSmartMixer *self = GES_SMART_MIXER (GST_OBJECT_PARENT (ghost));
meta = meta =
(GstFramePositionerMeta *) gst_buffer_get_meta ((GstBuffer *) info->data, (GstFramePositionerMeta *) gst_buffer_get_meta ((GstBuffer *) info->data,
@ -104,6 +175,34 @@ parse_metadata (GstPad * mixer_pad, GstPadProbeInfo * info,
if (!self->disable_zorder_alpha) { if (!self->disable_zorder_alpha) {
g_object_set (mixer_pad, "alpha", meta->alpha, g_object_set (mixer_pad, "alpha", meta->alpha,
"zorder", meta->zorder, NULL); "zorder", meta->zorder, NULL);
} else {
gint64 stream_time;
gdouble transalpha;
GST_OBJECT_LOCK (ghost);
if (ghost->segment.format == GST_FORMAT_UNDEFINED) {
const GstSegment *seg;
GstEvent *segev;
GST_OBJECT_UNLOCK (ghost);
segev = gst_pad_get_sticky_event (GST_PAD (ghost), GST_EVENT_SEGMENT, 0);
gst_event_parse_segment (segev, &seg);
gst_event_unref (segev);
GST_OBJECT_LOCK (ghost);
ghost->segment = *seg;
}
stream_time = gst_segment_to_stream_time (&ghost->segment, GST_FORMAT_TIME,
GST_BUFFER_PTS (info->data));
GST_OBJECT_UNLOCK (ghost);
if (GST_CLOCK_TIME_IS_VALID (stream_time))
gst_object_sync_values (GST_OBJECT (ghost), stream_time);
g_object_get (ghost, "alpha", &transalpha, NULL);
g_object_set (mixer_pad, "alpha", meta->alpha * transalpha, NULL);
} }
g_object_set (mixer_pad, "xpos", meta->posx, "ypos", g_object_set (mixer_pad, "xpos", meta->posx, "ypos",
@ -150,7 +249,10 @@ _request_new_pad (GstElement * element, GstPadTemplate * templ,
gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost); gst_element_add_pad (GST_ELEMENT (infos->bin), tmpghost);
gst_bin_add (GST_BIN (self), infos->bin); gst_bin_add (GST_BIN (self), infos->bin);
ghost = gst_ghost_pad_new (NULL, tmpghost); ghost = g_object_new (ges_smart_mixer_pad_get_type (), "name", name,
"direction", GST_PAD_DIRECTION (tmpghost), NULL);
gst_ghost_pad_construct (GST_GHOST_PAD (ghost));
gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (ghost), tmpghost);
gst_pad_set_active (ghost, TRUE); gst_pad_set_active (ghost, TRUE);
if (!gst_element_add_pad (GST_ELEMENT (self), ghost)) if (!gst_element_add_pad (GST_ELEMENT (self), ghost))
goto could_not_add; goto could_not_add;
@ -164,7 +266,7 @@ _request_new_pad (GstElement * element, GstPadTemplate * templ,
infos->probe_id = infos->probe_id =
gst_pad_add_probe (infos->mixer_pad, GST_PAD_PROBE_TYPE_BUFFER, gst_pad_add_probe (infos->mixer_pad, GST_PAD_PROBE_TYPE_BUFFER,
(GstPadProbeCallback) parse_metadata, self, NULL); (GstPadProbeCallback) parse_metadata, ghost, NULL);
LOCK (self); LOCK (self);
g_hash_table_insert (self->pads_infos, ghost, infos); g_hash_table_insert (self->pads_infos, ghost, infos);

View file

@ -350,6 +350,7 @@ ges_video_transition_create_element (GESTrackElement * object)
mixer = ges_smart_mixer_new (NULL); mixer = ges_smart_mixer_new (NULL);
GES_SMART_MIXER (mixer)->disable_zorder_alpha = TRUE; GES_SMART_MIXER (mixer)->disable_zorder_alpha = TRUE;
g_object_set (GES_SMART_MIXER (mixer)->mixer, "background", 3, NULL); /* transparent */
gst_bin_add (GST_BIN (topbin), mixer); gst_bin_add (GST_BIN (topbin), mixer);
priv->mixer_sinka = priv->mixer_sinka =
@ -361,7 +362,9 @@ ges_video_transition_create_element (GESTrackElement * object)
mixer, GES_VIDEO_STANDARD_TRANSITION_TYPE_BAR_WIPE_LR, &priv->smpte, mixer, GES_VIDEO_STANDARD_TRANSITION_TYPE_BAR_WIPE_LR, &priv->smpte,
priv, &priv->mixer_ghostb); priv, &priv->mixer_ghostb);
g_object_set (priv->mixer_sinka, "zorder", 0, NULL); g_object_set (priv->mixer_sinka, "zorder", 0, NULL);
gst_util_set_object_arg (G_OBJECT (priv->mixer_sinka), "operator", "source");
g_object_set (priv->mixer_sinkb, "zorder", 1, NULL); g_object_set (priv->mixer_sinkb, "zorder", 1, NULL);
gst_util_set_object_arg (G_OBJECT (priv->mixer_sinkb), "operator", "add");
fast_element_link (mixer, priv->positioner); fast_element_link (mixer, priv->positioner);
fast_element_link (priv->positioner, oconv); fast_element_link (priv->positioner, oconv);
@ -385,9 +388,9 @@ ges_video_transition_create_element (GESTrackElement * object)
/* set up interpolation */ /* set up interpolation */
priv->fade_out_control_source = priv->fade_out_control_source =
set_interpolation (GST_OBJECT (priv->mixer_sinka), priv, "alpha"); set_interpolation (GST_OBJECT (priv->mixer_ghosta), priv, "alpha");
priv->fade_in_control_source = priv->fade_in_control_source =
set_interpolation (GST_OBJECT (priv->mixer_sinkb), priv, "alpha"); set_interpolation (GST_OBJECT (priv->mixer_ghostb), priv, "alpha");
priv->smpte_control_source = priv->smpte_control_source =
set_interpolation (GST_OBJECT (priv->smpte), priv, "position"); set_interpolation (GST_OBJECT (priv->smpte), priv, "position");
priv->mixer = gst_object_ref (mixer); priv->mixer = gst_object_ref (mixer);

View file

@ -506,7 +506,7 @@ gst_frame_positioner_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
{ {
GstFramePositionerMeta *meta; GstFramePositionerMeta *meta;
GstFramePositioner *framepositioner = GST_FRAME_POSITIONNER (trans); GstFramePositioner *framepositioner = GST_FRAME_POSITIONNER (trans);
GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buf); GstClockTime timestamp = GST_BUFFER_PTS (buf);
if (GST_CLOCK_TIME_IS_VALID (timestamp)) { if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
gst_object_sync_values (GST_OBJECT (trans), timestamp); gst_object_sync_values (GST_OBJECT (trans), timestamp);