当前位置: 首页 > news >正文

GStreamer —— 2.7、Windows下Qt加载GStreamer库后运行 - “教程7:多线程和 Pad 可用性“(附:完整源码)

运行效果(音频)

在这里插入图片描述

简介

     上一个教程演示了媒体格式和Pad功能。本教程介绍多线程和 Pad 可用性。GStreamer 会自动处理多线程,但是,在某些 情况下,您可能需要手动解耦线程。这 教程 演示如何执行此作,此外,还完成了 Exposition 关于 Pad 可用性。更准确地说,本文档解释了:

          • 如何为 管道

          • 什么是 Pad 可用性

          • 如何复制流

     GStreamer 是一个多线程框架。这意味着在内部它根据需要创建和销毁线程,例如,解耦 从应用程序线程流式传输。此外,插件也是免费的 创建用于自身处理的线程,例如,视频解码器 可以创建 4 个线程以充分利用具有 4 个内核的 CPU。最重要的是,在构建管道时,应用程序可以指定 明确地,分支(管道的一部分)在不同的 thread 中执行 同时)。这是使用 element 完成的,其工作方式如下。 sink pad 只是将数据排入队列并返回控制权。在不同的 thread,数据将出列并推送到下游。此元素也是 用于缓冲,如后面的流式处理教程所示。

     源是合成音频信号(连续音调),即 使用 Element 进行 split(它通过其源 pad 发送所有内容 它通过其 Sink Pad 接收)。然后,一个分支将信号发送到 Audio Card 和 Present 的 Alpha S 的 S 的 S Alpha S 的 它到屏幕上。如图所示,队列会创建一个新线程,因此此管道 在 3 个线程中运行。具有多个 sink 的管道通常需要 multithreaded,因为要同步,sink 通常会阻塞 执行,直到所有其他 sink 都准备就绪,如果 只有一个线程被第一个 sink 阻塞。

在这里插入图片描述

GStreamer相关运行库
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0/gst
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/gstreamer-1.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/include/glib-2.0
INCLUDEPATH += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0/include

LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gstreamer-1.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/glib-2.0.lib
LIBS += D:/Software/GStreamer/1.0/mingw_x86_64/lib/gobject-2.0.lib

完整源码
#include <gst/gst.h>

