如何在轻量级RTSP服务支持H.264扩展SEI发送接收自定义数据?

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
对象存储 OSS,内容安全 1000次 1年
简介: 如何在轻量级RTSP服务支持H.264扩展SEI发送接收自定义数据?

为什么开发轻量级RTSP服务?

开发轻量级RTSP服务的目的是为了解决在某些场景下用户或开发者需要单独部署RTSP或RTMP服务的问题。这种服务的优势主要有以下几点:

  1. 便利性:通过轻量级RTSP服务,用户无需配置单独的服务器,降低了部署和配置的复杂性(无论是走RTMP还是GB28181,均需要平台服务支撑)。
  2. 可扩展性:该服务支持同时创建多个RTSP服务,便于根据需求扩展或缩减服务规模(在性能没问题的情况下,启动多个服务,支撑多路流数据并发)。
  3. 并发性:能满足内网无纸化/电子教室等场景中的低并发需求,对并发要求不高的场景也适用(低并发解决大问题)。
  4. 兼容性:支持H.264/H.265视频编码,以及RTSP鉴权、RTSP会话数查看、单播、组播模式。

总的来说,轻量级RTSP服务的目标是提供一种便捷、可扩展且能满足低并发需求的服务,特别适合在内网环境下使用。

如何在轻量级RTSP服务扩展SEI发送接收?

大牛直播SDK支持推送端通过H.264 SEI信息扩展,实时传输文本/二进制数据信息,播放端做相应解析和回显。

适用场景:

  1. 公告广播:推送将相对/绝对时间戳/时间/公告内容发到播放端,播放端实时接收消息并做相应的逻辑处理。
  2. 冲顶大会:推流端实时将题目分发到播放端,借助于大牛直播SDK低延迟特性,轻松实现“音-画-题”同步接收;
  3. 会议教育类直播:推流端将字幕等分发到播放端,播放端实时绘制出相关内容;
  4. 应急指挥/单兵:推送端将GIS信息/现场采集到的数据实时写入并分发到播放端;
  5. 在线教育:推流端将激光笔和涂鸦操作分发到播放端,播放端实时划圈划线,实现特定特效。

尽管Windows、Linux、Android和iOS平台,我们都支持了H.264扩展SEI发送和接收的模块,本文先以Windows平台为例,介绍下关键的接口设计思路:

轻量级RTSP服务.png

本文以Windows平台轻量级RTSP服务为例,数据源采集计时器窗体,然后,启动RTSP服务,发布RTSP流,发布后,自动发送自定义数据,播放端接收并回显轻量级RTSP服务发过来的自定义数据。上图可以看到,整体延迟在毫秒级(200多毫秒)。

先说启动停止轻量级RTSP服务关键接口设计:

/*+++rtsp server操作接口+++*//** 创建一个rtsp server * pRtspServerHandle: rtsp server 句柄* reserve:保留参数传0* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*OpenRtspServer)(NT_PHANDLEpRtspServerHandle, NT_INT32reserve);
/** 设置rtsp server 监听端口, 在StartRtspServer之前必须要设置端口* rtsp_server_handle: rtsp server 句柄* port: 端口号,可以设置为554,或者是1024到65535之间,其他值返回失败* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*SetRtspServerPort)(NT_HANDLErtsp_server_handle, NT_INT32port);
/** 设置rtsp server 鉴权用户名和密码, 这个可以不设置,只有需要鉴权的再设置* rtsp_server_handle: rtsp server 句柄* user_name: 用户名,必须是英文* password:密码,必须是英文* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*SetRtspServerUserNamePassword)(NT_HANDLErtsp_server_handle, NT_PCSTRuser_name, NT_PCSTRpassword);
/** 设置rtsp server 组播, 如果server设置成组播就不能单播,组播和单播只能选一个, 一般来说单播网络设备支持的好,wifi组播很多路由器不支持* rtsp_server_handle: rtsp server 句柄* is_multicast: 是否组播, 1为组播, 0为单播, 其他值接口返回错误, 默认是单播* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*SetRtspServerMulticast)(NT_HANDLErtsp_server_handle, NT_INT32is_multicast);
/** 设置rtsp server 组播组播地址 * rtsp_server_handle: rtsp server 句柄* multicast_address: 组播地址* 如果设置的不是组播地址, 将返回错误* 组播地址范围说明: [224.0.0.0, 224.0.0.255] 为组播预留地址, 不能设置. 可设置范围为[224.0.1.0, 239.255.255.255], 其中SSM地址范围为[232.0.0.0, 232.255.255.255]* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*SetRtspServerMulticastAddress)(NT_HANDLErtsp_server_handle, NT_PCSTRmulticast_address);
/** 获取rtsp server当前的客户会话数, 这个接口必须在StartRtspServer之后再调用* rtsp_server_handle: rtsp server 句柄* session_numbers: 会话数* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*GetRtspServerClientSessionNumbers)(NT_HANDLErtsp_server_handle, NT_INT32*session_numbers);
/** 启动rtsp server* rtsp_server_handle: rtsp server 句柄* reserve: 保留参数传0* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*StartRtspServer)(NT_HANDLErtsp_server_handle, NT_INT32reserve);
/** 停止rtsp server* rtsp_server_handle: rtsp server 句柄* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*StopRtspServer)(NT_HANDLErtsp_server_handle);
/** 关闭rtsp server* 调用这个接口之后rtsp_server_handle失效,* 成功返回 NT_ERC_OK*/NT_UINT32 (NT_API*CloseRtspServer)(NT_HANDLErtsp_server_handle);
/*---rtsp server操作接口---*/

再说发布RTSP流相关接口设计:

/*+++发布rtsp流相关接口+++*//** 设置rtsp的流名称* stream_name: 流程名称,不能为空字符串,必须是英文* 这个作用是: 比如rtsp的url是:rtsp://192.168.0.111/test, test就是设置下去的stream_name* 成功返回 NT_ERC_OK*/NT_UINT32(NT_API*SetRtspStreamName)(NT_HANDLEhandle, NT_PCSTRstream_name);
/** 给要发布的rtsp流设置rtsp server, 一个流可以发布到多个rtsp server上,rtsp server的创建启动请参考OpenRtspServer和StartRtspServer接口* handle: 推送实例句柄* rtsp_server_handle:rtsp server句柄 * reserve: 保留参数,传0*/NT_UINT32(NT_API*AddRtspStreamServer)(NT_HANDLEhandle, NT_HANDLErtsp_server_handle, NT_INT32reserve);
/** 清除设置的rtsp server*/NT_UINT32(NT_API*ClearRtspStreamServer)(NT_HANDLEhandle);
/*启动rtsp流reserve: 保留参数,传0*/NT_UINT32(NT_API*StartRtspStream)(NT_HANDLEhandle, NT_INT32reserve);
/*停止rtsp流*/NT_UINT32(NT_API*StopRtspStream)(NT_HANDLEhandle);
/*---发布rtsp流相关接口---*/

发送自定义数据相关接口设计:

/*++++发送用户自定义数据相关接口++++*//** 1. 目前使用sei机制发送用户自定数据到播放端* 2. 这种机制有可能会丢失数据, 所以这种方式不保证接收端一定能收到* 3. 优势:能和视频保持同步,虽然有可能丢失,但一般的需求都满足了* 4. 目前提供两种发送方式 第一种发送二进制数据, 第二种发送 utf8字符串*//** 设置发送队列大小,为保证实时性,默认大小为3, 必须设置一个大于0的数* 如果数据超过队列大小,将丢掉队头数据* 这个接口请在 StartPublisher 之前调用*/NT_UINT32(NT_API*SetPostUserDataQueueMaxSize)(NT_HANDLEhandle, NT_INT32max_size, NT_INT32reserve);
/** 清空用户数据队列, 有些情况可能会用到,比如发送队列里面有4条消息再等待发送,又想把最新的消息快速发出去, 可以 * 先清除掉正在排队消息, 再调用PostUserXXX  **/NT_UINT32(NT_API*ClearPostUserDataQueue)(NT_HANDLEhandle);
/** 发送二进制数据* data: 二进制数据* size:数据大小* 注意: 1.目前数据大小限制在256个字节以内,太大可能会影响视频传输,如果有特殊需求,需要增大限制,请联系我们* 2. 如果积累的数据超过了设置的队列大小,之前的队头数据将被丢弃* 3. 必须再调用StartPublisher之后再发送数据*/NT_UINT32(NT_API*PostUserData)(NT_HANDLEhandle, constNT_BYTE*data, NT_UINT32size, NT_INT32reserve);
/** 发送utf8字符串* utf8_str: utf8字符串* 注意: 1. 字符串长度不能超过256, 太大可能会影响视频传输,如果有特殊需求,需要增大限制,请联系我们* 2. 如果积累的数据超过了设置的队列大小,之前的队头数据将被丢弃* 3. 必须再调用StartPublisher之后再发送数据*/NT_UINT32(NT_API*PostUserUTF8StringData)(NT_HANDLEhandle, NT_PCSTRutf8_str, NT_INT32reserve);
/*----发送用户自定义数据相关接口----*/

播放端接收用户自定义数据接口:

设置用户数据回调:

player_api_.SetUserDataCallBack(player_handle_, GetSafeHwnd(), NT_SP_SDKUserDataHandle);

回调实现:

extern"C"NT_VOIDNT_CALLBACKNT_SP_SDKUserDataHandle(NT_HANDLEhandle, NT_PVOIDuser_data,
NT_INT32data_type,
NT_PVOIDdata,
NT_UINT32size,
NT_UINT64timestamp,
NT_UINT64reserve1,
NT_INT64reserve2,
NT_PVOIDreserve3)
{
if ( 1==data_type )
    {
std::wostringstreamoss;
oss<<L"userdata ";
constNT_BYTE*byte_data=reinterpret_cast<constNT_BYTE*>(data);
if ( byte_data!=nullptr&&size>0 )
        {
oss<<L" byte data size="<<size;
        }
std::wstring_convert<std::codecvt_utf8<wchar_t>>conv;
oss<<L" t:"<<timestamp<<L"\r\n";
OutputDebugStringW(oss.str().c_str());
    }
elseif ( 2==data_type )
    {
constNT_CHAR*str_data=reinterpret_cast<constNT_CHAR*>(data);
if (str_data!=nullptr&&size>0)
        {
std::unique_ptr<std::string>s(newstd::string(str_data, str_data+size));
// oss << L" utf8 string:" << conv.from_bytes(*s);// oss << L" size=" << size;if ( !s->empty() )
            {
HWNDhwnd=reinterpret_cast<HWND>(user_data);
if ( hwnd!=nullptr&& ::IsWindow(hwnd) )
                {
                    ::PostMessage(hwnd, WM_USER_SDK_SP_RECV_USER_DATA, (WPARAM)s.release(), (LPARAM)timestamp);
                }
            }
        }
    }
}

事件处理:

LRESULTCSmartPlayerDlg::OnSDKRecvUserData(WPARAMwParam, LPARAMlParam)
{
std::unique_ptr<std::string>str((std::string*)(wParam));
if (str&&!str->empty())
    {
autotimestamp= (NT_UINT64)(lParam);
std::wstring_convert<std::codecvt_utf8<wchar_t>>conv;
autow_str=conv.from_bytes(*str);
std::wostringstreamwss;
wss<<L"收到推送端消息:[ "<<w_str<<L" ] t:"<<timestamp;
edit_player_msg_.SetWindowTextW(wss.str().c_str());
    }
returnS_OK;
}

总结

需要注意的是,无论是轻量级RTSP服务还是RTMP推送设计,因为是通过H.264扩展SEI发送和接收自定义数据,会存在数据或消息丢失的情况,很难实现可靠传输,当然,也可以在多帧数据携带数据,确保消息多次重传达到防止部分数据丢失的目的。

相关实践学习
借助OSS搭建在线教育视频课程分享网站
本教程介绍如何基于云服务器ECS和对象存储OSS,搭建一个在线教育视频课程分享网站。
相关文章
|
5月前
|
编解码 监控 网络协议
GB28181设备接入模块和轻量级RTSP服务有什么区别?
本文对比了GB28181与轻量级RTSP服务的特点与应用场景。GB28181为国标视频监控技术规范,适用于大规模监控系统,如城市安防、交通监控等,强调设备接入、流传输及控制。RTSP则是一种控制流媒体传输的协议,广泛用于直播、点播及视频会议等场景。文中还介绍了SmartGBD模块,用于非国标Android终端接入GB28181系统,并列举了其多项功能。轻量级RTSP服务则便于用户在内网环境中无需额外部署即可提供RTSP流服务。两者各有优势,可根据具体需求选择使用。
124 1
|
8月前
|
网络协议 Linux iOS开发
推荐:实现RTSP/RTMP/HLS/HTTP协议的轻量级流媒体框架,支持大并发连接请求
推荐:实现RTSP/RTMP/HLS/HTTP协议的轻量级流媒体框架,支持大并发连接请求
308 1
|
编解码 Linux 数据安全/隐私保护
Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?
Linux平台如何实现采集音视频数据并注入轻量级RTSP服务?
268 1
|
4月前
|
编解码 Android开发 开发者
如何在轻量级RTSP服务中玩转H.264扩展SEI,实现自定义数据的发送与接收?
【9月更文挑战第4天】本文详细介绍了如何在轻量级RTSP服务中实现H.264标准的扩展SEI功能,包括环境准备、依赖引入、RTSP服务创建、自定义SEI数据发送与接收等步骤,并提供了具体代码示例,帮助开发者更好地利用SEI在视频流中嵌入元数据。
92 2
|
5月前
|
编解码 Android开发
### 揭秘!如何在轻量级RTSP服务中玩转H.264扩展SEI,实现自定义数据的发送与接收?
【8月更文挑战第14天】本文介绍如何在轻量级RTSP服务中实现H.264的SEI功能,允许在视频流中嵌入自定义数据。首先确保环境已安装Android Studio并具备基础开发技能。接着,通过Gradle添加必要依赖如`jrtsp`。创建RTSP服务并配置H.264编码器支持SEI。编码过程中可添加自定义SEI数据,并在客户端解析这些数据。此方案适用于需在视频流中传递元数据的应用场景。
58 0
|
编解码 开发工具 Android开发
Android平台如何实现外部RTSP|RTMP流注入轻量级RTSP服务模块(内网RTSP网关)
今天分享的是外部RTSP或RTMP流,拉取后注入到本地轻量级RTSP服务模块,供内网小并发场景下使用,这里我们叫做内网RTSP网关模块。
139 0
|
Web App开发 编解码 前端开发
2023年WEB内嵌VLC直接播放RTSP视频流,无需服务器转码,支持硬件解码及高版本Chrome
2015年之前还可以用VLC原生播放器在Chrome、Firefox等浏览器中直接播放,延迟比较低,效果也还不错。可惜好景不长,从 2015年Chrome、Firefox等浏览器取消了对 NPAPI插件的支持,海康威视官方提供的 web3.0开发包也只能在低版本浏览器播放。
491 0
|
开发工具 Android开发 开发者
Android平台轻量级RTSP服务模块如何实现一个服务发布多路RTSP流?
Android平台轻量级RTSP服务模块如何实现一个服务发布多路RTSP流?
286 0
|
定位技术 开发工具 Windows
如何在RTSP/RTMP直播过程中加入SEI扩展数据发送和接收解析
在直播系统中,除了直播音视频之外,有时候还想从主播端发布文本信息等,这些信息可以不通过视频传输通道发送给用户播放端,但如果传输的数据想和视频保持精准同步,那最好的办法就是这些信息和视频数据打包在一起传输,并通过h264 sei方式就可以把数据放入h264 Access Unit中传输。
327 0
|
编解码 监控 网络协议
Android平台GB28181设备接入侧(编码前|编码后|RTSP|RTMP)支持功能浅析
在之前,我有写过Android平台GB28181设备接入模块的好多blog,包括参数设置、功能支持与扩展等,以数据接入为例,支持的数据类型涉及编码前、编码后或直接流数据(RTSP或RTMP流)。可用于如智能监控、智慧零售、智慧教育、远程办公、生产运输、智慧交通、车载或执法记录仪等场景。
174 0