summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-08-28 19:57:23 +0200
committerwm4 <wm4@nowhere>2020-08-28 19:57:23 +0200
commit2c7139753d1e1530da44b781e9ae7c65874bb677 (patch)
treeaa7afc251095d47c284880086c47b6bd671caa21
parentb9f52105aec5fe0ffa69bb56229c673d9589ff29 (diff)
downloadmpv-2c7139753d1e1530da44b781e9ae7c65874bb677.tar.bz2
mpv-2c7139753d1e1530da44b781e9ae7c65874bb677.tar.xz
filter: add filter priority thing
This is a kind of bad hack (with bad implementation) to paint over other problems of the filter system. The main problem is that some filters might be left with pending frames if the filter runner is "paused", which we don't want. To be used in a later commit.
-rw-r--r--filters/filter.c33
-rw-r--r--filters/filter.h4
2 files changed, 31 insertions, 6 deletions
diff --git a/filters/filter.c b/filters/filter.c
index 4134aff88b..cddeea0a3f 100644
--- a/filters/filter.c
+++ b/filters/filter.c
@@ -110,13 +110,13 @@ struct mp_filter_internal {
struct mp_filter *error_handler;
char *name;
+ bool high_priority;
bool pending;
bool async_pending;
bool failed;
};
-
// Called when new work needs to be done on a pin belonging to the filter:
// - new data was requested
// - new data has been queued
@@ -133,7 +133,11 @@ static void add_pending(struct mp_filter *f)
// This should probably really be some sort of priority queue, but for now
// something naive and dumb does the job too.
f->in->pending = true;
- MP_TARRAY_APPEND(r, r->pending, r->num_pending, f);
+ if (f->in->high_priority) {
+ MP_TARRAY_INSERT_AT(r, r->pending, r->num_pending, 0, f);
+ } else {
+ MP_TARRAY_APPEND(r, r->pending, r->num_pending, f);
+ }
}
static void add_pending_pin(struct mp_pin *p)
@@ -217,6 +221,8 @@ bool mp_filter_graph_run(struct mp_filter *filter)
flush_async_notifications(r);
+ bool exit_req = false;
+
while (1) {
if (atomic_exchange_explicit(&r->interrupt_flag, false,
memory_order_acq_rel))
@@ -226,7 +232,7 @@ bool mp_filter_graph_run(struct mp_filter *filter)
r->wakeup_cb(r->wakeup_ctx);
r->async_wakeup_sent = true;
pthread_mutex_unlock(&r->async_lock);
- break;
+ exit_req = true;
}
if (!r->num_pending) {
@@ -235,10 +241,20 @@ bool mp_filter_graph_run(struct mp_filter *filter)
break;
}
- struct mp_filter *next = r->pending[r->num_pending - 1];
- r->num_pending -= 1;
- next->in->pending = false;
+ struct mp_filter *next = NULL;
+
+ if (r->pending[0]->in->high_priority) {
+ next = r->pending[0];
+ MP_TARRAY_REMOVE_AT(r->pending, r->num_pending, 0);
+ } else if (!exit_req) {
+ next = r->pending[r->num_pending - 1];
+ r->num_pending -= 1;
+ }
+
+ if (!next)
+ break;
+ next->in->pending = false;
if (next->in->info->process)
next->in->info->process(next);
@@ -517,6 +533,11 @@ const struct mp_filter_info *mp_filter_get_info(struct mp_filter *f)
return f->in->info;
}
+void mp_filter_set_high_priority(struct mp_filter *f, bool pri)
+{
+ f->in->high_priority = pri;
+}
+
void mp_filter_set_name(struct mp_filter *f, const char *name)
{
talloc_free(f->in->name);
diff --git a/filters/filter.h b/filters/filter.h
index 34cfcf0f54..19aafc6f3d 100644
--- a/filters/filter.h
+++ b/filters/filter.h
@@ -346,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);