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.

180 lines
5.1KB

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