You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
8.5KB

  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 Libav.
  8. *
  9. * Libav 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. * Libav 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 Libav; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. */
  23. #include <stdint.h>
  24. #include <string.h>
  25. #include <mfx/mfxvideo.h>
  26. #include "libavutil/common.h"
  27. #include "libavutil/fifo.h"
  28. #include "libavutil/opt.h"
  29. #include "avcodec.h"
  30. #include "internal.h"
  31. #include "qsv_internal.h"
  32. #include "qsvdec.h"
  33. #include "qsv.h"
  34. enum LoadPlugin {
  35. LOAD_PLUGIN_NONE,
  36. LOAD_PLUGIN_HEVC_SW,
  37. LOAD_PLUGIN_HEVC_HW,
  38. };
  39. typedef struct QSVH2645Context {
  40. AVClass *class;
  41. QSVContext qsv;
  42. int load_plugin;
  43. AVFifoBuffer *packet_fifo;
  44. AVPacket buffer_pkt;
  45. } QSVH2645Context;
  46. static void qsv_clear_buffers(QSVH2645Context *s)
  47. {
  48. AVPacket pkt;
  49. while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) {
  50. av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL);
  51. av_packet_unref(&pkt);
  52. }
  53. av_packet_unref(&s->buffer_pkt);
  54. }
  55. static av_cold int qsv_decode_close(AVCodecContext *avctx)
  56. {
  57. QSVH2645Context *s = avctx->priv_data;
  58. ff_qsv_decode_close(&s->qsv);
  59. qsv_clear_buffers(s);
  60. av_fifo_free(s->packet_fifo);
  61. return 0;
  62. }
  63. static av_cold int qsv_decode_init(AVCodecContext *avctx)
  64. {
  65. QSVH2645Context *s = avctx->priv_data;
  66. int ret;
  67. if (avctx->codec_id == AV_CODEC_ID_HEVC && s->load_plugin != LOAD_PLUGIN_NONE) {
  68. static const char *uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6";
  69. static const char *uid_hevcdec_hw = "33a61c0b4c27454ca8d85dde757c6f8e";
  70. if (s->qsv.load_plugins[0]) {
  71. av_log(avctx, AV_LOG_WARNING,
  72. "load_plugins is not empty, but load_plugin is not set to 'none'."
  73. "The load_plugin value will be ignored.\n");
  74. } else {
  75. av_freep(&s->qsv.load_plugins);
  76. if (s->load_plugin == LOAD_PLUGIN_HEVC_SW)
  77. s->qsv.load_plugins = av_strdup(uid_hevcdec_sw);
  78. else
  79. s->qsv.load_plugins = av_strdup(uid_hevcdec_hw);
  80. if (!s->qsv.load_plugins)
  81. return AVERROR(ENOMEM);
  82. }
  83. }
  84. s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
  85. if (!s->packet_fifo) {
  86. ret = AVERROR(ENOMEM);
  87. goto fail;
  88. }
  89. return 0;
  90. fail:
  91. qsv_decode_close(avctx);
  92. return ret;
  93. }
  94. static int qsv_decode_frame(AVCodecContext *avctx, void *data,
  95. int *got_frame, AVPacket *avpkt)
  96. {
  97. QSVH2645Context *s = avctx->priv_data;
  98. AVFrame *frame = data;
  99. int ret;
  100. /* buffer the input packet */
  101. if (avpkt->size) {
  102. AVPacket input_ref = { 0 };
  103. if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
  104. ret = av_fifo_realloc2(s->packet_fifo,
  105. av_fifo_size(s->packet_fifo) + sizeof(input_ref));
  106. if (ret < 0)
  107. return ret;
  108. }
  109. ret = av_packet_ref(&input_ref, avpkt);
  110. if (ret < 0)
  111. return ret;
  112. av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
  113. }
  114. /* process buffered data */
  115. while (!*got_frame) {
  116. /* prepare the input data */
  117. if (s->buffer_pkt.size <= 0) {
  118. /* no more data */
  119. if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
  120. return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
  121. av_packet_unref(&s->buffer_pkt);
  122. av_fifo_generic_read(s->packet_fifo, &s->buffer_pkt, sizeof(s->buffer_pkt), NULL);
  123. }
  124. ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->buffer_pkt);
  125. if (ret < 0)
  126. return ret;
  127. s->buffer_pkt.size -= ret;
  128. s->buffer_pkt.data += ret;
  129. }
  130. return avpkt->size;
  131. }
  132. static void qsv_decode_flush(AVCodecContext *avctx)
  133. {
  134. QSVH2645Context *s = avctx->priv_data;
  135. qsv_clear_buffers(s);
  136. ff_qsv_decode_flush(avctx, &s->qsv);
  137. }
  138. #define OFFSET(x) offsetof(QSVH2645Context, x)
  139. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  140. #if CONFIG_HEVC_QSV_HWACCEL
  141. AVHWAccel ff_hevc_qsv_hwaccel = {
  142. .name = "hevc_qsv",
  143. .type = AVMEDIA_TYPE_VIDEO,
  144. .id = AV_CODEC_ID_HEVC,
  145. .pix_fmt = AV_PIX_FMT_QSV,
  146. };
  147. #endif
  148. #if CONFIG_HEVC_QSV_DECODER
  149. static const AVOption hevc_options[] = {
  150. { "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 },
  151. { "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_HW, VD, "load_plugin" },
  152. { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" },
  153. { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" },
  154. { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" },
  155. { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
  156. OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD },
  157. { NULL },
  158. };
  159. static const AVClass hevc_class = {
  160. .class_name = "hevc_qsv",
  161. .item_name = av_default_item_name,
  162. .option = hevc_options,
  163. .version = LIBAVUTIL_VERSION_INT,
  164. };
  165. AVCodec ff_hevc_qsv_decoder = {
  166. .name = "hevc_qsv",
  167. .long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"),
  168. .priv_data_size = sizeof(QSVH2645Context),
  169. .type = AVMEDIA_TYPE_VIDEO,
  170. .id = AV_CODEC_ID_HEVC,
  171. .init = qsv_decode_init,
  172. .decode = qsv_decode_frame,
  173. .flush = qsv_decode_flush,
  174. .close = qsv_decode_close,
  175. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  176. .priv_class = &hevc_class,
  177. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  178. AV_PIX_FMT_P010,
  179. AV_PIX_FMT_QSV,
  180. AV_PIX_FMT_NONE },
  181. .bsfs = "hevc_mp4toannexb",
  182. };
  183. #endif
  184. #if CONFIG_H264_QSV_HWACCEL
  185. AVHWAccel ff_h264_qsv_hwaccel = {
  186. .name = "h264_qsv",
  187. .type = AVMEDIA_TYPE_VIDEO,
  188. .id = AV_CODEC_ID_H264,
  189. .pix_fmt = AV_PIX_FMT_QSV,
  190. };
  191. #endif
  192. #if CONFIG_H264_QSV_DECODER
  193. static const AVOption options[] = {
  194. { "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 },
  195. { NULL },
  196. };
  197. static const AVClass class = {
  198. .class_name = "h264_qsv",
  199. .item_name = av_default_item_name,
  200. .option = options,
  201. .version = LIBAVUTIL_VERSION_INT,
  202. };
  203. AVCodec ff_h264_qsv_decoder = {
  204. .name = "h264_qsv",
  205. .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"),
  206. .priv_data_size = sizeof(QSVH2645Context),
  207. .type = AVMEDIA_TYPE_VIDEO,
  208. .id = AV_CODEC_ID_H264,
  209. .init = qsv_decode_init,
  210. .decode = qsv_decode_frame,
  211. .flush = qsv_decode_flush,
  212. .close = qsv_decode_close,
  213. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  214. .priv_class = &class,
  215. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  216. AV_PIX_FMT_P010,
  217. AV_PIX_FMT_QSV,
  218. AV_PIX_FMT_NONE },
  219. .bsfs = "h264_mp4toannexb",
  220. };
  221. #endif