encoder: add properties API.
authorGwenole Beauchesne <gwenole.beauchesne@intel.com>
Mon, 6 Jan 2014 16:46:40 +0000 (17:46 +0100)
committerGwenole Beauchesne <gwenole.beauchesne@intel.com>
Mon, 13 Jan 2014 16:31:54 +0000 (17:31 +0100)
Add interface to communicate configurable properties to the encoder.
This covers both the common ones (rate-control, bitrate), and the
codec specific properties.

https://bugzilla.gnome.org/show_bug.cgi?id=719529

gst-libs/gst/vaapi/gstvaapiencoder.c
gst-libs/gst/vaapi/gstvaapiencoder.h
gst-libs/gst/vaapi/gstvaapiencoder_h264.c
gst-libs/gst/vaapi/gstvaapiencoder_h264.h
gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.c
gst-libs/gst/vaapi/gstvaapiencoder_mpeg2.h
gst-libs/gst/vaapi/gstvaapiencoder_priv.h

index fc00261..2e6def0 100644 (file)
 #include "gstvaapicontext.h"
 #include "gstvaapidisplay_priv.h"
 #include "gstvaapiutils.h"
+#include "gstvaapivalue.h"
 
 #define DEBUG 1
 #include "gstvaapidebug.h"
 
+/* Helper function to create a new encoder property object */
+static GstVaapiEncoderPropData *
+prop_new (gint id, GParamSpec * pspec)
+{
+  GstVaapiEncoderPropData *prop;
+
+  if (!id || !pspec)
+    return NULL;
+
+  prop = g_slice_new (GstVaapiEncoderPropData);
+  if (!prop)
+    return NULL;
+
+  prop->prop = id;
+  prop->pspec = g_param_spec_ref_sink (pspec);
+  return prop;
+}
+
+/* Helper function to release a property object and any memory held herein */
+static void
+prop_free (GstVaapiEncoderPropData * prop)
+{
+  if (!prop)
+    return;
+
+  if (prop->pspec) {
+    g_param_spec_unref (prop->pspec);
+    prop->pspec = NULL;
+  }
+  g_slice_free (GstVaapiEncoderPropData, prop);
+}
+
+/* Helper function to lookup the supplied property specification */
+static GParamSpec *
+prop_find_pspec (GstVaapiEncoder * encoder, gint prop_id)
+{
+  GPtrArray *const props = encoder->properties;
+  guint i;
+
+  if (props) {
+    for (i = 0; i < props->len; i++) {
+      GstVaapiEncoderPropInfo *const prop = g_ptr_array_index (props, i);
+      if (prop->prop == prop_id)
+        return prop->pspec;
+    }
+  }
+  return NULL;
+}
+
+/* Create a new array of properties, or NULL on error */
+GPtrArray *
+gst_vaapi_encoder_properties_append (GPtrArray * props, gint prop_id,
+    GParamSpec * pspec)
+{
+  GstVaapiEncoderPropData *prop;
+
+  if (!props) {
+    props = g_ptr_array_new_with_free_func ((GDestroyNotify) prop_free);
+    if (!props)
+      return NULL;
+  }
+
+  prop = prop_new (prop_id, pspec);
+  if (!prop)
+    goto error_allocation_failed;
+  g_ptr_array_add (props, prop);
+  return props;
+
+  /* ERRORS */
+error_allocation_failed:
+  {
+    GST_ERROR ("failed to allocate encoder property info structure");
+    g_ptr_array_unref (props);
+    return NULL;
+  }
+}
+
+/* Generate the common set of encoder properties */
+GPtrArray *
+gst_vaapi_encoder_properties_get_default (const GstVaapiEncoderClass * klass)
+{
+  const GstVaapiEncoderClassData *const cdata = klass->class_data;
+  GPtrArray *props = NULL;
+
+  /**
+   * GstVaapiEncoder:rate-control:
+   *
+   * The desired rate control mode, expressed as a #GstVaapiRateControl.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_PROP_RATECONTROL,
+      g_param_spec_enum ("rate-control",
+          "Rate Control", "Rate control mode",
+          GST_VAAPI_TYPE_RATE_CONTROL, cdata->default_rate_control,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstVaapiEncoder:bitrate:
+   *
+   * The desired bitrate, expressed in kbps.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_PROP_BITRATE,
+      g_param_spec_uint ("bitrate",
+          "Bitrate (kbps)",
+          "The desired bitrate expressed in kbps (0: auto-calculate)",
+          0, 100 * 1024, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  return props;
+}
+
 /**
  * gst_vaapi_encoder_ref:
  * @encoder: a #GstVaapiEncoder
@@ -390,6 +502,93 @@ error:
   return NULL;
 }
 
+/**
+ * gst_vaapi_encoder_set_property:
+ * @encoder: a #GstVaapiEncoder
+ * @prop_id: the id of the property to change
+ * @value: the new value to set
+ *
+ * Update the requested property, designed by @prop_id, with the
+ * supplied @value. A @NULL value argument resets the property to its
+ * default value.
+ *
+ * Return value: a #GstVaapiEncoderStatus
+ */
+static GstVaapiEncoderStatus
+set_property (GstVaapiEncoder * encoder, gint prop_id, const GValue * value)
+{
+  GstVaapiEncoderStatus status =
+      GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
+
+  g_assert (value != NULL);
+
+  /* Handle codec-specific properties */
+  if (prop_id < 0) {
+    GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
+
+    if (klass->set_property) {
+      if (encoder->num_codedbuf_queued > 0)
+        goto error_operation_failed;
+      status = klass->set_property (encoder, prop_id, value);
+    }
+    return status;
+  }
+
+  /* Handle common properties */
+  switch (prop_id) {
+    case GST_VAAPI_ENCODER_PROP_RATECONTROL:
+      status = gst_vaapi_encoder_set_rate_control (encoder,
+          g_value_get_enum (value));
+      break;
+    case GST_VAAPI_ENCODER_PROP_BITRATE:
+      status = gst_vaapi_encoder_set_bitrate (encoder,
+          g_value_get_uint (value));
+      break;
+  }
+  return status;
+
+  /* ERRORS */
+error_operation_failed:
+  {
+    GST_ERROR ("could not change codec state after encoding started");
+    return GST_VAAPI_ENCODER_STATUS_ERROR_OPERATION_FAILED;
+  }
+}
+
+GstVaapiEncoderStatus
+gst_vaapi_encoder_set_property (GstVaapiEncoder * encoder, gint prop_id,
+    const GValue * value)
+{
+  GstVaapiEncoderStatus status;
+  GValue default_value = G_VALUE_INIT;
+
+  g_return_val_if_fail (encoder != NULL,
+      GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER);
+
+  if (!value) {
+    GParamSpec *const pspec = prop_find_pspec (encoder, prop_id);
+    if (!pspec)
+      goto error_invalid_property;
+
+    g_value_init (&default_value, pspec->value_type);
+    g_param_value_set_default (pspec, &default_value);
+    value = &default_value;
+  }
+
+  status = set_property (encoder, prop_id, value);
+
+  if (default_value.g_type)
+    g_value_unset (&default_value);
+  return status;
+
+  /* ERRORS */
+error_invalid_property:
+  {
+    GST_ERROR ("unsupported property (%d)", prop_id);
+    return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
+  }
+}
+
 /* Determine the supported rate control modes */
 static gboolean
 get_rate_control_mask (GstVaapiEncoder * encoder)
@@ -524,6 +723,29 @@ error_operation_failed:
   }
 }
 
+/* Initialize default values for configurable properties */
+static gboolean
+gst_vaapi_encoder_init_properties (GstVaapiEncoder * encoder)
+{
+  GstVaapiEncoderClass *const klass = GST_VAAPI_ENCODER_GET_CLASS (encoder);
+  GPtrArray *props;
+  guint i;
+
+  props = klass->get_default_properties ();
+  if (!props)
+    return FALSE;
+
+  encoder->properties = props;
+  for (i = 0; i < props->len; i++) {
+    GstVaapiEncoderPropInfo *const prop = g_ptr_array_index (props, i);
+
+    if (gst_vaapi_encoder_set_property (encoder, prop->prop,
+            NULL) != GST_VAAPI_ENCODER_STATUS_SUCCESS)
+      return FALSE;
+  }
+  return TRUE;
+}
+
 /* Base encoder initialization (internal) */
 static gboolean
 gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
@@ -539,6 +761,7 @@ gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
 
   CHECK_VTABLE_HOOK (init);
   CHECK_VTABLE_HOOK (finalize);
+  CHECK_VTABLE_HOOK (get_default_properties);
   CHECK_VTABLE_HOOK (encode);
   CHECK_VTABLE_HOOK (reordering);
   CHECK_VTABLE_HOOK (flush);
@@ -562,7 +785,11 @@ gst_vaapi_encoder_init (GstVaapiEncoder * encoder, GstVaapiDisplay * display)
   if (!encoder->codedbuf_queue)
     return FALSE;
 
-  return klass->init (encoder);
+  if (!klass->init (encoder))
+    return FALSE;
+  if (!gst_vaapi_encoder_init_properties (encoder))
+    return FALSE;
+  return TRUE;
 
   /* ERRORS */
 error_invalid_vtable:
@@ -584,6 +811,11 @@ gst_vaapi_encoder_finalize (GstVaapiEncoder * encoder)
   gst_vaapi_display_replace (&encoder->display, NULL);
   encoder->va_display = NULL;
 
+  if (encoder->properties) {
+    g_ptr_array_unref (encoder->properties);
+    encoder->properties = NULL;
+  }
+
   gst_vaapi_video_pool_replace (&encoder->codedbuf_pool, NULL);
   if (encoder->codedbuf_queue) {
     g_async_queue_unref (encoder->codedbuf_queue);
index 2fc3e74..a4dbe3a 100644 (file)
@@ -68,6 +68,30 @@ typedef enum
   GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_HEADER = -103,
 } GstVaapiEncoderStatus;
 
+/**
+ * GstVaapiEncoderProp:
+ * @GST_VAAPI_ENCODER_PROP_RATECONTROL: Rate control (#GstVaapiRateControl).
+ * @GST_VAAPI_ENCODER_PROP_BITRATE: Bitrate expressed in kbps (uint).
+ *
+ * The set of configurable properties for the encoder.
+ */
+typedef enum {
+  GST_VAAPI_ENCODER_PROP_RATECONTROL = 1,
+  GST_VAAPI_ENCODER_PROP_BITRATE,
+} GstVaapiEncoderProp;
+
+/**
+ * GstVaapiEncoderPropInfo:
+ * @prop: the #GstVaapiEncoderProp
+ * @pspec: the #GParamSpec describing the associated configurable value
+ *
+ * A #GstVaapiEncoderProp descriptor.
+ */
+typedef struct {
+  const gint prop;
+  GParamSpec *const pspec;
+} GstVaapiEncoderPropInfo;
+
 GstVaapiEncoder *
 gst_vaapi_encoder_ref (GstVaapiEncoder * encoder);
 
@@ -87,6 +111,10 @@ gst_vaapi_encoder_set_format (GstVaapiEncoder * encoder,
     GstVideoCodecState * state, GstCaps * ref_caps);
 
 GstVaapiEncoderStatus
+gst_vaapi_encoder_set_property (GstVaapiEncoder * encoder, gint prop_id,
+    const GValue * value);
+
+GstVaapiEncoderStatus
 gst_vaapi_encoder_set_rate_control (GstVaapiEncoder * encoder,
     GstVaapiRateControl rate_control);
 
index 121c0d3..420a0e3 100644 (file)
@@ -1273,9 +1273,7 @@ init_encoder_public_attributes (GstVaapiEncoderH264 * encoder)
 
   _set_level (encoder);
 
-  if (!encoder->intra_period)
-    encoder->intra_period = GST_VAAPI_ENCODER_H264_DEFAULT_INTRA_PERIOD;
-  else if (encoder->intra_period > GST_VAAPI_ENCODER_H264_MAX_INTRA_PERIOD)
+  if (encoder->intra_period > GST_VAAPI_ENCODER_H264_MAX_INTRA_PERIOD)
     encoder->intra_period = GST_VAAPI_ENCODER_H264_MAX_INTRA_PERIOD;
 
   if (encoder->idr_period < encoder->intra_period)
@@ -1283,17 +1281,9 @@ init_encoder_public_attributes (GstVaapiEncoderH264 * encoder)
   if (encoder->idr_period > GST_VAAPI_ENCODER_H264_MAX_IDR_PERIOD)
     encoder->idr_period = GST_VAAPI_ENCODER_H264_MAX_IDR_PERIOD;
 
-  if (-1 == encoder->init_qp)
-    encoder->init_qp = GST_VAAPI_ENCODER_H264_DEFAULT_INIT_QP;
-
-  if (-1 == encoder->min_qp) {
-    if (GST_VAAPI_RATECONTROL_CQP == GST_VAAPI_ENCODER_RATE_CONTROL (encoder))
-      encoder->min_qp = encoder->init_qp;
-    else
-      encoder->min_qp = GST_VAAPI_ENCODER_H264_DEFAULT_MIN_QP;
-  }
-
-  if (encoder->min_qp > encoder->init_qp)
+  if (encoder->min_qp > encoder->init_qp ||
+      (GST_VAAPI_ENCODER_RATE_CONTROL (encoder) == GST_VAAPI_RATECONTROL_CQP &&
+          encoder->min_qp < encoder->init_qp))
     encoder->min_qp = encoder->init_qp;
 
   /* default compress ratio 1: (4*8*1.5) */
@@ -1309,9 +1299,6 @@ init_encoder_public_attributes (GstVaapiEncoderH264 * encoder)
   } else
     base_encoder->bitrate = 0;
 
-  if (!encoder->slice_num)
-    encoder->slice_num = GST_VAAPI_ENCODER_H264_DEFAULT_SLICE_NUM;
-
   width_mbs = (GST_VAAPI_ENCODER_WIDTH (encoder) + 15) / 16;
   height_mbs = (GST_VAAPI_ENCODER_HEIGHT (encoder) + 15) / 16;
   total_mbs = width_mbs * height_mbs;
@@ -1704,17 +1691,10 @@ gst_vaapi_encoder_h264_init (GstVaapiEncoder * base)
 {
   GstVaapiEncoderH264 *encoder = GST_VAAPI_ENCODER_H264 (base);
 
-  base->rate_control = DEFAULT_RATECONTROL;
-
   /* init attributes */
   encoder->profile = 0;
   encoder->level = 0;
   encoder->idr_period = 0;
-  encoder->intra_period = 0;
-  encoder->init_qp = -1;
-  encoder->min_qp = -1;
-  encoder->slice_num = 0;
-  encoder->b_frame_num = 0;
   //gst_vaapi_base_encoder_set_frame_notify(GST_VAAPI_BASE_ENCODER(encoder), TRUE);
 
   /* init private values */
@@ -1771,6 +1751,34 @@ gst_vaapi_encoder_h264_finalize (GstVaapiEncoder * base)
 
 }
 
+static GstVaapiEncoderStatus
+gst_vaapi_encoder_h264_set_property (GstVaapiEncoder * base_encoder,
+    gint prop_id, const GValue * value)
+{
+  GstVaapiEncoderH264 *const encoder = GST_VAAPI_ENCODER_H264 (base_encoder);
+
+  switch (prop_id) {
+    case GST_VAAPI_ENCODER_H264_PROP_KEY_PERIOD:
+      encoder->intra_period = g_value_get_uint (value);
+      break;
+    case GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES:
+      encoder->b_frame_num = g_value_get_uint (value);
+      break;
+    case GST_VAAPI_ENCODER_H264_PROP_INIT_QP:
+      encoder->init_qp = g_value_get_uint (value);
+      break;
+    case GST_VAAPI_ENCODER_H264_PROP_MIN_QP:
+      encoder->min_qp = g_value_get_uint (value);
+      break;
+    case GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES:
+      encoder->slice_num = g_value_get_uint (value);
+      break;
+    default:
+      return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
+  }
+  return GST_VAAPI_ENCODER_STATUS_SUCCESS;
+}
+
 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (H264);
 
 static inline const GstVaapiEncoderClass *
@@ -1778,6 +1786,7 @@ gst_vaapi_encoder_h264_class (void)
 {
   static const GstVaapiEncoderClass GstVaapiEncoderH264Class = {
     GST_VAAPI_ENCODER_CLASS_INIT (H264, h264),
+    .set_property = gst_vaapi_encoder_h264_set_property,
     .get_codec_data = gst_vaapi_encoder_h264_get_codec_data
   };
   return &GstVaapiEncoderH264Class;
@@ -1789,6 +1798,86 @@ gst_vaapi_encoder_h264_new (GstVaapiDisplay * display)
   return gst_vaapi_encoder_new (gst_vaapi_encoder_h264_class (), display);
 }
 
