amfcodec: add support of AMF AV1 encoder
authorEvgeny Pavlov <lucenticus@gmail.com>
Wed, 14 Dec 2022 09:35:53 +0000 (10:35 +0100)
committerSeungha Yang <seungha@centricular.com>
Wed, 21 Dec 2022 19:23:24 +0000 (19:23 +0000)
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/3569>

subprojects/gst-plugins-bad/sys/amfcodec/gstamfav1enc.cpp [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/amfcodec/gstamfav1enc.h [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/amfcodec/include/components/VideoEncoderAV1.h [new file with mode: 0644]
subprojects/gst-plugins-bad/sys/amfcodec/meson.build
subprojects/gst-plugins-bad/sys/amfcodec/plugin.cpp

diff --git a/subprojects/gst-plugins-bad/sys/amfcodec/gstamfav1enc.cpp b/subprojects/gst-plugins-bad/sys/amfcodec/gstamfav1enc.cpp
new file mode 100644 (file)
index 0000000..2615faa
--- /dev/null
@@ -0,0 +1,1174 @@
+/* GStreamer
+ * Copyright (C) 2022 Seungha Yang <seungha@centricular.com>
+ * Copyright (C) 2022 Evgeny Pavlov <lucenticus@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/**
+ * SECTION:element-amfav1enc
+ * @title: amfav1enc
+ * @short_description: An AMD AMF API based AV1 video encoder
+ *
+ * amfav1enc element encodes raw video stream into compressed AV1 bitstream
+ * via AMD AMF API.
+ *
+ * ## Example launch line
+ * ```
+ * gst-launch-1.0 videotestsrc num-buffers=100 ! amfav1enc ! av1parse ! webmmux ! filesink location=encoded.webm
+ * ```
+ *
+ * Since: 1.22
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstamfav1enc.h"
+#include <components/Component.h>
+#include <components/VideoEncoderAV1.h>
+#include <core/Factory.h>
+#include <string>
+#include <vector>
+#include <string.h>
+
+using namespace amf;
+
+GST_DEBUG_CATEGORY_STATIC (gst_amf_av1_enc_debug);
+#define GST_CAT_DEFAULT gst_amf_av1_enc_debug
+
+static GTypeClass *parent_class = nullptr;
+
+typedef struct
+{
+  amf_int64 num_of_hw_instances;
+  amf_int64 max_throughput;
+  amf_int64 requested_throughput;
+  amf_int64 color_conversion;
+  amf_int64 pre_analysis;
+  amf_int64 max_bitrate;
+  amf_int64 max_profile;
+  amf_int64 max_level;
+  amf_int64 max_num_temporal_layers;
+  amf_int64 max_num_ltr_frames;
+  amf_int64 default_qp_i;
+  amf_int64 default_qp_p;
+  amf_int64 min_gop_size;
+  amf_int64 max_gop_size;
+  amf_int64 default_gop_size;
+  guint valign;
+} GstAmfAv1EncDeviceCaps;
+
+/**
+ * GstAmfAv1EncUsage:
+ *
+ * Encoder usages
+ *
+ * Since: 1.22
+ */
+#define GST_TYPE_AMF_AV1_ENC_USAGE (gst_amf_av1_enc_usage_get_type ())
+static GType
+gst_amf_av1_enc_usage_get_type (void)
+{
+  static GType usage_type = 0;
+  static const GEnumValue usages[] = {
+    /**
+     * GstAmfAv1EncUsage::transcoding:
+     *
+     * Transcoding usage
+     */
+    {AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING, "Transcoding", "transcoding"},
+
+    /**
+     * GstAmfAv1EncUsage::low-latency:
+     *
+     * Low Latency usage
+     */
+    {AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY, "Low Latency", "low-latency"},
+    {0, nullptr, nullptr}
+  };
+
+  if (g_once_init_enter (&usage_type)) {
+    GType type = g_enum_register_static ("GstAmfAv1EncUsage", usages);
+    g_once_init_leave (&usage_type, type);
+  }
+
+  return usage_type;
+}
+
+/**
+ * GstAmfAv1EncRateControl:
+ *
+ * Rate control methods
+ *
+ * Since: 1.22
+ */
+#define GST_TYPE_AMF_AV1_ENC_RATE_CONTROL (gst_amf_av1_enc_rate_control_get_type ())
+static GType
+gst_amf_av1_enc_rate_control_get_type (void)
+{
+  static GType rate_control_type = 0;
+  static const GEnumValue rate_controls[] = {
+    /**
+     * GstAmfAv1EncRateControl::default:
+     *
+     * Default rate control method depending on usage
+     */
+    {AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN,
+        "Default, depends on Usage", "default"},
+
+    /**
+     * GstAmfAv1EncRateControl::cqp:
+     *
+     * Constant QP
+     */
+    {AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP, "Constant QP",
+        "cqp"},
+
+    /**
+     * GstAmfAv1EncRateControl::lcvbr:
+     *
+     * Latency Constrained Variable Bitrate
+     */
+    {AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR,
+        "Latency Constrained VBR", "lcvbr"},
+
+    /**
+     * GstAmfAv1EncRateControl::vbr:
+     *
+     * Peak Constrained Variable Bitrate
+     */
+    {AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR,
+        "Peak Constrained VBR", "vbr"},
+
+    /**
+     * GstAmfAv1EncRateControl::cbr:
+     *
+     * Constant Bitrate
+     */
+    {AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR, "Constant Bitrate", "cbr"},
+    {0, nullptr, nullptr}
+  };
+
+  if (g_once_init_enter (&rate_control_type)) {
+    GType type =
+        g_enum_register_static ("GstAmfAv1EncRateControl", rate_controls);
+    g_once_init_leave (&rate_control_type, type);
+  }
+
+  return rate_control_type;
+}
+
+/**
+ * GstAmfAv1EncPreset:
+ *
+ * Encoding quality presets
+ *
+ * Since: 1.22
+ */
+#define AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_UNKNOWN -1
+#define GST_TYPE_AMF_AV1_ENC_PRESET (gst_amf_av1_enc_preset_get_type ())
+static GType
+gst_amf_av1_enc_preset_get_type (void)
+{
+  static GType preset_type = 0;
+  static const GEnumValue presets[] = {
+    /**
+     * GstAmfAv1EncRateControl::default:
+     *
+     * Default preset depends on usage
+     */
+    {AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_UNKNOWN, "Default, depends on USAGE",
+        "default"},
+
+    /**
+     * GstAmfAv1EncRateControl::high-quality:
+     *
+     * High quality oriented preset
+     */
+    {AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY, "High quality",
+        "high-quality"},
+
+    /**
+     * GstAmfAv1EncRateControl::quality:
+     *
+     * Quality oriented preset
+     */
+    {AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY, "Quality", "quality"},
+
+    /**
+     *
+     * GstAmfAv1EncRateControl::balanced:
+     *
+     * Balanced preset
+     */
+    {AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED, "Balanced", "balanced"},
+
+    /**
+     * GstAmfAv1EncRateControl::speed:
+     *
+     * Speed oriented preset
+     */
+    {AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED, "Speed", "speed"},
+    {0, nullptr, nullptr}
+  };
+
+  if (g_once_init_enter (&preset_type)) {
+    GType type = g_enum_register_static ("GstAmfAv1EncPreset", presets);
+    g_once_init_leave (&preset_type, type);
+  }
+
+  return preset_type;
+}
+
+typedef struct
+{
+  GstCaps *sink_caps;
+  GstCaps *src_caps;
+
+  gint64 adapter_luid;
+
+  GstAmfAv1EncDeviceCaps dev_caps;
+} GstAmfAv1EncClassData;
+
+enum
+{
+  PROP_0,
+  PROP_ADAPTER_LUID,
+  PROP_USAGE,
+  PROP_RATE_CONTROL,
+  PROP_PRESET,
+  PROP_BITRATE,
+  PROP_MAX_BITRATE,
+  PROP_GOP_SIZE,
+  PROP_MIN_QP_I,
+  PROP_MAX_QP_I,
+  PROP_MIN_QP_P,
+  PROP_MAX_QP_P,
+  PROP_QP_I,
+  PROP_QP_P,
+  PROP_REF_FRAMES,
+};
+
+#define DEFAULT_USAGE AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING
+#define DEFAULT_RATE_CONTROL AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN
+#define DEFAULT_PRESET AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_UNKNOWN
+#define DEFAULT_BITRATE 0
+#define DEFAULT_MAX_BITRATE 0
+#define DEFAULT_MIN_MAX_QP -1
+#define DEFAULT_REF_FRAMES 1
+
+#define DOC_SINK_CAPS_COMM \
+    "format = (string) NV12, " \
+    "width = (int) [ 128, 4096 ], height = (int) [ 128, 4096 ]"
+
+#define DOC_SINK_CAPS \
+    "video/x-raw(memory:D3D11Memory), " DOC_SINK_CAPS_COMM "; " \
+    "video/x-raw, " DOC_SINK_CAPS_COMM
+
+#define DOC_SRC_CAPS \
+    "video/x-av1, width = (int) [ 128, 4096 ], height = (int) [ 128, 4096 ], " \
+    "profile = (string) main, alignment= (string) tu"
+
+typedef struct _GstAmfAv1Enc
+{
+  GstAmfEncoder parent;
+
+  GMutex prop_lock;
+  gboolean property_updated;
+  gint usage;
+  gint rate_control;
+  gint preset;
+  guint bitrate;
+  guint max_bitrate;
+  guint gop_size;
+  gint min_qp_i;
+  gint max_qp_i;
+  gint min_qp_p;
+  gint max_qp_p;
+  guint qp_i;
+  guint qp_p;
+  guint ref_frames;
+} GstAmfAv1Enc;
+
+typedef struct _GstAmfAv1EncClass
+{
+  GstAmfEncoderClass parent_class;
+  GstAmfAv1EncDeviceCaps dev_caps;
+
+  gint64 adapter_luid;
+} GstAmfAv1EncClass;
+
+#define GST_AMF_AV1_ENC(object) ((GstAmfAv1Enc *) (object))
+#define GST_AMF_AV1_ENC_GET_CLASS(object) \
+    (G_TYPE_INSTANCE_GET_CLASS ((object),G_TYPE_FROM_INSTANCE (object),GstAmfAv1EncClass))
+
+static void gst_amf_av1_enc_finalize (GObject * object);
+static void gst_amf_av1_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_amf_av1_enc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+static gboolean gst_amf_av1_enc_set_format (GstAmfEncoder * encoder,
+    GstVideoCodecState * state, gpointer component);
+static gboolean gst_amf_av1_enc_set_output_state (GstAmfEncoder * encoder,
+    GstVideoCodecState * state, gpointer component);
+static gboolean gst_amf_av1_enc_set_surface_prop (GstAmfEncoder * encoder,
+    GstVideoCodecFrame * frame, gpointer surface);
+static GstBuffer *gst_amf_av1_enc_create_output_buffer (GstAmfEncoder *
+    encoder, gpointer data, gboolean * sync_point);
+static gboolean gst_amf_av1_enc_check_reconfigure (GstAmfEncoder * encoder);
+
+static void
+gst_amf_av1_enc_class_init (GstAmfAv1EncClass * klass, gpointer data)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+  GstAmfEncoderClass *amf_class = GST_AMF_ENCODER_CLASS (klass);
+  GstAmfAv1EncClassData *cdata = (GstAmfAv1EncClassData *) data;
+  GstAmfAv1EncDeviceCaps *dev_caps = &cdata->dev_caps;
+  GParamFlags param_flags = (GParamFlags) (G_PARAM_READWRITE |
+      GST_PARAM_MUTABLE_PLAYING | G_PARAM_STATIC_STRINGS);
+  GstPadTemplate *pad_templ;
+  GstCaps *doc_caps;
+
+  parent_class = (GTypeClass *) g_type_class_peek_parent (klass);
+
+  object_class->finalize = gst_amf_av1_enc_finalize;
+  object_class->set_property = gst_amf_av1_enc_set_property;
+  object_class->get_property = gst_amf_av1_enc_get_property;
+
+  g_object_class_install_property (object_class, PROP_ADAPTER_LUID,
+      g_param_spec_int64 ("adapter-luid", "Adapter LUID",
+          "DXGI Adapter LUID (Locally Unique Identifier) of associated GPU",
+          G_MININT64, G_MAXINT64, 0, (GParamFlags) (GST_PARAM_DOC_SHOW_DEFAULT |
+              G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
+  g_object_class_install_property (object_class, PROP_USAGE,
+      g_param_spec_enum ("usage", "Usage",
+          "Target usage", GST_TYPE_AMF_AV1_ENC_USAGE,
+          DEFAULT_USAGE, param_flags));
+  g_object_class_install_property (object_class, PROP_RATE_CONTROL,
+      g_param_spec_enum ("rate-control", "Rate Control",
+          "Rate Control Method", GST_TYPE_AMF_AV1_ENC_RATE_CONTROL,
+          DEFAULT_RATE_CONTROL, param_flags));
+  g_object_class_install_property (object_class, PROP_PRESET,
+      g_param_spec_enum ("preset", "Preset",
+          "Preset", GST_TYPE_AMF_AV1_ENC_PRESET, DEFAULT_PRESET, param_flags));
+  g_object_class_install_property (object_class, PROP_BITRATE,
+      g_param_spec_uint ("bitrate", "Bitrate",
+          "Target bitrate in kbit/sec (0: USAGE default)",
+          0, G_MAXINT / 1000, DEFAULT_BITRATE, param_flags));
+  g_object_class_install_property (object_class, PROP_MAX_BITRATE,
+      g_param_spec_uint ("max-bitrate", "Max Bitrate",
+          "Maximum bitrate in kbit/sec (0: USAGE default)",
+          0, G_MAXINT / 1000, DEFAULT_MAX_BITRATE, param_flags));
+  g_object_class_install_property (object_class, PROP_GOP_SIZE,
+      g_param_spec_uint ("gop-size", "GOP Size",
+          "Number of pictures within a GOP",
+          (guint) dev_caps->min_gop_size, (guint) dev_caps->max_gop_size,
+          (guint) dev_caps->default_gop_size, param_flags));
+  g_object_class_install_property (object_class, PROP_MIN_QP_I,
+      g_param_spec_int ("min-qp-i", "Min QP I",
+          "Minimum allowed QP value for I frames (-1: USAGE default)",
+          -1, 255, DEFAULT_MIN_MAX_QP, param_flags));
+  g_object_class_install_property (object_class, PROP_MAX_QP_I,
+      g_param_spec_int ("max-qp-i", "Max QP I",
+          "Maximum allowed QP value for I frames (-1: USAGE default)",
+          -1, 255, DEFAULT_MIN_MAX_QP, param_flags));
+  g_object_class_install_property (object_class, PROP_MIN_QP_P,
+      g_param_spec_int ("min-qp-p", "Min QP P",
+          "Minimum allowed QP value for P frames (-1: USAGE default)",
+          -1, 255, DEFAULT_MIN_MAX_QP, param_flags));
+  g_object_class_install_property (object_class, PROP_MAX_QP_P,
+      g_param_spec_int ("max-qp-p", "Max QP P",
+          "Maximum allowed QP value for P frames (-1: USAGE default)",
+          -1, 255, DEFAULT_MIN_MAX_QP, param_flags));
+  g_object_class_install_property (object_class, PROP_QP_I,
+      g_param_spec_uint ("qp-i", "QP I",
+          "Constant QP for I frames", 0, 255,
+          (guint) dev_caps->default_qp_i, param_flags));
+  g_object_class_install_property (object_class, PROP_QP_P,
+      g_param_spec_uint ("qp-p", "QP P",
+          "Constant QP for P frames", 0, 255,
+          (guint) dev_caps->default_qp_p, param_flags));
+  g_object_class_install_property (object_class, PROP_REF_FRAMES,
+      g_param_spec_uint ("ref-frames", "Reference Frames",
+          "Number of reference frames", 0, 8, DEFAULT_REF_FRAMES, param_flags));
+
+  gst_element_class_set_metadata (element_class,
+      "AMD AMF AV1 Video Encoder",
+      "Codec/Encoder/Video/Hardware",
+      "Encode AV1 video streams using AMF API",
+      "Seungha Yang <seungha@centricular.com>, "
+      "Evgeny Pavlov <lucenticus@gmail.com>");
+
+  pad_templ = gst_pad_template_new ("sink",
+      GST_PAD_SINK, GST_PAD_ALWAYS, cdata->sink_caps);
+  doc_caps = gst_caps_from_string (DOC_SINK_CAPS);
+  gst_pad_template_set_documentation_caps (pad_templ, doc_caps);
+  gst_caps_unref (doc_caps);
+  gst_element_class_add_pad_template (element_class, pad_templ);
+
+  pad_templ = gst_pad_template_new ("src",
+      GST_PAD_SRC, GST_PAD_ALWAYS, cdata->src_caps);
+  doc_caps = gst_caps_from_string (DOC_SRC_CAPS);
+  gst_pad_template_set_documentation_caps (pad_templ, doc_caps);
+  gst_caps_unref (doc_caps);
+  gst_element_class_add_pad_template (element_class, pad_templ);
+
+  amf_class->set_format = GST_DEBUG_FUNCPTR (gst_amf_av1_enc_set_format);
+  amf_class->set_output_state =
+      GST_DEBUG_FUNCPTR (gst_amf_av1_enc_set_output_state);
+  amf_class->set_surface_prop =
+      GST_DEBUG_FUNCPTR (gst_amf_av1_enc_set_surface_prop);
+  amf_class->create_output_buffer =
+      GST_DEBUG_FUNCPTR (gst_amf_av1_enc_create_output_buffer);
+  amf_class->check_reconfigure =
+      GST_DEBUG_FUNCPTR (gst_amf_av1_enc_check_reconfigure);
+
+  klass->dev_caps = cdata->dev_caps;
+  klass->adapter_luid = cdata->adapter_luid;
+
+  gst_caps_unref (cdata->sink_caps);
+  gst_caps_unref (cdata->src_caps);
+  g_free (cdata);
+
+  gst_type_mark_as_plugin_api (GST_TYPE_AMF_AV1_ENC_USAGE,
+      (GstPluginAPIFlags) 0);
+  gst_type_mark_as_plugin_api (GST_TYPE_AMF_AV1_ENC_RATE_CONTROL,
+      (GstPluginAPIFlags) 0);
+  gst_type_mark_as_plugin_api (GST_TYPE_AMF_AV1_ENC_PRESET,
+      (GstPluginAPIFlags) 0);
+}
+
+static void
+gst_amf_av1_enc_init (GstAmfAv1Enc * self)
+{
+  GstAmfAv1EncClass *klass = GST_AMF_AV1_ENC_GET_CLASS (self);
+  GstAmfAv1EncDeviceCaps *dev_caps = &klass->dev_caps;
+
+  gst_amf_encoder_set_subclass_data (GST_AMF_ENCODER (self),
+      klass->adapter_luid, AMFVideoEncoder_AV1);
+
+  g_mutex_init (&self->prop_lock);
+
+  self->usage = DEFAULT_USAGE;
+  self->rate_control = DEFAULT_RATE_CONTROL;
+  self->preset = DEFAULT_PRESET;
+  self->bitrate = DEFAULT_BITRATE;
+  self->max_bitrate = DEFAULT_MAX_BITRATE;
+  self->gop_size = (guint) dev_caps->default_gop_size;
+  self->min_qp_i = DEFAULT_MIN_MAX_QP;
+  self->max_qp_i = DEFAULT_MIN_MAX_QP;
+  self->min_qp_p = DEFAULT_MIN_MAX_QP;
+  self->max_qp_p = DEFAULT_MIN_MAX_QP;
+  self->qp_i = (guint) dev_caps->default_qp_i;
+  self->qp_p = (guint) dev_caps->default_qp_p;
+  self->ref_frames = DEFAULT_REF_FRAMES;
+}
+
+static void
+gst_amf_av1_enc_finalize (GObject * object)
+{
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (object);
+
+  g_mutex_clear (&self->prop_lock);
+
+  G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+update_int (GstAmfAv1Enc * self, gint * old_val, const GValue * new_val)
+{
+  gint val = g_value_get_int (new_val);
+
+  if (*old_val == val)
+    return;
+
+  *old_val = val;
+  self->property_updated = TRUE;
+}
+
+static void
+update_uint (GstAmfAv1Enc * self, guint * old_val, const GValue * new_val)
+{
+  guint val = g_value_get_uint (new_val);
+
+  if (*old_val == val)
+    return;
+
+  *old_val = val;
+  self->property_updated = TRUE;
+}
+
+static void
+update_enum (GstAmfAv1Enc * self, gint * old_val, const GValue * new_val)
+{
+  gint val = g_value_get_enum (new_val);
+
+  if (*old_val == val)
+    return;
+
+  *old_val = val;
+  self->property_updated = TRUE;
+}
+
+static void
+gst_amf_av1_enc_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (object);
+
+  g_mutex_lock (&self->prop_lock);
+  switch (prop_id) {
+    case PROP_USAGE:
+      update_enum (self, &self->usage, value);
+      break;
+    case PROP_RATE_CONTROL:
+      update_enum (self, &self->rate_control, value);
+      break;
+    case PROP_PRESET:
+      update_enum (self, &self->preset, value);
+      break;
+    case PROP_BITRATE:
+      update_uint (self, &self->bitrate, value);
+      break;
+    case PROP_MAX_BITRATE:
+      update_uint (self, &self->max_bitrate, value);
+      break;
+    case PROP_GOP_SIZE:
+      update_uint (self, &self->gop_size, value);
+      break;
+    case PROP_MIN_QP_I:
+      update_int (self, &self->min_qp_i, value);
+      break;
+    case PROP_MAX_QP_I:
+      update_int (self, &self->max_qp_i, value);
+      break;
+    case PROP_MIN_QP_P:
+      update_int (self, &self->min_qp_p, value);
+      break;
+    case PROP_MAX_QP_P:
+      update_int (self, &self->max_qp_p, value);
+      break;
+    case PROP_QP_I:
+      update_uint (self, &self->qp_i, value);
+      break;
+    case PROP_QP_P:
+      update_uint (self, &self->qp_p, value);
+      break;
+    case PROP_REF_FRAMES:
+      update_uint (self, &self->ref_frames, value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+  g_mutex_unlock (&self->prop_lock);
+}
+
+static void
+gst_amf_av1_enc_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstAmfAv1EncClass *klass = GST_AMF_AV1_ENC_GET_CLASS (object);
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (object);
+
+  switch (prop_id) {
+    case PROP_ADAPTER_LUID:
+      g_value_set_int64 (value, klass->adapter_luid);
+      break;
+    case PROP_USAGE:
+      g_value_set_enum (value, self->usage);
+      break;
+    case PROP_RATE_CONTROL:
+      g_value_set_enum (value, self->rate_control);
+      break;
+    case PROP_PRESET:
+      g_value_set_enum (value, self->preset);
+      break;
+    case PROP_BITRATE:
+      g_value_set_uint (value, self->bitrate);
+      break;
+    case PROP_MAX_BITRATE:
+      g_value_set_uint (value, self->max_bitrate);
+      break;
+    case PROP_GOP_SIZE:
+      g_value_set_uint (value, self->gop_size);
+      break;
+    case PROP_MIN_QP_I:
+      g_value_set_int (value, self->min_qp_i);
+      break;
+    case PROP_MAX_QP_I:
+      g_value_set_int (value, self->max_qp_i);
+      break;
+    case PROP_MIN_QP_P:
+      g_value_set_int (value, self->min_qp_p);
+      break;
+    case PROP_MAX_QP_P:
+      g_value_set_int (value, self->max_qp_p);
+      break;
+    case PROP_QP_I:
+      g_value_set_uint (value, self->qp_i);
+      break;
+    case PROP_QP_P:
+      g_value_set_uint (value, self->qp_p);
+      break;
+    case PROP_REF_FRAMES:
+      g_value_set_uint (value, self->ref_frames);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static gboolean
+gst_amf_av1_enc_set_format (GstAmfEncoder * encoder,
+    GstVideoCodecState * state, gpointer component)
+{
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (encoder);
+  AMFComponent *comp = (AMFComponent *) component;
+  GstVideoInfo *info = &state->info;
+  AMF_RESULT result;
+  AMFRate framerate;
+  amf_int64 int64_val = 0;
+  AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_ENUM rc_mode;
+
+  g_mutex_lock (&self->prop_lock);
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_FRAMESIZE,
+      AMFConstructSize (info->width, info->height));
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set frame size, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_USAGE,
+      (amf_int64) self->usage);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set usage, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  if (self->preset > AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_UNKNOWN) {
+    result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET,
+        (amf_int64) self->preset);
+    if (result != AMF_OK) {
+      GST_ERROR_OBJECT (self, "Failed to set quality preset, result %"
+          GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+      goto error;
+    }
+  }
+
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_PROFILE,
+      (amf_int64) AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set profile, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE,
+      (amf_int64) AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set alignment mode, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_MAX_NUM_REFRAMES,
+      (amf_int64) self->ref_frames);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set ref-frames, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  result = comp->Init (AMF_SURFACE_NV12, info->width, info->height);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to init component, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  if (self->rate_control != AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN) {
+    result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD,
+        (amf_int64) self->rate_control);
+    if (result != AMF_OK) {
+      GST_ERROR_OBJECT (self, "Failed to set rate-control, result %"
+          GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+      goto error;
+    }
+  }
+
+  result = comp->GetProperty (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD,
+      &int64_val);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to get rate-control method, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  rc_mode = (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_ENUM) int64_val;
+  if (self->min_qp_i >= 0) {
+    comp->SetProperty (AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA,
+        (amf_int64) self->min_qp_i);
+  }
+  if (self->max_qp_i >= 0) {
+    comp->SetProperty (AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA,
+        (amf_int64) self->max_qp_i);
+  }
+  if (self->min_qp_p >= 0) {
+    comp->SetProperty (AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER,
+        (amf_int64) self->min_qp_p);
+  }
+  if (self->max_qp_p >= 0) {
+    comp->SetProperty (AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER,
+        (amf_int64) self->max_qp_p);
+  }
+
+  comp->SetProperty (AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA,
+      (amf_int64) self->qp_i);
+  comp->SetProperty (AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER,
+      (amf_int64) self->qp_p);
+
+  switch (rc_mode) {
+    case AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR:
+      if (self->bitrate > 0) {
+        comp->SetProperty (AMF_VIDEO_ENCODER_AV1_TARGET_BITRATE,
+            (amf_int64) self->bitrate * 1000);
+        comp->SetProperty (AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE,
+            (amf_int64) self->bitrate * 1000);
+      }
+      break;
+    case AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR:
+    case AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR:
+      if (self->bitrate > 0) {
+        comp->SetProperty (AMF_VIDEO_ENCODER_AV1_TARGET_BITRATE,
+            (amf_int64) self->bitrate * 1000);
+      }
+      if (self->max_bitrate > 0) {
+        comp->SetProperty (AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE,
+            (amf_int64) self->max_bitrate * 1000);
+      }
+      break;
+    default:
+      break;
+  }
+
+  /* Disable frame skip for now, need investigation the behavior */
+  result =
+      comp->SetProperty (AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME,
+      (amf_bool) false);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to disable skip frame, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  if (info->fps_n > 0 && info->fps_d) {
+    framerate = AMFConstructRate (info->fps_n, info->fps_d);
+  } else {
+    framerate = AMFConstructRate (25, 1);
+  }
+
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_FRAMERATE, framerate);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set frame rate, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  result = comp->SetProperty (AMF_VIDEO_ENCODER_AV1_GOP_SIZE,
+      (amf_int64) self->gop_size);
+  if (result != AMF_OK) {
+    GST_ERROR_OBJECT (self, "Failed to set gop-size, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    goto error;
+  }
+
+  self->property_updated = FALSE;
+  g_mutex_unlock (&self->prop_lock);
+
+  return TRUE;
+
+error:
+  g_mutex_unlock (&self->prop_lock);
+
+  return FALSE;
+}
+
+static gboolean
+gst_amf_av1_enc_set_output_state (GstAmfEncoder * encoder,
+    GstVideoCodecState * state, gpointer component)
+{
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (encoder);
+  GstVideoCodecState *output_state;
+  GstCaps *caps;
+  GstTagList *tags;
+
+  caps = gst_caps_from_string ("video/x-av1, profile = (string) main, "
+      "alignment = (string) tu");
+  output_state = gst_video_encoder_set_output_state (GST_VIDEO_ENCODER (self),
+      caps, state);
+
+  GST_INFO_OBJECT (self, "Output caps: %" GST_PTR_FORMAT, output_state->caps);
+  gst_video_codec_state_unref (output_state);
+
+  tags = gst_tag_list_new_empty ();
+  gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_ENCODER,
+      "amfav1enc", nullptr);
+
+  gst_video_encoder_merge_tags (GST_VIDEO_ENCODER (encoder),
+      tags, GST_TAG_MERGE_REPLACE);
+  gst_tag_list_unref (tags);
+
+  return TRUE;
+}
+
+static gboolean
+gst_amf_av1_enc_set_surface_prop (GstAmfEncoder * encoder,
+    GstVideoCodecFrame * frame, gpointer surface)
+{
+  AMFSurface *surf = (AMFSurface *) surface;
+  AMF_RESULT result;
+
+  if (GST_VIDEO_CODEC_FRAME_IS_FORCE_KEYFRAME (frame)) {
+    amf_int64 type = (amf_int64) AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_NONE;
+    result = surf->SetProperty (AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE, type);
+    if (result != AMF_OK) {
+      GST_WARNING_OBJECT (encoder, "Failed to set force frame type, result %"
+          GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    }
+  }
+  return TRUE;
+}
+
+static GstBuffer *
+gst_amf_av1_enc_create_output_buffer (GstAmfEncoder * encoder,
+    gpointer data, gboolean * sync_point)
+{
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (encoder);
+  AMFBuffer *amf_buf = (AMFBuffer *) data;
+  GstBuffer *buf;
+  guint8 *data_ptr;
+  gsize data_size;
+  amf_int64 output_type = 0;
+  AMF_RESULT result;
+
+  data_ptr = (guint8 *) amf_buf->GetNative ();
+  data_size = amf_buf->GetSize ();
+
+  if (!data_ptr || data_size == 0) {
+    GST_WARNING_OBJECT (self, "Empty buffer");
+    return nullptr;
+  }
+
+  buf = gst_buffer_new_memdup (data_ptr, data_size);
+
+  result = amf_buf->GetProperty (AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE,
+      &output_type);
+  if (result == AMF_OK &&
+      output_type == (amf_int64) AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY) {
+    *sync_point = TRUE;
+  }
+
+  return buf;
+}
+
+static gboolean
+gst_amf_av1_enc_check_reconfigure (GstAmfEncoder * encoder)
+{
+  GstAmfAv1Enc *self = GST_AMF_AV1_ENC (encoder);
+  gboolean ret;
+
+  g_mutex_lock (&self->prop_lock);
+  ret = self->property_updated;
+  g_mutex_unlock (&self->prop_lock);
+
+  return ret;
+}
+
+static GstAmfAv1EncClassData *
+gst_amf_av1_enc_create_class_data (GstD3D11Device * device, AMFComponent * comp)
+{
+  AMF_RESULT result;
+  GstAmfAv1EncDeviceCaps dev_caps = { 0, };
+  std::string sink_caps_str;
+  std::string src_caps_str;
+  std::vector < std::string > profiles;
+  std::string resolution_str;
+  GstAmfAv1EncClassData *cdata;
+  AMFCapsPtr amf_caps;
+  AMFIOCapsPtr in_iocaps;
+  AMFIOCapsPtr out_iocaps;
+  amf_int32 in_min_width = 0, in_max_width = 0;
+  amf_int32 in_min_height = 0, in_max_height = 0;
+  amf_int32 out_min_width = 0, out_max_width = 0;
+  amf_int32 out_min_height = 0, out_max_height = 0;
+  amf_int32 num_val;
+  gboolean have_nv12 = FALSE;
+  gboolean d3d11_supported = FALSE;
+  gint min_width, max_width, min_height, max_height;
+  GstCaps *sink_caps;
+  GstCaps *system_caps;
+
+  result = comp->GetCaps (&amf_caps);
+  if (result != AMF_OK) {
+    GST_WARNING_OBJECT (device, "Unable to get caps");
+    return nullptr;
+  }
+
+  result = amf_caps->GetInputCaps (&in_iocaps);
+  if (result != AMF_OK) {
+    GST_WARNING_OBJECT (device, "Unable to get input io caps");
+    return nullptr;
+  }
+
+  in_iocaps->GetWidthRange (&in_min_width, &in_max_width);
+  in_iocaps->GetHeightRange (&in_min_height, &in_max_height);
+  dev_caps.valign = in_iocaps->GetVertAlign ();
+
+  GST_INFO_OBJECT (device, "Input width: [%d, %d], height: [%d, %d], "
+      "valign: %d", in_min_width, in_max_width, in_min_height, in_max_height,
+      dev_caps.valign);
+
+  num_val = in_iocaps->GetNumOfFormats ();
+  GST_LOG_OBJECT (device, "Input format count: %d", num_val);
+  for (amf_int32 i = 0; i < num_val; i++) {
+    AMF_SURFACE_FORMAT format;
+    amf_bool native;
+
+    result = in_iocaps->GetFormatAt (i, &format, &native);
+    if (result != AMF_OK)
+      continue;
+
+    GST_INFO_OBJECT (device, "Format %d supported, native %d", format, native);
+    if (format == AMF_SURFACE_NV12)
+      have_nv12 = TRUE;
+  }
+
+  if (!have_nv12) {
+    GST_WARNING_OBJECT (device, "NV12 is not supported");
+    return nullptr;
+  }
+
+  num_val = in_iocaps->GetNumOfMemoryTypes ();
+  GST_LOG_OBJECT (device, "Input memory type count: %d", num_val);
+  for (amf_int32 i = 0; i < num_val; i++) {
+    AMF_MEMORY_TYPE type;
+    amf_bool native;
+
+    result = in_iocaps->GetMemoryTypeAt (i, &type, &native);
+    if (result != AMF_OK)
+      continue;
+
+    GST_INFO_OBJECT (device,
+        "MemoryType %d supported, native %d", type, native);
+    if (type == AMF_MEMORY_DX11)
+      d3d11_supported = TRUE;
+  }
+
+  if (!d3d11_supported) {
+    GST_WARNING_OBJECT (device, "D3D11 is not supported");
+    return nullptr;
+  }
+
+  result = amf_caps->GetOutputCaps (&out_iocaps);
+  if (result != AMF_OK) {
+    GST_WARNING_OBJECT (device, "Unable to get input io caps");
+    return nullptr;
+  }
+
+  out_iocaps->GetWidthRange (&out_min_width, &out_max_width);
+  out_iocaps->GetHeightRange (&out_min_height, &out_max_height);
+
+  GST_INFO_OBJECT (device, "Output width: [%d, %d], height: [%d, %d]",
+      in_min_width, in_max_width, in_min_height, in_max_height);
+
+#define QUERY_CAPS_PROP(prop,val) G_STMT_START { \
+  amf_int64 _val = 0; \
+  result = amf_caps->GetProperty (prop, &_val); \
+  if (result == AMF_OK) { \
+    GST_INFO_OBJECT (device, G_STRINGIFY (val) ": %" G_GINT64_FORMAT, _val); \
+    dev_caps.val = _val; \
+  } \
+} G_STMT_END
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_NUM_OF_HW_INSTANCES,
+      num_of_hw_instances);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_MAX_THROUGHPUT, max_throughput);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_REQUESTED_THROUGHPUT,
+      requested_throughput);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_COLOR_CONVERSION,
+      color_conversion);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_PRE_ANALYSIS, pre_analysis);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_MAX_BITRATE, max_bitrate);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_MAX_PROFILE, max_profile);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_MAX_LEVEL, max_level);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_TEMPORAL_LAYERS,
+      max_num_temporal_layers);
+  QUERY_CAPS_PROP (AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_LTR_FRAMES,
+      max_num_ltr_frames);
+
+#undef QUERY_CAPS_PROP
+
+#define QUERY_DEFAULT_PROP(prop,val,default_val) G_STMT_START { \
+  const AMFPropertyInfo *pinfo = nullptr; \
+  result = comp->GetPropertyInfo (prop, &pinfo); \
+  if (result == AMF_OK && pinfo) { \
+    dev_caps.val = AMFVariantGetInt64 (&pinfo->defaultValue); \
+    GST_INFO_OBJECT (device, G_STRINGIFY (val) ": %" G_GINT64_FORMAT, \
+        dev_caps.val); \
+  } else { \
+    dev_caps.val = default_val; \
+  } \
+} G_STMT_END
+
+  QUERY_DEFAULT_PROP (AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA, default_qp_i, 26);
+  QUERY_DEFAULT_PROP (AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER, default_qp_p, 26);
+#undef QUERY_DEFAULT_PROP
+
+  {
+    const AMFPropertyInfo *pinfo = nullptr;
+    result = comp->GetPropertyInfo (AMF_VIDEO_ENCODER_AV1_GOP_SIZE, &pinfo);
+    if (result == AMF_OK && pinfo) {
+      dev_caps.default_gop_size = AMFVariantGetInt64 (&pinfo->defaultValue);
+      dev_caps.min_gop_size = AMFVariantGetInt64 (&pinfo->minValue);
+      dev_caps.max_gop_size = AMFVariantGetInt64 (&pinfo->maxValue);
+      GST_INFO_OBJECT (device, "gop-size: default %d, min %d, max %d",
+          (guint) dev_caps.default_gop_size,
+          (guint) dev_caps.min_gop_size, (guint) dev_caps.max_gop_size);
+    } else {
+      dev_caps.default_gop_size = 30;
+      dev_caps.min_gop_size = 0;
+      dev_caps.max_gop_size = G_MAXINT;
+    }
+  }
+
+  min_width = MAX (in_min_width, 1);
+  max_width = in_max_width;
+  if (max_width == 0) {
+    GST_WARNING_OBJECT (device, "Unknown max width, assuming 4096");
+    max_width = 4096;
+  }
+
+  min_height = MAX (in_min_height, 1);
+  max_height = in_max_height;
+  if (max_height == 0) {
+    GST_WARNING_OBJECT (device, "Unknown max height, assuming 4096");
+    max_height = 4096;
+  }
+
+  resolution_str = "width = (int) [ " + std::to_string (min_width)
+      + ", " + std::to_string (max_width) + " ]";
+  resolution_str += ", height = (int) [ " + std::to_string (min_height)
+      + ", " + std::to_string (max_height) + " ]";
+
+  sink_caps_str = "video/x-raw, format = (string) NV12, " + resolution_str;
+  src_caps_str = "video/x-av1, " + resolution_str + ", profile = (string) main, "
+      "alignment = (string) tu";
+
+  system_caps = gst_caps_from_string (sink_caps_str.c_str ());
+  sink_caps = gst_caps_copy (system_caps);
+  gst_caps_set_features (sink_caps, 0,
+      gst_caps_features_new (GST_CAPS_FEATURE_MEMORY_D3D11_MEMORY, nullptr));
+  gst_caps_append (sink_caps, system_caps);
+
+  cdata = g_new0 (GstAmfAv1EncClassData, 1);
+  cdata->sink_caps = sink_caps;
+  cdata->src_caps = gst_caps_from_string (src_caps_str.c_str ());
+  cdata->dev_caps = dev_caps;
+  g_object_get (device, "adapter-luid", &cdata->adapter_luid, nullptr);
+
+  GST_MINI_OBJECT_FLAG_SET (cdata->sink_caps,
+      GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
+  GST_MINI_OBJECT_FLAG_SET (cdata->src_caps,
+      GST_MINI_OBJECT_FLAG_MAY_BE_LEAKED);
+
+  GST_DEBUG_OBJECT (device, "Sink caps %" GST_PTR_FORMAT, cdata->sink_caps);
+  GST_DEBUG_OBJECT (device, "Src caps %" GST_PTR_FORMAT, cdata->src_caps);
+
+  return cdata;
+}
+
+void
+gst_amf_av1_enc_register_d3d11 (GstPlugin * plugin, GstD3D11Device * device,
+    gpointer context, guint rank)
+{
+  GstAmfAv1EncClassData *cdata;
+  AMFContext *amf_context = (AMFContext *) context;
+  AMFFactory *factory = (AMFFactory *) gst_amf_get_factory ();
+  AMFComponentPtr comp;
+  AMF_RESULT result;
+
+  GST_DEBUG_CATEGORY_INIT (gst_amf_av1_enc_debug, "amfav1enc", 0, "amfav1enc");
+
+  result = factory->CreateComponent (amf_context, AMFVideoEncoder_AV1, &comp);
+  if (result != AMF_OK) {
+    GST_WARNING_OBJECT (device, "Failed to create component, result %"
+        GST_AMF_RESULT_FORMAT, GST_AMF_RESULT_ARGS (result));
+    return;
+  }
+
+  cdata = gst_amf_av1_enc_create_class_data (device, comp.GetPtr ());
+  if (!cdata)
+    return;
+
+  GType type;
+  gchar *type_name;
+  gchar *feature_name;
+  GTypeInfo type_info = {
+    sizeof (GstAmfAv1EncClass),
+    nullptr,
+    nullptr,
+    (GClassInitFunc) gst_amf_av1_enc_class_init,
+    nullptr,
+    cdata,
+    sizeof (GstAmfAv1Enc),
+    0,
+    (GInstanceInitFunc) gst_amf_av1_enc_init,
+  };
+
+  type_name = g_strdup ("GstAmfAv1Enc");
+  feature_name = g_strdup ("amfav1enc");
+
+  gint index = 0;
+  while (g_type_from_name (type_name)) {
+    index++;
+    g_free (type_name);
+    g_free (feature_name);
+    type_name = g_strdup_printf ("GstAmfAv1Device%dEnc", index);
+    feature_name = g_strdup_printf ("amfav1device%denc", index);
+  }
+
+  type = g_type_register_static (GST_TYPE_AMF_ENCODER, type_name,
+      &type_info, (GTypeFlags) 0);
+
+  if (rank > 0 && index != 0)
+    rank--;
+
+  if (index != 0)
+    gst_element_type_set_skip_documentation (type);
+
+  if (!gst_element_register (plugin, feature_name, rank, type))
+    GST_WARNING ("Failed to register plugin '%s'", type_name);
+
+  g_free (type_name);
+  g_free (feature_name);
+}
diff --git a/subprojects/gst-plugins-bad/sys/amfcodec/gstamfav1enc.h b/subprojects/gst-plugins-bad/sys/amfcodec/gstamfav1enc.h
new file mode 100644 (file)
index 0000000..93cc2f7
--- /dev/null
@@ -0,0 +1,29 @@
+/* GStreamer
+ * Copyright (C) 2022 Seungha Yang <seungha@centricular.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include "gstamfencoder.h"
+#include <gst/d3d11/gstd3d11.h>
+
+G_BEGIN_DECLS
+    void gst_amf_av1_enc_register_d3d11 (GstPlugin * plugin,
+    GstD3D11Device * device, gpointer context, guint rank);
+
+G_END_DECLS
diff --git a/subprojects/gst-plugins-bad/sys/amfcodec/include/components/VideoEncoderAV1.h b/subprojects/gst-plugins-bad/sys/amfcodec/include/components/VideoEncoderAV1.h
new file mode 100644 (file)
index 0000000..0b02009
--- /dev/null
@@ -0,0 +1,292 @@
+//
+// Copyright (c) 2021-2022 Advanced Micro Devices, Inc. All rights reserved.
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+//
+
+//-------------------------------------------------------------------------------------------------
+//  VideoEncoderHW_AV1 interface declaration
+//-------------------------------------------------------------------------------------------------
+
+#ifndef AMF_VideoEncoderAV1_h
+#define AMF_VideoEncoderAV1_h
+#pragma once
+
+#include "Component.h"
+#include "ColorSpace.h"
+#include "PreAnalysis.h"
+
+#define AMFVideoEncoder_AV1 L"AMFVideoEncoderHW_AV1"
+
+enum AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_NONE                    = 0,    // No encoding latency requirement. Encoder will balance encoding time and power consumption.
+    AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_POWER_SAVING_REAL_TIME  = 1,    // Try the best to finish encoding a frame within 1/framerate sec. This mode may cause more power consumption
+    AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_REAL_TIME               = 2,    // Try the best to finish encoding a frame within 1/(2 x framerate) sec. This mode will cause more power consumption than POWER_SAVING_REAL_TIME
+    AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_LOWEST_LATENCY          = 3     // Encoding as fast as possible. This mode causes highest power consumption.
+};
+
+enum AMF_VIDEO_ENCODER_AV1_USAGE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_USAGE_TRANSCODING     = 0,
+    AMF_VIDEO_ENCODER_AV1_USAGE_LOW_LATENCY     = 1
+};
+
+enum AMF_VIDEO_ENCODER_AV1_PROFILE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_PROFILE_MAIN = 1
+};
+
+enum AMF_VIDEO_ENCODER_AV1_LEVEL_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_LEVEL_2_0 = 0,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_2_1 = 1,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_2_2 = 2,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_2_3 = 3,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_3_0 = 4,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_3_1 = 5,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_3_2 = 6,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_3_3 = 7,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_4_0 = 8,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_4_1 = 9,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_4_2 = 10,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_4_3 = 11,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_5_0 = 12,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_5_1 = 13,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_5_2 = 14,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_5_3 = 15,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_6_0 = 16,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_6_1 = 17,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_6_2 = 18,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_6_3 = 19,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_7_0 = 20,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_7_1 = 21,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_7_2 = 22,
+    AMF_VIDEO_ENCODER_AV1_LEVEL_7_3 = 23
+};
+
+enum AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_UNKNOWN                   = -1,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CONSTANT_QP               = 0,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_LATENCY_CONSTRAINED_VBR   = 1,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_PEAK_CONSTRAINED_VBR      = 2,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_CBR                       = 3,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_QUALITY_VBR               = 4,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_VBR          = 5,
+    AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_HIGH_QUALITY_CBR          = 6
+};
+
+enum AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY               = 1,
+    AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_1080P_CODED_1082   = 2,
+    AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_NO_RESTRICTIONS          = 3
+};
+
+enum AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_NONE             = 0,
+    AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_KEY              = 1,
+    AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_INTRA_ONLY       = 2,
+    AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_SWITCH           = 3,
+    AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_SHOW_EXISTING    = 4
+};
+
+enum AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_KEY             = 0,
+    AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTRA_ONLY      = 1,
+    AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_INTER           = 2,
+    AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SWITCH          = 3,
+    AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_SHOW_EXISTING   = 4
+};
+
+enum AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_HIGH_QUALITY   = 0,    
+    AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_QUALITY        = 30,    
+    AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_BALANCED       = 70,
+    AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_SPEED          = 100
+};
+
+enum AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_NONE                = 0,
+    AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_GOP_ALIGNED         = 1,
+    AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_KEY_FRAME_ALIGNED   = 2
+};
+
+enum AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_NONE              = 0,
+    AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_FIXED_INTERVAL    = 1
+};
+
+enum AMF_VIDEO_ENCODER_AV1_CDEF_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_CDEF_DISABLE          = 0,
+    AMF_VIDEO_ENCODER_AV1_CDEF_ENABLE_DEFAULT   = 1
+};
+
+enum AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_DISABLE         = 0,
+    AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_ENABLE_DEFAULT  = 1
+};
+
+enum AMF_VIDEO_ENCODER_AV1_AQ_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_AQ_MODE_NONE = 0,
+    AMF_VIDEO_ENCODER_AV1_AQ_MODE_CAQ  = 1              // Content adaptive quantization mode
+};
+
+enum AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE_ENUM
+{
+    AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__DISABLED = 0,
+    AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__GOP_ALIGNED = 1,
+    AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__CONTINUOUS = 2
+};
+
+
+// *** Static properties - can be set only before Init() *** 
+
+// Encoder Engine Settings
+#define AMF_VIDEO_ENCODER_AV1_ENCODER_INSTANCE_INDEX                L"Av1EncoderInstanceIndex"          // amf_int64; default = 0; selected HW instance idx. The number of instances is queried by using AMF_VIDEO_ENCODER_AV1_CAP_NUM_OF_HW_INSTANCES
+#define AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE                 L"Av1EncodingLatencyMode"           // amf_int64(AMF_VIDEO_ENCODER_AV1_ENCODING_LATENCY_MODE_ENUM); default = depends on USAGE; The encoding latency mode. 
+#define AMF_VIDEO_ENCODER_AV1_QUERY_TIMEOUT                         L"Av1QueryTimeout"                  // amf_int64; default = 0 (no wait); timeout for QueryOutput call in ms.
+
+// Usage Settings
+#define AMF_VIDEO_ENCODER_AV1_USAGE                                 L"Av1Usage"                         // amf_int64(AMF_VIDEO_ENCODER_AV1_USAGE_ENUM); default = N/A; Encoder usage. fully configures parameter set.
+
+// Session Configuration
+#define AMF_VIDEO_ENCODER_AV1_FRAMESIZE                             L"Av1FrameSize"                     // AMFSize; default = 0,0; Frame size
+#define AMF_VIDEO_ENCODER_AV1_COLOR_BIT_DEPTH                       L"Av1ColorBitDepth"                 // amf_int64(AMF_COLOR_BIT_DEPTH_ENUM); default = AMF_COLOR_BIT_DEPTH_8
+#define AMF_VIDEO_ENCODER_AV1_PROFILE                               L"Av1Profile"                       // amf_int64(AMF_VIDEO_ENCODER_AV1_PROFILE_ENUM) ; default = depends on USAGE; the codec profile of the coded bitstream
+#define AMF_VIDEO_ENCODER_AV1_LEVEL                                 L"Av1Level"                         // amf_int64 (AMF_VIDEO_ENCODER_AV1_LEVEL_ENUM); default = depends on USAGE; the codec level of the coded bitstream
+#define AMF_VIDEO_ENCODER_AV1_TILES_PER_FRAME                       L"Av1NumTilesPerFrame"              // amf_int64; default = 1; Number of tiles Per Frame. This is treated as suggestion. The actual number of tiles might be different due to compliance or encoder limitation.
+#define AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET                        L"Av1QualityPreset"                 // amf_int64(AMF_VIDEO_ENCODER_AV1_QUALITY_PRESET_ENUM); default = depends on USAGE; Quality Preset
+
+// Codec Configuration
+#define AMF_VIDEO_ENCODER_AV1_SCREEN_CONTENT_TOOLS                  L"Av1ScreenContentTools"            // bool; default = depends on USAGE; If true, allow enabling screen content tools by AMF_VIDEO_ENCODER_AV1_PALETTE_MODE and AMF_VIDEO_ENCODER_AV1_FORCE_INTEGER_MV; if false, all screen content tools are disabled.
+#define AMF_VIDEO_ENCODER_AV1_ORDER_HINT                            L"Av1OrderHint"                     // bool; default = depends on USAGE; If true, code order hint; if false, don't code order hint
+#define AMF_VIDEO_ENCODER_AV1_FRAME_ID                              L"Av1FrameId"                       // bool; default = depends on USAGE; If true, code frame id; if false, don't code frame id
+#define AMF_VIDEO_ENCODER_AV1_TILE_GROUP_OBU                        L"Av1TileGroupObu"                  // bool; default = depends on USAGE; If true, code FrameHeaderObu + TileGroupObu and each TileGroupObu contains one tile; if false, code FrameObu.
+#define AMF_VIDEO_ENCODER_AV1_CDEF_MODE                             L"Av1CdefMode"                      // amd_int64(AMF_VIDEO_ENCODER_AV1_CDEF_MODE_ENUM); default = depends on USAGE; Cdef mode
+#define AMF_VIDEO_ENCODER_AV1_ERROR_RESILIENT_MODE                  L"Av1ErrorResilientMode"            // bool; default = depends on USAGE; If true, enable error resilient mode; if false, disable error resilient mode
+
+// Rate Control and Quality Enhancement
+#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD                   L"Av1RateControlMethod"             // amf_int64(AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_METHOD_ENUM); default = depends on USAGE; Rate Control Method
+#define AMF_VIDEO_ENCODER_AV1_QVBR_QUALITY_LEVEL                    L"Av1QvbrQualityLevel"              // amf_int64; default = 23; QVBR quality level; range = 1-51
+#define AMF_VIDEO_ENCODER_AV1_INITIAL_VBV_BUFFER_FULLNESS           L"Av1InitialVBVBufferFullness"      // amf_int64; default = depends on USAGE; Initial VBV Buffer Fullness 0=0% 64=100%
+
+// Alignment Mode Configuration
+#define AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE                        L"Av1AlignmentMode"                 // amf_int64(AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_ENUM); default = AMF_VIDEO_ENCODER_AV1_ALIGNMENT_MODE_64X16_ONLY; Alignment Mode.
+
+#define AMF_VIDEO_ENCODER_AV1_PRE_ANALYSIS_ENABLE                   L"Av1EnablePreAnalysis"             // bool; default = depends on USAGE; If true, enables the pre-analysis module. Refer to AMF Video PreAnalysis API reference for more details. If false, disable the pre-analysis module.
+#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_PREENCODE                L"Av1RateControlPreEncode"          // bool; default = depends on USAGE; If true, enables pre-encode assist in rate control; if false, disables pre-encode assist in rate control.
+#define AMF_VIDEO_ENCODER_AV1_HIGH_MOTION_QUALITY_BOOST             L"Av1HighMotionQualityBoost"        // bool; default = depends on USAGE; If true, enable high motion quality boost mode; if false, disable high motion quality boost mode.
+#define AMF_VIDEO_ENCODER_AV1_AQ_MODE                               L"Av1AQMode"                        // amd_int64(AMF_VIDEO_ENCODER_AV1_AQ_MODE_ENUM); default = depends on USAGE; AQ mode
+
+// Picture Management Configuration
+#define AMF_VIDEO_ENCODER_AV1_MAX_NUM_TEMPORAL_LAYERS               L"Av1MaxNumOfTemporalLayers"        // amf_int64; default = depends on USAGE; Max number of temporal layers might be enabled. The maximum value can be queried from AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_TEMPORAL_LAYERS
+#define AMF_VIDEO_ENCODER_AV1_MAX_LTR_FRAMES                        L"Av1MaxNumLTRFrames"               // amf_int64; default = depends on USAGE; Max number of LTR frames. The maximum value can be queried from AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_LTR_FRAMES
+#define AMF_VIDEO_ENCODER_AV1_MAX_NUM_REFRAMES                      L"Av1MaxNumRefFrames"               // amf_int64; default = 1; Maximum number of reference frames
+
+// color conversion
+#define AMF_VIDEO_ENCODER_AV1_INPUT_HDR_METADATA                    L"Av1InHDRMetadata"                 // AMFBuffer containing AMFHDRMetadata; default NULL
+
+// Miscellaneous
+#define AMF_VIDEO_ENCODER_AV1_EXTRA_DATA                            L"Av1ExtraData"                     // AMFInterface* - > AMFBuffer*; buffer to retrieve coded sequence header
+
+
+// *** Dynamic properties - can be set anytime *** 
+
+// Codec Configuration
+#define AMF_VIDEO_ENCODER_AV1_PALETTE_MODE                          L"Av1PaletteMode"                   // bool; default = depends on USAGE; If true, enable palette mode; if false, disable palette mode. Valid only when AMF_VIDEO_ENCODER_AV1_SCREEN_CONTENT_TOOLS is true.
+#define AMF_VIDEO_ENCODER_AV1_FORCE_INTEGER_MV                      L"Av1ForceIntegerMv"                // bool; default = depends on USAGE; If true, enable force integer MV; if false, disable force integer MV. Valid only when AMF_VIDEO_ENCODER_AV1_SCREEN_CONTENT_TOOLS is true.
+#define AMF_VIDEO_ENCODER_AV1_CDF_UPDATE                            L"Av1CdfUpdate"                     // bool; default = depends on USAGE; If true, enable CDF update; if false, disable CDF update.
+#define AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE             L"Av1CdfFrameEndUpdateMode"         // amd_int64(AMF_VIDEO_ENCODER_AV1_CDF_FRAME_END_UPDATE_MODE_ENUM); default = depends on USAGE; CDF frame end update mode
+
+
+// Rate Control and Quality Enhancement
+#define AMF_VIDEO_ENCODER_AV1_VBV_BUFFER_SIZE                       L"Av1VBVBufferSize"                 // amf_int64; default = depends on USAGE; VBV Buffer Size in bits
+#define AMF_VIDEO_ENCODER_AV1_FRAMERATE                             L"Av1FrameRate"                     // AMFRate; default = depends on usage; Frame Rate
+#define AMF_VIDEO_ENCODER_AV1_ENFORCE_HRD                           L"Av1EnforceHRD"                    // bool; default = depends on USAGE; If true, enforce HRD; if false, HRD is not enforced.
+#define AMF_VIDEO_ENCODER_AV1_FILLER_DATA                           L"Av1FillerData"                    // bool; default = depends on USAGE; If true, code filler data when needed; if false, don't code filler data.
+#define AMF_VIDEO_ENCODER_AV1_TARGET_BITRATE                        L"Av1TargetBitrate"                 // amf_int64; default = depends on USAGE; Target bit rate in bits
+#define AMF_VIDEO_ENCODER_AV1_PEAK_BITRATE                          L"Av1PeakBitrate"                   // amf_int64; default = depends on USAGE; Peak bit rate in bits
+
+#define AMF_VIDEO_ENCODER_AV1_MAX_COMPRESSED_FRAME_SIZE             L"Av1MaxCompressedFrameSize"        // amf_int64; default = 0; Max compressed frame Size in bits. 0 - no limit
+#define AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTRA                     L"Av1MinQIndex_Intra"               // amf_int64; default = depends on USAGE; Min QIndex for intra frames; range = 0-255
+#define AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTRA                     L"Av1MaxQIndex_Intra"               // amf_int64; default = depends on USAGE; Max QIndex for intra frames; range = 0-255
+#define AMF_VIDEO_ENCODER_AV1_MIN_Q_INDEX_INTER                     L"Av1MinQIndex_Inter"               // amf_int64; default = depends on USAGE; Min QIndex for inter frames; range = 0-255
+#define AMF_VIDEO_ENCODER_AV1_MAX_Q_INDEX_INTER                     L"Av1MaxQIndex_Inter"               // amf_int64; default = depends on USAGE; Max QIndex for inter frames; range = 0-255
+
+#define AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTRA                         L"Av1QIndex_Intra"                  // amf_int64; default = depends on USAGE; intra-frame QIndex; range = 0-255
+#define AMF_VIDEO_ENCODER_AV1_Q_INDEX_INTER                         L"Av1QIndex_Inter"                  // amf_int64; default = depends on USAGE; inter-frame QIndex; range = 0-255
+
+#define AMF_VIDEO_ENCODER_AV1_RATE_CONTROL_SKIP_FRAME               L"Av1RateControlSkipFrameEnable"    // bool; default = depends on USAGE; If true, rate control may code skip frame when needed; if false, rate control will not code skip frame.
+
+
+// Picture Management Configuration
+#define AMF_VIDEO_ENCODER_AV1_GOP_SIZE                              L"Av1GOPSize"                       // amf_int64; default = depends on USAGE; GOP Size (distance between automatically inserted key frames). If 0, key frame will be inserted at first frame only. Note that GOP may be interrupted by AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE.
+#define AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE                 L"Av1HeaderInsertionMode"           // amf_int64(AMF_VIDEO_ENCODER_AV1_HEADER_INSERTION_MODE_ENUM); default = depends on USAGE; sequence header insertion mode
+#define AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE           L"Av1SwitchFrameInsertionMode"      // amf_int64(AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_ENUM); default = depends on USAGE; switch frame insertin mode
+#define AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INTERVAL                 L"Av1SwitchFrameInterval"           // amf_int64; default = depends on USAGE; the interval between two inserted switch frames. Valid only when AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE is AMF_VIDEO_ENCODER_AV1_SWITCH_FRAME_INSERTION_MODE_FIXED_INTERVAL.
+#define AMF_VIDEO_ENCODER_AV1_NUM_TEMPORAL_LAYERS                   L"Av1NumTemporalLayers"             // amf_int64; default = depends on USAGE; Number of temporal layers. Can be changed at any time but the change is only applied when encoding next base layer frame.
+
+#define AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE                                       L"Av1IntraRefreshMode"              // amf_int64(AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE_ENUM); default AMF_VIDEO_ENCODER_AV1_INTRA_REFRESH_MODE__DISABLED
+#define AMF_VIDEO_ENCODER_AV1_INTRAREFRESH_STRIPES                                     L"Av1IntraRefreshNumOfStripes"      // amf_int64; default = N/A; Valid only when intra refresh is enabled.
+
+// color conversion
+#define AMF_VIDEO_ENCODER_AV1_INPUT_COLOR_PROFILE                   L"Av1InputColorProfile"             // amf_int64(AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM); default = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN - mean AUTO by size
+#define AMF_VIDEO_ENCODER_AV1_INPUT_TRANSFER_CHARACTERISTIC         L"Av1InputColorTransferChar"        // amf_int64(AMF_COLOR_TRANSFER_CHARACTERISTIC_ENUM); default = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, ISO/IEC 23001-8_2013 section 7.2 See VideoDecoderUVD.h for enum
+#define AMF_VIDEO_ENCODER_AV1_INPUT_COLOR_PRIMARIES                 L"Av1InputColorPrimaries"           // amf_int64(AMF_COLOR_PRIMARIES_ENUM); default = AMF_COLOR_PRIMARIES_UNDEFINED, ISO/IEC 23001-8_2013 section 7.1 See ColorSpace.h for enum
+
+#define AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PROFILE                  L"Av1OutputColorProfile"            // amf_int64(AMF_VIDEO_CONVERTER_COLOR_PROFILE_ENUM); default = AMF_VIDEO_CONVERTER_COLOR_PROFILE_UNKNOWN - mean AUTO by size
+#define AMF_VIDEO_ENCODER_AV1_OUTPUT_TRANSFER_CHARACTERISTIC        L"Av1OutputColorTransferChar"       // amf_int64(AMF_COLOR_TRANSFER_CHARACTERISTIC_ENUM); default = AMF_COLOR_TRANSFER_CHARACTERISTIC_UNDEFINED, ISO/IEC 23001-8_2013 ?7.2 See VideoDecoderUVD.h for enum
+#define AMF_VIDEO_ENCODER_AV1_OUTPUT_COLOR_PRIMARIES                L"Av1OutputColorPrimaries"          // amf_int64(AMF_COLOR_PRIMARIES_ENUM); default = AMF_COLOR_PRIMARIES_UNDEFINED, ISO/IEC 23001-8_2013 section 7.1 See ColorSpace.h for enum
+
+
+// Frame encode parameters
+#define AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE                      L"Av1ForceFrameType"                // amf_int64(AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_ENUM); default = AMF_VIDEO_ENCODER_AV1_FORCE_FRAME_TYPE_NONE; generate particular frame type
+#define AMF_VIDEO_ENCODER_AV1_FORCE_INSERT_SEQUENCE_HEADER          L"Av1ForceInsertSequenceHeader"     // bool; default = false; If true, force insert sequence header with current frame;
+#define AMF_VIDEO_ENCODER_AV1_MARK_CURRENT_WITH_LTR_INDEX           L"Av1MarkCurrentWithLTRIndex"       // amf_int64; default = N/A; Mark current frame with LTR index
+#define AMF_VIDEO_ENCODER_AV1_FORCE_LTR_REFERENCE_BITFIELD          L"Av1ForceLTRReferenceBitfield"     // amf_int64; default = 0; force LTR bit-field
+#define AMF_VIDEO_ENCODER_AV1_ROI_DATA                              L"Av1ROIData"                                          // 2D AMFSurface, surface format: AMF_SURFACE_GRAY32
+
+// Encode output parameters
+#define AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE                     L"Av1OutputFrameType"               // amf_int64(AMF_VIDEO_ENCODER_AV1_OUTPUT_FRAME_TYPE_ENUM); default = N/A
+#define AMF_VIDEO_ENCODER_AV1_OUTPUT_MARKED_LTR_INDEX               L"Av1MarkedLTRIndex"                // amf_int64; default = N/A; Marked LTR index
+#define AMF_VIDEO_ENCODER_AV1_OUTPUT_REFERENCED_LTR_INDEX_BITFIELD  L"Av1ReferencedLTRIndexBitfield"    // amf_int64; default = N/A; referenced LTR bit-field
+
+// AV1 Encoder capabilities - exposed in AMFCaps interface
+#define AMF_VIDEO_ENCODER_AV1_CAP_NUM_OF_HW_INSTANCES               L"Av1CapNumOfHwInstances"           // amf_int64; default = N/A; number of HW encoder instances
+#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_THROUGHPUT                    L"Av1CapMaxThroughput"              // amf_int64; default = N/A; MAX throughput for AV1 encoder in MB (16 x 16 pixel)
+#define AMF_VIDEO_ENCODER_AV1_CAP_REQUESTED_THROUGHPUT              L"Av1CapRequestedThroughput"        // amf_int64; default = N/A; Currently total requested throughput for AV1 encode in MB (16 x 16 pixel)
+#define AMF_VIDEO_ENCODER_AV1_CAP_COLOR_CONVERSION                  L"Av1CapColorConversion"            // amf_int64(AMF_ACCELERATION_TYPE); default = N/A; type of supported color conversion.
+#define AMF_VIDEO_ENCODER_AV1_CAP_PRE_ANALYSIS                      L"Av1PreAnalysis"                    // amf_bool - pre analysis module is available for AV1 UVE encoder, n/a for the other encoders
+#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_BITRATE                       L"Av1MaxBitrate"                    // amf_int64; default = N/A; Maximum bit rate in bits
+#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_PROFILE                       L"Av1MaxProfile"                    // amf_int64(AMF_VIDEO_ENCODER_AV1_PROFILE_ENUM); default = N/A; max value of code profile
+#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_LEVEL                         L"Av1MaxLevel"                      // amf_int64(AMF_VIDEO_ENCODER_AV1_LEVEL_ENUM); default = N/A; max value of codec level
+#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_TEMPORAL_LAYERS           L"Av1CapMaxNumTemporalLayers"       // amf_int64; default = N/A; The cap of maximum number of temporal layers
+#define AMF_VIDEO_ENCODER_AV1_CAP_MAX_NUM_LTR_FRAMES                L"Av1CapMaxNumLTRFrames"            // amf_int64; default = N/A; The cap of maximum number of LTR frames. This value is calculated based on current value of AMF_VIDEO_ENCODER_AV1_MAX_NUM_TEMPORAL_LAYERS.
+
+#endif //#ifndef AMF_VideoEncoderAV1_h
index adf5784..66018fc 100644 (file)
@@ -2,6 +2,7 @@ amf_sources = [
   'gstamfencoder.cpp',
   'gstamfh264enc.cpp',
   'gstamfh265enc.cpp',
+  'gstamfav1enc.cpp',
   'gstamfutils.cpp',
   'plugin.cpp',
 ]
index 825f3df..f549a0e 100644 (file)
@@ -35,6 +35,7 @@
 #include "gstamfutils.h"
 #include "gstamfh264enc.h"
 #include "gstamfh265enc.h"
+#include "gstamfav1enc.h"
 
 /* *INDENT-OFF* */
 using namespace Microsoft::WRL;
@@ -108,6 +109,8 @@ plugin_init (GstPlugin * plugin)
           (gpointer) context.GetPtr (), GST_RANK_PRIMARY);
       gst_amf_h265_enc_register_d3d11 (plugin, device,
           (gpointer) context.GetPtr (), GST_RANK_PRIMARY);
+      gst_amf_av1_enc_register_d3d11 (plugin, device,
+          (gpointer) context.GetPtr (), GST_RANK_NONE);
     }
 
     gst_clear_object (&device);