正确打开rtsp流需在avformat_open_input前设置av_dict_set:指定"rtsp_transport"为"tcp"防丢包,设"stimeout"(如10000000微秒=10秒)避免超时失败,url含鉴权信息,且不可省略avformat_find_stream_info解析sdp。

如何用 avformat_open_input 正确打开 RTSP 流
RTSP 流不是普通文件,avformat_open_input 默认超时极短(通常 5–10 秒),容易直接失败并返回 -110 (ETIMEDOUT) 或 -5 (EIO)。必须提前设置格式上下文的选项。
- 在调用
avformat_open_input前,用av_dict_set设置"rtsp_transport"(推荐"tcp",避免 UDP 丢包导致卡死) - 务必设置
"stimeout"(单位微秒),例如"10000000"表示 10 秒,否则默认可能仅 2 秒 - 若设备要求鉴权,需拼接带用户名密码的 URL:
"rtsp://user:pass@192.168.1.100:554/stream";FFmpeg 会自动处理 Basic Auth - 不要省略
avformat_find_stream_info—— RTSP 的 SDP 描述需解析才能拿到视频流索引,跳过会导致后续avcodec_parameters_to_context失败
为什么 av_read_frame 读不到关键帧就解码失败
RTSP 流起始往往是一段非关键帧(P/B 帧),直接送入解码器会返回 AVERROR_INVALIDDATA 或输出全黑/乱码图。不能靠“读一帧就解”来截图。
- 必须循环调用
av_read_frame,检查packet.flags & AV_PKT_FLAG_KEY,只把关键帧(I 帧)送入解码器 - 注意:有些 IPC 摄像头首帧就是 I 帧,但多数设备前几秒是 P 帧,建议至少读 50–100 包再放弃(避免无限等待)
- 解码后,
av_frame_get_buffer和sws_scale转换前,先确认frame->width和frame->height非零 —— 否则说明解码未成功或帧数据为空
保存为 JPEG 时 avcodec_encode_video2 已废弃,该用什么
avcodec_encode_video2 在 FFmpeg 4.0+ 已移除,强行链接会报错 undefined reference。当前标准流程是用编码器的 send_frame / receive_packet 模型。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 初始化 JPEG 编码器时,用
avcodec_find_encoder(AV_CODEC_ID_MJPEG),而非硬编码CODEC_ID_MJPEG(已废弃) - 编码前必须调用
avcodec_open2,且设置codec_ctx->pix_fmt = AV_PIX_FMT_YUVJ420P(JPEG 标准像素格式,YUV420P会导致色偏) - 编码后从
avcodec_receive_packet取出数据,直接写入文件即可 —— 不需要封装成 MP4/AVI,JPEG 是裸流格式 - 别忘了
av_packet_unref清理 packet,否则内存泄漏在循环中会迅速累积
常见崩溃点:没检查指针和返回值就直接访问
RTSP 场景下,任意一步失败都可能导致空指针:URL 错误、网络中断、设备离线、编解码器不支持……所有 FFmpeg API 调用后都必须检查返回值。
-
avformat_open_input返回负值 → 直接退出,打印av_err2str(ret) -
avcodec_find_decoder返回nullptr→ 说明没有注册对应解码器(确认是否 link 了libavcodec且调用过avcodec_register_all(),FFmpeg 4.0+ 已自动注册,但旧版本需手动) -
av_frame_alloc()可能失败 → 返回nullptr,后续av_frame_unref会崩溃 -
sws_getContext返回nullptr→ 常见于源/目标尺寸为 0 或 pix_fmt 不支持,需前置校验
实际部署时,RTSP 连接不稳定比代码逻辑错误更常见 —— 截图失败十次里九次是网络或设备问题,而不是少调了一个 av_init_packet。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










