diff options
Diffstat (limited to 'player/screenshot.c')
-rw-r--r-- | player/screenshot.c | 115 |
1 files changed, 91 insertions, 24 deletions
diff --git a/player/screenshot.c b/player/screenshot.c index b5bd5ea787..4c705556e4 100644 --- a/player/screenshot.c +++ b/player/screenshot.c @@ -28,6 +28,8 @@ #include "core.h" #include "command.h" #include "misc/bstr.h" +#include "misc/dispatch.h" +#include "misc/thread_pool.h" #include "common/msg.h" #include "options/path.h" #include "video/mp_image.h" @@ -50,6 +52,8 @@ typedef struct screenshot_ctx { bool osd; int frameno; + + struct mp_thread_pool *thread_pool; } screenshot_ctx; void screenshot_init(struct MPContext *mpctx) @@ -63,6 +67,7 @@ void screenshot_init(struct MPContext *mpctx) #define SMSG_OK 0 #define SMSG_ERR 1 +#define SMSG_V 2 static void screenshot_msg(screenshot_ctx *ctx, int status, const char *msg, ...) PRINTF_ATTRIBUTE(3,4); @@ -77,8 +82,14 @@ static void screenshot_msg(screenshot_ctx *ctx, int status, const char *msg, s = talloc_vasprintf(NULL, msg, ap); va_end(ap); - MP_MSG(ctx->mpctx, status == SMSG_ERR ? MSGL_ERR : MSGL_INFO, "%s\n", s); - if (ctx->osd) + int msg_level = MSGL_INFO; + if (status == SMSG_ERR) + msg_level = MSGL_ERR; + if (status == SMSG_V) + msg_level = MSGL_V; + + MP_MSG(ctx->mpctx, msg_level, "%s\n", s); + if (ctx->osd && msg_level <= MSGL_INFO) set_osd_msg(ctx->mpctx, 1, ctx->mpctx->opts->osd_duration, "%s", s); talloc_free(s); @@ -92,6 +103,75 @@ static char *stripext(void *talloc_ctx, const char *s) return talloc_asprintf(talloc_ctx, "%.*s", (int)(end - s), s); } +struct screenshot_item { + bool on_thread; + struct MPContext *mpctx; + const char *filename; + struct mp_image *img; + struct image_writer_opts opts; +}; + +#define LOCK(item) if (item->on_thread) mp_dispatch_lock(item->mpctx->dispatch); +#define UNLOCK(item) if (item->on_thread) mp_dispatch_unlock(item->mpctx->dispatch); + +static void write_screenshot_thread(void *arg) +{ + struct screenshot_item *item = arg; + screenshot_ctx *ctx = item->mpctx->screenshot_ctx; + + LOCK(item) + screenshot_msg(ctx, SMSG_OK, "Screenshot: '%s'", item->filename); + UNLOCK(item) + + if (!item->img || !write_image(item->img, &item->opts, item->filename, + item->mpctx->log)) + { + LOCK(item) + screenshot_msg(ctx, SMSG_ERR, "Error writing screenshot!"); + UNLOCK(item) + } + + if (item->on_thread) { + mp_dispatch_lock(item->mpctx->dispatch); + screenshot_msg(ctx, SMSG_V, "Screenshot writing done."); + item->mpctx->outstanding_async -= 1; + mp_wakeup_core(item->mpctx); + mp_dispatch_unlock(item->mpctx->dispatch); + } + + talloc_free(item); +} + +static void write_screenshot(struct MPContext *mpctx, struct mp_image *img, + const char *filename, struct image_writer_opts *opts, + bool async) +{ + screenshot_ctx *ctx = mpctx->screenshot_ctx; + struct image_writer_opts *gopts = mpctx->opts->screenshot_image_opts; + + struct screenshot_item *item = talloc_zero(NULL, struct screenshot_item); + *item = (struct screenshot_item){ + .mpctx = mpctx, + .filename = talloc_strdup(item, filename), + .img = talloc_steal(item, mp_image_new_ref(img)), + .opts = opts ? *opts : *gopts, + }; + + if (async) { + if (!ctx->thread_pool) + ctx->thread_pool = mp_thread_pool_create(ctx, 1); + if (ctx->thread_pool) { + item->on_thread = true; + mpctx->outstanding_async += 1; + mp_thread_pool_queue(ctx->thread_pool, write_screenshot_thread, item); + item = NULL; + } + } + + if (item) + write_screenshot_thread(item); +} + #ifdef _WIN32 #define ILLEGAL_FILENAME_CHARS "?\"/\\<>*|:" #else @@ -315,21 +395,6 @@ static void add_subs(struct MPContext *mpctx, struct mp_image *image) OSD_DRAW_SUB_ONLY, image); } -static void screenshot_save(struct MPContext *mpctx, struct mp_image *image) -{ - screenshot_ctx *ctx = mpctx->screenshot_ctx; - - struct image_writer_opts *opts = mpctx->opts->screenshot_image_opts; - - char *filename = gen_fname(ctx, image_writer_file_ext(opts)); - if (filename) { - screenshot_msg(ctx, SMSG_OK, "Screenshot: '%s'", filename); - if (!write_image(image, opts, filename, mpctx->log)) - screenshot_msg(ctx, SMSG_ERR, "Error writing screenshot!"); - talloc_free(filename); - } -} - static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode) { struct mp_image *image = NULL; @@ -376,7 +441,7 @@ struct mp_image *screenshot_get_rgb(struct MPContext *mpctx, int mode) } void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode, - bool osd) + bool osd, bool async) { screenshot_ctx *ctx = mpctx->screenshot_ctx; struct image_writer_opts opts = *mpctx->opts->screenshot_image_opts; @@ -392,9 +457,7 @@ void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode, screenshot_msg(ctx, SMSG_ERR, "Taking screenshot failed."); goto end; } - screenshot_msg(ctx, SMSG_OK, "Screenshot: '%s'", filename); - if (!write_image(image, &opts, filename, mpctx->log)) - screenshot_msg(ctx, SMSG_ERR, "Error writing screenshot!"); + write_screenshot(mpctx, image, filename, &opts, async); talloc_free(image); end: @@ -402,7 +465,7 @@ end: } void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame, - bool osd) + bool osd, bool async) { screenshot_ctx *ctx = mpctx->screenshot_ctx; @@ -423,7 +486,11 @@ void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame, struct mp_image *image = screenshot_get(mpctx, mode); if (image) { - screenshot_save(mpctx, image); + struct image_writer_opts *opts = mpctx->opts->screenshot_image_opts; + char *filename = gen_fname(ctx, image_writer_file_ext(opts)); + if (filename) + write_screenshot(mpctx, image, filename, NULL, async); + talloc_free(filename); } else { screenshot_msg(ctx, SMSG_ERR, "Taking screenshot failed."); } @@ -439,5 +506,5 @@ void screenshot_flip(struct MPContext *mpctx) return; ctx->each_frame = false; - screenshot_request(mpctx, ctx->mode, true, ctx->osd); + screenshot_request(mpctx, ctx->mode, true, ctx->osd, false); } |