From: Josef Zlomek
Fixes: 4907
Adds support for decoding of animated WebP.
The WebP decoder adds the animation related features according to the specs:
https://developers.google.com/speed/webp/docs/riff_container#animation
The frames of the animation may be smaller than the image canvas.
Therefore, the frame is decoded to a temporary frame,
then it is blended into the canvas, the canvas is copied to the output frame,
and finally the frame is disposed from the canvas.
The output to AV_PIX_FMT_YUVA420P/AV_PIX_FMT_YUV420P is still supported.
The background color is specified only as BGRA in the WebP file
so it is converted to YUVA if YUV formats are output.
Signed-off-by: Josef Zlomek
---
Changelog | 1 +
libavcodec/codec_desc.c | 3 +-
libavcodec/version.h| 2 +-
libavcodec/webp.c | 710
4 files changed, 653 insertions(+), 63 deletions(-)
diff --git a/Changelog b/Changelog
index e83a00e35c..bafa56dc2a 100644
--- a/Changelog
+++ b/Changelog
@@ -77,6 +77,7 @@ version 6.1:
- ffprobe XML output schema changed to account for multiple
variable-fields elements within the same parent element
- ffprobe -output_format option added as an alias of -of
+- animated WebP decoder
version 6.0:
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 3bab86db62..b017acbc74 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1259,8 +1259,7 @@ static const AVCodecDescriptor codec_descriptors[] = {
.type = AVMEDIA_TYPE_VIDEO,
.name = "webp",
.long_name = NULL_IF_CONFIG_SMALL("WebP"),
-.props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
- AV_CODEC_PROP_LOSSLESS,
+.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,
.mime_types= MT("image/webp"),
},
{
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 06631ffa8c..789d9047c2 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
#include "version_major.h"
#define LIBAVCODEC_VERSION_MINOR 4
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
diff --git a/libavcodec/webp.c b/libavcodec/webp.c
index d6af48585e..293bb485de 100644
--- a/libavcodec/webp.c
+++ b/libavcodec/webp.c
@@ -35,12 +35,15 @@
* Exif metadata
* ICC profile
*
+ * @author Josef Zlomek, Pexeso Inc.
+ * Animation
+ *
* Unimplemented:
- * - Animation
* - XMP metadata
*/
#include "libavutil/imgutils.h"
+#include "libavutil/colorspace.h"
#define BITSTREAM_READER_LE
#include "avcodec.h"
@@ -67,6 +70,14 @@
#define NUM_SHORT_DISTANCES 120
#define MAX_HUFFMAN_CODE_LENGTH 15
+#define ANMF_DISPOSAL_METHOD0x01
+#define ANMF_DISPOSAL_METHOD_UNCHANGED 0x00
+#define ANMF_DISPOSAL_METHOD_BACKGROUND 0x01
+
+#define ANMF_BLENDING_METHOD0x02
+#define ANMF_BLENDING_METHOD_ALPHA 0x00
+#define ANMF_BLENDING_METHOD_OVERWRITE 0x02
+
static const uint16_t alphabet_sizes[HUFFMAN_CODES_PER_META_CODE] = {
NUM_LITERAL_CODES + NUM_LENGTH_CODES,
NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
@@ -191,6 +202,8 @@ typedef struct ImageContext {
typedef struct WebPContext {
VP8Context v; /* VP8 Context used for lossy decoding
*/
GetBitContext gb; /* bitstream reader for main image
chunk */
+ThreadFrame canvas_frame; /* ThreadFrame for canvas */
+AVFrame *frame; /* AVFrame for decoded frame */
AVFrame *alpha_frame; /* AVFrame for alpha data decompressed
from VP8L */
AVPacket *pkt; /* AVPacket to be passed to the
underlying VP8 decoder */
AVCodecContext *avctx; /* parent AVCodecContext */
@@ -205,7 +218,22 @@ typedef struct WebPContext {
int has_iccp; /* set after an ICCP chunk has been
processed */
int width; /* image width */
int height; /* image height */
-int lossless; /* indicates lossless or lossy */
+int vp8x_flags; /* global flags from VP8X chunk */
+int canvas_width; /* canvas width */
+int canvas_height; /* canvas height */
+int anmf_flags; /* frame flags from ANMF chunk */
+int pos_x; /* frame position X */
+int pos_y; /* frame position Y */
+int prev_anmf_flags;/* previous frame flags from ANMF
chunk */
+int prev_width; /* previous frame width */
+int prev_height;/* previous frame height */
+int prev_pos_x;