summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-04-20 23:11:03 +0200
committerwm4 <wm4@nowhere>2015-04-20 23:11:03 +0200
commita3680d1b2d137461008d38486cdb2d5013291e61 (patch)
treee3bafaac8a13edf57ff3456333a26fd057ac0790
parentccfe4d64184ae4c2983ae6b099c7c7ebb3770d0f (diff)
downloadmpv-a3680d1b2d137461008d38486cdb2d5013291e61.tar.bz2
mpv-a3680d1b2d137461008d38486cdb2d5013291e61.tar.xz
client API: add a screenshot_raw command
Requested. The wild code for setting up the mpv_node probably deserves to be cleaned up later. Fixes #1800.
-rw-r--r--DOCS/man/input.rst9
-rw-r--r--input/cmd_list.c5
-rw-r--r--input/cmd_list.h1
-rw-r--r--player/command.c39
-rw-r--r--player/screenshot.c10
-rw-r--r--player/screenshot.h3
6 files changed, 67 insertions, 0 deletions
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 3c8c51e87b..e1c3a58421 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -631,6 +631,15 @@ Input Commands that are Possibly Subject to Change
unseekable streams that are going out of sync.
This command might be changed or removed in the future.
+``screenshot_raw [subtitles|video|window]``
+ Return a screenshot in memory. This can be used only through the client
+ API. The MPV_FORMAT_NODE_MAP returned by this command has the ``w``, ``h``,
+ ``stride`` fields set to obvious contents. A ``format`` field is set to
+ ``bgr0`` by default. This format is organized as ``B8G8R8X8`` (where ``B``
+ is the LSB). The contents of the padding ``X`` is undefined. The ``data``
+ field is of type MPV_FORMAT_BYTE_ARRAY with the actual image data. The image
+ is freed as soon as the result node is freed.
+
Undocumented commands: ``tv_last_channel`` (TV/DVB only),
``get_property`` (deprecated), ``ao_reload`` (experimental/internal).
diff --git a/input/cmd_list.c b/input/cmd_list.c
index 9005121985..acd8ae72a1 100644
--- a/input/cmd_list.c
+++ b/input/cmd_list.c
@@ -119,6 +119,11 @@ const struct mp_cmd_def mp_cmds[] = {
{"window", 1},
{"subtitles", 2})),
}},
+ { MP_CMD_SCREENSHOT_RAW, "screenshot_raw", {
+ OARG_CHOICE(2, ({"video", 0},
+ {"window", 1},
+ {"subtitles", 2})),
+ }},
{ MP_CMD_LOADFILE, "loadfile", {
ARG_STRING,
OARG_CHOICE(0, ({"replace", 0},
diff --git a/input/cmd_list.h b/input/cmd_list.h
index 52dc6426fa..e9418d4429 100644
--- a/input/cmd_list.h
+++ b/input/cmd_list.h
@@ -48,6 +48,7 @@ enum mp_command_type {
MP_CMD_OSD,
MP_CMD_SCREENSHOT,
MP_CMD_SCREENSHOT_TO_FILE,
+ MP_CMD_SCREENSHOT_RAW,
MP_CMD_LOADFILE,
MP_CMD_LOADLIST,
MP_CMD_PLAYLIST_CLEAR,
diff --git a/player/command.c b/player/command.c
index 376f2b6bed..d210398946 100644
--- a/player/command.c
+++ b/player/command.c
@@ -4040,6 +4040,22 @@ static bool check_property_autorepeat(char *property, struct MPContext *mpctx)
return true;
}
+static struct mpv_node *add_map_entry(struct mpv_node *dst, const char *key)
+{
+ struct mpv_node_list *list = dst->u.list;
+ assert(dst->format == MPV_FORMAT_NODE_MAP && dst->u.list);
+ MP_TARRAY_GROW(list, list->values, list->num);
+ MP_TARRAY_GROW(list, list->keys, list->num);
+ list->keys[list->num] = talloc_strdup(list, key);
+ return &list->values[list->num++];
+}
+
+#define ADD_MAP_INT(dst, name, i) (*add_map_entry(dst, name) = \
+ (struct mpv_node){ .format = MPV_FORMAT_INT64, .u.int64 = (i) });
+
+#define ADD_MAP_CSTR(dst, name, s) (*add_map_entry(dst, name) = \
+ (struct mpv_node){ .format = MPV_FORMAT_STRING, .u.string = (s) });
+
int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *res)
{
struct command_ctx *cmdctx = mpctx->command_ctx;
@@ -4552,6 +4568,29 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re
screenshot_to_file(mpctx, cmd->args[0].v.s, cmd->args[1].v.i, msg_osd);
break;
+ case MP_CMD_SCREENSHOT_RAW: {
+ if (!res)
+ return -1;
+ struct mp_image *img = screenshot_get_rgb(mpctx, cmd->args[0].v.i);
+ if (!img)
+ return -1;
+ struct mpv_node_list *info = talloc_zero(NULL, struct mpv_node_list);
+ talloc_steal(info, img);
+ *res = (mpv_node){ .format = MPV_FORMAT_NODE_MAP, .u.list = info };
+ ADD_MAP_INT(res, "w", img->w);
+ ADD_MAP_INT(res, "h", img->h);
+ ADD_MAP_INT(res, "stride", img->stride[0]);
+ ADD_MAP_CSTR(res, "format", "bgr0");
+ struct mpv_byte_array *ba = talloc_ptrtype(info, ba);
+ *ba = (struct mpv_byte_array){
+ .data = img->planes[0],
+ .size = img->stride[0] * img->h,
+ };
+ *add_map_entry(res, "data") =
+ (struct mpv_node){.format = MPV_FORMAT_BYTE_ARRAY, .u.ba = ba,};
+ break;
+ }
+
case MP_CMD_RUN: {
char *args[MP_CMD_MAX_ARGS + 1] = {0};
for (int n = 0; n < cmd->nargs; n++)
diff --git a/player/screenshot.c b/player/screenshot.c
index f722b9561f..a47de292d5 100644
--- a/player/screenshot.c
+++ b/player/screenshot.c
@@ -357,6 +357,16 @@ static struct mp_image *screenshot_get(struct MPContext *mpctx, int mode)
return image;
}
+struct mp_image *screenshot_get_rgb(struct MPContext *mpctx, int mode)
+{
+ struct mp_image *mpi = screenshot_get(mpctx, mode);
+ if (!mpi)
+ return NULL;
+ struct mp_image *res = convert_image(mpi, IMGFMT_BGR0, mpctx->log);
+ talloc_free(mpi);
+ return res;
+}
+
void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
bool osd)
{
diff --git a/player/screenshot.h b/player/screenshot.h
index 84b7ef4f58..9ebe9ef76e 100644
--- a/player/screenshot.h
+++ b/player/screenshot.h
@@ -39,6 +39,9 @@ void screenshot_request(struct MPContext *mpctx, int mode, bool each_frame,
void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
bool osd);
+// mode is the same as in screenshot_request()
+struct mp_image *screenshot_get_rgb(struct MPContext *mpctx, int mode);
+
// Called by the playback core code when a new frame is displayed.
void screenshot_flip(struct MPContext *mpctx);