vf_dlopen: remove this filter

It was an attempt to move some MPlayer filters (which were removed from
mpv) to external, loadable filters. That worked well, but then the
MPlayer filters were ported to libavfilter (independently), so they're
available again. Also there is a more widely supported and more advanced
loadable filter system supported by mpv: vapoursynth.

In conclusion, vf_dlopen is not useful anymore, confusing, and requires
quite a bit of code (and probably wouldn't survive the rewrite of the
mpv video filter chain, which has to come at some point). It has some
implicit dependencies on internal conventions, like possibly the format
names dropped in the previous commit.

We also deprecated it last release. Drop it.
This commit is contained in:
wm4 2017-06-18 13:53:44 +02:00
parent 937dcc25ad
commit c680cfd18a
16 changed files with 0 additions and 1906 deletions

View File

@ -281,7 +281,6 @@ x video/decode/dec_video.* hard
video/filter/vf_buffer.c LGPL
video/filter/vf_crop.c will be deleted
video/filter/vf_d3d11vpp.c LGPL
video/filter/vf_dlopen.* LGPL
video/filter/vf_dsize.c will be deleted
video/filter/vf_eq.c will be deleted
video/filter/vf_expand.c will be deleted

View File

@ -642,29 +642,6 @@ Available mpv-only filters are:
size of the filter in percent of the image diagonal size. This is
used to calculate the final radius size (default: 1).
``dlopen=dll[:a0[:a1[:a2[:a3]]]]``
Loads an external library to filter the image. The library interface
is the ``vf_dlopen`` interface specified using ``libmpcodecs/vf_dlopen.h``.
.. warning:: This filter is deprecated.
``dll=<library>``
Specify the library to load. This may require a full file system path
in some cases. This argument is required.
``a0=<string>``
Specify the first parameter to pass to the library.
``a1=<string>``
Specify the second parameter to pass to the library.
``a2=<string>``
Specify the third parameter to pass to the library.
``a3=<string>``
Specify the fourth parameter to pass to the library.
``vapoursynth=file:buffered-frames:concurrent-frames``
Loads a VapourSynth filter script. This is intended for streamed
processing: mpv actually provides a source filter, instead of using a

View File

@ -1,50 +0,0 @@
#
# Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
#
# This file is part of mpv's vf_dlopen examples.
#
# mpv's vf_dlopen examples are free software; you can redistribute them and/or
# modify them under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation; either version 2.1 of the
# License, or (at your option) any later version.
#
# mpv's vf_dlopen examples are distributed in the hope that they will be
# useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
# General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with mpv's vf_dlopen examples; if not, write to the Free
# Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
#
FILTERS = telecine tile rectangle framestep ildetect
COMMON = filterutils.o
OBJECTS = $(patsubst %,%.o,$(FILTERS)) $(COMMON)
HEADERS = $(wildcard *.h)
OUT = $(patsubst %,%.so,$(FILTERS))
CFLAGS ?= -Wall -Wextra -O3 -march=native -mtune=native -ffast-math
CPPFLAGS += -I../../video/filter
CFLAGS += -fPIC
LDFLAGS += -shared -fPIC
ifneq ($(LTO),)
CFLAGS += -flto
LDFLAGS += $(CFLAGS) -flto
endif
all: $(OUT)
clean:
$(RM) $(OBJECTS) $(OUT)
%.so: %.o $(COMMON)
$(CC) $(LDFLAGS) $(LIBS) -o $@ $(COMMON) $<
# FIXME replace this by real dependency tracking
%.o: %.c $(HEADERS)

View File

