mirror of https://github.com/mpv-player/mpv
filter: extend documentation comments
Add more explanations, and also fix some blatantly wrong things.
This commit is contained in:
parent
251f4e5d77
commit
3ffa70e2da
|
@ -36,6 +36,7 @@ bool mp_pin_in_needs_data(struct mp_pin *p);
|
||||||
// (does not normally happen, as long as mp_pin_in_needs_data() returned true).
|
// (does not normally happen, as long as mp_pin_in_needs_data() returned true).
|
||||||
// The callee owns the reference to the frame data, even on failure.
|
// The callee owns the reference to the frame data, even on failure.
|
||||||
// Writing a MP_FRAME_NONE has no effect (and returns false).
|
// Writing a MP_FRAME_NONE has no effect (and returns false).
|
||||||
|
// If you did not call mp_pin_in_needs_data() before this, it's likely a bug.
|
||||||
bool mp_pin_in_write(struct mp_pin *p, struct mp_frame frame);
|
bool mp_pin_in_write(struct mp_pin *p, struct mp_frame frame);
|
||||||
|
|
||||||
// True if a frame is actually available for reading right now, and
|
// True if a frame is actually available for reading right now, and
|
||||||
|
@ -119,8 +120,8 @@ bool mp_pin_can_transfer_data(struct mp_pin *dst, struct mp_pin *src);
|
||||||
// mp_pin_can_transfer_data(). Returns whether a transfer happened.
|
// mp_pin_can_transfer_data(). Returns whether a transfer happened.
|
||||||
bool mp_pin_transfer_data(struct mp_pin *dst, struct mp_pin *src);
|
bool mp_pin_transfer_data(struct mp_pin *dst, struct mp_pin *src);
|
||||||
|
|
||||||
// Connect src and dst, for automatic data flow. pin a will reflect the request
|
// Connect src and dst, for automatic data flow. Pin src will reflect the request
|
||||||
// state of pin src, and accept and pass down frames to dst when appropriate.
|
// state of pin dst, and accept and pass down frames to dst when appropriate.
|
||||||
// src must be MP_PIN_OUT, dst must be MP_PIN_IN.
|
// src must be MP_PIN_OUT, dst must be MP_PIN_IN.
|
||||||
// Previous connections are always removed. If the pins were already connected,
|
// Previous connections are always removed. If the pins were already connected,
|
||||||
// no action is taken.
|
// no action is taken.
|
||||||
|
@ -144,8 +145,7 @@ void mp_pin_set_manual_connection_for(struct mp_pin *p, struct mp_filter *f);
|
||||||
// Return the manual connection for this pin, or NULL if none.
|
// Return the manual connection for this pin, or NULL if none.
|
||||||
struct mp_filter *mp_pin_get_manual_connection(struct mp_pin *p);
|
struct mp_filter *mp_pin_get_manual_connection(struct mp_pin *p);
|
||||||
|
|
||||||
// If not connected, this will produce EOF for MP_PIN_IN, and never request
|
// Disconnect the pin, possibly breaking connections.
|
||||||
// data for MP_PIN_OUT.
|
|
||||||
void mp_pin_disconnect(struct mp_pin *p);
|
void mp_pin_disconnect(struct mp_pin *p);
|
||||||
|
|
||||||
// Return whether a connection was set on this pin. Note that this is not
|
// Return whether a connection was set on this pin. Note that this is not
|
||||||
|
@ -173,10 +173,42 @@ const char *mp_pin_get_name(struct mp_pin *p);
|
||||||
* things that require readahead). But in general, a filter should not request
|
* things that require readahead). But in general, a filter should not request
|
||||||
* input before output is needed.
|
* input before output is needed.
|
||||||
*
|
*
|
||||||
* The general goal is to reduce the amount of data buffered. If buffering is
|
* The general goal is to reduce the amount of data buffered. This is why
|
||||||
|
* mp_pins buffer at most 1 frame, and the API is designed such that queued
|
||||||
|
* data in pins will be immediately passed to the next filter. If buffering is
|
||||||
* actually desired, explicit filters for buffering have to be introduced into
|
* actually desired, explicit filters for buffering have to be introduced into
|
||||||
* the filter chain.
|
* the filter chain.
|
||||||
*
|
*
|
||||||
|
* Typically a filter will do something like this:
|
||||||
|
*
|
||||||
|
* process(struct mp_filter *f) {
|
||||||
|
* if (!mp_pin_in_needs_data(f->ppins[1]))
|
||||||
|
* return; // reader needs no output yet, so stop filtering
|
||||||
|
* if (!have_enough_data_for_output) {
|
||||||
|
* // Could check mp_pin_out_request_data(), but often just trying to
|
||||||
|
* // read is enough, as a failed read will request more data.
|
||||||
|
* struct mp_frame fr = mp_pin_out_read_data(f->ppins[0]);
|
||||||
|
* if (!fr.type)
|
||||||
|
* return; // no frame was returned - data was requested, and will
|
||||||
|
* // be queued when available, and invoke process() again
|
||||||
|
* ... do something with fr here ...
|
||||||
|
* }
|
||||||
|
* ... produce output frame (i.e. actual filtering) ...
|
||||||
|
* mp_pin_in_write(f->ppins[1], output_frame);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* Simpler filters can use utility functions like mp_pin_can_transfer_data(),
|
||||||
|
* which reduce the boilerplate. Such filters also may not need to buffer data
|
||||||
|
* as internal state.
|
||||||
|
*
|
||||||
|
* --- Driving filters:
|
||||||
|
*
|
||||||
|
* The filter root (created by mp_filter_create_root()) will internally create
|
||||||
|
* a graph runner, that can be entered with mp_filter_run(). This will check if
|
||||||
|
* any filter/pin has unhandled requests, and call filter process() functions
|
||||||
|
* accordingly. Outside of the filter, this can be triggered implicitly via the
|
||||||
|
* mp_pin_* functions.
|
||||||
|
*
|
||||||
* Multiple filters are driven by letting mp_pin flag filters which need
|
* Multiple filters are driven by letting mp_pin flag filters which need
|
||||||
* process() to be called. The process starts by requesting output from the
|
* process() to be called. The process starts by requesting output from the
|
||||||
* last filter. The requests will "bubble up" by iteratively calling process()
|
* last filter. The requests will "bubble up" by iteratively calling process()
|
||||||
|
@ -184,7 +216,12 @@ const char *mp_pin_get_name(struct mp_pin *p);
|
||||||
* filter's input pin is requested. The API user feeds it a frame, which will
|
* filter's input pin is requested. The API user feeds it a frame, which will
|
||||||
* call the first filter's process() function, which will filter and output
|
* call the first filter's process() function, which will filter and output
|
||||||
* the frame, and the frame is iteratively filtered until it reaches the output.
|
* the frame, and the frame is iteratively filtered until it reaches the output.
|
||||||
* (Depending on implementation, some if this wil be recursive not iterative.)
|
*
|
||||||
|
* (The mp_pin_* calls can recursively start filtering, but this is only the
|
||||||
|
* case if you access a separate graph with a different filter root. Most
|
||||||
|
* importantly, calling them from outside the filter's process() function (e.g.
|
||||||
|
* an outside filter user) will enter filtering. Within the filter, mp_pin_*
|
||||||
|
* will usually only set or query flags.)
|
||||||
*
|
*
|
||||||
* --- General rules for thread safety:
|
* --- General rules for thread safety:
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue