柴_笔记 2024-07-18 18:08 采纳率: 20%
浏览 71
已结题

ffmpeg库使用过程中遇到的问题

调用av_read_frame时,

报错 [rtsp @ 000001c7b34f0240] max delay reached. need to consume packet
[rtsp @ 000001c7b34f0240] RTP: missed 116 packets,但是返回值是0,

这种情况下画面会花屏,

确认是网络波动引起的,可以丢包,但是不能花屏

DTS的值和PTS的值是相同的,

用VLC查看同一个视频流地址,是没有花屏的现象的

  • 写回答

22条回答 默认 最新

  • 阿里嘎多学长 2024-07-18 18:13
    关注

    以下内容由AIGC及阿里嘎多学长共同生成、有用望采纳:


    在使用 FFmpeg 库处理视频流时遇到的问题确实比较复杂,以下是一些可能的解决方案和建议:

    1. 解决 av_read_frame 调用时的错误提示

    • 错误原因max delay reached 错误通常是因为解码器需要更多的数据来解码当前帧,但数据没有及时到达。这可能是由于网络延迟或丢包造成的。
    • 解决方案
      • 增加缓冲区:尝试增加 FFmpeg 的缓冲区大小,可以使用 avcodec_parameters_to_context 函数设置解码器的参数,增加 rc_buffer_size 值。
      • 调整网络参数:如果是网络问题,尝试优化网络连接或使用更稳定的网络环境。

    2. 避免画面花屏

    • 花屏原因:花屏通常是由于解码器无法正确解码帧,或者解码后的数据在显示时出现问题。
    • 解决方案
      • 检查解码器:确保使用的解码器是最新的,并且支持当前的视频格式。
      • 同步时间戳:确保解码后的视频帧的时间戳(DTS 和 PTS)正确同步。可以使用 av_frame_set_best_effort_timestamp 函数调整时间戳。

    3. 处理网络波动和丢包

    • 丢包原因:网络波动和丢包是常见的问题,特别是在实时视频流中。
    • 解决方案
      • 使用更稳定的协议:考虑使用更稳定的协议,如 TCP 而不是 UDP。
      • 增加重试机制:在代码中增加重试机制,当检测到丢包时,尝试重新请求丢失的数据。

    4. 调整 DTS 和 PTS 值

    • 时间戳问题:DTS 和 PTS 值相同可能会导致解码器无法正确处理视频帧。
    • 解决方案
      • 调整时间戳:在解码过程中,确保 DTS 和 PTS 值正确设置。可以使用 av_frame_set_ptsav_frame_set_pkt_dts 函数设置时间戳。

    5. 与 VLC 播放效果一致

    • VLC 播放机制:VLC 可能在内部使用了不同的解码器或处理机制,导致播放效果不同。
    • 解决方案
      • 分析 VLC 代码:尝试分析 VLC 的源代码,了解其处理视频流的机制。
      • 调整 FFmpeg 参数:根据 VLC 的处理方式,调整 FFmpeg 的参数,如解码器类型、缓冲区大小等。

    示例代码

    以下是一些示例代码,展示如何调整 FFmpeg 的参数和处理时间戳:

    // 设置解码器参数
    AVCodecParameters *codecpar = avcodec_parameters_alloc();
    codecpar->rc_buffer_size = 1024 * 1024; // 增加缓冲区大小
    
    // 打开解码器
    AVCodec *codec = avcodec_find_decoder(codecpar->codec_id);
    AVCodecContext *codec_ctx = avcodec_alloc_context3(codec);
    if (avcodec_open2(codec_ctx, codec, NULL) < 0) {
        fprintf(stderr, "Could not open codec.\n");
        exit(1);
    }
    
    // 读取帧
    AVPacket pkt;
    AVFrame *frame = av_frame_alloc();
    while (av_read_frame(ic, &pkt) >= 0) {
        // 解码帧
        if (avcodec_send_packet(codec_ctx, &pkt) < 0) {
            fprintf(stderr, "Failed to send packet to decoder.\n");
            exit(1);
        }
        if (avcodec_receive_frame(codec_ctx, frame) < 0) {
            fprintf(stderr, "Failed to receive frame from decoder.\n");
            exit(1);
        }
    
        // 调整时间戳
        av_frame_set_best_effort_timestamp(frame, pkt.pts);
        av_frame_set_pkt_dts(frame, pkt.dts);
    
        // 显示帧
        // ...
    }
    
    // 释放资源
    av_frame_free(&frame);
    avcodec_free_context(&codec_ctx);
    avcodec_parameters_free(&codecpar);
    

    这些只是基本的示例,具体实现可能需要根据你的应用场景和需求进行调整。希望这些建议能帮助你解决问题!

    评论 编辑记录

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月21日
  • 赞助了问题酬金15元 7月18日
  • 创建了问题 7月18日

悬赏问题

  • ¥15 is not in the mmseg::model registry。报错,模型注册表找不到自定义模块。
  • ¥15 安装quartus II18.1时弹出此error,怎么解决?
  • ¥15 keil官网下载psn序列号在哪
  • ¥15 想用adb命令做一个通话软件,播放录音
  • ¥30 Pytorch深度学习服务器跑不通问题解决?
  • ¥15 部分客户订单定位有误的问题
  • ¥15 如何在maya程序中利用python编写领子和褶裥的模型的方法
  • ¥15 Bug traq 数据包 大概什么价
  • ¥15 在anaconda上pytorch和paddle paddle下载报错
  • ¥25 自动填写QQ腾讯文档收集表