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.

289 lines
9.1KB

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