24 #define _WIN32_WINNT 0x0600
25 #define DXVA2API_USE_BITFIELDS
35 #include "libavcodec/dxva2.h"
37 #include "libavutil/avassert.h"
38 #include "libavutil/buffer.h"
39 #include "libavutil/frame.h"
40 #include "libavutil/imgutils.h"
41 #include "libavutil/pixfmt.h"
46 DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
48 DEFINE_GUID(DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9);
49 DEFINE_GUID(DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60);
50 DEFINE_GUID(DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
51 DEFINE_GUID(DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
52 DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
53 DEFINE_GUID(DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
54 DEFINE_GUID(DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
55 DEFINE_GUID(DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
56 DEFINE_GUID(GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
128 IDirect3DSurface9_Release(ctx->
surfaces[i]);
137 IDirectXVideoDecoder_Release(ctx->
decoder);
161 IDirect3DDeviceManager9_Release(ctx->
d3d9devmgr);
167 IDirect3D9_Release(ctx->
d3d9);
193 IDirect3DSurface9_Release(w->
surface);
194 IDirectXVideoDecoder_Release(w->
decoder);
202 int i, old_unused = -1;
203 LPDIRECT3DSURFACE9 surface;
213 if (old_unused == -1) {
228 if (!frame->
buf[0]) {
235 IDirect3DSurface9_AddRef(w->
surface);
237 IDirectXVideoDecoder_AddRef(w->
decoder);
249 LPDIRECT3DSURFACE9 surface = (LPDIRECT3DSURFACE9)frame->
data[3];
252 D3DSURFACE_DESC surfaceDesc;
253 D3DLOCKED_RECT LockedRect;
257 IDirect3DSurface9_GetDesc(surface, &surfaceDesc);
260 ctx->tmp_frame->height = frame->
height;
267 hr = IDirect3DSurface9_LockRect(surface, &LockedRect,
NULL, D3DLOCK_READONLY);
278 (
uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
279 LockedRect.Pitch, frame->
width, frame->
height / 2);
281 IDirect3DSurface9_UnlockRect(surface);
304 D3DPRESENT_PARAMETERS d3dpp = {0};
305 D3DDISPLAYMODE d3ddm;
306 unsigned resetToken = 0;
307 UINT adapter = D3DADAPTER_DEFAULT;
322 av_log(
NULL, loglevel,
"Failed to load D3D9 library\n");
327 av_log(
NULL, loglevel,
"Failed to load DXVA2 library\n");
333 av_log(
NULL, loglevel,
"Failed to locate Direct3DCreate9\n");
337 if (!createDeviceManager) {
338 av_log(
NULL, loglevel,
"Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
342 ctx->
d3d9 = createD3D(D3D_SDK_VERSION);
344 av_log(
NULL, loglevel,
"Failed to create IDirect3D object\n");
353 IDirect3D9_GetAdapterDisplayMode(ctx->
d3d9, adapter, &d3ddm);
354 d3dpp.Windowed = TRUE;
355 d3dpp.BackBufferWidth = 640;
356 d3dpp.BackBufferHeight = 480;
357 d3dpp.BackBufferCount = 0;
358 d3dpp.BackBufferFormat = d3ddm.Format;
359 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
360 d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
362 hr = IDirect3D9_CreateDevice(ctx->
d3d9, adapter, D3DDEVTYPE_HAL, GetShellWindow(),
363 D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
366 av_log(
NULL, loglevel,
"Failed to create Direct3D device\n");
370 hr = createDeviceManager(&resetToken, &ctx->
d3d9devmgr);
372 av_log(
NULL, loglevel,
"Failed to create Direct3D device manager\n");
378 av_log(
NULL, loglevel,
"Failed to bind Direct3D device to device manager\n");
384 av_log(
NULL, loglevel,
"Failed to open device handle\n");
390 av_log(
NULL, loglevel,
"Failed to create IDirectXVideoDecoderService\n");
409 const DXVA2_VideoDesc *desc,
410 DXVA2_ConfigPictureDecode *config)
415 unsigned cfg_count = 0, best_score = 0;
416 DXVA2_ConfigPictureDecode *cfg_list =
NULL;
417 DXVA2_ConfigPictureDecode best_cfg = {{0}};
421 hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->
decoder_service, device_guid, desc,
NULL, &cfg_count, &cfg_list);
423 av_log(
NULL, loglevel,
"Unable to retrieve decoder configurations\n");
427 for (i = 0; i < cfg_count; i++) {
428 DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
431 if (cfg->ConfigBitstreamRaw == 1)
437 if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt))
439 if (score > best_score) {
444 CoTaskMemFree(cfg_list);
447 av_log(
NULL, loglevel,
"No valid decoder configuration available\n");
461 GUID *guid_list =
NULL;
462 unsigned guid_count = 0, i, j;
463 GUID device_guid = GUID_NULL;
464 D3DFORMAT target_format = 0;
465 DXVA2_VideoDesc desc = { 0 };
466 DXVA2_ConfigPictureDecode config;
468 int surface_alignment;
471 hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->
decoder_service, &guid_count, &guid_list);
473 av_log(
NULL, loglevel,
"Failed to retrieve decoder device GUIDs\n");
477 for (i = 0; dxva2_modes[i].
guid; i++) {
478 D3DFORMAT *target_list =
NULL;
479 unsigned target_count = 0;
484 for (j = 0; j < guid_count; j++) {
485 if (IsEqualGUID(mode->
guid, &guid_list[j]))
491 hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->
decoder_service, mode->
guid, &target_count, &target_list);
495 for (j = 0; j < target_count; j++) {
496 const D3DFORMAT format = target_list[j];
497 if (format ==
MKTAG(
'N',
'V',
'1',
'2')) {
498 target_format = format;
502 CoTaskMemFree(target_list);
504 device_guid = *mode->
guid;
508 CoTaskMemFree(guid_list);
510 if (IsEqualGUID(&device_guid, &GUID_NULL)) {
511 av_log(
NULL, loglevel,
"No decoder device for codec found\n");
517 desc.Format = target_format;
527 surface_alignment = 32;
529 surface_alignment = 16;
548 av_log(
NULL, loglevel,
"Unable to allocate surface arrays\n");
556 target_format, D3DPOOL_DEFAULT, 0,
557 DXVA2_VideoDecoderRenderTarget,
564 hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->
decoder_service, &device_guid,
568 av_log(
NULL, loglevel,
"Failed to create DXVA2 video decoder\n");
580 if (IsEqualGUID(&ctx->
decoder_guid, &DXVADDI_Intel_ModeH264_E))
605 av_log(
NULL, loglevel,
"Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->
profile);
614 av_log(
NULL, loglevel,
"Error creating the DXVA2 decoder\n");
This structure describes decoded (raw) audio or video data.
static void dxva2_release_buffer(void *opaque, uint8_t *data)
int coded_width
Bitstream width / height, may be different from width/height e.g.
#define FF_PROFILE_H264_CONSTRAINED
#define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO
Work around for DXVA2 and old Intel GPUs with ClearVideo interface.
static int dxva2_get_decoder_configuration(AVCodecContext *s, const GUID *device_guid, const DXVA2_VideoDesc *desc, DXVA2_ConfigPictureDecode *config)
void av_log(void *avcl, int level, const char *fmt,...) av_printf_format(3
Send the specified message to the log if the level is less than or equal to the current av_log_level...
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everythnig contained in src to dst and reset src.
static const dxva2_mode dxva2_modes[]
IDirect3DDeviceManager9 * d3d9devmgr
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
unsigned surface_count
The number of surface in the surface array.
void av_freep(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
#define FF_PROFILE_H264_HIGH
uint64_t workaround
A bit field configuring the workarounds needed for using the decoder.
AVCodecID
Identify the syntax and semantics of the bitstream.
int width
width and height of the video frame
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void av_free(void *ptr)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc(). ...
int dxva2_init(AVCodecContext *s)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
int active_thread_type
Which multithreading methods are in use by the codec.
static void dxva2_uninit(AVCodecContext *s)
static int dxva2_create_decoder(AVCodecContext *s)
DXVA2_ConfigPictureDecode decoder_config
void * opaque
Private data of the user, can be used to carry app specific stuff.
static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
const DXVA2_ConfigPictureDecode * cfg
DXVA2 configuration used to create the decoder.
IDirectXVideoDecoder * decoder
preferred ID for MPEG-1/2 video decoding
int thread_count
thread count is used to decide how many independent tasks should be passed to execute() ...
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
LPDIRECT3DSURFACE9 * surfaces
#define AV_LOG_INFO
Standard information.
void * hwaccel_context
Hardware accelerator context.
main external API structure.
#define FF_THREAD_FRAME
Decode more than one frame at once.
static int dxva2_alloc(AVCodecContext *s)
static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame)
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
IDirectXVideoDecoder * decoder
IDirect3D9 *WINAPI pDirect3DCreate9(UINT)
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
#define MKTAG(a, b, c, d)
surface_info * surface_infos
LPDIRECT3DSURFACE9 * surface
The array of Direct3D surfaces used to create the decoder.
DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551, 0xd5e7, 0x11d9, 0xaf, 0x55, 0x00, 0x05, 0x4e, 0x43, 0xff, 0x02)
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
IDirectXVideoDecoderService * decoder_service
HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **)
LPDIRECT3DSURFACE9 surface
static void dxva2_destroy_decoder(AVCodecContext *s)
#define av_assert0(cond)
assert() equivalent, that is always enabled.
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
IDirectXVideoDecoder * decoder
DXVA2 decoder object.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
void * av_mallocz(size_t size) av_malloc_attrib 1(1)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
This structure is used to provides the necessary configurations and data to the DXVA2 Libav HWAccel i...
HW decoding through DXVA2, Picture.data[3] contains a LPDIRECT3DSURFACE9 pointer. ...
IDirect3DDevice9 * d3d9device