History

lavu: add new D3D11 pixfmt and hwcontext

To be used with the new d3d11 hwaccel decode API. With the new hwaccel API, we don't want surfaces to depend on the decoder (other than the required dimension and format). The old D3D11VA pixfmt uses ID3D11VideoDecoderOutputView pointers, which include the decoder configuration, and thus is incompatible with the new hwaccel API. This patch introduces AV_PIX_FMT_D3D11, which uses ID3D11Texture2D and an index. It's simpler and compatible with the new hwaccel API. The introduced hwcontext supports only the new pixfmt. Frame upload code untested. Significantly based on work by Steve Lhomme <robux4@gmail.com>, but with heavy changes/rewrites.

wm4 committed 9 years ago

Commit fff90421 parent ed434be10 files · +681 −3Browse files

Unified · Split

10 files
  1. doc/APIchanges +3 −0
  2. libavutil/Makefile +3 −0
  3. libavutil/hwcontext.c +4 −0
  4. libavutil/hwcontext.h +1 −0
  5. libavutil/hwcontext_d3d11va.c +490 −0
  6. libavutil/hwcontext_d3d11va.h +160 −0
  7. libavutil/hwcontext_internal.h +1 −0
  8. libavutil/pixdesc.c +4 −0
  9. libavutil/pixfmt.h +13 −1
  10. libavutil/version.h +2 −2
