summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libavcodec/dxva2.c64
1 files changed, 44 insertions, 20 deletions
diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
index e0c54068d6..9f4a5294a4 100644
--- a/libavcodec/dxva2.c
+++ b/libavcodec/dxva2.c
@@ -49,18 +49,34 @@ DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x
typedef struct dxva_mode {
const GUID *guid;
enum AVCodecID codec;
+ // List of supported profiles, terminated by a FF_PROFILE_UNKNOWN entry.
+ // If NULL, don't check profile.
+ const int *profiles;
} dxva_mode;
+static const int prof_mpeg2_main[] = {FF_PROFILE_MPEG2_SIMPLE,
+ FF_PROFILE_MPEG2_MAIN,
+ FF_PROFILE_UNKNOWN};
+static const int prof_h264_high[] = {FF_PROFILE_H264_CONSTRAINED_BASELINE,
+ FF_PROFILE_H264_MAIN,
+ FF_PROFILE_H264_HIGH,
+ FF_PROFILE_UNKNOWN};
+static const int prof_hevc_main[] = {FF_PROFILE_HEVC_MAIN,
+ FF_PROFILE_UNKNOWN};
+static const int prof_hevc_main10[] = {FF_PROFILE_HEVC_MAIN,
+ FF_PROFILE_HEVC_MAIN_10,
+ FF_PROFILE_UNKNOWN};
+
static const dxva_mode dxva_modes[] = {
/* MPEG-2 */
- { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO },
- { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO },
+ { &ff_DXVA2_ModeMPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main },
+ { &ff_DXVA2_ModeMPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO, prof_mpeg2_main },
/* H.264 */
- { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264 },
- { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264 },
+ { &ff_DXVA2_ModeH264_F, AV_CODEC_ID_H264, prof_h264_high },
+ { &ff_DXVA2_ModeH264_E, AV_CODEC_ID_H264, prof_h264_high },
/* Intel specific H.264 mode */
- { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264 },
+ { &ff_DXVADDI_Intel_ModeH264_E, AV_CODEC_ID_H264, prof_h264_high },
/* VC-1 / WMV3 */
{ &ff_DXVA2_ModeVC1_D2010, AV_CODEC_ID_VC1 },
@@ -69,8 +85,8 @@ static const dxva_mode dxva_modes[] = {
{ &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 },
/* HEVC/H.265 */
- { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC },
- { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC },
+ { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 },
+ { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main },
{ NULL, 0 },
};
@@ -160,6 +176,26 @@ static int dxva2_validate_output(void *decoder_service, GUID guid, void *surface
}
#endif
+static int dxva_check_codec_compatibility(AVCodecContext *avctx, const dxva_mode *mode)
+{
+ if (mode->codec != avctx->codec_id)
+ return 0;
+
+ if (mode->profiles && !(avctx->hwaccel_flags & AV_HWACCEL_FLAG_ALLOW_PROFILE_MISMATCH)) {
+ int i, found = 0;
+ for (i = 0; mode->profiles[i] != FF_PROFILE_UNKNOWN; i++) {
+ if (avctx->profile == mode->profiles[i]) {
+ found = 1;
+ break;
+ }
+ }
+ if (!found)
+ return 0;
+ }
+
+ return 1;
+}
+
static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *surface_format,
unsigned guid_count, const GUID *guid_list, GUID *decoder_guid)
{
@@ -170,7 +206,7 @@ static int dxva_get_decoder_guid(AVCodecContext *avctx, void *service, void *sur
for (i = 0; dxva_modes[i].guid; i++) {
const dxva_mode *mode = &dxva_modes[i];
int validate;
- if (mode->codec != avctx->codec_id)
+ if (!dxva_check_codec_compatibility(avctx, mode))
continue;
for (j = 0; j < guid_count; j++) {
@@ -552,18 +588,6 @@ int ff_dxva2_decode_init(AVCodecContext *avctx)
// (avctx->pix_fmt is not updated yet at this point)
sctx->pix_fmt = avctx->hwaccel->pix_fmt;
- if (avctx->codec_id == AV_CODEC_ID_H264 &&
- (avctx->profile & ~FF_PROFILE_H264_CONSTRAINED) > FF_PROFILE_H264_HIGH) {
- av_log(avctx, AV_LOG_VERBOSE, "Unsupported H.264 profile for DXVA HWAccel: %d\n",avctx->profile);
- return AVERROR(ENOTSUP);
- }
-
- if (avctx->codec_id == AV_CODEC_ID_HEVC &&
- avctx->profile != FF_PROFILE_HEVC_MAIN && avctx->profile != FF_PROFILE_HEVC_MAIN_10) {
- av_log(avctx, AV_LOG_VERBOSE, "Unsupported HEVC profile for DXVA HWAccel: %d\n", avctx->profile);
- return AVERROR(ENOTSUP);
- }
-
if (!avctx->hw_frames_ctx && !avctx->hw_device_ctx) {
av_log(avctx, AV_LOG_ERROR, "Either a hw_frames_ctx or a hw_device_ctx needs to be set for hardware decoding.\n");
return AVERROR(EINVAL);