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.

260 lines
8.4KB

  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. #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 * const uid_hevcdec_sw = "15dd936825ad475ea34e35f3f54217a6";
  69. static const char * const 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. #if defined(_WIN32)
  139. #define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_SW
  140. #else
  141. #define LOAD_PLUGIN_DEFAULT LOAD_PLUGIN_HEVC_HW
  142. #endif
  143. #define OFFSET(x) offsetof(QSVH2645Context, x)
  144. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  145. #if CONFIG_HEVC_QSV_DECODER
  146. static const AVOption hevc_options[] = {
  147. { "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 },
  148. { "load_plugin", "A user plugin to load in an internal session", OFFSET(load_plugin), AV_OPT_TYPE_INT, { .i64 = LOAD_PLUGIN_DEFAULT }, LOAD_PLUGIN_NONE, LOAD_PLUGIN_HEVC_HW, VD, "load_plugin" },
  149. { "none", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_NONE }, 0, 0, VD, "load_plugin" },
  150. { "hevc_sw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_SW }, 0, 0, VD, "load_plugin" },
  151. { "hevc_hw", NULL, 0, AV_OPT_TYPE_CONST, { .i64 = LOAD_PLUGIN_HEVC_HW }, 0, 0, VD, "load_plugin" },
  152. { "load_plugins", "A :-separate list of hexadecimal plugin UIDs to load in an internal session",
  153. OFFSET(qsv.load_plugins), AV_OPT_TYPE_STRING, { .str = "" }, 0, 0, VD },
  154. { NULL },
  155. };
  156. static const AVClass hevc_class = {
  157. .class_name = "hevc_qsv",
  158. .item_name = av_default_item_name,
  159. .option = hevc_options,
  160. .version = LIBAVUTIL_VERSION_INT,
  161. };
  162. AVCodec ff_hevc_qsv_decoder = {
  163. .name = "hevc_qsv",
  164. .long_name = NULL_IF_CONFIG_SMALL("HEVC (Intel Quick Sync Video acceleration)"),
  165. .priv_data_size = sizeof(QSVH2645Context),
  166. .type = AVMEDIA_TYPE_VIDEO,
  167. .id = AV_CODEC_ID_HEVC,
  168. .init = qsv_decode_init,
  169. .decode = qsv_decode_frame,
  170. .flush = qsv_decode_flush,
  171. .close = qsv_decode_close,
  172. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID,
  173. .priv_class = &hevc_class,
  174. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  175. AV_PIX_FMT_P010,
  176. AV_PIX_FMT_QSV,
  177. AV_PIX_FMT_NONE },
  178. .hw_configs = ff_qsv_hw_configs,
  179. .bsfs = "hevc_mp4toannexb",
  180. .wrapper_name = "qsv",
  181. };
  182. #endif
  183. #if CONFIG_H264_QSV_DECODER
  184. static const AVOption options[] = {
  185. { "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 },
  186. { NULL },
  187. };
  188. static const AVClass class = {
  189. .class_name = "h264_qsv",
  190. .item_name = av_default_item_name,
  191. .option = options,
  192. .version = LIBAVUTIL_VERSION_INT,
  193. };
  194. AVCodec ff_h264_qsv_decoder = {
  195. .name = "h264_qsv",
  196. .long_name = NULL_IF_CONFIG_SMALL("H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10 (Intel Quick Sync Video acceleration)"),
  197. .priv_data_size = sizeof(QSVH2645Context),
  198. .type = AVMEDIA_TYPE_VIDEO,
  199. .id = AV_CODEC_ID_H264,
  200. .init = qsv_decode_init,
  201. .decode = qsv_decode_frame,
  202. .flush = qsv_decode_flush,
  203. .close = qsv_decode_close,
  204. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HYBRID,
  205. .priv_class = &class,
  206. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  207. AV_PIX_FMT_P010,
  208. AV_PIX_FMT_QSV,
  209. AV_PIX_FMT_NONE },
  210. .hw_configs = ff_qsv_hw_configs,
  211. .bsfs = "h264_mp4toannexb",
  212. .wrapper_name = "qsv",
  213. };
  214. #endif