Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <windows.h>
  20.  
  21. #ifdef _WIN32_WINNT
  22. #undef _WIN32_WINNT
  23. #endif
  24. #define _WIN32_WINNT 0x0600
  25. #define DXVA2API_USE_BITFIELDS
  26. #define COBJMACROS
  27.  
  28. #include <stdint.h>
  29.  
  30. #include <d3d9.h>
  31. #include <dxva2api.h>
  32.  
  33. #include "ffmpeg.h"
  34.  
  35. #include "libavcodec/dxva2.h"
  36.  
  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"
  42.  
  43. /* define all the GUIDs used directly here,
  44.    to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */
  45. #include <initguid.h>
  46. DEFINE_GUID(IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
  47.  
  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_ModeHEVC_VLD_Main,  0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0);
  56. DEFINE_GUID(DXVA2_NoEncrypt,          0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
  57. DEFINE_GUID(GUID_NULL,                0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
  58.  
  59. typedef IDirect3D9* WINAPI pDirect3DCreate9(UINT);
  60. typedef HRESULT WINAPI pCreateDeviceManager9(UINT *, IDirect3DDeviceManager9 **);
  61.  
  62. typedef struct dxva2_mode {
  63.   const GUID     *guid;
  64.   enum AVCodecID codec;
  65. } dxva2_mode;
  66.  
  67. static const dxva2_mode dxva2_modes[] = {
  68.     /* MPEG-2 */
  69.     { &DXVA2_ModeMPEG2_VLD,      AV_CODEC_ID_MPEG2VIDEO },
  70.     { &DXVA2_ModeMPEG2and1_VLD,  AV_CODEC_ID_MPEG2VIDEO },
  71.  
  72.     /* H.264 */
  73.     { &DXVA2_ModeH264_F,         AV_CODEC_ID_H264 },
  74.     { &DXVA2_ModeH264_E,         AV_CODEC_ID_H264 },
  75.     /* Intel specific H.264 mode */
  76.     { &DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 },
  77.  
  78.     /* VC-1 / WMV3 */
  79.     { &DXVA2_ModeVC1_D2010,      AV_CODEC_ID_VC1  },
  80.     { &DXVA2_ModeVC1_D2010,      AV_CODEC_ID_WMV3 },
  81.     { &DXVA2_ModeVC1_D,          AV_CODEC_ID_VC1  },
  82.     { &DXVA2_ModeVC1_D,          AV_CODEC_ID_WMV3 },
  83.  
  84.     /* HEVC/H.265 */
  85.     { &DXVA2_ModeHEVC_VLD_Main,  AV_CODEC_ID_HEVC },
  86.  
  87.     { NULL,                      0 },
  88. };
  89.  
  90. typedef struct surface_info {
  91.     int used;
  92.     uint64_t age;
  93. } surface_info;
  94.  
  95. typedef struct DXVA2Context {
  96.     HMODULE d3dlib;
  97.     HMODULE dxva2lib;
  98.  
  99.     HANDLE  deviceHandle;
  100.  
  101.     IDirect3D9                  *d3d9;
  102.     IDirect3DDevice9            *d3d9device;
  103.     IDirect3DDeviceManager9     *d3d9devmgr;
  104.     IDirectXVideoDecoderService *decoder_service;
  105.     IDirectXVideoDecoder        *decoder;
  106.  
  107.     GUID                        decoder_guid;
  108.     DXVA2_ConfigPictureDecode   decoder_config;
  109.  
  110.     LPDIRECT3DSURFACE9          *surfaces;
  111.     surface_info                *surface_infos;
  112.     uint32_t                    num_surfaces;
  113.     uint64_t                    surface_age;
  114.  
  115.     AVFrame                     *tmp_frame;
  116. } DXVA2Context;
  117.  
  118. typedef struct DXVA2SurfaceWrapper {
  119.     DXVA2Context         *ctx;
  120.     LPDIRECT3DSURFACE9   surface;
  121.     IDirectXVideoDecoder *decoder;
  122. } DXVA2SurfaceWrapper;
  123.  
  124. static void dxva2_destroy_decoder(AVCodecContext *s)
  125. {
  126.     InputStream  *ist = s->opaque;
  127.     DXVA2Context *ctx = ist->hwaccel_ctx;
  128.     int i;
  129.  
  130.     if (ctx->surfaces) {
  131.         for (i = 0; i < ctx->num_surfaces; i++) {
  132.             if (ctx->surfaces[i])
  133.                 IDirect3DSurface9_Release(ctx->surfaces[i]);
  134.         }
  135.     }
  136.     av_freep(&ctx->surfaces);
  137.     av_freep(&ctx->surface_infos);
  138.     ctx->num_surfaces = 0;
  139.     ctx->surface_age  = 0;
  140.  
  141.     if (ctx->decoder) {
  142.         IDirectXVideoDecoder_Release(ctx->decoder);
  143.         ctx->decoder = NULL;
  144.     }
  145. }
  146.  
  147. static void dxva2_uninit(AVCodecContext *s)
  148. {
  149.     InputStream  *ist = s->opaque;
  150.     DXVA2Context *ctx = ist->hwaccel_ctx;
  151.  
  152.     ist->hwaccel_uninit        = NULL;
  153.     ist->hwaccel_get_buffer    = NULL;
  154.     ist->hwaccel_retrieve_data = NULL;
  155.  
  156.     if (ctx->decoder)
  157.         dxva2_destroy_decoder(s);
  158.  
  159.     if (ctx->decoder_service)
  160.         IDirectXVideoDecoderService_Release(ctx->decoder_service);
  161.  
  162.     if (ctx->d3d9devmgr && ctx->deviceHandle != INVALID_HANDLE_VALUE)
  163.         IDirect3DDeviceManager9_CloseDeviceHandle(ctx->d3d9devmgr, ctx->deviceHandle);
  164.  
  165.     if (ctx->d3d9devmgr)
  166.         IDirect3DDeviceManager9_Release(ctx->d3d9devmgr);
  167.  
  168.     if (ctx->d3d9device)
  169.         IDirect3DDevice9_Release(ctx->d3d9device);
  170.  
  171.     if (ctx->d3d9)
  172.         IDirect3D9_Release(ctx->d3d9);
  173.  
  174.     if (ctx->d3dlib)
  175.         FreeLibrary(ctx->d3dlib);
  176.  
  177.     if (ctx->dxva2lib)
  178.         FreeLibrary(ctx->dxva2lib);
  179.  
  180.     av_frame_free(&ctx->tmp_frame);
  181.  
  182.     av_freep(&ist->hwaccel_ctx);
  183.     av_freep(&s->hwaccel_context);
  184. }
  185.  
  186. static void dxva2_release_buffer(void *opaque, uint8_t *data)
  187. {
  188.     DXVA2SurfaceWrapper *w   = opaque;
  189.     DXVA2Context        *ctx = w->ctx;
  190.     int i;
  191.  
  192.     for (i = 0; i < ctx->num_surfaces; i++) {
  193.         if (ctx->surfaces[i] == w->surface) {
  194.             ctx->surface_infos[i].used = 0;
  195.             break;
  196.         }
  197.     }
  198.     IDirect3DSurface9_Release(w->surface);
  199.     IDirectXVideoDecoder_Release(w->decoder);
  200.     av_free(w);
  201. }
  202.  
  203. static int dxva2_get_buffer(AVCodecContext *s, AVFrame *frame, int flags)
  204. {
  205.     InputStream  *ist = s->opaque;
  206.     DXVA2Context *ctx = ist->hwaccel_ctx;
  207.     int i, old_unused = -1;
  208.     LPDIRECT3DSURFACE9 surface;
  209.     DXVA2SurfaceWrapper *w = NULL;
  210.  
  211.     av_assert0(frame->format == AV_PIX_FMT_DXVA2_VLD);
  212.  
  213.     for (i = 0; i < ctx->num_surfaces; i++) {
  214.         surface_info *info = &ctx->surface_infos[i];
  215.         if (!info->used && (old_unused == -1 || info->age < ctx->surface_infos[old_unused].age))
  216.             old_unused = i;
  217.     }
  218.     if (old_unused == -1) {
  219.         av_log(NULL, AV_LOG_ERROR, "No free DXVA2 surface!\n");
  220.         return AVERROR(ENOMEM);
  221.     }
  222.     i = old_unused;
  223.  
  224.     surface = ctx->surfaces[i];
  225.  
  226.     w = av_mallocz(sizeof(*w));
  227.     if (!w)
  228.         return AVERROR(ENOMEM);
  229.  
  230.     frame->buf[0] = av_buffer_create((uint8_t*)surface, 0,
  231.                                      dxva2_release_buffer, w,
  232.                                      AV_BUFFER_FLAG_READONLY);
  233.     if (!frame->buf[0]) {
  234.         av_free(w);
  235.         return AVERROR(ENOMEM);
  236.     }
  237.  
  238.     w->ctx     = ctx;
  239.     w->surface = surface;
  240.     IDirect3DSurface9_AddRef(w->surface);
  241.     w->decoder = ctx->decoder;
  242.     IDirectXVideoDecoder_AddRef(w->decoder);
  243.  
  244.     ctx->surface_infos[i].used = 1;
  245.     ctx->surface_infos[i].age  = ctx->surface_age++;
  246.  
  247.     frame->data[3] = (uint8_t *)surface;
  248.  
  249.     return 0;
  250. }
  251.  
  252. static int dxva2_retrieve_data(AVCodecContext *s, AVFrame *frame)
  253. {
  254.     LPDIRECT3DSURFACE9 surface =  (LPDIRECT3DSURFACE9)frame->data[3];
  255.     InputStream        *ist = s->opaque;
  256.     DXVA2Context       *ctx = ist->hwaccel_ctx;
  257.     D3DSURFACE_DESC    surfaceDesc;
  258.     D3DLOCKED_RECT     LockedRect;
  259.     HRESULT            hr;
  260.     int                ret;
  261.  
  262.     IDirect3DSurface9_GetDesc(surface, &surfaceDesc);
  263.  
  264.     ctx->tmp_frame->width  = frame->width;
  265.     ctx->tmp_frame->height = frame->height;
  266.     ctx->tmp_frame->format = AV_PIX_FMT_NV12;
  267.  
  268.     ret = av_frame_get_buffer(ctx->tmp_frame, 32);
  269.     if (ret < 0)
  270.         return ret;
  271.  
  272.     hr = IDirect3DSurface9_LockRect(surface, &LockedRect, NULL, D3DLOCK_READONLY);
  273.     if (FAILED(hr)) {
  274.         av_log(NULL, AV_LOG_ERROR, "Unable to lock DXVA2 surface\n");
  275.         return AVERROR_UNKNOWN;
  276.     }
  277.  
  278.     av_image_copy_plane(ctx->tmp_frame->data[0], ctx->tmp_frame->linesize[0],
  279.                         (uint8_t*)LockedRect.pBits,
  280.                         LockedRect.Pitch, frame->width, frame->height);
  281.  
  282.     av_image_copy_plane(ctx->tmp_frame->data[1], ctx->tmp_frame->linesize[1],
  283.                         (uint8_t*)LockedRect.pBits + LockedRect.Pitch * surfaceDesc.Height,
  284.                         LockedRect.Pitch, frame->width, frame->height / 2);
  285.  
  286.     IDirect3DSurface9_UnlockRect(surface);
  287.  
  288.     ret = av_frame_copy_props(ctx->tmp_frame, frame);
  289.     if (ret < 0)
  290.         goto fail;
  291.  
  292.     av_frame_unref(frame);
  293.     av_frame_move_ref(frame, ctx->tmp_frame);
  294.  
  295.     return 0;
  296. fail:
  297.     av_frame_unref(ctx->tmp_frame);
  298.     return ret;
  299. }
  300.  
  301. static int dxva2_alloc(AVCodecContext *s)
  302. {
  303.     InputStream  *ist = s->opaque;
  304.     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  305.     DXVA2Context *ctx;
  306.     pDirect3DCreate9      *createD3D = NULL;
  307.     pCreateDeviceManager9 *createDeviceManager = NULL;
  308.     HRESULT hr;
  309.     D3DPRESENT_PARAMETERS d3dpp = {0};
  310.     D3DDISPLAYMODE        d3ddm;
  311.     unsigned resetToken = 0;
  312.     UINT adapter = D3DADAPTER_DEFAULT;
  313.  
  314.     ctx = av_mallocz(sizeof(*ctx));
  315.     if (!ctx)
  316.         return AVERROR(ENOMEM);
  317.  
  318.     ctx->deviceHandle = INVALID_HANDLE_VALUE;
  319.  
  320.     ist->hwaccel_ctx           = ctx;
  321.     ist->hwaccel_uninit        = dxva2_uninit;
  322.     ist->hwaccel_get_buffer    = dxva2_get_buffer;
  323.     ist->hwaccel_retrieve_data = dxva2_retrieve_data;
  324.  
  325.     ctx->d3dlib = LoadLibrary("d3d9.dll");
  326.     if (!ctx->d3dlib) {
  327.         av_log(NULL, loglevel, "Failed to load D3D9 library\n");
  328.         goto fail;
  329.     }
  330.     ctx->dxva2lib = LoadLibrary("dxva2.dll");
  331.     if (!ctx->dxva2lib) {
  332.         av_log(NULL, loglevel, "Failed to load DXVA2 library\n");
  333.         goto fail;
  334.     }
  335.  
  336.     createD3D = (pDirect3DCreate9 *)GetProcAddress(ctx->d3dlib, "Direct3DCreate9");
  337.     if (!createD3D) {
  338.         av_log(NULL, loglevel, "Failed to locate Direct3DCreate9\n");
  339.         goto fail;
  340.     }
  341.     createDeviceManager = (pCreateDeviceManager9 *)GetProcAddress(ctx->dxva2lib, "DXVA2CreateDirect3DDeviceManager9");
  342.     if (!createDeviceManager) {
  343.         av_log(NULL, loglevel, "Failed to locate DXVA2CreateDirect3DDeviceManager9\n");
  344.         goto fail;
  345.     }
  346.  
  347.     ctx->d3d9 = createD3D(D3D_SDK_VERSION);
  348.     if (!ctx->d3d9) {
  349.         av_log(NULL, loglevel, "Failed to create IDirect3D object\n");
  350.         goto fail;
  351.     }
  352.  
  353.     if (ist->hwaccel_device) {
  354.         adapter = atoi(ist->hwaccel_device);
  355.         av_log(NULL, AV_LOG_INFO, "Using HWAccel device %d\n", adapter);
  356.     }
  357.  
  358.     IDirect3D9_GetAdapterDisplayMode(ctx->d3d9, adapter, &d3ddm);
  359.     d3dpp.Windowed         = TRUE;
  360.     d3dpp.BackBufferWidth  = 640;
  361.     d3dpp.BackBufferHeight = 480;
  362.     d3dpp.BackBufferCount  = 0;
  363.     d3dpp.BackBufferFormat = d3ddm.Format;
  364.     d3dpp.SwapEffect       = D3DSWAPEFFECT_DISCARD;
  365.     d3dpp.Flags            = D3DPRESENTFLAG_VIDEO;
  366.  
  367.     hr = IDirect3D9_CreateDevice(ctx->d3d9, adapter, D3DDEVTYPE_HAL, GetDesktopWindow(),
  368.                                  D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_MULTITHREADED | D3DCREATE_FPU_PRESERVE,
  369.                                  &d3dpp, &ctx->d3d9device);
  370.     if (FAILED(hr)) {
  371.         av_log(NULL, loglevel, "Failed to create Direct3D device\n");
  372.         goto fail;
  373.     }
  374.  
  375.     hr = createDeviceManager(&resetToken, &ctx->d3d9devmgr);
  376.     if (FAILED(hr)) {
  377.         av_log(NULL, loglevel, "Failed to create Direct3D device manager\n");
  378.         goto fail;
  379.     }
  380.  
  381.     hr = IDirect3DDeviceManager9_ResetDevice(ctx->d3d9devmgr, ctx->d3d9device, resetToken);
  382.     if (FAILED(hr)) {
  383.         av_log(NULL, loglevel, "Failed to bind Direct3D device to device manager\n");
  384.         goto fail;
  385.     }
  386.  
  387.     hr = IDirect3DDeviceManager9_OpenDeviceHandle(ctx->d3d9devmgr, &ctx->deviceHandle);
  388.     if (FAILED(hr)) {
  389.         av_log(NULL, loglevel, "Failed to open device handle\n");
  390.         goto fail;
  391.     }
  392.  
  393.     hr = IDirect3DDeviceManager9_GetVideoService(ctx->d3d9devmgr, ctx->deviceHandle, &IID_IDirectXVideoDecoderService, (void **)&ctx->decoder_service);
  394.     if (FAILED(hr)) {
  395.         av_log(NULL, loglevel, "Failed to create IDirectXVideoDecoderService\n");
  396.         goto fail;
  397.     }
  398.  
  399.     ctx->tmp_frame = av_frame_alloc();
  400.     if (!ctx->tmp_frame)
  401.         goto fail;
  402.  
  403.     s->hwaccel_context = av_mallocz(sizeof(struct dxva_context));
  404.     if (!s->hwaccel_context)
  405.         goto fail;
  406.  
  407.     return 0;
  408. fail:
  409.     dxva2_uninit(s);
  410.     return AVERROR(EINVAL);
  411. }
  412.  
  413. static int dxva2_get_decoder_configuration(AVCodecContext *s, const GUID *device_guid,
  414.                                            const DXVA2_VideoDesc *desc,
  415.                                            DXVA2_ConfigPictureDecode *config)
  416. {
  417.     InputStream  *ist = s->opaque;
  418.     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  419.     DXVA2Context *ctx = ist->hwaccel_ctx;
  420.     unsigned cfg_count = 0, best_score = 0;
  421.     DXVA2_ConfigPictureDecode *cfg_list = NULL;
  422.     DXVA2_ConfigPictureDecode best_cfg = {{0}};
  423.     HRESULT hr;
  424.     int i;
  425.  
  426.     hr = IDirectXVideoDecoderService_GetDecoderConfigurations(ctx->decoder_service, device_guid, desc, NULL, &cfg_count, &cfg_list);
  427.     if (FAILED(hr)) {
  428.         av_log(NULL, loglevel, "Unable to retrieve decoder configurations\n");
  429.         return AVERROR(EINVAL);
  430.     }
  431.  
  432.     for (i = 0; i < cfg_count; i++) {
  433.         DXVA2_ConfigPictureDecode *cfg = &cfg_list[i];
  434.  
  435.         unsigned score;
  436.         if (cfg->ConfigBitstreamRaw == 1)
  437.             score = 1;
  438.         else if (s->codec_id == AV_CODEC_ID_H264 && cfg->ConfigBitstreamRaw == 2)
  439.             score = 2;
  440.         else
  441.             continue;
  442.         if (IsEqualGUID(&cfg->guidConfigBitstreamEncryption, &DXVA2_NoEncrypt))
  443.             score += 16;
  444.         if (score > best_score) {
  445.             best_score = score;
  446.             best_cfg   = *cfg;
  447.         }
  448.     }
  449.     CoTaskMemFree(cfg_list);
  450.  
  451.     if (!best_score) {
  452.         av_log(NULL, loglevel, "No valid decoder configuration available\n");
  453.         return AVERROR(EINVAL);
  454.     }
  455.  
  456.     *config = best_cfg;
  457.     return 0;
  458. }
  459.  
  460. static int dxva2_create_decoder(AVCodecContext *s)
  461. {
  462.     InputStream  *ist = s->opaque;
  463.     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  464.     DXVA2Context *ctx = ist->hwaccel_ctx;
  465.     struct dxva_context *dxva_ctx = s->hwaccel_context;
  466.     GUID *guid_list = NULL;
  467.     unsigned guid_count = 0, i, j;
  468.     GUID device_guid = GUID_NULL;
  469.     D3DFORMAT target_format = 0;
  470.     DXVA2_VideoDesc desc = { 0 };
  471.     DXVA2_ConfigPictureDecode config;
  472.     HRESULT hr;
  473.     int surface_alignment;
  474.     int ret;
  475.  
  476.     hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(ctx->decoder_service, &guid_count, &guid_list);
  477.     if (FAILED(hr)) {
  478.         av_log(NULL, loglevel, "Failed to retrieve decoder device GUIDs\n");
  479.         goto fail;
  480.     }
  481.  
  482.     for (i = 0; dxva2_modes[i].guid; i++) {
  483.         D3DFORMAT *target_list = NULL;
  484.         unsigned target_count = 0;
  485.         const dxva2_mode *mode = &dxva2_modes[i];
  486.         if (mode->codec != s->codec_id)
  487.             continue;
  488.  
  489.         for (j = 0; j < guid_count; j++) {
  490.             if (IsEqualGUID(mode->guid, &guid_list[j]))
  491.                 break;
  492.         }
  493.         if (j == guid_count)
  494.             continue;
  495.  
  496.         hr = IDirectXVideoDecoderService_GetDecoderRenderTargets(ctx->decoder_service, mode->guid, &target_count, &target_list);
  497.         if (FAILED(hr)) {
  498.             continue;
  499.         }
  500.         for (j = 0; j < target_count; j++) {
  501.             const D3DFORMAT format = target_list[j];
  502.             if (format == MKTAG('N','V','1','2')) {
  503.                 target_format = format;
  504.                 break;
  505.             }
  506.         }
  507.         CoTaskMemFree(target_list);
  508.         if (target_format) {
  509.             device_guid = *mode->guid;
  510.             break;
  511.         }
  512.     }
  513.     CoTaskMemFree(guid_list);
  514.  
  515.     if (IsEqualGUID(&device_guid, &GUID_NULL)) {
  516.         av_log(NULL, loglevel, "No decoder device for codec found\n");
  517.         goto fail;
  518.     }
  519.  
  520.     desc.SampleWidth  = s->coded_width;
  521.     desc.SampleHeight = s->coded_height;
  522.     desc.Format       = target_format;
  523.  
  524.     ret = dxva2_get_decoder_configuration(s, &device_guid, &desc, &config);
  525.     if (ret < 0) {
  526.         goto fail;
  527.     }
  528.  
  529.     /* decoding MPEG-2 requires additional alignment on some Intel GPUs,
  530.        but it causes issues for H.264 on certain AMD GPUs..... */
  531.     if (s->codec_id == AV_CODEC_ID_MPEG2VIDEO)
  532.         surface_alignment = 32;
  533.     /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure
  534.        all coding features have enough room to work with */
  535.     else if  (s->codec_id == AV_CODEC_ID_HEVC)
  536.         surface_alignment = 128;
  537.     else
  538.         surface_alignment = 16;
  539.  
  540.     /* 4 base work surfaces */
  541.     ctx->num_surfaces = 4;
  542.  
  543.     /* add surfaces based on number of possible refs */
  544.     if (s->codec_id == AV_CODEC_ID_H264 || s->codec_id == AV_CODEC_ID_HEVC)
  545.         ctx->num_surfaces += 16;
  546.     else
  547.         ctx->num_surfaces += 2;
  548.  
  549.     /* add extra surfaces for frame threading */
  550.     if (s->active_thread_type & FF_THREAD_FRAME)
  551.         ctx->num_surfaces += s->thread_count;
  552.  
  553.     ctx->surfaces      = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surfaces));
  554.     ctx->surface_infos = av_mallocz(ctx->num_surfaces * sizeof(*ctx->surface_infos));
  555.  
  556.     if (!ctx->surfaces || !ctx->surface_infos) {
  557.         av_log(NULL, loglevel, "Unable to allocate surface arrays\n");
  558.         goto fail;
  559.     }
  560.  
  561.     hr = IDirectXVideoDecoderService_CreateSurface(ctx->decoder_service,
  562.                                                    FFALIGN(s->coded_width, surface_alignment),
  563.                                                    FFALIGN(s->coded_height, surface_alignment),
  564.                                                    ctx->num_surfaces - 1,
  565.                                                    target_format, D3DPOOL_DEFAULT, 0,
  566.                                                    DXVA2_VideoDecoderRenderTarget,
  567.                                                    ctx->surfaces, NULL);
  568.     if (FAILED(hr)) {
  569.         av_log(NULL, loglevel, "Failed to create %d video surfaces\n", ctx->num_surfaces);
  570.         goto fail;
  571.     }
  572.  
  573.     hr = IDirectXVideoDecoderService_CreateVideoDecoder(ctx->decoder_service, &device_guid,
  574.                                                         &desc, &config, ctx->surfaces,
  575.                                                         ctx->num_surfaces, &ctx->decoder);
  576.     if (FAILED(hr)) {
  577.         av_log(NULL, loglevel, "Failed to create DXVA2 video decoder\n");
  578.         goto fail;
  579.     }
  580.  
  581.     ctx->decoder_guid   = device_guid;
  582.     ctx->decoder_config = config;
  583.  
  584.     dxva_ctx->cfg           = &ctx->decoder_config;
  585.     dxva_ctx->decoder       = ctx->decoder;
  586.     dxva_ctx->surface       = ctx->surfaces;
  587.     dxva_ctx->surface_count = ctx->num_surfaces;
  588.  
  589.     if (IsEqualGUID(&ctx->decoder_guid, &DXVADDI_Intel_ModeH264_E))
  590.         dxva_ctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO;
  591.  
  592.     return 0;
  593. fail:
  594.     dxva2_destroy_decoder(s);
  595.     return AVERROR(EINVAL);
  596. }
  597.  
  598. int dxva2_init(AVCodecContext *s)
  599. {
  600.     InputStream *ist = s->opaque;
  601.     int loglevel = (ist->hwaccel_id == HWACCEL_AUTO) ? AV_LOG_VERBOSE : AV_LOG_ERROR;
  602.     DXVA2Context *ctx;
  603.     int ret;
  604.  
  605.     if (!ist->hwaccel_ctx) {
  606.         ret = dxva2_alloc(s);
  607.         if (ret < 0)
  608.             return ret;
  609.     }
  610.     ctx = ist->hwaccel_ctx;
  611.  
  612.     if (s->codec_id == AV_CODEC_ID_H264 &&
  613.         (s->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) {
  614.         av_log(NULL, loglevel, "Unsupported H.264 profile for DXVA2 HWAccel: %d\n", s->profile);
  615.         return AVERROR(EINVAL);
  616.     }
  617.  
  618.     if (ctx->decoder)
  619.         dxva2_destroy_decoder(s);
  620.  
  621.     ret = dxva2_create_decoder(s);
  622.     if (ret < 0) {
  623.         av_log(NULL, loglevel, "Error creating the DXVA2 decoder\n");
  624.         return ret;
  625.     }
  626.  
  627.     return 0;
  628. }
  629.