最近咱們項目有一個需求就是解決客戶端播放RTSP視頻流花屏的問題,通常來講丟包就會引發花屏,致使客戶端花屏的因素又有不少,好比說:服務器
其中服務器到客戶端的丟包問題咱們已經解決了,那麼相機到服務器的丟包問題怎麼解決呢?這個問題解決不了的,能夠解決的問題就是即便相機到服務器丟包後,也讓客戶端知道,而後不解碼丟包的那一幀數據直到下一個關鍵幀的到來,這樣客戶端播放視頻就不會
花屏了,可是這樣作就會讓視頻播放卡頓一下(以50幀一個關鍵幀來算的話會卡頓2秒),可是卡頓總比花屏強吧,由於花屏後咱們的AI服務器就採集不到人臉了,可是FFMpeg並無對外提供接口標誌該AVPacket不完整,內部也不會將AVPacket丟棄,這樣服務端調用av_read_frame讀取的AVPacket時並不知道該包是否完整,一小段調用例子以下:函數
while (1) { AVPacket pkt; // 不知道pkt是否完整 ret = av_read_frame(f->ctx, &pkt); if (ret == AVERROR(EAGAIN)) { av_usleep(10000); continue; } if (ret < 0) { av_thread_message_queue_set_err_recv(f->in_thread_queue, ret); break; } }
FFMpeg不提供接口,那麼就只有修改FFMpeg源碼,瀏覽FFMpeg源碼一天後,對外的接口只須要在AVPacket結構體裏面增長一個判斷包完整性的標誌變量,修改源碼後的接口調用以下:3d
while (1) { AVPacket pkt; ret = av_read_frame(f->ctx, &pkt); if (pkt.nLostPackets) { // Do something. } else { // Do something } }
下面將介紹修改FFMpeg源碼的細節。code
1、avformat.h裏面增長int av_read_frame_aozhen(AVFormatContext s, AVPacket pkt)函數:
而且在對應實現文件utils.c裏面對其實現:
orm
2、avcodec.h裏面的AVPacket結構體增長成員變量int nIsLostPackets:
而且在avpacket.c裏面的av_init_packets函數裏面對其初始化:
視頻
3、utils.c裏面read_frame_internal函數增長臨時變量int nIsLostPackets = 0,read_frame_internal函數調用ff_read_packet的後一句增長nIsLostPackets = cur_pkt.nIsLostPackets:
而且在函數末尾將nIsLostPackets賦值給pkt->nIsLostPackets:
blog
4、在rtpdec.c的rtp_parse_queued_packet函數裏面增長丟包判斷的代碼:
接口