Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 12 additions & 8 deletions src/py-opentimelineio/opentimelineio/adapters/cmx_3600.py
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,16 @@ def parse(self, comment):
self.unhandled.append(stripped)


def _get_next_clip(start_index, track):
"""Get the next clip with a non-zero duration"""
# Iterate over the following clips and return the first "real" one
for clip in track[start_index + 1:]:
if clip.duration().value > 0:
return clip

return None


def _expand_transitions(timeline):
"""Convert clips with metadata/transition == 'D' into OTIO transitions."""

Expand All @@ -635,13 +645,10 @@ def _expand_transitions(timeline):
replace_or_insert_list = []
append_list = []
for track in tracks:
track_iter = iter(track)
# avid inserts an extra clip for the source
prev_prev = None
prev = None
clip = next(track_iter, None)
next_clip = next(track_iter, None)
while clip is not None:
for index, clip in enumerate(track):
transition_type = clip.metadata.get('cmx_3600', {}).get(
'transition',
'C'
Expand All @@ -651,8 +658,6 @@ def _expand_transitions(timeline):
# nothing to do, continue to the next iteration of the loop
prev_prev = prev
prev = clip
clip = next_clip
next_clip = next(track_iter, None)
continue

wipe_match = re.match(r'W(\d{3})', transition_type)
Expand Down Expand Up @@ -730,6 +735,7 @@ def _expand_transitions(timeline):

# expand the next_clip or contract this clip
keep_transition_clip = False
next_clip = _get_next_clip(index, track)
if next_clip:
if _transition_clips_continuous(clip, next_clip):
sr = next_clip.source_range
Expand Down Expand Up @@ -771,8 +777,6 @@ def _expand_transitions(timeline):
del(new_trx.metadata['previous_metadata'])

prev = clip
clip = next_clip
next_clip = next(track_iter, None)

for (insert, track, from_clip, to_transition) in replace_or_insert_list:
clip_index = track.index(from_clip)
Expand Down
12 changes: 12 additions & 0 deletions tests/sample_data/dissolve_test_4.edl
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
TITLE: TRANSITION_TEST_2
FCM: NON-DROP FRAME
001 ABC0000. V C 01:00:06:18 01:00:08:00 01:04:11:17 01:04:12:23
002 ABC0010. V C 01:00:06:15 01:00:08:18 01:04:12:23 01:04:15:02
003 ABC0010. V C 01:00:08:18 01:00:08:18 01:04:15:02 01:04:15:02
003 ABC0020. V D 035 01:00:06:22 01:00:10:07 01:04:15:02 01:04:18:11
* BLEND, DISSOLVE
004 ABC0020. V C 01:00:10:07 01:00:10:07 01:04:18:11 01:04:18:11
004 ABC0030. V D 064 01:00:06:10 01:00:09:22 01:04:18:11 01:04:21:23
* BLEND, DISSOLVE
005 ABC0040. V C 01:00:08:14 01:00:12:14 01:04:21:23 01:04:25:23
060 ABC0050. V C 01:00:12:06 01:00:17:21 01:04:25:23 01:04:31:14
21 changes: 21 additions & 0 deletions tests/test_cmx_3600_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
DISSOLVE_TEST = os.path.join(SAMPLE_DATA_DIR, "dissolve_test.edl")
DISSOLVE_TEST_2 = os.path.join(SAMPLE_DATA_DIR, "dissolve_test_2.edl")
DISSOLVE_TEST_3 = os.path.join(SAMPLE_DATA_DIR, "dissolve_test_3.edl")
DISSOLVE_TEST_4 = os.path.join(SAMPLE_DATA_DIR, "dissolve_test_4.edl")
GAP_TEST = os.path.join(SAMPLE_DATA_DIR, "gap_test.edl")
WIPE_TEST = os.path.join(SAMPLE_DATA_DIR, "wipe_test.edl")
TIMECODE_MISMATCH_TEST = os.path.join(SAMPLE_DATA_DIR, "timecode_mismatch.edl")
Expand Down Expand Up @@ -1047,6 +1048,26 @@ def test_transition_duration(self):

self.assertEqual(tl.tracks[0][2].duration().value, 26.0)

def test_three_part_transition(self):
"""
Test A->B->C Transition
"""
tl = otio.adapters.read_from_file(DISSOLVE_TEST_4)
self.assertEqual(len(tl.tracks[0]), 8)

self.assertIsInstance(tl.tracks[0][2], otio.schema.Transition)
self.assertIsInstance(tl.tracks[0][4], otio.schema.Transition)

self.assertEqual(tl.tracks[0][2].duration().value, 35.0)
self.assertEqual(tl.tracks[0][4].duration().value, 64.0)

self.assertEqual(tl.tracks[0][0].duration().value, 30.0)
self.assertEqual(tl.tracks[0][1].duration().value, 68.0)
self.assertEqual(tl.tracks[0][3].duration().value, 96.0)
self.assertEqual(tl.tracks[0][5].duration().value, 52.0)
self.assertEqual(tl.tracks[0][6].duration().value, 96.0)
self.assertEqual(tl.tracks[0][7].duration().value, 135.0)


if __name__ == "__main__":
unittest.main()