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>
This commit is contained in:
committed by
Michael Niedermayer
parent
ebb0ca3d70
commit
02cf59f3a6
@@ -21,6 +21,7 @@ version <next>:
|
|||||||
- Automatically rotate videos based on metadata in ffmpeg
|
- Automatically rotate videos based on metadata in ffmpeg
|
||||||
- improved Quickdraw compatibility
|
- improved Quickdraw compatibility
|
||||||
- VP9 high bit-depth and extended colorspaces decoding support
|
- VP9 high bit-depth and extended colorspaces decoding support
|
||||||
|
- WebPAnimEncoder API when available for encoding and muxing WebP
|
||||||
|
|
||||||
|
|
||||||
version 2.6:
|
version 2.6:
|
||||||
|
9
configure
vendored
9
configure
vendored
@@ -1695,6 +1695,7 @@ HEADERS_LIST="
|
|||||||
udplite_h
|
udplite_h
|
||||||
unistd_h
|
unistd_h
|
||||||
valgrind_valgrind_h
|
valgrind_valgrind_h
|
||||||
|
webp_mux_h
|
||||||
windows_h
|
windows_h
|
||||||
winsock2_h
|
winsock2_h
|
||||||
"
|
"
|
||||||
@@ -1897,6 +1898,7 @@ CONFIG_EXTRA="
|
|||||||
intrax8
|
intrax8
|
||||||
jpegtables
|
jpegtables
|
||||||
lgplv3
|
lgplv3
|
||||||
|
libwebp_anim
|
||||||
llauddsp
|
llauddsp
|
||||||
llviddsp
|
llviddsp
|
||||||
lpc
|
lpc
|
||||||
@@ -2451,6 +2453,7 @@ libvpx_vp9_decoder_deps="libvpx"
|
|||||||
libvpx_vp9_encoder_deps="libvpx"
|
libvpx_vp9_encoder_deps="libvpx"
|
||||||
libwavpack_encoder_deps="libwavpack"
|
libwavpack_encoder_deps="libwavpack"
|
||||||
libwebp_encoder_deps="libwebp"
|
libwebp_encoder_deps="libwebp"
|
||||||
|
libwebp_anim_encoder_deps="libwebp"
|
||||||
libx264_encoder_deps="libx264"
|
libx264_encoder_deps="libx264"
|
||||||
libx264rgb_encoder_deps="libx264"
|
libx264rgb_encoder_deps="libx264"
|
||||||
libx264rgb_encoder_select="libx264_encoder"
|
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_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 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 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 ||
|
enabled libx264 && { use_pkg_config x264 "stdint.h x264.h" x264_encoder_encode ||
|
||||||
{ require libx264 x264.h x264_encoder_encode -lx264 &&
|
{ require libx264 x264.h x264_encoder_encode -lx264 &&
|
||||||
warn "using libx264 without pkg-config"; } } &&
|
warn "using libx264 without pkg-config"; } } &&
|
||||||
|
@@ -784,6 +784,7 @@ OBJS-$(CONFIG_LIBVPX_VP9_DECODER) += libvpxdec.o libvpx.o
|
|||||||
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o
|
OBJS-$(CONFIG_LIBVPX_VP9_ENCODER) += libvpxenc.o libvpx.o
|
||||||
OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o
|
OBJS-$(CONFIG_LIBWAVPACK_ENCODER) += libwavpackenc.o
|
||||||
OBJS-$(CONFIG_LIBWEBP_ENCODER) += libwebpenc_common.o libwebpenc.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_LIBX264_ENCODER) += libx264.o
|
||||||
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
|
OBJS-$(CONFIG_LIBX265_ENCODER) += libx265.o
|
||||||
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
|
OBJS-$(CONFIG_LIBXAVS_ENCODER) += libxavs.o
|
||||||
|
@@ -540,6 +540,7 @@ void avcodec_register_all(void)
|
|||||||
REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8);
|
REGISTER_ENCDEC (LIBVPX_VP8, libvpx_vp8);
|
||||||
REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9);
|
REGISTER_ENCDEC (LIBVPX_VP9, libvpx_vp9);
|
||||||
REGISTER_ENCODER(LIBWAVPACK, libwavpack);
|
REGISTER_ENCODER(LIBWAVPACK, libwavpack);
|
||||||
|
REGISTER_ENCODER(LIBWEBP_ANIM, libwebp_anim); /* preferred over libwebp */
|
||||||
REGISTER_ENCODER(LIBWEBP, libwebp);
|
REGISTER_ENCODER(LIBWEBP, libwebp);
|
||||||
REGISTER_ENCODER(LIBX264, libx264);
|
REGISTER_ENCODER(LIBX264, libx264);
|
||||||
REGISTER_ENCODER(LIBX264RGB, libx264rgb);
|
REGISTER_ENCODER(LIBX264RGB, libx264rgb);
|
||||||
|
146
libavcodec/libwebpenc_animencoder.c
Normal file
146
libavcodec/libwebpenc_animencoder.c
Normal file
@@ -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,
|
||||||
|
};
|
@@ -29,8 +29,8 @@
|
|||||||
#include "libavutil/version.h"
|
#include "libavutil/version.h"
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_MAJOR 56
|
#define LIBAVCODEC_VERSION_MAJOR 56
|
||||||
#define LIBAVCODEC_VERSION_MINOR 39
|
#define LIBAVCODEC_VERSION_MINOR 40
|
||||||
#define LIBAVCODEC_VERSION_MICRO 101
|
#define LIBAVCODEC_VERSION_MICRO 100
|
||||||
|
|
||||||
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
|
||||||
LIBAVCODEC_VERSION_MINOR, \
|
LIBAVCODEC_VERSION_MINOR, \
|
||||||
|
Reference in New Issue
Block a user