找回密码
 立即注册
首页 业界区 业界 GStreamer开发笔记(七):gstreamer播放ogg详解 ...

GStreamer开发笔记(七):gstreamer播放ogg详解

背竽 2025-9-24 16:48:06
前言

  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架构图

  
1.png

 探测本地组件

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

 播放ogg文件

步骤一:初始化gst

  
3.png

步骤二:创建消息循环

  
4.png

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

  
5.png

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

  
6.png

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

  
7.png

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

  
8.png

步骤七:连接组件

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

步骤八:开始运行

  
10.png

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

  
11.png

步骤十:清理资源

  
12.png

 Demo源码
  1. /******************** test003 ********************/
  2. static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
  3. {
  4.     GMainLoop* loop = (GMainLoop *) data;
  5.     switch(GST_MESSAGE_TYPE(msg))
  6.     {
  7.     case GST_MESSAGE_EOS:
  8.         g_print ("End of stream\n");
  9.         g_main_loop_quit (loop);
  10.         break;
  11.     case GST_MESSAGE_ERROR:
  12.         {
  13.             gchar  *debug;
  14.             GError *error;
  15.             gst_message_parse_error (msg, &error, &debug);
  16.             g_free (debug);
  17.             g_printerr ("Error: %s\n", error->message);
  18.             g_error_free (error);
  19.             g_main_loop_quit (loop);
  20.             break;
  21.         }
  22.         default:
  23.         break;
  24.     }
  25.     return TRUE;
  26. }
  27. static void on_pad_added (GstElement* element, GstPad* pad, gpointer data)
  28. {
  29.   GstPad *sinkpad;
  30.   GstElement *decoder = (GstElement *) data;
  31.   // 现在可以将这个焊盘与vorbis解码器接收焊盘连接起来
  32.   g_print ("Dynamic pad created, linking demuxer/decoder\n");
  33.   sinkpad = gst_element_get_static_pad(decoder, "sink");
  34.   gst_pad_link (pad, sinkpad);
  35.   gst_object_unref (sinkpad);
  36. }
  37. void test003PlayOggDemo(int *argc, char **argv[])
  38. {
  39.     char const * fileName = "/home/yang/work/test/1.ogg";
  40. //    char const * fileName = "/home/yang/work/test/1.mp3";
  41. //    char const * fileName = "/home/yang/work/test/1.mov";
  42.     GMainLoop *loop;
  43.     GstElement *pipeline, *source, *demuxer, *decoder, *conv, *sink;
  44.     GstBus *bus;
  45.     guint bus_watch_id;
  46.     // 步骤一:初始化gst
  47.     gst_init (argc, argv);
  48.     // 步骤二:创建gmain消息循环
  49.     loop = g_main_loop_new (NULL, FALSE);
  50.     // 步骤三:创建组建
  51.     pipeline = gst_pipeline_new ("audio-player");
  52.     //                                    组件类型          组件唯一名称
  53.     source   = gst_element_factory_make ("filesrc",       "file-source");
  54.     demuxer  = gst_element_factory_make ("oggdemux",      "ogg-demuxer");
  55. //    demuxer  = gst_element_factory_make ("mpeg123",      "mp3-demuxer");   // mp3: 不用分割,所以步骤不一样
  56. //    demuxer  = gst_element_factory_make ("splitmuxsink",      "mov-demuxer");// mov: 分割格式不一样,要修改代码,没改了
  57.     decoder  = gst_element_factory_make ("vorbisdec",     "vorbis-decoder");
  58.     conv     = gst_element_factory_make ("audioconvert",  "converter");
  59.     sink     = gst_element_factory_make ("autoaudiosink", "audio-output");
  60.     if(!pipeline || !source || !demuxer || !decoder || !conv || !sink)
  61.     {
  62.         g_printerr ("One element could not be created. Exiting.\n");
  63.         return;
  64.     }
  65.     // 步骤四:设置本地原的文件属性“location”,文件名
  66.     g_object_set (G_OBJECT (source), "location", fileName, NULL);
  67.     // 步骤五:添加一个消息处理程序
  68.     bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline));
  69.     // 消息回调函数原型:gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data)
  70.     bus_watch_id = gst_bus_add_watch (bus, bus_call, loop);
  71.     gst_object_unref(bus);
  72.     // 步骤六:将所有的组件添加到管道 */
  73.     // file-source | ogg-demuxer | vorbis-decoder | converter | alsa-output
  74.     gst_bin_add_many(GST_BIN(pipeline),
  75.                      source, demuxer, decoder, conv, sink, NULL);
  76.     // 步骤七:链接组件
  77.     // file-source -> ogg-demuxer ~> vorbis-decoder -> converter -> alsa-output
  78.     gst_element_link (source, demuxer);
  79.     gst_element_link_many (decoder, conv, sink, NULL);
  80.     // 注意1:这里demuxer的pad-added消息会出发on_pad_added回调函数
  81.     // 注意2:demuxer是解码器,解码出来有多个流,每个流会产出一个pad,然后动态链接
  82.     // 注意2:在这个回调函数里面,会把added的焊盘关联到decoder上,就实现了demuxer->decoder的链接
  83.     // 注意3:
  84.     g_signal_connect (demuxer, "pad-added", G_CALLBACK (on_pad_added), decoder);
  85.     /* 请注意,解复用器将动态链接到解码器。原因是Ogg可能包含各种流(例如音频和视频)。
  86.      * 当解复用器检测到流的数量和性质时,它将在运行时创建源焊盘。
  87.      * 因此,我们连接了一个回调函数,该函数将在发出“添加焊盘”时执行
  88.      */
  89.     // 步骤八:设置状态运行
  90.     g_print ("Now playing: %s\n", fileName);
  91.     gst_element_set_state (pipeline, GST_STATE_PLAYING);
  92.     // 步骤九:进入消息循环
  93.     g_print ("Running...\n");
  94.     g_main_loop_run (loop);
  95.     // 步骤十:离开主循环,好好清理
  96.     g_print ("Returned, stopping playback\n");
  97.     gst_element_set_state (pipeline, GST_STATE_NULL);
  98.     g_print ("Deleting pipeline\n");
  99.     gst_object_unref(GST_OBJECT (pipeline));
  100.     g_source_remove(bus_watch_id);
  101.     g_main_loop_unref(loop);
  102. }
复制代码
 工程模板v1.2.0

  
13.png

 入坑

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

问题

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

尝试

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

  继续扫描,可以看到:
  
16.png

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

  那么找一下mp3:
  
18.png

  测试:
  
19.png

解决

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


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册