gstreamer libav插件分析

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值