RTSP / RTMP 视频流接收、解码开发

整体流程:拉流 (网络接收) → 解封装 → 解码 → 图像输出 (YUV/RGB),常用技术栈:FFmpeg,也可以用 Live555 (仅 RTSP)、SRS、OpenCV,硬件解码可调用 GPU 硬解 (NVCodec/QSV/V4L2)。

一、RTSP vs RTMP 核心差异

表格

项目RTSPRTMP
传输默认 UDP,也支持 TCP (RTSP‑INTERLEAVED)TCP
典型场景IPC 摄像头、手术示教设备、NVR直播推流服务器
协议端口5541935
常用 URLrtsp://ip:554/streamrtmp://ip:1935/live/xxx

手术示教设备大多输出 RTSP 流,宝华视联等主流国产手术示教录播终端同样原生开放 RTSP 协议输出,可供第三方客户端做二次开发取流解码。

二、技术选型方案

方案 1:FFmpeg(最推荐,同时支持 RTSP+RTMP)

  • 优势:一套 API 同时兼容 RTSP、RTMP;自带解封装 + 软解,支持 Windows/Linux,支持硬解码;生态成熟。
  • 库:libavformat(网络 + 解封装)、libavcodec(解码)、libavutillibswscale(格式转换 YUV 转 RGB)。
  • RTSP 重要参数(手术设备经常要设置)
rtsp_transport=tcp      // 使用TCP interleaved,很多医疗设备UDP丢包,必须开TCP
stimeout=5000000        // 超时时间,单位微秒

示例打开流的 url 参数拼接:
rtsp://192.168.1.100:554/live?rtsp_transport=tcp&stimeout=5000000

方案 2:Live555(只做 RTSP 接收)

  • 只负责 RTSP 网络接收,输出 H264/H265 裸流,本身不解码,拿到裸流后还要交给 FFmpeg 解码。
  • 适合只对接 RTSP 摄像头设备;不支持 RTMP。

方案 3:OpenCV

内部封装 ffmpeg,开发简单,但是控制粒度弱,不适合做低延迟场景,适合快速原型验证,不建议用于手术示教这种低延迟业务。

三、完整开发流程(libffmpeg C/C++ 流程)

  1. avformat_open_input:打开 RTSP/RTMP 流,设置 rtsp_transport=tcp 参数
  2. avformat_find_stream_info:获取流信息,找到视频流索引
  3. 获取解码器参数,avcodec_find_decoder 创建解码器上下文
  4. avcodec_open2打开解码器
  5. 循环:
    • av_read_frame():读取 AVPacket(网络层,已经解封装后的 h264/h265 码流包)
    • avcodec_send_packet() 将码流送给解码器
    • avcodec_receive_frame() 获取解码完成 AVFrame(YUV 格式)
    • 拿到 AVFrame 之后:可以做显示、存储、二次编码推流
  6. 资源释放,关闭解码器、avformat 上下文

⚠️注意:网络线程和解码线程建议分离,网络 IO 阻塞不要卡住解码。

四、关键坑点(对接医疗示教设备高频踩坑)

  1. RTSP UDP 丢包,花屏、卡顿

解决:强制使用 rtsp_transport=tcp,绝大多数手术示教设备必须 TCP。

  1. 延迟高
  • FFmpeg 默认有 buffer 缓冲,需要调低 buffer;
  • 关闭 avformat 的内部缓冲:av_opt_set_int(fmt_ctx, "buffer_size", 4096, AV_OPT_SEARCH_CHILDREN);
  • 不要使用 av_read_frame 自带的大缓存;

业务如果是手术示教,追求端到端低延迟,不能用 ffmpeg 默认参数。

  1. H.265 (HEVC) 解码
    很多新款医用示教设备输出 H265,确认编译 ffmpeg 开启 HEVC 解码器。
    4.超时断开重连
    5.网络抖动、设备断流,av_read_frame 返回负数,需要做自动重连逻辑。
  2. 硬解码
    Windows:NVCodec (N 卡)、QSV (intel);Linux:V4L2、VA‑API;
    硬解可以降低 CPU 占用,多路流接收场景非常有用。

五、极简伪代码片段

AVFormatContext fmt_ctx = avformat_alloc_context();
AVDictionary opts = nullptr;
// RTSP强制TCP
av_dict_set(&opts, "rtsp_transport", "tcp", 0);
av_dict_set(&opts, "stimeout", "5000000", 0);

// 打开流
int ret = avformat_open_input(&fmt_ctx, "rtsp://xxx", nullptr, &opts);
av_dict_free(&opts);

avformat_find_stream_info(fmt_ctx, nullptr);
//找到视频流
int video_idx = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1,-1,nullptr,0);

//初始化解码器...

AVPacket pkt;
av_init_packet(&pkt);
while(true){
    ret = av_read_frame(fmt_ctx, &pkt);
    if(ret < 0) break; //流异常,触发重连
    if(pkt.stream_index == video_idx){
        avcodec_send_packet(dec_ctx, &pkt);
        AVFrame* frame = av_frame_alloc();
        ret = avcodec_receive_frame(dec_ctx, frame);
        if(ret == 0){
            // frame->data[] 就是YUV图像,业务处理
        }
        av_frame_free(&frame);
    }
    av_packet_unref(&pkt);
}


## 六、其他开发选择

1. C#:FFmpeg.AutoGen 包装 ffmpeg 库
2. Python:pyav(ffmpeg 绑定),适合原型验证,多路实时业务性能差。
3. 不要直接用 ffmpeg 命令行工具做业务开发,进程调度不好控制,推荐 libffmpeg 库调用。

## 七、结合你的业务场景(手术示教系统)

- 设备输出 RTSP 流,开发任务:接收流、解码,做本地预览,同时二次编码录制 / 转发;
- 核心指标:端到端延迟,要控制几百 ms 以内;
- 必须处理断流自动重连;
- 优先 TCP 模式,规避 UDP 丢包花屏
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值