GStreamer开发笔记(七):gstreamer播放ogg详解
前言
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详解的更多相关文章
- ArcGIS API for javascript开发笔记(六)——REST详解及如何使用REST API调用GP服务
感谢一路走来默默支持和陪伴的你~~~ -------------------欢迎来访,拒绝转载-------------------- 一.Rest API基础 ArcGIS 平台提供了丰富的REST ...
- Android开发笔记之: 数据存储方式详解
无论是神马平台,神马开发环境,神马软件程序,数据都是核心.对于开发平台来讲,如果对数据的存储有良好的支持,那么对应用程序的开发将会有很大的促进作用.总体的来讲,数据存储方式有三种:一个是文件,一个是数 ...
- python开发笔记之zip()函数用法详解
今天分享一篇关于python下的zip()函数用法. zip()是Python的一个内建函数,它接受一系列可迭代的对象作为参数,将对象中对应的元素按顺序组合成一个tuple,每个tuple中包含的是原 ...
- Android 高级UI设计笔记07:RecyclerView 的详解
1. 使用RecyclerView 在 Android 应用程序中列表是一个非常重要的控件,适用场合非常多,如新闻列表.应用列表.消息列表等等,但是从Android 一出生到现在并没有非常 ...
- IP地址和子网划分学习笔记之《IP地址详解》
2018-05-03 18:47:37 在学习IP地址和子网划分前,必须对进制计数有一定了解,尤其是二进制和十进制之间的相互转换,对于我们掌握IP地址和子网的划分非常有帮助,可参看如下目录详文. ...
- [ 转载 ] Java开发中的23种设计模式详解(转)
Java开发中的23种设计模式详解(转) 设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类 ...
- “全栈2019”Java第七十章:静态内部类详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 最锋利的Visual Studio Web开发工具扩展:Web Essentials详解
原文:最锋利的Visual Studio Web开发工具扩展:Web Essentials详解 Web Essentials是目前为止见过的最好用的VS扩展工具了,具体功能请待我一一道来. 首先,从E ...
- Android进阶笔记:Messenger源码详解
Messenger可以理解为一个是用于发送消息的一个类用法也很多,这里主要分析一下再跨进程的情况下Messenger的实现流程与源码分析.相信结合前面两篇关于aidl解析文章能够更好的对aidl有一个 ...
- 【笔记】Pandas分类数据详解
[笔记]Pandas分类数据详解 Pandas Pandas分类数据详解|轻松玩转Pandas(5) 参考:Pandas分类数据详解|轻松玩转Pandas(5)
随机推荐
- Oracle存储过程里操作BLOB的字节数据的办法
一.缘由 BLOB是指二进制大对象,也就是英文Binary Large Object的缩写. 在很多时候,我们是通过其他编程语言(如Java)访问BLOB的字节数据,进行字节级的操作的. 但是有些时候 ...
- Docker启动关闭所有容器命令
docker中 启动所有的容器命令 docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) docker中 关闭所有的容器命令 do ...
- 大型通用电子制造执行系统(MES)
简介: 系统参考西门子MOM智能制造Opcenter工业软件制造执行系统Camstar电子套件人机料法环数据建模业务对象和车间生产执行事务逻辑,采用面向对象分层设计与C#编程开发:包含电子制造企业 ...
- Hack The Box-Chemistry靶机渗透
通过信息收集访问5000端口,cif历史cve漏洞反弹shell,获取数据库,利用低权限用户登录,监听端口,开放8080端口,aihttp服务漏洞文件包含,获取root密码hash值,ssh指定登录 ...
- 什么是RESTful 或 GraphQL?
RESTful 与 GraphQL 深度解析 在前端的开发过程中,相信 everyone 对 Get.POST 等请求方式都很熟悉,那么这些请求是归于哪种架构或者设计风格可能又不是很熟.现在在这简单的 ...
- MySQL 创建数据库并指定字符集编码
备忘 CREATE DATABASE mydb CHARACTER SET utf8 COLLATE utf8_general_ci; GRANT ALL ON mydb.* TO "use ...
- 学习FASTAPI
弯弯曲曲的学习之路 学了那么多语言,都是半途而废.包括java,Javascript,go,php,ruby等等乱七八糟. 除了c的自由和pascal的优美,FoxPro简单,其他都似懂非懂入不了法眼 ...
- ChatGTP获取的d读取excel通用程序。
procedure ReadExcelFile(const FileName: string; AMemtable: TFDmemtable); var ExcelApp: OleVariant; S ...
- D常用快捷键大全(转)
Ctrl+PageUp将光标移至本屏的第一行,屏幕不滚动.Ctrl+PageDown将光标移至本屏的最后一行,屏幕不滚动.Ctrl+↓向下滚动屏幕,光标跟随滚动不出本屏.Ctrl+↑向上滚动屏幕,光标 ...
- DotNetGuide 突破了 8K + Star,努力打造C#/.NET/.NET Core全面的学习、工作、面试指南知识库!
前言 转眼之间维护DotNetGuide(全面的C#/.NET/.NET Core学习.工作.面试指南知识库)已经持续超过了4年多的时间,Commit提交数也超过1400+,在前几天在 GitHub ...