debugging gstreamer for Windows中的死锁

u5i3ibmn  于 2023-03-23  发布在  Windows
关注(0)|答案(1)|浏览(188)

我在C# WinForms应用程序中使用gstreamer 1.8.1库,它允许我同时从视频服务器设备观看多个RTSP视频流。
我写了一个原生的C++ dll来 Package 对gstreamer的调用。我通过DllImport属性从C#应用程序中使用它。
大多数时候一切都很完美。但有时(我认为当与视频服务器的连接不稳定时)我在本机dll中的gst_element_set_state(pipeline, GST_STATE_NULL);中出现死锁。
所有对gstreamer API的调用都是从主(GUI)线程进行的。死锁很少发生-每天只有一次。捕获这个错误非常繁琐,我不知道如何修复或解决它。
以下是Visual Studio调试器在死锁发生时的一些屏幕截图:
第一节第一节第一节第一节第一次
gstreamer Package 器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;
}

本机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);

有人知道为什么会出现死锁吗?

juud5qan

juud5qan1#

这可能只是我的猜测:
如果要在流式线程中设置管道的状态,实际上必须调用gst_element_call_async。GStreamer文档指出,在流式线程中调用gst_element_set_state可能会导致死锁:
gst_element_call_async
从另一个线程调用func并将user_data传递给它。这用于必须从流式线程执行状态更改的情况,直接通过gst_element_set_state或间接通过SEEK事件。
直接从流线程调用这些函数在许多情况下会导致死锁,因为它们可能需要等待流线程从这个流线程关闭。
MT安全。

相关问题