前言

  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. Oracle存储过程里操作BLOB的字节数据的办法

    一.缘由 BLOB是指二进制大对象,也就是英文Binary Large Object的缩写. 在很多时候,我们是通过其他编程语言(如Java)访问BLOB的字节数据,进行字节级的操作的. 但是有些时候 ...

  2. Docker启动关闭所有容器命令

    docker中 启动所有的容器命令 docker start $(docker ps -a | awk '{ print $1}' | tail -n +2) docker中 关闭所有的容器命令 do ...

  3. 大型通用电子制造执行系统(MES)

    ​ 简介: 系统参考西门子MOM智能制造Opcenter工业软件制造执行系统Camstar电子套件人机料法环数据建模业务对象和车间生产执行事务逻辑,采用面向对象分层设计与C#编程开发:包含电子制造企业 ...

  4. Hack The Box-Chemistry靶机渗透

    通过信息收集访问5000端口,cif历史cve漏洞反弹shell,获取数据库,利用低权限用户登录,监听端口,开放8080端口,aihttp服务漏洞文件包含,获取root密码hash值,ssh指定登录 ...

  5. 什么是RESTful 或 GraphQL?

    RESTful 与 GraphQL 深度解析 在前端的开发过程中,相信 everyone 对 Get.POST 等请求方式都很熟悉,那么这些请求是归于哪种架构或者设计风格可能又不是很熟.现在在这简单的 ...

  6. MySQL 创建数据库并指定字符集编码

    备忘 CREATE DATABASE mydb CHARACTER SET utf8 COLLATE utf8_general_ci; GRANT ALL ON mydb.* TO "use ...

  7. 学习FASTAPI

    弯弯曲曲的学习之路 学了那么多语言,都是半途而废.包括java,Javascript,go,php,ruby等等乱七八糟. 除了c的自由和pascal的优美,FoxPro简单,其他都似懂非懂入不了法眼 ...

  8. ChatGTP获取的d读取excel通用程序。

    procedure ReadExcelFile(const FileName: string; AMemtable: TFDmemtable); var ExcelApp: OleVariant; S ...

  9. D常用快捷键大全(转)

    Ctrl+PageUp将光标移至本屏的第一行,屏幕不滚动.Ctrl+PageDown将光标移至本屏的最后一行,屏幕不滚动.Ctrl+↓向下滚动屏幕,光标跟随滚动不出本屏.Ctrl+↑向上滚动屏幕,光标 ...

  10. DotNetGuide 突破了 8K + Star,努力打造C#/.NET/.NET Core全面的学习、工作、面试指南知识库!

    前言 转眼之间维护DotNetGuide(全面的C#/.NET/.NET Core学习.工作.面试指南知识库)已经持续超过了4年多的时间,Commit提交数也超过1400+,在前几天在 GitHub ...