GStreamer开发笔记(四):ubuntu搭建GStreamer基础开发环境以及基础Demo

笔记哥 / 05-22 / 40点赞 / 0评论 / 877阅读
# 前言 本篇开始gstreamer的编程学习,先搭建基础的环境,跑通一个基础的Demo对GStreamer编程有个初步的了解。 # Demo ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/dc7b2677.png?G1cAAETn9LyUgsDivtMdbIlTE20GLNIIKiWs13vO2jfR94dAND%2bj9Rn7w29an0FcL7YCEojBkIIIQ6EqjMRu5vBaS14jAA%3d%3d) ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/9901df43.png?G1YAAMR0rnGCXj9EtxGHaoJAgs2ARBZBpYT1ev5%2f7Yvo%2fUIglu%2fR%2boz94S%2btzyA%2bD3YFCcThSF6EYTBTl6QozqVqzWsE) # GStreamer GStreamer是一个灵活、快速、多平台的多媒体框架,此框架非常强大和通用,用于创建流媒体应用程序。GStreamer框架的许多优点来自其模块化,GStreamer可以无缝地整合新的插件模块。但是,由于模块化和强大的功能往往以更高的复杂性为代价,编写新的应用程序并不总是那么容易。 ## 结构 教程分为几个部分,围绕一个共同的主题: - 基础教程:描述理解GStreamer中其余教程所需的一般主题。 - 播放教程:解释使用GStreamer制作媒体播放应用程序所需知道的一切。 - Android教程:涉及您需要知道的几个Android特定主题的教程。 - iOS教程:涉及您需要知道的几个iOS特定主题的教程。   基础教程——理解其余教程所需的一般主题 # 搭建基础开发环境 ## 步骤一:安装gstreamer1.0环境 ```cpp sudo apt-get update sudo apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-bad1.0-dev gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio sudo apt-get install libglib2.0-0 ``` ## 步骤二:创建C工程 使用QtCreator新建空的C工程:   ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/f9fa9a23.png?G1YAAMTW3DgpD4Fk22gDdWfqnTUDElkElRLW6%2fn%2ftS%2bi9wuBaL5H6zP2h7%2b0PoO4OtsBEojBkLwIQ6EKs1QYfnotntcI) ## 步骤三:添加gstreamer开发环境 然后查找gst.h头文件: ```cpp sudo find / -name "gst.h" ``` ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/868f35d5.png?G1YAAMTydJz4%2b%2fNCu406fJsoEpoBiSyCSgnr9Z6z9i3y%2fU7Q4jNan74%2f%2fKX16aJX0ZwgBDMygicVBjOgBlbVZFVLXMMB) 查找库: ```cpp sudo find / -name "gstreamer-1.0*” ``` ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/3a36f551.png?G1cAAMTydJz4%2b%2fOiuo06fJsoEpoBizSCSgnr9Z6z9i3y%2fU7Q4jNan74%2f%2fKb16aK1aE4QghkZIZAKg5niCqqVqRhZ4hoO) 查找依赖的头文件: ```cpp sudo find / -name "glib.h" ``` ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/91d42f38.png?G1cAAER17rxgXRmgfice0wSBBJsBizSCSgnr9fz%2f2pfI%2bzlBi%2fdoffr%2b8JvWp4ueVXOCEMzICIFUGMyUFohUj1KgGtdw) ```cpp sudo find / -name “glibconfig” ``` ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/9f514aac.png?G1cAAER17rxg7Rygfice0wSBBJoBizSCSgnr9e491y3y%2fa5Qi0%2bvbfj68JvahguvwnRAFJqQEIIqYTAjNDAbM63wjLM7) 将头文件路径和库添加进pri:   ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/27ad8731.png?G1YAAOTcVkxwP3i2iOF0Q2CDZkAii6BSwnq956x9A3x%2fMLLmZ7Q%2bY3%2f4S%2bszgLySCQIjGxqSZyZUVCXxJHSRFS%2bS1wg%3d) ```cpp # gstreamer头文件和库文件 INCLUDEPATH += /usr/include/gstreamer-1.0 LIBS += -lgstreamer-1.0 #LIBS += -lgobject-2.0 -lgstreamer-1.0 -lgstvideo-1.0 # glibc头文件和库文件 INCLUDEPATH += /usr/include/glib-2.0 INCLUDEPATH += /usr/lib/x86_64-linux-gnu/glib-2.0/include LIBS += -lglib-2.0 ``` # 第一个GStreamer程序 ## 步骤一:初始化gst 这是每个程序都要做的。   ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/5f07cf5a.png?G1YAAMTydJz4%2b%2bsLuo06fJsoEpoBiSyCSgnr9Z6z9i3y%2fU7Q4jNan74%2f%2fKX16aI1a7ogBBMSgicVBjOUGgwsSuQS13A%3d) ## 步骤二:定义管道 ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/9f86e82a.png?G1cAAETn9LyUgsDivtMdbIlTE20GLNIIKiWs13vO2jfR94dAND%2bj9Rn7w29an0FcL7YCEojBkIIIQ6EK88SV4eoKy2sE) ## 步骤三:设置管道状态 ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/46fd6be9.png?G1cAAER17rxgXdmC%2bp14TBMEEmwGLNIIKiWs1%2fP%2fa18i7xcELd%2bj9Rn7w29anyF6VvUCIehwpEAqDGZKJFWWinKo5zUC) ## 步骤四:获取管道的总线bus ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/1b758bdc.png?G1cAAER17rxg3exQ%2fU48pgkCCTYDFmkElRLW6%2fn%2fuS6R9wuDMd%2b9thHrw29qGyF67uobxGAORwpmCoJEYVJ3BwsPz7MH) ## 步骤五:从总线bus中阻塞获取指定的信息 ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/641fc305.png?G1cAAMTsdJzIJ4Sm26hD2jvFHc2ARRpBpYT1es9Z%2byb6fhdIjs9offr%2b8JvWpxNbZU0ggSgUIYgwMnKyy4KgQpm5WFzDAQ%3d%3d) ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/a020b2a3.png?G1cAAMTsdJxI8hK026hD2jvFHc2ARRpBpYT1es9Z%2byb6fgdD4zNan74%2f%2fKb16SRXEUtMYBgbQgCElVUlI0jWpLWa5LiGAw%3d%3d) ## 步骤六:消息处理 ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/104b1ae7.png?G1UAAMTydJz4c%2f6JbqMO3yaKRJsBiSyCSgnr9fz%2fPpfI%2bzlBjffsY%2fn58Jc%2blktqNVmGEDQYgiYTFKrIFgpYc2mMezo%3d) ## 步骤七:释放资源 ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/186fefa4.png?G1YAAMR0rnGCXj8VtxGHaoJAAs2ARBZBpYT1evee6yb6%2fhCI5afXNmJ9%2bEttI4jLya4ggTgcyYswDGbOVzpUjBWF8%2bwB) # 关键函数 ## gst\_init() 初始化所有内部结构,检查哪些插件可用,执行GStreamer的任何命令行选项。 ## gst\_parse\_launch() 在GStreamer中,通过手动组装单个元素来构建管道,但是,当管道足够简单,并且不需要任何高级功能时,可以使用快捷方式:gst\_parse\_launch();   此函数接受管道的文本表示并将其转换为实际的管道,这非常方便。事实上,这个函数非常方便,有一个完全围绕它构建的工具,请参阅GStreamer工具,了解gst-launch-1.0和gst-launch-1.0语法。   本篇,我们正在构建一个由一个名为playbin的元素组成的管道。playbin是一个特殊的元素,它既是源又是汇,是一个完整的管道。在内部,它创建并连接了播放媒体所需的所有元素。 ## gst\_element\_set\_state() 每个GStreamer元素都有一个关联的状态,您或多或少可以将其视为常规DVD播放器中的播放/暂停按钮。现在,只需说,除非将管道设置为播放状态,否则播放将不会开始。   gst\_element\_set\_stat()将管道(我们唯一的元素,记住)设置为播放状态,从而启动播放。 ## gst\_element\_get\_bus() 检索管道的总线。 ## gst\_bus\_timed\_pop\_filtered() gst\_bus\_timed\_pop\_filtered()将阻塞,直到您通过该总线收到指定错误或指定的事件,这些事件预定义了。 ## gst\_message\_unref(msg); 清理消息。 ## gst\_object\_unref (bus); 清理qobject类型,按照生成顺序逆向的来unref释放引用。 ## gst\_element\_set\_state (pipeline, GST\_STATE\_NULL); 设置管道状态为空,资源都会被自动回收。 ## gst\_object\_unref (pipeline) 清理qobject类型,按照生成顺序逆向的来unref释放引用。 # 模块化 ![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/f6b26626.png?G1YAAER17rxgXd2C%2bp14TBMEEmgGJLIIKiWs17v3XLfI9wdBy0%2bvbcT68JfaRoheRf2AEHQ4kicVBjOoJTrtLG7Mswc%3d) ## gstreamerManager.pri ```cpp INCLUDEPATH += $$PWD DEPENDPATH += $$PWD HEADERS += \ $$PWD/gstreamerManager.h SOURCES += \ $$PWD/gstreamerManager.c QMAKE_CXXFLAGS += -fpermissive # gstreamer头文件和库文件 INCLUDEPATH += /usr/include/gstreamer-1.0 LIBS += -lgstreamer-1.0 #LIBS += -lgobject-2.0 -lgstreamer-1.0 -lgstvideo-1.0 # glibc头文件和库文件 INCLUDEPATH += /usr/include/glib-2.0 INCLUDEPATH += /usr/lib/x86_64-linux-gnu/glib-2.0/include LIBS += -lglib-2.0 ``` # Demo源码 ```cpp #include "gstreamerManager.h" #include #define DEBUG printf("%s:%d\n", __FILE__, __LINE__) void test001HelloWorldDemo(int *argc, char **argv[]) { GstElement *pipeline; GstBus *bus; GstMessage *msg; // 步骤一:初始化gst gst_init(argc, argv); // 步骤二:定义管道(指定渲染器,否则ubuntu上渲染画面会出错) // pipeline = gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm", NULL); pipeline = gst_parse_launch("playbin uri=https://gstreamer.freedesktop.org/data/media/sintel_trailer-480p.webm video-sink=\"ximagesink\"", NULL); // 步骤三:开始播放(设置管道的运行状态:空、准备、播放、暂停) gst_element_set_state (pipeline, GST_STATE_PLAYING); // 步骤四:获取管道的总线 bus = gst_element_get_bus (pipeline); // 步骤五:阻塞获取bus上指定的消息返回(未获取到则阻塞) msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, GST_MESSAGE_ERROR | GST_MESSAGE_EOS); // 步骤六:消息的处理(这里有很多消息,只是举例子一个 if(GST_MESSAGE_TYPE(msg) == GST_MESSAGE_ERROR) { g_printerr ("An error occurred! Re-run with the GST_DEBUG=*:WARN " "environment variable set for more details.\n"); } // 步骤七:释放资源(其中管道先设置状态空:该状态将会回收所有被该组件占用的资源,然后再释放) gst_message_unref (msg); gst_object_unref (bus); gst_element_set_state (pipeline, GST_STATE_NULL); gst_object_unref (pipeline); } ``` # 工程模板v1.0.0 emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/c619c068.png?G1YAAER17rxgpdui%2bp14TBMEEmgGJLIIKiWs17v3XLfI9wdBy0%2bvbcT68JfaRki5juIKIehwJE8WGMwIS65%2bqgKWZw8%3d) # 入坑 ## 入坑一:播放画面异常 ### 问题 emsp;emsp;播放画面错位 emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/ff850639.png?G1YAAMTsdJxI8hKl26hD2jvFHc2ARBZBpYT1es9Z%2byb6fgdD4zNan74%2f%2fKX16ST1EktMYBgbggeElVUZGnIpkGqpxDUc) emsp;emsp;测试原本文件应该是: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/3dc0434c.png?G1YAAMTsdJzIJxKq26hD2jvFHc2ARBZBpYT1es9Z%2byb6fheIxme0Pn1%2f%2bEvr04lrYUsggRgMwYswFKqoOdR8wRIrxzUc) ### 尝试 emsp;emsp;命令行去检测,也是异常: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/0184f559.png?G1cAAER17rxgXdlU%2fE480ASBBJoBizSCSgnr9e491y3y%2fZWgxaeXNur68JvSRhXNp3qCEHQ4QiAVBjPVFPQAcWW6xdkr) emsp;emsp;测试windows上,是正常: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/4491c42d.png?G1UAAMT0bJzotVrCNvqh%2f4lHQjMgkUVQKWG93nv3aUTf7wLR%2bMw%2blp8Pf%2bljOXEtbAkkEIMhaBGGQlUth2zItaQS93Q%3d) emsp;emsp;所以是系统装的环境可能有问题。重新切换虚拟机使用ubuntu20.04重新制作虚拟机,用起来还是一样,有问题: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/bb9fe4ef.png?G1YAAOTcVkxw9wu2iOF0Q2CDZkAii6BSwnq956x9A3x%2fMLLmZ7Q%2bY3%2f4S%2bszgOpFJgiMbGhInplQUZVcEql7tVIkrxE%3d) emsp;emsp;用网页测试,没问题: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/32e8ab23.png?G1UAAMTsdJxI8hKl26hD2jvFHc2ARBZBpYT1es9Z%2byb6fgdD4zNan74%2f%2fKX16ST1EktMYBgbggaElVUlachmFcVKXMMB) emsp;emsp;用vlc测试,也没问题: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/86db6efe.png?G1cAAMT0bJzo9VSEbfRD%2fxOPhGbAIo2gUsJ6vffu00S%2b3wlafGYfy8%2bH3%2fSxXLQWzQlCMCMjBFJhMINq0ARWlFQQ93Q%3d) emsp;emsp;然后测试其他地址试试,发现没问题: emsp;emsp;![在这里插入图片描述](https://cdn.res.knowhub.vip/c/2505/22/74a95882.png?G1cAAER17rxgXdmi%2bp14TBMEEmgGLNIIKiWs17v3XLfI9wdBy0%2bvbcT68JvaRoheh3qBEHQ4UiAVBjNVJAV5qtJLnj0A) ### 解决 后来发现是需要指定渲染器才行。