Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add marker to timeline when we can't find valid track #41

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
93 changes: 54 additions & 39 deletions src/otio_aaf_adapter/adapters/advanced_authoring_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -1255,33 +1255,21 @@ def _attach_markers(collection):
slot_id = metadata.get("AttachedSlotID")
track_number = metadata.get("AttachedPhysicalTrackNumber")
target_track = tracks_map.get((slot_id, track_number))
if target_track is None:
raise AAFAdapterError(
"Marker '{}' cannot be attached to an item. SlotID: '{}', "
"PhysicalTrackNumber: '{}'".format(
marker.name, slot_id, track_number
)
)

# remove marker from current parent track
current_track.markers.remove(marker)

# determine new item to attach the marker to
try:
target_item = _find_child_at_time(
target_track, marker.marked_range.start_time)

if target_item is None or not hasattr(target_item, 'markers'):
# Item found cannot have markers, for example Transition.
# See also `marker-over-transition.aaf` in test data.
#
# Leave markers on the track for now.
_transcribe_log(
'Skip target_item `{}` cannot have markers'.format(
target_item,
),
)
target_item = target_track
if target_track is None:
# This can happen if you export from Avid with "Use Selected Tracks"
# where markers will not point at the correct PhysicalTrackNumber!
_transcribe_log(
f"Cannot find target track for marker: {marker}. "
"Adding to timeline."
)
# Lets add it directly to the timeline "stack" the same way
# OTIO files generated by DaVinci Resolve does.
target_item = timeline.tracks

# transform marked range into new item range
marked_start_local = current_track.transformed_time(
Expand All @@ -1290,25 +1278,52 @@ def _attach_markers(collection):

marker.marked_range = otio.opentime.TimeRange(
start_time=marked_start_local,
duration=marker.marked_range.duration
duration=marker.marked_range.duration,
)

except otio.exceptions.CannotComputeAvailableRangeError as e:
# For audio media AAF file (marker-over-audio.aaf),
# this exception would be triggered in:
# `target_item = target_track.child_at_time()` with error
# message:
# "No available_range set on media reference on clip".
#
# Leave markers on the track for now.
_transcribe_log(
'Cannot compute availableRange from {} to {}: {}'.format(
marker,
target_track,
e,
),
)
target_item = target_track
else:
try:
target_item = _find_child_at_time(
target_track, marker.marked_range.start_time)

if target_item is None or not hasattr(target_item, 'markers'):
# Item found cannot have markers, for example Transition.
# See also `marker-over-transition.aaf` in test data.
#
# Leave markers on the track for now.
_transcribe_log(
'Skip target_item `{}` cannot have markers'.format(
target_item,
),
)
target_item = target_track

# transform marked range into new item range
marked_start_local = current_track.transformed_time(
marker.marked_range.start_time, target_item
)

marker.marked_range = otio.opentime.TimeRange(
start_time=marked_start_local,
duration=marker.marked_range.duration
)

except otio.exceptions.CannotComputeAvailableRangeError as e:
# For audio media AAF file (marker-over-audio.aaf),
# this exception would be triggered in:
# `target_item = target_track.child_at_time()` with error
# message:
# "No available_range set on media reference on clip".
#
# Leave markers on the track for now.
_transcribe_log(
'Cannot compute availableRange from {} to {}: {}'.format(
marker,
target_track,
e,
),
)
target_item = target_track

# attach marker to target item
target_item.markers.append(marker)
Expand Down
Binary file added tests/sample_data/bad_marker_track_from_avid.aaf
Binary file not shown.
28 changes: 28 additions & 0 deletions tests/test_aaf_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,10 @@
"avid_data_track_example.aaf"
)

BAD_TRACK_NUMBER_ON_MARKER_PATH = os.path.join(
SAMPLE_DATA_DIR,
"bad_marker_track_from_avid.aaf"
)

try:
lib_path = os.environ.get("OTIO_AAF_PYTHON_LIB")
Expand Down Expand Up @@ -1230,6 +1234,30 @@ def test_aaf_marker_over_audio_file(self):
self.assertEqual(label, expected_marker.get('label'))
self.assertEqual(start_time, expected_marker.get('start_time'))

def test_aaf_marker_with_bad_track(self):
"""
If you export from Avid with "Use Selected Tracks" selected, Avid
will rewrite the track numbers after omitted unselected tracks.
The markers, however, may not be updated by avid to reflect the
new track numbers!
This test confirms that we don't crash when reading such a file.
"""

timeline = None

try:
timeline = otio.adapters.read_from_file(
BAD_TRACK_NUMBER_ON_MARKER_PATH
)

except Exception as e:
print('[ERROR] Transcribing test sample data `{}` caused an exception: {}'.format( # noqa
os.path.basename(BAD_TRACK_NUMBER_ON_MARKER_PATH),
e)
)

self.assertIsNotNone(timeline)

def _verify_user_comments(self, aaf_metadata, expected_md):

self.assertTrue(aaf_metadata is not None)
Expand Down
Loading