mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
44d5a26bd6
commit
3e899b102e
109
player/command.c
109
player/command.c
|
@ -78,7 +78,7 @@ struct command_ctx {
|
||||||
struct cycle_counter *cycle_counters;
|
struct cycle_counter *cycle_counters;
|
||||||
int num_cycle_counters;
|
int num_cycle_counters;
|
||||||
|
|
||||||
struct sub_bitmap *overlays;
|
struct overlay *overlays;
|
||||||
int num_overlays;
|
int num_overlays;
|
||||||
// One of these is in use by the OSD; the other one exists so that the
|
// One of these is in use by the OSD; the other one exists so that the
|
||||||
// bitmap list can be manipulated without additional synchronization.
|
// bitmap list can be manipulated without additional synchronization.
|
||||||
|
@ -86,6 +86,12 @@ struct command_ctx {
|
||||||
struct sub_bitmaps *overlay_osd_current;
|
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,
|
static int edit_filters(struct MPContext *mpctx, enum stream_type mediatype,
|
||||||
const char *cmd, const char *arg);
|
const char *cmd, const char *arg);
|
||||||
static int set_filters(struct MPContext *mpctx, enum stream_type mediatype,
|
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;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_SYS_MMAN_H
|
|
||||||
|
|
||||||
static void recreate_overlays(struct MPContext *mpctx)
|
static void recreate_overlays(struct MPContext *mpctx)
|
||||||
{
|
{
|
||||||
struct command_ctx *cmd = mpctx->command_ctx;
|
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"
|
// overlay array can have unused entries, but parts list must be "packed"
|
||||||
new->num_parts = 0;
|
new->num_parts = 0;
|
||||||
for (int n = 0; n < cmd->num_overlays; n++) {
|
for (int n = 0; n < cmd->num_overlays; n++) {
|
||||||
struct sub_bitmap *s = &cmd->overlays[n];
|
struct overlay *o = &cmd->overlays[n];
|
||||||
if (s->bitmap)
|
if (o->osd.bitmap)
|
||||||
MP_TARRAY_APPEND(cmd, new->parts, new->num_parts, *s);
|
MP_TARRAY_APPEND(cmd, new->parts, new->num_parts, o->osd);
|
||||||
}
|
}
|
||||||
cmd->overlay_osd_current = new;
|
cmd->overlay_osd_current = new;
|
||||||
osd_set_external2(mpctx->osd, cmd->overlay_osd_current);
|
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,
|
static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
|
||||||
char *file, int offset, char *fmt, int w, int h,
|
char *file, int offset, char *fmt, int w, int h,
|
||||||
int stride)
|
int stride)
|
||||||
{
|
{
|
||||||
struct command_ctx *cmd = mpctx->command_ctx;
|
|
||||||
int r = -1;
|
int r = -1;
|
||||||
if (strcmp(fmt, "bgra") != 0) {
|
if (strcmp(fmt, "bgra") != 0) {
|
||||||
MP_ERR(mpctx, "overlay_add: unsupported OSD format '%s'\n", fmt);
|
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);
|
MP_ERR(mpctx, "overlay_add: invalid id %d\n", id);
|
||||||
goto error;
|
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;
|
int fd = -1;
|
||||||
bool close_fd = true;
|
bool close_fd = true;
|
||||||
|
void *p = (void *)-1;
|
||||||
if (file[0] == '@') {
|
if (file[0] == '@') {
|
||||||
char *end;
|
char *end;
|
||||||
fd = strtol(&file[1], &end, 10);
|
fd = strtol(&file[1], &end, 10);
|
||||||
|
@ -3286,30 +3329,20 @@ static int overlay_add(struct MPContext *mpctx, int id, int x, int y,
|
||||||
} else {
|
} else {
|
||||||
fd = open(file, O_RDONLY | O_BINARY | O_CLOEXEC);
|
fd = open(file, O_RDONLY | O_BINARY | O_CLOEXEC);
|
||||||
}
|
}
|
||||||
void *p = mmap(NULL, h * stride, PROT_READ, MAP_SHARED, fd, offset);
|
if (fd >= 0) {
|
||||||
if (fd >= 0 && close_fd)
|
#if HAVE_SYS_MMAN_H
|
||||||
close(fd);
|
overlay.map_size = h * stride;
|
||||||
if (!p) {
|
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);
|
MP_ERR(mpctx, "overlay_add: could not open or map '%s'\n", file);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
MP_TARRAY_GROW(cmd, cmd->overlays, id);
|
overlay.osd.bitmap = p;
|
||||||
while (cmd->num_overlays <= id)
|
replace_overlay(mpctx, id, &overlay);
|
||||||
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);
|
|
||||||
r = 0;
|
r = 0;
|
||||||
error:
|
error:
|
||||||
return r;
|
return r;
|
||||||
|
@ -3318,16 +3351,8 @@ error:
|
||||||
static void overlay_remove(struct MPContext *mpctx, int id)
|
static void overlay_remove(struct MPContext *mpctx, int id)
|
||||||
{
|
{
|
||||||
struct command_ctx *cmd = mpctx->command_ctx;
|
struct command_ctx *cmd = mpctx->command_ctx;
|
||||||
if (id >= 0 && id < cmd->num_overlays) {
|
if (id >= 0 && id < cmd->num_overlays)
|
||||||
struct sub_bitmap *overlay = &cmd->overlays[id];
|
replace_overlay(mpctx, id, &(struct overlay){0});
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void overlay_uninit(struct MPContext *mpctx)
|
static void overlay_uninit(struct MPContext *mpctx)
|
||||||
|
@ -3340,12 +3365,6 @@ static void overlay_uninit(struct MPContext *mpctx)
|
||||||
osd_set_external2(mpctx->osd, NULL);
|
osd_set_external2(mpctx->osd, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static void overlay_uninit(struct MPContext *mpctx){}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct cycle_counter {
|
struct cycle_counter {
|
||||||
char **args;
|
char **args;
|
||||||
int counter;
|
int counter;
|
||||||
|
@ -3955,7 +3974,6 @@ int run_command(MPContext *mpctx, mp_cmd_t *cmd)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HAVE_SYS_MMAN_H
|
|
||||||
case MP_CMD_OVERLAY_ADD:
|
case MP_CMD_OVERLAY_ADD:
|
||||||
overlay_add(mpctx,
|
overlay_add(mpctx,
|
||||||
cmd->args[0].v.i, cmd->args[1].v.i, cmd->args[2].v.i,
|
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:
|
case MP_CMD_OVERLAY_REMOVE:
|
||||||
overlay_remove(mpctx, cmd->args[0].v.i);
|
overlay_remove(mpctx, cmd->args[0].v.i);
|
||||||
break;
|
break;
|
||||||
#endif
|
|
||||||
|
|
||||||
case MP_CMD_COMMAND_LIST: {
|
case MP_CMD_COMMAND_LIST: {
|
||||||
for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
|
for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
|
||||||
|
|
Loading…
Reference in New Issue