Skip to content

Commit 383da22

Browse files
committed
*.rshift & *.rrshift to enhanced labeling
* added `_shift_labels` helper function * added `add_labels` to `Filter` & `Chain` * rewrote `Graph.add_labels` * `Graph.add_label` to accept bracketed label
1 parent 80ca5e0 commit 383da22

1 file changed

Lines changed: 127 additions & 60 deletions

File tree

src/ffmpegio/filtergraph.py

Lines changed: 127 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,17 @@ def as_filtergraph_object(filter_specs):
217217
return as_filtergraph(filter_specs)
218218

219219

220+
def _shift_labels(obj, label_type, args):
221+
if _is_label(args):
222+
return obj.add_labels(label_type, args)
223+
224+
if all(_is_label(arg) for arg in args):
225+
return obj.add_labels(label_type, [arg for arg in args])
226+
227+
assert len(args) == 2 and _is_label(args[0])
228+
return obj.add_labels(label_type, {args[1]: args[0]})
229+
230+
220231
###################################################################################################
221232

222233
# FILTER TOOLS
@@ -613,26 +624,25 @@ def _channelsplit():
613624
else inc()
614625
)
615626

616-
def add_labels(self, input_labels=None, output_labels=None):
627+
def add_labels(self, pad_type, labels):
617628
"""turn into filtergraph and add labels
618629
619-
:param input_labels: input pad labels keyed by pad index, defaults to None
620-
:type input_labels: dict(int:str), optional
621-
:param output_labels: output pad labels keyed by pad index, defaults to None
622-
:type output_labels: dict(int:str), optional
630+
:param pad_type: filter pad type
631+
:type pad_type: 'dst'|'src'
632+
:param labels: pad label(s) and optionally pad id
633+
:type labels: str|seq(str)|dict(int:str), optional
623634
"""
624635

625636
fg = Graph([[self]])
626-
if input_labels is not None:
627-
for pad, label in input_labels.items():
628-
if label[0] == "[" and label[-1] == "]":
629-
label = label[1:-1]
630-
fg.add_label(label, dst=(0, 0, pad))
631-
if output_labels is not None:
632-
for pad, label in output_labels.items():
633-
if label[0] == "[" and label[-1] == "]":
634-
label = label[1:-1]
635-
fg.add_label(label, src=(0, 0, pad))
637+
if labels is not None:
638+
if isinstance(labels, str):
639+
fg.add_label(labels, **{pad_type: (0, 0, 0)})
640+
elif isinstance(labels, dict):
641+
for pad, label in labels.items():
642+
fg.add_label(label, **{pad_type: fg._resolve_index(pad)})
643+
else:
644+
for pad, label in enumerate(labels):
645+
fg.add_label(label, **{pad_type: (0, 0, pad)})
636646
return fg
637647

638648
def apply(self, options, filter_id=None):
@@ -755,6 +765,14 @@ def __ror__(self, other):
755765
def __rshift__(self, other):
756766
"""self >> other | self >> (index, other)"""
757767

768+
# try labeling first
769+
try:
770+
return _shift_labels(self, "src", other)
771+
except FFmpegioError:
772+
raise
773+
except:
774+
pass
775+
758776
# resolve the index
759777
if type(other) == tuple:
760778
if len(other) > 2:
@@ -768,13 +786,6 @@ def __rshift__(self, other):
768786

769787
index = self._resolve_index(False, index)
770788

771-
# if label
772-
if _is_label(other):
773-
if other_index is None:
774-
return self.add_labels(output_labels={index: other})
775-
else:
776-
raise FiltergraphInvalidIndex("index cannot be assigned to a label")
777-
778789
# if other is Filter object, do add operation
779790
try:
780791
other = as_filtergraph_object(other)
@@ -798,6 +809,14 @@ def __rshift__(self, other):
798809
def __rrshift__(self, other):
799810
"""other >> self, (other, index) >> self : attach input label or filter"""
800811

