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.

254 lines
7.7KB

  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. /* Drop input packet when failed to decode the packet. Otherwise,
  115. the decoder will keep decoding the failure packet. */
  116. av_packet_unref(&s->input_ref);
  117. return ret;
  118. }
  119. s->input_ref.size -= ret;
  120. s->input_ref.data += ret;
  121. }
  122. return avpkt->size;
  123. }
  124. static void qsv_decode_flush(AVCodecContext *avctx)
  125. {
  126. QSVOtherContext *s = avctx->priv_data;
  127. qsv_clear_buffers(s);
  128. ff_qsv_decode_flush(avctx, &s->qsv);
  129. }
  130. #define OFFSET(x) offsetof(QSVOtherContext, x)
  131. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  132. static const AVOption options[] = {
  133. { "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 }, 1, INT_MAX, VD },
  134. { NULL },
  135. };
  136. #if CONFIG_MPEG2_QSV_DECODER
  137. static const AVClass mpeg2_qsv_class = {
  138. .class_name = "mpeg2_qsv",
  139. .item_name = av_default_item_name,
  140. .option = options,
  141. .version = LIBAVUTIL_VERSION_INT,
  142. };
  143. AVCodec ff_mpeg2_qsv_decoder = {
  144. .name = "mpeg2_qsv",
  145. .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"),
  146. .priv_data_size = sizeof(QSVOtherContext),
  147. .type = AVMEDIA_TYPE_VIDEO,
  148. .id = AV_CODEC_ID_MPEG2VIDEO,
  149. .init = qsv_decode_init,
  150. .decode = qsv_decode_frame,
  151. .flush = qsv_decode_flush,
  152. .close = qsv_decode_close,
  153. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID,
  154. .priv_class = &mpeg2_qsv_class,
  155. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  156. AV_PIX_FMT_QSV,
  157. AV_PIX_FMT_NONE },
  158. .hw_configs = ff_qsv_hw_configs,
  159. .wrapper_name = "qsv",
  160. };
  161. #endif
  162. #if CONFIG_VC1_QSV_DECODER
  163. static const AVClass vc1_qsv_class = {
  164. .class_name = "vc1_qsv",
  165. .item_name = av_default_item_name,
  166. .option = options,
  167. .version = LIBAVUTIL_VERSION_INT,
  168. };
  169. AVCodec ff_vc1_qsv_decoder = {
  170. .name = "vc1_qsv",
  171. .long_name = NULL_IF_CONFIG_SMALL("VC-1 video (Intel Quick Sync Video acceleration)"),
  172. .priv_data_size = sizeof(QSVOtherContext),
  173. .type = AVMEDIA_TYPE_VIDEO,
  174. .id = AV_CODEC_ID_VC1,
  175. .init = qsv_decode_init,
  176. .decode = qsv_decode_frame,
  177. .flush = qsv_decode_flush,
  178. .close = qsv_decode_close,
  179. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID,
  180. .priv_class = &vc1_qsv_class,
  181. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  182. AV_PIX_FMT_QSV,
  183. AV_PIX_FMT_NONE },
  184. .hw_configs = ff_qsv_hw_configs,
  185. .wrapper_name = "qsv",
  186. };
  187. #endif
  188. #if CONFIG_VP8_QSV_DECODER
  189. static const AVClass vp8_qsv_class = {
  190. .class_name = "vp8_qsv",
  191. .item_name = av_default_item_name,
  192. .option = options,
  193. .version = LIBAVUTIL_VERSION_INT,
  194. };
  195. AVCodec ff_vp8_qsv_decoder = {
  196. .name = "vp8_qsv",
  197. .long_name = NULL_IF_CONFIG_SMALL("VP8 video (Intel Quick Sync Video acceleration)"),
  198. .priv_data_size = sizeof(QSVOtherContext),
  199. .type = AVMEDIA_TYPE_VIDEO,
  200. .id = AV_CODEC_ID_VP8,
  201. .init = qsv_decode_init,
  202. .decode = qsv_decode_frame,
  203. .flush = qsv_decode_flush,
  204. .close = qsv_decode_close,
  205. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1 | AV_CODEC_CAP_HYBRID,
  206. .priv_class = &vp8_qsv_class,
  207. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  208. AV_PIX_FMT_QSV,
  209. AV_PIX_FMT_NONE },
  210. .hw_configs = ff_qsv_hw_configs,
  211. .wrapper_name = "qsv",
  212. };
  213. #endif