summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/input.rst3
-rw-r--r--input/input.c3
-rw-r--r--libvo/video_out.h2
-rw-r--r--libvo/vo_xv.c1
-rw-r--r--screenshot.c66
-rw-r--r--screenshot.h9
6 files changed, 65 insertions, 19 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst
index 74c4929684..63593c53ca 100644
--- a/DOCS/man/en/input.rst
+++ b/DOCS/man/en/input.rst
@@ -104,6 +104,9 @@ screenshot [single|each-frame] [video|window]
Save the video image, in its original resolution. Typically without
OSD or subtitles, but the exact behavior depends on the selected video
output.
+ <subtitles>
+ Like ``video``, but add subtitles. Some video outputs may still include
+ the OSD in the output under certain circumstances.
<window>
Save the contents of the mplayer window. Typically scaled, with OSD and
subtitles. The exact behavior depends on the selected video output, and
diff --git a/input/input.c b/input/input.c
index f2b601fdbe..ea9d2376b2 100644
--- a/input/input.c
+++ b/input/input.c
@@ -162,7 +162,8 @@ static const mp_cmd_t mp_cmds[] = {
OARG_CHOICE(0, ({"single", 0}, {"0", 0},
{"each-frame", 1}, {"1", 1})),
OARG_CHOICE(0, ({"video", 0}, {"0", 0},
- {"window", 1}, {"1", 1})),
+ {"window", 1}, {"1", 1},
+ {"subtitles", 2})),
}},
{ MP_CMD_LOADFILE, "loadfile", {
ARG_STRING,
diff --git a/libvo/video_out.h b/libvo/video_out.h
index ffb5c0c4f3..1c48b5fb06 100644
--- a/libvo/video_out.h
+++ b/libvo/video_out.h
@@ -105,6 +105,8 @@ struct voctrl_screenshot_args {
// image data directly.
// Is never NULL. (Failure has to be indicated by returning VO_FALSE.)
struct mp_image *out_image;
+ // Whether the VO rendered OSD/subtitles into out_image
+ bool has_osd;
};
typedef struct {
diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c
index 92ac9a2461..8095490f4a 100644
--- a/libvo/vo_xv.c
+++ b/libvo/vo_xv.c
@@ -679,6 +679,7 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_SCREENSHOT: {
struct voctrl_screenshot_args *args = data;
args->out_image = get_screenshot(vo);
+ args->has_osd = !ctx->have_image_copy;
return true;
}
}
diff --git a/screenshot.c b/screenshot.c
index 1f2b0694fc..c60b17649b 100644
--- a/screenshot.c
+++ b/screenshot.c
@@ -36,13 +36,17 @@
#include "libmpcodecs/vf.h"
#include "libvo/video_out.h"
#include "image_writer.h"
+#include "sub/sub.h"
#include "libvo/csputils.h"
+#define MODE_FULL_WINDOW 1
+#define MODE_SUBTITLES 2
+
typedef struct screenshot_ctx {
struct MPContext *mpctx;
- int full_window;
+ int mode;
int each_frame;
int using_vf_screenshot;
@@ -230,7 +234,35 @@ static char *gen_fname(screenshot_ctx *ctx, const char *file_ext)
}
}
-void screenshot_save(struct MPContext *mpctx, struct mp_image *image)
+static struct mp_image *add_subs(struct MPContext *mpctx,
+ struct mp_image *image,
+ struct mp_csp_details *csp)
+{
+ if (!(image->flags & MP_IMGFLAG_ALLOCATED)) {
+ struct mp_image *new_image = alloc_mpi(image->width, image->height,
+ image->imgfmt);
+ copy_mpi(new_image, image);
+ new_image->w = image->w;
+ new_image->h = image->h;
+ image = new_image;
+ }
+
+ double sar = (double)image->width / image->height;
+ double dar = (double)image->w / image->h;
+ struct mp_osd_res res = {
+ .w = image->width,
+ .h = image->height,
+ .display_par = sar / dar,
+ .video_par = dar / sar,
+ };
+ osd_draw_on_image(mpctx->osd, res, mpctx->osd->vo_pts,
+ OSD_DRAW_SUB_ONLY, image, csp);
+
+ return image;
+}
+
+static void screenshot_save(struct MPContext *mpctx, struct mp_image *image,
+ bool with_subs)
{
screenshot_ctx *ctx = mpctx->screenshot_ctx;
@@ -239,22 +271,29 @@ void screenshot_save(struct MPContext *mpctx, struct mp_image *image)
struct image_writer_opts *opts = mpctx->opts.screenshot_image_opts;
+ struct mp_image *new_image = image;
+ if (with_subs)
+ new_image = add_subs(mpctx, new_image, &colorspace);
+
char *filename = gen_fname(ctx, image_writer_file_ext(opts));
if (filename) {
mp_msg(MSGT_CPLAYER, MSGL_INFO, "*** screenshot '%s' ***\n", filename);
- if (!write_image(image, &colorspace, opts, filename))
+ if (!write_image(new_image, &colorspace, opts, filename))
mp_msg(MSGT_CPLAYER, MSGL_ERR, "\nError writing screenshot!\n");
talloc_free(filename);
}
+
+ if (new_image != image)
+ free_mp_image(new_image);
}
static void vf_screenshot_callback(void *pctx, struct mp_image *image)
{
struct MPContext *mpctx = (struct MPContext *)pctx;
screenshot_ctx *ctx = mpctx->screenshot_ctx;
- screenshot_save(mpctx, image);
+ screenshot_save(mpctx, image, ctx->mode);
if (ctx->each_frame)
- screenshot_request(mpctx, 0, ctx->full_window);
+ screenshot_request(mpctx, 0, ctx->mode);
}
static bool force_vf(struct MPContext *mpctx)
@@ -270,26 +309,31 @@ static bool force_vf(struct MPContext *mpctx)
return false;
}
-void screenshot_request(struct MPContext *mpctx, bool each_frame,
- bool full_window)
+void screenshot_request(struct MPContext *mpctx, bool each_frame, int mode)
{
if (mpctx->video_out && mpctx->video_out->config_ok) {
screenshot_ctx *ctx = mpctx->screenshot_ctx;
ctx->using_vf_screenshot = 0;
+ if (mode == MODE_SUBTITLES && mpctx->osd->render_subs_in_filter)
+ mode = 0;
+
if (each_frame) {
ctx->each_frame = !ctx->each_frame;
- ctx->full_window = full_window;
+ ctx->mode = mode;
if (!ctx->each_frame)
return;
}
- struct voctrl_screenshot_args args = { .full_window = full_window };
+ struct voctrl_screenshot_args args =
+ { .full_window = (mode == MODE_FULL_WINDOW) };
if (!force_vf(mpctx)
&& vo_control(mpctx->video_out, VOCTRL_SCREENSHOT, &args) == true)
{
- screenshot_save(mpctx, args.out_image);
+ if (args.has_osd)
+ mode = 0;
+ screenshot_save(mpctx, args.out_image, mode == MODE_SUBTITLES);
free_mp_image(args.out_image);
} else {
mp_msg(MSGT_CPLAYER, MSGL_INFO, "No VO support for taking"
@@ -322,5 +366,5 @@ void screenshot_flip(struct MPContext *mpctx)
if (ctx->using_vf_screenshot)
return;
- screenshot_request(mpctx, 0, ctx->full_window);
+ screenshot_request(mpctx, 0, ctx->mode);
}
diff --git a/screenshot.h b/screenshot.h
index 6d205990f8..01dd372aa2 100644
--- a/screenshot.h
+++ b/screenshot.h
@@ -22,7 +22,6 @@
#include <stdbool.h>
struct MPContext;
-struct mp_image;
// One time initialization at program start.
void screenshot_init(struct MPContext *mpctx);
@@ -30,13 +29,9 @@ void screenshot_init(struct MPContext *mpctx);
// Request a taking & saving a screenshot of the currently displayed frame.
// each_frame: If set, this toggles per-frame screenshots, exactly like the
// screenshot slave command (MP_CMD_SCREENSHOT).
-// full_window: If set, save the actual output window contents.
+// mode: 0: -, 1: save the actual output window contents, 2: with subtitles.
void screenshot_request(struct MPContext *mpctx, bool each_frame,
- bool full_window);
-
-// Save the screenshot contained in the image to disk.
-// The image can be in any format supported by libswscale.
-void screenshot_save(struct MPContext *mpctx, struct mp_image *image);
+ int mode);
// Called by the playback core code when a new frame is displayed.
void screenshot_flip(struct MPContext *mpctx);