@@ -25,6 +25,77 @@ defmodule Membrane.Core.Element.DiamondDetectionController do
25
25
optional ( :pad_ref ) => Pad . ref ( )
26
26
}
27
27
28
+ # DESCRIPTION OF THE ALGORITHM OF FINDING DIAMONDS IN THE PIPELINE
29
+
30
+ # Definitions:
31
+
32
+ # diamond - directed graph, that has at least two distinct elements (sink and source) and
33
+ # has two vertex-disjoint paths from the source to the sink.
34
+
35
+ # This algotithm takes the directed graph made by all Elements within single Pipeline and
36
+ # finds some diamond-subgraphs having all the edges (links) working in the :pull mode,
37
+ # it means in :manual flow control or in :auto flow controll if the effective flow control
38
+ # is set to :pull.
39
+
40
+ # These diamonds can be dangerous when used with pull flow control, e.g. let's consider
41
+ # a pipeline, that contains:
42
+ # * MP4 demuxer that has two output pads
43
+ # * MKV muxer that is linked to both of them
44
+ # and let's assume, that MP4 container that is consumed by MP4 demuxer is unbalanced.
45
+ # If MKV muxer has pads working in pull mode, then demand on one pad will be satisified,
46
+ # but on the another won't, because the MP4 container is unbalanced. Then, if MP4 demuxer
47
+ # has pads in auto flow control and its effective flow control is set to :pull, it won't
48
+ # demand on the input, because one of the pads output with :auto flow control doesn't
49
+ # have positive demand, so the whole pipeline will get stuck and won't process more data.
50
+
51
+ # The algorithms is made of two phases: (1) triggering and (2) proper searching.
52
+
53
+ # (1) Triggering
54
+
55
+ # Let's notice, that:
56
+ # * new diamond can be created only after linking new spec
57
+ # * if the new spec caused some new diamond to occur, this diamond will contain some of
58
+ # the links spawned in this spec
59
+
60
+ # If the diamond contains a link, it must also contain an element which output pad takes
61
+ # is the part of this link.
62
+
63
+ # After spec status is set to :done, parent component that returned the spec will trigger
64
+ # all elements, which output pads has been linked in this spec. Reference of the trigger
65
+ # is always set to the spec reference.
66
+
67
+ # If the element is triggered with a specific reference for the first time, it does two
68
+ # things:
69
+ # * the element forwards the trigger with the same reference via all input pads working
70
+ # in the pull mode
71
+ # * if the element has at least two output pads working in the pull mode, it postpones
72
+ # a proper searching that will be spawned from itself. Time between postponing and the
73
+ # proper searching is one second. If in this time an element will be triggered once
74
+ # again with a different reference, it won't cause another postponing a proper
75
+ # searching, this means that at the time there is at most one proper searching
76
+ # postponed in the single element
77
+
78
+ # (2) Proper searching:
79
+
80
+ # Proper searching is started only in the elements that have at lest two output pads
81
+ # working in the pull mode. When an elements starts proper searching, it assings
82
+ # a new reference to it, different from the reference of the related trigger.
83
+
84
+ # When a proper searching enters the element (no matter if it is the element that has
85
+ # hust started the proper searching, or maybe it was forwarded to it via link):
86
+ # * if the element sees the proper searching reference for the first time, then:
87
+ # - it forwards proper searching via all output pads working in the pull mode
88
+ # - when the proper searching is forwarded, it remembers the path in grapth through
89
+ # the elments that is has already passed
90
+ # * if the element has already seen the reference of proper searching, but there is
91
+ # a repeated element on the path, that proper searching traversed to this element,
92
+ # the element does nothing
93
+ # * if the element has already seen the reference of proper searching and the traversed
94
+ # path doesn't contain any repeated elements, it means that the current traversed path
95
+ # and the path that the proper searching traversed when it entered the element
96
+ # previous time together make a diamond. Then, the element logs the found diamond
97
+ # and doesn't forward proper searching fruther
98
+
28
99
@ spec handle_diamond_detection_message ( diamond_detection_message ( ) , State . t ( ) ) :: State . t ( )
29
100
def handle_diamond_detection_message ( % { type: type } = message , state ) do
30
101
case type do
0 commit comments