summaryrefslogtreecommitdiffstats
path: root/TOOLS/vf_dlopen/tile.c
diff options
context:
space:
mode:
authorRudolf Polzer <divverent@xonotic.org>2012-08-23 12:32:13 +0200
committerwm4 <wm4@nowhere>2012-08-23 13:13:53 +0200
commit2adc81f0a2459a565437009ff6f4ace1dca3d46c (patch)
tree4fb92807ad61980fac5230d670af374aaaa9d082 /TOOLS/vf_dlopen/tile.c
parent2e6450c7cc88f1e39034ac111e9b54a421bca661 (diff)
downloadmpv-2adc81f0a2459a565437009ff6f4ace1dca3d46c.tar.bz2
mpv-2adc81f0a2459a565437009ff6f4ace1dca3d46c.tar.xz
vf_dlopen: add a generic filter to load external filters
Usage: -vf dlopen=filename.so:args... Examples of such filters are provided in TOOLS/vf_dlopen/
Diffstat (limited to 'TOOLS/vf_dlopen/tile.c')
-rw-r--r--TOOLS/vf_dlopen/tile.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/TOOLS/vf_dlopen/tile.c b/TOOLS/vf_dlopen/tile.c
new file mode 100644
index 0000000000..0e9a14fb62
--- /dev/null
+++ b/TOOLS/vf_dlopen/tile.c
@@ -0,0 +1,157 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vf_dlopen.h"
+#include "filterutils.h"
+
+/*
+ * tile filter
+ *
+ * usage: -vf dlopen=./tile.so:4:3
+ *
+ * only supports rgb24 and yv12 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("yv12", 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 = malloc(sizeof(tile_data_t));
+ memset(tile, 0, sizeof(*tile));
+
+ 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;
+}