diff options
Diffstat (limited to 'filters/filter.h')
-rw-r--r-- | filters/filter.h | 82 |
1 files changed, 61 insertions, 21 deletions
diff --git a/filters/filter.h b/filters/filter.h index 5e09a17ee7..44d5f59707 100644 --- a/filters/filter.h +++ b/filters/filter.h @@ -63,7 +63,7 @@ bool mp_pin_out_has_data(struct mp_pin *p); // frame is available, but to get proper data flow in filters, you should // probably follow the preferred conventions.) // If no frame is returned, a frame is automatically requested via -// mp_pin_out_request_data() (so it might be retuned in the future). +// mp_pin_out_request_data() (so it might be returned in the future). // If a frame is returned, no new frame is automatically requested (this is // usually not wanted, because it could lead to additional buffering). // This is guaranteed to return a non-NONE frame if mp_pin_out_has_data() @@ -204,10 +204,10 @@ const char *mp_pin_get_name(struct mp_pin *p); * --- 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. + * a graph runner, that can be entered with mp_filter_graph_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 * process() to be called. The process starts by requesting output from the @@ -217,12 +217,6 @@ const char *mp_pin_get_name(struct mp_pin *p); * 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 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: * * Filters are by default not thread safe. However, some filters can be @@ -231,6 +225,14 @@ const char *mp_pin_get_name(struct mp_pin *p); * for some utility functions explicitly marked as such, and which are meant * to make implementing threaded filters easier. * + * (Semi-)automatic filter communication such as pins must always be within the + * same root filter. This is meant to help with ensuring thread-safety. Every + * thread that wants to run filters "on its own" should use a different filter + * graph, and disallowing different root filters ensures these graphs are not + * accidentally connected using non-thread safe mechanisms. Actual threaded + * filter graphs would use several independent graphs connected by asynchronous + * helpers (such as mp_async_queue instead of mp_pin connections). + * * --- Rules for manual connections: * * A pin can be marked for manual connection via mp_pin_set_manual_connection(). @@ -272,6 +274,11 @@ const char *mp_pin_get_name(struct mp_pin *p); * For running parts of a filter graph on a different thread, f_async_queue.h * can be used. * + * With different filter graphs working asynchronously, reset handling and start + * of filtering becomes more difficult. Since filtering is always triggered by + * requesting output from a filter, a simple way to solve this is to trigger + * resets from the consumer, and to synchronously reset the producer. + * * --- Format conversions and mid-stream format changes: * * Generally, all filters must support all formats, as well as mid-stream @@ -339,6 +346,10 @@ const char *mp_filter_get_name(struct mp_filter *f); // Change mp_filter_get_name() return value. void mp_filter_set_name(struct mp_filter *f, const char *name); +// Set filter priority. A higher priority gets processed first. Also, high +// priority filters disable "interrupting" the filter graph. +void mp_filter_set_high_priority(struct mp_filter *filter, bool pri); + // Get a pin from f->pins[] for which mp_pin_get_name() returns the same name. // If name is NULL, always return NULL. struct mp_pin *mp_filter_get_named_pin(struct mp_filter *f, const char *name); @@ -357,6 +368,7 @@ enum mp_filter_command_type { MP_FILTER_COMMAND_GET_META, MP_FILTER_COMMAND_SET_SPEED, MP_FILTER_COMMAND_SET_SPEED_RESAMPLE, + MP_FILTER_COMMAND_SET_SPEED_DROP, MP_FILTER_COMMAND_IS_ACTIVE, }; @@ -364,6 +376,7 @@ struct mp_filter_command { enum mp_filter_command_type type; // For MP_FILTER_COMMAND_TEXT + const char *target; const char *cmd; const char *arg; @@ -386,6 +399,7 @@ struct mp_stream_info { void *priv; // for use by whoever implements the callbacks double (*get_display_fps)(struct mp_stream_info *i); + void (*get_display_res)(struct mp_stream_info *i, int *res); struct mp_hwdec_devices *hwdec_devs; struct osd_state *osd; @@ -396,35 +410,61 @@ struct mp_stream_info { // Search for a parent filter (including f) that has this set, and return it. struct mp_stream_info *mp_filter_find_stream_info(struct mp_filter *f); -struct AVBufferRef; -struct AVBufferRef *mp_filter_load_hwdec_device(struct mp_filter *f, int avtype); +struct mp_hwdec_ctx *mp_filter_load_hwdec_device(struct mp_filter *f, int imgfmt); // Perform filtering. This runs until the filter graph is blocked (due to // missing external input or unread output). It returns whether any outside // pins have changed state. -// Does not perform recursive filtering to connected filters with different -// root filter, though it notifies them. -bool mp_filter_run(struct mp_filter *f); +// Can be called on the root filter only. +bool mp_filter_graph_run(struct mp_filter *root); + +// Set the maximum time mp_filter_graph_run() should block. If the maximum time +// expires, the effect is the same as calling mp_filter_graph_interrupt() while +// the function is running. See that function for further details. +// The default is seconds==INFINITY. Values <=0 make it return after 1 iteration. +// Can be called on the root filter only. +void mp_filter_graph_set_max_run_time(struct mp_filter *root, double seconds); + +// Interrupt mp_filter_graph_run() asynchronously. This does not stop filtering +// in a destructive way, but merely suspends it. In practice, this will make +// mp_filter_graph_run() return after the current filter's process() function has +// finished. Filtering can be resumed with subsequent mp_filter_graph_run() calls. +// When mp_filter_graph_run() is interrupted, it will trigger the filter graph +// wakeup callback, which in turn ensures that the user will call +// mp_filter_graph_run() again. +// If it is called if not in mp_filter_graph_run(), the next mp_filter_graph_run() +// call is interrupted and no filtering is done for that call. +// Calling this too often will starve filtering. +// This does not call the graph wakeup callback directly, which will avoid +// potential reentrancy issues. (But mp_filter_graph_run() will call it in +// reaction to it, as described above.) +// Explicitly thread-safe. +// Can be called on the root filter only. +void mp_filter_graph_interrupt(struct mp_filter *root); // Create a root dummy filter with no inputs or outputs. This fulfills the // following functions: +// - creating a new filter graph (attached to the root filter) // - passing it as parent filter to top-level filters // - driving the filter loop between the shared filters // - setting the wakeup callback for async filtering // - implicitly passing down global data like mpv_global and keeping filter // constructor functions simple // Note that you can still connect pins of filters with different parents or -// root filters, but then you may have to manually invoke mp_filter_run() on -// the root filters of the connected filters to drive data flow. +// root filters, but then you may have to manually invoke mp_filter_graph_run() +// on the root filters of the connected filters to drive data flow. struct mp_filter *mp_filter_create_root(struct mpv_global *global); // Asynchronous filters may need to wakeup the user thread if the status of any // mp_pin has changed. If this is called, the callback provider should get the -// user's thread to call mp_filter_run() again. +// user's thread to call mp_filter_graph_run() again. // The wakeup callback must not recursively call into any filter APIs, or do // blocking waits on the filter API (deadlocks will happen). -void mp_filter_root_set_wakeup_cb(struct mp_filter *root, - void (*wakeup_cb)(void *ctx), void *ctx); +// A wakeup callback should always set a "wakeup" flag, that is reset only when +// mp_filter_graph_run() is going to be called again with no wait time. +// Can be called on the root filter only. +void mp_filter_graph_set_wakeup_cb(struct mp_filter *root, + void (*wakeup_cb)(void *ctx), void *ctx); // Debugging internal stuff. void mp_filter_dump_states(struct mp_filter *f); |