当前位置:网站首页>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;
}
}
边栏推荐
- Why is BeanUtils not recommended?
- Does jQuery cache any selectors- Does jQuery do any kind of caching of “selectors”?
- Application runtime layotto enters CNCF cloud native panorama
- Use apiccloud AVM multi terminal component to quickly realize the search function in the app
- 再突破!阿里云进入Gartner云AI开发者服务挑战者象限
- 2022-2028 global cloud based remote browser isolation industry research and trend analysis report
- SSH modifies grub in heiqunhui ds918+ system 7.0.1 cfg
- How to guarantee idempotency of message queue
- Research and Analysis on the status quo of China's Cross lamp market and forecast report on its development prospect (2022)
- Obsidian basic tutorial
猜你喜欢
Pycharm 2022.1 EAP 2 release

QT learning setting executable exe attribute (solving the problem of Chinese attribute garbled)

Diagram of stack frame running process

Where is win11 screen recording data saved? Win11 screen recording data storage location
What are the debugging methods for nodejs
Evaluate the generalization performance of models and build integrated models using out of pocket prediction (oof)
Interview shock 23: talk about thread life cycle and transformation process?

Use of local stack in flask

2022-2028 global transmission type photoelectric circuit breaker industry research and trend analysis report

Obsidian基础教程
随机推荐
图解栈帧运行过程
2022-2028 global co extrusion production line industry research and trend analysis report
Illustration de l'exécution du cadre de pile
27 Chinese scholars including Yaoban and chendanqi from Tsinghua won the awards, and the list of winners of Sloan award in 2022 was issued
Flutter 网络请求封装之Dio(Cookie管理、添加拦截器、下载文件、异常处理、取消请求等)
Youku IPv6 evolution and Practice Guide
This 110 year old "longevity" enterprise has been planning for the next century
How to use Matplotlib library to realize enlarged display of graphic local data
聊聊Adapter模式
2022-2028 global proton exchange membrane hydrogen electrolyzer industry survey and trend analysis report
2022爱分析· IT运维厂商全景报告
Touring band: a 5g based multi camera remote distributed video production experiment
Progress of the 137th MPEG Conference
Application runtime layotto enters CNCF cloud native panorama
HNU network counting experiment: Experiment 5 network layer and link layer protocol analysis (packettracer)
Data governance is easier said than done
HotSpot JVM 「01」类加载、链接和初始化
Privatization lightweight continuous integration deployment scheme -- 03 deployment of Web services (Part 2)
Introduction to HNU database system ODBC
Evaluate the generalization performance of models and build integrated models using out of pocket prediction (oof)