vaapiencode: update for new properties API.

Update MPEG-2 and H.264 encode elements to cope with the new core
libgstvaapi properties API. i.e. all configurable properties are now
directly handled at the GstVaapiEncoder level.

Besides, this also makes sure to not use or modify the GstVaapiEncoder
private definitions directly. Private data need to remain private.

https://bugzilla.gnome.org/show_bug.cgi?id=719529
This commit is contained in:
Gwenole Beauchesne 2014-01-08 18:36:46 +01:00
parent dcc7a94408
commit a43d06dcf5
5 changed files with 193 additions and 252 deletions

View file

@ -48,8 +48,8 @@ G_DEFINE_TYPE_WITH_CODE (GstVaapiEncode,
enum
{
PROP_0,
PROP_RATE_CONTROL,
PROP_BITRATE,
PROP_BASE,
};
static inline gboolean
@ -90,6 +90,88 @@ gst_vaapiencode_query (GST_PAD_QUERY_FUNCTION_ARGS)
return success;
}
typedef struct
{
GstVaapiEncoderProp id;
GParamSpec *pspec;
GValue value;
} PropValue;
static PropValue *
prop_value_new (GstVaapiEncoderPropInfo * prop)
{
static const GValue default_value = G_VALUE_INIT;
PropValue *prop_value;
if (!prop || !prop->pspec)
return NULL;
prop_value = g_slice_new (PropValue);
if (!prop_value)
return NULL;
prop_value->id = prop->prop;
prop_value->pspec = g_param_spec_ref (prop->pspec);
memcpy (&prop_value->value, &default_value, sizeof (prop_value->value));
g_value_init (&prop_value->value, prop->pspec->value_type);
g_param_value_set_default (prop->pspec, &prop_value->value);
return prop_value;
}
static void
prop_value_free (PropValue * prop_value)
{
if (!prop_value)
return;
if (G_VALUE_TYPE (&prop_value->value))
g_value_unset (&prop_value->value);
if (prop_value->pspec) {
g_param_spec_unref (prop_value->pspec);
prop_value->pspec = NULL;
}
g_slice_free (PropValue, prop_value);
}
static inline PropValue *
prop_value_lookup (GstVaapiEncode * encode, guint prop_id)
{
GPtrArray *const prop_values = encode->prop_values;
if (prop_values &&
(prop_id >= PROP_BASE && prop_id < PROP_BASE + prop_values->len))
return g_ptr_array_index (prop_values, prop_id - PROP_BASE);
return NULL;
}
static gboolean
gst_vaapiencode_default_get_property (GstVaapiEncode * encode, guint prop_id,
GValue * value)
{
PropValue *const prop_value = prop_value_lookup (encode, prop_id);
if (prop_value) {
g_value_copy (&prop_value->value, value);
return TRUE;
}
return FALSE;
}
static gboolean
gst_vaapiencode_default_set_property (GstVaapiEncode * encode, guint prop_id,
const GValue * value)
{
PropValue *const prop_value = prop_value_lookup (encode, prop_id);
if (prop_value) {
g_value_copy (value, &prop_value->value);
return TRUE;
}
return FALSE;
}
static GstFlowReturn
gst_vaapiencode_default_allocate_buffer (GstVaapiEncode * encode,
GstVaapiCodedBuffer * coded_buf, GstBuffer ** outbuf_ptr)
@ -303,6 +385,8 @@ ensure_encoder (GstVaapiEncode * encode)
{
GstVaapiEncodeClass *klass = GST_VAAPIENCODE_GET_CLASS (encode);
GstVaapiEncoderStatus status;
GPtrArray *const prop_values = encode->prop_values;
guint i;
g_return_val_if_fail (klass->create_encoder, FALSE);
@ -314,14 +398,15 @@ ensure_encoder (GstVaapiEncode * encode)
if (!encode->encoder)
return FALSE;
status = gst_vaapi_encoder_set_rate_control (encode->encoder,
encode->rate_control);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return FALSE;
status = gst_vaapi_encoder_set_bitrate (encode->encoder, encode->bitrate);
if (prop_values) {
for (i = 0; i < prop_values->len; i++) {
PropValue *const prop_value = g_ptr_array_index (prop_values, i);
status = gst_vaapi_encoder_set_property (encode->encoder, prop_value->id,
&prop_value->value);
if (status != GST_VAAPI_ENCODER_STATUS_SUCCESS)
return FALSE;
}
}
return TRUE;
}
@ -562,44 +647,6 @@ gst_vaapiencode_propose_allocation (GstVideoEncoder * venc, GstQuery * query)
}
#endif
static void
gst_vaapiencode_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (object);
switch (prop_id) {
case PROP_RATE_CONTROL:
encode->rate_control = g_value_get_enum (value);
break;
case PROP_BITRATE:
encode->bitrate = g_value_get_uint (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_vaapiencode_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstVaapiEncode *const encode = GST_VAAPIENCODE_CAST (object);
switch (prop_id) {
case PROP_RATE_CONTROL:
g_value_set_enum (value, encode->rate_control);
break;
case PROP_BITRATE:
g_value_set_uint (value, encode->bitrate);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
static void
gst_vaapiencode_finalize (GObject * object)
{
@ -607,6 +654,11 @@ gst_vaapiencode_finalize (GObject * object)
gst_vaapiencode_destroy (encode);
if (encode->prop_values) {
g_ptr_array_unref (encode->prop_values);
encode->prop_values = NULL;
}
encode->sinkpad = NULL;
encode->srcpad = NULL;
@ -644,8 +696,6 @@ gst_vaapiencode_class_init (GstVaapiEncodeClass * klass)
gst_vaapi_plugin_base_class_init (GST_VAAPI_PLUGIN_BASE_CLASS (klass));
object_class->finalize = gst_vaapiencode_finalize;
object_class->set_property = gst_vaapiencode_set_property;
object_class->get_property = gst_vaapiencode_get_property;
venc_class->open = GST_DEBUG_FUNCPTR (gst_vaapiencode_open);
venc_class->close = GST_DEBUG_FUNCPTR (gst_vaapiencode_close);
@ -660,24 +710,61 @@ gst_vaapiencode_class_init (GstVaapiEncodeClass * klass)
GST_DEBUG_FUNCPTR (gst_vaapiencode_propose_allocation);
#endif
klass->get_property = gst_vaapiencode_default_get_property;
klass->set_property = gst_vaapiencode_default_set_property;
klass->allocate_buffer = gst_vaapiencode_default_allocate_buffer;
/* Registering debug symbols for function pointers */
GST_DEBUG_REGISTER_FUNCPTR (gst_vaapiencode_query);
g_object_class_install_property (object_class,
PROP_RATE_CONTROL,
g_param_spec_enum ("rate-control",
"Rate Control",
"Rate control mode",
GST_VAAPI_TYPE_RATE_CONTROL,
GST_VAAPI_RATECONTROL_CQP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
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));
}
static inline GPtrArray *
get_properties (GstVaapiEncodeClass * klass)
{
return klass->get_properties ? klass->get_properties () : NULL;
}
gboolean
gst_vaapiencode_init_properties (GstVaapiEncode * encode)
{
GPtrArray *const props = get_properties (GST_VAAPIENCODE_GET_CLASS (encode));
guint i;
/* XXX: use base_init()/base_finalize() to avoid multiple initializations */
if (!props)
return FALSE;
encode->prop_values =
g_ptr_array_new_full (props->len, (GDestroyNotify) prop_value_free);
if (!encode->prop_values) {
g_ptr_array_unref (props);
return FALSE;
}
for (i = 0; i < props->len; i++) {
PropValue *const prop_value = prop_value_new ((GstVaapiEncoderPropInfo *)
g_ptr_array_index (props, i));
if (!prop_value)
return FALSE;
g_ptr_array_add (encode->prop_values, prop_value);
}
return TRUE;
}
gboolean
gst_vaapiencode_class_init_properties (GstVaapiEncodeClass * klass)
{
GObjectClass *const object_class = G_OBJECT_CLASS (klass);
GPtrArray *const props = get_properties (klass);
guint i;
if (!props)
return FALSE;
for (i = 0; i < props->len; i++) {
GstVaapiEncoderPropInfo *const prop = g_ptr_array_index (props, i);
g_object_class_install_property (object_class, PROP_BASE + i, prop->pspec);
}
g_ptr_array_unref (props);
return TRUE;
}

View file

@ -59,8 +59,7 @@ struct _GstVaapiEncode
GstPadQueryFunction srcpad_query;
GstVaapiEncoder *encoder;
GstVaapiRateControl rate_control;
guint32 bitrate; /* kbps */
GPtrArray *prop_values;
guint32 out_caps_done:1;
};
@ -70,6 +69,12 @@ struct _GstVaapiEncodeClass
/*< private >*/
GstVaapiPluginBaseClass parent_class;
GPtrArray * (*get_properties) (void);
gboolean (*get_property) (GstVaapiEncode * encode,
guint prop_id, GValue * value);
gboolean (*set_property) (GstVaapiEncode * encode,
guint prop_id, const GValue * value);
GstVaapiEncoder * (*create_encoder) (GstVaapiEncode * encode,
GstVaapiDisplay * display);
GstFlowReturn (*allocate_buffer) (GstVaapiEncode * encode,
@ -80,6 +85,14 @@ struct _GstVaapiEncodeClass
GType
gst_vaapiencode_get_type (void) G_GNUC_CONST;
G_GNUC_INTERNAL
gboolean
gst_vaapiencode_init_properties (GstVaapiEncode * encode);
G_GNUC_INTERNAL
gboolean
gst_vaapiencode_class_init_properties (GstVaapiEncodeClass * encode_class);
G_END_DECLS
#endif /* GST_VAAPIENCODE_H */

View file

@ -22,7 +22,6 @@
#include "gst/vaapi/sysdeps.h"
#include <gst/vaapi/gstvaapidisplay.h>
#include <gst/vaapi/gstvaapiencoder_h264.h>
#include "gst/vaapi/gstvaapiencoder_h264_priv.h"
#include "gstvaapiencode_h264.h"
#include "gstvaapipluginutil.h"
#if GST_CHECK_VERSION(1,0,0)
@ -80,19 +79,10 @@ static GstStaticPadTemplate gst_vaapiencode_h264_src_factory =
/* h264 encode */
G_DEFINE_TYPE (GstVaapiEncodeH264, gst_vaapiencode_h264, GST_TYPE_VAAPIENCODE);
enum
{
PROP_0,
PROP_KEY_PERIOD,
PROP_MAX_BFRAMES,
PROP_INIT_QP,
PROP_MIN_QP,
PROP_NUM_SLICES,
};
static void
gst_vaapiencode_h264_init (GstVaapiEncodeH264 * encode)
{
gst_vaapiencode_init_properties (GST_VAAPIENCODE_CAST (encode));
}
static void
@ -105,25 +95,12 @@ static void
gst_vaapiencode_h264_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstVaapiEncodeH264 *const encode = GST_VAAPIENCODE_H264_CAST (object);
GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (object);
switch (prop_id) {
case PROP_KEY_PERIOD:
encode->intra_period = g_value_get_uint (value);
break;
case PROP_INIT_QP:
encode->init_qp = g_value_get_uint (value);
break;
case PROP_MIN_QP:
encode->min_qp = g_value_get_uint (value);
break;
case PROP_NUM_SLICES:
encode->num_slices = g_value_get_uint (value);
break;
case PROP_MAX_BFRAMES:
encode->max_bframes = g_value_get_uint (value);
break;
default:
if (!encode_class->set_property (base_encode, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
@ -133,25 +110,12 @@ static void
gst_vaapiencode_h264_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
GstVaapiEncodeH264 *const encode = GST_VAAPIENCODE_H264_CAST (object);
GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (object);
switch (prop_id) {
case PROP_KEY_PERIOD:
g_value_set_uint (value, encode->intra_period);
break;
case PROP_INIT_QP:
g_value_set_uint (value, encode->init_qp);
break;
case PROP_MIN_QP:
g_value_set_uint (value, encode->min_qp);
break;
case PROP_NUM_SLICES:
g_value_set_uint (value, encode->num_slices);
break;
case PROP_MAX_BFRAMES:
g_value_set_uint (value, encode->max_bframes);
break;
default:
if (!encode_class->get_property (base_encode, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
@ -161,23 +125,7 @@ static GstVaapiEncoder *
gst_vaapiencode_h264_create_encoder (GstVaapiEncode * base,
GstVaapiDisplay * display)
{
GstVaapiEncodeH264 *const encode = GST_VAAPIENCODE_H264_CAST (base);
GstVaapiEncoder *base_encoder;
GstVaapiEncoderH264 *encoder;
base_encoder = gst_vaapi_encoder_h264_new (display);
if (!base_encoder)
return NULL;
encoder = GST_VAAPI_ENCODER_H264 (base_encoder);
encoder->profile = GST_VAAPI_PROFILE_UNKNOWN;
encoder->level = GST_VAAPI_ENCODER_H264_DEFAULT_LEVEL;
encoder->intra_period = encode->intra_period;
encoder->init_qp = encode->init_qp;
encoder->min_qp = encode->min_qp;
encoder->slice_num = encode->num_slices;
encoder->b_frame_num = encode->max_bframes;
return base_encoder;
return gst_vaapi_encoder_h264_new (display);
}
/* h264 NAL byte stream operations */
@ -276,7 +224,7 @@ static GstFlowReturn
gst_vaapiencode_h264_allocate_buffer (GstVaapiEncode * encode,
GstVaapiCodedBuffer * coded_buf, GstBuffer ** out_buffer_ptr)
{
GstVaapiEncoderH264 *const encoder = GST_VAAPI_ENCODER_H264 (encode->encoder);
GstVaapiEncoderH264 *const encoder = (GstVaapiEncoderH264 *) encode->encoder;
GstFlowReturn ret;
g_return_val_if_fail (encoder != NULL, GST_FLOW_ERROR);
@ -318,6 +266,7 @@ gst_vaapiencode_h264_class_init (GstVaapiEncodeH264Class * klass)
object_class->set_property = gst_vaapiencode_h264_set_property;
object_class->get_property = gst_vaapiencode_h264_get_property;
encode_class->get_properties = gst_vaapi_encoder_h264_get_default_properties;
encode_class->create_encoder = gst_vaapiencode_h264_create_encoder;
encode_class->allocate_buffer = gst_vaapiencode_h264_allocate_buffer;
@ -334,41 +283,5 @@ gst_vaapiencode_h264_class_init (GstVaapiEncodeH264Class * klass)
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_vaapiencode_h264_src_factory));
g_object_class_install_property (object_class,
PROP_KEY_PERIOD,
g_param_spec_uint ("key-period",
"Key Period",
"Maximal distance between two key-frames",
1, 300, GST_VAAPI_ENCODER_H264_DEFAULT_INTRA_PERIOD,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
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));
g_object_class_install_property (object_class,
PROP_INIT_QP,
g_param_spec_uint ("init-qp",
"Initial QP",
"Initial quantizer value",
1, 51, GST_VAAPI_ENCODER_H264_DEFAULT_INIT_QP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
PROP_MIN_QP,
g_param_spec_uint ("min-qp",
"Minimum QP",
"Minimum quantizer value",
1, 51, GST_VAAPI_ENCODER_H264_DEFAULT_MIN_QP,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class,
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));
gst_vaapiencode_class_init_properties (encode_class);
}

View file

@ -52,12 +52,6 @@ struct _GstVaapiEncodeH264
{
/*< private >*/
GstVaapiEncode parent_instance;
guint32 intra_period;
guint32 init_qp;
guint32 min_qp;
guint32 num_slices;
guint32 max_bframes;
};
struct _GstVaapiEncodeH264Class

View file

@ -22,7 +22,6 @@
#include "gst/vaapi/sysdeps.h"
#include <gst/vaapi/gstvaapidisplay.h>
#include <gst/vaapi/gstvaapiencoder_mpeg2.h>
#include "gst/vaapi/gstvaapiencoder_mpeg2_priv.h"
#include "gstvaapiencode_mpeg2.h"
#include "gstvaapipluginutil.h"
#if GST_CHECK_VERSION(1,0,0)
@ -82,20 +81,10 @@ static GstStaticPadTemplate gst_vaapiencode_mpeg2_src_factory =
G_DEFINE_TYPE (GstVaapiEncodeMpeg2, gst_vaapiencode_mpeg2,
GST_TYPE_VAAPIENCODE);
enum
{
PROP_0,
PROP_QUANTIZER,
PROP_KEY_PERIOD,
PROP_MAX_BFRAMES
};
static void
gst_vaapiencode_mpeg2_init (GstVaapiEncodeMpeg2 * encode)
{
encode->quantizer = GST_VAAPI_ENCODER_MPEG2_DEFAULT_CQP;
encode->intra_period = GST_VAAPI_ENCODER_MPEG2_DEFAULT_GOP_SIZE;
encode->ip_period = GST_VAAPI_ENCODER_MPEG2_DEFAULT_MAX_BFRAMES;
gst_vaapiencode_init_properties (GST_VAAPIENCODE_CAST (encode));
}
static void
@ -108,19 +97,12 @@ static void
gst_vaapiencode_mpeg2_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
{
GstVaapiEncodeMpeg2 *const encode = GST_VAAPIENCODE_MPEG2_CAST (object);
GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (object);
switch (prop_id) {
case PROP_QUANTIZER:
encode->quantizer = g_value_get_uint (value);
break;
case PROP_KEY_PERIOD:
encode->intra_period = g_value_get_uint (value);
break;
case PROP_MAX_BFRAMES:
encode->ip_period = g_value_get_uint (value);
break;
default:
if (!encode_class->set_property (base_encode, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
@ -130,19 +112,12 @@ static void
gst_vaapiencode_mpeg2_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec)
{
GstVaapiEncodeMpeg2 *const encode = GST_VAAPIENCODE_MPEG2_CAST (object);
GstVaapiEncodeClass *const encode_class = GST_VAAPIENCODE_GET_CLASS (object);
GstVaapiEncode *const base_encode = GST_VAAPIENCODE_CAST (object);
switch (prop_id) {
case PROP_QUANTIZER:
g_value_set_uint (value, encode->quantizer);
break;
case PROP_KEY_PERIOD:
g_value_set_uint (value, encode->intra_period);
break;
case PROP_MAX_BFRAMES:
g_value_set_uint (value, encode->ip_period);
break;
default:
if (!encode_class->get_property (base_encode, prop_id, value))
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
@ -152,21 +127,7 @@ static GstVaapiEncoder *
gst_vaapiencode_mpeg2_create_encoder (GstVaapiEncode * base,
GstVaapiDisplay * display)
{
GstVaapiEncodeMpeg2 *const encode = GST_VAAPIENCODE_MPEG2_CAST (base);
GstVaapiEncoder *base_encoder;
GstVaapiEncoderMpeg2 *encoder;
base_encoder = gst_vaapi_encoder_mpeg2_new (display);
if (!base_encoder)
return NULL;
encoder = GST_VAAPI_ENCODER_MPEG2 (base_encoder);
encoder->profile = GST_VAAPI_ENCODER_MPEG2_DEFAULT_PROFILE;
encoder->level = GST_VAAPI_ENCODER_MPEG2_DEFAULT_LEVEL;
encoder->cqp = encode->quantizer;
encoder->intra_period = encode->intra_period;
encoder->ip_period = encode->ip_period;
return base_encoder;
return gst_vaapi_encoder_mpeg2_new (display);
}
static void
@ -183,6 +144,7 @@ gst_vaapiencode_mpeg2_class_init (GstVaapiEncodeMpeg2Class * klass)
object_class->set_property = gst_vaapiencode_mpeg2_set_property;
object_class->get_property = gst_vaapiencode_mpeg2_get_property;
encode_class->get_properties = gst_vaapi_encoder_mpeg2_get_default_properties;
encode_class->create_encoder = gst_vaapiencode_mpeg2_create_encoder;
gst_element_class_set_static_metadata (element_class,
@ -198,33 +160,5 @@ gst_vaapiencode_mpeg2_class_init (GstVaapiEncodeMpeg2Class * klass)
gst_element_class_add_pad_template (element_class,
gst_static_pad_template_get (&gst_vaapiencode_mpeg2_src_factory));
g_object_class_install_property (object_class,
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));
g_object_class_install_property (object_class,
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));
g_object_class_install_property (object_class,
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));
gst_vaapiencode_class_init_properties (encode_class);
}