812+
# try to label first
813+
try:
814+
return _shift_labels(self, "dst", other)
815+
except FFmpegioError:
816+
raise
817+
except:
818+
pass
819+
801820
# resolve the index
802821
if type(other) == tuple:
803822
if len(other) > 2:
@@ -814,7 +833,7 @@ def __rrshift__(self, other):
814833
# if label
815834
if _is_label(other):
816835
if other_index is None:
817-
return self.add_labels(input_labels={index: other})
836+
return self.add_labels("dst", {index: other})
818837
else:
819838
raise FiltergraphInvalidIndex("index cannot be assigned to a label")
820839

@@ -980,6 +999,15 @@ def __ror__(self, other):
980999
return Graph([other, self]) if n and m else self if n else other
9811000

9821001
def __rshift__(self, other):
1002+
"""self >> other | self >> (index, other) | self >> (index, other_index, other)"""
1003+
1004+
# try to label first
1005+
try:
1006+
return _shift_labels(self, "src", other)
1007+
except FFmpegioError:
1008+
raise
1009+
except:
1010+
pass
9831011

9841012
if type(other) == tuple:
9851013
if len(other) > 2:
@@ -1010,15 +1038,6 @@ def __rshift__(self, other):
10101038

10111039
index = self._resolve_index(False, index)
10121040

1013-
# if label
1014-
if _is_label(other):
1015-
if other_index is None:
1016-
fg = Graph([self])
1017-
fg.add_label(other[1:-1], src=(0, *index))
1018-
return fg
1019-
else:
1020-
raise FiltergraphInvalidIndex("index cannot be assigned to a label")
1021-
10221041
# if other is Filter object, do add operation
10231042
try:
10241043
other = as_filtergraph_object(other)
@@ -1041,6 +1060,14 @@ def __rshift__(self, other):
10411060
def __rrshift__(self, other):
10421061
"""other >> self, (other, index) >> self : attach input label or filter"""
10431062

1063+
# try to label first
1064+
try:
1065+
return _shift_labels(self, "dst", other)
1066+
except FFmpegioError:
1067+
raise
1068+
except:
1069+
pass
1070+
10441071
# resolve the index
10451072
if type(other) == tuple:
10461073
if len(other) > 2:
@@ -1065,15 +1092,6 @@ def __rrshift__(self, other):
10651092

10661093
index = self._resolve_index(True, index)
10671094

1068-
# if label
1069-
if _is_label(other):
1070-
if other_index is None:
1071-
fg = Graph([self])
1072-
fg.add_label(other[1:-1], dst=(0, *index))
1073-
return fg
1074-
else:
1075-
raise FiltergraphInvalidIndex("index cannot be assigned to a label")
1076-
10771095
# if other is Filter object, do add operation
10781096
try:
10791097
other = as_filtergraph_object(other)
@@ -1230,6 +1248,30 @@ def validate_output_index(self, pos, pad_pos):
12301248
if pad_pos < 0 or pad_pos >= (n - 1 if pos < len(self.data) - 1 else n):
12311249
raise Chain.Error(f"invliad output pad position #{pos} for {self[pos]}.")
12321250

1251+
def add_labels(self, pad_type, labels):
1252+
"""turn into filtergraph and add labels
1253+
1254+
:param input_labels: input pad labels keyed by pad index, defaults to None
1255+
:type input_labels: dict(int:str), optional
1256+
:param output_labels: output pad labels keyed by pad index, defaults to None
1257+
:type output_labels: dict(int:str), optional
1258+
"""
1259+
1260+
fg = Graph([self])
1261+
is_input = pad_type == "dst"
1262+
if isinstance(labels, str):
1263+
pad = fg._resolve_index(is_input, None)
1264+
fg.add_label(labels, **{pad_type: pad})
1265+
elif isinstance(labels, dict):
1266+
for pad, label in labels.items():
1267+
pad = fg._resolve_index(is_input, pad)
1268+
fg.add_label(label, **{pad_type: pad})
1269+
else:
1270+
for pad, label in enumerate(labels):
1271+
pad = fg._resolve_index(is_input, pad)
1272+
fg.add_label(label, **{pad_type: pad})
1273+
return fg
1274+
12331275

12341276
####################################################################################
12351277

@@ -1495,6 +1537,14 @@ def __ror__(self, other):
14951537
def __rshift__(self, other):
14961538
"""self >> other | self >> (index, other) | self >> (index, other_index, other)"""
14971539

