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.

249 lines
7.5KB

  1. /*
  2. * Intel MediaSDK QSV based MPEG-2, VC-1 and VP8 decoders
  3. *
  4. * copyright (c) 2015 Anton Khirnov
  5. *
  6. * This file is part of Libav.
  7. *
  8. * Libav is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * Libav is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with Libav; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include <stdint.h>
  23. #include <string.h>
  24. #include <mfx/mfxvideo.h>
  25. #include "libavutil/common.h"
  26. #include "libavutil/fifo.h"
  27. #include "libavutil/opt.h"
  28. #include "avcodec.h"
  29. #include "internal.h"
  30. #include "qsv_internal.h"
  31. #include "qsvdec.h"
  32. #include "qsv.h"
  33. typedef struct QSVOtherContext {
  34. AVClass *class;
  35. QSVContext qsv;
  36. AVFifoBuffer *packet_fifo;
  37. AVPacket input_ref;
  38. } QSVOtherContext;
  39. static void qsv_clear_buffers(QSVOtherContext *s)
  40. {
  41. AVPacket pkt;
  42. while (av_fifo_size(s->packet_fifo) >= sizeof(pkt)) {
  43. av_fifo_generic_read(s->packet_fifo, &pkt, sizeof(pkt), NULL);
  44. av_packet_unref(&pkt);
  45. }
  46. av_packet_unref(&s->input_ref);
  47. }
  48. static av_cold int qsv_decode_close(AVCodecContext *avctx)
  49. {
  50. QSVOtherContext *s = avctx->priv_data;
  51. #if CONFIG_VP8_QSV_DECODER
  52. if (avctx->codec_id == AV_CODEC_ID_VP8)
  53. av_freep(&s->qsv.load_plugins);
  54. #endif
  55. ff_qsv_decode_close(&s->qsv);
  56. qsv_clear_buffers(s);
  57. av_fifo_free(s->packet_fifo);
  58. return 0;
  59. }
  60. static av_cold int qsv_decode_init(AVCodecContext *avctx)
  61. {
  62. QSVOtherContext *s = avctx->priv_data;
  63. int ret;
  64. #if CONFIG_VP8_QSV_DECODER
  65. if (avctx->codec_id == AV_CODEC_ID_VP8) {
  66. static const char *uid_vp8dec_hw = "f622394d8d87452f878c51f2fc9b4131";
  67. av_freep(&s->qsv.load_plugins);
  68. s->qsv.load_plugins = av_strdup(uid_vp8dec_hw);
  69. if (!s->qsv.load_plugins)
  70. return AVERROR(ENOMEM);
  71. }
  72. #endif
  73. s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
  74. if (!s->packet_fifo) {
  75. ret = AVERROR(ENOMEM);
  76. goto fail;
  77. }
  78. return 0;
  79. fail:
  80. qsv_decode_close(avctx);
  81. return ret;
  82. }
  83. static int qsv_decode_frame(AVCodecContext *avctx, void *data,
  84. int *got_frame, AVPacket *avpkt)
  85. {
  86. QSVOtherContext *s = avctx->priv_data;
  87. AVFrame *frame = data;
  88. int ret;
  89. /* buffer the input packet */
  90. if (avpkt->size) {
  91. AVPacket input_ref = { 0 };
  92. if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
  93. ret = av_fifo_realloc2(s->packet_fifo,
  94. av_fifo_size(s->packet_fifo) + sizeof(input_ref));
  95. if (ret < 0)
  96. return ret;
  97. }
  98. ret = av_packet_ref(&input_ref, avpkt);
  99. if (ret < 0)
  100. return ret;
  101. av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
  102. }
  103. /* process buffered data */
  104. while (!*got_frame) {
  105. if (s->input_ref.size <= 0) {
  106. /* no more data */
  107. if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
  108. return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
  109. av_packet_unref(&s->input_ref);
  110. av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL);
  111. }
  112. ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref);
  113. if (ret < 0)
  114. return ret;
  115. s->input_ref.size -= ret;
  116. s->input_ref.data += ret;
  117. }
  118. return avpkt->size;
  119. }
  120. static void qsv_decode_flush(AVCodecContext *avctx)
  121. {
  122. QSVOtherContext *s = avctx->priv_data;
  123. qsv_clear_buffers(s);
  124. ff_qsv_decode_flush(avctx, &s->qsv);
  125. }
  126. #define OFFSET(x) offsetof(QSVOtherContext, x)
  127. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  128. static const AVOption options[] = {
  129. { "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 },
  130. { NULL },
  131. };
  132. #if CONFIG_MPEG2_QSV_DECODER
  133. static const AVClass mpeg2_qsv_class = {
  134. .class_name = "mpeg2_qsv",
  135. .item_name = av_default_item_name,
  136. .option = options,
  137. .version = LIBAVUTIL_VERSION_INT,
  138. };
  139. AVCodec ff_mpeg2_qsv_decoder = {
  140. .name = "mpeg2_qsv",
  141. .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"),
  142. .priv_data_size = sizeof(QSVOtherContext),
  143. .type = AVMEDIA_TYPE_VIDEO,
  144. .id = AV_CODEC_ID_MPEG2VIDEO,
  145. .init = qsv_decode_init,
  146. .decode = qsv_decode_frame,
  147. .flush = qsv_decode_flush,
  148. .close = qsv_decode_close,
  149. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID,
  150. .priv_class = &mpeg2_qsv_class,
  151. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  152. AV_PIX_FMT_QSV,
  153. AV_PIX_FMT_NONE },
  154. .hw_configs = ff_qsv_hw_configs,
  155. .wrapper_name = "qsv",
  156. };
  157. #endif
  158. #if CONFIG_VC1_QSV_DECODER
  159. static const AVClass vc1_qsv_class = {
  160. .class_name = "vc1_qsv",
  161. .item_name = av_default_item_name,
  162. .option = options,
  163. .version = LIBAVUTIL_VERSION_INT,
  164. };
  165. AVCodec ff_vc1_qsv_decoder = {
  166. .name = "vc1_qsv",
  167. .long_name = NULL_IF_CONFIG_SMALL("VC-1 video (Intel Quick Sync Video acceleration)"),
  168. .priv_data_size = sizeof(QSVOtherContext),
  169. .type = AVMEDIA_TYPE_VIDEO,
  170. .id = AV_CODEC_ID_VC1,
  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 | AV_CODEC_CAP_HYBRID,
  176. .priv_class = &vc1_qsv_class,
  177. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  178. AV_PIX_FMT_QSV,
  179. AV_PIX_FMT_NONE },
  180. .hw_configs = ff_qsv_hw_configs,
  181. .wrapper_name = "qsv",
  182. };
  183. #endif
  184. #if CONFIG_VP8_QSV_DECODER
  185. static const AVClass vp8_qsv_class = {
  186. .class_name = "vp8_qsv",
  187. .item_name = av_default_item_name,
  188. .option = options,
  189. .version = LIBAVUTIL_VERSION_INT,
  190. };
  191. AVCodec ff_vp8_qsv_decoder = {
  192. .name = "vp8_qsv",
  193. .long_name = NULL_IF_CONFIG_SMALL("VP8 video (Intel Quick Sync Video acceleration)"),
  194. .priv_data_size = sizeof(QSVOtherContext),
  195. .type = AVMEDIA_TYPE_VIDEO,
  196. .id = AV_CODEC_ID_VP8,
  197. .init = qsv_decode_init,
  198. .decode = qsv_decode_frame,
  199. .flush = qsv_decode_flush,
  200. .close = qsv_decode_close,
  201. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID,
  202. .priv_class = &vp8_qsv_class,
  203. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  204. AV_PIX_FMT_QSV,
  205. AV_PIX_FMT_NONE },
  206. .hw_configs = ff_qsv_hw_configs,
  207. .wrapper_name = "qsv",
  208. };
  209. #endif