[pitivi: 3/9] mixer: track: undo: curve: Only allow alpha passthrough when all alpha=1.0
- From: Edward Hervey <edwardrv src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi: 3/9] mixer: track: undo: curve: Only allow alpha passthrough when all alpha=1.0
- Date: Thu, 19 Aug 2010 08:38:53 +0000 (UTC)
commit d7b447f189e1ef4159dff89dcc17f3a17a1ef2ac
Author: Robert Swain <robert swain collabora co uk>
Date: Wed Aug 4 16:13:49 2010 +0200
mixer: track: undo: curve: Only allow alpha passthrough when all alpha=1.0
This works around an issue with videomixer where it fixes its caps and so all
its inputs to non-alpha if ramping from alpha=1.0 down to less than 1.0. This
caused the pipeline to not use alpha when it should have been.
pitivi/elements/mixer.py | 94 +++++++++++++++++++++++++++++++++++++-
pitivi/timeline/timeline_undo.py | 4 +-
pitivi/timeline/track.py | 12 +++--
pitivi/ui/curve.py | 7 ++-
4 files changed, 106 insertions(+), 11 deletions(-)
---
diff --git a/pitivi/elements/mixer.py b/pitivi/elements/mixer.py
index 78aac17..b2859d0 100644
--- a/pitivi/elements/mixer.py
+++ b/pitivi/elements/mixer.py
@@ -26,6 +26,8 @@ Audio and Video mixers
import gobject
import gst
+from pitivi.signalinterface import Signallable
+
class SmartAdderBin(gst.Bin):
@@ -122,7 +124,7 @@ class SmartVideomixerBin(gst.Bin):
)
- def __init__(self):
+ def __init__(self, track):
gst.Bin.__init__(self)
self.videomixer = gst.element_factory_make("videomixer", "real-videomixer")
# black background
@@ -138,6 +140,8 @@ class SmartVideomixerBin(gst.Bin):
self.inputs = {} # key : pad_name,
# value : (sinkpad, ffmpegcolorspace, capsfilter, videomixerpad)
+ self.alpha_helper = SmartVideomixerBinPropertyHelper(track, self.inputs)
+
def update_priority(self, pad, priority):
self.debug("pad:%r, priority:%d" % ( pad, priority))
if priority > 10000:
@@ -156,7 +160,11 @@ class SmartVideomixerBin(gst.Bin):
csp = gst.element_factory_make("ffmpegcolorspace", "csp-%d" % self.pad_count)
capsfilter = gst.element_factory_make("capsfilter", "capsfilter-%d" % self.pad_count)
- capsfilter.props.caps = gst.Caps("video/x-raw-yuv")
+ # configure the capsfilter caps
+ if self.alpha_helper.alpha_count != 0:
+ capsfilter.props.caps = gst.Caps('video/x-raw-yuv,format=(fourcc)AYUV')
+ else:
+ capsfilter.props.caps = gst.Caps('video/x-raw-yuv')
self.add(csp, capsfilter)
@@ -189,6 +197,88 @@ class SmartVideomixerBin(gst.Bin):
self.remove(capsfilter)
self.debug("done")
+class SmartVideomixerBinPropertyHelper(Signallable):
+ """A set of callbacks used for considering the alpha state of all track
+ objects in the composition."""
+
+ def __init__(self, track, inputs):
+ # this import is here because of a circular dependence
+ from pitivi.timeline.track import TrackError
+ self.inputs = inputs
+ self.alpha_count = 0
+ # connect track-object-{added,removed} signals from track to callbacks
+ track.connect("track-object-added", self._trackAddedCb)
+ track.connect("track-object-removed", self._trackRemovedCb)
+ # connect track_objects' alpha interpolator keyframe-moved signals
+ # to callback and configure initial alpha state
+ for track_object in track.track_objects:
+ try:
+ interpolator = track_object.getInterpolator("alpha")
+ except TrackError:
+ # no alpha
+ pass
+ else:
+ interpolator.connect("keyframe-added", self._keyframeChangedCb)
+ interpolator.connect("keyframe-moved", self._keyframeChangedCb)
+ interpolator.connect("keyframe-removed", self._keyframeChangedCb)
+ for kf in interpolator.getKeyframes():
+ if interpolator.valueAt(kf.time) < 1.0:
+ self.alpha_count += 1
+ if self.alpha_count != 0:
+ self.alphaStateChanged(True)
+ else:
+ self.alphaStateChanged(False)
+
+
+ def _trackAddedCb(self, track, track_object):
+ # this import is here because of a circular dependence
+ from pitivi.timeline.track import TrackError
+ try:
+ interpolator = track_object.getInterpolator("alpha")
+ except TrackError:
+ # no alpha
+ pass
+ else:
+ interpolator.connect("keyframe-added", self._keyframeChangedCb)
+ interpolator.connect("keyframe-moved", self._keyframeChangedCb)
+ interpolator.connect("keyframe-removed", self._keyframeChangedCb)
+
+ def _trackRemovedCb(self, track, track_object):
+ # this import is here because of a circular dependence
+ from pitivi.timeline.track import TrackError
+ try:
+ interpolator = track_object.getInterpolator("alpha")
+ except TrackError:
+ # no alpha
+ pass
+ else:
+ interpolator.disconnect_by_func(self._keyframeChangedCb)
+
+ def _keyframeChangedCb(self, interpolator, keyframe, old_value=None):
+ """Checks the alpha state and emits a signal if it has changed"""
+ # FIXME: This code assumes the interpolation mode is linear and as
+ # such only considers the alpha values at keyframes
+ old_alpha_count = self.alpha_count
+ new_value = interpolator.valueAt(keyframe.time)
+ if old_value == 1.0 or old_value is None:
+ if new_value < 1.0:
+ self.alpha_count += 1
+ elif old_value < 1.0 or old_value is not None:
+ if new_value == 1.0:
+ self.alpha_count -= 1
+ if old_alpha_count == 0 and self.alpha_count > 0:
+ self.alphaStateChanged(True)
+ elif old_alpha_count > 0 and self.alpha_count == 0:
+ self.alphaStateChanged(False)
+
+ def alphaStateChanged(self, has_alpha):
+ """Updates capsfilter caps to reflect the alpha state of composition"""
+ caps = gst.Caps('video/x-raw-yuv')
+ if has_alpha == True:
+ caps[0]["format"] = gst.Fourcc('AYUV')
+ for input in self.inputs.values():
+ input[2].props.caps = caps
+
gobject.type_register(SmartVideomixerBin)
gst.element_register(SmartVideomixerBin, 'smart-videomixer-bin')
diff --git a/pitivi/timeline/timeline_undo.py b/pitivi/timeline/timeline_undo.py
index a846b14..b7a29ff 100644
--- a/pitivi/timeline/timeline_undo.py
+++ b/pitivi/timeline/timeline_undo.py
@@ -85,10 +85,10 @@ class KeyframeChangeTracker(Signallable):
def _keyframeAddedCb(self, interpolator, keyframe):
self.keyframes[keyframe] = self._getKeyframeSnapshot(keyframe)
- def _keyframeRemovedCb(self, interpolator, keyframe):
+ def _keyframeRemovedCb(self, interpolator, keyframe, old_value=None):
pass
- def _keyframeMovedCb(self, interpolator, keyframe):
+ def _keyframeMovedCb(self, interpolator, keyframe, old_value=None):
old_snapshot = self.keyframes[keyframe]
new_snapshot = self._getKeyframeSnapshot(keyframe)
self.keyframes[keyframe] = new_snapshot
diff --git a/pitivi/timeline/track.py b/pitivi/timeline/track.py
index 41cae1f..7b99fd7 100644
--- a/pitivi/timeline/track.py
+++ b/pitivi/timeline/track.py
@@ -132,8 +132,8 @@ class Interpolator(Signallable, Loggable):
__signals__ = {
'keyframe-added' : ['keyframe'],
- 'keyframe-removed' : ['keyframe'],
- 'keyframe-moved' : ['keyframe'],
+ 'keyframe-removed' : ['keyframe', 'old_value'],
+ 'keyframe-moved' : ['keyframe', 'old_value'],
}
def __init__(self, trackobject, element, prop, minimum=None, maximum=None,
@@ -217,10 +217,11 @@ class Interpolator(Signallable, Loggable):
return keyframe
def removeKeyframe(self, keyframe):
+ old_value = self._controller.get(self._property.name, keyframe.time)
self._controller.unset(self._property.name, keyframe.time)
if keyframe is not self.start and keyframe is not self.end:
self._keyframes.remove(keyframe)
- self.emit("keyframe-removed", keyframe)
+ self.emit("keyframe-removed", keyframe, old_value)
def setKeyframeMode(self, kf, mode):
# FIXME: currently InterpolationSourceControllers only support a
@@ -246,10 +247,11 @@ class Interpolator(Signallable, Loggable):
self.debug("kf.time:%s, ptime:%s, value:%r",
gst.TIME_ARGS(kf.time),
gst.TIME_ARGS(ptime), value)
+ old_value = self._controller.get(self._property.name, ptime)
self._controller.set(self._property.name, ptime, value)
if kf.time != ptime:
self._controller.unset(self._property.name, kf.time)
- self.emit("keyframe-moved", kf)
+ self.emit("keyframe-moved", kf, old_value)
def getKeyframes(self):
# TODO: This could be more efficient. We are re-sorting all the keyframes
@@ -979,7 +981,7 @@ class Track(Signallable, Loggable):
return gnl
elif isinstance(stream, VideoStream):
gnl = gst.element_factory_make("gnloperation", "top-level-video-mixer")
- m = SmartVideomixerBin()
+ m = SmartVideomixerBin(self)
gnl.add(m)
gnl.props.expandable = True
gnl.props.priority = 0
diff --git a/pitivi/ui/curve.py b/pitivi/ui/curve.py
index 17ddcab..6e2d41c 100644
--- a/pitivi/ui/curve.py
+++ b/pitivi/ui/curve.py
@@ -173,7 +173,7 @@ class Curve(goocanvas.ItemSimple, goocanvas.Item, View, Zoomable):
interpolator = receiver()
@handler(interpolator, "keyframe-removed")
- def keyframeRemoved(self, unused_interpolator, keyframe):
+ def keyframeRemoved(self, unused_interpolator, keyframe, old_value=None):
if keyframe in self.keyframes:
del self.keyframes[keyframe]
if keyframe is self._focused_kf:
@@ -181,10 +181,13 @@ class Curve(goocanvas.ItemSimple, goocanvas.Item, View, Zoomable):
self.changed(False)
@handler(interpolator, "keyframe-added")
- @handler(interpolator, "keyframe-moved")
def curveChanged(self, unused_interpolator, unused_keyframe):
self.changed(False)
+ @handler(interpolator, "keyframe-moved")
+ def curveChanged(self, unused_interpolator, unused_keyframe, old_value=None):
+ self.changed(False)
+
## Zoomable interface overries
def zoomChanged(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]