[FFmpeg-devel,v2] avcodec/dxva2: add support for HEVC RExt DXVA profiles
Checks
Context |
Check |
Description |
yinshiyou/make_loongarch64 |
success
|
Make finished
|
yinshiyou/make_fate_loongarch64 |
success
|
Make fate finished
|
andriy/make_x86 |
success
|
Make finished
|
andriy/make_fate_x86 |
success
|
Make fate finished
|
Commit Message
Microsoft has formally standardized DXVA GUIDs for HEVC Range Extension
profiles in the Windows 11 24H2 SDK. They are supported by Intel GPUs
starting with Tiger Lake.
Like VDPAU and VAAPI, DXVA has separate GUIDs for each RExt profile, so
we must parse the SPS like those hwaccels do to figure out which one to
use when creating our decoder.
The new RExt profiles are supported with DXVA2 and D3D11VA (depending on
driver support).
Signed-off-by: Cameron Gutman <aicommander@gmail.com>
---
v2 addresses some off-list feedback regarding the duplicate definition
of some DXVA GUIDs and incorrect handling of the pixel format of the
hw_frames_ctx when FFmpeg creates one internally.
---
libavcodec/d3d12va_hevc.c | 21 ++++---
libavcodec/dxva2.c | 77 +++++++++++++++++++++---
libavcodec/dxva2_hevc.c | 115 ++++++++++++++++++++++++++++++++++--
libavcodec/dxva2_internal.h | 47 ++++++++++++++-
libavcodec/hevc/hevcdec.c | 28 +++++++++
5 files changed, 266 insertions(+), 22 deletions(-)
Comments
Hi,
For the record we have been running this in VLC for quite some time,
only for Intel hardware.
https://code.videolan.org/videolan/vlc/-/blob/3.0.x/contrib/src/ffmpeg/0001-avcodec-dxva2_hevc-add-support-for-parsing-HEVC-Rang.patch?ref_type=heads
https://code.videolan.org/videolan/vlc/-/blob/3.0.x/contrib/src/ffmpeg/0002-avcodec-hevcdec-allow-HEVC-444-8-10-12-bits-decoding.patch?ref_type=heads
https://code.videolan.org/videolan/vlc/-/blob/3.0.x/contrib/src/ffmpeg/0003-avcodec-hevcdec-allow-HEVC-422-10-12-bits-decoding-w.patch?ref_type=heads
It seems the MS GUID are not the same as Intel...
On 13/11/2024 04:25, Cameron Gutman wrote:
> Microsoft has formally standardized DXVA GUIDs for HEVC Range Extension
> profiles in the Windows 11 24H2 SDK. They are supported by Intel GPUs
> starting with Tiger Lake.
>
> Like VDPAU and VAAPI, DXVA has separate GUIDs for each RExt profile, so
> we must parse the SPS like those hwaccels do to figure out which one to
> use when creating our decoder.
>
> The new RExt profiles are supported with DXVA2 and D3D11VA (depending on
> driver support).
>
> Signed-off-by: Cameron Gutman <aicommander@gmail.com>
> ---
> v2 addresses some off-list feedback regarding the duplicate definition
> of some DXVA GUIDs and incorrect handling of the pixel format of the
> hw_frames_ctx when FFmpeg creates one internally.
> ---
> libavcodec/d3d12va_hevc.c | 21 ++++---
> libavcodec/dxva2.c | 77 +++++++++++++++++++++---
> libavcodec/dxva2_hevc.c | 115 ++++++++++++++++++++++++++++++++++--
> libavcodec/dxva2_internal.h | 47 ++++++++++++++-
> libavcodec/hevc/hevcdec.c | 28 +++++++++
> 5 files changed, 266 insertions(+), 22 deletions(-)
>
> diff --git a/libavcodec/d3d12va_hevc.c b/libavcodec/d3d12va_hevc.c
> index 7686f0eb6c..f4272cec1e 100644
> --- a/libavcodec/d3d12va_hevc.c
> +++ b/libavcodec/d3d12va_hevc.c
> @@ -33,12 +33,15 @@
> #define MAX_SLICES 256
>
> typedef struct HEVCDecodePictureContext {
> - DXVA_PicParams_HEVC pp;
> - DXVA_Qmatrix_HEVC qm;
> - unsigned slice_count;
> - DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
> - const uint8_t *bitstream;
> - unsigned bitstream_size;
> + union {
> + DXVA_PicParams_HEVC pp;
> + ff_DXVA_PicParams_HEVC_RangeExt ppext;
> + };
> + DXVA_Qmatrix_HEVC qm;
> + unsigned slice_count;
> + DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
> + const uint8_t *bitstream;
> + unsigned bitstream_size;
> } HEVCDecodePictureContext;
>
> static void fill_slice_short(DXVA_Slice_HEVC_Short *slice, unsigned position, unsigned size)
> @@ -62,7 +65,7 @@ static int d3d12va_hevc_start_frame(AVCodecContext *avctx, av_unused const uint8
>
> ctx->used_mask = 0;
>
> - ff_dxva2_hevc_fill_picture_parameters(avctx, (AVDXVAContext *)ctx, &ctx_pic->pp);
> + ff_dxva2_hevc_fill_picture_parameters(avctx, (AVDXVAContext *)ctx, &ctx_pic->ppext);
>
> ff_dxva2_hevc_fill_scaling_lists(avctx, (AVDXVAContext *)ctx, &ctx_pic->qm);
>
> @@ -152,11 +155,13 @@ static int d3d12va_hevc_end_frame(AVCodecContext *avctx)
> HEVCDecodePictureContext *ctx_pic = h->cur_frame->hwaccel_picture_private;
>
> int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
> + int rext = avctx->profile == AV_PROFILE_HEVC_REXT;
>
> if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
> return -1;
>
> - return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
> + return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp,
> + rext ? sizeof(ctx_pic->ppext) : sizeof(ctx_pic->pp),
> scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, update_input_arguments);
> }
>
> diff --git a/libavcodec/dxva2.c b/libavcodec/dxva2.c
> index 22ecd5acaf..ed6036e099 100644
> --- a/libavcodec/dxva2.c
> +++ b/libavcodec/dxva2.c
> @@ -48,7 +48,6 @@ DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x8
> DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7);
> DEFINE_GUID(ff_DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a);
> DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
> -DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
> DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
>
> typedef struct dxva_mode {
> @@ -70,6 +69,8 @@ static const int prof_hevc_main[] = {AV_PROFILE_HEVC_MAIN,
> AV_PROFILE_UNKNOWN};
> static const int prof_hevc_main10[] = {AV_PROFILE_HEVC_MAIN_10,
> AV_PROFILE_UNKNOWN};
> +static const int prof_hevc_rext[] = {AV_PROFILE_HEVC_REXT,
> + AV_PROFILE_UNKNOWN};
> static const int prof_vp9_profile0[] = {AV_PROFILE_VP9_0,
> AV_PROFILE_UNKNOWN};
> static const int prof_vp9_profile2[] = {AV_PROFILE_VP9_2,
> @@ -95,8 +96,14 @@ static const dxva_mode dxva_modes[] = {
> { &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 },
>
> /* HEVC/H.265 */
> - { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 },
> - { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main },
> + { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 },
> + { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main },
> + { &ff_DXVA2_ModeHEVC_VLD_Main12, AV_CODEC_ID_HEVC, prof_hevc_rext },
> + { &ff_DXVA2_ModeHEVC_VLD_Main10_422, AV_CODEC_ID_HEVC, prof_hevc_rext },
> + { &ff_DXVA2_ModeHEVC_VLD_Main12_422, AV_CODEC_ID_HEVC, prof_hevc_rext },
> + { &ff_DXVA2_ModeHEVC_VLD_Main_444, AV_CODEC_ID_HEVC, prof_hevc_rext },
> + { &ff_DXVA2_ModeHEVC_VLD_Main10_444, AV_CODEC_ID_HEVC, prof_hevc_rext },
> + { &ff_DXVA2_ModeHEVC_VLD_Main12_444, AV_CODEC_ID_HEVC, prof_hevc_rext },
>
> /* VP8/9 */
> { &ff_DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9, prof_vp9_profile0 },
> @@ -208,6 +215,8 @@ static int dxva_check_codec_compatibility(AVCodecContext *avctx, const dxva_mode
> }
> if (!found)
> return 0;
> + if (avctx->codec_id == AV_CODEC_ID_HEVC && avctx->profile == AV_PROFILE_HEVC_REXT)
> + return IsEqualGUID(ff_dxva2_hevc_parse_rext_profile(avctx), mode->guid);
> }
>
> return 1;
> @@ -246,7 +255,16 @@ static void dxva_list_guids_debug(AVCodecContext *avctx, void *service,
> #if CONFIG_DXVA2
> if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
> const D3DFORMAT formats[] = {MKTAG('N', 'V', '1', '2'),
> - MKTAG('P', '0', '1', '0')};
> + MKTAG('A', 'Y', 'U', 'V'),
> + MKTAG('Y', 'U', 'Y', '2'),
> + MKTAG('P', '0', '1', '0'),
> + MKTAG('P', '0', '1', '6'),
> + MKTAG('P', '2', '1', '0'),
> + MKTAG('P', '2', '1', '6'),
> + MKTAG('Y', '2', '1', '0'),
> + MKTAG('Y', '2', '1', '6'),
> + MKTAG('Y', '4', '1', '0'),
> + MKTAG('Y', '4', '1', '6'),};
> int i;
> for (i = 0; i < FF_ARRAY_ELEMS(formats); i++) {
> if (dxva2_validate_output(service, *guid, &formats[i]))
> @@ -315,6 +333,22 @@ static AVBufferRef *bufref_wrap_interface(IUnknown *iface)
> return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0);
> }
>
> +static enum AVPixelFormat dxva_map_sw_to_hw_frames_format(enum AVPixelFormat pix_fmt)
> +{
> + switch (pix_fmt) {
> + case AV_PIX_FMT_YUV420P: return AV_PIX_FMT_NV12;
> + case AV_PIX_FMT_YUV420P10: return AV_PIX_FMT_P010;
> + case AV_PIX_FMT_YUV420P12: return AV_PIX_FMT_P012;
> + case AV_PIX_FMT_YUV422P: return AV_PIX_FMT_YUYV422;
> + case AV_PIX_FMT_YUV422P10: return AV_PIX_FMT_Y210;
> + case AV_PIX_FMT_YUV422P12: return AV_PIX_FMT_Y212;
> + case AV_PIX_FMT_YUV444P: return AV_PIX_FMT_VUYX;
> + case AV_PIX_FMT_YUV444P10: return AV_PIX_FMT_XV30;
> + case AV_PIX_FMT_YUV444P12: return AV_PIX_FMT_XV36;
> + default: return AV_PIX_FMT_NONE;
> + }
> +}
> +
> #if CONFIG_DXVA2
>
> static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *device_guid,
> @@ -340,14 +374,31 @@ static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *de
> return ret;
> }
>
> +static D3DFORMAT dxva2_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
> +{
> + switch (pix_fmt) {
> + case AV_PIX_FMT_NV12: return MKTAG('N', 'V', '1', '2');
> + case AV_PIX_FMT_P010: return MKTAG('P', '0', '1', '0');
> + case AV_PIX_FMT_P012: return MKTAG('P', '0', '1', '6');
> + case AV_PIX_FMT_P016: return MKTAG('P', '0', '1', '6');
> + case AV_PIX_FMT_YUYV422: return MKTAG('Y', 'U', 'Y', '2');
> + case AV_PIX_FMT_Y210: return MKTAG('Y', '2', '1', '0');
> + case AV_PIX_FMT_Y212: return MKTAG('Y', '2', '1', '6');
> + case AV_PIX_FMT_Y216: return MKTAG('Y', '2', '1', '6');
> + case AV_PIX_FMT_VUYX: return MKTAG('A', 'Y', 'U', 'V');
> + case AV_PIX_FMT_XV30: return MKTAG('Y', '4', '1', '0');
> + case AV_PIX_FMT_XV36: return MKTAG('Y', '4', '1', '6');
> + case AV_PIX_FMT_XV48: return MKTAG('Y', '4', '1', '6');
> + default: return D3DFMT_UNKNOWN;
> + }
> +}
> +
> static int dxva2_create_decoder(AVCodecContext *avctx)
> {
> FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
> GUID *guid_list;
> unsigned guid_count;
> GUID device_guid;
> - D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
> - MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2');
> DXVA2_VideoDesc desc = { 0 };
> DXVA2_ConfigPictureDecode config;
> HRESULT hr;
> @@ -356,6 +407,7 @@ static int dxva2_create_decoder(AVCodecContext *avctx)
> AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
> AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
> AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
> + D3DFORMAT surface_format = dxva2_map_sw_to_hw_format(frames_ctx->sw_format);
>
> hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
> &device_handle);
> @@ -459,6 +511,16 @@ static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
> case AV_PIX_FMT_NV12: return DXGI_FORMAT_NV12;
> case AV_PIX_FMT_P010: return DXGI_FORMAT_P010;
> case AV_PIX_FMT_YUV420P: return DXGI_FORMAT_420_OPAQUE;
> + case AV_PIX_FMT_VUYX: return DXGI_FORMAT_AYUV;
> + case AV_PIX_FMT_YUYV422: return DXGI_FORMAT_YUY2;
> + case AV_PIX_FMT_Y210: return DXGI_FORMAT_Y210;
> + case AV_PIX_FMT_XV30: return DXGI_FORMAT_Y410;
> + case AV_PIX_FMT_P012: return DXGI_FORMAT_P016;
> + case AV_PIX_FMT_P016: return DXGI_FORMAT_P016;
> + case AV_PIX_FMT_Y212: return DXGI_FORMAT_Y216;
> + case AV_PIX_FMT_Y216: return DXGI_FORMAT_Y216;
> + case AV_PIX_FMT_XV36: return DXGI_FORMAT_Y416;
> + case AV_PIX_FMT_XV48: return DXGI_FORMAT_Y416;
> default: return DXGI_FORMAT_UNKNOWN;
> }
> }
> @@ -627,8 +689,7 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
> else
> num_surfaces += 2;
>
> - frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
> - AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
> + frames_ctx->sw_format = dxva_map_sw_to_hw_frames_format(avctx->sw_pix_fmt);
> frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
> frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment);
> frames_ctx->initial_pool_size = num_surfaces;
> diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c
> index d01d1e76e8..f9af5cbd02 100644
> --- a/libavcodec/dxva2_hevc.c
> +++ b/libavcodec/dxva2_hevc.c
> @@ -28,11 +28,15 @@
> #include "hevc/data.h"
> #include "hevc/hevcdec.h"
> #include "hwaccel_internal.h"
> +#include "h265_profile_level.h"
>
> #define MAX_SLICES 256
>
> struct hevc_dxva2_picture_context {
> - DXVA_PicParams_HEVC pp;
> + union {
> + DXVA_PicParams_HEVC pp;
> + ff_DXVA_PicParams_HEVC_RangeExt ppext;
> + };
> DXVA_Qmatrix_HEVC qm;
> unsigned slice_count;
> DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
> @@ -57,9 +61,82 @@ static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index)
> return 0xff;
> }
>
> +static int ptl_convert(const PTLCommon *general_ptl, H265RawProfileTierLevel *h265_raw_ptl)
> +{
> + h265_raw_ptl->general_profile_space = general_ptl->profile_space;
> + h265_raw_ptl->general_tier_flag = general_ptl->tier_flag;
> + h265_raw_ptl->general_profile_idc = general_ptl->profile_idc;
> +
> + memcpy(h265_raw_ptl->general_profile_compatibility_flag,
> + general_ptl->profile_compatibility_flag, 32 * sizeof(uint8_t));
> +
> +#define copy_field(name) h265_raw_ptl->general_ ## name = general_ptl->name
> + copy_field(progressive_source_flag);
> + copy_field(interlaced_source_flag);
> + copy_field(non_packed_constraint_flag);
> + copy_field(frame_only_constraint_flag);
> + copy_field(max_12bit_constraint_flag);
> + copy_field(max_10bit_constraint_flag);
> + copy_field(max_8bit_constraint_flag);
> + copy_field(max_422chroma_constraint_flag);
> + copy_field(max_420chroma_constraint_flag);
> + copy_field(max_monochrome_constraint_flag);
> + copy_field(intra_constraint_flag);
> + copy_field(one_picture_only_constraint_flag);
> + copy_field(lower_bit_rate_constraint_flag);
> + copy_field(max_14bit_constraint_flag);
> + copy_field(inbld_flag);
> + copy_field(level_idc);
> +#undef copy_field
> +
> + return 0;
> +}
> +
> +const GUID *ff_dxva2_hevc_parse_rext_profile(AVCodecContext *avctx)
> +{
> + const HEVCContext *h = avctx->priv_data;
> + const HEVCSPS *sps = h->pps->sps;
> + const PTL *ptl = &sps->ptl;
> + const PTLCommon *general_ptl = &ptl->general_ptl;
> + const H265ProfileDescriptor *profile;
> + H265RawProfileTierLevel h265_raw_ptl = {0};
> +
> + /* convert PTLCommon to H265RawProfileTierLevel */
> + ptl_convert(general_ptl, &h265_raw_ptl);
> +
> + profile = ff_h265_get_profile(&h265_raw_ptl);
> + if (!profile) {
> + av_log(avctx, AV_LOG_ERROR, "HEVC profile is not found.\n");
> + return &ff_GUID_NULL;
> + }
> +
> + if (!strcmp(profile->name, "Main 12") ||
> + !strcmp(profile->name, "Main 12 Intra"))
> + return &ff_DXVA2_ModeHEVC_VLD_Main12;
> + else if (!strcmp(profile->name, "Main 4:2:2 10") ||
> + !strcmp(profile->name, "Main 4:2:2 10 Intra"))
> + return &ff_DXVA2_ModeHEVC_VLD_Main10_422;
> + else if (!strcmp(profile->name, "Main 4:2:2 12") ||
> + !strcmp(profile->name, "Main 4:2:2 12 Intra"))
> + return &ff_DXVA2_ModeHEVC_VLD_Main12_422;
> + else if (!strcmp(profile->name, "Main 4:4:4") ||
> + !strcmp(profile->name, "Main 4:4:4 Intra"))
> + return &ff_DXVA2_ModeHEVC_VLD_Main_444;
> + else if (!strcmp(profile->name, "Main 4:4:4 10") ||
> + !strcmp(profile->name, "Main 4:4:4 10 Intra"))
> + return &ff_DXVA2_ModeHEVC_VLD_Main10_444;
> + else if (!strcmp(profile->name, "Main 4:4:4 12") ||
> + !strcmp(profile->name, "Main 4:4:4 12 Intra"))
> + return &ff_DXVA2_ModeHEVC_VLD_Main12_444;
> +
> + av_log(avctx, AV_LOG_ERROR, "Unsupported HEVC RExt profile: %s\n", profile->name);
> + return &ff_GUID_NULL;
> +}
> +
> void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx,
> - DXVA_PicParams_HEVC *pp)
> + ff_DXVA_PicParams_HEVC_RangeExt *ppext)
> {
> + DXVA_PicParams_HEVC *pp = &ppext->params;
> const HEVCContext *h = avctx->priv_data;
> const HEVCLayerContext *l = &h->layers[h->cur_layer];
> const HEVCFrame *current_picture = h->cur_frame;
> @@ -67,7 +144,7 @@ void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
> const HEVCSPS *sps = pps->sps;
> int i, j;
>
> - memset(pp, 0, sizeof(*pp));
> + memset(ppext, 0, sizeof(*ppext));
>
> pp->PicWidthInMinCbsY = sps->min_cb_width;
> pp->PicHeightInMinCbsY = sps->min_cb_height;
> @@ -200,6 +277,32 @@ void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
> DO_REF_LIST(LT_CURR, RefPicSetLtCurr);
>
> pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
> +
> + if (sps->range_extension) {
> + ppext->transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled;
> + ppext->transform_skip_context_enabled_flag = sps->transform_skip_context_enabled;
> + ppext->implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled;
> + ppext->explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled;
> + ppext->extended_precision_processing_flag = sps->extended_precision_processing;
> + ppext->intra_smoothing_disabled_flag = sps->intra_smoothing_disabled;
> + ppext->persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled;
> + ppext->high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled;
> + ppext->cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled;
> + }
> + if (pps->pps_range_extensions_flag) {
> + ppext->cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag;
> + ppext->chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag;
> +
> + ppext->diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth;
> + ppext->log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma;
> + ppext->log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma;
> + ppext->log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2;
> + ppext->chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1;
> + for (i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
> + ppext->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
> + ppext->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
> + }
> + }
> }
>
> void ff_dxva2_hevc_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_HEVC *qm)
> @@ -375,7 +478,7 @@ static int dxva2_hevc_start_frame(AVCodecContext *avctx,
> av_assert0(ctx_pic);
>
> /* Fill up DXVA_PicParams_HEVC */
> - ff_dxva2_hevc_fill_picture_parameters(avctx, ctx, &ctx_pic->pp);
> + ff_dxva2_hevc_fill_picture_parameters(avctx, ctx, &ctx_pic->ppext);
>
> /* Fill up DXVA_Qmatrix_HEVC */
> ff_dxva2_hevc_fill_scaling_lists(avctx, ctx, &ctx_pic->qm);
> @@ -414,13 +517,15 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx)
> HEVCContext *h = avctx->priv_data;
> struct hevc_dxva2_picture_context *ctx_pic = h->cur_frame->hwaccel_picture_private;
> int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
> + int rext = avctx->profile == AV_PROFILE_HEVC_REXT;
> int ret;
>
> if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
> return -1;
>
> ret = ff_dxva2_common_end_frame(avctx, h->cur_frame->f,
> - &ctx_pic->pp, sizeof(ctx_pic->pp),
> + &ctx_pic->pp,
> + rext ? sizeof(ctx_pic->ppext) : sizeof(ctx_pic->pp),
> scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0,
> commit_bitstream_and_slice_buffer);
> return ret;
> diff --git a/libavcodec/dxva2_internal.h b/libavcodec/dxva2_internal.h
> index 6cbd0e42d7..4d5656e09b 100644
> --- a/libavcodec/dxva2_internal.h
> +++ b/libavcodec/dxva2_internal.h
> @@ -69,6 +69,49 @@
> #include "avcodec.h"
> #include "internal.h"
>
> +DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
> +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main12, 0x1a72925f, 0x0c2c,0x4f15,0x96,0xfb,0xb1,0x7d,0x14,0x73,0x60,0x3f);
> +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10_422, 0x0bac4fe5, 0x1532,0x4429,0xa8,0x54,0xf8,0x4d,0xe0,0x49,0x53,0xdb);
> +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main12_422, 0x55bcac81, 0xf311,0x4093,0xa7,0xd0,0x1c,0xbc,0x0b,0x84,0x9b,0xee);
> +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main_444, 0x4008018f, 0xf537,0x4b36,0x98,0xcf,0x61,0xaf,0x8a,0x2c,0x1a,0x33);
> +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10_444, 0x0dabeffa, 0x4458,0x4602,0xbc,0x03,0x07,0x95,0x65,0x9d,0x61,0x7c);
> +DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main12_444, 0x9798634d, 0xfe9d,0x48e5,0xb4,0xda,0xdb,0xec,0x45,0xb3,0xdf,0x01);
> +
> +/* This is only defined starting in the Windows 11 24H2 SDK */
> +#pragma pack(push,1)
> +typedef struct ff_DXVA_PicParams_HEVC_RangeExt {
> + DXVA_PicParams_HEVC params;
> +
> + union {
> + struct {
> + USHORT transform_skip_rotation_enabled_flag : 1;
> + USHORT transform_skip_context_enabled_flag : 1;
> + USHORT implicit_rdpcm_enabled_flag : 1;
> + USHORT explicit_rdpcm_enabled_flag : 1;
> + USHORT extended_precision_processing_flag : 1;
> + USHORT intra_smoothing_disabled_flag : 1;
> + USHORT persistent_rice_adaptation_enabled_flag : 1;
> + USHORT high_precision_offsets_enabled_flag : 1;
> + USHORT cabac_bypass_alignment_enabled_flag : 1;
> + USHORT cross_component_prediction_enabled_flag : 1;
> + USHORT chroma_qp_offset_list_enabled_flag : 1;
> + USHORT ReservedBits8 : 5;
> + };
> + USHORT dwRangeExtensionFlags;
> + };
> +
> + UCHAR diff_cu_chroma_qp_offset_depth;
> + UCHAR log2_sao_offset_scale_luma;
> + UCHAR log2_sao_offset_scale_chroma;
> + UCHAR log2_max_transform_skip_block_size_minus2;
> + CHAR cb_qp_offset_list[6];
> + CHAR cr_qp_offset_list[6];
> + UCHAR chroma_qp_offset_list_len_minus1;
> + USHORT ReservedBits9;
> +
> +} ff_DXVA_PicParams_HEVC_RangeExt;
> +#pragma pack(pop)
> +
> typedef void DECODER_BUFFER_DESC;
>
> typedef union {
> @@ -172,9 +215,11 @@ void ff_dxva2_h264_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
> void ff_dxva2_h264_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_H264 *qm);
>
> #if CONFIG_HEVC_D3D12VA_HWACCEL || CONFIG_HEVC_D3D11VA_HWACCEL || CONFIG_HEVC_D3D11VA2_HWACCEL || CONFIG_HEVC_DXVA2_HWACCEL
> -void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_PicParams_HEVC *pp);
> +void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, ff_DXVA_PicParams_HEVC_RangeExt *ppext);
>
> void ff_dxva2_hevc_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_HEVC *qm);
> +
> +const GUID *ff_dxva2_hevc_parse_rext_profile(AVCodecContext *avctx);
> #endif
>
> #if CONFIG_VP9_D3D12VA_HWACCEL || CONFIG_VP9_D3D11VA_HWACCEL || CONFIG_VP9_D3D11VA2_HWACCEL || CONFIG_VP9_DXVA2_HWACCEL
> diff --git a/libavcodec/hevc/hevcdec.c b/libavcodec/hevc/hevcdec.c
> index 1ea8df0fa0..f94aa45e3d 100644
> --- a/libavcodec/hevc/hevcdec.c
> +++ b/libavcodec/hevc/hevcdec.c
> @@ -592,6 +592,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
> #endif
> break;
> case AV_PIX_FMT_YUV444P:
> +#if CONFIG_HEVC_DXVA2_HWACCEL
> + *fmt++ = AV_PIX_FMT_DXVA2_VLD;
> +#endif
> +#if CONFIG_HEVC_D3D11VA_HWACCEL
> + *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
> + *fmt++ = AV_PIX_FMT_D3D11;
> +#endif
> #if CONFIG_HEVC_VAAPI_HWACCEL
> *fmt++ = AV_PIX_FMT_VAAPI;
> #endif
> @@ -610,6 +617,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
> break;
> case AV_PIX_FMT_YUV422P:
> case AV_PIX_FMT_YUV422P10LE:
> +#if CONFIG_HEVC_DXVA2_HWACCEL
> + *fmt++ = AV_PIX_FMT_DXVA2_VLD;
> +#endif
> +#if CONFIG_HEVC_D3D11VA_HWACCEL
> + *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
> + *fmt++ = AV_PIX_FMT_D3D11;
> +#endif
> #if CONFIG_HEVC_VAAPI_HWACCEL
> *fmt++ = AV_PIX_FMT_VAAPI;
> #endif
> @@ -627,6 +641,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
> /* NOTE: fallthrough */
> case AV_PIX_FMT_YUV420P12:
> case AV_PIX_FMT_YUV444P12:
> +#if CONFIG_HEVC_DXVA2_HWACCEL
> + *fmt++ = AV_PIX_FMT_DXVA2_VLD;
> +#endif
> +#if CONFIG_HEVC_D3D11VA_HWACCEL
> + *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
> + *fmt++ = AV_PIX_FMT_D3D11;
> +#endif
> #if CONFIG_HEVC_VAAPI_HWACCEL
> *fmt++ = AV_PIX_FMT_VAAPI;
> #endif
> @@ -641,6 +662,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
> #endif
> break;
> case AV_PIX_FMT_YUV422P12:
> +#if CONFIG_HEVC_DXVA2_HWACCEL
> + *fmt++ = AV_PIX_FMT_DXVA2_VLD;
> +#endif
> +#if CONFIG_HEVC_D3D11VA_HWACCEL
> + *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
> + *fmt++ = AV_PIX_FMT_D3D11;
> +#endif
> #if CONFIG_HEVC_VAAPI_HWACCEL
> *fmt++ = AV_PIX_FMT_VAAPI;
> #endif
> --
> 2.47.0.windows.2
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
@@ -33,12 +33,15 @@
#define MAX_SLICES 256
typedef struct HEVCDecodePictureContext {
- DXVA_PicParams_HEVC pp;
- DXVA_Qmatrix_HEVC qm;
- unsigned slice_count;
- DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
- const uint8_t *bitstream;
- unsigned bitstream_size;
+ union {
+ DXVA_PicParams_HEVC pp;
+ ff_DXVA_PicParams_HEVC_RangeExt ppext;
+ };
+ DXVA_Qmatrix_HEVC qm;
+ unsigned slice_count;
+ DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
+ const uint8_t *bitstream;
+ unsigned bitstream_size;
} HEVCDecodePictureContext;
static void fill_slice_short(DXVA_Slice_HEVC_Short *slice, unsigned position, unsigned size)
@@ -62,7 +65,7 @@ static int d3d12va_hevc_start_frame(AVCodecContext *avctx, av_unused const uint8
ctx->used_mask = 0;
- ff_dxva2_hevc_fill_picture_parameters(avctx, (AVDXVAContext *)ctx, &ctx_pic->pp);
+ ff_dxva2_hevc_fill_picture_parameters(avctx, (AVDXVAContext *)ctx, &ctx_pic->ppext);
ff_dxva2_hevc_fill_scaling_lists(avctx, (AVDXVAContext *)ctx, &ctx_pic->qm);
@@ -152,11 +155,13 @@ static int d3d12va_hevc_end_frame(AVCodecContext *avctx)
HEVCDecodePictureContext *ctx_pic = h->cur_frame->hwaccel_picture_private;
int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
+ int rext = avctx->profile == AV_PROFILE_HEVC_REXT;
if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
return -1;
- return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp, sizeof(ctx_pic->pp),
+ return ff_d3d12va_common_end_frame(avctx, h->cur_frame->f, &ctx_pic->pp,
+ rext ? sizeof(ctx_pic->ppext) : sizeof(ctx_pic->pp),
scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, update_input_arguments);
}
@@ -48,7 +48,6 @@ DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_Profile0,0x463707f8,0xa1d0,0x4585,0x87,0x6d,0x8
DEFINE_GUID(ff_DXVA2_ModeVP9_VLD_10bit_Profile2,0xa4c749ef,0x6ecf,0x48aa,0x84,0x48,0x50,0xa7,0xa1,0x16,0x5f,0xf7);
DEFINE_GUID(ff_DXVA2_ModeAV1_VLD_Profile0,0xb8be4ccb,0xcf53,0x46ba,0x8d,0x59,0xd6,0xb8,0xa6,0xda,0x5d,0x2a);
DEFINE_GUID(ff_DXVA2_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5);
-DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
DEFINE_GUID(ff_IID_IDirectXVideoDecoderService, 0xfc51a551,0xd5e7,0x11d9,0xaf,0x55,0x00,0x05,0x4e,0x43,0xff,0x02);
typedef struct dxva_mode {
@@ -70,6 +69,8 @@ static const int prof_hevc_main[] = {AV_PROFILE_HEVC_MAIN,
AV_PROFILE_UNKNOWN};
static const int prof_hevc_main10[] = {AV_PROFILE_HEVC_MAIN_10,
AV_PROFILE_UNKNOWN};
+static const int prof_hevc_rext[] = {AV_PROFILE_HEVC_REXT,
+ AV_PROFILE_UNKNOWN};
static const int prof_vp9_profile0[] = {AV_PROFILE_VP9_0,
AV_PROFILE_UNKNOWN};
static const int prof_vp9_profile2[] = {AV_PROFILE_VP9_2,
@@ -95,8 +96,14 @@ static const dxva_mode dxva_modes[] = {
{ &ff_DXVA2_ModeVC1_D, AV_CODEC_ID_WMV3 },
/* HEVC/H.265 */
- { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 },
- { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main },
+ { &ff_DXVA2_ModeHEVC_VLD_Main10, AV_CODEC_ID_HEVC, prof_hevc_main10 },
+ { &ff_DXVA2_ModeHEVC_VLD_Main, AV_CODEC_ID_HEVC, prof_hevc_main },
+ { &ff_DXVA2_ModeHEVC_VLD_Main12, AV_CODEC_ID_HEVC, prof_hevc_rext },
+ { &ff_DXVA2_ModeHEVC_VLD_Main10_422, AV_CODEC_ID_HEVC, prof_hevc_rext },
+ { &ff_DXVA2_ModeHEVC_VLD_Main12_422, AV_CODEC_ID_HEVC, prof_hevc_rext },
+ { &ff_DXVA2_ModeHEVC_VLD_Main_444, AV_CODEC_ID_HEVC, prof_hevc_rext },
+ { &ff_DXVA2_ModeHEVC_VLD_Main10_444, AV_CODEC_ID_HEVC, prof_hevc_rext },
+ { &ff_DXVA2_ModeHEVC_VLD_Main12_444, AV_CODEC_ID_HEVC, prof_hevc_rext },
/* VP8/9 */
{ &ff_DXVA2_ModeVP9_VLD_Profile0, AV_CODEC_ID_VP9, prof_vp9_profile0 },
@@ -208,6 +215,8 @@ static int dxva_check_codec_compatibility(AVCodecContext *avctx, const dxva_mode
}
if (!found)
return 0;
+ if (avctx->codec_id == AV_CODEC_ID_HEVC && avctx->profile == AV_PROFILE_HEVC_REXT)
+ return IsEqualGUID(ff_dxva2_hevc_parse_rext_profile(avctx), mode->guid);
}
return 1;
@@ -246,7 +255,16 @@ static void dxva_list_guids_debug(AVCodecContext *avctx, void *service,
#if CONFIG_DXVA2
if (sctx->pix_fmt == AV_PIX_FMT_DXVA2_VLD) {
const D3DFORMAT formats[] = {MKTAG('N', 'V', '1', '2'),
- MKTAG('P', '0', '1', '0')};
+ MKTAG('A', 'Y', 'U', 'V'),
+ MKTAG('Y', 'U', 'Y', '2'),
+ MKTAG('P', '0', '1', '0'),
+ MKTAG('P', '0', '1', '6'),
+ MKTAG('P', '2', '1', '0'),
+ MKTAG('P', '2', '1', '6'),
+ MKTAG('Y', '2', '1', '0'),
+ MKTAG('Y', '2', '1', '6'),
+ MKTAG('Y', '4', '1', '0'),
+ MKTAG('Y', '4', '1', '6'),};
int i;
for (i = 0; i < FF_ARRAY_ELEMS(formats); i++) {
if (dxva2_validate_output(service, *guid, &formats[i]))
@@ -315,6 +333,22 @@ static AVBufferRef *bufref_wrap_interface(IUnknown *iface)
return av_buffer_create((uint8_t*)iface, 1, bufref_free_interface, iface, 0);
}
+static enum AVPixelFormat dxva_map_sw_to_hw_frames_format(enum AVPixelFormat pix_fmt)
+{
+ switch (pix_fmt) {
+ case AV_PIX_FMT_YUV420P: return AV_PIX_FMT_NV12;
+ case AV_PIX_FMT_YUV420P10: return AV_PIX_FMT_P010;
+ case AV_PIX_FMT_YUV420P12: return AV_PIX_FMT_P012;
+ case AV_PIX_FMT_YUV422P: return AV_PIX_FMT_YUYV422;
+ case AV_PIX_FMT_YUV422P10: return AV_PIX_FMT_Y210;
+ case AV_PIX_FMT_YUV422P12: return AV_PIX_FMT_Y212;
+ case AV_PIX_FMT_YUV444P: return AV_PIX_FMT_VUYX;
+ case AV_PIX_FMT_YUV444P10: return AV_PIX_FMT_XV30;
+ case AV_PIX_FMT_YUV444P12: return AV_PIX_FMT_XV36;
+ default: return AV_PIX_FMT_NONE;
+ }
+}
+
#if CONFIG_DXVA2
static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *device_guid,
@@ -340,14 +374,31 @@ static int dxva2_get_decoder_configuration(AVCodecContext *avctx, const GUID *de
return ret;
}
+static D3DFORMAT dxva2_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
+{
+ switch (pix_fmt) {
+ case AV_PIX_FMT_NV12: return MKTAG('N', 'V', '1', '2');
+ case AV_PIX_FMT_P010: return MKTAG('P', '0', '1', '0');
+ case AV_PIX_FMT_P012: return MKTAG('P', '0', '1', '6');
+ case AV_PIX_FMT_P016: return MKTAG('P', '0', '1', '6');
+ case AV_PIX_FMT_YUYV422: return MKTAG('Y', 'U', 'Y', '2');
+ case AV_PIX_FMT_Y210: return MKTAG('Y', '2', '1', '0');
+ case AV_PIX_FMT_Y212: return MKTAG('Y', '2', '1', '6');
+ case AV_PIX_FMT_Y216: return MKTAG('Y', '2', '1', '6');
+ case AV_PIX_FMT_VUYX: return MKTAG('A', 'Y', 'U', 'V');
+ case AV_PIX_FMT_XV30: return MKTAG('Y', '4', '1', '0');
+ case AV_PIX_FMT_XV36: return MKTAG('Y', '4', '1', '6');
+ case AV_PIX_FMT_XV48: return MKTAG('Y', '4', '1', '6');
+ default: return D3DFMT_UNKNOWN;
+ }
+}
+
static int dxva2_create_decoder(AVCodecContext *avctx)
{
FFDXVASharedContext *sctx = DXVA_SHARED_CONTEXT(avctx);
GUID *guid_list;
unsigned guid_count;
GUID device_guid;
- D3DFORMAT surface_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
- MKTAG('P', '0', '1', '0') : MKTAG('N', 'V', '1', '2');
DXVA2_VideoDesc desc = { 0 };
DXVA2_ConfigPictureDecode config;
HRESULT hr;
@@ -356,6 +407,7 @@ static int dxva2_create_decoder(AVCodecContext *avctx)
AVHWFramesContext *frames_ctx = (AVHWFramesContext*)avctx->hw_frames_ctx->data;
AVDXVA2FramesContext *frames_hwctx = frames_ctx->hwctx;
AVDXVA2DeviceContext *device_hwctx = frames_ctx->device_ctx->hwctx;
+ D3DFORMAT surface_format = dxva2_map_sw_to_hw_format(frames_ctx->sw_format);
hr = IDirect3DDeviceManager9_OpenDeviceHandle(device_hwctx->devmgr,
&device_handle);
@@ -459,6 +511,16 @@ static DXGI_FORMAT d3d11va_map_sw_to_hw_format(enum AVPixelFormat pix_fmt)
case AV_PIX_FMT_NV12: return DXGI_FORMAT_NV12;
case AV_PIX_FMT_P010: return DXGI_FORMAT_P010;
case AV_PIX_FMT_YUV420P: return DXGI_FORMAT_420_OPAQUE;
+ case AV_PIX_FMT_VUYX: return DXGI_FORMAT_AYUV;
+ case AV_PIX_FMT_YUYV422: return DXGI_FORMAT_YUY2;
+ case AV_PIX_FMT_Y210: return DXGI_FORMAT_Y210;
+ case AV_PIX_FMT_XV30: return DXGI_FORMAT_Y410;
+ case AV_PIX_FMT_P012: return DXGI_FORMAT_P016;
+ case AV_PIX_FMT_P016: return DXGI_FORMAT_P016;
+ case AV_PIX_FMT_Y212: return DXGI_FORMAT_Y216;
+ case AV_PIX_FMT_Y216: return DXGI_FORMAT_Y216;
+ case AV_PIX_FMT_XV36: return DXGI_FORMAT_Y416;
+ case AV_PIX_FMT_XV48: return DXGI_FORMAT_Y416;
default: return DXGI_FORMAT_UNKNOWN;
}
}
@@ -627,8 +689,7 @@ int ff_dxva2_common_frame_params(AVCodecContext *avctx,
else
num_surfaces += 2;
- frames_ctx->sw_format = avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
- AV_PIX_FMT_P010 : AV_PIX_FMT_NV12;
+ frames_ctx->sw_format = dxva_map_sw_to_hw_frames_format(avctx->sw_pix_fmt);
frames_ctx->width = FFALIGN(avctx->coded_width, surface_alignment);
frames_ctx->height = FFALIGN(avctx->coded_height, surface_alignment);
frames_ctx->initial_pool_size = num_surfaces;
@@ -28,11 +28,15 @@
#include "hevc/data.h"
#include "hevc/hevcdec.h"
#include "hwaccel_internal.h"
+#include "h265_profile_level.h"
#define MAX_SLICES 256
struct hevc_dxva2_picture_context {
- DXVA_PicParams_HEVC pp;
+ union {
+ DXVA_PicParams_HEVC pp;
+ ff_DXVA_PicParams_HEVC_RangeExt ppext;
+ };
DXVA_Qmatrix_HEVC qm;
unsigned slice_count;
DXVA_Slice_HEVC_Short slice_short[MAX_SLICES];
@@ -57,9 +61,82 @@ static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index)
return 0xff;
}
+static int ptl_convert(const PTLCommon *general_ptl, H265RawProfileTierLevel *h265_raw_ptl)
+{
+ h265_raw_ptl->general_profile_space = general_ptl->profile_space;
+ h265_raw_ptl->general_tier_flag = general_ptl->tier_flag;
+ h265_raw_ptl->general_profile_idc = general_ptl->profile_idc;
+
+ memcpy(h265_raw_ptl->general_profile_compatibility_flag,
+ general_ptl->profile_compatibility_flag, 32 * sizeof(uint8_t));
+
+#define copy_field(name) h265_raw_ptl->general_ ## name = general_ptl->name
+ copy_field(progressive_source_flag);
+ copy_field(interlaced_source_flag);
+ copy_field(non_packed_constraint_flag);
+ copy_field(frame_only_constraint_flag);
+ copy_field(max_12bit_constraint_flag);
+ copy_field(max_10bit_constraint_flag);
+ copy_field(max_8bit_constraint_flag);
+ copy_field(max_422chroma_constraint_flag);
+ copy_field(max_420chroma_constraint_flag);
+ copy_field(max_monochrome_constraint_flag);
+ copy_field(intra_constraint_flag);
+ copy_field(one_picture_only_constraint_flag);
+ copy_field(lower_bit_rate_constraint_flag);
+ copy_field(max_14bit_constraint_flag);
+ copy_field(inbld_flag);
+ copy_field(level_idc);
+#undef copy_field
+
+ return 0;
+}
+
+const GUID *ff_dxva2_hevc_parse_rext_profile(AVCodecContext *avctx)
+{
+ const HEVCContext *h = avctx->priv_data;
+ const HEVCSPS *sps = h->pps->sps;
+ const PTL *ptl = &sps->ptl;
+ const PTLCommon *general_ptl = &ptl->general_ptl;
+ const H265ProfileDescriptor *profile;
+ H265RawProfileTierLevel h265_raw_ptl = {0};
+
+ /* convert PTLCommon to H265RawProfileTierLevel */
+ ptl_convert(general_ptl, &h265_raw_ptl);
+
+ profile = ff_h265_get_profile(&h265_raw_ptl);
+ if (!profile) {
+ av_log(avctx, AV_LOG_ERROR, "HEVC profile is not found.\n");
+ return &ff_GUID_NULL;
+ }
+
+ if (!strcmp(profile->name, "Main 12") ||
+ !strcmp(profile->name, "Main 12 Intra"))
+ return &ff_DXVA2_ModeHEVC_VLD_Main12;
+ else if (!strcmp(profile->name, "Main 4:2:2 10") ||
+ !strcmp(profile->name, "Main 4:2:2 10 Intra"))
+ return &ff_DXVA2_ModeHEVC_VLD_Main10_422;
+ else if (!strcmp(profile->name, "Main 4:2:2 12") ||
+ !strcmp(profile->name, "Main 4:2:2 12 Intra"))
+ return &ff_DXVA2_ModeHEVC_VLD_Main12_422;
+ else if (!strcmp(profile->name, "Main 4:4:4") ||
+ !strcmp(profile->name, "Main 4:4:4 Intra"))
+ return &ff_DXVA2_ModeHEVC_VLD_Main_444;
+ else if (!strcmp(profile->name, "Main 4:4:4 10") ||
+ !strcmp(profile->name, "Main 4:4:4 10 Intra"))
+ return &ff_DXVA2_ModeHEVC_VLD_Main10_444;
+ else if (!strcmp(profile->name, "Main 4:4:4 12") ||
+ !strcmp(profile->name, "Main 4:4:4 12 Intra"))
+ return &ff_DXVA2_ModeHEVC_VLD_Main12_444;
+
+ av_log(avctx, AV_LOG_ERROR, "Unsupported HEVC RExt profile: %s\n", profile->name);
+ return &ff_GUID_NULL;
+}
+
void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx,
- DXVA_PicParams_HEVC *pp)
+ ff_DXVA_PicParams_HEVC_RangeExt *ppext)
{
+ DXVA_PicParams_HEVC *pp = &ppext->params;
const HEVCContext *h = avctx->priv_data;
const HEVCLayerContext *l = &h->layers[h->cur_layer];
const HEVCFrame *current_picture = h->cur_frame;
@@ -67,7 +144,7 @@ void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
const HEVCSPS *sps = pps->sps;
int i, j;
- memset(pp, 0, sizeof(*pp));
+ memset(ppext, 0, sizeof(*ppext));
pp->PicWidthInMinCbsY = sps->min_cb_width;
pp->PicHeightInMinCbsY = sps->min_cb_height;
@@ -200,6 +277,32 @@ void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
DO_REF_LIST(LT_CURR, RefPicSetLtCurr);
pp->StatusReportFeedbackNumber = 1 + DXVA_CONTEXT_REPORT_ID(avctx, ctx)++;
+
+ if (sps->range_extension) {
+ ppext->transform_skip_rotation_enabled_flag = sps->transform_skip_rotation_enabled;
+ ppext->transform_skip_context_enabled_flag = sps->transform_skip_context_enabled;
+ ppext->implicit_rdpcm_enabled_flag = sps->implicit_rdpcm_enabled;
+ ppext->explicit_rdpcm_enabled_flag = sps->explicit_rdpcm_enabled;
+ ppext->extended_precision_processing_flag = sps->extended_precision_processing;
+ ppext->intra_smoothing_disabled_flag = sps->intra_smoothing_disabled;
+ ppext->persistent_rice_adaptation_enabled_flag = sps->persistent_rice_adaptation_enabled;
+ ppext->high_precision_offsets_enabled_flag = sps->high_precision_offsets_enabled;
+ ppext->cabac_bypass_alignment_enabled_flag = sps->cabac_bypass_alignment_enabled;
+ }
+ if (pps->pps_range_extensions_flag) {
+ ppext->cross_component_prediction_enabled_flag = pps->cross_component_prediction_enabled_flag;
+ ppext->chroma_qp_offset_list_enabled_flag = pps->chroma_qp_offset_list_enabled_flag;
+
+ ppext->diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth;
+ ppext->log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma;
+ ppext->log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma;
+ ppext->log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2;
+ ppext->chroma_qp_offset_list_len_minus1 = pps->chroma_qp_offset_list_len_minus1;
+ for (i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) {
+ ppext->cb_qp_offset_list[i] = pps->cb_qp_offset_list[i];
+ ppext->cr_qp_offset_list[i] = pps->cr_qp_offset_list[i];
+ }
+ }
}
void ff_dxva2_hevc_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_HEVC *qm)
@@ -375,7 +478,7 @@ static int dxva2_hevc_start_frame(AVCodecContext *avctx,
av_assert0(ctx_pic);
/* Fill up DXVA_PicParams_HEVC */
- ff_dxva2_hevc_fill_picture_parameters(avctx, ctx, &ctx_pic->pp);
+ ff_dxva2_hevc_fill_picture_parameters(avctx, ctx, &ctx_pic->ppext);
/* Fill up DXVA_Qmatrix_HEVC */
ff_dxva2_hevc_fill_scaling_lists(avctx, ctx, &ctx_pic->qm);
@@ -414,13 +517,15 @@ static int dxva2_hevc_end_frame(AVCodecContext *avctx)
HEVCContext *h = avctx->priv_data;
struct hevc_dxva2_picture_context *ctx_pic = h->cur_frame->hwaccel_picture_private;
int scale = ctx_pic->pp.dwCodingParamToolFlags & 1;
+ int rext = avctx->profile == AV_PROFILE_HEVC_REXT;
int ret;
if (ctx_pic->slice_count <= 0 || ctx_pic->bitstream_size <= 0)
return -1;
ret = ff_dxva2_common_end_frame(avctx, h->cur_frame->f,
- &ctx_pic->pp, sizeof(ctx_pic->pp),
+ &ctx_pic->pp,
+ rext ? sizeof(ctx_pic->ppext) : sizeof(ctx_pic->pp),
scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0,
commit_bitstream_and_slice_buffer);
return ret;
@@ -69,6 +69,49 @@
#include "avcodec.h"
#include "internal.h"
+DEFINE_GUID(ff_GUID_NULL, 0x00000000, 0x0000,0x0000,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main12, 0x1a72925f, 0x0c2c,0x4f15,0x96,0xfb,0xb1,0x7d,0x14,0x73,0x60,0x3f);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10_422, 0x0bac4fe5, 0x1532,0x4429,0xa8,0x54,0xf8,0x4d,0xe0,0x49,0x53,0xdb);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main12_422, 0x55bcac81, 0xf311,0x4093,0xa7,0xd0,0x1c,0xbc,0x0b,0x84,0x9b,0xee);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main_444, 0x4008018f, 0xf537,0x4b36,0x98,0xcf,0x61,0xaf,0x8a,0x2c,0x1a,0x33);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main10_444, 0x0dabeffa, 0x4458,0x4602,0xbc,0x03,0x07,0x95,0x65,0x9d,0x61,0x7c);
+DEFINE_GUID(ff_DXVA2_ModeHEVC_VLD_Main12_444, 0x9798634d, 0xfe9d,0x48e5,0xb4,0xda,0xdb,0xec,0x45,0xb3,0xdf,0x01);
+
+/* This is only defined starting in the Windows 11 24H2 SDK */
+#pragma pack(push,1)
+typedef struct ff_DXVA_PicParams_HEVC_RangeExt {
+ DXVA_PicParams_HEVC params;
+
+ union {
+ struct {
+ USHORT transform_skip_rotation_enabled_flag : 1;
+ USHORT transform_skip_context_enabled_flag : 1;
+ USHORT implicit_rdpcm_enabled_flag : 1;
+ USHORT explicit_rdpcm_enabled_flag : 1;
+ USHORT extended_precision_processing_flag : 1;
+ USHORT intra_smoothing_disabled_flag : 1;
+ USHORT persistent_rice_adaptation_enabled_flag : 1;
+ USHORT high_precision_offsets_enabled_flag : 1;
+ USHORT cabac_bypass_alignment_enabled_flag : 1;
+ USHORT cross_component_prediction_enabled_flag : 1;
+ USHORT chroma_qp_offset_list_enabled_flag : 1;
+ USHORT ReservedBits8 : 5;
+ };
+ USHORT dwRangeExtensionFlags;
+ };
+
+ UCHAR diff_cu_chroma_qp_offset_depth;
+ UCHAR log2_sao_offset_scale_luma;
+ UCHAR log2_sao_offset_scale_chroma;
+ UCHAR log2_max_transform_skip_block_size_minus2;
+ CHAR cb_qp_offset_list[6];
+ CHAR cr_qp_offset_list[6];
+ UCHAR chroma_qp_offset_list_len_minus1;
+ USHORT ReservedBits9;
+
+} ff_DXVA_PicParams_HEVC_RangeExt;
+#pragma pack(pop)
+
typedef void DECODER_BUFFER_DESC;
typedef union {
@@ -172,9 +215,11 @@ void ff_dxva2_h264_fill_picture_parameters(const AVCodecContext *avctx, AVDXVACo
void ff_dxva2_h264_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_H264 *qm);
#if CONFIG_HEVC_D3D12VA_HWACCEL || CONFIG_HEVC_D3D11VA_HWACCEL || CONFIG_HEVC_D3D11VA2_HWACCEL || CONFIG_HEVC_DXVA2_HWACCEL
-void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_PicParams_HEVC *pp);
+void ff_dxva2_hevc_fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, ff_DXVA_PicParams_HEVC_RangeExt *ppext);
void ff_dxva2_hevc_fill_scaling_lists(const AVCodecContext *avctx, AVDXVAContext *ctx, DXVA_Qmatrix_HEVC *qm);
+
+const GUID *ff_dxva2_hevc_parse_rext_profile(AVCodecContext *avctx);
#endif
#if CONFIG_VP9_D3D12VA_HWACCEL || CONFIG_VP9_D3D11VA_HWACCEL || CONFIG_VP9_D3D11VA2_HWACCEL || CONFIG_VP9_DXVA2_HWACCEL
@@ -592,6 +592,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
break;
case AV_PIX_FMT_YUV444P:
+#if CONFIG_HEVC_DXVA2_HWACCEL
+ *fmt++ = AV_PIX_FMT_DXVA2_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+ *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+ *fmt++ = AV_PIX_FMT_D3D11;
+#endif
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
@@ -610,6 +617,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
break;
case AV_PIX_FMT_YUV422P:
case AV_PIX_FMT_YUV422P10LE:
+#if CONFIG_HEVC_DXVA2_HWACCEL
+ *fmt++ = AV_PIX_FMT_DXVA2_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+ *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+ *fmt++ = AV_PIX_FMT_D3D11;
+#endif
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
@@ -627,6 +641,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
/* NOTE: fallthrough */
case AV_PIX_FMT_YUV420P12:
case AV_PIX_FMT_YUV444P12:
+#if CONFIG_HEVC_DXVA2_HWACCEL
+ *fmt++ = AV_PIX_FMT_DXVA2_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+ *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+ *fmt++ = AV_PIX_FMT_D3D11;
+#endif
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif
@@ -641,6 +662,13 @@ static enum AVPixelFormat get_format(HEVCContext *s, const HEVCSPS *sps)
#endif
break;
case AV_PIX_FMT_YUV422P12:
+#if CONFIG_HEVC_DXVA2_HWACCEL
+ *fmt++ = AV_PIX_FMT_DXVA2_VLD;
+#endif
+#if CONFIG_HEVC_D3D11VA_HWACCEL
+ *fmt++ = AV_PIX_FMT_D3D11VA_VLD;
+ *fmt++ = AV_PIX_FMT_D3D11;
+#endif
#if CONFIG_HEVC_VAAPI_HWACCEL
*fmt++ = AV_PIX_FMT_VAAPI;
#endif