1、插件注册初始化
static gboolean
plugin_init (GstPlugin * plugin)
{
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;
}
#ifndef GST_DISABLE_GST_DEBUG
av_log_set_callback (gst_ffmpeg_log_callback);
#endif
gst_ffmpeg_init_pix_fmt_info ();
/* build global ffmpeg param/property info */
gst_ffmpeg_cfg_init (); //配置参数
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;
}
2、以音频编码器插件注册为例
gboolean
gst_ffmpegaudenc_register (GstPlugin * plugin)
{
GTypeInfo typeinfo = {
sizeof (GstFFMpegAudEncClass),
(GBaseInitFunc) gst_ffmpegaudenc_base_init,
NULL,
(GClassInitFunc) gst_ffmpegaudenc_class_init,
NULL,
NULL,
sizeof (GstFFMpegAudEnc),
0,
(GInstanceInitFunc) gst_ffmpegaudenc_init,
};
GType type;
AVCodec *in_plugin;
void *i = 0;
GST_LOG ("Registering encoders");
//遍历所有编码器
while ((in_plugin = (AVCodec *) av_codec_iterate (&i))) {
gchar *type_name;
guint rank;
//过滤出音频
if (in_plugin->type != AVMEDIA_TYPE_AUDIO)
continue;
//排除PCM类编码器
if (in_plugin->id == AV_CODEC_ID_PCM_S16LE_PLANAR ||
(in_plugin->id >= AV_CODEC_ID_PCM_S16LE &&
in_plugin->id <= AV_CODEC_ID_PCM_BLURAY) ||
(in_plugin->id >= AV_CODEC_ID_PCM_S8_PLANAR &&
in_plugin->id <= AV_CODEC_ID_PCM_F24LE)) {
continue;
}
/* No encoders depending on external libraries (we don't build them, but
* people who build against an external ffmpeg might have them.
* We have native gstreamer plugins for all of those libraries anyway. */
if (!strncmp (in_plugin->name, "lib", 3)) {
GST_DEBUG("Not using external library encoder %s. Use the gstreamer-native ones instead.", in_plugin->name);
continue;
}
//编码器
if (!av_codec_is_encoder (in_plugin)) {
continue;
}
/* FIXME : We should have a method to know cheaply whether we have a mapping for the given plugin or not */
GST_DEBUG ("Trying plugin %s [%s]", in_plugin->name, in_plugin->long_name);
/* no codecs for which we're GUARANTEED to have better alternatives */
if (!strcmp (in_plugin->name, "vorbis") || !strcmp (in_plugin->name, "flac")) {
GST_LOG ("Ignoring encoder %s", in_plugin->name);
continue;
}
//构建音频编码类
type_name = g_strdup_printf ("avenc_%s", in_plugin->name);
type = g_type_from_name (type_name);
if (!type) {
/* create the glib type now */
type = g_type_register_static (GST_TYPE_AUDIO_ENCODER, type_name, &typeinfo,0);
g_type_set_qdata (type, GST_FFENC_PARAMS_QDATA, (gpointer) in_plugin);
{
static const GInterfaceInfo preset_info = {
NULL,
NULL,
NULL
};
g_type_add_interface_static (type, GST_TYPE_PRESET, &preset_info);
}
}
switch (in_plugin->id) {
/* avenc_aac: see https://bugzilla.gnome.org/show_bug.cgi?id=691617 */
case AV_CODEC_ID_AAC:
rank = GST_RANK_NONE;
break;
default:
rank = GST_RANK_SECONDARY;
break;
}
if (!gst_element_register (plugin, type_name, rank, type)) {
g_free (type_name);
return FALSE;
}
g_free (type_name);
}
GST_LOG ("Finished registering encoders");
return TRUE;
}
3、音频类初始化
static void
gst_ffmpegaudenc_class_init (GstFFMpegAudEncClass * klass)
{
GObjectClass *gobject_class;
GstAudioEncoderClass *gstaudioencoder_class;
gobject_class = (GObjectClass *) klass;
gstaudioencoder_class = (GstAudioEncoderClass *) klass;
parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = gst_ffmpegaudenc_set_property;
gobject_class->get_property = gst_ffmpegaudenc_get_property;
gst_ffmpeg_cfg_install_properties (gobject_class, klass->in_plugin, PROP_CFG_BASE, AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_AUDIO_PARAM);
gobject_class->finalize = gst_ffmpegaudenc_finalize;
gstaudioencoder_class->start = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_start);
gstaudioencoder_class->stop = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_stop);
gstaudioencoder_class->flush = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_flush);
gstaudioencoder_class->set_format = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_set_format);
gstaudioencoder_class->handle_frame = GST_DEBUG_FUNCPTR (gst_ffmpegaudenc_handle_frame);
}
4、音频对象初始化
static void
gst_ffmpegaudenc_base_init (GstFFMpegAudEncClass * klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
AVCodec *in_plugin;
GstPadTemplate *srctempl = NULL, *sinktempl = NULL;
GstCaps *srccaps = NULL, *sinkcaps = NULL;
gchar *longname, *description;
in_plugin = (AVCodec *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), GST_FFENC_PARAMS_QDATA);
g_assert (in_plugin != NULL);
/* construct the element details struct */
longname = g_strdup_printf ("libav %s encoder", in_plugin->long_name);
description = g_strdup_printf ("libav %s encoder", in_plugin->name);
gst_element_class_set_metadata (element_class, longname,
"Codec/Encoder/Audio", description,
"Wim Taymans <wim.taymans@gmail.com>, "
"Ronald Bultje <rbultje@ronald.bitfreak.net>");
g_free (longname);
g_free (description);
if (!(srccaps = gst_ffmpeg_codecid_to_caps (in_plugin->id, NULL, TRUE))) {
GST_DEBUG ("Couldn't get source caps for encoder '%s'", in_plugin->name);
srccaps = gst_caps_new_empty_simple ("unknown/unknown");
}
sinkcaps = gst_ffmpeg_codectype_to_audio_caps (NULL, in_plugin->id, TRUE, in_plugin);
if (!sinkcaps) {
GST_DEBUG ("Couldn't get sink caps for encoder '%s'", in_plugin->name);
sinkcaps = gst_caps_new_empty_simple ("unknown/unknown");
}
/* pad templates */
sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, sinkcaps);
srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, srccaps);
gst_element_class_add_pad_template (element_class, srctempl);
gst_element_class_add_pad_template (element_class, sinktempl);
gst_caps_unref (sinkcaps);
gst_caps_unref (srccaps);
klass->in_plugin = in_plugin;
klass->srctempl = srctempl;
klass->sinktempl = sinktempl;
return;
}