summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-10-03 01:22:07 +0200
committerwm4 <wm4@nowhere>2014-10-03 01:22:07 +0200
commit3e899b102e4644baf347520d98ff44fd8a842fec (patch)
tree5b2e6e6476b61648e413ff3f5bc5414410082c57
parent44d5a26bd6976115cf9b10461e9b5aef4fe143cb (diff)
downloadmpv-3e899b102e4644baf347520d98ff44fd8a842fec.tar.bz2
mpv-3e899b102e4644baf347520d98ff44fd8a842fec.tar.xz
command: restructure overlay_add code
Somewhat more flexible: now there's a separate overlay struct, and you don't need to coerce all state into struct sub_bitmap. Also, removing the previous mapping (munmap call) is now all in one place, the replace_overlay function. Makes the next commit easier to implement.
-rw-r--r--player/command.c109
1 files changed, 63 insertions, 46 deletions
diff --git a/player/command.c b/player/command.c
index ed36ab4d69..ef75594f7b 100644
--- a/player/command.c
+++ b/player/command.c
@@ -78,7 +78,7 @@ struct command_ctx {
struct cycle_counter *cycle_counters;
int num_cycle_counters;
- struct sub_bitmap *overlays;
+ struct overlay *overlays;
int num_overlays;
// One of these is in use by the OSD; the other one exists so that the
// bitmap list can be manipulated without additional synchronization.
@@ -86,6 +86,12 @@ struct command_ctx {
struct sub_bitmaps *overlay_osd_current;
};
+struct overlay {
+ bool need_unmap : 1;
+ size_t map_size;
+ struct sub_bitmap osd;
+};
+
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,
@@ -3240,8 +3246,6 @@ static int edit_filters_osd(struct MPContext *mpctx, enum stream_type mediatype,
return r;
}
-#if HAVE_SYS_MMAN_H
-
static void recreate_overlays(struct MPContext *mpctx)
{
struct command_ctx *cmd = mpctx->command_ctx;
@@ -3253,19 +3257,45 @@ static void recreate_overlays(struct MPContext *mpctx)
// overlay array can have unused entries, but parts list must be "packed"
new->num_parts = 0;
for (int n = 0; n < cmd->num_overlays; n++) {
- struct sub_bitmap *s = &cmd->overlays[n];
- if (s->bitmap)
- MP_TARRAY_APPEND(cmd, new->parts, new->num_parts, *s);
+ struct overlay *o = &cmd->overlays[n];
+ if (o->osd.bitmap)
+ MP_TARRAY_APPEND(cmd, new->parts, new->num_parts, o->osd);
}
cmd->overlay_osd_current = new;
osd_set_external2(mpctx->osd, cmd->overlay_osd_current);
}
+// Set overlay with the given ID to the contents as described by "new".
+static void replace_overlay(struct MPContext *mpctx, int id, struct overlay *new)
+{
+ struct command_ctx *cmd = mpctx->command_ctx;
+ assert(id >= 0);
+ if (id >= cmd->num_overlays) {
+ MP_TARRAY_GROW(cmd, cmd->overlays, id);
+ while (cmd->num_overlays <= id)
+ cmd->overlays[cmd->num_overlays++] = (struct overlay){0};
+ }
+
+ struct overlay *ptr = &cmd->overlays[id];
+ struct overlay old = *ptr;
+
+ if (!ptr->osd.bitmap && !new->osd.bitmap)
+ return; // don't need to recreate or unmap
+
+ *ptr = *new;
+ recreate_overlays(mpctx);
+
+#if HAVE_SYS_MMAN_H
+ // Do this afterwards, so we never unmap while the OSD is using it.
+ if (old.osd.bitmap && old.map_size)
+ munmap(old.osd.bitmap, old.map_size);
+#endif
+}
+
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;
int r = -1;
if (strcmp(fmt, "bgra") != 0) {
MP_ERR(mpctx, "overlay_add: unsupported OSD format '%s'\n", fmt);
@@ -3275,8 +3305,21 @@ static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
MP_ERR(mpctx, "overlay_add: invalid id %d\n", id);
goto error;
}
+ if (w < 0 || h < 0 || stride < w * 4 || (stride % 4)) {
+ MP_ERR(mpctx, "overlay_add: inconsistent parameters\n");
+ goto error;
+ }
+ struct overlay overlay = {
+ .osd = {
+ .stride = stride,
+ .x = x, .y = y,
+ .w = w, .h = h,
+ .dw = w, .dh = h,
+ },
+ };
int fd = -1;
bool close_fd = true;
+ void *p = (void *)-1;
if (file[0] == '@') {
char *end;
fd = strtol(&file[1], &end, 10);
@@ -3286,30 +3329,20 @@ static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
} else {
fd = open(file, O_RDONLY | O_BINARY | O_CLOEXEC);
}
- void *p = mmap(NULL, h * stride, PROT_READ, MAP_SHARED, fd, offset);
- if (fd >= 0 && close_fd)
- close(fd);
- if (!p) {
+ if (fd >= 0) {
+#if HAVE_SYS_MMAN_H
+ overlay.map_size = h * stride;
+ p = mmap(NULL, overlay.map_size, PROT_READ, MAP_SHARED, fd, offset);
+#endif
+ if (close_fd)
+ close(fd);
+ }
+ if (!p || p == (void *)-1) {
MP_ERR(mpctx, "overlay_add: could not open or map '%s'\n", file);
goto error;
}
- MP_TARRAY_GROW(cmd, cmd->overlays, id);
- while (cmd->num_overlays <= id)
- cmd->overlays[cmd->num_overlays++].bitmap = NULL;
- struct sub_bitmap *overlay = &cmd->overlays[id];
- void *prev = overlay->bitmap;
- size_t prev_size = overlay->stride * overlay->h;
- *overlay = (struct sub_bitmap) {
- .bitmap = p,
- .stride = stride,
- .x = x, .y = y,
- .w = w, .h = h,
- .dw = w, .dh = h,
- };
- recreate_overlays(mpctx);
- // unmap afterwards, to avoid unmapping while OSD uses the memory
- if (prev)
- munmap(prev, prev_size);
+ overlay.osd.bitmap = p;
+ replace_overlay(mpctx, id, &overlay);
r = 0;
error:
return r;
@@ -3318,16 +3351,8 @@ error:
static void overlay_remove(struct MPContext *mpctx, int id)
{
struct command_ctx *cmd = mpctx->command_ctx;
- if (id >= 0 && id < cmd->num_overlays) {
- struct sub_bitmap *overlay = &cmd->overlays[id];
- if (overlay->bitmap) {
- void *ptr = overlay->bitmap;
- size_t ptr_size = overlay->h * overlay->stride;
- overlay->bitmap = NULL; // remove
- recreate_overlays(mpctx);
- munmap(ptr, ptr_size);
- }
- }
+ if (id >= 0 && id < cmd->num_overlays)
+ replace_overlay(mpctx, id, &(struct overlay){0});
}
static void overlay_uninit(struct MPContext *mpctx)
@@ -3340,12 +3365,6 @@ static void overlay_uninit(struct MPContext *mpctx)
osd_set_external2(mpctx->osd, NULL);
}
-#else
-
-static void overlay_uninit(struct MPContext *mpctx){}
-
-#endif
-
struct cycle_counter {
char **args;
int counter;
@@ -3955,7 +3974,6 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
break;
}
-#if 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,
@@ -3966,7 +3984,6 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
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)