static void ges_track_video_transition_dispose (GObject * object) { GESTrackVideoTransition *self = GES_TRACK_VIDEO_TRANSITION (object); GESTrackVideoTransitionPrivate *priv = self->priv; GST_DEBUG ("disposing"); GST_LOG ("mixer: %p smpte: %p sinka: %p sinkb: %p", priv->mixer, priv->smpte, priv->sinka, priv->sinkb); if (priv->control_source) { if (priv->control_source) gst_object_unref (priv->control_source); priv->control_source = NULL; } if (priv->sinka && priv->sinkb) { GST_DEBUG ("releasing request pads for mixer"); gst_element_release_request_pad (priv->mixer, priv->sinka); gst_element_release_request_pad (priv->mixer, priv->sinkb); gst_object_unref (priv->sinka); gst_object_unref (priv->sinkb); priv->sinka = NULL; priv->sinkb = NULL; } if (priv->mixer) { GST_LOG ("unrefing mixer"); gst_object_unref (priv->mixer); priv->mixer = NULL; } G_OBJECT_CLASS (ges_track_video_transition_parent_class)->dispose (object); }
static void ges_track_video_transition_duration_changed (GESTrackObject * object, guint64 duration) { GstElement *gnlobj = ges_track_object_get_gnlobject (object); GESTrackVideoTransition *self = GES_TRACK_VIDEO_TRANSITION (object); GESTrackVideoTransitionPrivate *priv = self->priv; GstTimedValueControlSource *ts; GST_LOG ("updating controller"); if (G_UNLIKELY (!gnlobj || !priv->control_source)) return; ts = GST_TIMED_VALUE_CONTROL_SOURCE (priv->control_source); GST_INFO ("duration: %" G_GUINT64_FORMAT, duration); GST_LOG ("setting values on controller"); gst_timed_value_control_source_unset_all (ts); gst_timed_value_control_source_set (ts, 0, priv->start_value); gst_timed_value_control_source_set (ts, duration, priv->end_value); priv->dur = duration; GST_LOG ("done updating controller"); }
static void ges_track_video_transition_duration_changed (GESTrackObject * object, guint64 duration) { GValue start_value = { 0, }; GValue end_value = { 0, }; GstElement *gnlobj = ges_track_object_get_gnlobject (object); GESTrackVideoTransition *self = GES_TRACK_VIDEO_TRANSITION (object); GESTrackVideoTransitionPrivate *priv = self->priv; GST_LOG ("updating controller"); if (G_UNLIKELY (!gnlobj || !priv->control_source)) return; GST_INFO ("duration: %" G_GUINT64_FORMAT, duration); g_value_init (&start_value, G_TYPE_DOUBLE); g_value_init (&end_value, G_TYPE_DOUBLE); g_value_set_double (&start_value, priv->start_value); g_value_set_double (&end_value, priv->end_value); GST_LOG ("setting values on controller"); gst_interpolation_control_source_unset_all (priv->control_source); gst_interpolation_control_source_set (priv->control_source, 0, &start_value); gst_interpolation_control_source_set (priv->control_source, duration, &end_value); GST_LOG ("done updating controller"); }
static void ges_timeline_standard_transition_update_vtype_internal (GESTimelineObject * self, GESVideoStandardTransitionType value) { GSList *tmp; GESTimelineStandardTransition *trself = GES_TIMELINE_STANDARD_TRANSITION (self); for (tmp = trself->priv->track_video_transitions; tmp; tmp = tmp->next) { if (!ges_track_video_transition_set_transition_type (GES_TRACK_VIDEO_TRANSITION (tmp->data), value)) return; } trself->vtype = value; }
static void ges_track_video_transition_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) { GESTrackVideoTransition *tr = GES_TRACK_VIDEO_TRANSITION (object); switch (property_id) { case PROP_BORDER: g_value_set_uint (value, ges_track_video_transition_get_border (tr)); break; case PROP_TRANSITION_TYPE: g_value_set_enum (value, ges_track_video_transition_get_transition_type (tr)); break; case PROP_INVERT: g_value_set_boolean (value, ges_track_video_transition_is_inverted (tr)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } }
static GstElement * ges_track_video_transition_create_element (GESTrackObject * object) { GstElement *topbin, *iconva, *iconvb, *scalea, *scaleb, *capsfilt, *oconv; GstObject *target = NULL; const gchar *propname = NULL; GstElement *mixer = NULL; GstPad *sinka_target, *sinkb_target, *src_target, *sinka, *sinkb, *src, *srca_pad; GESTrackVideoTransition *self; GESTrackVideoTransitionPrivate *priv; self = GES_TRACK_VIDEO_TRANSITION (object); priv = self->priv; GST_LOG ("creating a video bin"); topbin = gst_bin_new ("transition-bin"); iconva = gst_element_factory_make ("videoconvert", "tr-csp-a"); iconvb = gst_element_factory_make ("videoconvert", "tr-csp-b"); scalea = gst_element_factory_make ("videoscale", "vs-a"); scaleb = gst_element_factory_make ("videoscale", "vs-b"); capsfilt = gst_element_factory_make ("capsfilter", "capsfilt"); oconv = gst_element_factory_make ("videoconvert", "tr-csp-output"); gst_bin_add_many (GST_BIN (topbin), iconva, iconvb, scalea, scaleb, capsfilt, oconv, NULL); mixer = gst_element_factory_make ("videomixer", NULL); g_assert (mixer); g_object_set (G_OBJECT (mixer), "background", 1, NULL); gst_bin_add (GST_BIN (topbin), mixer); if (priv->pending_type != GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE) { priv->sinka = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconva, mixer, priv->pending_type, NULL); priv->sinkb = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconvb, mixer, priv->pending_type, &priv->smpte); target = GST_OBJECT (priv->smpte); propname = "position"; priv->start_value = 1.0; priv->end_value = 0.0; } else { gst_element_link_pads_full (iconva, "src", scalea, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (iconvb, "src", scaleb, "sink", GST_PAD_LINK_CHECK_NOTHING); gst_element_link_pads_full (scaleb, "src", capsfilt, "sink", GST_PAD_LINK_CHECK_NOTHING); priv->sinka = (GstPad *) link_element_to_mixer (scalea, mixer); priv->sinkb = (GstPad *) link_element_to_mixer (capsfilt, mixer); target = GST_OBJECT (priv->sinkb); propname = "alpha"; priv->start_value = 0.0; priv->end_value = 1.0; } priv->mixer = gst_object_ref (mixer); fast_element_link (mixer, oconv); sinka_target = gst_element_get_static_pad (iconva, "sink"); sinkb_target = gst_element_get_static_pad (iconvb, "sink"); src_target = gst_element_get_static_pad (oconv, "src"); sinka = gst_ghost_pad_new ("sinka", sinka_target); sinkb = gst_ghost_pad_new ("sinkb", sinkb_target); src = gst_ghost_pad_new ("src", src_target); gst_element_add_pad (topbin, src); gst_element_add_pad (topbin, sinka); gst_element_add_pad (topbin, sinkb); srca_pad = gst_element_get_static_pad (scalea, "src"); g_signal_connect (srca_pad, "notify::caps", G_CALLBACK (on_caps_set), (GstElement *) capsfilt); gst_object_unref (sinka_target); gst_object_unref (sinkb_target); gst_object_unref (src_target); gst_object_unref (srca_pad); /* set up interpolation */ set_interpolation (target, priv, propname); priv->topbin = topbin; priv->type = priv->pending_type; return topbin; }
static GstElement * ges_track_video_transition_create_element (GESTrackObject * object) { GstElement *topbin, *iconva, *iconvb, *oconv; GObject *target = NULL; const gchar *propname = NULL; GstElement *mixer = NULL; GstPad *sinka_target, *sinkb_target, *src_target, *sinka, *sinkb, *src; GstController *controller; GstInterpolationControlSource *control_source; GESTrackVideoTransition *self; GESTrackVideoTransitionPrivate *priv; self = GES_TRACK_VIDEO_TRANSITION (object); priv = self->priv; GST_LOG ("creating a video bin"); topbin = gst_bin_new ("transition-bin"); iconva = gst_element_factory_make ("ffmpegcolorspace", "tr-csp-a"); iconvb = gst_element_factory_make ("ffmpegcolorspace", "tr-csp-b"); oconv = gst_element_factory_make ("ffmpegcolorspace", "tr-csp-output"); gst_bin_add_many (GST_BIN (topbin), iconva, iconvb, oconv, NULL); /* Prefer videomixer2 to videomixer */ mixer = gst_element_factory_make ("videomixer2", NULL); if (mixer == NULL) mixer = gst_element_factory_make ("videomixer", NULL); g_object_set (G_OBJECT (mixer), "background", 1, NULL); gst_bin_add (GST_BIN (topbin), mixer); if (priv->type != GES_VIDEO_STANDARD_TRANSITION_TYPE_CROSSFADE) { priv->sinka = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconva, mixer, priv->type, NULL); priv->sinkb = (GstPad *) link_element_to_mixer_with_smpte (GST_BIN (topbin), iconvb, mixer, priv->type, &priv->smpte); target = (GObject *) priv->smpte; propname = "position"; priv->start_value = 1.0; priv->end_value = 0.0; } else { priv->sinka = (GstPad *) link_element_to_mixer (iconva, mixer); priv->sinkb = (GstPad *) link_element_to_mixer (iconvb, mixer); target = (GObject *) priv->sinkb; propname = "alpha"; priv->start_value = 0.0; priv->end_value = 1.0; } priv->mixer = gst_object_ref (mixer); fast_element_link (mixer, oconv); sinka_target = gst_element_get_static_pad (iconva, "sink"); sinkb_target = gst_element_get_static_pad (iconvb, "sink"); src_target = gst_element_get_static_pad (oconv, "src"); sinka = gst_ghost_pad_new ("sinka", sinka_target); sinkb = gst_ghost_pad_new ("sinkb", sinkb_target); src = gst_ghost_pad_new ("src", src_target); gst_element_add_pad (topbin, src); gst_element_add_pad (topbin, sinka); gst_element_add_pad (topbin, sinkb); gst_object_unref (sinka_target); gst_object_unref (sinkb_target); gst_object_unref (src_target); /* set up interpolation */ g_object_set (target, propname, (gfloat) 0.0, NULL); controller = gst_object_control_properties (target, propname, NULL); control_source = gst_interpolation_control_source_new (); gst_controller_set_control_source (controller, propname, GST_CONTROL_SOURCE (control_source)); gst_interpolation_control_source_set_interpolation_mode (control_source, GST_INTERPOLATE_LINEAR); priv->controller = controller; priv->control_source = control_source; return topbin; }