1
# PiTiVi , Non-linear video editor
5
# Copyright (c) 2009, Alessandro Decina <alessandro.decina@collabora.co.uk>
7
# This program is free software; you can redistribute it and/or
8
# modify it under the terms of the GNU Lesser General Public
9
# License as published by the Free Software Foundation; either
10
# version 2.1 of the License, or (at your option) any later version.
12
# This program is distributed in the hope that it will be useful,
13
# but WITHOUT ANY WARRANTY; without even the implied warranty of
14
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
# Lesser General Public License for more details.
17
# You should have received a copy of the GNU Lesser General Public
18
# License along with this program; if not, write to the
19
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
20
# Boston, MA 02110-1301, USA.
22
from unittest import TestCase
24
from xml.etree.ElementTree import Element, SubElement
26
from pitivi.reflect import qual
27
from pitivi.formatters.etree import ElementTreeFormatter, version,\
29
from pitivi.stream import VideoStream, AudioStream
30
from pitivi.factories.file import FileSourceFactory
31
from pitivi.factories.test import VideoTestSourceFactory, \
32
AudioTestSourceFactory
33
from pitivi.factories.operation import EffectFactory
34
from pitivi.timeline.track import Track, SourceTrackObject, Interpolator,\
36
from pitivi.timeline.timeline import Timeline, TimelineObject
37
from pitivi.project import Project
38
from pitivi.utils import get_controllable_properties
39
from pitivi.effects import EffectsHandler
42
class FakeElementTreeFormatter(ElementTreeFormatter):
47
return "(gint64)%s" % time
50
class TestSerialization(TestCase):
52
self.formatter = FakeElementTreeFormatter(EffectsHandler())
54
def testSerializeAndDeserialize(self):
55
element = Element('tag')
62
self.formatter._serializeDict(element, values_dict)
63
# Make sure that all the keys end up in element.
64
for key, unused_value in values_dict.iteritems():
65
self.assertTrue(key in element.attrib)
67
deserialized_values_dict = self.formatter._deserializeDict(element)
68
# Make sure that all the keys in the original dict end up in the
71
set(values_dict.keys()), set(deserialized_values_dict.keys()))
72
for key, value in values_dict.iteritems():
73
self.assertEqual(value, deserialized_values_dict[key])
75
def testEmptyValuesDeserialization(self):
76
self.assertEqual("", self.formatter._parsePropertyValue(""))
79
class TestFormatterSave(TestCase):
81
self.formatter = FakeElementTreeFormatter(EffectsHandler())
83
def testSaveStream(self):
84
stream = VideoStream(gst.Caps("video/x-raw-rgb, blah=meh"))
85
element = self.formatter._saveStream(stream)
86
self.failUnlessEqual(element.tag, "stream")
87
self.failUnless("id" in element.attrib)
88
self.failUnlessEqual(element.attrib["type"], qual(stream.__class__))
89
self.failUnlessEqual(element.attrib["caps"], str(stream.caps))
91
def testSaveStreamRef(self):
92
# save a stream so that a mapping is created in the context
93
stream = VideoStream(gst.Caps("video/x-raw-rgb, blah=meh"))
94
element = self.formatter._saveStream(stream)
95
element_ref = self.formatter._saveStreamRef(stream)
96
self.failUnlessEqual(element_ref.tag, "stream-ref")
97
self.failUnlessEqual(element_ref.attrib["id"], element.attrib["id"])
99
def testSaveSource(self):
100
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
101
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
102
source1 = FileSourceFactory("file1.ogg")
103
source1.addOutputStream(video_stream)
104
source1.addOutputStream(audio_stream)
105
element = self.formatter._saveSource(source1)
106
self.failUnlessEqual(element.tag, "source")
107
self.failUnlessEqual(element.attrib["type"], qual(source1.__class__))
108
self.failUnlessEqual(element.attrib["filename"], "file1.ogg")
110
streams = element.find("output-streams")
111
self.failUnlessEqual(len(streams), 2)
113
def testSaveFactories(self):
114
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
115
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
117
source1 = FileSourceFactory("file1.ogg")
118
source1.addOutputStream(video_stream)
119
source1.addOutputStream(audio_stream)
121
source2 = FileSourceFactory("file2.ogg")
122
source2.addOutputStream(video_stream)
123
source2.addOutputStream(audio_stream)
125
source_factories = [source1, source2]
126
element = self.formatter._saveFactories(source_factories)
127
self.failUnlessEqual(element.tag, "factories")
129
sources = element.find("sources")
130
self.failUnlessEqual(len(sources), 2)
131
#source tags are tested in testSaveSource
133
def testSaveFactoryRef(self):
134
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
135
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
136
source1 = FileSourceFactory("file1.ogg")
137
source1.addOutputStream(video_stream)
138
source1.addOutputStream(audio_stream)
139
element = self.formatter._saveSource(source1)
141
element_ref = self.formatter._saveFactoryRef(source1)
142
self.failUnlessEqual(element_ref.tag, "factory-ref")
143
self.failUnlessEqual(element_ref.attrib["id"], element.attrib["id"])
145
def testSaveTrackEffect(self):
146
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
147
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
149
effect1 = EffectFactory('identity', 'identity')
150
effect1.addOutputStream(video_stream)
151
effect1.addInputStream(video_stream)
153
#It is necessary to had the identity factory to the
154
#effect_factories_dictionnary
155
self.formatter.avalaible_effects._effect_factories_dict['identity'] =\
157
track_effect = TrackEffect(effect1, video_stream,
158
start=10 * gst.SECOND, duration=20 * gst.SECOND,
159
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
162
track = Track(video_stream)
163
track.addTrackObject(track_effect)
165
element = self.formatter._saveTrackObject(track_effect)
166
self.failUnlessEqual(element.tag, "track-object")
167
self.failUnlessEqual(element.attrib["type"],
168
qual(track_effect.__class__))
169
self.failUnlessEqual(element.attrib["start"], ts(10 * gst.SECOND))
170
self.failUnlessEqual(element.attrib["duration"], ts(20 * gst.SECOND))
171
self.failUnlessEqual(element.attrib["in_point"], ts(5 * gst.SECOND))
172
self.failUnlessEqual(element.attrib["media_duration"],
174
self.failUnlessEqual(element.attrib["priority"], "(int)10")
176
effect_element = element.find('effect')
177
self.failIfEqual(effect_element, None)
178
self.failIfEqual(effect_element.find("factory"), None)
179
self.failIfEqual(effect_element.find("gst-element-properties"), None)
181
def testSaveTrackSource(self):
182
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
183
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
184
source1 = FileSourceFactory("file1.ogg")
185
source1.addOutputStream(video_stream)
187
# these two calls are needed to populate the context for the -ref
189
self.formatter._saveSource(source1)
190
self.formatter._saveStream(video_stream)
192
track_source = SourceTrackObject(source1, video_stream,
193
start=10 * gst.SECOND, duration=20 * gst.SECOND,
194
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
197
track = Track(video_stream)
198
track.addTrackObject(track_source)
200
# create an interpolator and insert it into the track object
201
fakevol = gst.element_factory_make("volume")
202
prop = get_controllable_properties(fakevol)[1][1]
203
volcurve = Interpolator(track_source, fakevol, prop)
204
track_source.interpolators[prop.name] = (prop, volcurve)
206
# add some points to the interpolator
208
volcurve.start.setObjectTime(0)
209
volcurve.start.value = 0
210
for t in xrange(3, 15, 3):
212
volcurve.newKeyframe(t * gst.SECOND, value)
213
volcurve.end.setObjectTime(15 * gst.SECOND)
214
volcurve.end.value = 15 % 2
216
element = self.formatter._saveTrackObject(track_source)
217
self.failUnlessEqual(element.tag, "track-object")
218
self.failUnlessEqual(element.attrib["type"],
219
qual(track_source.__class__))
220
self.failUnlessEqual(element.attrib["start"], ts(10 * gst.SECOND))
221
self.failUnlessEqual(element.attrib["duration"], ts(20 * gst.SECOND))
222
self.failUnlessEqual(element.attrib["in_point"], ts(5 * gst.SECOND))
223
self.failUnlessEqual(element.attrib["media_duration"],
225
self.failUnlessEqual(element.attrib["priority"], "(int)10")
227
self.failIfEqual(element.find("factory-ref"), None)
228
self.failIfEqual(element.find("stream-ref"), None)
230
# find the interpolation keyframes
231
curves = element.find("curves")
232
self.failIfEqual(curves, None)
233
curve = curves.find("curve")
234
self.failIfEqual(curve, None)
235
self.failUnlessEqual(curve.attrib["property"], "volume")
237
# compute a dictionary of keyframes
238
saved_points = dict(((obj.attrib["time"], (obj.attrib["value"],
239
obj.attrib["mode"])) for obj in curve.getiterator("keyframe")))
241
# compare this with the expected values
242
expected = dict(((str(t * gst.SECOND), ("(gdouble)%s" % (t % 2), "2")) for t in
244
self.failUnlessEqual(expected, saved_points)
246
def testSaveTrackObjectRef(self):
247
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
248
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
249
source1 = FileSourceFactory("file1.ogg")
250
source1.addOutputStream(video_stream)
252
# these two calls are needed to populate the context for the -ref
254
self.formatter._saveSource(source1)
255
self.formatter._saveStream(video_stream)
257
track_object = SourceTrackObject(source1, video_stream,
258
start=10 * gst.SECOND, duration=20 * gst.SECOND,
259
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
261
track = Track(video_stream)
262
track.addTrackObject(track_object)
264
element = self.formatter._saveTrackObject(track_object)
265
element_ref = self.formatter._saveTrackObjectRef(track_object)
266
self.failUnlessEqual(element_ref.tag, "track-object-ref")
267
self.failUnlessEqual(element.attrib["id"], element.attrib["id"])
269
def testSaveTrack(self):
270
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
271
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
272
source1 = VideoTestSourceFactory()
274
# these two calls are needed to populate the context for the -ref
276
self.formatter._saveSource(source1)
277
self.formatter._saveStream(video_stream)
279
track_object = SourceTrackObject(source1, video_stream,
280
start=10 * gst.SECOND, duration=20 * gst.SECOND,
281
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
284
track = Track(video_stream)
285
track.addTrackObject(track_object)
287
element = self.formatter._saveTrack(track)
288
self.failUnlessEqual(element.tag, "track")
289
track_objects_element = element.find("track-objects")
290
self.failUnlessEqual(len(track_objects_element), 1)
292
def testSaveTimelineObject(self):
293
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
294
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
295
source1 = FileSourceFactory("file1.ogg")
296
source1.addOutputStream(video_stream)
298
# these two calls are needed to populate the context for the -ref
300
self.formatter._saveSource(source1)
301
self.formatter._saveStream(video_stream)
303
track_object = SourceTrackObject(source1, video_stream,
304
start=10 * gst.SECOND, duration=20 * gst.SECOND,
305
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
307
track = Track(video_stream)
308
track.addTrackObject(track_object)
310
self.formatter._saveTrackObject(track_object)
312
timeline_object = TimelineObject(source1)
313
timeline_object.addTrackObject(track_object)
315
element = self.formatter._saveTimelineObject(timeline_object)
316
self.failUnlessEqual(element.tag, "timeline-object")
317
self.failIfEqual(element.find("factory-ref"), None)
318
track_object_refs = element.find("track-object-refs")
319
self.failUnlessEqual(len(track_object_refs), 1)
321
def testSavetimelineObjects(self):
322
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
323
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
324
source1 = FileSourceFactory("file1.ogg")
325
source1.addOutputStream(video_stream)
327
# these two calls are needed to populate the context for the -ref
329
self.formatter._saveSource(source1)
330
self.formatter._saveStream(video_stream)
332
track_object = SourceTrackObject(source1, video_stream,
333
start=10 * gst.SECOND, duration=20 * gst.SECOND,
334
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
336
track = Track(video_stream)
337
track.addTrackObject(track_object)
338
self.formatter._saveTrackObject(track_object)
340
timeline_object = TimelineObject(source1)
341
timeline_object.addTrackObject(track_object)
343
element = self.formatter._saveTimelineObjects([timeline_object])
344
self.failUnlessEqual(len(element), 1)
346
def testSaveTimeline(self):
347
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
348
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
349
source1 = VideoTestSourceFactory()
350
source1.addOutputStream(video_stream)
352
self.formatter._saveSource(source1)
353
self.formatter._saveStream(video_stream)
355
track_object = SourceTrackObject(source1, video_stream,
356
start=10 * gst.SECOND, duration=20 * gst.SECOND,
357
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
360
track = Track(video_stream)
361
track.addTrackObject(track_object)
363
self.formatter._saveTrackObject(track_object)
365
timeline_object = TimelineObject(source1)
366
timeline_object.addTrackObject(track_object)
368
self.formatter._saveTimelineObject(timeline_object)
370
timeline = Timeline()
371
timeline.addTrack(track)
373
element = self.formatter._saveTimeline(timeline)
374
self.failUnlessEqual(element.tag, "timeline")
375
tracks = element.find("tracks")
376
self.failUnlessEqual(len(tracks), 1)
378
def testSaveMainTag(self):
379
element = self.formatter._saveMainTag()
380
self.failUnlessEqual(element.tag, "pitivi")
381
self.failUnlessEqual(element.attrib["formatter"], "etree")
382
self.failUnlessEqual(element.attrib["version"], version)
384
def testSaveProject(self):
385
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
386
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
387
source1 = VideoTestSourceFactory()
389
self.formatter._saveSource(source1)
390
self.formatter._saveStream(video_stream)
392
track_object = SourceTrackObject(source1, video_stream,
393
start=10 * gst.SECOND, duration=20 * gst.SECOND,
394
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
397
track = Track(video_stream)
398
track.addTrackObject(track_object)
400
self.formatter._saveTrackObject(track_object)
402
timeline_object = TimelineObject(source1)
403
timeline_object.addTrackObject(track_object)
405
self.formatter._saveTimelineObject(timeline_object)
407
timeline = Timeline()
408
timeline.addTrack(track)
410
self.formatter._saveTimeline(timeline)
413
project.timeline = timeline
414
project.sources.addFactory(source1)
416
element = self.formatter._serializeProject(project)
418
self.failUnlessEqual(element.tag, "pitivi")
419
self.failIfEqual(element.find("factories"), None)
420
self.failIfEqual(element.find("timeline"), None)
423
class TestFormatterLoad(TestCase):
425
self.formatter = FakeElementTreeFormatter(EffectsHandler())
427
def testLoadStream(self):
428
caps = gst.Caps("video/x-raw-yuv")
429
element = Element("stream")
430
element.attrib["id"] = "1"
431
element.attrib["type"] = "pitivi.stream.VideoStream"
432
element.attrib["caps"] = str(caps)
434
stream = self.formatter._loadStream(element)
435
self.failUnlessEqual(qual(stream.__class__), element.attrib["type"])
436
self.failUnlessEqual(str(stream.caps), str(caps))
437
self.failUnlessEqual(stream, self.formatter._context.streams["1"])
439
def testLoadTrackEffect(self):
440
# create fake document tree
441
element = Element("track-object",\
442
type="pitivi.timeline.track.TrackEffect",
443
start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
444
in_point=ts(5 * gst.SECOND),
445
media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
446
effect_elem = SubElement(element, "effect")
447
factory_elem = SubElement(effect_elem, "factory", name="identity")
448
properties_elem = SubElement(effect_elem, "gst-element-properties", sync="(bool)True")
450
# insert our fake factory into the context
451
stream = AudioStream(gst.Caps("audio/x-raw-int"))
452
factory = EffectFactory('identity')
453
factory.addInputStream(stream)
454
factory.addOutputStream(stream)
455
self.formatter.avalaible_effects._effect_factories_dict['identity'] = factory
457
track = Track(stream)
458
track_object = self.formatter._loadTrackObject(track, element)
459
self.failUnless(isinstance(track_object, TrackEffect))
460
self.failUnlessEqual(track_object.factory, factory)
461
self.failUnlessEqual(track_object.stream, stream)
463
self.failUnlessEqual(track_object.start, 1 * gst.SECOND)
464
self.failUnlessEqual(track_object.duration, 10 * gst.SECOND)
465
self.failUnlessEqual(track_object.in_point, 5 * gst.SECOND)
466
self.failUnlessEqual(track_object.media_duration, 15 * gst.SECOND)
467
self.failUnlessEqual(track_object.priority, 5)
469
def testLoadStreamRef(self):
470
stream = VideoStream(gst.Caps("meh"))
471
self.formatter._context.streams["1"] = stream
472
element = Element("stream-ref")
473
element.attrib["id"] = "1"
474
stream1 = self.formatter._loadStreamRef(element)
475
self.failUnlessEqual(stream, stream1)
477
def testLoadFactory(self):
478
element = Element("source")
479
element.attrib["id"] = "1"
480
element.attrib["type"] = "pitivi.factories.test.VideoTestSourceFactory"
481
element.attrib["duration"] = 5 * gst.SECOND
482
element.attrib["default_duration"] = 5 * gst.SECOND
483
output_streams = SubElement(element, "output-streams")
484
output_stream = SubElement(output_streams, "stream")
485
caps = gst.Caps("video/x-raw-yuv")
486
output_stream.attrib["id"] = "1"
487
output_stream.attrib["type"] = "pitivi.stream.VideoStream"
488
output_stream.attrib["caps"] = str(caps)
490
factory = self.formatter._loadFactory(element)
491
self.failUnless(isinstance(factory, VideoTestSourceFactory))
492
self.failUnlessEqual(len(factory.output_streams), 2)
494
self.failUnlessEqual(self.formatter._context.factories["1"], factory)
495
self.failUnlessEqual(factory.duration, 5 * gst.SECOND)
496
self.failUnlessEqual(factory.default_duration, 5 * gst.SECOND)
498
def testLoadFactoryRef(self):
502
self.formatter._context.factories["1"] = tag
503
element = Element("factory-ref", id="1")
504
ret = self.formatter._loadFactoryRef(element)
505
self.failUnless(ret is tag)
507
def testLoadTrackSource(self):
508
# create fake document tree
509
element = Element("track-object",
510
type="pitivi.timeline.track.SourceTrackObject",
511
start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
512
in_point=ts(5 * gst.SECOND),
513
media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
514
factory_ref = SubElement(element, "factory-ref", id="1")
515
stream_ref = SubElement(element, "stream-ref", id="1")
517
# insert our fake factory into the context
518
factory = AudioTestSourceFactory()
519
factory.duration = 10 * gst.SECOND
520
self.formatter._context.factories["1"] = factory
522
# insert fake stream into the context
523
stream = AudioStream(gst.Caps("audio/x-raw-int"))
524
self.formatter._context.streams["1"] = stream
527
curves = SubElement(element, "curves")
528
curve = SubElement(curves, "curve", property="volume",
530
expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
531
for t in xrange(1, 10))
532
start = SubElement(curve, "start", value="0.0", mode="2")
533
for time, (value, mode) in expected.iteritems():
534
SubElement(curve, "keyframe", time=str(time), value=str(value),
536
end = SubElement(curve, "end", value=str(10 % 2), mode="2")
538
track = Track(stream)
539
# point gun at foot; pull trigger
540
track_object = self.formatter._loadTrackObject(track, element)
541
self.failUnless(isinstance(track_object, SourceTrackObject))
542
self.failUnlessEqual(track_object.factory, factory)
543
self.failUnlessEqual(track_object.stream, stream)
545
self.failUnlessEqual(track_object.start, 1 * gst.SECOND)
546
self.failUnlessEqual(track_object.duration, 10 * gst.SECOND)
547
self.failUnlessEqual(track_object.in_point, 5 * gst.SECOND)
548
self.failUnlessEqual(track_object.media_duration, 15 * gst.SECOND)
549
self.failUnlessEqual(track_object.priority, 5)
551
self.failIfEqual(track_object.interpolators, None)
552
interpolator = track_object.getInterpolator("volume")
553
self.failIfEqual(interpolator, None)
554
curve = dict(((kf.time, (kf.value, kf.mode)) for kf in
555
interpolator.getInteriorKeyframes()))
556
self.failUnlessEqual(curve, expected)
558
self.failUnlessEqual(interpolator.start.value, 0.0)
559
self.failUnlessEqual(interpolator.start.time, 5 * gst.SECOND)
560
self.failUnlessEqual(interpolator.end.value, 0.0)
561
self.failUnlessEqual(interpolator.end.time, 15 * gst.SECOND)
563
def testLoadInterpolatorV0(self):
564
# create fake document tree
565
element = Element("track-object",
566
type="pitivi.timeline.track.SourceTrackObject",
567
start=ts(1 * gst.SECOND), duration=ts(15 * gst.SECOND),
568
in_point=ts(5 * gst.SECOND),
569
media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
570
factory_ref = SubElement(element, "factory-ref", id="1")
571
stream_ref = SubElement(element, "stream-ref", id="1")
573
# insert our fake factory into the context
574
factory = AudioTestSourceFactory()
575
factory.duration = 20 * gst.SECOND
576
self.formatter._context.factories["1"] = factory
578
# insert fake stream into the context
579
stream = AudioStream(gst.Caps("audio/x-raw-int"))
580
self.formatter._context.streams["1"] = stream
583
curves = SubElement(element, "curves")
584
curve = SubElement(curves, "curve", property="volume")
585
expected = dict((long(t * gst.SECOND), (float(t % 2), gst.INTERPOLATE_LINEAR))
586
for t in xrange(6, 15))
587
start = SubElement(curve, "start", value="1.0", mode="2")
588
for time, (value, mode) in expected.iteritems():
589
SubElement(curve, "keyframe", time=str(time), value=str(value),
591
end = SubElement(curve, "end", value="1.0", mode="2")
593
track = Track(stream)
594
# point gun at foot; pull trigger
595
track_object = self.formatter._loadTrackObject(track, element)
596
self.failIfEqual(track_object.interpolators, None)
597
interpolator = track_object.getInterpolator("volume")
598
self.failIfEqual(interpolator, None)
599
curve = dict(((kf.time, (kf.value, kf.mode)) for kf in
600
interpolator.getInteriorKeyframes()))
601
self.failUnlessEqual(curve, expected)
603
# check that start keyframe value has been properly adjusted so as not
604
# to change the shape of the curve. rounding is applied here because
605
# the controller seems to round to a different precision
606
# than python. we just want to check that the value is "in the
607
# ballpark", indicating the keyframes have been updated. If you do the
608
# math you'll see that both start and end keyframe values should be
610
self.failUnlessEqual(
611
round(interpolator.start.value, 6),
612
round((-5.0 / 6) + 1, 6))
613
self.failUnlessEqual(interpolator.start.time, 5 * gst.SECOND)
615
# check that end keyrame value has been properly adjusted so as not to
616
# change the shape of the curve
617
self.failUnlessEqual(interpolator.end.time, 15 * gst.SECOND)
618
self.failUnlessEqual(
619
round(interpolator.end.value, 6),
620
round((15.0 / 6) - (7.0 / 3), 6))
622
def testLoadTrackObjectRef(self):
626
self.formatter._context.track_objects["1"] = tag
627
element = Element("track-object-ref", id="1")
628
ret = self.formatter._loadTrackObjectRef(element)
629
self.failUnless(ret is tag)
631
def testLoadTrack(self):
632
# create fake document tree
633
element = Element("track")
634
stream_element = SubElement(element, "stream", id="1",
635
type="pitivi.stream.VideoStream", caps="video/x-raw-rgb")
637
track_objects_element = SubElement(element, "track-objects")
638
track_object = SubElement(track_objects_element, "track-object",
639
type="pitivi.timeline.track.SourceTrackObject",
640
start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
641
in_point=ts(5 * gst.SECOND),
642
media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
643
factory_ref = SubElement(track_object, "factory-ref", id="1")
644
stream_ref = SubElement(track_object, "stream-ref", id="1")
646
# insert fake factories and streams into current context
647
factory = VideoTestSourceFactory()
648
self.formatter._context.factories["1"] = factory
649
stream = VideoStream(gst.Caps("video/x-raw-rgb"))
650
self.formatter._context.streams["1"] = stream
652
# point gun at foot; pull trigger
653
track = self.formatter._loadTrack(element)
655
self.failUnlessEqual(len(track.track_objects), 1)
656
# FIXME: this is an hack
657
self.failUnlessEqual(str(track.stream), str(stream))
659
def testLoadTimelineObject(self):
660
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
661
source1 = VideoTestSourceFactory()
662
self.formatter._context.factories["1"] = source1
663
self.formatter._context.track_objects["1"] = SourceTrackObject(source1, video_stream)
665
element = Element("timeline-object")
666
factory_ref = SubElement(element, "factory-ref", id="1")
667
stream_ref = SubElement(element, "stream-ref", id="1")
668
track_object_refs = SubElement(element, "track-object-refs")
669
track_object_ref = SubElement(track_object_refs,
670
"track-object-ref", id="1")
673
self.formatter._loadTimelineObject(element)
675
self.failUnlessEqual(timeline_object.factory, source1)
676
self.failUnlessEqual(len(timeline_object.track_objects), 1)
678
def testLoadTimeline(self):
679
# we need a project for this to work
680
self.formatter.project = Project()
682
# create fake document tree
683
timeline_element = Element("timeline")
685
tracks_element = SubElement(timeline_element, "tracks")
686
track_element = SubElement(tracks_element, "track")
687
stream_element = SubElement(track_element, "stream", id="1",
688
type="pitivi.stream.VideoStream", caps="video/x-raw-rgb")
689
track_objects_element = SubElement(track_element, "track-objects")
690
track_object = SubElement(track_objects_element, "track-object",
691
type="pitivi.timeline.track.SourceTrackObject",
692
start=ts(1 * gst.SECOND), duration=ts(10 * gst.SECOND),
693
in_point=ts(5 * gst.SECOND),
694
media_duration=ts(15 * gst.SECOND), priority=ts(5), id="1")
695
factory_ref = SubElement(track_object, "factory-ref", id="1")
696
stream_ref = SubElement(track_object, "stream-ref", id="1")
697
timeline_objects_element = SubElement(timeline_element,
699
timeline_object_element = \
700
SubElement(timeline_objects_element, "timeline-object")
701
factory_ref = SubElement(timeline_object_element, "factory-ref", id="1")
702
stream_ref = SubElement(timeline_object_element, "stream-ref", id="1")
703
track_object_refs = SubElement(timeline_object_element, "track-object-refs")
704
track_object_ref = SubElement(track_object_refs,
705
"track-object-ref", id="1")
707
# insert fake streams and factories into context
708
factory = VideoTestSourceFactory()
709
self.formatter._context.factories["1"] = factory
710
stream = VideoStream(gst.Caps("video/x-raw-rgb"))
711
self.formatter._context.streams["1"] = stream
712
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
713
source1 = VideoTestSourceFactory()
714
self.formatter._context.factories["2"] = source1
715
self.formatter._context.track_objects["1"] = SourceTrackObject(source1, video_stream)
717
# point gun at foot; pull trigger
718
self.formatter._loadTimeline(timeline_element)
719
self.failUnlessEqual(len(self.formatter.project.timeline.tracks), 1)
721
def testLoadProject(self):
722
video_stream = VideoStream(gst.Caps("video/x-raw-yuv"))
723
audio_stream = AudioStream(gst.Caps("audio/x-raw-int"))
724
source1 = VideoTestSourceFactory()
726
self.formatter._saveSource(source1)
727
self.formatter._saveStream(video_stream)
729
track_object = SourceTrackObject(source1, video_stream,
730
start=10 * gst.SECOND, duration=20 * gst.SECOND,
731
in_point=5 * gst.SECOND, media_duration=15 * gst.SECOND,
734
track = Track(video_stream)
735
track.addTrackObject(track_object)
737
self.formatter._saveTrackObject(track_object)
739
timeline_object = TimelineObject(source1)
740
timeline_object.addTrackObject(track_object)
742
self.formatter._saveTimelineObject(timeline_object)
744
timeline = Timeline()
745
timeline.addTrack(track)
747
self.formatter._saveTimeline(timeline)
750
project.timeline = timeline
751
project.sources.addFactory(source1)
753
element = self.formatter._serializeProject(project)
755
self.failUnlessEqual(element.tag, "pitivi")
756
self.failIfEqual(element.find("factories"), None)
757
self.failIfEqual(element.find("timeline"), None)
760
f = file("/tmp/untitled.pptv", "w")
761
f.write(tostring(element))
764
## following test is disabled until I figure out a better way of
765
## testing the mapping system.
766
# def testDirectoryMapping(self):
767
# pa = "file:///if/you/have/this/file/you/are/on/crack.avi"
768
# pb = "file:///I/really/mean/it/you/crack.avi"
770
# self.formatter.addMapping(pa,pb)
771
# self.assertEquals(self.formatter.validateSourceURI(pa),