αλε*_*λυτ 5 c# c++ debugging deadlock gstreamer
我在 C# WinForms 应用程序中使用gstreamer 1.8.1 库,它允许我同时观看来自视频服务器设备的多个 RTSP 视频流。
我编写了一个本机 c++ dll,它包装了对 gstreamer 的调用。我通过 DllImport 属性从 C# 应用程序使用它。
大多数时候一切都很完美。但有时(我认为当与视频服务器的连接不稳定时)我gst_element_set_state(pipeline, GST_STATE_NULL);的本机 dll 中出现死锁。
对 gstreamer API 的所有调用都是从主 (GUI) 线程进行的。死锁发生的情况非常罕见——每天只发生一次。发现这个错误非常乏味,而且我不知道如何修复或解决它。
以下是发生死锁时 Visual Studio 调试器的一些屏幕截图:
gstreamer 包装器 dll 的源代码非常小:
#pragma comment(lib, "gstreamer-1.0.lib")
#pragma comment(lib, "glib-2.0.lib")
#pragma comment(lib, "gobject-2.0.lib")
#pragma comment(lib, "gstvideo-1.0.lib")
GSTLIB_API void init()
{
gst_init(NULL, NULL);
}
GSTLIB_API GstElement* create(const char* uri, const void* hwnd)
{
GstElement* pipeline = gst_element_factory_make("playbin", "play");
g_object_set(G_OBJECT(pipeline), "uri", uri, NULL);
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(pipeline), (guintptr)hwnd);
return pipeline;
}
GSTLIB_API void play(GstElement* pipeline)
{
gst_element_set_state(pipeline, GST_STATE_PLAYING);
}
GSTLIB_API void stop(GstElement* pipeline)
{
gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(pipeline), 0);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(GST_OBJECT(pipeline));
}
GSTLIB_API bool hasError(GstElement* pipeline)
{
auto state = GST_STATE(pipeline);
return state != GST_STATE_PLAYING;
}
Run Code Online (Sandbox Code Playgroud)
本机 dll 的 C# 绑定:
[DllImport("GstLib.dll", EntryPoint = @"?init@@YAXXZ",
CallingConvention = CallingConvention.Cdecl)]
private static extern void init();
[DllImport("GstLib.dll", EntryPoint = @"?create@@YAPAU_GstElement@@PBDPBX@Z",
CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr create([MarshalAs(UnmanagedType.LPStr)] string uri, IntPtr hwnd);
[DllImport("GstLib.dll", EntryPoint = @"?stop@@YAXPAU_GstElement@@@Z",
CallingConvention = CallingConvention.Cdecl)]
private static extern void stop(IntPtr pipeline);
[DllImport("GstLib.dll", EntryPoint = @"?play@@YAXPAU_GstElement@@@Z",
CallingConvention = CallingConvention.Cdecl)]
private static extern void play(IntPtr pipeline);
[DllImport("GstLib.dll", EntryPoint = @"?hasError@@YA_NPAU_GstElement@@@Z",
CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.U1)]
private static extern bool hasError(IntPtr pipeline);
Run Code Online (Sandbox Code Playgroud)
有谁知道为什么会发生死锁?
小智 1
这可能只是我的纯粹猜测:
如果您要在流线程中设置管道的状态,则实际上必须调用gst_element_call_async来完成。GStreamer 文档指出,在流线程中调用gst_element_set_state可能会导致死锁:
gst_element_call_async
从另一个线程调用 func 并将 user_data 传递给它。这用于必须从流线程直接通过 gst_element_set_state 或间接(例如通过 SEEK 事件)执行状态更改的情况。
在许多情况下,直接从流线程调用这些函数会导致死锁,因为它们可能涉及等待流线程从该流线程关闭。
MT 安全。
| 归档时间: |
|
| 查看次数: |
474 次 |
| 最近记录: |