Hi Justin,

On Sunday, December 8, 2013, Justin Ruggles wrote:

> ---
> Updated patch takes into account suggestions from Pascal. Also includes
> better documentation about the -method and -qscale options.
>
> Info about lossless options taken from this thread:
>
> https://groups.google.com/a/webmproject.org/d/msg/webp-discuss/HsAzfpKksEo/Dn4zad67S28J
>
>  Changelog               |    1 +
>  configure               |    4 +
>  doc/encoders.texi       |   61 ++++++++++
>  doc/general.texi        |    4 +-
>  libavcodec/Makefile     |    1 +
>  libavcodec/allcodecs.c  |    1 +
>  libavcodec/libwebpenc.c |  291
> +++++++++++++++++++++++++++++++++++++++++++++++
>  libavcodec/version.h    |    2 +-
>  libavformat/img2enc.c   |    2 +-
>  9 files changed, 363 insertions(+), 4 deletions(-)
>  create mode 100644 libavcodec/libwebpenc.c
>
> diff --git a/Changelog b/Changelog
> index 9747720..110b8cb 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -50,6 +50,7 @@ version 10:
>  - VP9 decoder
>  - support for decoding through VDPAU in avconv (the -hwaccel option)
>  - remove mp3_header_(de)compress bitstream filters
> +- WebP encoding via libwebp
>
>
>  version 9:
> diff --git a/configure b/configure
> index 6fdcb7b..3932ee4 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,
> @@ -1092,6 +1093,7 @@ EXTERNAL_LIBRARY_LIST="
>      libvorbis
>      libvpx
>      libwavpack
> +    libwebp
>      libx264
>      libxavs
>      libxvid
> @@ -1836,6 +1838,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"
> @@ -3881,6 +3884,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/encoders.texi b/doc/encoders.texi
> index d6f4bce..fc4cb34 100644
> --- a/doc/encoders.texi
> +++ b/doc/encoders.texi
> @@ -446,6 +446,67 @@ Same as 3, but with extra processing enabled -
> corresponding to the wavpack
>  @chapter Video Encoders
>  @c man begin VIDEO ENCODERS
>
> +@section libwebp
> +
> +libwebp WebP Image encoder wrapper
> +
> +libwebp is Google's official encoder for WebP images. It can encode in
> either
> +lossy or lossless mode. Lossy images are essentially a wrapper around a
> VP8
> +frame. Lossless images are a separate codec developed by Google.
> +
> +@subsection Pixel Format
> +
> +Currently, libwebp only supports YUV420 for lossy and RGB for lossless due
> +to limitations of the format and libwebp. Alpha is supported for either
> mode.
> +Because of API limitations, if RGB is passed in when encoding lossy or
> YUV is
> +passed in for encoding lossless, the pixel format will automatically be
> +converted using functions from libwebp. This is not ideal and is done
> only for
> +convenience.
> +
> +@subsection Options
> +
> +@table @option
> +
> +@item -lossless @var{boolean}
> +Enables/Disables use of lossless mode. Default is 0.
> +
> +@item -compression_level @var{number}


I prefer @var{integer}. Same applies for -qscale.


> +For lossy, this is a quality/speed tradeoff. Higher values give better
> quality
> +for a given size at the cost of increased encoding time. For lossless,
> this is
> +a size/speed tradeoff. Higher values give smaller size at the cost of
> increased
> +encoding time. More specifically, it controls the number of extra
> algorithms
> +and compression tools used, and varies the combination of these tools.
> This
> +maps to the @var{method} option in libwebp. The valid range is 0 to 6.
> +Default is 4.
> +
> +@item -qscale @var{number}
> +For lossy encoding, this controls image quality, 0 to 100. For lessless


lossless typo


> +encoding, this controls the effort and time spent at compressing more. The


Maybe you can add how qscale differs from compression_quality for lossless
more. Also qscale is originally for lossy encoding only so it feels kinda
weird that it also applies to lossless


