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

Initial data track support #1362

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,8 @@ def _transcribe(item, parents, edit_rate, indent=0):
result.kind = otio.schema.TrackKind.Video
elif media_kind in ("SoundMasterTrack", "Sound"):
result.kind = otio.schema.TrackKind.Audio
elif media_kind == "Descriptive Metadata":
result.kind = otio.schema.TrackKind.Data
else:
Copy link
Contributor

@markreidvfx markreidvfx Jul 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Descriptive Metadata is not the media kind for the Data tracks your referring too. The media kind for the Data track is DataEssenceTrack.

# Timecode, Edgecode, others?
result.kind = ""
Expand Down Expand Up @@ -1444,6 +1446,28 @@ def _simplify(thing):
return thing


def _update_kind_of_data_tracks(thing):
if isinstance(thing, otio.schema.Timeline):
for track in thing.tracks:
track = _update_kind_of_data_tracks(track)
elif isinstance(thing, otio.schema.Stack):
for child in thing:
if isinstance(child, otio.schema.Track):
metadata = child.metadata.get("AAF", {})
media_kind = metadata.get("MediaKind", "")
if media_kind == "DataEssenceTrack":
child.kind = otio.schema.TrackKind.Data
elif isinstance(child, otio.schema.Stack):
child = _update_kind_of_data_tracks(child)
elif isinstance(thing, otio.schema.Track):
metadata = thing.metadata.get("AAF", {})
media_kind = metadata.get("MediaKind", "")
if media_kind == "DataEssenceTrack":
thing.kind = otio.schema.TrackKind.Data

return thing


def _has_effects(thing):
if isinstance(thing, otio.core.Item):
if len(thing.effects) > 0:
Expand Down Expand Up @@ -1595,6 +1619,9 @@ def read_from_file(
if simplify:
result = _simplify(result)

# Make sure that any AAF Data tracks are marked as such
result = _update_kind_of_data_tracks(result)

Copy link
Contributor

@markreidvfx markreidvfx Jul 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AAF's store markers on special slots called EventMobSlots. The markers on these slots reference the slot(s) they are actually on by their DescribedSlots property. The_attach_markers function already does this resolving, so _update_kind_of_data_tracks should not be needed.

# OTIO represents transitions a bit different than AAF, so
# we need to iterate over them and modify the items on either side.
# Note that we do this *after* simplifying, since the structure
Expand Down
Binary file not shown.
37 changes: 37 additions & 0 deletions contrib/opentimelineio_contrib/adapters/tests/test_aaf_adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,11 @@
"marker-over-audio.aaf"
)

DATA_TRACK_MARKERS_PATH = os.path.join(
SAMPLE_DATA_DIR,
"simple_data_track_marker_test.aaf"
)


def safe_str(maybe_str):
"""To help with testing between python 2 and 3, this function attempts to
Expand Down Expand Up @@ -1952,6 +1957,38 @@ def test_simplify_stack_track_clip(self):
for i in simple_tl.tracks:
self.assertNotEqual(type(i), otio.schema.Clip)

def test_aaf_data_track_markers(self):
"""Test that we can load a Data track and read the markers on it."""
expected_markers = [('Frame 1', 0.0, 1.0, 24.0, 'GREEN'),
('Frame 23', 22.0, 1.0, 24.0, 'RED'),
('Frame 56', 55.0, 1.0, 24.0, 'GREEN'),
('Frame 100', 99.0, 1.0, 24.0, 'RED')]
aaf_path = DATA_TRACK_MARKERS_PATH
timeline = otio.adapters.read_from_file(aaf_path, simplify=True)
self.assertIsNotNone(timeline)
self.assertEqual(type(timeline), otio.schema.Timeline)
self.assertEqual(len(timeline.tracks), 2)

data_track = timeline.tracks[1]
self.assertEqual(otio.schema.TrackKind.Data, data_track.kind)
self.assertEqual(1, len(data_track))

filler = data_track[0]
self.assertEqual(otio.schema.Gap, type(filler))
markers = filler.markers
self.assertEqual(4, len(markers))

markers = [
(
m.name,
m.marked_range.start_time.value,
m.marked_range.duration.value,
m.marked_range.start_time.rate,
m.color
) for m in filler.markers
]
self.assertEqual(expected_markers, markers)


if __name__ == '__main__':
unittest.main()
1 change: 1 addition & 0 deletions src/opentimelineio/track.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Track : public Composition
{
static auto constexpr video = "Video";
static auto constexpr audio = "Audio";
static auto constexpr data = "Data";
redroy marked this conversation as resolved.
Show resolved Hide resolved
};

enum NeighborGapPolicy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,8 @@ Should be subclassed (for example by :class:`.Track` and :class:`.Stack`), not u

py::class_<Track::Kind>(track_class, "Kind")
.def_property_readonly_static("Audio", [](py::object /* self */) { return Track::Kind::audio; })
.def_property_readonly_static("Video", [](py::object /* self */) { return Track::Kind::video; });
.def_property_readonly_static("Video", [](py::object /* self */) { return Track::Kind::video; })
.def_property_readonly_static("Data", [](py::object /* self */) { return Track::Kind::data; });


py::class_<Stack, Composition, managing_ptr<Stack>>(m, "Stack", py::dynamic_attr())
Expand Down