FFmpeg 解碼 H.264 視頻出現(xiàn)花屏和馬賽克的解決辦法
四個可能的原因
- 發(fā)送數(shù)據(jù)包太大,超過了 FFmpeg 的默認最大值。
- 網(wǎng)絡(luò)情況較差時,因網(wǎng)絡(luò)狀況出現(xiàn)的丟包。
- 解碼出錯。
- 包亂序。
原因一的解決方法
一種方法是控制播放源的發(fā)送數(shù)據(jù)大小,但這極大浪費了當前的網(wǎng)絡(luò)帶寬,非優(yōu)選方案。
更好的做法是擴大接收端的接收緩沖區(qū),其修改方法為:
在 FFmpeg 的源碼中,找到 udp.c 文件并修改 UDP_MAX_PKT_SIZE 默認值。
這里將 UDP_MAX_PKT_SIZE × 10,將緩沖區(qū)擴大了10倍。
原因二的解決方法
排查方法:
- 設(shè)全局變量:在丟包時將全局變量置為不同的值,最后在使用的地方根據(jù)全局變量的值來判斷該幀是否完整,全局變量可在 FFmpeg 任意的頭文件中設(shè)置(比如 avcodec.h)。
- 修改rtpdec.c文件包含 missed %d package 的地方,這里出現(xiàn)丟包,需修改代碼,對幀序號作標記。
在接收端根據(jù)RTP包的SeqNumber來判斷是否丟包,如果丟包就標記一下。在mark為1或時間戳改變的時候,說明一幀結(jié)束了,此時如果標記為丟包了,就扔掉數(shù)據(jù),沒有丟包就給解碼器。如果丟包的幀為I幀,則不僅丟掉當前I幀,此I幀之后的P幀也要丟掉,也就是說在下一個I幀到來之前,所有過來的包都丟掉,然后開始判斷收到的RTP包是不是I幀。
判斷函數(shù):
static bool isH264iFrame(byte[] paket)
{
int RTPHeaderBytes = 0;
int fragment_type = paket[RTPHeaderBytes + 0] & 0x1F;
int nal_type = paket[RTPHeaderBytes + 1] & 0x1F;
int start_bit = paket[RTPHeaderBytes + 1] & 0x80;
if (((fragment_type == 28 || fragment_type == 29) && nal_type == 5 && start_bit == 128) ||
fragment_type == 5 || fragment_type == 7 || fragment_type == 8)
{
return true;
}
return false;
}
原因三的解決方法
排查方法:
- 設(shè)全局變量:在解碼出錯時將全局變量置為不同的值,最后在使用的地方根據(jù)全局變量的值來判斷該幀是否完整,全局變量可在 FFmpeg 任意的頭文件中設(shè)置(比如 avcodec.h)。
- 修改error_resilience.c文件 包含concealing %d DC, %d AC, %d MV errors in %c frame的地方。這里出現(xiàn)解包錯誤,需標記。
- 修改h264_cavlc.c文件中包含 Invalid level prefix處 這里出錯,需標記。
修改h264_cavlc.c文件中包含dquant out of range處,出錯,需標記。
修改h264_cavlc.c文件中包含corrupted macroblock處,出錯,需標記。
修改h264_cavlc.c文件中包含negative number of zero coeffs at處,出錯,需標記。
修改h264_cavlc.c文件中包含mb_type %d in %c slice too large at %d %d處,出錯,需標記。
修改h264_cavlc.c文件中包含cbp too large處,出錯,需標記。 - 修改error_resilience.c文件中包含Cannot use previous picture in error concealment處,出錯,需標記。
修改error_resilience.c文件中包含Cannot use next picture in error concealment處,出錯,需標記。 - 修改h264.c文件中包含out of range intra chroma pred mode at處,出錯,需標記。
修改h264.c文件中包含top block unavailable for requested intra mode at處,出錯,需標記。
修改h264.c文件中包含left block unavailable for requested intra mode at處,出錯,需標記。 - 修改h264_slice.c文件中包含error while decoding MB處,出錯,需標記。
- 修改svq3.c文件中包含error while decoding MB處,出錯,需標記。
當我們從網(wǎng)絡(luò)中接收到RTP包,去了包頭,拿到Payload數(shù)據(jù)之后一般就會送去解碼,但是如果直接送去解碼器解碼,很可能會出現(xiàn)花屏。這個問題我很早就遇到過,當時查閱過資料,發(fā)現(xiàn)送給H264解碼器的必須是一個NALU單元,或者是完整的一幀數(shù)據(jù)(包含H264 StartCode),也就是說我們拿到Payload數(shù)據(jù)之后,還要將分片的數(shù)據(jù)組成一個NALU或完整的一幀之后才送給解碼器。文章來源:http://www.zghlxwxcb.cn/news/detail-859026.html
原因四的解決方法
打印RTP包的SeqNumber看有沒有不連續(xù)或亂序的問題,如果是用UDP傳輸,則RTP包容易發(fā)生亂序,需要對包按順序進行重組再解碼。文章來源地址http://www.zghlxwxcb.cn/news/detail-859026.html
參考
- https://blog.csdn.net/zhoubotong2012/article/details/103002257
- https://blog.csdn.net/c_base_jin/article/details/106772949
- https://blog.csdn.net/sz76211822/article/details/87797475
- https://www.ebaina.com/articles/140000016765
到了這里,關(guān)于FFmpeg 解碼 H.264 視頻出現(xiàn)花屏和馬賽克的解決辦法的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!