> +default value is 75. Note that for usage via libavcodec, this option is
> called
> +@var{global_quality} and must be multiplied by @var{FF_QP2LAMBDA}.
> +
> +@item -preset @var{type}
> +Configuration preset. This does some automatic settings based on the
> general
> +type of the image.
> +@table @option
> +@item none
> +Do not use a preset.
> +@item default
> +Use the encoder default.
> +@item picture
> +Digital picture, like portrait, inner shot
> +@item photo
> +Outdoor photograph, with natural lighting
> +@item drawing
> +Hand or line drawing, with high-contrast details
> +@item icon
> +Small-sized colorful images
> +@item text
> +Text-like
> +@end table
> +
> +@end table
> +
>  @section libx264
>
>  x264 H.264/MPEG-4 AVC encoder wrapper
>
>  (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..399ee12
> --- /dev/null
> +++ b/libavcodec/libwebpenc.c
> @@ -0,0 +1,291 @@
> +/*
> + * 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/frame.h"
> +#include "libavutil/imgutils.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 preset;             // configuration preset
> +    WebPConfig config;      // libwebp configuration
> +    int chroma_warning;     // chroma linesize mismatch warning has been
> printed
> +    int conversion_warning; // pixel format conversion warning has been
> printed
> +} LibWebPContext;
> +
> +static int libwebp_error_to_averror(int err)
> +{
> +    switch (err) {
> +    case VP8_ENC_ERROR_OUT_OF_MEMORY:
> +    case VP8_ENC_ERROR_BITSTREAM_OUT_OF_MEMORY:
> +        return AVERROR(ENOMEM);
> +    case VP8_ENC_ERROR_NULL_PARAMETER:
> +    case VP8_ENC_ERROR_INVALID_CONFIGURATION:
> +    case VP8_ENC_ERROR_BAD_DIMENSION:
> +        return AVERROR(EINVAL);
> +    }
> +    return AVERROR_UNKNOWN;
> +}
> +
> +static av_cold int libwebp_encode_init(AVCodecContext *avctx)
> +{
> +    LibWebPContext *s = avctx->priv_data;
> +    int ret;
> +
> +    if (avctx->global_quality < 0)
> +        avctx->global_quality = 75 * FF_QP2LAMBDA;
> +    s->quality = av_clipf(avctx->global_quality / (float)FF_QP2LAMBDA,
> +                          0.0f, 100.0f);
> +
> +    if (avctx->compression_level < 0 || avctx->compression_level > 6) {
> +        av_log(avctx, AV_LOG_WARNING, "invalid compression level: %d\n",
> +               avctx->compression_level);
> +        avctx->compression_level = av_clip(avctx->compression_level, 0,
> 6);
> +    }
> +
> +    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;
> +        avctx->compression_level = 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   = avctx->compression_level;
> +
> +        ret = WebPValidateConfig(&s->config);
> +        if (!ret)
> +            return AVERROR(EINVAL);
> +    }
> +
> +    av_log(avctx, AV_LOG_DEBUG, "%s - quality=%.1f method=%d\n",
> +           s->lossless ? "Lossless" : "Lossy", s->quality,
> +           avctx->compression_level);
> +
> +    return 0;
> +}
> +
> +static int libwebp_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
> +                                const AVFrame *frame, int *got_packet)
> +{
> +    LibWebPContext *s  = avctx->priv_data;
> +    AVFrame *alt_frame = NULL;
> +    WebPPicture *pic = NULL;
> +    WebPMemoryWriter mw = { 0 };
> +    int ret, pic_is_copy = 0;
> +
> +    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);
> +    }
> +
> +    pic = av_malloc(sizeof(*pic));
> +    if (!pic)
> +        return AVERROR(ENOMEM);
> +
> +    ret = WebPPictureInit(pic);
> +    if (!ret) {
> +        ret = AVERROR_UNKNOWN;
> +        goto end;
> +    }
> +    pic->width  = avctx->width;
> +    pic->height = avctx->height;
> +
> +    if (avctx->pix_fmt == AV_PIX_FMT_RGB32) {
> +        if (!s->lossless) {
> +            /* libwebp will automatically convert RGB input to YUV when
> +               encoding lossy. */
> +            if (!s->conversion_warning) {
> +                av_log(avctx, AV_LOG_WARNING,
> +                       "Using libwebp for RGB-to-YUV conversion. You may
> want "
> +                       "to consider passing in YUV instead for lossy "
> +                       "encoding.\n");
> +                s->conversion_warning = 1;
> +            }
> +            pic_is_copy = 1;
> +        }
> +        pic->use_argb    = 1;
> +        pic->argb        = (uint32_t *)frame->data[0];
> +        pic->argb_stride = frame->linesize[0] / 4;
> +    } else {
> +        if (frame->linesize[1] != frame->linesize[2]) {
> +            if (!s->chroma_warning) {
> +                av_log(avctx, AV_LOG_WARNING,
> +                       "Copying frame due to differing chroma
> linesizes.\n");
> +                s->chroma_warning = 1;
> +            }
> +            alt_frame = av_frame_alloc();
> +            if (!alt_frame) {
> +                ret = AVERROR(ENOMEM);
> +                goto end;
> +            }
> +            alt_frame->width  = frame->width;
> +            alt_frame->height = frame->height;
> +            alt_frame->format = frame->format;
> +            ret = av_frame_get_buffer(alt_frame, 32);
> +            if (ret < 0)
> +                goto end;
> +            av_image_copy(alt_frame->data, alt_frame->linesize,
> +                          frame->data, frame->linesize,
> +                 --
> 1.7.1
>
> _______________________________________________
> libav-devel mailing list
> [email protected] <javascript:;>
> https://lists.libav.org/mailman/listinfo/libav-devel
>
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to