doc/APIchanges+3−0
@@ -13,6 +13,9 @@ libavutil: 2017-03-23 · 12 unmodified lines
1313
1414 API changes, most recent first:
1515
16+2017-xx-xx - xxxxxxx - lavu 56.2.0 - hwcontext.h
17+ Add AV_HWDEVICE_TYPE_D3D11VA and AV_PIX_FMT_D3D11.
18+
1619 2017-04-30 - xxxxxxx - lavu 56.1.1 - hwcontext.h
1720 av_hwframe_ctx_create_derived() now takes some AV_HWFRAME_MAP_* combination
1821 as its flags argument (which was previously unused).
libavutil/Makefile+3−0
@@ -27,6 +27,7 @@ HEADERS = adler32.h \ · 26 unmodified lines
2727 hmac.h \
2828 hwcontext.h \
2929 hwcontext_cuda.h \
30+ hwcontext_d3d11va.h \
3031 hwcontext_dxva2.h \
3132 hwcontext_qsv.h \
3233 hwcontext_vaapi.h \
@@ -112,6 +113,7 @@ OBJS = adler32.o \ · 79 unmodified lines
112113 xtea.o \
113114
114115 OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
116+OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
115117 OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
116118 OBJS-$(CONFIG_LIBMFX) += hwcontext_qsv.o
117119 OBJS-$(CONFIG_LZO) += lzo.o
@@ -121,6 +123,7 @@ OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o · 3 unmodified lines
121123 OBJS += $(COMPAT_OBJS:%=../compat/%)
122124
123125 SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda.h
126+SKIPHEADERS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.h
124127 SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h
125128 SKIPHEADERS-$(CONFIG_LIBMFX) += hwcontext_qsv.h
126129 SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h
libavutil/hwcontext.c+4−0
@@ -32,6 +32,9 @@ static const HWContextType * const hw_table[] = { · 31 unmodified lines
3232 #if CONFIG_CUDA
3333 &ff_hwcontext_type_cuda,
3434 #endif
35+#if CONFIG_D3D11VA
36+ &ff_hwcontext_type_d3d11va,
37+#endif
3538 #if CONFIG_DXVA2
3639 &ff_hwcontext_type_dxva2,
3740 #endif
@@ -50,6 +53,7 @@ static const HWContextType * const hw_table[] = { · 12 unmodified lines
5053 const char *hw_type_names[] = {
5154 [AV_HWDEVICE_TYPE_CUDA] = "cuda",
5255 [AV_HWDEVICE_TYPE_DXVA2] = "dxva2",
56+ [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
5357 [AV_HWDEVICE_TYPE_QSV] = "qsv",
5458 [AV_HWDEVICE_TYPE_VAAPI] = "vaapi",
5559 [AV_HWDEVICE_TYPE_VDPAU] = "vdpau",
libavutil/hwcontext.h+1−0
@@ -31,6 +31,7 @@ enum AVHWDeviceType { · 30 unmodified lines
3131 AV_HWDEVICE_TYPE_VAAPI,
3232 AV_HWDEVICE_TYPE_DXVA2,
3333 AV_HWDEVICE_TYPE_QSV,
34+ AV_HWDEVICE_TYPE_D3D11VA,
3435 };
3536
3637 typedef struct AVHWDeviceInternal AVHWDeviceInternal;
libavutil/hwcontext_d3d11va.c+490−0
@@ -0,0 +1,490 @@
1+/*
2+ * This file is part of Libav.
3+ *
4+ * Libav 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+ * Libav 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 Libav; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#include <windows.h>
20+
21+#if !defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600
22+#undef _WIN32_WINNT
23+#define _WIN32_WINNT 0x0600
24+#endif
25+#define COBJMACROS
26+
27+#include <initguid.h>
28+#include <d3d11.h>
29+#include <dxgi1_2.h>
30+
31+#include "avassert.h"
32+#include "common.h"
33+#include "hwcontext.h"
34+#include "hwcontext_d3d11va.h"
35+#include "hwcontext_internal.h"
36+#include "imgutils.h"
37+#include "pixdesc.h"
38+#include "pixfmt.h"
39+
40+typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
41+
42+typedef struct D3D11VAFramesContext {
43+ int nb_surfaces_used;
44+
45+ DXGI_FORMAT format;
46+
47+ ID3D11Texture2D *staging_texture;
48+} D3D11VAFramesContext;
49+
50+static const struct {
51+ DXGI_FORMAT d3d_format;
52+ enum AVPixelFormat pix_fmt;
53+} supported_formats[] = {
54+ { DXGI_FORMAT_NV12, AV_PIX_FMT_NV12 },
55+ { DXGI_FORMAT_P010, AV_PIX_FMT_P010 },
56+};
57+
58+static void d3d11va_default_lock(void *ctx)
59+{
60+ WaitForSingleObjectEx(ctx, INFINITE, FALSE);
61+}
62+
63+static void d3d11va_default_unlock(void *ctx)
64+{
65+ ReleaseMutex(ctx);
66+}
67+
68+static void d3d11va_frames_uninit(AVHWFramesContext *ctx)
69+{
70+ AVD3D11VAFramesContext *frames_hwctx = ctx->hwctx;
71+ D3D11VAFramesContext *s = ctx->internal->priv;
72+
73+ if (frames_hwctx->texture)
74+ ID3D11Texture2D_Release(frames_hwctx->texture);
75+
76+ if (s->staging_texture)
77+ ID3D11Texture2D_Release(s->staging_texture);
78+}
79+
80+static void free_texture(void *opaque, uint8_t *data)
81+{
82+ ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
83+}
84+
85+static AVBufferRef *wrap_texture_buf(ID3D11Texture2D *tex, int index)
86+{
87+ AVBufferRef *buf;
88+ AVD3D11FrameDescriptor *desc = av_mallocz(sizeof(*desc));
89+ if (!desc) {
90+ ID3D11Texture2D_Release(tex);
91+ return NULL;
92+ }
93+
94+ desc->texture = tex;
95+ desc->index = index;
96+
97+ buf = av_buffer_create((uint8_t *)desc, sizeof(desc), free_texture, tex, 0);
98+ if (!buf) {
99+ ID3D11Texture2D_Release(tex);
100+ av_free(desc);
101+ return NULL;
102+ }
103+
104+ return buf;
105+}
106+
107+static AVBufferRef *d3d11va_alloc_single(AVHWFramesContext *ctx)
108+{
109+ D3D11VAFramesContext *s = ctx->internal->priv;
110+ AVD3D11VAFramesContext *hwctx = ctx->hwctx;
111+ AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
112+ HRESULT hr;
113+ ID3D11Texture2D *tex;
114+ D3D11_TEXTURE2D_DESC texDesc = {
115+ .Width = ctx->width,
116+ .Height = ctx->height,
117+ .MipLevels = 1,
118+ .Format = s->format,
119+ .SampleDesc = { .Count = 1 },
120+ .ArraySize = 1,
121+ .Usage = D3D11_USAGE_DEFAULT,
122+ .BindFlags = hwctx->BindFlags,
123+ .MiscFlags = hwctx->MiscFlags,
124+ };
125+
126+ hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &tex);
127+ if (FAILED(hr)) {
128+ av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
129+ return NULL;
130+ }
131+
132+ return wrap_texture_buf(tex, 0);
133+}
134+
135+static AVBufferRef *d3d11va_pool_alloc(void *opaque, int size)
136+{
137+ AVHWFramesContext *ctx = (AVHWFramesContext*)opaque;
138+ D3D11VAFramesContext *s = ctx->internal->priv;
139+ AVD3D11VAFramesContext *hwctx = ctx->hwctx;
140+ D3D11_TEXTURE2D_DESC texDesc;
141+
142+ if (!hwctx->texture)
143+ return d3d11va_alloc_single(ctx);
144+
145+ ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc);
146+
147+ if (s->nb_surfaces_used >= texDesc.ArraySize) {
148+ av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
149+ return NULL;
150+ }
151+
152+ ID3D11Texture2D_AddRef(hwctx->texture);
153+ return wrap_texture_buf(hwctx->texture, s->nb_surfaces_used++);
154+}
155+
156+static int d3d11va_frames_init(AVHWFramesContext *ctx)
157+{
158+ AVD3D11VAFramesContext *hwctx = ctx->hwctx;
159+ AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
160+ D3D11VAFramesContext *s = ctx->internal->priv;
161+
162+ int i;
163+ HRESULT hr;
164+ D3D11_TEXTURE2D_DESC texDesc;
165+
166+ for (i = 0; i < FF_ARRAY_ELEMS(supported_formats); i++) {
167+ if (ctx->sw_format == supported_formats[i].pix_fmt) {
168+ s->format = supported_formats[i].d3d_format;
169+ break;
170+ }
171+ }
172+ if (i == FF_ARRAY_ELEMS(supported_formats)) {
173+ av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n",
174+ av_get_pix_fmt_name(ctx->sw_format));
175+ return AVERROR(EINVAL);
176+ }
177+
178+ texDesc = (D3D11_TEXTURE2D_DESC){
179+ .Width = ctx->width,
180+ .Height = ctx->height,
181+ .MipLevels = 1,
182+ .Format = s->format,
183+ .SampleDesc = { .Count = 1 },
184+ .ArraySize = ctx->initial_pool_size,
185+ .Usage = D3D11_USAGE_DEFAULT,
186+ .BindFlags = hwctx->BindFlags,
187+ .MiscFlags = hwctx->MiscFlags,
188+ };
189+
190+ if (hwctx->texture) {
191+ D3D11_TEXTURE2D_DESC texDesc2;
192+ ID3D11Texture2D_GetDesc(hwctx->texture, &texDesc2);
193+
194+ if (texDesc.Width != texDesc2.Width ||
195+ texDesc.Height != texDesc2.Height ||
196+ texDesc.Format != texDesc2.Format) {
197+ av_log(ctx, AV_LOG_ERROR, "User-provided texture has mismatching parameters\n");
198+ return AVERROR(EINVAL);
199+ }
200+ } else if (texDesc.ArraySize > 0) {
201+ hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &hwctx->texture);
202+ if (FAILED(hr)) {
203+ av_log(ctx, AV_LOG_ERROR, "Could not create the texture (%lx)\n", (long)hr);
204+ return AVERROR_UNKNOWN;
205+ }
206+ }
207+
208+ texDesc.ArraySize = 1;
209+ texDesc.Usage = D3D11_USAGE_STAGING;
210+ texDesc.BindFlags = 0;
211+ texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
212+ texDesc.MiscFlags = 0;
213+ hr = ID3D11Device_CreateTexture2D(device_hwctx->device, &texDesc, NULL, &s->staging_texture);
214+ if (FAILED(hr)) {
215+ av_log(ctx, AV_LOG_ERROR, "Could not create the staging texture (%lx)\n", (long)hr);
216+ return AVERROR_UNKNOWN;
217+ }
218+
219+ ctx->internal->pool_internal = av_buffer_pool_init2(sizeof(AVD3D11FrameDescriptor),
220+ ctx, d3d11va_pool_alloc, NULL);
221+ if (!ctx->internal->pool_internal)
222+ return AVERROR(ENOMEM);
223+
224+ return 0;
225+}
226+
227+static int d3d11va_get_buffer(AVHWFramesContext *ctx, AVFrame *frame)
228+{
229+ AVD3D11FrameDescriptor *desc;
230+
231+ frame->buf[0] = av_buffer_pool_get(ctx->pool);
232+ if (!frame->buf[0])
233+ return AVERROR(ENOMEM);
234+
235+ desc = (AVD3D11FrameDescriptor *)frame->buf[0]->data;
236+
237+ frame->data[0] = (uint8_t *)desc->texture;
238+ frame->data[1] = (uint8_t *)desc->index;
239+ frame->format = AV_PIX_FMT_D3D11;
240+ frame->width = ctx->width;
241+ frame->height = ctx->height;
242+
243+ return 0;
244+}
245+
246+static int d3d11va_transfer_get_formats(AVHWFramesContext *ctx,
247+ enum AVHWFrameTransferDirection dir,
248+ enum AVPixelFormat **formats)
249+{
250+ enum AVPixelFormat *fmts;
251+
252+ fmts = av_malloc_array(2, sizeof(*fmts));
253+ if (!fmts)
254+ return AVERROR(ENOMEM);
255+
256+ fmts[0] = ctx->sw_format;
257+ fmts[1] = AV_PIX_FMT_NONE;
258+
259+ *formats = fmts;
260+
261+ return 0;
262+}
263+
264+static void fill_texture_ptrs(uint8_t *data[4], int linesize[4],
265+ AVHWFramesContext *ctx,
266+ D3D11_TEXTURE2D_DESC *desc,
267+ D3D11_MAPPED_SUBRESOURCE *map)
268+{
269+ int i;
270+
271+ for (i = 0; i < 4; i++)
272+ linesize[i] = map->RowPitch;
273+
274+ av_image_fill_pointers(data, ctx->sw_format, desc->Height,
275+ (uint8_t*)map->pData, linesize);
276+}
277+
278+static int d3d11va_transfer_data(AVHWFramesContext *ctx, AVFrame *dst,
279+ const AVFrame *src)
280+{
281+ AVD3D11VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
282+ D3D11VAFramesContext *s = ctx->internal->priv;
283+ int download = src->format == AV_PIX_FMT_D3D11;
284+ const AVFrame *frame = download ? src : dst;
285+ const AVFrame *other = download ? dst : src;
286+ // (The interface types are compatible.)
287+ ID3D11Resource *texture = (ID3D11Resource *)(ID3D11Texture2D *)frame->data[0];
288+ int index = (intptr_t)frame->data[1];
289+ ID3D11Resource *staging = (ID3D11Resource *)s->staging_texture;
290+ int w = FFMIN(dst->width, src->width);
291+ int h = FFMIN(dst->height, src->height);
292+ uint8_t *map_data[4];
293+ int map_linesize[4];
294+ D3D11_TEXTURE2D_DESC desc;
295+ D3D11_MAPPED_SUBRESOURCE map;
296+ HRESULT hr;
297+
298+ if (frame->hw_frames_ctx->data != (uint8_t *)ctx || other->format != ctx->sw_format)
299+ return AVERROR(EINVAL);
300+
301+ device_hwctx->lock(device_hwctx->lock_ctx);
302+
303+ ID3D11Texture2D_GetDesc(s->staging_texture, &desc);
304+
305+ if (download) {
306+ ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
307+ staging, 0, 0, 0, 0,
308+ texture, index, NULL);
309+
310+ hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
311+ staging, 0, D3D11_MAP_READ, 0, &map);
312+ if (FAILED(hr))
313+ goto map_failed;
314+
315+ fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
316+
317+ av_image_copy(dst->data, dst->linesize, map_data, map_linesize,
318+ ctx->sw_format, w, h);
319+
320+ ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
321+ } else {
322+ hr = ID3D11DeviceContext_Map(device_hwctx->device_context,
323+ staging, 0, D3D11_MAP_WRITE, 0, &map);
324+ if (FAILED(hr))
325+ goto map_failed;
326+
327+ fill_texture_ptrs(map_data, map_linesize, ctx, &desc, &map);
328+
329+ av_image_copy(map_data, map_linesize, src->data, src->linesize,
330+ ctx->sw_format, w, h);
331+
332+ ID3D11DeviceContext_Unmap(device_hwctx->device_context, staging, 0);
333+
334+ ID3D11DeviceContext_CopySubresourceRegion(device_hwctx->device_context,
335+ texture, index, 0, 0, 0,
336+ staging, 0, NULL);
337+ }
338+
339+ device_hwctx->unlock(device_hwctx->lock_ctx);
340+ return 0;
341+
342+map_failed:
343+ av_log(ctx, AV_LOG_ERROR, "Unable to lock D3D11VA surface (%lx)\n", (long)hr);
344+ device_hwctx->unlock(device_hwctx->lock_ctx);
345+ return AVERROR_UNKNOWN;
346+}
347+
348+static int d3d11va_device_init(AVHWDeviceContext *hwdev)
349+{
350+ AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
351+ HRESULT hr;
352+
353+ if (!device_hwctx->lock) {
354+ device_hwctx->lock_ctx = CreateMutex(NULL, 0, NULL);
355+ if (device_hwctx->lock_ctx == INVALID_HANDLE_VALUE) {
356+ av_log(NULL, AV_LOG_ERROR, "Failed to create a mutex\n");
357+ return AVERROR(EINVAL);
358+ }
359+ device_hwctx->lock = d3d11va_default_lock;
360+ device_hwctx->unlock = d3d11va_default_unlock;
361+ }
362+
363+ if (!device_hwctx->device_context) {
364+ ID3D11Device_GetImmediateContext(device_hwctx->device, &device_hwctx->device_context);
365+ if (!device_hwctx->device_context)
366+ return AVERROR_UNKNOWN;
367+ }
368+
369+ if (!device_hwctx->video_device) {
370+ hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device, &IID_ID3D11VideoDevice,
371+ (void **)&device_hwctx->video_device);
372+ if (FAILED(hr))
373+ return AVERROR_UNKNOWN;
374+ }
375+
376+ if (!device_hwctx->video_context) {
377+ hr = ID3D11DeviceContext_QueryInterface(device_hwctx->device_context, &IID_ID3D11VideoContext,
378+ (void **)&device_hwctx->video_context);
379+ if (FAILED(hr))
380+ return AVERROR_UNKNOWN;
381+ }
382+
383+ return 0;
384+}
385+
386+static void d3d11va_device_uninit(AVHWDeviceContext *hwdev)
387+{
388+ AVD3D11VADeviceContext *device_hwctx = hwdev->hwctx;
389+
390+ if (device_hwctx->device)
391+ ID3D11Device_Release(device_hwctx->device);
392+
393+ if (device_hwctx->device_context)
394+ ID3D11DeviceContext_Release(device_hwctx->device_context);
395+
396+ if (device_hwctx->video_device)
397+ ID3D11VideoDevice_Release(device_hwctx->video_device);
398+
399+ if (device_hwctx->video_context)
400+ ID3D11VideoContext_Release(device_hwctx->video_context);
401+
402+ if (device_hwctx->lock == d3d11va_default_lock)
403+ CloseHandle(device_hwctx->lock_ctx);
404+}
405+
406+static int d3d11va_device_create(AVHWDeviceContext *ctx, const char *device,
407+ AVDictionary *opts, int flags)
408+{
409+ AVD3D11VADeviceContext *device_hwctx = ctx->hwctx;
410+ HANDLE d3dlib;
411+
412+ HRESULT hr;
413+ PFN_D3D11_CREATE_DEVICE createD3D;
414+ IDXGIAdapter *pAdapter = NULL;
415+ ID3D10Multithread *pMultithread;
416+ UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT;
417+
418+ if (device) {
419+ PFN_CREATE_DXGI_FACTORY mCreateDXGIFactory;
420+ HMODULE dxgilib = LoadLibrary("dxgi.dll");
421+ if (!dxgilib)
422+ return AVERROR_UNKNOWN;
423+
424+ mCreateDXGIFactory = (PFN_CREATE_DXGI_FACTORY) GetProcAddress(dxgilib, "CreateDXGIFactory");
425+ if (mCreateDXGIFactory) {
426+ IDXGIFactory2 *pDXGIFactory;
427+ hr = mCreateDXGIFactory(&IID_IDXGIFactory2, (void **)&pDXGIFactory);
428+ if (SUCCEEDED(hr)) {
429+ int adapter = atoi(device);
430+ if (FAILED(IDXGIFactory2_EnumAdapters(pDXGIFactory, adapter, &pAdapter)))
431+ pAdapter = NULL;
432+ IDXGIFactory2_Release(pDXGIFactory);
433+ }
434+ }
435+ FreeLibrary(dxgilib);
436+ }
437+
438+ // We let this "leak" - this is fine, as unloading has no great benefit, and
439+ // Windows will mark a DLL as loaded forever if its internal refcount overflows
440+ // from too many LoadLibrary calls.
441+ d3dlib = LoadLibrary("d3d11.dll");
442+ if (!d3dlib) {
443+ av_log(ctx, AV_LOG_ERROR, "Failed to load D3D11 library\n");
444+ return AVERROR_UNKNOWN;
445+ }
446+
447+ createD3D = (PFN_D3D11_CREATE_DEVICE) GetProcAddress(d3dlib, "D3D11CreateDevice");
448+ if (!createD3D) {
449+ av_log(ctx, AV_LOG_ERROR, "Failed to locate D3D11CreateDevice\n");
450+ return AVERROR_UNKNOWN;
451+ }
452+
453+ hr = createD3D(pAdapter, pAdapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE, NULL, creationFlags, NULL, 0,
454+ D3D11_SDK_VERSION, &device_hwctx->device, NULL, NULL);
455+ if (pAdapter)
456+ IDXGIAdapter_Release(pAdapter);
457+ if (FAILED(hr)) {
458+ av_log(ctx, AV_LOG_ERROR, "Failed to create Direct3D device (%lx)\n", (long)hr);
459+ return AVERROR_UNKNOWN;
460+ }
461+
462+ hr = ID3D11Device_QueryInterface(device_hwctx->device, &IID_ID3D10Multithread, (void **)&pMultithread);
463+ if (SUCCEEDED(hr)) {
464+ ID3D10Multithread_SetMultithreadProtected(pMultithread, TRUE);
465+ ID3D10Multithread_Release(pMultithread);
466+ }
467+
468+ return 0;
469+}
470+
471+const HWContextType ff_hwcontext_type_d3d11va = {
472+ .type = AV_HWDEVICE_TYPE_D3D11VA,
473+ .name = "D3D11VA",
474+
475+ .device_hwctx_size = sizeof(AVD3D11VADeviceContext),
476+ .frames_hwctx_size = sizeof(AVD3D11VAFramesContext),
477+ .frames_priv_size = sizeof(D3D11VAFramesContext),
478+
479+ .device_create = d3d11va_device_create,
480+ .device_init = d3d11va_device_init,
481+ .device_uninit = d3d11va_device_uninit,
482+ .frames_init = d3d11va_frames_init,
483+ .frames_uninit = d3d11va_frames_uninit,
484+ .frames_get_buffer = d3d11va_get_buffer,
485+ .transfer_get_formats = d3d11va_transfer_get_formats,
486+ .transfer_data_to = d3d11va_transfer_data,
487+ .transfer_data_from = d3d11va_transfer_data,
488+
489+ .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_D3D11, AV_PIX_FMT_NONE },
490+};
libavutil/hwcontext_d3d11va.h+160−0
@@ -0,0 +1,160 @@
1+/*
2+ * This file is part of Libav.
3+ *
4+ * Libav 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+ * Libav 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 Libav; if not, write to the Free Software
16+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17+ */
18+
19+#ifndef AVUTIL_HWCONTEXT_D3D11VA_H
20+#define AVUTIL_HWCONTEXT_D3D11VA_H
21+
22+/**
23+ * @file
24+ * An API-specific header for AV_HWDEVICE_TYPE_D3D11VA.
25+ *
26+ * The default pool implementation will be fixed-size if initial_pool_size is
27+ * set (and allocate elements from an array texture). Otherwise it will allocate
28+ * individual textures. Be aware that decoding requires a single array texture.
29+ */
30+
31+#include <d3d11.h>
32+
33+/**
34+ * This struct is allocated as AVHWDeviceContext.hwctx
35+ */
36+typedef struct AVD3D11VADeviceContext {
37+ /**
38+ * Device used for texture creation and access. This can also be used to
39+ * set the libavcodec decoding device.
40+ *
41+ * Must be set by the user. This is the only mandatory field - the other
42+ * device context fields are set from this and are available for convenience.
43+ *
44+ * Deallocating the AVHWDeviceContext will always release this interface,
45+ * and it does not matter whether it was user-allocated.
46+ */
47+ ID3D11Device *device;
48+
49+ /**
50+ * If unset, this will be set from the device field on init.
51+ *
52+ * Deallocating the AVHWDeviceContext will always release this interface,
53+ * and it does not matter whether it was user-allocated.
54+ */
55+ ID3D11DeviceContext *device_context;
56+
57+ /**
58+ * If unset, this will be set from the device field on init.
59+ *
60+ * Deallocating the AVHWDeviceContext will always release this interface,
61+ * and it does not matter whether it was user-allocated.
62+ */
63+ ID3D11VideoDevice *video_device;
64+
65+ /**
66+ * If unset, this will be set from the device_context field on init.
67+ *
68+ * Deallocating the AVHWDeviceContext will always release this interface,
69+ * and it does not matter whether it was user-allocated.
70+ */
71+ ID3D11VideoContext *video_context;
72+
73+ /**
74+ * Callbacks for locking. They protect accesses to device_context and
75+ * video_context calls. They also protect access to the internal staging
76+ * texture (for av_hwframe_transfer_data() calls). They do NOT protect
77+ * access to hwcontext or decoder state in general.
78+ *
79+ * If unset on init, the hwcontext implementation will set them to use an
80+ * internal mutex.
81+ *
82+ * The underlying lock must be recursive. lock_ctx is for free use by the
83+ * locking implementation.
84+ */
85+ void (*lock)(void *lock_ctx);
86+ void (*unlock)(void *lock_ctx);
87+ void *lock_ctx;
88+} AVD3D11VADeviceContext;
89+
90+/**
91+ * D3D11 frame descriptor for pool allocation.
92+ *
93+ * In user-allocated pools, AVHWFramesContext.pool must return AVBufferRefs
94+ * with the data pointer pointing at an object of this type describing the
95+ * planes of the frame.
96+ *
97+ * This has no use outside of custom allocation, and AVFrame AVBufferRef do not
98+ * necessarily point to an instance of this struct.
99+ */
100+typedef struct AVD3D11FrameDescriptor {
101+ /**
102+ * The texture in which the frame is located. The reference count is
103+ * managed by the AVBufferRef, and destroying the reference will release
104+ * the interface.
105+ *
106+ * Normally stored in AVFrame.data[0].
107+ */
108+ ID3D11Texture2D *texture;
109+
110+ /**
111+ * The index into the array texture element representing the frame, or 0
112+ * if the texture is not an array texture.
113+ *
114+ * Normally stored in AVFrame.data[1] (cast from intptr_t).
115+ */
116+ intptr_t index;
117+} AVD3D11FrameDescriptor;
118+
119+/**
120+ * This struct is allocated as AVHWFramesContext.hwctx
121+ */
122+typedef struct AVD3D11VAFramesContext {
123+ /**
124+ * The canonical texture used for pool allocation. If this is set to NULL
125+ * on init, the hwframes implementation will allocate and set an array
126+ * texture if initial_pool_size > 0.
127+ *
128+ * The only situation when the API user should set this is:
129+ * - the user wants to do manual pool allocation (setting
130+ * AVHWFramesContext.pool), instead of letting AVHWFramesContext
131+ * allocate the pool
132+ * - of an array texture
133+ * - and wants it to use it for decoding
134+ * - this has to be done before calling av_hwframe_ctx_init()
135+ *
136+ * Deallocating the AVHWFramesContext will always release this interface,
137+ * and it does not matter whether it was user-allocated.
138+ *
139+ * This is in particular used by the libavcodec D3D11VA hwaccel, which
140+ * requires a single array texture. It will create ID3D11VideoDecoderOutputView
141+ * objects for each array texture element on decoder initialization.
142+ */
143+ ID3D11Texture2D *texture;
144+
145+ /**
146+ * D3D11_TEXTURE2D_DESC.BindFlags used for texture creation. The user must
147+ * at least set D3D11_BIND_DECODER if the frames context is to be used for
148+ * video decoding.
149+ * This field is ignored/invalid if a user-allocated texture is provided.
150+ */
151+ UINT BindFlags;
152+
153+ /**
154+ * D3D11_TEXTURE2D_DESC.MiscFlags used for texture creation.
155+ * This field is ignored/invalid if a user-allocated texture is provided.
156+ */
157+ UINT MiscFlags;
158+} AVD3D11VAFramesContext;
159+
160+#endif /* AVUTIL_HWCONTEXT_D3D11VA_H */
libavutil/hwcontext_internal.h+1−0
@@ -158,6 +158,7 @@ int ff_hwframe_map_create(AVBufferRef *hwframe_ref, · 157 unmodified lines
158158
159159
160160 extern const HWContextType ff_hwcontext_type_cuda;
161+extern const HWContextType ff_hwcontext_type_d3d11va;
161162 extern const HWContextType ff_hwcontext_type_dxva2;
162163 extern const HWContextType ff_hwcontext_type_qsv;
163164 extern const HWContextType ff_hwcontext_type_vaapi;
libavutil/pixdesc.c+4−0
@@ -1739,6 +1739,10 @@ static const AVPixFmtDescriptor av_pix_fmt_descriptors[AV_PIX_FMT_NB] = { · 1738 unmodified lines
17391739 .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
17401740 AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA,
17411741 },
1742+ [AV_PIX_FMT_D3D11] = {
1743+ .name = "d3d11",
1744+ .flags = AV_PIX_FMT_FLAG_HWACCEL,
1745+ },
17421746 };
17431747 #if FF_API_PLUS1_MINUS1
17441748 FF_ENABLE_DEPRECATION_WARNINGS
libavutil/pixfmt.h+13−1
@@ -205,7 +205,7 @@ enum AVPixelFormat { · 204 unmodified lines
205205 */
206206 AV_PIX_FMT_MMAL,
207207
208− AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
208+ AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
209209
210210 /**
211211 * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
@@ -237,6 +237,18 @@ enum AVPixelFormat { · 25 unmodified lines
237237 AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian
238238 AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian
239239
240+ /**
241+ * Hardware surfaces for Direct3D11.
242+ *
243+ * This is preferred over the legacy AV_PIX_FMT_D3D11VA_VLD. The new D3D11
244+ * hwaccel API and filtering support AV_PIX_FMT_D3D11 only.
245+ *
246+ * data[0] contains a ID3D11Texture2D pointer, and data[1] contains the
247+ * texture array index of the frame as intptr_t if the ID3D11Texture2D is
248+ * an array texture (or always 0 if it's a normal texture).
249+ */
250+ AV_PIX_FMT_D3D11,
251+
240252 AV_PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions
241253 };
242254
libavutil/version.h+2−2
@@ -54,8 +54,8 @@ · 53 unmodified lines
5454 */
5555
5656 #define LIBAVUTIL_VERSION_MAJOR 56
57−#define LIBAVUTIL_VERSION_MINOR 1
58−#define LIBAVUTIL_VERSION_MICRO 1
57+#define LIBAVUTIL_VERSION_MINOR 2
58+#define LIBAVUTIL_VERSION_MICRO 0
5959
6060 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
6161 LIBAVUTIL_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t