Qt渲染視頻常見問題(視頻渲染窗口上子窗口設置透明出現陰影問題、主窗口縮放導致視頻渲染窗口部分出現視頻閃爍問題)
Qt渲染視頻常見問題(視頻渲染窗口上子窗口設置透明出現陰影問題、主窗口縮放導致視頻渲染窗口部分出現視頻閃爍問題)
開發環境
Qt5.9.6+VS2015
1.視頻渲染窗口上子窗口設置透明出現陰影問題
平時為了方便代碼管理,一般窗口上設置窗口或者控件,都會設置Parent(setParent),這樣對主窗口進行某種操作,不需要用代碼去管理其他窗口。
但是在視頻渲染窗口上設置子窗口或者子控件,哪怕將子窗口或者子控件設置透明無邊框,還是會出現一個陰影背景。
陰影問題出現的效果圖:
出現的原因:由于視頻窗口背景顏色一般情況下都是灰色陰影背景,當子窗口和子控件繼承視頻窗口時,會默認使用視頻窗口的背景顏色,所以導致上述問題出現。
Qt有三種窗口顯示方式:Qt::Widget,Qt::Dialog,Qt::Windows。
其中Widget強制使用父窗體背景。
以下提供解決方法有三種。
解決辦法一:
先設置無邊框和透明化。
MediaPlayer.setWindowFlags(Qt::FramelessWindowHint | Qt::SubWindow);
MediaPlayer.setAttribute(Qt::WA_TranslucentBackground, true);
然后重載MediaPlayer中paintEvent方法。
void MediaPlayer::paintEvent(QPaintEvent *e)
{QPainter painter(this);painter.fillRect(this->rect(), m_color);
}
這種解決辦法可以解決問題,但是使用不方便。
解決方法二:
使用Dialog的顯示方法,使用于窗口和控件。
MediaPlayer.setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);
MediaPlayer.setAttribute(Qt::WA_TranslucentBackground, true);
解決辦法三:
窗口之間不僅只有父子關系,還有從屬關系,因此窗口疊加還能通過owner的方式實現。
具體實現可以查看win32的setwindowlong,可以去msdn查看對應方法。
陰影問題解決后的效果圖:
2.主窗口縮放導致視頻渲染窗口部分出現視頻閃爍問題
這種問題主要出現在調用第三方庫渲染視頻的時候縮放窗口就會出現視頻閃爍問題。
產生閃爍的主要原因是由于Qt自身的渲染引擎和第三方庫渲染沖突造成的。
因此解決辦法可以采用屏蔽Qt自身的渲染。
屏蔽方法有兩種:
第一種方法,重載QPaintEngine方法。
首先在視頻渲染窗口構造函數中添加。
setAttribute(Qt::WA_PaintOnScreen,true);
然后重載QPaintEngine接口,直接返回即可。
QPaintEngine *MediaPlayer::paintEngine()
{return 0;
}
第二種方法,直接設置窗口關閉自動刷新。
MediaPlayer.setUpdatesEnabled(false);
以上的辦法可以從根本上解決視頻閃爍問題,但是在屏蔽Qt自身渲染的時候,一定要使用得當,畢竟Qt窗口初始化的時候,是需要調用Updates的,不然窗口會一片空白的哦
下面還有一種方法,改變窗口縮放樣式。
windows下有一種窗口縮放樣式:
因此也可以采用這種縮放模式,完美的避免了窗口閃爍的問題。
實現的方式有兩種:
第一種是調用WinAPI實現。
第二種是Qt調用橡皮筋類模擬陰影窗口實現。
WinAPI實現代碼部分:
https://download.csdn.net/download/qq_36651243/11247196
Qt調用橡皮筋類模擬陰影窗口實現效果圖:
解決以上兩種問題還可以這樣做:(參考FFmpeg緩存機制)
自己編寫緩存區管理視頻流數據,通過管理視頻流緩存區,通過Qt本身QPainter事件繪制視頻緩存區讀到的視頻流數據
這也是小編目前使用的解決辦法
最后還有一種方法,叫雙緩沖技術,有興趣的可以去網上了解下。