Browse code

Merge commit 'c4bfa098072ba338d83555d6e2199f7e1e64ffff'

* commit 'c4bfa098072ba338d83555d6e2199f7e1e64ffff':
Add a WebP decoder

Conflicts:
Changelog
doc/general.texi
libavcodec/Makefile
libavcodec/avcodec.h
libavcodec/version.h
libavformat/img2.c

The previously existing webp decoder is disabled as the new
one supports lossless mode and alpha while the previous does not.

Merged-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2013/09/19 19:06:39
Showing 10 changed files
... ...
@@ -26,6 +26,7 @@ version <next>
26 26
 - adelay filter
27 27
 - pullup filter ported from libmpcodecs
28 28
 - ffprobe -read_intervals option
29
+- Lossless and alpha support for WebP decoder
29 30
 
30 31
 
31 32
 version 2.0:
... ...
@@ -488,6 +488,8 @@ following image formats are supported:
488 488
     @tab YUV, JPEG and some extension is not supported yet.
489 489
 @item Truevision Targa  @tab X @tab X
490 490
     @tab Targa (.TGA) image format
491
+@item WebP         @tab @tab X
492
+    @tab WebP image format
491 493
 @item XBM  @tab X @tab X
492 494
     @tab X BitMap image format
493 495
 @item XFace @tab X @tab X
... ...
@@ -476,6 +476,7 @@ OBJS-$(CONFIG_VQA_DECODER)             += vqavideo.o
476 476
 OBJS-$(CONFIG_WAVPACK_DECODER)         += wavpack.o
477 477
 OBJS-$(CONFIG_WAVPACK_ENCODER)         += wavpackenc.o
478 478
 OBJS-$(CONFIG_WEBP_DECODER)            += vp8.o vp8dsp.o vp56rac.o
479
+OBJS-$(CONFIG_WEBP_DECODER)            += webp.o
479 480
 OBJS-$(CONFIG_WEBVTT_DECODER)          += webvttdec.o
480 481
 OBJS-$(CONFIG_WMALOSSLESS_DECODER)     += wmalosslessdec.o wma_common.o
481 482
 OBJS-$(CONFIG_WMAPRO_DECODER)          += wmaprodec.o wma.o wma_common.o
... ...
@@ -275,6 +275,7 @@ enum AVCodecID {
275 275
     AV_CODEC_ID_AIC,
276 276
     AV_CODEC_ID_ESCAPE130_DEPRECATED,
277 277
     AV_CODEC_ID_G2M_DEPRECATED,
278
+    AV_CODEC_ID_WEBP_DEPRECATED,
278 279
 
279 280
     AV_CODEC_ID_BRENDER_PIX= MKBETAG('B','P','I','X'),
280 281
     AV_CODEC_ID_Y41P       = MKBETAG('Y','4','1','P'),
... ...
@@ -1045,13 +1045,6 @@ static const AVCodecDescriptor codec_descriptors[] = {
1045 1045
         .props     = AV_CODEC_PROP_LOSSY,
1046 1046
     },
1047 1047
     {
1048
-        .id        = AV_CODEC_ID_WEBP,
1049
-        .type      = AVMEDIA_TYPE_VIDEO,
1050
-        .name      = "webp",
1051
-        .long_name = NULL_IF_CONFIG_SMALL("WebP"),
1052
-        .props     = AV_CODEC_PROP_LOSSY,
1053
-    },
1054
-    {
1055 1048
         .id        = AV_CODEC_ID_PICTOR,
1056 1049
         .type      = AVMEDIA_TYPE_VIDEO,
1057 1050
         .name      = "pictor",
... ...
@@ -1393,6 +1386,14 @@ static const AVCodecDescriptor codec_descriptors[] = {
1393 1393
         .long_name = NULL_IF_CONFIG_SMALL("Go2Meeting"),
1394 1394
         .props     = AV_CODEC_PROP_LOSSY,
1395 1395
     },
1396
+    {
1397
+        .id        = AV_CODEC_ID_WEBP,
1398
+        .type      = AVMEDIA_TYPE_VIDEO,
1399
+        .name      = "webp",
1400
+        .long_name = NULL_IF_CONFIG_SMALL("WebP"),
1401
+        .props     = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY |
1402
+                     AV_CODEC_PROP_LOSSLESS,
1403
+    },
1396 1404
 
1397 1405
     /* various PCM "codecs" */
1398 1406
     {
... ...
@@ -2487,6 +2487,7 @@ static enum AVCodecID remap_deprecated_codec_id(enum AVCodecID id)
2487 2487
         case AV_CODEC_ID_TAK_DEPRECATED : return AV_CODEC_ID_TAK;
2488 2488
         case AV_CODEC_ID_ESCAPE130_DEPRECATED : return AV_CODEC_ID_ESCAPE130;
2489 2489
         case AV_CODEC_ID_G2M_DEPRECATED : return AV_CODEC_ID_G2M;
2490
+        case AV_CODEC_ID_WEBP_DEPRECATED: return AV_CODEC_ID_WEBP;
2490 2491
         default                         : return id;
2491 2492
     }
2492 2493
 }
... ...
@@ -29,8 +29,8 @@
29 29
 #include "libavutil/avutil.h"
30 30
 
31 31
 #define LIBAVCODEC_VERSION_MAJOR 55
32
-#define LIBAVCODEC_VERSION_MINOR  31
33
-#define LIBAVCODEC_VERSION_MICRO 101
32
+#define LIBAVCODEC_VERSION_MINOR  32
33
+#define LIBAVCODEC_VERSION_MICRO 100
34 34
 
35 35
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
36 36
                                                LIBAVCODEC_VERSION_MINOR, \
... ...
@@ -1854,8 +1854,8 @@ static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata,
1854 1854
     return 0;
1855 1855
 }
1856 1856
 
1857
-static int vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
1858
-                            AVPacket *avpkt)
1857
+int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
1858
+                        AVPacket *avpkt)
1859 1859
 {
1860 1860
     VP8Context *s = avctx->priv_data;
1861 1861
     int ret, i, referenced, num_jobs;
... ...
@@ -2009,7 +2009,7 @@ err:
2009 2009
     return ret;
2010 2010
 }
2011 2011
 
2012
-static av_cold int vp8_decode_free(AVCodecContext *avctx)
2012
+av_cold int ff_vp8_decode_free(AVCodecContext *avctx)
2013 2013
 {
2014 2014
     VP8Context *s = avctx->priv_data;
2015 2015
     int i;
... ...
@@ -2032,7 +2032,7 @@ static av_cold int vp8_init_frames(VP8Context *s)
2032 2032
     return 0;
2033 2033
 }
2034 2034
 
2035
-static av_cold int vp8_decode_init(AVCodecContext *avctx)
2035
+av_cold int ff_vp8_decode_init(AVCodecContext *avctx)
2036 2036
 {
2037 2037
     VP8Context *s = avctx->priv_data;
2038 2038
     int ret;
... ...
@@ -2046,7 +2046,7 @@ static av_cold int vp8_decode_init(AVCodecContext *avctx)
2046 2046
     ff_vp8dsp_init(&s->vp8dsp);
2047 2047
 
2048 2048
     if ((ret = vp8_init_frames(s)) < 0) {
2049
-        vp8_decode_free(avctx);
2049
+        ff_vp8_decode_free(avctx);
2050 2050
         return ret;
2051 2051
     }
2052 2052
 
... ...
@@ -2061,7 +2061,7 @@ static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx)
2061 2061
     s->avctx = avctx;
2062 2062
 
2063 2063
     if ((ret = vp8_init_frames(s)) < 0) {
2064
-        vp8_decode_free(avctx);
2064
+        ff_vp8_decode_free(avctx);
2065 2065
         return ret;
2066 2066
     }
2067 2067
 
... ...
@@ -2147,7 +2147,7 @@ static int webp_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
2147 2147
     pkt.data = buf;
2148 2148
     pkt.size = buf_size;
2149 2149
 
2150
-    return vp8_decode_frame(avctx, data, data_size, &pkt);
2150
+    return ff_vp8_decode_frame(avctx, data, data_size, &pkt);
2151 2151
 }
2152 2152
 
2153 2153
 AVCodec ff_vp8_decoder = {
... ...
@@ -2155,9 +2155,9 @@ AVCodec ff_vp8_decoder = {
2155 2155
     .type                  = AVMEDIA_TYPE_VIDEO,
2156 2156
     .id                    = AV_CODEC_ID_VP8,
2157 2157
     .priv_data_size        = sizeof(VP8Context),
2158
-    .init                  = vp8_decode_init,
2159
-    .close                 = vp8_decode_free,
2160
-    .decode                = vp8_decode_frame,
2158
+    .init                  = ff_vp8_decode_init,
2159
+    .close                 = ff_vp8_decode_free,
2160
+    .decode                = ff_vp8_decode_frame,
2161 2161
     .capabilities          = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS,
2162 2162
     .flush                 = vp8_decode_flush,
2163 2163
     .long_name             = NULL_IF_CONFIG_SMALL("On2 VP8"),
... ...
@@ -2165,17 +2165,17 @@ AVCodec ff_vp8_decoder = {
2165 2165
     .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context),
2166 2166
 };
2167 2167
 
2168
-AVCodec ff_webp_decoder = {
2169
-    .name                  = "webp",
2170
-    .type                  = AVMEDIA_TYPE_VIDEO,
2171
-    .id                    = AV_CODEC_ID_WEBP,
2172
-    .priv_data_size        = sizeof(VP8Context),
2173
-    .init                  = vp8_decode_init,
2174
-    .close                 = vp8_decode_free,
2175
-    .decode                = webp_decode_frame,
2176
-    .capabilities          = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS,
2177
-    .flush                 = vp8_decode_flush,
2178
-    .long_name             = NULL_IF_CONFIG_SMALL("WebP"),
2179
-    .init_thread_copy      = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy),
2180
-    .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context),
2181
-};
2168
+// AVCodec ff_webp_decoder = {
2169
+//     .name                  = "webp",
2170
+//     .type                  = AVMEDIA_TYPE_VIDEO,
2171
+//     .id                    = AV_CODEC_ID_WEBP,
2172
+//     .priv_data_size        = sizeof(VP8Context),
2173
+//     .init                  = vp8_decode_init,
2174
+//     .close                 = vp8_decode_free,
2175
+//     .decode                = webp_decode_frame,
2176
+//     .capabilities          = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS,
2177
+//     .flush                 = vp8_decode_flush,
2178
+//     .long_name             = NULL_IF_CONFIG_SMALL("WebP"),
2179
+//     .init_thread_copy      = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy),
2180
+//     .update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context),
2181
+// };
... ...
@@ -271,4 +271,11 @@ typedef struct VP8Context {
271 271
     int mb_layout;
272 272
 } VP8Context;
