Skip to content

Commit b2790af

Browse files
authored
Tt1 to tt3/mspa 705 smpte (#43)
* Validate bindings for EBU-TT-1 documents by dynamically setting superseding class on document creation * MSPA-702: Check existence of Styling and Layout elements for EBU-TT-1 * MSPA-702: EBU-TT-1 document must contain a tt:region element * MSPA-702: body/dur attribute is not allowed in EBU-TT-1 * MSPA-702: Check that smpte timeBase is acceptable in EBU-TT-1 * Validate bindings for EBU-TT-1 documents by dynamically setting superseding class on document creation * MSPA-702: EBU-TT-1 document must contain a tt:region element * tt3 to ttd conversion (#41) MSPA-728 ebu-tt-3 to ebu-tt-d conversion * rebased and fixed ebuttd test files * extracting ebutt1object base into generic ebuttdocumentbase class * Add EBU-TT 1 to EBU-TT 3 conversion Does not handle time conversion. Sets `ebuttp:sequenceIdentifier` to the value of `tt/head/metadata/documentMetadata/documentIdentifier` if present, otherwise uses "TestConverter". Resets the `conformsToStandard` to say it is EBU-TT-3 conformant. Sets the `timeBase` to `media` whether you like it or not, but doesn't do any other conversions. * Address review comments Also allows for a setting that specifies whether or not to use `ebuttm:documentIdentifier` element value in the input as the `ebuttp:sequenceIdentifier` attribute value in the output. Adds a test for this. * Unit test EBUTT1 to EBUTT3 conversion * Fix validation error messages for unexpected attributes so it doesn't say they are missing. * Fix cloning of unknown element, and conversion of metadata * Make EBUTT1Document instantiatable by including required attributes and elements in the constructor * Add unit test cases for programmatical construction with smpte (skipped) and media timebase * Add unit test cases for from-document construction with smpte (skipped) and media timebase * Timedelta converter Creates a fixed offset SMPTE timecode converter that can return a timedelta equivalent for any valid SMPTE timecode value equal to or after the provided reference start point. Invalid timecodes throw errors. The timedelta returned is the difference between the input timecode and the reference timecode. * Reimplement ebu#516 See ebu#516 for further details. Enables an `ebuttm:documentStartOfProgramme` element to be included in a document without causing a crash. * Make a smpte timecode converter Make a FixedOffsetSMPTEtoTimedeltaConverter to convert SMPTE times based on the `ebuttm:documentStartOfProgramme` element if present, or assuming `00:00:00:00` otherwise. * pep8 tidying, where possible * test smpte time conversion * Unskip tests that now pass because they're implemented * add a test to check that using the `ebuttm:documentStartOfProgramme` as the basis for time conversion works. * pep8 tidying * Discard elements that end up with negative times Unit test for this also added. Tidy out some print statements that had made their way in there. * Add some documentation The docs in current state don't build properly because autodoc throws a "cannot import name `EBUTT1EBUTT3Converter`" exception. This is possibly a problem with circular `import` references, which should be resolved before we merge. This can be demonstrated by adding `from . import ebutt1_ebutt3` to `ebu_tt_live/bindings/converters/__init__.py` and running `python -m ebu_tt_live.bindings.converters` which shows a stack trace illustrating the issue. * Resolve circular import loop This was preventing documentation from building correctly. * Prune empty output elements * Add documentation and fix node code * Add EBUTT1 to EBUTT3 producer node config parameters * Add example config file for EBUTT1 to EBUTT3 conversion Also a manifest file for its input, using existing test XML file. * Add documentation * Correctly format code blocks RST uses double backticks, not like markdown's single ones! * Allow start of programme timecode to be manually overridden Sometimes we might know better than the document what start of programe timecode to use, so allow any value specified in the EBU-TT 1 document to be overridden. * Address @danielthepope's excellent review comments * Tidy .gitignore * Fix up documentation - backticks, mainly * Fix/improve code comments * Use snake case for method name instead of camelCase, to match PEP8 * Test that negative times raise errors * Fix dropped frame algorithm typo - it really should check frame values! Update tests to be more rigorous in checking that too, since they shouldn't have passed before.
1 parent 71ac319 commit b2790af

31 files changed

+996
-106
lines changed

.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,9 @@ ENV/
104104
out
105105
gen
106106

107+
# VSCode project files
108+
.vscode/
109+
107110
# Oxygen XML project files
108111
*.xpr
109112

@@ -134,4 +137,3 @@ export/
134137

135138
# Mac OS X files
136139
.DS_Store
137-

docs/source/configurator.rst

+5
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,11 @@ Node type dependent options for [nodeN] : ::
103103
└─clock
104104
└─type : ["local" (default) | "auto" | "clock"]
105105

106+
type="ebutt1-ebutt3-producer"
107+
├─sequence_identifier : sequence identifier, default "SequenceFromEBUTT1"
108+
├─use_doc_id_as_sequence_id : whether to use the ebuttm:documentIdentifier element contents as the output sequence identifier if it is present, default False
109+
└─smpte_start_of_programme : start of programme timecode override in case you know better than the document start of programme metadata, default None
110+
106111
type="ebuttd-encoder"
107112
├─media_time_zero : ["current" (default) | clock time at media time zero TODO: check format]
108113
├─default_namespace : ["false" (default) | "true"]

docs/source/conversion_from_ebutt.rst

+20-3
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,25 @@ have a sequence number. EBU-TT part 3 documents must have both.
2323

2424
In order to set the sequence identifier the converter can be
2525
configured with the desired value, or it can be set to extract the
26-
document identifier from the `ebuttm:documentIdentifier` element
26+
document identifier from the ``ebuttm:documentIdentifier`` element
2727
and use it, if it exists.
2828

29-
TODO: how to convert smpte timebase time expressions into clock or media
30-
timebase time expressions.
29+
If the EBU-TT part 1 document uses the ``smpte`` timebase, then all
30+
the time expressions must be converted to some other timebase.
31+
Currently they are all converted to ``media``, using a simple fixed
32+
offset based conversion strategy, encapsulated in the utility class
33+
:py:class:`ebu_tt_live.bindings.converters.timedelta_converter.FixedOffsetSMPTEtoTimedeltaConverter`.
34+
This currently looks for the metadata attribute
35+
``tt/head/metadata/ebuttm:documentMetadata/ebuttm:documentStartOfProgramme``
36+
and if it finds it, uses that as
37+
the zero point, otherwise it uses ``00:00:00:00``. This can be
38+
overridden by setting the ``smpte_start_of_programme`` parameter to the
39+
start of programme timecode to use instead.
40+
41+
The document's frame rate, frame rate multiplier and drop mode are taken into
42+
account when doing the conversion. This means that illegal frame
43+
values will cause a
44+
:py:class:`ebu_tt_live.errors.TimeFormatError` exception to be raised.
45+
46+
Elements with ``begin`` or ``end`` attributes that fall before the start of
47+
programme are discarded.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
converters package
2+
==================
3+
4+
:mod:`converters` Package
5+
-------------------------
6+
7+
.. currentmodule:: ebu_tt_live.bindings.converters
8+
9+
:mod:`ebutt3_ebuttd` Module
10+
---------------------------
11+
12+
.. automodule:: ebu_tt_live.bindings.converters.ebutt3_ebuttd
13+
:members:
14+
:private-members:
15+
:undoc-members:
16+
:show-inheritance:
17+
18+
:mod:`ebutt1_ebutt3` Module
19+
---------------------------
20+
21+
.. automodule:: ebu_tt_live.bindings.converters.ebutt1_ebutt3
22+
:members:
23+
:private-members:
24+
:undoc-members:
25+
:show-inheritance:
26+
27+
:mod:`timedelta_converter` Module
28+
---------------------------------
29+
30+
.. automodule:: ebu_tt_live.bindings.converters.timedelta_converter
31+
:members:
32+
:private-members:
33+
:undoc-members:
34+
:show-inheritance:

docs/source/ebu_tt_live.bindings.rst

+1
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,6 @@ Subpackages
7979
.. toctree::
8080

8181
ebu_tt_live.bindings.raw
82+
ebu_tt_live.bindings.converters
8283
ebu_tt_live.bindings.validation
8384

docs/source/ebu_tt_live.documents.rst

-9
Original file line numberDiff line numberDiff line change
@@ -44,15 +44,6 @@ documents Package
4444
:undoc-members:
4545
:show-inheritance:
4646

47-
:mod:`bindings_converters` Module
48-
---------------------------------
49-
50-
.. automodule:: ebu_tt_live.bindings.converters.ebutt3_ebuttd
51-
:members:
52-
:private-members:
53-
:undoc-members:
54-
:show-inheritance:
55-
5647
:mod:`document_converters` Module
5748
---------------------------------
5849

docs/source/ebu_tt_live.node.rst

+8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,14 @@ node Package
4141
:undoc-members:
4242
:show-inheritance:
4343

44+
:mod:`ebutt1_ebutt3_producer` Module
45+
------------------------------------
46+
47+
.. automodule:: ebu_tt_live.node.ebutt1_ebutt3_producer
48+
:members:
49+
:undoc-members:
50+
:show-inheritance:
51+
4452
:mod:`encoder` Module
4553
---------------------
4654

docs/source/scripts_and_their_functions.rst

+19
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,25 @@ Retiming Delay Node is primarily intended for delaying explicitly timed
128128
documents. Use ``ebu-run`` to start this script, for example ``ebu-run
129129
--admin.conf=ebu_tt_live/examples/config/retiming_delay.json.``
130130

131+
EBU-TT-1 Producer
132+
-----------------
133+
This script produces an EBU-TT Part 3 document from an EBU-TT Part 1 source.
134+
If SMPTE timecode is used (``ttp:timeBase="smpte"``) then the script looks for
135+
an ``ebuttm:documentStartOfProgramme`` element in the input document, and if
136+
present, maps that to the zero media time, and discards any elements that
137+
begin or end before that time. If that element is absent, then times are
138+
converted assuming that media time zero is SMPTE timecode ``00:00:00:00``.
139+
Alternatively both of those values can be overridden by specifying a
140+
start of programme timecode to use with the ``smpte_start_of_programme``
141+
configuration parameter.
142+
The timecode conversion currently assumes that
143+
the timecode is continuous.
144+
145+
The default output sequence identifier can be specified. There is also a
146+
parameter to allow the value of the input ``ebuttm:documentIdentifier`` element
147+
to be used as the output sequence identifier, if present, overriding the
148+
specified default.
149+
131150
EBU-TT-D Encoder
132151
----------------
133152
This script is an extension of simple consumer and is responsible for

ebu_tt_live/bindings/_ebuttdt.py

+19-14
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,25 @@ def _ConvertArguments_vx(cls, args, kw):
7070
# This means we are in XML parsing context. There should be a timeBase and a timing_attribute_name in the
7171
# context object.
7272
time_base = context['timeBase']
73-
timing_att_name = context['timing_attribute_name']
74-
if time_base not in cls._compatible_timebases[timing_att_name]:
75-
log.debug(ERR_SEMANTIC_VALIDATION_TIMING_TYPE.format(
76-
attr_name=timing_att_name,
77-
attr_type=cls,
78-
attr_value=args,
79-
time_base=time_base
80-
))
81-
raise pyxb.SimpleTypeValueError(ERR_SEMANTIC_VALIDATION_TIMING_TYPE.format(
82-
attr_name=timing_att_name,
83-
attr_type=cls,
84-
attr_value=args,
85-
time_base=time_base
86-
))
73+
# It is possible for a timing type to exist as the value of an element not an attribute,
74+
# in which case no timing_attribute_name is in the context; in that case don't attempt
75+
# to validate the data against a timebase. At the moment this only affects the
76+
# documentStartOfProgramme metadata element.
77+
if 'timing_attribute_name' in context:
78+
timing_att_name = context['timing_attribute_name']
79+
if time_base not in cls._compatible_timebases[timing_att_name]:
80+
log.debug(ERR_SEMANTIC_VALIDATION_TIMING_TYPE.format(
81+
attr_name=timing_att_name,
82+
attr_type=cls,
83+
attr_value=args,
84+
time_base=time_base
85+
))
86+
raise pyxb.SimpleTypeValueError(ERR_SEMANTIC_VALIDATION_TIMING_TYPE.format(
87+
attr_name=timing_att_name,
88+
attr_type=cls,
89+
attr_value=args,
90+
time_base=time_base
91+
))
8792
for item in args:
8893
if isinstance(item, timedelta):
8994
result.append(cls.from_timedelta(item))

0 commit comments

Comments
 (0)