From 2c7139753d1e1530da44b781e9ae7c65874bb677 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 28 Aug 2020 19:57:23 +0200 Subject: 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. --- filters/filter.c | 33 +++++++++++++++++++++++++++------ filters/filter.h | 4 ++++ 2 files changed, 31 insertions(+), 6 deletions(-) (limited to 'filters') 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); -- cgit v1.2.3