11# Manual demands
22
3- Elements with ` : manual` flow control pads have two responsibilities:
3+ Elements with pads using manual flow control have two responsibilities:
44
55- ** Output pads** : produce exactly the amount of data requested in the
66 [ ` handle_demand/5 ` ] ( `c:Membrane.Element.WithOutputPads.handle_demand/5` )
@@ -12,9 +12,9 @@ Elements with `:manual` flow control pads have two responsibilities:
1212## Output pads and ` handle_demand `
1313
1414When downstream requests data, Membrane invokes ` handle_demand/5 ` on the
15- element whose output pad is connected to that downstream. The callback receives
16- the pad name, the demanded amount, and the demand unit. The element is expected
17- to produce and send that amount of data.
15+ element whose output pad with manual flow control is connected to that
16+ downstream. The callback receives the pad name, the demanded amount, and the
17+ demand unit. The element is expected to produce and send that amount of data.
1818
1919The unit in which ` demand_size ` is expressed is resolved as follows:
2020
@@ -79,9 +79,9 @@ downstream.
7979
8080## Input pads and the demand action
8181
82- To receive data on a ` :manual ` input pad, the element must issue a
83- [ ` :demand ` ] ( `t:Membrane.Element.Action.demand/0` ) action. The demand unit
84- is declared in the input pad spec.
82+ To receive data on an input pad with manual flow control , the element must
83+ issue a [ ` :demand ` ] ( `t:Membrane.Element.Action.demand/0` ) action. The demand
84+ unit is declared in the input pad spec.
8585
8686### ` :buffers ` and ` :bytes `
8787
@@ -141,6 +141,10 @@ timestamps as the original buffer.
141141
142142#### Declarative nature of demands
143143
144+ This section applies to ` :buffers ` and ` :bytes ` demand units. Timestamp demand
145+ units behave differently — see the [ timestamp section] ( #timestamp-demand-units )
146+ below.
147+
144148The ` :demand ` action ** overwrites** the current demand — it does not add to it.
145149Issuing ` demand: {:input, 5} ` sets the demand to 5 regardless of how much
146150demand was already pending.
@@ -179,37 +183,57 @@ Timestamp demand units let an element request buffers by specifying a
179183all buffers up to and including the first one whose timestamp meets or exceeds
180184the demanded value.
181185
182- Timestamp demand units are only applicable to ** input pads** . Output pads do
183- not support them. If an input pad uses a timestamp demand unit and the linked
184- upstream element's output pad does not specify a ` demand_unit ` , that element
185- will receive ` handle_demand/5 ` with demand expressed in ` :buffers ` .
186+ Timestamp demand units are only applicable to ** input pads with manual flow
187+ control ** . Output pads do not support them. If an input pad uses a timestamp
188+ demand unit and the linked upstream output pad does not specify a ` demand_unit ` ,
189+ that element will receive ` handle_demand/5 ` with demand expressed in ` :buffers ` .
186190
187191#### Available variants
188192
189- - ` {:timestamp, :pts} ` — demand is expressed in terms of each buffer's PTS.
190- - ` {:timestamp, :dts} ` — demand is expressed in terms of each buffer's DTS.
191- - ` :timestamp ` or ` {:timestamp, :dts_or_pts} ` — uses DTS if present on a
192- buffer, falls back to PTS.
193+ - ` {:timestamp, :pts} ` — uses each buffer's ` :pts ` field.
194+ - ` {:timestamp, :dts} ` — uses each buffer's ` :dts ` field.
195+ - ` :timestamp ` or ` {:timestamp, :dts_or_pts} ` — uses ` buffer.dts || buffer.pts ` .
196+
197+ #### Timestamp requirements
198+
199+ All buffers passing through an input pad with a timestamp demand unit must have
200+ their relevant timestamp field set to a non-` nil ` value — Membrane will raise
201+ an error if a buffer is missing its timestamp. Additionally, timestamps must be
202+ ** monotonically non-decreasing** ; non-monotonic timestamps will cause a warning.
203+
204+ For ` {:timestamp, :pts} ` , note that PTS can be non-monotonic in streams with
205+ B-frames (see the [ timestamps guide] ( timestamps.md ) ). Prefer
206+ ` {:timestamp, :dts} ` when DTS is available.
193207
194208#### How timestamp demands work
195209
196- The demand value is a ` t:Membrane.Time.t/0 ` duration (in nanoseconds),
197- interpreted relative to an ** offset** — the timestamp of the very first buffer
198- ever received on the pad. You never need to know the actual starting timestamp;
199- all demand values are expressed as durations from that origin.
210+ The demand value is a ` t:Membrane.Time.t/0 ` value. Use ` Membrane.Time `
211+ functions to construct it, for example ` Membrane.Time.seconds(1) ` .
212+
213+ Timestamps are interpreted relative to an ** offset** — the timestamp of the
214+ very first buffer ever received on the pad. This means you never need to know
215+ the absolute starting timestamp of the stream; you only work with durations
216+ from that origin.
217+
218+ For example, if the first buffer arrives with ` pts: Membrane.Time.seconds(100) `
219+ and you issue ` demand: {:input, Membrane.Time.seconds(1)} ` , Membrane will
220+ deliver buffers until it reaches the first one with
221+ ` pts >= Membrane.Time.seconds(100) + Membrane.Time.seconds(1) ` , i.e.
222+ ` pts >= Membrane.Time.seconds(101) ` .
200223
201224When you issue ` demand: {:input, t} ` , Membrane delivers all buffered buffers
202225whose timestamp (minus the offset) is strictly less than ` t ` , plus the first
203226buffer whose timestamp (minus the offset) equals or exceeds ` t ` . This means
204- that ** if you demand a value greater than the last received buffer's timestamp,
205- you are guaranteed to receive at least one new buffer** .
227+ that ** if you demand a value strictly greater than the last received buffer's
228+ timestamp (minus the offset), you are guaranteed to receive at least one new
229+ buffer** .
206230
207231#### Incrementing demands
208232
209233To receive a continuous stream in time-based chunks, always demand a value
210- larger than the timestamp of the last received buffer. Issuing a demand at or
211- below the last received timestamp will result in a warning and no buffers being
212- delivered.
234+ larger than the timestamp (minus the offset) of the last received buffer.
235+ Issuing a demand at or below that value will result in a warning and no buffers
236+ being delivered.
213237
214238#### Example: a sink consuming one second of data per second
215239
@@ -250,26 +274,19 @@ Each timer tick advances the demanded threshold by one second: `1s`, `2s`,
250274on ` :input ` , so each demand naturally covers the next one-second slice of the
251275stream.
252276
253- > #### Buffers must carry timestamps {: .warning}
254- >
255- > Every buffer must have its relevant timestamp field (` :pts ` or ` :dts ` ) set to
256- > a non-` nil ` value. Missing timestamps will cause incorrect behavior.
277+ ## Filters with manual flow control
257278
258- > #### Prefer DTS for encoded video {: .warning}
259- >
260- > PTS can be non-monotonic in streams with B-frames. Prefer
261- > ` {:timestamp, :dts} ` when DTS is available and monotonic, to avoid warnings.
262-
263- ## Filters: manual input and output
264-
265- A filter with both a manual input and a manual output is the most common case
266- for manual flow control. The canonical pattern is:
279+ The canonical pattern for a filter with both pads using manual flow control is:
267280
268281- ** ` handle_demand ` ** — propagate the demand upstream by returning a ` :demand `
269282 action on the input pad.
270283- ** ` handle_buffer ` ** — process the incoming buffer and forward it (possibly
271284 modified) downstream via a ` :buffer ` action.
272285
286+ The following example doubles each buffer's payload, so one input buffer
287+ produces one output buffer. To satisfy a demand of ` n ` output buffers, the
288+ filter demands ` n ` input buffers.
289+
273290``` elixir
274291defmodule MyFilter do
275292 use Membrane .Filter
@@ -285,21 +302,35 @@ defmodule MyFilter do
285302
286303 @impl true
287304 def handle_demand (:output , demand_size, :buffers , _ctx , state) do
288- {[demand: {:input , demand_size}], state}
305+ # Each output buffer requires 2 input buffers to produce
306+ {[demand: {:input , demand_size * 2 }], state}
289307 end
290308
291309 @impl true
292310 def handle_buffer (:input , buffer, _ctx , state) do
293- processed = %{buffer | payload: process (buffer.payload)}
294- {[buffer: {:output , processed}], state}
311+ # Combine every two input buffers into one output buffer
312+ buffers = [buffer | state.pending]
313+
314+ case buffers do
315+ [second, first] ->
316+ output = %Membrane .Buffer {payload: first.payload <> second.payload}
317+ {[buffer: {:output , output}], %{state | pending: []}}
318+
319+ [_one ] ->
320+ {[], %{state | pending: buffers}}
321+ end
295322 end
296323
297- defp process (payload), do: payload
324+ @impl true
325+ def handle_init (_ctx , _opts ) do
326+ {[], %{pending: []}}
327+ end
298328end
299329```
300330
301- > #### Do not use redemand in a filter's ` handle_demand ` {: .warning}
331+ > #### Do not use redemand in ` handle_demand ` of a pad with manual flow control that has a corresponding input pad {: .warning}
302332>
303- > Returning ` :redemand ` from ` handle_demand ` in a filter is illegal.
304- > ` handle_demand ` should propagate the demand to the input pad and return.
305- > Processing happens in ` handle_buffer ` when the data actually arrives.
333+ > Returning ` :redemand ` from ` handle_demand ` is illegal when the element also
334+ > has an input pad it relies on for data. ` handle_demand ` should propagate the
335+ > demand upstream and return. Processing happens in ` handle_buffer ` when the
336+ > data actually arrives.
0 commit comments