thanks for doing this!
On Thu, Nov 21, 2013 at 6:12 PM, Justin Ruggles <[email protected]>wrote: > --- > 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; > if you use WEBP_YUV420A (as opposed to just WEBP_YUV420), you need to set up the alpha plane (pic.a and pic.a_stride). > + 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); > this conversion is automatically made by the call to WebPEncode(), internally. libwebp will look at the format requirement (YUV(A) for lossy, RGBA for lossless) and perform the needed conversion based on the value of pic.use_argb > + 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 > _______________________________________________ libav-devel mailing list [email protected] https://lists.libav.org/mailman/listinfo/libav-devel
