C++ 将帧从网络摄像机(RTSP)保存到mp4文件

C++ 将帧从网络摄像机(RTSP)保存到mp4文件,c++,ffmpeg,rtsp,libav,C++,Ffmpeg,Rtsp,Libav,我很困惑如何将视频流保存到mp4文件中。我正在使用ffmpeg。让我解释一下问题: 我通过RTSP(H.264流)连接到网络摄像头,并使用avformat_open_input()、avformat_find_stream_info()、av_read_play(),然后使用av_read_frame()获取帧 每次我用av_read_frame()获得一个帧时,我都将相应的AVPacket存储在一个循环缓冲区中 在我的应用程序的某些点中,选择了此循环缓冲区的一个范围。我发现一个关键帧用于开始

我很困惑如何将视频流保存到mp4文件中。我正在使用ffmpeg。让我解释一下问题:

  • 我通过RTSP(H.264流)连接到网络摄像头,并使用avformat_open_input()、avformat_find_stream_info()、av_read_play(),然后使用av_read_frame()获取帧
  • 每次我用av_read_frame()获得一个帧时,我都将相应的AVPacket存储在一个循环缓冲区中
  • 在我的应用程序的某些点中,选择了此循环缓冲区的一个范围。我发现一个关键帧用于开始
  • 一旦我有了一个从一个关键帧开始的AVPacket列表,我就编写了header、frames和tail,正如我在下面的代码中所描述的那样
  • 问题是,如果我尝试使用VLC、Windows Media Player或其他工具观看mp4视频,结果会出现瑕疵

    我还意识到,数据包的pts不是连续的,而dts是连续的。我知道B帧,但这是我的问题吗

    // Prepare the output
    AVFormatContext* oc = avformat_alloc_context();
    oc->oformat = av_guess_format(NULL, "video.mp4", NULL);
    
    // Must write header, packets, and trailing
    avio_open2(&oc->pb, "video.mp4", AVIO_FLAG_WRITE, NULL, NULL);
    
    // Write header
    AVStream* stream = avformat_new_stream(oc, (AVCodec*) context->streams[video_stream_index]->codec->codec);
    avcodec_copy_context(stream->codec, context->streams[video_stream_index]->codec);
    stream->sample_aspect_ratio = context->streams[video_stream_index]->codec->sample_aspect_ratio;
    avformat_write_header(oc, NULL);
    
    // FOR EACH FRAME...
    ... av_write_frame(oc, circular[k]); ...
    
    // Write trailer and close the file
    av_write_trailer(oc);
    avcodec_close(stream->codec);
    avio_close(oc->pb);
    avformat_free_context(oc);
    

    非常感谢您,

    首先:当您使用相机时,最好使用TCP上的RTP(TCP作为传输协议)。 要启用此功能,请执行以下操作:

    AVDictionary *ifmtdict;
    av_dict_set(&ifmtdict, "rtsp_transport", "tcp", 0);
    ...
    avformat_open_input (..., &ifmtdict);
    
    第二:
    数据包开始发送后,等待第一个关键帧,并从此时开始写入文件。

    您可以查看rtmpdump以供参考(甚至直接使用librtmp)-此外,我正在从许多IP摄像头写入许多视频流。很好:)对不起我的英语。