@ -1,40 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <string.h>
#include "filterutils.h"
void copy_plane(
unsigned char *dest, unsigned dest_stride,
const unsigned char *src, unsigned src_stride,
unsigned length,
unsigned rows
)
{
unsigned i;
assert(dest_stride >= length);
assert(src_stride >= length);
for (i = 0; i < rows; ++i)
memcpy(&dest[dest_stride * i], &src[src_stride * i], length);
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
void copy_plane(
unsigned char *dest, unsigned dest_stride,
const unsigned char *src, unsigned src_stride,
unsigned length,
unsigned rows
);

View File

@ -1,103 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vf_dlopen.h"
#include "filterutils.h"
#define MIN(a,b) ((a)<(b)?(a):(b))
/*
* frame stepping filter
*
* usage: --vf=dlopen=/path/to/framestep.so:5
*
* outputs every 5th frame
*
* usage: --vf=dlopen=/path/to/framestep.so:5:3
*
* outputs every 5th frame, starting with frame index 3 (default: 0)
*/
typedef struct {
int step, pos;
} framestep_data_t;
static int framestep_put_image(struct vf_dlopen_context *ctx)
{
framestep_data_t *framestep = ctx->priv;
// stepping
if (framestep->pos < 0)
return 0;
--framestep->pos;
if (framestep->pos >= 0)
return 0;
framestep->pos += framestep->step;
// copying
assert(ctx->inpic.planes == ctx->outpic[0].planes);
int np = ctx->inpic.planes;
int p;
for (p = 0; p < np; ++p) {
assert(ctx->inpic.planewidth[p] == ctx->outpic->planewidth[p]);
assert(ctx->inpic.planeheight[p] == ctx->outpic->planeheight[p]);
copy_plane(
ctx->outpic->plane[p],
ctx->outpic->planestride[p],
ctx->inpic.plane[p],
ctx->inpic.planestride[p],
MIN(ctx->inpic.planestride[p], ctx->outpic->planestride[p]),
ctx->inpic.planeheight[p]
);
}
ctx->outpic->pts = ctx->inpic.pts;
return 1;
}
void framestep_uninit(struct vf_dlopen_context *ctx)
{
free(ctx->priv);
}
int vf_dlopen_getcontext(struct vf_dlopen_context *ctx, int argc, const char **argv)
{
VF_DLOPEN_CHECK_VERSION(ctx);
if (argc != 1 && argc != 2)
return -1;
framestep_data_t *framestep = calloc(1,sizeof(framestep_data_t));
framestep->step = atoi(argv[0]);
framestep->pos = (argc >= 2) ? atoi(argv[1]) : 0;
ctx->priv = framestep;
ctx->put_image = framestep_put_image;
ctx->uninit = framestep_uninit;
return 1;
}

View File

@ -1,295 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "vf_dlopen.h"
#include "filterutils.h"
/*
* interlacing detector
*
* usage: -vf dlopen=./ildetect.so:<method>:<threshold>
*
* outputs an interlacing detection report at the end
*
* methods:
* 0 = transcode 32detect (default)
* 1 = decomb IsCombed
* 2 = IsCombedTIVTC
* 3 = simple average
*
* threshold:
* normalized at 1
*/
typedef struct {
int method;
double combing_threshold;
double motion_threshold;
double motion_amount;
double yes_threshold;
double no_threshold;
double total_yes_threshold;
double total_no_threshold;
double tc_threshold;
double decision_threshold;
double tc_decision_threshold;
double lastcombed;
int numtotalframes;
int numdecidedframes;
int totalcombedframes;
int numjumpingadjacentframes;
int numdecidedadjacentframes;
unsigned char *buffer_data;
size_t buffer_size;
} ildetect_data_t;
static int il_config(struct vf_dlopen_context *ctx)
{
ctx->out_height -= 4;
ctx->out_d_height = ctx->out_height;
return 1;
}
static int il_decision(struct vf_dlopen_context *ctx,
int p0, int p1, int p2, int p3, int p4)
{
ildetect_data_t *il = ctx->priv;
// model for threshold: p0, p2, p4 = 0; p1, p3 = t
switch (il->method) {
case 0: { // diff-diff (transcode 32detect)
int d12 = p1 - p2; // t
int d13 = p1 - p3; // 0
if (abs(d12) > 15 * il->combing_threshold &&
abs(d13) < 10 * il->combing_threshold)
return 1;
// true for t > 15
break;
}
case 1: { // multiply (decomb IsCombed)
int d12 = p1 - p2; // t
int d32 = p3 - p2; // t
if (d12 * d32 > pow(il->combing_threshold, 2) * (25*25))
return 1;
// true for t > 21
break;
}
case 2: { // blur-blur (IsCombedTIVTC)
int b024 = p0 + 6 * p2 + p4; // 0
int b13 = 4 * p1 + 4 * p3; // 8t
if (abs(b024 - b13) > il->combing_threshold * 8 * 20)
return 1;
// true for t > 20
break;
}
case 3: { // average-average
int d123 = p1 + p3 - 2 * p2; // 2t
int d024 = p0 + p4 - 2 * p2; // 0
if ((abs(d123) - abs(d024)) > il->combing_threshold * 30)
return 1;
// true for t > 15
break;
}
}
return 0;
}
static int il_put_image(struct vf_dlopen_context *ctx)
{
ildetect_data_t *il = ctx->priv;
unsigned int x, y;
int first_frame = 0;
size_t sz = ctx->inpic.planestride[0] * ctx->inpic.planeheight[0];
if (sz != il->buffer_size) {
il->buffer_data = realloc(il->buffer_data, sz);
il->buffer_size = sz;
first_frame = 1;
}
assert(ctx->inpic.planes == 1);
assert(ctx->outpic[0].planes == 1);
assert(ctx->inpic.planewidth[0] == ctx->outpic[0].planewidth[0]);
assert(ctx->inpic.planeheight[0] == ctx->outpic[0].planeheight[0] + 4);
if (first_frame) {
printf("First frame\n");
il->lastcombed = -1;
} else {
// detect interlacing
// for each row of 5 pixels, compare:
// p2 vs (p1 + p3) / 2
// p2 vs (p0 + p4) / 2
unsigned int totalcombedframes = 0; // add 255 per combed pixel
unsigned int totalpixels = 0;
for (y = 0; y < ctx->inpic.planeheight[0] - 4; ++y) {
unsigned char *in_line =
&ctx->inpic.plane[0][ctx->inpic.planestride[0] * y];
unsigned char *buf_line =
&il->buffer_data[ctx->inpic.planestride[0] * y];
unsigned char *out_line =
&ctx->outpic->plane[0][ctx->outpic->planestride[0] * y];
for (x = 0; x < ctx->inpic.planewidth[0]; ++x) {
int b2 = buf_line[x + ctx->inpic.planestride[0] * 2];
int p0 = in_line[x];
int p1 = in_line[x + ctx->inpic.planestride[0]];
int p2 = in_line[x + ctx->inpic.planestride[0] * 2];
int p3 = in_line[x + ctx->inpic.planestride[0] * 3];
int p4 = in_line[x + ctx->inpic.planestride[0] * 4];
int is_moving = abs(b2 - p2) > il->motion_threshold;
if (!is_moving) {
out_line[x] = 128;
continue;
}
++totalpixels;
int combed = il_decision(ctx, p0, p1, p2, p3, p4);
totalcombedframes += combed;
out_line[x] = 255 * combed;
}
}
double avgpixels = totalpixels / (double)
((ctx->inpic.planeheight[0] - 4) * ctx->inpic.planewidth[0]);
if (avgpixels > il->motion_amount) {
double avgcombed = totalcombedframes / (double) totalpixels;
if (il->lastcombed >= 0) {
if (il->lastcombed < il->no_threshold ||
il->lastcombed > il->yes_threshold)
if (avgcombed < il->no_threshold ||
avgcombed > il->yes_threshold)
++il->numdecidedadjacentframes;
if (il->lastcombed > il->yes_threshold &&
avgcombed < il->no_threshold)
++il->numjumpingadjacentframes;
if (il->lastcombed < il->no_threshold &&
avgcombed > il->yes_threshold)
++il->numjumpingadjacentframes;
}
il->lastcombed = avgcombed;
if (avgcombed > il->yes_threshold) {
++il->numdecidedframes;
++il->totalcombedframes;
} else if (avgcombed < il->no_threshold) {
++il->numdecidedframes;
}
} else
il->lastcombed = -1;
}
++il->numtotalframes;
copy_plane(
il->buffer_data, ctx->inpic.planestride[0],
ctx->inpic.plane[0], ctx->inpic.planestride[0],
ctx->inpic.planewidth[0],
ctx->inpic.planeheight[0]);
ctx->outpic[0].pts = ctx->inpic.pts;
return 1;
}
void il_uninit(struct vf_dlopen_context *ctx)
{
ildetect_data_t *il = ctx->priv;
double avgdecided = il->numtotalframes
? il->numdecidedframes / (double) il->numtotalframes : -1;
double avgadjacent = il->numdecidedframes
? il->numdecidedadjacentframes / (double) il->numdecidedframes : -1;
double avgscore = il->numdecidedframes
? il->totalcombedframes / (double) il->numdecidedframes : -1;
double avgjumps = il->numdecidedadjacentframes
? il->numjumpingadjacentframes / (double) il->numdecidedadjacentframes : -1;
printf("ildetect: Avg decided: %f\n", avgdecided);
printf("ildetect: Avg adjacent decided: %f\n", avgadjacent);
printf("ildetect: Avg interlaced decided: %f\n", avgscore);
printf("ildetect: Avg interlaced/progressive adjacent decided: %f\n", avgjumps);
if (avgdecided < il->decision_threshold)
avgadjacent = avgscore = avgjumps = -1;
if (avgadjacent < il->tc_decision_threshold)
avgadjacent = avgjumps = -1;
if (avgscore < 0)
printf("ildetect: Content is probably: undecided\n");
else if (avgscore < il->total_no_threshold)
printf("ildetect: Content is probably: PROGRESSIVE\n");
else if (avgscore > il->total_yes_threshold && avgjumps < 0)
printf("ildetect: Content is probably: INTERLACED (possibly telecined)\n");
else if (avgjumps > il->tc_threshold)
printf("ildetect: Content is probably: TELECINED\n");
else if (avgscore > il->total_yes_threshold)
printf("ildetect: Content is probably: INTERLACED\n");
else
printf("ildetect: Content is probably: unknown\n");
free(ctx->priv);
}
int vf_dlopen_getcontext(struct vf_dlopen_context *ctx, int argc, const char **argv)
{
VF_DLOPEN_CHECK_VERSION(ctx);
(void) argc;
(void) argv;
ildetect_data_t *il = calloc(1,sizeof(ildetect_data_t));
#define A(i,d) ((argc>(i) && *argv[i]) ? atof(argv[i]) : (d))
il->method = A(0, 0);
il->combing_threshold = A(1, 1);
il->motion_threshold = A(2, 6);
il->motion_amount = A(3, 0.1);
il->yes_threshold = A(4, 0.1);
il->no_threshold = A(5, 0.05);
il->total_yes_threshold = A(6, 0.1);
il->total_no_threshold = A(7, 0.05);
il->tc_threshold = A(8, 0.1);
il->decision_threshold = A(9, 0.2);
il->tc_decision_threshold = A(10, 0.2);
static struct vf_dlopen_formatpair map[] = {
{ "gray", "gray" },
{ NULL, NULL }
};
ctx->format_mapping = map;
ctx->config = il_config;
ctx->put_image = il_put_image;
ctx->uninit = il_uninit;
ctx->priv = il;
return 1;
}

View File

@ -1,89 +0,0 @@
#!/bin/sh
case "$0" in
*/*)
MYDIR=${0%/*}
;;
*)
MYDIR=.
;;
esac
: ${MPV:=mpv}
: ${ILDETECT_MPV:=$MPV}
: ${ILDETECT_MPVFLAGS:=--start=35% --length=35}
: ${ILDETECT_DRY_RUN:=}
: ${ILDETECT_QUIET:=}
: ${ILDETECT_RUN_INTERLACED_ONLY:=}
: ${ILDETECT_FORCE_RUN:=}
: ${MAKE:=make}
# exit status:
# 0 progressive
# 1 telecine
# 2 interlaced
# 8 unknown
# 15 compile fail
# 16 detect fail
# 17+ mpv's status | 16
$MAKE -C "$MYDIR" ildetect.so || exit 15
testfun()
{
$ILDETECT_MPV "$@" \
--vf=dlopen="$MYDIR/ildetect.so" \
--o= --vo=null --no-audio --untimed \
$ILDETECT_MPVFLAGS \
| { if [ -n "$ILDETECT_QUIET" ]; then cat; else tee /dev/stderr; fi } \
| grep "^ildetect:"
}
out=`testfun "$@"`
case "$out" in
*"probably: PROGRESSIVE"*)
[ -n "$ILDETECT_DRY_RUN" ] || \
[ -n "$ILDETECT_RUN_INTERLACED_ONLY" ] || \
$ILDETECT_MPV "$@"
r=$?
[ $r -eq 0 ] || exit $(($r | 16))
exit 0
;;
*"probably: TELECINED"*)
out2=`ILDETECT_MPVFLAGS="$ILDETECT_MPVFLAGS --vf-pre=pullup,scale" testfun "$@"`
case "$out2" in
*"probably: TELECINED"*|*"probably: INTERLACED"*)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" -vf-pre yadif
r=$?
[ $r -eq 0 ] || exit $(($r | 16))
exit 2
;;
*)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" -vf-pre pullup
r=$?
[ $r -eq 0 ] || exit $(($r | 16))
exit 1
;;
esac
;;
*"probably: INTERLACED"*)
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" -vf-pre yadif
r=$?
[ $r -eq 0 ] || exit $(($r | 16))
exit 2
;;
*"probably: "*)
[ -n "$ILDETECT_FORCE_RUN" ] || exit 8
[ -n "$ILDETECT_DRY_RUN" ] || \
$ILDETECT_MPV "$@" -vf-pre yadif
r=$?
[ $r -eq 0 ] || exit $(($r | 16))
exit 0
;;
*)
exit 16
;;
esac

View File

@ -1,367 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include "vf_dlopen.h"
#include "filterutils.h"
/*
* rectangle
*
* usage: --vf=dlopen=/path/to/rectangle.so
*
* provides an editable rectangle
* NOTE: unix only, and requires xterm to be installed. Don't ask.
*/
typedef struct
{
int x, y, w, h;
int step;
int inpid;
int infd;
int ansimode;
int rectmode;
} privdata;
enum {
RECTMODE_LINES = 0,
RECTMODE_BOX,
RECTMODE_COUNT
};
static int put_image(struct vf_dlopen_context *ctx)
{
privdata *priv = ctx->priv;
unsigned int p;
assert(ctx->inpic.planes == ctx->outpic->planes);
for (p = 0; p < ctx->outpic->planes; ++p) {
assert(ctx->inpic.planewidth[p] == ctx->outpic->planewidth[p]);
assert(ctx->inpic.planeheight[p] == ctx->outpic->planeheight[p]);
}
char data;
while(read(priv->infd, &data, sizeof(data)) > 0) {
// printf("\nMODE: %d, CHAR: %d (%c)\n", priv->ansimode, data, data);
switch(priv->ansimode) {
case 0: // initial
switch(data) {
case 27: priv->ansimode = 1; break;
default: priv->ansimode = 0; break;
}
break;
case 1: // seen ESC
switch(data) {
case '[': priv->ansimode = 2; break;
default: priv->ansimode = 0; break;
}
break;
case 2: // seen ESC [
switch(data) {
case 'D': priv->ansimode = 0; data = 'h'; break; // arrow
case 'B': priv->ansimode = 0; data = 'j'; break; // arrow
case 'A': priv->ansimode = 0; data = 'k'; break; // arrow
case 'C': priv->ansimode = 0; data = 'l'; break; // arrow
case 'd': priv->ansimode = 0; data = 'H'; break; // rxvt shift-arrow
case 'b': priv->ansimode = 0; data = 'J'; break; // rxvt shift-arrow
case 'a': priv->ansimode = 0; data = 'K'; break; // rxvt shift-arrow
case 'c': priv->ansimode = 0; data = 'L'; break; // rxvt shift-arrow
case '1': priv->ansimode = 3; break;
default: priv->ansimode = -1; break;
}
break;
case 3: // seen ESC [ 1
switch(data) {
case ';': priv->ansimode = 4; break;
default: priv->ansimode = -1; break;
}
break;
case 4: // seen ESC [ 1 ;
switch(data) {
case '2': priv->ansimode = 5; break;
default: priv->ansimode = -1; break;
}
break;
case 5: // seen ESC [ 1 ; 2
switch(data) {
case 'D': priv->ansimode = 0; data = 'H'; break; // xterm shift-arrow
case 'B': priv->ansimode = 0; data = 'J'; break; // xterm shift-arrow
case 'A': priv->ansimode = 0; data = 'K'; break; // xterm shift-arrow
case 'C': priv->ansimode = 0; data = 'L'; break; // xterm shift-arrow
default: priv->ansimode = -1; break;
}
break;
case -1: // wait for end of ESC [ sequence
if((data > '9' || data < '0') && (data != ';')) {
priv->ansimode = 0;
data = 0; // do not process
}
break;
}
if(priv->ansimode == 0) {
switch(data) {
case 'h': case 'D': priv->x -= priv->step; priv->w += priv->step; break;
case 'j': case 'B': priv->y += priv->step; priv->h -= priv->step; break;
case 'k': case 'A': priv->y -= priv->step; priv->h += priv->step; break;
case 'l': case 'C': priv->x += priv->step; priv->w -= priv->step; break;
case 'H': case 'd': priv->w -= priv->step; break;
case 'J': case 'b': priv->h += priv->step; break;
case 'K': case 'a': priv->h -= priv->step; break;
case 'L': case 'c': priv->w += priv->step; break;
case ' ': priv->step ^= 9; break;
case 9: ++priv->rectmode; priv->rectmode %= RECTMODE_COUNT; break;
}
}
}
// apply limits
if(priv->x < 0) {
priv->w += priv->x;
priv->x = 0;
}
if(priv->y < 0) {
priv->h += priv->y;
priv->y = 0;
}
if(priv->w < 0) {
priv->w = 0;
}
if(priv->h < 0) {
priv->h = 0;
}
if(priv->x >= (int) ctx->inpic.planewidth[0]) {
priv->x = ctx->inpic.planewidth[0] - 1;
}
if(priv->y >= (int) ctx->inpic.planeheight[0]) {
priv->y = ctx->inpic.planeheight[0] - 1;
}
if(priv->x + priv->w > (int) ctx->inpic.planewidth[0]) {
priv->w = ctx->inpic.planewidth[0] - priv->x;
}
if(priv->y + priv->h > (int) ctx->inpic.planeheight[0]) {
priv->h = ctx->inpic.planeheight[0] - priv->y;
}
// apply step
priv->x = ((priv->x + priv->step - 1) / priv->step) * priv->step;
priv->y = ((priv->y + priv->step - 1) / priv->step) * priv->step;
priv->w = (priv->w / priv->step) * priv->step;
priv->h = (priv->h / priv->step) * priv->step;
// print
printf("\nRECTANGLE: -vf crop=%d:%d:%d:%d\n", priv->w, priv->h, priv->x, priv->y);
// copy picture
for (p = 0; p < ctx->outpic->planes; ++p) {
copy_plane(
ctx->outpic->plane[p], ctx->outpic->planestride[p],
ctx->inpic.plane[p], ctx->inpic.planestride[p],
ctx->inpic.planewidth[p], ctx->inpic.planeheight[p]
);
}
ctx->outpic->pts = ctx->inpic.pts;
// draw rectangle
#define PUT_PIXEL(x,y) \
do { \
int x_ = (x); \
int y_ = (y); \
if(x_ >= 0 && y_ >= 0 && x_ < (int) ctx->outpic->planewidth[0] && y_ < (int) ctx->outpic->planeheight[0]) { \
ctx->outpic->plane[0][y_ * ctx->outpic->planestride[0] + x_] ^= 0x80; \
} \
} while(0)
switch(priv->rectmode) {
case RECTMODE_LINES:
{
unsigned int i;
unsigned int n;
if(priv->w > priv->h)
n = priv->h / 3;
else
n = priv->w / 3;
if(n > 64)
n = 64;
for (i = 0; i < n; ++i) {
// topleft
PUT_PIXEL(priv->x + i, priv->y);
if(i)
PUT_PIXEL(priv->x, priv->y + i);
// topright
PUT_PIXEL(priv->x + priv->w - 1 - i, priv->y);
if(i)
PUT_PIXEL(priv->x + priv->w - 1, priv->y + i);
// bottomright
PUT_PIXEL(priv->x + priv->w - 1 - i, priv->y + priv->h - 1);
if(i)
PUT_PIXEL(priv->x + priv->w - 1, priv->y + priv->h - 1 - i);
// bottomleft
PUT_PIXEL(priv->x + i, priv->y + priv->h - 1);
if(i)
PUT_PIXEL(priv->x, priv->y + priv->h - 1 - i);
}
}
break;
case RECTMODE_BOX:
{
int x, y;
for(y = 0; y < priv->y; ++y) {
for(x = 0; x < (int) ctx->outpic->planewidth[0]; ++x) {
PUT_PIXEL(x, y);
}
}
for(y = priv->y; y < priv->y + priv->h; ++y) {
for(x = 0; x < priv->x; ++x) {
PUT_PIXEL(x, y);
}
for(x = priv->x + priv->w; x < (int) ctx->outpic->planewidth[0]; ++x) {
PUT_PIXEL(x, y);
}
}
for(y = priv->y + priv->h; y < (int) ctx->outpic->planeheight[0]; ++y) {
for(x = 0; x < (int) ctx->outpic->planewidth[0]; ++x) {
PUT_PIXEL(x, y);
}
}
}
break;
}
return 1;
}
int config(struct vf_dlopen_context *ctx)
{
privdata *priv = ctx->priv;
if(priv->w == 0 || priv->h == 0) {
priv->x = 0;
priv->y = 0;
priv->w = ctx->in_width;
priv->h = ctx->in_height;
}
printf("\nRECTANGLE: reconfigured\n");
if(priv->inpid == 0) {
int fd[2];
if(pipe(fd)) {
perror("pipe");
return -1;
}
priv->inpid = fork();
if(priv->inpid < 0) {
perror("fork");
return -1;
}
if(priv->inpid == 0) {
close(fd[0]);
if(fd[1] != 3) {
dup2(fd[1], 3);
close(fd[1]);
}
execlp("xterm", "xterm",
"-geometry", "40x10",
"-e",
"echo \"rectangle.so control window\";"
"echo \"\";"
"echo \"Arrow or hjkl: top left corner\";"
"echo \"Shift-Arrow or HJKL: bottom right corner\";"
"echo \"SPACE: toggle 8-px alignment\";"
"echo \"TAB: toggle rectangle display\";"
"echo \"\";"
"stty raw -echo;"
"cat >&3",
NULL
);
_exit(1);
}
close(fd[1]);
priv->infd = fd[0];
int flags;
if(fcntl(priv->infd, F_GETFL, &flags)) {
perror("fcntl F_GETFL");
close(priv->infd);
kill(priv->inpid, SIGTERM);
waitpid(priv->inpid, NULL, 0);
priv->inpid = 0;
}
flags |= O_NONBLOCK;
if(fcntl(priv->infd, F_SETFL, flags)) {
perror("fcntl F_SETFL");
close(priv->infd);
kill(priv->inpid, SIGTERM);
waitpid(priv->inpid, NULL, 0);
priv->inpid = 0;
}
}
return 1;
}
void uninit(struct vf_dlopen_context *ctx)
{
privdata *priv = ctx->priv;
if(priv->inpid) {
close(priv->infd);
kill(priv->inpid, SIGTERM);
waitpid(priv->inpid, NULL, 0);
priv->inpid = 0;
}
printf("\nRECTANGLE: finished\n");
free(priv);
}
int vf_dlopen_getcontext(struct vf_dlopen_context *ctx, int argc, const char **argv)
{
VF_DLOPEN_CHECK_VERSION(ctx);
(void) argc;
(void) argv;
static struct vf_dlopen_formatpair map[] = {
{ "yuv420p", "yuv420p" },
{ NULL, NULL }
};
privdata *priv = calloc(1,sizeof(privdata));
priv->step = 8;
if(argc >= 1)
priv->w = atoi(argv[0]);
if(argc >= 2)
priv->h = atoi(argv[1]);
if(argc >= 3)
priv->x = atoi(argv[2]);
if(argc >= 4)
priv->y = atoi(argv[3]);
ctx->priv = priv;
ctx->format_mapping = map;
ctx->config = config;
ctx->put_image = put_image;
ctx->uninit = uninit;
return 1;
}

View File

@ -1,269 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vf_dlopen.h"
#include "filterutils.h"
#define MIN(a,b) ((a)<(b)?(a):(b))
/*
* telecine filter
*
* usage: --vf=dlopen=/path/to/telecine.so:t:23
*
* Parameter: first parameter is "t" for top field first, "b" for bottom field first
* then digits (0-9) for how many fields a frame is to be displayed
*
* Typical patterns (see http://en.wikipedia.org/wiki/Telecine):
*
* NTSC output (30i):
* 27.5p: 32222
* 24p: 23 (classic)
* 24p: 2332 (preferred)
* 20p: 33
* 18p: 334
* 16p: 3444
*
* PAL output (25i):
* 27.5p: 12222
* 24p: 222222222223 ("Euro pulldown")
* 16.67p: 33
* 16p: 33333334
*/
typedef struct {
int firstfield;
const char *pattern;
unsigned int pattern_pos;
unsigned char *buffer_plane[4];
size_t buffer_size[4];
int pts_num;
int pts_denom;
int occupied;
double lastpts_in;
double lastpts_out;
int first_frame_of_group;
} tc_data_t;
static int tc_config(struct vf_dlopen_context *ctx)
{
// we may return more than one pic!
tc_data_t *tc = ctx->priv;
const char *p;
int max = 0;
tc->pts_num = 0;
tc->pts_denom = 0;
for (p = tc->pattern; *p; ++p) {
if (*p - '0' > max)
max = *p - '0';
tc->pts_num += 2;
tc->pts_denom += *p - '0';
}
ctx->out_cnt = (max + 1) / 2;
printf(
"Telecine pattern %s yields up to %d frames per frame, pts advance factor: %d/%d\n",
tc->pattern, ctx->out_cnt, tc->pts_num, tc->pts_denom);
return 1;
}
static int tc_put_image(struct vf_dlopen_context *ctx)
{
tc_data_t *tc = ctx->priv;
unsigned p;
unsigned np = ctx->outpic[0].planes;
assert(ctx->inpic.planes == ctx->outpic[0].planes);
int need_reinit = 0;
// fix buffers
for (p = 0; p < np; ++p) {
size_t sz = ctx->inpic.planestride[p] * ctx->inpic.planeheight[p];
if (sz != tc->buffer_size[p]) {
if (p == 0 && tc->buffer_plane[p])
printf("WARNING: reinitializing telecine buffers.\n");
tc->buffer_plane[p] = realloc(tc->buffer_plane[p], sz);
tc->buffer_size[p] = sz;
need_reinit = 1;
}
}
// too big pts change? reinit
if (ctx->inpic.pts < tc->lastpts_in || ctx->inpic.pts > tc->lastpts_in + 0.5)
need_reinit = 1;
if (need_reinit) {
// initialize telecine
tc->pattern_pos = 0;
tc->occupied = 0;
tc->lastpts_in = ctx->inpic.pts;
tc->lastpts_out = ctx->inpic.pts;
}
int len = tc->pattern[tc->pattern_pos] - '0';
unsigned nout;
double delta = ctx->inpic.pts - tc->lastpts_in;
tc->lastpts_in = ctx->inpic.pts;
for (nout = 0; nout < ctx->out_cnt; ++nout) {
for (p = 0; p < np; ++p) {
assert(ctx->inpic.planewidth[p] == ctx->outpic[nout].planewidth[p]);
assert(ctx->inpic.planeheight[p] == ctx->outpic[nout].planeheight[p]);
}
}
nout = 0;
if (tc->pattern_pos == 0 && !tc->occupied) {
// at the start of the pattern, reset pts
// printf("pts reset: %f -> %f (delta: %f)\n", tc->lastpts_out, ctx->inpic.pts, ctx->inpic.pts - tc->lastpts_out);
tc->lastpts_out = ctx->inpic.pts;
tc->first_frame_of_group = 1;
}
++tc->pattern_pos;
if (!tc->pattern[tc->pattern_pos])
tc->pattern_pos = 0;
if (len == 0) {
// do not output any field from this frame
return 0;
}
if (tc->occupied) {
for (p = 0; p < np; ++p) {
// fill in the EARLIER field from the buffered pic
copy_plane(
&ctx->outpic[nout].plane[p][ctx->outpic[nout].planestride[p] * tc->firstfield],
ctx->outpic[nout].planestride[p] * 2,
&tc->buffer_plane[p][ctx->inpic.planestride[p] * tc->firstfield],
ctx->inpic.planestride[p] * 2,
MIN(ctx->inpic.planestride[p], ctx->outpic[nout].planestride[p]),
(ctx->inpic.planeheight[p] - tc->firstfield + 1) / 2
);
// fill in the LATER field from the new pic
copy_plane(
&ctx->outpic[nout].plane[p][ctx->outpic[nout].planestride[p] * !tc->firstfield],
ctx->outpic[nout].planestride[p] * 2,
&ctx->inpic.plane[p][ctx->inpic.planestride[p] * !tc->firstfield],
ctx->inpic.planestride[p] * 2,
MIN(ctx->inpic.planestride[p], ctx->outpic[nout].planestride[p]),
(ctx->inpic.planeheight[p] - !tc->firstfield + 1) / 2
);
}
if (tc->first_frame_of_group)
tc->first_frame_of_group = 0;
else
tc->lastpts_out += (delta * tc->pts_num) / tc->pts_denom;
ctx->outpic[nout].pts = tc->lastpts_out;
// printf("pts written: %f\n", ctx->outpic[nout].pts);
++nout;
--len;
tc->occupied = 0;
}
while (len >= 2) {
// output THIS image as-is
for (p = 0; p < np; ++p)
copy_plane(
ctx->outpic[nout].plane[p], ctx->outpic[nout].planestride[p],
ctx->inpic.plane[p], ctx->inpic.planestride[p],
MIN(ctx->inpic.planestride[p], ctx->outpic[nout].planestride[p]),
ctx->inpic.planeheight[p]
);
if (tc->first_frame_of_group)
tc->first_frame_of_group = 0;
else
tc->lastpts_out += (delta * tc->pts_num) / tc->pts_denom;
ctx->outpic[nout].pts = tc->lastpts_out;
// printf("pts written: %f\n", ctx->outpic[nout].pts);
++nout;
len -= 2;
}
if (len >= 1) {
// copy THIS image to the buffer, we need it later
for (p = 0; p < np; ++p)
copy_plane(
&tc->buffer_plane[p][0], ctx->inpic.planestride[p],
&ctx->inpic.plane[p][0], ctx->inpic.planestride[p],
ctx->inpic.planestride[p],
ctx->inpic.planeheight[p]
);
tc->occupied = 1;
}
return nout;
}
void tc_uninit(struct vf_dlopen_context *ctx)
{
tc_data_t *tc = ctx->priv;
free(tc->buffer_plane[3]);
free(tc->buffer_plane[2]);
free(tc->buffer_plane[1]);
free(tc->buffer_plane[0]);
free(tc);
}
int vf_dlopen_getcontext(struct vf_dlopen_context *ctx, int argc, const char **argv)
{
VF_DLOPEN_CHECK_VERSION(ctx);
const char *a0 = (argc < 1) ? "t" : argv[0];
const char *a1 = (argc < 2) ? "23" : argv[1];
if (!a0[0] || a0[1] || !a1[0] || argc > 2)
return -1;
tc_data_t *tc = calloc(1,sizeof(tc_data_t));
if (a0[0] == 't')
tc->firstfield = 0;
else if (a0[0] == 'b')
tc->firstfield = 1;
else {
printf("telecine: invalid first field\n");
free(tc);
return -1;
}
tc->pattern = a1;
const char *p;
for (p = tc->pattern; *p; ++p)
if (*p < '0' || *p > '9') {
printf("telecine: invalid pattern\n");
free(tc);
return -1;
}
ctx->priv = tc;
ctx->format_mapping = NULL; // anything goes
ctx->config = tc_config;
ctx->put_image = tc_put_image;
ctx->uninit = tc_uninit;
return 1;
}

View File

@ -1,177 +0,0 @@
/*
* Copyright (c) 2012 Rudolf Polzer <divVerent@xonotic.org>
*
* This file is part of mpv's vf_dlopen examples.
*
* mpv's vf_dlopen examples are free software; you can redistribute them and/or
* modify them under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of the
* License, or (at your option) any later version.
*
* mpv's vf_dlopen examples are distributed in the hope that they will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv's vf_dlopen examples; if not, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vf_dlopen.h"
#include "filterutils.h"
/*
* tile filter
*
* usage: --vf=dlopen=/path/to/tile.so:4:3
*
* only supports rgb24 and yuv420p for now
* in theory can support any format where rows are a multiple of bytes, and the
* multiple is known
*/
#define ALLFORMATS \
/* format bytes xmul ymul */ \
FORMAT("rgb24" , 3, 1, 1) \
FORMAT("yuv420p", 1, 2, 2)
typedef struct {
int rows, cols;
unsigned char *buffer_plane[4];
size_t buffer_size[4];
int pos;
int pixelbytes;
} tile_data_t;
static int tile_config(struct vf_dlopen_context *ctx)
{
// we may return more than one pic!
tile_data_t *tile = ctx->priv;
ctx->out_width = tile->cols * ctx->in_width;
ctx->out_height = tile->rows * ctx->in_height;
ctx->out_d_width = tile->cols * ctx->in_d_width;
ctx->out_d_height = tile->rows * ctx->in_d_height;
#define FORMAT(fmt,sz,xmul,ymul) \
if (!strcmp(ctx->in_fmt, fmt)) { \
if (ctx->in_width % xmul || ctx->in_height % ymul) { \
printf("Format " fmt " requires width to be a multiple of %d and height to be a multiple of %d\n", \
xmul, ymul); \
return -1; \
} \
tile->pixelbytes = sz; \
} else
ALLFORMATS
#undef FORMAT
{
printf("Format %s is not in the list, how come?\n", ctx->in_fmt);
return -1;
}
return 1;
}
static int tile_put_image(struct vf_dlopen_context *ctx)
{
tile_data_t *tile = ctx->priv;
unsigned p;
unsigned np = ctx->outpic[0].planes;
assert(ctx->inpic.planes == ctx->outpic[0].planes);
// fix buffers
for (p = 0; p < np; ++p) {
size_t sz = ctx->outpic->planestride[p] * ctx->outpic->planeheight[p];
if (sz != tile->buffer_size[p]) {
if (p == 0 && tile->buffer_plane[p])
printf("WARNING: reinitializing output buffers.\n");
tile->buffer_plane[p] = realloc(tile->buffer_plane[p], sz);
tile->buffer_size[p] = sz;
tile->pos = 0;
}
}
for (p = 0; p < np; ++p) {
assert(ctx->inpic.planewidth[p] * tile->cols == ctx->outpic->planewidth[p]);
assert(ctx->inpic.planeheight[p] * tile->rows == ctx->outpic->planeheight[p]);
}
// copy this frame
for (p = 0; p < np; ++p)
copy_plane(
&tile->buffer_plane[p][ctx->outpic->planestride[p] * ctx->inpic.planeheight[p] * (tile->pos / tile->cols) + tile->pixelbytes * ctx->inpic.planewidth[p] * (tile->pos % tile->cols)],
ctx->outpic->planestride[p],
ctx->inpic.plane[p],
ctx->inpic.planestride[p],
tile->pixelbytes * ctx->inpic.planewidth[p],
ctx->inpic.planeheight[p]
);
++tile->pos;
if (tile->pos == tile->rows * tile->cols) {
// copy THIS image to the buffer, we need it later
for (p = 0; p < np; ++p)
copy_plane(
ctx->outpic->plane[p], ctx->outpic->planestride[p],
&tile->buffer_plane[p][0], ctx->outpic->planestride[p],
tile->pixelbytes * ctx->outpic->planewidth[p],
ctx->outpic->planeheight[p]
);
ctx->outpic->pts = ctx->inpic.pts;
tile->pos = 0;
return 1;
}
return 0;
}
void tile_uninit(struct vf_dlopen_context *ctx)
{
tile_data_t *tile = ctx->priv;
free(tile->buffer_plane[3]);
free(tile->buffer_plane[2]);
free(tile->buffer_plane[1]);
free(tile->buffer_plane[0]);
free(tile);
}
int vf_dlopen_getcontext(struct vf_dlopen_context *ctx, int argc, const char **argv)
{
VF_DLOPEN_CHECK_VERSION(ctx);
if (argc != 2)
return -1;
tile_data_t *tile = calloc(1,sizeof(tile_data_t));
tile->cols = atoi(argv[0]);
tile->rows = atoi(argv[1]);
if (!tile->rows || !tile->cols) {
printf("tile: invalid rows/cols\n");
free(tile);
return -1;
}
ctx->priv = tile;
static struct vf_dlopen_formatpair map[] = {
#define FORMAT(fmt,sz,xmul,ymul) {fmt, NULL},
ALLFORMATS
#undef FORMAT
{NULL, NULL}
};
ctx->format_mapping = map;
ctx->config = tile_config;
ctx->put_image = tile_put_image;
ctx->uninit = tile_uninit;
return 1;
}

View File

@ -54,7 +54,6 @@ extern const vf_info_t vf_info_pullup;
extern const vf_info_t vf_info_sub;
extern const vf_info_t vf_info_yadif;
extern const vf_info_t vf_info_stereo3d;
extern const vf_info_t vf_info_dlopen;
extern const vf_info_t vf_info_lavfi;
extern const vf_info_t vf_info_lavfi_bridge;
extern const vf_info_t vf_info_vaapi;
@ -86,9 +85,6 @@ static const vf_info_t *const filter_list[] = {
&vf_info_dsize,
&vf_info_sub,
&vf_info_buffer,
#if HAVE_DLOPEN
&vf_info_dlopen,
#endif
#if HAVE_VAPOURSYNTH_CORE && HAVE_VAPOURSYNTH
&vf_info_vapoursynth,
#endif

View File

@ -1,350 +0,0 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <assert.h>
#include "config.h"
#include "common/msg.h"
#include "video/img_format.h"
#include "video/mp_image.h"
#include "vf.h"
#include "options/m_option.h"
#include "vf_dlopen.h"
#ifdef _WIN32
# include <windows.h>
# define DLLOpen(name) LoadLibraryA(name)
# define DLLClose(handle) FreeLibrary(handle)
# define DLLSymbol(handle, name) ((void *)GetProcAddress(handle, name))
#else
# include <dlfcn.h>
# define DLLOpen(name) dlopen(name, RTLD_NOW)
# define DLLClose(handle) dlclose(handle)
# define DLLSymbol(handle, name) dlsym(handle, name)
#endif
struct vf_priv_s {
char *cfg_dllname;
int cfg_argc;
char *cfg_argv[16];
void *dll;
struct vf_dlopen_context filter;
// output mp_image_t stuff
mp_image_t *outpic[FILTER_MAX_OUTCNT];
// generic
unsigned int out_cnt, out_width, out_height;
// multi frame output
unsigned int outbufferpos;
unsigned int outbufferlen;
mp_image_t *outbuffermpi;
unsigned int outfmt;
int argc;
};
struct fmtname {
const char *name;
enum mp_imgfmt fmt;
};
//===========================================================================//
static void set_imgprop(struct vf_dlopen_picdata *out, const mp_image_t *mpi)
{
int i;
out->planes = mpi->num_planes;
for (i = 0; i < mpi->num_planes; ++i) {
out->plane[i] = mpi->planes[i];
out->planestride[i] = mpi->stride[i];
out->planewidth[i] =
i ? (/*mpi->chroma_width*/ mpi->w >> mpi->fmt.chroma_xs) : mpi->w;
out->planeheight[i] =
i ? (/*mpi->chroma_height*/ mpi->h >> mpi->fmt.chroma_ys) : mpi->h;
out->planexshift[i] = i ? mpi->fmt.chroma_xs : 0;
out->planeyshift[i] = i ? mpi->fmt.chroma_ys : 0;
}
}
static int reconfig(struct vf_instance *vf, struct mp_image_params *in,
struct mp_image_params *out)
{
mp_image_params_get_dsize(in, &vf->priv->filter.in_d_width,
&vf->priv->filter.in_d_height);
vf->priv->filter.in_width = in->w;
vf->priv->filter.in_height = in->h;
vf->priv->filter.in_fmt = talloc_strdup(vf, mp_imgfmt_to_name(in->imgfmt));
vf->priv->filter.out_width = vf->priv->filter.in_width;
vf->priv->filter.out_height = vf->priv->filter.in_height;
vf->priv->filter.out_d_width = vf->priv->filter.in_d_width;
vf->priv->filter.out_d_height = vf->priv->filter.in_d_height;
vf->priv->filter.out_fmt = NULL;
vf->priv->filter.out_cnt = 1;
if (!vf->priv->filter.in_fmt) {
MP_ERR(vf, "invalid input/output format\n");
return -1;
}
if (vf->priv->filter.config && vf->priv->filter.config(&vf->priv->filter) < 0) {
MP_ERR(vf, "filter config failed\n");
return -1;
}
// copy away stuff to sanity island
vf->priv->out_cnt = vf->priv->filter.out_cnt;
vf->priv->out_width = vf->priv->filter.out_width;
vf->priv->out_height = vf->priv->filter.out_height;
if (vf->priv->filter.out_fmt)
vf->priv->outfmt = mp_imgfmt_from_name(bstr0(vf->priv->filter.out_fmt), false);
else {
struct vf_dlopen_formatpair *p = vf->priv->filter.format_mapping;
vf->priv->outfmt = 0;
if (p) {
for (; p->from; ++p) {
// TODO support pixel format classes in matching
if (!strcmp(p->from, vf->priv->filter.in_fmt)) {
if(p->to)
vf->priv->outfmt = mp_imgfmt_from_name(bstr0(p->to), false);
else
vf->priv->outfmt = mp_imgfmt_from_name(bstr0(p->from), false);
break;
}
}
} else
vf->priv->outfmt = in->imgfmt;
vf->priv->filter.out_fmt =
talloc_strdup(vf, mp_imgfmt_to_name(vf->priv->outfmt));
}
if (!vf->priv->outfmt) {
MP_ERR(vf, "filter config wants an unsupported output format\n");
return -1;
}
if (!vf->priv->out_cnt || vf->priv->out_cnt > FILTER_MAX_OUTCNT) {
MP_ERR(vf, "filter config wants to yield zero or too many output frames\n");
return -1;
}
for (int i = 0; i < vf->priv->out_cnt; ++i) {
talloc_free(vf->priv->outpic[i]);
vf->priv->outpic[i] =
mp_image_alloc(vf->priv->outfmt,
vf->priv->out_width, vf->priv->out_height);
if (!vf->priv->outpic[i])
return -1; // OOM
talloc_steal(vf, vf->priv->outpic[i]);
set_imgprop(&vf->priv->filter.outpic[i], vf->priv->outpic[i]);
}
*out = *in;
out->w = vf->priv->out_width;
out->h = vf->priv->out_height;
mp_image_params_set_dsize(out, vf->priv->filter.out_d_width,
vf->priv->filter.out_d_height);
out->imgfmt = vf->priv->outfmt;
return 0;
}
static void uninit(struct vf_instance *vf)
{
if (vf->priv->filter.uninit)
vf->priv->filter.uninit(&vf->priv->filter);
memset(&vf->priv->filter, 0, sizeof(vf->priv->filter));
if (vf->priv->dll) {
DLLClose(vf->priv->dll);
vf->priv->dll = NULL;
}
}
static int filter(struct vf_instance *vf, struct mp_image *mpi)
{
if (!mpi)
return 0;
set_imgprop(&vf->priv->filter.inpic, mpi);
vf->priv->filter.inpic_qscale = NULL;
vf->priv->filter.inpic_qscalestride = 0;
vf->priv->filter.inpic_qscaleshift = 0;
vf->priv->filter.inpic.pts = mpi->pts;
struct mp_image *out[FILTER_MAX_OUTCNT] = {0};
for (int n = 0; n < vf->priv->out_cnt; n++) {
out[n] = vf_alloc_out_image(vf);
if (!out[n]) {
talloc_free(mpi);
return -1;
}
mp_image_copy_attributes(out[n], mpi);
set_imgprop(&vf->priv->filter.outpic[n], out[n]);
}
// more than one out pic
int ret = vf->priv->filter.put_image(&vf->priv->filter);
if (ret < 0)
ret = 0;
assert(ret <= vf->priv->out_cnt);
for (int n = 0; n < ret; n++) {
out[n]->pts = vf->priv->filter.outpic[n].pts;
vf_add_output_frame(vf, out[n]);
}
for (int n = ret; n < FILTER_MAX_OUTCNT; n++) {
talloc_free(out[n]);
}
talloc_free(mpi);
return 0;
}
//===========================================================================//
static int query_format(struct vf_instance *vf, unsigned int fmt)
{
if (IMGFMT_IS_HWACCEL(fmt))
return 0; // these can't really be filtered
if (fmt == IMGFMT_PAL8)
return 0; // we don't have palette support, sorry
const char *fmtname = mp_imgfmt_to_name(fmt);
if (!fmtname)
return 0;
struct vf_dlopen_formatpair *p = vf->priv->filter.format_mapping;
unsigned int outfmt = 0;
if (p) {
for (; p->from; ++p) {
// TODO support pixel format classes in matching
if (!strcmp(p->from, fmtname)) {
if (p->to)
outfmt = mp_imgfmt_from_name(bstr0(p->to), false);
else
outfmt = mp_imgfmt_from_name(bstr0(p->from), false);
break;
}
}
} else {
outfmt = fmt;
}
if (!outfmt)
return 0;
return vf_next_query_format(vf, outfmt);
}
static int vf_open(vf_instance_t *vf)
{
int i;
if (!vf->priv->cfg_dllname) {
MP_ERR(vf, "usage: --vf=dlopen=/path/to/filename.so:args\n");
return 0;
}
MP_WARN(vf, "This filter is deprecated. No replacement.\n");
vf->priv->dll = DLLOpen(vf->priv->cfg_dllname);
if (!vf->priv->dll) {
MP_ERR(vf, "library not found: %s\n",
vf->priv->cfg_dllname);
return 0;
}
vf_dlopen_getcontext_func *func =
(vf_dlopen_getcontext_func *) DLLSymbol(vf->priv->dll, "vf_dlopen_getcontext");
if (!func) {
MP_ERR(vf, "library is not a filter: %s\n",
vf->priv->cfg_dllname);
return 0;
}
memset(&vf->priv->filter, 0, sizeof(vf->priv->filter));
vf->priv->filter.major_version = VF_DLOPEN_MAJOR_VERSION;
vf->priv->filter.minor_version = VF_DLOPEN_MINOR_VERSION;
// count arguments
for (vf->priv->cfg_argc = sizeof(vf->priv->cfg_argv) / sizeof(vf->priv->cfg_argv[0]);
vf->priv->cfg_argc > 0 && !vf->priv->cfg_argv[vf->priv->cfg_argc - 1];
--vf->priv->cfg_argc)
;
// fix empty arguments
for (i = 0; i < vf->priv->cfg_argc; ++i)
if (vf->priv->cfg_argv[i] == NULL)
vf->priv->cfg_argv[i] = talloc_strdup (vf->priv, "");
if (func(&vf->priv->filter, vf->priv->cfg_argc,
(const char **)vf->priv->cfg_argv) < 0)
{
MP_ERR(vf, "function did not create a filter: %s\n",
vf->priv->cfg_dllname);
return 0;
}
if (!vf->priv->filter.put_image) {
MP_ERR(vf, "function did not create a filter that can put images: %s\n",
vf->priv->cfg_dllname);
return 0;
}
vf->filter_ext = filter;
vf->query_format = query_format;
vf->reconfig = reconfig;
vf->uninit = uninit;
return 1;
}
#define OPT_BASE_STRUCT struct vf_priv_s
static const m_option_t vf_opts_fields[] = {
OPT_STRING("dll", cfg_dllname, 0),
OPT_STRING("a0", cfg_argv[0], 0),
OPT_STRING("a1", cfg_argv[1], 0),
OPT_STRING("a2", cfg_argv[2], 0),
OPT_STRING("a3", cfg_argv[3], 0),
OPT_STRING("a4", cfg_argv[4], 0),
OPT_STRING("a5", cfg_argv[5], 0),
OPT_STRING("a6", cfg_argv[6], 0),
OPT_STRING("a7", cfg_argv[7], 0),
OPT_STRING("a8", cfg_argv[8], 0),
OPT_STRING("a9", cfg_argv[9], 0),
OPT_STRING("a10", cfg_argv[10], 0),
OPT_STRING("a11", cfg_argv[11], 0),
OPT_STRING("a12", cfg_argv[12], 0),
OPT_STRING("a13", cfg_argv[13], 0),
OPT_STRING("a14", cfg_argv[14], 0),
OPT_STRING("a15", cfg_argv[15], 0),
{0}
};
const vf_info_t vf_info_dlopen = {
.description = "Dynamic library filter",
.name = "dlopen",
.open = vf_open,
.priv_size = sizeof(struct vf_priv_s),
.options = vf_opts_fields,
};
//===========================================================================//

View File

@ -1,93 +0,0 @@
/*
* Warning: this filter is deprecated.
*/
#ifndef VF_DLOPEN_H
#define VF_DLOPEN_H
// when doing a two-way compatible change, don't change these
// when doing a backwards compatible change, bump minor version
// when doing an incompatible change, bump major version and zero minor version
#define VF_DLOPEN_MAJOR_VERSION 1
#define VF_DLOPEN_MINOR_VERSION 0
#if VF_DLOPEN_MINOR_VERSION > 0
# define VF_DLOPEN_CHECK_VERSION(ctx) \
do { \
if (ctx->major_version != VF_DLOPEN_MAJOR_VERSION || \
ctx->minor_version < VF_DLOPEN_MINOR_VERSION) \
return -1; \
} while (0)
#else
// workaround for "comparison is always false" warning
# define VF_DLOPEN_CHECK_VERSION(ctx) \
do { \
if (ctx->major_version != VF_DLOPEN_MAJOR_VERSION) \
return -1; \
} while (0)
#endif
// some common valid pixel format names:
// "gray": 8 bit grayscale
// "yuv420p": planar YUV, U and V planes have an xshift and yshift of 1
// "rgb24": packed RGB24
struct vf_dlopen_formatpair {
const char *from;
const char *to; // if NULL, this means identical format as source
};
#define FILTER_MAX_OUTCNT 16
struct vf_dlopen_picdata {
unsigned int planes;
unsigned char *plane[4];
signed int planestride[4];
unsigned int planewidth[4];
unsigned int planeheight[4];
unsigned int planexshift[4];
unsigned int planeyshift[4];
double pts;
};
struct vf_dlopen_context {
unsigned short major_version;
unsigned short minor_version;
void *priv;
struct vf_dlopen_formatpair *format_mapping;
// {NULL, NULL} terminated list of supported format pairs
// if NULL, anything goes
int (*config)(struct vf_dlopen_context *ctx); // -1 = error
// image config is put into the in_* members before calling this
// fills in the out_* members (which are preinitialized for an identity vf_dlopen_context)
int (*put_image)(struct vf_dlopen_context *ctx); // returns number of images written, or negative on error
// before this is called, inpic_* and outpic_* are filled
void (*uninit)(struct vf_dlopen_context *ctx);
unsigned int in_width;
unsigned int in_height;
unsigned int in_d_width;
unsigned int in_d_height;
const char *in_fmt;
unsigned int out_width;
unsigned int out_height;
unsigned int out_d_width;
unsigned int out_d_height;
const char *out_fmt;
unsigned int out_cnt;
struct vf_dlopen_picdata inpic;
char *inpic_qscale;
unsigned int inpic_qscalestride;
unsigned int inpic_qscaleshift;
struct vf_dlopen_picdata outpic[FILTER_MAX_OUTCNT];
};
typedef int (vf_dlopen_getcontext_func)(struct vf_dlopen_context *ctx, int argc, const char **argv); // negative on error
vf_dlopen_getcontext_func vf_dlopen_getcontext;
#endif

View File

@ -78,12 +78,6 @@ build_options = [
'desc': 'dlopen',
'deps_any': [ 'libdl', 'os-win32', 'os-cygwin' ],
'func': check_true
}, {
'name': '--vf-dlopen-filters',
'desc': 'compilation of default filters for vf_dlopen',
'deps': [ 'dlopen' ],
'default': 'disable',
'func': check_true
}, {
'name': '--zsh-comp',
'desc': 'zsh completion',

View File

@ -324,7 +324,6 @@ def build(ctx):
( "video/filter/vf_buffer.c" ),
( "video/filter/vf_crop.c" ),
( "video/filter/vf_d3d11vpp.c", "d3d-hwaccel" ),
( "video/filter/vf_dlopen.c", "dlopen" ),
( "video/filter/vf_dsize.c" ),
( "video/filter/vf_eq.c" ),
( "video/filter/vf_expand.c" ),
@ -598,17 +597,6 @@ def build(ctx):
ctx.install_as(ctx.env.LIBDIR + '/pkgconfig/mpv.pc', 'libmpv/mpv.pc')
if ctx.dependency_satisfied("vf-dlopen-filters"):
dlfilters = "telecine tile rectangle framestep ildetect".split()
for dlfilter in dlfilters:
ctx(
target = dlfilter,
source = ['TOOLS/vf_dlopen/'+dlfilter+'.c',
'TOOLS/vf_dlopen/filterutils.c'],
includes = [ctx.srcnode.abspath() + '/video/filter'],
features = 'c cshlib',
install_path = ctx.env.LIBDIR + '/mpv' )
if ctx.dependency_satisfied('html-build'):
_build_html(ctx)