summaryrefslogtreecommitdiffstats
path: root/filters/filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'filters/filter.c')
-rw-r--r--filters/filter.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/filters/filter.c b/filters/filter.c
index dfe6df953a..a600b7dec4 100644
--- a/filters/filter.c
+++ b/filters/filter.c
@@ -1,8 +1,11 @@
+#include <math.h>
#include <pthread.h>
#include "common/common.h"
#include "common/global.h"
#include "common/msg.h"
+#include "osdep/atomic.h"
+#include "osdep/timer.h"
#include "video/hwdec.h"
#include "filter.h"
@@ -65,6 +68,9 @@ struct filter_runner {
struct mp_filter *root_filter;
+ double max_run_time;
+ atomic_bool interrupt_flag;
+
// If we're currently running the filter graph (for avoiding recursion).
bool filtering;
@@ -177,6 +183,10 @@ bool mp_filter_run(struct mp_filter *filter)
{
struct filter_runner *r = filter->in->runner;
+ int64_t end_time = 0;
+ if (isfinite(r->max_run_time))
+ end_time = mp_add_timeout(mp_time_us(), MPMAX(r->max_run_time, 0));
+
// (could happen with separate filter graphs calling each other, for now
// ignore this issue as we don't use such a setup anywhere)
assert(!r->filtering);
@@ -187,13 +197,30 @@ bool mp_filter_run(struct mp_filter *filter)
// to queue a wakeup again later. So do not call this in the loop.
flush_async_notifications(r);
- while (r->num_pending) {
+ while (1) {
+ if (atomic_exchange_explicit(&r->interrupt_flag, false,
+ memory_order_acq_rel))
+ {
+ pthread_mutex_lock(&r->async_lock);
+ if (!r->async_wakeup_sent && r->wakeup_cb)
+ r->wakeup_cb(r->wakeup_ctx);
+ r->async_wakeup_sent = true;
+ pthread_mutex_unlock(&r->async_lock);
+ break;
+ }
+
+ if (!r->num_pending)
+ break;
+
struct mp_filter *next = r->pending[r->num_pending - 1];
r->num_pending -= 1;
next->in->pending = false;
if (next->in->info->process)
next->in->info->process(next);
+
+ if (end_time && mp_time_us() >= end_time)
+ mp_filter_graph_interrupt(r->root_filter);
}
r->filtering = false;
@@ -644,6 +671,18 @@ void mp_filter_mark_async_progress(struct mp_filter *f)
filter_wakeup(f, true);
}
+void mp_filter_graph_set_max_run_time(struct mp_filter *f, double seconds)
+{
+ struct filter_runner *r = f->in->runner;
+ r->max_run_time = seconds;
+}
+
+void mp_filter_graph_interrupt(struct mp_filter *f)
+{
+ struct filter_runner *r = f->in->runner;
+ atomic_store(&r->interrupt_flag, true);
+}
+
void mp_filter_free_children(struct mp_filter *f)
{
while(f->in->num_children)
@@ -717,6 +756,7 @@ struct mp_filter *mp_filter_create_with_params(struct mp_filter_params *params)
*f->in->runner = (struct filter_runner){
.global = params->global,
.root_filter = f,
+ .max_run_time = INFINITY,
};
pthread_mutex_init(&f->in->runner->async_lock, NULL);
}