273 273
 
274
+int ff_vp8_decode_init(AVCodecContext *avctx);
275
+
276
+int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
277
+                        AVPacket *avpkt);
278
+
279
+int ff_vp8_decode_free(AVCodecContext *avctx);
280
+
274 281
 #endif /* AVCODEC_VP8_H */
275 282
new file mode 100644
... ...
@@ -0,0 +1,1455 @@
0
+/*
1
+ * WebP (.webp) image decoder
2
+ * Copyright (c) 2013 Aneesh Dogra <aneesh@sugarlabs.org>
3
+ * Copyright (c) 2013 Justin Ruggles <justin.ruggles@gmail.com>
4
+ *
5
+ * This file is part of FFmpeg.
6
+ *
7
+ * FFmpeg is free software; you can redistribute it and/or
8
+ * modify it under the terms of the GNU Lesser General Public
9
+ * License as published by the Free Software Foundation; either
10
+ * version 2.1 of the License, or (at your option) any later version.
11
+ *
12
+ * FFmpeg is distributed in the hope that it will be useful,
13
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
+ * Lesser General Public License for more details.
16
+ *
17
+ * You should have received a copy of the GNU Lesser General Public
18
+ * License along with FFmpeg; if not, write to the Free Software
19
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
+ */
21
+
22
+/**
23
+ * @file
24
+ * WebP image decoder
25
+ *
26
+ * @author Aneesh Dogra <aneesh@sugarlabs.org>
27
+ * Container and Lossy decoding
28
+ *
29
+ * @author Justin Ruggles <justin.ruggles@gmail.com>
30
+ * Lossless decoder
31
+ * Compressed alpha for lossy
32
+ *
33
+ * Unimplemented:
34
+ *   - Animation
35
+ *   - ICC profile
36
+ *   - Exif and XMP metadata
37
+ */
38
+
39
+#define BITSTREAM_READER_LE
40
+#include "libavutil/imgutils.h"
41
+#include "avcodec.h"
42
+#include "bytestream.h"
43
+#include "internal.h"
44
+#include "get_bits.h"
45
+#include "thread.h"
46
+#include "vp8.h"
47
+
48
+#define VP8X_FLAG_ANIMATION             0x02
49
+#define VP8X_FLAG_XMP_METADATA          0x04
50
+#define VP8X_FLAG_EXIF_METADATA         0x08
51
+#define VP8X_FLAG_ALPHA                 0x10
52
+#define VP8X_FLAG_ICC                   0x20
53
+
54
+#define MAX_PALETTE_SIZE                256
55
+#define MAX_CACHE_BITS                  11
56
+#define NUM_CODE_LENGTH_CODES           19
57
+#define HUFFMAN_CODES_PER_META_CODE     5
58
+#define NUM_LITERAL_CODES               256
59
+#define NUM_LENGTH_CODES                24
60
+#define NUM_DISTANCE_CODES              40
61
+#define NUM_SHORT_DISTANCES             120
62
+#define MAX_HUFFMAN_CODE_LENGTH         15
63
+
64
+static const uint16_t alphabet_sizes[HUFFMAN_CODES_PER_META_CODE] = {
65
+    NUM_LITERAL_CODES + NUM_LENGTH_CODES,
66
+    NUM_LITERAL_CODES, NUM_LITERAL_CODES, NUM_LITERAL_CODES,
67
+    NUM_DISTANCE_CODES
68
+};
69
+
70
+static const uint8_t code_length_code_order[NUM_CODE_LENGTH_CODES] = {
71
+    17, 18, 0, 1, 2, 3, 4, 5, 16, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
72
+};
73
+
74
+static const int8_t lz77_distance_offsets[NUM_SHORT_DISTANCES][2] = {
75
+    {  0, 1 }, {  1, 0 }, {  1, 1 }, { -1, 1 }, {  0, 2 }, {  2, 0 }, {  1, 2 }, { -1, 2 },
76
+    {  2, 1 }, { -2, 1 }, {  2, 2 }, { -2, 2 }, {  0, 3 }, {  3, 0 }, {  1, 3 }, { -1, 3 },
77
+    {  3, 1 }, { -3, 1 }, {  2, 3 }, { -2, 3 }, {  3, 2 }, { -3, 2 }, {  0, 4 }, {  4, 0 },
78
+    {  1, 4 }, { -1, 4 }, {  4, 1 }, { -4, 1 }, {  3, 3 }, { -3, 3 }, {  2, 4 }, { -2, 4 },
79
+    {  4, 2 }, { -4, 2 }, {  0, 5 }, {  3, 4 }, { -3, 4 }, {  4, 3 }, { -4, 3 }, {  5, 0 },
80
+    {  1, 5 }, { -1, 5 }, {  5, 1 }, { -5, 1 }, {  2, 5 }, { -2, 5 }, {  5, 2 }, { -5, 2 },
81
+    {  4, 4 }, { -4, 4 }, {  3, 5 }, { -3, 5 }, {  5, 3 }, { -5, 3 }, {  0, 6 }, {  6, 0 },
82
+    {  1, 6 }, { -1, 6 }, {  6, 1 }, { -6, 1 }, {  2, 6 }, { -2, 6 }, {  6, 2 }, { -6, 2 },
83
+    {  4, 5 }, { -4, 5 }, {  5, 4 }, { -5, 4 }, {  3, 6 }, { -3, 6 }, {  6, 3 }, { -6, 3 },
84
+    {  0, 7 }, {  7, 0 }, {  1, 7 }, { -1, 7 }, {  5, 5 }, { -5, 5 }, {  7, 1 }, { -7, 1 },
85
+    {  4, 6 }, { -4, 6 }, {  6, 4 }, { -6, 4 }, {  2, 7 }, { -2, 7 }, {  7, 2 }, { -7, 2 },
86
+    {  3, 7 }, { -3, 7 }, {  7, 3 }, { -7, 3 }, {  5, 6 }, { -5, 6 }, {  6, 5 }, { -6, 5 },
87
+    {  8, 0 }, {  4, 7 }, { -4, 7 }, {  7, 4 }, { -7, 4 }, {  8, 1 }, {  8, 2 }, {  6, 6 },
88
+    { -6, 6 }, {  8, 3 }, {  5, 7 }, { -5, 7 }, {  7, 5 }, { -7, 5 }, {  8, 4 }, {  6, 7 },
89
+    { -6, 7 }, {  7, 6 }, { -7, 6 }, {  8, 5 }, {  7, 7 }, { -7, 7 }, {  8, 6 }, {  8, 7 }
90
+};
91
+
92
+enum AlphaCompression {
93
+    ALPHA_COMPRESSION_NONE,
94
+    ALPHA_COMPRESSION_VP8L,
95
+};
96
+
97
+enum AlphaFilter {
98
+    ALPHA_FILTER_NONE,
99
+    ALPHA_FILTER_HORIZONTAL,
100
+    ALPHA_FILTER_VERTICAL,
101
+    ALPHA_FILTER_GRADIENT,
102
+};
103
+
104
+enum TransformType {
105
+    PREDICTOR_TRANSFORM      = 0,
106
+    COLOR_TRANSFORM          = 1,
107
+    SUBTRACT_GREEN           = 2,
108
+    COLOR_INDEXING_TRANSFORM = 3,
109
+};
110
+
111
+enum PredictionMode {
112
+    PRED_MODE_BLACK,
113
+    PRED_MODE_L,
114
+    PRED_MODE_T,
115
+    PRED_MODE_TR,
116
+    PRED_MODE_TL,
117
+    PRED_MODE_AVG_T_AVG_L_TR,
118
+    PRED_MODE_AVG_L_TL,
119
+    PRED_MODE_AVG_L_T,
120
+    PRED_MODE_AVG_TL_T,
121
+    PRED_MODE_AVG_T_TR,
122
+    PRED_MODE_AVG_AVG_L_TL_AVG_T_TR,
123
+    PRED_MODE_SELECT,
124
+    PRED_MODE_ADD_SUBTRACT_FULL,
125
+    PRED_MODE_ADD_SUBTRACT_HALF,
126
+};
127
+
128
+enum HuffmanIndex {
129
+    HUFF_IDX_GREEN = 0,
130
+    HUFF_IDX_RED   = 1,
131
+    HUFF_IDX_BLUE  = 2,
132
+    HUFF_IDX_ALPHA = 3,
133
+    HUFF_IDX_DIST  = 4
134
+};
135
+
136
+/* The structure of WebP lossless is an optional series of transformation data,
137
+ * followed by the primary image. The primary image also optionally contains
138
+ * an entropy group mapping if there are multiple entropy groups. There is a
139
+ * basic image type called an "entropy coded image" that is used for all of
140
+ * these. The type of each entropy coded image is referred to by the
141
+ * specification as its role. */
142
+enum ImageRole {
143
+    /* Primary Image: Stores the actual pixels of the image. */
144
+    IMAGE_ROLE_ARGB,
145
+
146
+    /* Entropy Image: Defines which Huffman group to use for different areas of
147
+     *                the primary image. */
148
+    IMAGE_ROLE_ENTROPY,
149
+
150
+    /* Predictors: Defines which predictor type to use for different areas of
151
+     *             the primary image. */
152
+    IMAGE_ROLE_PREDICTOR,
153
+
154
+    /* Color Transform Data: Defines the color transformation for different
155
+     *                       areas of the primary image. */
156
+    IMAGE_ROLE_COLOR_TRANSFORM,
157
+
158
+    /* Color Index: Stored as an image of height == 1. */
159
+    IMAGE_ROLE_COLOR_INDEXING,
160
+
161
+    IMAGE_ROLE_NB,
162
+};
163
+
164
+typedef struct HuffReader {
165
+    VLC vlc;                            /* Huffman decoder context */
166
+    int simple;                         /* whether to use simple mode */
167
+    int nb_symbols;                     /* number of coded symbols */
168
+    uint16_t simple_symbols[2];         /* symbols for simple mode */
169
+} HuffReader;
170
+
171
+typedef struct ImageContext {
172
+    enum ImageRole role;                /* role of this image */
173
+    AVFrame *frame;                     /* AVFrame for data */
174
+    int color_cache_bits;               /* color cache size, log2 */
175
+    uint32_t *color_cache;              /* color cache data */
176
+    int nb_huffman_groups;              /* number of huffman groups */
177
+    HuffReader *huffman_groups;         /* reader for each huffman group */
178
+    int size_reduction;                 /* relative size compared to primary image, log2 */
179
+    int is_alpha_primary;
180
+} ImageContext;
181
+
182
+typedef struct WebPContext {
183
+    VP8Context v;                       /* VP8 Context used for lossy decoding */
184
+    GetBitContext gb;                   /* bitstream reader for main image chunk */
185
+    AVFrame *alpha_frame;               /* AVFrame for alpha data decompressed from VP8L */
186
+    AVCodecContext *avctx;              /* parent AVCodecContext */
187
+    int initialized;                    /* set once the VP8 context is initialized */
188
+    int has_alpha;                      /* has a separate alpha chunk */
189
+    enum AlphaCompression alpha_compression; /* compression type for alpha chunk */
190
+    enum AlphaFilter alpha_filter;      /* filtering method for alpha chunk */
191
+    uint8_t *alpha_data;                /* alpha chunk data */
192
+    int alpha_data_size;                /* alpha chunk data size */
193
+    int width;                          /* image width */
194
+    int height;                         /* image height */
195
+    int lossless;                       /* indicates lossless or lossy */
196
+
197
+    int nb_transforms;                  /* number of transforms */
198
+    enum TransformType transforms[4];   /* transformations used in the image, in order */
199
+    int reduced_width;                  /* reduced width for index image, if applicable */
200
+    int nb_huffman_groups;              /* number of huffman groups in the primary image */
201
+    ImageContext image[IMAGE_ROLE_NB];  /* image context for each role */
202
+} WebPContext;
203
+
204
+#define GET_PIXEL(frame, x, y) \
205
+    ((frame)->data[0] + (y) * frame->linesize[0] + 4 * (x))
206
+
207
+#define GET_PIXEL_COMP(frame, x, y, c) \
208
+    (*((frame)->data[0] + (y) * frame->linesize[0] + 4 * (x) + c))
209
+
210
+static void image_ctx_free(ImageContext *img)
211
+{
212
+    int i, j;
213
+
214
+    av_free(img->color_cache);
215
+    if (img->role != IMAGE_ROLE_ARGB && !img->is_alpha_primary)
216
+        av_frame_free(&img->frame);
217
+    if (img->huffman_groups) {
218
+        for (i = 0; i < img->nb_huffman_groups; i++) {
219
+            for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; j++)
220
+                ff_free_vlc(&img->huffman_groups[i * HUFFMAN_CODES_PER_META_CODE + j].vlc);
221
+        }
222
+        av_free(img->huffman_groups);
223
+    }
224
+    memset(img, 0, sizeof(*img));
225
+}
226
+
227
+
228
+/* Differs from get_vlc2() in the following ways:
229
+ *   - codes are bit-reversed
230
+ *   - assumes 8-bit table to make reversal simpler
231
+ *   - assumes max depth of 2 since the max code length for WebP is 15
232
+ */
233
+static av_always_inline int webp_get_vlc(GetBitContext *gb, VLC_TYPE (*table)[2])
234
+{
235
+    int n, nb_bits;
236
+    unsigned int index;
237
+    int code;
238
+
239
+    OPEN_READER(re, gb);
240
+    UPDATE_CACHE(re, gb);
241
+
242
+    index = SHOW_UBITS(re, gb, 8);
243
+    index = ff_reverse[index];
244
+    code  = table[index][0];
245
+    n     = table[index][1];
246
+
247
+    if (n < 0) {
248
+        LAST_SKIP_BITS(re, gb, 8);
249
+        UPDATE_CACHE(re, gb);
250
+
251
+        nb_bits = -n;
252
+
253
+        index = SHOW_UBITS(re, gb, nb_bits);
254
+        index = (ff_reverse[index] >> (8 - nb_bits)) + code;
255
+        code  = table[index][0];
256
+        n     = table[index][1];
257
+    }
258
+    SKIP_BITS(re, gb, n);
259
+
260
+    CLOSE_READER(re, gb);
261
+
262
+    return code;
263
+}
264
+
265
+static int huff_reader_get_symbol(HuffReader *r, GetBitContext *gb)
266
+{
267
+    if (r->simple) {
268
+        if (r->nb_symbols == 1)
269
+            return r->simple_symbols[0];
270
+        else
271
+            return r->simple_symbols[get_bits1(gb)];
272
+    } else
273
+        return webp_get_vlc(gb, r->vlc.table);
274
+}
275
+
276
+static int huff_reader_build_canonical(HuffReader *r, int *code_lengths,
277
+                                       int alphabet_size)
278
+{
279
+    int len, sym, code, ret;
280
+    int max_code_length = 0;
281
+    uint16_t *codes;
282
+
283
+    for (sym = 0; sym < alphabet_size; sym++)
284
+        max_code_length = FFMAX(max_code_length, code_lengths[sym]);
285
+
286
+    if (max_code_length == 0 || max_code_length > MAX_HUFFMAN_CODE_LENGTH)
287
+        return AVERROR(EINVAL);
288
+
289
+    codes = av_malloc(alphabet_size * sizeof(*codes));
290
+    if (!codes)
291
+        return AVERROR(ENOMEM);
292
+
293
+    code = 0;
294
+    r->nb_symbols = 0;
295
+    for (len = 1; len <= max_code_length; len++) {
296
+        for (sym = 0; sym < alphabet_size; sym++) {
297
+            if (code_lengths[sym] != len)
298
+                continue;
299
+            codes[sym] = code++;
300
+            r->nb_symbols++;
301
+        }
302
+        code <<= 1;
303
+    }
304
+    if (!r->nb_symbols) {
305
+        av_free(codes);
306
+        return AVERROR_INVALIDDATA;
307
+    }
308
+
309
+    ret = init_vlc(&r->vlc, 8, alphabet_size,
310
+                   code_lengths, sizeof(*code_lengths), sizeof(*code_lengths),
311
+                   codes, sizeof(*codes), sizeof(*codes), 0);
312
+    if (ret < 0) {
313
+        av_free(codes);
314
+        return ret;
315
+    }
316
+    r->simple = 0;
317
+
318
+    av_free(codes);
319
+    return 0;
320
+}
321
+
322
+static void read_huffman_code_simple(WebPContext *s, HuffReader *hc)
323
+{
324
+    hc->nb_symbols = get_bits1(&s->gb) + 1;
325
+
326
+    if (get_bits1(&s->gb))
327
+        hc->simple_symbols[0] = get_bits(&s->gb, 8);
328
+    else
329
+        hc->simple_symbols[0] = get_bits1(&s->gb);
330
+
331
+    if (hc->nb_symbols == 2)
332
+        hc->simple_symbols[1] = get_bits(&s->gb, 8);
333
+
334
+    hc->simple = 1;
335
+}
336
+
337
+static int read_huffman_code_normal(WebPContext *s, HuffReader *hc,
338
+                                    int alphabet_size)
339
+{
340
+    HuffReader code_len_hc = { { 0 }, 0, 0, { 0 } };
341
+    int *code_lengths = NULL;
342
+    int code_length_code_lengths[NUM_CODE_LENGTH_CODES] = { 0 };
343
+    int i, symbol, max_symbol, prev_code_len, ret;
344
+    int num_codes = 4 + get_bits(&s->gb, 4);
345
+
346
+    if (num_codes > NUM_CODE_LENGTH_CODES)
347
+        return AVERROR_INVALIDDATA;
348
+
349
+    for (i = 0; i < num_codes; i++)
350
+        code_length_code_lengths[code_length_code_order[i]] = get_bits(&s->gb, 3);
351
+
352
+    ret = huff_reader_build_canonical(&code_len_hc, code_length_code_lengths,
353
+                                      NUM_CODE_LENGTH_CODES);
354
+    if (ret < 0)
355
+        goto finish;
356
+
357
+    code_lengths = av_mallocz_array(alphabet_size, sizeof(*code_lengths));
358
+    if (!code_lengths) {
359
+        ret = AVERROR(ENOMEM);
360
+        goto finish;
361
+    }
362
+
363
+    if (get_bits1(&s->gb)) {
364
+        int bits   = 2 + 2 * get_bits(&s->gb, 3);
365
+        max_symbol = 2 + get_bits(&s->gb, bits);
366
+        if (max_symbol > alphabet_size) {
367
+            av_log(s->avctx, AV_LOG_ERROR, "max symbol %d > alphabet size %d\n",
368
+                   max_symbol, alphabet_size);
369
+            ret = AVERROR_INVALIDDATA;
370
+            goto finish;
371
+        }
372
+    } else {
373
+        max_symbol = alphabet_size;
374
+    }
375
+
376
+    prev_code_len = 8;
377
+    symbol        = 0;
378
+    while (symbol < alphabet_size) {
379
+        int code_len;
380
+
381
+        if (!max_symbol--)
382
+            break;
383
+        code_len = huff_reader_get_symbol(&code_len_hc, &s->gb);
384
+        if (code_len < 16) {
385
+            /* Code length code [0..15] indicates literal code lengths. */
386
+            code_lengths[symbol++] = code_len;
387
+            if (code_len)
388
+                prev_code_len = code_len;
389
+        } else {
390
+            int repeat = 0, length = 0;
391
+            switch (code_len) {
392
+            case 16:
393
+                /* Code 16 repeats the previous non-zero value [3..6] times,
394
+                 * i.e., 3 + ReadBits(2) times. If code 16 is used before a
395
+                 * non-zero value has been emitted, a value of 8 is repeated. */
396
+                repeat = 3 + get_bits(&s->gb, 2);
397
+                length = prev_code_len;
398
+                break;
399
+            case 17:
400
+                /* Code 17 emits a streak of zeros [3..10], i.e.,
401
+                 * 3 + ReadBits(3) times. */
402
+                repeat = 3 + get_bits(&s->gb, 3);
403
+                break;
404
+            case 18:
405
+                /* Code 18 emits a streak of zeros of length [11..138], i.e.,
406
+                 * 11 + ReadBits(7) times. */
407
+                repeat = 11 + get_bits(&s->gb, 7);
408
+                break;
409
+            }
410
+            if (symbol + repeat > alphabet_size) {
411
+                av_log(s->avctx, AV_LOG_ERROR,
412
+                       "invalid symbol %d + repeat %d > alphabet size %d\n",
413
+                       symbol, repeat, alphabet_size);
414
+                ret = AVERROR_INVALIDDATA;
415
+                goto finish;
416
+            }
417
+            while (repeat-- > 0)
418
+                code_lengths[symbol++] = length;
419
+        }
420
+    }
421
+
422
+    ret = huff_reader_build_canonical(hc, code_lengths, alphabet_size);
423
+
424
+finish:
425
+    ff_free_vlc(&code_len_hc.vlc);
426
+    av_free(code_lengths);
427
+    return ret;
428
+}
429
+
430
+static int decode_entropy_coded_image(WebPContext *s, enum ImageRole role,
431
+                                      int w, int h);
432
+
433
+#define PARSE_BLOCK_SIZE(w, h) do {                                         \
434
+    block_bits = get_bits(&s->gb, 3) + 2;                                   \
435
+    blocks_w   = FFALIGN((w), 1 << block_bits) >> block_bits;               \
436
+    blocks_h   = FFALIGN((h), 1 << block_bits) >> block_bits;               \
437
+} while (0)
438
+
439
+static int decode_entropy_image(WebPContext *s)
440
+{
441
+    ImageContext *img;
442
+    int ret, block_bits, width, blocks_w, blocks_h, x, y, max;
443
+
444
+    width = s->width;
445
+    if (s->reduced_width > 0)
446
+        width = s->reduced_width;
447
+
448
+    PARSE_BLOCK_SIZE(width, s->height);
449
+
450
+    ret = decode_entropy_coded_image(s, IMAGE_ROLE_ENTROPY, blocks_w, blocks_h);
451
+    if (ret < 0)
452
+        return ret;
453
+
454
+    img = &s->image[IMAGE_ROLE_ENTROPY];
455
+    img->size_reduction = block_bits;
456
+
457
+    /* the number of huffman groups is determined by the maximum group number
458
+     * coded in the entropy image */
459
+    max = 0;
460
+    for (y = 0; y < img->frame->height; y++) {
461
+        for (x = 0; x < img->frame->width; x++) {
462
+            int p = GET_PIXEL_COMP(img->frame, x, y, 2);
463
+            max = FFMAX(max, p);
464
+        }
465
+    }
466
+    s->nb_huffman_groups = max + 1;
467
+
468
+    return 0;
469
+}
470
+
471
+static int parse_transform_predictor(WebPContext *s)
472
+{
473
+    int block_bits, blocks_w, blocks_h, ret;
474
+
475
+    PARSE_BLOCK_SIZE(s->width, s->height);
476
+
477
+    ret = decode_entropy_coded_image(s, IMAGE_ROLE_PREDICTOR, blocks_w,
478
+                                     blocks_h);
479
+    if (ret < 0)
480
+        return ret;
481
+
482
+    s->image[IMAGE_ROLE_PREDICTOR].size_reduction = block_bits;
483
+
484
+    return 0;
485
+}
486
+
487
+static int parse_transform_color(WebPContext *s)
488
+{
489
+    int block_bits, blocks_w, blocks_h, ret;
490
+
491
+    PARSE_BLOCK_SIZE(s->width, s->height);
492
+
493
+    ret = decode_entropy_coded_image(s, IMAGE_ROLE_COLOR_TRANSFORM, blocks_w,
494
+                                     blocks_h);
495
+    if (ret < 0)
496
+        return ret;
497
+
498
+    s->image[IMAGE_ROLE_COLOR_TRANSFORM].size_reduction = block_bits;
499
+
500
+    return 0;
501
+}
502
+
503
+static int parse_transform_color_indexing(WebPContext *s)
504
+{
505
+    ImageContext *img;
506
+    int width_bits, index_size, ret, x;
507
+    uint8_t *ct;
508
+
509
+    index_size = get_bits(&s->gb, 8) + 1;
510
+
511
+    if (index_size <= 2)
512
+        width_bits = 3;
513
+    else if (index_size <= 4)
514
+        width_bits = 2;
515
+    else if (index_size <= 16)
516
+        width_bits = 1;
517
+    else
518
+        width_bits = 0;
519
+
520
+    ret = decode_entropy_coded_image(s, IMAGE_ROLE_COLOR_INDEXING,
521
+                                     index_size, 1);
522
+    if (ret < 0)
523
+        return ret;
524
+
525
+    img = &s->image[IMAGE_ROLE_COLOR_INDEXING];
526
+    img->size_reduction = width_bits;
527
+    if (width_bits > 0)
528
+        s->reduced_width = (s->width + ((1 << width_bits) - 1)) >> width_bits;
529
+
530
+    /* color index values are delta-coded */
531
+    ct  = img->frame->data[0] + 4;
532
+    for (x = 4; x < img->frame->width * 4; x++, ct++)
533
+        ct[0] += ct[-4];
534
+
535
+    return 0;
536
+}
537
+
538
+static HuffReader *get_huffman_group(WebPContext *s, ImageContext *img,
539
+                                     int x, int y)
540
+{
541
+    ImageContext *gimg = &s->image[IMAGE_ROLE_ENTROPY];
542
+    int group = 0;
543
+
544
+    if (gimg->size_reduction > 0) {
545
+        int group_x = x >> gimg->size_reduction;
546
+        int group_y = y >> gimg->size_reduction;
547
+        group       = GET_PIXEL_COMP(gimg->frame, group_x, group_y, 2);
548
+    }
549
+
550
+    return &img->huffman_groups[group * HUFFMAN_CODES_PER_META_CODE];
551
+}
552
+
553
+static av_always_inline void color_cache_put(ImageContext *img, uint32_t c)
554
+{
555
+    uint32_t cache_idx = (0x1E35A7BD * c) >> (32 - img->color_cache_bits);
556
+    img->color_cache[cache_idx] = c;
557
+}
558
+
559
+static int decode_entropy_coded_image(WebPContext *s, enum ImageRole role,
560
+                                      int w, int h)
561
+{
562
+    ImageContext *img;
563
+    HuffReader *hg;
564
+    int i, j, ret, x, y, width;
565
+
566
+    img       = &s->image[role];
567
+    img->role = role;
568
+
569
+    if (!img->frame) {
570
+        img->frame = av_frame_alloc();
571
+        if (!img->frame)
572
+            return AVERROR(ENOMEM);
573
+    }
574
+
575
+    img->frame->format = AV_PIX_FMT_ARGB;
576
+    img->frame->width  = w;
577
+    img->frame->height = h;
578
+
579
+    if (role == IMAGE_ROLE_ARGB && !img->is_alpha_primary) {
580
+        ThreadFrame pt = { .f = img->frame };
581
+        ret = ff_thread_get_buffer(s->avctx, &pt, 0);
582
+    } else
583
+        ret = av_frame_get_buffer(img->frame, 1);
584
+    if (ret < 0)
585
+        return ret;
586
+
587
+    if (get_bits1(&s->gb)) {
588
+        img->color_cache_bits = get_bits(&s->gb, 4);
589
+        if (img->color_cache_bits < 1 || img->color_cache_bits > 11) {
590
+            av_log(s->avctx, AV_LOG_ERROR, "invalid color cache bits: %d\n",
591
+                   img->color_cache_bits);
592
+            return AVERROR_INVALIDDATA;
593
+        }
594
+        img->color_cache = av_mallocz_array(1 << img->color_cache_bits,
595
+                                            sizeof(*img->color_cache));
596
+        if (!img->color_cache)
597
+            return AVERROR(ENOMEM);
598
+    } else {
599
+        img->color_cache_bits = 0;
600
+    }
601
+
602
+    img->nb_huffman_groups = 1;
603
+    if (role == IMAGE_ROLE_ARGB && get_bits1(&s->gb)) {
604
+        ret = decode_entropy_image(s);
605
+        if (ret < 0)
606
+            return ret;
607
+        img->nb_huffman_groups = s->nb_huffman_groups;
608
+    }
609
+    img->huffman_groups = av_mallocz_array(img->nb_huffman_groups *
610
+                                           HUFFMAN_CODES_PER_META_CODE,
611
+                                           sizeof(*img->huffman_groups));
612
+    if (!img->huffman_groups)
613
+        return AVERROR(ENOMEM);
614
+
615
+    for (i = 0; i < img->nb_huffman_groups; i++) {
616
+        hg = &img->huffman_groups[i * HUFFMAN_CODES_PER_META_CODE];
617
+        for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; j++) {
618
+            int alphabet_size = alphabet_sizes[j];
619
+            if (!j && img->color_cache_bits > 0)
620
+                alphabet_size += 1 << img->color_cache_bits;
621
+
622
+            if (get_bits1(&s->gb)) {
623
+                read_huffman_code_simple(s, &hg[j]);
624
+            } else {
625
+                ret = read_huffman_code_normal(s, &hg[j], alphabet_size);
626
+                if (ret < 0)
627
+                    return ret;
628
+            }
629
+        }
630
+    }
631
+
632
+    width = img->frame->width;
633
+    if (role == IMAGE_ROLE_ARGB && s->reduced_width > 0)
634
+        width = s->reduced_width;
635
+
636
+    x = 0; y = 0;
637
+    while (y < img->frame->height) {
638
+        int v;
639
+
640
+        hg = get_huffman_group(s, img, x, y);
641
+        v = huff_reader_get_symbol(&hg[HUFF_IDX_GREEN], &s->gb);
642
+        if (v < NUM_LITERAL_CODES) {
643
+            /* literal pixel values */
644
+            uint8_t *p = GET_PIXEL(img->frame, x, y);
645
+            p[2] = v;
646
+            p[1] = huff_reader_get_symbol(&hg[HUFF_IDX_RED],   &s->gb);
647
+            p[3] = huff_reader_get_symbol(&hg[HUFF_IDX_BLUE],  &s->gb);
648
+            p[0] = huff_reader_get_symbol(&hg[HUFF_IDX_ALPHA], &s->gb);
649
+            if (img->color_cache_bits)
650
+                color_cache_put(img, AV_RB32(p));
651
+            x++;
652
+            if (x == width) {
653
+                x = 0;
654
+                y++;
655
+            }
656
+        } else if (v < NUM_LITERAL_CODES + NUM_LENGTH_CODES) {
657
+            /* LZ77 backwards mapping */
658
+            int prefix_code, length, distance, ref_x, ref_y;
659
+
660
+            /* parse length and distance */
661
+            prefix_code = v - NUM_LITERAL_CODES;
662
+            if (prefix_code < 4) {
663
+                length = prefix_code + 1;
664
+            } else {
665
+                int extra_bits = (prefix_code - 2) >> 1;
666
+                int offset     = 2 + (prefix_code & 1) << extra_bits;
667
+                length = offset + get_bits(&s->gb, extra_bits) + 1;
668
+            }
669
+            prefix_code = huff_reader_get_symbol(&hg[HUFF_IDX_DIST], &s->gb);
670
+            if (prefix_code < 4) {
671
+                distance = prefix_code + 1;
672
+            } else {
673
+                int extra_bits = prefix_code - 2 >> 1;
674
+                int offset     = 2 + (prefix_code & 1) << extra_bits;
675
+                distance = offset + get_bits(&s->gb, extra_bits) + 1;
676
+            }
677
+
678
+            /* find reference location */
679
+            if (distance <= NUM_SHORT_DISTANCES) {
680
+                int xi = lz77_distance_offsets[distance - 1][0];
681
+                int yi = lz77_distance_offsets[distance - 1][1];
682
+                distance = FFMAX(1, xi + yi * width);
683
+            } else {
684
+                distance -= NUM_SHORT_DISTANCES;
685
+            }
686
+            ref_x = x;
687
+            ref_y = y;
688
+            if (distance <= x) {
689
+                ref_x -= distance;
690
+                distance = 0;
691
+            } else {
692
+                ref_x = 0;
693
+                distance -= x;
694
+            }
695
+            while (distance >= width) {
696
+                ref_y--;
697
+                distance -= width;
698
+            }
699
+            if (distance > 0) {
700
+                ref_x = width - distance;
701
+                ref_y--;
702
+            }
703
+            ref_x = FFMAX(0, ref_x);
704
+            ref_y = FFMAX(0, ref_y);
705
+
706
+            /* copy pixels
707
+             * source and dest regions can overlap and wrap lines, so just
708
+             * copy per-pixel */
709
+            for (i = 0; i < length; i++) {
710
+                uint8_t *p_ref = GET_PIXEL(img->frame, ref_x, ref_y);
711
+                uint8_t *p     = GET_PIXEL(img->frame,     x,     y);
712
+
713
+                AV_COPY32(p, p_ref);
714
+                if (img->color_cache_bits)
715
+                    color_cache_put(img, AV_RB32(p));
716
+                x++;
717
+                ref_x++;
718
+                if (x == width) {
719
+                    x = 0;
720
+                    y++;
721
+                }
722
+                if (ref_x == width) {
723
+                    ref_x = 0;
724
+                    ref_y++;
725
+                }
726
+                if (y == img->frame->height || ref_y == img->frame->height)
727
+                    break;
728
+            }
729
+        } else {
730
+            /* read from color cache */
731
+            uint8_t *p = GET_PIXEL(img->frame, x, y);
732
+            int cache_idx = v - (NUM_LITERAL_CODES + NUM_LENGTH_CODES);
733
+
734
+            if (!img->color_cache_bits) {
735
+                av_log(s->avctx, AV_LOG_ERROR, "color cache not found\n");
736
+                return AVERROR_INVALIDDATA;
737
+            }
738
+            if (cache_idx >= 1 << img->color_cache_bits) {
739
+                av_log(s->avctx, AV_LOG_ERROR,
740
+                       "color cache index out-of-bounds\n");
741
+                return AVERROR_INVALIDDATA;
742
+            }
743
+            AV_WB32(p, img->color_cache[cache_idx]);
744
+            x++;
745
+            if (x == width) {
746
+                x = 0;
747
+                y++;
748
+            }
749
+        }
750
+    }
751
+
752
+    return 0;
753
+}
754
+
755
+/* PRED_MODE_BLACK */
756
+static void inv_predict_0(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
757
+                          const uint8_t *p_t, const uint8_t *p_tr)
758
+{
759
+    AV_WB32(p, 0xFF000000);
760
+}
761
+
762
+/* PRED_MODE_L */
763
+static void inv_predict_1(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
764
+                          const uint8_t *p_t, const uint8_t *p_tr)
765
+{
766
+    AV_COPY32(p, p_l);
767
+}
768
+
769
+/* PRED_MODE_T */
770
+static void inv_predict_2(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
771
+                          const uint8_t *p_t, const uint8_t *p_tr)
772
+{
773
+    AV_COPY32(p, p_t);
774
+}
775
+
776
+/* PRED_MODE_TR */
777
+static void inv_predict_3(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
778
+                          const uint8_t *p_t, const uint8_t *p_tr)
779
+{
780
+    AV_COPY32(p, p_tr);
781
+}
782
+
783
+/* PRED_MODE_TL */
784
+static void inv_predict_4(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
785
+                          const uint8_t *p_t, const uint8_t *p_tr)
786
+{
787
+    AV_COPY32(p, p_tl);
788
+}
789
+
790
+/* PRED_MODE_AVG_T_AVG_L_TR */
791
+static void inv_predict_5(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
792
+                          const uint8_t *p_t, const uint8_t *p_tr)
793
+{
794
+    p[0] = p_t[0] + (p_l[0] + p_tr[0] >> 1) >> 1;
795
+    p[1] = p_t[1] + (p_l[1] + p_tr[1] >> 1) >> 1;
796
+    p[2] = p_t[2] + (p_l[2] + p_tr[2] >> 1) >> 1;
797
+    p[3] = p_t[3] + (p_l[3] + p_tr[3] >> 1) >> 1;
798
+}
799
+
800
+/* PRED_MODE_AVG_L_TL */
801
+static void inv_predict_6(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
802
+                          const uint8_t *p_t, const uint8_t *p_tr)
803
+{
804
+    p[0] = p_l[0] + p_tl[0] >> 1;
805
+    p[1] = p_l[1] + p_tl[1] >> 1;
806
+    p[2] = p_l[2] + p_tl[2] >> 1;
807
+    p[3] = p_l[3] + p_tl[3] >> 1;
808
+}
809
+
810
+/* PRED_MODE_AVG_L_T */
811
+static void inv_predict_7(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
812
+                          const uint8_t *p_t, const uint8_t *p_tr)
813
+{
814
+    p[0] = p_l[0] + p_t[0] >> 1;
815
+    p[1] = p_l[1] + p_t[1] >> 1;
816
+    p[2] = p_l[2] + p_t[2] >> 1;
817
+    p[3] = p_l[3] + p_t[3] >> 1;
818
+}
819
+
820
+/* PRED_MODE_AVG_TL_T */
821
+static void inv_predict_8(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
822
+                          const uint8_t *p_t, const uint8_t *p_tr)
823
+{
824
+    p[0] = p_tl[0] + p_t[0] >> 1;
825
+    p[1] = p_tl[1] + p_t[1] >> 1;
826
+    p[2] = p_tl[2] + p_t[2] >> 1;
827
+    p[3] = p_tl[3] + p_t[3] >> 1;
828
+}
829
+
830
+/* PRED_MODE_AVG_T_TR */
831
+static void inv_predict_9(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
832
+                          const uint8_t *p_t, const uint8_t *p_tr)
833
+{
834
+    p[0] = p_t[0] + p_tr[0] >> 1;
835
+    p[1] = p_t[1] + p_tr[1] >> 1;
836
+    p[2] = p_t[2] + p_tr[2] >> 1;
837
+    p[3] = p_t[3] + p_tr[3] >> 1;
838
+}
839
+
840
+/* PRED_MODE_AVG_AVG_L_TL_AVG_T_TR */
841
+static void inv_predict_10(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
842
+                           const uint8_t *p_t, const uint8_t *p_tr)
843
+{
844
+    p[0] = (p_l[0] + p_tl[0] >> 1) + (p_t[0] + p_tr[0] >> 1) >> 1;
845
+    p[1] = (p_l[1] + p_tl[1] >> 1) + (p_t[1] + p_tr[1] >> 1) >> 1;
846
+    p[2] = (p_l[2] + p_tl[2] >> 1) + (p_t[2] + p_tr[2] >> 1) >> 1;
847
+    p[3] = (p_l[3] + p_tl[3] >> 1) + (p_t[3] + p_tr[3] >> 1) >> 1;
848
+}
849
+
850
+/* PRED_MODE_SELECT */
851
+static void inv_predict_11(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
852
+                           const uint8_t *p_t, const uint8_t *p_tr)
853
+{
854
+    int diff = (FFABS(p_l[0] - p_tl[0]) - FFABS(p_t[0] - p_tl[0])) +
855
+               (FFABS(p_l[1] - p_tl[1]) - FFABS(p_t[1] - p_tl[1])) +
856
+               (FFABS(p_l[2] - p_tl[2]) - FFABS(p_t[2] - p_tl[2])) +
857
+               (FFABS(p_l[3] - p_tl[3]) - FFABS(p_t[3] - p_tl[3]));
858
+    if (diff <= 0)
859
+        AV_COPY32(p, p_t);
860
+    else
861
+        AV_COPY32(p, p_l);
862
+}
863
+
864
+/* PRED_MODE_ADD_SUBTRACT_FULL */
865
+static void inv_predict_12(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
866
+                           const uint8_t *p_t, const uint8_t *p_tr)
867
+{
868
+    p[0] = av_clip_uint8(p_l[0] + p_t[0] - p_tl[0]);
869
+    p[1] = av_clip_uint8(p_l[1] + p_t[1] - p_tl[1]);
870
+    p[2] = av_clip_uint8(p_l[2] + p_t[2] - p_tl[2]);
871
+    p[3] = av_clip_uint8(p_l[3] + p_t[3] - p_tl[3]);
872
+}
873
+
874
+static av_always_inline uint8_t clamp_add_subtract_half(int a, int b, int c)
875
+{
876
+    int d = a + b >> 1;
877
+    return av_clip_uint8(d + (d - c) / 2);
878
+}
879
+
880
+/* PRED_MODE_ADD_SUBTRACT_HALF */
881
+static void inv_predict_13(uint8_t *p, const uint8_t *p_l, const uint8_t *p_tl,
882
+                           const uint8_t *p_t, const uint8_t *p_tr)
883
+{
884
+    p[0] = clamp_add_subtract_half(p_l[0], p_t[0], p_tl[0]);
885
+    p[1] = clamp_add_subtract_half(p_l[1], p_t[1], p_tl[1]);
886
+    p[2] = clamp_add_subtract_half(p_l[2], p_t[2], p_tl[2]);
887
+    p[3] = clamp_add_subtract_half(p_l[3], p_t[3], p_tl[3]);
888
+}
889
+
890
+typedef void (*inv_predict_func)(uint8_t *p, const uint8_t *p_l,
891
+                                 const uint8_t *p_tl, const uint8_t *p_t,
892
+                                 const uint8_t *p_tr);
893
+
894
+static const inv_predict_func inverse_predict[14] = {
895
+    inv_predict_0,  inv_predict_1,  inv_predict_2,  inv_predict_3,
896
+    inv_predict_4,  inv_predict_5,  inv_predict_6,  inv_predict_7,
897
+    inv_predict_8,  inv_predict_9,  inv_predict_10, inv_predict_11,
898
+    inv_predict_12, inv_predict_13,
899
+};
900
+
901
+static void inverse_prediction(AVFrame *frame, enum PredictionMode m, int x, int y)
902
+{
903
+    uint8_t *dec, *p_l, *p_tl, *p_t, *p_tr;
904
+    uint8_t p[4];
905
+
906
+    dec  = GET_PIXEL(frame, x,     y);
907
+    p_l  = GET_PIXEL(frame, x - 1, y);
908
+    p_tl = GET_PIXEL(frame, x - 1, y - 1);
909
+    p_t  = GET_PIXEL(frame, x,     y - 1);
910
+    if (x == frame->width - 1)
911
+        p_tr = GET_PIXEL(frame, 0, y);
912
+    else
913
+        p_tr = GET_PIXEL(frame, x + 1, y - 1);
914
+
915
+    inverse_predict[m](p, p_l, p_tl, p_t, p_tr);
916
+
917
+    dec[0] += p[0];
918
+    dec[1] += p[1];
919
+    dec[2] += p[2];
920
+    dec[3] += p[3];
921
+}
922
+
923
+static int apply_predictor_transform(WebPContext *s)
924
+{
925
+    ImageContext *img  = &s->image[IMAGE_ROLE_ARGB];
926
+    ImageContext *pimg = &s->image[IMAGE_ROLE_PREDICTOR];
927
+    int x, y;
928
+
929
+    for (y = 0; y < img->frame->height; y++) {
930
+        for (x = 0; x < img->frame->width; x++) {
931
+            int tx = x >> pimg->size_reduction;
932
+            int ty = y >> pimg->size_reduction;
933
+            enum PredictionMode m = GET_PIXEL_COMP(pimg->frame, tx, ty, 2);
934
+
935
+            if (x == 0) {
936
+                if (y == 0)
937
+                    m = PRED_MODE_BLACK;
938
+                else
939
+                    m = PRED_MODE_T;
940
+            } else if (y == 0)
941
+                m = PRED_MODE_L;
942
+
943
+            if (m > 13) {
944
+                av_log(s->avctx, AV_LOG_ERROR,
945
+                       "invalid predictor mode: %d\n", m);
946
+                return AVERROR_INVALIDDATA;
947
+            }
948
+            inverse_prediction(img->frame, m, x, y);
949
+        }
950
+    }
951
+    return 0;
952
+}
953
+
954
+static av_always_inline uint8_t color_transform_delta(uint8_t color_pred,
955
+                                                      uint8_t color)
956
+{
957
+    return (int)ff_u8_to_s8(color_pred) * ff_u8_to_s8(color) >> 5;
958
+}
959
+
960
+static int apply_color_transform(WebPContext *s)
961
+{
962
+    ImageContext *img, *cimg;
963
+    int x, y, cx, cy;
964
+    uint8_t *p, *cp;
965
+
966
+    img  = &s->image[IMAGE_ROLE_ARGB];
967
+    cimg = &s->image[IMAGE_ROLE_COLOR_TRANSFORM];
968
+
969
+    for (y = 0; y < img->frame->height; y++) {
970
+        for (x = 0; x < img->frame->width; x++) {
971
+            cx = x >> cimg->size_reduction;
972
+            cy = y >> cimg->size_reduction;
973
+            cp = GET_PIXEL(cimg->frame, cx, cy);
974
+            p  = GET_PIXEL(img->frame,   x,  y);
975
+
976
+            p[1] += color_transform_delta(cp[3], p[2]);
977
+            p[3] += color_transform_delta(cp[2], p[2]) +
978
+                    color_transform_delta(cp[1], p[1]);
979
+        }
980
+    }
981
+    return 0;
982
+}
983
+
984
+static int apply_subtract_green_transform(WebPContext *s)
985
+{
986
+    int x, y;
987
+    ImageContext *img = &s->image[IMAGE_ROLE_ARGB];
988
+
989
+    for (y = 0; y < img->frame->height; y++) {
990
+        for (x = 0; x < img->frame->width; x++) {
991
+            uint8_t *p = GET_PIXEL(img->frame, x, y);
992
+            p[1] += p[2];
993
+            p[3] += p[2];
994
+        }
995
+    }
996
+    return 0;
997
+}
998
+
999
+static int apply_color_indexing_transform(WebPContext *s)
1000
+{
1001
+    ImageContext *img;
1002
+    ImageContext *pal;
1003
+    int i, x, y;
1004
+    uint8_t *p, *pi;
1005
+
1006
+    img = &s->image[IMAGE_ROLE_ARGB];
1007
+    pal = &s->image[IMAGE_ROLE_COLOR_INDEXING];
1008
+
1009
+    if (pal->size_reduction > 0) {
1010
+        GetBitContext gb_g;
1011
+        uint8_t *line;
1012
+        int pixel_bits = 8 >> pal->size_reduction;
1013
+
1014
+        line = av_malloc(img->frame->linesize[0]);
1015
+        if (!line)
1016
+            return AVERROR(ENOMEM);
1017
+
1018
+        for (y = 0; y < img->frame->height; y++) {
1019
+            p = GET_PIXEL(img->frame, 0, y);
1020
+            memcpy(line, p, img->frame->linesize[0]);
1021
+            init_get_bits(&gb_g, line, img->frame->linesize[0] * 8);
1022
+            skip_bits(&gb_g, 16);
1023
+            i = 0;
1024
+            for (x = 0; x < img->frame->width; x++) {
1025
+                p    = GET_PIXEL(img->frame, x, y);
1026
+                p[2] = get_bits(&gb_g, pixel_bits);
1027
+                i++;
1028
+                if (i == 1 << pal->size_reduction) {
1029
+                    skip_bits(&gb_g, 24);
1030
+                    i = 0;
1031
+                }
1032
+            }
1033
+        }
1034
+        av_free(line);
1035
+    }
1036
+
1037
+    for (y = 0; y < img->frame->height; y++) {
1038
+        for (x = 0; x < img->frame->width; x++) {
1039
+            p = GET_PIXEL(img->frame, x, y);
1040
+            i = p[2];
1041
+            if (i >= pal->frame->width) {
1042
+                av_log(s->avctx, AV_LOG_ERROR, "invalid palette index %d\n", i);
1043
+                return AVERROR_INVALIDDATA;
1044
+            }
1045
+            pi = GET_PIXEL(pal->frame, i, 0);
1046
+            AV_COPY32(p, pi);
1047
+        }
1048
+    }
1049
+
1050
+    return 0;
1051
+}
1052
+
1053
+static int vp8_lossless_decode_frame(AVCodecContext *avctx, AVFrame *p,
1054
+                                     int *got_frame, uint8_t *data_start,
1055
+                                     unsigned int data_size, int is_alpha_chunk)
1056
+{
1057
+    WebPContext *s = avctx->priv_data;
1058
+    int w, h, ret, i;
1059
+
1060
+    if (!is_alpha_chunk) {
1061
+        s->lossless = 1;
1062
+        avctx->pix_fmt = AV_PIX_FMT_ARGB;
1063
+    }
1064
+
1065
+    ret = init_get_bits(&s->gb, data_start, data_size * 8);
1066
+    if (ret < 0)
1067
+        return ret;
1068
+
1069
+    if (!is_alpha_chunk) {
1070
+        if (get_bits(&s->gb, 8) != 0x2F) {
1071
+            av_log(avctx, AV_LOG_ERROR, "Invalid WebP Lossless signature\n");
1072
+            return AVERROR_INVALIDDATA;
1073
+        }
1074
+
1075
+        w = get_bits(&s->gb, 14) + 1;
1076
+        h = get_bits(&s->gb, 14) + 1;
1077
+        if (s->width && s->width != w) {
1078
+            av_log(avctx, AV_LOG_WARNING, "Width mismatch. %d != %d\n",
1079
+                   s->width, w);
1080
+        }
1081
+        s->width = w;
1082
+        if (s->height && s->height != h) {
1083
+            av_log(avctx, AV_LOG_WARNING, "Height mismatch. %d != %d\n",
1084
+                   s->width, w);
1085
+        }
1086
+        s->height = h;
1087
+        ret = av_image_check_size(s->width, s->height, 0, avctx);
1088
+        if (ret < 0)
1089
+            return ret;
1090
+        avcodec_set_dimensions(avctx, s->width, s->height);
1091
+
1092
+        s->has_alpha = get_bits1(&s->gb);
1093
+
1094
+        if (get_bits(&s->gb, 3) != 0x0) {
1095
+            av_log(avctx, AV_LOG_ERROR, "Invalid WebP Lossless version\n");
1096
+            return AVERROR_INVALIDDATA;
1097
+        }
1098
+    } else {
1099
+        if (!s->width || !s->height)
1100
+            return AVERROR_BUG;
1101
+        w = s->width;
1102
+        h = s->height;
1103
+    }
1104
+
1105
+    /* parse transformations */
1106
+    s->nb_transforms = 0;
1107
+    s->reduced_width = 0;
1108
+    while (get_bits1(&s->gb)) {
1109
+        enum TransformType transform = get_bits(&s->gb, 2);
1110
+        s->transforms[s->nb_transforms++] = transform;
1111
+        switch (transform) {
1112
+        case PREDICTOR_TRANSFORM:
1113
+            ret = parse_transform_predictor(s);
1114
+            break;
1115
+        case COLOR_TRANSFORM:
1116
+            ret = parse_transform_color(s);
1117
+            break;
1118
+        case COLOR_INDEXING_TRANSFORM:
1119
+            ret = parse_transform_color_indexing(s);
1120
+            break;
1121
+        }
1122
+        if (ret < 0)
1123
+            goto free_and_return;
1124
+    }
1125
+
1126
+    /* decode primary image */
1127
+    s->image[IMAGE_ROLE_ARGB].frame = p;
1128
+    if (is_alpha_chunk)
1129
+        s->image[IMAGE_ROLE_ARGB].is_alpha_primary = 1;
1130
+    ret = decode_entropy_coded_image(s, IMAGE_ROLE_ARGB, w, h);
1131
+    if (ret < 0) {
1132
+        av_frame_free(&p);
1133
+        goto free_and_return;
1134
+    }
1135
+
1136
+    /* apply transformations */
1137
+    for (i = s->nb_transforms - 1; i >= 0; i--) {
1138
+        switch (s->transforms[i]) {
1139
+        case PREDICTOR_TRANSFORM:
1140
+            ret = apply_predictor_transform(s);
1141
+            break;
1142
+        case COLOR_TRANSFORM:
1143
+            ret = apply_color_transform(s);
1144
+            break;
1145
+        case SUBTRACT_GREEN:
1146
+            ret = apply_subtract_green_transform(s);
1147
+            break;
1148
+        case COLOR_INDEXING_TRANSFORM:
1149
+            ret = apply_color_indexing_transform(s);
1150
+            break;
1151
+        }
1152
+        if (ret < 0) {
1153
+            av_frame_free(&p);
1154
+            goto free_and_return;
1155
+        }
1156
+    }
1157
+
1158
+    *got_frame   = 1;
1159
+    p->pict_type = AV_PICTURE_TYPE_I;
1160
+    p->key_frame = 1;
1161
+    ret          = data_size;
1162
+
1163
+free_and_return:
1164
+    for (i = 0; i < IMAGE_ROLE_NB; i++)
1165
+        image_ctx_free(&s->image[i]);
1166
+
1167
+    return ret;
1168
+}
1169
+
1170
+static void alpha_inverse_prediction(AVFrame *frame, enum AlphaFilter m)
1171
+{
1172
+    int x, y, ls;
1173
+    uint8_t *dec;
1174
+
1175
+    ls = frame->linesize[3];
1176
+
1177
+    /* filter first row using horizontal filter */
1178
+    dec = frame->data[3] + 1;
1179
+    for (x = 1; x < frame->width; x++, dec++)
1180
+        *dec += *(dec - 1);
1181
+
1182
+    /* filter first column using vertical filter */
1183
+    dec = frame->data[3] + ls;
1184
+    for (y = 1; y < frame->height; y++, dec += ls)
1185
+        *dec += *(dec - ls);
1186
+
1187
+    /* filter the rest using the specified filter */
1188
+    switch (m) {
1189
+    case ALPHA_FILTER_HORIZONTAL:
1190
+        for (y = 1; y < frame->height; y++) {
1191
+            dec = frame->data[3] + y * ls + 1;
1192
+            for (x = 1; x < frame->width; x++, dec++)
1193
+                *dec += *(dec - 1);
1194
+        }
1195
+        break;
1196
+    case ALPHA_FILTER_VERTICAL:
1197
+        for (y = 1; y < frame->height; y++) {
1198
+            dec = frame->data[3] + y * ls + 1;
1199
+            for (x = 1; x < frame->width; x++, dec++)
1200
+                *dec += *(dec - ls);
1201
+        }
1202
+        break;
1203
+    case ALPHA_FILTER_GRADIENT:
1204
+        for (y = 1; y < frame->height; y++) {
1205
+            dec = frame->data[3] + y * ls + 1;
1206
+            for (x = 1; x < frame->width; x++, dec++)
1207
+                dec[0] += av_clip_uint8(*(dec - 1) + *(dec - ls) - *(dec - ls - 1));
1208
+        }
1209
+        break;
1210
+    }
1211
+}
1212
+
1213
+static int vp8_lossy_decode_alpha(AVCodecContext *avctx, AVFrame *p,
1214
+                                  uint8_t *data_start,
1215
+                                  unsigned int data_size)
1216
+{
1217
+    WebPContext *s = avctx->priv_data;
1218
+    int x, y, ret;
1219
+
1220
+    if (s->alpha_compression == ALPHA_COMPRESSION_NONE) {
1221
+        GetByteContext gb;
1222
+
1223
+        bytestream2_init(&gb, data_start, data_size);
1224
+        for (y = 0; y < s->height; y++)
1225
+            bytestream2_get_buffer(&gb, p->data[3] + p->linesize[3] * y,
1226
+                                   s->width);
1227
+    } else if (s->alpha_compression == ALPHA_COMPRESSION_VP8L) {
1228
+        uint8_t *ap, *pp;
1229
+        int alpha_got_frame = 0;
1230
+
1231
+        s->alpha_frame = av_frame_alloc();
1232
+        if (!s->alpha_frame)
1233
+            return AVERROR(ENOMEM);
1234
+
1235
+        ret = vp8_lossless_decode_frame(avctx, s->alpha_frame, &alpha_got_frame,
1236
+                                        data_start, data_size, 1);
1237
+        if (ret < 0) {
1238
+            av_frame_free(&s->alpha_frame);
1239
+            return ret;
1240
+        }
1241
+        if (!alpha_got_frame) {
1242
+            av_frame_free(&s->alpha_frame);
1243
+            return AVERROR_INVALIDDATA;
1244
+        }
1245
+
1246
+        /* copy green component of alpha image to alpha plane of primary image */
1247
+        for (y = 0; y < s->height; y++) {
1248
+            ap = GET_PIXEL(s->alpha_frame, 0, y) + 2;
1249
+            pp = p->data[3] + p->linesize[3] * y;
1250
+            for (x = 0; x < s->width; x++) {
1251
+                *pp = *ap;
1252
+                pp++;
1253
+                ap += 4;
1254
+            }
1255
+        }
1256
+        av_frame_free(&s->alpha_frame);
1257
+    }
1258
+
1259
+    /* apply alpha filtering */
1260
+    if (s->alpha_filter)
1261
+        alpha_inverse_prediction(p, s->alpha_filter);
1262
+
1263
+    return 0;
1264
+}
1265
+
1266
+static int vp8_lossy_decode_frame(AVCodecContext *avctx, AVFrame *p,
1267
+                                  int *got_frame, uint8_t *data_start,
1268
+                                  unsigned int data_size)
1269
+{
1270
+    WebPContext *s = avctx->priv_data;
1271
+    AVPacket pkt;
1272
+    int ret;
1273
+
1274
+    if (!s->initialized) {
1275
+        ff_vp8_decode_init(avctx);
1276
+        s->initialized = 1;
1277
+        if (s->has_alpha)
1278
+            avctx->pix_fmt = AV_PIX_FMT_YUVA420P;
1279
+    }
1280
+    s->lossless = 0;
1281
+
1282
+    if (data_size > INT_MAX) {
1283
+        av_log(avctx, AV_LOG_ERROR, "unsupported chunk size\n");
1284
+        return AVERROR_PATCHWELCOME;
1285
+    }
1286
+
1287
+    av_init_packet(&pkt);
1288
+    pkt.data = data_start;
1289
+    pkt.size = data_size;
1290
+
1291
+    ret = ff_vp8_decode_frame(avctx, p, got_frame, &pkt);
1292
+    if (s->has_alpha) {
1293
+        ret = vp8_lossy_decode_alpha(avctx, p, s->alpha_data,
1294
+                                     s->alpha_data_size);
1295
+        if (ret < 0)
1296
+            return ret;
1297
+    }
1298
+    return ret;
1299
+}
1300
+
1301
+static int webp_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
1302
+                             AVPacket *avpkt)
1303
+{
1304
+    AVFrame * const p = data;
1305
+    WebPContext *s = avctx->priv_data;
1306
+    GetByteContext gb;
1307
+    int ret;
1308
+    uint32_t chunk_type, chunk_size;
1309
+    int vp8x_flags = 0;
1310
+
1311
+    s->avctx     = avctx;
1312
+    s->width     = 0;
1313
+    s->height    = 0;
1314
+    *got_frame   = 0;
1315
+    s->has_alpha = 0;
1316
+    bytestream2_init(&gb, avpkt->data, avpkt->size);
1317
+
1318
+    if (bytestream2_get_bytes_left(&gb) < 12)
1319
+        return AVERROR_INVALIDDATA;
1320
+
1321
+    if (bytestream2_get_le32(&gb) != MKTAG('R', 'I', 'F', 'F')) {
1322
+        av_log(avctx, AV_LOG_ERROR, "missing RIFF tag\n");
1323
+        return AVERROR_INVALIDDATA;
1324
+    }
1325
+
1326
+    chunk_size = bytestream2_get_le32(&gb);
1327
+    if (bytestream2_get_bytes_left(&gb) < chunk_size)
1328
+        return AVERROR_INVALIDDATA;
1329
+
1330
+    if (bytestream2_get_le32(&gb) != MKTAG('W', 'E', 'B', 'P')) {
1331
+        av_log(avctx, AV_LOG_ERROR, "missing WEBP tag\n");
1332
+        return AVERROR_INVALIDDATA;
1333
+    }
1334
+
1335
+    while (bytestream2_get_bytes_left(&gb) > 0) {
1336
+        char chunk_str[5] = { 0 };
1337
+
1338
+        chunk_type = bytestream2_get_le32(&gb);
1339
+        chunk_size = bytestream2_get_le32(&gb);
1340
+        if (chunk_size == UINT32_MAX)
1341
+            return AVERROR_INVALIDDATA;
1342
+        chunk_size += chunk_size & 1;
1343
+
1344
+        if (bytestream2_get_bytes_left(&gb) < chunk_size)
1345
+            return AVERROR_INVALIDDATA;
1346
+
1347
+        switch (chunk_type) {
1348
+        case MKTAG('V', 'P', '8', ' '):
1349
+            if (!*got_frame) {
1350
+                ret = vp8_lossy_decode_frame(avctx, p, got_frame,
1351
+                                             avpkt->data + bytestream2_tell(&gb),
1352
+                                             chunk_size);
1353
+                if (ret < 0)
1354
+                    return ret;
1355
+            }
1356
+            bytestream2_skip(&gb, chunk_size);
1357
+            break;
1358
+        case MKTAG('V', 'P', '8', 'L'):
1359
+            if (!*got_frame) {
1360
+                ret = vp8_lossless_decode_frame(avctx, p, got_frame,
1361
+                                                avpkt->data + bytestream2_tell(&gb),
1362
+                                                chunk_size, 0);
1363
+                if (ret < 0)
1364
+                    return ret;
1365
+            }
1366
+            bytestream2_skip(&gb, chunk_size);
1367
+            break;
1368
+        case MKTAG('V', 'P', '8', 'X'):
1369
+            vp8x_flags = bytestream2_get_byte(&gb);
1370
+            bytestream2_skip(&gb, 3);
1371
+            s->width  = bytestream2_get_le24(&gb) + 1;
1372
+            s->height = bytestream2_get_le24(&gb) + 1;
1373
+            ret = av_image_check_size(s->width, s->height, 0, avctx);
1374
+            if (ret < 0)
1375
+                return ret;
1376
+            break;
1377
+        case MKTAG('A', 'L', 'P', 'H'): {
1378
+            int alpha_header, filter_m, compression;
1379
+
1380
+            if (!(vp8x_flags & VP8X_FLAG_ALPHA)) {
1381
+                av_log(avctx, AV_LOG_WARNING,
1382
+                       "ALPHA chunk present, but alpha bit not set in the "
1383
+                       "VP8X header\n");
1384
+            }
1385
+            if (chunk_size == 0) {
1386
+                av_log(avctx, AV_LOG_ERROR, "invalid ALPHA chunk size\n");
1387
+                return AVERROR_INVALIDDATA;
1388
+            }
1389
+            alpha_header       = bytestream2_get_byte(&gb);
1390
+            s->alpha_data      = avpkt->data + bytestream2_tell(&gb);
1391
+            s->alpha_data_size = chunk_size - 1;
1392
+            bytestream2_skip(&gb, s->alpha_data_size);
1393
+
1394
+            filter_m    = (alpha_header >> 2) & 0x03;
1395
+            compression =  alpha_header       & 0x03;
1396
+
1397
+            if (compression > ALPHA_COMPRESSION_VP8L) {
1398
+                av_log(avctx, AV_LOG_VERBOSE,
1399
+                       "skipping unsupported ALPHA chunk\n");
1400
+            } else {
1401
+                s->has_alpha         = 1;
1402
+                s->alpha_compression = compression;
1403
+                s->alpha_filter      = filter_m;
1404
+            }
1405
+
1406
+            break;
1407
+        }
1408
+        case MKTAG('I', 'C', 'C', 'P'):
1409
+        case MKTAG('A', 'N', 'I', 'M'):
1410
+        case MKTAG('A', 'N', 'M', 'F'):
1411
+        case MKTAG('E', 'X', 'I', 'F'):
1412
+        case MKTAG('X', 'M', 'P', ' '):
1413
+            AV_WL32(chunk_str, chunk_type);
1414
+            av_log(avctx, AV_LOG_VERBOSE, "skipping unsupported chunk: %s\n",
1415
+                   chunk_str);
1416
+            bytestream2_skip(&gb, chunk_size);
1417
+            break;
1418
+        default:
1419
+            AV_WL32(chunk_str, chunk_type);
1420
+            av_log(avctx, AV_LOG_VERBOSE, "skipping unknown chunk: %s\n",
1421
+                   chunk_str);
1422
+            bytestream2_skip(&gb, chunk_size);
1423
+            break;
1424
+        }
1425
+    }
1426
+
1427
+    if (!*got_frame) {
1428
+        av_log(avctx, AV_LOG_ERROR, "image data not found\n");
1429
+        return AVERROR_INVALIDDATA;
1430
+    }
1431
+
1432
+    return avpkt->size;
1433
+}
1434
+
1435
+static av_cold int webp_decode_close(AVCodecContext *avctx)
1436
+{
1437
+    WebPContext *s = avctx->priv_data;
1438
+
1439
+    if (s->initialized)
1440
+        return ff_vp8_decode_free(avctx);
1441
+
1442
+    return 0;
1443
+}
1444
+
1445
+AVCodec ff_webp_decoder = {
1446
+    .name           = "webp",
1447
+    .long_name      = NULL_IF_CONFIG_SMALL("WebP image"),
1448
+    .type           = AVMEDIA_TYPE_VIDEO,
1449
+    .id             = AV_CODEC_ID_WEBP,
1450
+    .priv_data_size = sizeof(WebPContext),
1451
+    .decode         = webp_decode_frame,
1452
+    .close          = webp_decode_close,
1453
+    .capabilities   = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS,
1454
+};