summaryrefslogtreecommitdiffstats
path: root/filters/filter_internal.h
diff options
context:
space:
mode:
Diffstat (limited to 'filters/filter_internal.h')
-rw-r--r--filters/filter_internal.h144
1 files changed, 144 insertions, 0 deletions
diff --git a/filters/filter_internal.h b/filters/filter_internal.h
new file mode 100644
index 0000000000..bd901db7d8
--- /dev/null
+++ b/filters/filter_internal.h
@@ -0,0 +1,144 @@
+#pragma once
+
+#include <stddef.h>
+
+#include "filter.h"
+
+// Flag the thread as needing mp_filter_process() to be called. Useful for
+// (some) async filters only. Idempotent.
+// Explicitly thread-safe.
+void mp_filter_wakeup(struct mp_filter *f);
+
+// Same as mp_filter_wakeup(), but skip the wakeup, and only mark the filter
+// as requiring processing to possibly update pin states changed due to async
+// processing.
+// Explicitly thread-safe.
+void mp_filter_mark_async_progress(struct mp_filter *f);
+
+// Flag the thread as needing mp_filter_process() to be called. Unlike
+// mp_filter_wakeup(), not thread-safe, and must be called from the process()
+// function of f (in exchange this is very light-weight).
+// In practice, this means process() is repeated.
+void mp_filter_internal_mark_progress(struct mp_filter *f);
+
+// Flag the filter as having failed, and propagate the error to the parent
+// filter. The error propagation stops either at the root filter, or if a filter
+// has an error handler set.
+// Must be called from f's process function.
+void mp_filter_internal_mark_failed(struct mp_filter *f);
+
+// If handler is not NULL, then if filter f errors, don't propagate the error
+// flag to its parent. Also invoke the handler's process() function, which is
+// supposed to use mp_filter_has_failed(f) to check any filters for which it has
+// set itself as error handler.
+// A filter must manually unset itself as error handler if it gets destroyed
+// before the filter f, otherwise dangling pointers will occur.
+void mp_filter_set_error_handler(struct mp_filter *f, struct mp_filter *handler);
+
+// Add a pin. Returns the private handle (same as f->ppins[f->num_pins-1]).
+// The name must be unique across all filter pins (you must verify this
+// yourself if filter names are from user input). name=="" is not allowed.
+// Never returns NULL. dir should be the external filter direction (a filter
+// input will use dir==MP_PIN_IN, and the returned pin will use MP_PIN_OUT,
+// because the internal pin is the opposite end of the external one).
+struct mp_pin *mp_filter_add_pin(struct mp_filter *f, enum mp_pin_dir dir,
+ const char *name);
+
+// Remove and deallocate a pin. The caller must be sure that nothing else
+// references the pin anymore. You must pass the private pin (from
+// mp_filter.ppin). This removes/deallocates the public paired pin as well.
+void mp_filter_remove_pin(struct mp_filter *f, struct mp_pin *p);
+
+// Free all filters which have f as parent. (This has nothing to do with
+// talloc.)
+void mp_filter_free_children(struct mp_filter *f);
+
+struct mp_filter_params;
+
+struct mp_filter_info {
+ // Informational name, in some cases might be used for filter discovery.
+ const char *name;
+
+ // mp_filter.priv is set to memory allocated with this size (if > 0)
+ size_t priv_size;
+
+ // Called during mp_filter_create(). Optional, can be NULL if use of a
+ // constructor function is required, which sets up the real filter after
+ // creation. Actually turns out nothing uses this.
+ bool (*init)(struct mp_filter *f, struct mp_filter_params *params);
+
+ // Free internal resources. Optional.
+ void (*destroy)(struct mp_filter *f);
+
+ // Called if any mp_pin was signalled (i.e. likely new data to process), or
+ // an async wakeup was received some time earlier.
+ // Generally, the implementation would consist of 2 stages:
+ // 1. check for the pin states, possibly request/probe for input/output
+ // 2. if data flow can happen, read a frame, perform actual work, write
+ // result
+ // The process function will usually run very often, when pin states are
+ // updated, so the generic code can determine where data flow can happen.
+ // The common case will be that process() is called running stage 1 a bunch
+ // of times, until it finally can run stage 2 too.
+ // Optional.
+ void (*process)(struct mp_filter *f);
+
+ // Clear internal state and buffers (e.g. on seeks). Filtering can restart
+ // after this, and all settings are preserved. It makes sense to preserve
+ // internal resources for further filtering as well if you can.
+ // Input/output pins are always cleared by the common code before invoking
+ // this callback.
+ // Optional, can be NULL for filters without state.
+ // Don't create or destroy filters in this function, don't reconnect pins,
+ // don't access pins.
+ void (*reset)(struct mp_filter *f);
+
+ // Send a command to the filter. Highly implementation specific, usually
+ // user-initiated. Optional.
+ bool (*command)(struct mp_filter *f, struct mp_filter_command *cmd);
+};
+
+// Create a filter instance. Returns NULL on failure.
+// Destroy/free with talloc_free().
+// This is for filter implementers only. Filters are created with their own
+// constructor functions (instead of a generic one), which call this function
+// to create the filter itself.
+// parent is never NULL; use mp_filter_create_root() to create a top most
+// filter.
+// The parent does not imply anything about the position of the filter in
+// the dataflow (only the mp_pin connections matter). The parent exists for
+// convenience, which includes:
+// - passing down implicit and explicit parameters (such as the filter driver
+// loop)
+// - auto freeing child filters if the parent is free'd
+// - propagating errors
+// - setting the parent as default manual connection for new external filter
+// pins
+// The parent filter stays valid for the lifetime of any filters having it
+// directly or indirectly as parent. If the parent is free'd, all children are
+// automatically free'd.
+// All filters in the same parent tree must be driven in the same thread (or be
+// explicitly synchronized otherwise).
+// Driving the parent (or root) filter with mp_filter_run() will make sure this
+// filter is driven too, without having to resort to recursion.
+struct mp_filter *mp_filter_create(struct mp_filter *parent,
+ const struct mp_filter_info *info);
+
+struct mp_filter_params {
+ // Identifies the filter and its implementation. The pointer must stay
+ // valid for the life time of the created filter instance.
+ const struct mp_filter_info *info;
+
+ // Must be set if global==NULL. See mp_filter_create() for remarks.
+ struct mp_filter *parent;
+
+ // Must be set if parent==NULL, can otherwise be NULL.
+ struct mpv_global *global;
+
+ // Filter specific parameters. Most filters will have a constructor
+ // function, and pass in something internal.
+ void *params;
+};
+
+// Same as mp_filter_create(), but technically more flexible.
+struct mp_filter *mp_filter_create_with_params(struct mp_filter_params *params);