修改FFMpeg源碼—捕獲丟包

概述

最近咱們項目有一個需求就是解決客戶端播放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

修改FFMpeg源碼(ffmpeg2.8.6)

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函數裏面增長丟包判斷的代碼:
接口

相關文章
相關標籤/搜索