前言

  gtreamer播放ogg音频文件的流程讲解。

 

Ogg

  Ogg全称是OGGVobis(oggVorbis)是一种音频压缩容器格式。Ogg格式不仅是一个高效的容器格式,它还融合了Vorbis、Theora和Speex等多种媒体压缩技术。Ogg不仅是一个容器格式,更融合了多种媒体压缩技术,如Vorbis(音频)、Theora(视频)和Speex(语音)。值得一提的是,我们之前介绍的高保真FLAC格式也可以被纳入Ogg框架之中。因此,我们所探讨的Ogg,通常指的是Ogg与Vorbis的组合。

 

GStreamer

  GStreamer是一个非常强大和通用的框架,用于创建流媒体应用程序。GStreamer框架的许多优点来自其模块化:GStreamer可以无缝地整合新的插件模块。但是,由于模块化和强大的功能往往以更高的复杂性为代价,编写新的应用程序并不总是那么容易。
  GStreamer分为:

  • gstreamer:核心包
  • gst-plugins-base:一组基本的示例元素
  • gst-plugins-good:LGPL下的一组高质量插件
  • gst-plugins-ugly:一组可能造成分发问题的高质量插件
  • gst-plugins bad:一组需要更高质量的插件
  • gst-libav:一组封装libav进行解码和编码的插件
  • 其他几个包
 

GStreamer架构图

  

 

探测本地组件

  使用gst-inspect-1.0可以检测到本地安装了哪些模块,如下:
  

 

播放ogg文件

步骤一:初始化gst

  

步骤二:创建消息循环

  

步骤三:创建所有需要的组件

  

步骤四:设置本地文件路径属性

  

步骤五:添加一个检测管道消息处理

  

步骤六:将组件都放入管道

  

步骤七:连接组件

  连接组件后,这里分割器分割一个流就会回调产出一个pad,要对pad在创建时动态关联解码器,解码器才到sink播放。
  

步骤八:开始运行

  

步骤九:开始播放,进去循环阻塞

  

步骤十:清理资源

  

 

Demo源码

