* commit 'b23613268c6b56a8f9de7859562d82b4b88353d9':
avconv_dxva2: use the hwcontext API
Merged-by: Hendrik Leppkes <h.leppkes@gmail.com>
... | ... |
@@ -40,6 +40,9 @@ |
40 | 40 |
#include "libavutil/imgutils.h" |
41 | 41 |
#include "libavutil/pixfmt.h" |
42 | 42 |
|
43 |
+#include "libavutil/hwcontext.h" |
|
44 |
+#include "libavutil/hwcontext_dxva2.h" |
|
45 |
+ |
|
43 | 46 |
/* define all the GUIDs used directly here, |
44 | 47 |
to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */ |
45 | 48 |
#include <initguid.h> |
... | ... |
@@ -93,12 +96,7 @@ static const dxva2_mode dxva2_modes[] = { |
93 | 93 |
{ NULL, 0 }, |
94 | 94 |
}; |
95 | 95 |
|
96 |
-typedef struct surface_info { |
|
97 |
- int used; |
|
98 |
- uint64_t age; |
|
99 |
-} surface_info; |
|
100 |
- |
|
101 |
-typedef struct DXVA2Context { |
|
96 |
+typedef struct DXVA2DevicePriv { |
|
102 | 97 |
HMODULE d3dlib; |
103 | 98 |
HMODULE dxva2lib; |
104 | 99 |
|
... | ... |
@@ -106,49 +104,45 @@ typedef struct DXVA2Context { |
106 | 106 |
|
107 | 107 |
IDirect3D9 *d3d9; |
108 | 108 |
IDirect3DDevice9 *d3d9device; |
109 |
- IDirect3DDeviceManager9 *d3d9devmgr; |
|
110 |
- IDirectXVideoDecoderService *decoder_service; |
|
109 |
+} DXVA2DevicePriv; |
|
110 |
+ |
|
111 |
+typedef struct DXVA2Context { |
|
111 | 112 |
IDirectXVideoDecoder *decoder; |
112 | 113 |
|
113 | 114 |
GUID decoder_guid; |
114 | 115 |
DXVA2_ConfigPictureDecode decoder_config; |
115 |
- |
|
116 |
- LPDIRECT3DSURFACE9 *surfaces; |
|
117 |
- surface_info *surface_infos; |
|
118 |
- uint32_t num_surfaces; |
|
119 |
- uint64_t surface_age; |
|
120 |
- D3DFORMAT surface_format; |
|
116 |
+ IDirectXVideoDecoderService *decoder_service; |
|
121 | 117 |
|
122 | 118 |
AVFrame *tmp_frame; |
123 |
-} DXVA2Context; |
|
124 | 119 |
|
125 |
-typedef struct DXVA2SurfaceWrapper { |
|
126 |
- DXVA2Context *ctx; |
|
127 |
- LPDIRECT3DSURFACE9 surface; |
|
128 |
- IDirectXVideoDecoder *decoder; |
|
129 |
-} DXVA2SurfaceWrapper; |
|
120 |
+ AVBufferRef *hw_device_ctx; |
|
121 |
+ AVBufferRef *hw_frames_ctx; |
|
122 |
+} DXVA2Context; |
|
130 | 123 |
|
131 |
-static void dxva2_destroy_decoder(AVCodecContext *s) |
|
124 |
+static void dxva2_device_uninit(AVHWDeviceContext *ctx) |
|
132 | 125 |
{ |
133 |
- InputStream *ist = s->opaque; |
|
134 |
- DXVA2Context *ctx = ist->hwaccel_ctx; |
|
135 |
- int i; |
|
126 |
+ AVDXVA2DeviceContext *hwctx = ctx->hwctx; |
|
127 |
+ DXVA2DevicePriv *priv = ctx->user_opaque; |
|
136 | 128 |
|
137 |
- if (ctx->surfaces) { |
|
138 |
- for (i = 0; i < ctx->num_surfaces; i++) { |
|
139 |
- if (ctx->surfaces[i]) |
|
140 |
- IDirect3DSurface9_Release(ctx->surfaces[i]); |
|
141 |
- } |
|
142 |
- } |
|
143 |
- av_freep(&ctx->surfaces); |
|
144 |
- av_freep(&ctx->surface_infos); |
|
145 |
- ctx->num_surfaces = 0; |
|
146 |
- ctx->surface_age = 0; |
|
147 |
- |
|
148 |
- if (ctx->decoder) { |
|
149 |
- IDirectXVideoDecoder_Release(ctx->decoder); |
|
150 |
- ctx->decoder = NULL; |
|
151 |
- } |
|
129 |
+ if (hwctx->devmgr && priv->deviceHandle != INVALID_HANDLE_VALUE) |
|
130 |
+ IDirect3DDeviceManager9_CloseDeviceHandle(hwctx->devmgr, priv->deviceHandle); |
|
131 |
+ |
|
132 |
+ if (hwctx->devmgr) |
|
133 |
+ IDirect3DDeviceManager9_Release(hwctx->devmgr); |
|
134 |
+ |
|
135 |
+ if (priv->d3d9device) |
|
136 |
+ IDirect3DDevice9_Release(priv->d3d9device); |
|
137 |
+ |
|
138 |
+ if (priv->d3d9) |
|
139 |
+ IDirect3D9_Release(priv->d3d9); |
|
140 |
+ |
|
141 |
+ if (priv->d3dlib) |
|
142 |
+ FreeLibrary(priv->d3dlib); |
|
143 |
+ |
|
144 |
+ if (priv->dxva2lib) |
|
145 |
+ FreeLibrary(priv->dxva2lib); |
|
146 |
+ |
|
147 |
+ av_freep(&ctx->user_opaque); |
|
152 | 148 |
} |
153 | 149 |
|
154 | 150 |
static void dxva2_uninit(AVCodecContext *s) |
... | ... |
@@ -160,29 +154,11 @@ static void dxva2_uninit(AVCodecContext *s) |
160 | 160 |
ist->hwaccel_get_buffer = NULL; |
161 | 161 |
ist->hwaccel_retrieve_data = NULL; |
162 | 162 |
|
163 |
- if (ctx->decoder) |
|
164 |
- dxva2_destroy_decoder(s); |
|
165 |
- |
|
166 | 163 |
if (ctx->decoder_service) |
167 | 164 |
IDirectXVideoDecoderService_Release(ctx->decoder_service); |
168 | 165 |
|
169 |
- if (ctx->d3d9devmgr && ctx->deviceHandle != INVALID_HANDLE_VALUE) |
|
170 |
- IDirect3DDeviceManager9_CloseDeviceHandle(ctx->d3d9devmgr, ctx->deviceHandle); |
|
171 |
- |
|
172 |
- if (ctx->d3d9devmgr) |
|
173 |
- IDirect3DDeviceManager9_Release(ctx->d3d9devmgr); |
|
174 |
- |
|
175 |
- if (ctx->d3d9device) |
|
176 |
- IDirect3DDevice9_Release(ctx->d3d9device); |
|
177 |
- |
|
178 |
- if (ctx->d3d9) |
|
179 |
- IDirect3D9_Release(ctx->d3d9); |
|
180 |
- |
|
181 |
- if (ctx->d3dlib) |
|
182 |
- FreeLibrary(ctx->d3dlib); |
|
183 |
- |
|
184 |
- if (ctx->dxva2lib) |
|
185 |
- FreeLibrary(ctx->dxva2lib); |
|
166 |
+ av_buffer_unref(&ctx->hw_frames_ctx); |
|
167 |
+ av_buffer_unref(&ctx->hw_device_ctx); |
|
186 | 168 |
|
187 | 169 |
av_frame_free(&ctx->tmp_frame); |
188 | 170 |
|
... | ... |
@@ -190,130 +166,34 @@ static void dxva2_uninit(AVCodecContext *s) |
190 | 190 |
av_freep(&s->hwaccel_context); |
191 | 191 |
} |
192 | 192 |
|
193 |
-static void dxva2_release_buffer(void *opaque, uint8_t *data) |
|
194 |
-{ |
|
195 |
- DXVA2SurfaceWrapper *w = opaque; |
|
196 |
- DXVA2Context *ctx = w->ctx; |
|
197 |
- int i; |
|
198 |
- |
|
199 |
- for (i = 0; i < ctx->num_surfaces; i++) { |
|
200 |
- if (ctx->surfaces[i] == w->surface) { |
|
201 |
- ctx->surface_infos[i].used = 0; |
|
202 |
- break; |
|
203 |
- } |
|
204 |
- } |
|
205 |
- IDirect3DSurface9_Release(w->surface); |
|
206 |
- IDirectXVideoDecoder_Release(w->decoder); |
|
207 |
- av_free(w); |
|
208 |
-} |
|
209 |
- |
|
210 | 193 |
static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags) |
211 | 194 |
{ |
212 | 195 |
InputStream *ist = s->opaque; |
213 | 196 |
DXVA2Context *ctx = ist->hwaccel_ctx; |
214 |
- int i, old_unused = -1; |
|
215 |
- LPDIRECT3DSURFACE9 surface; |
|
216 |
- DXVA2SurfaceWrapper *w = NULL; |
|
217 |
- |
|
218 |
- av_assert0(frame->format == AV_PIX_FMT_DXVA2_VLD); |
|
219 |
- |
|
220 |
- for (i = 0; i < ctx->num_surfaces; i++) { |
|
221 |
- surface_info *info = &ctx->surface_infos[i]; |
|
222 |
- if (!info->used && (old_unused == -1 || info->age < ctx->surface_infos[old_unused].age)) |
|
223 |
- old_unused = i; |
|
224 |
- } |
|
225 |
- if (old_unused == -1) { |
|
226 |
- av_log(NULL, AV_LOG_ERROR, "No free DXVA2 surface!\n"); |
|
227 |
- return AVERROR(ENOMEM); |
|
228 |
- } |
|
229 |
- i = old_unused; |
|
230 | 197 |
|
231 |
- surface = ctx->surfaces[i]; |
|
232 |
- |
|
233 |
- w = av_mallocz(sizeof(*w)); |
|
234 |
- if (!w) |
|
235 |
- return AVERROR(ENOMEM); |
|
236 |
- |
|
237 |
- frame->buf[0] = av_buffer_create((uint8_t*)surface, 0, |
|
238 |
- dxva2_release_buffer, w, |
|
239 |
- AV_BUFFER_FLAG_READONLY); |
|
240 |
- if (!frame->buf[0]) { |
|
241 |
- av_free(w); |
|
242 |
- return AVERROR(ENOMEM); |
|
243 |
- } |
|
244 |
- |
|
245 |
- w->ctx = ctx; |
|
246 |
- w->surface = surface; |
|
247 |
- IDirect3DSurface9_AddRef(w->surface); |
|
248 |
- w->decoder = ctx->decoder; |
|
249 |
- IDirectXVideoDecoder_AddRef(w->decoder); |
|
250 |
- |
|
251 |
- ctx->surface_infos[i].used = 1; |
|
252 |
- ctx->surface_infos[i].age = ctx->surface_age++; |
|
253 |
- |
|
254 |
- frame->data[3] = (uint8_t *)surface; |
|
255 |
- |
|
256 |
- return 0; |
|
198 |
+ return av_hwframe_get_buffer(ctx->hw_frames_ctx, frame, 0); |
|
257 | 199 |
} |
258 | 200 |
|
259 | 201 |
static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame) |
260 | 202 |
{ |
261 |
- LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->data[3]; |
|
262 | 203 |
InputStream *ist = s->opaque; |
263 | 204 |
DXVA2Context *ctx = ist->hwaccel_ctx; |
264 |
- D3DSURFACE_DESC surfaceDesc; |
|
265 |
- D3DLOCKED_RECT LockedRect; |
|
266 |
- HRESULT hr; |
|
267 |
- int ret, nbytes; |
|
268 |
- |
|
269 |
- IDirect3DSurface9_GetDesc(surface, &surfaceDesc); |
|
270 |
- |
|
271 |
- ctx->tmp_frame->width = frame->width; |
|
272 |
- ctx->tmp_frame->height = frame->height; |
|
273 |
- switch (ctx->surface_format){ |
|
274 |
- case MKTAG('N','V','1','2'): |
|
275 |
- ctx->tmp_frame->format = AV_PIX_FMT_NV12; |
|
276 |
- nbytes = 1; |
|
277 |
- break; |
|
278 |
- case MKTAG('P','0','1','0'): |
|
279 |
- ctx->tmp_frame->format = AV_PIX_FMT_P010; |
|
280 |
- nbytes = 2; |
|
281 |
- break; |
|
282 |
- default: |
|
283 |
- av_assert0(0); |
|
284 |
- } |
|
205 |
+ int ret; |
|
285 | 206 |
|
286 |
- ret = av_frame_get_buffer(ctx->tmp_frame, 32); |
|
207 |
+ ret = av_hwframe_transfer_data(ctx->tmp_frame, frame, 0); |
|
287 | 208 |
if (ret < 0) |
288 | 209 |
return ret; |
289 | 210 |
|
290 |
- hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY); |
|
291 |
- if (FAILED(hr)) { |
|
292 |
- av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n"); |
|
293 |
- return AVERROR_UNKNOWN; |
|
294 |
- } |
|
295 |
- |
|
296 |
- av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0], |
|
297 |
- (uint8_t*)LockedRect.pBits, |
|
298 |
- LockedRect.Pitch, frame->width * nbytes, frame->height); |
|
299 |
- |
|
300 |
- av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1], |
|
301 |
- (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height, |
|
302 |
- LockedRect.Pitch, frame->width * nbytes, frame->height / 2); |
|
303 |
- |
|
304 |
- IDirect3DSurface9_UnlockRect(surface); |
|
305 |
- |
|
306 | 211 |
ret = av_frame_copy_props(ctx->tmp_frame, frame); |
307 |
- if (ret < 0) |
|
308 |
- goto fail; |
|
212 |
+ if (ret < 0) { |
|
213 |
+ av_frame_unref(ctx->tmp_frame); |
|
214 |
+ return ret; |
|
215 |
+ } |
|
309 | 216 |
|
310 | 217 |
av_frame_unref(frame); |
311 | 218 |
av_frame_move_ref(frame, ctx->tmp_frame); |
312 | 219 |
|
313 | 220 |
return 0; |
314 |
-fail: |
|
315 |
- av_frame_unref(ctx->tmp_frame); |
|
316 |
- return ret; |
|
317 | 221 |
} |
318 | 222 |
|
319 | 223 |
static int dxva2_alloc(AVCodecContext *s) |
... | ... |
@@ -329,41 +209,60 @@ static int dxva2_alloc(AVCodecContext *s) |
329 | 329 |
unsigned resetToken = 0; |
330 | 330 |
UINT adapter = D3DADAPTER_DEFAULT; |
331 | 331 |
|
332 |
+ AVHWDeviceContext *device_ctx; |
|
333 |
+ AVDXVA2DeviceContext *device_hwctx; |
|
334 |
+ DXVA2DevicePriv *device_priv; |
|
335 |
+ int ret; |
|
336 |
+ |
|
332 | 337 |
ctx = av_mallocz(sizeof(*ctx)); |
333 | 338 |
if (!ctx) |
334 | 339 |
return AVERROR(ENOMEM); |
335 | 340 |
|
336 |
- ctx->deviceHandle = INVALID_HANDLE_VALUE; |
|
337 |
- |
|
338 | 341 |
ist->hwaccel_ctx = ctx; |
339 | 342 |
ist->hwaccel_uninit = dxva2_uninit; |
340 | 343 |
ist->hwaccel_get_buffer = dxva2_get_buffer; |
341 | 344 |
ist->hwaccel_retrieve_data = dxva2_retrieve_data; |
342 | 345 |
|
343 |
- ctx->d3dlib = LoadLibrary("d3d9.dll"); |
|
344 |
- if (!ctx->d3dlib) { |
|
346 |
+ ctx->hw_device_ctx = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_DXVA2); |
|
347 |
+ if (!ctx->hw_device_ctx) |
|
348 |
+ goto fail; |
|
349 |
+ |
|
350 |
+ device_ctx = (AVHWDeviceContext*)ctx->hw_device_ctx->data; |
|
351 |
+ device_hwctx = device_ctx->hwctx; |
|
352 |
+ |
|
353 |
+ device_priv = av_mallocz(sizeof(*device_priv)); |
|
354 |
+ if (!device_priv) |
|
355 |
+ goto fail; |
|
356 |
+ |
|
357 |
+ device_ctx->user_opaque = device_priv; |
|
358 |
+ device_ctx->free = dxva2_device_uninit; |
|
359 |
+ |
|
360 |
+ device_priv->deviceHandle = INVALID_HANDLE_VALUE; |
|
361 |
+ |
|
362 |
+ device_priv->d3dlib = LoadLibrary("d3d9.dll"); |
|
363 |
+ if (!device_priv->d3dlib) { |
|
345 | 364 |
av_log(NULL, loglevel, "Failed to load D3D9 library\n"); |
346 | 365 |
goto fail; |
347 | 366 |
} |
348 |
- ctx->dxva2lib = LoadLibrary("dxva2.dll"); |
|
349 |
- if (!ctx->dxva2lib) { |
|
367 |
+ device_priv->dxva2lib = LoadLibrary("dxva2.dll"); |
|
368 |
+ if (!device_priv->dxva2lib) { |
|
350 | 369 |
av_log(NULL, loglevel, "Failed to load DXVA2 library\n"); |
351 | 370 |
goto fail; |
352 | 371 |
} |
353 | 372 |
|
354 |
- createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9"); |
|
373 |
+ createD3D = (pDirect3DCreate9 *)GetProcAddress(device_priv->d3dlib, "Direct3DCreate9"); |
|
355 | 374 |
if (!createD3D) { |
356 | 375 |
av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n"); |
357 | 376 |
goto fail; |
358 | 377 |
} |
359 |
- createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9"); |
|
378 |
+ createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(device_priv->dxva2lib, "DXVA2CreateDirect3DDeviceManager9"); |
|
360 | 379 |
if (!createDeviceManager) { |
361 | 380 |
av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n"); |
362 | 381 |
goto fail; |
363 | 382 |
} |
364 | 383 |
|
365 |
- ctx->d3d9 = createD3D(D3D_SDK_VERSION); |
|
366 |
- if (!ctx->d3d9) { |
|
384 |
+ device_priv->d3d9 = createD3D(D3D_SDK_VERSION); |
|
385 |
+ if (!device_priv->d3d9) { |
|
367 | 386 |
av_log(NULL, loglevel, "Failed to create IDirect3D object\n"); |
368 | 387 |
goto fail; |
369 | 388 |
} |
... | ... |
@@ -373,7 +272,7 @@ static int dxva2_alloc(AVCodecContext *s) |
373 | 373 |
av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter); |
374 | 374 |
} |
375 | 375 |
|
376 |
- IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm); |
|
376 |
+ IDirect3D9_GetAdapterDisplayMode(device_priv->d3d9, adapter, &d3ddm); |
|
377 | 377 |
d3dpp.Windowed = TRUE; |
378 | 378 |
d3dpp.BackBufferWidth = 640; |
379 | 379 |
d3dpp.BackBufferHeight = 480; |
... | ... |
@@ -382,38 +281,44 @@ static int dxva2_alloc(AVCodecContext *s) |
382 | 382 |
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; |
383 | 383 |
d3dpp.Flags = D3DPRESENTFLAG_VIDEO; |
384 | 384 |
|
385 |
- hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(), |
|
385 |
+ hr = IDirect3D9_CreateDevice(device_priv->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(), |
|
386 | 386 |
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE, |
387 |
- &d3dpp, &ctx->d3d9device); |
|
387 |
+ &d3dpp, &device_priv->d3d9device); |
|
388 | 388 |
if (FAILED(hr)) { |
389 | 389 |
av_log(NULL, loglevel, "Failed to create Direct3D device\n"); |
390 | 390 |
goto fail; |
391 | 391 |
} |
392 | 392 |
|
393 |
- hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr); |
|
393 |
+ hr = createDeviceManager(&resetToken, &device_hwctx->devmgr); |
|
394 | 394 |
if (FAILED(hr)) { |
395 | 395 |
av_log(NULL, loglevel, "Failed to create Direct3D device manager\n"); |
396 | 396 |
goto fail; |
397 | 397 |
} |
398 | 398 |
|
399 |
- hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken); |
|
399 |
+ hr = IDirect3DDeviceManager9_ResetDevice(device_hwctx->devmgr, device_priv->d3d9device, resetToken); |
|
400 | 400 |
if (FAILED(hr)) { |
401 | 401 |
av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n"); |
402 | 402 |
goto fail; |
403 | 403 |
} |
404 | 404 |
|
405 |
- hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle); |
|
405 |
+ hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, &device_priv->deviceHandle); |
|
406 | 406 |
if (FAILED(hr)) { |
407 | 407 |
av_log(NULL, loglevel, "Failed to open device handle\n"); |
408 | 408 |
goto fail; |
409 | 409 |
} |
410 | 410 |
|
411 |
- hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); |
|
411 |
+ hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_priv->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service); |
|
412 | 412 |
if (FAILED(hr)) { |
413 | 413 |
av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n"); |
414 | 414 |
goto fail; |
415 | 415 |
} |
416 | 416 |
|
417 |
+ ret = av_hwdevice_ctx_init(ctx->hw_device_ctx); |
|
418 |
+ if (ret < 0) { |
|
419 |
+ av_log(NULL, loglevel, "Failed to initialize the HW device context\n"); |
|
420 |
+ goto fail; |
|
421 |
+ } |
|
422 |
+ |
|
417 | 423 |
ctx->tmp_frame = av_frame_alloc(); |
418 | 424 |
if (!ctx->tmp_frame) |
419 | 425 |
goto fail; |
... | ... |
@@ -489,9 +394,12 @@ static int dxva2_create_decoder(AVCodecContext *s) |
489 | 489 |
DXVA2_VideoDesc desc = { 0 }; |
490 | 490 |
DXVA2_ConfigPictureDecode config; |
491 | 491 |
HRESULT hr; |
492 |
- int surface_alignment; |
|
492 |
+ int surface_alignment, num_surfaces; |
|
493 | 493 |
int ret; |
494 | 494 |
|
495 |
+ AVDXVA2FramesContext *frames_hwctx; |
|
496 |
+ AVHWFramesContext *frames_ctx; |
|
497 |
+ |
|
495 | 498 |
hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list); |
496 | 499 |
if (FAILED(hr)) { |
497 | 500 |
av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n"); |
... | ... |
@@ -557,44 +465,43 @@ static int dxva2_create_decoder(AVCodecContext *s) |
557 | 557 |
surface_alignment = 16; |
558 | 558 |
|
559 | 559 |
/* 4 base work surfaces */ |
560 |
- ctx->num_surfaces = 4; |
|
560 |
+ num_surfaces = 4; |
|
561 | 561 |
|
562 | 562 |
/* add surfaces based on number of possible refs */ |
563 | 563 |
if (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC) |
564 |
- ctx->num_surfaces += 16; |
|
564 |
+ num_surfaces += 16; |
|
565 | 565 |
else if (s->codec_id == AV_CODEC_ID_VP9) |
566 |
- ctx->num_surfaces += 8; |
|
566 |
+ num_surfaces += 8; |
|
567 | 567 |
else |
568 |
- ctx->num_surfaces += 2; |
|
568 |
+ num_surfaces += 2; |
|
569 | 569 |
|
570 | 570 |
/* add extra surfaces for frame threading */ |
571 | 571 |
if (s->active_thread_type & FF_THREAD_FRAME) |
572 |
- ctx->num_surfaces += s->thread_count; |
|
573 |
- |
|
574 |
- ctx->surfaces = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surfaces)); |
|
575 |
- ctx->surface_infos = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surface_infos)); |
|
576 |
- ctx->surface_format = target_format; |
|
572 |
+ num_surfaces += s->thread_count; |
|
577 | 573 |
|
578 |
- if (!ctx->surfaces || !ctx->surface_infos) { |
|
579 |
- av_log(NULL, loglevel, "Unable to allocate surface arrays\n"); |
|
574 |
+ ctx->hw_frames_ctx = av_hwframe_ctx_alloc(ctx->hw_device_ctx); |
|
575 |
+ if (!ctx->hw_frames_ctx) |
|
580 | 576 |
goto fail; |
581 |
- } |
|
577 |
+ frames_ctx = (AVHWFramesContext*)ctx->hw_frames_ctx->data; |
|
578 |
+ frames_hwctx = frames_ctx->hwctx; |
|
582 | 579 |
|
583 |
- hr = IDirectXVideoDecoderService_CreateSurface(ctx->decoder_service, |
|
584 |
- FFALIGN(s->coded_width, surface_alignment), |
|
585 |
- FFALIGN(s->coded_height, surface_alignment), |
|
586 |
- ctx->num_surfaces - 1, |
|
587 |
- target_format, D3DPOOL_DEFAULT, 0, |
|
588 |
- DXVA2_VideoDecoderRenderTarget, |
|
589 |
- ctx->surfaces, NULL); |
|
590 |
- if (FAILED(hr)) { |
|
591 |
- av_log(NULL, loglevel, "Failed to create %d video surfaces\n", ctx->num_surfaces); |
|
580 |
+ frames_ctx->format = AV_PIX_FMT_DXVA2_VLD; |
|
581 |
+ frames_ctx->sw_format = (target_format == MKTAG('P','0','1','0') ? AV_PIX_FMT_P010 : AV_PIX_FMT_NV12); |
|
582 |
+ frames_ctx->width = FFALIGN(s->coded_width, surface_alignment); |
|
583 |
+ frames_ctx->height = FFALIGN(s->coded_height, surface_alignment); |
|
584 |
+ frames_ctx->initial_pool_size = num_surfaces; |
|
585 |
+ |
|
586 |
+ frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; |
|
587 |
+ |
|
588 |
+ ret = av_hwframe_ctx_init(ctx->hw_frames_ctx); |
|
589 |
+ if (ret < 0) { |
|
590 |
+ av_log(NULL, loglevel, "Failed to initialize the HW frames context\n"); |
|
592 | 591 |
goto fail; |
593 | 592 |
} |
594 | 593 |
|
595 | 594 |
hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid, |
596 |
- &desc, &config, ctx->surfaces, |
|
597 |
- ctx->num_surfaces, &ctx->decoder); |
|
595 |
+ &desc, &config, frames_hwctx->surfaces, |
|
596 |
+ frames_hwctx->nb_surfaces, &frames_hwctx->decoder_to_release); |
|
598 | 597 |
if (FAILED(hr)) { |
599 | 598 |
av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n"); |
600 | 599 |
goto fail; |
... | ... |
@@ -604,16 +511,16 @@ static int dxva2_create_decoder(AVCodecContext *s) |
604 | 604 |
ctx->decoder_config = config; |
605 | 605 |
|
606 | 606 |
dxva_ctx->cfg = &ctx->decoder_config; |
607 |
- dxva_ctx->decoder = ctx->decoder; |
|
608 |
- dxva_ctx->surface = ctx->surfaces; |
|
609 |
- dxva_ctx->surface_count = ctx->num_surfaces; |
|
607 |
+ dxva_ctx->decoder = frames_hwctx->decoder_to_release; |
|
608 |
+ dxva_ctx->surface = frames_hwctx->surfaces; |
|
609 |
+ dxva_ctx->surface_count = frames_hwctx->nb_surfaces; |
|
610 | 610 |
|
611 | 611 |
if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E)) |
612 | 612 |
dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; |
613 | 613 |
|
614 | 614 |
return 0; |
615 | 615 |
fail: |
616 |
- dxva2_destroy_decoder(s); |
|
616 |
+ av_buffer_unref(&ctx->hw_frames_ctx); |
|
617 | 617 |
return AVERROR(EINVAL); |
618 | 618 |
} |
619 | 619 |
|
... | ... |
@@ -643,8 +550,7 @@ int dxva2_init(AVCodecContext *s) |
643 | 643 |
return AVERROR(EINVAL); |
644 | 644 |
} |
645 | 645 |
|
646 |
- if (ctx->decoder) |
|
647 |
- dxva2_destroy_decoder(s); |
|
646 |
+ av_buffer_unref(&ctx->hw_frames_ctx); |
|
648 | 647 |
|
649 | 648 |
ret = dxva2_create_decoder(s); |
650 | 649 |
if (ret < 0) { |