Libav
|
00001 /* 00002 * Copyright (c) 2010, Google, Inc. 00003 * 00004 * This file is part of FFmpeg. 00005 * 00006 * FFmpeg is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * FFmpeg is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with FFmpeg; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00026 #define VPX_CODEC_DISABLE_COMPAT 1 00027 #include <vpx/vpx_decoder.h> 00028 #include <vpx/vp8dx.h> 00029 00030 #include "avcodec.h" 00031 00032 typedef struct VP8DecoderContext { 00033 struct vpx_codec_ctx decoder; 00034 } VP8Context; 00035 00036 static av_cold int vp8_init(AVCodecContext *avctx) 00037 { 00038 VP8Context *ctx = avctx->priv_data; 00039 const struct vpx_codec_iface *iface = &vpx_codec_vp8_dx_algo; 00040 struct vpx_codec_dec_cfg deccfg = { 00041 /* token partitions+1 would be a decent choice */ 00042 .threads = FFMIN(avctx->thread_count, 16) 00043 }; 00044 00045 av_log(avctx, AV_LOG_INFO, "%s\n", vpx_codec_version_str()); 00046 av_log(avctx, AV_LOG_VERBOSE, "%s\n", vpx_codec_build_config()); 00047 00048 if (vpx_codec_dec_init(&ctx->decoder, iface, &deccfg, 0) != VPX_CODEC_OK) { 00049 const char *error = vpx_codec_error(&ctx->decoder); 00050 av_log(avctx, AV_LOG_ERROR, "Failed to initialize decoder: %s\n", 00051 error); 00052 return AVERROR(EINVAL); 00053 } 00054 00055 avctx->pix_fmt = PIX_FMT_YUV420P; 00056 return 0; 00057 } 00058 00059 static int vp8_decode(AVCodecContext *avctx, 00060 void *data, int *data_size, AVPacket *avpkt) 00061 { 00062 VP8Context *ctx = avctx->priv_data; 00063 AVFrame *picture = data; 00064 const void *iter = NULL; 00065 struct vpx_image *img; 00066 00067 if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) != 00068 VPX_CODEC_OK) { 00069 const char *error = vpx_codec_error(&ctx->decoder); 00070 const char *detail = vpx_codec_error_detail(&ctx->decoder); 00071 00072 av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error); 00073 if (detail) 00074 av_log(avctx, AV_LOG_ERROR, " Additional information: %s\n", 00075 detail); 00076 return AVERROR_INVALIDDATA; 00077 } 00078 00079 if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) { 00080 if (img->fmt != VPX_IMG_FMT_I420) { 00081 av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d)\n", 00082 img->fmt); 00083 return AVERROR_INVALIDDATA; 00084 } 00085 00086 if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) { 00087 av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n", 00088 avctx->width, avctx->height, img->d_w, img->d_h); 00089 if (avcodec_check_dimensions(avctx, img->d_w, img->d_h)) 00090 return AVERROR_INVALIDDATA; 00091 avcodec_set_dimensions(avctx, img->d_w, img->d_h); 00092 } 00093 picture->data[0] = img->planes[0]; 00094 picture->data[1] = img->planes[1]; 00095 picture->data[2] = img->planes[2]; 00096 picture->data[3] = NULL; 00097 picture->linesize[0] = img->stride[0]; 00098 picture->linesize[1] = img->stride[1]; 00099 picture->linesize[2] = img->stride[2]; 00100 picture->linesize[3] = 0; 00101 *data_size = sizeof(AVPicture); 00102 } 00103 return avpkt->size; 00104 } 00105 00106 static av_cold int vp8_free(AVCodecContext *avctx) 00107 { 00108 VP8Context *ctx = avctx->priv_data; 00109 vpx_codec_destroy(&ctx->decoder); 00110 return 0; 00111 } 00112 00113 AVCodec libvpx_decoder = { 00114 "libvpx", 00115 AVMEDIA_TYPE_VIDEO, 00116 CODEC_ID_VP8, 00117 sizeof(VP8Context), 00118 vp8_init, 00119 NULL, /* encode */ 00120 vp8_free, 00121 vp8_decode, 00122 0, /* capabilities */ 00123 .long_name = NULL_IF_CONFIG_SMALL("libvpx VP8"), 00124 };