1cabdff1aSopenharmony_ci/* 2cabdff1aSopenharmony_ci * DXVA2 HW acceleration. 3cabdff1aSopenharmony_ci * 4cabdff1aSopenharmony_ci * copyright (c) 2010 Laurent Aimar 5cabdff1aSopenharmony_ci * 6cabdff1aSopenharmony_ci * This file is part of FFmpeg. 7cabdff1aSopenharmony_ci * 8cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or 9cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public 10cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either 11cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version. 12cabdff1aSopenharmony_ci * 13cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful, 14cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 15cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16cabdff1aSopenharmony_ci * Lesser General Public License for more details. 17cabdff1aSopenharmony_ci * 18cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public 19cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software 20cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 21cabdff1aSopenharmony_ci */ 22cabdff1aSopenharmony_ci 23cabdff1aSopenharmony_ci#include <assert.h> 24cabdff1aSopenharmony_ci#include <string.h> 25cabdff1aSopenharmony_ci#include <initguid.h> 26cabdff1aSopenharmony_ci 27cabdff1aSopenharmony_ci#include "libavutil/common.h" 28cabdff1aSopenharmony_ci#include "libavutil/log.h" 29cabdff1aSopenharmony_ci#include "libavutil/time.h" 30cabdff1aSopenharmony_ci 31cabdff1aSopenharmony_ci#include "avcodec.h" 32cabdff1aSopenharmony_ci#include "decode.h" 33cabdff1aSopenharmony_ci#include "dxva2_internal.h" 34cabdff1aSopenharmony_ci 35cabdff1aSopenharmony_ci/* define all the GUIDs used directly here, 36cabdff1aSopenharmony_ci to avoid problems with inconsistent dxva2api.h versions in mingw-w64 and different MSVC version */ 37cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeMPEG2_VLD, 0xee27417f, 0x5e28,0x4e65,0xbe,0xea,0x1d,0x26,0xb5,0x08,0xad,0xc9); 38cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeMPEG2and1_VLD, 0x86695f12, 0x340e,0x4f04,0x9f,0xd3,0x92,0x53,0xdd,0x32,0x74,0x60); 39cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeH264_E, 0x1b81be68, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); 40cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeH264_F, 0x1b81be69, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); 41cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVADDI_Intel_ModeH264_E, 0x604F8E68, 0x4951,0x4C54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6); 42cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeVC1_D, 0x1b81beA3, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); 43cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeVC1_D2010, 0x1b81beA4, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); 44cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main, 0x5b11d51b, 0x2f4c,0x4452,0xbc,0xc3,0x09,0xf2,0xa1,0x16,0x0c,0xc0); 45cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10,0x107af0e0, 0xef1a,0x4d19,0xab,0xa8,0x67,0xa1,0x63,0x07,0x3d,0x13); 46cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x83,0xaa,0x6d,0x60,0xb8,0x9e); 47cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7); 48cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a); 49cabdff1aSopenharmony_ciDEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); 50cabdff1aSopenharmony_ciDEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00); 51cabdff1aSopenharmony_ciDEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02); 52cabdff1aSopenharmony_ci 53cabdff1aSopenharmony_citypedef struct dxva_mode { 54cabdff1aSopenharmony_ci const GUID *guid; 55cabdff1aSopenharmony_ci enum AVCodecID codec; 56cabdff1aSopenharmony_ci // List of supported profiles, terminated by a FF_PROFILE_UNKNOWN entry. 57cabdff1aSopenharmony_ci // If NULL, don't check profile. 58cabdff1aSopenharmony_ci const int *profiles; 59cabdff1aSopenharmony_ci} dxva_mode; 60cabdff1aSopenharmony_ci 61cabdff1aSopenharmony_cistatic const int prof_mpeg2_main[] = {FF_PROFILE_MPEG2_SIMPLE, 62cabdff1aSopenharmony_ci FF_PROFILE_MPEG2_MAIN, 63cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 64cabdff1aSopenharmony_cistatic const int prof_h264_high[] = {FF_PROFILE_H264_CONSTRAINED_BASELINE, 65cabdff1aSopenharmony_ci FF_PROFILE_H264_MAIN, 66cabdff1aSopenharmony_ci FF_PROFILE_H264_HIGH, 67cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 68cabdff1aSopenharmony_cistatic const int prof_hevc_main[] = {FF_PROFILE_HEVC_MAIN, 69cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 70cabdff1aSopenharmony_cistatic const int prof_hevc_main10[] = {FF_PROFILE_HEVC_MAIN_10, 71cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 72cabdff1aSopenharmony_cistatic const int prof_vp9_profile0[] = {FF_PROFILE_VP9_0, 73cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 74cabdff1aSopenharmony_cistatic const int prof_vp9_profile2[] = {FF_PROFILE_VP9_2, 75cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 76cabdff1aSopenharmony_cistatic const int prof_av1_profile0[] = {FF_PROFILE_AV1_MAIN, 77cabdff1aSopenharmony_ci FF_PROFILE_UNKNOWN}; 78cabdff1aSopenharmony_ci 79cabdff1aSopenharmony_cistatic const dxva_mode dxva_modes[] = { 80cabdff1aSopenharmony_ci /* MPEG-2 */ 81cabdff1aSopenharmony_ci { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main }, 82cabdff1aSopenharmony_ci { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main }, 83cabdff1aSopenharmony_ci 84cabdff1aSopenharmony_ci /* H.264 */ 85cabdff1aSopenharmony_ci { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264, prof_h264_high }, 86cabdff1aSopenharmony_ci { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264, prof_h264_high }, 87cabdff1aSopenharmony_ci /* Intel specific H.264 mode */ 88cabdff1aSopenharmony_ci { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264, prof_h264_high }, 89cabdff1aSopenharmony_ci 90cabdff1aSopenharmony_ci /* VC-1 / WMV3 */ 91cabdff1aSopenharmony_ci { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 }, 92cabdff1aSopenharmony_ci { &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_WMV3 }, 93cabdff1aSopenharmony_ci { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_VC1 }, 94cabdff1aSopenharmony_ci { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 }, 95cabdff1aSopenharmony_ci 96cabdff1aSopenharmony_ci /* HEVC/H.265 */ 97cabdff1aSopenharmony_ci { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 }, 98cabdff1aSopenharmony_ci { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main }, 99cabdff1aSopenharmony_ci 100cabdff1aSopenharmony_ci /* VP8/9 */ 101cabdff1aSopenharmony_ci { &ff_DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9, prof_vp9_profile0 }, 102cabdff1aSopenharmony_ci { &ff_DXVA2_ModeVP9_VLD_10bit_Profile2, AV_CODEC_ID_VP9, prof_vp9_profile2 }, 103cabdff1aSopenharmony_ci 104cabdff1aSopenharmony_ci /* AV1 */ 105cabdff1aSopenharmony_ci { &ff_DXVA2_ModeAV1_VLD_Profile0, AV_CODEC_ID_AV1, prof_av1_profile0 }, 106cabdff1aSopenharmony_ci 107cabdff1aSopenharmony_ci { NULL, 0 }, 108cabdff1aSopenharmony_ci}; 109cabdff1aSopenharmony_ci 110cabdff1aSopenharmony_cistatic int dxva_get_decoder_configuration(AVCodecContext *avctx, 111cabdff1aSopenharmony_ci const void *cfg_list, 112cabdff1aSopenharmony_ci unsigned cfg_count) 113cabdff1aSopenharmony_ci{ 114cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 115cabdff1aSopenharmony_ci unsigned i, best_score = 0; 116cabdff1aSopenharmony_ci int best_cfg = -1; 117cabdff1aSopenharmony_ci 118cabdff1aSopenharmony_ci for (i = 0; i < cfg_count; i++) { 119cabdff1aSopenharmony_ci unsigned score; 120cabdff1aSopenharmony_ci UINT ConfigBitstreamRaw; 121cabdff1aSopenharmony_ci GUID guidConfigBitstreamEncryption; 122cabdff1aSopenharmony_ci 123cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 124cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { 125cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_CONFIG *cfg = &((D3D11_VIDEO_DECODER_CONFIG *)cfg_list)[i]; 126cabdff1aSopenharmony_ci ConfigBitstreamRaw = cfg->ConfigBitstreamRaw; 127cabdff1aSopenharmony_ci guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption; 128cabdff1aSopenharmony_ci } 129cabdff1aSopenharmony_ci#endif 130cabdff1aSopenharmony_ci#if CONFIG_DXVA2 131cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 132cabdff1aSopenharmony_ci DXVA2_ConfigPictureDecode *cfg = &((DXVA2_ConfigPictureDecode *)cfg_list)[i]; 133cabdff1aSopenharmony_ci ConfigBitstreamRaw = cfg->ConfigBitstreamRaw; 134cabdff1aSopenharmony_ci guidConfigBitstreamEncryption = cfg->guidConfigBitstreamEncryption; 135cabdff1aSopenharmony_ci } 136cabdff1aSopenharmony_ci#endif 137cabdff1aSopenharmony_ci 138cabdff1aSopenharmony_ci if (ConfigBitstreamRaw == 1) 139cabdff1aSopenharmony_ci score = 1; 140cabdff1aSopenharmony_ci else if (avctx->codec_id == AV_CODEC_ID_H264 && ConfigBitstreamRaw == 2) 141cabdff1aSopenharmony_ci score = 2; 142cabdff1aSopenharmony_ci else 143cabdff1aSopenharmony_ci continue; 144cabdff1aSopenharmony_ci if (IsEqualGUID(&guidConfigBitstreamEncryption, &ff_DXVA2_NoEncrypt)) 145cabdff1aSopenharmony_ci score += 16; 146cabdff1aSopenharmony_ci if (score > best_score) { 147cabdff1aSopenharmony_ci best_score = score; 148cabdff1aSopenharmony_ci best_cfg = i; 149cabdff1aSopenharmony_ci } 150cabdff1aSopenharmony_ci } 151cabdff1aSopenharmony_ci 152cabdff1aSopenharmony_ci if (!best_score) { 153cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "No valid decoder configuration available\n"); 154cabdff1aSopenharmony_ci return AVERROR(EINVAL); 155cabdff1aSopenharmony_ci } 156cabdff1aSopenharmony_ci 157cabdff1aSopenharmony_ci return best_cfg; 158cabdff1aSopenharmony_ci} 159cabdff1aSopenharmony_ci 160cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 161cabdff1aSopenharmony_cistatic int d3d11va_validate_output(void *service, GUID guid, const void *surface_format) 162cabdff1aSopenharmony_ci{ 163cabdff1aSopenharmony_ci HRESULT hr; 164cabdff1aSopenharmony_ci BOOL is_supported = FALSE; 165cabdff1aSopenharmony_ci hr = ID3D11VideoDevice_CheckVideoDecoderFormat((ID3D11VideoDevice *)service, 166cabdff1aSopenharmony_ci &guid, 167cabdff1aSopenharmony_ci *(DXGI_FORMAT *)surface_format, 168cabdff1aSopenharmony_ci &is_supported); 169cabdff1aSopenharmony_ci return SUCCEEDED(hr) && is_supported; 170cabdff1aSopenharmony_ci} 171cabdff1aSopenharmony_ci#endif 172cabdff1aSopenharmony_ci 173cabdff1aSopenharmony_ci#if CONFIG_DXVA2 174cabdff1aSopenharmony_cistatic int dxva2_validate_output(void *decoder_service, GUID guid, const void *surface_format) 175cabdff1aSopenharmony_ci{ 176cabdff1aSopenharmony_ci HRESULT hr; 177cabdff1aSopenharmony_ci int ret = 0; 178cabdff1aSopenharmony_ci unsigned j, target_count; 179cabdff1aSopenharmony_ci D3DFORMAT *target_list; 180cabdff1aSopenharmony_ci hr = IDirectXVideoDecoderService_GetDecoderRenderTargets((IDirectXVideoDecoderService *)decoder_service, &guid, &target_count, &target_list); 181cabdff1aSopenharmony_ci if (SUCCEEDED(hr)) { 182cabdff1aSopenharmony_ci for (j = 0; j < target_count; j++) { 183cabdff1aSopenharmony_ci const D3DFORMAT format = target_list[j]; 184cabdff1aSopenharmony_ci if (format == *(D3DFORMAT *)surface_format) { 185cabdff1aSopenharmony_ci ret = 1; 186cabdff1aSopenharmony_ci break; 187cabdff1aSopenharmony_ci } 188cabdff1aSopenharmony_ci } 189cabdff1aSopenharmony_ci CoTaskMemFree(target_list); 190cabdff1aSopenharmony_ci } 191cabdff1aSopenharmony_ci return ret; 192cabdff1aSopenharmony_ci} 193cabdff1aSopenharmony_ci#endif 194cabdff1aSopenharmony_ci 195cabdff1aSopenharmony_cistatic int dxva_check_codec_compatibility(AVCodecContext *avctx, const dxva_mode *mode) 196cabdff1aSopenharmony_ci{ 197cabdff1aSopenharmony_ci if (mode->codec != avctx->codec_id) 198cabdff1aSopenharmony_ci return 0; 199cabdff1aSopenharmony_ci 200cabdff1aSopenharmony_ci if (mode->profiles && !(avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH)) { 201cabdff1aSopenharmony_ci int i, found = 0; 202cabdff1aSopenharmony_ci for (i = 0; mode->profiles[i] != FF_PROFILE_UNKNOWN; i++) { 203cabdff1aSopenharmony_ci if (avctx->profile == mode->profiles[i]) { 204cabdff1aSopenharmony_ci found = 1; 205cabdff1aSopenharmony_ci break; 206cabdff1aSopenharmony_ci } 207cabdff1aSopenharmony_ci } 208cabdff1aSopenharmony_ci if (!found) 209cabdff1aSopenharmony_ci return 0; 210cabdff1aSopenharmony_ci } 211cabdff1aSopenharmony_ci 212cabdff1aSopenharmony_ci return 1; 213cabdff1aSopenharmony_ci} 214cabdff1aSopenharmony_ci 215cabdff1aSopenharmony_cistatic void dxva_list_guids_debug(AVCodecContext *avctx, void *service, 216cabdff1aSopenharmony_ci unsigned guid_count, const GUID *guid_list) 217cabdff1aSopenharmony_ci{ 218cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 219cabdff1aSopenharmony_ci int i; 220cabdff1aSopenharmony_ci 221cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "Decoder GUIDs reported as supported:\n"); 222cabdff1aSopenharmony_ci 223cabdff1aSopenharmony_ci for (i = 0; i < guid_count; i++) { 224cabdff1aSopenharmony_ci const GUID *guid = &guid_list[i]; 225cabdff1aSopenharmony_ci 226cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, 227cabdff1aSopenharmony_ci "{%8.8x-%4.4x-%4.4x-%2.2x%2.2x-%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x}", 228cabdff1aSopenharmony_ci (unsigned) guid->Data1, guid->Data2, guid->Data3, 229cabdff1aSopenharmony_ci guid->Data4[0], guid->Data4[1], 230cabdff1aSopenharmony_ci guid->Data4[2], guid->Data4[3], 231cabdff1aSopenharmony_ci guid->Data4[4], guid->Data4[5], 232cabdff1aSopenharmony_ci guid->Data4[6], guid->Data4[7]); 233cabdff1aSopenharmony_ci 234cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 235cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { 236cabdff1aSopenharmony_ci DXGI_FORMAT format; 237cabdff1aSopenharmony_ci // We don't know the maximum valid DXGI_FORMAT, so use 200 as 238cabdff1aSopenharmony_ci // arbitrary upper bound (that could become outdated). 239cabdff1aSopenharmony_ci for (format = 0; format < 200; format++) { 240cabdff1aSopenharmony_ci if (d3d11va_validate_output(service, *guid, &format)) 241cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, " %d", (int)format); 242cabdff1aSopenharmony_ci } 243cabdff1aSopenharmony_ci } 244cabdff1aSopenharmony_ci#endif 245cabdff1aSopenharmony_ci#if CONFIG_DXVA2 246cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 247cabdff1aSopenharmony_ci const D3DFORMAT formats[] = {MKTAG('N', 'V', '1', '2'), 248cabdff1aSopenharmony_ci MKTAG('P', '0', '1', '0')}; 249cabdff1aSopenharmony_ci int i; 250cabdff1aSopenharmony_ci for (i = 0; i < FF_ARRAY_ELEMS(formats); i++) { 251cabdff1aSopenharmony_ci if (dxva2_validate_output(service, *guid, &formats[i])) 252cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, " %d", i); 253cabdff1aSopenharmony_ci } 254cabdff1aSopenharmony_ci } 255cabdff1aSopenharmony_ci#endif 256cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "\n"); 257cabdff1aSopenharmony_ci } 258cabdff1aSopenharmony_ci} 259cabdff1aSopenharmony_ci 260cabdff1aSopenharmony_cistatic int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format, 261cabdff1aSopenharmony_ci unsigned guid_count, const GUID *guid_list, GUID *decoder_guid) 262cabdff1aSopenharmony_ci{ 263cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 264cabdff1aSopenharmony_ci unsigned i, j; 265cabdff1aSopenharmony_ci 266cabdff1aSopenharmony_ci dxva_list_guids_debug(avctx, service, guid_count, guid_list); 267cabdff1aSopenharmony_ci 268cabdff1aSopenharmony_ci *decoder_guid = ff_GUID_NULL; 269cabdff1aSopenharmony_ci for (i = 0; dxva_modes[i].guid; i++) { 270cabdff1aSopenharmony_ci const dxva_mode *mode = &dxva_modes[i]; 271cabdff1aSopenharmony_ci int validate; 272cabdff1aSopenharmony_ci if (!dxva_check_codec_compatibility(avctx, mode)) 273cabdff1aSopenharmony_ci continue; 274cabdff1aSopenharmony_ci 275cabdff1aSopenharmony_ci for (j = 0; j < guid_count; j++) { 276cabdff1aSopenharmony_ci if (IsEqualGUID(mode->guid, &guid_list[j])) 277cabdff1aSopenharmony_ci break; 278cabdff1aSopenharmony_ci } 279cabdff1aSopenharmony_ci if (j == guid_count) 280cabdff1aSopenharmony_ci continue; 281cabdff1aSopenharmony_ci 282cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 283cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_D3D11) 284cabdff1aSopenharmony_ci validate = d3d11va_validate_output(service, *mode->guid, surface_format); 285cabdff1aSopenharmony_ci#endif 286cabdff1aSopenharmony_ci#if CONFIG_DXVA2 287cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 288cabdff1aSopenharmony_ci validate = dxva2_validate_output(service, *mode->guid, surface_format); 289cabdff1aSopenharmony_ci#endif 290cabdff1aSopenharmony_ci if (validate) { 291cabdff1aSopenharmony_ci *decoder_guid = *mode->guid; 292cabdff1aSopenharmony_ci break; 293cabdff1aSopenharmony_ci } 294cabdff1aSopenharmony_ci } 295cabdff1aSopenharmony_ci 296cabdff1aSopenharmony_ci if (IsEqualGUID(decoder_guid, &ff_GUID_NULL)) { 297cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_VERBOSE, "No decoder device for codec found\n"); 298cabdff1aSopenharmony_ci return AVERROR(EINVAL); 299cabdff1aSopenharmony_ci } 300cabdff1aSopenharmony_ci 301cabdff1aSopenharmony_ci if (IsEqualGUID(decoder_guid, &ff_DXVADDI_Intel_ModeH264_E)) 302cabdff1aSopenharmony_ci sctx->workaround |= FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO; 303cabdff1aSopenharmony_ci 304cabdff1aSopenharmony_ci return 0; 305cabdff1aSopenharmony_ci} 306cabdff1aSopenharmony_ci 307cabdff1aSopenharmony_cistatic void bufref_free_interface(void *opaque, uint8_t *data) 308cabdff1aSopenharmony_ci{ 309cabdff1aSopenharmony_ci IUnknown_Release((IUnknown *)opaque); 310cabdff1aSopenharmony_ci} 311cabdff1aSopenharmony_ci 312cabdff1aSopenharmony_cistatic AVBufferRef *bufref_wrap_interface(IUnknown *iface) 313cabdff1aSopenharmony_ci{ 314cabdff1aSopenharmony_ci return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0); 315cabdff1aSopenharmony_ci} 316cabdff1aSopenharmony_ci 317cabdff1aSopenharmony_ci#if CONFIG_DXVA2 318cabdff1aSopenharmony_ci 319cabdff1aSopenharmony_cistatic int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *device_guid, 320cabdff1aSopenharmony_ci const DXVA2_VideoDesc *desc, 321cabdff1aSopenharmony_ci DXVA2_ConfigPictureDecode *config) 322cabdff1aSopenharmony_ci{ 323cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 324cabdff1aSopenharmony_ci unsigned cfg_count; 325cabdff1aSopenharmony_ci DXVA2_ConfigPictureDecode *cfg_list; 326cabdff1aSopenharmony_ci HRESULT hr; 327cabdff1aSopenharmony_ci int ret; 328cabdff1aSopenharmony_ci 329cabdff1aSopenharmony_ci hr = IDirectXVideoDecoderService_GetDecoderConfigurations(sctx->dxva2_service, device_guid, desc, NULL, &cfg_count, &cfg_list); 330cabdff1aSopenharmony_ci if (FAILED(hr)) { 331cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n"); 332cabdff1aSopenharmony_ci return AVERROR(EINVAL); 333cabdff1aSopenharmony_ci } 334cabdff1aSopenharmony_ci 335cabdff1aSopenharmony_ci ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count); 336cabdff1aSopenharmony_ci if (ret >= 0) 337cabdff1aSopenharmony_ci *config = cfg_list[ret]; 338cabdff1aSopenharmony_ci CoTaskMemFree(cfg_list); 339cabdff1aSopenharmony_ci return ret; 340cabdff1aSopenharmony_ci} 341cabdff1aSopenharmony_ci 342cabdff1aSopenharmony_cistatic int dxva2_create_decoder(AVCodecContext *avctx) 343cabdff1aSopenharmony_ci{ 344cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 345cabdff1aSopenharmony_ci GUID *guid_list; 346cabdff1aSopenharmony_ci unsigned guid_count; 347cabdff1aSopenharmony_ci GUID device_guid; 348cabdff1aSopenharmony_ci D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? 349cabdff1aSopenharmony_ci MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2'); 350cabdff1aSopenharmony_ci DXVA2_VideoDesc desc = { 0 }; 351cabdff1aSopenharmony_ci DXVA2_ConfigPictureDecode config; 352cabdff1aSopenharmony_ci HRESULT hr; 353cabdff1aSopenharmony_ci int ret; 354cabdff1aSopenharmony_ci HANDLE device_handle; 355cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 356cabdff1aSopenharmony_ci AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; 357cabdff1aSopenharmony_ci AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; 358cabdff1aSopenharmony_ci 359cabdff1aSopenharmony_ci hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr, 360cabdff1aSopenharmony_ci &device_handle); 361cabdff1aSopenharmony_ci if (FAILED(hr)) { 362cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to open a device handle\n"); 363cabdff1aSopenharmony_ci goto fail; 364cabdff1aSopenharmony_ci } 365cabdff1aSopenharmony_ci 366cabdff1aSopenharmony_ci hr = IDirect3DDeviceManager9_GetVideoService(device_hwctx->devmgr, device_handle, 367cabdff1aSopenharmony_ci &ff_IID_IDirectXVideoDecoderService, 368cabdff1aSopenharmony_ci (void **)&sctx->dxva2_service); 369cabdff1aSopenharmony_ci IDirect3DDeviceManager9_CloseDeviceHandle(device_hwctx->devmgr, device_handle); 370cabdff1aSopenharmony_ci if (FAILED(hr)) { 371cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to create IDirectXVideoDecoderService\n"); 372cabdff1aSopenharmony_ci goto fail; 373cabdff1aSopenharmony_ci } 374cabdff1aSopenharmony_ci 375cabdff1aSopenharmony_ci hr = IDirectXVideoDecoderService_GetDecoderDeviceGuids(sctx->dxva2_service, &guid_count, &guid_list); 376cabdff1aSopenharmony_ci if (FAILED(hr)) { 377cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder device GUIDs\n"); 378cabdff1aSopenharmony_ci goto fail; 379cabdff1aSopenharmony_ci } 380cabdff1aSopenharmony_ci 381cabdff1aSopenharmony_ci ret = dxva_get_decoder_guid(avctx, sctx->dxva2_service, &surface_format, 382cabdff1aSopenharmony_ci guid_count, guid_list, &device_guid); 383cabdff1aSopenharmony_ci CoTaskMemFree(guid_list); 384cabdff1aSopenharmony_ci if (ret < 0) { 385cabdff1aSopenharmony_ci goto fail; 386cabdff1aSopenharmony_ci } 387cabdff1aSopenharmony_ci 388cabdff1aSopenharmony_ci desc.SampleWidth = avctx->coded_width; 389cabdff1aSopenharmony_ci desc.SampleHeight = avctx->coded_height; 390cabdff1aSopenharmony_ci desc.Format = surface_format; 391cabdff1aSopenharmony_ci 392cabdff1aSopenharmony_ci ret = dxva2_get_decoder_configuration(avctx, &device_guid, &desc, &config); 393cabdff1aSopenharmony_ci if (ret < 0) { 394cabdff1aSopenharmony_ci goto fail; 395cabdff1aSopenharmony_ci } 396cabdff1aSopenharmony_ci 397cabdff1aSopenharmony_ci hr = IDirectXVideoDecoderService_CreateVideoDecoder(sctx->dxva2_service, &device_guid, 398cabdff1aSopenharmony_ci &desc, &config, frames_hwctx->surfaces, 399cabdff1aSopenharmony_ci frames_hwctx->nb_surfaces, &sctx->dxva2_decoder); 400cabdff1aSopenharmony_ci if (FAILED(hr)) { 401cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to create DXVA2 video decoder\n"); 402cabdff1aSopenharmony_ci goto fail; 403cabdff1aSopenharmony_ci } 404cabdff1aSopenharmony_ci 405cabdff1aSopenharmony_ci sctx->dxva2_config = config; 406cabdff1aSopenharmony_ci 407cabdff1aSopenharmony_ci sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->dxva2_decoder); 408cabdff1aSopenharmony_ci if (!sctx->decoder_ref) 409cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 410cabdff1aSopenharmony_ci 411cabdff1aSopenharmony_ci return 0; 412cabdff1aSopenharmony_cifail: 413cabdff1aSopenharmony_ci return AVERROR(EINVAL); 414cabdff1aSopenharmony_ci} 415cabdff1aSopenharmony_ci 416cabdff1aSopenharmony_ci#endif 417cabdff1aSopenharmony_ci 418cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 419cabdff1aSopenharmony_ci 420cabdff1aSopenharmony_cistatic int d3d11va_get_decoder_configuration(AVCodecContext *avctx, 421cabdff1aSopenharmony_ci ID3D11VideoDevice *video_device, 422cabdff1aSopenharmony_ci const D3D11_VIDEO_DECODER_DESC *desc, 423cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_CONFIG *config) 424cabdff1aSopenharmony_ci{ 425cabdff1aSopenharmony_ci unsigned cfg_count = 0; 426cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_CONFIG *cfg_list = NULL; 427cabdff1aSopenharmony_ci HRESULT hr; 428cabdff1aSopenharmony_ci int i, ret; 429cabdff1aSopenharmony_ci 430cabdff1aSopenharmony_ci hr = ID3D11VideoDevice_GetVideoDecoderConfigCount(video_device, desc, &cfg_count); 431cabdff1aSopenharmony_ci if (FAILED(hr)) { 432cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations\n"); 433cabdff1aSopenharmony_ci return AVERROR(EINVAL); 434cabdff1aSopenharmony_ci } 435cabdff1aSopenharmony_ci 436cabdff1aSopenharmony_ci cfg_list = av_malloc_array(cfg_count, sizeof(D3D11_VIDEO_DECODER_CONFIG)); 437cabdff1aSopenharmony_ci if (cfg_list == NULL) 438cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 439cabdff1aSopenharmony_ci for (i = 0; i < cfg_count; i++) { 440cabdff1aSopenharmony_ci hr = ID3D11VideoDevice_GetVideoDecoderConfig(video_device, desc, i, &cfg_list[i]); 441cabdff1aSopenharmony_ci if (FAILED(hr)) { 442cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Unable to retrieve decoder configurations. (hr=0x%lX)\n", hr); 443cabdff1aSopenharmony_ci av_free(cfg_list); 444cabdff1aSopenharmony_ci return AVERROR(EINVAL); 445cabdff1aSopenharmony_ci } 446cabdff1aSopenharmony_ci } 447cabdff1aSopenharmony_ci 448cabdff1aSopenharmony_ci ret = dxva_get_decoder_configuration(avctx, cfg_list, cfg_count); 449cabdff1aSopenharmony_ci if (ret >= 0) 450cabdff1aSopenharmony_ci *config = cfg_list[ret]; 451cabdff1aSopenharmony_ci av_free(cfg_list); 452cabdff1aSopenharmony_ci return ret; 453cabdff1aSopenharmony_ci} 454cabdff1aSopenharmony_ci 455cabdff1aSopenharmony_cistatic DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt) 456cabdff1aSopenharmony_ci{ 457cabdff1aSopenharmony_ci switch (pix_fmt) { 458cabdff1aSopenharmony_ci case AV_PIX_FMT_NV12: return DXGI_FORMAT_NV12; 459cabdff1aSopenharmony_ci case AV_PIX_FMT_P010: return DXGI_FORMAT_P010; 460cabdff1aSopenharmony_ci case AV_PIX_FMT_YUV420P: return DXGI_FORMAT_420_OPAQUE; 461cabdff1aSopenharmony_ci default: return DXGI_FORMAT_UNKNOWN; 462cabdff1aSopenharmony_ci } 463cabdff1aSopenharmony_ci} 464cabdff1aSopenharmony_ci 465cabdff1aSopenharmony_cistatic int d3d11va_create_decoder(AVCodecContext *avctx) 466cabdff1aSopenharmony_ci{ 467cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 468cabdff1aSopenharmony_ci GUID *guid_list; 469cabdff1aSopenharmony_ci unsigned guid_count, i; 470cabdff1aSopenharmony_ci GUID decoder_guid; 471cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_DESC desc = { 0 }; 472cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_CONFIG config; 473cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = (AVHWFramesContext *)avctx->hw_frames_ctx->data; 474cabdff1aSopenharmony_ci AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; 475cabdff1aSopenharmony_ci AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx; 476cabdff1aSopenharmony_ci DXGI_FORMAT surface_format = d3d11va_map_sw_to_hw_format(frames_ctx->sw_format); 477cabdff1aSopenharmony_ci D3D11_TEXTURE2D_DESC texdesc; 478cabdff1aSopenharmony_ci HRESULT hr; 479cabdff1aSopenharmony_ci int ret; 480cabdff1aSopenharmony_ci 481cabdff1aSopenharmony_ci if (!frames_hwctx->texture) { 482cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "AVD3D11VAFramesContext.texture not set.\n"); 483cabdff1aSopenharmony_ci return AVERROR(EINVAL); 484cabdff1aSopenharmony_ci } 485cabdff1aSopenharmony_ci ID3D11Texture2D_GetDesc(frames_hwctx->texture, &texdesc); 486cabdff1aSopenharmony_ci 487cabdff1aSopenharmony_ci guid_count = ID3D11VideoDevice_GetVideoDecoderProfileCount(device_hwctx->video_device); 488cabdff1aSopenharmony_ci guid_list = av_malloc_array(guid_count, sizeof(*guid_list)); 489cabdff1aSopenharmony_ci if (guid_list == NULL || guid_count == 0) { 490cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to get the decoder GUIDs\n"); 491cabdff1aSopenharmony_ci av_free(guid_list); 492cabdff1aSopenharmony_ci return AVERROR(EINVAL); 493cabdff1aSopenharmony_ci } 494cabdff1aSopenharmony_ci for (i = 0; i < guid_count; i++) { 495cabdff1aSopenharmony_ci hr = ID3D11VideoDevice_GetVideoDecoderProfile(device_hwctx->video_device, i, &guid_list[i]); 496cabdff1aSopenharmony_ci if (FAILED(hr)) { 497cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to retrieve decoder GUID %d\n", i); 498cabdff1aSopenharmony_ci av_free(guid_list); 499cabdff1aSopenharmony_ci return AVERROR(EINVAL); 500cabdff1aSopenharmony_ci } 501cabdff1aSopenharmony_ci } 502cabdff1aSopenharmony_ci 503cabdff1aSopenharmony_ci ret = dxva_get_decoder_guid(avctx, device_hwctx->video_device, &surface_format, 504cabdff1aSopenharmony_ci guid_count, guid_list, &decoder_guid); 505cabdff1aSopenharmony_ci av_free(guid_list); 506cabdff1aSopenharmony_ci if (ret < 0) 507cabdff1aSopenharmony_ci return AVERROR(EINVAL); 508cabdff1aSopenharmony_ci 509cabdff1aSopenharmony_ci desc.SampleWidth = avctx->coded_width; 510cabdff1aSopenharmony_ci desc.SampleHeight = avctx->coded_height; 511cabdff1aSopenharmony_ci desc.OutputFormat = surface_format; 512cabdff1aSopenharmony_ci desc.Guid = decoder_guid; 513cabdff1aSopenharmony_ci 514cabdff1aSopenharmony_ci ret = d3d11va_get_decoder_configuration(avctx, device_hwctx->video_device, &desc, &config); 515cabdff1aSopenharmony_ci if (ret < 0) 516cabdff1aSopenharmony_ci return AVERROR(EINVAL); 517cabdff1aSopenharmony_ci 518cabdff1aSopenharmony_ci sctx->d3d11_views = av_calloc(texdesc.ArraySize, sizeof(sctx->d3d11_views[0])); 519cabdff1aSopenharmony_ci if (!sctx->d3d11_views) 520cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 521cabdff1aSopenharmony_ci sctx->nb_d3d11_views = texdesc.ArraySize; 522cabdff1aSopenharmony_ci 523cabdff1aSopenharmony_ci for (i = 0; i < sctx->nb_d3d11_views; i++) { 524cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc = { 525cabdff1aSopenharmony_ci .DecodeProfile = decoder_guid, 526cabdff1aSopenharmony_ci .ViewDimension = D3D11_VDOV_DIMENSION_TEXTURE2D, 527cabdff1aSopenharmony_ci .Texture2D = { 528cabdff1aSopenharmony_ci .ArraySlice = i, 529cabdff1aSopenharmony_ci } 530cabdff1aSopenharmony_ci }; 531cabdff1aSopenharmony_ci hr = ID3D11VideoDevice_CreateVideoDecoderOutputView(device_hwctx->video_device, 532cabdff1aSopenharmony_ci (ID3D11Resource*) frames_hwctx->texture, 533cabdff1aSopenharmony_ci &viewDesc, 534cabdff1aSopenharmony_ci (ID3D11VideoDecoderOutputView**) &sctx->d3d11_views[i]); 535cabdff1aSopenharmony_ci if (FAILED(hr)) { 536cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Could not create the decoder output view %d\n", i); 537cabdff1aSopenharmony_ci return AVERROR_UNKNOWN; 538cabdff1aSopenharmony_ci } 539cabdff1aSopenharmony_ci } 540cabdff1aSopenharmony_ci 541cabdff1aSopenharmony_ci hr = ID3D11VideoDevice_CreateVideoDecoder(device_hwctx->video_device, &desc, 542cabdff1aSopenharmony_ci &config, &sctx->d3d11_decoder); 543cabdff1aSopenharmony_ci if (FAILED(hr)) { 544cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to create D3D11VA video decoder\n"); 545cabdff1aSopenharmony_ci return AVERROR(EINVAL); 546cabdff1aSopenharmony_ci } 547cabdff1aSopenharmony_ci 548cabdff1aSopenharmony_ci sctx->d3d11_config = config; 549cabdff1aSopenharmony_ci sctx->d3d11_texture = frames_hwctx->texture; 550cabdff1aSopenharmony_ci 551cabdff1aSopenharmony_ci sctx->decoder_ref = bufref_wrap_interface((IUnknown *)sctx->d3d11_decoder); 552cabdff1aSopenharmony_ci if (!sctx->decoder_ref) 553cabdff1aSopenharmony_ci return AVERROR(ENOMEM); 554cabdff1aSopenharmony_ci 555cabdff1aSopenharmony_ci return 0; 556cabdff1aSopenharmony_ci} 557cabdff1aSopenharmony_ci 558cabdff1aSopenharmony_ci#endif 559cabdff1aSopenharmony_ci 560cabdff1aSopenharmony_cistatic void ff_dxva2_lock(AVCodecContext *avctx) 561cabdff1aSopenharmony_ci{ 562cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 563cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) { 564cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 565cabdff1aSopenharmony_ci AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 566cabdff1aSopenharmony_ci if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) 567cabdff1aSopenharmony_ci WaitForSingleObjectEx(D3D11VA_CONTEXT(ctx)->context_mutex, INFINITE, FALSE); 568cabdff1aSopenharmony_ci if (sctx->device_ctx) { 569cabdff1aSopenharmony_ci AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx; 570cabdff1aSopenharmony_ci hwctx->lock(hwctx->lock_ctx); 571cabdff1aSopenharmony_ci } 572cabdff1aSopenharmony_ci } 573cabdff1aSopenharmony_ci#endif 574cabdff1aSopenharmony_ci} 575cabdff1aSopenharmony_ci 576cabdff1aSopenharmony_cistatic void ff_dxva2_unlock(AVCodecContext *avctx) 577cabdff1aSopenharmony_ci{ 578cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 579cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) { 580cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 581cabdff1aSopenharmony_ci AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 582cabdff1aSopenharmony_ci if (D3D11VA_CONTEXT(ctx)->context_mutex != INVALID_HANDLE_VALUE) 583cabdff1aSopenharmony_ci ReleaseMutex(D3D11VA_CONTEXT(ctx)->context_mutex); 584cabdff1aSopenharmony_ci if (sctx->device_ctx) { 585cabdff1aSopenharmony_ci AVD3D11VADeviceContext *hwctx = sctx->device_ctx->hwctx; 586cabdff1aSopenharmony_ci hwctx->unlock(hwctx->lock_ctx); 587cabdff1aSopenharmony_ci } 588cabdff1aSopenharmony_ci } 589cabdff1aSopenharmony_ci#endif 590cabdff1aSopenharmony_ci} 591cabdff1aSopenharmony_ci 592cabdff1aSopenharmony_ciint ff_dxva2_common_frame_params(AVCodecContext *avctx, 593cabdff1aSopenharmony_ci AVBufferRef *hw_frames_ctx) 594cabdff1aSopenharmony_ci{ 595cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx = (AVHWFramesContext *)hw_frames_ctx->data; 596cabdff1aSopenharmony_ci AVHWDeviceContext *device_ctx = frames_ctx->device_ctx; 597cabdff1aSopenharmony_ci int surface_alignment, num_surfaces; 598cabdff1aSopenharmony_ci 599cabdff1aSopenharmony_ci if (device_ctx->type == AV_HWDEVICE_TYPE_DXVA2) { 600cabdff1aSopenharmony_ci frames_ctx->format = AV_PIX_FMT_DXVA2_VLD; 601cabdff1aSopenharmony_ci } else if (device_ctx->type == AV_HWDEVICE_TYPE_D3D11VA) { 602cabdff1aSopenharmony_ci frames_ctx->format = AV_PIX_FMT_D3D11; 603cabdff1aSopenharmony_ci } else { 604cabdff1aSopenharmony_ci return AVERROR(EINVAL); 605cabdff1aSopenharmony_ci } 606cabdff1aSopenharmony_ci 607cabdff1aSopenharmony_ci /* decoding MPEG-2 requires additional alignment on some Intel GPUs, 608cabdff1aSopenharmony_ci but it causes issues for H.264 on certain AMD GPUs..... */ 609cabdff1aSopenharmony_ci if (avctx->codec_id == AV_CODEC_ID_MPEG2VIDEO) 610cabdff1aSopenharmony_ci surface_alignment = 32; 611cabdff1aSopenharmony_ci /* the HEVC DXVA2 spec asks for 128 pixel aligned surfaces to ensure 612cabdff1aSopenharmony_ci all coding features have enough room to work with */ 613cabdff1aSopenharmony_ci else if (avctx->codec_id == AV_CODEC_ID_HEVC || avctx->codec_id == AV_CODEC_ID_AV1) 614cabdff1aSopenharmony_ci surface_alignment = 128; 615cabdff1aSopenharmony_ci else 616cabdff1aSopenharmony_ci surface_alignment = 16; 617cabdff1aSopenharmony_ci 618cabdff1aSopenharmony_ci /* 1 base work surface */ 619cabdff1aSopenharmony_ci num_surfaces = 1; 620cabdff1aSopenharmony_ci 621cabdff1aSopenharmony_ci /* add surfaces based on number of possible refs */ 622cabdff1aSopenharmony_ci if (avctx->codec_id == AV_CODEC_ID_H264 || avctx->codec_id == AV_CODEC_ID_HEVC) 623cabdff1aSopenharmony_ci num_surfaces += 16; 624cabdff1aSopenharmony_ci else if (avctx->codec_id == AV_CODEC_ID_VP9 || avctx->codec_id == AV_CODEC_ID_AV1) 625cabdff1aSopenharmony_ci num_surfaces += 8; 626cabdff1aSopenharmony_ci else 627cabdff1aSopenharmony_ci num_surfaces += 2; 628cabdff1aSopenharmony_ci 629cabdff1aSopenharmony_ci frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ? 630cabdff1aSopenharmony_ci AV_PIX_FMT_P010 : AV_PIX_FMT_NV12; 631cabdff1aSopenharmony_ci frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment); 632cabdff1aSopenharmony_ci frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment); 633cabdff1aSopenharmony_ci frames_ctx->initial_pool_size = num_surfaces; 634cabdff1aSopenharmony_ci 635cabdff1aSopenharmony_ci 636cabdff1aSopenharmony_ci#if CONFIG_DXVA2 637cabdff1aSopenharmony_ci if (frames_ctx->format == AV_PIX_FMT_DXVA2_VLD) { 638cabdff1aSopenharmony_ci AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; 639cabdff1aSopenharmony_ci 640cabdff1aSopenharmony_ci frames_hwctx->surface_type = DXVA2_VideoDecoderRenderTarget; 641cabdff1aSopenharmony_ci } 642cabdff1aSopenharmony_ci#endif 643cabdff1aSopenharmony_ci 644cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 645cabdff1aSopenharmony_ci if (frames_ctx->format == AV_PIX_FMT_D3D11) { 646cabdff1aSopenharmony_ci AVD3D11VAFramesContext *frames_hwctx = frames_ctx->hwctx; 647cabdff1aSopenharmony_ci 648cabdff1aSopenharmony_ci frames_hwctx->BindFlags |= D3D11_BIND_DECODER; 649cabdff1aSopenharmony_ci } 650cabdff1aSopenharmony_ci#endif 651cabdff1aSopenharmony_ci 652cabdff1aSopenharmony_ci return 0; 653cabdff1aSopenharmony_ci} 654cabdff1aSopenharmony_ci 655cabdff1aSopenharmony_ciint ff_dxva2_decode_init(AVCodecContext *avctx) 656cabdff1aSopenharmony_ci{ 657cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 658cabdff1aSopenharmony_ci AVHWFramesContext *frames_ctx; 659cabdff1aSopenharmony_ci enum AVHWDeviceType dev_type = avctx->hwaccel->pix_fmt == AV_PIX_FMT_DXVA2_VLD 660cabdff1aSopenharmony_ci ? AV_HWDEVICE_TYPE_DXVA2 : AV_HWDEVICE_TYPE_D3D11VA; 661cabdff1aSopenharmony_ci int ret = 0; 662cabdff1aSopenharmony_ci 663cabdff1aSopenharmony_ci // Old API. 664cabdff1aSopenharmony_ci if (avctx->hwaccel_context) 665cabdff1aSopenharmony_ci return 0; 666cabdff1aSopenharmony_ci 667cabdff1aSopenharmony_ci // (avctx->pix_fmt is not updated yet at this point) 668cabdff1aSopenharmony_ci sctx->pix_fmt = avctx->hwaccel->pix_fmt; 669cabdff1aSopenharmony_ci 670cabdff1aSopenharmony_ci ret = ff_decode_get_hw_frames_ctx(avctx, dev_type); 671cabdff1aSopenharmony_ci if (ret < 0) 672cabdff1aSopenharmony_ci return ret; 673cabdff1aSopenharmony_ci 674cabdff1aSopenharmony_ci frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data; 675cabdff1aSopenharmony_ci sctx->device_ctx = frames_ctx->device_ctx; 676cabdff1aSopenharmony_ci 677cabdff1aSopenharmony_ci if (frames_ctx->format != sctx->pix_fmt) { 678cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Invalid pixfmt for hwaccel!\n"); 679cabdff1aSopenharmony_ci ret = AVERROR(EINVAL); 680cabdff1aSopenharmony_ci goto fail; 681cabdff1aSopenharmony_ci } 682cabdff1aSopenharmony_ci 683cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 684cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_D3D11) { 685cabdff1aSopenharmony_ci AVD3D11VADeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx; 686cabdff1aSopenharmony_ci AVD3D11VAContext *d3d11_ctx = &sctx->ctx.d3d11va; 687cabdff1aSopenharmony_ci 688cabdff1aSopenharmony_ci ff_dxva2_lock(avctx); 689cabdff1aSopenharmony_ci ret = d3d11va_create_decoder(avctx); 690cabdff1aSopenharmony_ci ff_dxva2_unlock(avctx); 691cabdff1aSopenharmony_ci if (ret < 0) 692cabdff1aSopenharmony_ci goto fail; 693cabdff1aSopenharmony_ci 694cabdff1aSopenharmony_ci d3d11_ctx->decoder = sctx->d3d11_decoder; 695cabdff1aSopenharmony_ci d3d11_ctx->video_context = device_hwctx->video_context; 696cabdff1aSopenharmony_ci d3d11_ctx->cfg = &sctx->d3d11_config; 697cabdff1aSopenharmony_ci d3d11_ctx->surface_count = sctx->nb_d3d11_views; 698cabdff1aSopenharmony_ci d3d11_ctx->surface = sctx->d3d11_views; 699cabdff1aSopenharmony_ci d3d11_ctx->workaround = sctx->workaround; 700cabdff1aSopenharmony_ci d3d11_ctx->context_mutex = INVALID_HANDLE_VALUE; 701cabdff1aSopenharmony_ci } 702cabdff1aSopenharmony_ci#endif 703cabdff1aSopenharmony_ci 704cabdff1aSopenharmony_ci#if CONFIG_DXVA2 705cabdff1aSopenharmony_ci if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 706cabdff1aSopenharmony_ci AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx; 707cabdff1aSopenharmony_ci struct dxva_context *dxva_ctx = &sctx->ctx.dxva2; 708cabdff1aSopenharmony_ci 709cabdff1aSopenharmony_ci ff_dxva2_lock(avctx); 710cabdff1aSopenharmony_ci ret = dxva2_create_decoder(avctx); 711cabdff1aSopenharmony_ci ff_dxva2_unlock(avctx); 712cabdff1aSopenharmony_ci if (ret < 0) 713cabdff1aSopenharmony_ci goto fail; 714cabdff1aSopenharmony_ci 715cabdff1aSopenharmony_ci dxva_ctx->decoder = sctx->dxva2_decoder; 716cabdff1aSopenharmony_ci dxva_ctx->cfg = &sctx->dxva2_config; 717cabdff1aSopenharmony_ci dxva_ctx->surface = frames_hwctx->surfaces; 718cabdff1aSopenharmony_ci dxva_ctx->surface_count = frames_hwctx->nb_surfaces; 719cabdff1aSopenharmony_ci dxva_ctx->workaround = sctx->workaround; 720cabdff1aSopenharmony_ci } 721cabdff1aSopenharmony_ci#endif 722cabdff1aSopenharmony_ci 723cabdff1aSopenharmony_ci return 0; 724cabdff1aSopenharmony_ci 725cabdff1aSopenharmony_cifail: 726cabdff1aSopenharmony_ci ff_dxva2_decode_uninit(avctx); 727cabdff1aSopenharmony_ci return ret; 728cabdff1aSopenharmony_ci} 729cabdff1aSopenharmony_ci 730cabdff1aSopenharmony_ciint ff_dxva2_decode_uninit(AVCodecContext *avctx) 731cabdff1aSopenharmony_ci{ 732cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 733cabdff1aSopenharmony_ci int i; 734cabdff1aSopenharmony_ci 735cabdff1aSopenharmony_ci av_buffer_unref(&sctx->decoder_ref); 736cabdff1aSopenharmony_ci 737cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 738cabdff1aSopenharmony_ci for (i = 0; i < sctx->nb_d3d11_views; i++) { 739cabdff1aSopenharmony_ci if (sctx->d3d11_views[i]) 740cabdff1aSopenharmony_ci ID3D11VideoDecoderOutputView_Release(sctx->d3d11_views[i]); 741cabdff1aSopenharmony_ci } 742cabdff1aSopenharmony_ci av_freep(&sctx->d3d11_views); 743cabdff1aSopenharmony_ci#endif 744cabdff1aSopenharmony_ci 745cabdff1aSopenharmony_ci#if CONFIG_DXVA2 746cabdff1aSopenharmony_ci if (sctx->dxva2_service) 747cabdff1aSopenharmony_ci IDirectXVideoDecoderService_Release(sctx->dxva2_service); 748cabdff1aSopenharmony_ci#endif 749cabdff1aSopenharmony_ci 750cabdff1aSopenharmony_ci return 0; 751cabdff1aSopenharmony_ci} 752cabdff1aSopenharmony_ci 753cabdff1aSopenharmony_cistatic void *get_surface(const AVCodecContext *avctx, const AVFrame *frame) 754cabdff1aSopenharmony_ci{ 755cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 756cabdff1aSopenharmony_ci if (frame->format == AV_PIX_FMT_D3D11) { 757cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 758cabdff1aSopenharmony_ci intptr_t index = (intptr_t)frame->data[1]; 759cabdff1aSopenharmony_ci if (index < 0 || index >= sctx->nb_d3d11_views || 760cabdff1aSopenharmony_ci sctx->d3d11_texture != (ID3D11Texture2D *)frame->data[0]) { 761cabdff1aSopenharmony_ci av_log((void *)avctx, AV_LOG_ERROR, "get_buffer frame is invalid!\n"); 762cabdff1aSopenharmony_ci return NULL; 763cabdff1aSopenharmony_ci } 764cabdff1aSopenharmony_ci return sctx->d3d11_views[index]; 765cabdff1aSopenharmony_ci } 766cabdff1aSopenharmony_ci#endif 767cabdff1aSopenharmony_ci return frame->data[3]; 768cabdff1aSopenharmony_ci} 769cabdff1aSopenharmony_ci 770cabdff1aSopenharmony_ciunsigned ff_dxva2_get_surface_index(const AVCodecContext *avctx, 771cabdff1aSopenharmony_ci const AVDXVAContext *ctx, 772cabdff1aSopenharmony_ci const AVFrame *frame) 773cabdff1aSopenharmony_ci{ 774cabdff1aSopenharmony_ci void *surface = get_surface(avctx, frame); 775cabdff1aSopenharmony_ci unsigned i; 776cabdff1aSopenharmony_ci 777cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 778cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_D3D11) 779cabdff1aSopenharmony_ci return (intptr_t)frame->data[1]; 780cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD) { 781cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_OUTPUT_VIEW_DESC viewDesc; 782cabdff1aSopenharmony_ci ID3D11VideoDecoderOutputView_GetDesc((ID3D11VideoDecoderOutputView*) surface, &viewDesc); 783cabdff1aSopenharmony_ci return viewDesc.Texture2D.ArraySlice; 784cabdff1aSopenharmony_ci } 785cabdff1aSopenharmony_ci#endif 786cabdff1aSopenharmony_ci#if CONFIG_DXVA2 787cabdff1aSopenharmony_ci for (i = 0; i < DXVA_CONTEXT_COUNT(avctx, ctx); i++) { 788cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD && ctx->dxva2.surface[i] == surface) 789cabdff1aSopenharmony_ci return i; 790cabdff1aSopenharmony_ci } 791cabdff1aSopenharmony_ci#endif 792cabdff1aSopenharmony_ci 793cabdff1aSopenharmony_ci assert(0); 794cabdff1aSopenharmony_ci return 0; 795cabdff1aSopenharmony_ci} 796cabdff1aSopenharmony_ci 797cabdff1aSopenharmony_ciint ff_dxva2_commit_buffer(AVCodecContext *avctx, 798cabdff1aSopenharmony_ci AVDXVAContext *ctx, 799cabdff1aSopenharmony_ci DECODER_BUFFER_DESC *dsc, 800cabdff1aSopenharmony_ci unsigned type, const void *data, unsigned size, 801cabdff1aSopenharmony_ci unsigned mb_count) 802cabdff1aSopenharmony_ci{ 803cabdff1aSopenharmony_ci void *dxva_data = NULL; 804cabdff1aSopenharmony_ci unsigned dxva_size; 805cabdff1aSopenharmony_ci int result; 806cabdff1aSopenharmony_ci HRESULT hr = 0; 807cabdff1aSopenharmony_ci 808cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 809cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) 810cabdff1aSopenharmony_ci hr = ID3D11VideoContext_GetDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, 811cabdff1aSopenharmony_ci D3D11VA_CONTEXT(ctx)->decoder, 812cabdff1aSopenharmony_ci type, 813cabdff1aSopenharmony_ci &dxva_size, &dxva_data); 814cabdff1aSopenharmony_ci#endif 815cabdff1aSopenharmony_ci#if CONFIG_DXVA2 816cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 817cabdff1aSopenharmony_ci hr = IDirectXVideoDecoder_GetBuffer(DXVA2_CONTEXT(ctx)->decoder, type, 818cabdff1aSopenharmony_ci &dxva_data, &dxva_size); 819cabdff1aSopenharmony_ci#endif 820cabdff1aSopenharmony_ci if (FAILED(hr)) { 821cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to get a buffer for %u: 0x%x\n", 822cabdff1aSopenharmony_ci type, (unsigned)hr); 823cabdff1aSopenharmony_ci return -1; 824cabdff1aSopenharmony_ci } 825cabdff1aSopenharmony_ci if (dxva_data && size <= dxva_size) { 826cabdff1aSopenharmony_ci memcpy(dxva_data, data, size); 827cabdff1aSopenharmony_ci 828cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 829cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) { 830cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_BUFFER_DESC *dsc11 = dsc; 831cabdff1aSopenharmony_ci memset(dsc11, 0, sizeof(*dsc11)); 832cabdff1aSopenharmony_ci dsc11->BufferType = type; 833cabdff1aSopenharmony_ci dsc11->DataSize = size; 834cabdff1aSopenharmony_ci dsc11->NumMBsInBuffer = mb_count; 835cabdff1aSopenharmony_ci } 836cabdff1aSopenharmony_ci#endif 837cabdff1aSopenharmony_ci#if CONFIG_DXVA2 838cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 839cabdff1aSopenharmony_ci DXVA2_DecodeBufferDesc *dsc2 = dsc; 840cabdff1aSopenharmony_ci memset(dsc2, 0, sizeof(*dsc2)); 841cabdff1aSopenharmony_ci dsc2->CompressedBufferType = type; 842cabdff1aSopenharmony_ci dsc2->DataSize = size; 843cabdff1aSopenharmony_ci dsc2->NumMBsInBuffer = mb_count; 844cabdff1aSopenharmony_ci } 845cabdff1aSopenharmony_ci#endif 846cabdff1aSopenharmony_ci 847cabdff1aSopenharmony_ci result = 0; 848cabdff1aSopenharmony_ci } else { 849cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Buffer for type %u was too small\n", type); 850cabdff1aSopenharmony_ci result = -1; 851cabdff1aSopenharmony_ci } 852cabdff1aSopenharmony_ci 853cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 854cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) 855cabdff1aSopenharmony_ci hr = ID3D11VideoContext_ReleaseDecoderBuffer(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, type); 856cabdff1aSopenharmony_ci#endif 857cabdff1aSopenharmony_ci#if CONFIG_DXVA2 858cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 859cabdff1aSopenharmony_ci hr = IDirectXVideoDecoder_ReleaseBuffer(DXVA2_CONTEXT(ctx)->decoder, type); 860cabdff1aSopenharmony_ci#endif 861cabdff1aSopenharmony_ci if (FAILED(hr)) { 862cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 863cabdff1aSopenharmony_ci "Failed to release buffer type %u: 0x%x\n", 864cabdff1aSopenharmony_ci type, (unsigned)hr); 865cabdff1aSopenharmony_ci result = -1; 866cabdff1aSopenharmony_ci } 867cabdff1aSopenharmony_ci return result; 868cabdff1aSopenharmony_ci} 869cabdff1aSopenharmony_ci 870cabdff1aSopenharmony_cistatic int frame_add_buf(AVFrame *frame, AVBufferRef *ref) 871cabdff1aSopenharmony_ci{ 872cabdff1aSopenharmony_ci int i; 873cabdff1aSopenharmony_ci 874cabdff1aSopenharmony_ci for (i = 0; i < AV_NUM_DATA_POINTERS; i++) { 875cabdff1aSopenharmony_ci if (!frame->buf[i]) { 876cabdff1aSopenharmony_ci frame->buf[i] = av_buffer_ref(ref); 877cabdff1aSopenharmony_ci return frame->buf[i] ? 0 : AVERROR(ENOMEM); 878cabdff1aSopenharmony_ci } 879cabdff1aSopenharmony_ci } 880cabdff1aSopenharmony_ci 881cabdff1aSopenharmony_ci // For now we expect that the caller does not use more than 882cabdff1aSopenharmony_ci // AV_NUM_DATA_POINTERS-1 buffers if the user uses a custom pool. 883cabdff1aSopenharmony_ci return AVERROR(EINVAL); 884cabdff1aSopenharmony_ci} 885cabdff1aSopenharmony_ci 886cabdff1aSopenharmony_ciint ff_dxva2_common_end_frame(AVCodecContext *avctx, AVFrame *frame, 887cabdff1aSopenharmony_ci const void *pp, unsigned pp_size, 888cabdff1aSopenharmony_ci const void *qm, unsigned qm_size, 889cabdff1aSopenharmony_ci int (*commit_bs_si)(AVCodecContext *, 890cabdff1aSopenharmony_ci DECODER_BUFFER_DESC *bs, 891cabdff1aSopenharmony_ci DECODER_BUFFER_DESC *slice)) 892cabdff1aSopenharmony_ci{ 893cabdff1aSopenharmony_ci AVDXVAContext *ctx = DXVA_CONTEXT(avctx); 894cabdff1aSopenharmony_ci unsigned buffer_count = 0; 895cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 896cabdff1aSopenharmony_ci D3D11_VIDEO_DECODER_BUFFER_DESC buffer11[4]; 897cabdff1aSopenharmony_ci#endif 898cabdff1aSopenharmony_ci#if CONFIG_DXVA2 899cabdff1aSopenharmony_ci DXVA2_DecodeBufferDesc buffer2[4]; 900cabdff1aSopenharmony_ci#endif 901cabdff1aSopenharmony_ci DECODER_BUFFER_DESC *buffer = NULL, *buffer_slice = NULL; 902cabdff1aSopenharmony_ci int result, runs = 0; 903cabdff1aSopenharmony_ci HRESULT hr; 904cabdff1aSopenharmony_ci unsigned type; 905cabdff1aSopenharmony_ci FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx); 906cabdff1aSopenharmony_ci 907cabdff1aSopenharmony_ci if (sctx->decoder_ref) { 908cabdff1aSopenharmony_ci result = frame_add_buf(frame, sctx->decoder_ref); 909cabdff1aSopenharmony_ci if (result < 0) 910cabdff1aSopenharmony_ci return result; 911cabdff1aSopenharmony_ci } 912cabdff1aSopenharmony_ci 913cabdff1aSopenharmony_ci do { 914cabdff1aSopenharmony_ci ff_dxva2_lock(avctx); 915cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 916cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) 917cabdff1aSopenharmony_ci hr = ID3D11VideoContext_DecoderBeginFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder, 918cabdff1aSopenharmony_ci get_surface(avctx, frame), 919cabdff1aSopenharmony_ci 0, NULL); 920cabdff1aSopenharmony_ci#endif 921cabdff1aSopenharmony_ci#if CONFIG_DXVA2 922cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 923cabdff1aSopenharmony_ci hr = IDirectXVideoDecoder_BeginFrame(DXVA2_CONTEXT(ctx)->decoder, 924cabdff1aSopenharmony_ci get_surface(avctx, frame), 925cabdff1aSopenharmony_ci NULL); 926cabdff1aSopenharmony_ci#endif 927cabdff1aSopenharmony_ci if (hr != E_PENDING || ++runs > 50) 928cabdff1aSopenharmony_ci break; 929cabdff1aSopenharmony_ci ff_dxva2_unlock(avctx); 930cabdff1aSopenharmony_ci av_usleep(2000); 931cabdff1aSopenharmony_ci } while(1); 932cabdff1aSopenharmony_ci 933cabdff1aSopenharmony_ci if (FAILED(hr)) { 934cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to begin frame: 0x%x\n", (unsigned)hr); 935cabdff1aSopenharmony_ci ff_dxva2_unlock(avctx); 936cabdff1aSopenharmony_ci return -1; 937cabdff1aSopenharmony_ci } 938cabdff1aSopenharmony_ci 939cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 940cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) { 941cabdff1aSopenharmony_ci buffer = &buffer11[buffer_count]; 942cabdff1aSopenharmony_ci type = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS; 943cabdff1aSopenharmony_ci } 944cabdff1aSopenharmony_ci#endif 945cabdff1aSopenharmony_ci#if CONFIG_DXVA2 946cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 947cabdff1aSopenharmony_ci buffer = &buffer2[buffer_count]; 948cabdff1aSopenharmony_ci type = DXVA2_PictureParametersBufferType; 949cabdff1aSopenharmony_ci } 950cabdff1aSopenharmony_ci#endif 951cabdff1aSopenharmony_ci result = ff_dxva2_commit_buffer(avctx, ctx, buffer, 952cabdff1aSopenharmony_ci type, 953cabdff1aSopenharmony_ci pp, pp_size, 0); 954cabdff1aSopenharmony_ci if (result) { 955cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 956cabdff1aSopenharmony_ci "Failed to add picture parameter buffer\n"); 957cabdff1aSopenharmony_ci goto end; 958cabdff1aSopenharmony_ci } 959cabdff1aSopenharmony_ci buffer_count++; 960cabdff1aSopenharmony_ci 961cabdff1aSopenharmony_ci if (qm_size > 0) { 962cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 963cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) { 964cabdff1aSopenharmony_ci buffer = &buffer11[buffer_count]; 965cabdff1aSopenharmony_ci type = D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX; 966cabdff1aSopenharmony_ci } 967cabdff1aSopenharmony_ci#endif 968cabdff1aSopenharmony_ci#if CONFIG_DXVA2 969cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 970cabdff1aSopenharmony_ci buffer = &buffer2[buffer_count]; 971cabdff1aSopenharmony_ci type = DXVA2_InverseQuantizationMatrixBufferType; 972cabdff1aSopenharmony_ci } 973cabdff1aSopenharmony_ci#endif 974cabdff1aSopenharmony_ci result = ff_dxva2_commit_buffer(avctx, ctx, buffer, 975cabdff1aSopenharmony_ci type, 976cabdff1aSopenharmony_ci qm, qm_size, 0); 977cabdff1aSopenharmony_ci if (result) { 978cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 979cabdff1aSopenharmony_ci "Failed to add inverse quantization matrix buffer\n"); 980cabdff1aSopenharmony_ci goto end; 981cabdff1aSopenharmony_ci } 982cabdff1aSopenharmony_ci buffer_count++; 983cabdff1aSopenharmony_ci } 984cabdff1aSopenharmony_ci 985cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 986cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) { 987cabdff1aSopenharmony_ci buffer = &buffer11[buffer_count + 0]; 988cabdff1aSopenharmony_ci buffer_slice = &buffer11[buffer_count + 1]; 989cabdff1aSopenharmony_ci } 990cabdff1aSopenharmony_ci#endif 991cabdff1aSopenharmony_ci#if CONFIG_DXVA2 992cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 993cabdff1aSopenharmony_ci buffer = &buffer2[buffer_count + 0]; 994cabdff1aSopenharmony_ci buffer_slice = &buffer2[buffer_count + 1]; 995cabdff1aSopenharmony_ci } 996cabdff1aSopenharmony_ci#endif 997cabdff1aSopenharmony_ci 998cabdff1aSopenharmony_ci result = commit_bs_si(avctx, 999cabdff1aSopenharmony_ci buffer, 1000cabdff1aSopenharmony_ci buffer_slice); 1001cabdff1aSopenharmony_ci if (result) { 1002cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, 1003cabdff1aSopenharmony_ci "Failed to add bitstream or slice control buffer\n"); 1004cabdff1aSopenharmony_ci goto end; 1005cabdff1aSopenharmony_ci } 1006cabdff1aSopenharmony_ci buffer_count += 2; 1007cabdff1aSopenharmony_ci 1008cabdff1aSopenharmony_ci /* TODO Film Grain when possible */ 1009cabdff1aSopenharmony_ci 1010cabdff1aSopenharmony_ci assert(buffer_count == 1 + (qm_size > 0) + 2); 1011cabdff1aSopenharmony_ci 1012cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 1013cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) 1014cabdff1aSopenharmony_ci hr = ID3D11VideoContext_SubmitDecoderBuffers(D3D11VA_CONTEXT(ctx)->video_context, 1015cabdff1aSopenharmony_ci D3D11VA_CONTEXT(ctx)->decoder, 1016cabdff1aSopenharmony_ci buffer_count, buffer11); 1017cabdff1aSopenharmony_ci#endif 1018cabdff1aSopenharmony_ci#if CONFIG_DXVA2 1019cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) { 1020cabdff1aSopenharmony_ci DXVA2_DecodeExecuteParams exec = { 1021cabdff1aSopenharmony_ci .NumCompBuffers = buffer_count, 1022cabdff1aSopenharmony_ci .pCompressedBuffers = buffer2, 1023cabdff1aSopenharmony_ci .pExtensionData = NULL, 1024cabdff1aSopenharmony_ci }; 1025cabdff1aSopenharmony_ci hr = IDirectXVideoDecoder_Execute(DXVA2_CONTEXT(ctx)->decoder, &exec); 1026cabdff1aSopenharmony_ci } 1027cabdff1aSopenharmony_ci#endif 1028cabdff1aSopenharmony_ci if (FAILED(hr)) { 1029cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to execute: 0x%x\n", (unsigned)hr); 1030cabdff1aSopenharmony_ci result = -1; 1031cabdff1aSopenharmony_ci } 1032cabdff1aSopenharmony_ci 1033cabdff1aSopenharmony_ciend: 1034cabdff1aSopenharmony_ci#if CONFIG_D3D11VA 1035cabdff1aSopenharmony_ci if (ff_dxva2_is_d3d11(avctx)) 1036cabdff1aSopenharmony_ci hr = ID3D11VideoContext_DecoderEndFrame(D3D11VA_CONTEXT(ctx)->video_context, D3D11VA_CONTEXT(ctx)->decoder); 1037cabdff1aSopenharmony_ci#endif 1038cabdff1aSopenharmony_ci#if CONFIG_DXVA2 1039cabdff1aSopenharmony_ci if (avctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) 1040cabdff1aSopenharmony_ci hr = IDirectXVideoDecoder_EndFrame(DXVA2_CONTEXT(ctx)->decoder, NULL); 1041cabdff1aSopenharmony_ci#endif 1042cabdff1aSopenharmony_ci ff_dxva2_unlock(avctx); 1043cabdff1aSopenharmony_ci if (FAILED(hr)) { 1044cabdff1aSopenharmony_ci av_log(avctx, AV_LOG_ERROR, "Failed to end frame: 0x%x\n", (unsigned)hr); 1045cabdff1aSopenharmony_ci result = -1; 1046cabdff1aSopenharmony_ci } 1047cabdff1aSopenharmony_ci 1048cabdff1aSopenharmony_ci return result; 1049cabdff1aSopenharmony_ci} 1050cabdff1aSopenharmony_ci 1051cabdff1aSopenharmony_ciint ff_dxva2_is_d3d11(const AVCodecContext *avctx) 1052cabdff1aSopenharmony_ci{ 1053cabdff1aSopenharmony_ci if (CONFIG_D3D11VA) 1054cabdff1aSopenharmony_ci return avctx->pix_fmt == AV_PIX_FMT_D3D11VA_VLD || 1055cabdff1aSopenharmony_ci avctx->pix_fmt == AV_PIX_FMT_D3D11; 1056cabdff1aSopenharmony_ci else 1057cabdff1aSopenharmony_ci return 0; 1058cabdff1aSopenharmony_ci} 1059