Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Intel MediaSDK QSV based H.264 / HEVC decoder
  3.  *
  4.  * copyright (c) 2013 Luca Barbato
  5.  * copyright (c) 2015 Anton Khirnov
  6.  *
  7.  * This file is part of FFmpeg.
  8.  *
  9.  * FFmpeg is free software; you can redistribute it and/or
  10.  * modify it under the terms of the GNU Lesser General Public
  11.  * License as published by the Free Software Foundation; either
  12.  * version 2.1 of the License, or (at your option) any later version.
  13.  *
  14.  * FFmpeg is distributed in the hope that it will be useful,
  15.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17.  * Lesser General Public License for more details.
  18.  *
  19.  * You should have received a copy of the GNU Lesser General Public
  20.  * License along with FFmpeg; if not, write to the Free Software
  21.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22.  */
  23.  
  24.  
  25. #include <stdint.h>
  26. #include <string.h>
  27.  
  28. #include <mfx/mfxvideo.h>
  29.  
  30. #include "libavutil/common.h"
  31. #include "libavutil/fifo.h"
  32. #include "libavutil/opt.h"
  33.  
  34. #include "avcodec.h"
  35. #include "internal.h"
  36. #include "qsvdec.h"
  37.  
  38. enum LoadPlugin {
  39.     LOAD_PLUGIN_NONE,
  40.     LOAD_PLUGIN_HEVC_SW,
  41. };
  42.  
  43. typedef struct QSVH2645Context {
  44.     AVClass *class;
  45.     QSVContext qsv;
  46.  
  47.     int load_plugin;
  48.  
  49.     // the filter for converting to Annex B
  50.     AVBitStreamFilterContext *bsf;
  51.  
  52. } QSVH2645Context;
  53.  
  54. static av_cold int qsv_decode_close(AVCodecContext *avctx)
  55. {
  56.     QSVH2645Context *s = avctx->priv_data;
  57.  
  58.     ff_qsv_decode_close(&s->qsv);
  59.  
  60.     av_bitstream_filter_close(s->bsf);
  61.  
  62.     return 0;
  63. }
  64.  
  65. static av_cold int qsv_decode_init(AVCodecContext *avctx)
  66. {
  67.     QSVH2645Context *s = avctx->priv_data;
  68.     int ret;
  69.  
  70.     if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) {
  71.         static const char *uid_hevcenc_sw = "15dd936825ad475ea34e35f3f54217a6";
  72.  
  73.         if (s->qsv.load_plugins[0]) {
  74.             av_log(avctx, AV_LOG_WARNING,
  75.                    "load_plugins is not empty, but load_plugin is not set to 'none'."
  76.                    "The load_plugin value will be ignored.\n");
  77.         } else {
  78.             av_freep(&s->qsv.load_plugins);
  79.             s->qsv.load_plugins = av_strdup(uid_hevcenc_sw);
  80.             if (!s->qsv.load_plugins)
  81.                 return AVERROR(ENOMEM);
  82.         }
  83.     }
  84.  
  85.     if (avctx->codec_id == AV_CODEC_ID_H264)
  86.         s->bsf = av_bitstream_filter_init("h264_mp4toannexb");
  87.     else
  88.         s->bsf = av_bitstream_filter_init("hevc_mp4toannexb");
  89.     if (!s->bsf) {
  90.         ret = AVERROR(ENOMEM);
  91.         goto fail;
  92.     }
  93.  
  94.     return 0;
  95. fail:
  96.     qsv_decode_close(avctx);
  97.     return ret;
  98. }
  99.  
  100. static int qsv_decode_frame(AVCodecContext *avctx, void *data,
  101.                             int *got_frame, AVPacket *avpkt)
  102. {
  103.     QSVH2645Context *s = avctx->priv_data;
  104.     AVFrame *frame    = data;
  105.     int ret;
  106.     uint8_t *p_filtered = NULL;
  107.     int      n_filtered = NULL;
  108.     AVPacket pkt_filtered = { 0 };
  109.  
  110.     if (avpkt->size) {
  111.         if (avpkt->size > 3 && !avpkt->data[0] &&
  112.             !avpkt->data[1] && !avpkt->data[2] && 1==avpkt->data[3]) {
  113.             /* we already have annex-b prefix */
  114.             return ff_qsv_decode(avctx, &s->qsv, frame, got_frame, avpkt);
  115.  
  116.         } else {
  117.             /* no annex-b prefix. try to restore: */
  118.             ret = av_bitstream_filter_filter(s->bsf, avctx, "private_spspps_buf",
  119.                                          &p_filtered, &n_filtered,
  120.                                          avpkt->data, avpkt->size, 0);
  121.             if (ret>=0) {
  122.                 pkt_filtered.pts  = avpkt->pts;
  123.                 pkt_filtered.data = p_filtered;
  124.                 pkt_filtered.size = n_filtered;
  125.  
  126.                 ret = ff_qsv_decode(avctx, &s->qsv, frame, got_frame, &pkt_filtered);
  127.  
  128.                 if (p_filtered != avpkt->data)
  129.                     av_free(p_filtered);
  130.                 return ret > 0 ? avpkt->size : ret;
  131.             }
  132.         }
  133.     }
  134.  
  135.     return ff_qsv_decode(avctx, &s->qsv, frame, got_frame, avpkt);
  136. }
  137.  
  138. static void qsv_decode_flush(AVCodecContext *avctx)
  139. {
  140. //    QSVH2645Context *s = avctx->priv_data;
  141.     /* TODO: flush qsv engine if necessary */
  142. }
  143.  
  144. #define OFFSET(x) offsetof(QSVH2645Context, x)
  145. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  146.  
  147. #if CONFIG_HEVC_QSV_DECODER
  148. AVHWAccel ff_hevc_qsv_hwaccel = {
  149.     .name           = "hevc_qsv",
  150.     .type           = AVMEDIA_TYPE_VIDEO,
  151.     .id             = AV_CODEC_ID_HEVC,
  152.     .pix_fmt        = AV_PIX_FMT_QSV,
  153. };
  154.  
  155. static const AVOption hevc_options[] = {
  156.     { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
  157.  
  158.     { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_HEVC_SW }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_SW, VD, "load_plugin" },
  159.     { "none",     NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE },    0, 0, VD, "load_plugin" },
  160.     { "hevc_sw",  NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" },
  161.  
  162.     { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
  163.         OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD },
  164.     { NULL },
  165. };
  166.  
  167. static const AVClass hevc_class = {
  168.     .class_name = "hevc_qsv",
  169.     .item_name  = av_default_item_name,
  170.     .option     = hevc_options,
  171.     .version    = LIBAVUTIL_VERSION_INT,
  172. };
  173.  
  174. AVCodec ff_hevc_qsv_decoder = {
  175.     .name           = "hevc_qsv",
  176.     .long_name      = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"),
  177.     .priv_data_size = sizeof(QSVH2645Context),
  178.     .type           = AVMEDIA_TYPE_VIDEO,
  179.     .id             = AV_CODEC_ID_HEVC,
  180.     .init           = qsv_decode_init,
  181.     .decode         = qsv_decode_frame,
  182.     .flush          = qsv_decode_flush,
  183.     .close          = qsv_decode_close,
  184.     .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  185.     .priv_class     = &hevc_class,
  186. };
  187. #endif
  188.  
  189. #if CONFIG_H264_QSV_DECODER
  190. AVHWAccel ff_h264_qsv_hwaccel = {
  191.     .name           = "h264_qsv",
  192.     .type           = AVMEDIA_TYPE_VIDEO,
  193.     .id             = AV_CODEC_ID_H264,
  194.     .pix_fmt        = AV_PIX_FMT_QSV,
  195. };
  196.  
  197. static const AVOption options[] = {
  198.     { "async_depth", "Internal parallelization depth, the higher the value the higher the latency.", OFFSET(qsv.async_depth), AV_OPT_TYPE_INT, { .i64 = ASYNC_DEPTH_DEFAULT }, 0, INT_MAX, VD },
  199.     { NULL },
  200. };
  201.  
  202. static const AVClass class = {
  203.     .class_name = "h264_qsv",
  204.     .item_name  = av_default_item_name,
  205.     .option     = options,
  206.     .version    = LIBAVUTIL_VERSION_INT,
  207. };
  208.  
  209. AVCodec ff_h264_qsv_decoder = {
  210.     .name           = "h264_qsv",
  211.     .long_name      = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"),
  212.     .priv_data_size = sizeof(QSVH2645Context),
  213.     .type           = AVMEDIA_TYPE_VIDEO,
  214.     .id             = AV_CODEC_ID_H264,
  215.     .init           = qsv_decode_init,
  216.     .decode         = qsv_decode_frame,
  217.     .flush          = qsv_decode_flush,
  218.     .close          = qsv_decode_close,
  219.     .capabilities   = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  220.     .priv_class     = &class,
  221. };
  222. #endif
  223.