文章目录
- 一 、28181-2016标准文档中的点播流程
- 二 、点播流程源码分析
-
- 2.1 页面发起点播请求
- 2.2 与ZLM协商SSRC信息
- 2.3 订阅zlmediakit的hook消息及发送invite信令
- 2.4 处理invite信令响应并应答
- 2.5 收到ZLM的推流通知
- 2.6 播放成功
- 2.7 停止点播流程
2024年6月20日下载的wvp-GB28181-pro,版本号为2.7.2,使用ZLMediakit主干版本。
本节阐述wvp摄像机点播流程。
一 、28181-2016标准文档中的点播流程
图中的媒体接收者,SIP服务器,媒体服务器和媒体发送者都是逻辑模块,在实际上可以不按照这样的步骤来完成。媒体发送者是摄像机,而媒体接收者、SIP服务器和媒体服务器是wvp和zlmediakit组成,wvp和zlmediakit内部之间通信并没有按照28181的步骤来,wvp只要实现上图的第4、5、7、19、20就可以播放视频和停止播放。至于网页、wvp跟zlmediakit之间是按照自己的私有接口格式来完成的。
附上wvp的点播流程图,可以对比分析下。
二 、点播流程源码分析
2.1 页面发起点播请求
接口控制类PlayController在如下包路径下:
com.genersoft.iot.vmp.vmanager.gb28181.play
调用playService.play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback callback),进入PlayServiceImpl类,在如下的包路径下:
com.genersoft.iot.vmp.service.impl
核心方法源码
@Override
public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) {
if (mediaServerItem == null) {
logger.warn("[点播] 未找到可用的zlm deviceId: {},channelId:{}", deviceId, channelId);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到可用的zlm");
}
Device device = redisCatchStorage.getDevice(deviceId);
if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && !mediaServerItem.isRtpEnable()) {
logger.warn("[点播] 单端口收流时不支持TCP主动方式收流 deviceId: {},channelId:{}", deviceId, channelId);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "单端口收流时不支持TCP主动方式收流");
}
DeviceChannel channel = channelService.getOne(deviceId, channelId);
if (channel == null) {
logger.warn("[点播] 未找到通道 deviceId: {},channelId:{}", deviceId, channelId);
throw new ControllerException(ErrorCode.ERROR100.getCode(), "未找到通道");
}
InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId);
if (inviteInfo != null ) {
if (inviteInfo.getStreamInfo() == null) {
// 释放生成的ssrc,使用上一次申请的
ssrcFactory.releaseSsrc(mediaServerItem.getId(), ssrc);
// 点播发起了但是尚未成功, 仅注册回调等待结果即可
inviteStreamService.once(InviteSessionType.PLAY, deviceId, channelId, null, callback);
logger.info("[点播开始] 已经请求中,等待结果, deviceId: {}, channelId: {}", device.getDeviceId(), channelId);
return inviteInfo.getSsrcInfo();
}else {
StreamInfo streamInfo = inviteInfo.