gstreamer-1.0 通过 GUI 停止和启动记录管道
gstreamer-1.0 stopping and starting recording pipeline via GUI
我正在尝试编写基于 gstreamer 框架的简单录像机,用于我自己的自定义板,使用 ARM 处理器和 Wayland+Qt 作为 window 子系统。
我用 rec_start 槽和 rec_stop public 方法创建了 class RecordBin:
void RecordBin::rec_start ()
{
/* Set pipeline to the PLAYING state */
gst_element_set_state (record_pipeline, GST_STATE_PLAYING);
g_print ("setting playing state\n");
/* Start main loop context */
g_main_loop_run (rec_loop);
}
void RecordBin::rec_stop ()
{
/* Set pipeline to the NULL state */
change_ret = gst_element_set_state (record_pipeline, GST_STATE_NULL);
/* Quit from main loop context */
g_main_loop_quit (rec_loop);
}
这是我在 mainwindow 中的插槽,用于 play/stop 按钮点击:
void MainWindow::on_recordButton_clicked ()
{
if (!is_recording) {
if (window_is_opened == false) {
cout << "start recording" << endl;
/* Start recording */
window_is_opened = true;
emit start_recording ();
} else {
cout << "playing window already opened" << endl;
}
} else {
cout << "recording reset" << endl;
/* Stop recording */
record_bin->rec_stop ();
window_is_opened = false;
}
}
RecordBin class 在一个单独的线程中工作(它是通过 QThread 实现的),因此 glib mainloop 上下文不会阻塞 Qt main window。
我不能将 rec_stop 方法用作插槽,因为 rec_loop 会阻止消息处理,并且当录制开始时,无法通过信号停止。
但是直接调用 rec_stop 是线程不安全的。
谁能帮我解决两个问题:
1. 我应该如何从另一个线程更改管道状态?
2.通过将管道状态更改为NULL来停止记录是否正确?可能我应该在总线上发送 EOS 信号并处理它?
gst_element_set_state()
被标记为 MT 安全,因此它可以从任何线程停止。我在将 gst_element_set_state()
设置为 NULL 时遇到问题:管道末尾的 filesink
没有正确完成输出文件(必须使用 EOS 并捕获另一个确认 filesink
有那个 EOS)。但是 NULL 对玩家来说效果很好。
总的来说,我会摆脱油嘴滑舌的主循环。您可以使用 gst_bus_set_sync_handler()
设置回调。在回调中,向 RecordBin
发出 Qt 信号。 RecordBin
将是一个存在于主 Qt 线程中的 QObject
。在其插槽中处理到达的 GstMessage*
。
我正在尝试编写基于 gstreamer 框架的简单录像机,用于我自己的自定义板,使用 ARM 处理器和 Wayland+Qt 作为 window 子系统。 我用 rec_start 槽和 rec_stop public 方法创建了 class RecordBin:
void RecordBin::rec_start ()
{
/* Set pipeline to the PLAYING state */
gst_element_set_state (record_pipeline, GST_STATE_PLAYING);
g_print ("setting playing state\n");
/* Start main loop context */
g_main_loop_run (rec_loop);
}
void RecordBin::rec_stop ()
{
/* Set pipeline to the NULL state */
change_ret = gst_element_set_state (record_pipeline, GST_STATE_NULL);
/* Quit from main loop context */
g_main_loop_quit (rec_loop);
}
这是我在 mainwindow 中的插槽,用于 play/stop 按钮点击:
void MainWindow::on_recordButton_clicked ()
{
if (!is_recording) {
if (window_is_opened == false) {
cout << "start recording" << endl;
/* Start recording */
window_is_opened = true;
emit start_recording ();
} else {
cout << "playing window already opened" << endl;
}
} else {
cout << "recording reset" << endl;
/* Stop recording */
record_bin->rec_stop ();
window_is_opened = false;
}
}
RecordBin class 在一个单独的线程中工作(它是通过 QThread 实现的),因此 glib mainloop 上下文不会阻塞 Qt main window。 我不能将 rec_stop 方法用作插槽,因为 rec_loop 会阻止消息处理,并且当录制开始时,无法通过信号停止。 但是直接调用 rec_stop 是线程不安全的。
谁能帮我解决两个问题: 1. 我应该如何从另一个线程更改管道状态? 2.通过将管道状态更改为NULL来停止记录是否正确?可能我应该在总线上发送 EOS 信号并处理它?
gst_element_set_state()
被标记为 MT 安全,因此它可以从任何线程停止。我在将 gst_element_set_state()
设置为 NULL 时遇到问题:管道末尾的 filesink
没有正确完成输出文件(必须使用 EOS 并捕获另一个确认 filesink
有那个 EOS)。但是 NULL 对玩家来说效果很好。
总的来说,我会摆脱油嘴滑舌的主循环。您可以使用 gst_bus_set_sync_handler()
设置回调。在回调中,向 RecordBin
发出 Qt 信号。 RecordBin
将是一个存在于主 Qt 线程中的 QObject
。在其插槽中处理到达的 GstMessage*
。