• 修改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结构体里面增加一个判断包完整性的标志变量,修改源码后的接口调用如下:

    
        while (1) {
            AVPacket pkt;
    
            ret = av_read_frame(f->ctx, &pkt);
            if (pkt.nLostPackets) {
                // Do something.
            } else {
                // Do something
            }
        }
    
    

    下面将介绍修改FFMpeg源码的细节。

    修改FFMpeg源码(ffmpeg2.8.6)

    一、avformat.h里面增加int av_read_frame_aozhen(AVFormatContext *s, AVPacket *pkt)函数:

    并且在对应实现文件utils.c里面对其实现:

    二、avcodec.h里面的AVPacket结构体增加成员变量int nIsLostPackets:

    并且在avpacket.c里面的av_init_packets函数里面对其初始化:

    三、utils.c里面read_frame_internal函数增加临时变量int nIsLostPackets = 0,read_frame_internal函数调用ff_read_packet的后一句增加nIsLostPackets = cur_pkt.nIsLostPackets:

    并且在函数末尾将nIsLostPackets赋值给pkt->nIsLostPackets:

    四、在rtpdec.c的rtp_parse_queued_packet函数里面增加丢包判断的代码:

  • 相关阅读:
    查看文件方法、vim末行操作
    目录结构、文件管理命令
    计算机快捷键、常用命令、别名、
    Redis 使用与优化
    Redis-Sentinel
    Redis主从复制
    Redis持久化
    API的使用
    Redis安装和配置
    集群搭建(脑裂)
  • 原文地址:https://www.cnblogs.com/highway-9/p/5595101.html
Copyright © 2020-2023  润新知