GStreamer中如何自定义配置线程优先级

1.引言

如果看了gstreamer官方教程配置多线程出现编译不过的问题了,不妨进来看看这篇文章或许能解决一些编译问题。

GStreamer 本质上是多线程的,并且是完全线程安全的。大多数线程内部对应用程序是隐藏的,这应该使应用程序开发更容易。但是,在某些情况下,应用程序可能希望影响其中的某些部分。 GStreamer 允许应用程序在pipeline的某些部分强制使用多个线程,GStreamer 还可以在创建线程时通知您,以便您可以配置要使用的线程优先级或线程池等内容。

2.GStreamer 中的调度

GStreamer pipeline中的每个element决定如何调度它。element可以选择是基于推还是基于拉的方式调度它们的pad。例如,一个element可以选择启动一个线程以开始从sink pad拉取 或/并 开始从source pad推送。element也可以选择使用上游(upstream )或下游(downstream )线程分别以推和拉模式对数据进行处理。 GStreamer 对element选择如何调度没有任何限制。有关更多详细信息,请参阅插件编写指南。

在任何情况下都会发生的是,某些element将启动一个线程来处理它们的数据,称为“流线程”(“streaming threads”)。当element需要创建一个流线程时,流线程或叫做 GstTask 对象是从 GstTaskPool 创建的。在下一节中,我们将看到如何接收任务和池的通知。

3.在 GStreamer 中配置线程

STREAM_STATUS 消息发布在总线上以通知有关流线程的状态。你将从消息中获得以下信息:

当将要创建新线程时,您将收到 GST_STREAM_STATUS_TYPE_CREATE 类型的通知。然后可以在 GstTask 中配置 GstTaskPool。自定义任务池将为任务提供自定义线程以实现流线程。

  • 如果要配置自定义任务池,则需要同步处理此消息。如果你在此消息返回时未在任务上配置任务池,则任务将使用其默认池。

  • 进入或离开线程时。这是你可以配置线程优先级的时刻。当线程被销毁时,你也会收到通知。

  • 当线程开始、暂停和停止时,你会收到消息。这可用于在 gui 应用程序中可视化流线程的状态。

4.如何提高线程的优先级

请添加图片描述
让我们看一下上面的pipeline。我们希望提高流线程的优先级。appsrc element将启动流线程来将appsrc中src pad上的数据推送给对端queue element的sink pad。改变优先级的流程是这样的:

  • 当从 READY 到 PAUSED 状态时, appsrc 将需要一个流线程来将数据推送到 queue 中。它将发布一条STREAM_STATUS 消息,指示其对流线程的需求。

  • 应用程序将使用同步总线处理程序对 STREAM_STATUS 消息做出反应。然后它将在消息内的 GstTask 上配置自定义GstTaskPool。自定义任务池负责创建线程。在这个例子中,我们将创建一个具有更高优先级的线程。

  • 或者,由于同步消息是在线程上下文中调用的,您可以使用线程 ENTER/LEAVE 通知来更改当前线程的优先级或调度策略。

第一步,我们需要实现一个可以在任务上配置的自定义 GstTaskPool。下面是一个 GstTaskPool 子类的实现,它使用 pthreads 创建一个 SCHED_RR 实时线程。请注意,创建实时线程可能需要额外的权限。

#include <gst/gst.h>
#include <gst/gsttaskpool.h>#define TEST_TYPE_RT_POOL \(test_rt_pool_get_type())GType test_rt_pool_get_type (void);
GstTaskPool *test_rt_pool_new (void);typedef struct _GstTaskPool      TestRTPool;
typedef struct _GstTaskPoolClass TestRTPoolClass;typedef struct
{pthread_t thread;
} TaskPoolRTId;G_DEFINE_TYPE (TestRTPool, test_rt_pool, GST_TYPE_TASK_POOL);static void
default_prepare (GstTaskPool * pool, GError ** error)
{/* we don't do anything here. We could construct a pool of threads here that* we could reuse later but we don't */
}static void
default_cleanup (GstTaskPool * pool)
{
}static gpointer
default_push (GstTaskPool * pool, GstTaskPoolFunction func, gpointer data,GError ** error)
{TestRTId *tid;gint res;pthread_attr_t attr;struct sched_param param;tid = g_slice_new0 (TestRTId);pthread_attr_init (&attr);if ((res = pthread_attr_setschedpolicy (&attr, SCHED_RR)) != 0)g_warning ("setschedpolicy: failure: %p", g_strerror (res));param.sched_priority = 50;if ((res = pthread_attr_setschedparam (&attr, &param)) != 0)g_warning ("setschedparam: failure: %p", g_strerror (res));if ((res = pthread_attr_setinheritsched (&attr, PTHREAD_EXPLICIT_SCHED)) != 0)g_warning ("setinheritsched: failure: %p", g_strerror (res));res = pthread_create (&tid->thread, &attr, (void *(*)(void *)) func, data);if (res != 0) {g_set_error (error, G_THREAD_ERROR, G_THREAD_ERROR_AGAIN,"Error creating thread: %s", g_strerror (res));g_slice_free (TestRTId, tid);tid = NULL;}return tid;
}static void
default_join (GstTaskPool * pool, gpointer id)
{TestRTId *tid = (TestRTId *) id;pthread_join (tid->thread, NULL);g_slice_free (TestRTId, tid);
}static void
test_rt_pool_class_init (TestRTPoolClass * klass)
{GstTaskPoolClass *gsttaskpool_class;gsttaskpool_class = (GstTaskPoolClass *) klass;gsttaskpool_class->prepare = default_prepare;gsttaskpool_class->cleanup = default_cleanup;gsttaskpool_class->push = default_push;gsttaskpool_class->join = default_join;
}static void
test_rt_pool_init (TestRTPool * pool)
{
}GstTaskPool *
test_rt_pool_new (void)
{GstTaskPool *pool;pool = g_object_new (TEST_TYPE_RT_POOL, NULL);return pool;
}

