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.

182 lines
5.1KB

  1. /*
  2. * Intel MediaSDK QSV based MPEG2 decoder
  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 QSVMPEG2Context {
  34. AVClass *class;
  35. QSVContext qsv;
  36. AVFifoBuffer *packet_fifo;
  37. AVPacket input_ref;
  38. } QSVMPEG2Context;
  39. static void qsv_clear_buffers(QSVMPEG2Context *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. QSVMPEG2Context *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. QSVMPEG2Context *s = avctx->priv_data;
  59. int ret;
  60. s->packet_fifo = av_fifo_alloc(sizeof(AVPacket));
  61. if (!s->packet_fifo) {
  62. ret = AVERROR(ENOMEM);
  63. goto fail;
  64. }
  65. s->qsv.iopattern = MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
  66. return 0;
  67. fail:
  68. qsv_decode_close(avctx);
  69. return ret;
  70. }
  71. static int qsv_decode_frame(AVCodecContext *avctx, void *data,
  72. int *got_frame, AVPacket *avpkt)
  73. {
  74. QSVMPEG2Context *s = avctx->priv_data;
  75. AVFrame *frame = data;
  76. int ret;
  77. /* buffer the input packet */
  78. if (avpkt->size) {
  79. AVPacket input_ref = { 0 };
  80. if (av_fifo_space(s->packet_fifo) < sizeof(input_ref)) {
  81. ret = av_fifo_realloc2(s->packet_fifo,
  82. av_fifo_size(s->packet_fifo) + sizeof(input_ref));
  83. if (ret < 0)
  84. return ret;
  85. }
  86. ret = av_packet_ref(&input_ref, avpkt);
  87. if (ret < 0)
  88. return ret;
  89. av_fifo_generic_write(s->packet_fifo, &input_ref, sizeof(input_ref), NULL);
  90. }
  91. /* process buffered data */
  92. while (!*got_frame) {
  93. if (s->input_ref.size <= 0) {
  94. /* no more data */
  95. if (av_fifo_size(s->packet_fifo) < sizeof(AVPacket))
  96. return avpkt->size ? avpkt->size : ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, avpkt);
  97. av_packet_unref(&s->input_ref);
  98. av_fifo_generic_read(s->packet_fifo, &s->input_ref, sizeof(s->input_ref), NULL);
  99. }
  100. ret = ff_qsv_process_data(avctx, &s->qsv, frame, got_frame, &s->input_ref);
  101. if (ret < 0)
  102. return ret;
  103. s->input_ref.size -= ret;
  104. s->input_ref.data += ret;
  105. }
  106. return avpkt->size;
  107. }
  108. static void qsv_decode_flush(AVCodecContext *avctx)
  109. {
  110. QSVMPEG2Context *s = avctx->priv_data;
  111. qsv_clear_buffers(s);
  112. ff_qsv_decode_flush(avctx, &s->qsv);
  113. }
  114. AVHWAccel ff_mpeg2_qsv_hwaccel = {
  115. .name = "mpeg2_qsv",
  116. .type = AVMEDIA_TYPE_VIDEO,
  117. .id = AV_CODEC_ID_MPEG2VIDEO,
  118. .pix_fmt = AV_PIX_FMT_QSV,
  119. };
  120. #define OFFSET(x) offsetof(QSVMPEG2Context, x)
  121. #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
  122. static const AVOption options[] = {
  123. { "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 },
  124. { NULL },
  125. };
  126. static const AVClass class = {
  127. .class_name = "mpeg2_qsv",
  128. .item_name = av_default_item_name,
  129. .option = options,
  130. .version = LIBAVUTIL_VERSION_INT,
  131. };
  132. AVCodec ff_mpeg2_qsv_decoder = {
  133. .name = "mpeg2_qsv",
  134. .long_name = NULL_IF_CONFIG_SMALL("MPEG-2 video (Intel Quick Sync Video acceleration)"),
  135. .priv_data_size = sizeof(QSVMPEG2Context),
  136. .type = AVMEDIA_TYPE_VIDEO,
  137. .id = AV_CODEC_ID_MPEG2VIDEO,
  138. .init = qsv_decode_init,
  139. .decode = qsv_decode_frame,
  140. .flush = qsv_decode_flush,
  141. .close = qsv_decode_close,
  142. .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_DR1,
  143. .priv_class = &class,
  144. .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_NV12,
  145. AV_PIX_FMT_QSV,
  146. AV_PIX_FMT_NONE },
  147. };