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 <stdatomic.h>
20 #include <stdint.h>
21 #include <string.h>
22 
23 #include <mfxvideo.h>
24 
25 #include "config.h"
26 
27 #if HAVE_PTHREADS
28 #include <pthread.h>
29 #endif
30 
31 #define COBJMACROS
32 #if CONFIG_VAAPI
33 #include "hwcontext_vaapi.h"
34 #endif
35 #if CONFIG_D3D11VA
36 #include "hwcontext_d3d11va.h"
37 #endif
38 #if CONFIG_DXVA2
39 #include "hwcontext_dxva2.h"
40 #endif
41 
42 #include "buffer.h"
43 #include "common.h"
44 #include "hwcontext.h"
45 #include "hwcontext_internal.h"
46 #include "hwcontext_qsv.h"
47 #include "mem.h"
48 #include "pixfmt.h"
49 #include "pixdesc.h"
50 #include "time.h"
51 #include "imgutils.h"
52 #include "avassert.h"
53 
54 #define QSV_VERSION_ATLEAST(MAJOR, MINOR) \
55  (MFX_VERSION_MAJOR > (MAJOR) || \
56  MFX_VERSION_MAJOR == (MAJOR) && MFX_VERSION_MINOR >= (MINOR))
57 
58 #define MFX_IMPL_VIA_MASK(impl) (0x0f00 & (impl))
59 #define QSV_ONEVPL QSV_VERSION_ATLEAST(2, 0)
60 #define QSV_HAVE_OPAQUE !QSV_ONEVPL
61 
62 #if QSV_ONEVPL
63 #include <mfxdispatcher.h>
64 #else
65 #define MFXUnload(a) do { } while(0)
66 #endif
67 
68 typedef struct QSVDevicePriv {
71 
72 typedef struct QSVDeviceContext {
73  mfxHDL handle;
74  mfxHandleType handle_type;
75  mfxVersion ver;
76  mfxIMPL impl;
77 
81 
82 typedef struct QSVFramesContext {
83  mfxSession session_download;
85  mfxSession session_upload;
87 #if HAVE_PTHREADS
88  pthread_mutex_t session_lock;
89 #endif
90 
92  mfxFrameSurface1 *surfaces_internal;
93  mfxHDLPair *handle_pairs_internal;
95 
96  // used in the frame allocator for non-opaque surfaces
97  mfxMemId *mem_ids;
98 #if QSV_HAVE_OPAQUE
99  // used in the opaque alloc request for opaque surfaces
100  mfxFrameSurface1 **surface_ptrs;
101 
102  mfxExtOpaqueSurfaceAlloc opaque_alloc;
103  mfxExtBuffer *ext_buffers[1];
104 #endif
108 
109 static const struct {
111  uint32_t fourcc;
113  { AV_PIX_FMT_NV12, MFX_FOURCC_NV12 },
114  { AV_PIX_FMT_BGRA, MFX_FOURCC_RGB4 },
115  { AV_PIX_FMT_P010, MFX_FOURCC_P010 },
116  { AV_PIX_FMT_PAL8, MFX_FOURCC_P8 },
117 #if CONFIG_VAAPI
119  MFX_FOURCC_YUY2 },
120  { AV_PIX_FMT_Y210,
121  MFX_FOURCC_Y210 },
122  // VUYX is used for VAAPI child device,
123  // the SDK only delares support for AYUV
124  { AV_PIX_FMT_VUYX,
125  MFX_FOURCC_AYUV },
126 #endif
127 };
128 
129 extern int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf,
130  enum AVHWDeviceType base_dev_type,
131  void **base_handle);
132 
133 /**
134  * Caller needs to allocate enough space for base_handle pointer.
135  **/
136 int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf,
137  enum AVHWDeviceType base_dev_type,
138  void **base_handle)
139 {
140  mfxHDLPair *handle_pair;
141  handle_pair = surf->Data.MemId;
142  switch (base_dev_type) {
143 #if CONFIG_VAAPI
145  base_handle[0] = handle_pair->first;
146  return 0;
147 #endif
148 #if CONFIG_D3D11VA
150  base_handle[0] = handle_pair->first;
151  base_handle[1] = handle_pair->second;
152  return 0;
153 #endif
154 #if CONFIG_DXVA2
156  base_handle[0] = handle_pair->first;
157  return 0;
158 #endif
159  }
160  return AVERROR(EINVAL);
161 }
162 
164 {
165  int i;
166  for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++) {
168  return supported_pixel_formats[i].fourcc;
169  }
170  return 0;
171 }
172 
173 #if CONFIG_D3D11VA
174 static uint32_t qsv_get_d3d11va_bind_flags(int mem_type)
175 {
176  uint32_t bind_flags = 0;
177 
178  if ((mem_type & MFX_MEMTYPE_VIDEO_MEMORY_ENCODER_TARGET) && (mem_type & MFX_MEMTYPE_INTERNAL_FRAME))
179  bind_flags = D3D11_BIND_DECODER | D3D11_BIND_VIDEO_ENCODER;
180  else
181  bind_flags = D3D11_BIND_DECODER;
182 
183  if ((MFX_MEMTYPE_FROM_VPPOUT & mem_type) || (MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET & mem_type))
184  bind_flags = D3D11_BIND_RENDER_TARGET;
185 
186  return bind_flags;
187 }
188 #endif
189 
190 static int qsv_fill_border(AVFrame *dst, const AVFrame *src)
191 {
192  const AVPixFmtDescriptor *desc;
193  int i, planes_nb = 0;
194  if (dst->format != src->format)
195  return AVERROR(EINVAL);
196 
198 
199  for (i = 0; i < desc->nb_components; i++)
200  planes_nb = FFMAX(planes_nb, desc->comp[i].plane + 1);
201 
202  for (i = 0; i < planes_nb; i++) {
203  int sheight, dheight, y;
204  ptrdiff_t swidth = av_image_get_linesize(src->format,
205  src->width,
206  i);
207  ptrdiff_t dwidth = av_image_get_linesize(dst->format,
208  dst->width,
209  i);
210  const AVComponentDescriptor comp = desc->comp[i];
211  if (swidth < 0 || dwidth < 0) {
212  av_log(NULL, AV_LOG_ERROR, "av_image_get_linesize failed\n");
213  return AVERROR(EINVAL);
214  }
215  sheight = src->height;
216  dheight = dst->height;
217  if (i) {
218  sheight = AV_CEIL_RSHIFT(src->height, desc->log2_chroma_h);
219  dheight = AV_CEIL_RSHIFT(dst->height, desc->log2_chroma_h);
220  }
221  //fill right padding
222  for (y = 0; y < sheight; y++) {
223  void *line_ptr = dst->data[i] + y*dst->linesize[i] + swidth;
224  av_memcpy_backptr(line_ptr,
225  comp.depth > 8 ? 2 : 1,
226  dwidth - swidth);
227  }
228  //fill bottom padding
229  for (y = sheight; y < dheight; y++) {
230  memcpy(dst->data[i]+y*dst->linesize[i],
231  dst->data[i]+(sheight-1)*dst->linesize[i],
232  dwidth);
233  }
234  }
235  return 0;
236 }
237 
239 {
240  AVQSVDeviceContext *hwctx = ctx->hwctx;
241  QSVDeviceContext *s = ctx->internal->priv;
242  int hw_handle_supported = 0;
243  mfxHandleType handle_type;
244  enum AVHWDeviceType device_type;
245  enum AVPixelFormat pix_fmt;
246  mfxStatus err;
247 
248  err = MFXQueryIMPL(hwctx->session, &s->impl);
249  if (err == MFX_ERR_NONE)
250  err = MFXQueryVersion(hwctx->session, &s->ver);
251  if (err != MFX_ERR_NONE) {
252  av_log(ctx, AV_LOG_ERROR, "Error querying the session attributes\n");
253  return AVERROR_UNKNOWN;
254  }
255 
256  if (MFX_IMPL_VIA_VAAPI == MFX_IMPL_VIA_MASK(s->impl)) {
257 #if CONFIG_VAAPI
258  handle_type = MFX_HANDLE_VA_DISPLAY;
259  device_type = AV_HWDEVICE_TYPE_VAAPI;
261  hw_handle_supported = 1;
262 #endif
263  } else if (MFX_IMPL_VIA_D3D11 == MFX_IMPL_VIA_MASK(s->impl)) {
264 #if CONFIG_D3D11VA
265  handle_type = MFX_HANDLE_D3D11_DEVICE;
266  device_type = AV_HWDEVICE_TYPE_D3D11VA;
268  hw_handle_supported = 1;
269 #endif
270  } else if (MFX_IMPL_VIA_D3D9 == MFX_IMPL_VIA_MASK(s->impl)) {
271 #if CONFIG_DXVA2
272  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
273  device_type = AV_HWDEVICE_TYPE_DXVA2;
275  hw_handle_supported = 1;
276 #endif
277  }
278 
279  if (hw_handle_supported) {
280  err = MFXVideoCORE_GetHandle(hwctx->session, handle_type, &s->handle);
281  if (err == MFX_ERR_NONE) {
282  s->handle_type = handle_type;
283  s->child_device_type = device_type;
284  s->child_pix_fmt = pix_fmt;
285  }
286  }
287  if (!s->handle) {
288  av_log(ctx, AV_LOG_VERBOSE, "No supported hw handle could be retrieved "
289  "from the session\n");
290  }
291  return 0;
292 }
293 
295 {
296  QSVFramesContext *s = ctx->internal->priv;
297 
298  if (s->session_download) {
299  MFXVideoVPP_Close(s->session_download);
300  MFXClose(s->session_download);
301  }
302  s->session_download = NULL;
303  s->session_download_init = 0;
304 
305  if (s->session_upload) {
306  MFXVideoVPP_Close(s->session_upload);
307  MFXClose(s->session_upload);
308  }
309  s->session_upload = NULL;
310  s->session_upload_init = 0;
311 
312 #if HAVE_PTHREADS
313  pthread_mutex_destroy(&s->session_lock);
314 #endif
315 
316  av_freep(&s->mem_ids);
317 #if QSV_HAVE_OPAQUE
318  av_freep(&s->surface_ptrs);
319 #endif
320  av_freep(&s->surfaces_internal);
321  av_freep(&s->handle_pairs_internal);
322  av_frame_unref(&s->realigned_upload_frame);
323  av_frame_unref(&s->realigned_download_frame);
324  av_buffer_unref(&s->child_frames_ref);
325 }
326 
327 static void qsv_pool_release_dummy(void *opaque, uint8_t *data)
328 {
329 }
330 
331 static AVBufferRef *qsv_pool_alloc(void *opaque, size_t size)
332 {
334  QSVFramesContext *s = ctx->internal->priv;
335  AVQSVFramesContext *hwctx = ctx->hwctx;
336 
337  if (s->nb_surfaces_used < hwctx->nb_surfaces) {
338  s->nb_surfaces_used++;
339  return av_buffer_create((uint8_t*)(s->surfaces_internal + s->nb_surfaces_used - 1),
340  sizeof(*hwctx->surfaces), qsv_pool_release_dummy, NULL, 0);
341  }
342 
343  return NULL;
344 }
345 
347 {
348  AVQSVFramesContext *hwctx = ctx->hwctx;
349  QSVFramesContext *s = ctx->internal->priv;
350  QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv;
351 
352  AVBufferRef *child_device_ref = NULL;
353  AVBufferRef *child_frames_ref = NULL;
354 
355  AVHWDeviceContext *child_device_ctx;
356  AVHWFramesContext *child_frames_ctx;
357 
358  int i, ret = 0;
359 
360  if (!device_priv->handle) {
362  "Cannot create a non-opaque internal surface pool without "
363  "a hardware handle\n");
364  return AVERROR(EINVAL);
365  }
366 
367  child_device_ref = av_hwdevice_ctx_alloc(device_priv->child_device_type);
368  if (!child_device_ref)
369  return AVERROR(ENOMEM);
370  child_device_ctx = (AVHWDeviceContext*)child_device_ref->data;
371 
372 #if CONFIG_VAAPI
373  if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
374  AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
375  child_device_hwctx->display = (VADisplay)device_priv->handle;
376  }
377 #endif
378 #if CONFIG_D3D11VA
379  if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
380  AVD3D11VADeviceContext *child_device_hwctx = child_device_ctx->hwctx;
381  ID3D11Device_AddRef((ID3D11Device*)device_priv->handle);
382  child_device_hwctx->device = (ID3D11Device*)device_priv->handle;
383  }
384 #endif
385 #if CONFIG_DXVA2
386  if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
387  AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
388  child_device_hwctx->devmgr = (IDirect3DDeviceManager9*)device_priv->handle;
389  }
390 #endif
391 
392  ret = av_hwdevice_ctx_init(child_device_ref);
393  if (ret < 0) {
394  av_log(ctx, AV_LOG_ERROR, "Error initializing a child device context\n");
395  goto fail;
396  }
397 
398  child_frames_ref = av_hwframe_ctx_alloc(child_device_ref);
399  if (!child_frames_ref) {
400  ret = AVERROR(ENOMEM);
401  goto fail;
402  }
403  child_frames_ctx = (AVHWFramesContext*)child_frames_ref->data;
404 
405  child_frames_ctx->format = device_priv->child_pix_fmt;
406  child_frames_ctx->sw_format = ctx->sw_format;
407  child_frames_ctx->initial_pool_size = ctx->initial_pool_size;
408  child_frames_ctx->width = FFALIGN(ctx->width, 16);
409  child_frames_ctx->height = FFALIGN(ctx->height, 16);
410 
411 #if CONFIG_D3D11VA
412  if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
413  AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
414  if (hwctx->frame_type == 0)
415  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
416  if (hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
417  child_frames_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
418  child_frames_hwctx->BindFlags = qsv_get_d3d11va_bind_flags(hwctx->frame_type);
419  }
420 #endif
421 #if CONFIG_DXVA2
422  if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
423  AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
424  if (hwctx->frame_type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET)
425  child_frames_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget;
426  else
427  child_frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
428  }
429 #endif
430 
431  ret = av_hwframe_ctx_init(child_frames_ref);
432  if (ret < 0) {
433  av_log(ctx, AV_LOG_ERROR, "Error initializing a child frames context\n");
434  goto fail;
435  }
436 
437 #if CONFIG_VAAPI
438  if (child_device_ctx->type == AV_HWDEVICE_TYPE_VAAPI) {
439  AVVAAPIFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
440  for (i = 0; i < ctx->initial_pool_size; i++) {
441  s->handle_pairs_internal[i].first = child_frames_hwctx->surface_ids + i;
442  s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
443  s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
444  }
445  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
446  }
447 #endif
448 #if CONFIG_D3D11VA
449  if (child_device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
450  AVD3D11VAFramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
451  for (i = 0; i < ctx->initial_pool_size; i++) {
452  s->handle_pairs_internal[i].first = (mfxMemId)child_frames_hwctx->texture_infos[i].texture;
453  if(child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
454  s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
455  } else {
456  s->handle_pairs_internal[i].second = (mfxMemId)child_frames_hwctx->texture_infos[i].index;
457  }
458  s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
459  }
460  if (child_frames_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
461  hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
462  } else {
463  hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
464  }
465  }
466 #endif
467 #if CONFIG_DXVA2
468  if (child_device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) {
469  AVDXVA2FramesContext *child_frames_hwctx = child_frames_ctx->hwctx;
470  for (i = 0; i < ctx->initial_pool_size; i++) {
471  s->handle_pairs_internal[i].first = (mfxMemId)child_frames_hwctx->surfaces[i];
472  s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
473  s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
474  }
475  if (child_frames_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
476  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
477  else
478  hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
479  }
480 #endif
481 
482  s->child_frames_ref = child_frames_ref;
483  child_frames_ref = NULL;
484 
485 fail:
486  av_buffer_unref(&child_device_ref);
487  av_buffer_unref(&child_frames_ref);
488  return ret;
489 }
490 
491 static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
492 {
493  const AVPixFmtDescriptor *desc;
494  uint32_t fourcc;
495 
496  desc = av_pix_fmt_desc_get(ctx->sw_format);
497  if (!desc)
498  return AVERROR(EINVAL);
499 
500  fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
501  if (!fourcc)
502  return AVERROR(EINVAL);
503 
504  surf->Info.BitDepthLuma = desc->comp[0].depth;
505  surf->Info.BitDepthChroma = desc->comp[0].depth;
506  surf->Info.Shift = desc->comp[0].depth > 8;
507 
508  if (desc->log2_chroma_w && desc->log2_chroma_h)
509  surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV420;
510  else if (desc->log2_chroma_w)
511  surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV422;
512  else
513  surf->Info.ChromaFormat = MFX_CHROMAFORMAT_YUV444;
514 
515  surf->Info.FourCC = fourcc;
516  surf->Info.Width = FFALIGN(ctx->width, 16);
517  surf->Info.CropW = ctx->width;
518  surf->Info.Height = FFALIGN(ctx->height, 16);
519  surf->Info.CropH = ctx->height;
520  surf->Info.FrameRateExtN = 25;
521  surf->Info.FrameRateExtD = 1;
522  surf->Info.PicStruct = MFX_PICSTRUCT_PROGRESSIVE;
523 
524  return 0;
525 }
526 
528 {
529  QSVFramesContext *s = ctx->internal->priv;
530  AVQSVFramesContext *frames_hwctx = ctx->hwctx;
531 
532  int i, ret = 0;
533 
534  if (ctx->initial_pool_size <= 0) {
535  av_log(ctx, AV_LOG_ERROR, "QSV requires a fixed frame pool size\n");
536  return AVERROR(EINVAL);
537  }
538 
539  s->handle_pairs_internal = av_calloc(ctx->initial_pool_size,
540  sizeof(*s->handle_pairs_internal));
541  if (!s->handle_pairs_internal)
542  return AVERROR(ENOMEM);
543 
544  s->surfaces_internal = av_calloc(ctx->initial_pool_size,
545  sizeof(*s->surfaces_internal));
546  if (!s->surfaces_internal)
547  return AVERROR(ENOMEM);
548 
549  for (i = 0; i < ctx->initial_pool_size; i++) {
550  ret = qsv_init_surface(ctx, &s->surfaces_internal[i]);
551  if (ret < 0)
552  return ret;
553  }
554 
555 #if QSV_HAVE_OPAQUE
556  if (!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME)) {
558  if (ret < 0)
559  return ret;
560  }
561 #else
563  if (ret < 0)
564  return ret;
565 #endif
566 
567  ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(mfxFrameSurface1),
569  if (!ctx->internal->pool_internal)
570  return AVERROR(ENOMEM);
571 
572  frames_hwctx->surfaces = s->surfaces_internal;
573  frames_hwctx->nb_surfaces = ctx->initial_pool_size;
574 
575  return 0;
576 }
577 
578 static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req,
579  mfxFrameAllocResponse *resp)
580 {
581  AVHWFramesContext *ctx = pthis;
582  QSVFramesContext *s = ctx->internal->priv;
583  AVQSVFramesContext *hwctx = ctx->hwctx;
584  mfxFrameInfo *i = &req->Info;
585  mfxFrameInfo *i1 = &hwctx->surfaces[0].Info;
586 
587  if (!(req->Type & MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET) ||
588  !(req->Type & (MFX_MEMTYPE_FROM_VPPIN | MFX_MEMTYPE_FROM_VPPOUT)) ||
589  !(req->Type & MFX_MEMTYPE_EXTERNAL_FRAME))
590  return MFX_ERR_UNSUPPORTED;
591  if (i->Width > i1->Width || i->Height > i1->Height ||
592  i->FourCC != i1->FourCC || i->ChromaFormat != i1->ChromaFormat) {
593  av_log(ctx, AV_LOG_ERROR, "Mismatching surface properties in an "
594  "allocation request: %dx%d %d %d vs %dx%d %d %d\n",
595  i->Width, i->Height, i->FourCC, i->ChromaFormat,
596  i1->Width, i1->Height, i1->FourCC, i1->ChromaFormat);
597  return MFX_ERR_UNSUPPORTED;
598  }
599 
600  resp->mids = s->mem_ids;
601  resp->NumFrameActual = hwctx->nb_surfaces;
602 
603  return MFX_ERR_NONE;
604 }
605 
606 static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
607 {
608  return MFX_ERR_NONE;
609 }
610 
611 static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
612 {
613  return MFX_ERR_UNSUPPORTED;
614 }
615 
616 static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
617 {
618  return MFX_ERR_UNSUPPORTED;
619 }
620 
621 static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
622 {
623  mfxHDLPair *pair_dst = (mfxHDLPair*)hdl;
624  mfxHDLPair *pair_src = (mfxHDLPair*)mid;
625 
626  pair_dst->first = pair_src->first;
627 
628  if (pair_src->second != (mfxMemId)MFX_INFINITE)
629  pair_dst->second = pair_src->second;
630  return MFX_ERR_NONE;
631 }
632 
633 #if QSV_ONEVPL
634 
635 static int qsv_d3d11_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
636 {
637 #if CONFIG_D3D11VA
638  mfxStatus sts;
639  IDXGIAdapter *pDXGIAdapter;
640  DXGI_ADAPTER_DESC adapterDesc;
641  IDXGIDevice *pDXGIDevice = NULL;
642  HRESULT hr;
643  ID3D11Device *device = handle;
644  mfxVariant impl_value;
645 
646  hr = ID3D11Device_QueryInterface(device, &IID_IDXGIDevice, (void**)&pDXGIDevice);
647  if (SUCCEEDED(hr)) {
648  hr = IDXGIDevice_GetAdapter(pDXGIDevice, &pDXGIAdapter);
649  if (FAILED(hr)) {
650  av_log(ctx, AV_LOG_ERROR, "Error IDXGIDevice_GetAdapter %d\n", hr);
651  goto fail;
652  }
653 
654  hr = IDXGIAdapter_GetDesc(pDXGIAdapter, &adapterDesc);
655  if (FAILED(hr)) {
656  av_log(ctx, AV_LOG_ERROR, "Error IDXGIAdapter_GetDesc %d\n", hr);
657  goto fail;
658  }
659  } else {
660  av_log(ctx, AV_LOG_ERROR, "Error ID3D11Device_QueryInterface %d\n", hr);
661  goto fail;
662  }
663 
664  impl_value.Type = MFX_VARIANT_TYPE_U16;
665  impl_value.Data.U16 = adapterDesc.DeviceId;
666  sts = MFXSetConfigFilterProperty(cfg,
667  (const mfxU8 *)"mfxExtendedDeviceId.DeviceID", impl_value);
668  if (sts != MFX_ERR_NONE) {
669  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
670  "DeviceID property: %d.\n", sts);
671  goto fail;
672  }
673 
674  impl_value.Type = MFX_VARIANT_TYPE_PTR;
675  impl_value.Data.Ptr = &adapterDesc.AdapterLuid;
676  sts = MFXSetConfigFilterProperty(cfg,
677  (const mfxU8 *)"mfxExtendedDeviceId.DeviceLUID", impl_value);
678  if (sts != MFX_ERR_NONE) {
679  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
680  "DeviceLUID property: %d.\n", sts);
681  goto fail;
682  }
683 
684  impl_value.Type = MFX_VARIANT_TYPE_U32;
685  impl_value.Data.U32 = 0x0001;
686  sts = MFXSetConfigFilterProperty(cfg,
687  (const mfxU8 *)"mfxExtendedDeviceId.LUIDDeviceNodeMask", impl_value);
688  if (sts != MFX_ERR_NONE) {
689  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
690  "LUIDDeviceNodeMask property: %d.\n", sts);
691  goto fail;
692  }
693 
694  return 0;
695 
696 fail:
697 #endif
698  return AVERROR_UNKNOWN;
699 }
700 
701 static int qsv_d3d9_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
702 {
703  int ret = AVERROR_UNKNOWN;
704 #if CONFIG_DXVA2
705  mfxStatus sts;
706  IDirect3DDeviceManager9* devmgr = handle;
707  IDirect3DDevice9Ex *device = NULL;
708  HANDLE device_handle = 0;
709  IDirect3D9Ex *d3d9ex = NULL;
710  LUID luid;
711  D3DDEVICE_CREATION_PARAMETERS params;
712  HRESULT hr;
713  mfxVariant impl_value;
714 
715  hr = IDirect3DDeviceManager9_OpenDeviceHandle(devmgr, &device_handle);
716  if (FAILED(hr)) {
717  av_log(ctx, AV_LOG_ERROR, "Error OpenDeviceHandle %d\n", hr);
718  goto fail;
719  }
720 
721  hr = IDirect3DDeviceManager9_LockDevice(devmgr, device_handle, &device, TRUE);
722  if (FAILED(hr)) {
723  av_log(ctx, AV_LOG_ERROR, "Error LockDevice %d\n", hr);
724  goto fail;
725  }
726 
727  hr = IDirect3DDevice9Ex_GetCreationParameters(device, &params);
728  if (FAILED(hr)) {
729  av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9_GetCreationParameters %d\n", hr);
730  goto unlock;
731  }
732 
733  hr = IDirect3DDevice9Ex_GetDirect3D(device, &d3d9ex);
734  if (FAILED(hr)) {
735  av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9Ex_GetAdapterLUID %d\n", hr);
736  goto unlock;
737  }
738 
739  hr = IDirect3D9Ex_GetAdapterLUID(d3d9ex, params.AdapterOrdinal, &luid);
740  if (FAILED(hr)) {
741  av_log(ctx, AV_LOG_ERROR, "Error IDirect3DDevice9Ex_GetAdapterLUID %d\n", hr);
742  goto unlock;
743  }
744 
745  impl_value.Type = MFX_VARIANT_TYPE_PTR;
746  impl_value.Data.Ptr = &luid;
747  sts = MFXSetConfigFilterProperty(cfg,
748  (const mfxU8 *)"mfxExtendedDeviceId.DeviceLUID", impl_value);
749  if (sts != MFX_ERR_NONE) {
750  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
751  "DeviceLUID property: %d.\n", sts);
752  goto unlock;
753  }
754 
755  ret = 0;
756 
757 unlock:
758  IDirect3DDeviceManager9_UnlockDevice(devmgr, device_handle, FALSE);
759 fail:
760 #endif
761  return ret;
762 }
763 
764 static int qsv_va_update_config(void *ctx, mfxHDL handle, mfxConfig cfg)
765 {
766 #if CONFIG_VAAPI
767 #if VA_CHECK_VERSION(1, 15, 0)
768  mfxStatus sts;
769  VADisplay dpy = handle;
770  VAStatus vas;
771  VADisplayAttribute attr = {
772  .type = VADisplayPCIID,
773  };
774  mfxVariant impl_value;
775 
776  vas = vaGetDisplayAttributes(dpy, &attr, 1);
777  if (vas == VA_STATUS_SUCCESS && attr.flags != VA_DISPLAY_ATTRIB_NOT_SUPPORTED) {
778  impl_value.Type = MFX_VARIANT_TYPE_U16;
779  impl_value.Data.U16 = (attr.value & 0xFFFF);
780  sts = MFXSetConfigFilterProperty(cfg,
781  (const mfxU8 *)"mfxExtendedDeviceId.DeviceID", impl_value);
782  if (sts != MFX_ERR_NONE) {
783  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
784  "DeviceID property: %d.\n", sts);
785  goto fail;
786  }
787  } else {
788  av_log(ctx, AV_LOG_ERROR, "libva: Failed to get device id from the driver. Please "
789  "consider to upgrade the driver to support VA-API 1.15.0\n");
790  goto fail;
791  }
792 
793  return 0;
794 
795 fail:
796 #else
797  av_log(ctx, AV_LOG_ERROR, "libva: This version of libva doesn't support retrieving "
798  "the device information from the driver. Please consider to upgrade libva to "
799  "support VA-API 1.15.0\n");
800 #endif
801 #endif
802  return AVERROR_UNKNOWN;
803 }
804 
805 static int qsv_new_mfx_loader(void *ctx,
806  mfxHDL handle,
807  mfxHandleType handle_type,
808  mfxIMPL implementation,
809  mfxVersion *pver,
810  void **ploader)
811 {
812  mfxStatus sts;
813  mfxLoader loader = NULL;
814  mfxConfig cfg;
815  mfxVariant impl_value;
816 
817  *ploader = NULL;
818  loader = MFXLoad();
819  if (!loader) {
820  av_log(ctx, AV_LOG_ERROR, "Error creating a MFX loader\n");
821  goto fail;
822  }
823 
824  /* Create configurations for implementation */
825  cfg = MFXCreateConfig(loader);
826  if (!cfg) {
827  av_log(ctx, AV_LOG_ERROR, "Error creating a MFX configuration\n");
828  goto fail;
829  }
830 
831  impl_value.Type = MFX_VARIANT_TYPE_U32;
832  impl_value.Data.U32 = (implementation == MFX_IMPL_SOFTWARE) ?
833  MFX_IMPL_TYPE_SOFTWARE : MFX_IMPL_TYPE_HARDWARE;
834  sts = MFXSetConfigFilterProperty(cfg,
835  (const mfxU8 *)"mfxImplDescription.Impl", impl_value);
836  if (sts != MFX_ERR_NONE) {
837  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration "
838  "property: %d.\n", sts);
839  goto fail;
840  }
841 
842  impl_value.Type = MFX_VARIANT_TYPE_U32;
843  impl_value.Data.U32 = pver->Version;
844  sts = MFXSetConfigFilterProperty(cfg,
845  (const mfxU8 *)"mfxImplDescription.ApiVersion.Version",
846  impl_value);
847  if (sts != MFX_ERR_NONE) {
848  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration "
849  "property: %d.\n", sts);
850  goto fail;
851  }
852 
853  impl_value.Type = MFX_VARIANT_TYPE_U16;
854  impl_value.Data.U16 = 0x8086; // Intel device only
855  sts = MFXSetConfigFilterProperty(cfg,
856  (const mfxU8 *)"mfxExtendedDeviceId.VendorID", impl_value);
857  if (sts != MFX_ERR_NONE) {
858  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
859  "VendorID property: %d.\n", sts);
860  goto fail;
861  }
862 
863  if (MFX_HANDLE_VA_DISPLAY == handle_type) {
864  if (handle && qsv_va_update_config(ctx, handle, cfg))
865  goto fail;
866 
867  impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_VAAPI;
868  } else if (MFX_HANDLE_D3D9_DEVICE_MANAGER == handle_type) {
869  if (handle && qsv_d3d9_update_config(ctx, handle, cfg))
870  goto fail;
871 
872  impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D9;
873  } else {
874  if (handle && qsv_d3d11_update_config(ctx, handle, cfg))
875  goto fail;
876 
877  impl_value.Data.U32 = MFX_ACCEL_MODE_VIA_D3D11;
878  }
879 
880  impl_value.Type = MFX_VARIANT_TYPE_U32;
881  sts = MFXSetConfigFilterProperty(cfg,
882  (const mfxU8 *)"mfxImplDescription.AccelerationMode", impl_value);
883  if (sts != MFX_ERR_NONE) {
884  av_log(ctx, AV_LOG_ERROR, "Error adding a MFX configuration"
885  "AccelerationMode property: %d.\n", sts);
886  goto fail;
887  }
888 
889  *ploader = loader;
890 
891  return 0;
892 
893 fail:
894  if (loader)
895  MFXUnload(loader);
896 
897  return AVERROR_UNKNOWN;
898 }
899 
900 static int qsv_create_mfx_session_from_loader(void *ctx, mfxLoader loader, mfxSession *psession)
901 {
902  mfxStatus sts;
903  mfxSession session = NULL;
904  uint32_t impl_idx = 0;
905  mfxVersion ver;
906 
907  while (1) {
908  /* Enumerate all implementations */
909  mfxImplDescription *impl_desc;
910 
911  sts = MFXEnumImplementations(loader, impl_idx,
912  MFX_IMPLCAPS_IMPLDESCSTRUCTURE,
913  (mfxHDL *)&impl_desc);
914  /* Failed to find an available implementation */
915  if (sts == MFX_ERR_NOT_FOUND)
916  break;
917  else if (sts != MFX_ERR_NONE) {
918  impl_idx++;
919  continue;
920  }
921 
922  sts = MFXCreateSession(loader, impl_idx, &session);
923  MFXDispReleaseImplDescription(loader, impl_desc);
924  if (sts == MFX_ERR_NONE)
925  break;
926 
927  impl_idx++;
928  }
929 
930  if (sts != MFX_ERR_NONE) {
931  av_log(ctx, AV_LOG_ERROR, "Error creating a MFX session: %d.\n", sts);
932  goto fail;
933  }
934 
935  sts = MFXQueryVersion(session, &ver);
936  if (sts != MFX_ERR_NONE) {
937  av_log(ctx, AV_LOG_ERROR, "Error querying a MFX session: %d.\n", sts);
938  goto fail;
939  }
940 
941  av_log(ctx, AV_LOG_VERBOSE, "Initialize MFX session: implementation "
942  "version is %d.%d\n", ver.Major, ver.Minor);
943 
944  *psession = session;
945 
946  return 0;
947 
948 fail:
949  if (session)
950  MFXClose(session);
951 
952  return AVERROR_UNKNOWN;
953 }
954 
955 static int qsv_create_mfx_session(void *ctx,
956  mfxHDL handle,
957  mfxHandleType handle_type,
958  mfxIMPL implementation,
959  mfxVersion *pver,
960  mfxSession *psession,
961  void **ploader)
962 {
963  mfxLoader loader = NULL;
964 
966  "Use Intel(R) oneVPL to create MFX session, API version is "
967  "%d.%d, the required implementation version is %d.%d\n",
968  MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
969 
970  if (handle_type != MFX_HANDLE_VA_DISPLAY &&
971  handle_type != MFX_HANDLE_D3D9_DEVICE_MANAGER &&
972  handle_type != MFX_HANDLE_D3D11_DEVICE) {
974  "Invalid MFX device handle type\n");
975  return AVERROR(EXDEV);
976  }
977 
978  *psession = NULL;
979 
980  if (!*ploader) {
981  if (qsv_new_mfx_loader(ctx, handle, handle_type, implementation, pver, (void **)&loader))
982  goto fail;
983 
984  av_assert0(loader);
985  } else
986  loader = *ploader; // Use the input mfxLoader to create mfx session
987 
988  if (qsv_create_mfx_session_from_loader(ctx, loader, psession))
989  goto fail;
990 
991  if (!*ploader)
992  *ploader = loader;
993 
994  return 0;
995 
996 fail:
997  if (!*ploader && loader)
998  MFXUnload(loader);
999 
1000  return AVERROR_UNKNOWN;
1001 }
1002 
1003 #else
1004 
1005 static int qsv_create_mfx_session(void *ctx,
1006  mfxHDL handle,
1007  mfxHandleType handle_type,
1008  mfxIMPL implementation,
1009  mfxVersion *pver,
1010  mfxSession *psession,
1011  void **ploader)
1012 {
1013  mfxVersion ver;
1014  mfxStatus sts;
1015  mfxSession session = NULL;
1016 
1018  "Use Intel(R) Media SDK to create MFX session, API version is "
1019  "%d.%d, the required implementation version is %d.%d\n",
1020  MFX_VERSION_MAJOR, MFX_VERSION_MINOR, pver->Major, pver->Minor);
1021 
1022  *ploader = NULL;
1023  *psession = NULL;
1024  ver = *pver;
1025  sts = MFXInit(implementation, &ver, &session);
1026  if (sts != MFX_ERR_NONE) {
1027  av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
1028  "%d.\n", sts);
1029  goto fail;
1030  }
1031 
1032  sts = MFXQueryVersion(session, &ver);
1033  if (sts != MFX_ERR_NONE) {
1034  av_log(ctx, AV_LOG_ERROR, "Error querying an MFX session: "
1035  "%d.\n", sts);
1036  goto fail;
1037  }
1038 
1039  av_log(ctx, AV_LOG_VERBOSE, "Initialize MFX session: implementation "
1040  "version is %d.%d\n", ver.Major, ver.Minor);
1041 
1042  MFXClose(session);
1043 
1044  sts = MFXInit(implementation, &ver, &session);
1045  if (sts != MFX_ERR_NONE) {
1046  av_log(ctx, AV_LOG_ERROR, "Error initializing an MFX session: "
1047  "%d.\n", sts);
1048  goto fail;
1049  }
1050 
1051  *psession = session;
1052 
1053  return 0;
1054 
1055 fail:
1056  if (session)
1057  MFXClose(session);
1058 
1059  return AVERROR_UNKNOWN;
1060 }
1061 
1062 #endif
1063 
1065  mfxSession *session, int upload)
1066 {
1067  AVQSVFramesContext *frames_hwctx = ctx->hwctx;
1068  QSVDeviceContext *device_priv = ctx->device_ctx->internal->priv;
1069  int opaque = 0;
1070 
1071  mfxFrameAllocator frame_allocator = {
1072  .pthis = ctx,
1073  .Alloc = frame_alloc,
1074  .Lock = frame_lock,
1075  .Unlock = frame_unlock,
1076  .GetHDL = frame_get_hdl,
1077  .Free = frame_free,
1078  };
1079 
1080  mfxVideoParam par;
1081  mfxStatus err;
1082  int ret = AVERROR_UNKNOWN;
1083  AVQSVDeviceContext *hwctx = ctx->device_ctx->hwctx;
1084  /* hwctx->loader is non-NULL for oneVPL user and NULL for non-oneVPL user */
1085  void **loader = &hwctx->loader;
1086 
1087 #if QSV_HAVE_OPAQUE
1088  QSVFramesContext *s = ctx->internal->priv;
1089  opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
1090 #endif
1091 
1092  ret = qsv_create_mfx_session(ctx, device_priv->handle, device_priv->handle_type,
1093  device_priv->impl, &device_priv->ver, session, loader);
1094  if (ret)
1095  goto fail;
1096 
1097  if (device_priv->handle) {
1098  err = MFXVideoCORE_SetHandle(*session, device_priv->handle_type,
1099  device_priv->handle);
1100  if (err != MFX_ERR_NONE) {
1101  ret = AVERROR_UNKNOWN;
1102  goto fail;
1103  }
1104  }
1105 
1106  if (!opaque) {
1107  err = MFXVideoCORE_SetFrameAllocator(*session, &frame_allocator);
1108  if (err != MFX_ERR_NONE) {
1109  ret = AVERROR_UNKNOWN;
1110  goto fail;
1111  }
1112  }
1113 
1114  memset(&par, 0, sizeof(par));
1115 
1116  if (!opaque) {
1117  par.IOPattern = upload ? MFX_IOPATTERN_OUT_VIDEO_MEMORY :
1118  MFX_IOPATTERN_IN_VIDEO_MEMORY;
1119  }
1120 #if QSV_HAVE_OPAQUE
1121  else {
1122  par.ExtParam = s->ext_buffers;
1123  par.NumExtParam = FF_ARRAY_ELEMS(s->ext_buffers);
1124  par.IOPattern = upload ? MFX_IOPATTERN_OUT_OPAQUE_MEMORY :
1125  MFX_IOPATTERN_IN_OPAQUE_MEMORY;
1126  }
1127 #endif
1128 
1129  par.IOPattern |= upload ? MFX_IOPATTERN_IN_SYSTEM_MEMORY :
1130  MFX_IOPATTERN_OUT_SYSTEM_MEMORY;
1131  par.AsyncDepth = 1;
1132 
1133  par.vpp.In = frames_hwctx->surfaces[0].Info;
1134 
1135  /* Apparently VPP requires the frame rate to be set to some value, otherwise
1136  * init will fail (probably for the framerate conversion filter). Since we
1137  * are only doing data upload/download here, we just invent an arbitrary
1138  * value */
1139  par.vpp.In.FrameRateExtN = 25;
1140  par.vpp.In.FrameRateExtD = 1;
1141  par.vpp.Out = par.vpp.In;
1142 
1143  err = MFXVideoVPP_Init(*session, &par);
1144  if (err != MFX_ERR_NONE) {
1145  av_log(ctx, AV_LOG_VERBOSE, "Error opening the internal VPP session."
1146  "Surface upload/download will not be possible\n");
1147 
1148  ret = AVERROR_UNKNOWN;
1149  goto fail;
1150  }
1151 
1152  return 0;
1153 
1154 fail:
1155  if (*session)
1156  MFXClose(*session);
1157 
1158  *session = NULL;
1159 
1160  return ret;
1161 }
1162 
1164 {
1165  QSVFramesContext *s = ctx->internal->priv;
1166  AVQSVFramesContext *frames_hwctx = ctx->hwctx;
1167 
1168  int opaque = 0;
1169 
1170  uint32_t fourcc;
1171  int i, ret;
1172 
1173 #if QSV_HAVE_OPAQUE
1174  opaque = !!(frames_hwctx->frame_type & MFX_MEMTYPE_OPAQUE_FRAME);
1175 #endif
1176 
1177  fourcc = qsv_fourcc_from_pix_fmt(ctx->sw_format);
1178  if (!fourcc) {
1179  av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format\n");
1180  return AVERROR(ENOSYS);
1181  }
1182 
1183  if (!ctx->pool) {
1185  if (ret < 0) {
1186  av_log(ctx, AV_LOG_ERROR, "Error creating an internal frame pool\n");
1187  return ret;
1188  }
1189  }
1190 
1191  if (!opaque) {
1192  s->mem_ids = av_calloc(frames_hwctx->nb_surfaces, sizeof(*s->mem_ids));
1193  if (!s->mem_ids)
1194  return AVERROR(ENOMEM);
1195 
1196  for (i = 0; i < frames_hwctx->nb_surfaces; i++)
1197  s->mem_ids[i] = frames_hwctx->surfaces[i].Data.MemId;
1198  }
1199 #if QSV_HAVE_OPAQUE
1200  else {
1201  s->surface_ptrs = av_calloc(frames_hwctx->nb_surfaces,
1202  sizeof(*s->surface_ptrs));
1203  if (!s->surface_ptrs)
1204  return AVERROR(ENOMEM);
1205 
1206  for (i = 0; i < frames_hwctx->nb_surfaces; i++)
1207  s->surface_ptrs[i] = frames_hwctx->surfaces + i;
1208 
1209  s->opaque_alloc.In.Surfaces = s->surface_ptrs;
1210  s->opaque_alloc.In.NumSurface = frames_hwctx->nb_surfaces;
1211  s->opaque_alloc.In.Type = frames_hwctx->frame_type;
1212 
1213  s->opaque_alloc.Out = s->opaque_alloc.In;
1214 
1215  s->opaque_alloc.Header.BufferId = MFX_EXTBUFF_OPAQUE_SURFACE_ALLOCATION;
1216  s->opaque_alloc.Header.BufferSz = sizeof(s->opaque_alloc);
1217 
1218  s->ext_buffers[0] = (mfxExtBuffer*)&s->opaque_alloc;
1219  }
1220 #endif
1221 
1222  s->session_download = NULL;
1223  s->session_upload = NULL;
1224 
1225  s->session_download_init = 0;
1226  s->session_upload_init = 0;
1227 
1228 #if HAVE_PTHREADS
1229  pthread_mutex_init(&s->session_lock, NULL);
1230 #endif
1231 
1232  return 0;
1233 }
1234 
1236 {
1237  frame->buf[0] = av_buffer_pool_get(ctx->pool);
1238  if (!frame->buf[0])
1239  return AVERROR(ENOMEM);
1240 
1241  frame->data[3] = frame->buf[0]->data;
1242  frame->format = AV_PIX_FMT_QSV;
1243  frame->width = ctx->width;
1244  frame->height = ctx->height;
1245 
1246  return 0;
1247 }
1248 
1250  enum AVHWFrameTransferDirection dir,
1251  enum AVPixelFormat **formats)
1252 {
1253  enum AVPixelFormat *fmts;
1254 
1255  fmts = av_malloc_array(2, sizeof(*fmts));
1256  if (!fmts)
1257  return AVERROR(ENOMEM);
1258 
1259  fmts[0] = ctx->sw_format;
1260  fmts[1] = AV_PIX_FMT_NONE;
1261 
1262  *formats = fmts;
1263 
1264  return 0;
1265 }
1266 
1268  AVHWFramesContext *src_ctx, int flags)
1269 {
1270  AVQSVFramesContext *src_hwctx = src_ctx->hwctx;
1271  int i;
1272 
1273  switch (dst_ctx->device_ctx->type) {
1274 #if CONFIG_VAAPI
1276  {
1277  AVVAAPIFramesContext *dst_hwctx = dst_ctx->hwctx;
1278  dst_hwctx->surface_ids = av_calloc(src_hwctx->nb_surfaces,
1279  sizeof(*dst_hwctx->surface_ids));
1280  if (!dst_hwctx->surface_ids)
1281  return AVERROR(ENOMEM);
1282  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
1283  mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
1284  dst_hwctx->surface_ids[i] = *(VASurfaceID*)pair->first;
1285  }
1286  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
1287  }
1288  break;
1289 #endif
1290 #if CONFIG_D3D11VA
1292  {
1293  D3D11_TEXTURE2D_DESC texDesc;
1294  dst_ctx->initial_pool_size = src_ctx->initial_pool_size;
1295  AVD3D11VAFramesContext *dst_hwctx = dst_ctx->hwctx;
1296  dst_hwctx->texture_infos = av_calloc(src_hwctx->nb_surfaces,
1297  sizeof(*dst_hwctx->texture_infos));
1298  if (!dst_hwctx->texture_infos)
1299  return AVERROR(ENOMEM);
1300  if (src_hwctx->frame_type & MFX_MEMTYPE_SHARED_RESOURCE)
1301  dst_hwctx->MiscFlags = D3D11_RESOURCE_MISC_SHARED;
1302  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
1303  mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
1304  dst_hwctx->texture_infos[i].texture = (ID3D11Texture2D*)pair->first;
1305  dst_hwctx->texture_infos[i].index = pair->second == (mfxMemId)MFX_INFINITE ? (intptr_t)0 : (intptr_t)pair->second;
1306  }
1307  ID3D11Texture2D_GetDesc(dst_hwctx->texture_infos[0].texture, &texDesc);
1308  dst_hwctx->BindFlags = texDesc.BindFlags;
1309  }
1310  break;
1311 #endif
1312 #if CONFIG_DXVA2
1314  {
1315  AVDXVA2FramesContext *dst_hwctx = dst_ctx->hwctx;
1316  dst_hwctx->surfaces = av_calloc(src_hwctx->nb_surfaces,
1317  sizeof(*dst_hwctx->surfaces));
1318  if (!dst_hwctx->surfaces)
1319  return AVERROR(ENOMEM);
1320  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
1321  mfxHDLPair *pair = (mfxHDLPair*)src_hwctx->surfaces[i].Data.MemId;
1322  dst_hwctx->surfaces[i] = (IDirect3DSurface9*)pair->first;
1323  }
1324  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
1325  if (src_hwctx->frame_type == MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET)
1326  dst_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget;
1327  else
1328  dst_hwctx->surface_type = DXVA2_VideoProcessorRenderTarget;
1329  }
1330  break;
1331 #endif
1332  default:
1333  return AVERROR(ENOSYS);
1334  }
1335 
1336  return 0;
1337 }
1338 
1340  AVFrame *dst, const AVFrame *src, int flags)
1341 {
1342  QSVFramesContext *s = ctx->internal->priv;
1343  mfxFrameSurface1 *surf = (mfxFrameSurface1*)src->data[3];
1344  AVHWFramesContext *child_frames_ctx;
1345  const AVPixFmtDescriptor *desc;
1346  uint8_t *child_data;
1347  AVFrame *dummy;
1348  int ret = 0;
1349 
1350  if (!s->child_frames_ref)
1351  return AVERROR(ENOSYS);
1352  child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
1353 
1354  switch (child_frames_ctx->device_ctx->type) {
1355 #if CONFIG_VAAPI
1357  {
1358  mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1359  /* pair->first is *VASurfaceID while data[3] in vaapi frame is VASurfaceID, so
1360  * we need this casting for vaapi.
1361  * Add intptr_t to force cast from VASurfaceID(uint) type to pointer(long) type
1362  * to avoid compile warning */
1363  child_data = (uint8_t*)(intptr_t)*(VASurfaceID*)pair->first;
1364  break;
1365  }
1366 #endif
1367 #if CONFIG_D3D11VA
1369  {
1370  mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1371  child_data = pair->first;
1372  break;
1373  }
1374 #endif
1375 #if CONFIG_DXVA2
1377  {
1378  mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1379  child_data = pair->first;
1380  break;
1381  }
1382 #endif
1383  default:
1384  return AVERROR(ENOSYS);
1385  }
1386 
1387  if (dst->format == child_frames_ctx->format) {
1388  ret = ff_hwframe_map_create(s->child_frames_ref,
1389  dst, src, NULL, NULL);
1390  if (ret < 0)
1391  return ret;
1392 
1393  dst->width = src->width;
1394  dst->height = src->height;
1395 
1396  if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
1397  mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1398  dst->data[0] = pair->first;
1399  dst->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? (uint8_t *)0 : pair->second;
1400  } else {
1401  dst->data[3] = child_data;
1402  }
1403 
1404  return 0;
1405  }
1406 
1408  if (desc && desc->flags & AV_PIX_FMT_FLAG_HWACCEL) {
1409  // This only supports mapping to software.
1410  return AVERROR(ENOSYS);
1411  }
1412 
1413  dummy = av_frame_alloc();
1414  if (!dummy)
1415  return AVERROR(ENOMEM);
1416 
1417  dummy->buf[0] = av_buffer_ref(src->buf[0]);
1418  dummy->hw_frames_ctx = av_buffer_ref(s->child_frames_ref);
1419  if (!dummy->buf[0] || !dummy->hw_frames_ctx)
1420  goto fail;
1421 
1422  dummy->format = child_frames_ctx->format;
1423  dummy->width = src->width;
1424  dummy->height = src->height;
1425 
1426  if (child_frames_ctx->device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) {
1427  mfxHDLPair *pair = (mfxHDLPair*)surf->Data.MemId;
1428  dummy->data[0] = pair->first;
1429  dummy->data[1] = pair->second == (mfxMemId)MFX_INFINITE ? (uint8_t *)0 : pair->second;
1430  } else {
1431  dummy->data[3] = child_data;
1432  }
1433 
1434  ret = av_hwframe_map(dst, dummy, flags);
1435 
1436 fail:
1437  av_frame_free(&dummy);
1438 
1439  return ret;
1440 }
1441 
1443  const AVFrame *src)
1444 {
1445  QSVFramesContext *s = ctx->internal->priv;
1446  AVHWFramesContext *child_frames_ctx = (AVHWFramesContext*)s->child_frames_ref->data;
1447  int download = !!src->hw_frames_ctx;
1448  mfxFrameSurface1 *surf = (mfxFrameSurface1*)(download ? src->data[3] : dst->data[3]);
1449 
1450  AVFrame *dummy;
1451  int ret;
1452 
1453  dummy = av_frame_alloc();
1454  if (!dummy)
1455  return AVERROR(ENOMEM);
1456 
1457  dummy->format = child_frames_ctx->format;
1458  dummy->width = src->width;
1459  dummy->height = src->height;
1460  dummy->buf[0] = download ? src->buf[0] : dst->buf[0];
1461  dummy->data[3] = surf->Data.MemId;
1462  dummy->hw_frames_ctx = s->child_frames_ref;
1463 
1464  ret = download ? av_hwframe_transfer_data(dst, dummy, 0) :
1466 
1467  dummy->buf[0] = NULL;
1468  dummy->data[3] = NULL;
1469  dummy->hw_frames_ctx = NULL;
1470 
1471  av_frame_free(&dummy);
1472 
1473  return ret;
1474 }
1475 
1476 static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
1477 {
1478  switch (frame->format) {
1479  case AV_PIX_FMT_NV12:
1480  case AV_PIX_FMT_P010:
1481  surface->Data.Y = frame->data[0];
1482  surface->Data.UV = frame->data[1];
1483  break;
1484 
1485  case AV_PIX_FMT_YUV420P:
1486  surface->Data.Y = frame->data[0];
1487  surface->Data.U = frame->data[1];
1488  surface->Data.V = frame->data[2];
1489  break;
1490 
1491  case AV_PIX_FMT_BGRA:
1492  surface->Data.B = frame->data[0];
1493  surface->Data.G = frame->data[0] + 1;
1494  surface->Data.R = frame->data[0] + 2;
1495  surface->Data.A = frame->data[0] + 3;
1496  break;
1497 #if CONFIG_VAAPI
1498  case AV_PIX_FMT_YUYV422:
1499  surface->Data.Y = frame->data[0];
1500  surface->Data.U = frame->data[0] + 1;
1501  surface->Data.V = frame->data[0] + 3;
1502  break;
1503 
1504  case AV_PIX_FMT_Y210:
1505  surface->Data.Y16 = (mfxU16 *)frame->data[0];
1506  surface->Data.U16 = (mfxU16 *)frame->data[0] + 1;
1507  surface->Data.V16 = (mfxU16 *)frame->data[0] + 3;
1508  break;
1509  case AV_PIX_FMT_VUYX:
1510  surface->Data.V = frame->data[0];
1511  surface->Data.U = frame->data[0] + 1;
1512  surface->Data.Y = frame->data[0] + 2;
1513  // Only set Data.A to a valid address, the SDK doesn't
1514  // use the value from the frame.
1515  surface->Data.A = frame->data[0] + 3;
1516  break;
1517 #endif
1518  default:
1519  return MFX_ERR_UNSUPPORTED;
1520  }
1521  surface->Data.Pitch = frame->linesize[0];
1522  surface->Data.TimeStamp = frame->pts;
1523 
1524  return 0;
1525 }
1526 
1528 {
1529  QSVFramesContext *s = ctx->internal->priv;
1530  atomic_int *inited = upload ? &s->session_upload_init : &s->session_download_init;
1531  mfxSession *session = upload ? &s->session_upload : &s->session_download;
1532  int ret = 0;
1533 
1534  if (atomic_load(inited))
1535  return 0;
1536 
1537 #if HAVE_PTHREADS
1538  pthread_mutex_lock(&s->session_lock);
1539 #endif
1540 
1541  if (!atomic_load(inited)) {
1542  ret = qsv_init_internal_session(ctx, session, upload);
1543  atomic_store(inited, 1);
1544  }
1545 
1546 #if HAVE_PTHREADS
1547  pthread_mutex_unlock(&s->session_lock);
1548 #endif
1549 
1550  return ret;
1551 }
1552 
1554  const AVFrame *src)
1555 {
1556  QSVFramesContext *s = ctx->internal->priv;
1557  mfxFrameSurface1 out = {{ 0 }};
1558  mfxFrameSurface1 *in = (mfxFrameSurface1*)src->data[3];
1559 
1560  mfxSyncPoint sync = NULL;
1561  mfxStatus err;
1562  int ret = 0;
1563  /* download to temp frame if the output is not padded as libmfx requires */
1564  AVFrame *tmp_frame = &s->realigned_download_frame;
1565  AVFrame *dst_frame;
1566  int realigned = 0;
1567 
1569  if (ret < 0)
1570  return ret;
1571 
1572  /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16.
1573  * Height must be a multiple of 16 for progressive frame sequence and a
1574  * multiple of 32 otherwise.", so allign all frames to 16 before downloading. */
1575  if (dst->height & 15 || dst->linesize[0] & 15) {
1576  realigned = 1;
1577  if (tmp_frame->format != dst->format ||
1578  tmp_frame->width != FFALIGN(dst->linesize[0], 16) ||
1579  tmp_frame->height != FFALIGN(dst->height, 16)) {
1580  av_frame_unref(tmp_frame);
1581 
1582  tmp_frame->format = dst->format;
1583  tmp_frame->width = FFALIGN(dst->linesize[0], 16);
1584  tmp_frame->height = FFALIGN(dst->height, 16);
1585  ret = av_frame_get_buffer(tmp_frame, 0);
1586  if (ret < 0)
1587  return ret;
1588  }
1589  }
1590 
1591  dst_frame = realigned ? tmp_frame : dst;
1592 
1593  if (!s->session_download) {
1594  if (s->child_frames_ref)
1595  return qsv_transfer_data_child(ctx, dst_frame, src);
1596 
1597  av_log(ctx, AV_LOG_ERROR, "Surface download not possible\n");
1598  return AVERROR(ENOSYS);
1599  }
1600 
1601  out.Info = in->Info;
1602  map_frame_to_surface(dst_frame, &out);
1603 
1604  do {
1605  err = MFXVideoVPP_RunFrameVPPAsync(s->session_download, in, &out, NULL, &sync);
1606  if (err == MFX_WRN_DEVICE_BUSY)
1607  av_usleep(1);
1608  } while (err == MFX_WRN_DEVICE_BUSY);
1609 
1610  if (err < 0 || !sync) {
1611  av_log(ctx, AV_LOG_ERROR, "Error downloading the surface\n");
1612  return AVERROR_UNKNOWN;
1613  }
1614 
1615  do {
1616  err = MFXVideoCORE_SyncOperation(s->session_download, sync, 1000);
1617  } while (err == MFX_WRN_IN_EXECUTION);
1618  if (err < 0) {
1619  av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation: %d\n", err);
1620  return AVERROR_UNKNOWN;
1621  }
1622 
1623  if (realigned) {
1624  tmp_frame->width = dst->width;
1625  tmp_frame->height = dst->height;
1626  ret = av_frame_copy(dst, tmp_frame);
1627  tmp_frame->width = FFALIGN(dst->linesize[0], 16);
1628  tmp_frame->height = FFALIGN(dst->height, 16);
1629  if (ret < 0)
1630  return ret;
1631  }
1632 
1633  return 0;
1634 }
1635 
1637  const AVFrame *src)
1638 {
1639  QSVFramesContext *s = ctx->internal->priv;
1640  mfxFrameSurface1 in = {{ 0 }};
1641  mfxFrameSurface1 *out = (mfxFrameSurface1*)dst->data[3];
1642  mfxFrameInfo tmp_info;
1643 
1644  mfxSyncPoint sync = NULL;
1645  mfxStatus err;
1646  int ret = 0;
1647  /* make a copy if the input is not padded as libmfx requires */
1648  AVFrame *tmp_frame = &s->realigned_upload_frame;
1649  const AVFrame *src_frame;
1650  int realigned = 0;
1651 
1653  if (ret < 0)
1654  return ret;
1655 
1656  /* According to MSDK spec for mfxframeinfo, "Width must be a multiple of 16.
1657  * Height must be a multiple of 16 for progressive frame sequence and a
1658  * multiple of 32 otherwise.", so allign all frames to 16 before uploading. */
1659  if (src->height & 15 || src->linesize[0] & 15) {
1660  realigned = 1;
1661  if (tmp_frame->format != src->format ||
1662  tmp_frame->width != FFALIGN(src->width, 16) ||
1663  tmp_frame->height != FFALIGN(src->height, 16)) {
1664  av_frame_unref(tmp_frame);
1665 
1666  tmp_frame->format = src->format;
1667  tmp_frame->width = FFALIGN(src->width, 16);
1668  tmp_frame->height = FFALIGN(src->height, 16);
1669  ret = av_frame_get_buffer(tmp_frame, 0);
1670  if (ret < 0)
1671  return ret;
1672  }
1673  ret = av_frame_copy(tmp_frame, src);
1674  if (ret < 0) {
1675  av_frame_unref(tmp_frame);
1676  return ret;
1677  }
1678  ret = qsv_fill_border(tmp_frame, src);
1679  if (ret < 0) {
1680  av_frame_unref(tmp_frame);
1681  return ret;
1682  }
1683 
1684  tmp_info = out->Info;
1685  out->Info.CropW = FFMIN(out->Info.Width, tmp_frame->width);
1686  out->Info.CropH = FFMIN(out->Info.Height, tmp_frame->height);
1687  }
1688 
1689  src_frame = realigned ? tmp_frame : src;
1690 
1691  if (!s->session_upload) {
1692  if (s->child_frames_ref)
1693  return qsv_transfer_data_child(ctx, dst, src_frame);
1694 
1695  av_log(ctx, AV_LOG_ERROR, "Surface upload not possible\n");
1696  return AVERROR(ENOSYS);
1697  }
1698 
1699  in.Info = out->Info;
1700  map_frame_to_surface(src_frame, &in);
1701 
1702  do {
1703  err = MFXVideoVPP_RunFrameVPPAsync(s->session_upload, &in, out, NULL, &sync);
1704  if (err == MFX_WRN_DEVICE_BUSY)
1705  av_usleep(1);
1706  } while (err == MFX_WRN_DEVICE_BUSY);
1707 
1708  if (err < 0 || !sync) {
1709  av_log(ctx, AV_LOG_ERROR, "Error uploading the surface\n");
1710  return AVERROR_UNKNOWN;
1711  }
1712 
1713  do {
1714  err = MFXVideoCORE_SyncOperation(s->session_upload, sync, 1000);
1715  } while (err == MFX_WRN_IN_EXECUTION);
1716  if (err < 0) {
1717  av_log(ctx, AV_LOG_ERROR, "Error synchronizing the operation\n");
1718  return AVERROR_UNKNOWN;
1719  }
1720 
1721  if (realigned) {
1722  out->Info.CropW = tmp_info.CropW;
1723  out->Info.CropH = tmp_info.CropH;
1724  }
1725 
1726  return 0;
1727 }
1728 
1730  AVHWFramesContext *src_ctx, int flags)
1731 {
1732  QSVFramesContext *s = dst_ctx->internal->priv;
1733  AVQSVFramesContext *dst_hwctx = dst_ctx->hwctx;
1734  int i;
1735 
1736  if (src_ctx->initial_pool_size == 0) {
1737  av_log(dst_ctx, AV_LOG_ERROR, "Only fixed-size pools can be "
1738  "mapped to QSV frames.\n");
1739  return AVERROR(EINVAL);
1740  }
1741 
1742  switch (src_ctx->device_ctx->type) {
1743 #if CONFIG_VAAPI
1745  {
1746  AVVAAPIFramesContext *src_hwctx = src_ctx->hwctx;
1747  s->handle_pairs_internal = av_calloc(src_ctx->initial_pool_size,
1748  sizeof(*s->handle_pairs_internal));
1749  if (!s->handle_pairs_internal)
1750  return AVERROR(ENOMEM);
1751  s->surfaces_internal = av_calloc(src_hwctx->nb_surfaces,
1752  sizeof(*s->surfaces_internal));
1753  if (!s->surfaces_internal)
1754  return AVERROR(ENOMEM);
1755  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
1756  qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
1757  s->handle_pairs_internal[i].first = src_hwctx->surface_ids + i;
1758  s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
1759  s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
1760  }
1761  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
1762  dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1763  }
1764  break;
1765 #endif
1766 #if CONFIG_D3D11VA
1768  {
1769  AVD3D11VAFramesContext *src_hwctx = src_ctx->hwctx;
1770  s->handle_pairs_internal = av_calloc(src_ctx->initial_pool_size,
1771  sizeof(*s->handle_pairs_internal));
1772  if (!s->handle_pairs_internal)
1773  return AVERROR(ENOMEM);
1774  s->surfaces_internal = av_calloc(src_ctx->initial_pool_size,
1775  sizeof(*s->surfaces_internal));
1776  if (!s->surfaces_internal)
1777  return AVERROR(ENOMEM);
1778  for (i = 0; i < src_ctx->initial_pool_size; i++) {
1779  qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
1780  s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->texture_infos[i].texture;
1781  if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
1782  s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
1783  } else {
1784  s->handle_pairs_internal[i].second = (mfxMemId)src_hwctx->texture_infos[i].index;
1785  }
1786  s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
1787  }
1788  dst_hwctx->nb_surfaces = src_ctx->initial_pool_size;
1789  if (src_hwctx->BindFlags & D3D11_BIND_RENDER_TARGET) {
1790  dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
1791  } else {
1792  dst_hwctx->frame_type |= MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1793  }
1794  }
1795  break;
1796 #endif
1797 #if CONFIG_DXVA2
1799  {
1800  AVDXVA2FramesContext *src_hwctx = src_ctx->hwctx;
1801  s->handle_pairs_internal = av_calloc(src_ctx->initial_pool_size,
1802  sizeof(*s->handle_pairs_internal));
1803  if (!s->handle_pairs_internal)
1804  return AVERROR(ENOMEM);
1805  s->surfaces_internal = av_calloc(src_hwctx->nb_surfaces,
1806  sizeof(*s->surfaces_internal));
1807  if (!s->surfaces_internal)
1808  return AVERROR(ENOMEM);
1809  for (i = 0; i < src_hwctx->nb_surfaces; i++) {
1810  qsv_init_surface(dst_ctx, &s->surfaces_internal[i]);
1811  s->handle_pairs_internal[i].first = (mfxMemId)src_hwctx->surfaces[i];
1812  s->handle_pairs_internal[i].second = (mfxMemId)MFX_INFINITE;
1813  s->surfaces_internal[i].Data.MemId = (mfxMemId)&s->handle_pairs_internal[i];
1814  }
1815  dst_hwctx->nb_surfaces = src_hwctx->nb_surfaces;
1816  if (src_hwctx->surface_type == DXVA2_VideoProcessorRenderTarget)
1817  dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_PROCESSOR_TARGET;
1818  else
1819  dst_hwctx->frame_type = MFX_MEMTYPE_VIDEO_MEMORY_DECODER_TARGET;
1820  }
1821  break;
1822 #endif
1823  default:
1824  return AVERROR(ENOSYS);
1825  }
1826 
1827  dst_hwctx->surfaces = s->surfaces_internal;
1828 
1829  return 0;
1830 }
1831 
1832 static int qsv_map_to(AVHWFramesContext *dst_ctx,
1833  AVFrame *dst, const AVFrame *src, int flags)
1834 {
1835  AVQSVFramesContext *hwctx = dst_ctx->hwctx;
1836  int i, err, index = -1;
1837 
1838  for (i = 0; i < hwctx->nb_surfaces && index < 0; i++) {
1839  switch(src->format) {
1840 #if CONFIG_VAAPI
1841  case AV_PIX_FMT_VAAPI:
1842  {
1843  mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
1844  if (*(VASurfaceID*)pair->first == (VASurfaceID)src->data[3]) {
1845  index = i;
1846  break;
1847  }
1848  }
1849 #endif
1850 #if CONFIG_D3D11VA
1851  case AV_PIX_FMT_D3D11:
1852  {
1853  mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
1854  if (pair->first == src->data[0]
1855  && (pair->second == src->data[1]
1856  || (pair->second == (mfxMemId)MFX_INFINITE && src->data[1] == (uint8_t *)0))) {
1857  index = i;
1858  break;
1859  }
1860  }
1861 #endif
1862 #if CONFIG_DXVA2
1863  case AV_PIX_FMT_DXVA2_VLD:
1864  {
1865  mfxHDLPair *pair = (mfxHDLPair*)hwctx->surfaces[i].Data.MemId;
1866  if (pair->first == src->data[3]) {
1867  index = i;
1868  break;
1869  }
1870  }
1871 #endif
1872  }
1873  }
1874  if (index < 0) {
1875  av_log(dst_ctx, AV_LOG_ERROR, "Trying to map from a surface which "
1876  "is not in the mapped frames context.\n");
1877  return AVERROR(EINVAL);
1878  }
1879 
1881  dst, src, NULL, NULL);
1882  if (err)
1883  return err;
1884 
1885  dst->width = src->width;
1886  dst->height = src->height;
1887  dst->data[3] = (uint8_t*)&hwctx->surfaces[index];
1888 
1889  return 0;
1890 }
1891 
1893  const void *hwconfig,
1894  AVHWFramesConstraints *constraints)
1895 {
1896  int i;
1897 
1899  sizeof(*constraints->valid_sw_formats));
1900  if (!constraints->valid_sw_formats)
1901  return AVERROR(ENOMEM);
1902 
1903  for (i = 0; i < FF_ARRAY_ELEMS(supported_pixel_formats); i++)
1904  constraints->valid_sw_formats[i] = supported_pixel_formats[i].pix_fmt;
1906 
1907  constraints->valid_hw_formats = av_malloc_array(2, sizeof(*constraints->valid_hw_formats));
1908  if (!constraints->valid_hw_formats)
1909  return AVERROR(ENOMEM);
1910 
1911  constraints->valid_hw_formats[0] = AV_PIX_FMT_QSV;
1912  constraints->valid_hw_formats[1] = AV_PIX_FMT_NONE;
1913 
1914  return 0;
1915 }
1916 
1918 {
1919  AVQSVDeviceContext *hwctx = ctx->hwctx;
1920  QSVDevicePriv *priv = ctx->user_opaque;
1921 
1922  if (hwctx->session)
1923  MFXClose(hwctx->session);
1924 
1925  if (hwctx->loader)
1926  MFXUnload(hwctx->loader);
1928  av_freep(&priv);
1929 }
1930 
1931 static mfxIMPL choose_implementation(const char *device, enum AVHWDeviceType child_device_type)
1932 {
1933  static const struct {
1934  const char *name;
1935  mfxIMPL impl;
1936  } impl_map[] = {
1937  { "auto", MFX_IMPL_AUTO },
1938  { "sw", MFX_IMPL_SOFTWARE },
1939  { "hw", MFX_IMPL_HARDWARE },
1940  { "auto_any", MFX_IMPL_AUTO_ANY },
1941  { "hw_any", MFX_IMPL_HARDWARE_ANY },
1942  { "hw2", MFX_IMPL_HARDWARE2 },
1943  { "hw3", MFX_IMPL_HARDWARE3 },
1944  { "hw4", MFX_IMPL_HARDWARE4 },
1945  };
1946 
1947  mfxIMPL impl = MFX_IMPL_AUTO_ANY;
1948  int i;
1949 
1950  if (device) {
1951  for (i = 0; i < FF_ARRAY_ELEMS(impl_map); i++)
1952  if (!strcmp(device, impl_map[i].name)) {
1953  impl = impl_map[i].impl;
1954  break;
1955  }
1956  if (i == FF_ARRAY_ELEMS(impl_map))
1957  impl = strtol(device, NULL, 0);
1958  }
1959 
1960  if (impl != MFX_IMPL_SOFTWARE) {
1961  if (child_device_type == AV_HWDEVICE_TYPE_D3D11VA)
1962  impl |= MFX_IMPL_VIA_D3D11;
1963  else if (child_device_type == AV_HWDEVICE_TYPE_DXVA2)
1964  impl |= MFX_IMPL_VIA_D3D9;
1965  }
1966 
1967  return impl;
1968 }
1969 
1971  mfxIMPL implementation,
1972  AVHWDeviceContext *child_device_ctx,
1973  int flags)
1974 {
1975  AVQSVDeviceContext *hwctx = ctx->hwctx;
1976 
1977  mfxVersion ver = { { 3, 1 } };
1978  mfxHDL handle;
1979  mfxHandleType handle_type;
1980  mfxStatus err;
1981  int ret;
1982 
1983  switch (child_device_ctx->type) {
1984 #if CONFIG_VAAPI
1986  {
1987  AVVAAPIDeviceContext *child_device_hwctx = child_device_ctx->hwctx;
1988  handle_type = MFX_HANDLE_VA_DISPLAY;
1989  handle = (mfxHDL)child_device_hwctx->display;
1990  }
1991  break;
1992 #endif
1993 #if CONFIG_D3D11VA
1995  {
1996  AVD3D11VADeviceContext *child_device_hwctx = child_device_ctx->hwctx;
1997  handle_type = MFX_HANDLE_D3D11_DEVICE;
1998  handle = (mfxHDL)child_device_hwctx->device;
1999  }
2000  break;
2001 #endif
2002 #if CONFIG_DXVA2
2004  {
2005  AVDXVA2DeviceContext *child_device_hwctx = child_device_ctx->hwctx;
2006  handle_type = MFX_HANDLE_D3D9_DEVICE_MANAGER;
2007  handle = (mfxHDL)child_device_hwctx->devmgr;
2008  }
2009  break;
2010 #endif
2011  default:
2012  ret = AVERROR(ENOSYS);
2013  goto fail;
2014  }
2015 
2016  ret = qsv_create_mfx_session(ctx, handle, handle_type, implementation, &ver,
2017  &hwctx->session, &hwctx->loader);
2018  if (ret)
2019  goto fail;
2020 
2021  err = MFXVideoCORE_SetHandle(hwctx->session, handle_type, handle);
2022  if (err != MFX_ERR_NONE) {
2023  av_log(ctx, AV_LOG_ERROR, "Error setting child device handle: "
2024  "%d\n", err);
2025  ret = AVERROR_UNKNOWN;
2026  goto fail;
2027  }
2028 
2029  return 0;
2030 
2031 fail:
2032  if (hwctx->session)
2033  MFXClose(hwctx->session);
2034 
2035  if (hwctx->loader)
2036  MFXUnload(hwctx->loader);
2037 
2038  hwctx->session = NULL;
2039  hwctx->loader = NULL;
2040  return ret;
2041 }
2042 
2044  AVHWDeviceContext *child_device_ctx,
2045  AVDictionary *opts, int flags)
2046 {
2047  mfxIMPL impl;
2048  impl = choose_implementation("hw_any", child_device_ctx->type);
2049  return qsv_device_derive_from_child(ctx, impl,
2050  child_device_ctx, flags);
2051 }
2052 
2053 static int qsv_device_create(AVHWDeviceContext *ctx, const char *device,
2054  AVDictionary *opts, int flags)
2055 {
2056  QSVDevicePriv *priv;
2057  enum AVHWDeviceType child_device_type;
2058  AVHWDeviceContext *child_device;
2059  AVDictionary *child_device_opts;
2060  AVDictionaryEntry *e;
2061 
2062  mfxIMPL impl;
2063  int ret;
2064 
2065  priv = av_mallocz(sizeof(*priv));
2066  if (!priv)
2067  return AVERROR(ENOMEM);
2068 
2069  ctx->user_opaque = priv;
2070  ctx->free = qsv_device_free;
2071 
2072  e = av_dict_get(opts, "child_device_type", NULL, 0);
2073  if (e) {
2074  child_device_type = av_hwdevice_find_type_by_name(e->value);
2075  if (child_device_type == AV_HWDEVICE_TYPE_NONE) {
2076  av_log(ctx, AV_LOG_ERROR, "Unknown child device type "
2077  "\"%s\".\n", e->value);
2078  return AVERROR(EINVAL);
2079  }
2080  } else if (CONFIG_VAAPI) {
2081  child_device_type = AV_HWDEVICE_TYPE_VAAPI;
2082 #if QSV_ONEVPL
2083  } else if (CONFIG_D3D11VA) { // Use D3D11 by default if d3d11va is enabled
2085  "Defaulting child_device_type to AV_HWDEVICE_TYPE_D3D11VA for oneVPL."
2086  "Please explicitly set child device type via \"-init_hw_device\" "
2087  "option if needed.\n");
2088  child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
2089  } else if (CONFIG_DXVA2) {
2090  child_device_type = AV_HWDEVICE_TYPE_DXVA2;
2091 #else
2092  } else if (CONFIG_DXVA2) {
2094  "WARNING: defaulting child_device_type to AV_HWDEVICE_TYPE_DXVA2 for compatibility "
2095  "with old commandlines. This behaviour will be removed "
2096  "in the future. Please explicitly set device type via \"-init_hw_device\" option.\n");
2097  child_device_type = AV_HWDEVICE_TYPE_DXVA2;
2098  } else if (CONFIG_D3D11VA) {
2099  child_device_type = AV_HWDEVICE_TYPE_D3D11VA;
2100 #endif
2101  } else {
2102  av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
2103  return AVERROR(ENOSYS);
2104  }
2105 
2106  child_device_opts = NULL;
2107  switch (child_device_type) {
2108 #if CONFIG_VAAPI
2110  {
2111  // libmfx does not actually implement VAAPI properly, rather it
2112  // depends on the specific behaviour of a matching iHD driver when
2113  // used on recent Intel hardware. Set options to the VAAPI device
2114  // creation so that we should pick a usable setup by default if
2115  // possible, even when multiple devices and drivers are available.
2116  av_dict_set(&child_device_opts, "kernel_driver", "i915", 0);
2117  av_dict_set(&child_device_opts, "driver", "iHD", 0);
2118  }
2119  break;
2120 #endif
2121 #if CONFIG_D3D11VA
2123  break;
2124 #endif
2125 #if CONFIG_DXVA2
2127 #if QSV_ONEVPL
2128  {
2130  "d3d11va is not available or child device type is set to dxva2 "
2131  "explicitly for oneVPL.\n");
2132  }
2133 #endif
2134  break;
2135 #endif
2136  default:
2137  {
2138  av_log(ctx, AV_LOG_ERROR, "No supported child device type is enabled\n");
2139  return AVERROR(ENOSYS);
2140  }
2141  break;
2142  }
2143 
2144  e = av_dict_get(opts, "child_device", NULL, 0);
2145  ret = av_hwdevice_ctx_create(&priv->child_device_ctx, child_device_type,
2146  e ? e->value : NULL, child_device_opts, 0);
2147 
2148  av_dict_free(&child_device_opts);
2149  if (ret < 0)
2150  return ret;
2151 
2152  child_device = (AVHWDeviceContext*)priv->child_device_ctx->data;
2153 
2154  impl = choose_implementation(device, child_device_type);
2155 
2156  return qsv_device_derive_from_child(ctx, impl, child_device, 0);
2157 }
2158 
2161  .name = "QSV",
2162 
2163  .device_hwctx_size = sizeof(AVQSVDeviceContext),
2164  .device_priv_size = sizeof(QSVDeviceContext),
2165  .frames_hwctx_size = sizeof(AVQSVFramesContext),
2166  .frames_priv_size = sizeof(QSVFramesContext),
2167 
2168  .device_create = qsv_device_create,
2169  .device_derive = qsv_device_derive,
2170  .device_init = qsv_device_init,
2171  .frames_get_constraints = qsv_frames_get_constraints,
2172  .frames_init = qsv_frames_init,
2173  .frames_uninit = qsv_frames_uninit,
2174  .frames_get_buffer = qsv_get_buffer,
2175  .transfer_get_formats = qsv_transfer_get_formats,
2176  .transfer_data_to = qsv_transfer_data_to,
2177  .transfer_data_from = qsv_transfer_data_from,
2178  .map_to = qsv_map_to,
2179  .map_from = qsv_map_from,
2180  .frames_derive_to = qsv_frames_derive_to,
2181  .frames_derive_from = qsv_frames_derive_from,
2182 
2183  .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_QSV, AV_PIX_FMT_NONE },
2184 };
formats
formats
Definition: signature.h:48
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
AVHWDeviceContext::hwctx
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:92
qsv_transfer_data_child
static int qsv_transfer_data_child(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_qsv.c:1442
AVQSVFramesContext::frame_type
int frame_type
A combination of MFX_MEMTYPE_* describing the frame pool.
Definition: hwcontext_qsv.h:60
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
atomic_store
#define atomic_store(object, desired)
Definition: stdatomic.h:85
AVERROR
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
out
FILE * out
Definition: movenc.c:54
av_frame_get_buffer
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:259
comp
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:86
QSVFramesContext::child_frames_ref
AVBufferRef * child_frames_ref
Definition: hwcontext_qsv.c:91
qsv_transfer_data_to
static int qsv_transfer_data_to(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_qsv.c:1636
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2858
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
qsv_map_from
static int qsv_map_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_qsv.c:1339
qsv_fourcc_from_pix_fmt
static uint32_t qsv_fourcc_from_pix_fmt(enum AVPixelFormat pix_fmt)
Definition: hwcontext_qsv.c:163
supported_pixel_formats
static const struct @320 supported_pixel_formats[]
AVHWFramesContext::format
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:209
qsv_fill_border
static int qsv_fill_border(AVFrame *dst, const AVFrame *src)
Definition: hwcontext_qsv.c:190
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
QSVDeviceContext::ver
mfxVersion ver
Definition: hwcontext_qsv.c:75
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:334
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:325
pixdesc.h
AVFrame::width
int width
Definition: frame.h:397
AVQSVDeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_qsv.h:35
AVD3D11VAFramesContext::MiscFlags
UINT MiscFlags
D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation.
Definition: hwcontext_d3d11va.h:166
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:248
qsv_device_derive
static int qsv_device_derive(AVHWDeviceContext *ctx, AVHWDeviceContext *child_device_ctx, AVDictionary *opts, int flags)
Definition: hwcontext_qsv.c:2043
AVDXVA2FramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_dxva2.h:46
qsv_frames_derive_from
static int qsv_frames_derive_from(AVHWFramesContext *dst_ctx, AVHWFramesContext *src_ctx, int flags)
Definition: hwcontext_qsv.c:1267
AV_HWDEVICE_TYPE_NONE
@ AV_HWDEVICE_TYPE_NONE
Definition: hwcontext.h:28
av_hwframe_map
int av_hwframe_map(AVFrame *dst, const AVFrame *src, int flags)
Map a hardware frame.
Definition: hwcontext.c:790
qsv_init_surface
static int qsv_init_surface(AVHWFramesContext *ctx, mfxFrameSurface1 *surf)
Definition: hwcontext_qsv.c:491
data
const char data[16]
Definition: mxf.c:146
atomic_int
intptr_t atomic_int
Definition: stdatomic.h:55
choose_implementation
static mfxIMPL choose_implementation(const char *device, enum AVHWDeviceType child_device_type)
Definition: hwcontext_qsv.c:1931
QSVDeviceContext
Definition: hwcontext_qsv.c:72
av_hwdevice_find_type_by_name
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition: hwcontext.c:83
AVDXVA2DeviceContext::devmgr
IDirect3DDeviceManager9 * devmgr
Definition: hwcontext_dxva2.h:40
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
AVVAAPIDeviceContext::display
VADisplay display
The VADisplay handle, to be filled by the user.
Definition: hwcontext_vaapi.h:72
AV_PIX_FMT_BGRA
@ AV_PIX_FMT_BGRA
packed BGRA 8:8:8:8, 32bpp, BGRABGRA...
Definition: pixfmt.h:95
AVHWFramesContext::internal
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:134
AVDictionary
Definition: dict.c:31
ff_hwframe_map_create
int ff_hwframe_map_create(AVBufferRef *hwframe_ref, AVFrame *dst, const AVFrame *src, void(*unmap)(AVHWFramesContext *ctx, HWMapDescriptor *hwmap), void *priv)
Definition: hwcontext.c:738
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVHWFramesConstraints::valid_hw_formats
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:458
AVERROR_UNKNOWN
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
Definition: error.h:73
AVHWFramesContext::width
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:229
fourcc
uint32_t fourcc
Definition: hwcontext_qsv.c:111
av_hwdevice_ctx_init
int av_hwdevice_ctx_init(AVBufferRef *ref)
Finalize the device context before use.
Definition: hwcontext.c:201
AVFrame::buf
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:525
QSVDeviceContext::handle_type
mfxHandleType handle_type
Definition: hwcontext_qsv.c:74
qsv_transfer_data_from
static int qsv_transfer_data_from(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
Definition: hwcontext_qsv.c:1553
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:346
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
QSVDevicePriv
Definition: hwcontext_qsv.c:68
AVD3D11VAFramesContext::BindFlags
UINT BindFlags
D3D11_TEXTURE2D_DESC.BindFlags used for texture creation.
Definition: hwcontext_d3d11va.h:160
AVVAAPIFramesContext::surface_ids
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
Definition: hwcontext_vaapi.h:101
AVHWFramesInternal::priv
void * priv
Definition: hwcontext_internal.h:116
AVD3D11FrameDescriptor::texture
ID3D11Texture2D * texture
The texture in which the frame is located.
Definition: hwcontext_d3d11va.h:117
QSVDeviceContext::child_device_type
enum AVHWDeviceType child_device_type
Definition: hwcontext_qsv.c:78
qsv_init_child_ctx
static int qsv_init_child_ctx(AVHWFramesContext *ctx)
Definition: hwcontext_qsv.c:346
fail
#define fail()
Definition: checkasm.h:133
AV_PIX_FMT_FLAG_HWACCEL
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition: pixdesc.h:128
dummy
int dummy
Definition: motion.c:65
AV_HWDEVICE_TYPE_D3D11VA
@ AV_HWDEVICE_TYPE_D3D11VA
Definition: hwcontext.h:35
qsv_frames_get_constraints
static int qsv_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
Definition: hwcontext_qsv.c:1892
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
QSVFramesContext::session_download_init
atomic_int session_download_init
Definition: hwcontext_qsv.c:84
qsv_frames_derive_to
static int qsv_frames_derive_to(AVHWFramesContext *dst_ctx, AVHWFramesContext *src_ctx, int flags)
Definition: hwcontext_qsv.c:1729
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:104
frame_free
static mfxStatus frame_free(mfxHDL pthis, mfxFrameAllocResponse *resp)
Definition: hwcontext_qsv.c:606
AV_PIX_FMT_Y210
#define AV_PIX_FMT_Y210
Definition: pixfmt.h:484
avassert.h
HWContextType::type
enum AVHWDeviceType type
Definition: hwcontext_internal.h:30
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
AVHWFramesContext::height
int height
Definition: hwcontext.h:229
av_hwdevice_ctx_alloc
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given hardware type.
Definition: hwcontext.c:143
AVHWFramesConstraints::valid_sw_formats
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:465
QSVFramesContext::ext_buffers
mfxExtBuffer * ext_buffers[1]
Definition: hwcontext_qsv.c:103
QSVFramesContext::session_upload_init
atomic_int session_upload_init
Definition: hwcontext_qsv.c:86
frame_alloc
static mfxStatus frame_alloc(mfxHDL pthis, mfxFrameAllocRequest *req, mfxFrameAllocResponse *resp)
Definition: hwcontext_qsv.c:578
av_dict_get
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:41
av_memcpy_backptr
void av_memcpy_backptr(uint8_t *dst, int back, int cnt)
Overlapping memcpy() implementation.
Definition: mem.c:455
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:384
QSVDevicePriv::child_device_ctx
AVBufferRef * child_device_ctx
Definition: hwcontext_qsv.c:69
AV_PIX_FMT_DXVA2_VLD
@ AV_PIX_FMT_DXVA2_VLD
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer.
Definition: pixfmt.h:127
s
#define s(width, name)
Definition: cbs_vp9.c:256
AVD3D11VADeviceContext::device
ID3D11Device * device
Device used for texture creation and access.
Definition: hwcontext_d3d11va.h:56
AV_CEIL_RSHIFT
#define AV_CEIL_RSHIFT(a, b)
Definition: common.h:50
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
AVHWDeviceType
AVHWDeviceType
Definition: hwcontext.h:27
QSVDeviceContext::handle
mfxHDL handle
Definition: hwcontext_qsv.c:73
QSVFramesContext::mem_ids
mfxMemId * mem_ids
Definition: hwcontext_qsv.c:97
ctx
AVFormatContext * ctx
Definition: movenc.c:48
AVDXVA2FramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_dxva2.h:59
AV_PIX_FMT_YUV420P
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition: pixfmt.h:66
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
atomic_load
#define atomic_load(object)
Definition: stdatomic.h:93
MFXUnload
#define MFXUnload(a)
Definition: hwcontext_qsv.c:65
if
if(ret)
Definition: filter_design.txt:179
ff_hwcontext_type_qsv
const HWContextType ff_hwcontext_type_qsv
Definition: hwcontext_qsv.c:2159
qsv_create_mfx_session
static int qsv_create_mfx_session(void *ctx, mfxHDL handle, mfxHandleType handle_type, mfxIMPL implementation, mfxVersion *pver, mfxSession *psession, void **ploader)
Definition: hwcontext_qsv.c:1005
opts
AVDictionary * opts
Definition: movenc.c:50
AVD3D11VAFramesContext::texture_infos
AVD3D11FrameDescriptor * texture_infos
In case if texture structure member above is not NULL contains the same texture pointer for all eleme...
Definition: hwcontext_d3d11va.h:175
AVQSVFramesContext::surfaces
mfxFrameSurface1 * surfaces
Definition: hwcontext_qsv.h:54
NULL
#define NULL
Definition: coverity.c:32
AVHWFramesContext::sw_format
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:222
qsv_frames_uninit
static void qsv_frames_uninit(AVHWFramesContext *ctx)
Definition: hwcontext_qsv.c:294
av_buffer_unref
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:139
AVComponentDescriptor
Definition: pixdesc.h:30
AV_HWDEVICE_TYPE_DXVA2
@ AV_HWDEVICE_TYPE_DXVA2
Definition: hwcontext.h:32
AV_PIX_FMT_YUYV422
@ AV_PIX_FMT_YUYV422
packed YUV 4:2:2, 16bpp, Y0 Cb Y1 Cr
Definition: pixfmt.h:67
MFX_IMPL_VIA_MASK
#define MFX_IMPL_VIA_MASK(impl)
Definition: hwcontext_qsv.c:58
qsv_internal_session_check_init
static int qsv_internal_session_check_init(AVHWFramesContext *ctx, int upload)
Definition: hwcontext_qsv.c:1527
qsv_frames_init
static int qsv_frames_init(AVHWFramesContext *ctx)
Definition: hwcontext_qsv.c:1163
time.h
AV_PIX_FMT_QSV
@ AV_PIX_FMT_QSV
HW acceleration through QSV, data[3] contains a pointer to the mfxFrameSurface1 structure.
Definition: pixfmt.h:212
map_frame_to_surface
static int map_frame_to_surface(const AVFrame *frame, mfxFrameSurface1 *surface)
Definition: hwcontext_qsv.c:1476
frame_unlock
static mfxStatus frame_unlock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: hwcontext_qsv.c:616
index
int index
Definition: gxfenc.c:89
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:78
AVD3D11VAFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_d3d11va.h:131
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
QSVFramesContext::realigned_upload_frame
AVFrame realigned_upload_frame
Definition: hwcontext_qsv.c:105
qsv_init_internal_session
static int qsv_init_internal_session(AVHWFramesContext *ctx, mfxSession *session, int upload)
Definition: hwcontext_qsv.c:1064
hwcontext_dxva2.h
QSVFramesContext::opaque_alloc
mfxExtOpaqueSurfaceAlloc opaque_alloc
Definition: hwcontext_qsv.c:102
qsv_get_buffer
static int qsv_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
Definition: hwcontext_qsv.c:1235
AVDXVA2FramesContext::surface_type
DWORD surface_type
The surface type (e.g.
Definition: hwcontext_dxva2.h:51
av_frame_copy
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition: frame.c:771
size
int size
Definition: twinvq_data.h:10344
QSVFramesContext::nb_surfaces_used
int nb_surfaces_used
Definition: hwcontext_qsv.c:94
qsv_device_free
static void qsv_device_free(AVHWDeviceContext *ctx)
Definition: hwcontext_qsv.c:1917
AVFrame::format
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:412
ff_qsv_get_surface_base_handle
int ff_qsv_get_surface_base_handle(mfxFrameSurface1 *surf, enum AVHWDeviceType base_dev_type, void **base_handle)
Caller needs to allocate enough space for base_handle pointer.
Definition: hwcontext_qsv.c:136
qsv_transfer_get_formats
static int qsv_transfer_get_formats(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
Definition: hwcontext_qsv.c:1249
buffer.h
qsv_device_derive_from_child
static int qsv_device_derive_from_child(AVHWDeviceContext *ctx, mfxIMPL implementation, AVHWDeviceContext *child_device_ctx, int flags)
Definition: hwcontext_qsv.c:1970
AVQSVDeviceContext::loader
void * loader
The mfxLoader handle used for mfxSession creation.
Definition: hwcontext_qsv.h:47
AV_PIX_FMT_D3D11
@ AV_PIX_FMT_D3D11
Hardware surfaces for Direct3D11.
Definition: pixfmt.h:305
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:208
AVQSVFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_qsv.h:55
frame_get_hdl
static mfxStatus frame_get_hdl(mfxHDL pthis, mfxMemId mid, mfxHDL *hdl)
Definition: hwcontext_qsv.c:621
AV_PIX_FMT_VAAPI
@ AV_PIX_FMT_VAAPI
Hardware acceleration through VA-API, data[3] contains a VASurfaceID.
Definition: pixfmt.h:119
AV_HWDEVICE_TYPE_VAAPI
@ AV_HWDEVICE_TYPE_VAAPI
Definition: hwcontext.h:31
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
av_image_get_linesize
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane.
Definition: imgutils.c:76
hwcontext_qsv.h
qsv_device_init
static int qsv_device_init(AVHWDeviceContext *ctx)
Definition: hwcontext_qsv.c:238
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVDXVA2DeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_dxva2.h:39
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
common.h
AVD3D11VADeviceContext
This struct is allocated as AVHWDeviceContext.hwctx.
Definition: hwcontext_d3d11va.h:45
QSVFramesContext::handle_pairs_internal
mfxHDLPair * handle_pairs_internal
Definition: hwcontext_qsv.c:93
AVD3D11FrameDescriptor::index
intptr_t index
The index into the array texture element representing the frame, or 0 if the texture is not an array ...
Definition: hwcontext_d3d11va.h:125
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
QSVFramesContext::surface_ptrs
mfxFrameSurface1 ** surface_ptrs
Definition: hwcontext_qsv.c:100
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:487
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:264
QSVFramesContext::session_download
mfxSession session_download
Definition: hwcontext_qsv.c:83
AVDXVA2FramesContext::surfaces
IDirect3DSurface9 ** surfaces
The surface pool.
Definition: hwcontext_dxva2.h:58
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
AVHWFrameTransferDirection
AVHWFrameTransferDirection
Definition: hwcontext.h:415
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
hwcontext_vaapi.h
qsv_map_to
static int qsv_map_to(AVHWFramesContext *dst_ctx, AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext_qsv.c:1832
AV_PIX_FMT_PAL8
@ AV_PIX_FMT_PAL8
8 bits with AV_PIX_FMT_RGB32 palette
Definition: pixfmt.h:77
ret
ret
Definition: filter_design.txt:187
pix_fmt
enum AVPixelFormat pix_fmt
Definition: hwcontext_qsv.c:110
AVHWDeviceContext::type
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:79
pixfmt.h
AV_PIX_FMT_NV12
@ AV_PIX_FMT_NV12
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
frame
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
Definition: filter_design.txt:264
AVHWFramesContext::device_ctx
AVHWDeviceContext * device_ctx
The parent AVHWDeviceContext.
Definition: hwcontext.h:149
AVHWFramesContext::hwctx
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:162
av_hwdevice_ctx_create
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:611
QSVDeviceContext::impl
mfxIMPL impl
Definition: hwcontext_qsv.c:76
QSVFramesContext::realigned_download_frame
AVFrame realigned_download_frame
Definition: hwcontext_qsv.c:106
av_hwframe_transfer_data
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:444
frame_lock
static mfxStatus frame_lock(mfxHDL pthis, mfxMemId mid, mfxFrameData *ptr)
Definition: hwcontext_qsv.c:611
AVFrame::hw_frames_ctx
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame.
Definition: frame.h:664
AV_HWDEVICE_TYPE_QSV
@ AV_HWDEVICE_TYPE_QSV
Definition: hwcontext.h:33
qsv_pool_release_dummy
static void qsv_pool_release_dummy(void *opaque, uint8_t *data)
Definition: hwcontext_qsv.c:327
AVFrame::height
int height
Definition: frame.h:397
QSVDeviceContext::child_pix_fmt
enum AVPixelFormat child_pix_fmt
Definition: hwcontext_qsv.c:79
AVVAAPIFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_vaapi.h:102
AVQSVDeviceContext::session
mfxSession session
Definition: hwcontext_qsv.h:36
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
QSVFramesContext::session_upload
mfxSession session_upload
Definition: hwcontext_qsv.c:85
qsv_device_create
static int qsv_device_create(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
Definition: hwcontext_qsv.c:2053
AV_PIX_FMT_P010
#define AV_PIX_FMT_P010
Definition: pixfmt.h:480
AVQSVFramesContext
This struct is allocated as AVHWFramesContext.hwctx.
Definition: hwcontext_qsv.h:53
AVHWFramesContext::initial_pool_size
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:199
desc
const char * desc
Definition: libsvtav1.c:83
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
hwcontext_internal.h
AVVAAPIFramesContext
VAAPI-specific data associated with a frame pool.
Definition: hwcontext_vaapi.h:88
QSVFramesContext::surfaces_internal
mfxFrameSurface1 * surfaces_internal
Definition: hwcontext_qsv.c:92
AVDictionaryEntry
Definition: dict.h:79
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
QSVFramesContext
Definition: qsv_internal.h:109
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
av_dict_set
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:71
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
imgutils.h
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
hwcontext.h
AVFrame::linesize
int linesize[AV_NUM_DATA_POINTERS]
For video, a positive or negative value, which is typically indicating the size in bytes of each pict...
Definition: frame.h:370
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
HWContextType
Definition: hwcontext_internal.h:29
qsv_pool_alloc
static AVBufferRef * qsv_pool_alloc(void *opaque, size_t size)
Definition: hwcontext_qsv.c:331
ID3D11Device
void ID3D11Device
Definition: nvenc.h:28
AVVAAPIDeviceContext
VAAPI connection details.
Definition: hwcontext_vaapi.h:68
AVDictionaryEntry::value
char * value
Definition: dict.h:81
AV_PIX_FMT_VUYX
@ AV_PIX_FMT_VUYX
packed VUYX 4:4:4, 32bpp, Variant of VUYA where alpha channel is left undefined
Definition: pixfmt.h:375
hwcontext_d3d11va.h
qsv_init_pool
static int qsv_init_pool(AVHWFramesContext *ctx, uint32_t fourcc)
Definition: hwcontext_qsv.c:527
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:74