docs: go over design docs and fix things
[platform/upstream/gstreamer.git] / docs / design / part-block.txt
1 Pad block
2 ---------
3
4 The purpose of blocking a pad is to be notified of downstream dataflow
5 and events. The notification can be used for
6
7  - (Re)connecting/disconnecting the pad.
8  - performing a seek 
9  - inspecting the data/events on the pad
10
11 The pad block is performed on a source pad (push based) or sink pad (pull based)
12 and will succeed when the following events happen on the pad:
13
14  - gst_pad_push()
15  - gst_pad_alloc_buffer()
16  - gst_pad_push_event() except for FLUSH_START and FLUSH_STOP events.
17  - gst_pad_pull_range () (on a sinkpad)
18
19
20 Flushing
21 ~~~~~~~~
22
23 The flushing event is used to clear any data out of the
24 downstream elements.
25
26 Generic case
27 ^^^^^^^^^^^^
28
29 Consider the following pipeline: 
30
31  .-----.      .-------.      .-------.
32  | src |      | elem1 |\/    | elem2 |
33  |    src -> sink    src -> sink    src ....
34  '-----'      '-------'/\    '-------'              
35
36 Where elem1.src is blocked. If the pad block is taken (the callback
37 is called or the sync block returned) no data is flowing in elem2.sink.
38 In this situation, the streaming thread is blocked on a GCond and is
39 waiting to be unblocked.
40
41 When sending a flushing seek upstream on elem1.src, the FLUSH_START event
42 will temporary unblock the streaming thread and make all pad functions that
43 triggers a block (_push/_alloc_buffer/_push_event/_pull_range) return
44 GST_FLOW_WRONG_STATE. This will then eventually pause the streaming thread
45 and release the STREAM_LOCK. 
46
47 Since no STREAM lock is taken after the pad block it is not needed to send
48 the FLUSH_START event further downstream.
49
50 The FLUSH_STOP will set the srcpad to non-flushing again and is dropped 
51 for the same reason. From then on, the new data after the flushing seek 
52 will be queued when the pad block is taken again.
53
54 Case where the stream is blocking downstream
55 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56
57 The example above is only valid if the elem1.src pad is really blocking
58 (callback called or sync block returned).
59
60 In the case where the stream is blocking further downstream (on elem2.src
61 for example, or on a blocking queue), extra care has to be taken.
62
63 Consider the following pipeline:
64
65  .-----.      .-------.      .-------.
66  | src |      | elem1 |\/    | elem2 |
67  |    src -> sink    src -> sink    src .... Blocking somewhere downstream
68  '-----'      '-------'/\    '-------'              
69
70 A pad block has been requested by the user on elem1.src , but since the stream
71 is blocking somewhere downstream, the callback is not called or the sync block
72 does not return.
73
74 In order for the block to happen, a FLUSH_START needs to be sent directly on
75 the downstream blocking element/pad so that it releases the stream lock, and it
76 gives a chance for the elem1.src pad to block.
77
78
79 Use cases
80 ~~~~~~~~~
81
82 Prerolling a partial pipeline
83 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84
85  .---------.      .---------.                .----------.
86  | filesrc |      | demuxer |     .-----.    | decoder1 |
87  |        src -> sink      src1 ->|queue|-> sink       src 
88  '---------'      |         |     '-----'    '----------' X
89                   |         |                .----------.
90                   |         |     .-----.    | decoder2 |
91                   |        src2 ->|queue|-> sink       src
92                   '---------'     '-----'    '----------' X
93
94
95 The purpose is to create the pipeline dynamically up to the
96 decoders but not yet connect them to a sink and without losing
97 any data.
98
99 To do this, the source pads of the decoders is blocked so that no
100 events or buffers can escape and we don't interrupt the stream.
101
102 When all of the dynamic pad are created (no-more-pads emited by the
103 branching point, ie, the demuxer or the queues filled) and the pads
104 are blocked (blocked callback received) the pipeline is completely
105 prerolled.
106
107 It should then be possible to perform the following actions on the
108 prerolled pipeline:
109
110 - query duration/position
111 - perform a flushing seek to preroll a new position
112 - connect other elements and unblock the blocked pads.
113
114
115 dynamically switching an element in a PLAYING pipeline
116 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
117
118
119   .----------.      .----------.      .----------.
120   | element1 |      | element2 |      | element3 |
121  ...        src -> sink       src -> sink       ...
122   '----------'      '----------'      '----------'
123                     .----------.
124                     | element4 |
125                    sink       src                  
126                     '----------'                     
127
128 The purpose is to replace element2 with element4 in the PLAYING 
129 pipeline. 
130
131   1) block element1 src pad. This can be done async.
132   2) wait for block to happen. at that point nothing is flowing between
133      element1 and element2 and nothing will flow until unblocked.
134   3) unlink element1 and element2
135   4) optional step: make sure data is flushed out of element2:
136      4a) pad event probe on element2 src
137      4b) send EOS to element2, this makes sure that element2 flushes
138          out the last bits of data it holds.
139      4c) wait for EOS to appear in the probe, drop the EOS.
140      4d) remove the EOS pad event probe.
141   5) unlink element2 and element3
142      5a) optionally element2 can now be set to NULL and/or removed from the
143          pipeline.
144   6) link element4 and element3
145   7) link element1 and element4 (FIXME, how about letting element4 know
146      about the currently running segment?, see issues.)
147   8) make sure element4 is in the same state as the rest of the elements. The
148      element should at least be PAUSED.
149   9) unblock element1 src
150
151 The same flow can be used to replace an element in a PAUSED pipeline. Only
152 special care has to be taken when performing step 2) which has to be done
153 async or it might deadlock. In the async callback one can then perform the
154 steps from 3). In a playing pipeline one can of course use the async block
155 as well, so that there is a generic method for both PAUSED and PLAYING.
156
157 The same flow works as well for any chain of multiple elements and might 
158 be implemented with a helper function in the future.