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

GeneratorReference implementation. #148

Merged
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
36 changes: 25 additions & 11 deletions contrib/adapters/extern_rv.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,29 @@ def _write_timeline(tl, to_session):
return result


def _create_media_reference(mr, to_session):
if hasattr(mr, "media_reference") and mr.media_reference:
if isinstance(mr.media_reference, otio.schema.ExternalReference):
to_session.setMedia([str(mr.media_reference.target_url)])
return True
elif isinstance(mr.media_reference, otio.schema.GeneratorReference):
if mr.media_reference.generator_kind == "SMPTEBars":
kind = "smptebars"
to_session.setMedia(
[
"{},start={},end={},fps={}.movieproc".format(
kind,
mr.available_range().start_time.value,
mr.available_range().end_time_inclusive().value,
mr.available_range().duration.rate
)
]
)
return True

return False


def _write_item(it, to_session):
src = to_session.newNode("Source", str(it.name) or "clip")

Expand Down Expand Up @@ -240,17 +263,8 @@ def _write_item(it, to_session):
)
src.setFPS(range_to_read.duration.rate)

# if the media reference is not missing
if (
hasattr(it, "media_reference") and
it.media_reference and
isinstance(
it.media_reference,
otio.schema.ExternalReference
)
):
src.setMedia([str(it.media_reference.target_url)])
else:
# if the media reference is missing
if not _create_media_reference(it, src):
kind = "smptebars"
if isinstance(it, otio.schema.Gap):
kind = "blank"
Expand Down
3 changes: 3 additions & 0 deletions opentimelineio/schema/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,3 +64,6 @@
from .serializable_collection import (
SerializableCollection
)
from .generator_reference import (
GeneratorReference
)
76 changes: 76 additions & 0 deletions opentimelineio/schema/generator_reference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"""
Generators are media references that _produce_ media rather than refer to it.
"""

from .. import (
core,
)


@core.register_type
class GeneratorReference(core.MediaReference):
"""
Base class for Generators.

Generators are media references that become "generators" in editorial
systems. For example, color bars or a solid color.
"""

_serializable_label = "GeneratorReference.1"
_name = "GeneratorReference"

def __init__(
self,
name=None,
generator_kind=None,
available_range=None,
parameters=None,
metadata=None
):
super(GeneratorReference, self).__init__(
name,
available_range,
metadata
)

if parameters is None:
parameters = {}
self.parameters = parameters
self.generator_kind = generator_kind

parameters = core.serializable_field(
"parameters",
dict,
doc="Dictionary of parameters for generator."
)
generator_kind = core.serializable_field(
"generator_kind",
required_type=type(""),
# @TODO: need to clarify if this also has an enum of supported types
# / generic
doc="Kind of generator reference, as defined by the "
"schema.generator_reference.GeneratorReferenceTypes enum."
)

def __str__(self):
return 'GeneratorReference("{}", "{}", {}, {})'.format(
self.name,
self.generator_kind,
self.parameters,
self.metadata
)

def __repr__(self):
return (
'otio.schema.GeneratorReference('
'name={}, '
'generator_kind={}, '
'parameters={}, '
'metadata={}'
')'.format(
repr(self.name),
repr(self.generator_kind),
repr(self.parameters),
repr(self.metadata),
)
)
8 changes: 8 additions & 0 deletions tests/baselines/empty_generator_reference.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"OTIO_SCHEMA" : "GeneratorReference.1",
"available_range" : null,
"generator_kind" : null,
"metadata" : {},
"parameters" : {},
"name" : null
}
67 changes: 67 additions & 0 deletions tests/sample_data/generator_reference_test.otio
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
{
"OTIO_SCHEMA": "Timeline.1",
"metadata": {},
"name": "transition_test",
"tracks": {
"OTIO_SCHEMA": "Stack.1",
"children": [
{
"OTIO_SCHEMA": "Sequence.1",
"children": [
{
"OTIO_SCHEMA": "Clip.1",
"effects": [],
"markers": [],
"media_reference": {
"OTIO_SCHEMA" : "GeneratorReference.1",
"available_range" : {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 50
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0.0
}
},
"generator_kind" : "SMPTEBars",
"metadata" : {},
"parameters" : {},
"name" : "bars"
},
"metadata": {},
"name": "C",
"source_range": {
"OTIO_SCHEMA": "TimeRange.1",
"duration": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 50
},
"start_time": {
"OTIO_SCHEMA": "RationalTime.1",
"rate": 24,
"value": 0.0
}
}

}
],
"effects": [],
"kind": "Video",
"markers": [],
"metadata": {},
"name": "Sequence1",
"source_range": null
}
],
"effects": [],
"markers": [],
"metadata": {},
"name": "tracks",
"source_range": null
}
}
83 changes: 83 additions & 0 deletions tests/test_generator_reference.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
""" Generator Reference class test harness. """

import unittest
import os

import opentimelineio as otio

SAMPLE_DATA_DIR = os.path.join(os.path.dirname(__file__), "sample_data")
GEN_REF_TEST = os.path.join(SAMPLE_DATA_DIR, "generator_reference_test.otio")


class GeneratorReferenceTests(unittest.TestCase):
def setUp(self):
self.gen = otio.schema.GeneratorReference(
name="SMPTEBars",
generator_kind="SMPTEBars",
available_range=otio.opentime.TimeRange(
otio.opentime.RationalTime(0, 24),
otio.opentime.RationalTime(100, 24),
),
parameters={
"test_param": 5.0,
},
metadata={
"foo": "bar"
}
)

def test_constructor(self):
self.assertEqual(self.gen.generator_kind, "SMPTEBars")
self.assertEqual(self.gen.name, "SMPTEBars")
self.assertEqual(self.gen.parameters, {"test_param": 5.0})
self.assertEqual(self.gen.metadata, {"foo": "bar"})
self.assertEqual(
self.gen.available_range,
otio.opentime.TimeRange(
otio.opentime.RationalTime(0, 24),
otio.opentime.RationalTime(100, 24),
)
)

def test_serialize(self):
encoded = otio.adapters.otio_json.write_to_string(self.gen)
decoded = otio.adapters.otio_json.read_from_string(encoded)
self.assertEqual(self.gen, decoded)

def test_read_file(self):
self.assertTrue(os.path.exists(GEN_REF_TEST))
decoded = otio.adapters.otio_json.read_from_file(GEN_REF_TEST)
self.assertEqual(
decoded.tracks[0][0].media_reference.generator_kind, "SMPTEBars"
)

def test_stringify(self):
self.assertMultiLineEqual(
str(self.gen),
"GeneratorReference("
'"{}", '
'"{}", '
'{}, '
"{}"
")".format(
str(self.gen.name),
str(self.gen.generator_kind),
str(self.gen.parameters),
str(self.gen.metadata),
)
)

self.assertMultiLineEqual(
repr(self.gen),
"otio.schema.GeneratorReference("
"name={}, "
"generator_kind={}, "
"parameters={}, "
"metadata={}"
")".format(
repr(self.gen.name),
repr(self.gen.generator_kind),
repr(self.gen.parameters),
repr(self.gen.metadata),
)
)
4 changes: 4 additions & 0 deletions tests/test_json_backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ def test_serializable_collection(self):
)
self.check_against_baseline(tr, "empty_serializable_collection")

def test_generator_reference(self):
trx = otio.schema.GeneratorReference()
self.check_against_baseline(trx, "empty_generator_reference")


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