avcodec/d3d12va_encode: D3D12 AV1 encoding support

Implement AV1 hardware encoding
using Direct3D 12 Video API (D3D12VA).
This commit is contained in:
Araz Iusubov
2025-11-10 17:23:25 +01:00
committed by Tong Wu
parent 81362b319e
commit 92f2f9ea5c
7 changed files with 1241 additions and 5 deletions
+1
View File
@@ -10,6 +10,7 @@ version <next>:
- D3D12 H.264 encoder
- drawvg filter via libcairo
- ffmpeg CLI tiled HEIF support
- D3D12 AV1 encoder
version 8.0:
Vendored
+3
View File
@@ -3444,6 +3444,8 @@ amrwb_mediacodec_decoder_select="amr_parser"
av1_amf_encoder_deps="amf"
av1_amf_decoder_deps="amf"
av1_cuvid_decoder_deps="cuvid CUVIDAV1PICPARAMS"
av1_d3d12va_encoder_deps="d3d12va d3d12va_av1_headers"
av1_d3d12va_encoder_select="cbs_av1 d3d12va_encode"
av1_mediacodec_decoder_deps="mediacodec"
av1_mediacodec_encoder_deps="mediacodec"
av1_mediacodec_encoder_select="extract_extradata_bsf"
@@ -6958,6 +6960,7 @@ check_type "windows.h d3d12video.h" "ID3D12VideoDecoder"
check_type "windows.h d3d12video.h" "ID3D12VideoEncoder"
test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_VIDEO feature = D3D12_FEATURE_VIDEO_ENCODER_CODEC" && \
test_code cc "windows.h d3d12video.h" "D3D12_FEATURE_DATA_VIDEO_ENCODER_RESOURCE_REQUIREMENTS req" && enable d3d12_encoder_feature
test_code cc "windows.h d3d12video.h" "D3D12_VIDEO_ENCODER_CODEC c = D3D12_VIDEO_ENCODER_CODEC_AV1; (void)c;" && enable d3d12va_av1_headers
check_type "windows.h" "DPI_AWARENESS_CONTEXT" -D_WIN32_WINNT=0x0A00
check_type "windows.h security.h schnlsp.h" SecPkgContext_KeyingMaterialInfo -DSECURITY_WIN32
check_type "d3d9.h dxva2api.h" DXVA2_ConfigPictureDecode -D_WIN32_WINNT=0x0602
+1
View File
@@ -274,6 +274,7 @@ OBJS-$(CONFIG_AURA_DECODER) += cyuv.o
OBJS-$(CONFIG_AURA2_DECODER) += aura.o
OBJS-$(CONFIG_AV1_DECODER) += av1dec.o av1_parse.o
OBJS-$(CONFIG_AV1_CUVID_DECODER) += cuviddec.o
OBJS-$(CONFIG_AV1_D3D12VA_ENCODER) += d3d12va_encode_av1.o av1_levels.o
OBJS-$(CONFIG_AV1_MEDIACODEC_DECODER) += mediacodecdec.o
OBJS-$(CONFIG_AV1_MEDIACODEC_ENCODER) += mediacodecenc.o
OBJS-$(CONFIG_AV1_NVENC_ENCODER) += nvenc_av1.o nvenc.o
+1
View File
@@ -855,6 +855,7 @@ extern const FFCodec ff_libaom_av1_decoder;
/* hwaccel hooks only, so prefer external decoders */
extern const FFCodec ff_av1_decoder;
extern const FFCodec ff_av1_cuvid_decoder;
extern const FFCodec ff_av1_d3d12va_encoder;
extern const FFCodec ff_av1_mediacodec_decoder;
extern const FFCodec ff_av1_mediacodec_encoder;
extern const FFCodec ff_av1_nvenc_encoder;
+40 -5
View File
@@ -29,6 +29,7 @@
#include "libavutil/hwcontext_d3d12va_internal.h"
#include "libavutil/hwcontext_d3d12va.h"
#include "config_components.h"
#include "avcodec.h"
#include "d3d12va_encode.h"
#include "encode.h"
@@ -144,6 +145,12 @@ static int d3d12va_encode_create_metadata_buffers(AVCodecContext *avctx,
{
D3D12VAEncodeContext *ctx = avctx->priv_data;
int width = sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) + sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA);
#if CONFIG_AV1_D3D12VA_ENCODER
if (ctx->codec->d3d12_codec == D3D12_VIDEO_ENCODER_CODEC_AV1) {
width += sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES)
+ sizeof(D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES);
}
#endif
D3D12_HEAP_PROPERTIES encoded_meta_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }, resolved_meta_props;
D3D12_HEAP_TYPE resolved_heap_type = D3D12_HEAP_TYPE_READBACK;
HRESULT hr;
@@ -211,7 +218,7 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
.RateControl = ctx->rc,
.PictureTargetResolution = ctx->resolution,
.SelectedLayoutMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
.FrameSubregionsLayoutData = { 0 },
.FrameSubregionsLayoutData = ctx->subregions_layout,
.CodecGopSequence = ctx->gop,
},
.pInputFrame = pic->input_surface->texture,
@@ -732,16 +739,21 @@ end:
static int d3d12va_encode_output(AVCodecContext *avctx,
FFHWBaseEncodePicture *base_pic, AVPacket *pkt)
{
D3D12VAEncodeContext *ctx = avctx->priv_data;
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
D3D12VAEncodePicture *pic = base_pic->priv;
AVPacket *pkt_ptr = pkt;
int err;
D3D12VAEncodePicture *pic = base_pic->priv;
AVPacket *pkt_ptr = pkt;
int err = 0;
err = d3d12va_encode_wait(avctx, base_pic);
if (err < 0)
return err;
err = d3d12va_encode_get_coded_data(avctx, pic, pkt);
if (ctx->codec->get_coded_data)
err = ctx->codec->get_coded_data(avctx, pic, pkt);
else
err = d3d12va_encode_get_coded_data(avctx, pic, pkt);
if (err < 0)
return err;
@@ -1129,6 +1141,9 @@ static int d3d12va_encode_init_gop_structure(AVCodecContext *avctx)
union {
D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264;
D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevc;
#if CONFIG_AV1_D3D12VA_ENCODER
D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT av1;
#endif
} codec_support;
support.NodeIndex = 0;
@@ -1146,6 +1161,13 @@ static int d3d12va_encode_init_gop_structure(AVCodecContext *avctx)
support.PictureSupport.pHEVCSupport = &codec_support.hevc;
break;
#if CONFIG_AV1_D3D12VA_ENCODER
case D3D12_VIDEO_ENCODER_CODEC_AV1:
memset(&codec_support.av1, 0, sizeof(codec_support.av1));
support.PictureSupport.DataSize = sizeof(codec_support.av1);
support.PictureSupport.pAV1Support = &codec_support.av1;
break;
#endif
default:
av_assert0(0);
}
@@ -1171,6 +1193,13 @@ static int d3d12va_encode_init_gop_structure(AVCodecContext *avctx)
ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
break;
#if CONFIG_AV1_D3D12VA_ENCODER
case D3D12_VIDEO_ENCODER_CODEC_AV1:
ref_l0 = support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
// AV1 doesn't use traditional L1 references like H.264/HEVC
ref_l1 = 0;
break;
#endif
default:
av_assert0(0);
}
@@ -1521,6 +1550,12 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx)
if (err < 0)
goto fail;
if (ctx->codec->set_tile) {
err = ctx->codec->set_tile(avctx);
if (err < 0)
goto fail;
}
err = d3d12va_encode_init_rate_control(avctx);
if (err < 0)
goto fail;
+13
View File
@@ -264,6 +264,8 @@ typedef struct D3D12VAEncodeContext {
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE gop;
D3D12_VIDEO_ENCODER_LEVEL_SETTING level;
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA subregions_layout;
} D3D12VAEncodeContext;
typedef struct D3D12VAEncodeType {
@@ -306,6 +308,11 @@ typedef struct D3D12VAEncodeType {
*/
int (*set_level)(AVCodecContext *avctx);
/**
* Set codec-specific tile setting.
*/
int (*set_tile)(AVCodecContext *avctx);
/**
* The size of any private data structure associated with each
* picture (can be zero if not required).
@@ -327,6 +334,12 @@ typedef struct D3D12VAEncodeType {
*/
int (*write_sequence_header)(AVCodecContext *avctx,
char *data, size_t *data_len);
/**
* Fill the coded data into AVPacket
*/
int (*get_coded_data)(AVCodecContext *avctx,
D3D12VAEncodePicture *pic, AVPacket *pkt);
} D3D12VAEncodeType;
int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt);
File diff suppressed because it is too large Load Diff