编写任务池时要实现的重要功能是“push”功能。 实现上应该启动一个调用给定函数的线程。 更复杂的实现可能希望在池中保留一些线程,因为创建和销毁线程并不总是最快的操作。

在下一步中,我们需要在 appsrc 需要时实际配置自定义任务池。 为此,我们使用同步处理程序拦截 STREAM_STATUS 消息。

static GMainLoop* loop;static void
on_stream_status (GstBus     *bus,GstMessage *message,gpointer    user_data)
{GstStreamStatusType type;GstElement *owner;const GValue *val;GstTask *task = NULL;gst_message_parse_stream_status (message, &type, &owner);val = gst_message_get_stream_status_object (message);/* see if we know how to deal with this object */if (G_VALUE_TYPE (val) == GST_TYPE_TASK) {task = g_value_get_object (val);}switch (type) {case GST_STREAM_STATUS_TYPE_CREATE:if (task) {GstTaskPool *pool;pool = test_rt_pool_new();gst_task_set_pool (task, pool);}break;default:break;}
}static void
on_error (GstBus     *bus,GstMessage *message,gpointer    user_data)
{g_message ("received ERROR");g_main_loop_quit (loop);
}static void
on_eos (GstBus     *bus,GstMessage *message,gpointer    user_data)
{g_main_loop_quit (loop);
}int
main (int argc, char *argv[])
{GstElement *bin, *AppSrc;GstBus *bus;GstStateChangeReturn ret;gst_init (&argc, &argv);/* create a new bin to hold the elements */bin = gst_pipeline_new ("pipeline");g_assert (bin);//pseudo-code/* create some elements */AppSrc = gst_element_factory_make ("appsrc", "appsrc");............./* add objects to the main pipeline */gst_bin_add_many (GST_BIN (bin),AppSrc ,..., ..., NULL);/* link the elements */gst_element_link_many(AppSrc,..., ...,null);loop = g_main_loop_new (NULL, FALSE);/* get the bus, we need to install a sync handler */bus = gst_pipeline_get_bus (GST_PIPELINE (bin));gst_bus_enable_sync_message_emission (bus);gst_bus_add_signal_watch (bus);g_signal_connect (bus, "sync-message::stream-status",(GCallback) on_stream_status, NULL);g_signal_connect (bus, "message::error",(GCallback) on_error, NULL);g_signal_connect (bus, "message::eos",(GCallback) on_eos, NULL);/* start playing */ret = gst_element_set_state (bin, GST_STATE_PLAYING);if (ret != GST_STATE_CHANGE_SUCCESS) {g_message ("failed to change state");return -1;}/* Run event loop listening for bus messages until EOS or ERROR */g_main_loop_run (loop);/* stop the bin */gst_element_set_state (bin, GST_STATE_NULL);gst_object_unref (bus);g_main_loop_unref (loop);return 0;
}

请注意,该程序可能需要 root 权限才能创建实时线程。 当无法创建线程时,状态更改函数将失败,我们在上面的应用程序中捕获了这一点。

当pipeline中有多个线程时,您将收到多个 STREAM_STATUS 消息。 您应该使用消息的所有者(可能是 pad 或启动线程的element)来确定该线程在应用程序上下文中的功能是什么。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/698407.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大语言模型的数据预处理

文章目录 质量过滤敏感内容过滤数据去重 当收集了丰富的文本数据之后&#xff0c;为了确保数据的质量和效用&#xff0c;还需要对数据进行预处理&#xff0c;从而消除低质量、冗余、无关甚可能有害的数据。一般来说&#xff0c;需要构建并使用系统化的数据处理框架&#xff08;…