/******************** test003 ********************/
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
{
GMainLoop* loop = (GMainLoop *) data;
switch(GST_MESSAGE_TYPE(msg))
{
case GST_MESSAGE_EOS:
g_print ("End of stream\n");
g_main_loop_quit (loop);
break;
case GST_MESSAGE_ERROR:
{
gchar *debug;
GError *error;
gst_message_parse_error (msg, &error, &debug);
g_free (debug);
g_printerr ("Error: %s\n", error->message);
g_error_free (error);
g_main_loop_quit (loop);
break;
}
default:
break;
}
return TRUE;
} static void on_pad_added (GstElement* element, GstPad* pad, gpointer data)
{
GstPad *sinkpad;
GstElement *decoder = (GstElement *) data; // 现在可以将这个焊盘与vorbis解码器接收焊盘连接起来
g_print ("Dynamic pad created, linking demuxer/decoder\n");
sinkpad = gst_element_get_static_pad(decoder, "sink");
gst_pad_link (pad, sinkpad);
gst_object_unref (sinkpad);
} void test003PlayOggDemo(int *argc, char **argv[])
{
char const * fileName = "/home/yang/work/test/1.ogg";
// char const * fileName = "/home/yang/work/test/1.mp3";
// char const * fileName = "/home/yang/work/test/1.mov"; GMainLoop *loop; GstElement *pipeline, *source, *demuxer, *decoder, *conv, *sink;
GstBus *bus;
guint bus_watch_id; // 步骤一:初始化gst
gst_init (argc, argv); // 步骤二:创建gmain消息循环
loop = g_main_loop_new (NULL, FALSE); // 步骤三:创建组建
pipeline = gst_pipeline_new ("audio-player");
// 组件类型 组件唯一名称
source = gst_element_factory_make ("filesrc", "file-source");
demuxer = gst_element_factory_make ("oggdemux", "ogg-demuxer");
// demuxer = gst_element_factory_make ("mpeg123", "mp3-demuxer"); // mp3: 不用分割,所以步骤不一样
// demuxer = gst_element_factory_make ("splitmuxsink", "mov-demuxer");// mov: 分割格式不一样,要修改代码,没改了
decoder = gst_element_factory_make ("vorbisdec", "vorbis-decoder");
conv = gst_element_factory_make ("audioconvert", "converter");
sink = gst_element_factory_make ("autoaudiosink", "audio-output"); if(!pipeline || !source || !demuxer || !decoder || !conv || !sink)
{
g_printerr ("One element could not be created. Exiting.\n");
return;
} // 步骤四:设置本地原的文件属性“location”,文件名
g_object_set (G_OBJECT (source), "location", fileName, NULL); // 步骤五:添加一个消息处理程序
bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
// 消息回调函数原型:gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
gst_object_unref(bus); // 步骤六:将所有的组件添加到管道 */
// file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output
gst_bin_add_many(GST_BIN(pipeline),
source, demuxer, decoder, conv, sink, NULL); // 步骤七:链接组件
// file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output
gst_element_link (source, demuxer);
gst_element_link_many (decoder, conv, sink, NULL);
// 注意1:这里demuxer的pad-added消息会出发on_pad_added回调函数
// 注意2:demuxer是解码器,解码出来有多个流,每个流会产出一个pad,然后动态链接
// 注意2:在这个回调函数里面,会把added的焊盘关联到decoder上,就实现了demuxer->decoder的链接
// 注意3:
g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder);
/* 请注意,解复用器将动态链接到解码器。原因是Ogg可能包含各种流(例如音频和视频)。
* 当解复用器检测到流的数量和性质时,它将在运行时创建源焊盘。
* 因此,我们连接了一个回调函数,该函数将在发出“添加焊盘”时执行
*/ // 步骤八:设置状态运行
g_print ("Now playing: %s\n", fileName);
gst_element_set_state (pipeline, GST_STATE_PLAYING); // 步骤九:进入消息循环
g_print ("Running...\n");
g_main_loop_run (loop); // 步骤十:离开主循环,好好清理
g_print ("Returned, stopping playback\n");
gst_element_set_state (pipeline, GST_STATE_NULL);
g_print ("Deleting pipeline\n");
gst_object_unref(GST_OBJECT (pipeline));
g_source_remove(bus_watch_id);
g_main_loop_unref(loop);
}
 

工程模板v1.2.0

  

 

入坑

入坑一:创建mp3分流器是吧

问题

  举一反三,试一试mp3分流器,结果失败:
  

尝试

  使用gst-inspect-1.0可以检测到本地安装了哪些模块,举例部分如下:
  

  继续扫描,可以看到:
  

  会扫描,然后又刷这些,定期更新吧,我们查找下ogg:
  

  那么找一下mp3:
  

  测试:
  

解决

  未尝试,mp3就是一个文件格式,不是封装容器,不需要分割器进行动态pad关联。其管道过程不一样。
  

