summaryrefslogtreecommitdiffstats
path: root/video/filter/vf_vapoursynth.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/filter/vf_vapoursynth.c')
-rw-r--r--video/filter/vf_vapoursynth.c143
1 files changed, 78 insertions, 65 deletions
diff --git a/video/filter/vf_vapoursynth.c b/video/filter/vf_vapoursynth.c
index d6cef08b3f..0b798c8daf 100644
--- a/video/filter/vf_vapoursynth.c
+++ b/video/filter/vf_vapoursynth.c
@@ -19,7 +19,6 @@
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
-#include <pthread.h>
#include <limits.h>
#include <assert.h>
@@ -28,17 +27,17 @@
#include <libavutil/rational.h>
#include <libavutil/cpu.h>
-
-#include "config.h"
+#include <libplacebo/utils/libav.h>
#include "common/msg.h"
-#include "options/m_option.h"
-#include "options/path.h"
#include "filters/f_autoconvert.h"
#include "filters/f_utils.h"
-#include "filters/filter.h"
#include "filters/filter_internal.h"
+#include "filters/filter.h"
#include "filters/user_filters.h"
+#include "options/m_option.h"
+#include "options/path.h"
+#include "osdep/threads.h"
#include "video/img_format.h"
#include "video/mp_image.h"
#include "video/sws_utils.h"
@@ -72,8 +71,8 @@ struct priv {
// Format for which VS is currently configured.
struct mp_image_params fmt_in;
- pthread_mutex_t lock;
- pthread_cond_t wakeup;
+ mp_mutex lock;
+ mp_cond wakeup;
// --- the following members are all protected by lock
struct mp_image **buffered; // oldest image first
@@ -111,25 +110,25 @@ struct script_driver {
struct mpvs_fmt {
VSPresetFormat vs;
- int bits, cw, ch;
+ int bits, xs, ys;
};
static const struct mpvs_fmt mpvs_fmt_table[] = {
- {pfYUV420P8, 8, 2, 2},
- {pfYUV420P9, 9, 2, 2},
- {pfYUV420P10, 10, 2, 2},
- {pfYUV420P16, 16, 2, 2},
- {pfYUV422P8, 8, 2, 1},
- {pfYUV422P9, 9, 2, 1},
- {pfYUV422P10, 10, 2, 1},
- {pfYUV422P16, 16, 2, 1},
- {pfYUV410P8, 8, 4, 4},
- {pfYUV411P8, 8, 4, 1},
- {pfYUV440P8, 8, 1, 2},
- {pfYUV444P8, 8, 1, 1},
- {pfYUV444P9, 9, 1, 1},
- {pfYUV444P10, 10, 1, 1},
- {pfYUV444P16, 16, 1, 1},
+ {pfYUV420P8, 8, 1, 1},
+ {pfYUV420P9, 9, 1, 1},
+ {pfYUV420P10, 10, 1, 1},
+ {pfYUV420P16, 16, 1, 1},
+ {pfYUV422P8, 8, 1, 0},
+ {pfYUV422P9, 9, 1, 0},
+ {pfYUV422P10, 10, 1, 0},
+ {pfYUV422P16, 16, 1, 0},
+ {pfYUV410P8, 8, 2, 2},
+ {pfYUV411P8, 8, 2, 0},
+ {pfYUV440P8, 8, 0, 1},
+ {pfYUV444P8, 8, 0, 0},
+ {pfYUV444P9, 9, 0, 0},
+ {pfYUV444P10, 10, 0, 0},
+ {pfYUV444P16, 16, 0, 0},
{pfNone}
};
@@ -140,7 +139,7 @@ static bool compare_fmt(int imgfmt, const struct mpvs_fmt *vs)
return false;
if (rfmt.component_pad > 0)
return false;
- if (rfmt.chroma_w != vs->cw || rfmt.chroma_h != vs->ch)
+ if (rfmt.chroma_xs != vs->xs || rfmt.chroma_ys != vs->ys)
return false;
if (rfmt.component_size * 8 + rfmt.component_pad != vs->bits)
return false;
@@ -186,16 +185,16 @@ static void copy_mp_to_vs_frame_props_map(struct priv *p, VSMap *map,
struct mp_image_params *params = &img->params;
p->vsapi->propSetInt(map, "_SARNum", params->p_w, 0);
p->vsapi->propSetInt(map, "_SARDen", params->p_h, 0);
- if (params->color.levels) {
+ if (params->repr.levels) {
p->vsapi->propSetInt(map, "_ColorRange",
- params->color.levels == MP_CSP_LEVELS_TV, 0);
+ params->repr.levels == PL_COLOR_LEVELS_LIMITED, 0);
}
// The docs explicitly say it uses libavcodec values.
p->vsapi->propSetInt(map, "_ColorSpace",
- mp_csp_to_avcol_spc(params->color.space), 0);
+ pl_system_to_av(params->repr.sys), 0);
if (params->chroma_location) {
p->vsapi->propSetInt(map, "_ChromaLocation",
- params->chroma_location == MP_CHROMA_CENTER, 0);
+ params->chroma_location == PL_CHROMA_CENTER, 0);
}
char pict_type = 0;
switch (img->pict_type) {
@@ -272,6 +271,8 @@ static void VS_CC vs_frame_done(void *userData, const VSFrameRef *f, int n,
if (f) {
struct mp_image img = map_vs_frame(p, f, false);
struct mp_image dummy = {.params = p->fmt_in};
+ if (p->fmt_in.w != img.w || p->fmt_in.h != img.h)
+ dummy.params.crop = (struct mp_rect){0, 0, img.w, img.h};
mp_image_copy_attributes(&img, &dummy);
img.pkt_duration = -1;
const VSMap *map = p->vsapi->getFramePropsRO(f);
@@ -282,13 +283,16 @@ static void VS_CC vs_frame_done(void *userData, const VSFrameRef *f, int n,
if (!err1 && !err2)
img.pkt_duration = num / (double)den;
}
- if (img.pkt_duration < 0)
+ if (img.pkt_duration < 0) {
MP_ERR(p, "No PTS after filter at frame %d!\n", n);
+ } else {
+ img.nominal_fps = 1.0 / img.pkt_duration;
+ }
res = mp_image_new_copy(&img);
p->vsapi->freeFrame(f);
}
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
// If these assertions fail, n is an unrequested frame (or filtered twice).
assert(n >= p->out_frameno && n < p->out_frameno + p->max_requests);
@@ -305,8 +309,8 @@ static void VS_CC vs_frame_done(void *userData, const VSFrameRef *f, int n,
}
}
p->requested[index] = res;
- pthread_cond_broadcast(&p->wakeup);
- pthread_mutex_unlock(&p->lock);
+ mp_cond_broadcast(&p->wakeup);
+ mp_mutex_unlock(&p->lock);
mp_filter_wakeup(p->f);
}
@@ -314,7 +318,7 @@ static void vf_vapoursynth_process(struct mp_filter *f)
{
struct priv *p = f->priv;
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
if (p->failed) {
// Not sure what we do on errors, but at least don't deadlock.
@@ -333,7 +337,7 @@ static void vf_vapoursynth_process(struct mp_filter *f)
if (p->out_node && !p->eof) {
MP_VERBOSE(p, "initiate EOF\n");
p->eof = true;
- pthread_cond_broadcast(&p->wakeup);
+ mp_cond_broadcast(&p->wakeup);
}
if (!p->out_node && mp_pin_in_needs_data(f->ppins[1])) {
MP_VERBOSE(p, "return EOF\n");
@@ -357,11 +361,11 @@ static void vf_vapoursynth_process(struct mp_filter *f)
MP_VERBOSE(p, "draining VS for format change\n");
mp_pin_out_unread(p->in_pin, frame);
p->eof = true;
- pthread_cond_broadcast(&p->wakeup);
+ mp_cond_broadcast(&p->wakeup);
mp_filter_internal_mark_progress(f);
goto done;
}
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
if (p->out_node)
destroy_vs(p);
p->fmt_in = mpi->params;
@@ -371,13 +375,13 @@ static void vf_vapoursynth_process(struct mp_filter *f)
mp_filter_internal_mark_failed(f);
return;
}
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
}
if (p->out_pts == MP_NOPTS_VALUE)
p->out_pts = mpi->pts;
p->frames_sent++;
p->buffered[p->num_buffered++] = mpi;
- pthread_cond_broadcast(&p->wakeup);
+ mp_cond_broadcast(&p->wakeup);
} else if (frame.type != MP_FRAME_NONE) {
MP_ERR(p, "discarding unknown frame type\n");
mp_frame_unref(&frame);
@@ -410,7 +414,7 @@ static void vf_vapoursynth_process(struct mp_filter *f)
if (p->requested[0] == &dummy_img_eof) {
MP_VERBOSE(p, "finishing up\n");
assert(p->eof);
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
destroy_vs(p);
mp_filter_internal_mark_progress(f);
return;
@@ -433,7 +437,7 @@ static void vf_vapoursynth_process(struct mp_filter *f)
}
done:
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
}
static void VS_CC infiltInit(VSMap *in, VSMap *out, void **instanceData,
@@ -470,7 +474,7 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason,
struct priv *p = *instanceData;
VSFrameRef *ret = NULL;
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
MP_TRACE(p, "VS asking for frame %d (at %d)\n", frameno, p->in_frameno);
while (1) {
if (p->shutdown) {
@@ -508,7 +512,7 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason,
// queue new frames.
if (p->num_buffered) {
drain_oldest_buffered_frame(p);
- pthread_cond_broadcast(&p->wakeup);
+ mp_cond_broadcast(&p->wakeup);
mp_filter_wakeup(p->f);
continue;
}
@@ -533,19 +537,19 @@ static const VSFrameRef *VS_CC infiltGetFrame(int frameno, int activationReason,
break;
}
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
struct mp_image vsframe = map_vs_frame(p, ret, true);
mp_image_copy(&vsframe, img);
int res = 1e6;
int dur = img->pkt_duration * res + 0.5;
set_vs_frame_props(p, ret, img, dur, res);
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
break;
}
- pthread_cond_wait(&p->wakeup, &p->lock);
+ mp_cond_wait(&p->wakeup, &p->lock);
}
- pthread_cond_broadcast(&p->wakeup);
- pthread_mutex_unlock(&p->lock);
+ mp_cond_broadcast(&p->wakeup);
+ mp_mutex_unlock(&p->lock);
return ret;
}
@@ -553,10 +557,10 @@ static void VS_CC infiltFree(void *instanceData, VSCore *core, const VSAPI *vsap
{
struct priv *p = instanceData;
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
p->in_node_active = false;
- pthread_cond_broadcast(&p->wakeup);
- pthread_mutex_unlock(&p->lock);
+ mp_cond_broadcast(&p->wakeup);
+ mp_mutex_unlock(&p->lock);
}
// number of getAsyncFrame calls in progress
@@ -577,13 +581,13 @@ static void destroy_vs(struct priv *p)
MP_DBG(p, "destroying VS filters\n");
// Wait until our frame callbacks return.
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
p->initializing = false;
p->shutdown = true;
- pthread_cond_broadcast(&p->wakeup);
+ mp_cond_broadcast(&p->wakeup);
while (num_requested(p))
- pthread_cond_wait(&p->wakeup, &p->lock);
- pthread_mutex_unlock(&p->lock);
+ mp_cond_wait(&p->wakeup, &p->lock);
+ mp_mutex_unlock(&p->lock);
MP_DBG(p, "all requests terminated\n");
@@ -668,12 +672,20 @@ static int reinit_vs(struct priv *p, struct mp_image *input)
struct mp_stream_info *info = mp_filter_find_stream_info(p->f);
double container_fps = input->nominal_fps;
double display_fps = 0;
+ int64_t display_res[2] = {0};
if (info) {
if (info->get_display_fps)
display_fps = info->get_display_fps(info);
+ if (info->get_display_res) {
+ int tmp[2] = {0};
+ info->get_display_res(info, tmp);
+ display_res[0] = tmp[0];
+ display_res[1] = tmp[1];
+ }
}
p->vsapi->propSetFloat(vars, "container_fps", container_fps, 0);
p->vsapi->propSetFloat(vars, "display_fps", display_fps, 0);
+ p->vsapi->propSetIntArray(vars, "display_res", display_res, 2);
if (p->drv->load(p, vars) < 0)
goto error;
@@ -688,9 +700,9 @@ static int reinit_vs(struct priv *p, struct mp_image *input)
goto error;
}
- pthread_mutex_lock(&p->lock);
+ mp_mutex_lock(&p->lock);
p->initializing = false;
- pthread_mutex_unlock(&p->lock);
+ mp_mutex_unlock(&p->lock);
MP_DBG(p, "initialized.\n");
res = 0;
error:
@@ -718,8 +730,8 @@ static void vf_vapoursynth_destroy(struct mp_filter *f)
destroy_vs(p);
p->drv->uninit(p);
- pthread_cond_destroy(&p->wakeup);
- pthread_mutex_destroy(&p->lock);
+ mp_cond_destroy(&p->wakeup);
+ mp_mutex_destroy(&p->lock);
mp_filter_free_children(f);
}
@@ -752,8 +764,8 @@ static struct mp_filter *vf_vapoursynth_create(struct mp_filter *parent,
p->drv = p->opts->drv;
p->f = f;
- pthread_mutex_init(&p->lock, NULL);
- pthread_cond_init(&p->wakeup, NULL);
+ mp_mutex_init(&p->lock);
+ mp_cond_init(&p->wakeup);
if (!p->opts->file || !p->opts->file[0]) {
MP_FATAL(p, "'file' parameter must be set.\n");
@@ -800,10 +812,11 @@ error:
#define OPT_BASE_STRUCT struct vapoursynth_opts
static const m_option_t vf_opts_fields[] = {
- OPT_STRING("file", file, M_OPT_FILE),
- OPT_INTRANGE("buffered-frames", maxbuffer, 0, 1, 9999, OPTDEF_INT(4)),
- OPT_CHOICE_OR_INT("concurrent-frames", maxrequests, 0, 1, 99,
- ({"auto", -1}), OPTDEF_INT(-1)),
+ {"file", OPT_STRING(file), .flags = M_OPT_FILE},
+ {"buffered-frames", OPT_INT(maxbuffer), M_RANGE(1, 9999),
+ OPTDEF_INT(4)},
+ {"concurrent-frames", OPT_CHOICE(maxrequests, {"auto", -1}),
+ M_RANGE(1, 99), OPTDEF_INT(-1)},
{0}
};