summaryrefslogtreecommitdiffstats
path: root/filters/filter.h
diff options
context:
space:
mode:
Diffstat (limited to 'filters/filter.h')
-rw-r--r--filters/filter.h82
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);