Gstreamer基础课程3: 动态管道

本文档介绍了如何动态创建Gstreamer管道,重点关注如何处理demuxer的src pad,控制element链接,响应信号以及管理Gstreamer的state。内容包括demuxer的工作原理,创建元素、链接元素、设置属性,以及在pad-added信号触发时的回调处理。目标是实现从url到原始音频流的转换,并确保在不同平台上的兼容性。
摘要由CSDN通过智能技术生成

1.Goal

动态创建pipeline,而不是在应用程序开始时定义一个整体式pipeline。

  • 链接element时如何更好的控制
  • 如何收到感兴趣的信号,并作出反应
  • elements可以处于各种状态

2.Introduce

2.1 Pad

Gstreamer的element通过pad相互通信。source element只包含src pad, sink element只包含sink pad,filter element包含src sink pad。
在这里插入图片描述

2.2 Demuxer

本教程中会打开一个muxer文件,这是个包含音频和视频的容器文件。容器的格式还有MKV, QT, MOV, Ogg, ASF, WMV, WMA等。
用于打开容器文件的element为***demuxer***,它可以分离容器中的多个流,并输出到对应的pad。***demuxer***包含一个sink pad, 多个src pad。
在这里插入图片描述
处理***demuxer***的复杂性在于,它在收到数据之前,不能产生任何信息,也即,***demuxer***在开始时没有其他element可以链接到src pad,所以pipeline会在src pad处停住。
解决方法是建立从源到***demuxer***的管道,并将其设置为play。当***demuxer***收到足够的信息来获取容器中流的数量和类型时,它将开始正确的创建src pad。这是我们完成pipeline建设和附加到新增加的demuxer垫的正确时间。

3.Implement

3.1 Pipeline

在这里插入图片描述

为了简化,教程只获取音频流。

3.2 Compile

gcc basic-tutorial-3.c -o basic-tutorial-3 `pkg-config --cflags --libs gstreamer-1.0`

3.3 Code

#include <gst/gst.h>

/* Structure to contain all our information, so we can pass it to callbacks */
typedef struct _CustomData {
   
  GstElement *pipeline;
  GstElement *source;
  GstElement *convert;
  GstElement *resample;
  GstElement *sink;
} CustomData;

/* Handler for the pad-added signal */
static void pad_added_handler (GstElement *src, GstPad *pad, CustomData *data);

int main(int argc, char *argv[]) {
   
  CustomData data;
  GstBus *bus;
  GstMessage *msg;
  GstStateChangeReturn ret;
  gboolean terminate = FALSE;

  /* Initialize GStreamer */
  gst_init (&argc, &argv);

  /* 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");

  /* Create the empty pipeline */
  data.pipeline = gst_pipeline_new ("test-pipeline");

  if (!data.pipeline || !data.source || !data.convert || !data.resample || !data.sink) {
   
    g_printerr ("Not all elements could be created.\n");
    return -1;
  }

  /* Build the pipeline. Note that we are NOT linking the source at this
   * point. We will do it later. */
  gst_bin_add_many (GST_BIN (data.pipeline), data.source, data.convert, data.resample, data.sink, NULL);
  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;
  }

  /* Set the URI to play */
  g_object_set (data.source, "uri", "https://www.freedesktop.org/software/gstreamer-sdk/data/media/sintel_trailer-480p.webm", NULL);

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

  /* Start playing */
  ret = gst_element_set_state (data.pipeline, GST_STATE_PLAYING);
  if (ret == GST_STATE_CHANGE_FAILURE) {
   
    g_printerr ("Unable to set the pipeline to the playing state.\n");
    gst_object_unref (data.pipeline);
    return -1;
  }

  /* Listen to the bus */
  bus = gst_element_get_bus (data.pipeline);
  do {
   
    msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE,
        GST_MESSAGE_STATE_CHANGED | GST_MESSAGE_ERROR | GST_MESSAGE_EOS);

    /* Parse message */
    if (msg != NULL) {
   
      GError *err;
      gchar *debug_info;

      switch (GST_MESSAGE_TYPE (msg)) {
   
        case GST_MESSAGE_ERROR:
          gst_message_parse_error (msg, &err,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值