1)概述

BUS(总线) 是一个简单的系统,它采用自己的线程机制将一个管道线程的消息分发到一个应用程序当中。总线的优势是:当使用GStreamer的时候,应用程序不需要线程识别,即便GStreamer已经被加载了多个线程。

每一个管道默认包含一个总线,所以应用程序不需要再创建总线。应用程序只需要在总线上设置一个类似于对象的信号处理器的消息处理器。当主循环运行的时候,总线将会轮询这个消息处理器是否有新的消息,当消息被采集到后,总线将呼叫相应的回调函数来完成任务。

2)如何使用一个总线(Bus)

使用总线有两种方法,如下:

I.运行GLib/Gtk+ 主循环 (你也可以自己运行默认的GLib的主循环),然后使用侦听器对总线进行侦听。使用这种方法,GLib的主循环将轮询总线上是否存在新的消息,当存在新的消息的时候,总线会马上通知你。在这种情况下,你会用到gst_bus_add_watch () / gst_bus_add_signal_watch ()两个函数。当使用总线时,设置消息处理器到管道的总线上可以使用gst_bus_add_watch ()。 来创建一个消息处理器来侦听管道。每当管道发出一个消息到总线,这个消息处理器就会被触发,消息处理器则开始检测消息信号类型从而决定哪些事件将被处理。当处理器从总线删除某个消息的时候,其返回值应为TRUE。

II. 自己侦听总线消息,使用gst_bus_peek () 和/或 gst_bus_poll () 就可以实现。

#include <gst/gst.h>

static GMainLoop *loop;

static gboolean my_bus_callback (GstBus *bus, GstMessage *message, gpointer data)
{
  g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message));

  switch (GST_MESSAGE_TYPE (message)) {
    case GST_MESSAGE_ERROR: {
      GError *err;
      gchar *debug;

      gst_message_parse_error (message, &err, &debug);
      g_print ("Error: %s\n", err->message);
      g_error_free (err);
      g_free (debug);

      g_main_loop_quit (loop);
      break;
    }
    case GST_MESSAGE_EOS:
      /* end-of-stream */
      g_main_loop_quit (loop);
      break;
    default:
      /* unhandled message */
      break;
  }

  /* we want to be notified again the next time there is a message
   * on the bus, so returning TRUE (FALSE means we want to stop watching
   * for messages on the bus and our callback should not be called again)
   */
  return TRUE;
}

gint main (gint   argc, gchar *argv[])
{
  GstElement *pipeline;
  GstBus *bus;

  /* init */
  gst_init (&argc, &argv);

  /* create pipeline, add handler */
  pipeline = gst_pipeline_new ("my_pipeline");

  /* adds a watch for new message on our pipeline's message bus to
   * the default GLib main context, which is the main context that our
   * GLib main loop is attached to below
   */
  bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  gst_bus_add_watch (bus, my_bus_callback, NULL);
  gst_object_unref (bus);

//[..]

  /* create a mainloop that runs/iterates the default GLib main context
   * (context NULL), in other words: makes the context check if anything
   * it watches for has happened. When a message has been posted on the
   * bus, the default main context will automatically call our
   * my_bus_callback() function to notify us of that message.
   * The main loop will be run until someone calls g_main_loop_quit()
   */
  loop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (loop);

  /* clean up */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  g_main_loop_unref (loop);

  return 0;
}

 

3) 消息类型(Message types)

GStreamer有几种由总线传递的预定义消息类型,这些消息都是可扩展的。插件可以定义另外的一些消息,应用程序可以有这些消息的绝对代码或者忽略它们。强烈推荐应用程序至少要处理错误消息并直接的反馈给用户。

所有的消息都有一个消息源、类型和时间戳。这个消息源能被用来判断由哪个element发出消息。例如,在众多的消息中,应用程序只对上层的管道发出的消息感兴趣(如状态变换的提示)。下面列出所有的消息种类、代表的意义,以及如何解析具体消息的内容。

1) 错误、警告和消息提示:它们被各个元件用来在必要的时候告知用户现在管道的状态。错误信息表明有致命的错误并且终止数据传送。错误应该被修复,这样才能继续管道的工作。警告并不是致命的,但是暗示有问题存在。消息提示用来告知非错误的信息。这些消息含有一个带有主要的错误类型和消息的GError,和一个任选的调试字符串。这两项都可以用gst_message_parse_error (), _parse_warning () 以及 _parse_info ()三个函数来提取其信息。当使用完毕后,错误和修正字符串都将被释放。

2) 数据流结束(End-of-stream)提示:当数据流结束的时候,该消息被发送。管道的状态不会改变,但是之后的媒体操作将会停止。应用程序可以通过收到这一消息来跳到播放列表的下一首歌。在数据流结束提示出现之后,仍然可以通过向后搜索来回到以前数据流前面的位置。之后的播放工作将会自动的继续执行。这个消息没有特殊的参数。

3) 标签(Tags):当元数据在数据流中被找到的时候,此消息被发送。一个管道可以发出多个Tag(如元数据的描述里有艺术家、歌曲名,另外的例子如流的信息采样率和比特率)。应用程序应该将元数据存储在缓存里。函数gst_message_parse_tag () 被用来解析tag的列表,当该列表不再使用的时候,函数gst_tag_list_free () 释放其相应的tag。

4) 状态转换(State-changes):当状态成功的转换时发送该消息。函数gst_message_parse_state_changed ()可以用来解析转换中的新旧状态。

5) 缓冲(Buffering):当缓冲网络数据流时此消息被发送。你可以通过函数gst_message_get_structure ()的返回值,来解析"buffer-percent" 属性,从而手动的得到缓冲进度(该缓冲进度以百分比的形式表示)。

