[FFmpeg-devel] [PATCH v2] avcodec/dxva2: add support for HEVC RExt DXVA profiles

Steve Lhomme robux4 at ycbcr.xyz
Thu Nov 14 11:57:07 EET 2024


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 at 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 at ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request at ffmpeg.org with subject "unsubscribe".



More information about the ffmpeg-devel mailing list