summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUrvang Joshi <urvang@google.com>2015-05-19 18:04:07 -0700
committerMichael Niedermayer <michaelni@gmx.at>2015-05-23 03:31:28 +0200
commit02cf59f3a6192c95ef1394e21a6f87704194bc21 (patch)
treed1f586dcb5a52faf4c1675f41f5210e09df8dc6f
parentebb0ca3d70465ab6d369a66b2ef43bb059705db8 (diff)
WebP encoder: use WebPAnimEncoder API when available.
WebPAnimEncoder API is a combination of encoder (WebPEncoder) and muxer (WebPMux). It performs several optimizations to make it more efficient than the combination of WebPEncode() and native ffmpeg muxer. When WebPAnimEncoder API is used: - In the encoder layer: we use WebPAnimEncoderAdd() instead of WebPEncode(). - The muxer layer: works like a raw muxer. On the other hand, when WebPAnimEncoder API isn't available, the old code is used as it is: - In the codec layer: WebPEncode is used to encode each frame - In the muxer layer: ffmpeg muxer is used Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r--Changelog1
-rwxr-xr-xconfigure9
-rw-r--r--libavcodec/Makefile1
-rw-r--r--libavcodec/allcodecs.c1
-rw-r--r--libavcodec/libwebpenc_animencoder.c146
-rw-r--r--libavcodec/version.h4
6 files changed, 159 insertions, 3 deletions
diff --git a/Changelog b/Changelog
index 667dd2961b..e9e925af5d 100644
--- a/Changelog
+++ b/Changelog
@@ -21,6 +21,7 @@ version <next>:
- Automatically rotate videos based on metadata in ffmpeg
- improved Quickdraw compatibility
- VP9 high bit-depth and extended colorspaces decoding support
+- WebPAnimEncoder API when available for encoding and muxing WebP
version 2.6:
diff --git a/configure b/configure
index a02fe4a57c..8b9c3e2217 100755
--- a/configure
+++ b/configure
@@ -1695,6 +1695,7 @@ HEADERS_LIST="
udplite_h
unistd_h
valgrind_valgrind_h
+ webp_mux_h
windows_h
winsock2_h
"
@@ -1897,6 +1898,7 @@ CONFIG_EXTRA="
intrax8
jpegtables
lgplv3
+ libwebp_anim
llauddsp
llviddsp
lpc
@@ -2451,6 +2453,7 @@ libvpx_vp9_decoder_deps="libvpx"
libvpx_vp9_encoder_deps="libvpx"
libwavpack_encoder_deps="libwavpack"
libwebp_encoder_deps="libwebp"
+libwebp_anim_encoder_deps="libwebp"
libx264_encoder_deps="libx264"
libx264rgb_encoder_deps="libx264"
libx264rgb_encoder_select="libx264_encoder"
@@ -5102,7 +5105,11 @@ 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 VP9E_SET_AQ_MODE" -lvpx || disable libvpx_vp9_encoder; } }
enabled libwavpack && require libwavpack wavpack/wavpack.h WavpackOpenFileOutput -lwavpack
-enabled libwebp && require_pkg_config "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion
+enabled libwebp && {
+ enabled libwebp_encoder && require_pkg_config "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion;
+ enabled libwebp_anim_encoder && require_pkg_config "libwebp >= 0.2.0" webp/encode.h WebPGetEncoderVersion &&
+ { use_pkg_config "libwebpmux >= 0.4.0" webp/mux.h WebPAnimEncoderOptionsInit ||
+ { disable libwebp_anim_encoder && warn "using libwebp without libwebpmux"; } } }
enabled libx264 && { use_pkg_config x264 "stdint.h x264.h" x264_encoder_encode ||
{ require libx264 x264.h x264_encoder_encode -lx264 &&
warn "using libx264 without pkg-config"; } } &&
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 789a6d0fa5..02aa61e682 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -784,6 +784,7 @@ OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o
OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o
OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.o
+OBJS-$(CONFIG_LIBWEBP_ANIM_ENCODER) += libwebpenc_common.o libwebpenc_animencoder.o
OBJS-$(CONFIG_LIBX264_ENCODER) += libx264.o
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 25529628da..fe79d0bb3b 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -540,6 +540,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_ANIM, libwebp_anim); /* preferred over libwebp */
REGISTER_ENCODER(LIBWEBP, libwebp);
REGISTER_ENCODER(LIBX264, libx264);
REGISTER_ENCODER(LIBX264RGB, libx264rgb);
diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c
new file mode 100644
index 0000000000..860973e7a3
--- /dev/null
+++ b/libavcodec/libwebpenc_animencoder.c
@@ -0,0 +1,146 @@
+/*
+ * WebP encoding support via libwebp
+ * Copyright (c) 2015 Urvang Joshi
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg 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.
+ *
+ * FFmpeg 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 FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/**
+ * @file
+ * WebP encoder using libwebp (WebPAnimEncoder API)
+ */
+
+#include "config.h"
+#include "libwebpenc_common.h"
+
+#if HAVE_WEBP_MUX_H
+#include <webp/mux.h>
+#endif
+
+typedef struct LibWebPAnimContext {
+ LibWebPContextCommon cc;
+ WebPAnimEncoder *enc; // the main AnimEncoder object
+ int64_t prev_frame_pts; // pts of the previously encoded frame.
+ int done; // If true, we have assembled the bitstream already
+} LibWebPAnimContext;
+
+static av_cold int libwebp_anim_encode_init(AVCodecContext *avctx)
+{
+ int ret = ff_libwebp_encode_init_common(avctx);
+ if (!ret) {
+ LibWebPAnimContext *s = avctx->priv_data;
+ WebPAnimEncoderOptions enc_options;
+ WebPAnimEncoderOptionsInit(&enc_options);
+ // TODO(urvang): Expose some options on command-line perhaps.
+ s->enc = WebPAnimEncoderNew(avctx->width, avctx->height, &enc_options);
+ if (!s->enc)
+ return AVERROR(EINVAL);
+ s->prev_frame_pts = -1;
+ s->done = 0;
+ }
+ return ret;
+}
+
+static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
+ const AVFrame *frame, int *got_packet) {
+ LibWebPAnimContext *s = avctx->priv_data;
+ int ret;
+
+ if (!frame) {
+ if (s->done) { // Second flush: return empty package to denote finish.
+ *got_packet = 0;
+ return 0;
+ } else { // First flush: assemble bitstream and return it.
+ WebPData assembled_data = { 0 };
+ ret = WebPAnimEncoderAssemble(s->enc, &assembled_data);
+ if (ret) {
+ ret = ff_alloc_packet(pkt, assembled_data.size);
+ if (ret < 0)
+ return ret;
+ memcpy(pkt->data, assembled_data.bytes, assembled_data.size);
+ s->done = 1;
+ pkt->flags |= AV_PKT_FLAG_KEY;
+ pkt->pts = pkt->dts = s->prev_frame_pts + 1;
+ *got_packet = 1;
+ return 0;
+ } else {
+ av_log(s, AV_LOG_ERROR,
+ "WebPAnimEncoderAssemble() failed with error: %d\n",
+ VP8_ENC_ERROR_OUT_OF_MEMORY);
+ return AVERROR(ENOMEM);
+ }
+ }
+ } else {
+ int timestamp_ms;
+ WebPPicture *pic = NULL;
+ AVFrame *alt_frame = NULL;
+ ret = ff_libwebp_get_frame(avctx, &s->cc, frame, &alt_frame, &pic);
+ if (ret < 0)
+ goto end;
+
+ timestamp_ms =
+ avctx->time_base.num * frame->pts * 1000 / avctx->time_base.den;
+ ret = WebPAnimEncoderAdd(s->enc, pic, timestamp_ms, &s->cc.config);
+ if (!ret) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Encoding WebP frame failed with error: %d\n",
+ pic->error_code);
+ ret = ff_libwebp_error_to_averror(pic->error_code);
+ goto end;
+ }
+
+ pkt->pts = pkt->dts = frame->pts;
+ s->prev_frame_pts = frame->pts; // Save for next frame.
+ ret = 0;
+ *got_packet = 1;
+
+end:
+ WebPPictureFree(pic);
+ av_freep(&pic);
+ av_frame_free(&alt_frame);
+ return ret;
+ }
+}
+
+static int libwebp_anim_encode_close(AVCodecContext *avctx)
+{
+ int ret = ff_libwebp_encode_close_common(avctx);
+ if (!ret) {
+ LibWebPAnimContext *s = avctx->priv_data;
+ WebPAnimEncoderDelete(s->enc);
+ }
+ return ret;
+}
+
+AVCodec ff_libwebp_anim_encoder = {
+ .name = "libwebp_anim",
+ .long_name = NULL_IF_CONFIG_SMALL("libwebp WebP image"),
+ .type = AVMEDIA_TYPE_VIDEO,
+ .id = AV_CODEC_ID_WEBP,
+ .priv_data_size = sizeof(LibWebPAnimContext),
+ .init = libwebp_anim_encode_init,
+ .encode2 = libwebp_anim_encode_frame,
+ .close = libwebp_anim_encode_close,
+ .capabilities = CODEC_CAP_DELAY,
+ .pix_fmts = (const enum AVPixelFormat[]) {
+ AV_PIX_FMT_RGB32,
+ AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUVA420P,
+ AV_PIX_FMT_NONE
+ },
+ .priv_class = &class,
+ .defaults = libwebp_defaults,
+};
diff --git a/libavcodec/version.h b/libavcodec/version.h
index dd47af0f81..b9f99d7181 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,8 +29,8 @@
#include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 56
-#define LIBAVCODEC_VERSION_MINOR 39
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR 40
+#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \