Message ID | 20200313102354.2500-1-robux4@ycbcr.xyz |
---|---|
State | New |
Headers | show |
Series | [FFmpeg-devel,1/3] avcodec/dxva2_hevc: add support for parsing HEVC Range Extension data | expand |
Context | Check | Description |
---|---|---|
andriy/ffmpeg-patchwork | success | Make fate finished |
On Fri, Mar 13, 2020 at 11:25 AM Steve Lhomme <robux4@ycbcr.xyz> wrote: > > Mimick the existing structure and add the extra fields from the Range Extension > in a wrapping structure. > > The FF_DXVA2_WORKAROUND_HEVC_REXT is set by the decoder user to signal the > selected decoder is expecting this extended structure rather than the default > one. > --- > libavcodec/d3d11va.h | 1 + > libavcodec/dxva2.h | 1 + > libavcodec/dxva2_hevc.c | 79 ++++++++++++++++++++++++++++++++++++++--- > 3 files changed, 76 insertions(+), 5 deletions(-) > > diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h > index 6816b6c1e6..68a69c372d 100644 > --- a/libavcodec/d3d11va.h > +++ b/libavcodec/d3d11va.h > @@ -47,6 +47,7 @@ > > #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards > #define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface > +#define FF_DXVA2_WORKAROUND_HEVC_REXT 4 ///< Signal the D3D11VA decoder is using the HEVC Rext picture structure > > /** > * This structure is used to provides the necessary configurations and data > diff --git a/libavcodec/dxva2.h b/libavcodec/dxva2.h > index 22c93992f2..024999239d 100644 > --- a/libavcodec/dxva2.h > +++ b/libavcodec/dxva2.h > @@ -47,6 +47,7 @@ > > #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards > #define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface > +#define FF_DXVA2_WORKAROUND_HEVC_REXT 4 ///< Signal the DXVA2 decoder is using the HEVC Rext picture structure > > /** > * This structure is used to provides the necessary configurations and data > diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c > index dbb701fb1c..98b3e74bd7 100644 > --- a/libavcodec/dxva2_hevc.c > +++ b/libavcodec/dxva2_hevc.c > @@ -26,10 +26,47 @@ > #include "hevc_data.h" > #include "hevcdec.h" > > +#pragma pack(push, 1) > +typedef struct > +{ > + DXVA_PicParams_HEVC main; > + > + // HEVC Range Extension > + __C89_NAMELESS union { > + __C89_NAMELESS struct { > + UINT32 transform_skip_rotation_enabled_flag : 1; > + UINT32 transform_skip_context_enabled_flag : 1; > + UINT32 implicit_rdpcm_enabled_flag : 1; > + UINT32 explicit_rdpcm_enabled_flag : 1; > + UINT32 extended_precision_processing_flag : 1; > + UINT32 intra_smoothing_disabled_flag : 1; > + UINT32 high_precision_offsets_enabled_flag : 1; > + UINT32 persistent_rice_adaptation_enabled_flag : 1; > + UINT32 cabac_bypass_alignment_enabled_flag : 1; > + UINT32 cross_component_prediction_enabled_flag : 1; > + UINT32 chroma_qp_offset_list_enabled_flag : 1; > + UINT32 BitDepthLuma16 : 1; // TODO merge in ReservedBits5 if not needed > + UINT32 BitDepthChroma16 : 1; // TODO merge in ReservedBits5 if not needed > + UINT32 ReservedBits8 : 19; > + }; > + UINT32 dwRangeExtensionFlags; > + }; > + > + UCHAR diff_cu_chroma_qp_offset_depth; > + UCHAR chroma_qp_offset_list_len_minus1; > + 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]; > + > +} DXVA_PicParams_HEVC_Rext; > +#pragma pack(pop) > + Where is this struct specified? I don't see it in the latest released Windows SDK. - Hendrik
> On March 13, 2020 3:46 PM Hendrik Leppkes <h.leppkes@gmail.com> wrote: > > > On Fri, Mar 13, 2020 at 11:25 AM Steve Lhomme <robux4@ycbcr.xyz> wrote: > > > > Mimick the existing structure and add the extra fields from the Range Extension > > in a wrapping structure. > > > > The FF_DXVA2_WORKAROUND_HEVC_REXT is set by the decoder user to signal the > > selected decoder is expecting this extended structure rather than the default > > one. > > --- > > libavcodec/d3d11va.h | 1 + > > libavcodec/dxva2.h | 1 + > > libavcodec/dxva2_hevc.c | 79 ++++++++++++++++++++++++++++++++++++++--- > > 3 files changed, 76 insertions(+), 5 deletions(-) > > > > diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h > > index 6816b6c1e6..68a69c372d 100644 > > --- a/libavcodec/d3d11va.h > > +++ b/libavcodec/d3d11va.h > > @@ -47,6 +47,7 @@ > > > > #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards > > #define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface > > +#define FF_DXVA2_WORKAROUND_HEVC_REXT 4 ///< Signal the D3D11VA decoder is using the HEVC Rext picture structure > > > > /** > > * This structure is used to provides the necessary configurations and data > > diff --git a/libavcodec/dxva2.h b/libavcodec/dxva2.h > > index 22c93992f2..024999239d 100644 > > --- a/libavcodec/dxva2.h > > +++ b/libavcodec/dxva2.h > > @@ -47,6 +47,7 @@ > > > > #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards > > #define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface > > +#define FF_DXVA2_WORKAROUND_HEVC_REXT 4 ///< Signal the DXVA2 decoder is using the HEVC Rext picture structure > > > > /** > > * This structure is used to provides the necessary configurations and data > > diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c > > index dbb701fb1c..98b3e74bd7 100644 > > --- a/libavcodec/dxva2_hevc.c > > +++ b/libavcodec/dxva2_hevc.c > > @@ -26,10 +26,47 @@ > > #include "hevc_data.h" > > #include "hevcdec.h" > > > > +#pragma pack(push, 1) > > +typedef struct > > +{ > > + DXVA_PicParams_HEVC main; > > + > > + // HEVC Range Extension > > + __C89_NAMELESS union { > > + __C89_NAMELESS struct { > > + UINT32 transform_skip_rotation_enabled_flag : 1; > > + UINT32 transform_skip_context_enabled_flag : 1; > > + UINT32 implicit_rdpcm_enabled_flag : 1; > > + UINT32 explicit_rdpcm_enabled_flag : 1; > > + UINT32 extended_precision_processing_flag : 1; > > + UINT32 intra_smoothing_disabled_flag : 1; > > + UINT32 high_precision_offsets_enabled_flag : 1; > > + UINT32 persistent_rice_adaptation_enabled_flag : 1; > > + UINT32 cabac_bypass_alignment_enabled_flag : 1; > > + UINT32 cross_component_prediction_enabled_flag : 1; > > + UINT32 chroma_qp_offset_list_enabled_flag : 1; > > + UINT32 BitDepthLuma16 : 1; // TODO merge in ReservedBits5 if not needed > > + UINT32 BitDepthChroma16 : 1; // TODO merge in ReservedBits5 if not needed > > + UINT32 ReservedBits8 : 19; > > + }; > > + UINT32 dwRangeExtensionFlags; > > + }; > > + > > + UCHAR diff_cu_chroma_qp_offset_depth; > > + UCHAR chroma_qp_offset_list_len_minus1; > > + 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]; > > + > > +} DXVA_PicParams_HEVC_Rext; > > +#pragma pack(pop) > > + > > Where is this struct specified? I don't see it in the latest released > Windows SDK. It is not. It is reversed engineered from the existing structure and wild guessing based on the HEVC Range Extension specs. The bits/fields are in the same order as the specs. Then I tested some GUIDs that output non 4:2:0 pixel formats on an Intel GPU that is known to decoder HEVC Range Extension. Apparently NVIDIA doesn't provide DXVA GUIDs that output non 4:2:0 pixel formats on GPUs that supposedly decode HEVC 444 (likley nvdec only). AMD doesn't have such GPUs AFAIK. So for now it's Intel only.
On Sun, Mar 15, 2020 at 8:12 AM Steve Lhomme <robux4@ycbcr.xyz> wrote: > > Where is this struct specified? I don't see it in the latest released > > Windows SDK. > > It is not. It is reversed engineered from the existing structure and wild guessing based on the HEVC Range Extension specs. The bits/fields are in the same order as the specs. Then I tested some GUIDs that output non 4:2:0 pixel formats on an Intel GPU that is known to decoder HEVC Range Extension. > > Apparently NVIDIA doesn't provide DXVA GUIDs that output non 4:2:0 pixel formats on GPUs that supposedly decode HEVC 444 (likley nvdec only). AMD doesn't have such GPUs AFAIK. > > So for now it's Intel only. That seems very hackish for something thats otherwise cleanly based on official specifications only. Maybe try to get them to release specs for this instead? - Hendrik
On 2020-03-15 13:05, Hendrik Leppkes wrote: > On Sun, Mar 15, 2020 at 8:12 AM Steve Lhomme <robux4@ycbcr.xyz> wrote: >>> Where is this struct specified? I don't see it in the latest released >>> Windows SDK. >> >> It is not. It is reversed engineered from the existing structure and wild guessing based on the HEVC Range Extension specs. The bits/fields are in the same order as the specs. Then I tested some GUIDs that output non 4:2:0 pixel formats on an Intel GPU that is known to decoder HEVC Range Extension. >> >> Apparently NVIDIA doesn't provide DXVA GUIDs that output non 4:2:0 pixel formats on GPUs that supposedly decode HEVC 444 (likley nvdec only). AMD doesn't have such GPUs AFAIK. >> >> So for now it's Intel only. > > That seems very hackish for something thats otherwise cleanly based on > official specifications only. Maybe try to get them to release specs > for this instead? From what I understand only MS publishes DXVA specs and it seems they have no intention on doing one for HEVC Range Extension. That may be why NVIDIA has not implemented it. I don't know if Intel is planning to release a documentation.
diff --git a/libavcodec/d3d11va.h b/libavcodec/d3d11va.h index 6816b6c1e6..68a69c372d 100644 --- a/libavcodec/d3d11va.h +++ b/libavcodec/d3d11va.h @@ -47,6 +47,7 @@ #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for Direct3D11 and old UVD/UVD+ ATI video cards #define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for Direct3D11 and old Intel GPUs with ClearVideo interface +#define FF_DXVA2_WORKAROUND_HEVC_REXT 4 ///< Signal the D3D11VA decoder is using the HEVC Rext picture structure /** * This structure is used to provides the necessary configurations and data diff --git a/libavcodec/dxva2.h b/libavcodec/dxva2.h index 22c93992f2..024999239d 100644 --- a/libavcodec/dxva2.h +++ b/libavcodec/dxva2.h @@ -47,6 +47,7 @@ #define FF_DXVA2_WORKAROUND_SCALING_LIST_ZIGZAG 1 ///< Work around for DXVA2 and old UVD/UVD+ ATI video cards #define FF_DXVA2_WORKAROUND_INTEL_CLEARVIDEO 2 ///< Work around for DXVA2 and old Intel GPUs with ClearVideo interface +#define FF_DXVA2_WORKAROUND_HEVC_REXT 4 ///< Signal the DXVA2 decoder is using the HEVC Rext picture structure /** * This structure is used to provides the necessary configurations and data diff --git a/libavcodec/dxva2_hevc.c b/libavcodec/dxva2_hevc.c index dbb701fb1c..98b3e74bd7 100644 --- a/libavcodec/dxva2_hevc.c +++ b/libavcodec/dxva2_hevc.c @@ -26,10 +26,47 @@ #include "hevc_data.h" #include "hevcdec.h" +#pragma pack(push, 1) +typedef struct +{ + DXVA_PicParams_HEVC main; + + // HEVC Range Extension + __C89_NAMELESS union { + __C89_NAMELESS struct { + UINT32 transform_skip_rotation_enabled_flag : 1; + UINT32 transform_skip_context_enabled_flag : 1; + UINT32 implicit_rdpcm_enabled_flag : 1; + UINT32 explicit_rdpcm_enabled_flag : 1; + UINT32 extended_precision_processing_flag : 1; + UINT32 intra_smoothing_disabled_flag : 1; + UINT32 high_precision_offsets_enabled_flag : 1; + UINT32 persistent_rice_adaptation_enabled_flag : 1; + UINT32 cabac_bypass_alignment_enabled_flag : 1; + UINT32 cross_component_prediction_enabled_flag : 1; + UINT32 chroma_qp_offset_list_enabled_flag : 1; + UINT32 BitDepthLuma16 : 1; // TODO merge in ReservedBits5 if not needed + UINT32 BitDepthChroma16 : 1; // TODO merge in ReservedBits5 if not needed + UINT32 ReservedBits8 : 19; + }; + UINT32 dwRangeExtensionFlags; + }; + + UCHAR diff_cu_chroma_qp_offset_depth; + UCHAR chroma_qp_offset_list_len_minus1; + 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]; + +} DXVA_PicParams_HEVC_Rext; +#pragma pack(pop) + #define MAX_SLICES 256 struct hevc_dxva2_picture_context { - DXVA_PicParams_HEVC pp; + DXVA_PicParams_HEVC_Rext pp; DXVA_Qmatrix_HEVC qm; unsigned slice_count; DXVA_Slice_HEVC_Short slice_short[MAX_SLICES]; @@ -55,18 +92,48 @@ static int get_refpic_index(const DXVA_PicParams_HEVC *pp, int surface_index) } static void fill_picture_parameters(const AVCodecContext *avctx, AVDXVAContext *ctx, const HEVCContext *h, - DXVA_PicParams_HEVC *pp) + DXVA_PicParams_HEVC_Rext *ppext) { const HEVCFrame *current_picture = h->ref; const HEVCSPS *sps = h->ps.sps; const HEVCPPS *pps = h->ps.pps; int i, j; + DXVA_PicParams_HEVC *pp = &ppext->main; - memset(pp, 0, sizeof(*pp)); + memset(ppext, 0, sizeof(*ppext)); pp->PicWidthInMinCbsY = sps->min_cb_width; pp->PicHeightInMinCbsY = sps->min_cb_height; + if (sps->sps_range_extension_flag) { + ppext->dwRangeExtensionFlags |= (sps->transform_skip_rotation_enabled_flag << 0) | + (sps->transform_skip_context_enabled_flag << 1) | + (sps->implicit_rdpcm_enabled_flag << 2) | + (sps->explicit_rdpcm_enabled_flag << 3) | + (sps->extended_precision_processing_flag << 4) | + (sps->intra_smoothing_disabled_flag << 5) | + (sps->high_precision_offsets_enabled_flag << 5) | + (sps->persistent_rice_adaptation_enabled_flag << 7) | + (sps->cabac_bypass_alignment_enabled_flag << 8); + } + if (pps->pps_range_extensions_flag) { + ppext->dwRangeExtensionFlags |= (pps->cross_component_prediction_enabled_flag << 9) | + (pps->chroma_qp_offset_list_enabled_flag << 10); + if (pps->chroma_qp_offset_list_enabled_flag) { + ppext->diff_cu_chroma_qp_offset_depth = pps->diff_cu_chroma_qp_offset_depth; + 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]; + } + } + ppext->log2_sao_offset_scale_luma = pps->log2_sao_offset_scale_luma; + ppext->log2_sao_offset_scale_chroma = pps->log2_sao_offset_scale_chroma; + if (pps->transform_skip_enabled_flag) { + ppext->log2_max_transform_skip_block_size_minus2 = pps->log2_max_transform_skip_block_size - 2; + } + } + pp->wFormatAndSequenceInfoFlags = (sps->chroma_format_idc << 0) | (sps->separate_colour_plane_flag << 2) | ((sps->bit_depth - 8) << 3) | @@ -402,16 +469,18 @@ static int dxva2_hevc_decode_slice(AVCodecContext *avctx, static int dxva2_hevc_end_frame(AVCodecContext *avctx) { + AVDXVAContext *ctx = DXVA_CONTEXT(avctx); HEVCContext *h = avctx->priv_data; struct hevc_dxva2_picture_context *ctx_pic = h->ref->hwaccel_picture_private; - int scale = ctx_pic->pp.dwCodingParamToolFlags & 1; + int scale = ctx_pic->pp.main.dwCodingParamToolFlags & 1; + int rext = (DXVA_CONTEXT_WORKAROUND(avctx, ctx) & FF_DXVA2_WORKAROUND_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->ref->frame, - &ctx_pic->pp, sizeof(ctx_pic->pp), + &ctx_pic->pp, rext ? sizeof(ctx_pic->pp) : sizeof(ctx_pic->pp.main), scale ? &ctx_pic->qm : NULL, scale ? sizeof(ctx_pic->qm) : 0, commit_bitstream_and_slice_buffer); return ret;