summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorsfan5 <sfan5@live.de>2019-09-14 22:18:02 +0200
committersfan5 <sfan5@live.de>2019-09-14 23:02:39 +0200
commit0f79444c6dfe48a4d3a6b5075e504decca8c967a (patch)
tree5ee0c56e0fcb0b48571025603b33115ffdd48446 /video
parent8925f10962d13d9c3cbcb2e198b892177366c09f (diff)
downloadmpv-0f79444c6dfe48a4d3a6b5075e504decca8c967a.tar.bz2
mpv-0f79444c6dfe48a4d3a6b5075e504decca8c967a.tar.xz
image_writer: add WebP support (lossy or lossless)
Diffstat (limited to 'video')
-rw-r--r--video/image_writer.c46
-rw-r--r--video/image_writer.h2
2 files changed, 41 insertions, 7 deletions
diff --git a/video/image_writer.c b/video/image_writer.c
index 347adb350a..29cdac10c1 100644
--- a/video/image_writer.c
+++ b/video/image_writer.c
@@ -48,6 +48,8 @@ const struct image_writer_opts image_writer_opts_defaults = {
.png_filter = 5,
.jpeg_quality = 90,
.jpeg_source_chroma = 1,
+ .webp_lossless = 0,
+ .webp_quality = 75,
.tag_csp = 0,
};
@@ -55,6 +57,7 @@ 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},
+ {"webp", AV_CODEC_ID_WEBP},
{0}
};
@@ -66,6 +69,8 @@ const struct m_option image_writer_opts[] = {
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_FLAG("webp-lossless", webp_lossless, 0),
+ OPT_INTRANGE("webp-quality", webp_quality, 0, 0, 100),
OPT_FLAG("high-bit-depth", high_bit_depth, 0),
OPT_FLAG("tag-colorspace", tag_csp, 0),
{0},
@@ -96,7 +101,13 @@ 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->opts->format);
+ struct AVCodec *codec;
+ if (ctx->opts->format == AV_CODEC_ID_WEBP) {
+ codec = avcodec_find_encoder_by_name("libwebp"); // non-animated encoder
+ } else {
+ codec = avcodec_find_encoder(ctx->opts->format);
+ }
+
AVCodecContext *avctx = NULL;
if (!codec)
goto print_open_fail;
@@ -109,9 +120,11 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
avctx->height = image->h;
avctx->color_range = mp_csp_levels_to_avcol_range(image->params.color.levels);
avctx->pix_fmt = imgfmt2pixfmt(image->imgfmt);
- // Annoying deprecated garbage for the jpg encoder.
- if (image->params.color.levels == MP_CSP_LEVELS_PC)
- avctx->pix_fmt = replace_j_format(avctx->pix_fmt);
+ if (codec->id == AV_CODEC_ID_MJPEG) {
+ // Annoying deprecated garbage for the jpg encoder.
+ if (image->params.color.levels == MP_CSP_LEVELS_PC)
+ avctx->pix_fmt = replace_j_format(avctx->pix_fmt);
+ }
if (avctx->pix_fmt == AV_PIX_FMT_NONE) {
MP_ERR(ctx, "Image format %s not supported by lavc.\n",
mp_imgfmt_to_name(image->imgfmt));
@@ -121,6 +134,11 @@ static bool write_lavc(struct image_writer_ctx *ctx, mp_image_t *image, FILE *fp
avctx->compression_level = ctx->opts->png_compression;
av_opt_set_int(avctx, "pred", ctx->opts->png_filter,
AV_OPT_SEARCH_CHILDREN);
+ } else if (codec->id == AV_CODEC_ID_WEBP) {
+ av_opt_set_int(avctx, "lossless", ctx->opts->webp_lossless,
+ AV_OPT_SEARCH_CHILDREN);
+ av_opt_set_int(avctx, "quality", ctx->opts->webp_quality,
+ AV_OPT_SEARCH_CHILDREN);
}
if (avcodec_open2(avctx, codec, NULL) < 0) {
@@ -292,6 +310,7 @@ int image_writer_format_from_ext(const char *ext)
}
static struct mp_image *convert_image(struct mp_image *image, int destfmt,
+ enum mp_csp_levels yuv_levels,
struct mp_log *log)
{
int d_w, d_h;
@@ -308,9 +327,9 @@ static struct mp_image *convert_image(struct mp_image *image, int destfmt,
// If RGB, just assume everything is correct.
if (p.color.space != MP_CSP_RGB) {
- // Currently, assume what FFmpeg's jpg encoder needs.
+ // Currently, assume what FFmpeg's jpg encoder or libwebp needs.
// Of course this works only for non-HDR (no HDR support in libswscale).
- p.color.levels = MP_CSP_LEVELS_PC;
+ p.color.levels = yuv_levels;
p.color.space = MP_CSP_BT_601;
p.chroma_location = MP_CHROMA_CENTER;
mp_image_params_guess_csp(&p);
@@ -354,11 +373,24 @@ bool write_image(struct mp_image *image, const struct image_writer_opts *opts,
destfmt = IMGFMT_RGB24;
}
#endif
+ if (opts->format == AV_CODEC_ID_WEBP && !opts->webp_lossless) {
+ // For lossy images, libwebp has its own RGB->YUV conversion.
+ // We don't want that, so force YUV/YUVA here.
+ int alpha = image->fmt.flags & MP_IMGFLAG_ALPHA;
+ destfmt = alpha ? pixfmt2imgfmt(AV_PIX_FMT_YUVA420P) : IMGFMT_420P;
+ }
if (!destfmt)
destfmt = get_target_format(&ctx);
- struct mp_image *dst = convert_image(image, destfmt, log);
+ enum mp_csp_levels levels; // Ignored if destfmt is a RGB format
+ if (opts->format == AV_CODEC_ID_WEBP) {
+ levels = MP_CSP_LEVELS_TV;
+ } else {
+ levels = MP_CSP_LEVELS_PC;
+ }
+
+ struct mp_image *dst = convert_image(image, destfmt, levels, log);
if (!dst)
return false;
diff --git a/video/image_writer.h b/video/image_writer.h
index c9932e93ee..e9564e06de 100644
--- a/video/image_writer.h
+++ b/video/image_writer.h
@@ -32,6 +32,8 @@ struct image_writer_opts {
int jpeg_progressive;
int jpeg_baseline;
int jpeg_source_chroma;
+ int webp_lossless;
+ int webp_quality;
int tag_csp;
};