Skip to content

Commit 501aeee

Browse files
committed
Write some comments describing how the diamond detection mechanism works
1 parent 1d003ba commit 501aeee

File tree

2 files changed

+73
-2
lines changed

2 files changed

+73
-2
lines changed

lib/membrane/core/element/diamond_detection_controller.ex

+71
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,77 @@ defmodule Membrane.Core.Element.DiamondDetectionController do
2525
optional(:pad_ref) => Pad.ref()
2626
}
2727

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+
2899
@spec handle_diamond_detection_message(diamond_detection_message(), State.t()) :: State.t()
29100
def handle_diamond_detection_message(%{type: type} = message, state) do
30101
case type do

lib/membrane/core/element/diamond_detection_controller/diamond_logger.ex

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ defmodule Membrane.Core.Element.DiamondDetectionController.DiamondLogger do
3535
|> Enum.chunk_every(2, 1, :discard)
3636
|> Enum.map_join("\n", fn [%Vertex{} = from, %Vertex{} = to] ->
3737
"""
38-
From #{from.component_path} via output pad #{inspect(from.output_pad_ref)} \
39-
to #{to.component_path} via input pad #{inspect(to.input_pad_ref)}.
38+
* from #{from.component_path} via output pad #{inspect(from.output_pad_ref)} to \
39+
#{to.component_path} via input pad #{inspect(to.input_pad_ref)}
4040
"""
4141
end)
4242
end

0 commit comments

Comments
 (0)