player/screenshot: support more formats for screenshot-raw command

This adds a format parameter to screenshot-raw command which controls
the format of the returned image data. In addition to the bgr0 format,
this adds support for 3 other formats: bgra, rgba, rgba64.

bgra is used by overlay-add command and several window systems.
rgba and rgba64 are used by several GPU APIs and are the formats
returned by the gpu and gpu-next screenshot code, which avoid the need
for further format conversion (see convert_image function).
rgba64 also adds the ability to acquire high bit depth screenshots
for screenshot-raw command.
This commit is contained in:
nanahi
2025-01-04 23:08:54 -05:00
committed by Kacper Michajłow
parent c1237c1d48
commit ab47e95197
4 changed files with 42 additions and 12 deletions

View File

@@ -0,0 +1 @@
add `format` argument to `screenshot-raw` command

View File

@@ -1395,21 +1395,38 @@ Screenshot Commands
Like all input command parameters, the filename is subject to property
expansion as described in `Property Expansion`_.
``screenshot-raw [<flags>]``
``screenshot-raw [<flags> [<format>]]``
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. The ``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`` are 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 mpv_node is freed. As usual with client API
semantics, you are not allowed to write to the image data.
``stride`` fields set to obvious contents.
The ``format`` field is set to the format of the screenshot image data.
This can be controlled by the ``format`` argument. The format can be one of
the following:
bgr0 (default)
This format is organized as ``B8G8R8X8`` (where ``B`` is the LSB).
The contents of the padding ``X`` are undefined.
bgra
This format is organized as ``B8G8R8A8`` (where ``B`` is the LSB).
rgba
This format is organized as ``R8G8B8A8`` (where ``R`` is the LSB).
rgba64
This format is organized as ``R16G16B16A16`` (where ``R`` is the LSB).
Each component occupies 2 bytes per pixel.
When this format is used, the image data will be high bit depth, and
``--screenshot-high-bit-depth`` is ignored.
The ``data`` field is of type MPV_FORMAT_BYTE_ARRAY with the actual image
data. The image is freed as soon as the result mpv_node is freed. As usual
with client API semantics, you are not allowed to write to the image data.
The ``stride`` is the number of bytes from a pixel at ``(x0, y0)`` to the
pixel at ``(x0, y0 + 1)``. This can be larger than ``w * 4`` if the image
pixel at ``(x0, y0 + 1)``. This can be larger than ``w * bpp`` if the image
was cropped, or if there is padding. This number can be negative as well.
You access a pixel with ``byte_index = y * stride + x * 4`` (assuming the
``bgr0`` format).
You access a pixel with ``byte_index = y * stride + x * bpp``.
Here, ``bpp`` is the number of bytes per pixel, which is 8 for ``rgba64``
format and 4 for other formats.
The ``flags`` argument is like the first argument to ``screenshot`` and
supports ``subtitles``, ``video``, ``window``.

View File

@@ -7176,6 +7176,12 @@ const struct mp_cmd_def mp_cmds[] = {
{"window", 1},
{"subtitles", 2}),
OPTDEF_INT(2)},
{"format", OPT_CHOICE(v.i,
{"bgr0", 0},
{"bgra", 1},
{"rgba", 2},
{"rgba64", 3}),
OPTDEF_INT(0)},
},
},
{ "loadfile", cmd_loadfile,

View File

@@ -558,8 +558,14 @@ void cmd_screenshot_raw(void *p)
struct MPContext *mpctx = cmd->mpctx;
struct mpv_node *res = &cmd->result;
const enum mp_imgfmt formats[] = {IMGFMT_BGR0, IMGFMT_BGRA, IMGFMT_RGBA, IMGFMT_RGBA64};
const char *format_names[] = {"bgr0", "bgra", "rgba", "rgba64"};
int idx = cmd->args[1].v.i;
assert(idx >= 0 && idx <= 3);
bool high_depth = formats[idx] == IMGFMT_RGBA64;
struct mp_image *img = screenshot_get_rgb(mpctx, cmd->args[0].v.i,
false, IMGFMT_BGR0);
high_depth, formats[idx]);
if (!img) {
cmd->success = false;
return;
@@ -569,7 +575,7 @@ void cmd_screenshot_raw(void *p)
node_map_add_int64(res, "w", img->w);
node_map_add_int64(res, "h", img->h);
node_map_add_int64(res, "stride", img->stride[0]);
node_map_add_string(res, "format", "bgr0");
node_map_add_string(res, "format", format_names[idx]);
struct mpv_byte_array *ba =
node_map_add(res, "data", MPV_FORMAT_BYTE_ARRAY)->u.ba;
*ba = (struct mpv_byte_array){