ASC SOP and SAT support in Edit type

This commit is contained in:
2025-12-16 12:14:26 -08:00
parent 039bf8de6d
commit 8a825c8164
4 changed files with 48 additions and 9 deletions

View File

@@ -1,6 +1,7 @@
# pycmx # pycmx
# (c) 2018 Jamie Hardt # (c) 2018 Jamie Hardt
from pycmx.statements import StmtCdlSat, StmtCdlSop
from .transition import Transition from .transition import Transition
from .channel_map import ChannelMap from .channel_map import ChannelMap
# from .parse_cmx_statements import StmtEffectsName # from .parse_cmx_statements import StmtEffectsName
@@ -16,12 +17,17 @@ class Edit:
def __init__(self, edit_statement, audio_ext_statement, def __init__(self, edit_statement, audio_ext_statement,
clip_name_statement, source_file_statement, clip_name_statement, source_file_statement,
trans_name_statement=None): trans_name_statement=None, asc_sop_statement=None,
asc_sat_statement=None, frmc_statement=None):
self.edit_statement = edit_statement self.edit_statement = edit_statement
self.audio_ext = audio_ext_statement self.audio_ext = audio_ext_statement
self.clip_name_statement = clip_name_statement self.clip_name_statement = clip_name_statement
self.source_file_statement = source_file_statement self.source_file_statement = source_file_statement
self.trans_name_statement = trans_name_statement self.trans_name_statement = trans_name_statement
self.asc_sop_statement: Optional[StmtCdlSop] = asc_sop_statement
self.asc_sat_statement: Optional[StmtCdlSat] = asc_sat_statement
self.frmc_statement = frmc_statement
@property @property
def line_number(self) -> int: def line_number(self) -> int:
@@ -131,3 +137,17 @@ class Edit:
return None return None
else: else:
return self.clip_name_statement.name return self.clip_name_statement.name
@property
def asc_sop(self) -> Optional[StmtCdlSop]:
"""
Get ASC CDL Slope-Offset-Power transfer function for clip, if present
"""
return self.asc_sop_statement
@property
def asc_sat(self) -> Optional[StmtCdlSat]:
"""
Get ASC CDL saturation value for clip, if present
"""
return self.asc_sat_statement

View File

@@ -75,7 +75,9 @@ class Event:
audio_ext_statement=e1[1], audio_ext_statement=e1[1],
clip_name_statement=n1, clip_name_statement=n1,
source_file_statement=s1, source_file_statement=s1,
trans_name_statement=u1) trans_name_statement=u1,
asc_sop_statement=self._asc_sop_statement(),
asc_sat_statement=self._asc_sat_statement())
for (e1, n1, s1, u1) in zip(*the_zip)] for (e1, n1, s1, u1) in zip(*the_zip)]
@property @property
@@ -108,5 +110,10 @@ class Event:
elif type(s1) is StmtEvent: elif type(s1) is StmtEvent:
yield (s1, None) yield (s1, None)
def _asc_sop_statements(self) -> list[StmtCdlSop]: def _asc_sop_statement(self) -> Optional[StmtCdlSop]:
return [s for s in self.statements if type(s) == StmtCdlSop] return next((s for s in self.statements if type(s) == StmtCdlSop),
None)
def _asc_sat_statement(self) -> Optional[StmtCdlSat]:
return next((s for s in self.statements if type(s) == StmtCdlSat),
None)

View File

@@ -106,9 +106,11 @@ def _parse_remark(line, line_number) -> object:
elif line.startswith("ASC_SOP"): elif line.startswith("ASC_SOP"):
group_patterns: list[str] = re.findall(r'\((.*?)\)', line) group_patterns: list[str] = re.findall(r'\((.*?)\)', line)
v: list[list[str]] = [re.findall(r'-?\d+(\.\d+)?', a) for v1: list[list[tuple[str, str]]] = [re.findall(r'(-?\d+(\.\d+)?)', a) for
a in group_patterns] a in group_patterns]
v: list[list[str]] = [[a[0] for a in b] for b in v1]
if len(v) != 3 or any([len(a) != 3 for a in v]): if len(v) != 3 or any([len(a) != 3 for a in v]):
return StmtRemark(line, line_number) return StmtRemark(line, line_number)
@@ -120,13 +122,13 @@ def _parse_remark(line, line_number) -> object:
power_b=v[2][2], line_number=line_number) power_b=v[2][2], line_number=line_number)
elif line.startswith("ASC_SAT"): elif line.startswith("ASC_SAT"):
value = re.findall(r'-?\d+(\.\d+)?', line) value = re.findall(r'(-?\d+(\.\d+)?)', line)
if len(value) != 1: if len(value) != 1:
return StmtRemark(line, line_number) return StmtRemark(line, line_number)
else: else:
return StmtCdlSat(value=value[0], line_number=line_number) return StmtCdlSat(value=value[0][0], line_number=line_number)
elif line.startswith("FRMC"): elif line.startswith("FRMC"):
match = re.match( match = re.match(

View File

@@ -143,7 +143,16 @@ class TestParse(TestCase):
edl = pycmx.parse_cmx3600(f) edl = pycmx.parse_cmx3600(f)
for event in edl.events: for event in edl.events:
if event.number == 1: if event.number == 1:
... sop = event.edits[0].asc_sop_statement
self.assertIsNotNone(sop)
assert sop
self.assertEqual(sop.slope_r, "0.9405")
self.assertEqual(sop.offset_g, "-0.0276")
sat = event.edits[0].asc_sat_statement
self.assertIsNotNone(sat)
assert sat
self.assertEqual(sat.value, '0.9640')
def test_frmc(self): def test_frmc(self):
with open("tests/edls/cdl_frmc_example01.edl", "r") as f: with open("tests/edls/cdl_frmc_example01.edl", "r") as f:
@@ -151,3 +160,4 @@ class TestParse(TestCase):
for event in edl.events: for event in edl.events:
if event.number == 1: if event.number == 1:
... ...