Gstreamer - 如何构建具有多个 src 的应用程序?
Gstreamer - How to structure application with multiple src's?
我有多个摄像头 (rtspsrc
) 和一个对传入视频流进行分析的单例元素。我称它为单例元素,因为它有请求源和接收垫。应用程序中应该只存在其中一个,因为它在 GPU 上工作,并且可以通过批处理获得更好的性能。将我正在构建的应用程序想象成一个 API 来添加摄像头、移除摄像头、打开和关闭每个摄像头的分析等。摄像头将对其进行分析、捕获结果并将它们发送出去。复杂的是,我需要共享一个 Gstreamer 元素(分析元素)。
所以我有多个摄像头,输入到这个单一元素,然后输出到 appsinks。这工作得相当好,但我希望能够:
- 暂停特定相机
- 让每个
rtspsrc
完全隔离,所以一个错误不会影响整个管道
- 侦听特定相机上的事件
如果我将所有摄像头放在一个管道中,我不知道如何暂停特定摄像头。我不能暂停整个流水线,因为那样会停止所有摄像头。我想出的最好办法是删除和不同于特定相机的元素,然后在恢复时重新添加并重新 link。这有点像。如果特定 rtspsrc
停止响应,则整个管道停止。如果特定 rtspsrc
不存在,则整个管道将不会转换为 PLAYING 状态
我应该如何构建我的应用程序?你认为我应该有一个大管道吗?或者我应该有一个包含单例分析元素的管道,以及每个摄像头的管道,然后使用 appsink 和 appsrc 连接它们?这种方法可能更容易处理事情,因为每个管道都是完全独立的?
如果您需要更多信息,请告诉我。
编程中的单体架构should generally be avoided,您的场景也不例外。您已经经历过在一个管道中管理所有内容的一些复杂情况,发现的解决方法可能会在未来导致更多问题,而且它们不提供管理每个摄像头的便捷访问。
因此,我建议采用第二种方法,让每个摄像头都有一个管道,并另外使用类似于 this SO answer. You may also want to ensure your singleton is thread safe 中的架构实现缓冲队列,以避免在分析时管道之间出现任何竞争条件从相机发送。
根据您的要求,我将使用 MVVM 模式和 DI 容器在 c# 中构建大部分 API、相机管理和 GUI,这样您就可以尽可能地解耦您的API 部分,并使它们尽可能可测试。另一个动机是使用这个生态系统(C#,Visual Studio)可以很快地生成一个 UI;同样对于大多数项目,您知道维护将是主要成本 Development cost versus maintenance cost, hence decoupling and testing against interfaces is excellent to keep those costs as low as possible.; MVVM will allow you to test your UI Writing a Testable Presentation Layer with MVVM. Decoupling your software components will also allow you to upgrade a certain implementation without touching the rest, and compose your software with its components in the composition root。通常这样的做法允许您从测试 (TDD) 开始。
我会确保每个摄像头有 1 个管道,以简化资源管理,如果您使用 cudastreams (cudastreams to simplify concurrency),您可以在一个 GPU 上执行多个视频分析任务,每个流执行一个摄像机视频流的分析。您可能想使用 opencv 中的一些经过验证的代码,并确保它可以在 cudastream 中转换。如果数据量,你的性能要求,你的硬件不会need/allow这样的事情,你可以只用一个opencv处理。
在本机部分,(gstreamer),通过互操作将组件与 c# 连接起来相对容易;例如:
extern "C" __declspec(dllexport) auto Query(myClass* p, const wchar_t* somePath)
-> structResult*
{ return p->Query(somePath); }
在托管部分:
[DllImport("myAssembly.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr Query(IntPtr myClassPointer, IntPtr somePath);
我有多个摄像头 (rtspsrc
) 和一个对传入视频流进行分析的单例元素。我称它为单例元素,因为它有请求源和接收垫。应用程序中应该只存在其中一个,因为它在 GPU 上工作,并且可以通过批处理获得更好的性能。将我正在构建的应用程序想象成一个 API 来添加摄像头、移除摄像头、打开和关闭每个摄像头的分析等。摄像头将对其进行分析、捕获结果并将它们发送出去。复杂的是,我需要共享一个 Gstreamer 元素(分析元素)。
所以我有多个摄像头,输入到这个单一元素,然后输出到 appsinks。这工作得相当好,但我希望能够:
- 暂停特定相机
- 让每个
rtspsrc
完全隔离,所以一个错误不会影响整个管道 - 侦听特定相机上的事件
如果我将所有摄像头放在一个管道中,我不知道如何暂停特定摄像头。我不能暂停整个流水线,因为那样会停止所有摄像头。我想出的最好办法是删除和不同于特定相机的元素,然后在恢复时重新添加并重新 link。这有点像。如果特定 rtspsrc
停止响应,则整个管道停止。如果特定 rtspsrc
不存在,则整个管道将不会转换为 PLAYING 状态
我应该如何构建我的应用程序?你认为我应该有一个大管道吗?或者我应该有一个包含单例分析元素的管道,以及每个摄像头的管道,然后使用 appsink 和 appsrc 连接它们?这种方法可能更容易处理事情,因为每个管道都是完全独立的?
如果您需要更多信息,请告诉我。
编程中的单体架构should generally be avoided,您的场景也不例外。您已经经历过在一个管道中管理所有内容的一些复杂情况,发现的解决方法可能会在未来导致更多问题,而且它们不提供管理每个摄像头的便捷访问。
因此,我建议采用第二种方法,让每个摄像头都有一个管道,并另外使用类似于 this SO answer. You may also want to ensure your singleton is thread safe 中的架构实现缓冲队列,以避免在分析时管道之间出现任何竞争条件从相机发送。
根据您的要求,我将使用 MVVM 模式和 DI 容器在 c# 中构建大部分 API、相机管理和 GUI,这样您就可以尽可能地解耦您的API 部分,并使它们尽可能可测试。另一个动机是使用这个生态系统(C#,Visual Studio)可以很快地生成一个 UI;同样对于大多数项目,您知道维护将是主要成本 Development cost versus maintenance cost, hence decoupling and testing against interfaces is excellent to keep those costs as low as possible.; MVVM will allow you to test your UI Writing a Testable Presentation Layer with MVVM. Decoupling your software components will also allow you to upgrade a certain implementation without touching the rest, and compose your software with its components in the composition root。通常这样的做法允许您从测试 (TDD) 开始。
我会确保每个摄像头有 1 个管道,以简化资源管理,如果您使用 cudastreams (cudastreams to simplify concurrency),您可以在一个 GPU 上执行多个视频分析任务,每个流执行一个摄像机视频流的分析。您可能想使用 opencv 中的一些经过验证的代码,并确保它可以在 cudastream 中转换。如果数据量,你的性能要求,你的硬件不会need/allow这样的事情,你可以只用一个opencv处理。
在本机部分,(gstreamer),通过互操作将组件与 c# 连接起来相对容易;例如:
extern "C" __declspec(dllexport) auto Query(myClass* p, const wchar_t* somePath)
-> structResult*
{ return p->Query(somePath); }
在托管部分:
[DllImport("myAssembly.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr Query(IntPtr myClassPointer, IntPtr somePath);