ffmpeg_qsv.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. /*
  2. * This file is part of FFmpeg.
  3. *
  4. * FFmpeg is free software; you can redistribute it and/or
  5. * modify it under the terms of the GNU Lesser General Public
  6. * License as published by the Free Software Foundation; either
  7. * version 2.1 of the License, or (at your option) any later version.
  8. *
  9. * FFmpeg is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. * Lesser General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU Lesser General Public
  15. * License along with FFmpeg; if not, write to the Free Software
  16. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. */
  18. #include <mfx/mfxvideo.h>
  19. #include <stdlib.h>
  20. #include "libavutil/dict.h"
  21. #include "libavutil/mem.h"
  22. #include "libavutil/opt.h"
  23. #include "libavcodec/qsv.h"
  24. #include "ffmpeg.h"
  25. typedef struct QSVContext {
  26. OutputStream *ost;
  27. mfxSession session;
  28. mfxExtOpaqueSurfaceAlloc opaque_alloc;
  29. AVBufferRef *opaque_surfaces_buf;
  30. uint8_t *surface_used;
  31. mfxFrameSurface1 **surface_ptrs;
  32. int nb_surfaces;
  33. mfxExtBuffer *ext_buffers[1];
  34. } QSVContext;
  35. static void buffer_release(void *opaque, uint8_t *data)
  36. {
  37. *(uint8_t*)opaque = 0;
  38. }
  39. static int qsv_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
  40. {
  41. InputStream *ist = s->opaque;
  42. QSVContext *qsv = ist->hwaccel_ctx;
  43. int i;
  44. for (i = 0; i < qsv->nb_surfaces; i++) {
  45. if (qsv->surface_used[i])
  46. continue;
  47. frame->buf[0] = av_buffer_create((uint8_t*)qsv->surface_ptrs[i], sizeof(*qsv->surface_ptrs[i]),
  48. buffer_release, &qsv->surface_used[i], 0);
  49. if (!frame->buf[0])
  50. return AVERROR(ENOMEM);
  51. frame->data[3] = (uint8_t*)qsv->surface_ptrs[i];
  52. qsv->surface_used[i] = 1;
  53. return 0;
  54. }
  55. return AVERROR(ENOMEM);
  56. }
  57. static int init_opaque_surf(QSVContext *qsv)
  58. {
  59. AVQSVContext *hwctx_enc = qsv->ost->enc_ctx->hwaccel_context;
  60. mfxFrameSurface1 *surfaces;
  61. int i;
  62. qsv->nb_surfaces = hwctx_enc->nb_opaque_surfaces;
  63. qsv->opaque_surfaces_buf = av_buffer_ref(hwctx_enc->opaque_surfaces);
  64. qsv->surface_ptrs = av_mallocz_array(qsv->nb_surfaces, sizeof(*qsv->surface_ptrs));
  65. qsv->surface_used = av_mallocz_array(qsv->nb_surfaces, sizeof(*qsv->surface_used));
  66. if (!qsv->opaque_surfaces_buf || !qsv->surface_ptrs || !qsv->surface_used)
  67. return AVERROR(ENOMEM);
  68. surfaces = (mfxFrameSurface1*)qsv->opaque_surfaces_buf->data;
  69. for (i = 0; i < qsv->nb_surfaces; i++)
  70. qsv->surface_ptrs[i] = surfaces + i;
  71. qsv->opaque_alloc.Out.Surfaces = qsv->surface_ptrs;
  72. qsv->opaque_alloc.Out.NumSurface = qsv->nb_surfaces;
  73. qsv->opaque_alloc.Out.Type = hwctx_enc->opaque_alloc_type;
  74. qsv->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
  75. qsv->opaque_alloc.Header.BufferSz = sizeof(qsv->opaque_alloc);
  76. qsv->ext_buffers[0] = (mfxExtBuffer*)&qsv->opaque_alloc;
  77. return 0;
  78. }
  79. static void qsv_uninit(AVCodecContext *s)
  80. {
  81. InputStream *ist = s->opaque;
  82. QSVContext *qsv = ist->hwaccel_ctx;
  83. av_freep(&qsv->ost->enc_ctx->hwaccel_context);
  84. av_freep(&s->hwaccel_context);
  85. av_buffer_unref(&qsv->opaque_surfaces_buf);
  86. av_freep(&qsv->surface_used);
  87. av_freep(&qsv->surface_ptrs);
  88. av_freep(&qsv);
  89. }
  90. int qsv_init(AVCodecContext *s)
  91. {
  92. InputStream *ist = s->opaque;
  93. QSVContext *qsv = ist->hwaccel_ctx;
  94. AVQSVContext *hwctx_dec;
  95. int ret;
  96. if (!qsv) {
  97. av_log(NULL, AV_LOG_ERROR, "QSV transcoding is not initialized. "
  98. "-hwaccel qsv should only be used for one-to-one QSV transcoding "
  99. "with no filters.\n");
  100. return AVERROR_BUG;
  101. }
  102. ret = init_opaque_surf(qsv);
  103. if (ret < 0)
  104. return ret;
  105. hwctx_dec = av_qsv_alloc_context();
  106. if (!hwctx_dec)
  107. return AVERROR(ENOMEM);
  108. hwctx_dec->session = qsv->session;
  109. hwctx_dec->iopattern = MFX_IOPATTERN_OUT_OPAQUE_MEMORY;
  110. hwctx_dec->ext_buffers = qsv->ext_buffers;
  111. hwctx_dec->nb_ext_buffers = FF_ARRAY_ELEMS(qsv->ext_buffers);
  112. av_freep(&s->hwaccel_context);
  113. s->hwaccel_context = hwctx_dec;
  114. ist->hwaccel_get_buffer = qsv_get_buffer;
  115. ist->hwaccel_uninit = qsv_uninit;
  116. return 0;
  117. }
  118. static mfxIMPL choose_implementation(const InputStream *ist)
  119. {
  120. static const struct {
  121. const char *name;
  122. mfxIMPL impl;
  123. } impl_map[] = {
  124. { "auto", MFX_IMPL_AUTO },
  125. { "sw", MFX_IMPL_SOFTWARE },
  126. { "hw", MFX_IMPL_HARDWARE },
  127. { "auto_any", MFX_IMPL_AUTO_ANY },
  128. { "hw_any", MFX_IMPL_HARDWARE_ANY },
  129. { "hw2", MFX_IMPL_HARDWARE2 },
  130. { "hw3", MFX_IMPL_HARDWARE3 },
  131. { "hw4", MFX_IMPL_HARDWARE4 },
  132. };
  133. mfxIMPL impl = MFX_IMPL_AUTO_ANY;
  134. int i;
  135. if (ist->hwaccel_device) {
  136. for (i = 0; i < FF_ARRAY_ELEMS(impl_map); i++)
  137. if (!strcmp(ist->hwaccel_device, impl_map[i].name)) {
  138. impl = impl_map[i].impl;
  139. break;
  140. }
  141. if (i == FF_ARRAY_ELEMS(impl_map))
  142. impl = strtol(ist->hwaccel_device, NULL, 0);
  143. }
  144. return impl;
  145. }
  146. int qsv_transcode_init(OutputStream *ost)
  147. {
  148. InputStream *ist;
  149. const enum AVPixelFormat *pix_fmt;
  150. AVDictionaryEntry *e;
  151. const AVOption *opt;
  152. int flags = 0;
  153. int err, i;
  154. QSVContext *qsv = NULL;
  155. AVQSVContext *hwctx = NULL;
  156. mfxIMPL impl;
  157. mfxVersion ver = { { 3, 1 } };
  158. /* check if the encoder supports QSV */
  159. if (!ost->enc->pix_fmts)
  160. return 0;
  161. for (pix_fmt = ost->enc->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++)
  162. if (*pix_fmt == AV_PIX_FMT_QSV)
  163. break;
  164. if (*pix_fmt == AV_PIX_FMT_NONE)
  165. return 0;
  166. if (strcmp(ost->avfilter, "null") || ost->source_index < 0)
  167. return 0;
  168. /* check if the decoder supports QSV and the output only goes to this stream */
  169. ist = input_streams[ost->source_index];
  170. if (ist->nb_filters || ist->hwaccel_id != HWACCEL_QSV ||
  171. !ist->dec || !ist->dec->pix_fmts)
  172. return 0;
  173. for (pix_fmt = ist->dec->pix_fmts; *pix_fmt != AV_PIX_FMT_NONE; pix_fmt++)
  174. if (*pix_fmt == AV_PIX_FMT_QSV)
  175. break;
  176. if (*pix_fmt == AV_PIX_FMT_NONE)
  177. return 0;
  178. for (i = 0; i < nb_output_streams; i++)
  179. if (output_streams[i] != ost &&
  180. output_streams[i]->source_index == ost->source_index)
  181. return 0;
  182. av_log(NULL, AV_LOG_VERBOSE, "Setting up QSV transcoding\n");
  183. qsv = av_mallocz(sizeof(*qsv));
  184. hwctx = av_qsv_alloc_context();
  185. if (!qsv || !hwctx)
  186. goto fail;
  187. impl = choose_implementation(ist);
  188. err = MFXInit(impl, &ver, &qsv->session);
  189. if (err != MFX_ERR_NONE) {
  190. av_log(NULL, AV_LOG_ERROR, "Error initializing an MFX session: %d\n", err);
  191. goto fail;
  192. }
  193. e = av_dict_get(ost->encoder_opts, "flags", NULL, 0);
  194. opt = av_opt_find(ost->enc_ctx, "flags", NULL, 0, 0);
  195. if (e && opt)
  196. av_opt_eval_flags(ost->enc_ctx, opt, e->value, &flags);
  197. qsv->ost = ost;
  198. hwctx->session = qsv->session;
  199. hwctx->iopattern = MFX_IOPATTERN_IN_OPAQUE_MEMORY;
  200. hwctx->opaque_alloc = 1;
  201. hwctx->nb_opaque_surfaces = 16;
  202. ost->hwaccel_ctx = qsv;
  203. ost->enc_ctx->hwaccel_context = hwctx;
  204. ost->enc_ctx->pix_fmt = AV_PIX_FMT_QSV;
  205. ist->hwaccel_ctx = qsv;
  206. ist->dec_ctx->pix_fmt = AV_PIX_FMT_QSV;
  207. ist->resample_pix_fmt = AV_PIX_FMT_QSV;
  208. return 0;
  209. fail:
  210. av_freep(&hwctx);
  211. av_freep(&qsv);
  212. return AVERROR_UNKNOWN;
  213. }