GStreamer开发笔记(七):gstreamer播放ogg详解的更多相关文章

  1. ArcGIS API for javascript开发笔记(六)——REST详解及如何使用REST API调用GP服务

    感谢一路走来默默支持和陪伴的你~~~ -------------------欢迎来访,拒绝转载-------------------- 一.Rest API基础 ArcGIS 平台提供了丰富的REST ...

  2. Android开发笔记之: 数据存储方式详解

    无论是神马平台,神马开发环境,神马软件程序,数据都是核心.对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用.总体的来讲,数据存储方式有三种:一个是文件,一个是数 ...

  3. python开发笔记之zip()函数用法详解

    今天分享一篇关于python下的zip()函数用法. zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素按顺序组合成一个tuple,每个tuple中包含的是原 ...

  4. Android 高级UI设计笔记07:RecyclerView 的详解

    1. 使用RecyclerView       在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...

  5. IP地址和子网划分学习笔记之《IP地址详解》

    2018-05-03 18:47:37   在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. ...

  6. [ 转载 ] Java开发中的23种设计模式详解(转)

    Java开发中的23种设计模式详解(转)   设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...

  7. “全栈2019”Java第七十章:静态内部类详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  8. 最锋利的Visual Studio Web开发工具扩展:Web Essentials详解

    原文:最锋利的Visual Studio Web开发工具扩展:Web Essentials详解 Web Essentials是目前为止见过的最好用的VS扩展工具了,具体功能请待我一一道来. 首先,从E ...

  9. Android进阶笔记:Messenger源码详解

    Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...

  10. 【笔记】Pandas分类数据详解

    [笔记]Pandas分类数据详解 Pandas  Pandas分类数据详解|轻松玩转Pandas(5) 参考:Pandas分类数据详解|轻松玩转Pandas(5)

随机推荐

  1. bs4库爬取天气预报

    Python不仅用于网站开发,数据分析,图像处理,也常用于爬虫技术方向,最近学习了解下,爬虫技术入门一般先使用bs4库,爬取天气预报简单尝试下. 第一步:首先选定目标网站地址 网上查询,天气预报准确率 ...

  2. RSA密钥生成-已知p、q、e求私钥d的python脚本

    题目: 在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17 求解出d作为flag提交 求解过程: 首先计算n和ϕ(n) n=p*q  ϕ(n)=(p-1)(q-1 ...

  3. 接口中的成员特点、类和接口之间的各种关系--java进阶day02

    1.接口的成员特点 1.接口没有构造方法 接口没有构造方法,但是实现类中有构造方法,super()又该访问谁呢? 类实现接口只是认干爹,类本身还是会有亲爹Object,super()会访问Object ...

  4. 【JDBC第9章】Apache-DBUtils实现CRUD操作

    第9章:Apache-DBUtils实现CRUD操作 9.1 Apache-DBUtils简介 commons-dbutils 是 Apache 组织提供的一个开源 JDBC工具类库,它是对JDBC的 ...

  5. 【SpringMVC】处理模型数据

    处理模型数据 Spring MVC 提供了以下几种途径输出模型数据: ModelAndView: 处理方法返回值类型为 ModelAndView时, 方法体即可通过该对象添加模型数据 Map 及 Mo ...

  6. TCP延迟调优之PSH参数与passt延迟问题修复

    qemu中使用passt来作为虚拟机的网卡NAT实现,希望能够利用它IP地址与host一致的优点.这本来是没有啥问题的,但是不知道为什么它的TCP入口流量的延迟很严重. 好吧,反正以后总是要改pass ...

  7. 活动中台系统慢 SQL 治理实践

    作者:vivo 互联网服务器团队- Zhang Mengtao 活动中台系统作为中台项目非常注重系统性能和用户体验,数据库系统性能问题会对应用程序的性能和用户体验产生负面影响.慢查询可能导致应用程序响 ...

  8. 中文Markmap v2.0 现已上线,新增高效功能,老板再也留不住你下班的脚步!

    介绍 Markmap.js 是一款开源项目,在 GitHub 上获得了超过 1.7 万个星的关注,它的主要功能是将 Markdown 文档可视化为思维导图. 在日常使用中,用户经常需要面对老板的&qu ...

  9. Aspnet Core 10 Preview3已对最小API提供参数验证支持

    前言 相信大家都或多或少用上了Minimal API,快速简洁,性能炸裂,是快速开发API端口的不二之选!但是呢目前正式版为止 最小API还并不内置支持对请求参数的内置验证支持,比如[Required ...

  10. Postman+Newman生成接口测试报告

    1.安装node 安装完后进入cmd输入node检验版本 2.安装newman 打开cmd-->输入npm install -g newman,然后输入newman -v验证版本 3.安装htm ...