工作小记 ffmpeg avcodec_receive_frame 缓存问题

最近的流媒体项目中,在拉车辆流的过程中,发现调用ffmpeg avcodec_send_packetavcodec_receive_frame 时总是不能做到送入1包,立刻吐出对应pts的一帧,总是有缓存2-3帧的问题。对于普通的播放器已经足够,但是平行驾驶要求的极低延时就无法做到了。因为传输的h264流完全是只有IP帧,并没有依赖后向的B帧。所以开始调查问题解决办法。
1 首先尝试一些低延时参数,无效

AVDictionary *avdic=NULL;
av_dict_set(&avdic, "rtsp_transport", "tcp", 1);
av_dict_set(&avdic, "muxdelay", "0", 0);
av_dict_set(&avdic, "fflags", "nobuffer", 0);
av_dict_set(&avdic, "tune", "zerolatency", 0);
av_dict_set(&avdic, "max_delay", "0", 0);
av_dict_set(&avdic, "preset", "superfast", 0);
av_dict_set(&avdic, "packet-buffering", "0", 0);

2 查看官网发现有送入flush包的说法,用于刷新解码器,但是只是用于seek操作
https://ffmpeg.org/doxygen/4.0/group__lavc__encdec.html
3 开始dump ffmepg和webrtc两端的流,终于发现端倪
dump类工具

#include 

class H264Dump
{
public:
    //static H264Dump &Instance();
    H264Dump();
    ~H264Dump();

    //void inputFrame(const H264Frame::Ptr &frame);
    void inputPkt(const char* data, int size);
    static int i;
    std::ofstream out;
    // std::mutex frame_list_mutex;
    // std::list frame_list;
};

int H264Dump::i = 0;
H264Dump::H264Dump()
{
    std::string _ = "player_11_5_" + std::to_string(++H264Dump::i) + ".h264";
    out = std::ofstream( _ , std::ios_base::out | std::ios::trunc | std::ios::binary);
}
H264Dump::~H264Dump()
{
    out.close();
}

void H264Dump::inputPkt(const char* data, int size)
{
    out.write(data, size);
    out.flush();
}

_ffmpeg_dump_h264.inputPkt((char*)packet->data, packet->size);

相同的文件,webrtc在收端,接到的流和原文件有一些小小的差异。在每个I帧(5)pps帧(8)之前,即**sps帧(7)**有一些不同,影响到了解码器能否立刻输出的情况!

H264码流中SPS PPS详解
vui参数的提问
H264裸流分析中,能获取哪些信息?
BSAnalyzer工具分析dump下的流
工作小记 ffmpeg avcodec_receive_frame 缓存问题_第1张图片
可以看到主要的不同就是在于num_reorder_framesmax_dec_frame_buffering的设置,webrtc是01,而我们的是22对于IPPP这种时不要缓存或者重排的,修改编码器后,果然解决了。
能正常拉到的流不一定就没问题,要仔细分析sps,pps等参数!

framerate=(time_scale/num_unit_in_tick)/2;
(pic_width_in_mbs_minus1+1 )*16 = 宽
(pic_height_in_map_units_minus1+1)*16 = 高

你可能感兴趣的:(工作杂记,ffmpeg,缓存)