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 decoder support via libvpx 24 */ 25 26#define VPX_CODEC_DISABLE_COMPAT 1 27#include <vpx/vpx_decoder.h> 28#include <vpx/vp8dx.h> 29 30#include "libavutil/common.h" 31#include "libavutil/imgutils.h" 32#include "avcodec.h" 33#include "internal.h" 34#include "libvpx.h" 35 36typedef struct VP8DecoderContext { 37 struct vpx_codec_ctx decoder; 38} VP8Context; 39 40static av_cold int vpx_init(AVCodecContext *avctx, 41 const struct vpx_codec_iface *iface) 42{ 43 VP8Context *ctx = avctx->priv_data; 44 struct vpx_codec_dec_cfg deccfg = { 45 /* token partitions+1 would be a decent choice */ 46 .threads = FFMIN(avctx->thread_count, 16) 47 }; 48 49 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); 50 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); 51 52 if (vpx_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != VPX_CODEC_OK) { 53 const char *error = vpx_codec_error(&ctx->decoder); 54 av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n", 55 error); 56 return AVERROR(EINVAL); 57 } 58 59 avctx->pix_fmt = AV_PIX_FMT_YUV420P; 60 return 0; 61} 62 63static int vp8_decode(AVCodecContext *avctx, 64 void *data, int *got_frame, AVPacket *avpkt) 65{ 66 VP8Context *ctx = avctx->priv_data; 67 AVFrame *picture = data; 68 const void *iter = NULL; 69 struct vpx_image *img; 70 int ret; 71 72 if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) != 73 VPX_CODEC_OK) { 74 const char *error = vpx_codec_error(&ctx->decoder); 75 const char *detail = vpx_codec_error_detail(&ctx->decoder); 76 77 av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error); 78 if (detail) 79 av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", 80 detail); 81 return AVERROR_INVALIDDATA; 82 } 83 84 if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) { 85 if (img->fmt != VPX_IMG_FMT_I420) { 86 av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n", 87 img->fmt); 88 return AVERROR_INVALIDDATA; 89 } 90 91 if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) { 92 av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", 93 avctx->width, avctx->height, img->d_w, img->d_h); 94 ret = ff_set_dimensions(avctx, img->d_w, img->d_h); 95 if (ret < 0) 96 return ret; 97 } 98 if ((ret = ff_get_buffer(avctx, picture, 0)) < 0) 99 return ret; 100 av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes, 101 img->stride, avctx->pix_fmt, img->d_w, img->d_h); 102 *got_frame = 1; 103 } 104 return avpkt->size; 105} 106 107static av_cold int vp8_free(AVCodecContext *avctx) 108{ 109 VP8Context *ctx = avctx->priv_data; 110 vpx_codec_destroy(&ctx->decoder); 111 return 0; 112} 113 114#if CONFIG_LIBVPX_VP8_DECODER 115static av_cold int vp8_init(AVCodecContext *avctx) 116{ 117 return vpx_init(avctx, &vpx_codec_vp8_dx_algo); 118} 119 120AVCodec ff_libvpx_vp8_decoder = { 121 .name = "libvpx", 122 .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), 123 .type = AVMEDIA_TYPE_VIDEO, 124 .id = AV_CODEC_ID_VP8, 125 .priv_data_size = sizeof(VP8Context), 126 .init = vp8_init, 127 .close = vp8_free, 128 .decode = vp8_decode, 129 .capabilities = CODEC_CAP_AUTO_THREADS | CODEC_CAP_DR1, 130}; 131#endif /* CONFIG_LIBVPX_VP8_DECODER */ 132 133#if CONFIG_LIBVPX_VP9_DECODER 134static av_cold int vp9_init(AVCodecContext *avctx) 135{ 136 return vpx_init(avctx, &vpx_codec_vp9_dx_algo); 137} 138 139AVCodec ff_libvpx_vp9_decoder = { 140 .name = "libvpx-vp9", 141 .long_name = NULL_IF_CONFIG_SMALL("libvpx VP9"), 142 .type = AVMEDIA_TYPE_VIDEO, 143 .id = AV_CODEC_ID_VP9, 144 .priv_data_size = sizeof(VP8Context), 145 .init = vp9_init, 146 .close = vp8_free, 147 .decode = vp8_decode, 148 .capabilities = CODEC_CAP_AUTO_THREADS | CODEC_CAP_DR1, 149 .init_static_data = ff_vp9_init_static, 150}; 151#endif /* CONFIG_LIBVPX_VP9_DECODER */ 152