1 /*
2 * Copyright (c) 2010, Google, Inc.
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * @file
23 * VP8/9 decoder support via libvpx
24 */
25
26 #define VPX_CODEC_DISABLE_COMPAT 1
27 #include <vpx/vpx_decoder.h>
28 #include <vpx/vpx_frame_buffer.h>
29 #include <vpx/vp8dx.h>
30
40
47 } VPxContext;
48
49
51 {
52 VPxContext *
ctx = priv;
54
55 if (min_size >
ctx->pool_size) {
57 /* According to the libvpx docs the buffer must be zeroed out. */
62 }
63 ctx->pool_size = min_size;
64 }
65
67 if (!buf)
69
71 fb->size =
ctx->pool_size;
73
74 return 0;
75 }
76
78 {
81 return 0;
82 }
83
86 const struct vpx_codec_iface *iface)
87 {
88 struct vpx_codec_dec_cfg deccfg = {
90 };
91
94
95 if (vpx_codec_dec_init(
decoder, iface, &deccfg, 0) != VPX_CODEC_OK) {
100 }
101
104
105 return 0;
106 }
107
108 // returns 0 on success, AVERROR_INVALIDDATA otherwise
110 int has_alpha_channel)
111 {
115 };
116 #if VPX_IMAGE_ABI_VERSION >= 4
119 };
121 #endif
126 case VPX_IMG_FMT_I420:
131 return 0;
132 #if CONFIG_LIBVPX_VP9_DECODER
133 case VPX_IMG_FMT_I422:
136 return 0;
137 case VPX_IMG_FMT_I440:
140 return 0;
141 case VPX_IMG_FMT_I444:
145 return 0;
146 case VPX_IMG_FMT_I42016:
148 if (
img->bit_depth == 10) {
150 return 0;
151 }
else if (
img->bit_depth == 12) {
153 return 0;
154 } else {
156 }
157 case VPX_IMG_FMT_I42216:
159 if (
img->bit_depth == 10) {
161 return 0;
162 }
else if (
img->bit_depth == 12) {
164 return 0;
165 } else {
167 }
168 case VPX_IMG_FMT_I44016:
170 if (
img->bit_depth == 10) {
172 return 0;
173 }
else if (
img->bit_depth == 12) {
175 return 0;
176 } else {
178 }
179 case VPX_IMG_FMT_I44416:
181 if (
img->bit_depth == 10) {
184 return 0;
185 }
else if (
img->bit_depth == 12) {
188 return 0;
189 } else {
191 }
192 #endif
193 default:
195 }
196 }
197
199 uint8_t *
data, uint32_t data_sz)
200 {
201 if (vpx_codec_decode(
decoder,
data, data_sz,
NULL, 0) != VPX_CODEC_OK) {
203 const char *detail = vpx_codec_error_detail(
decoder);
204
206 if (detail) {
208 detail);
209 }
211 }
212 return 0;
213 }
214
217 {
220 const void *iter =
NULL;
221 const void *iter_alpha =
NULL;
222 struct vpx_image *
img, *img_alpha;
224 uint8_t *side_data =
NULL;
225 size_t side_data_size;
226
230
233 &side_data_size);
234 if (side_data_size >= 8) {
235 const uint64_t additional_id =
AV_RB64(side_data);
236 side_data += 8;
237 side_data_size -= 8;
238 if (additional_id == 1) { // 1 stands for alpha channel data.
239 if (!
ctx->has_alpha_channel) {
240 ctx->has_alpha_channel = 1;
243 #if CONFIG_LIBVPX_VP8_DECODER && CONFIG_LIBVPX_VP9_DECODER
245 vpx_codec_vp8_dx() : vpx_codec_vp9_dx()
246 #elif CONFIG_LIBVPX_VP8_DECODER
247 vpx_codec_vp8_dx()
248 #else
249 vpx_codec_vp9_dx()
250 #endif
251 );
254 }
256 side_data_size);
259 }
260 }
261
262 if ((
img = vpx_codec_get_frame(&
ctx->decoder, &iter)) &&
263 (!
ctx->has_alpha_channel ||
264 (img_alpha = vpx_codec_get_frame(&
ctx->decoder_alpha, &iter_alpha)))) {
266 int linesizes[4];
267
272 }
273
276 img->fmt,
img->bit_depth);
278 }
279
286 }
287
288 if (
ctx->has_alpha_channel &&
289 (
img->d_w != img_alpha->d_w ||
290 img->d_h != img_alpha->d_h ||
291 img->bit_depth != img_alpha->bit_depth)) {
293 "Video dimensions %dx%d@%dbpc differ from alpha dimensions %dx%d@%dbpc\n",
295 img_alpha->d_w, img_alpha->d_h, img_alpha->bit_depth);
297 }
298
303 ctx->has_alpha_channel ? img_alpha->planes[VPX_PLANE_Y] :
NULL;
304 linesizes[0] =
img->stride[VPX_PLANE_Y];
305 linesizes[1] =
img->stride[VPX_PLANE_U];
306 linesizes[2] =
img->stride[VPX_PLANE_V];
307 linesizes[3] =
308 ctx->has_alpha_channel ? img_alpha->stride[VPX_PLANE_Y] : 0;
309
310 if (
img->fb_priv && (!
ctx->has_alpha_channel || img_alpha->fb_priv)) {
315 if (!picture->
buf[0])
317 if (
ctx->has_alpha_channel) {
319 if (!picture->
buf[1]) {
322 }
323 }
324 for (
int i = 0;
i < 4;
i++) {
327 }
328 } else {
333 }
334 *got_frame = 1;
335 }
337 }
338
340 {
342 vpx_codec_destroy(&
ctx->decoder);
343 if (
ctx->has_alpha_channel)
344 vpx_codec_destroy(&
ctx->decoder_alpha);
346 return 0;
347 }
348
349 #if CONFIG_LIBVPX_VP8_DECODER
351 {
353 return vpx_init(avctx, &
ctx->decoder, vpx_codec_vp8_dx());
354 }
355
361 .priv_data_size = sizeof(VPxContext),
367 .wrapper_name = "libvpx",
368 };
369 #endif /* CONFIG_LIBVPX_VP8_DECODER */
370
371 #if CONFIG_LIBVPX_VP9_DECODER
373 {
375 return vpx_init(avctx, &
ctx->decoder, vpx_codec_vp9_dx());
376 }
377
379 .
name =
"libvpx-vp9",
383 .priv_data_size = sizeof(VPxContext),
391 .wrapper_name = "libvpx",
392 };
393 #endif /* CONFIG_LIBVPX_VP9_DECODER */