aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthexai <58434170+thexai@users.noreply.github.com>2023-04-07 20:37:42 +0200
committerthexai <58434170+thexai@users.noreply.github.com>2023-04-09 17:01:38 +0200
commit6915b62be0a8c07d87e9375d2a33fae3cdcf3c41 (patch)
treee55bfc39c0f0dbbf80eaac6732a2ced9a5f0bccd
parent42f35c38da5395d6a1aa44d84a1c391ffcdc5a89 (diff)
[Windows] Implements DXVA2 AV1 HW video decoding 8-bit and 10-bit
Tested on Intel 13700K with AV1 8 and 10 bit videos profile0 (main)
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp6
-rw-r--r--xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp68
2 files changed, 50 insertions, 24 deletions
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
index bb9c20bf9d..2737cbdada 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DVDVideoCodecFFmpeg.cpp
@@ -1028,9 +1028,9 @@ bool CDVDVideoCodecFFmpeg::GetPictureCommon(VideoPicture* pVideoPicture)
(m_pCodecContext->profile == FF_PROFILE_H264_HIGH_10||
m_pCodecContext->profile == FF_PROFILE_H264_HIGH_10_INTRA))
pVideoPicture->colorBits = 10;
- else if (m_pCodecContext->codec_id == AV_CODEC_ID_VP9 &&
- (m_pCodecContext->profile == FF_PROFILE_VP9_2 ||
- m_pCodecContext->profile == FF_PROFILE_VP9_3))
+ else if ((m_pCodecContext->codec_id == AV_CODEC_ID_VP9 ||
+ m_pCodecContext->codec_id == AV_CODEC_ID_AV1) &&
+ m_pCodecContext->sw_pix_fmt == AV_PIX_FMT_YUV420P10)
pVideoPicture->colorBits = 10;
if (m_pCodecContext->color_range == AVCOL_RANGE_JPEG ||
diff --git a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
index dda3d0c5af..5eb5d7208a 100644
--- a/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
+++ b/xbmc/cores/VideoPlayer/DVDCodecs/Video/DXVA.cpp
@@ -35,11 +35,13 @@
#include <d3d11_4.h>
#include <dxva.h>
#include <initguid.h>
+#include <sdkddkver.h>
using namespace DXVA;
using namespace Microsoft::WRL;
using namespace std::chrono_literals;
+// clang-format off
DEFINE_GUID(DXVADDI_Intel_ModeH264_A, 0x604F8E64,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
DEFINE_GUID(DXVADDI_Intel_ModeH264_C, 0x604F8E66,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
DEFINE_GUID(DXVADDI_Intel_ModeH264_E, 0x604F8E68,0x4951,0x4c54,0x88,0xFE,0xAB,0xD2,0x5C,0x15,0xB3,0xD6);
@@ -47,30 +49,37 @@ DEFINE_GUID(DXVADDI_Intel_ModeVC1_E, 0xBCC5DB6D,0xA2B6,0x4AF0,0xAC,0xE4,0x
DEFINE_GUID(DXVA_ModeH264_VLD_NoFGT_Flash, 0x4245F676,0x2BBC,0x4166,0xa0,0xBB,0x54,0xE7,0xB8,0x49,0xC3,0x80);
DEFINE_GUID(DXVA_Intel_VC1_ClearVideo_2, 0xE07EC519,0xE651,0x4CD6,0xAC,0x84,0x13,0x70,0xCC,0xEE,0xC8,0x51);
+// These AV1 GUIDs are only defined from Windows SDK 10.0.22000.0
+// Defined conditional here to able compile with lower SDK versions
+#ifndef NTDDI_WIN10_CO
+DEFINE_GUID(D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0, 0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a);
+DEFINE_GUID(D3D11_DECODER_PROFILE_AV1_VLD_PROFILE1, 0x6936ff0f,0x45b1,0x4163,0x9c,0xc1,0x64,0x6e,0xf6,0x94,0x61,0x08);
+DEFINE_GUID(D3D11_DECODER_PROFILE_AV1_VLD_PROFILE2, 0x0c5f2aa1,0xe541,0x4089,0xbb,0x7b,0x98,0x11,0x0a,0x19,0xd7,0xc8);
+#endif
+
// redefine DXVA_NoEncrypt with other macro, solves unresolved external symbol linker error
#ifndef DXVA_NoEncrypt
DEFINE_GUID(DXVA_NoEncrypt, 0x1b81beD0, 0xa0c7, 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5);
#endif
+// clang-format on
-static const int PROFILES_MPEG2_SIMPLE[] = { FF_PROFILE_MPEG2_SIMPLE,
- FF_PROFILE_UNKNOWN };
-static const int PROFILES_MPEG2_MAIN[] = { FF_PROFILE_MPEG2_SIMPLE,
- FF_PROFILE_MPEG2_MAIN,
- FF_PROFILE_UNKNOWN };
-static const int PROFILES_H264_HIGH[] = { FF_PROFILE_H264_BASELINE,
- FF_PROFILE_H264_CONSTRAINED_BASELINE,
- FF_PROFILE_H264_MAIN,
- FF_PROFILE_H264_HIGH,
- FF_PROFILE_UNKNOWN };
-static const int PROFILES_HEVC_MAIN[] = { FF_PROFILE_HEVC_MAIN,
- FF_PROFILE_UNKNOWN };
-static const int PROFILES_HEVC_MAIN10[] = { FF_PROFILE_HEVC_MAIN,
- FF_PROFILE_HEVC_MAIN_10,
- FF_PROFILE_UNKNOWN };
-static const int PROFILES_VP9_0[] = { FF_PROFILE_VP9_0,
- FF_PROFILE_UNKNOWN };
-static const int PROFILES_VP9_10_2[] = { FF_PROFILE_VP9_2,
- FF_PROFILE_UNKNOWN };
+namespace
+{
+constexpr int PROFILES_MPEG2_SIMPLE[] = {FF_PROFILE_MPEG2_SIMPLE, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_MPEG2_MAIN[] = {FF_PROFILE_MPEG2_SIMPLE, FF_PROFILE_MPEG2_MAIN,
+ FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_H264_HIGH[] = {FF_PROFILE_H264_BASELINE,
+ FF_PROFILE_H264_CONSTRAINED_BASELINE, FF_PROFILE_H264_MAIN,
+ FF_PROFILE_H264_HIGH, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_HEVC_MAIN[] = {FF_PROFILE_HEVC_MAIN, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_HEVC_MAIN10[] = {FF_PROFILE_HEVC_MAIN, FF_PROFILE_HEVC_MAIN_10,
+ FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_VP9_0[] = {FF_PROFILE_VP9_0, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_VP9_10_2[] = {FF_PROFILE_VP9_2, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_AV1_MAIN[] = {FF_PROFILE_AV1_MAIN, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_AV1_HIGH[] = {FF_PROFILE_AV1_HIGH, FF_PROFILE_UNKNOWN};
+constexpr int PROFILES_AV1_PROFESSIONAL[] = {FF_PROFILE_AV1_PROFESSIONAL, FF_PROFILE_UNKNOWN};
+} // namespace
typedef struct
{
@@ -81,6 +90,7 @@ typedef struct
} dxva2_mode_t;
/* XXX Preferred modes must come first */
+// clang-format off
static const std::vector<dxva2_mode_t> dxva2_modes = {
{ "MPEG2 variable-length decoder", &D3D11_DECODER_PROFILE_MPEG2_VLD, AV_CODEC_ID_MPEG2VIDEO, PROFILES_MPEG2_MAIN },
{ "MPEG1/2 variable-length decoder", &D3D11_DECODER_PROFILE_MPEG2and1_VLD, AV_CODEC_ID_MPEG2VIDEO, PROFILES_MPEG2_MAIN },
@@ -130,7 +140,12 @@ static const std::vector<dxva2_mode_t> dxva2_modes = {
{ "VP9 variable-length decoder, Profile 0", &D3D11_DECODER_PROFILE_VP9_VLD_PROFILE0, AV_CODEC_ID_VP9, PROFILES_VP9_0 },
{ "VP9 variable-length decoder, 10bit, profile 2", &D3D11_DECODER_PROFILE_VP9_VLD_10BIT_PROFILE2, AV_CODEC_ID_VP9, PROFILES_VP9_10_2 },
+
+ { "AV1 Profile 0 (main)", &D3D11_DECODER_PROFILE_AV1_VLD_PROFILE0, AV_CODEC_ID_AV1, PROFILES_AV1_MAIN },
+ { "AV1 Profile 1 (high)", &D3D11_DECODER_PROFILE_AV1_VLD_PROFILE1, AV_CODEC_ID_AV1, PROFILES_AV1_HIGH },
+ { "AV1 Profile 2 (professional)", &D3D11_DECODER_PROFILE_AV1_VLD_PROFILE2, AV_CODEC_ID_AV1, PROFILES_AV1_PROFESSIONAL },
};
+// clang-format on
// Preferred targets must be first
static const DXGI_FORMAT render_targets_dxgi[] = {
@@ -467,8 +482,13 @@ bool CContext::GetFormatAndConfig(AVCodecContext* avctx, D3D11_VIDEO_DECODER_DES
CLog::Log(LOGDEBUG, "DXVA: trying '{}'.", mode.name);
for (unsigned j = 0; render_targets_dxgi[j]; ++j)
{
- bool bHighBits = (avctx->codec_id == AV_CODEC_ID_HEVC && (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 || avctx->profile == FF_PROFILE_HEVC_MAIN_10))
- || (avctx->codec_id == AV_CODEC_ID_VP9 && (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 || avctx->profile == FF_PROFILE_VP9_2));
+ bool bHighBits =
+ (avctx->codec_id == AV_CODEC_ID_HEVC && (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ||
+ avctx->profile == FF_PROFILE_HEVC_MAIN_10)) ||
+ (avctx->codec_id == AV_CODEC_ID_VP9 &&
+ (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 || avctx->profile == FF_PROFILE_VP9_2)) ||
+ (avctx->codec_id == AV_CODEC_ID_AV1 && avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10);
+
if (bHighBits && render_targets_dxgi[j] < DXGI_FORMAT_P010)
continue;
@@ -1266,6 +1286,12 @@ bool CDecoder::Open(AVCodecContext* avctx, AVCodecContext* mainctx, enum AVPixel
case AV_CODEC_ID_VP9:
m_refs += 8;
break;
+ case AV_CODEC_ID_AV1:
+ // the AV1 DXVA2 spec asks for 128 pixel aligned surfaces
+ m_surface_alignment = 128;
+ // by specification AV1 decoder can hold up to 8 unique refs
+ m_refs += 8;
+ break;
default:
m_refs += 2;
}