如何将GstPadProbe回调的流采集通知传递到wxWidgets主代码以更新UI
解决方法
你的需求核心是跨线程传递GStreamer流状态到wxWidgets主线程操作UI,核心要注意两个规则:
- GStreamer的pad probe回调运行在GStreamer内部工作线程,绝对不能直接操作wxWidgets UI控件,否则会随机崩溃
- 要把MainWindow实例指针传给回调,才能访问工具栏等UI成员
步骤1:添加自定义事件和处理函数
首先在MainWindow.h中添加如下内容:
// 自定义事件ID,放在头文件全局位置 const int wxSTREAM_RUNNING_EVT = 10002; class MainWindow : public wxFrame { // ... 原有成员声明不变 private: // 新增流状态正常的事件处理函数声明 void OnStreamRunning(wxCommandEvent& evt); };
然后修改MainWindow的事件表绑定:
wxBEGIN_EVENT_TABLE(MainWindow, wxFrame) EVT_TOOL(10001, LoadVideo) // 新增自定义事件绑定 EVT_COMMAND(wxID_ANY, wxSTREAM_RUNNING_EVT, MainWindow::OnStreamRunning) wxEND_EVENT_TABLE()
步骤2:修改pad probe的传参
修改LoadVideo函数中添加probe的代码,把原来传m_pipeline改成传MainWindow实例指针this:
// 原来的代码:gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback)buffer_out_cb, m_pipeline, NULL); // 修改为: gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, (GstPadProbeCallback)buffer_out_cb, this, NULL);
步骤3:修改probe回调函数
回调里只做发事件的操作,不要操作UI,也不要随便暂停pipeline:
GstPadProbeReturn buffer_out_cb(GstPad* pad, GstPadProbeInfo* info, gpointer user_data) { // 拿到MainWindow实例指针 MainWindow* mainWin = static_cast<MainWindow*>(user_data); // 发自定义事件到主线程 wxCommandEvent runEvt(wxSTREAM_RUNNING_EVT, mainWin->GetId()); wxQueueEvent(mainWin, runEvt.Clone()); // 如果只需要检测第一次采集到流就移除probe,就保留下面这行;如果要持续监控就返回GST_PAD_PROBE_OK return GST_PAD_PROBE_REMOVE; }
步骤4:实现UI更新函数
在主线程的事件处理函数里安全操作UI:
void MainWindow::OnStreamRunning(wxCommandEvent& evt) { // 这里可以安全执行所有UI操作 toolbar->SetToolNormalBitmap(10001, wxBitmap(wxT("icon-open-device.png"), wxBITMAP_TYPE_PNG)); // 也可以加状态栏提示、修改可用状态等 SetStatusText("流采集正常,可执行显示操作"); // 确认流正常后再执行显示相关逻辑即可 }
注意事项
- 你原有代码里回调中调用了
gst_element_set_state(pipe, GST_STATE_PAUSED)会把流暂停,如果你不需要暂停就删掉这行 - 如果需要持续监控流的存活状态,可以把回调返回值改成
GST_PAD_PROBE_OK,同时加超时逻辑判断流是否中断
内容的提问来源于stack exchange,提问作者Arnaud Tullio
相关产品推荐
相关产品推荐