int main(int argc, char *argv[])
{
    /* 初始化GStreamer */
    gst_init (&argc, &argv);

    /* 创建元素 */
    GstElement *audio_source = gst_element_factory_make ("audiotestsrc", "audio_source");
    GstElement *tee = gst_element_factory_make ("tee", "tee");
    GstElement *audio_queue = gst_element_factory_make ("queue", "audio_queue");
    GstElement *audio_convert = gst_element_factory_make ("audioconvert", "audio_convert");
    GstElement *audio_resample = gst_element_factory_make ("audioresample", "audio_resample");
    GstElement *audio_sink = gst_element_factory_make ("autoaudiosink", "audio_sink");
    GstElement *video_queue = gst_element_factory_make ("queue", "video_queue");
    GstElement *visual = gst_element_factory_make ("wavescope", "visual");
    GstElement *video_convert = gst_element_factory_make ("videoconvert", "csp");
    GstElement *video_sink = gst_element_factory_make ("autovideosink", "video_sink");

    /* 创建空管道 */
    GstElement *pipeline = gst_pipeline_new ("test-pipeline");

    if (!pipeline || !audio_source || !tee || !audio_queue || !audio_convert || !audio_resample || !audio_sink || !video_queue || !visual || !video_convert || !video_sink)
    { g_printerr ("Not all elements could be created.\n"); return -1; }

    /* 配置元素 */
    g_object_set (audio_source, "freq", 215.0f, NULL);
    g_object_set (visual, "shader", 0, "style", 1, NULL);

    /* 链接所有可以自动链接的元素,因为它们有"Always"的pod */
    gst_bin_add_many (GST_BIN (pipeline), audio_source, tee, audio_queue, audio_convert, audio_resample, audio_sink, video_queue, visual, video_convert, video_sink, NULL);
    if (gst_element_link_many (audio_source, tee, NULL) != TRUE ||
            gst_element_link_many (audio_queue, audio_convert, audio_resample, audio_sink, NULL) != TRUE ||
            gst_element_link_many (video_queue, visual, video_convert, video_sink, NULL) != TRUE)
    {
        g_printerr ("Elements could not be linked.\n");
        gst_object_unref (pipeline); return -1;
    }

    /* 手动连接带有"Request"的pads */
    GstPad *tee_audio_pad = gst_element_request_pad_simple (tee, "src_%u");
    g_print ("Obtained request pad %s for audio branch.\n", gst_pad_get_name (tee_audio_pad));
    GstPad *queue_audio_pad = gst_element_get_static_pad (audio_queue, "sink");
    GstPad *tee_video_pad = gst_element_request_pad_simple (tee, "src_%u");
    g_print ("Obtained request pad %s for video branch.\n", gst_pad_get_name (tee_video_pad));
    GstPad *queue_video_pad = gst_element_get_static_pad (video_queue, "sink");
    if (gst_pad_link (tee_audio_pad, queue_audio_pad) != GST_PAD_LINK_OK || gst_pad_link (tee_video_pad, queue_video_pad) != GST_PAD_LINK_OK)
    {
        g_printerr ("Tee could not be linked.\n");
        gst_object_unref (pipeline); return -1;
    }
    gst_object_unref (queue_audio_pad);
    gst_object_unref (queue_video_pad);

    /* 开始播放管道 */
    gst_element_set_state (pipeline, GST_STATE_PLAYING);

    /* 等待错误或EOS */
    GstBus *bus = gst_element_get_bus (pipeline);
    GstMessage *msg = gst_bus_timed_pop_filtered (bus, GST_CLOCK_TIME_NONE, (GstMessageType)(GST_MESSAGE_ERROR | GST_MESSAGE_EOS));

    /* 释放请求的pad从tee中,然后释放 */
    gst_element_release_request_pad (tee, tee_audio_pad);
    gst_element_release_request_pad (tee, tee_video_pad);
    gst_object_unref (tee_audio_pad);
    gst_object_unref (tee_video_pad);

    /* 释放资源 */
    if (msg != NULL)
        gst_message_unref (msg);
    gst_object_unref (bus);
    gst_element_set_state (pipeline, GST_STATE_NULL);

    gst_object_unref (pipeline);
    return 0;
}

关注

笔者 - jxd

相关文章:

  • 深入解析Java MDC:日志链路追踪的利器
  • 4.2 使用VNote写作手册页面(CHM助手)
  • Python 第二章:夯实基础,掌握核心
  • 玉米籽粒品质相关性状的GWAS和Meta-QTL分析
  • 【Unity】改变游戏运行时Window的窗口标题
  • DeepSeek + 飞书多维表格搭建你的高效工作流
  • React基础之项目创建
  • 在 CentOS 上,常用几种方法来确保 Python 脚本在断开终端后继续运行
  • Cursor如何调试.Net Core控制台程序
  • (接“使用js去复制网页内容的方法”)js中的execCommand怎么复制富文本内容解析
  • Nacos 核心功能实战笔记(超详细)
  • SELECT ... FOR UPDATE 加锁后,其他线程能读取数据吗
  • java下载多个网络文件并压缩成压缩包保存到本地
  • 上传文件到对象存储是选择前端还是后端
  • Compose Multiplatform开发记录之文本输入框
  • window下的docker内使用gpu
  • 从零开始:使用 Python 实现机器学习的基础与实践
  • 2025年天梯赛第1场选拔赛
  • 软考高级信息系统项目管理师笔记-第10章项目进度管理
  • python实现的可爱卸载动画
  • 微信公众号做电影网站要域名吗/百度网站名称及网址
  • 网站建设 模仿阿里云官网/b站推广入口2023mmm无病毒
  • 团购网站案例/百度快照入口
  • 什么网站可以做装修效果图/巨量算数
  • 资讯网站模板带会员投稿功能/长春seo排名外包
  • 网站模板预览/站长工具seo综合查询推广