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 #include "config_components.h"
27
28 #define VPX_CODEC_DISABLE_COMPAT 1
29 #include <vpx/vpx_decoder.h>
30 #include <vpx/vpx_frame_buffer.h>
31 #include <vpx/vp8dx.h>
32
42
49 } VPxContext;
50
51
53 {
54 VPxContext *
ctx = priv;
56
57 if (min_size >
ctx->pool_size) {
59 /* According to the libvpx docs the buffer must be zeroed out. */
64 }
65 ctx->pool_size = min_size;
66 }
67
69 if (!buf)
71
73 fb->size =
ctx->pool_size;
75
76 return 0;
77 }
78
80 {
83 return 0;
84 }
85
88 const struct vpx_codec_iface *iface)
89 {
90 struct vpx_codec_dec_cfg deccfg = {
92 };
93
96
97 if (vpx_codec_dec_init(
decoder, iface, &deccfg, 0) != VPX_CODEC_OK) {
102 }
103
106
107 return 0;
108 }
109
110 // returns 0 on success, AVERROR_INVALIDDATA otherwise
112 int has_alpha_channel)
113 {
117 };
118 #if VPX_IMAGE_ABI_VERSION >= 4
121 };
123 #endif
128 case VPX_IMG_FMT_I420:
133 return 0;
134 #if CONFIG_LIBVPX_VP9_DECODER
135 case VPX_IMG_FMT_I422:
138 return 0;
139 case VPX_IMG_FMT_I440:
142 return 0;
143 case VPX_IMG_FMT_I444:
147 return 0;
148 case VPX_IMG_FMT_I42016:
150 if (
img->bit_depth == 10) {
152 return 0;
153 }
else if (
img->bit_depth == 12) {
155 return 0;
156 } else {
158 }
159 case VPX_IMG_FMT_I42216:
161 if (
img->bit_depth == 10) {
163 return 0;
164 }
else if (
img->bit_depth == 12) {
166 return 0;
167 } else {
169 }
170 case VPX_IMG_FMT_I44016:
172 if (
img->bit_depth == 10) {
174 return 0;
175 }
else if (
img->bit_depth == 12) {
177 return 0;
178 } else {
180 }
181 case VPX_IMG_FMT_I44416:
183 if (
img->bit_depth == 10) {
186 return 0;
187 }
else if (
img->bit_depth == 12) {
190 return 0;
191 } else {
193 }
194 #endif
195 default:
197 }
198 }
199
201 const uint8_t *
data, uint32_t data_sz)
202 {
203 if (vpx_codec_decode(
decoder,
data, data_sz,
NULL, 0) != VPX_CODEC_OK) {
205 const char *detail = vpx_codec_error_detail(
decoder);
206
208 if (detail) {
210 detail);
211 }
213 }
214 return 0;
215 }
216
219 {
221 const void *iter =
NULL;
222 const void *iter_alpha =
NULL;
223 struct vpx_image *
img, *img_alpha;
225 uint8_t *side_data =
NULL;
226 size_t side_data_size;
227
231
234 &side_data_size);
235 if (side_data_size >= 8) {
236 const uint64_t additional_id =
AV_RB64(side_data);
237 side_data += 8;
238 side_data_size -= 8;
239 if (additional_id == 1) { // 1 stands for alpha channel data.
240 if (!
ctx->has_alpha_channel) {
241 ctx->has_alpha_channel = 1;
244 #if CONFIG_LIBVPX_VP8_DECODER && CONFIG_LIBVPX_VP9_DECODER
246 vpx_codec_vp8_dx() : vpx_codec_vp9_dx()
247 #elif CONFIG_LIBVPX_VP8_DECODER
248 vpx_codec_vp8_dx()
249 #else
250 vpx_codec_vp9_dx()
251 #endif
252 );
255 }
257 side_data_size);
260 }
261 }
262
263 if ((
img = vpx_codec_get_frame(&
ctx->decoder, &iter)) &&
264 (!
ctx->has_alpha_channel ||
265 (img_alpha = vpx_codec_get_frame(&
ctx->decoder_alpha, &iter_alpha)))) {
267 int linesizes[4];
268
273 }
274
277 img->fmt,
img->bit_depth);
279 }
280
287 }
288
289 if (
ctx->has_alpha_channel &&
290 (
img->d_w != img_alpha->d_w ||
291 img->d_h != img_alpha->d_h ||
292 img->bit_depth != img_alpha->bit_depth)) {
294 "Video dimensions %dx%d@%dbpc differ from alpha dimensions %dx%d@%dbpc\n",
296 img_alpha->d_w, img_alpha->d_h, img_alpha->bit_depth);
298 }
299
304 ctx->has_alpha_channel ? img_alpha->planes[VPX_PLANE_Y] :
NULL;
305 linesizes[0] =
img->stride[VPX_PLANE_Y];
306 linesizes[1] =
img->stride[VPX_PLANE_U];
307 linesizes[2] =
img->stride[VPX_PLANE_V];
308 linesizes[3] =
309 ctx->has_alpha_channel ? img_alpha->stride[VPX_PLANE_Y] : 0;
310
311 if (
img->fb_priv && (!
ctx->has_alpha_channel || img_alpha->fb_priv)) {
316 if (!picture->
buf[0])
318 if (
ctx->has_alpha_channel) {
320 if (!picture->
buf[1])
322 }
323 for (
int i = 0;
i < 4;
i++) {
326 }
327 } else {
332 }
333 *got_frame = 1;
334 }
336 }
337
339 {
341 vpx_codec_destroy(&
ctx->decoder);
342 if (
ctx->has_alpha_channel)
343 vpx_codec_destroy(&
ctx->decoder_alpha);
345 return 0;
346 }
347
348 #if CONFIG_LIBVPX_VP8_DECODER
350 {
352 return vpx_init(avctx, &
ctx->decoder, vpx_codec_vp8_dx());
353 }
354
361 .p.wrapper_name = "libvpx",
362 .priv_data_size = sizeof(VPxContext),
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 .
p.
name =
"libvpx-vp9",
385 .p.wrapper_name = "libvpx",
386 .priv_data_size = sizeof(VPxContext),
392 };
393 #endif /* CONFIG_LIBVPX_VP9_DECODER */