summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst1
-rw-r--r--DOCS/man/options.rst2
-rw-r--r--player/screenshot.c5
-rw-r--r--video/image_writer.c86
-rw-r--r--video/image_writer.h5
5 files changed, 50 insertions, 49 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index 76c8e5f596..c82b0a62d0 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -24,6 +24,7 @@ Interface changes
(see git "vo_opengl: remove dxva2 dummy hwdec backend")
- remove ppm, pgm, pgmyuv, tga choices from the --screenshot-format and
--vo-image-format options
+ - the "jpeg" choice in the option above now leads to a ".jpg" file extension
--- mpv 0.24.0 ---
- deprecate --hwdec-api and replace it with --opengl-hwdec-interop.
The new option accepts both --hwdec values, as well as named backends.
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 469ed29c44..4ee702df61 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -3108,7 +3108,7 @@ Screenshot
:png: PNG
:jpg: JPEG (default)
- :jpeg: JPEG (same as jpg, but with .jpeg file ending)
+ :jpeg: JPEG (alias for jpg)
``--screenshot-tag-colorspace=<yes|no>``
Tag screenshots with the appropriate colorspace.
diff --git a/player/screenshot.c b/player/screenshot.c
index dc3cca3d33..b5bd5ea787 100644
--- a/player/screenshot.c
+++ b/player/screenshot.c
@@ -384,8 +384,9 @@ void screenshot_to_file(struct MPContext *mpctx, const char *filename, int mode,
ctx->osd = osd;
char *ext = mp_splitext(filename, NULL);
- if (ext)
- opts.format = ext;
+ int format = image_writer_format_from_ext(ext);
+ if (format)
+ opts.format = format;
struct mp_image *image = screenshot_get(mpctx, mode);
if (!image) {
screenshot_msg(ctx, SMSG_ERR, "Taking screenshot failed.");
diff --git a/video/image_writer.c b/video/image_writer.c
index 3c280f278d..eda02bef81 100644
--- a/video/image_writer.c
+++ b/video/image_writer.c
@@ -42,7 +42,7 @@
#include "options/m_option.h"
const struct image_writer_opts image_writer_opts_defaults = {
- .format = "jpg",
+ .format = AV_CODEC_ID_MJPEG,
.high_bit_depth = 1,
.png_compression = 7,
.png_filter = 5,
@@ -52,15 +52,22 @@ const struct image_writer_opts image_writer_opts_defaults = {
.tag_csp = 0,
};
+const struct m_opt_choice_alternatives mp_image_writer_formats[] = {
+ {"jpg", AV_CODEC_ID_MJPEG},
+ {"jpeg", AV_CODEC_ID_MJPEG},
+ {"png", AV_CODEC_ID_PNG},
+ {0}
+};
+
#define OPT_BASE_STRUCT struct image_writer_opts
const struct m_option image_writer_opts[] = {
+ OPT_CHOICE_C("format", format, 0, mp_image_writer_formats),
OPT_INTRANGE("jpeg-quality", jpeg_quality, 0, 0, 100),
OPT_INTRANGE("jpeg-smooth", jpeg_smooth, 0, 0, 100),
OPT_FLAG("jpeg-source-chroma", jpeg_source_chroma, 0),
OPT_INTRANGE("png-compression", png_compression, 0, 0, 9),
OPT_INTRANGE("png-filter", png_filter, 0, 0, 5),
- OPT_STRING("format", format, 0),
OPT_FLAG("high-bit-depth", high_bit_depth, 0),
OPT_FLAG("tag-colorspace", tag_csp, 0),
{0},
@@ -69,17 +76,9 @@ const struct m_option image_writer_opts[] = {
struct image_writer_ctx {
struct mp_log *log;
const struct image_writer_opts *opts;
- const struct img_writer *writer;
struct mp_imgfmt_desc original_format;
};
-struct img_writer {
- const char *file_ext;
- bool (*write)(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp);
- const int *pixfmts;
- int lavc_codec;
-};
-
static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp)
{
bool success = 0;
@@ -89,7 +88,7 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
av_init_packet(&pkt);
- struct AVCodec *codec = avcodec_find_encoder(ctx->writer->lavc_codec);
+ struct AVCodec *codec = avcodec_find_encoder(ctx->opts->format);
AVCodecContext *avctx = NULL;
if (!codec)
goto print_open_fail;
@@ -106,7 +105,7 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
mp_imgfmt_to_name(image->imgfmt));
goto error_exit;
}
- if (ctx->writer->lavc_codec == AV_CODEC_ID_PNG) {
+ if (codec->id == AV_CODEC_ID_PNG) {
avctx->compression_level = ctx->opts->png_compression;
av_opt_set_int(avctx, "pred", ctx->opts->png_filter,
AV_OPT_SEARCH_CHILDREN);
@@ -237,15 +236,14 @@ static int get_encoder_format(struct AVCodec *codec, int srcfmt, bool highdepth)
return current;
}
-static int get_target_format(struct image_writer_ctx *ctx, int srcfmt)
+static int get_target_format(struct image_writer_ctx *ctx)
{
- if (!ctx->writer->lavc_codec)
- goto unknown;
-
- struct AVCodec *codec = avcodec_find_encoder(ctx->writer->lavc_codec);
+ struct AVCodec *codec = avcodec_find_encoder(ctx->opts->format);
if (!codec)
goto unknown;
+ int srcfmt = ctx->original_format.id;
+
int target = get_encoder_format(codec, srcfmt, ctx->opts->high_bit_depth);
if (!target)
target = get_encoder_format(codec, srcfmt, true);
@@ -256,28 +254,7 @@ static int get_target_format(struct image_writer_ctx *ctx, int srcfmt)
return target;
unknown:
- return IMGFMT_RGB24;
-}
-
-static const struct img_writer img_writers[] = {
- { "png", write_lavc, .lavc_codec = AV_CODEC_ID_PNG },
-#if HAVE_JPEG
- { "jpg", write_jpeg },
- { "jpeg", write_jpeg },
-#endif
-};
-
-static const struct img_writer *get_writer(const struct image_writer_opts *opts)
-{
- const char *type = opts->format;
-
- for (size_t n = 0; n < sizeof(img_writers) / sizeof(img_writers[0]); n++) {
- const struct img_writer *writer = &img_writers[n];
- if (type && strcmp(type, writer->file_ext) == 0)
- return writer;
- }
-
- return &img_writers[0];
+ return IMGFMT_RGB0;
}
const char *image_writer_file_ext(const struct image_writer_opts *opts)
@@ -287,7 +264,16 @@ const char *image_writer_file_ext(const struct image_writer_opts *opts)
if (!opts)
opts = &defs;
- return get_writer(opts)->file_ext;
+ return m_opt_choice_str(mp_image_writer_formats, opts->format);
+}
+
+int image_writer_format_from_ext(const char *ext)
+{
+ for (int n = 0; mp_image_writer_formats[n].name; n++) {
+ if (ext && strcmp(mp_image_writer_formats[n].name, ext) == 0)
+ return mp_image_writer_formats[n].value;
+ }
+ return 0;
}
struct mp_image *convert_image(struct mp_image *image, int destfmt,
@@ -325,9 +311,19 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
if (!opts)
opts = &defs;
- const struct img_writer *writer = get_writer(opts);
- struct image_writer_ctx ctx = { log, opts, writer, image->fmt };
- int destfmt = get_target_format(&ctx, image->imgfmt);
+ struct image_writer_ctx ctx = { log, opts, image->fmt };
+ bool (*write)(struct image_writer_ctx *, mp_image_t *, FILE *) = write_lavc;
+ int destfmt = 0;
+
+#if HAVE_JPEG
+ if (opts->format == AV_CODEC_ID_MJPEG) {
+ write = write_jpeg;
+ destfmt = IMGFMT_RGB24;
+ }
+#endif
+
+ if (!destfmt)
+ destfmt = get_target_format(&ctx);
struct mp_image *dst = convert_image(image, destfmt, log);
if (!dst)
@@ -338,7 +334,7 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
if (fp == NULL) {
mp_err(log, "Error opening '%s' for writing!\n", filename);
} else {
- success = writer->write(&ctx, dst, fp);
+ success = write(&ctx, dst, fp);
success = !fclose(fp) && success;
if (!success)
mp_err(log, "Error writing file '%s'!\n", filename);
@@ -351,6 +347,6 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
void dump_png(struct mp_image *image, const char *filename, struct mp_log *log)
{
struct image_writer_opts opts = image_writer_opts_defaults;
- opts.format = "png";
+ opts.format = AV_CODEC_ID_PNG;
write_image(image, &opts, filename, log);
}
diff --git a/video/image_writer.h b/video/image_writer.h
index 8b7414b62a..723dffc3ef 100644
--- a/video/image_writer.h
+++ b/video/image_writer.h
@@ -21,7 +21,7 @@ struct mp_image;
struct mp_log;
struct image_writer_opts {
- char *format;
+ int format;
int high_bit_depth;
int png_compression;
int png_filter;
@@ -42,6 +42,9 @@ extern const struct m_option image_writer_opts[];
// Return the file extension that will be used, e.g. "png".
const char *image_writer_file_ext(const struct image_writer_opts *opts);
+// Map file extension to format ID - return 0 (which is invalid) if unknown.
+int image_writer_format_from_ext(const char *ext);
+
/*
* Save the given image under the given filename. The parameters csp and opts
* are optional. All pixel formats supported by swscale are supported.