summaryrefslogtreecommitdiffstats
path: root/mpvcore
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-09-30 22:27:37 +0200
committerwm4 <wm4@nowhere>2013-10-05 22:46:55 +0200
commitae9a3e33aafaa0d708d54e2c42a563e45dadb0f7 (patch)
treedcdd7a4ee2e1b6456c69b02a90a15fad410fbff3 /mpvcore
parentfd49edccf811de0d6c61f30d8b2b524f8df93b36 (diff)
downloadmpv-ae9a3e33aafaa0d708d54e2c42a563e45dadb0f7.tar.bz2
mpv-ae9a3e33aafaa0d708d54e2c42a563e45dadb0f7.tar.xz
command: add commands for displaying overlays
Requested by github issue #255. Does not work where mmap is not available (i.e. Windows).
Diffstat (limited to 'mpvcore')
-rw-r--r--mpvcore/command.c141
-rw-r--r--mpvcore/command.h1
-rw-r--r--mpvcore/input/input.c5
-rw-r--r--mpvcore/input/input.h3
-rw-r--r--mpvcore/mplayer.c2
5 files changed, 148 insertions, 4 deletions
diff --git a/mpvcore/command.c b/mpvcore/command.c
index e1c7e6e79e..038e58bc8d 100644
--- a/mpvcore/command.c
+++ b/mpvcore/command.c
@@ -65,11 +65,21 @@
#include "stream/stream_dvd.h"
#endif
#include "screenshot.h"
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
#include "mpvcore/mp_core.h"
#include "mp_lua.h"
+struct command_ctx {
+ int events;
+
+#define OVERLAY_MAX_ID 64
+ void *overlay_map[OVERLAY_MAX_ID];
+};
+
static int edit_filters(struct MPContext *mpctx, enum stream_type mediatype,
const char *cmd, const char *arg);
static int set_filters(struct MPContext *mpctx, enum stream_type mediatype,
@@ -2227,6 +2237,113 @@ static int edit_filters_osd(struct MPContext *mpctx, enum stream_type mediatype,
return r;
}
+#ifdef HAVE_SYS_MMAN_H
+
+static int ext2_sub_find(struct MPContext *mpctx, int id)
+{
+ struct command_ctx *cmd = mpctx->command_ctx;
+ struct sub_bitmaps *sub = &mpctx->osd->external2;
+ void *p = NULL;
+ if (id >= 0 && id < OVERLAY_MAX_ID)
+ p = cmd->overlay_map[id];
+ if (sub && p) {
+ for (int n = 0; n < sub->num_parts; n++) {
+ if (sub->parts[n].bitmap == p)
+ return n;
+ }
+ }
+ return -1;
+}
+
+static int ext2_sub_alloc(struct MPContext *mpctx)
+{
+ struct osd_state *osd = mpctx->osd;
+ struct sub_bitmaps *sub = &osd->external2;
+ struct sub_bitmap b = {0};
+ MP_TARRAY_APPEND(osd, sub->parts, sub->num_parts, b);
+ return sub->num_parts - 1;
+}
+
+static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
+ char *file, int offset, char *fmt, int w, int h,
+ int stride)
+{
+ struct command_ctx *cmd = mpctx->command_ctx;
+ struct osd_state *osd = mpctx->osd;
+ if (strcmp(fmt, "bgra") != 0) {
+ MP_ERR(mpctx, "overlay_add: unsupported OSD format '%s'\n", fmt);
+ return -1;
+ }
+ if (id < 0 || id >= OVERLAY_MAX_ID) {
+ MP_ERR(mpctx, "overlay_add: invalid id %d\n", id);
+ return -1;
+ }
+ int fd = -1;
+ bool close_fd = true;
+ if (file[0] == '@') {
+ char *end;
+ fd = strtol(&file[1], &end, 10);
+ if (!file[1] || end[0])
+ fd = -1;
+ close_fd = false;
+ } else {
+ fd = open(file, O_RDONLY | O_BINARY);
+ }
+ void *p = mmap(NULL, h * stride, PROT_READ, MAP_SHARED, fd, offset);
+ if (fd >= 0 && close_fd)
+ close(fd);
+ if (!p) {
+ MP_ERR(mpctx, "overlay_add: could not open or map '%s'\n", file);
+ return -1;
+ }
+ int index = ext2_sub_find(mpctx, id);
+ if (index < 0)
+ index = ext2_sub_alloc(mpctx);
+ if (index < 0) {
+ munmap(p, h * stride);
+ return -1;
+ }
+ cmd->overlay_map[id] = p;
+ osd->external2.parts[index] = (struct sub_bitmap) {
+ .bitmap = p,
+ .stride = stride,
+ .x = x, .y = y,
+ .w = w, .h = h,
+ .dw = w, .dh = h,
+ };
+ osd->external2.bitmap_id = osd->external2.bitmap_pos_id = 1;
+ osd->external2.format = SUBBITMAP_RGBA;
+ osd->want_redraw = true;
+ return 0;
+}
+
+static void overlay_remove(struct MPContext *mpctx, int id)
+{
+ struct command_ctx *cmd = mpctx->command_ctx;
+ struct osd_state *osd = mpctx->osd;
+ int index = ext2_sub_find(mpctx, id);
+ if (index >= 0) {
+ struct sub_bitmaps *sub = &osd->external2;
+ struct sub_bitmap *part = &sub->parts[index];
+ munmap(part->bitmap, part->h * part->stride);
+ MP_TARRAY_REMOVE_AT(sub->parts, sub->num_parts, index);
+ cmd->overlay_map[id] = NULL;
+ sub->bitmap_id = sub->bitmap_pos_id = 1;
+ }
+}
+
+static void overlay_uninit(struct MPContext *mpctx)
+{
+ for (int id = 0; id < OVERLAY_MAX_ID; id++)
+ overlay_remove(mpctx, id);
+}
+
+#else
+
+static void overlay_uninit(struct MPContext *mpctx){}
+
+#endif
+
void run_command(MPContext *mpctx, mp_cmd_t *cmd)
{
struct MPOpts *opts = mpctx->opts;
@@ -2775,6 +2892,19 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
}
break;
+#ifdef HAVE_SYS_MMAN_H
+ case MP_CMD_OVERLAY_ADD:
+ overlay_add(mpctx,
+ cmd->args[0].v.i, cmd->args[1].v.i, cmd->args[2].v.i,
+ cmd->args[3].v.s, cmd->args[4].v.i, cmd->args[5].v.s,
+ cmd->args[6].v.i, cmd->args[7].v.i, cmd->args[8].v.i);
+ break;
+
+ case MP_CMD_OVERLAY_REMOVE:
+ overlay_remove(mpctx, cmd->args[0].v.i);
+ break;
+#endif
+
case MP_CMD_COMMAND_LIST: {
for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
run_command(mpctx, sub);
@@ -2802,13 +2932,16 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
}
}
-struct command_ctx {
- int events;
-};
+void command_uninit(struct MPContext *mpctx)
+{
+ overlay_uninit(mpctx);
+ talloc_free(mpctx->command_ctx);
+ mpctx->command_ctx = NULL;
+}
void command_init(struct MPContext *mpctx)
{
- mpctx->command_ctx = talloc_zero(mpctx, struct command_ctx);
+ mpctx->command_ctx = talloc_zero(NULL, struct command_ctx);
}
// Notify that a property might have changed.
diff --git a/mpvcore/command.h b/mpvcore/command.h
index dfdc066ac7..d3469fc131 100644
--- a/mpvcore/command.h
+++ b/mpvcore/command.h
@@ -23,6 +23,7 @@ struct MPContext;
struct mp_cmd;
void command_init(struct MPContext *mpctx);
+void command_uninit(struct MPContext *mpctx);
void run_command(struct MPContext *mpctx, struct mp_cmd *cmd);
char *mp_property_expand_string(struct MPContext *mpctx, const char *str);
diff --git a/mpvcore/input/input.c b/mpvcore/input/input.c
index c78447c4bf..4ce7fe0156 100644
--- a/mpvcore/input/input.c
+++ b/mpvcore/input/input.c
@@ -232,6 +232,11 @@ static const mp_cmd_t mp_cmds[] = {
{ MP_CMD_SCRIPT_DISPATCH, "script_dispatch", { ARG_STRING, ARG_INT } },
+ { MP_CMD_OVERLAY_ADD, "overlay_add",
+ { ARG_INT, ARG_INT, ARG_INT, ARG_STRING, ARG_INT, ARG_STRING, ARG_INT,
+ ARG_INT, ARG_INT }},
+ { MP_CMD_OVERLAY_REMOVE, "overlay_remove", { ARG_INT } },
+
{0}
};
diff --git a/mpvcore/input/input.h b/mpvcore/input/input.h
index 33c269c1a7..dc308ff9f6 100644
--- a/mpvcore/input/input.h
+++ b/mpvcore/input/input.h
@@ -89,6 +89,9 @@ enum mp_command_type {
/// Internal for Lua scripts
MP_CMD_SCRIPT_DISPATCH,
+ MP_CMD_OVERLAY_ADD,
+ MP_CMD_OVERLAY_REMOVE,
+
// Internal
MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p
};
diff --git a/mpvcore/mplayer.c b/mpvcore/mplayer.c
index b82e6a9e5d..4d3f24d057 100644
--- a/mpvcore/mplayer.c
+++ b/mpvcore/mplayer.c
@@ -563,6 +563,8 @@ static MP_NORETURN void exit_player(struct MPContext *mpctx,
cocoa_set_input_context(NULL);
#endif
+ command_uninit(mpctx);
+
mp_input_uninit(mpctx->input);
osd_free(mpctx->osd);