---
Changelog | 1 +
configure | 4 +
doc/general.texi | 4 +-
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/libwebpenc.c | 203 ++++++++++++++++++++++++++++++++++++++++++++++++
libavcodec/version.h | 2 +-
libavformat/img2enc.c | 2 +-
8 files changed, 214 insertions(+), 4 deletions(-)
create mode 100644 libavcodec/libwebpenc.c
diff --git a/Changelog b/Changelog
index 1e58a2c..79f19a1 100644
--- a/Changelog
+++ b/Changelog
@@ -48,6 +48,7 @@ version 10:
- setsar/setdar filters now support variables in ratio expressions
- dar variable in the scale filter now returns the actual DAR (i.e. a * sar)
- VP9 decoder
+- WebP encoding via libwebp
version 9:
diff --git a/configure b/configure
index 05dbca7..e7f41dd 100755
--- a/configure
+++ b/configure
@@ -202,6 +202,7 @@ External library support:
--enable-libvorbis enable Vorbis encoding via libvorbis [no]
--enable-libvpx enable VP8 and VP9 de/encoding via libvpx [no]
--enable-libwavpack enable wavpack encoding via libwavpack [no]
+ --enable-libwebp enable WebP encoding via libwebp [no]
--enable-libx264 enable H.264 encoding via x264 [no]
--enable-libxavs enable AVS encoding via xavs [no]
--enable-libxvid enable Xvid encoding via xvidcore,
@@ -1069,6 +1070,7 @@ EXTERNAL_LIBRARY_LIST="
libvorbis
libvpx
libwavpack
+ libwebp
libx264
libxavs
libxvid
@@ -1808,6 +1810,7 @@ libvpx_vp8_encoder_deps="libvpx"
libvpx_vp9_decoder_deps="libvpx"
libvpx_vp9_encoder_deps="libvpx"
libwavpack_encoder_deps="libwavpack"
+libwebp_encoder_deps="libwebp"
libx264_encoder_deps="libx264"
libxavs_encoder_deps="libxavs"
libxvid_encoder_deps="libxvid"
@@ -3837,6 +3840,7 @@ enabled libvpx && {
enabled libvpx_vp9_decoder && { check_lib2 "vpx/vpx_decoder.h vpx/vp8dx.h"
"vpx_codec_vp9_dx" -lvpx || disable libvpx_vp9_decoder; }
enabled libvpx_vp9_encoder && { check_lib2 "vpx/vpx_encoder.h vpx/vp8cx.h"
"vpx_codec_vp9_cx" -lvpx || disable libvpx_vp9_encoder; } }
enabled libwavpack && require libwavpack wavpack/wavpack.h
WavpackOpenFileOutput -lwavpack
+enabled libwebp && require_pkg_config libwebp webp/encode.h
WebPGetEncoderVersion
enabled libx264 && require libx264 x264.h x264_encoder_encode -lx264
&&
{ check_cpp_condition x264.h "X264_BUILD >= 118"
||
die "ERROR: libx264 version must be >= 0.118.";
}
diff --git a/doc/general.texi b/doc/general.texi
index c1809e2..a1996d0 100644
--- a/doc/general.texi
+++ b/doc/general.texi
@@ -415,8 +415,8 @@ following image formats are supported:
@tab YUV, JPEG and some extension is not supported yet.
@item Truevision Targa @tab X @tab X
@tab Targa (.TGA) image format
-@item WebP @tab @tab X
- @tab WebP image format
+@item WebP @tab E @tab X
+ @tab WebP image format, encoding supported through external library libwebp
@item XBM @tab X @tab
@tab X BitMap image format
@item XWD @tab X @tab X
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 1674d47..6413e24 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -614,6 +614,7 @@ OBJS-$(CONFIG_LIBVPX_VP8_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o
OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o
+OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc.o
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
OBJS-$(CONFIG_LIBXVID_ENCODER) += libxvid.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 6453e30..89dc34a 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -437,6 +437,7 @@ void avcodec_register_all(void)
REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8);
REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9);
REGISTER_ENCODER(LIBWAVPACK, libwavpack);
+ REGISTER_ENCODER(LIBWEBP, libwebp);
REGISTER_ENCODER(LIBX264, libx264);
REGISTER_ENCODER(LIBXAVS, libxavs);
REGISTER_ENCODER(LIBXVID, libxvid);
diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c
new file mode 100644
index 0000000..d762eb1
--- /dev/null
+++ b/libavcodec/libwebpenc.c
@@ -0,0 +1,203 @@
+/*
+ * WebP encoding support via libwebp
+ * Copyright (c) 2013 Justin Ruggles <[email protected]>
+ *
+ * This file is part of Libav.
+ *
+ * Libav is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * Libav is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Libav; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * WebP encoder using libwebp
+ */
+
+#include <webp/encode.h>
+
+#include "libavutil/common.h"
+#include "libavutil/opt.h"
+#include "avcodec.h"
+#include "internal.h"
+
+typedef struct {
+ AVClass *avclass; // class for AVOptions
+ int lossless; // use lossless encoding
+ float quality; // lossy quality 0 - 100
+ int method; // algorithmic complexity 0=fast to 6=slow
+ int preset; // configuration preset
+ WebPConfig config; // libwebp configuration
+} LibWebPContext;
+
+static av_cold int libwebp_encode_init(AVCodecContext *avctx)
+{
+ LibWebPContext *s = avctx->priv_data;
+ int ret;
+
+ if (s->preset >= WEBP_PRESET_DEFAULT) {
+ ret = WebPConfigPreset(&s->config, s->preset, s->quality);
+ if (!ret)
+ return AVERROR_UNKNOWN;
+ s->lossless = s->config.lossless;
+ s->quality = s->config.quality;
+ s->method = s->config.method;
+ } else {
+ ret = WebPConfigInit(&s->config);
+ if (!ret)
+ return AVERROR_UNKNOWN;
+ s->config.lossless = s->lossless;
+ s->config.quality = s->quality;
+ s->config.method = s->method;
+
+ ret = WebPValidateConfig(&s->config);
+ if (!ret)
+ return AVERROR(EINVAL);
+ }
+
+ if (s->lossless)
+ av_log(avctx, AV_LOG_DEBUG, "Lossless - method=%d\n", s->method);
+ else
+ av_log(avctx, AV_LOG_DEBUG, "Lossy - quality=%.1f method=%d\n",
s->quality, s->method);
+
+ return 0;
+}
+
+static int libwebp_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *frame, int *got_packet)
+{
+ LibWebPContext *s = avctx->priv_data;
+ WebPPicture pic;
+ WebPMemoryWriter mw;
+ int ret;
+
+ if (avctx->width > WEBP_MAX_DIMENSION || avctx->height >
WEBP_MAX_DIMENSION) {
+ av_log(avctx, AV_LOG_ERROR, "Picture size is too large. Max is
%dx%d\n",
+ WEBP_MAX_DIMENSION, WEBP_MAX_DIMENSION);
+ return AVERROR(EINVAL);
+ }
+
+ ret = WebPPictureInit(&pic);
+ if (!ret)
+ return AVERROR_UNKNOWN;
+ pic.width = avctx->width;
+ pic.height = avctx->height;
+
+ if (avctx->pix_fmt == AV_PIX_FMT_RGB32) {
+ if (!s->lossless) {
+ av_log(avctx, AV_LOG_WARNING,
+ "Using libwebp for RGB-to-YUV conversion\n");
+ }
+ pic.use_argb = 1;
+ pic.argb = (uint32_t *)frame->data[0];
+ pic.argb_stride = frame->linesize[0] / 4;
+ } else {
+ if (avctx->pix_fmt == AV_PIX_FMT_YUV420P)
+ pic.colorspace = WEBP_YUV420;
+ else
+ pic.colorspace = WEBP_YUV420A;
+ pic.use_argb = 0;
+ pic.y = frame->data[0];
+ pic.u = frame->data[1];
+ pic.v = frame->data[2];
+ pic.y_stride = frame->linesize[0];
+ pic.uv_stride = frame->linesize[1];
+
+ /* We do not have a way to automatically prioritize RGB over YUV
+ in automatic pixel format conversion based on whether we're encoding
+ lossless or lossy, so we do conversion here as a convenience. */
+ if (s->lossless) {
+ WebPPicture rgb_pic;
+
+ av_log(avctx, AV_LOG_WARNING,
+ "Using libwebp for YUV-to-RGB conversion\n");
+
+ ret = WebPPictureCopy(&pic, &rgb_pic);
+ if (!ret) {
+ av_log(avctx, AV_LOG_ERROR,
+ "WebPPictureCopy() failed with error: %d\n",
+ pic.error_code);
+ return AVERROR_UNKNOWN;
+ }
+ ret = WebPPictureYUVAToARGB(&rgb_pic);
+ if (!ret) {
+ av_log(avctx, AV_LOG_ERROR,
+ "WebPPictureYUVAToARGB() failed with error: %d\n",
+ pic.error_code);
+ return AVERROR_UNKNOWN;
+ }
+ pic = rgb_pic;
+ }
+ }
+
+ WebPMemoryWriterInit(&mw);
+ pic.custom_ptr = &mw;
+ pic.writer = WebPMemoryWrite;
+
+ ret = WebPEncode(&s->config, &pic);
+ if (!ret) {
+ av_log(avctx, AV_LOG_ERROR, "WebPEncode() failed with error: %d",
+ pic.error_code);
+ return AVERROR_UNKNOWN;
+ }
+
+ ret = av_new_packet(pkt, mw.size);
+ if (ret < 0)
+ return ret;
+ memcpy(pkt->data, mw.mem, mw.size);
+
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ *got_packet = 1;
+
+ return 0;
+}
+
+#define OFFSET(x) offsetof(LibWebPContext, x)
+#define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM
+static const AVOption options[] = {
+ { "lossless", "Use lossless mode", OFFSET(lossless),
AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, VE
},
+ { "method", "quality/speed trade-off", OFFSET(method),
AV_OPT_TYPE_INT, { .i64 = 4 }, 0, 6, VE
},
+ { "quality", "lossy quality", OFFSET(quality),
AV_OPT_TYPE_FLOAT, { .dbl = 75 }, 0, 100, VE
},
+ { "preset", "Configuration preset", OFFSET(preset),
AV_OPT_TYPE_INT, { .i64 = -1 }, -1, WEBP_PRESET_TEXT, VE, "preset"
},
+ { "none", "do not use a preset", 0,
AV_OPT_TYPE_CONST, { .i64 = -1 }, 0, 0, VE, "preset" },
+ { "default", "default preset", 0,
AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_DEFAULT }, 0, 0, VE, "preset" },
+ { "picture", "digital picture, like portrait, inner shot", 0,
AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_PICTURE }, 0, 0, VE, "preset" },
+ { "photo", "outdoor photograph, with natural lighting", 0,
AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_PHOTO }, 0, 0, VE, "preset" },
+ { "drawing", "hand or line drawing, with high-contrast details", 0,
AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_DRAWING }, 0, 0, VE, "preset" },
+ { "icon", "small-sized colorful images", 0,
AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_ICON }, 0, 0, VE, "preset" },
+ { "text", "text-like", 0,
AV_OPT_TYPE_CONST, { .i64 = WEBP_PRESET_TEXT }, 0, 0, VE, "preset" },
+ { NULL },
+};
+
+static const AVClass class = {
+ .class_name = "libwebp",
+ .item_name = av_default_item_name,
+ .option = options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+AVCodec ff_libwebp_encoder = {
+ .name = "libwebp",
+ .long_name = NULL_IF_CONFIG_SMALL("libwebp WebP image"),
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_WEBP,
+ .priv_data_size = sizeof(LibWebPContext),
+ .init = libwebp_encode_init,
+ .encode2 = libwebp_encode_frame,
+ .pix_fmts = (const enum AVPixelFormat[]) {
+ AV_PIX_FMT_RGB32,
+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
+ AV_PIX_FMT_NONE
+ },
+ .priv_class = &class,
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index c828dc8..c5a777b 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -27,7 +27,7 @@
*/
#define LIBAVCODEC_VERSION_MAJOR 55
-#define LIBAVCODEC_VERSION_MINOR 28
+#define LIBAVCODEC_VERSION_MINOR 29
#define LIBAVCODEC_VERSION_MICRO 0
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c
index 7b94869..4cc5c3f 100644
--- a/libavformat/img2enc.c
+++ b/libavformat/img2enc.c
@@ -148,7 +148,7 @@ AVOutputFormat ff_image2_muxer = {
.long_name = NULL_IF_CONFIG_SMALL("image2 sequence"),
.extensions = "bmp,dpx,jpeg,jpg,ljpg,pam,pbm,pcx,pgm,pgmyuv,png,"
"ppm,sgi,tga,tif,tiff,jp2,xwd,sun,ras,rs,im1,im8,im24,"
- "sunras,xbm",
+ "sunras,webp,xbm",
.priv_data_size = sizeof(VideoMuxData),
.video_codec = AV_CODEC_ID_MJPEG,
.write_header = write_header,
--
1.8.1.2
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel