技术背景
好多开发者,问我们最多的问题是,为什么要设计轻量级RTSP服务?轻量级RTSP服务,和RTSP服务有什么区别?
针对这个问题,我们的回答是:轻量级RTSP服务解决的核心痛点是避免用户或者开发者单独部署RTSP服务或者RTMP服务,RTSP服务,并发或功能相对强大,数据注入模式一般是外部直接推流到RTSP服务(目前大多流媒体服务,以RTMP居多,RTSP的相对较少,或者说,可以商用的RTSP服务,相对较少,音视频数据推送这块,RTMP推送为主,很少有RTSP推流),轻量级RTSP服务,直接部署在数据源测,相当于采集到的屏幕、摄像头、麦克风数据,直接编码注入本地的轻量级RTSP服务,对外提供个可供拉流的RTSP URL,说到这里,轻量级RTSP服务,更像一个IPC摄像头,侧重的不是并发,而是便捷。
设计架构图

Windows、Android、iOS平台的轻量级RTSP服务,不再赘述,之前都有描述,今天介绍的是Linux平台下的轻量级RTSP服务。
和其他平台一样,我们Linux平台依然实现的是本地的音视频数据(如屏幕、摄像头、麦克风),编码打包后,汇聚到内置RTSP服务,对外提供可供拉流的RTSP URL,轻量级RTSP服务,适用于内网环境下,对并发要求不高的场景,支持H.264/H.265,支持RTSP鉴权、单播、组播模式,考虑到单个服务承载能力,我们支持同时创建多个RTSP服务,并支持获取当前RTSP服务会话连接数。
功能设计
- [基础功能]支持常规的屏幕、摄像机、音频采集处理等;
- [音频格式]AAC;
- [视频格式]H.264、H.265;
- [协议类型]RTSP;
- [传输模式]支持单播和组播模式;
- [端口设置]支持RTSP端口设置;
- [鉴权设置]支持RTSP鉴权用户名、密码设置;
- [获取session连接数]支持获取当前RTSP服务会话连接数;
- [多服务支持]支持同时创建多个内置RTSP服务;
- [H.265支持]Windows内置rtsp server支持发布H.265视频(64位库);
- [RTSP url回调]支持设置后的rtsp url通过event回调到上层。
接口设计
RTSP Server操作接口设计:
NT_UINT32(NT_API *OpenRtspServer)(NT_PHANDLE pRtspServerHandle, NT_INT32 reserve);
NT_UINT32(NT_API *SetRtspServerPort)(NT_HANDLE rtsp_server_handle, NT_INT32 port);
NT_UINT32(NT_API *SetRtspServerUserNamePassword)(NT_HANDLE rtsp_server_handle, NT_PCSTR user_name, NT_PCSTR password);
NT_UINT32(NT_API *SetRtspServerMulticast)(NT_HANDLE rtsp_server_handle, NT_INT32 is_multicast);
NT_UINT32(NT_API *SetRtspServerMulticastAddress)(NT_HANDLE rtsp_server_handle, NT_PCSTR multicast_address);
NT_UINT32(NT_API *GetRtspServerClientSessionNumbers)(NT_HANDLE rtsp_server_handle, NT_INT32* session_numbers);
NT_UINT32(NT_API *StartRtspServer)(NT_HANDLE rtsp_server_handle, NT_INT32 reserve);
NT_UINT32(NT_API *StopRtspServer)(NT_HANDLE rtsp_server_handle);
NT_UINT32 (NT_API *CloseRtspServer)(NT_HANDLE rtsp_server_handle);

发布RTSP流相关接口设计:
NT_UINT32(NT_API *SetRtspStreamName)(NT_HANDLE handle, NT_PCSTR stream_name);
NT_UINT32(NT_API *AddRtspStreamServer)(NT_HANDLE handle, NT_HANDLE rtsp_server_handle, NT_INT32 reserve);
NT_UINT32(NT_API *ClearRtspStreamServer)(NT_HANDLE handle);
NT_UINT32(NT_API *StartRtspStream)(NT_HANDLE handle, NT_INT32 reserve);
NT_UINT32(NT_API *StopRtspStream)(NT_HANDLE handle);

调用实现
启动RTSP Server:
NT_HANDLE start_rtsp_server(NT_SmartPublisherSDKAPI* push_api, int port, std::string user_name, std::string password) {
NT_HANDLE rtsp_server_handle = nullptr;
if (NT_ERC_OK != push_api->OpenRtspServer(&rtsp_server_handle, 0)) {
fprintf(stderr, "OpenRtspServer failed\n");
return nullptr;
}
if (nullptr == rtsp_server_handle) {
fprintf(stderr, "rtsp_server_handle is null\n");
return nullptr;
}
if (NT_ERC_OK != push_api->SetRtspServerPort(rtsp_server_handle, port)) {
push_api->CloseRtspServer(rtsp_server_handle);
return nullptr;
}
if (!user_name.empty() && !password.empty())
push_api->SetRtspServerUserNamePassword(rtsp_server_handle, user_name.c_str(), password.c_str());
if (NT_ERC_OK == push_api->StartRtspServer(rtsp_server_handle, 0))
return rtsp_server_handle;
fprintf(stderr, "StartRtspServer failed\n");
push_api->CloseRtspServer(rtsp_server_handle);
return nullptr;
}

停止RTSP Server:
void stop_rtsp_server(NT_SmartPublisherSDKAPI* push_api, NT_HANDLE& rtsp_server_handle) {
if (nullptr == rtsp_server_handle)
return;
NT_HANDLE handle = rtsp_server_handle;
rtsp_server_handle = nullptr;
push_api->StopRtspServer(handle);
push_api->CloseRtspServer(handle);
}

开始发布RTSP Stream:
bool start_rtsp_stream(NT_SmartPublisherSDKAPI* push_api, NT_HANDLE rtsp_server_handle, NT_HANDLE handle, const std::string stream_name) {
push_api->SetRtspStreamName(handle, stream_name.c_str());
push_api->ClearRtspStreamServer(handle);
push_api->AddRtspStreamServer(handle, rtsp_server_handle, 0);
if (NT_ERC_OK != push_api->StartRtspStream(handle, 0))
return false;
return true;
}

如需停止RTSP流的发布,直接调用:
stop_rtsp_server(&push_api, rtsp_server_handle);

如果需要采集到的音视频数据预览,调用预览接口即可:
push_api.SetPreviewXWindow(push_handle, "", sub_wid);
push_api.StartPreview(push_handle, 0, nullptr);

总结
轻量级RTSP服务,并发这块不是强项,不过确实解决了单独部署RTSP或RTMP服务的痛点,减少了工程实施成本,在并发量要求不高的场景下,非常方便。