6) 元件消息(Element messages):它是一组特殊的消息,用以标识一个特定元件。这样一组特殊的消息通常表述了一些额外的信息。元件的信息应该被详细的描述,因为这样一些元件信息将被作为消息而发送给其他元件。例如:'qtdemux' QuickTime 整流器(demuxer)应该把'redirect'信息保存于该元件信息当中,以便在某种特殊情况下将'redirect'元件信息发送出去。

7) Application-specific消息:我们可以将取得的消息结构解析出来,从而得到有关Application-specific消息的任何信息。通常这些信息是能够被安全地忽略。

应用程序消息主要用于内部,以备从一些线程排列信息到主线程应用的需求。这些在使用元件信号的应用中非常实用(这些信号在数据流线程的上下文被发射)。

openwrt gstreamer实例学习笔记(五. gstreamer BUS)的更多相关文章

  1. openwrt gstreamer实例学习笔记(一.初始化gstreamer)

    GStreamer 是一个非常强大而且通用的流媒体应用程序框架. GStreamer所具备的很多优点来源于其框架的模块化: GStreamer能够无缝的合并新的插件. 但是, 由于追求模块化和高效率, ...

  2. openwrt gstreamer实例学习笔记(七. gstreamer 缓冲区(Buffers)和事件(Events))

    1)概述 管道的数据流由一组缓冲区和事件组成,缓冲区包括实际的管道数据,事件包括控制信息,如寻找信息和流的终止信号.所有这些数据流在运行的时候自动的流过管道. 2) 缓冲区(Buffers) 缓冲区包 ...

  3. openwrt gstreamer实例学习笔记(六. gstreamer Pads及其功能)

    一:概述 如我们在Elements一章中看到的那样,Pads是element对外的接口.数据流从一个element的source pad到另一个element的sink pad.pads的功能(cap ...

  4. openwrt gstreamer实例学习笔记(四. gstreamer Bins)

    1)概述 Bins是一种容器element.你可以往Bins中添加element.由于Bins本身也是一种element,所以你可以像普通element一样 操作Bins.因此,先前关element的 ...

  5. openwrt gstreamer实例学习笔记(三.深入了解gstreamer 的 Element)

    在前面的部分,我们简要介绍过 GstElementFactory 可以用来创建一个element的实例,但是GstElementFactory不仅仅只能做这件事,GstElementFactory作为 ...

  6. openwrt gstreamer实例学习笔记(二.gstreamer 的 Element)

    对程序员来说,GStreamer 中最重要的一个概念就是 GstElement 对象.该对象是构建一个媒体管道的基本块.所有上层(high-level)部件都源自GstElement对象.任何一个解码 ...

  7. gstreamer应用笔记

    gstreamer官网 https://gstreamer.freedesktop.org/ 应用手册 https://gstreamer.freedesktop.org/documentation/ ...

  8. [Openwrt 项目开发笔记]:DDNS设置(五)

    [Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一节中,我主要讲述了如何在Openwrt上安 ...

  9. [openwrt 项目开发笔记]: 传送门

    “Openwrt 项目开发笔记”系列传送门: [Openwrt 项目开发笔记]:Openwrt平台搭建(一) (2014-07-11 00:11) [Openwrt 项目开发笔记]:Openwrt平台 ...

随机推荐

  1. 从PHP5到PHP7的注意事项——PHP7全面删除Mysql扩展支持

    PHP删除了一些函数,其中是吓人的是两个: 1. ereg_* 系列的正则函数 2. mysql_* 系列的数据库连接函数 PHP7全面删除Mysql扩展支持,原本的mysql_*系列函数将在mysq ...

  2. 【LeetCode】Reorder Log Files(重新排列日志文件)

    这道题是LeetCode里的第937道题. 题目描述: 你有一个日志数组 logs.每条日志都是以空格分隔的字串. 对于每条日志,其第一个字为字母数字标识符.然后,要么: 标识符后面的每个字将仅由小写 ...

  3. Educational Codeforces Round 31

    A. Book Reading time limit per test 2 seconds memory limit per test 256 megabytes input standard inp ...

  4. 九度oj 题目1250:矩阵变换

    题目描述: 对于一个整数矩阵,存在一种运算,对矩阵中任意元素加一时,需要其相邻(上下左右)某一个元素也加一, 现给出一正数矩阵,判断其是否能够由一个全零矩阵经过上述运算得到. 输入: 输出: 如果可以 ...

  5. bzoj3743 [Coci2015]Kamp 常州模拟赛d6t2

    3743: [Coci2015]Kamp Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 484  Solved: 229[Submit][Status ...

  6. es6 箭头函数 map、find

    var  value = arr.map(function (x) {return x * x}); const arr = [1,2,3,4]; const value = arr.map(x =& ...

  7. Spoj-DRUIDEOI Fata7y Ya Warda!

    Fata7y Ya Warda! Druid (AKA Amr Alaa El-Deen) and little EOIers have finished their training and the ...

  8. .NET Core 3.0之创建基于Consul的Configuration扩展组件

    写在前面 经过前面三篇关于.NET Core Configuration的文章之后,本篇文章主要讨论如何扩展一个Configuration组件出来.如果前面三篇文章没有看到,可以点击如下地址访问 .N ...

  9. Spring的IoC容器概述

    以下内容引用自http://wiki.jikexueyuan.com/project/spring/ioc-containers.html: IoC容器 Spring容器是Spring框架的核心.容器 ...

  10. mysql 密碼忘記 解決

    WINDOW 1.my.ini 加入 [mysqld] skip-grant-tables 2.mysql -uroot -p 登入 USE MYSQL: update user set passwo ...