The branch, master has been updated
       via  92f2f9ea5c49e94814693861a7e9e47c993fca2e (commit)
      from  81362b319ea7244d8d17110adfa59f10c7e78268 (commit)


- Log -----------------------------------------------------------------
commit 92f2f9ea5c49e94814693861a7e9e47c993fca2e
Author:     Araz Iusubov <[email protected]>
AuthorDate: Mon Nov 10 17:23:25 2025 +0100
Commit:     Tong Wu <[email protected]>
CommitDate: Wed Nov 26 09:58:44 2025 +0000

    avcodec/d3d12va_encode: D3D12 AV1 encoding support
    
    Implement AV1 hardware encoding
    using Direct3D 12 Video API (D3D12VA).

diff --git a/Changelog b/Changelog
index b4c23ac1ee..4648899ca3 100644
--- a/Changelog
+++ b/Changelog
@@ -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:
diff --git a/configure b/configure
index 99734e9d03..7ef50095a3 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 0cd2408865..fba9f0aff0 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -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
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 251ffae390..cce23d1541 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -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;
diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c
index aa8a5982be..d28447c3c9 100644
--- a/libavcodec/d3d12va_encode.c
+++ b/libavcodec/d3d12va_encode.c
@@ -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;
diff --git a/libavcodec/d3d12va_encode.h b/libavcodec/d3d12va_encode.h
index 5bd1eedb7f..b7cfea0582 100644
--- a/libavcodec/d3d12va_encode.h
+++ b/libavcodec/d3d12va_encode.h
@@ -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);
diff --git a/libavcodec/d3d12va_encode_av1.c b/libavcodec/d3d12va_encode_av1.c
new file mode 100644
index 0000000000..e7a115a2ee
--- /dev/null
+++ b/libavcodec/d3d12va_encode_av1.c
@@ -0,0 +1,1182 @@
+/*
+ * Direct3D 12 HW acceleration video encoder
+ *
+ * Copyright (c) 2024 Intel Corporation
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/opt.h"
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
+#include "libavutil/pixdesc.h"
+#include "libavutil/hwcontext_d3d12va_internal.h"
+
+#include "config_components.h"
+#include "avcodec.h"
+#include "cbs.h"
+#include "cbs_av1.h"
+#include "av1_levels.h"
+#include "codec_internal.h"
+#include "d3d12va_encode.h"
+#include "encode.h"
+#include "hw_base_encode.h"
+
+#include <d3d12.h>
+#include <d3d12video.h>
+
+#ifndef D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX
+#define        D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX      ( 0xff )
+#endif
+
+typedef struct D3D12VAHWBaseEncodeAV1 {
+    AV1RawOBU    raw_sequence_header;
+    AV1RawOBU       raw_frame_header;
+    AV1RawOBU         raw_tile_group;
+} D3D12VAHWBaseEncodeAV1;
+
+typedef struct D3D12VAHWBaseEncodeAV1Opts {
+    int                 tier; // 0: Main tier, 1: High tier
+    int                level; // AV1 level (2.0-7.3 map to 0-23)
+
+    int          enable_cdef; // Constrained Directional Enhancement Filter
+    int   enable_restoration; // loop restoration
+    int      enable_superres; // super-resolution
+    int enable_ref_frame_mvs;
+
+    int            enable_jnt_comp;
+    int  enable_128x128_superblock;
+
+    int       enable_warped_motion;
+    int   enable_intra_edge_filter;
+    int enable_interintra_compound;
+    int     enable_masked_compound;
+    int        enable_filter_intra;
+
+    int         enable_loop_filter;
+    int   enable_loop_filter_delta;
+    int         enable_dual_filter;
+
+    int             enable_palette;
+    int    enable_intra_block_copy;
+} D3D12VAHWBaseEncodeAV1Opts;
+
+typedef struct D3D12VAEncodeAV1Picture {
+    uint8_t     temporal_id;
+    uint8_t      spatial_id;
+    uint8_t      show_frame;
+    uint8_t      frame_type;
+    uint16_t last_idr_frame;
+    uint8_t            slot;
+} D3D12VAEncodeAV1Picture;
+
+typedef struct D3D12VAEncodeAV1Context {
+    D3D12VAEncodeContext common;
+    // User options.
+    int      qp;
+    int profile;
+    int   level;
+    int    tier;
+
+    uint8_t q_idx_idr;
+    uint8_t   q_idx_p;
+
+    // Writer structures.
+    D3D12VAHWBaseEncodeAV1         units;
+    D3D12VAHWBaseEncodeAV1Opts unit_opts;
+
+    CodedBitstreamContext              *cbc;
+    CodedBitstreamFragment      current_obu;
+    D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAGS post_encode_values_flag;
+    AVFifo             *picture_header_list;
+} D3D12VAEncodeAV1Context;
+
+typedef struct D3D12VAEncodeAV1Level {
+    uint8_t                              level;
+    D3D12_VIDEO_ENCODER_AV1_LEVELS d3d12_level;
+} D3D12VAEncodeAV1Level;
+
+
+static const D3D12VAEncodeAV1Level av1_levels[] = {
+    { 0,  D3D12_VIDEO_ENCODER_AV1_LEVELS_2_0 },
+    { 1,  D3D12_VIDEO_ENCODER_AV1_LEVELS_2_1 },
+    { 2,  D3D12_VIDEO_ENCODER_AV1_LEVELS_2_2 },
+    { 3,  D3D12_VIDEO_ENCODER_AV1_LEVELS_2_3 },
+    { 4,  D3D12_VIDEO_ENCODER_AV1_LEVELS_3_0 },
+    { 5,  D3D12_VIDEO_ENCODER_AV1_LEVELS_3_1 },
+    { 6,  D3D12_VIDEO_ENCODER_AV1_LEVELS_3_2 },
+    { 7,  D3D12_VIDEO_ENCODER_AV1_LEVELS_3_3 },
+    { 8,  D3D12_VIDEO_ENCODER_AV1_LEVELS_4_0 },
+    { 9,  D3D12_VIDEO_ENCODER_AV1_LEVELS_4_1 },
+    { 10, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_2 },
+    { 11, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_3 },
+    { 12, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_0 },
+    { 13, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_1 },
+    { 14, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2 },
+    { 15, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_3 },
+    { 16, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_0 },
+    { 17, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_1 },
+    { 18, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_2 },
+    { 19, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_3 },
+    { 20, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_0 },
+    { 21, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_1 },
+    { 22, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_2 },
+    { 23, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_3 },
+};
+
+static const D3D12_VIDEO_ENCODER_AV1_PROFILE         profile_main = 
D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
+static const D3D12_VIDEO_ENCODER_AV1_PROFILE         profile_high = 
D3D12_VIDEO_ENCODER_AV1_PROFILE_HIGH;
+static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_professional = 
D3D12_VIDEO_ENCODER_AV1_PROFILE_PROFESSIONAL;
+
+#define D3D_PROFILE_DESC(name) \
+    { sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE), { .pAV1Profile = 
(D3D12_VIDEO_ENCODER_AV1_PROFILE *)&profile_ ## name } }
+static const D3D12VAEncodeProfile d3d12va_encode_av1_profiles[] = {
+    { AV_PROFILE_AV1_MAIN,          8, 3, 1, 1, D3D_PROFILE_DESC(main)         
},
+    { AV_PROFILE_AV1_MAIN,         10, 3, 1, 1, D3D_PROFILE_DESC(main)         
},
+    { AV_PROFILE_AV1_HIGH,         10, 3, 1, 1, D3D_PROFILE_DESC(high)         
},
+    { AV_PROFILE_AV1_PROFESSIONAL,  8, 3, 1, 1, D3D_PROFILE_DESC(professional) 
},
+    { AV_PROFILE_AV1_PROFESSIONAL, 10, 3, 1, 1, D3D_PROFILE_DESC(professional) 
},
+    { AV_PROFILE_AV1_PROFESSIONAL, 12, 3, 1, 1, D3D_PROFILE_DESC(professional) 
},
+    { AV_PROFILE_UNKNOWN },
+};
+
+static int d3d12va_encode_av1_write_obu(AVCodecContext *avctx,
+                                        char *data, size_t *data_len,
+                                        CodedBitstreamFragment *obu)
+{
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+    int                       err = 0;
+
+    err = ff_cbs_write_fragment_data(priv->cbc, obu);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to write packed OBU data.\n");
+        return err;
+    }
+
+    memcpy(data, obu->data, obu->data_size);
+    *data_len = (8 * obu->data_size) - obu->data_bit_padding;
+
+    return 0;
+}
+
+static int d3d12va_encode_av1_add_obu(AVCodecContext* avctx,
+                                      CodedBitstreamFragment* au,
+                                      CodedBitstreamUnitType obu_type,
+                                      void* obu_unit)
+{
+    int err = 0;
+
+    err = ff_cbs_insert_unit_content(au, -1, obu_type, obu_unit, NULL);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
+            "type = %d.\n", obu_type);
+        return err;
+    }
+    return 0;
+}
+
+static int d3d12va_encode_av1_write_sequence_header(AVCodecContext *avctx,
+                                                    char *data, size_t 
*data_len)
+{
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+    CodedBitstreamFragment   *obu = &priv->current_obu;
+    int                       err = 0;
+
+    priv->units.raw_sequence_header.header.obu_type = AV1_OBU_SEQUENCE_HEADER;
+    err = d3d12va_encode_av1_add_obu(avctx, obu, AV1_OBU_SEQUENCE_HEADER, 
&priv->units.raw_sequence_header);
+    if (err < 0)
+        goto fail;
+
+    err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
+
+fail:
+    ff_cbs_fragment_reset(obu);
+    return err;
+}
+
+static int 
d3d12va_encode_av1_update_current_frame_picture_header(AVCodecContext *avctx,
+                                                                  
D3D12VAEncodePicture *pic,
+                                                                  AV1RawOBU 
*frameheader_obu)
+{
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+    AV1RawFrameHeader         *fh = &frameheader_obu->obu.frame_header;
+    uint8_t                 *data = NULL;
+    HRESULT                    hr = S_OK;
+    int                       err = 0;
+    D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES *post_encode_values = NULL;
+
+    // Update the frame header according to the picture post_encode_values
+    hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&data);
+    if (FAILED(hr)) {
+        err = AVERROR_UNKNOWN;
+        return err;
+    }
+    post_encode_values = (D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES*) (data +
+            sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
+            sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) +
+            
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES));
+
+    if (priv->post_encode_values_flag & 
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_QUANTIZATION) {
+        fh->base_q_idx = post_encode_values->Quantization.BaseQIndex;
+        fh->delta_q_y_dc = post_encode_values->Quantization.YDCDeltaQ;
+        fh->delta_q_u_dc = post_encode_values->Quantization.UDCDeltaQ;
+        fh->delta_q_u_ac = post_encode_values->Quantization.UACDeltaQ;
+        fh->delta_q_v_dc = post_encode_values->Quantization.VDCDeltaQ;
+        fh->delta_q_v_ac = post_encode_values->Quantization.VACDeltaQ;
+        fh->using_qmatrix = post_encode_values->Quantization.UsingQMatrix;
+        fh->qm_y = post_encode_values->Quantization.QMY;
+        fh->qm_u = post_encode_values->Quantization.QMU;
+        fh->qm_v = post_encode_values->Quantization.QMV;
+    }
+
+    if (priv->post_encode_values_flag & 
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_LOOP_FILTER) {
+        fh->loop_filter_level[0] = 
post_encode_values->LoopFilter.LoopFilterLevel[0];
+        fh->loop_filter_level[1] = 
post_encode_values->LoopFilter.LoopFilterLevel[1];
+        fh->loop_filter_level[2] = 
post_encode_values->LoopFilter.LoopFilterLevelU;
+        fh->loop_filter_level[3] = 
post_encode_values->LoopFilter.LoopFilterLevelV;
+        fh->loop_filter_sharpness = 
post_encode_values->LoopFilter.LoopFilterSharpnessLevel;
+        fh->loop_filter_delta_enabled = 
post_encode_values->LoopFilter.LoopFilterDeltaEnabled;
+        if (fh->loop_filter_delta_enabled) {
+            for (int i = 0; i < AV1_TOTAL_REFS_PER_FRAME; i++) {
+                fh->loop_filter_ref_deltas[i] = 
post_encode_values->LoopFilter.RefDeltas[i];
+                fh->update_ref_delta[i]       = 
post_encode_values->LoopFilter.RefDeltas[i];
+            }
+            for (int i = 0; i < 2; i++) {
+                fh->loop_filter_mode_deltas[i] = 
post_encode_values->LoopFilter.ModeDeltas[i];
+                fh->update_mode_delta[i]       = 
post_encode_values->LoopFilter.ModeDeltas[i];
+            }
+        }
+    }
+    if (priv->post_encode_values_flag & 
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_CDEF_DATA) {
+        fh->cdef_damping_minus_3 = post_encode_values->CDEF.CdefDampingMinus3;
+        fh->cdef_bits = post_encode_values->CDEF.CdefBits;
+        for (int i = 0; i < 8; i++) {
+            fh->cdef_y_pri_strength[i]  = 
post_encode_values->CDEF.CdefYPriStrength[i];
+            fh->cdef_y_sec_strength[i]  = 
post_encode_values->CDEF.CdefYSecStrength[i];
+            fh->cdef_uv_pri_strength[i] = 
post_encode_values->CDEF.CdefUVPriStrength[i];
+            fh->cdef_uv_sec_strength[i] = 
post_encode_values->CDEF.CdefUVSecStrength[i];
+        }
+    }
+    if (priv->post_encode_values_flag & 
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_QUANTIZATION_DELTA) {
+        fh->delta_q_present = 
post_encode_values->QuantizationDelta.DeltaQPresent;
+        fh->delta_q_res = post_encode_values->QuantizationDelta.DeltaQRes;
+    }
+
+    if (priv->post_encode_values_flag & 
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAG_REFERENCE_INDICES) {
+        for (int i = 0; i < AV1_REFS_PER_FRAME; i++) {
+            fh->ref_frame_idx[i] = post_encode_values->ReferenceIndices[i];
+        }
+    }
+
+    ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
+    return 0;
+}
+
+static int d3d12va_encode_av1_write_picture_header(AVCodecContext *avctx,
+                                                   D3D12VAEncodePicture *pic,
+                                                   char *data, size_t 
*data_len)
+{
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+    CodedBitstreamFragment  *obu  = &priv->current_obu;
+    AV1RawOBU    *frameheader_obu = av_mallocz(sizeof(AV1RawOBU));
+    int                       err = 0;
+
+    av_fifo_read(priv->picture_header_list, frameheader_obu, 1);
+    err = d3d12va_encode_av1_update_current_frame_picture_header(avctx, 
pic,frameheader_obu);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to update current frame picture 
header: %d.\n", err);
+        return err;
+    }
+
+    // Add the frame header OBU
+    frameheader_obu->header.obu_has_size_field = 1;
+
+    err = d3d12va_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, 
frameheader_obu);
+    if (err < 0)
+        goto fail;
+    err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
+
+fail:
+    ff_cbs_fragment_reset(obu);
+    av_freep(&frameheader_obu);
+    return err;
+}
+
+static int d3d12va_encode_av1_write_tile_group(AVCodecContext *avctx,
+                                               uint8_t* tile_group,
+                                               uint32_t tile_group_size,
+                                               char *data, size_t *data_len)
+{
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+    CodedBitstreamFragment  *obu  = &priv->current_obu;
+    AV1RawOBU     *tile_group_obu = &priv->units.raw_tile_group;
+    AV1RawTileGroup           *tg = &tile_group_obu->obu.tile_group;
+    int                       err = 0;
+
+    tg->tile_data.data = tile_group;
+    tg->tile_data.data_ref = NULL;
+    tg->tile_data.data_size = tile_group_size;
+    tile_group_obu->header.obu_has_size_field = 1;
+    tile_group_obu->header.obu_type = AV1_OBU_TILE_GROUP;
+
+    err = d3d12va_encode_av1_add_obu(avctx, obu, AV1_OBU_TILE_GROUP, 
tile_group_obu);
+    if (err < 0)
+        goto fail;
+    err = d3d12va_encode_av1_write_obu(avctx, data, data_len, obu);
+
+fail:
+    ff_cbs_fragment_reset(obu);
+    return err;
+}
+
+static int d3d12va_encode_av1_get_buffer_size(AVCodecContext *avctx,
+                                              D3D12VAEncodePicture *pic, 
size_t *size)
+{
+    D3D12VAEncodeContext                                    *ctx = 
avctx->priv_data;
+    D3D12_VIDEO_ENCODER_OUTPUT_METADATA                    *meta = NULL;
+    D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *subregion_meta = NULL;
+    uint8_t                                                *data = NULL;
+    HRESULT                                                   hr = S_OK;
+    int                                                      err = 0;
+
+    hr = ID3D12Resource_Map(pic->resolved_metadata, 0, NULL, (void **)&data);
+    if (FAILED(hr)) {
+        err = AVERROR_UNKNOWN;
+        return err;
+    }
+
+    subregion_meta = (D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA*)(data + 
sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA));
+    if (subregion_meta->bSize == 0) {
+        av_log(avctx, AV_LOG_ERROR, "No subregion metadata found\n");
+        err = AVERROR(EINVAL);
+        return err;
+    }
+    *size = subregion_meta->bSize;
+
+    ID3D12Resource_Unmap(pic->resolved_metadata, 0, NULL);
+
+    return 0;
+}
+
+static int d3d12va_encode_av1_get_coded_data(AVCodecContext *avctx,
+                                             D3D12VAEncodePicture *pic, 
AVPacket *pkt)
+{
+    int                   err = 0;
+    uint8_t              *ptr = NULL;
+    uint8_t      *mapped_data = NULL;
+    size_t         total_size = 0;
+    HRESULT                hr = S_OK;
+    size_t    av1_pic_hd_size = 0;
+    int tile_group_extra_size = 0;
+    size_t            bit_len = 0;
+    D3D12VAEncodeContext *ctx = avctx->priv_data;
+
+    char pic_hd_data[MAX_PARAM_BUFFER_SIZE] = { 0 };
+
+    err = d3d12va_encode_av1_get_buffer_size(avctx, pic, &total_size);
+    if (err < 0)
+        goto end;
+
+    // Update the picture header and calculate the picture header size
+    memset(pic_hd_data, 0, sizeof(pic_hd_data));
+    err = d3d12va_encode_av1_write_picture_header(avctx, pic, pic_hd_data, 
&av1_pic_hd_size);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to write picture header: %d.\n", 
err);
+        return err;
+    }
+    av1_pic_hd_size /= 8;
+    av_log(avctx, AV_LOG_DEBUG, "AV1 picture header size: %zu bytes.\n", 
av1_pic_hd_size);
+
+
+    tile_group_extra_size = (av_log2(total_size) + 7) / 7 + 1; // 1 byte for 
obu header, rest for tile group LEB128 size
+    av_log(avctx, AV_LOG_DEBUG, "Tile group extra size: %d bytes.\n", 
tile_group_extra_size);
+
+    total_size += (pic->header_size + tile_group_extra_size + av1_pic_hd_size);
+    av_log(avctx, AV_LOG_DEBUG, "Output buffer size %"SIZE_SPECIFIER"\n", 
total_size);
+
+    hr = ID3D12Resource_Map(pic->output_buffer, 0, NULL, (void 
**)&mapped_data);
+    if (FAILED(hr)) {
+        err = AVERROR_UNKNOWN;
+        goto end;
+    }
+
+    err = ff_get_encode_buffer(avctx, pkt, total_size, 0);
+    if (err < 0)
+        goto end;
+    ptr = pkt->data;
+
+    memcpy(ptr, mapped_data, pic->header_size);
+
+    ptr += pic->header_size;
+    mapped_data += pic->aligned_header_size;
+    total_size -= pic->header_size;
+
+    memcpy(ptr, pic_hd_data, av1_pic_hd_size);
+    ptr += av1_pic_hd_size;
+    total_size -= av1_pic_hd_size;
+    av_log(avctx, AV_LOG_DEBUG, "AV1 total_size after write picture header: 
%d.\n", total_size);
+
+    total_size -= tile_group_extra_size;
+    err = d3d12va_encode_av1_write_tile_group(avctx, mapped_data, total_size, 
ptr, &bit_len);
+    if (err < 0) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to write tile group: %d.\n", err);
+        goto end;
+    }
+    assert((total_size + tile_group_extra_size) * 8 == bit_len);
+
+    ID3D12Resource_Unmap(pic->output_buffer, 0, NULL);
+
+end:
+    av_buffer_unref(&pic->output_buffer_ref);
+    pic->output_buffer = NULL;
+    return err;
+}
+
+static int d3d12va_hw_base_encode_init_params_av1(FFHWBaseEncodeContext 
*base_ctx,
+                                                  AVCodecContext *avctx,
+                                                  D3D12VAHWBaseEncodeAV1 
*common,
+                                                  D3D12VAHWBaseEncodeAV1Opts 
*opts)
+{
+    AV1RawOBU      *seqheader_obu = &common->raw_sequence_header;
+    AV1RawSequenceHeader     *seq = &seqheader_obu->obu.sequence_header;
+    const AVPixFmtDescriptor *desc;
+
+    seq->seq_profile = avctx->profile;
+    if (!seq->seq_force_screen_content_tools)
+        seq->seq_force_integer_mv = AV1_SELECT_INTEGER_MV;
+    seq->seq_tier[0] = opts->tier;
+
+    desc = av_pix_fmt_desc_get(base_ctx->input_frames->sw_format);
+    seq->color_config = (AV1RawColorConfig){
+        .high_bitdepth = desc->comp[0].depth == 8 ? 0 : 1,
+        .color_primaries = avctx->color_primaries,
+        .transfer_characteristics = avctx->color_trc,
+        .matrix_coefficients = avctx->colorspace,
+        .color_description_present_flag = (avctx->color_primaries != 
AVCOL_PRI_UNSPECIFIED ||
+                                           avctx->color_trc != 
AVCOL_TRC_UNSPECIFIED ||
+                                           avctx->colorspace != 
AVCOL_SPC_UNSPECIFIED),
+        .color_range = avctx->color_range == AVCOL_RANGE_JPEG,
+        .subsampling_x = desc->log2_chroma_w,
+        .subsampling_y = desc->log2_chroma_h,
+    };
+
+    switch (avctx->chroma_sample_location) {
+    case AVCHROMA_LOC_LEFT:
+        seq->color_config.chroma_sample_position = AV1_CSP_VERTICAL;
+        break;
+    case AVCHROMA_LOC_TOPLEFT:
+        seq->color_config.chroma_sample_position = AV1_CSP_COLOCATED;
+        break;
+    default:
+        seq->color_config.chroma_sample_position = AV1_CSP_UNKNOWN;
+        break;
+    }
+
+    if (avctx->level != AV_LEVEL_UNKNOWN) {
+        seq->seq_level_idx[0] = avctx->level;
+    }
+    else {
+        const AV1LevelDescriptor *level;
+        float framerate;
+
+        if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
+            framerate = avctx->framerate.num / avctx->framerate.den;
+        else
+            framerate = 0;
+
+        //currently only supporting 1 tile
+        level = ff_av1_guess_level(avctx->bit_rate, opts->tier,
+            base_ctx->surface_width, base_ctx->surface_height,
+            /*priv->tile_rows*/1 * 1/*priv->tile_cols*/,
+            /*priv->tile_cols*/1, framerate);
+        if (level) {
+            av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
+            seq->seq_level_idx[0] = level->level_idx;
+        }
+        else {
+            av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
+                "any normal level, using maximum parameters level by 
default.\n");
+            seq->seq_level_idx[0] = 31;
+            seq->seq_tier[0] = 1;
+        }
+    }
+
+    // Still picture mode
+    seq->still_picture = (base_ctx->gop_size == 1);
+    seq->reduced_still_picture_header = seq->still_picture;
+
+    // Feature flags
+    seq->enable_filter_intra = opts->enable_filter_intra;
+    seq->enable_intra_edge_filter = opts->enable_intra_edge_filter;
+    seq->enable_interintra_compound = opts->enable_interintra_compound;
+    seq->enable_masked_compound = opts->enable_masked_compound;
+    seq->enable_warped_motion = opts->enable_warped_motion;
+    seq->enable_dual_filter = opts->enable_dual_filter;
+    seq->enable_order_hint = !seq->still_picture;
+    if (seq->enable_order_hint) {
+        seq->order_hint_bits_minus_1 = 7;
+    }
+    seq->enable_jnt_comp = opts->enable_jnt_comp && seq->enable_order_hint;
+    seq->enable_ref_frame_mvs = opts->enable_ref_frame_mvs && 
seq->enable_order_hint;
+    seq->enable_superres = opts->enable_superres;
+    seq->enable_cdef = opts->enable_cdef;
+    seq->enable_restoration = opts->enable_restoration;
+
+    return 0;
+
+}
+
+static int d3d12va_encode_av1_init_sequence_params(AVCodecContext *avctx)
+{
+    FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
+    D3D12VAEncodeContext      *ctx  = avctx->priv_data;
+    D3D12VAEncodeAV1Context   *priv = avctx->priv_data;
+    AVD3D12VAFramesContext   *hwctx = base_ctx->input_frames->hwctx;
+    AV1RawOBU        *seqheader_obu = &priv->units.raw_sequence_header;
+    AV1RawSequenceHeader       *seq = 
&priv->units.raw_sequence_header.obu.sequence_header;
+
+    D3D12_VIDEO_ENCODER_AV1_PROFILE profile = 
D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
+    D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS level = { 0 };
+    HRESULT hr;
+    int err;
+
+    D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 support = {
+        .NodeIndex                        = 0,
+        .Codec                            = D3D12_VIDEO_ENCODER_CODEC_AV1,
+        .InputFormat                      = hwctx->format,
+        .RateControl                      = ctx->rc,
+        .IntraRefresh                     = 
D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE,
+        .SubregionFrameEncoding           = 
D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
+        .ResolutionsListCount             = 1,
+        .pResolutionList                  = &ctx->resolution,
+        .CodecGopSequence                 = ctx->gop,
+        .MaxReferenceFramesInDPB          = AV1_NUM_REF_FRAMES,
+        .CodecConfiguration               = ctx->codec_conf,
+        .SuggestedProfile.DataSize        = 
sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE),
+        .SuggestedProfile.pAV1Profile     = &profile,
+        .SuggestedLevel.DataSize          = 
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS),
+        .SuggestedLevel.pAV1LevelSetting  = &level,
+        .pResolutionDependentSupport      = &ctx->res_limits,
+        .SubregionFrameEncodingData.pTilesPartition_AV1 = 
ctx->subregions_layout.pTilesPartition_AV1,
+    };
+
+    hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, 
D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1,
+                                                &support, sizeof(support));
+
+    if (FAILED(hr)) {
+        av_log(avctx, AV_LOG_ERROR, "Failed to check encoder support(%lx).\n", 
(long)hr);
+        return AVERROR(EINVAL);
+    }
+
+    if (!(support.SupportFlags & 
D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
+        av_log(avctx, AV_LOG_ERROR, "Driver does not support some request 
D3D12VA AV1 features. %#x\n",
+               support.ValidationFlags);
+        return AVERROR(EINVAL);
+    }
+
+    if (support.SupportFlags & 
D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
+        ctx->is_texture_array = 1;
+        av_log(avctx, AV_LOG_DEBUG, "D3D12 video encode on this device uses 
texture array mode.\n");
+    }
+
+    memset(seqheader_obu, 0, sizeof(*seqheader_obu));
+    seq->seq_profile = profile;
+    seq->seq_level_idx[0] = level.Level;
+    seq->seq_tier[0] = level.Tier;
+
+    seq->max_frame_width_minus_1 = ctx->resolution.Width - 1;
+    seq->max_frame_height_minus_1 = ctx->resolution.Height - 1;
+    seq->frame_width_bits_minus_1 = av_log2(ctx->resolution.Width);
+    seq->frame_height_bits_minus_1 = av_log2(ctx->resolution.Height);
+
+    seqheader_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
+
+    err = d3d12va_hw_base_encode_init_params_av1(base_ctx, avctx,
+                                                 &priv->units, 
&priv->unit_opts);
+    if (err < 0)
+        return err;
+
+    if (avctx->level == AV_LEVEL_UNKNOWN)
+        avctx->level = level.Level;
+
+    return 0;
+}
+
+static int d3d12va_encode_av1_get_encoder_caps(AVCodecContext *avctx)
+{
+    HRESULT                      hr = S_OK;
+    FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
+    D3D12VAEncodeContext       *ctx = avctx->priv_data;
+    D3D12VAEncodeAV1Context   *priv = avctx->priv_data;
+
+    D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION *config;
+    D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT av1_caps;
+
+    D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codec_caps = {
+        .NodeIndex                   = 0,
+        .Codec                       = D3D12_VIDEO_ENCODER_CODEC_AV1,
+        .Profile                     = ctx->profile->d3d12_profile,
+        .CodecSupportLimits.DataSize = 
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT),
+    };
+
+    codec_caps.CodecSupportLimits.pAV1Support = &av1_caps;
+
+    hr = ID3D12VideoDevice3_CheckFeatureSupport(ctx->video_device3, 
D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT,
+                                                &codec_caps, 
sizeof(codec_caps));
+    if (!(SUCCEEDED(hr) && codec_caps.IsSupported))
+        return AVERROR(EINVAL);
+
+    ctx->codec_conf.DataSize = 
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION);
+    ctx->codec_conf.pAV1Config = av_mallocz(ctx->codec_conf.DataSize);
+    if (!ctx->codec_conf.pAV1Config)
+        return AVERROR(ENOMEM);
+
+    priv->post_encode_values_flag = av1_caps.PostEncodeValuesFlags;
+    config = ctx->codec_conf.pAV1Config;
+
+    config->FeatureFlags = D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_NONE;
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) {
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK;
+        priv->unit_opts.enable_128x128_superblock = 1;
+    }
+
+    base_ctx->surface_width  = FFALIGN(avctx->width,  
priv->unit_opts.enable_128x128_superblock ? 128 : 64);
+    base_ctx->surface_height = FFALIGN(avctx->height, 
priv->unit_opts.enable_128x128_superblock ? 128 : 64);
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) {
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER;
+        priv->unit_opts.enable_loop_filter = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) {
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING;
+        priv->unit_opts.enable_palette = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) {
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY;
+        priv->unit_opts.enable_intra_block_copy = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS) {
+        // Loop filter deltas
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS;
+        priv->unit_opts.enable_loop_filter_delta = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) {
+        // CDEF (Constrained Directional Enhancement Filter)
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING;
+        priv->unit_opts.enable_cdef = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) {
+        // Dual filter
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER;
+        priv->unit_opts.enable_dual_filter = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) {
+        // Joint compound prediction
+        config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP;
+        priv->unit_opts.enable_jnt_comp = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) {
+        // Frame reference motion vectors
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS;
+        priv->unit_opts.enable_ref_frame_mvs = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) {
+        // Super-resolution
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION;
+        priv->unit_opts.enable_superres = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) {
+        // Warped motion
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION;
+        priv->unit_opts.enable_warped_motion = 1;
+    }
+
+    if (av1_caps.SupportedFeatureFlags & 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) {
+        // Inter-intra compound prediction
+        config->FeatureFlags |= 
D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND;
+        priv->unit_opts.enable_interintra_compound = 1;
+    }
+
+    return 0;
+}
+
+static int d3d12va_encode_av1_configure(AVCodecContext *avctx)
+{
+    FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
+    D3D12VAEncodeContext       *ctx = avctx->priv_data;
+    D3D12VAEncodeAV1Context   *priv = avctx->priv_data;
+    int                         err = 0;
+    int fixed_qp_key, fixed_qp_inter;
+
+    err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_AV1, avctx);
+    if (err < 0)
+        return err;
+
+    if (ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
+        D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
+        fixed_qp_inter = av_clip_uintp2(ctx->rc_quality, 8);
+
+        if (avctx->i_quant_factor > 0.0)
+            fixed_qp_key = av_clip_uintp2((avctx->i_quant_factor * 
fixed_qp_inter +
+                                    avctx->i_quant_offset) + 0.5, 8);
+        else
+            fixed_qp_key = fixed_qp_inter;
+
+        av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
+               "%d / %d for Key / Inter frames.\n",
+               fixed_qp_key, fixed_qp_inter);
+
+        ctx->rc.ConfigParams.DataSize = 
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
+        cqp_ctl = av_mallocz(ctx->rc.ConfigParams.DataSize);
+        if (!cqp_ctl)
+            return AVERROR(ENOMEM);
+
+        cqp_ctl->ConstantQP_FullIntracodedFrame                  = 
fixed_qp_key;
+        cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly      = 
fixed_qp_inter;
+        cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = 
fixed_qp_inter;
+
+        ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
+
+        priv->q_idx_idr = fixed_qp_key;
+        priv->q_idx_p   = fixed_qp_inter;
+
+    }
+
+    // GOP configuration for AV1
+    ctx->gop.DataSize = sizeof(D3D12_VIDEO_ENCODER_AV1_SEQUENCE_STRUCTURE);
+    ctx->gop.pAV1SequenceStructure = av_mallocz(ctx->gop.DataSize);
+    if (!ctx->gop.pAV1SequenceStructure)
+        return AVERROR(ENOMEM);
+
+    ctx->gop.pAV1SequenceStructure->IntraDistance = base_ctx->gop_size;
+    ctx->gop.pAV1SequenceStructure->InterFramePeriod = base_ctx->b_per_p + 1;
+
+    return 0;
+}
+
+static int d3d12va_encode_av1_set_level(AVCodecContext *avctx)
+{
+    D3D12VAEncodeContext     *ctx = avctx->priv_data;
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+    int                         i = 0;
+
+    ctx->level.DataSize = 
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
+    ctx->level.pAV1LevelSetting = av_mallocz(ctx->level.DataSize);
+    if (!ctx->level.pAV1LevelSetting)
+        return AVERROR(ENOMEM);
+
+    if (avctx->level != AV_LEVEL_UNKNOWN) {
+        for (i = 0; i < FF_ARRAY_ELEMS(av1_levels); i++) {
+            if (avctx->level == av1_levels[i].level) {
+                ctx->level.pAV1LevelSetting->Level = av1_levels[i].d3d12_level;
+                break;
+            }
+        }
+
+        if (i == FF_ARRAY_ELEMS(av1_levels) ) {
+            av_log(avctx, AV_LOG_ERROR, "Invalid AV1 level %d.\n", 
avctx->level);
+            return AVERROR(EINVAL);
+        }
+    } else {
+        ctx->level.pAV1LevelSetting->Level = 
D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
+        avctx->level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
+        av_log(avctx, AV_LOG_DEBUG, "Using default AV1 level 5.2\n");
+    }
+
+    if (priv->tier == 1 || avctx->bit_rate > 30000000) {
+        ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
+        av_log(avctx, AV_LOG_DEBUG, "Using AV1 High tier\n");
+    } else {
+        ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_MAIN;
+        av_log(avctx, AV_LOG_DEBUG, "Using AV1 Main tier\n");
+    }
+
+    if (priv->tier >= 0) {
+        ctx->level.pAV1LevelSetting->Tier = priv->tier == 0 ?
+                                            D3D12_VIDEO_ENCODER_AV1_TIER_MAIN :
+                                            D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
+    }
+
+    av_log(avctx, AV_LOG_DEBUG, "AV1 level set to %d, tier: %s\n",
+           ctx->level.pAV1LevelSetting->Level,
+           ctx->level.pAV1LevelSetting->Tier == 
D3D12_VIDEO_ENCODER_AV1_TIER_MAIN ? "Main" : "High");
+
+    return 0;
+}
+
+static int d3d12va_encode_av1_set_tile(AVCodecContext *avctx)
+{
+    D3D12VAEncodeContext *ctx = avctx->priv_data;
+
+    ctx->subregions_layout.DataSize = 
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES);
+    D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES 
*tiles_layout = av_mallocz(ctx->subregions_layout.DataSize);
+    ctx->subregions_layout.pTilesPartition_AV1 = tiles_layout;
+
+    // Currently only support 1 tile
+    tiles_layout->RowCount = 1;
+    tiles_layout->ColCount = 1;
+
+    return 0;
+}
+
+static void d3d12va_encode_av1_free_picture_params(D3D12VAEncodePicture *pic)
+{
+    if (!pic->pic_ctl.pAV1PicData)
+        return;
+
+    av_freep(&pic->pic_ctl.pAV1PicData);
+}
+
+static int d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx,
+                                                  FFHWBaseEncodePicture *pic)
+{
+    FFHWBaseEncodeContext             *base_ctx = avctx->priv_data;
+    D3D12VAEncodeAV1Context               *priv = avctx->priv_data;
+    D3D12VAEncodeContext                   *ctx = avctx->priv_data;
+    D3D12VAEncodePicture           *d3d12va_pic = pic->priv;
+    D3D12VAEncodeAV1Picture               *hpic = pic->codec_priv;
+    CodedBitstreamAV1Context             *cbctx = priv->cbc->priv_data;
+    AV1RawOBU                  *frameheader_obu = 
&priv->units.raw_frame_header;
+    AV1RawFrameHeader                       *fh = 
&frameheader_obu->obu.frame_header;
+
+    FFHWBaseEncodePicture *ref;
+    D3D12VAEncodeAV1Picture *href;
+    int i;
+
+    static const int8_t 
default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] =
+        { 1, 0, 0, 0, -1, 0, -1, -1 };
+
+    memset(frameheader_obu, 0, sizeof(*frameheader_obu));
+
+    frameheader_obu->header.obu_type = AV1_OBU_FRAME_HEADER;
+
+    d3d12va_pic->pic_ctl.DataSize = 
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_CODEC_DATA);
+    d3d12va_pic->pic_ctl.pAV1PicData = 
av_mallocz(d3d12va_pic->pic_ctl.DataSize);
+    if (!d3d12va_pic->pic_ctl.pAV1PicData)
+        return AVERROR(ENOMEM);
+
+    // Initialize frame type and reference frame management
+    switch(pic->type) {
+        case FF_HW_PICTURE_TYPE_IDR:
+            fh->frame_type = AV1_FRAME_KEY;
+            fh->refresh_frame_flags = 0xFF;
+            fh->base_q_idx = priv->q_idx_idr;
+            hpic->slot = 0;
+            hpic->last_idr_frame = pic->display_order;
+            fh->tx_mode = AV1_TX_MODE_LARGEST;
+            break;
+
+        case FF_HW_PICTURE_TYPE_P:
+            fh->frame_type = AV1_FRAME_INTER;
+            fh->base_q_idx = priv->q_idx_p;
+            fh->tx_mode = AV1_TX_MODE_SELECT;
+
+            ref = pic->refs[0][pic->nb_refs[0] - 1];
+            href = ref->codec_priv;
+
+            /**
+             * The encoder uses a simple alternating reference frame strategy:
+             * - For P-frames, it uses the last reconstructed frame as a 
reference.
+             * - To simplify the reference model of the encoder, the encoder 
alternates between
+             * two reference frame slots (typically slot 0 and slot 1) for 
storing reconstructed
+             * images and providing prediction references for the next frame.
+             */
+            if (base_ctx->ref_l0 > 1) {
+                hpic->slot = !href->slot;
+            } else {
+                hpic->slot = 0;
+            }
+            hpic->last_idr_frame = href->last_idr_frame;
+            fh->refresh_frame_flags = 1 << hpic->slot;
+
+            // Set the nearest frame in L0 as all reference frame.
+            for (i = 0; i < AV1_REFS_PER_FRAME; i++)
+                fh->ref_frame_idx[i] = href->slot;
+
+            fh->primary_ref_frame = href->slot;
+            fh->ref_order_hint[href->slot] = ref->display_order - 
href->last_idr_frame;
+
+            // Set the 2nd nearest frame in L0 as Golden frame.
+            if (pic->nb_refs[0] > 1) {
+                ref = pic->refs[0][pic->nb_refs[0] - 2];
+                href = ref->codec_priv;
+                // Reference frame index 3 is the GOLDEN_FRAME
+                fh->ref_frame_idx[3] = href->slot;
+                fh->ref_order_hint[href->slot] = ref->display_order - 
href->last_idr_frame;
+            } else if (base_ctx->ref_l0 == 1) {
+                fh->ref_order_hint[!href->slot] = 
cbctx->ref[!href->slot].order_hint;
+            }
+            break;
+
+        case FF_HW_PICTURE_TYPE_B:
+            av_log(avctx, AV_LOG_ERROR, "D3D12 AV1 video encode on this device 
requires B-frame support, "
+                "but it's not implemented.\n");
+            return AVERROR_PATCHWELCOME;
+        default:
+            av_log(avctx, AV_LOG_ERROR, "Unsupported picture type %d.\n", 
pic->type);
+    }
+
+
+    cbctx->seen_frame_header = 0;
+
+    fh->show_frame                = pic->display_order <= pic->encode_order;
+    fh->showable_frame            = fh->frame_type != AV1_FRAME_KEY;
+    fh->order_hint                = pic->display_order - hpic->last_idr_frame;
+    fh->frame_width_minus_1       = ctx->resolution.Width - 1;
+    fh->frame_height_minus_1      = ctx->resolution.Height - 1;
+    fh->render_width_minus_1      = fh->frame_width_minus_1;
+    fh->render_height_minus_1     = fh->frame_height_minus_1;
+    fh->is_filter_switchable      = 1;
+    fh->interpolation_filter      = AV1_INTERPOLATION_FILTER_SWITCHABLE;
+    fh->uniform_tile_spacing_flag = 1;
+    fh->width_in_sbs_minus_1[0]   = (ctx->resolution.Width  + 63 >> 6) -1; // 
64x64 superblock size
+    fh->height_in_sbs_minus_1[0]  = (ctx->resolution.Height + 63 >> 6) -1; // 
64x64 superblock size
+
+    memcpy(fh->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
+           AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
+
+    if (fh->frame_type == AV1_FRAME_KEY && fh->show_frame)
+        fh->error_resilient_mode = 1;
+
+    if (fh->frame_type == AV1_FRAME_KEY || fh->error_resilient_mode)
+        fh->primary_ref_frame = AV1_PRIMARY_REF_NONE;
+
+    d3d12va_pic->pic_ctl.pAV1PicData->FrameType = fh->frame_type;
+    d3d12va_pic->pic_ctl.pAV1PicData->TxMode = fh->tx_mode;
+    d3d12va_pic->pic_ctl.pAV1PicData->RefreshFrameFlags = 
fh->refresh_frame_flags;
+    d3d12va_pic->pic_ctl.pAV1PicData->TemporalLayerIndexPlus1 = 
hpic->temporal_id + 1;
+    d3d12va_pic->pic_ctl.pAV1PicData->SpatialLayerIndexPlus1 = 
hpic->spatial_id + 1;
+    d3d12va_pic->pic_ctl.pAV1PicData->PictureIndex = pic->display_order;
+    d3d12va_pic->pic_ctl.pAV1PicData->InterpolationFilter = 
D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_SWITCHABLE;
+    d3d12va_pic->pic_ctl.pAV1PicData->PrimaryRefFrame = fh->primary_ref_frame;
+    if (fh->error_resilient_mode)
+        d3d12va_pic->pic_ctl.pAV1PicData->Flags |= 
D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_FLAG_ENABLE_ERROR_RESILIENT_MODE;
+
+    if (pic->type == FF_HW_PICTURE_TYPE_IDR)
+    {
+        for (int i = 0; i < AV1_NUM_REF_FRAMES; i++) {
+            
d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[i].ReconstructedPictureResourceIndex
 =
+            D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX;
+        }
+    } else if (pic->type == FF_HW_PICTURE_TYPE_P) {
+        for (i = 0; i < pic->nb_refs[0]; i++) {
+            FFHWBaseEncodePicture *ref_pic = pic->refs[0][i];
+            
d3d12va_pic->pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[i].ReconstructedPictureResourceIndex
 =
+            ((D3D12VAEncodeAV1Picture*)ref_pic->codec_priv)->slot;
+        }
+    }
+    // Set reference frame management
+    memset(d3d12va_pic->pic_ctl.pAV1PicData->ReferenceIndices, 0, sizeof(UINT) 
* AV1_REFS_PER_FRAME);
+    if (pic->type == FF_HW_PICTURE_TYPE_P) {
+        for (i = 0; i < AV1_REFS_PER_FRAME; i++)
+            d3d12va_pic->pic_ctl.pAV1PicData->ReferenceIndices[i] = 
fh->ref_frame_idx[i];
+    }
+
+    int ret = av_fifo_write(priv->picture_header_list, 
&priv->units.raw_frame_header, 1);
+
+    return 0;
+}
+
+
+static const D3D12VAEncodeType d3d12va_encode_type_av1 = {
+    .profiles               = d3d12va_encode_av1_profiles,
+
+    .d3d12_codec            = D3D12_VIDEO_ENCODER_CODEC_AV1,
+
+    .flags                  = FF_HW_FLAG_B_PICTURES |
+                              FF_HW_FLAG_B_PICTURE_REFERENCES |
+                              FF_HW_FLAG_NON_IDR_KEY_PICTURES,
+
+    .default_quality        = 25,
+
+    .get_encoder_caps       = &d3d12va_encode_av1_get_encoder_caps,
+
+    .configure              = &d3d12va_encode_av1_configure,
+
+    .set_level              = &d3d12va_encode_av1_set_level,
+
+    .set_tile               = &d3d12va_encode_av1_set_tile,
+
+    .picture_priv_data_size = sizeof(D3D12VAEncodeAV1Picture),
+
+    .init_sequence_params   = &d3d12va_encode_av1_init_sequence_params,
+
+    .init_picture_params    = &d3d12va_encode_av1_init_picture_params,
+
+    .free_picture_params    = &d3d12va_encode_av1_free_picture_params,
+
+    .write_sequence_header  = &d3d12va_encode_av1_write_sequence_header,
+
+#ifdef CONFIG_AV1_D3D12VA_ENCODER
+    .get_coded_data         = &d3d12va_encode_av1_get_coded_data,
+#endif
+};
+
+static int d3d12va_encode_av1_init(AVCodecContext *avctx)
+{
+    D3D12VAEncodeContext     *ctx = avctx->priv_data;
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+
+    ctx->codec = &d3d12va_encode_type_av1;
+
+    if (avctx->profile == AV_PROFILE_UNKNOWN)
+        avctx->profile = priv->profile;
+    if (avctx->level == AV_LEVEL_UNKNOWN)
+        avctx->level = priv->level;
+
+    if (avctx->level != AV_LEVEL_UNKNOWN && avctx->level & ~0xff) {
+        av_log(avctx, AV_LOG_ERROR, "Invalid level %d: must fit "
+               "in 8-bit unsigned integer.\n", avctx->level);
+        return AVERROR(EINVAL);
+    }
+
+    if (priv->qp > 0)
+        ctx->explicit_qp = priv->qp;
+
+    priv->picture_header_list = av_fifo_alloc2(2, sizeof(AV1RawOBU), 
AV_FIFO_FLAG_AUTO_GROW);
+
+    return ff_d3d12va_encode_init(avctx);
+}
+
+static int d3d12va_encode_av1_close(AVCodecContext *avctx)
+{
+    D3D12VAEncodeAV1Context *priv = avctx->priv_data;
+
+    ff_cbs_fragment_free(&priv->current_obu);
+    ff_cbs_close(&priv->cbc);
+
+    av_freep(&priv->common.codec_conf.pAV1Config);
+    av_freep(&priv->common.gop.pAV1SequenceStructure);
+    av_freep(&priv->common.level.pAV1LevelSetting);
+    av_freep(&priv->common.subregions_layout.pTilesPartition_AV1);
+
+    av_fifo_freep2(&priv->picture_header_list);
+
+    return ff_d3d12va_encode_close(avctx);
+}
+
+#define OFFSET(x) offsetof(D3D12VAEncodeAV1Context, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
+static const AVOption d3d12va_encode_av1_options[] = {
+    HW_BASE_ENCODE_COMMON_OPTIONS,
+    D3D12VA_ENCODE_RC_OPTIONS,
+
+    { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
+      OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 52, FLAGS },
+
+    { "profile", "Set profile (general_profile_idc)",
+      OFFSET(profile), AV_OPT_TYPE_INT,
+      { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xff, FLAGS, 
"profile" },
+
+#define PROFILE(name, value)  name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, "profile"
+    { PROFILE("main",             AV_PROFILE_AV1_MAIN) },
+    { PROFILE("high",             AV_PROFILE_AV1_HIGH) },
+    { PROFILE("professional",     AV_PROFILE_AV1_PROFESSIONAL) },
+#undef PROFILE
+
+    { "tier", "Set tier (general_tier_flag)",
+      OFFSET(unit_opts.tier), AV_OPT_TYPE_INT,
+      { .i64 = 0 }, 0, 1, FLAGS, "tier" },
+    { "main", NULL, 0, AV_OPT_TYPE_CONST,
+      { .i64 = 0 }, 0, 0, FLAGS, "tier" },
+    { "high", NULL, 0, AV_OPT_TYPE_CONST,
+      { .i64 = 1 }, 0, 0, FLAGS, "tier" },
+
+    { "level", "Set level (general_level_idc)",
+      OFFSET(level), AV_OPT_TYPE_INT,
+      { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0xff, FLAGS, "level" },
+
+#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
+      { .i64 = value }, 0, 0, FLAGS, "level"
+    { LEVEL("2.0",  0) },
+    { LEVEL("2.1",  1) },
+    { LEVEL("2.2",  2) },
+    { LEVEL("2.3",  3) },
+    { LEVEL("3.0",  4) },
+    { LEVEL("3.1",  5) },
+    { LEVEL("3.2",  6) },
+    { LEVEL("3.3",  7) },
+    { LEVEL("4.0",  8) },
+    { LEVEL("4.1",  9) },
+    { LEVEL("4.2",  10) },
+    { LEVEL("4.3",  11) },
+    { LEVEL("5.0",  12) },
+    { LEVEL("5.1",  13) },
+    { LEVEL("5.2",  14) },
+    { LEVEL("5.3",  15) },
+    { LEVEL("6.0",  16) },
+    { LEVEL("6.1",  17) },
+    { LEVEL("6.2",  18) },
+    { LEVEL("6.3",  19) },
+    { LEVEL("7.0",  20) },
+    { LEVEL("7.1",  21) },
+    { LEVEL("7.2",  22) },
+    { LEVEL("7.3",  23) },
+#undef LEVEL
+    { NULL },
+};
+
+static const FFCodecDefault d3d12va_encode_av1_defaults[] = {
+    { "b",              "0"   },
+    { "bf",             "0"   },
+    { "g",              "120" },
+    { "i_qfactor",      "1"   },
+    { "i_qoffset",      "0"   },
+    { "b_qfactor",      "1"   },
+    { "b_qoffset",      "0"   },
+    { "qmin",           "-1"  },
+    { "qmax",           "-1"  },
+    { "refs",           "0"   },
+    { NULL },
+};
+
+static const AVClass d3d12va_encode_av1_class = {
+    .class_name = "av1_d3d12va",
+    .item_name  = av_default_item_name,
+    .option     = d3d12va_encode_av1_options,
+    .version    = LIBAVUTIL_VERSION_INT,
+};
+
+const FFCodec ff_av1_d3d12va_encoder = {
+    .p.name         = "av1_d3d12va",
+    CODEC_LONG_NAME("D3D12VA av1 encoder"),
+    .p.type         = AVMEDIA_TYPE_VIDEO,
+    .p.id           = AV_CODEC_ID_AV1,
+    .priv_data_size = sizeof(D3D12VAEncodeAV1Context),
+    .init           = &d3d12va_encode_av1_init,
+    FF_CODEC_RECEIVE_PACKET_CB(&ff_d3d12va_encode_receive_packet),
+    .close          = &d3d12va_encode_av1_close,
+    .p.priv_class   = &d3d12va_encode_av1_class,
+    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
+    .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
+                      FF_CODEC_CAP_INIT_CLEANUP,
+    .defaults       = d3d12va_encode_av1_defaults,
+    CODEC_PIXFMTS(AV_PIX_FMT_D3D12),
+    .hw_configs     = ff_d3d12va_encode_hw_configs,
+    .p.wrapper_name = "d3d12va",
+};

-----------------------------------------------------------------------

Summary of changes:
 Changelog                       |    1 +
 configure                       |    3 +
 libavcodec/Makefile             |    1 +
 libavcodec/allcodecs.c          |    1 +
 libavcodec/d3d12va_encode.c     |   45 +-
 libavcodec/d3d12va_encode.h     |   13 +
 libavcodec/d3d12va_encode_av1.c | 1182 +++++++++++++++++++++++++++++++++++++++
 7 files changed, 1241 insertions(+), 5 deletions(-)
 create mode 100644 libavcodec/d3d12va_encode_av1.c


hooks/post-receive
-- 

_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to