我正在嘗試使用 libav 解碼器實作視頻解碼應用程式。大多數 libav 示例都是這樣構建的(偽代碼):
while true {
auto packet = receive_packet_from_network();
avcodec_send_packet(packet);
auto frame = alloc_empty_frame();
int r = avcodec_receive_frame(&frame);
if (r==0) {
send_to_render(frame);
}
}
上面是偽代碼。無論如何,在這個傳統的回圈中,當我等待接收幀完成,然后等待渲染完成,然后等待從網路傳入解碼器緩沖區接收的下一個資料變空。沒有硬體解碼器管道,解碼性能低。我的應用程式中的其他限制 - 我確切地知道從網路接收到的一個資料包直接對應于一個解碼幀。
除此之外,我想更快地解決問題。為此,我想將此回圈拆分為 2 個不同的執行緒,如下所示:
//thread one
while true {
auto packet = receive_packet_from_network();
avcodec_send_packet(packet);
}
//thread two
while true {
auto frame = alloc_empty_frame();
int r = avcodec_receive_frame(&frame);
if (r==0) {
send_to_render(frame);
}
將回圈拆分為 2 個不同執行緒的目的是保持傳入的解碼器緩沖區始終提供足夠的資料,大部分是滿的。只有在這種情況下,我想我希望使用的硬體解碼器才會很樂意不斷地流水線作業。當然,我需要執行緒同步機制,為了簡單起見,這里沒有顯示。當然,當從 avcodec_send_packet() 或 avcodec_receive_frame() 回傳 EGAIN 時,我需要等待其他執行緒完成其作業來提供傳入緩沖區或獲取準備好的幀。那是另一個故事。
除此之外,這個執行緒解決方案不適用于我隨機分段錯誤。不幸的是,我找不到任何 libav 檔案明確說明這種方法是否可以接受,avcodec_send_packet() 和 avcodec_receive_frame() 呼叫執行緒安全與否?
那么,加載硬體解碼器管道的最佳方法是什么?對我來說,顯然任何 libav 示例中顯示的傳統輪詢周期都無效。
uj5u.com熱心網友回復:
不,libavcodec 中不允許這樣的執行緒。
但是,FFmpeg 和 libavcodec 確實支持執行緒和硬體流水線。但是,這要低得多,需要您作為用戶讓 FFmpeg/libavcodec 完成它的作業,而不用擔心它:
- 不要從不同的執行緒呼叫
send_packet()和;receive_frame() - 設定
AVCodecContext.thread_count執行緒; - 讓 FFmpeg 中的硬體包裝器在內部處理流水線,他們比你更清楚該做什么。如果您有興趣,我可以向專家詢問更多資訊,我不是 100% 了解這方面的知識,但可以將您推薦給了解的人。
- 如果
send_packet()回傳AVERROR(EAGAIN),receive_frame()請先呼叫 - 如果
receive_frame()回傳AVERROR(EAGAIN),請致電send_packet()下一步。
使用正確thread_count的 FFmpeg/libavcodec 將并行解碼多個幀并使用多個內核。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/531160.html
標籤:多线程ffmpeg库
上一篇:是否有可能在多核處理器上發生背景關系切換,還是僅在單核處理器上發生?
下一篇:如何映射一個陣列并洗掉對應的陣列
