当前位置:网站首页>Initialization process of gstlibav
Initialization process of gstlibav
2022-06-25 22:44:00 【Hui's technical notes】
gst-libav File directory structure
gstlibav The core code is gst-libav/ext/libav Under the table of contents , hold plugin Corresponding c There are so many documents listed as follows :
gst-libav/ext/libav
├── gstavauddec.c
├── gstavaudenc.c
├── gstav.c
├── gstavdemux.c
├── gstavmux.c
├── gstavprotocol.c
├── gstavutils.c
├── gstavviddec.c
├── gstavvidenc.c
gstav.c It defines plugin_init function ,plugin_init yes libav The entry function of , stay plugin_init Will call decoder, demux, mux Corresponding register function
plugin_init
- gst_ffmpeg_log_callback
- gst_ffmpeg_init_pix_fmt_info
- gst_ffmpeg_cfg_init
- gst_ffmpegaudenc_register
- gst_ffmpegvidenc_register
- gst_ffmpegauddec_register
- gst_ffmpegviddec_register
- gst_ffmpegdemux_register
- gst_ffmpegmux_register
- gst_ffmpegdeinterlace_register
GST_PLUGIN_DEFINE Expansion of
gst/gstplugin.h
gstav.c Of GST_PLUGIN_DEFINE Initialize the plugin Basic information of , hold plugin_init As a parameter init Passed on to gst_plugin_register_static,gst_plugin_register_static In the following decomposition analysis, we can see .
#define GST_VERSION_MAJOR (1)
#define GST_VERSION_MINOR (14)
#define GST_VERSION_MICRO (5)
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
GST_VERSION_MINOR,
libav,
"All libav codecs and formats (" LIBAV_SOURCE ")",
plugin_init, PACKAGE_VERSION, LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
GST_PLUGIN_DEFINE Macro definition
#define GST_PLUGIN_DEFINE(major,minor,name,description,init,version,license,package,origin) \
G_BEGIN_DECLS \
GST_PLUGIN_EXPORT const GstPluginDesc * G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void); \
GST_PLUGIN_EXPORT void G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void); \
\
static const GstPluginDesc gst_plugin_desc = { \
major, \
minor, \
G_STRINGIFY(name), \
(gchar *) description, \
init, \
version, \
license, \
PACKAGE, \
package, \
origin, \
__GST_PACKAGE_RELEASE_DATETIME, \
GST_PADDING_INIT \
}; \
\
const GstPluginDesc * \c++
G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void) \
{ \
return &gst_plugin_desc; \
} \
\
void \
G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void) \
{ \
gst_plugin_register_static (major, minor, G_STRINGIFY(name), \
description, init, version, license, \
PACKAGE, package, origin); \
} \
G_END_DECLS
gst_plugin_register_static: gstreamer/gst/gstplugin.c
gst_plugin_register_func: gstreamer/gst/gstplugin.c
G_PASTE & G_PASTE_ARGS
#define G_PASTE_ARGS(identifier1,identifier2) identifier1 ## identifier2
#define G_PASTE(identifier1,identifier2) G_PASTE_ARGS (identifier1, identifier2)
According to the following GST_PLUGIN_DEFINE The definition of , front GST_PLUGIN_DEFINE Defined libav You can expand them one by one .
The first two function declarations expand :
const GstPluginDesc * G_PASTE(gst_plugin_, G_PASTE(name, _get_desc)) (void);
\
const GstPluginDesc *G_PASTE(gst_plugin_, libav_get_desc)) (void);
\
const GstPluginDesc gst_plugin_libav_get_desc (void);
void G_PASTE(gst_plugin_, G_PASTE(name, _register)) (void);
\
void G_PASTE(gst_plugin_, libav_register) (void);
void gst_plugin_libav_register(void);
After deployment , The first two lines declare two functions gst_plugin_libav_get_desc and gst_plugin_libav_register.
gst_plugin_desc
The middle part is right gst_plugin_desc Initialization of structure :
static const GstPluginDesc gst_plugin_desc = { \
major, \
minor, \
G_STRINGIFY(name), \
(gchar *) description, \
init, \
version, \
license, \
PACKAGE, \
package, \
origin, \
__GST_PACKAGE_RELEASE_DATETIME, \
GST_PADDING_INIT \
};
_GstPluginDesc Prototype
struct _GstPluginDesc {
gint major_version;
gint minor_version;
const gchar *name;
const gchar *description;
GstPluginInitFunc plugin_init;
const gchar *version;
const gchar *license;
const gchar *source;
const gchar *package;
const gchar *origin;
const gchar *release_datetime;
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
gst_plugin_libav_register & gst_plugin_libav_get_desc
The macro expands as follows :
const GstPluginDesc gst_plugin_libav_get_desc (void) {
return &gst_plugin_desc;
}
void gst_plugin_libav_register(void) {
gst_plugin_register_static (major, minor, G_STRINGIFY(name),
description, init, version, license, PACKAGE, package, origin);
}
gst_plugin_register_static
gst_plugin_register_func Created in GObject Type of plugin, Through the gst_plugin_desc initialization , And then call plugin_init function
gboolean
gst_plugin_register_static (gint major_version, gint minor_version,
const gchar * name, const gchar * description, GstPluginInitFunc init_func,
const gchar * version, const gchar * license, const gchar * source,
const gchar * package, const gchar * origin)
{
GstPluginDesc desc = {
major_version, minor_version, name, description,
init_func, version, license, source, package, origin, NULL,
};
GstPlugin *plugin;
gboolean res = FALSE;
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (description != NULL, FALSE);
g_return_val_if_fail (init_func != NULL, FALSE);
g_return_val_if_fail (version != NULL, FALSE);
g_return_val_if_fail (license != NULL, FALSE);
g_return_val_if_fail (source != NULL, FALSE);
g_return_val_if_fail (package != NULL, FALSE);
g_return_val_if_fail (origin != NULL, FALSE);
/* make sure gst_init() has been called */
g_return_val_if_fail (_gst_plugin_inited != FALSE, FALSE);
GST_LOG ("attempting to load static plugin \"%s\" now...", name);
// establish plugin
plugin = g_object_new (GST_TYPE_PLUGIN, NULL);
// call gst_plugin_register_func
if (gst_plugin_register_func (plugin, &desc, NULL) != NULL) {
GST_INFO ("registered static plugin \"%s\"", name);
// gst_registry_get get registry, It's actually a GstRegistry Type of static Global variable of
// gst_registry_add_plugin Put this plugin Add to registry Of list Inside
res = gst_registry_add_plugin (gst_registry_get (), plugin);
GST_INFO ("added static plugin \"%s\", result: %d", name, res);
}
return res;
}
gst_plugin_register_func
gst_plugin_register_func() Function plugin Registration of , Information such as version will be checked , Then copy about plugin Description information of , Through the function pointer desc->plugin_init Real completion plugin Registration of .
static GstPlugin *
gst_plugin_register_func (GstPlugin * plugin, const GstPluginDesc * desc,
gpointer user_data)
{
if (!gst_plugin_check_version (desc->major_version, desc->minor_version)) {
if (GST_CAT_DEFAULT)
GST_WARNING ("plugin \"%s\" has incompatible version "
"(plugin: %d.%d, gst: %d,%d), not loading",
GST_STR_NULL (plugin->filename), desc->major_version,
desc->minor_version, GST_VERSION_MAJOR, GST_VERSION_MINOR);
return NULL;
}
if (!desc->license || !desc->description || !desc->source ||
!desc->package || !desc->origin) {
if (GST_CAT_DEFAULT)
GST_WARNING ("plugin \"%s\" has missing detail in GstPluginDesc, not "
"loading", GST_STR_NULL (plugin->filename));
return NULL;
}
if (!gst_plugin_check_license (desc->license)) {
if (GST_CAT_DEFAULT)
GST_WARNING ("plugin \"%s\" has invalid license \"%s\", not loading",
GST_STR_NULL (plugin->filename), desc->license);
return NULL;
}
if (GST_CAT_DEFAULT)
GST_LOG ("plugin \"%s\" looks good", GST_STR_NULL (plugin->filename));
gst_plugin_desc_copy (&plugin->desc, desc);
/* make resident so we're really sure it never gets unloaded again. * Theoretically this is not needed, but practically it doesn't hurt. * And we're rather safe than sorry. */
if (plugin->module)
g_module_make_resident (plugin->module);
if (user_data) {
// plugin_init call
if (!(((GstPluginInitFullFunc) (desc->plugin_init)) (plugin, user_data))) {
if (GST_CAT_DEFAULT)
GST_WARNING ("plugin \"%s\" failed to initialise",
GST_STR_NULL (plugin->filename));
return NULL;
}
} else {
// plugin_init call
if (!((desc->plugin_init) (plugin))) {
if (GST_CAT_DEFAULT)
GST_WARNING ("plugin \"%s\" failed to initialise",
GST_STR_NULL (plugin->filename));
return NULL;
}
}
if (GST_CAT_DEFAULT)
GST_LOG ("plugin \"%s\" initialised", GST_STR_NULL (plugin->filename));
return plugin;
}
gst_registry_add_plugin
gst_registry_add_plugin() Function and gst_registry_add_feature() Function similar to ,gst_registry_add_feature() Yes, it will feature Saved to the global variable _gst_registry_default Of ``priv->features member , and gst_registry_add_plugin Will create plugin Add to save to _gst_registry_default Of priv->plugins` member .
gboolean
gst_registry_add_plugin (GstRegistry * registry, GstPlugin * plugin)
{
GstPlugin *existing_plugin;
g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE);
GST_OBJECT_LOCK (registry);
if (G_LIKELY (plugin->basename)) {
/* we have a basename, see if we find the plugin */
existing_plugin =
gst_registry_lookup_bn_locked (registry, plugin->basename);
if (existing_plugin) {
// ... ...
}
}
// pipeline When it's running grep ‘adding plugin‘ You can see plugin Registered log
GST_DEBUG_OBJECT (registry, "adding plugin %p for filename \"%s\"",
plugin, GST_STR_NULL (plugin->filename));
// add to plugin To registry Of list
registry->priv->plugins = g_list_prepend (registry->priv->plugins, plugin);
++registry->priv->n_plugins;
if (G_LIKELY (plugin->basename))
g_hash_table_replace (registry->priv->basename_hash, plugin->basename,
plugin);
gst_object_ref_sink (plugin);
GST_OBJECT_UNLOCK (registry);
GST_LOG_OBJECT (registry, "emitting plugin-added for filename \"%s\"",
GST_STR_NULL (plugin->filename));
g_signal_emit (registry, gst_registry_signals[PLUGIN_ADDED], 0, plugin);
return TRUE;
}
libav plugin Of log Output :
grep 'adding plugin' pipeline.log
adding plugin 0x55fdcb68d190 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstx265.so"
adding plugin 0x55fdcb68d2c0 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgsttimecode.so"
adding plugin 0x55fdcb68d3f0 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstinterlace.so"
adding plugin 0x55fdcb68d520 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstdc1394.so"
adding plugin 0x55fdcb68d650 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstde265.so"
adding plugin 0x55fdcb68d780 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstadpcmdec.so"
adding plugin 0x55fdcb68d8b0 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfaad.so"
adding plugin 0x55fdcb68d9e0 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstvcdsrc.so"
adding plugin 0x55fdcb68db10 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfrei0r.so"
adding plugin 0x55fdcb68dc40 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfieldanalysis.so"
adding plugin 0x55fdcb68dd70 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstasf.so"
adding plugin 0x55fdcb68dea0 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstopenglmixers.so"
adding plugin 0x55fdcb697060 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstwaylandsink.so"
adding plugin 0x55fdcb697190 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfbdevsink.so"
adding plugin 0x55fdcb6972c0 for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstuvch264.so"
grep 'plugin-added' pipeline.log
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstx265.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgsttimecode.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstinterlace.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstdc1394.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstde265.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstadpcmdec.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfaad.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstvcdsrc.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfrei0r.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstfieldanalysis.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstasf.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstopenglmixers.so"
emitting plugin-added for filename "/usr/lib/x86_64-linux-gnu/gstreamer-1.0/libgstwaylandsink.so"
plugin_init
plugin The parameter is gst_plugin_register_static Call in plugin_init Function ,
static gboolean
plugin_init (GstPlugin * plugin)
{
// initialization debug Parameters
GST_DEBUG_CATEGORY_INIT (ffmpeg_debug, "libav", 0, "libav elements");
/* Bail if not FFmpeg. We can no longer ensure operation with Libav */
if (!gst_ffmpeg_avcodec_is_ffmpeg ()) {
GST_ERROR_OBJECT (plugin,
"Incompatible, non-FFmpeg libavcodec/format found");
return FALSE;
}
// Set up callback
#ifndef GST_DISABLE_GST_DEBUG
av_log_set_callback (gst_ffmpeg_log_callback);
#endif
// initialization pix_fmt
gst_ffmpeg_init_pix_fmt_info ();
// initialization bitrate/gop/max-bframe/profile/level/color Equal parameter
/* build global ffmpeg param/property info */
gst_ffmpeg_cfg_init ();
// Register separately audio enc/video enc/audio dec/video dec/demux/mux/interlace
gst_ffmpegaudenc_register (plugin);
gst_ffmpegvidenc_register (plugin);
gst_ffmpegauddec_register (plugin);
gst_ffmpegviddec_register (plugin);
gst_ffmpegdemux_register (plugin);
gst_ffmpegmux_register (plugin);
gst_ffmpegdeinterlace_register (plugin);
/* Now we can return the pointer to the newly created Plugin object. */
return TRUE;
}
gst_ffmpeg_avcodec_is_ffmpeg
Judge ffmpeg Whether the version of is valid ,avcodec_version yes ffmpeg The function in , stay ffmpeg/libavcodec/avcodec.c in :
static inline gboolean
gst_ffmpeg_avcodec_is_ffmpeg (void)
{
guint av_version = avcodec_version ();
GST_DEBUG ("Using libavcodec version %d.%d.%d",
av_version >> 16, (av_version & 0x00ff00) >> 8, av_version & 0xff);
/* FFmpeg *_MICRO versions start at 100 and Libav's at 0 */
if ((av_version & 0xff) < 100)
return FALSE;
return TRUE;
}
gst_ffmpegdemux_register Expansion of
Definition typeinfo
initialization typeinfo Several function pointers to :
base_init = gst_ffmpegdemux_base_init
class_init = gst_ffmpegdemux_class_init
instance_init = gst_ffmpegdemux_init
GTypeInfo typeinfo = { sizeof (GstFFMpegDemuxClass), (GBaseInitFunc) gst_ffmpegdemux_base_init, NULL, (GClassInitFunc) gst_ffmpegdemux_class_init, NULL, NULL, sizeof (GstFFMpegDemux), 0, (GInstanceInitFunc) gst_ffmpegdemux_init, };
register ffmpeg All in demuxer
The code is as follows ,av_demuxer_iterate It's defined in ffmpeg/libavformat/allformats.c in , iteration , Traverse in turn demuxer_list All in demux.
Whole while The loop will take all plugin Go through it , If register_typefind_func Set to false,gst_type_find_register Certainly not .
while ((in_plugin = av_demuxer_iterate (&i))) {
/* Don't use the typefind functions of formats for which we already have * better typefind functions */
if (!strcmp (in_plugin->name, "mov,mp4,m4a,3gp,3g2,mj2") ||
!strcmp (in_plugin->name, "ass") ||
// ...
) {
// typefind Set to FALSE, no need libav
register_typefind_func = FALSE;
}
/* Set the rank of demuxers known to work to MARGINAL. * Set demuxers for which we already have another implementation to NONE * Set All others to NONE*/
if (!strcmp(in_plugin->name, "mov,mp4,m4a,3gp,3g2,mj2") ||
!strcmp(in_plugin->name, "matroska,webm") ||
!strcmp(in_plugin->name, "mpegts") ||
!strcmp(in_plugin->name, "flv") ||
// ...
) {
// The code of this department has been modified , hold avdemux The value of is set to the maximum rank value , And added mov etc.
rank = GST_RANK_PRIMARY + 1;
}
// Generate type_name, Finally through gst-inspect-1.0 | grep avdemux You can see things like avdemux_gif,avdemux_ape wait
/* construct the type */
type_name = g_strdup_printf ("avdemux_%s", in_plugin->name);
g_strdelimit (type_name, ".,|-<> ", '_');
// Generate typefind_name,dup 了 in_plugin->name
typefind_name = g_strdup_printf ("avtype_%s", in_plugin->name);
g_strdelimit (typefind_name, ".,|-<> ", '_');
// g_type_register_static yes GObject A function of
// GST_TYPE_ELEMENT Is to return element type
// typeinfo It was just the beginning typeinfo
/* create the type now */
type = g_type_register_static (GST_TYPE_ELEMENT, type_name, &typeinfo, 0);
g_type_set_qdata (type, GST_FFDEMUX_PARAMS_QDATA, (gpointer) in_plugin);
// gst_element_register register plugin
// register_typefind_func by true when , register type_find
if (!gst_element_register (plugin, type_name, rank, type) ||
(register_typefind_func == TRUE &&
!gst_type_find_register (plugin, typefind_name, rank,
gst_ffmpegdemux_type_find, extensions, NULL,
(gpointer) in_plugin, NULL))) {
g_warning ("Registration of type %s failed", type_name);
g_free (type_name);
g_free (typefind_name);
g_free (extensions);
return FALSE;
}
}
g_type_register_static
gobject/gtype.c
GType
g_type_register_static (GType parent_type,
const gchar *type_name,
const GTypeInfo *info,
GTypeFlags flags)
{
TypeNode *pnode, *node;
GType type = 0;
g_assert_type_system_initialized ();
g_return_val_if_fail (parent_type > 0, 0);
g_return_val_if_fail (type_name != NULL, 0);
g_return_val_if_fail (info != NULL, 0);
if (!check_type_name_I (type_name) ||
!check_derivation_I (parent_type, type_name))
return 0;
if (info->class_finalize)
{
g_warning ("class finalizer specified for static type '%s'",
type_name);
return 0;
}
pnode = lookup_type_node_I (parent_type);
G_WRITE_LOCK (&type_rw_lock);
type_data_ref_Wm (pnode);
if (check_type_info_I (pnode, NODE_FUNDAMENTAL_TYPE (pnode), type_name, info))
{
node = type_node_new_W (pnode, type_name, NULL);
type_add_flags_W (node, flags);
type = NODE_TYPE (node);
// This will info and node Connect
type_data_make_W (node, info,
check_value_table_I (type_name, info->value_table) ? info->value_table : NULL);
}
G_WRITE_UNLOCK (&type_rw_lock);
return type;
}
type_data_make_W
from type_data_make_W You can see in the implementation of class_init, front gst_ffmpegdemux_register Just beginning to define GTypeinfo The corresponding three functions in base_init = gst_ffmpegdemux_base_init、class_init = gst_ffmpegdemux_class_init、instance_init = gst_ffmpegdemux_init Is in this function and data Related to .
struct _GTypeInfo
{
/* interface types, classed types, instantiated types */
guint16 class_size;
GBaseInitFunc base_init;
GBaseFinalizeFunc base_finalize;
/* interface types, classed types, instantiated types */
GClassInitFunc class_init;
GClassFinalizeFunc class_finalize;
gconstpointer class_data;
/* instantiated types */
guint16 instance_size;
guint16 n_preallocs;
GInstanceInitFunc instance_init;
/* value handling */
const GTypeValueTable *value_table;
};
union _TypeData
{
CommonData common;
BoxedData boxed;
IFaceData iface;
ClassData class;
InstanceData instance;
};
struct _InstanceData
{
CommonData common;
guint16 class_size;
guint16 class_private_size;
int volatile init_state; /* atomic - g_type_class_ref reads it unlocked */
GBaseInitFunc class_init_base;
GBaseFinalizeFunc class_finalize_base;
GClassInitFunc class_init;
GClassFinalizeFunc class_finalize;
gconstpointer class_data;
gpointer class;
guint16 instance_size;
guint16 private_size;
guint16 n_preallocs;
GInstanceInitFunc instance_init;
};
struct _ClassData
{
CommonData common;
guint16 class_size;
guint16 class_private_size;
int volatile init_state; /* atomic - g_type_class_ref reads it unlocked */
GBaseInitFunc class_init_base;
GBaseFinalizeFunc class_finalize_base;
GClassInitFunc class_init;
GClassFinalizeFunc class_finalize;
gconstpointer class_data;
gpointer class;
};
TypeData It's a union type , It can be _ClassData, It can also be _InstanceData, stay type_data_make_W use _GTypeInfo Medium base_init、class_init、instance_init To assign a value to the corresponding item , that instance_init Where is it called ?
static void
type_data_make_W (TypeNode *node,
const GTypeInfo *info,
const GTypeValueTable *value_table)
{
TypeData *data;
GTypeValueTable *vtable = NULL;
guint vtable_size = 0;
g_assert (node->data == NULL && info != NULL);
if (!value_table)
{
TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
if (pnode)
vtable = pnode->data->common.value_table;
else
{
static const GTypeValueTable zero_vtable = {
NULL, };
value_table = &zero_vtable;
}
}
if (value_table)
{
/* need to setup vtable_size since we have to allocate it with data in one chunk */
vtable_size = sizeof (GTypeValueTable);
if (value_table->collect_format)
vtable_size += strlen (value_table->collect_format);
if (value_table->lcopy_format)
vtable_size += strlen (value_table->lcopy_format);
vtable_size += 2;
}
if (node->is_instantiatable) /* careful, is_instantiatable is also is_classed */
{
TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
data = g_malloc0 (sizeof (InstanceData) + vtable_size);
if (vtable_size)
vtable = G_STRUCT_MEMBER_P (data, sizeof (InstanceData));
data->instance.class_size = info->class_size;
data->instance.class_init_base = info->base_init;
data->instance.class_finalize_base = info->base_finalize;
data->instance.class_init = info->class_init;
data->instance.class_finalize = info->class_finalize;
data->instance.class_data = info->class_data;
data->instance.class = NULL;
data->instance.init_state = UNINITIALIZED;
data->instance.instance_size = info->instance_size;
/* We'll set the final value for data->instance.private size * after the parent class has been initialized */
data->instance.private_size = 0;
data->instance.class_private_size = 0;
if (pnode)
data->instance.class_private_size = pnode->data->instance.class_private_size;
data->instance.n_preallocs = MIN (info->n_preallocs, 1024);
data->instance.instance_init = info->instance_init;
}
else if (node->is_classed) /* only classed */
{
TypeNode *pnode = lookup_type_node_I (NODE_PARENT_TYPE (node));
data = g_malloc0 (sizeof (ClassData) + vtable_size);
if (vtable_size)
vtable = G_STRUCT_MEMBER_P (data, sizeof (ClassData));
data->class.class_size = info->class_size;
data->class.class_init_base = info->base_init;
data->class.class_finalize_base = info->base_finalize;
data->class.class_init = info->class_init;
data->class.class_finalize = info->class_finalize;
data->class.class_data = info->class_data;
data->class.class = NULL;
data->class.class_private_size = 0;
if (pnode)
data->class.class_private_size = pnode->data->class.class_private_size;
data->class.init_state = UNINITIALIZED;
}
else if (NODE_IS_IFACE (node))
{
data = g_malloc0 (sizeof (IFaceData) + vtable_size);
if (vtable_size)
vtable = G_STRUCT_MEMBER_P (data, sizeof (IFaceData));
data->iface.vtable_size = info->class_size;
data->iface.vtable_init_base = info->base_init;
data->iface.vtable_finalize_base = info->base_finalize;
data->iface.dflt_init = info->class_init;
data->iface.dflt_finalize = info->class_finalize;
data->iface.dflt_data = info->class_data;
data->iface.dflt_vtable = NULL;
}
else if (NODE_IS_BOXED (node))
{
data = g_malloc0 (sizeof (BoxedData) + vtable_size);
if (vtable_size)
vtable = G_STRUCT_MEMBER_P (data, sizeof (BoxedData));
}
else
{
data = g_malloc0 (sizeof (CommonData) + vtable_size);
if (vtable_size)
vtable = G_STRUCT_MEMBER_P (data, sizeof (CommonData));
}
node->data = data;
if (vtable_size)
{
gchar *p;
/* we allocate the vtable and its strings together with the type data, so * children can take over their parent's vtable pointer, and we don't * need to worry freeing it or not when the child data is destroyed */
*vtable = *value_table;
p = G_STRUCT_MEMBER_P (vtable, sizeof (*vtable));
p[0] = 0;
vtable->collect_format = p;
if (value_table->collect_format)
{
strcat (p, value_table->collect_format);
p += strlen (value_table->collect_format);
}
p++;
p[0] = 0;
vtable->lcopy_format = p;
if (value_table->lcopy_format)
strcat (p, value_table->lcopy_format);
}
node->data->common.value_table = vtable;
node->mutatable_check_cache = (node->data->common.value_table->value_init != NULL &&
!((G_TYPE_FLAG_VALUE_ABSTRACT | G_TYPE_FLAG_ABSTRACT) &
GPOINTER_TO_UINT (type_get_qdata_L (node, static_quark_type_flags))));
g_assert (node->data->common.value_table != NULL); /* paranoid */
g_atomic_int_set ((int *) &node->ref_count, 1);
}
g_type_create_instance
gobject/gtype.c
call instance.instance_size Is in g_type_create_instance Medium , These belong to Glib The content of , In fact, by g_object_new To call indirectly g_type_create_instance, The call stack is roughly as follows , I have to look at the details Glib Code for :
g_object_new
- g_object_new_internal
- g_type_create_instance
GTypeInstance*
g_type_create_instance (GType type)
{
TypeNode *node;
GTypeInstance *instance;
GTypeClass *class;
gchar *allocated;
gint private_size;
gint ivar_size;
guint i;
node = lookup_type_node_I (type);
if (!node || !node->is_instantiatable)
{
g_error ("cannot create new instance of invalid (non-instantiatable) type '%s'",
type_descriptive_name_I (type));
}
/* G_TYPE_IS_ABSTRACT() is an external call: _U */
if (!node->mutatable_check_cache && G_TYPE_IS_ABSTRACT (type))
{
g_error ("cannot create instance of abstract (non-instantiatable) type '%s'",
type_descriptive_name_I (type));
}
class = g_type_class_ref (type);
/* We allocate the 'private' areas before the normal instance data, in * reverse order. This allows the private area of a particular class * to always be at a constant relative address to the instance data. * If we stored the private data after the instance data this would * not be the case (since a subclass that added more instance * variables would push the private data further along). * * This presents problems for valgrindability, of course, so we do a * workaround for that case. We identify the start of the object to * valgrind as an allocated block (so that pointers to objects show up * as 'reachable' instead of 'possibly lost'). We then add an extra * pointer at the end of the object, after all instance data, back to * the start of the private area so that it is also recorded as * reachable. We also add extra private space at the start because * valgrind doesn't seem to like us claiming to have allocated an * address that it saw allocated by malloc(). */
private_size = node->data->instance.private_size;
ivar_size = node->data->instance.instance_size;
#ifdef ENABLE_VALGRIND
if (private_size && RUNNING_ON_VALGRIND)
{
private_size += ALIGN_STRUCT (1);
/* Allocate one extra pointer size... */
allocated = g_slice_alloc0 (private_size + ivar_size + sizeof (gpointer));
/* ... and point it back to the start of the private data. */
*(gpointer *) (allocated + private_size + ivar_size) = allocated + ALIGN_STRUCT (1);
/* Tell valgrind that it should treat the object itself as such */
VALGRIND_MALLOCLIKE_BLOCK (allocated + private_size, ivar_size + sizeof (gpointer), 0, TRUE);
VALGRIND_MALLOCLIKE_BLOCK (allocated + ALIGN_STRUCT (1), private_size - ALIGN_STRUCT (1), 0, TRUE);
}
else
#endif
allocated = g_slice_alloc0 (private_size + ivar_size);
instance = (GTypeInstance *) (allocated + private_size);
for (i = node->n_supers; i > 0; i--)
{
TypeNode *pnode;
pnode = lookup_type_node_I (node->supers[i]);
if (pnode->data->instance.instance_init)
{
instance->g_class = pnode->data->instance.class;
pnode->data->instance.instance_init (instance, class);
}
}
instance->g_class = class;
if (node->data->instance.instance_init)
node->data->instance.instance_init (instance, class);
#ifdef G_ENABLE_DEBUG
IF_DEBUG (INSTANCE_COUNT)
{
g_atomic_int_inc ((int *) &node->instance_count);
}
#endif
TRACE(GOBJECT_OBJECT_NEW(instance, type));
return instance;
}
av_demuxer_iterate
Traverse in turn demuxer_list All in demux
miui12-q-cas-stable.xmlconst AVInputFormat *av_demuxer_iterate(void **opaque)
{
static const uintptr_t size = sizeof(demuxer_list)/sizeof(demuxer_list[0]) - 1;
uintptr_t i = (uintptr_t)*opaque;
const AVInputFormat *f = NULL;
if (i < size) {
f = demuxer_list[i];
} else if (indev_list) {
f = indev_list[i - size];
}
// opaque It's a int* A pointer to a type is passed in ,*quaque The initial value is 0,
// Assign a value to i,i Point to demuxer_list The first of demuxer,i+1 Is the second corresponding address
if (f)
*opaque = (void*)(i + 1);
return f;
}
demuxer_list
demuxer_list Yes 300 Multiple lines , A variety of definitions are given demux, With ff_mov_demuxer For example , You can see movdemux The definition of includes mov,mp4,m4a,3gp,3g2,mj2
static const AVInputFormat * const demuxer_list[] = {
&ff_aa_demuxer,
&ff_aac_demuxer,
&ff_aax_demuxer,
&ff_ac3_demuxer,
&ff_ace_demuxer,
&ff_acm_demuxer,
// ...
};
ff_mov_demuxer
AVInputFormat ff_mov_demuxer = {
.name = "mov,mp4,m4a,3gp,3g2,mj2",
.long_name = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
.priv_class = &mov_class,
.priv_data_size = sizeof(MOVContext),
.extensions = "mov,mp4,m4a,3gp,3g2,mj2,psp,m4b,ism,ismv,isma,f4v",
.read_probe = mov_probe,
.read_header = mov_read_header,
.read_packet = mov_read_packet,
.read_close = mov_read_close,
.read_seek = mov_read_seek,
.flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS,
};
gst_element_register
adopt gst_element_register() Function will plugin The corresponding information of is registered to gstreamer in , Through this function , You can create one named name、 The priority for rank Of type type elementfactory, And will elementfactory Add to registry.
gboolean
gst_element_register (GstPlugin * plugin, const gchar * name, guint rank,
GType type)
{
GstPluginFeature *existing_feature;
GstRegistry *registry;
GstElementFactory *factory;
GType *interfaces;
guint n_interfaces, i;
GstElementClass *klass;
GList *item;
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (g_type_is_a (type, GST_TYPE_ELEMENT), FALSE);
registry = gst_registry_get ();
/* check if feature already exists, if it exists there is no need to update it * when the registry is getting updated, outdated plugins and all their * features are removed and readded. */
existing_feature = gst_registry_lookup_feature (registry, name);
if (existing_feature && existing_feature->plugin == plugin) {
GST_DEBUG_OBJECT (registry, "update existing feature %p (%s)",
existing_feature, name);
factory = GST_ELEMENT_FACTORY_CAST (existing_feature);
factory->type = type;
existing_feature->loaded = TRUE;
g_type_set_qdata (type, __gst_elementclass_factory, factory);
gst_object_unref (existing_feature);
return TRUE;
} else if (existing_feature) {
gst_object_unref (existing_feature);
}
factory = g_object_new (GST_TYPE_ELEMENT_FACTORY, NULL);
gst_plugin_feature_set_name (GST_PLUGIN_FEATURE_CAST (factory), name);
GST_LOG_OBJECT (factory, "Created new elementfactory for type %s",
g_type_name (type));
/* provide info needed during class structure setup */
g_type_set_qdata (type, __gst_elementclass_factory, factory);
klass = GST_ELEMENT_CLASS (g_type_class_ref (type));
CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_LONGNAME);
CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_KLASS);
CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_DESCRIPTION);
CHECK_METADATA_FIELD (klass, name, GST_ELEMENT_METADATA_AUTHOR);
factory->type = type;
factory->metadata = gst_structure_copy ((GstStructure *) klass->metadata);
for (item = klass->padtemplates; item; item = item->next) {
GstPadTemplate *templ = item->data;
GstStaticPadTemplate *newt;
gchar *caps_string = gst_caps_to_string (templ->caps);
newt = g_slice_new (GstStaticPadTemplate);
newt->name_template = g_intern_string (templ->name_template);
newt->direction = templ->direction;
newt->presence = templ->presence;
newt->static_caps.caps = NULL;
newt->static_caps.string = g_intern_string (caps_string);
factory->staticpadtemplates =
g_list_append (factory->staticpadtemplates, newt);
g_free (caps_string);
}
factory->numpadtemplates = klass->numpadtemplates;
/* special stuff for URI handling */
if (g_type_is_a (type, GST_TYPE_URI_HANDLER)) {
GstURIHandlerInterface *iface = (GstURIHandlerInterface *)
g_type_interface_peek (klass, GST_TYPE_URI_HANDLER);
if (!iface || !iface->get_type || !iface->get_protocols)
goto urierror;
if (iface->get_type)
factory->uri_type = iface->get_type (factory->type);
if (!GST_URI_TYPE_IS_VALID (factory->uri_type))
goto urierror;
if (iface->get_protocols) {
const gchar *const *protocols;
protocols = iface->get_protocols (factory->type);
factory->uri_protocols = g_strdupv ((gchar **) protocols);
}
if (!factory->uri_protocols)
goto urierror;
}
interfaces = g_type_interfaces (type, &n_interfaces);
for (i = 0; i < n_interfaces; i++) {
__gst_element_factory_add_interface (factory, g_type_name (interfaces[i]));
}
g_free (interfaces);
if (plugin && plugin->desc.name) {
GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = plugin->desc.name;
GST_PLUGIN_FEATURE_CAST (factory)->plugin = plugin;
g_object_add_weak_pointer ((GObject *) plugin,
(gpointer *) & GST_PLUGIN_FEATURE_CAST (factory)->plugin);
} else {
GST_PLUGIN_FEATURE_CAST (factory)->plugin_name = "NULL";
GST_PLUGIN_FEATURE_CAST (factory)->plugin = NULL;
}
gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE_CAST (factory), rank);
GST_PLUGIN_FEATURE_CAST (factory)->loaded = TRUE;
gst_registry_add_feature (registry, GST_PLUGIN_FEATURE_CAST (factory));
return TRUE;
/* ERRORS */
urierror:
{
GST_WARNING_OBJECT (factory, "error with uri handler!");
gst_element_factory_cleanup (factory);
return FALSE;
}
detailserror:
{
gst_element_factory_cleanup (factory);
return FALSE;
}
}
边栏推荐
- Data governance is easier said than done
- Analysis of China's tractor manufacturing and operation situation and forecast report of prospect trend 2022-2028
- GridView component of swiftui 4 new features (tutorial includes source code)
- This 110 year old "longevity" enterprise has been planning for the next century
- What is the difficulty of the form tool that costs billions of dollars? Exclusive interview with si no
- Yyds dry goods inventory JD 2, why is redis so fast?
- Research and Analysis on the current situation of Chinese acne drug market and forecast report on its development prospect (2022)
- Hard liver! Super detailed basic introduction to Matplotlib!!!
- HNU network counting experiment: Experiment 4 application layer and transport layer protocol analysis (packettracer)
- China soft magnetic material market demand status and prospect scale forecast report 2022-2028
猜你喜欢

Obsidian基础教程

Diagram of stack frame running process

Summary of basic knowledge of neural network

图解栈帧运行过程

How to design a complex business system? From the understanding of domain design, cloud native, micro service, and middle platform

Tiger Dao VC products are officially launched, a powerful supplement to seektiger ecology

Illustration de l'exécution du cadre de pile

Yyds dry goods inventory CEPH installation visual dashboard
[invitation letter] on March 4, the platform enabled digital intelligence Innovation -- UFIDA BiP PAAS cloud platform IUAP digital intelligence hundred cities forum · Jinan Station

Understand which C standards are there & understand the C compilation pipeline
随机推荐
聊聊Adapter模式
Summary of basic knowledge of neural network
Nacos source code analysis 01 code structure
Simple and easy-to-use cache library gcache
Research and Analysis on the current situation of Chinese acne drug market and forecast report on its development prospect (2022)
Dialog+: Audio dialogue enhancement technology based on deep learning
[HNU summer semester] preparation stage of database system design
数据治理,说起来容易,做起来难
Mastering quantization technology is the key to video compression
How to design a complex business system? From the understanding of domain design, cloud native, micro service, and middle platform
2022-2028 global TFT touch screen industry research and trend analysis report
Factorymethod factory method
In depth analysis of Flink fine-grained resource management
How to use Matplotlib library to realize enlarged display of graphic local data
Openwrt (VIII) application layer development
No nonsense, code practice will help you master strong caching and negotiation caching!
简单好用的缓存库 gcache
Perceptual video coding based on saliency
Yyds dry goods inventory CEPH installation visual dashboard
2022-2028 global SiC igniter industry research and trend analysis report