Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  
  36. typedef struct VP8DecoderContext {
  37.     struct vpx_codec_ctx decoder;
  38. } VP8Context;
  39.  
  40. static 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.     return 0;
  60. }
  61.  
  62. // returns 0 on success, AVERROR_INVALIDDATA otherwise
  63. static int set_pix_fmt(AVCodecContext *avctx, struct vpx_image *img)
  64. {
  65. #if VPX_IMAGE_ABI_VERSION >= 3
  66.     static const enum AVColorSpace colorspaces[8] = {
  67.         AVCOL_SPC_UNSPECIFIED, AVCOL_SPC_BT470BG, AVCOL_SPC_BT709, AVCOL_SPC_SMPTE170M,
  68.         AVCOL_SPC_SMPTE240M, AVCOL_SPC_BT2020_NCL, AVCOL_SPC_RESERVED, AVCOL_SPC_RGB,
  69.     };
  70.     avctx->colorspace = colorspaces[img->cs];
  71. #endif
  72.     if (avctx->codec_id == AV_CODEC_ID_VP8 && img->fmt != VPX_IMG_FMT_I420)
  73.         return AVERROR_INVALIDDATA;
  74.     switch (img->fmt) {
  75.     case VPX_IMG_FMT_I420:
  76.         if (avctx->codec_id == AV_CODEC_ID_VP9)
  77.             avctx->profile = FF_PROFILE_VP9_0;
  78.         avctx->pix_fmt = AV_PIX_FMT_YUV420P;
  79.         return 0;
  80. #if CONFIG_LIBVPX_VP9_DECODER
  81.     case VPX_IMG_FMT_I422:
  82.         avctx->profile = FF_PROFILE_VP9_1;
  83.         avctx->pix_fmt = AV_PIX_FMT_YUV422P;
  84.         return 0;
  85. #if VPX_IMAGE_ABI_VERSION >= 3
  86.     case VPX_IMG_FMT_I440:
  87.         avctx->profile = FF_PROFILE_VP9_1;
  88.         avctx->pix_fmt = AV_PIX_FMT_YUV440P;
  89.         return 0;
  90. #endif
  91.     case VPX_IMG_FMT_I444:
  92.         avctx->profile = FF_PROFILE_VP9_1;
  93. #if VPX_IMAGE_ABI_VERSION >= 3
  94.         avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
  95.                          AV_PIX_FMT_GBRP : AV_PIX_FMT_YUV444P;
  96. #else
  97.         avctx->pix_fmt = AV_PIX_FMT_YUV444P;
  98. #endif
  99.         return 0;
  100. #ifdef VPX_IMG_FMT_HIGHBITDEPTH
  101.     case VPX_IMG_FMT_I42016:
  102.         avctx->profile = FF_PROFILE_VP9_2;
  103.         if (img->bit_depth == 10) {
  104.             avctx->pix_fmt = AV_PIX_FMT_YUV420P10LE;
  105.             return 0;
  106.         } else if (img->bit_depth == 12) {
  107.             avctx->pix_fmt = AV_PIX_FMT_YUV420P12LE;
  108.             return 0;
  109.         } else {
  110.             return AVERROR_INVALIDDATA;
  111.         }
  112.     case VPX_IMG_FMT_I42216:
  113.         avctx->profile = FF_PROFILE_VP9_3;
  114.         if (img->bit_depth == 10) {
  115. #if VPX_IMAGE_ABI_VERSION >= 3
  116.             avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
  117.                              AV_PIX_FMT_GBRP10LE : AV_PIX_FMT_YUV422P10LE;
  118. #else
  119.             avctx->pix_fmt = AV_PIX_FMT_YUV422P10LE;
  120. #endif
  121.             return 0;
  122.         } else if (img->bit_depth == 12) {
  123. #if VPX_IMAGE_ABI_VERSION >= 3
  124.             avctx->pix_fmt = avctx->colorspace == AVCOL_SPC_RGB ?
  125.                              AV_PIX_FMT_GBRP12LE : AV_PIX_FMT_YUV422P12LE;
  126. #else
  127.             avctx->pix_fmt = AV_PIX_FMT_YUV422P12LE;
  128. #endif
  129.             return 0;
  130.         } else {
  131.             return AVERROR_INVALIDDATA;
  132.         }
  133. #if VPX_IMAGE_ABI_VERSION >= 3
  134.     case VPX_IMG_FMT_I44016:
  135.         avctx->profile = FF_PROFILE_VP9_3;
  136.         if (img->bit_depth == 10) {
  137.             avctx->pix_fmt = AV_PIX_FMT_YUV440P10LE;
  138.             return 0;
  139.         } else if (img->bit_depth == 12) {
  140.             avctx->pix_fmt = AV_PIX_FMT_YUV440P12LE;
  141.             return 0;
  142.         } else {
  143.             return AVERROR_INVALIDDATA;
  144.         }
  145. #endif
  146.     case VPX_IMG_FMT_I44416:
  147.         avctx->profile = FF_PROFILE_VP9_3;
  148.         if (img->bit_depth == 10) {
  149.             avctx->pix_fmt = AV_PIX_FMT_YUV444P10LE;
  150.             return 0;
  151.         } else if (img->bit_depth == 12) {
  152.             avctx->pix_fmt = AV_PIX_FMT_YUV444P12LE;
  153.             return 0;
  154.         } else {
  155.             return AVERROR_INVALIDDATA;
  156.         }
  157. #endif
  158. #endif
  159.     default:
  160.         return AVERROR_INVALIDDATA;
  161.     }
  162. }
  163.  
  164. static int vp8_decode(AVCodecContext *avctx,
  165.                       void *data, int *got_frame, AVPacket *avpkt)
  166. {
  167.     VP8Context *ctx = avctx->priv_data;
  168.     AVFrame *picture = data;
  169.     const void *iter = NULL;
  170.     struct vpx_image *img;
  171.     int ret;
  172.  
  173.     if (vpx_codec_decode(&ctx->decoder, avpkt->data, avpkt->size, NULL, 0) !=
  174.         VPX_CODEC_OK) {
  175.         const char *error  = vpx_codec_error(&ctx->decoder);
  176.         const char *detail = vpx_codec_error_detail(&ctx->decoder);
  177.  
  178.         av_log(avctx, AV_LOG_ERROR, "Failed to decode frame: %s\n", error);
  179.         if (detail)
  180.             av_log(avctx, AV_LOG_ERROR, "  Additional information: %s\n",
  181.                    detail);
  182.         return AVERROR_INVALIDDATA;
  183.     }
  184.  
  185.     if ((img = vpx_codec_get_frame(&ctx->decoder, &iter))) {
  186.         if ((ret = set_pix_fmt(avctx, img)) < 0) {
  187. #ifdef VPX_IMG_FMT_HIGHBITDEPTH
  188.             av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n",
  189.                    img->fmt, img->bit_depth);
  190. #else
  191.             av_log(avctx, AV_LOG_ERROR, "Unsupported output colorspace (%d) / bit_depth (%d)\n",
  192.                    img->fmt, 8);
  193. #endif
  194.             return ret;
  195.         }
  196.  
  197.         if ((int) img->d_w != avctx->width || (int) img->d_h != avctx->height) {
  198.             av_log(avctx, AV_LOG_INFO, "dimension change! %dx%d -> %dx%d\n",
  199.                    avctx->width, avctx->height, img->d_w, img->d_h);
  200.             ret = ff_set_dimensions(avctx, img->d_w, img->d_h);
  201.             if (ret < 0)
  202.                 return ret;
  203.         }
  204.         if ((ret = ff_get_buffer(avctx, picture, 0)) < 0)
  205.             return ret;
  206.         av_image_copy(picture->data, picture->linesize, (const uint8_t **)img->planes,
  207.                       img->stride, avctx->pix_fmt, img->d_w, img->d_h);
  208.         *got_frame           = 1;
  209.     }
  210.     return avpkt->size;
  211. }
  212.  
  213. static av_cold int vp8_free(AVCodecContext *avctx)
  214. {
  215.     VP8Context *ctx = avctx->priv_data;
  216.     vpx_codec_destroy(&ctx->decoder);
  217.     return 0;
  218. }
  219.  
  220. #if CONFIG_LIBVPX_VP8_DECODER
  221. static av_cold int vp8_init(AVCodecContext *avctx)
  222. {
  223.     return vpx_init(avctx, &vpx_codec_vp8_dx_algo);
  224. }
  225.  
  226. AVCodec ff_libvpx_vp8_decoder = {
  227.     .name           = "libvpx",
  228.     .long_name      = NULL_IF_CONFIG_SMALL("libvpx VP8"),
  229.     .type           = AVMEDIA_TYPE_VIDEO,
  230.     .id             = AV_CODEC_ID_VP8,
  231.     .priv_data_size = sizeof(VP8Context),
  232.     .init           = vp8_init,
  233.     .close          = vp8_free,
  234.     .decode         = vp8_decode,
  235.     .capabilities   = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1,
  236. };
  237. #endif /* CONFIG_LIBVPX_VP8_DECODER */
  238.  
  239. #if CONFIG_LIBVPX_VP9_DECODER
  240. static av_cold int vp9_init(AVCodecContext *avctx)
  241. {
  242.     return vpx_init(avctx, &vpx_codec_vp9_dx_algo);
  243. }
  244.  
  245. static const AVProfile profiles[] = {
  246.     { FF_PROFILE_VP9_0, "Profile 0" },
  247.     { FF_PROFILE_VP9_1, "Profile 1" },
  248.     { FF_PROFILE_VP9_2, "Profile 2" },
  249.     { FF_PROFILE_VP9_3, "Profile 3" },
  250.     { FF_PROFILE_UNKNOWN },
  251. };
  252.  
  253. AVCodec ff_libvpx_vp9_decoder = {
  254.     .name           = "libvpx-vp9",
  255.     .long_name      = NULL_IF_CONFIG_SMALL("libvpx VP9"),
  256.     .type           = AVMEDIA_TYPE_VIDEO,
  257.     .id             = AV_CODEC_ID_VP9,
  258.     .priv_data_size = sizeof(VP8Context),
  259.     .init           = vp9_init,
  260.     .close          = vp8_free,
  261.     .decode         = vp8_decode,
  262.     .capabilities   = AV_CODEC_CAP_AUTO_THREADS | AV_CODEC_CAP_DR1,
  263.     .init_static_data = ff_vp9_init_static,
  264.     .profiles       = NULL_IF_CONFIG_SMALL(profiles),
  265. };
  266. #endif /* CONFIG_LIBVPX_VP9_DECODER */
  267.