From ae9a3e33aafaa0d708d54e2c42a563e45dadb0f7 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 30 Sep 2013 22:27:37 +0200 Subject: command: add commands for displaying overlays Requested by github issue #255. Does not work where mmap is not available (i.e. Windows). --- mpvcore/command.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++-- mpvcore/command.h | 1 + mpvcore/input/input.c | 5 ++ mpvcore/input/input.h | 3 ++ mpvcore/mplayer.c | 2 + 5 files changed, 148 insertions(+), 4 deletions(-) (limited to 'mpvcore') 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 +#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); -- cgit v1.2.3