v4l2videodec: Simplify sub-instanciation mechanism

Simplify sub-instanciation by defining an absract type and using subtype
class and instance init callback. This also fixes a bug where the template
pads get initialized too late.

https://bugzilla.gnome.org/show_bug.cgi?id=727925
This commit is contained in:
Nicolas Dufresne 2014-03-16 11:38:07 +01:00 committed by Nicolas Dufresne
parent e06c9f7fce
commit f7d34bd237
2 changed files with 44 additions and 73 deletions

View file

@ -37,9 +37,6 @@
#define DEFAULT_PROP_DEVICE "/dev/video0"
#define V4L2_VIDEO_DEC_QUARK \
g_quark_from_static_string("gst-v4l2-video-dec-info")
GST_DEBUG_CATEGORY_STATIC (gst_v4l2_video_dec_debug);
#define GST_CAT_DEFAULT gst_v4l2_video_dec_debug
@ -50,7 +47,7 @@ typedef struct
gchar *device;
GstCaps *sink_caps;
GstCaps *src_caps;
} Gstv4l2VideoDecQData;
} GstV4l2VideoDecCData;
enum
{
@ -59,39 +56,9 @@ enum
PROP_CAPTURE_IO_MODE,
};
static void gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass);
static void gst_v4l2_video_dec_init (GstV4l2VideoDec * self, gpointer g_class);
static void gst_v4l2_video_dec_base_init (gpointer g_class);
static GstVideoDecoderClass *parent_class = NULL;
GType
gst_v4l2_video_dec_get_type (void)
{
static volatile gsize type = 0;
if (g_once_init_enter (&type)) {
GType _type;
static const GTypeInfo info = {
sizeof (GstV4l2VideoDecClass),
gst_v4l2_video_dec_base_init,
NULL,
(GClassInitFunc) gst_v4l2_video_dec_class_init,
NULL,
NULL,
sizeof (GstV4l2VideoDec),
0,
(GInstanceInitFunc) gst_v4l2_video_dec_init,
NULL
};
_type = g_type_register_static (GST_TYPE_VIDEO_DECODER, "GstV4l2VideoDec",
&info, 0);
g_once_init_leave (&type, _type);
}
return type;
}
#define gst_v4l2_video_dec_parent_class parent_class
G_DEFINE_ABSTRACT_TYPE (GstV4l2VideoDec, gst_v4l2_video_dec,
GST_TYPE_VIDEO_DECODER);
static void
gst_v4l2_video_dec_set_property (GObject * object,
@ -711,52 +678,33 @@ gst_v4l2_video_dec_finalize (GObject * object)
}
static void
gst_v4l2_video_dec_base_init (gpointer g_class)
gst_v4l2_video_dec_init (GstV4l2VideoDec * self)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
Gstv4l2VideoDecQData *qdata;
GstPadTemplate *templ;
qdata = g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), V4L2_VIDEO_DEC_QUARK);
if (!qdata)
return;
templ =
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
qdata->sink_caps);
gst_element_class_add_pad_template (element_class, templ);
templ =
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
qdata->src_caps);
gst_element_class_add_pad_template (element_class, templ);
/* V4L2 object are created in subinstance_init */
}
static void
gst_v4l2_video_dec_init (GstV4l2VideoDec * self, gpointer g_class)
gst_v4l2_video_dec_subinstance_init (GTypeInstance * instance, gpointer g_class)
{
GstVideoDecoder *decoder = (GstVideoDecoder *) self;
Gstv4l2VideoDecQData *qdata;
qdata = g_type_get_qdata (G_TYPE_FROM_CLASS (g_class), V4L2_VIDEO_DEC_QUARK);
if (!qdata)
return;
GstV4l2VideoDecClass *klass = GST_V4L2_VIDEO_DEC_CLASS (g_class);
GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (instance);
GstVideoDecoder *decoder = GST_VIDEO_DECODER (instance);
gst_video_decoder_set_packetized (decoder, TRUE);
self->v4l2output = gst_v4l2_object_new (GST_ELEMENT (self),
V4L2_BUF_TYPE_VIDEO_OUTPUT, qdata->device,
V4L2_BUF_TYPE_VIDEO_OUTPUT, klass->default_device,
gst_v4l2_get_output, gst_v4l2_set_output, NULL);
self->v4l2output->no_initial_format = TRUE;
self->v4l2output->keep_aspect = FALSE;
self->v4l2capture = gst_v4l2_object_new (GST_ELEMENT (self),
V4L2_BUF_TYPE_VIDEO_CAPTURE, qdata->device,
V4L2_BUF_TYPE_VIDEO_CAPTURE, klass->default_device,
gst_v4l2_get_input, gst_v4l2_set_input, NULL);
self->v4l2capture->no_initial_format = TRUE;
self->v4l2output->keep_aspect = FALSE;
g_object_set (self, "device", qdata->device, NULL);
g_object_set (self, "device", klass->default_device, NULL);
}
static void
@ -825,6 +773,26 @@ gst_v4l2_video_dec_class_init (GstV4l2VideoDecClass * klass)
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
gst_v4l2_video_dec_subclass_init (gpointer g_class, gpointer data)
{
GstV4l2VideoDecClass *klass = GST_V4L2_VIDEO_DEC_CLASS (g_class);
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
GstV4l2VideoDecCData *cdata = data;
klass->default_device = cdata->device;
/* Note: gst_pad_template_new() take the floating ref from the caps */
gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS,
cdata->sink_caps));
gst_element_class_add_pad_template (element_class,
gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
cdata->src_caps));
g_free (cdata);
}
/* Probing functions */
static GstCaps *
gst_v4l2_video_dec_probe_caps (gchar * device, gint video_fd,
@ -911,24 +879,25 @@ gst_v4l2_video_dec_register (GstPlugin * plugin)
GTypeInfo type_info = { 0, };
GType type, subtype;
gchar *type_name;
Gstv4l2VideoDecQData *qdata;
GstV4l2VideoDecCData *cdata;
cdata = g_new0 (GstV4l2VideoDecCData, 1);
cdata->device = g_strdup (device);
cdata->sink_caps = gst_caps_ref (sink_caps);
cdata->src_caps = gst_caps_ref (src_caps);
type = gst_v4l2_video_dec_get_type ();
g_type_query (type, &type_query);
memset (&type_info, 0, sizeof (type_info));
type_info.class_size = type_query.class_size;
type_info.instance_size = type_query.instance_size;
type_info.class_init = gst_v4l2_video_dec_subclass_init;
type_info.class_data = cdata;
type_info.instance_init = gst_v4l2_video_dec_subinstance_init;
type_name = g_strdup_printf ("v4l2video%ddec", i);
subtype = g_type_register_static (type, type_name, &type_info, 0);
qdata = g_new0 (Gstv4l2VideoDecQData, 1);
qdata->device = g_strdup (device);
qdata->sink_caps = gst_caps_ref (sink_caps);
qdata->src_caps = gst_caps_ref (src_caps);
g_type_set_qdata (subtype, V4L2_VIDEO_DEC_QUARK, qdata);
gst_element_register (plugin, type_name, GST_RANK_PRIMARY + 1, subtype);
g_free (type_name);

View file

@ -72,6 +72,8 @@ struct _GstV4l2VideoDec
struct _GstV4l2VideoDecClass
{
GstVideoDecoderClass parent_class;
gchar *default_device;
};
GType gst_v4l2_video_dec_get_type (void);