0. filesrc插件介绍
filesrc在gstreamer的官方介绍可参考此链接,其主要作用是从一个本地文件系统中的一个文件中读取数据。
根据上一篇博客知道一个plugin有哪些部分组成,那么本文就按照之前的框架来对filesrc插件进行分析。在分析filesrc插件之前,说明一下我获取插件源码的方式:
- 假设你系统中已经按照好了gstreamer,那么通过命令 gst-inspect-1.0 filesrc就能获取到filesrc插件的相关信息,同样你也能看到下图
根据Origin URL,我们就能链接到源码的位置。
2. 此时的界面的内容应该与下图类似
我们下滑页面,通过filesrc信息中提供的版本号Version选择对应的版本进行下载解压就能得到firesrc的源码。
1. 代码分析
根据上一篇博客的内容,首先应该是一些basic code来注册element,然后是plugin_init函数用于判断是否正确加载element的依赖项,之后就是最主要的两个构造函数_class_init和_init,同时也关心一下element的pad和metadata信息,因此我们也就按照这样的结构来分析filesrc插件。
1.1 basic code
这些东西都大差不差,就是一些宏定义加上两个结构体。
#define GST_TYPE_FILE_SRC \
(gst_file_src_get_type())
#define GST_FILE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_FILE_SRC,GstFileSrc))
#define GST_FILE_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_FILE_SRC,GstFileSrcClass))
#define GST_IS_FILE_SRC(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_FILE_SRC))
#define GST_IS_FILE_SRC_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_FILE_SRC))
#define GST_FILE_SRC_CAST(obj) ((GstFileSrc*) obj)
struct _GstFileSrc {
GstBaseSrc element;
/*< private >*/
gchar *filename; /* filename */
gchar *uri; /* caching the URI */
gint fd; /* open file descriptor */
guint64 read_position; /* position of fd */
gboolean seekable; /* whether the file is seekable */
gboolean is_regular; /* whether it's a (symlink to a)
regular file */
};
struct _GstFileSrcClass {
GstBaseSrcClass parent_class;
};
1.2 plugin_init函数
//! plugins/elements/gstelements.c
static gboolean
plugin_init (GstPlugin * plugin)
{
...
if (!gst_element_register (plugin, "filesrc", GST_RANK_PRIMARY,
gst_file_src_get_type ()))
return FALSE;
...
}
1.3 两个构造函数
gst_file_src_class_init函数调用一次用来初始化GstFileClass类。
static void
gst_file_src_class_init (GstFileSrcClass * klass)
{
GObjectClass *gobject_class;
GstElementClass *gstelement_class;
GstBaseSrcClass *gstbasesrc_class;
gobject_class = G_OBJECT_CLASS (klass);
gstelement_class = GST_ELEMENT_CLASS (klass);
gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
...
}
而gst_file_src_init更像传统意义上类的构造函数,用来初始化类中成员变量。
static void
gst_file_src_init (GstFileSrc * src)
{
src->filename = NULL;
src->fd = 0;
src->uri = NULL;
src->is_regular = FALSE;
gst_base_src_set_blocksize (GST_BASE_SRC (src), DEFAULT_BLOCKSIZE);
}
1.4 element的pad信息
filesrc作为一个source element,其仅包含src pad。
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS_ANY);
// 在_class_init函数中
gst_element_class_add_static_pad_template (gstelement_class, &srctemplate);
1.5 metadata信息
gst_element_class_set_static_metadata (gstelement_class,
"File Source",
"Source/File",
"Read from arbitrary point in a file",
"Erik Walthinsen <omega@cse.ogi.edu>");
2.继承 GstBaseSrc类
通过下面的继承结果,可以知道filesrc插件是继承之GstBaseSrc类的。因此filesrc的实现通过重载GstBaseSrc中的函数来完成相应的功能。
GstBaseSrc的介绍的链接在此,大家可以简单的浏览一下。接下来就来分析filesrc插件具体实现功能的代码。
在gst_file_src_class_init函数中,使用了不同的函数指针初始化了不同的功能,大致情况如下:
// 设置gobject_class的成员函数
// 设置filesrc的属性
gobject_class->set_property = gst_file_src_set_property;
// 获取属性
gobject_class->get_property = gst_file_src_get_property;
//
gobject_class->finalize = gst_file_src_finalize;
// GstBaseSrc属性设置
gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_file_src_start);
gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_file_src_stop);
gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR (gst_file_src_is_seekable);
gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_file_src_get_size);
gstbasesrc_class->fill = GST_DEBUG_FUNCPTR (gst_file_src_fill);
接下来分别解析这些函数的含义。
2.1 set_property函数
static void
gst_file_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstFileSrc *src;
g_return_if_fail (GST_IS_FILE_SRC (object));
src = GST_FILE_SRC (object);
switch (prop_id) {
case PROP_LOCATION: // location属性设置
gst_file_src_set_location (src, g_value_get_string (value), NULL);
break;
default: // 其他不支持的属性(错误输入)
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
}
set_property主要是对element的属性设置,而在filesrc插件可设置的输入包含如下一些内容:
其中最主要的是location属性的设置,具体实现代码如下:
static gboolean
gst_file_src_set_location (GstFileSrc * src, const gchar * location,
GError ** err)
{
GstState state;
/* the element must be stopped in order to do this */
GST_OBJECT_LOCK (src);
state = GST_STATE (src);
// 只有在GST_STATE_READY和GST_STATE_NULL状态下才能对location属性进行修改
if (state != GST_STATE_READY && state != GST_STATE_NULL)
goto wrong_state;
GST_OBJECT_UNLOCK (src);
// 释放filename和uri之前指向的内存空间
g_free (src->filename);
g_free (src->uri);
/* clear the filename if we get a NULL */
if (location == NULL) {
src->filename = NULL;
src->uri = NULL;
} else {
/* we store the filename as received by the application. On Windows this
* should be UTF8 */
src->filename = g_strdup (location); // filename和uri属性设置
src->uri = gst_filename_to_uri (location, NULL);
GST_INFO ("filename : %s", src->filename);
GST_INFO ("uri : %s", src->uri);
}
g_object_notify (G_OBJECT (src), "location");
/* FIXME 2.0: notify "uri" property once there is one */
return TRUE;
}
2.2 finalize函数
finalize函数在对象析构时被调用。
static void
gst_file_src_finalize (GObject * object)
{
GstFileSrc *src;
src = GST_FILE_SRC (object);
g_free (src->filename);
g_free (src->uri);
// 子类析构调用父类析构
G_OBJECT_CLASS (parent_class)->finalize (object);
}
2.3 GstBaseSrc属性设置