gstreamer-1.0学习笔记

gstreamer-1.0安装

apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

概念

GStreamer应用开发手册学习笔记之一
GStreamer应用开发手册学习笔记之二

官网例程

Basic tutorial

例程源码

git clone https://gitlab.freedesktop.org/gstreamer/gst-docs

例1

GStreamer-1.0的使用–基础教程(1):Hello world! C语言

例2

GStreamer-1.0的使用–基础教程(2):GStreamer的概念 C语言

例3

目标:
本教程介绍了使用GStreamer所需的其余基本概念,它允许在信息可用时“动态”构建管道,而不是在应用程序开始时定义单一管道。
完成本教程后,您将具备开始播放教程所需的知识。此处审查的要点包括:
如何在链接元素时实现更精细的控制。
如何得知有趣的事件,以便及时做出反应。
一个元素可以处于的各种状态。
介绍:
正如您即将看到的,本教程中的管道在设置为播放状态之前尚未完全构建。这没关系。如果我们不采取进一步的行动,数据将到达管道的末端,管道将产生错误消息并停止。但我们将采取进一步行动。。。
在本例中,我们打开一个multiplexed (or muxed)多路复用(或多路复用)的文件,即音频和视频一起存储在一个容器文件中。负责打开此类容器的元素称为demuxers解复用器,容器格式的一些示例有Matroska(MKV)、Quick Time(QT、MOV)、Ogg或Advanced Systems Format(ASF、WMV、WMA)。
如果容器嵌入多个流(例如,一个视频和两个音频曲目),demuxer解复用器将分离它们并通过不同的输出端口公开它们。通过这种方式,可以在管道中创建不同的分支,处理不同类型的数据。
GStreamer元素相互通信的端口称为pads(GstPad)。存在数据进入元素的sink pads接收器焊盘和数据退出元素的source pads源焊盘。很自然地,source elements源元素仅包含源焊盘,sink elements汇元素仅包含汇焊盘,而filter elements过滤器元素同时包含这两者
请添加图片描述demuxer:
请添加图片描述请添加图片描述
代码解释

/* Create the elements */
data.source = gst_element_factory_make ("uridecodebin", "source");
data.convert = gst_element_factory_make ("audioconvert", "convert");
data.resample = gst_element_factory_make ("audioresample", "resample");
data.sink = gst_element_factory_make ("autoaudiosink", "sink");

我们像往常一样创建元素。uridecodebin将在内部实例化所有必要的元素(源、解复用器和解码器),以将URI转换为原始音频和/或视频流。它完成了playbin一半的工作。由于它包含解复用器,它的源焊盘最初不可用,我们需要动态链接到它们。
audioconvert对于在不同的音频格式之间进行转换非常有用,因为音频解码器生成的格式可能与音频接收器期望的格式不同,因此,请确保此示例在任何平台上都能正常工作。
audioresample对于在不同的音频采样率之间进行转换非常有用,同样,可以确保此示例在任何平台上都能工作,因为音频解码器产生的音频采样率可能不是音频接收器支持的。
对于音频,autoaudiosink与上一教程中的autovideosink等效。它将向声卡呈现音频流。

if (!gst_element_link_many (data.convert, data.resample, data.sink, NULL)) {
  g_printerr ("Elements could not be linked.\n");
  gst_object_unref (data.pipeline);
  return -1;
}

在这里,我们链接元素转换器、重采样和接收器,但我们不将它们与源链接,因为此时它不包含源焊盘。我们只是让这个分支(转换器+接收器)保持未链接状态,直到稍后。

/* Connect to the pad-added signal */
g_signal_connect (data.source, "pad-added", G_CALLBACK (pad_added_handler), &data);

GST信号是GStreamer中的一个关键点。它们允许在发生有趣的事情时通知您(通过回调)。信号由名称标识,每个GObject都有自己的信号。
在这一行中,我们附加到源的“pad added”信号(一个uridecodebin元素)。为此,我们使用g_signal_connect()并提供要使用的回调函数(pad_added_handler)和数据指针。GStreamer对这个数据指针不做任何处理,它只是将它转发给回调,以便我们可以与它共享信息。在本例中,我们将传递一个指针,指向为此专门构建的CustomData结构。
GstElement生成的信号可以在其文档中找到,也可以使用gst-inspect-1.0工具,如基础教程10:GStreamer工具中所述。
我们现在准备出发了!只需将管道设置为播放状态,并开始收听总线上有趣的消息(如错误或EOS),就像前面的教程一样。

回调函数解析:

static void pad_added_handler (GstElement *src, GstPad *new_pad, CustomData *data)

当我们的源元素最终有足够的信息开始生成数据时,它将创建源焊盘,并触发“添加焊盘”信号。此时将调用我们的回调函数

GstPad *sink_pad = gst_element_get_static_pad (data->convert, "sink");

新建convert的sink

/* If our converter is already linked, we have nothing to do here */
if (gst_pad_is_linked (sink_pad)) {
  g_print ("We are already linked. Ignoring.\n");
  goto exit;
}

检查是否已链接

/* Check the new pad's type */
new_pad_caps = gst_pad_get_current_caps (new_pad, NULL);
new_pad_struct = gst_caps_get_structure (new_pad_caps, 0);
new_pad_type = gst_structure_get_name (new_pad_struct);
if (!g_str_has_prefix (new_pad_type, "audio/x-raw")) {
  g_print ("It has type '%s' which is not raw audio. Ignoring.\n", new_pad_type);
  goto exit;
}

检查是否为audio/x-raw

/* Attempt the link */
ret = gst_pad_link (new_pad, sink_pad);
if (GST_PAD_LINK_FAILED (ret)) {
  g_print ("Type is '%s' but link failed.\n", new_pad_type);
} else {
  g_print ("Link succeeded (type '%s').\n", new_pad_type);
}

林肯死大头

GStreamer States的四种状态:NULL,READY,PAUSED,PLAYING
你只能在相邻的状态之间移动,也就是说,你不能从空变为播放,你必须经历中间的准备状态和暂停状态。但是,如果将管道设置为播放,GStreamer将为您进行中间转换。

case GST_MESSAGE_STATE_CHANGED:
  /* We are only interested in state-changed messages from the pipeline */
  if (GST_MESSAGE_SRC (msg) == GST_OBJECT (data.pipeline)) {
    GstState old_state, new_state, pending_state;
    gst_message_parse_state_changed (msg, &old_state, &new_state,
        &pending_state);
    g_print ("Pipeline state changed from %s to %s:\n",
        gst_element_state_get_name (old_state),
        gst_element_state_get_name (new_state));
  }

我们添加了这段代码,用于侦听有关状态更改的总线消息,并在屏幕上打印这些消息,以帮助您理解转换。每个元素都会将有关其当前状态的消息放在总线上,因此我们会将它们过滤掉,只侦听来自管道的消息。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值