live555基础入门
live555基础入门
一、live555简介
Live555 是一个为流媒体提供解决方案的跨平台 C++ 开源项目,它实现了对标准流媒体传输协议如 RTP/RTCP、RTSP、SIP 等的支持。
Live555 实现了对多种音视频编码格式的音视频数据的流化、接收和处理等支持,包括 MPEG、H.263+、DV、JPEG 视频和多种音频编码。同时由于良好的设计,Live555 非常容易扩展对其他格式的支持。
目前,Live555 已经被用于多款播放器的流媒体播放功能的实现,如 VLC (VideoLan)、MPlayer。
该项目的源代码包括四个基本的库,各种测试代码以及 LIVE555 Media Server。四个基本的库分别是:
- UsageEnvironment & TaskScheduler:任务调度和环境管理
- groupsock:网络 socket 封装
- liveMedia:媒体处理核心
- BasicUsageEnvironment:基础使用环境实现
二、live555分层介绍
Live555 的架构设计非常清晰,采用分层设计思想,各层职责分明。从底层到顶层依次为:
2.1 基础任务调度层 (UsageEnvironment & TaskScheduler)
这是 live555 的心脏,负责解决"什么时候该干什么事"的问题。
📌 TaskScheduler(任务调度器)
它是单线程模型的核心。通过 select 机制监听 socket 状态,并管理延时任务和事件处理器。
📌 UsageEnvironment(使用环境)
它是所有组件运行的"上下文"。它是一个抽象基类,包含了错误处理、内存管理以及对调度器的引用。
👉 分层意义:这一层屏蔽了操作系统底层的差异,确保了整个库在单线程下也能高效地处理并发流,避免了多线程死锁和频繁上下文切换的开销。
2.2 核心数据抽象层 (Medium, Source & Sink)
📌 Medium(媒介):所有流媒体组件的基类。
📌 FramedSource(数据源):数据的产生者(例如:读取文件、采集摄像头)。它的职责是产生出一帧帧的数据。
📌 FramedSink(数据接收器):数据的消耗者(例如:发送 RTP 包到网络、保存到文件、将数据给用户层)。
📌 数据流向:这里的逻辑是由 Sink 向 Source 请求数据。Sink 会调用 getNextFrame(),Source 完成数据读取后通过回调通知 Sink。
👉 分层意义:通过 Source 和 Sink 的递归嵌套(比如 FileSource -> H264Framer -> RTPSink),实现了类似"流水线"的处理逻辑,每一层只负责一个微小的任务(如加头、打包)。
2.3 网络协议实现层 (RTCP, RTP & RTSP)
这一层是在 Source/Sink 的基础上,实现了具体的流媒体协议标准。
📌 RTP/RTCP 层
负责将编码后的数据(如 H.264)封装成 RTP 数据包,并处理 RTCP 质量反馈。对应的类如 RTPSink 和 RTCPSession。
📌 RTSP 层
负责控制信令(DESCRIBE, SETUP, PLAY, PAUSE)。RTSPServer 监听 554 端口,管理客户端的状态机会话(RTSPServer::RTSPClientSession)。
👉 分层意义:协议层与编解码层分离。如果你要支持一种新的编码格式(比如 H.265),你只需要实现对应的 RTPSink 和 Source,而不需要改动 RTSP 的信令逻辑。
2.4 媒体服务器/客户端应用层 (Server & Client)
这是最顶层,直接面向开发者。
📌 ServerMediaSession
代表一个"流",比如一个直播频道或一个 VOD 文件。它管理着多个 ServerMediaSubsession(通常一个负责音频,一个负责视频)。
👉 分层意义:开发者通常只需要操作这一层。例如,通过:
sms->addSubsession(H264VideoStorageServerMediaSubsession::createNew(...))
就能快速搭建一个支持 H.264 的 RTSP 服务器。
三、live555中事件类型介绍
在 Live555 的异步事件驱动模型中,TaskScheduler 负责管理所有事件。理解这些事件类型是掌握 Live555 运行机制的关键。从代码实现和逻辑分类来看,事件主要分为以下三类:
3.1 Socket 事件 (Socket Handlers)
这是最基础的事件,对应于网络 I/O。Live555 使用 select()(在某些平台上也可以配置为 poll)来监控 Socket 状态。
- 读事件 (Read Handler):当 Socket 缓冲区有数据到达时触发。例如,RTSP 服务器收到客户端的请求,或者 RTP 客户端收到视频数据包。
- 写事件 (Write Handler):当 Socket 缓冲区可写时触发。通常用于异步发送较大的数据块,防止阻塞主线程。
3.2 延时事件 (Delayed Events / Alarm Handlers)
这类事件用于处理"在未来的某个时间点执行"的任务。
触发机制:Live555 维护了一个由 DelayQueue(延迟队列)管理的链表。每次执行完一次 Socket 事件检查后,调度器会检查队列中是否有任务到期。
典型场景:
- RTCP 发送:根据协议规定,RTCP 包需要每隔一段时间发送一次。
- 超时处理:例如 RTSP 会话在一定时间内没有心跳请求,则触发超时关断。
- 帧率控制:如果读取文件的速度快于播放速度,会设置一个延时任务,等下一帧的时间到了再读取。
3.3 外部事件 (Event Triggers)
这是 Live555 提供的一种线程安全(在有限范围内)的通知机制,主要用于解决"非 Live555 线程"触发"Live555 任务调度线程"执行操作的需求。
触发机制:通过 TaskScheduler::triggerEvent() 函数触发。Live555 内部使用一个位掩码(bitmask)来记录被触发的事件 ID。
典型场景:
- 多线程集成:如果你有一个单独的编码线程,当编码出一帧数据后,需要通知 Live555 线程:“数据准备好了,快来取”。由于 Live555 本身是单线程设计的,直接操作 Live555 的对象是不安全的,此时必须通过
triggerEvent来唤醒调度器。
特点:外部事件的优先级通常高于 Socket 事件。
3.4 事件处理的优先级顺序
在 BasicTaskScheduler::doEventLoop() 的每一次循环中,处理顺序大致如下:
- 检查外部事件:如果有通过
triggerEvent触发的标识,优先执行其对应的处理函数。 - Socket 轮询:执行
select(),查看哪些 Socket 有读写事件。如果发现有事件,立即执行对应的 Handler。 - 处理延时任务:检查
DelayQueue。如果有到期的任务,执行它;如果没有,计算出距离下一个任务到期还有多久,以便在下一次select()时设置合适的超时时间。
⚠️ 注意事项
在开发 Live555 应用时,千万不要在任何事件的回调函数中调用阻塞函数(如 sleep() 或同步读取大文件)。因为 Live555 是单线程运行的,一旦一个事件处理函数被阻塞,整个服务器的 RTSP 信令和所有流的传输都会卡死。
四、live555中常用类介绍
4.1 BasicUsageEnvironment 和 UsageEnvironment
BasicUsageEnvironment 和 UsageEnvironment 中的类都是用于整个系统的基础功能类。
UsageEnvironment 代表了整个系统运行的环境,它提供了错误记录和错误报告的功能,无论哪一个类要输出错误,就需要保存 UsageEnvironment 的指针。
TaskScheduler 则提供了任务调度功能。整个程序的运行发动机就是它,它调度任务,执行任务(任务就是一个函数)。TaskScheduler 由于在全局中只有一个,所以保存在了 UsageEnvironment 中。而所有的类又都保存了 UsageEnvironment 的指针,所以谁想把自己的任务加入调度中,那是很容易的。
结论:整个 live555(服务端)只有一个线程。
4.2 Groupsocket 类
这个类放在单独的库 Groupsock 中。它封装了 socket 操作,增加了多播放支持和一对多单播的功能。
但目前只看到它对 UDP 的支持,好像不支持 TCP。它管理着一个本地 socket 和多个目的地址,因为是 UDP,所以只需知道对方地址和端口即可发送数据。
Groupsock 的构造函数有一个参数是 struct in_addr const& groupAddr,在构造函数中首先会调用父类构造函数创建 socket 对象,然后判断这个地址,若是多播地址,则加入多播组。
Groupsock 的两个成员变量:
destRecord* fDestsDirectedNetInterfaceSet fMembers
这两个都表示目的地址集合,但实际上 fMembers 似乎没有什么用,且 DirectedNetInterfaceSet 是一个没有被继承的虚类。仅 fDests 也够用了,在 addDestination() 和 removeDestination() 函数中就是操作 fDests,添加或删除目的地址。
参考资料
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)