FFmpeg
hwcontext_qsv.c
Go to the documentation of this file.
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 
19 #include <stdint.h>
20 #include <string.h>
21 
22 #include <mfx/mfxvideo.h>
23 
24 #include "config.h"
25 
26 #if HAVE_PTHREADS
27 #include <pthread.h>
28 #endif
29 
30 #if CONFIG_VAAPI
31 #include "hwcontext_vaapi.h"
32 #endif
33 #if CONFIG_DXVA2
34 #include "hwcontext_dxva2.h"
35 #endif
36 
37 #include "buffer.h"
38 #include "common.h"
39 #include "hwcontext.h"
40 #include "hwcontext_internal.h"
41 #include "hwcontext_qsv.h"
42 #include "mem.h"
43 #include "pixfmt.h"
44 #include "pixdesc.h"
45 #include "time.h"
46 
47 typedef struct QSVDevicePriv {
50 
51 typedef struct QSVDeviceContext {
52  mfxHDL handle;
53  mfxHandleType handle_type;
54  mfxVersion ver;
55  mfxIMPL impl;
56 
57  enum AVHWDeviceType child_device_type;
58  enum AVPixelFormat child_pix_fmt;
60 
61 typedef struct QSVFramesContext {
62  mfxSession session_download;
64  mfxSession session_upload;
66 #if HAVE_PTHREADS
67  pthread_mutex_t session_lock;
68  pthread_cond_t session_cond;
69 #endif
70 
72  mfxFrameSurface1 *surfaces_internal;
74 
75  // used in the frame allocator for non-opaque surfaces
76  mfxMemId *mem_ids;
77  // used in the opaque alloc request for opaque surfaces
78  mfxFrameSurface1 **surface_ptrs;
79 
80  mfxExtOpaqueSurfaceAlloc opaque_alloc;
81  mfxExtBuffer *ext_buffers[1];
83 
84 static const struct {
85  mfxHandleType handle_type;
89 #if CONFIG_VAAPI
90  { MFX_HANDLE_VA_DISPLAY, AV_HWDEVICE_TYPE_VAAPI, AV_PIX_FMT_VAAPI },
91 #endif
92 #if CONFIG_DXVA2
93  { MFX_HANDLE_D3D9_DEVICE_MANAGER, AV_HWDEVICE_TYPE_DXVA2, AV_PIX_FMT_DXVA2_VLD },
94 #endif
95  { 0 },
96 };
97 
98 static const struct {
100  uint32_t fourcc;
102  { AV_PIX_FMT_NV12, MFX_FOURCC_NV12 },
103  { AV_PIX_FMT_BGRA, MFX_FOURCC_RGB4 },
104  { AV_PIX_FMT_P010, MFX_FOURCC_P010 },
105  { AV_PIX_FMT_PAL8, MFX_FOURCC_P8 },
106 };
107 
109 {
110  int i;
111  for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) {
112  if (supported_pixel_formats[i].pix_fmt == pix_fmt)
113  return supported_pixel_formats[i].fourcc;
114  }
115  return 0;
116 }
117 
119 {
120  AVQSVDeviceContext *hwctx = ctx->hwctx;
121  QSVDeviceContext *s = ctx->internal->priv;
122 
123  mfxStatus err;
124  int i;
125 
126  for (i = 0; supported_handle_types[i].handle_type; i++) {
127  err = MFXVideoCORE_GetHandle(hwctx->session, supported_handle_types[i].handle_type,
128  &s->handle);
129  if (err == MFX_ERR_NONE) {
130  s->handle_type = supported_handle_types[i].handle_type;
131  s->child_device_type = supported_handle_types[i].device_type;
132  s->child_pix_fmt = supported_handle_types[i].pix_fmt;
133  break;
134  }
135  }
136  if (!s->handle) {
137  av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
138  "from the session\n");
139  }
140 
141  err = MFXQueryIMPL(hwctx->session, &s->impl);
142  if (err == MFX_ERR_NONE)
143  err = MFXQueryVersion(hwctx->session, &s->ver);
144  if (err != MFX_ERR_NONE) {
145  av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n");
146  return AVERROR_UNKNOWN;
147  }
148 
149  return 0;
150 }
151 
153 {
154  QSVFramesContext *s = ctx->internal->priv;
155 
156  if (s->session_download) {
157  MFXVideoVPP_Close(s->session_download);
158  MFXClose(s->session_download);
159  }
160  s->session_download = NULL;
161  s->session_download_init = 0;
162 
163  if (s->session_upload) {
164  MFXVideoVPP_Close(s->session_upload);
165  MFXClose(s->session_upload);
166  }
167  s->session_upload = NULL;
168  s->session_upload_init = 0;
169 
170 #if HAVE_PTHREADS
171  pthread_mutex_destroy(&s->session_lock);
172  pthread_cond_destroy(&s->session_cond);
173 #endif
174 
175  av_freep(&s->mem_ids);
176  av_freep(&s->surface_ptrs);
179 }
180 
181 static void qsv_pool_release_dummy(void *opaque, uint8_t *data)
182 {
183 }
184 
185 static AVBufferRef *qsv_pool_alloc(void *opaque, int size)
186 {
188  QSVFramesContext *s = ctx->internal->priv;
189  AVQSVFramesContext *hwctx = ctx->hwctx;
190 
191  if (s->nb_surfaces_used < hwctx->nb_surfaces) {
192  s->nb_surfaces_used++;
194  sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0);
195  }
196 
197  return NULL;
198 }
199 
201 {
202  AVQSVFramesContext *hwctx = ctx->hwctx;
203  QSVFramesContext *s = ctx->internal->priv;
204  QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv;
205 
206  AVBufferRef *child_device_ref = NULL;
207  AVBufferRef *child_frames_ref = NULL;
208 
210  AVHWFramesContext *child_frames_ctx;
211 
212  int i, ret = 0;
213 
214  if (!device_priv->handle) {
215  av_log(ctx, AV_LOG_ERROR,
216  "Cannot create a non-opaque internal surface pool without "
217  "a hardware handle\n");
218  return AVERROR(EINVAL);
219  }
220 
221  child_device_ref = av_hwdevice_ctx_alloc(device_priv->child_device_type);
222  if (!child_device_ref)
223  return AVERROR(ENOMEM);
224  child_device_ctx = (AVHWDeviceContext*)child_device_ref->data;
225 
226 #if CONFIG_VAAPI
227  if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
228  AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
229  child_device_hwctx->display = (VADisplay)device_priv->handle;
230  }
231 #endif
232 #if CONFIG_DXVA2
233  if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
234  AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
235  child_device_hwctx->devmgr = (IDirect3DDeviceManager9*)device_priv->handle;
236  }
237 #endif
238 
239  ret = av_hwdevice_ctx_init(child_device_ref);
240  if (ret < 0) {
241  av_log(ctx, AV_LOG_ERROR, "Error initializing a child device context\n");
242  goto fail;
243  }
244 
245  child_frames_ref = av_hwframe_ctx_alloc(child_device_ref);
246  if (!child_frames_ref) {
247  ret = AVERROR(ENOMEM);
248  goto fail;
249  }
250  child_frames_ctx = (AVHWFramesContext*)child_frames_ref->data;
251 
252  child_frames_ctx->format = device_priv->child_pix_fmt;
253  child_frames_ctx->sw_format = ctx->sw_format;
254  child_frames_ctx->initial_pool_size = ctx->initial_pool_size;
255  child_frames_ctx->width = FFALIGN(ctx->width, 16);
256  child_frames_ctx->height = FFALIGN(ctx->height, 16);
257 
258 #if CONFIG_DXVA2
259  if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
260  AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
261  if (hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)
262  child_frames_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget;
263  else
264  child_frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
265  }
266 #endif
267 
268  ret = av_hwframe_ctx_init(child_frames_ref);
269  if (ret < 0) {
270  av_log(ctx, AV_LOG_ERROR, "Error initializing a child frames context\n");
271  goto fail;
272  }
273 
274 #if CONFIG_VAAPI
275  if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
276  AVVAAPIFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
277  for (i = 0; i < ctx->initial_pool_size; i++)
278  s->surfaces_internal[i].Data.MemId = child_frames_hwctx->surface_ids + i;
279  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
280  }
281 #endif
282 #if CONFIG_DXVA2
283  if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
284  AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
285  for (i = 0; i < ctx->initial_pool_size; i++)
286  s->surfaces_internal[i].Data.MemId = (mfxMemId)child_frames_hwctx->surfaces[i];
287  if (child_frames_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
288  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
289  else
290  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
291  }
292 #endif
293 
294  s->child_frames_ref = child_frames_ref;
295  child_frames_ref = NULL;
296 
297 fail:
298  av_buffer_unref(&child_device_ref);
299  av_buffer_unref(&child_frames_ref);
300  return ret;
301 }
302 
303 static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
304 {
305  const AVPixFmtDescriptor *desc;
306  uint32_t fourcc;
307 
308  desc = av_pix_fmt_desc_get(ctx->sw_format);
309  if (!desc)
310  return AVERROR(EINVAL);
311 
312  fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
313  if (!fourcc)
314  return AVERROR(EINVAL);
315 
316  surf->Info.BitDepthLuma = desc->comp[0].depth;
317  surf->Info.BitDepthChroma = desc->comp[0].depth;
318  surf->Info.Shift = desc->comp[0].depth > 8;
319 
320  if (desc->log2_chroma_w && desc->log2_chroma_h)
321  surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
322  else if (desc->log2_chroma_w)
323  surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
324  else
325  surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
326 
327  surf->Info.FourCC = fourcc;
328  surf->Info.Width = FFALIGN(ctx->width, 16);
329  surf->Info.CropW = ctx->width;
330  surf->Info.Height = FFALIGN(ctx->height, 16);
331  surf->Info.CropH = ctx->height;
332  surf->Info.FrameRateExtN = 25;
333  surf->Info.FrameRateExtD = 1;
334  surf->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
335 
336  return 0;
337 }
338 
340 {
341  QSVFramesContext *s = ctx->internal->priv;
342  AVQSVFramesContext *frames_hwctx = ctx->hwctx;
343 
344  int i, ret = 0;
345 
346  if (ctx->initial_pool_size <= 0) {
347  av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n");
348  return AVERROR(EINVAL);
349  }
350 
352  sizeof(*s->surfaces_internal));
353  if (!s->surfaces_internal)
354  return AVERROR(ENOMEM);
355 
356  for (i = 0; i < ctx->initial_pool_size; i++) {
357  ret = qsv_init_surface(ctx, &s->surfaces_internal[i]);
358  if (ret < 0)
359  return ret;
360  }
361 
362  if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
363  ret = qsv_init_child_ctx(ctx);
364  if (ret < 0)
365  return ret;
366  }
367 
368  ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(mfxFrameSurface1),
369  ctx, qsv_pool_alloc, NULL);
370  if (!ctx->internal->pool_internal)
371  return AVERROR(ENOMEM);
372 
373  frames_hwctx->surfaces = s->surfaces_internal;
374  frames_hwctx->nb_surfaces = ctx->initial_pool_size;
375 
376  return 0;
377 }
378 
379 static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
380  mfxFrameAllocResponse *resp)
381 {
382  AVHWFramesContext *ctx = pthis;
383  QSVFramesContext *s = ctx->internal->priv;
384  AVQSVFramesContext *hwctx = ctx->hwctx;
385  mfxFrameInfo *i = &req->Info;
386  mfxFrameInfo *i1 = &hwctx->surfaces[0].Info;
387 
388  if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
389  !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
390  !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
391  return MFX_ERR_UNSUPPORTED;
392  if (i->Width > i1->Width || i->Height > i1->Height ||
393  i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
394  av_log(ctx, AV_LOG_ERROR, "Mismatching surface properties in an "
395  "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
396  i->Width, i->Height, i->FourCC, i->ChromaFormat,
397  i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
398  return MFX_ERR_UNSUPPORTED;
399  }
400 
401  resp->mids = s->mem_ids;
402  resp->NumFrameActual = hwctx->nb_surfaces;
403 
404  return MFX_ERR_NONE;
405 }
406 
407 static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
408 {
409  return MFX_ERR_NONE;
410 }
411 
412 static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
413 {
414  return MFX_ERR_UNSUPPORTED;
415 }
416 
417 static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
418 {
419  return MFX_ERR_UNSUPPORTED;
420 }
421 
422 static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
423 {
424  *hdl = mid;
425  return MFX_ERR_NONE;
426 }
427 
429  mfxSession *session, int upload)
430 {
431  QSVFramesContext *s = ctx->internal->priv;
432  AVQSVFramesContext *frames_hwctx = ctx->hwctx;
433  QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv;
434  int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
435 
436  mfxFrameAllocator frame_allocator = {
437  .pthis = ctx,
438  .Alloc = frame_alloc,
439  .Lock = frame_lock,
440  .Unlock = frame_unlock,
441  .GetHDL = frame_get_hdl,
442  .Free = frame_free,
443  };
444 
445  mfxVideoParam par;
446  mfxStatus err;
447 
448  err = MFXInit(device_priv->impl, &device_priv->ver, session);
449  if (err != MFX_ERR_NONE) {
450  av_log(ctx, AV_LOG_ERROR, "Error initializing an internal session\n");
451  return AVERROR_UNKNOWN;
452  }
453 
454  if (device_priv->handle) {
455  err = MFXVideoCORE_SetHandle(*session, device_priv->handle_type,
456  device_priv->handle);
457  if (err != MFX_ERR_NONE)
458  return AVERROR_UNKNOWN;
459  }
460 
461  if (!opaque) {
462  err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator);
463  if (err != MFX_ERR_NONE)
464  return AVERROR_UNKNOWN;
465  }
466 
467  memset(&par, 0, sizeof(par));
468 
469  if (opaque) {
470  par.ExtParam = s->ext_buffers;
471  par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers);
472  par.IOPattern = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY :
473  MFX_IOPATTERN_IN_OPAQUE_MEMORY;
474  } else {
475  par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY :
476  MFX_IOPATTERN_IN_VIDEO_MEMORY;
477  }
478 
479  par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY :
480  MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
481  par.AsyncDepth = 1;
482 
483  par.vpp.In = frames_hwctx->surfaces[0].Info;
484 
485  /* Apparently VPP requires the frame rate to be set to some value, otherwise
486  * init will fail (probably for the framerate conversion filter). Since we
487  * are only doing data upload/download here, we just invent an arbitrary
488  * value */
489  par.vpp.In.FrameRateExtN = 25;
490  par.vpp.In.FrameRateExtD = 1;
491  par.vpp.Out = par.vpp.In;
492 
493  err = MFXVideoVPP_Init(*session, &par);
494  if (err != MFX_ERR_NONE) {
495  av_log(ctx, AV_LOG_VERBOSE, "Error opening the internal VPP session."
496  "Surface upload/download will not be possible\n");
497  MFXClose(*session);
498  *session = NULL;
499  }
500 
501  return 0;
502 }
503 
505 {
506  QSVFramesContext *s = ctx->internal->priv;
507  AVQSVFramesContext *frames_hwctx = ctx->hwctx;
508 
509  int opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
510 
511  uint32_t fourcc;
512  int i, ret;
513 
514  fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
515  if (!fourcc) {
516  av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n");
517  return AVERROR(ENOSYS);
518  }
519 
520  if (!ctx->pool) {
521  ret = qsv_init_pool(ctx, fourcc);
522  if (ret < 0) {
523  av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n");
524  return ret;
525  }
526  }
527 
528  if (opaque) {
529  s->surface_ptrs = av_mallocz_array(frames_hwctx->nb_surfaces,
530  sizeof(*s->surface_ptrs));
531  if (!s->surface_ptrs)
532  return AVERROR(ENOMEM);
533 
534  for (i = 0; i < frames_hwctx->nb_surfaces; i++)
535  s->surface_ptrs[i] = frames_hwctx->surfaces + i;
536 
537  s->opaque_alloc.In.Surfaces = s->surface_ptrs;
538  s->opaque_alloc.In.NumSurface = frames_hwctx->nb_surfaces;
539  s->opaque_alloc.In.Type = frames_hwctx->frame_type;
540 
541  s->opaque_alloc.Out = s->opaque_alloc.In;
542 
543  s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
544  s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
545 
546  s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc;
547  } else {
548  s->mem_ids = av_mallocz_array(frames_hwctx->nb_surfaces, sizeof(*s->mem_ids));
549  if (!s->mem_ids)
550  return AVERROR(ENOMEM);
551 
552  for (i = 0; i < frames_hwctx->nb_surfaces; i++)
553  s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
554  }
555 
556  s->session_download = NULL;
557  s->session_upload = NULL;
558 
559  s->session_download_init = 0;
560  s->session_upload_init = 0;
561 
562 #if HAVE_PTHREADS
563  pthread_mutex_init(&s->session_lock, NULL);
564  pthread_cond_init(&s->session_cond, NULL);
565 #endif
566 
567  return 0;
568 }
569 
571 {
572  frame->buf[0] = av_buffer_pool_get(ctx->pool);
573  if (!frame->buf[0])
574  return AVERROR(ENOMEM);
575 
576  frame->data[3] = frame->buf[0]->data;
577  frame->format = AV_PIX_FMT_QSV;
578  frame->width = ctx->width;
579  frame->height = ctx->height;
580 
581  return 0;
582 }
583 
586  enum AVPixelFormat **formats)
587 {
588  enum AVPixelFormat *fmts;
589 
590  fmts = av_malloc_array(2, sizeof(*fmts));
591  if (!fmts)
592  return AVERROR(ENOMEM);
593 
594  fmts[0] = ctx->sw_format;
595  fmts[1] = AV_PIX_FMT_NONE;
596 
597  *formats = fmts;
598 
599  return 0;
600 }
601 
603  AVHWFramesContext *src_ctx, int flags)
604 {
605  AVQSVFramesContext *src_hwctx = src_ctx->hwctx;
606  int i;
607 
608  switch (dst_ctx->device_ctx->type) {
609 #if CONFIG_VAAPI
611  {
612  AVVAAPIFramesContext *dst_hwctx = dst_ctx->hwctx;
613  dst_hwctx->surface_ids = av_mallocz_array(src_hwctx->nb_surfaces,
614  sizeof(*dst_hwctx->surface_ids));
615  if (!dst_hwctx->surface_ids)
616  return AVERROR(ENOMEM);
617  for (i = 0; i < src_hwctx->nb_surfaces; i++)
618  dst_hwctx->surface_ids[i] =
619  *(VASurfaceID*)src_hwctx->surfaces[i].Data.MemId;
620  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
621  }
622  break;
623 #endif
624 #if CONFIG_DXVA2
626  {
627  AVDXVA2FramesContext *dst_hwctx = dst_ctx->hwctx;
628  dst_hwctx->surfaces = av_mallocz_array(src_hwctx->nb_surfaces,
629  sizeof(*dst_hwctx->surfaces));
630  if (!dst_hwctx->surfaces)
631  return AVERROR(ENOMEM);
632  for (i = 0; i < src_hwctx->nb_surfaces; i++)
633  dst_hwctx->surfaces[i] =
634  (IDirect3DSurface9*)src_hwctx->surfaces[i].Data.MemId;
635  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
636  if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
637  dst_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
638  else
639  dst_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget;
640  }
641  break;
642 #endif
643  default:
644  return AVERROR(ENOSYS);
645  }
646 
647  return 0;
648 }
649 
651  AVFrame *dst, const AVFrame *src, int flags)
652 {
653  QSVFramesContext *s = ctx->internal->priv;
654  mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3];
655  AVHWFramesContext *child_frames_ctx;
656  const AVPixFmtDescriptor *desc;
657  uint8_t *child_data;
658  AVFrame *dummy;
659  int ret = 0;
660 
661  if (!s->child_frames_ref)
662  return AVERROR(ENOSYS);
663  child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
664 
665  switch (child_frames_ctx->device_ctx->type) {
666 #if CONFIG_VAAPI
668  child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)surf->Data.MemId;
669  break;
670 #endif
671 #if CONFIG_DXVA2
673  child_data = surf->Data.MemId;
674  break;
675 #endif
676  default:
677  return AVERROR(ENOSYS);
678  }
679 
680  if (dst->format == child_frames_ctx->format) {
682  dst, src, NULL, NULL);
683  if (ret < 0)
684  return ret;
685 
686  dst->width = src->width;
687  dst->height = src->height;
688  dst->data[3] = child_data;
689 
690  return 0;
691  }
692 
694  if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
695  // This only supports mapping to software.
696  return AVERROR(ENOSYS);
697  }
698 
699  dummy = av_frame_alloc();
700  if (!dummy)
701  return AVERROR(ENOMEM);
702 
703  dummy->buf[0] = av_buffer_ref(src->buf[0]);
704  dummy->hw_frames_ctx = av_buffer_ref(s->child_frames_ref);
705  if (!dummy->buf[0] || !dummy->hw_frames_ctx)
706  goto fail;
707 
708  dummy->format = child_frames_ctx->format;
709  dummy->width = src->width;
710  dummy->height = src->height;
711  dummy->data[3] = child_data;
712 
713  ret = av_hwframe_map(dst, dummy, flags);
714 
715 fail:
717 
718  return ret;
719 }
720 
722  const AVFrame *src)
723 {
724  QSVFramesContext *s = ctx->internal->priv;
725  AVHWFramesContext *child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
726  int download = !!src->hw_frames_ctx;
727  mfxFrameSurface1 *surf = (mfxFrameSurface1*)(download ? src->data[3] : dst->data[3]);
728 
729  AVFrame *dummy;
730  int ret;
731 
732  dummy = av_frame_alloc();
733  if (!dummy)
734  return AVERROR(ENOMEM);
735 
736  dummy->format = child_frames_ctx->format;
737  dummy->width = src->width;
738  dummy->height = src->height;
739  dummy->buf[0] = download ? src->buf[0] : dst->buf[0];
740  dummy->data[3] = surf->Data.MemId;
741  dummy->hw_frames_ctx = s->child_frames_ref;
742 
743  ret = download ? av_hwframe_transfer_data(dst, dummy, 0) :
744  av_hwframe_transfer_data(dummy, src, 0);
745 
746  dummy->buf[0] = NULL;
747  dummy->data[3] = NULL;
748  dummy->hw_frames_ctx = NULL;
749 
750  av_frame_free(&dummy);
751 
752  return ret;
753 }
754 
755 static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
756 {
757  switch (frame->format) {
758  case AV_PIX_FMT_NV12:
759  case AV_PIX_FMT_P010:
760  surface->Data.Y = frame->data[0];
761  surface->Data.UV = frame->data[1];
762  break;
763 
764  case AV_PIX_FMT_YUV420P:
765  surface->Data.Y = frame->data[0];
766  surface->Data.U = frame->data[1];
767  surface->Data.V = frame->data[2];
768  break;
769 
770  case AV_PIX_FMT_BGRA:
771  surface->Data.B = frame->data[0];
772  surface->Data.G = frame->data[0] + 1;
773  surface->Data.R = frame->data[0] + 2;
774  surface->Data.A = frame->data[0] + 3;
775  break;
776 
777  default:
778  return MFX_ERR_UNSUPPORTED;
779  }
780  surface->Data.Pitch = frame->linesize[0];
781  surface->Data.TimeStamp = frame->pts;
782 
783  return 0;
784 }
785 
787  const AVFrame *src)
788 {
789  QSVFramesContext *s = ctx->internal->priv;
790  mfxFrameSurface1 out = {{ 0 }};
791  mfxFrameSurface1 *in = (mfxFrameSurface1*)src->data[3];
792 
793  mfxSyncPoint sync = NULL;
794  mfxStatus err;
795  int ret = 0;
796 
797  while (!s->session_download_init && !s->session_download && !ret) {
798 #if HAVE_PTHREADS
799  if (pthread_mutex_trylock(&s->session_lock) == 0) {
800 #endif
801  if (!s->session_download_init) {
803  if (s->session_download)
804  s->session_download_init = 1;
805  }
806 #if HAVE_PTHREADS
807  pthread_mutex_unlock(&s->session_lock);
808  pthread_cond_signal(&s->session_cond);
809  } else {
810  pthread_mutex_lock(&s->session_lock);
811  while (!s->session_download_init && !s->session_download) {
812  pthread_cond_wait(&s->session_cond, &s->session_lock);
813  }
814  pthread_mutex_unlock(&s->session_lock);
815  }
816 #endif
817  }
818 
819  if (ret < 0)
820  return ret;
821 
822  if (!s->session_download) {
823  if (s->child_frames_ref)
824  return qsv_transfer_data_child(ctx, dst, src);
825 
826  av_log(ctx, AV_LOG_ERROR, "Surface download not possible\n");
827  return AVERROR(ENOSYS);
828  }
829 
830  out.Info = in->Info;
831  map_frame_to_surface(dst, &out);
832 
833  do {
834  err = MFXVideoVPP_RunFrameVPPAsync(s->session_download, in, &out, NULL, &sync);
835  if (err == MFX_WRN_DEVICE_BUSY)
836  av_usleep(1);
837  } while (err == MFX_WRN_DEVICE_BUSY);
838 
839  if (err < 0 || !sync) {
840  av_log(ctx, AV_LOG_ERROR, "Error downloading the surface\n");
841  return AVERROR_UNKNOWN;
842  }
843 
844  do {
845  err = MFXVideoCORE_SyncOperation(s->session_download, sync, 1000);
846  } while (err == MFX_WRN_IN_EXECUTION);
847  if (err < 0) {
848  av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err);
849  return AVERROR_UNKNOWN;
850  }
851 
852  return 0;
853 }
854 
856  const AVFrame *src)
857 {
858  QSVFramesContext *s = ctx->internal->priv;
859  mfxFrameSurface1 in = {{ 0 }};
860  mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3];
861 
862  mfxSyncPoint sync = NULL;
863  mfxStatus err;
864  int ret = 0;
865  /* make a copy if the input is not padded as libmfx requires */
866  AVFrame tmp_frame;
867  const AVFrame *src_frame;
868  int realigned = 0;
869 
870 
871  while (!s->session_upload_init && !s->session_upload && !ret) {
872 #if HAVE_PTHREADS
873  if (pthread_mutex_trylock(&s->session_lock) == 0) {
874 #endif
875  if (!s->session_upload_init) {
877  if (s->session_upload)
878  s->session_upload_init = 1;
879  }
880 #if HAVE_PTHREADS
881  pthread_mutex_unlock(&s->session_lock);
882  pthread_cond_signal(&s->session_cond);
883  } else {
884  pthread_mutex_lock(&s->session_lock);
885  while (!s->session_upload_init && !s->session_upload) {
886  pthread_cond_wait(&s->session_cond, &s->session_lock);
887  }
888  pthread_mutex_unlock(&s->session_lock);
889  }
890 #endif
891  }
892  if (ret < 0)
893  return ret;
894 
895  if (src->height & 15 || src->linesize[0] & 15) {
896  realigned = 1;
897  memset(&tmp_frame, 0, sizeof(tmp_frame));
898  tmp_frame.format = src->format;
899  tmp_frame.width = FFALIGN(src->width, 16);
900  tmp_frame.height = FFALIGN(src->height, 16);
901  ret = av_frame_get_buffer(&tmp_frame, 32);
902  if (ret < 0)
903  return ret;
904 
905  ret = av_frame_copy(&tmp_frame, src);
906  if (ret < 0) {
907  av_frame_unref(&tmp_frame);
908  return ret;
909  }
910  }
911 
912  src_frame = realigned ? &tmp_frame : src;
913 
914  if (!s->session_upload) {
915  if (s->child_frames_ref)
916  return qsv_transfer_data_child(ctx, dst, src_frame);
917 
918  av_log(ctx, AV_LOG_ERROR, "Surface upload not possible\n");
919  return AVERROR(ENOSYS);
920  }
921 
922  in.Info = out->Info;
923  map_frame_to_surface(src_frame, &in);
924 
925  do {
926  err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, &in, out, NULL, &sync);
927  if (err == MFX_WRN_DEVICE_BUSY)
928  av_usleep(1);
929  } while (err == MFX_WRN_DEVICE_BUSY);
930 
931  if (err < 0 || !sync) {
932  av_log(ctx, AV_LOG_ERROR, "Error uploading the surface\n");
933  return AVERROR_UNKNOWN;
934  }
935 
936  do {
937  err = MFXVideoCORE_SyncOperation(s->session_upload, sync, 1000);
938  } while (err == MFX_WRN_IN_EXECUTION);
939  if (err < 0) {
940  av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation\n");
941  return AVERROR_UNKNOWN;
942  }
943 
944  if (realigned)
945  av_frame_unref(&tmp_frame);
946 
947  return 0;
948 }
949 
951  AVHWFramesContext *src_ctx, int flags)
952 {
953  QSVFramesContext *s = dst_ctx->internal->priv;
954  AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
955  int i;
956 
957  switch (src_ctx->device_ctx->type) {
958 #if CONFIG_VAAPI
960  {
961  AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx;
963  sizeof(*s->surfaces_internal));
964  if (!s->surfaces_internal)
965  return AVERROR(ENOMEM);
966  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
967  qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
968  s->surfaces_internal[i].Data.MemId = src_hwctx->surface_ids + i;
969  }
970  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
971  dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
972  }
973  break;
974 #endif
975 #if CONFIG_DXVA2
977  {
978  AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx;
980  sizeof(*s->surfaces_internal));
981  if (!s->surfaces_internal)
982  return AVERROR(ENOMEM);
983  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
984  qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
985  s->surfaces_internal[i].Data.MemId = (mfxMemId)src_hwctx->surfaces[i];
986  }
987  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
988  if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
989  dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
990  else
991  dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
992  }
993  break;
994 #endif
995  default:
996  return AVERROR(ENOSYS);
997  }
998 
999  dst_hwctx->surfaces = s->surfaces_internal;
1000 
1001  return 0;
1002 }
1003 
1004 static int qsv_map_to(AVHWFramesContext *dst_ctx,
1005  AVFrame *dst, const AVFrame *src, int flags)
1006 {
1007  AVQSVFramesContext *hwctx = dst_ctx->hwctx;
1008  int i, err;
1009 
1010  for (i = 0; i < hwctx->nb_surfaces; i++) {
1011 #if CONFIG_VAAPI
1012  if (*(VASurfaceID*)hwctx->surfaces[i].Data.MemId ==
1013  (VASurfaceID)(uintptr_t)src->data[3])
1014  break;
1015 #endif
1016 #if CONFIG_DXVA2
1017  if ((IDirect3DSurface9*)hwctx->surfaces[i].Data.MemId ==
1018  (IDirect3DSurface9*)(uintptr_t)src->data[3])
1019  break;
1020 #endif
1021  }
1022  if (i >= hwctx->nb_surfaces) {
1023  av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which "
1024  "is not in the mapped frames context.\n");
1025  return AVERROR(EINVAL);
1026  }
1027 
1029  dst, src, NULL, NULL);
1030  if (err)
1031  return err;
1032 
1033  dst->width = src->width;
1034  dst->height = src->height;
1035  dst->data[3] = (uint8_t*)&hwctx->surfaces[i];
1036 
1037  return 0;
1038 }
1039 
1041  const void *hwconfig,
1042  AVHWFramesConstraints *constraints)
1043 {
1044  int i;
1045 
1047  sizeof(*constraints->valid_sw_formats));
1048  if (!constraints->valid_sw_formats)
1049  return AVERROR(ENOMEM);
1050 
1051  for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++)
1052  constraints->valid_sw_formats[i] = supported_pixel_formats[i].pix_fmt;
1053  constraints->valid_sw_formats[FF_ARRAY_ELEMS(supported_pixel_formats)] = AV_PIX_FMT_NONE;
1054 
1055  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
1056  if (!constraints->valid_hw_formats)
1057  return AVERROR(ENOMEM);
1058 
1059  constraints->valid_hw_formats[0] = AV_PIX_FMT_QSV;
1060  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
1061 
1062  return 0;
1063 }
1064 
1066 {
1067  AVQSVDeviceContext *hwctx = ctx->hwctx;
1068  QSVDevicePriv *priv = ctx->user_opaque;
1069 
1070  if (hwctx->session)
1071  MFXClose(hwctx->session);
1072 
1074  av_freep(&priv);
1075 }
1076 
1077 static mfxIMPL choose_implementation(const char *device)
1078 {
1079  static const struct {
1080  const char *name;
1081  mfxIMPL impl;
1082  } impl_map[] = {
1083  { "auto", MFX_IMPL_AUTO },
1084  { "sw", MFX_IMPL_SOFTWARE },
1085  { "hw", MFX_IMPL_HARDWARE },
1086  { "auto_any", MFX_IMPL_AUTO_ANY },
1087  { "hw_any", MFX_IMPL_HARDWARE_ANY },
1088  { "hw2", MFX_IMPL_HARDWARE2 },
1089  { "hw3", MFX_IMPL_HARDWARE3 },
1090  { "hw4", MFX_IMPL_HARDWARE4 },
1091  };
1092 
1093  mfxIMPL impl = MFX_IMPL_AUTO_ANY;
1094  int i;
1095 
1096  if (device) {
1097  for (i = 0; i < FF_ARRAY_ELEMS(impl_map); i++)
1098  if (!strcmp(device, impl_map[i].name)) {
1099  impl = impl_map[i].impl;
1100  break;
1101  }
1102  if (i == FF_ARRAY_ELEMS(impl_map))
1103  impl = strtol(device, NULL, 0);
1104  }
1105 
1106  return impl;
1107 }
1108 
1110  mfxIMPL implementation,
1112  int flags)
1113 {
1114  AVQSVDeviceContext *hwctx = ctx->hwctx;
1115 
1116  mfxVersion ver = { { 3, 1 } };
1117  mfxHDL handle;
1118  mfxHandleType handle_type;
1119  mfxStatus err;
1120  int ret;
1121 
1122  switch (child_device_ctx->type) {
1123 #if CONFIG_VAAPI
1125  {
1126  AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
1127  handle_type = MFX_HANDLE_VA_DISPLAY;
1128  handle = (mfxHDL)child_device_hwctx->display;
1129  }
1130  break;
1131 #endif
1132 #if CONFIG_DXVA2
1134  {
1135  AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
1136  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
1137  handle = (mfxHDL)child_device_hwctx->devmgr;
1138  }
1139  break;
1140 #endif
1141  default:
1142  ret = AVERROR(ENOSYS);
1143  goto fail;
1144  }
1145 
1146  err = MFXInit(implementation, &ver, &hwctx->session);
1147  if (err != MFX_ERR_NONE) {
1148  av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
1149  "%d.\n", err);
1150  ret = AVERROR_UNKNOWN;
1151  goto fail;
1152  }
1153 
1154  err = MFXQueryVersion(hwctx->session, &ver);
1155  if (err != MFX_ERR_NONE) {
1156  av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: %d.\n", err);
1157  ret = AVERROR_UNKNOWN;
1158  goto fail;
1159  }
1160 
1161  av_log(ctx, AV_LOG_VERBOSE,
1162  "Initialize MFX session: API version is %d.%d, implementation version is %d.%d\n",
1163  MFX_VERSION_MAJOR, MFX_VERSION_MINOR, ver.Major, ver.Minor);
1164 
1165  MFXClose(hwctx->session);
1166 
1167  err = MFXInit(implementation, &ver, &hwctx->session);
1168  if (err != MFX_ERR_NONE) {
1169  av_log(ctx, AV_LOG_ERROR,
1170  "Error initializing an MFX session: %d.\n", err);
1171  ret = AVERROR_UNKNOWN;
1172  goto fail;
1173  }
1174 
1175  err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
1176  if (err != MFX_ERR_NONE) {
1177  av_log(ctx, AV_LOG_ERROR, "Error setting child device handle: "
1178  "%d\n", err);
1179  ret = AVERROR_UNKNOWN;
1180  goto fail;
1181  }
1182 
1183  return 0;
1184 
1185 fail:
1186  if (hwctx->session)
1187  MFXClose(hwctx->session);
1188  return ret;
1189 }
1190 
1193 {
1194  return qsv_device_derive_from_child(ctx, MFX_IMPL_HARDWARE_ANY,
1195  child_device_ctx, flags);
1196 }
1197 
1198 static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
1199  AVDictionary *opts, int flags)
1200 {
1201  QSVDevicePriv *priv;
1202  enum AVHWDeviceType child_device_type;
1203  AVHWDeviceContext *child_device;
1204  AVDictionary *child_device_opts;
1205  AVDictionaryEntry *e;
1206 
1207  mfxIMPL impl;
1208  int ret;
1209 
1210  priv = av_mallocz(sizeof(*priv));
1211  if (!priv)
1212  return AVERROR(ENOMEM);
1213 
1214  ctx->user_opaque = priv;
1215  ctx->free = qsv_device_free;
1216 
1217  e = av_dict_get(opts, "child_device", NULL, 0);
1218 
1219  child_device_opts = NULL;
1220  if (CONFIG_VAAPI) {
1221  child_device_type = AV_HWDEVICE_TYPE_VAAPI;
1222  // libmfx does not actually implement VAAPI properly, rather it
1223  // depends on the specific behaviour of a matching iHD driver when
1224  // used on recent Intel hardware. Set options to the VAAPI device
1225  // creation so that we should pick a usable setup by default if
1226  // possible, even when multiple devices and drivers are available.
1227  av_dict_set(&child_device_opts, "kernel_driver", "i915", 0);
1228  av_dict_set(&child_device_opts, "driver", "iHD", 0);
1229  } else if (CONFIG_DXVA2)
1230  child_device_type = AV_HWDEVICE_TYPE_DXVA2;
1231  else {
1232  av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
1233  return AVERROR(ENOSYS);
1234  }
1235 
1236  ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type,
1237  e ? e->value : NULL, child_device_opts, 0);
1238 
1239  av_dict_free(&child_device_opts);
1240  if (ret < 0)
1241  return ret;
1242 
1243  child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
1244 
1245  impl = choose_implementation(device);
1246 
1247  return qsv_device_derive_from_child(ctx, impl, child_device, 0);
1248 }
1249 
1252  .name = "QSV",
1253 
1254  .device_hwctx_size = sizeof(AVQSVDeviceContext),
1255  .device_priv_size = sizeof(QSVDeviceContext),
1256  .frames_hwctx_size = sizeof(AVQSVFramesContext),
1257  .frames_priv_size = sizeof(QSVFramesContext),
1258 
1259  .device_create = qsv_device_create,
1260  .device_derive = qsv_device_derive,
1261  .device_init = qsv_device_init,
1262  .frames_get_constraints = qsv_frames_get_constraints,
1263  .frames_init = qsv_frames_init,
1264  .frames_uninit = qsv_frames_uninit,
1265  .frames_get_buffer = qsv_get_buffer,
1266  .transfer_get_formats = qsv_transfer_get_formats,
1267  .transfer_data_to = qsv_transfer_data_to,
1268  .transfer_data_from = qsv_transfer_data_from,
1269  .map_to = qsv_map_to,
1270  .map_from = qsv_map_from,
1271  .frames_derive_to = qsv_frames_derive_to,
1272  .frames_derive_from = qsv_frames_derive_from,
1273 
1274  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE },
1275 };
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
#define NULL
Definition: coverity.c:32
uint32_t fourcc
static int qsv_init_child_ctx(AVHWFramesContext *ctx)
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:108
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2522
VAAPI-specific data associated with a frame pool.
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
#define pthread_mutex_lock(a)
Definition: ffprobe.c:61
static av_always_inline int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
Definition: os2threads.h:166
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:100
static int qsv_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
mfxFrameSurface1 * surfaces_internal
Definition: hwcontext_qsv.c:72
int frame_type
A combination of MFX_MEMTYPE_* describing the frame pool.
Definition: hwcontext_qsv.h:49
mfxExtBuffer * ext_buffers[1]
Definition: hwcontext_qsv.c:81
This struct is allocated as AVHWFramesContext.hwctx.
Memory handling functions.
mfxHandleType handle_type
Definition: hwcontext_qsv.c:85
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:486
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:42
const char * desc
Definition: nvenc.c:68
An API-specific header for AV_HWDEVICE_TYPE_DXVA2.
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
mfxMemId * mem_ids
Definition: hwcontext_qsv.c:76
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:208
mfxHandleType handle_type
Definition: hwcontext_qsv.c:53
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
mfxVersion ver
Definition: hwcontext_qsv.c:54
#define src
Definition: vp8dsp.c:254
static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
static av_always_inline int pthread_cond_destroy(pthread_cond_t *cond)
Definition: os2threads.h:140
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
API-specific header for AV_HWDEVICE_TYPE_VAAPI.
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:634
#define AV_PIX_FMT_P010
Definition: pixfmt.h:436
static int qsv_transfer_data_child(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
AVBufferPool * pool_internal
static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
enum AVHWDeviceType type
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
DWORD surface_type
The surface type (e.g.
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:388
enum AVHWDeviceType child_device_type
Definition: hwcontext_qsv.c:57
static int qsv_map_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition: hwcontext.c:571
static const struct @302 supported_pixel_formats[]
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
static av_always_inline int pthread_cond_signal(pthread_cond_t *cond)
Definition: os2threads.h:148
ptrdiff_t size
Definition: opengl_enc.c:100
static int qsv_frames_init(AVHWFramesContext *ctx)
#define FFALIGN(x, a)
Definition: macros.h:48
#define av_log(a,...)
static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
static const struct @301 supported_handle_types[]
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
static int qsv_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int width
Definition: frame.h:353
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:89
enum AVHWDeviceType device_type
Definition: hwcontext_qsv.c:86
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:140
static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
IDirect3DDeviceManager9 * devmgr
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:329
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:78
static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, AVHWFramesContext *src_ctx, int flags)
#define fail()
Definition: checkasm.h:122
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:792
static int qsv_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:439
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:198
AVDictionary * opts
Definition: movenc.c:50
static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:148
AVFormatContext * ctx
Definition: movenc.c:48
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:100
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
#define s(width, name)
Definition: cbs_vp9.c:257
mfxFrameSurface1 ** surface_ptrs
Definition: hwcontext_qsv.c:78
int dummy
Definition: motion.c:64
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:65
mfxSession session_download
Definition: hwcontext_qsv.c:62
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:218
#define FF_ARRAY_ELEMS(a)
if(ret)
VADisplay display
The VADisplay handle, to be filled by the user.
mfxSession session
Definition: hwcontext_qsv.h:36
static void qsv_frames_uninit(AVHWFramesContext *ctx)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given hardware type.
Definition: hwcontext.c:138
static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
const HWContextType ff_hwcontext_type_qsv
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:432
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
mfxFrameSurface1 * surfaces
Definition: hwcontext_qsv.h:43
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
uint8_t * data
The data buffer.
Definition: buffer.h:89
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:161
static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
int av_hwdevice_ctx_init(AVBufferRef *ref)
Finalize the device context before use.
Definition: hwcontext.c:196
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:688
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
static int qsv_init_internal_session(AVHWFramesContext *ctx, mfxSession *session, int upload)
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:222
static mfxIMPL choose_implementation(const char *device)
refcounted data buffer API
enum AVPixelFormat * valid_hw_formats
A list of possible values for format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:437
mfxExtOpaqueSurfaceAlloc opaque_alloc
Definition: hwcontext_qsv.c:80
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer. ...
Definition: pixfmt.h:137
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:133
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:324
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:553
#define flags(name, subs,...)
Definition: cbs_av1.c:561
static AVBufferRef * qsv_pool_alloc(void *opaque, int size)
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
void * user_opaque
Arbitrary user data, to be used e.g.
Definition: hwcontext.h:108
static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, mfxIMPL implementation, AVHWDeviceContext *child_device_ctx, int flags)
A reference to a data buffer.
Definition: buffer.h:81
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
static void qsv_device_free(AVHWDeviceContext *ctx)
_fmutex pthread_mutex_t
Definition: os2threads.h:49
common internal and external API header
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:740
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:243
static int qsv_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *child_device_ctx, int flags)
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
static av_always_inline int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)
Definition: os2threads.h:129
static int qsv_device_init(AVHWDeviceContext *ctx)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:71
enum AVPixelFormat child_pix_fmt
Definition: hwcontext_qsv.c:58
IDirect3DSurface9 ** surfaces
The surface pool.
AVHWFrameTransferDirection
Definition: hwcontext.h:394
pixel format definitions
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:189
AVHWDeviceType
Definition: hwcontext.h:27
This struct is allocated as AVHWDeviceContext.hwctx.
char * value
Definition: dict.h:87
static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt)
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:444
VAAPI connection details.
static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx, AVHWFramesContext *src_ctx, int flags)
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:103
int height
Definition: frame.h:353
FILE * out
Definition: movenc.c:54
#define av_freep(p)
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
An API-specific header for AV_HWDEVICE_TYPE_QSV.
AVBufferRef * child_device_ctx
Definition: hwcontext_qsv.c:48
AVBufferRef * child_frames_ref
Definition: hwcontext_qsv.c:71
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:334
#define av_malloc_array(a, b)
formats
Definition: signature.h:48
AVHWDeviceInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:70
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
int depth
Number of bits in the component.
Definition: pixdesc.h:58
static void qsv_pool_release_dummy(void *opaque, uint8_t *data)
static int qsv_map_to(AVHWFramesContext *dst_ctx, AVFrame *dst, const AVFrame *src, int flags)
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
enum AVPixelFormat pix_fmt
Definition: hwcontext_qsv.c:87
mfxSession session_upload
Definition: hwcontext_qsv.c:64
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191
const char * name
Definition: opengl_enc.c:102