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.

307 lines
9.2KB

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