Docker 的 Ubuntu 操作系统镜像

Debian 和 Ubuntu 都是目前较为流行的 Debian 系列 的服务器操作系统&#xff0c;十分适合研发场景。 Debian 和 Ubuntu 属于同一系列的发行版。Debian 是由 Ian Murdock 在 1993 年创建的最初的发行版。Ubuntu 是 Mark Shuttleworth 在 2004 年基于 Debian 创建的发行版。 Li…

300订单,成交大于一切

最近一直在忙于做老客户的需求&#xff0c;新客户挖掘方面有点大大的落后了&#xff0c;新客户的成交率接近0。 今天来了一个新客户&#xff0c;部署一套系统&#xff0c;我的正常报价都是300/次&#xff0c;至于为什么定这个价格后面再说&#xff0c;经过沟通客户没有服务器&…

《基于GNU-Radio和USRP的雷达通信系统的实现》文献阅读

文章目录 前言一、摘要二、引言三、联合系统实施1、基本原理2、实验方案 四、软件设置1、发射机2、接收机 五、实验结果1、实验设置2、波形3、室内外对比4、不同参数的结果 六、结论七、参考文献八、论文自取九、阅读收获 前言 本文记录《基于GNU-Radio和USRP的雷达通信系统的实…

第2章Spring Boot实践,开发社区登录模块【仿牛客网社区论坛项目】

第2章Spring Boot实践&#xff0c;开发社区登录模块【仿牛客网社区论坛项目】 前言推荐项目总结第2章Spring Boot实践&#xff0c;开发社区登录模块1.发送邮件配置MailClient测试 2.开发注册功能访问注册页面提交注册数据激活注册账号 3.会话管理体验cookie体验session 4.生成验…

VRRP虚拟路由器冗余协议

VRRP概述 VRRP是什么 VRRP&#xff1a;虚拟路由器冗余协议过把几台路由设备联合组成一台虚拟的路由设备&#xff0c;将虚拟路由设备的IP地址作为用户的默认网关实现与外部网络通信当网关设备发生故障时&#xff0c;VRRP能够选举新的网关设备承担数据流量&#xff0c;从而保障…

研发管理-选择研发管理系统-研发管理系统哪个好

选择研发管理系统-研发管理系统哪个好 选择研发管理系统时&#xff0c;并没有一个绝对的“最好”的系统&#xff0c;因为每个企业的需求和情况都是独特的。然而&#xff0c;我可以向您介绍一些在市场上广受欢迎且功能强大的研发管理系统&#xff0c;供您参考&#xff1a; 1、彩…

2024第二届区块链、物联网与金融管理国际会议(ICBITFM2024)

2024第二届区块链、物联网与金融管理国际会议(ICBITFM2024) 会议简介 2024第二届区块链、物联网与金融管理国际会议(ICBITFM 2024)是一个重要的学术会议&#xff0c;旨在促进区块链、物联网和金融管理领域的交流和合作&#xff0c;对于推动这些领域的发展和创新具有重要意义。…

Spring MVC(五) 文件上传

1 单文件上传 在程序开发中&#xff0c;有时候需要上传一些文件。我们在学习Servlet的时候&#xff0c;也做过文件上传的操作&#xff0c;只不过基于Servlet的文件上传操作起来过于复杂&#xff0c;因此所有的MVC框架都提供了自己的文件上传操作&#xff0c;基本上都是基于File…

【CSP CCF记录】202009-1 称检测点查询

题目 过程 难点&#xff1a;编号和位置的一一对应&#xff0c;不同位置的距离可能相等。 所以使用一个结构体记录不同检测点的编号和到居民地的距离。 sort函数进行排序。Sort函数使用方法 参考&#xff1a;http://t.csdnimg.cn/Y0Hpi 代码 #include <bits/stdc.h>…

一觉醒来 AI科技圈发生的大小事儿 05月13日

&#x1f4f3;博弈论让 AI 更加正确、高效&#xff0c;LLM 与自己竞争 研究团队设计了共识博弈&#xff0c;通过让语言模型的生成器和判别器相互博弈来提高模型的准确性和内部一致性。这种方法不需要对基础模型进行训练或修改&#xff0c;可以在笔记本电脑上快速执行。研究结果…

uview-plus在uniapp项目中单选和复选框不显示问题

在我的uniapp小程序项目中&#xff0c;我使用了vue3ts的组合&#xff0c;ui组件库使用了uview-plus这个组件库&#xff0c;但是在使用个别组件的时候&#xff0c;没有显示出效果&#xff0c;就像单选或者复选框&#xff0c;官方效果&#xff1a; 但是当我用到自己项目中的时候&…