1540+
# try to label first
1541+
try:
1542+
return _shift_labels(self, "src", other)
1543+
except FFmpegioError:
1544+
raise
1545+
except:
1546+
pass
1547+
14981548
# resolve the index
14991549
if type(other) == tuple:
15001550
if len(other) > 2:
@@ -1519,15 +1569,6 @@ def __rshift__(self, other):
15191569

15201570
index = self._resolve_index(False, index)
15211571

1522-
# if label
1523-
if _is_label(other):
1524-
if other_index is None:
1525-
fg = Graph(self) # copy
1526-
fg.add_label(other[1:-1], src=index)
1527-
return fg
1528-
else:
1529-
raise FiltergraphInvalidIndex("index cannot be assigned to a label")
1530-
15311572
# if other is Filter object, do add operation
15321573
try:
15331574
other = as_filtergraph_object(other)
@@ -1539,6 +1580,14 @@ def __rshift__(self, other):
15391580
def __rrshift__(self, other):
15401581
"""other >> self, (other, index) >> self, (other, other_index, index) >> self : attach input label or filter"""
15411582

1583+
# try to label first
1584+
try:
1585+
return _shift_labels(self, "dst", other)
1586+
except FFmpegioError:
1587+
raise
1588+
except:
1589+
pass
1590+
15421591
# resolve the index
15431592
if type(other) == tuple:
15441593
if len(other) > 2:
@@ -1563,15 +1612,6 @@ def __rrshift__(self, other):
15631612

15641613
index = self._resolve_index(True, index)
15651614

1566-
# if label
1567-
if _is_label(other):
1568-
if other_index is None:
1569-
fg = Graph(self) # copy
1570-
fg.add_label(other[1:-1], dst=index)
1571-
return fg
1572-
else:
1573-
raise FiltergraphInvalidIndex("index cannot be assigned to a label")
1574-
15751615
# if other is Filter object, do add operation
15761616
try:
15771617
other = as_filtergraph(other)
@@ -1952,7 +1992,7 @@ def link(self, dst, src, label=None, preserve_src_label=False, force=False):
19521992
def add_label(self, label, dst=None, src=None, force=None):
19531993
"""label a filter pad
19541994
1955-
:param label: name of the new label
1995+
:param label: name of the new label. Square brackets are optional.
19561996
:type label: str
19571997
:param dst: input filter pad index or a sequence of pads, defaults to None
19581998
:type dst: tuple(int,int,int) | seq(tuple(int,int,int)), optional
@@ -1972,6 +2012,9 @@ def add_label(self, label, dst=None, src=None, force=None):
19722012
19732013
"""
19742014

2015+
if label[0] == "[" and label[-1] == "]":
2016+
label = label[1:-1]
2017+
19752018
GraphLinks.validate_label(
19762019
label, named_only=True, no_stream_spec=src is not None
19772020
)
@@ -2428,6 +2471,30 @@ def rattach(self, left, right_on=None, left_on=None):
24282471
right_on = self._resolve_index(True, right_on)
24292472
return left.connect(self, [left_on], [right_on], chain_siso=True)
24302473

2474+
def add_labels(self, pad_type, labels):
2475+
"""turn into filtergraph and add labels
2476+
2477+
:param input_labels: input pad labels keyed by pad index, defaults to None
2478+
:type input_labels: dict(int:str), optional
2479+
:param output_labels: output pad labels keyed by pad index, defaults to None
2480+
:type output_labels: dict(int:str), optional
2481+
"""
2482+
2483+
fg = Graph(self)
2484+
is_input = pad_type == "dst"
2485+
if isinstance(labels, str):
2486+
pad = fg._resolve_index(is_input, None)
2487+
fg.add_label(labels, **{pad_type: pad})
2488+
elif isinstance(labels, dict):
2489+
for pad, label in labels.items():
2490+
pad = fg._resolve_index(is_input, None)
2491+
fg.add_label(label, **{pad_type: pad})
2492+
else:
2493+
for label in labels:
2494+
pad = fg._resolve_index(is_input, None)
2495+
fg.add_label(label, **{pad_type: pad})
2496+
return fg
2497+
24312498
@contextmanager
24322499
def as_script_file(self):
24332500
"""return script file containing the filtergraph description

0 commit comments

Comments
 (0)