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
13 13
14API changes, most recent first:14API changes, most recent first:
15 15
162017-xx-xx - xxxxxxx - lavu 56.2.0 - hwcontext.h
17 Add AV_HWDEVICE_TYPE_D3D11VA and AV_PIX_FMT_D3D11.
18
162017-04-30 - xxxxxxx - lavu 56.1.1 - hwcontext.h192017-04-30 - xxxxxxx - lavu 56.1.1 - hwcontext.h
17 av_hwframe_ctx_create_derived() now takes some AV_HWFRAME_MAP_* combination20 av_hwframe_ctx_create_derived() now takes some AV_HWFRAME_MAP_* combination
18 as its flags argument (which was previously unused).21 as its flags argument (which was previously unused).
libavutil/Makefile+3−0
@@ -27,6 +27,7 @@ HEADERS = adler32.h \ · 26 unmodified lines
27 hmac.h \27 hmac.h \
28 hwcontext.h \28 hwcontext.h \
29 hwcontext_cuda.h \29 hwcontext_cuda.h \
30 hwcontext_d3d11va.h \
30 hwcontext_dxva2.h \31 hwcontext_dxva2.h \
31 hwcontext_qsv.h \32 hwcontext_qsv.h \
32 hwcontext_vaapi.h \33 hwcontext_vaapi.h \
@@ -112,6 +113,7 @@ OBJS = adler32.o \ · 79 unmodified lines
112 xtea.o \113 xtea.o \
113 114
114OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o115OBJS-$(CONFIG_CUDA) += hwcontext_cuda.o
116OBJS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.o
115OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o117OBJS-$(CONFIG_DXVA2) += hwcontext_dxva2.o
116OBJS-$(CONFIG_LIBMFX) += hwcontext_qsv.o118OBJS-$(CONFIG_LIBMFX) += hwcontext_qsv.o
117OBJS-$(CONFIG_LZO) += lzo.o119OBJS-$(CONFIG_LZO) += lzo.o
@@ -121,6 +123,7 @@ OBJS-$(CONFIG_VDPAU) += hwcontext_vdpau.o · 3 unmodified lines
121OBJS += $(COMPAT_OBJS:%=../compat/%)123OBJS += $(COMPAT_OBJS:%=../compat/%)
122 124
123SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda.h125SKIPHEADERS-$(CONFIG_CUDA) += hwcontext_cuda.h
126SKIPHEADERS-$(CONFIG_D3D11VA) += hwcontext_d3d11va.h
124SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h127SKIPHEADERS-$(CONFIG_DXVA2) += hwcontext_dxva2.h
125SKIPHEADERS-$(CONFIG_LIBMFX) += hwcontext_qsv.h128SKIPHEADERS-$(CONFIG_LIBMFX) += hwcontext_qsv.h
126SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h129SKIPHEADERS-$(CONFIG_VAAPI) += hwcontext_vaapi.h
libavutil/hwcontext.c+4−0
@@ -32,6 +32,9 @@ static const HWContextType * const hw_table[] = { · 31 unmodified lines
32#if CONFIG_CUDA32#if CONFIG_CUDA
33 &ff_hwcontext_type_cuda,33 &ff_hwcontext_type_cuda,
34#endif34#endif
35#if CONFIG_D3D11VA
36 &ff_hwcontext_type_d3d11va,
37#endif
35#if CONFIG_DXVA238#if CONFIG_DXVA2
36 &ff_hwcontext_type_dxva2,39 &ff_hwcontext_type_dxva2,
37#endif40#endif
@@ -50,6 +53,7 @@ static const HWContextType * const hw_table[] = { · 12 unmodified lines
50const char *hw_type_names[] = {53const char *hw_type_names[] = {
51 [AV_HWDEVICE_TYPE_CUDA] = "cuda",54 [AV_HWDEVICE_TYPE_CUDA] = "cuda",
52 [AV_HWDEVICE_TYPE_DXVA2] = "dxva2",55 [AV_HWDEVICE_TYPE_DXVA2] = "dxva2",
56 [AV_HWDEVICE_TYPE_D3D11VA] = "d3d11va",
53 [AV_HWDEVICE_TYPE_QSV] = "qsv",57 [AV_HWDEVICE_TYPE_QSV] = "qsv",
54 [AV_HWDEVICE_TYPE_VAAPI] = "vaapi",58 [AV_HWDEVICE_TYPE_VAAPI] = "vaapi",
55 [AV_HWDEVICE_TYPE_VDPAU] = "vdpau",59 [AV_HWDEVICE_TYPE_VDPAU] = "vdpau",
libavutil/hwcontext.h+1−0
@@ -31,6 +31,7 @@ enum AVHWDeviceType { · 30 unmodified lines
31 AV_HWDEVICE_TYPE_VAAPI,31 AV_HWDEVICE_TYPE_VAAPI,
32 AV_HWDEVICE_TYPE_DXVA2,32 AV_HWDEVICE_TYPE_DXVA2,
33 AV_HWDEVICE_TYPE_QSV,33 AV_HWDEVICE_TYPE_QSV,
34 AV_HWDEVICE_TYPE_D3D11VA,
34};35};
35 36
36typedef struct AVHWDeviceInternal AVHWDeviceInternal;37typedef 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
40typedef HRESULT(WINAPI *PFN_CREATE_DXGI_FACTORY)(REFIID riid, void **ppFactory);
41
42typedef struct D3D11VAFramesContext {
43 int nb_surfaces_used;
44
45 DXGI_FORMAT format;
46
47 ID3D11Texture2D *staging_texture;
48} D3D11VAFramesContext;
49
50static 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
58static void d3d11va_default_lock(void *ctx)
59{
60 WaitForSingleObjectEx(ctx, INFINITE, FALSE);
61}
62
63static void d3d11va_default_unlock(void *ctx)
64{
65 ReleaseMutex(ctx);
66}
67
68static 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
80static void free_texture(void *opaque, uint8_t *data)
81{
82 ID3D11Texture2D_Release((ID3D11Texture2D *)opaque);
83}
84
85static 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
107static 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
135static 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
156static 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
227static 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
246static 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
264static 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
278static 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
342map_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
348static 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
386static 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
406static 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
471const 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 */
36typedef 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 */
100typedef 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 */
122typedef 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
158 158
159 159
160extern const HWContextType ff_hwcontext_type_cuda;160extern const HWContextType ff_hwcontext_type_cuda;
161extern const HWContextType ff_hwcontext_type_d3d11va;
161extern const HWContextType ff_hwcontext_type_dxva2;162extern const HWContextType ff_hwcontext_type_dxva2;
162extern const HWContextType ff_hwcontext_type_qsv;163extern const HWContextType ff_hwcontext_type_qsv;
163extern const HWContextType ff_hwcontext_type_vaapi;164extern 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
1739 .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |1739 .flags = AV_PIX_FMT_FLAG_BE | AV_PIX_FMT_FLAG_PLANAR |
1740 AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA,1740 AV_PIX_FMT_FLAG_RGB | AV_PIX_FMT_FLAG_ALPHA,
1741 },1741 },
1742 [AV_PIX_FMT_D3D11] = {
1743 .name = "d3d11",
1744 .flags = AV_PIX_FMT_FLAG_HWACCEL,
1745 },
1742};1746};
1743#if FF_API_PLUS1_MINUS11747#if FF_API_PLUS1_MINUS1
1744FF_ENABLE_DEPRECATION_WARNINGS1748FF_ENABLE_DEPRECATION_WARNINGS
libavutil/pixfmt.h+13−1
@@ -205,7 +205,7 @@ enum AVPixelFormat { · 204 unmodified lines
205 */205 */
206 AV_PIX_FMT_MMAL,206 AV_PIX_FMT_MMAL,
207 207
208 AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer208 AV_PIX_FMT_D3D11VA_VLD, ///< HW decoding through Direct3D11 via old API, Picture.data[3] contains a ID3D11VideoDecoderOutputView pointer
209 209
210 /**210 /**
211 * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers211 * HW acceleration through CUDA. data[i] contain CUdeviceptr pointers
@@ -237,6 +237,18 @@ enum AVPixelFormat { · 25 unmodified lines
237 AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian237 AV_PIX_FMT_GBRAP10BE, ///< planar GBR 4:4:4:4 40bpp, big-endian
238 AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian238 AV_PIX_FMT_GBRAP10LE, ///< planar GBR 4:4:4:4 40bpp, little-endian
239 239
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
240 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 versions252 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
241};253};
242 254
libavutil/version.h+2−2
@@ -54,8 +54,8 @@ · 53 unmodified lines
54 */54 */
55 55
56#define LIBAVUTIL_VERSION_MAJOR 5656#define LIBAVUTIL_VERSION_MAJOR 56
57#define LIBAVUTIL_VERSION_MINOR 157#define LIBAVUTIL_VERSION_MINOR 2
58#define LIBAVUTIL_VERSION_MICRO 158#define LIBAVUTIL_VERSION_MICRO 0
59 59
60#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \60#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
61 LIBAVUTIL_VERSION_MINOR, \61 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