libvpxdec.c (13590B)
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 33 #include "libavutil/common.h" 34 #include "libavutil/cpu.h" 35 #include "libavutil/imgutils.h" 36 #include "libavutil/intreadwrite.h" 37 #include "avcodec.h" 38 #include "codec_internal.h" 39 #include "decode.h" 40 #include "libvpx.h" 41 #include "profiles.h" 42 43 typedef struct VPxDecoderContext { 44 struct vpx_codec_ctx decoder; 45 struct vpx_codec_ctx decoder_alpha; 46 AVBufferPool *pool; 47 size_t pool_size; 48 int has_alpha_channel; 49 } VPxContext; 50 51 52 static int get_frame_buffer(void *priv, size_t min_size, vpx_codec_frame_buffer_t *fb) 53 { 54 VPxContext *ctx = priv; 55 AVBufferRef *buf; 56 57 if (min_size > ctx->pool_size) { 58 av_buffer_pool_uninit(&ctx->pool); 59 /* According to the libvpx docs the buffer must be zeroed out. */ 60 ctx->pool = av_buffer_pool_init(min_size, av_buffer_allocz); 61 if (!ctx->pool) { 62 ctx->pool_size = 0; 63 return AVERROR(ENOMEM); 64 } 65 ctx->pool_size = min_size; 66 } 67 68 buf = av_buffer_pool_get(ctx->pool); 69 if (!buf) 70 return AVERROR(ENOMEM); 71 72 fb->priv = buf; 73 fb->size = ctx->pool_size; 74 fb->data = buf->data; 75 76 return 0; 77 } 78 79 static int release_frame_buffer(void *priv, vpx_codec_frame_buffer_t *fb) 80 { 81 AVBufferRef *buf = fb->priv; 82 av_buffer_unref(&buf); 83 return 0; 84 } 85 86 static av_cold int vpx_init(AVCodecContext *avctx, 87 struct vpx_codec_ctx* decoder, 88 const struct vpx_codec_iface *iface) 89 { 90 struct vpx_codec_dec_cfg deccfg = { 91 .threads = FFMIN(avctx->thread_count ? avctx->thread_count : av_cpu_count(), MAX_VPX_THREADS) 92 }; 93 94 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); 95 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); 96 97 if (vpx_codec_dec_init(decoder, iface, &deccfg, 0) != VPX_CODEC_OK) { 98 const char *error = vpx_codec_error(decoder); 99 av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n", 100 error); 101 return AVERROR(EINVAL); 102 } 103 104 if (avctx->codec_id == AV_CODEC_ID_VP9) 105 vpx_codec_set_frame_buffer_functions(decoder, get_frame_buffer, release_frame_buffer, avctx->priv_data); 106 107 return 0; 108 } 109 110 // returns 0 on success, AVERROR_INVALIDDATA otherwise 111 static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img, 112 int has_alpha_channel) 113 { 114 static const enum AVColorSpace colorspaces[8] = { 115 AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M, 116 AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB, 117 }; 118 #if VPX_IMAGE_ABI_VERSION >= 4 119 static const enum AVColorRange color_ranges[] = { 120 AVCOL_RANGE_MPEG, AVCOL_RANGE_JPEG 121 }; 122 avctx->color_range = color_ranges[img->range]; 123 #endif 124 avctx->colorspace = colorspaces[img->cs]; 125 if (avctx->codec_id == AV_CODEC_ID_VP8 && img->fmt != VPX_IMG_FMT_I420) 126 return AVERROR_INVALIDDATA; 127 switch (img->fmt) { 128 case VPX_IMG_FMT_I420: 129 if (avctx->codec_id == AV_CODEC_ID_VP9) 130 avctx->profile = AV_PROFILE_VP9_0; 131 avctx->pix_fmt = 132 has_alpha_channel ? AV_PIX_FMT_YUVA420P : AV_PIX_FMT_YUV420P; 133 return 0; 134 #if CONFIG_LIBVPX_VP9_DECODER 135 case VPX_IMG_FMT_I422: 136 avctx->profile = AV_PROFILE_VP9_1; 137 avctx->pix_fmt = AV_PIX_FMT_YUV422P; 138 return 0; 139 case VPX_IMG_FMT_I440: 140 avctx->profile = AV_PROFILE_VP9_1; 141 avctx->pix_fmt = AV_PIX_FMT_YUV440P; 142 return 0; 143 case VPX_IMG_FMT_I444: 144 avctx->profile = AV_PROFILE_VP9_1; 145 avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? 146 AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P; 147 return 0; 148 case VPX_IMG_FMT_I42016: 149 avctx->profile = AV_PROFILE_VP9_2; 150 if (img->bit_depth == 10) { 151 avctx->pix_fmt = AV_PIX_FMT_YUV420P10; 152 return 0; 153 } else if (img->bit_depth == 12) { 154 avctx->pix_fmt = AV_PIX_FMT_YUV420P12; 155 return 0; 156 } else { 157 return AVERROR_INVALIDDATA; 158 } 159 case VPX_IMG_FMT_I42216: 160 avctx->profile = AV_PROFILE_VP9_3; 161 if (img->bit_depth == 10) { 162 avctx->pix_fmt = AV_PIX_FMT_YUV422P10; 163 return 0; 164 } else if (img->bit_depth == 12) { 165 avctx->pix_fmt = AV_PIX_FMT_YUV422P12; 166 return 0; 167 } else { 168 return AVERROR_INVALIDDATA; 169 } 170 case VPX_IMG_FMT_I44016: 171 avctx->profile = AV_PROFILE_VP9_3; 172 if (img->bit_depth == 10) { 173 avctx->pix_fmt = AV_PIX_FMT_YUV440P10; 174 return 0; 175 } else if (img->bit_depth == 12) { 176 avctx->pix_fmt = AV_PIX_FMT_YUV440P12; 177 return 0; 178 } else { 179 return AVERROR_INVALIDDATA; 180 } 181 case VPX_IMG_FMT_I44416: 182 avctx->profile = AV_PROFILE_VP9_3; 183 if (img->bit_depth == 10) { 184 avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? 185 AV_PIX_FMT_GBRP10 : AV_PIX_FMT_YUV444P10; 186 return 0; 187 } else if (img->bit_depth == 12) { 188 avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ? 189 AV_PIX_FMT_GBRP12 : AV_PIX_FMT_YUV444P12; 190 return 0; 191 } else { 192 return AVERROR_INVALIDDATA; 193 } 194 #endif 195 default: 196 return AVERROR_INVALIDDATA; 197 } 198 } 199 200 static int decode_frame(AVCodecContext *avctx, vpx_codec_ctx_t *decoder, 201 const uint8_t *data, uint32_t data_sz) 202 { 203 if (vpx_codec_decode(decoder, data, data_sz, NULL, 0) != VPX_CODEC_OK) { 204 const char *error = vpx_codec_error(decoder); 205 const char *detail = vpx_codec_error_detail(decoder); 206 207 av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error); 208 if (detail) { 209 av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", 210 detail); 211 } 212 return AVERROR_INVALIDDATA; 213 } 214 return 0; 215 } 216 217 static int vpx_decode(AVCodecContext *avctx, AVFrame *picture, 218 int *got_frame, AVPacket *avpkt) 219 { 220 VPxContext *ctx = avctx->priv_data; 221 const void *iter = NULL; 222 const void *iter_alpha = NULL; 223 struct vpx_image *img, *img_alpha; 224 int ret; 225 uint8_t *side_data = NULL; 226 size_t side_data_size; 227 228 ret = decode_frame(avctx, &ctx->decoder, avpkt->data, avpkt->size); 229 if (ret) 230 return ret; 231 232 side_data = av_packet_get_side_data(avpkt, 233 AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, 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; 242 ret = vpx_init(avctx, 243 &ctx->decoder_alpha, 244 #if CONFIG_LIBVPX_VP8_DECODER && CONFIG_LIBVPX_VP9_DECODER 245 (avctx->codec_id == AV_CODEC_ID_VP8) ? 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 ); 253 if (ret) 254 return ret; 255 } 256 ret = decode_frame(avctx, &ctx->decoder_alpha, side_data, 257 side_data_size); 258 if (ret) 259 return ret; 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)))) { 266 uint8_t *planes[4]; 267 int linesizes[4]; 268 269 if (img->d_w > img->w || img->d_h > img->h) { 270 av_log(avctx, AV_LOG_ERROR, "Display dimensions %dx%d exceed storage %dx%d\n", 271 img->d_w, img->d_h, img->w, img->h); 272 return AVERROR_EXTERNAL; 273 } 274 275 if ((ret = set_pix_fmt(avctx, img, ctx->has_alpha_channel)) < 0) { 276 av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n", 277 img->fmt, img->bit_depth); 278 return ret; 279 } 280 281 if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) { 282 av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", 283 avctx->width, avctx->height, img->d_w, img->d_h); 284 ret = ff_set_dimensions(avctx, img->d_w, img->d_h); 285 if (ret < 0) 286 return ret; 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)) { 293 av_log(avctx, AV_LOG_ERROR, 294 "Video dimensions %dx%d@%dbpc differ from alpha dimensions %dx%d@%dbpc\n", 295 img->d_w, img->d_h, img->bit_depth, 296 img_alpha->d_w, img_alpha->d_h, img_alpha->bit_depth); 297 return AVERROR_INVALIDDATA; 298 } 299 300 planes[0] = img->planes[VPX_PLANE_Y]; 301 planes[1] = img->planes[VPX_PLANE_U]; 302 planes[2] = img->planes[VPX_PLANE_V]; 303 planes[3] = 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)) { 312 ret = ff_decode_frame_props(avctx, picture); 313 if (ret < 0) 314 return ret; 315 picture->buf[0] = av_buffer_ref(img->fb_priv); 316 if (!picture->buf[0]) 317 return AVERROR(ENOMEM); 318 if (ctx->has_alpha_channel) { 319 picture->buf[1] = av_buffer_ref(img_alpha->fb_priv); 320 if (!picture->buf[1]) 321 return AVERROR(ENOMEM); 322 } 323 for (int i = 0; i < 4; i++) { 324 picture->data[i] = planes[i]; 325 picture->linesize[i] = linesizes[i]; 326 } 327 } else { 328 if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) 329 return ret; 330 av_image_copy2(picture->data, picture->linesize, planes, 331 linesizes, avctx->pix_fmt, img->d_w, img->d_h); 332 } 333 *got_frame = 1; 334 } 335 return avpkt->size; 336 } 337 338 static av_cold int vpx_free(AVCodecContext *avctx) 339 { 340 VPxContext *ctx = avctx->priv_data; 341 vpx_codec_destroy(&ctx->decoder); 342 if (ctx->has_alpha_channel) 343 vpx_codec_destroy(&ctx->decoder_alpha); 344 av_buffer_pool_uninit(&ctx->pool); 345 return 0; 346 } 347 348 #if CONFIG_LIBVPX_VP8_DECODER 349 static av_cold int vp8_init(AVCodecContext *avctx) 350 { 351 VPxContext *ctx = avctx->priv_data; 352 return vpx_init(avctx, &ctx->decoder, vpx_codec_vp8_dx()); 353 } 354 355 const FFCodec ff_libvpx_vp8_decoder = { 356 .p.name = "libvpx", 357 CODEC_LONG_NAME("libvpx VP8"), 358 .p.type = AVMEDIA_TYPE_VIDEO, 359 .p.id = AV_CODEC_ID_VP8, 360 .p.capabilities = AV_CODEC_CAP_OTHER_THREADS | AV_CODEC_CAP_DR1, 361 .p.wrapper_name = "libvpx", 362 .priv_data_size = sizeof(VPxContext), 363 .init = vp8_init, 364 .close = vpx_free, 365 FF_CODEC_DECODE_CB(vpx_decode), 366 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | 367 FF_CODEC_CAP_AUTO_THREADS, 368 }; 369 #endif /* CONFIG_LIBVPX_VP8_DECODER */ 370 371 #if CONFIG_LIBVPX_VP9_DECODER 372 static av_cold int vp9_init(AVCodecContext *avctx) 373 { 374 VPxContext *ctx = avctx->priv_data; 375 return vpx_init(avctx, &ctx->decoder, vpx_codec_vp9_dx()); 376 } 377 378 const FFCodec ff_libvpx_vp9_decoder = { 379 .p.name = "libvpx-vp9", 380 CODEC_LONG_NAME("libvpx VP9"), 381 .p.type = AVMEDIA_TYPE_VIDEO, 382 .p.id = AV_CODEC_ID_VP9, 383 .p.capabilities = AV_CODEC_CAP_OTHER_THREADS, 384 .p.profiles = NULL_IF_CONFIG_SMALL(ff_vp9_profiles), 385 .p.wrapper_name = "libvpx", 386 .priv_data_size = sizeof(VPxContext), 387 .init = vp9_init, 388 .close = vpx_free, 389 FF_CODEC_DECODE_CB(vpx_decode), 390 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE | 391 FF_CODEC_CAP_AUTO_THREADS, 392 }; 393 #endif /* CONFIG_LIBVPX_VP9_DECODER */