gst是基于Gobject来开发的,Gobject提供 类,继承 对象注册 和gst信号机制的基础。GStreamer代码里面有充斥着Goject的代码,Gobject也是理解Gstreamer各个模块的基础。需要了解的是几个方面, 如何向GOject注册一个新类, 如何创建一个新类, 一个类如何继承另一类。
3.1了解如何向Goject注册类
以video_decoder类为例
#define GST_TYPE_VIDEO_DECODER \
(gst_video_decoder_get_type())
其中gst_video_decoder_get_type:
GType
gst_video_decoder_get_type (void)
{
static volatile gsize type = 0;
if (g_once_init_enter (&type)) {
GType _type;
static const GTypeInfo info = {
sizeof (GstVideoDecoderClass),
NULL,
NULL,
(GClassInitFunc) gst_video_decoder_class_init,
NULL,
NULL,
sizeof (GstVideoDecoder),
0,
(GInstanceInitFunc) gst_video_decoder_init,
};
_type = g_type_register_static (GST_TYPE_ELEMENT,
"GstVideoDecoder", &info, G_TYPE_FLAG_ABSTRACT);
g_once_init_leave (&type, _type);
}
return type;
}
可以看出向Gobject注册一个类 需要先定义GTypeInfo 类型,然后调用g_type_register_static 向GTYPE去注册。Goject也提供一个宏G_DEFINE_TYPE , 直接传入注册的名字,名字的小写 和 父类 就可以代替上面的代码完成注册如下:
G_DEFINE_TYPE (GstDecodebin3, gst_decodebin3, GST_TYPE_BIN);
注册了之后,在这个Goject系统里面就有了这个类,可以直接调用g_object_new来创建一个类。
3.2 理解类结构体和实例结构体
在Goject中将类分成两个部分一个是实例结构体 一个类结构体。实例结构体就是每创建一个对象要给对象分配一个即成员变量,类结构就只有一个,类结构体一般定义的是能够被继承的函数即成员函数。
还是gstvideodecoder为例
typedef struct _GstVideoDecoder GstVideoDecoder;
typedef struct _GstVideoDecoderClass GstVideoDecoderClass;
定义了两个结构体
其中实例结构体_GstVideoDecoder 定义了一堆的变量
struct _GstVideoDecoder
{
/*< private >*/
GstElement element;
/*< protected >*/
GstPad *sinkpad;
GstPad *srcpad;
/* protects all data processing, i.e. is locked
* in the chain function, finish_frame and when
* processing serialized events */
GRecMutex stream_lock;
/* MT-protected (with STREAM_LOCK) */
GstSegment input_segment;
GstSegment output_segment;
GstVideoDecoderPrivate *priv;
/*< private >*/
void *padding[GST_PADDING_LARGE];
};
而class里面就定义一堆的函数指针。
struct _GstVideoDecoderClass
{
/*< private >*/
GstElementClass element_class;
/*< public >*/
gboolean (*open) (GstVideoDecoder *decoder);
gboolean (*close) (GstVideoDecoder *decoder);
gboolean (*start) (GstVideoDecoder *decoder);
gboolean (*stop) (GstVideoDecoder *decoder);
GstFlowReturn (*parse) (GstVideoDecoder *decoder,
GstVideoCodecFrame *frame,
GstAdapter *adapter,
gboolean at_eos);
gboolean (*set_format) (GstVideoDecoder *decoder,
GstVideoCodecState * state);
gboolean (*reset) (GstVideoDecoder *decoder,
gboolean hard);
GstFlowReturn (*finish) (GstVideoDecoder *decoder);
GstFlowReturn (*handle_frame) (GstVideoDecoder *decoder,
GstVideoCodecFrame *frame);
gboolean (*sink_event) (GstVideoDecoder *decoder,
GstEvent *event);
gboolean (*src_event) (GstVideoDecoder *decoder,
GstEvent *event);
gboolean (*negotiate) (GstVideoDecoder *decoder);
gboolean (*decide_allocation) (GstVideoDecoder *decoder, GstQuery *query);
gboolean (*propose_allocation) (GstVideoDecoder *decoder, GstQuery * query);
gboolean (*flush) (GstVideoDecoder *decoder);
gboolean (*sink_query) (GstVideoDecoder *decoder,
GstQuery *query);
gboolean (*src_query) (GstVideoDecoder *decoder,
GstQuery *query);
GstCaps* (*getcaps) (GstVideoDecoder *decoder,
GstCaps *filter);
GstFlowReturn (*drain) (GstVideoDecoder *decoder);
gboolean (*transform_meta) (GstVideoDecoder *decoder,
GstVideoCodecFrame *frame,
GstMeta * meta);
/*< private >*/
void *padding[GST_PADDING_LARGE-6];
}
另外从上面的代码也可以看到子类继承父类的方式 就是在子类定义类和结构体中分别包含父类的类和结构体,从上面可以看到GstVideoDecoder继承自Gstelement。当新建一个类的对象时 会默认调用以下类结构体和实例结构体初始化函数,其中类结构只在第一次创建的时候调用,同样类结构体中做了一些初始化函数指针的操作,而实例结构体则是成员的赋值。
static void
gst_video_decoder_init (GstVideoDecoder * decoder, GstVideoDecoderClass * klass)
static void
gst_video_decoder_class_init (GstVideoDecoderClass * klass)
综上:
Goject 将类抽象成两个不同的结构体,并分别用不同的函数进行注册,另外还有调用GOject的宏向Gtype系统注册类