+/**
+ * gst_vaapi_encoder_h264_get_default_properties:
+ *
+ * Determines the set of common and H.264 specific encoder properties.
+ * The caller owns an extra reference to the resulting array of
+ * #GstVaapiEncoderPropInfo elements, so it shall be released with
+ * g_ptr_array_unref() after usage.
+ *
+ * Return value: the set of encoder properties for #GstVaapiEncoderH264,
+ *   or %NULL if an error occurred.
+ */
+GPtrArray *
+gst_vaapi_encoder_h264_get_default_properties (void)
+{
+  const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_h264_class ();
+  GPtrArray *props;
+
+  props = gst_vaapi_encoder_properties_get_default (klass);
+  if (!props)
+    return NULL;
+
+  /**
+   * GstVaapiEncoderH264:key-period
+   *
+   * The maximal distance between two keyframes.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_H264_PROP_KEY_PERIOD,
+      g_param_spec_uint ("key-period",
+          "Key Period", "Maximal distance between two key-frames", 1, 300, 30,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstVaapiEncoderH264:max-bframes:
+   *
+   * The number of B-frames between I and P.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES,
+      g_param_spec_uint ("max-bframes",
+          "Max B-Frames", "Number of B-frames between I and P", 0, 10, 0,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstVaapiEncoderH264:init-qp:
+   *
+   * The initial quantizer value.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_H264_PROP_INIT_QP,
+      g_param_spec_uint ("init-qp",
+          "Initial QP", "Initial quantizer value", 1, 51, 26,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstVaapiEncoderH264:min-qp:
+   *
+   * The minimum quantizer value.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_H264_PROP_MIN_QP,
+      g_param_spec_uint ("min-qp",
+          "Minimum QP", "Minimum quantizer value", 1, 51, 1,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  /**
+   * GstVaapiEncoderH264:num-slices:
+   *
+   * The number of slices per frame.
+   */
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES,
+      g_param_spec_uint ("num-slices",
+          "Number of Slices",
+          "Number of slices per frame",
+          1, 200, 1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  return props;
+}
+
 void
 gst_vaapi_encoder_h264_set_avc (GstVaapiEncoderH264 * encoder, gboolean is_avc)
 {
index 3eee7c8..b6c4a1c 100644 (file)
@@ -28,9 +28,32 @@ G_BEGIN_DECLS
 
 typedef struct _GstVaapiEncoderH264 GstVaapiEncoderH264;
 
+/**
+ * GstVaapiEncoderH264Prop:
+ * @GST_VAAPI_ENCODER_H264_PROP_KEY_PERIOD: Maximal distance between two
+ *   keyframes (uint).
+ * @GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES: Number of B-frames between I
+ *   and P (uint).
+ * @GST_VAAPI_ENCODER_H264_PROP_INIT_QP: Initial quantizer value (uint).
+ * @GST_VAAPI_ENCODER_H264_PROP_MIN_QP: Minimal quantizer value (uint).
+ * @GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES: Number of slices per frame (uint).
+ *
+ * The set of H.264 encoder specific configurable properties.
+ */
+typedef enum {
+  GST_VAAPI_ENCODER_H264_PROP_KEY_PERIOD = -1,
+  GST_VAAPI_ENCODER_H264_PROP_MAX_BFRAMES = -2,
+  GST_VAAPI_ENCODER_H264_PROP_INIT_QP = -3,
+  GST_VAAPI_ENCODER_H264_PROP_MIN_QP = -4,
+  GST_VAAPI_ENCODER_H264_PROP_NUM_SLICES = -5,
+} GstVaapiEncoderH264Prop;
+
 GstVaapiEncoder *
 gst_vaapi_encoder_h264_new (GstVaapiDisplay * display);
 
+GPtrArray *
+gst_vaapi_encoder_h264_get_default_properties (void);
+
 void
 gst_vaapi_encoder_h264_set_avc (GstVaapiEncoderH264 * encoder, gboolean is_avc);
 
index 9104eaf..fb7e042 100644 (file)
@@ -732,8 +732,6 @@ gst_vaapi_encoder_mpeg2_init (GstVaapiEncoder * base)
 {
   GstVaapiEncoderMpeg2 *encoder = GST_VAAPI_ENCODER_MPEG2 (base);
 
-  base->rate_control = DEFAULT_RATECONTROL;
-
   /* re-ordering */
   g_queue_init (&encoder->b_frames);
   encoder->dump_frames = FALSE;
@@ -792,6 +790,28 @@ gst_vaapi_encoder_mpeg2_finalize (GstVaapiEncoder * base)
   g_queue_clear (&encoder->b_frames);
 }
 
+static GstVaapiEncoderStatus
+gst_vaapi_encoder_mpeg2_set_property (GstVaapiEncoder * base_encoder,
+    gint prop_id, const GValue * value)
+{
+  GstVaapiEncoderMpeg2 *const encoder = GST_VAAPI_ENCODER_MPEG2 (base_encoder);
+
+  switch (prop_id) {
+    case GST_VAAPI_ENCODER_MPEG2_PROP_QUANTIZER:
+      encoder->cqp = g_value_get_uint (value);
+      break;
+    case GST_VAAPI_ENCODER_MPEG2_PROP_KEY_PERIOD:
+      encoder->intra_period = g_value_get_uint (value);
+      break;
+    case GST_VAAPI_ENCODER_MPEG2_PROP_MAX_BFRAMES:
+      encoder->ip_period = g_value_get_uint (value);
+      break;
+    default:
+      return GST_VAAPI_ENCODER_STATUS_ERROR_INVALID_PARAMETER;
+  }
+  return GST_VAAPI_ENCODER_STATUS_SUCCESS;
+}
+
 GST_VAAPI_ENCODER_DEFINE_CLASS_DATA (MPEG2);
 
 static inline const GstVaapiEncoderClass *
@@ -799,6 +819,7 @@ gst_vaapi_encoder_mpeg2_class (void)
 {
   static const GstVaapiEncoderClass GstVaapiEncoderMpeg2Class = {
     GST_VAAPI_ENCODER_CLASS_INIT (Mpeg2, mpeg2),
+    .set_property = gst_vaapi_encoder_mpeg2_set_property,
   };
   return &GstVaapiEncoderMpeg2Class;
 }
@@ -809,6 +830,55 @@ gst_vaapi_encoder_mpeg2_new (GstVaapiDisplay * display)
   return gst_vaapi_encoder_new (gst_vaapi_encoder_mpeg2_class (), display);
 }
 
+/**
+ * gst_vaapi_encoder_mpeg2_get_default_properties:
+ *
+ * Determines the set of common and MPEG-2 specific encoder properties.
+ * The caller owns an extra reference to the resulting array of
+ * #GstVaapiEncoderPropInfo elements, so it shall be released with
+ * g_ptr_array_unref() after usage.
+ *
+ * Return value: the set of encoder properties for #GstVaapiEncoderMpeg2,
+ *   or %NULL if an error occurred.
+ */
+GPtrArray *
+gst_vaapi_encoder_mpeg2_get_default_properties (void)
+{
+  const GstVaapiEncoderClass *const klass = gst_vaapi_encoder_mpeg2_class ();
+  GPtrArray *props;
+
+  props = gst_vaapi_encoder_properties_get_default (klass);
+  if (!props)
+    return NULL;
+
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_MPEG2_PROP_QUANTIZER,
+      g_param_spec_uint ("quantizer",
+          "Constant Quantizer",
+          "Constant quantizer (if rate-control mode is CQP)",
+          GST_VAAPI_ENCODER_MPEG2_MIN_CQP, GST_VAAPI_ENCODER_MPEG2_MAX_CQP,
+          GST_VAAPI_ENCODER_MPEG2_DEFAULT_CQP,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_MPEG2_PROP_KEY_PERIOD,
+      g_param_spec_uint ("key-period",
+          "Key Period", "Maximal distance between two key-frames", 1,
+          GST_VAAPI_ENCODER_MPEG2_MAX_GOP_SIZE,
+          GST_VAAPI_ENCODER_MPEG2_DEFAULT_GOP_SIZE,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  GST_VAAPI_ENCODER_PROPERTIES_APPEND (props,
+      GST_VAAPI_ENCODER_MPEG2_PROP_MAX_BFRAMES,
+      g_param_spec_uint ("max-bframes", "Max B-Frames",
+          "Number of B-frames between I and P", 0,
+          GST_VAAPI_ENCODER_MPEG2_MAX_MAX_BFRAMES,
+          GST_VAAPI_ENCODER_MPEG2_DEFAULT_MAX_BFRAMES,
+          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  return props;
+}
+
 static struct
 {
   int code;
index a880875..bd6d1a7 100644 (file)
@@ -28,9 +28,28 @@ G_BEGIN_DECLS
 
 typedef struct _GstVaapiEncoderMpeg2 GstVaapiEncoderMpeg2;
 
+/**
+ * GstVaapiEncoderMpeg2Prop:
+ * @GST_VAAPI_ENCODER_MPEG2_PROP_QUANTIZER: Constant quantizer value (uint).
+ * @GST_VAAPI_ENCODER_MPEG2_PROP_KEY_PERIOD: Maximal distance between two
+ *   keyframes (uint).
+ * @GST_VAAPI_ENCODER_MPEG2_PROP_MAX_BFRAMES: Number of B-frames between I
+ *   and P (uint).
+ *
+ * The set of MPEG-2 encoder specific configurable properties.
+ */
+typedef enum {
+  GST_VAAPI_ENCODER_MPEG2_PROP_QUANTIZER = -1,
+  GST_VAAPI_ENCODER_MPEG2_PROP_KEY_PERIOD = -2,
+  GST_VAAPI_ENCODER_MPEG2_PROP_MAX_BFRAMES = -3,
+} GstVaapiEncoderMpeg2Prop;
+
 GstVaapiEncoder *
 gst_vaapi_encoder_mpeg2_new (GstVaapiDisplay * display);
 
+GPtrArray *
+gst_vaapi_encoder_mpeg2_get_default_properties (void);
+
 G_END_DECLS
 
 #endif /* GST_VAAPI_ENCODER_MPEG2_H */
index dd0a41e..0238ac1 100644 (file)
@@ -83,11 +83,33 @@ G_BEGIN_DECLS
 typedef struct _GstVaapiEncoderClass GstVaapiEncoderClass;
 typedef struct _GstVaapiEncoderClassData GstVaapiEncoderClassData;
 
+/* Private GstVaapiEncoderPropInfo definition */
+typedef struct {
+  gint prop;
+  GParamSpec *pspec;
+} GstVaapiEncoderPropData;
+
+#define GST_VAAPI_ENCODER_PROPERTIES_APPEND(props, id, pspec) do {      \
+    props = gst_vaapi_encoder_properties_append (props, id, pspec);     \
+    if (!props)                                                         \
+      return NULL;                                                      \
+  } while (0)
+
+G_GNUC_INTERNAL
+GPtrArray *
+gst_vaapi_encoder_properties_append (GPtrArray * props, gint prop_id,
+    GParamSpec *pspec);
+
+G_GNUC_INTERNAL
+GPtrArray *
+gst_vaapi_encoder_properties_get_default (const GstVaapiEncoderClass * klass);
+
 struct _GstVaapiEncoder
 {
   /*< private >*/
   GstVaapiMiniObject parent_instance;
 
+  GPtrArray *properties;
   GstVaapiDisplay *display;
   GstVaapiContext *context;
   GstVaapiContextInfo context_info;
@@ -141,6 +163,11 @@ struct _GstVaapiEncoderClass
 
   void                  (*set_context_info) (GstVaapiEncoder * encoder);
 
+  GPtrArray *           (*get_default_properties) (void);
+  GstVaapiEncoderStatus (*set_property) (GstVaapiEncoder * encoder,
+                                         gint prop_id,
+                                         const GValue * value);
+
   GstVaapiEncoderStatus (*reordering)   (GstVaapiEncoder * encoder,
                                          GstVideoCodecFrame * in,
                                          GstVaapiEncPicture ** out);
@@ -169,6 +196,7 @@ struct _GstVaapiEncoderClass
     .class_data = &g_class_data,                                \
     GST_VAAPI_ENCODER_CLASS_HOOK (codec, init),                 \
     GST_VAAPI_ENCODER_CLASS_HOOK (codec, finalize),             \
+    GST_VAAPI_ENCODER_CLASS_HOOK (codec, get_default_properties), \
     GST_VAAPI_ENCODER_CLASS_HOOK (codec, set_format),           \
     GST_VAAPI_ENCODER_CLASS_HOOK (codec, set_context_info),     \
     GST_VAAPI_ENCODER_CLASS_HOOK (codec, reordering),           \