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.

265 lines
7.8KB

  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. ff_qsv_decode_close(&s->qsv);
  52. qsv_clear_buffers(s);
  53. av_fifo_free(s->packet_fifo);
  54. return 0;
  55. }
  56. static av_cold int qsv_decode_init(AVCodecContext *avctx)
  57. {
  58. QSVOtherContext *s = avctx->priv_data;
  59. int ret;
  60. #if CONFIG_VP8_QSV_DECODER
  61. if (avctx->codec_id == AV_CODEC_ID_VP8) {
  62. static const char *uid_vp8dec_hw = "f622394d8d87452f878c51f2fc9b4131";
  63. av_freep(&s->qsv.load_plugins);
  64. s->qsv.load_plugins = av_strdup(uid_vp8dec_hw);
  65. if (!s->qsv.load_plugins)
  66. return AVERROR(ENOMEM);
  67. }
  68. #endif
  69. s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
  70. if (!s->packet_fifo) {
  71. ret = AVERROR(ENOMEM);
  72. goto fail;
  73. }
  74. return 0;
  75. fail:
  76. qsv_decode_close(avctx);
  77. return ret;
  78. }
  79. static int qsv_decode_frame(AVCodecContext *avctx, void *data,
  80. int *got_frame, AVPacket *avpkt)
  81. {
  82. QSVOtherContext *s = avctx->priv_data;
  83. AVFrame *frame = data;
  84. int ret;
  85. /* buffer the input packet */
  86. if (avpkt->size) {
  87. AVPacket input_ref = { 0 };
  88. if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
  89. ret = av_fifo_realloc2(s->packet_fifo,
  90. av_fifo_size(s->packet_fifo) + sizeof(input_ref));
  91. if (ret < 0)
  92. return ret;
  93. }
  94. ret = av_packet_ref(&input_ref, avpkt);
  95. if (ret < 0)
  96. return ret;
  97. av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
  98. }
  99. /* process buffered data */
  100. while (!*got_frame) {
  101. if (s->input_ref.size <= 0) {
  102. /* no more data */
  103. if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
  104. return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
  105. av_packet_unref(&s->input_ref);
  106. av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL);
  107. }
  108. ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref);
  109. if (ret < 0)
  110. return ret;
  111. s->input_ref.size -= ret;
  112. s->input_ref.data += ret;
  113. }
  114. return avpkt->size;
  115. }
  116. static void qsv_decode_flush(AVCodecContext *avctx)
  117. {
  118. QSVOtherContext *s = avctx->priv_data;
  119. qsv_clear_buffers(s);
  120. ff_qsv_decode_flush(avctx, &s->qsv);
  121. }
  122. #define OFFSET(x) offsetof(QSVOtherContext, x)
  123. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  124. static const AVOption options[] = {
  125. { "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 },
  126. { NULL },
  127. };
  128. #if CONFIG_MPEG2_QSV_HWACCEL
  129. AVHWAccel ff_mpeg2_qsv_hwaccel = {
  130. .name = "mpeg2_qsv",
  131. .type = AVMEDIA_TYPE_VIDEO,
  132. .id = AV_CODEC_ID_MPEG2VIDEO,
  133. .pix_fmt = AV_PIX_FMT_QSV,
  134. };
  135. #endif
  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,
  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. };
  159. #endif
  160. #if CONFIG_VC1_QSV_HWACCEL
  161. AVHWAccel ff_vc1_qsv_hwaccel = {
  162. .name = "vc1_qsv",
  163. .type = AVMEDIA_TYPE_VIDEO,
  164. .id = AV_CODEC_ID_VC1,
  165. .pix_fmt = AV_PIX_FMT_QSV,
  166. };
  167. #endif
  168. #if CONFIG_VC1_QSV_DECODER
  169. static const AVClass vc1_qsv_class = {
  170. .class_name = "vc1_qsv",
  171. .item_name = av_default_item_name,
  172. .option = options,
  173. .version = LIBAVUTIL_VERSION_INT,
  174. };
  175. AVCodec ff_vc1_qsv_decoder = {
  176. .name = "vc1_qsv",
  177. .long_name = NULL_IF_CONFIG_SMALL("VC-1 video (Intel Quick Sync Video acceleration)"),
  178. .priv_data_size = sizeof(QSVOtherContext),
  179. .type = AVMEDIA_TYPE_VIDEO,
  180. .id = AV_CODEC_ID_VC1,
  181. .init = qsv_decode_init,
  182. .decode = qsv_decode_frame,
  183. .flush = qsv_decode_flush,
  184. .close = qsv_decode_close,
  185. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  186. .priv_class = &vc1_qsv_class,
  187. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  188. AV_PIX_FMT_QSV,
  189. AV_PIX_FMT_NONE },
  190. };
  191. #endif
  192. #if CONFIG_VP8_QSV_HWACCEL
  193. AVHWAccel ff_vp8_qsv_hwaccel = {
  194. .name = "vp8_qsv",
  195. .type = AVMEDIA_TYPE_VIDEO,
  196. .id = AV_CODEC_ID_VP8,
  197. .pix_fmt = AV_PIX_FMT_QSV,
  198. };
  199. #endif
  200. #if CONFIG_VP8_QSV_DECODER
  201. static const AVClass vp8_qsv_class = {
  202. .class_name = "vp8_qsv",
  203. .item_name = av_default_item_name,
  204. .option = options,
  205. .version = LIBAVUTIL_VERSION_INT,
  206. };
  207. AVCodec ff_vp8_qsv_decoder = {
  208. .name = "vp8_qsv",
  209. .long_name = NULL_IF_CONFIG_SMALL("VP8 video (Intel Quick Sync Video acceleration)"),
  210. .priv_data_size = sizeof(QSVOtherContext),
  211. .type = AVMEDIA_TYPE_VIDEO,
  212. .id = AV_CODEC_ID_VP8,
  213. .init = qsv_decode_init,
  214. .decode = qsv_decode_frame,
  215. .flush = qsv_decode_flush,
  216. .close = qsv_decode_close,
  217. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  218. .priv_class = &vp8_qsv_class,
  219. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  220. AV_PIX_FMT_QSV,
  221. AV_PIX_FMT_NONE },
  222. };
  223. #endif