2017-03-09 244 views
0

我正在嘗試編寫簡單的錄像機,基於gstreamer框架爲我自己的用ARM處理器和Wayland + Qt作爲窗口子系統的定製板。 我創建的類RecordBin與rec_start插槽和rec_stop公共方法:gstreamer-1.0通過GUI停止和啓動錄製流水線

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); 
} 

這是我在主窗口的播放插槽/停止按鈕點擊:

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類是工作在一個單獨的線程(它通過QThread實現),這樣glib mainloop上下文不會阻塞Qt主窗口。 我不能使用rec_stop方法作爲插槽,因爲rec_loop會阻止消息處理,並且在開始記錄時,不能通過信號停止。 但直接調用rec_stop是線程不安全的。

任何人都可以幫助我兩個問題: 1.我應該如何從另一個線程更改管道狀態? 2.通過將管道狀態更改爲NULL來停止記錄是否正確?可能我應該在公共汽車上發送EOS信號並處理它?

回答

0

gst_element_set_state()被標記爲MT安全,所以它可以從任何線程停止。我在將gst_element_set_state()設置爲NULL時遇到問題:管道末端的filesink未正確完成輸出文件(必須使用EOS並捕獲另一個確認filesink已獲得EOS的事件)。但NULL對於玩家來說工作正常。總的來說,我會擺脫glib mainloop。您可以使用gst_bus_set_sync_handler()來設置回調。在回調中,發出一個Qt信號給RecordBinRecordBin將生活在主Qt線程中的QObject。在其插槽中處理到達GstMessage*