diff options
-rw-r--r-- | DOCS/interface-changes.rst | 1 | ||||
-rw-r--r-- | DOCS/man/options.rst | 2 | ||||
-rw-r--r-- | player/screenshot.c | 5 | ||||
-rw-r--r-- | video/image_writer.c | 86 | ||||
-rw-r--r-- | video/image_writer.h | 5 |
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. |