00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00026 #define VPX_CODEC_DISABLE_COMPAT 1
00027 #include <vpx/vpx_decoder.h>
00028 #include <vpx/vp8dx.h>
00029
00030 #include "libavutil/common.h"
00031 #include "libavutil/imgutils.h"
00032 #include "avcodec.h"
00033
00034 typedef struct VP8DecoderContext {
00035 struct vpx_codec_ctx decoder;
00036 } VP8Context;
00037
00038 static av_cold int vp8_init(AVCodecContext *avctx)
00039 {
00040 VP8Context *ctx = avctx->priv_data;
00041 const struct vpx_codec_iface *iface = &vpx_codec_vp8_dx_algo;
00042 struct vpx_codec_dec_cfg deccfg = {
00043
00044 .threads = FFMIN(avctx->thread_count, 16)
00045 };
00046
00047 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str());
00048 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config());
00049
00050 if (vpx_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != VPX_CODEC_OK) {
00051 const char *error = vpx_codec_error(&ctx->decoder);
00052 av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n",
00053 error);
00054 return AVERROR(EINVAL);
00055 }
00056
00057 avctx->pix_fmt = PIX_FMT_YUV420P;
00058 return 0;
00059 }
00060
00061 static int vp8_decode(AVCodecContext *avctx,
00062 void *data, int *data_size, AVPacket *avpkt)
00063 {
00064 VP8Context *ctx = avctx->priv_data;
00065 AVFrame *picture = data;
00066 const void *iter = NULL;
00067 struct vpx_image *img;
00068
00069 if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) !=
00070 VPX_CODEC_OK) {
00071 const char *error = vpx_codec_error(&ctx->decoder);
00072 const char *detail = vpx_codec_error_detail(&ctx->decoder);
00073
00074 av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
00075 if (detail)
00076 av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n",
00077 detail);
00078 return AVERROR_INVALIDDATA;
00079 }
00080
00081 if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) {
00082 if (img->fmt != VPX_IMG_FMT_I420) {
00083 av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n",
00084 img->fmt);
00085 return AVERROR_INVALIDDATA;
00086 }
00087
00088 if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) {
00089 av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n",
00090 avctx->width, avctx->height, img->d_w, img->d_h);
00091 if (av_image_check_size(img->d_w, img->d_h, 0, avctx))
00092 return AVERROR_INVALIDDATA;
00093 avcodec_set_dimensions(avctx, img->d_w, img->d_h);
00094 }
00095 picture->data[0] = img->planes[0];
00096 picture->data[1] = img->planes[1];
00097 picture->data[2] = img->planes[2];
00098 picture->data[3] = NULL;
00099 picture->linesize[0] = img->stride[0];
00100 picture->linesize[1] = img->stride[1];
00101 picture->linesize[2] = img->stride[2];
00102 picture->linesize[3] = 0;
00103 *data_size = sizeof(AVPicture);
00104 }
00105 return avpkt->size;
00106 }
00107
00108 static av_cold int vp8_free(AVCodecContext *avctx)
00109 {
00110 VP8Context *ctx = avctx->priv_data;
00111 vpx_codec_destroy(&ctx->decoder);
00112 return 0;
00113 }
00114
00115 AVCodec ff_libvpx_decoder = {
00116 .name = "libvpx",
00117 .type = AVMEDIA_TYPE_VIDEO,
00118 .id = AV_CODEC_ID_VP8,
00119 .priv_data_size = sizeof(VP8Context),
00120 .init = vp8_init,
00121 .close = vp8_free,
00122 .decode = vp8_decode,
00123 .capabilities = CODEC_CAP_AUTO_THREADS,
00124 .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"),
00125 };