...
 
Commits (19)
    https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/9e75d25ed37ba8195898fd3922133076873399de modify:RTMPProtocol_Help_ParseVideo method of use 2023-07-27T13:43:38+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/86b7f039126339ff6ec565321d7834d8610b65b5 fixed:some problem with xstream convert 2023-07-27T13:58:50+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/a4d67a925865f5b2dd4af1d11e5bc9127ce085a4 added:srt supported 2023-07-28T14:58:03+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/bbd2513d3b5d127781bf962fe583e74282393636 added:the srt difference between publish and request 2023-07-28T17:37:51+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/b9466750376a8a09be87e734e1be439894bf3f9c added:forward data for srt supported 2023-07-31T10:25:58+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/de1d213f8029a32dd1d8adc074aff8d4b4ca2ab6 fixed:srt forward data is incorrent 2023-07-31T10:34:12+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/bd3e5f86f662dc33fa0d224280b0a6ed73d140c8 modify:the srt can be process client close event now 2023-07-31T10:47:41+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/ea0d9c73a1d367eff4fc5d38001e90c945580b98 fixed:clean client resource is incorrent when client close 2023-07-31T11:14:42+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/4e1b1251fe538cd135c92ab135386400c84f337b fixed:crashed when program exit 2023-07-31T11:31:33+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/ab4a8fa7b3916b58a4442402cee3ea6f36ebfcad delete:unused code for session module 2023-07-31T15:48:56+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/c86dd344b6d305f752090c41d7c98b30ceb2bf85 added:publish and pull stream for http api 2023-08-01T11:31:51+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/fe04b0540fa436a98276024493656d0d28fc9493 fixed:pull client smsaddr is incorrent 2023-08-01T11:37:21+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/37739f99da14a6aa2b259b65829688e04db914df fixed:linux build error 2023-08-01T14:12:56+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/648f82baf845b181ceecc4ca63ac32d81c35bf73 modify:srt use method 2023-08-01T15:06:25+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/2eabdeb04177c9f0c26227714393233beb3e61b8 update:readme and docment 2023-08-04T10:51:49+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/b9cf2f54785bd0cdd6695c90acacb57f7958b1d2 update:configure file 2023-08-04T10:52:14+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/d0a220bb34341d69ebb93cf9a937ffab5a192b5c update:CHANGELOG and COPYRIGHT 2023-08-04T10:52:26+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/f2c1426972a237c991c2c36ebf2d93f2b4d047f5 update:readme 2023-08-04T10:57:56+08:00 qyt 486179@qq.com https://gitcode.net/xengine/XEngine_StreamMedia/-/commit/923db642cd33d6d89924f5b5a753a0784105076e !9 V2.2.0.1001 Merge 2023-08-04T03:00:29+00:00 qyt 486179@qq.com Merge pull request !9 from qyt/develop
XEngine_StreamMedia V2.2.0.1001
添加:SRT推拉流支持
添加:为HTTP管理接口增加推拉流信息获取的支持
修改:RTMPProtocol_Help_ParseVideo 的使用方法
修复:xstream流转换的一些问题
修复:当客户端关闭的时候清理客户端资源不正确的问题
修复:拉流客户端的流地址不正确的问题
删除:没有使用的会话代码
added:srt publish and pull stream supported
added:get publish and pull stream information for http api
modify:RTMPProtocol_Help_ParseVideo method of use
fixed:some problem with xstream convert
fixed:clean client resource is incorrent when client close
fixed:pull client smsaddr is incorrent
delete:unused code for session module
=======================================================
XEngine_StreamMedia V2.1.0.1001
增加:RTMP拉流支持
......
the open source software depend on the following libraries, please note the copyright
XEngine:https://gitee.com/xyry/libxengine or https://github.com/libxengine/xengine
jsoncpp:https://github.com/open-source-parsers/jsoncpp
\ No newline at end of file
jsoncpp:https://github.com/open-source-parsers/jsoncpp
srt:https://github.com/Haivision/srt
\ No newline at end of file
......@@ -6,32 +6,39 @@ As long as the repository is not in suspended state, we will maintain and develo
## Introduction
c c++ 流媒体服务器
c c++ streammedia server
This is a streaming media server that supports multiple streaming protocols. It supports push and pull stream, and supports streaming media servers of various standards
This is a streaming media server that supports multiple streaming protocols. It supports push and pull stream, and supports streaming media servers of various standards protocols
It can also be used as a frame extraction service and transcoding service
This is a cross-platform server, provides a complete demo code
## Software feature
A set of concise and high-performance cross-platform streaming media analysis and push streaming services developed and implemented based on libXEngine
Push stream Protocol:
1. RTMP
2. XStream(H264,H265)
3. WEBRTC(planning)
4. GB28181(planning)
5. JT1078(planning)
6. SRT(planning)
1. RTMP(H264,H265,AAC)
2. XStream
3. SRT
4. JT1078(planning)
5. GB28181(planning)
6. WEBRTC(planning)
Pull Stream Protocols:
1. RTSP(planning)
2. RTMP(H264,H265)
3. FLV(H264,H265)
1. srt
2. RTMP(H264,H265,AAC)
3. FLV(H264,H265,AAC)
4. XStream
4. HLS(TS)(planning)
5. webrtc(planning)
6. srt(planning)
feature
1. Support voice intercom
2. Support video transcoding
3. Support frame extraction
6. RTSP(planning)
feature:
1. Support voice intercom(planning)
2. Support video transcoding(planning)
3. Support frame extraction(planning)
4. Support Re-push stream
5. Support Transparent transmission
5. Support Transparent transmission(planning)
6. Support HTTP API Management interface
7. Support HTTP HOOK(planning)
## install
#### XEngine environment
......@@ -40,15 +47,19 @@ GITEE:https://gitee.com/xyry/libxengine
GITHUB:https://github.com/libxengine/xengine
#### fast to deployment
git clone https://gitee.com/xyry/libxengine.git or git clone https://github.com/libxengine/xengine.git
window Exection XEngine_WINEnv.bat
Linux Exection:sudo ./XEngine_LINEnv.sh -i 3
Macos Exection:./XEngine_LINEnv.sh -i 3
git clone https://gitee.com/xyry/libxengine.git or git clone https://github.com/libxengine/xengine.git
window Exection XEngine_WINEnv.bat
Linux Exection:sudo ./XEngine_LINEnv.sh -i 3
Macos Exection:./XEngine_LINEnv.sh -i 3
#### Windows
use vs open and complie
#### Linux
install srt library after Configure Xengine to Completed
ubuntu:sudo apt install libsrt-openssl-dev
Rockylinux:sudo dnf install srt-devel
Linux use Makefile complie
UBUNTU22.04 x64 or RockyLinux 9 x64
......@@ -59,6 +70,8 @@ make FLAGS=InstallAll Install File
make FLAGS=CleanAll Clear Complie
#### MacOS
install srt library after Configure Xengine to Completed
ubuntu:sudo brew install libsrt
Linux use Makefile to complie,terminal exection,Requires mac 13 and above
##### Compile Command
......@@ -75,9 +88,20 @@ refer to linux
7. use vlc play
## example
Publish Stream Address:rtmp://127.0.0.1/live/stream
Pull Stream Address-HTTPFLV: http://127.0.0.1:5600/api?stream=play&sms=live/qyt&type=flv
Pull Stream Address-RTMP: rtmp://127.0.0.1/live/qyt
#### publish Stream
rtmp://127.0.0.1/live/qyt  
srt://127.0.0.1:5603?streamid=#!::h=live/qyt,m=publish
xstream://127.0.0.1:5601(refer example)
#### Pull Stream
http://127.0.0.1:5600/api?stream=play&sms=live/qyt&type=flv(http-flv)
rtmp://127.0.0.1/live/qyt  
srt://127.0.0.1:5603?streamid=#!::r=live/qyt,m=request
xstream://127.0.0.1:5601?api?stream=play&sms=live/qyt&type=xstream(http-xstream)
#### Management HTTP API
http://127.0.0.1:5600/api?function=publish&method=get
http://127.0.0.1:5600/api?function=pull&method=get
## Dir Struct
- XEngine_Docment Docment Dir Struct
- XEngine_Release Install Dir Struct
......
[中文](README.md) || [English](README.en.md)
[中文](README.md) ||  [English](README.en.md)  
# XEngine_StreamMedia
本仓库有开发和主分支,如果要使用,请使用master分支下的代码
只要仓库不是在暂停状态,那么就会有人一直维护和开发,请放心使用
本仓库有开发和主分支,如果要使用,请使用master分支下的代码  
只要仓库不是在暂停状态,那么就会有人一直维护和开发,请放心使用  
## 介绍
c c++ 流媒体服务器
c c++ streammedia server
这是一个支持多种流协议的流媒体服务器,他支持推流和拉流,支持各种主流标准的流媒体服务器
他还可以作为抽帧服务和转码服务使用.
这是一个跨平台的流媒体服务器,提供了完整的演示代码
c c++ 流媒体服务器  
c c++ streammedia server  
这是一个支持多种流协议的流媒体服务器,他支持推流和拉流,支持各种主流标准协议的流媒体服务器
他还可以作为抽帧服务和转码服务使用.
这是一个跨平台的流媒体服务器,提供了完整的演示代码  
## 软件架构
基于libXEngine开发并实现的一套简洁高性能跨平台流媒体解析推流服务
基于libXEngine开发并实现的一套简洁高性能跨平台流媒体解析推流服务  
推流支持:
1. RTMP(H264,H265)
2. XStream(H264,H265)
3. WEBRTC(planning)
4. GB28181(planning)
5. JT1078(planning)
6. SRT(planning)
1. RTMP(H264,H265,AAC)
2. XStream
3. SRT
4. JT1078(planning)
5. GB28181(planning)
6. WEBRTC(planning)
拉流支持:
1. RTSP(planning)
2. RTMP(H264,H265)
3. FLV(H264,H265)
4. HLS(TS)(planning)
5. webrtc(planning)
6. srt(planning)
特性:
1. 支持语音对讲
2. 支持视频转码
3. 支持抽帧
1. srt
2. RTMP(H264,H265,AAC)
3. FLV(H264,H265,AAC)
4. XStream
5. HLS(TS)(planning)
6. webrtc(planning)
7. RTSP(planning)
特性:  
1. 支持语音对讲(planning)
2. 支持视频转码(planning)
3. 支持抽帧(planning)
4. 支持转推流
5. 支持透传数据
5. 支持透传数据(planning)
6. 支持HTTP API管理接口
7. 支持HTTP HOOK(planning)
## 安装教程
#### XEngine环境
在编译之前必须安装XEngine,可以参考其Readme文档
GITEE:https://gitee.com/xyry/libxengine
GITHUB:https://github.com/libxengine/xengine
在编译之前必须安装XEngine,可以参考其Readme文档  
GITEE:https://gitee.com/xyry/libxengine  
GITHUB:https://github.com/libxengine/xengine  
#### 快速部署
git clone https://gitee.com/xyry/libxengine.git 或者 git clone https://github.com/libxengine/xengine.git
window执行XEngine_WINEnv.bat 脚本.
Linux执行:sudo ./XEngine_LINEnv.sh -i 3
macos执行:./XEngine_LINEnv.sh -i 3
git clone https://gitee.com/xyry/libxengine.git 或者 git clone https://github.com/libxengine/xengine.git
window执行XEngine_WINEnv.bat 脚本.
Linux执行:sudo ./XEngine_LINEnv.sh -i 3
macos执行:./XEngine_LINEnv.sh -i 3
#### Windows
使用VS打开并且编译,你需要优先配置XEngine环境才能使用
使用VS打开并且编译,你需要优先配置XEngine环境才能使用
还需要libsrt库,通过vcpkg安装
#### Linux
Linux使用Makefile编译
UBUNTU22.04 或者 RockyLinux 9 x64均可
配置完XEngine后需要安装srt库
ubuntu:sudo apt install libsrt-openssl-dev
Rockylinux:sudo dnf install srt-devel
Linux使用Makefile编译  
UBUNTU22.04 或者 RockyLinux 9 x64均可  
###### 编译命令
在XEngine_Source目录下执行命令
make 编译
make FLAGS=InstallAll 安装库程序
make FLAGS=CleanAll 清理编译
在XEngine_Source目录下执行命令  
make 编译  
make FLAGS=InstallAll 安装库程序  
make FLAGS=CleanAll 清理编译  
#### MacOS
配置完XEngine后需要安装srt库
ubuntu:sudo brew install libsrt
使用makefile编译,控制台运行,需要mac 13以及以上版本
###### 编译命令
参考Linux
## 使用说明
1. 切换到MASTER分支
2. 下载代码
3. 编译
4. 安装
5. 运行XEngine_StreamMediaApp,linux可以使用 -d 1 命令在后台运行
7. 使用obs推流
8. 使用VLC等工具播放
1. 切换到MASTER分支
2. 下载代码
3. 编译
4. 安装
5. 运行XEngine_StreamMediaApp,linux可以使用 -d 1 命令在后台运行
6. 使用obs推流
7. 使用VLC等工具播放
## 示例
推流地址:rtmp://127.0.0.1/live/qyt
播放地址:HTTP-FLV http://127.0.0.1:5600/api?stream=play&sms=live/qyt&type=flv
播放地址:RTMP rtmp://127.0.0.1/live/qyt
#### 推流示例
rtmp://127.0.0.1/live/qyt  
srt://127.0.0.1:5603?streamid=#!::h=live/qyt,m=publish
xstream://127.0.0.1:5601(参考例子)
#### 拉流示例
http://127.0.0.1:5600/api?stream=play&sms=live/qyt&type=flv(http-flv)
rtmp://127.0.0.1/live/qyt  
srt://127.0.0.1:5603?streamid=#!::r=live/qyt,m=request
xstream://127.0.0.1:5601?api?stream=play&sms=live/qyt&type=xstream(http-xstream)
#### 管理接口示例
http://127.0.0.1:5600/api?function=publish&method=get
http://127.0.0.1:5600/api?function=pull&method=get
## 目录结构
- XEngine_Docment 文档目录结构
- XEngine_Release 安装目录结构
- XEngine_Source 源代目录结构
......@@ -87,13 +122,15 @@ make FLAGS=CleanAll 清理编译
## 参与贡献
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
1. Fork 本仓库
2. 新建 Feat_xxx 分支
3. 提交代码
4. 新建 Pull Request
## 关注我们
如果你觉得这个软件对你有帮助,请你给我们一个START吧
## 提交问题
如果你有问题或者发现程序有BUG和意见,可以在issues中提交
\ No newline at end of file
如果你有问题或者发现程序有BUG和意见,可以在issues中提交
......@@ -9,6 +9,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APPClient_FLVPull", "APPCli
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APPClient_XStream", "APPClient_XStream\APPClient_XStream.vcxproj", "{706EEB19-180B-405F-BDAD-C114AF2B8952}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "APPClient_SRTPull", "APPClient_SRTPull\APPClient_SRTPull.vcxproj", "{CB0FA700-6BC1-45CC-8090-74B498E37A4B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
......@@ -41,6 +43,14 @@ Global
{706EEB19-180B-405F-BDAD-C114AF2B8952}.Release|x64.Build.0 = Release|x64
{706EEB19-180B-405F-BDAD-C114AF2B8952}.Release|x86.ActiveCfg = Release|Win32
{706EEB19-180B-405F-BDAD-C114AF2B8952}.Release|x86.Build.0 = Release|Win32
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Debug|x64.ActiveCfg = Debug|x64
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Debug|x64.Build.0 = Debug|x64
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Debug|x86.ActiveCfg = Debug|Win32
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Debug|x86.Build.0 = Debug|Win32
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Release|x64.ActiveCfg = Release|x64
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Release|x64.Build.0 = Release|x64
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Release|x86.ActiveCfg = Release|Win32
{CB0FA700-6BC1-45CC-8090-74B498E37A4B}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
......
......@@ -6,6 +6,7 @@
"nHttpPort":5600,
"nXStreamPort":5601,
"nJT1078Port":5602,
"nSrtPort":5603,
"XMax":{
"nMaxClient":10000,
"nMaxQueue":10000,
......@@ -24,7 +25,7 @@
},
"XPull":{
"XStream":{
"bEnable":true
"bEnable":false
},
"RTMP":{
"bEnable":true
......@@ -33,7 +34,7 @@
"bEnable":true
},
"RTSP":{
"bEnable":true
"bEnable":false
}
},
"XLog":{
......@@ -42,6 +43,7 @@
"LogLeave":32
},
"XVer":[
"V2.2.0.1001 Build20230804",
"V2.1.0.1001 Build20230726",
"V2.0.0.1001 Build20230615",
"V1.4.1.1001 Build20230515",
......
......@@ -23,6 +23,7 @@ typedef struct tag_XEngine_ServiceConfig
int nRTMPPort; //RTMP流服务
int nXStreamPort; //X流协议服务
int nJT1078Port; //JT1078协议流支持
int nSrtPort; //srt协议端口
struct
{
int nMaxClient; //最大客户端个数
......
......@@ -89,6 +89,7 @@ bool CModuleConfigure_Json::ModuleConfigure_Json_File(LPCXSTR lpszConfigFile, XE
pSt_ServerConfig->nHttpPort = st_JsonRoot["nHttpPort"].asInt();
pSt_ServerConfig->nXStreamPort = st_JsonRoot["nXStreamPort"].asInt();
pSt_ServerConfig->nJT1078Port = st_JsonRoot["nJT1078Port"].asInt();
pSt_ServerConfig->nSrtPort = st_JsonRoot["nSrtPort"].asInt();
//最大配置
if (st_JsonRoot["XMax"].empty() || (7 != st_JsonRoot["XMax"].size()))
{
......
......@@ -9,8 +9,8 @@ UNICODE = 0
LOADHDR = -I ./
LOADSO = -L /usr/local/lib/XEngine_Release/XEngine_Core
LIB = -lXEngine_OPenSsl
LIBEX =
OBJECTS = ModuleHelp_JT1078.o pch.o
LIBEX = -lsrt
OBJECTS = ModuleHelp_JT1078.o ModuleHelp_SrtCore.o pch.o
ifeq ($(RELEASE),1)
FLAGS = -c
......@@ -54,6 +54,8 @@ all:$(OBJECTS)
ModuleHelp_JT1078.o:./ModuleHelp_JT1078/ModuleHelp_JT1078.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./ModuleHelp_JT1078/ModuleHelp_JT1078.cpp
ModuleHelp_SrtCore.o:./ModuleHelp_Srt/ModuleHelp_SrtCore.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./ModuleHelp_Srt/ModuleHelp_SrtCore.cpp
pch.o:./pch.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./pch.cpp
......
......@@ -49,4 +49,106 @@ extern "C" bool ModuleHelp_JT1078_BCDToString(XBYTE bySIMNumber[6], XCHAR* ptszM
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_JT1078_StringToBCD(LPCXSTR lpszMsgBuffer, XBYTE* pbySIMNumber);
\ No newline at end of file
extern "C" bool ModuleHelp_JT1078_StringToBCD(LPCXSTR lpszMsgBuffer, XBYTE* pbySIMNumber);
/************************************************************************/
/* 导出的SRT函数 */
/************************************************************************/
/********************************************************************
函数名称:ModuleHelp_SrtCore_Start
函数功能:启动SRT
参数.一:nPort
In/Out:In
类型:整数型
可空:N
意思:输入要绑定的端口
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_SrtCore_Start(int nPort);
/********************************************************************
函数名称:ModuleHelp_SrtCore_SetCallback
函数功能:设置数据回调函数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_SrtCore_SetCallback(CALLBACK_NETCORE_SOCKET_NETEVENT_LOGIN fpCallePoll_Login, CALLBACK_NETCORE_SOCKET_NETEVENT_RECV fpCallePoll_Recv, CALLBACK_NETCORE_SOCKET_NETEVENT_LEAVE fpCallePoll_Leave, XPVOID lPLogin = NULL, XPVOID lPRecv = NULL, XPVOID lPLeave = NULL);
/********************************************************************
函数名称:ModuleHelp_SrtCore_Send
函数功能:发送指定数据给客户端
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:要操作的客户端
参数.二:lpszMsgBuffer
In/Out:In
类型:常量字符指针
可空:N
意思:发送的数据
参数.三:nMsgLen
In/Out:In
类型:整数型
可空:N
意思:发送的大小
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_SrtCore_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen);
/********************************************************************
函数名称:ModuleHelp_SrtCore_GetStreamID
函数功能:获取流信息
参数.一:hSocket
In/Out:In
类型:句柄
可空:N
意思:输入要操作的客户端
参数.二:ptszSMSAddr
In/Out:Out
类型:字符指针
可空:N
意思:输出获取到的推流地址
参数.三:pbPublish
In/Out:Out
类型:逻辑型指针
可空:N
意思:输出这个地址是推流还是拉流
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_SrtCore_GetStreamID(SRTSOCKET hSocket, XCHAR * ptszSMSAddr, bool* pbPublish);
/********************************************************************
函数名称:ModuleHelp_SrtCore_Close
函数功能:关闭一个指定的客户端
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:Y
意思:输入关闭的客户端低脂
参数.二:hSocket
In/Out:In
类型:句柄
可空:Y
意思:或者输入客户端句柄
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_SrtCore_Close(LPCXSTR lpszClientAddr = NULL, SRTSOCKET hSocket = 0);
/********************************************************************
函数名称:ModuleHelp_SrtCore_Destory
函数功能:销毁SRT服务
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleHelp_SrtCore_Destory();
\ No newline at end of file
......@@ -13,4 +13,17 @@
//////////////////////////////////////////////////////////////////////////
// 导出的JT1078错误
//////////////////////////////////////////////////////////////////////////
#define ERROR_MODULE_HELP_JT1078_PARAMENT 0xD0001 //参数错误
\ No newline at end of file
#define ERROR_MODULE_HELP_JT1078_PARAMENT 0xD0001 //参数错误
//////////////////////////////////////////////////////////////////////////
// 导出的SRT错误
//////////////////////////////////////////////////////////////////////////
#define ERROR_MODULE_HELP_SRT_PARAMENT 0xD1001 //参数错误
#define ERROR_MODULE_HELP_SRT_CRAETE 0xD1002 //创建SRT失败
#define ERROR_MODULE_HELP_SRT_BIND 0xD1003 //绑定失败
#define ERROR_MODULE_HELP_SRT_LISTEN 0xD1004 //监听失败
#define ERROR_MODULE_HELP_SRT_EPOLL 0xD1005 //EPOLL创建失败
#define ERROR_MODULE_HELP_SRT_ADD 0xD1006 //添加事件失败
#define ERROR_MODULE_HELP_SRT_THREAD 0xD1007 //创建线程失败
#define ERROR_MODULE_HELP_SRT_ACCEPT 0xD1008 //接受失败
#define ERROR_MODULE_HELP_SRT_GETID 0xD1009 //获取STREAMID
#define ERROR_MODULE_HELP_SRT_NOTFOUND 0xD100A //没有找到
\ No newline at end of file
#include "pch.h"
#include "ModuleHelp_SrtCore.h"
/********************************************************************
// Created: 2023/07/28 13:51:06
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_Srt\ModuleHelp_SrtCore.cpp
// File Path: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_Srt
// File Base: ModuleHelp_SrtCore
// File Ext: cpp
// Project: XEngine(网络通信引擎)
// Author: qyt
// Purpose:
// History:
*********************************************************************/
CModuleHelp_SrtCore::CModuleHelp_SrtCore()
{
}
CModuleHelp_SrtCore::~CModuleHelp_SrtCore()
{
}
//////////////////////////////////////////////////////////////////////////
// 公有函数
//////////////////////////////////////////////////////////////////////////
/********************************************************************
函数名称:ModuleHelp_SrtCore_Start
函数功能:启动SRT
参数.一:nPort
In/Out:In
类型:整数型
可空:N
意思:输入要绑定的端口
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Start(int nPort)
{
ModuleHelp_IsErrorOccur = false;
hSRTSocket = srt_create_socket();
if (hSRTSocket < 0)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_CRAETE;
return false;
}
bool bFlag = false;
SRT_TRANSTYPE nType = SRTT_LIVE;
srt_setsockopt(hSRTSocket, 0, SRTO_TRANSTYPE, &nType, sizeof(nType));
srt_setsockopt(hSRTSocket, 0, SRTO_SNDSYN, (const void*)&bFlag, sizeof(bool));
srt_setsockopt(hSRTSocket, 0, SRTO_RCVSYN, (const void*)&bFlag, sizeof(bool));
sockaddr_in st_SockBind = { '\0' };
st_SockBind.sin_family = AF_INET;
st_SockBind.sin_port = htons(nPort);
st_SockBind.sin_addr.s_addr = INADDR_ANY;
if (SRT_ERROR == srt_bind(hSRTSocket, (sockaddr*)&st_SockBind, sizeof(st_SockBind)))
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_BIND;
return false;
}
if (SRT_ERROR == srt_listen(hSRTSocket, 100))
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_LISTEN;
return false;
}
//创建EPOLL
hSRTEPoll = srt_epoll_create();
if (hSRTEPoll < 0)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_EPOLL;
return false;
}
int nSrtEvent = SRT_EPOLL_IN | SRT_EPOLL_ERR;
if (SRT_ERROR == srt_epoll_add_usock(hSRTEPoll, hSRTSocket, &nSrtEvent))
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_ADD;
return false;
}
bRun = true;
pSDTThread = make_unique<thread>(ModuleHelp_SrtCore_Thread, this);
if (NULL == pSDTThread)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_THREAD;
return false;
}
return true;
}
/********************************************************************
函数名称:ModuleHelp_SrtCore_SetCallback
函数功能:设置数据回调函数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_SetCallback(CALLBACK_NETCORE_SOCKET_NETEVENT_LOGIN fpCallePoll_Login, CALLBACK_NETCORE_SOCKET_NETEVENT_RECV fpCallePoll_Recv, CALLBACK_NETCORE_SOCKET_NETEVENT_LEAVE fpCallePoll_Leave, XPVOID lPLogin /* = NULL */, XPVOID lPRecv /* = NULL */, XPVOID lPLeave /* = NULL */)
{
ModuleHelp_IsErrorOccur = false;
m_lLogin = lPLogin;
m_lRecv = lPRecv;
m_lLeave = lPLeave;
lpCall_Login = fpCallePoll_Login;
lpCall_Recv = fpCallePoll_Recv;
lpCall_Leave = fpCallePoll_Leave;
return true;
}
/********************************************************************
函数名称:ModuleHelp_SrtCore_Send
函数功能:发送指定数据给客户端
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:要操作的客户端
参数.二:lpszMsgBuffer
In/Out:In
类型:常量字符指针
可空:N
意思:发送的数据
参数.三:nMsgLen
In/Out:In
类型:整数型
可空:N
意思:发送的大小
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen)
{
ModuleHelp_IsErrorOccur = false;
if (NULL == lpszClientAddr)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_PARAMENT;
return false;
}
bool bFound = false;
st_Locker.lock_shared();
auto stl_MapIterator = stl_MapClients.begin();
for (; stl_MapIterator != stl_MapClients.end(); stl_MapIterator++)
{
if (0 == _tcsxnicmp(lpszClientAddr, stl_MapIterator->second.tszClientAddr, _tcsxlen(lpszClientAddr)))
{
bFound = true;
break;
}
}
if (!bFound)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_NOTFOUND;
st_Locker.unlock_shared();
return false;
}
//int nSRTEvent = SRT_EPOLL_OUT | SRT_EPOLL_ERR;
//srt_epoll_add_usock(hSRTEPoll, hSRTSocket, &nSRTEvent);
SRTSOCKET hSocket = stl_MapIterator->second.hSocket;
st_Locker.unlock_shared();
while (true)
{
int nRet = srt_sendmsg(hSocket, lpszMsgBuffer, nMsgLen, -1, 1);
if (nRet >= 0)
{
break;
}
nRet = srt_getlasterror(NULL);
if (SRT_EASYNCSND != nRet)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_NOTFOUND;
return false;
}
}
//nSRTEvent = SRT_EPOLL_IN | SRT_EPOLL_ERR;
//srt_epoll_update_usock(hSRTEPoll, hSRTSocket, &nSRTEvent);
return true;
}
/********************************************************************
函数名称:ModuleHelp_SrtCore_GetStreamID
函数功能:获取流信息
参数.一:hSocket
In/Out:In
类型:句柄
可空:N
意思:输入要操作的客户端
参数.二:ptszSMSAddr
In/Out:Out
类型:字符指针
可空:N
意思:输出获取到的推流地址
参数.三:pbPublish
In/Out:Out
类型:逻辑型指针
可空:N
意思:输出这个地址是推流还是拉流
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_GetStreamID(SRTSOCKET hSocket, XCHAR* ptszSMSAddr, bool* pbPublish)
{
ModuleHelp_IsErrorOccur = false;
st_Locker.lock_shared();
auto stl_MapIterator = stl_MapClients.find(hSocket);
if (stl_MapIterator == stl_MapClients.end())
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_NOTFOUND;
st_Locker.unlock_shared();
return false;
}
if (0 == stl_MapIterator->second.nIDLen)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_GETID;
st_Locker.unlock_shared();
return false;
}
//#!::h=live/livestream,m=publish
XCHAR tszTmpStr[MAX_PATH];
XCHAR tszSMSAddr[MAX_PATH];
XCHAR tszSMSMode[MAX_PATH];
memset(tszSMSAddr, '\0', sizeof(tszSMSAddr));
memset(tszSMSMode, '\0', sizeof(tszSMSMode));
BaseLib_OperatorString_GetKeyValue(stl_MapIterator->second.tszStreamBuffer + 4, _X(","), tszSMSAddr, tszSMSMode);
BaseLib_OperatorString_GetKeyValue(tszSMSAddr, _X("="), tszTmpStr, ptszSMSAddr);
if (NULL != _tcsxstr(tszSMSMode, _X("publish")))
{
*pbPublish = true;
}
else
{
*pbPublish = false;
}
st_Locker.unlock_shared();
return true;
}
/********************************************************************
函数名称:ModuleHelp_SrtCore_Close
函数功能:关闭一个指定的客户端
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:Y
意思:输入关闭的客户端低脂
参数.二:hSocket
In/Out:In
类型:句柄
可空:Y
意思:或者输入客户端句柄
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Close(LPCXSTR lpszClientAddr /* = NULL */, SRTSOCKET hSocket /* = 0 */)
{
ModuleHelp_IsErrorOccur = false;
if (0 != hSocket)
{
st_Locker.lock();
auto stl_MapIterator = stl_MapClients.find(hSocket);
if (stl_MapIterator != stl_MapClients.end())
{
srt_epoll_remove_usock(hSRTEPoll, stl_MapIterator->second.hSocket);
srt_close(stl_MapIterator->second.hSocket);
stl_MapClients.erase(stl_MapIterator);
}
st_Locker.unlock();
}
return true;
}
/********************************************************************
函数名称:ModuleHelp_SrtCore_Destory
函数功能:销毁SRT服务
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Destory()
{
ModuleHelp_IsErrorOccur = false;
bRun = false;
srt_close(hSRTSocket);
srt_epoll_release(hSRTEPoll);
if (NULL != pSDTThread)
{
pSDTThread->join();
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// 保护函数
//////////////////////////////////////////////////////////////////////////
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Accept(SRTSOCKET hSRTSocket)
{
ModuleHelp_IsErrorOccur = false;
SRTCORE_CLIENTINFO st_SRTClient;
sockaddr_storage st_ClientAddr;
memset(&st_SRTClient, '\0', sizeof(SRTCORE_CLIENTINFO));
int nADDRLen = sizeof(st_ClientAddr);
st_SRTClient.hSocket = srt_accept(hSRTSocket, (sockaddr*)&st_ClientAddr, &nADDRLen);
if (SRT_INVALID_SOCK == st_SRTClient.hSocket)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_ACCEPT;
return false;
}
XCHAR tszAddrBuffer[128];
XCHAR tszPortBuffer[128];
memset(tszAddrBuffer, '\0', sizeof(tszAddrBuffer));
memset(tszPortBuffer, '\0', sizeof(tszPortBuffer));
st_SRTClient.nIDLen = 512;
int nRet = srt_getsockflag(st_SRTClient.hSocket, SRTO_STREAMID, st_SRTClient.tszStreamBuffer, &st_SRTClient.nIDLen);
if (SRT_ERROR == nRet)
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_GETID;
return false;
}
getnameinfo((sockaddr*)&st_ClientAddr, nADDRLen, tszAddrBuffer, sizeof(tszAddrBuffer), tszPortBuffer, sizeof(tszPortBuffer), NI_NUMERICHOST | NI_NUMERICSERV);
int nEPollEvent = SRT_EPOLL_IN | SRT_EPOLL_ERR;
if (SRT_ERROR == srt_epoll_add_usock(hSRTEPoll, st_SRTClient.hSocket, &nEPollEvent))
{
ModuleHelp_IsErrorOccur = true;
ModuleHelp_dwErrorCode = ERROR_MODULE_HELP_SRT_ADD;
return false;
}
_xstprintf(st_SRTClient.tszClientAddr, _X("%s:%s"), tszAddrBuffer, tszPortBuffer);
st_Locker.lock();
stl_MapClients.insert(make_pair(st_SRTClient.hSocket, st_SRTClient));
st_Locker.unlock();
lpCall_Login(st_SRTClient.tszClientAddr, st_SRTClient.hSocket, m_lLogin);
return true;
}
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Recv(SRTSOCKET hSocket)
{
ModuleHelp_IsErrorOccur = false;
st_Locker.lock_shared();
auto stl_MapIterator = stl_MapClients.find(hSocket);
if (stl_MapIterator == stl_MapClients.end())
{
st_Locker.unlock_shared();
return false;
}
SRTCORE_CLIENTINFO st_SRTClient = stl_MapIterator->second;
st_Locker.unlock_shared();
XCHAR tszMsgBuffer[1500];
while (true)
{
int nRet = srt_recvmsg(hSocket, tszMsgBuffer, sizeof(tszMsgBuffer));
if (SRT_ERROR == nRet)
{
if (SRT_EASYNCRCV != srt_getlasterror(NULL))
{
return false;
}
break;
}
lpCall_Recv(st_SRTClient.tszClientAddr, hSocket, tszMsgBuffer, nRet, m_lRecv);
}
return true;
}
bool CModuleHelp_SrtCore::ModuleHelp_SrtCore_Leave(SRTSOCKET hSocket)
{
ModuleHelp_IsErrorOccur = false;
if (0 != hSocket)
{
XCHAR tszClientAddr[128];
memset(tszClientAddr, '\0', sizeof(tszClientAddr));
st_Locker.lock();
auto stl_MapIterator = stl_MapClients.find(hSocket);
if (stl_MapIterator != stl_MapClients.end())
{
_tcsxcpy(tszClientAddr, stl_MapIterator->second.tszClientAddr);
srt_epoll_remove_usock(hSRTEPoll, stl_MapIterator->second.hSocket);
srt_close(stl_MapIterator->second.hSocket);
stl_MapClients.erase(stl_MapIterator);
}
st_Locker.unlock();
lpCall_Leave(tszClientAddr, hSocket, m_lLeave);
}
return true;
}
//////////////////////////////////////////////////////////////////////////
// 线程函数
//////////////////////////////////////////////////////////////////////////
XHTHREAD CALLBACK CModuleHelp_SrtCore::ModuleHelp_SrtCore_Thread(XPVOID lParam)
{
CModuleHelp_SrtCore* pClass_This = (CModuleHelp_SrtCore*)lParam;
while (pClass_This->bRun)
{
int nSRTCount = 100;
SRTSOCKET hSRTClient[100];
int nSRTIndex = srt_epoll_wait(pClass_This->hSRTEPoll, hSRTClient, &nSRTCount, 0, 0, 100, 0, 0, 0, 0);
for (int i = 0; i < nSRTIndex; i++)
{
SRT_SOCKSTATUS nSRTStatus = srt_getsockstate(hSRTClient[i]);
if ((nSRTStatus == SRTS_BROKEN) || (nSRTStatus == SRTS_NONEXIST) || (nSRTStatus == SRTS_CLOSED))
{
pClass_This->ModuleHelp_SrtCore_Leave(hSRTClient[i]);
continue;
}
else if (hSRTClient[i] == pClass_This->hSRTSocket)
{
pClass_This->ModuleHelp_SrtCore_Accept(pClass_This->hSRTSocket);
}
else
{
pClass_This->ModuleHelp_SrtCore_Recv(hSRTClient[i]);
}
}
}
return 0;
}
\ No newline at end of file
#pragma once
/********************************************************************
// Created: 2023/07/28 13:40:26
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_Srt\ModuleHelp_SrtCore.h
// File Path: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ModuleHelp\ModuleHelp_Srt
// File Base: ModuleHelp_SrtCore
// File Ext: h
// Project: XEngine(网络通信引擎)
// Author: qyt
// Purpose: ModuleHelp_SrtCore
// History:
*********************************************************************/
typedef struct
{
XCHAR tszStreamBuffer[512];
XCHAR tszClientAddr[MAX_PATH];
int nIDLen;
SRTSOCKET hSocket;
}SRTCORE_CLIENTINFO;
class CModuleHelp_SrtCore
{
public:
CModuleHelp_SrtCore();
~CModuleHelp_SrtCore();
public:
bool ModuleHelp_SrtCore_Start(int nPort);
bool ModuleHelp_SrtCore_SetCallback(CALLBACK_NETCORE_SOCKET_NETEVENT_LOGIN fpCallePoll_Login, CALLBACK_NETCORE_SOCKET_NETEVENT_RECV fpCallePoll_Recv, CALLBACK_NETCORE_SOCKET_NETEVENT_LEAVE fpCallePoll_Leave, XPVOID lPLogin = NULL, XPVOID lPRecv = NULL, XPVOID lPLeave = NULL);
bool ModuleHelp_SrtCore_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen);
bool ModuleHelp_SrtCore_GetStreamID(SRTSOCKET hSocket, XCHAR* ptszSMSAddr, bool* pbPublish);
bool ModuleHelp_SrtCore_Close(LPCXSTR lpszClientAddr = NULL, SRTSOCKET hSocket = 0);
bool ModuleHelp_SrtCore_Destory();
protected:
bool ModuleHelp_SrtCore_Accept(SRTSOCKET hSRTSocket);
bool ModuleHelp_SrtCore_Recv(SRTSOCKET hSocket);
bool ModuleHelp_SrtCore_Leave(SRTSOCKET hSocket);
protected:
static XHTHREAD CALLBACK ModuleHelp_SrtCore_Thread(XPVOID lParam);
private:
bool bRun = false;
int hSRTEPoll = 0;
SRTSOCKET hSRTSocket;
private:
XPVOID m_lLogin;
XPVOID m_lRecv;
XPVOID m_lLeave;
CALLBACK_NETCORE_SOCKET_NETEVENT_LOGIN lpCall_Login;
CALLBACK_NETCORE_SOCKET_NETEVENT_RECV lpCall_Recv;
CALLBACK_NETCORE_SOCKET_NETEVENT_LEAVE lpCall_Leave;
private:
shared_mutex st_Locker;
unique_ptr<thread> pSDTThread;
private:
unordered_map<SRTSOCKET, SRTCORE_CLIENTINFO> stl_MapClients;
};
\ No newline at end of file
......@@ -4,4 +4,11 @@ EXPORTS
ModuleHelp_GetLastError
ModuleHelp_JT1078_BCDToString
ModuleHelp_JT1078_StringToBCD
\ No newline at end of file
ModuleHelp_JT1078_StringToBCD
ModuleHelp_SrtCore_Start
ModuleHelp_SrtCore_SetCallback
ModuleHelp_SrtCore_Send
ModuleHelp_SrtCore_GetStreamID
ModuleHelp_SrtCore_Close
ModuleHelp_SrtCore_Destory
\ No newline at end of file
......@@ -167,11 +167,13 @@
<ClInclude Include="ModuleHelp_Define.h" />
<ClInclude Include="ModuleHelp_Error.h" />
<ClInclude Include="ModuleHelp_JT1078\ModuleHelp_JT1078.h" />
<ClInclude Include="ModuleHelp_Srt\ModuleHelp_SrtCore.h" />
<ClInclude Include="pch.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp" />
<ClCompile Include="ModuleHelp_JT1078\ModuleHelp_JT1078.cpp" />
<ClCompile Include="ModuleHelp_Srt\ModuleHelp_SrtCore.cpp" />
<ClCompile Include="pch.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader>
......
......@@ -19,6 +19,12 @@
<Filter Include="源文件\ModuleHelp_JT1078">
<UniqueIdentifier>{944d79f0-5bb6-4f2d-a4ea-d3f7a864a3ca}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\ModuleHelp_Srt">
<UniqueIdentifier>{ea2ab8f4-de01-4f72-b26b-8492e6f6fa1e}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\ModuleHelp_Srt">
<UniqueIdentifier>{ee56b71a-ffa5-43b1-83e4-60b522a2c79d}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="framework.h">
......@@ -36,6 +42,9 @@
<ClInclude Include="ModuleHelp_JT1078\ModuleHelp_JT1078.h">
<Filter>头文件\ModuleHelp_JT1078</Filter>
</ClInclude>
<ClInclude Include="ModuleHelp_Srt\ModuleHelp_SrtCore.h">
<Filter>头文件\ModuleHelp_Srt</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="dllmain.cpp">
......@@ -47,6 +56,9 @@
<ClCompile Include="ModuleHelp_JT1078\ModuleHelp_JT1078.cpp">
<Filter>源文件\ModuleHelp_JT1078</Filter>
</ClCompile>
<ClCompile Include="ModuleHelp_Srt\ModuleHelp_SrtCore.cpp">
<Filter>源文件\ModuleHelp_Srt</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<None Include="XEngine_ModuleHelp.def">
......
#include "pch.h"
#include "ModuleHelp_JT1078/ModuleHelp_JT1078.h"
#include "ModuleHelp_Srt/ModuleHelp_SrtCore.h"
/********************************************************************
// Created: 2022/04/24 16:28:09
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ModuleHelp\pch.cpp
......@@ -15,6 +16,7 @@ bool ModuleHelp_IsErrorOccur = false;
XLONG ModuleHelp_dwErrorCode = 0;
//////////////////////////////////////////////////////////////////////////
CModuleHelp_JT1078 m_HelpJT1078;
CModuleHelp_SrtCore m_SrtCore;
//////////////////////////////////////////////////////////////////////////
/// 导出的函数
//////////////////////////////////////////////////////////////////////////
......@@ -36,4 +38,31 @@ extern "C" bool ModuleHelp_JT1078_BCDToString(XBYTE bySIMNumber[6], XCHAR * ptsz
extern "C" bool ModuleHelp_JT1078_StringToBCD(LPCXSTR lpszMsgBuffer, XBYTE * pbySIMNumber)
{
return m_HelpJT1078.ModuleHelp_JT1078_StringToBCD(lpszMsgBuffer, pbySIMNumber);
}
/************************************************************************/
/* 导出的SRT函数 */
/************************************************************************/
extern "C" bool ModuleHelp_SrtCore_Start(int nPort)
{
return m_SrtCore.ModuleHelp_SrtCore_Start(nPort);
}
extern "C" bool ModuleHelp_SrtCore_SetCallback(CALLBACK_NETCORE_SOCKET_NETEVENT_LOGIN fpCallePoll_Login, CALLBACK_NETCORE_SOCKET_NETEVENT_RECV fpCallePoll_Recv, CALLBACK_NETCORE_SOCKET_NETEVENT_LEAVE fpCallePoll_Leave, XPVOID lPLogin, XPVOID lPRecv, XPVOID lPLeave)
{
return m_SrtCore.ModuleHelp_SrtCore_SetCallback(fpCallePoll_Login, fpCallePoll_Recv, fpCallePoll_Leave, lPLogin, lPRecv, lPLeave);
}
extern "C" bool ModuleHelp_SrtCore_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen)
{
return m_SrtCore.ModuleHelp_SrtCore_Send(lpszClientAddr, lpszMsgBuffer, nMsgLen);
}
extern "C" bool ModuleHelp_SrtCore_GetStreamID(SRTSOCKET hSocket, XCHAR * ptszSMSAddr, bool* pbPublish)
{
return m_SrtCore.ModuleHelp_SrtCore_GetStreamID(hSocket, ptszSMSAddr, pbPublish);
}
extern "C" bool ModuleHelp_SrtCore_Close(LPCXSTR lpszClientAddr, SRTSOCKET hSocket)
{
return m_SrtCore.ModuleHelp_SrtCore_Close(lpszClientAddr, hSocket);
}
extern "C" bool ModuleHelp_SrtCore_Destory()
{
return m_SrtCore.ModuleHelp_SrtCore_Destory();
}
\ No newline at end of file
......@@ -17,11 +17,18 @@
#include <string.h>
#include <errno.h>
#include <time.h>
#include <memory>
#include <thread>
#include <shared_mutex>
#include <unordered_map>
#include <srt/srt.h>
using namespace std;
#include <XEngine_Include/XEngine_CommHdr.h>
#include <XEngine_Include/XEngine_Types.h>
#include <XEngine_Include/XEngine_ProtocolHdr.h>
#include <XEngine_Include/XEngine_BaseLib/BaseLib_Define.h>
#include <XEngine_Include/XEngine_BaseLib/BaseLib_Error.h>
#include <XEngine_Include/XEngine_Core/NetCore_Define.h>
#include <XEngine_Include/XEngine_Core/OPenSsl_Define.h>
#include <XEngine_Include/XEngine_Core/OPenSsl_Error.h>
#include "../XEngine_UserProtocol.h"
......@@ -42,5 +49,8 @@ extern bool ModuleHelp_IsErrorOccur;
extern XLONG ModuleHelp_dwErrorCode;
#ifdef _MSC_BUILD
#pragma comment(lib,"XEngine_BaseLib/XEngine_BaseLib")
#pragma comment(lib,"XEngine_Core/XEngine_OPenSsl")
#pragma comment(lib,"Ws2_32")
#pragma comment(lib,"srt")
#endif
\ No newline at end of file
......@@ -133,6 +133,64 @@ extern "C" bool ModuleProtocol_Packet_Push(XCHAR* ptszMsgBuffer, int* pInt_MsgLe
备注:
*********************************************************************/
extern "C" bool ModuleProtocol_Packet_Destroy(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PROTOCOLSTREAM * pSt_ProtocolStream);
/********************************************************************
函数名称:ModuleProtocol_Packet_HTTPPublishGet
函数功能:获取发布流的信息
参数.一:ptszMsgBuffer
In/Out:Out
类型:字符指针
可空:N
意思:输出协议缓冲区
参数.二:pInt_MsgLen
In/Out:Out
类型:整数型指针
可空:N
意思:输出缓冲区大小
参数.三:pppSt_PublishInfo
In/Out:In
类型:数据结构指针
可空:N
意思:输入发布流信息列表数据
参数.四:nListCount
In/Out:In
类型:整数型
可空:N
意思:输入数据个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleProtocol_Packet_HTTPPublishGet(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PUBLISHINFO*** pppSt_PublishInfo, int nListCount);
/********************************************************************
函数名称:ModuleProtocol_Packet_HTTPPullGet
函数功能:获取拉流的信息
参数.一:ptszMsgBuffer
In/Out:Out
类型:字符指针
可空:N
意思:输出协议缓冲区
参数.二:pInt_MsgLen
In/Out:Out
类型:整数型指针
可空:N
意思:输出缓冲区大小
参数.三:pppSt_PublishInfo
In/Out:In
类型:数据结构指针
可空:N
意思:输入拉流客户端数据
参数.四:nListCount
In/Out:In
类型:整数型
可空:N
意思:输入数据个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleProtocol_Packet_HTTPPullGet(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PULLLISTINFO*** pppSt_PullInfo, int nListCount);
/************************************************************************/
/* 导出的协议解析函数 */
/************************************************************************/
......
......@@ -249,4 +249,145 @@ bool CModuleProtocol_Packet::ModuleProtocol_Packet_Destroy(XCHAR* ptszMsgBuffer,
memcpy(ptszMsgBuffer, &st_ProcotolHdr, sizeof(XENGINE_PROTOCOLHDR));
memcpy(ptszMsgBuffer + sizeof(XENGINE_PROTOCOLHDR), pSt_ProtocolStream, sizeof(XENGINE_PROTOCOLSTREAM));
return true;
}
/********************************************************************
函数名称:ModuleProtocol_Packet_HTTPPublishGet
函数功能:获取发布流的信息
参数.一:ptszMsgBuffer
In/Out:Out
类型:字符指针
可空:N
意思:输出协议缓冲区
参数.二:pInt_MsgLen
In/Out:Out
类型:整数型指针
可空:N
意思:输出缓冲区大小
参数.三:pppSt_PublishInfo
In/Out:In
类型:数据结构指针
可空:N
意思:输入发布流信息列表数据
参数.四:nListCount
In/Out:In
类型:整数型
可空:N
意思:输入数据个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleProtocol_Packet::ModuleProtocol_Packet_HTTPPublishGet(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PUBLISHINFO*** pppSt_PublishInfo, int nListCount)
{
ModuleProtocol_IsErrorOccur = false;
if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen))
{
ModuleProtocol_IsErrorOccur = true;
ModuleProtocol_dwErrorCode = ERROR_MODULE_PROTOCOL_PACKET_PARAMENT;
return false;
}
Json::Value st_JsonRoot;
Json::Value st_JsonArray;
st_JsonRoot["code"] = 0;
st_JsonRoot["msg"] = "success";
for (int i = 0; i < nListCount; i++)
{
Json::Value st_JsonObject;
Json::Value st_JsonVideo;
Json::Value st_JsonAudio;
st_JsonObject["nClientCount"] = (*pppSt_PublishInfo)[i]->nClientCount;
st_JsonObject["tszSMSAddr"] = (*pppSt_PublishInfo)[i]->tszSMSAddr;
st_JsonObject["enStreamType"] = (*pppSt_PublishInfo)[i]->enStreamType;
st_JsonVideo["bEnable"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.bEnable;
if ((*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.bEnable)
{
st_JsonVideo["nBitRate"] = (Json::Value::UInt64)(*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.nBitRate;
st_JsonVideo["enAVCodec"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.enAVCodec;
st_JsonVideo["nWidth"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.nWidth;
st_JsonVideo["nHeight"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.nHeight;
st_JsonVideo["nFrameRate"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_VideoInfo.nFrameRate;
}
st_JsonAudio["bEnable"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.bEnable;
if ((*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.bEnable)
{
st_JsonAudio["nBitRate"] = (Json::Value::UInt64)(*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.nBitRate;
st_JsonAudio["enAVCodec"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.enAVCodec;
st_JsonAudio["nChannel"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.nChannel;
st_JsonAudio["nSampleRate"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.nSampleRate;
st_JsonAudio["nSampleFmt"] = (*pppSt_PublishInfo)[i]->st_AVInfo.st_AudioInfo.nSampleFmt;
}
st_JsonObject["st_VideoInfo"] = st_JsonVideo;
st_JsonObject["st_AudioInfo"] = st_JsonAudio;
st_JsonArray.append(st_JsonObject);
}
st_JsonRoot["Array"] = st_JsonArray;
*pInt_MsgLen = st_JsonRoot.toStyledString().length();
memcpy(ptszMsgBuffer, st_JsonRoot.toStyledString().c_str(), st_JsonRoot.toStyledString().length());
return true;
}
/********************************************************************
函数名称:ModuleProtocol_Packet_HTTPPullGet
函数功能:获取拉流的信息
参数.一:ptszMsgBuffer
In/Out:Out
类型:字符指针
可空:N
意思:输出协议缓冲区
参数.二:pInt_MsgLen
In/Out:Out
类型:整数型指针
可空:N
意思:输出缓冲区大小
参数.三:pppSt_PublishInfo
In/Out:In
类型:数据结构指针
可空:N
意思:输入拉流客户端数据
参数.四:nListCount
In/Out:In
类型:整数型
可空:N
意思:输入数据个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleProtocol_Packet::ModuleProtocol_Packet_HTTPPullGet(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PULLLISTINFO*** pppSt_PullInfo, int nListCount)
{
ModuleProtocol_IsErrorOccur = false;
if ((NULL == ptszMsgBuffer) || (NULL == pInt_MsgLen))
{
ModuleProtocol_IsErrorOccur = true;
ModuleProtocol_dwErrorCode = ERROR_MODULE_PROTOCOL_PACKET_PARAMENT;
return false;
}
Json::Value st_JsonRoot;
Json::Value st_JsonArray;
st_JsonRoot["code"] = 0;
st_JsonRoot["msg"] = "success";
for (int i = 0; i < nListCount; i++)
{
Json::Value st_JsonObject;
st_JsonObject["tszPushAddr"] = (*pppSt_PullInfo)[i]->tszPushAddr;
st_JsonObject["tszSMSAddr"] = (*pppSt_PullInfo)[i]->tszSMSAddr;
st_JsonObject["enStreamType"] = (*pppSt_PullInfo)[i]->enStreamType;
st_JsonArray.append(st_JsonObject);
}
st_JsonRoot["Array"] = st_JsonArray;
*pInt_MsgLen = st_JsonRoot.toStyledString().length();
memcpy(ptszMsgBuffer, st_JsonRoot.toStyledString().c_str(), st_JsonRoot.toStyledString().length());
return true;
}
\ No newline at end of file
......@@ -22,5 +22,8 @@ public:
bool ModuleProtocol_Packet_Create(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PROTOCOLSTREAM* pSt_ProtocolStream);
bool ModuleProtocol_Packet_Push(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PROTOCOLSTREAM* pSt_ProtocolStream, int nMsgLen, int nMsgType);
bool ModuleProtocol_Packet_Destroy(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, XENGINE_PROTOCOLSTREAM* pSt_ProtocolStream);
public:
bool ModuleProtocol_Packet_HTTPPublishGet(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PUBLISHINFO*** pppSt_PublishInfo, int nListCount);
bool ModuleProtocol_Packet_HTTPPullGet(XCHAR* ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PULLLISTINFO*** pppSt_PullInfo, int nListCount);
private:
};
\ No newline at end of file
......@@ -7,5 +7,7 @@ EXPORTS
ModuleProtocol_Packet_Create
ModuleProtocol_Packet_Push
ModuleProtocol_Packet_Destroy
ModuleProtocol_Packet_HTTPPublishGet
ModuleProtocol_Packet_HTTPPullGet
ModuleProtocol_Parse_HTTPForward
\ No newline at end of file
......@@ -47,6 +47,14 @@ extern "C" bool ModuleProtocol_Packet_Destroy(XCHAR * ptszMsgBuffer, int* pInt_M
{
return m_ProtocolPacket.ModuleProtocol_Packet_Destroy(ptszMsgBuffer, pInt_MsgLen, pSt_ProtocolStream);
}
extern "C" bool ModuleProtocol_Packet_HTTPPublishGet(XCHAR * ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PUBLISHINFO * **pppSt_PublishInfo, int nListCount)
{
return m_ProtocolPacket.ModuleProtocol_Packet_HTTPPublishGet(ptszMsgBuffer, pInt_MsgLen, pppSt_PublishInfo, nListCount);
}
extern "C" bool ModuleProtocol_Packet_HTTPPullGet(XCHAR * ptszMsgBuffer, int* pInt_MsgLen, STREAMMEDIA_PULLLISTINFO * **pppSt_PullInfo, int nListCount)
{
return m_ProtocolPacket.ModuleProtocol_Packet_HTTPPullGet(ptszMsgBuffer, pInt_MsgLen, pppSt_PullInfo, nListCount);
}
/************************************************************************/
/* 导出的协议解析函数 */
/************************************************************************/
......
......@@ -13,12 +13,15 @@
#include <tchar.h>
#endif
#endif //PCH_H
#include <list>
#include <json/json.h>
#include <errno.h>
using namespace std;
#include <XEngine_Include/XEngine_CommHdr.h>
#include <XEngine_Include/XEngine_Types.h>
#include <XEngine_Include/XEngine_ProtocolHdr.h>
#include "../XEngine_UserProtocol.h"
#include "../XEngine_ModuleSession/ModuleSession_Define.h"
#include "ModuleProtocol_Define.h"
#include "ModuleProtocol_Error.h"
/********************************************************************
......
......@@ -15,6 +15,20 @@ typedef struct
XCHAR tszClientID[128];
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enClientType;
}STREAMMEDIA_SESSIONCLIENT;
typedef struct
{
XENGINE_PROTOCOL_AVINFO st_AVInfo;
XCHAR tszSMSAddr[MAX_PATH];
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType;
int nClientCount;
}STREAMMEDIA_PUBLISHINFO;
typedef struct
{
XCHAR tszSMSAddr[MAX_PATH];
XCHAR tszPushAddr[MAX_PATH];
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType;
}STREAMMEDIA_PULLLISTINFO;
//////////////////////////////////////////////////////////////////////////
// 导出的函数
//////////////////////////////////////////////////////////////////////////
......@@ -122,6 +136,39 @@ extern "C" bool ModuleSession_PullStream_GetStreamType(LPCXSTR lpszClientAddr, E
备注:
*********************************************************************/
extern "C" bool ModuleSession_PullStream_Delete(LPCXSTR lpszClientAddr);
/********************************************************************
函数名称:ModuleSession_PullStream_Delete
函数功能:删除整个推流端关联的拉流地址
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:输入要处理的客户端
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PullStream_PublishDelete(LPCXSTR lpszClientAddr);
/********************************************************************
函数名称:ModuleSession_PullStream_GetList
函数功能:获取用户列表
参数.一:pppSt_PullList
In/Out:Out
类型:三级指针
可空:N
意思:输出用户列表数据
参数.二:pInt_ListCount
In/Out:Out
类型:整数型指针
可空:N
意思:输出列表个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PullStream_GetList(STREAMMEDIA_PULLLISTINFO*** pppSt_PullList, int* pInt_ListCount);
/*********************************************************************************
* 推流端导出会话模块 *
*********************************************************************************/
......@@ -138,12 +185,17 @@ extern "C" bool ModuleSession_PullStream_Delete(LPCXSTR lpszClientAddr);
类型:常量字符指针
可空:N
意思:输入流媒体ID
参数.三:enStreamType
In/Out:In
类型:枚举型
可空:N
意思:输入推流类型
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr);
extern "C" bool ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType);
/********************************************************************
函数名称:ModuleSession_PushStream_Destroy
函数功能:销毁一个管理器
......@@ -255,74 +307,6 @@ extern "C" bool ModuleSession_PushStream_GetHDRBuffer(LPCXSTR lpszClientAddr, XC
*********************************************************************/
extern "C" bool ModuleSession_PushStream_FindStream(LPCXSTR lpszSMSAddr, XCHAR* ptszClientAddr);
/********************************************************************
函数名称:ModuleSession_PushStream_Send
函数功能:投递一段数据给会话管理器
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:输入要操作的流
参数.二:lpszMsgBuffer
In/Out:In
类型:常量字符指针
可空:N
意思:输入要投递的数据缓冲区
参数.三:nMsgLen
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区大小
参数.四:nAVType
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区类型.0视频1音频
参数.五:nFrameType
In/Out:In
类型:整数型
可空:N
意思:输入帧类型,视频的关键帧还是PB
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PushStream_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, int nAVType, int nFrameType);
/********************************************************************
函数名称:ModuleSession_PushStream_Recv
函数功能:获取缓冲区队列数据
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:输入要操作的流
参数.二:lpszMsgBuffer
In/Out:In
类型:常量字符指针
可空:N
意思:输入要投递的数据缓冲区
参数.三:nMsgLen
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区大小
参数.四:nAVType
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区类型.0视频1音频
参数.五:nFrameType
In/Out:In
类型:整数型
可空:N
意思:输入帧类型,视频的关键帧还是PB
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PushStream_Recv(LPCXSTR lpszClientAddr, XCHAR** pptszMsgBuffer, int* pInt_MsgLen, int* pInt_AVType, int* pInt_FrameType);
/********************************************************************
函数名称:ModuleSession_PushStream_ClientInsert
函数功能:客户端插入
参数.一:lpszClientAddr
......@@ -421,4 +405,23 @@ extern "C" bool ModuleSession_PushStream_SetAVInfo(LPCXSTR lpszClientAddr, XENGI
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PushStream_GetAVInfo(LPCXSTR lpszClientAddr, XENGINE_PROTOCOL_AVINFO* pSt_AVInfo);
\ No newline at end of file
extern "C" bool ModuleSession_PushStream_GetAVInfo(LPCXSTR lpszClientAddr, XENGINE_PROTOCOL_AVINFO* pSt_AVInfo);
/********************************************************************
函数名称:ModuleSession_PushStream_GetInfo
函数功能:获取推流信息
参数.一:pppSt_ProtocolStream
In/Out:In/Out
类型:三级指针
可空:N
意思:输出推流统计信息
参数.二:pInt_ListCount
In/Out:Out
类型:整数型指针
可空:N
意思:输出获取到的个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
extern "C" bool ModuleSession_PushStream_GetInfo(STREAMMEDIA_PUBLISHINFO*** pppSt_ProtocolStream, int* pInt_ListCount);
\ No newline at end of file
......@@ -52,14 +52,14 @@ bool CModuleSession_PullStream::ModuleSession_PullStream_Insert(LPCXSTR lpszClie
{
Session_IsErrorOccur = false;
PULLSTREAM_CLIENTINFO* pSt_PullStream = new PULLSTREAM_CLIENTINFO;
STREAMMEDIA_PULLLISTINFO* pSt_PullStream = new STREAMMEDIA_PULLLISTINFO;
if (NULL == pSt_PullStream)
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_MALLOC;
return false;
}
memset(pSt_PullStream, '\0', sizeof(PULLSTREAM_CLIENTINFO));
memset(pSt_PullStream, '\0', sizeof(STREAMMEDIA_PULLLISTINFO));
pSt_PullStream->enStreamType = enStreamType;
_tcsxcpy(pSt_PullStream->tszSMSAddr, lpszSMSAddr);
......@@ -103,6 +103,44 @@ bool CModuleSession_PullStream::ModuleSession_PullStream_Delete(LPCXSTR lpszClie
return true;
}
/********************************************************************
函数名称:ModuleSession_PullStream_Delete
函数功能:删除整个推流端关联的拉流地址
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:输入要处理的客户端
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleSession_PullStream::ModuleSession_PullStream_PublishDelete(LPCXSTR lpszClientAddr)
{
Session_IsErrorOccur = false;
if (NULL == lpszClientAddr)
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_PARAMENT;
return false;
}
st_Locker.lock();
for (auto stl_MapIterator = stl_MapClient.begin(); stl_MapIterator != stl_MapClient.end(); )
{
if (0 == _tcsxnicmp(lpszClientAddr, stl_MapIterator->second->tszSMSAddr, _tcsxlen(lpszClientAddr)))
{
stl_MapIterator = stl_MapClient.erase(stl_MapIterator);
}
else
{
stl_MapIterator++;
}
}
st_Locker.unlock();
return true;
}
/********************************************************************
函数名称:ModuleSession_PullStream_GetSMSAddr
函数功能:获取客户端绑定的流ID
参数.一:lpszClientAddr
......@@ -227,4 +265,39 @@ bool CModuleSession_PullStream::ModuleSession_PullStream_GetStreamType(LPCXSTR l
*penStreamType = stl_MapIterator->second->enStreamType;
st_Locker.unlock_shared();
return true;
}
/********************************************************************
函数名称:ModuleSession_PullStream_GetList
函数功能:获取用户列表
参数.一:pppSt_PullList
In/Out:Out
类型:三级指针
可空:N
意思:输出用户列表数据
参数.二:pInt_ListCount
In/Out:Out
类型:整数型指针
可空:N
意思:输出列表个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleSession_PullStream::ModuleSession_PullStream_GetList(STREAMMEDIA_PULLLISTINFO*** pppSt_PullList, int* pInt_ListCount)
{
Session_IsErrorOccur = false;
st_Locker.lock_shared();
*pInt_ListCount = stl_MapClient.size();
BaseLib_OperatorMemory_Malloc((XPPPMEM)pppSt_PullList, stl_MapClient.size(), sizeof(STREAMMEDIA_PULLLISTINFO));
auto stl_MapIterator = stl_MapClient.begin();
for (int i = 0; stl_MapIterator != stl_MapClient.end(); stl_MapIterator++, i++)
{
(*pppSt_PullList)[i] = stl_MapIterator->second;
}
st_Locker.unlock_shared();
return true;
}
\ No newline at end of file
......@@ -10,14 +10,6 @@
// Purpose: 拉流端会话管理器
// History:
*********************************************************************/
typedef struct
{
XCHAR tszSMSAddr[MAX_PATH];
XCHAR tszPushAddr[MAX_PATH];
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType;
}PULLSTREAM_CLIENTINFO;
class CModuleSession_PullStream
{
public:
......@@ -29,8 +21,10 @@ public:
bool ModuleSession_PullStream_GetPushAddr(LPCXSTR lpszClientAddr, XCHAR* ptszPushAddr);
bool ModuleSession_PullStream_GetStreamType(LPCXSTR lpszClientAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE* penStreamType);
bool ModuleSession_PullStream_Delete(LPCXSTR lpszClientAddr);
bool ModuleSession_PullStream_PublishDelete(LPCXSTR lpszClientAddr);
bool ModuleSession_PullStream_GetList(STREAMMEDIA_PULLLISTINFO*** pppSt_PullList, int* pInt_ListCount);
private:
shared_mutex st_Locker;
private:
unordered_map<xstring, PULLSTREAM_CLIENTINFO*> stl_MapClient;
unordered_map<xstring, STREAMMEDIA_PULLLISTINFO*> stl_MapClient;
};
\ No newline at end of file
......@@ -33,12 +33,17 @@ CModuleSession_PushStream::~CModuleSession_PushStream()
类型:常量字符指针
可空:N
意思:输入流媒体ID
参数.三:enStreamType
In/Out:In
类型:枚举型
可空:N
意思:输入推流类型
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleSession_PushStream::ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr)
bool CModuleSession_PushStream::ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType)
{
Session_IsErrorOccur = false;
......@@ -61,15 +66,15 @@ bool CModuleSession_PushStream::ModuleSession_PushStream_Create(LPCXSTR lpszClie
pSt_Packet->st_ClientLocker = make_unique<mutex>();
pSt_Packet->st_MSGLocker = make_unique<mutex>();
pSt_Packet->pStl_ListClient = make_unique<list<STREAMMEDIA_SESSIONCLIENT>>();
pSt_Packet->pStl_ListPacket = make_unique<list<AVPACKET_MSGBUFFER>>();
pSt_Packet->pStl_MapPushStream = make_unique<unordered_map<int, AVPACKET_HDRBUFFER>>();
if ((NULL == pSt_Packet->pStl_ListPacket) || (NULL == pSt_Packet->pStl_ListClient))
if ((NULL == pSt_Packet->pStl_MapPushStream) || (NULL == pSt_Packet->pStl_ListClient))
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_MALLOC;
return false;
}
pSt_Packet->enStreamType = enStreamType;
_tcsxcpy(pSt_Packet->tszSMSAddr, lpszSMSAddr);
//是否存在
st_Locker.lock();
......@@ -457,160 +462,40 @@ bool CModuleSession_PushStream::ModuleSession_PushStream_FindStream(LPCXSTR lpsz
return true;
}
/********************************************************************
函数名称:ModuleSession_PushStream_Send
函数功能:投递一段数据给会话管理器
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:输入客户端地址
参数.二:lpszMsgBuffer
In/Out:In
类型:常量字符指针
可空:N
意思:输入要投递的数据缓冲区
参数.三:nMsgLen
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区大小
参数.四:nAVType
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区类型.0视频1音频
参数.五:nFrameType
In/Out:In
类型:整数型
函数名称:ModuleSession_PushStream_GetInfo
函数功能:获取推流信息
参数.一:pppSt_ProtocolStream
In/Out:In/Out
类型:三级指针
可空:N
意思:输出推流统计信息
参数.二:pInt_ListCount
In/Out:Out
类型:整数型指针
可空:N
意思:输入帧类型,视频的关键帧还是PB
意思:输出获取到的个数
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleSession_PushStream::ModuleSession_PushStream_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, int nAVType, int nFrameType)
bool CModuleSession_PushStream::ModuleSession_PushStream_GetInfo(STREAMMEDIA_PUBLISHINFO*** pppSt_ProtocolStream, int* pInt_ListCount)
{
Session_IsErrorOccur = false;
if (NULL == lpszClientAddr)
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_PARAMENT;
return false;
}
//是否存在
st_Locker.lock_shared();
unordered_map<xstring, PUSHSTREAM_PACKET*>::iterator stl_MapIterator = stl_MapPushStream.find(lpszClientAddr);
if (stl_MapIterator == stl_MapPushStream.end())
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_NOTFOUND;
st_Locker.unlock_shared();
return false;
}
AVPACKET_MSGBUFFER st_MSGBuffer;
memset(&st_MSGBuffer, '\0', sizeof(AVPACKET_MSGBUFFER));
st_MSGBuffer.nAVType = nAVType;
st_MSGBuffer.nFrameType = nFrameType;
st_MSGBuffer.nMsgLen = nMsgLen;
st_MSGBuffer.ptszMsgBuffer = (XCHAR*)malloc(nMsgLen);
if (NULL == st_MSGBuffer.ptszMsgBuffer)
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_MALLOC;
st_Locker.unlock_shared();
return false;
}
memcpy(st_MSGBuffer.ptszMsgBuffer, lpszMsgBuffer, nMsgLen);
*pInt_ListCount = stl_MapPushStream.size();
BaseLib_OperatorMemory_Malloc((XPPPMEM)pppSt_ProtocolStream, stl_MapPushStream.size(), sizeof(STREAMMEDIA_PUBLISHINFO));
stl_MapIterator->second->st_MSGLocker->lock();
//视频?
if (0 == nAVType)
{
//遇到关键帧
if (1 == nFrameType)
{
//释放所有包
for (auto stl_ListIterator = stl_MapIterator->second->pStl_ListPacket->begin(); stl_ListIterator != stl_MapIterator->second->pStl_ListPacket->end(); stl_ListIterator++)
{
free(stl_ListIterator->ptszMsgBuffer);
}
stl_MapIterator->second->pStl_ListPacket->clear();
}
}
stl_MapIterator->second->pStl_ListPacket->push_back(st_MSGBuffer);
stl_MapIterator->second->st_MSGLocker->unlock();
st_Locker.unlock_shared();
return true;
}
/********************************************************************
函数名称:ModuleSession_PushStream_Recv
函数功能:获取缓冲区队列数据
参数.一:lpszClientAddr
In/Out:In
类型:常量字符指针
可空:N
意思:输入客户端地址
参数.二:lpszMsgBuffer
In/Out:In
类型:常量字符指针
可空:N
意思:输入要投递的数据缓冲区
参数.三:nMsgLen
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区大小
参数.四:nAVType
In/Out:In
类型:整数型
可空:N
意思:输入缓冲区类型.0视频1音频
参数.五:nFrameType
In/Out:In
类型:整数型
可空:N
意思:输入帧类型,视频的关键帧还是PB
返回值
类型:逻辑型
意思:是否成功
备注:
*********************************************************************/
bool CModuleSession_PushStream::ModuleSession_PushStream_Recv(LPCXSTR lpszClientAddr, XCHAR** pptszMsgBuffer, int* pInt_MsgLen, int* pInt_AVType, int* pInt_FrameType)
{
Session_IsErrorOccur = false;
if (NULL == lpszClientAddr)
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_PARAMENT;
return false;
}
//是否存在
st_Locker.lock_shared();
unordered_map<xstring, PUSHSTREAM_PACKET*>::iterator stl_MapIterator = stl_MapPushStream.find(lpszClientAddr);
if (stl_MapIterator == stl_MapPushStream.end())
unordered_map<xstring, PUSHSTREAM_PACKET*>::iterator stl_MapIterator = stl_MapPushStream.begin();
for (int i = 0; stl_MapIterator != stl_MapPushStream.end(); stl_MapIterator++, i++)
{
Session_IsErrorOccur = true;
Session_dwErrorCode = ERROR_STREAMMEDIA_MODULE_SESSION_NOTFOUND;
st_Locker.unlock_shared();
return false;
(*pppSt_ProtocolStream)[i]->nClientCount = stl_MapIterator->second->pStl_ListClient->size();
(*pppSt_ProtocolStream)[i]->enStreamType = stl_MapIterator->second->enStreamType;
(*pppSt_ProtocolStream)[i]->st_AVInfo = stl_MapIterator->second->st_AVInfo;
_tcsxcpy((*pppSt_ProtocolStream)[i]->tszSMSAddr, stl_MapIterator->second->tszSMSAddr);
}
//输出内容
stl_MapIterator->second->st_MSGLocker->lock();
AVPACKET_MSGBUFFER st_MSGBuffer = stl_MapIterator->second->pStl_ListPacket->front();
stl_MapIterator->second->pStl_ListPacket->pop_front();
*pInt_AVType = st_MSGBuffer.nAVType;
*pInt_FrameType = st_MSGBuffer.nFrameType;
*pInt_MsgLen = st_MSGBuffer.nMsgLen;
*pptszMsgBuffer = st_MSGBuffer.ptszMsgBuffer;
stl_MapIterator->second->st_MSGLocker->unlock();
st_Locker.unlock_shared();
return true;
}
......
......@@ -10,13 +10,6 @@
// Purpose: 推流全局会话
// History:
*********************************************************************/
typedef struct
{
int nAVType; //包类型
int nFrameType; //帧类型
int nMsgLen; //大小
XCHAR* ptszMsgBuffer;
}AVPACKET_MSGBUFFER;
typedef struct
{
XCHAR tszMsgBuffer[2048]; //缓存的头
......@@ -27,12 +20,12 @@ typedef struct
{
XENGINE_PROTOCOL_AVINFO st_AVInfo;
XCHAR tszSMSAddr[MAX_PATH];
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType;
unique_ptr<mutex> st_MSGLocker;
unique_ptr<mutex> st_ClientLocker;
unique_ptr<list<STREAMMEDIA_SESSIONCLIENT>> pStl_ListClient;
unique_ptr<list<AVPACKET_MSGBUFFER>> pStl_ListPacket;
unique_ptr<unordered_map<int, AVPACKET_HDRBUFFER>> pStl_MapPushStream;
}PUSHSTREAM_PACKET;
......@@ -42,7 +35,7 @@ public:
CModuleSession_PushStream();
~CModuleSession_PushStream();
public:
bool ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr);
bool ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType);
bool ModuleSession_PushStream_Destroy(LPCXSTR lpszClientAddr);
bool ModuleSession_PushStream_GetAddrForAddr(LPCXSTR lpszClientAddr, XCHAR* ptszSMSAddr);
bool ModuleSession_PushStream_SetHDRBuffer(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType);
......@@ -50,8 +43,7 @@ public:
bool ModuleSession_PushStream_SetAVInfo(LPCXSTR lpszClientAddr, XENGINE_PROTOCOL_AVINFO *pSt_AVInfo);
bool ModuleSession_PushStream_GetAVInfo(LPCXSTR lpszClientAddr, XENGINE_PROTOCOL_AVINFO* pSt_AVInfo);
bool ModuleSession_PushStream_FindStream(LPCXSTR lpszSMSAddr, XCHAR* ptszClientAddr);
bool ModuleSession_PushStream_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, int nAVType, int nFrameType);
bool ModuleSession_PushStream_Recv(LPCXSTR lpszClientAddr, XCHAR** pptszMsgBuffer, int* pInt_MsgLen, int* pInt_AVType, int* pInt_FrameType);
bool ModuleSession_PushStream_GetInfo(STREAMMEDIA_PUBLISHINFO*** pppSt_ProtocolStream, int* pInt_ListCount);
public:
bool ModuleSession_PushStream_ClientInsert(LPCXSTR lpszClientAddr, LPCXSTR lpszPullAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType);
bool ModuleSession_PushStream_ClientDelete(LPCXSTR lpszClientAddr, LPCXSTR lpszPullAddr);
......
......@@ -8,6 +8,8 @@ EXPORTS
ModuleSession_PullStream_GetPushAddr
ModuleSession_PullStream_GetStreamType
ModuleSession_PullStream_Delete
ModuleSession_PullStream_PublishDelete
ModuleSession_PullStream_GetList
ModuleSession_PushStream_Create
ModuleSession_PushStream_Destroy
......@@ -15,10 +17,9 @@ EXPORTS
ModuleSession_PushStream_SetHDRBuffer
ModuleSession_PushStream_GetHDRBuffer
ModuleSession_PushStream_FindStream
ModuleSession_PushStream_Send
ModuleSession_PushStream_Recv
ModuleSession_PushStream_ClientInsert
ModuleSession_PushStream_ClientDelete
ModuleSession_PushStream_ClientList
ModuleSession_PushStream_SetAVInfo
ModuleSession_PushStream_GetAVInfo
\ No newline at end of file
ModuleSession_PushStream_GetAVInfo
ModuleSession_PushStream_GetInfo
\ No newline at end of file
......@@ -51,12 +51,20 @@ extern "C" bool ModuleSession_PullStream_Delete(LPCXSTR lpszClientAddr)
{
return m_PullStream.ModuleSession_PullStream_Delete(lpszClientAddr);
}
extern "C" bool ModuleSession_PullStream_PublishDelete(LPCXSTR lpszClientAddr)
{
return m_PullStream.ModuleSession_PullStream_PublishDelete(lpszClientAddr);
}
extern "C" bool ModuleSession_PullStream_GetList(STREAMMEDIA_PULLLISTINFO * **pppSt_PullList, int* pInt_ListCount)
{
return m_PullStream.ModuleSession_PullStream_GetList(pppSt_PullList, pInt_ListCount);
}
/*********************************************************************************
* 推流导出会话模块 *
*********************************************************************************/
extern "C" bool ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr)
extern "C" bool ModuleSession_PushStream_Create(LPCXSTR lpszClientAddr, LPCXSTR lpszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType)
{
return m_PushStream.ModuleSession_PushStream_Create(lpszClientAddr, lpszSMSAddr);
return m_PushStream.ModuleSession_PushStream_Create(lpszClientAddr, lpszSMSAddr, enStreamType);
}
extern "C" bool ModuleSession_PushStream_Destroy(LPCXSTR lpszClientAddr)
{
......@@ -78,14 +86,6 @@ extern "C" bool ModuleSession_PushStream_FindStream(LPCXSTR lpszSMSAddr, XCHAR *
{
return m_PushStream.ModuleSession_PushStream_FindStream(lpszSMSAddr, ptszClientAddr);
}
extern "C" bool ModuleSession_PushStream_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, int nAVType, int nFrameType)
{
return m_PushStream.ModuleSession_PushStream_Send(lpszClientAddr, lpszMsgBuffer, nMsgLen, nAVType, nFrameType);
}
extern "C" bool ModuleSession_PushStream_Recv(LPCXSTR lpszClientAddr, XCHAR * *pptszMsgBuffer, int* pInt_MsgLen, int* pInt_AVType, int* pInt_FrameType)
{
return m_PushStream.ModuleSession_PushStream_Recv(lpszClientAddr, pptszMsgBuffer, pInt_MsgLen, pInt_AVType, pInt_FrameType);
}
extern "C" bool ModuleSession_PushStream_ClientInsert(LPCXSTR lpszClientAddr, LPCXSTR lpszPullAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enStreamType)
{
return m_PushStream.ModuleSession_PushStream_ClientInsert(lpszClientAddr, lpszPullAddr, enStreamType);
......@@ -105,4 +105,8 @@ extern "C" bool ModuleSession_PushStream_SetAVInfo(LPCXSTR lpszClientAddr, XENGI
extern "C" bool ModuleSession_PushStream_GetAVInfo(LPCXSTR lpszClientAddr, XENGINE_PROTOCOL_AVINFO * pSt_AVInfo)
{
return m_PushStream.ModuleSession_PushStream_GetAVInfo(lpszClientAddr, pSt_AVInfo);
}
extern "C" bool ModuleSession_PushStream_GetInfo(STREAMMEDIA_PUBLISHINFO * **pppSt_ProtocolStream, int* pInt_ListCount)
{
return m_PushStream.ModuleSession_PushStream_GetInfo(pppSt_ProtocolStream, pInt_ListCount);
}
\ No newline at end of file
......@@ -10,10 +10,11 @@ LOADSO = -L /usr/local/lib/XEngine_Release/XEngine_BaseLib -L /usr/local/lib/XEn
-L ../../XEngine_ThirdPart/jsoncpp
LIB = -lXEngine_BaseLib -lXEngine_Algorithm -lXEngine_Core -lXEngine_ManagePool -lHelpComponents_XLog -lHelpComponents_Packets -lNetHelp_APIHelp -lRfcComponents_HttpProtocol -lXEngine_AVHelp -lStreamMedia_FLVProtocol -lStreamMedia_RTMPProtocol \
-lXEngine_ModuleConfigure -lXEngine_ModuleProtocol -lXEngine_ModuleSession -lXEngine_ModuleHelp \
-ljsoncpp
-ljsoncpp -lsrt
LIBEX =
OBJECTS = PullStream_ClientTask.o \
PushStream_JT1078Task.o PushStream_RTMPTask.o PushStream_XStreamTask.o \
PushStream_JT1078Task.o PushStream_RTMPTask.o PushStream_XStreamTask.o PushStream_SrtTask.o \
StreamMedia_HTTPApi.o \
XEngine_AVPacket.o XEngine_Configure.o XEngine_HttpTask.o XEngine_Network.o XEngine_StreamMediaApp.o
ifeq ($(RELEASE),1)
......@@ -60,6 +61,11 @@ PushStream_JT1078Task.o:./StreamMedia_PushStream/PushStream_JT1078Task.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./StreamMedia_PushStream/PushStream_JT1078Task.cpp
PushStream_RTMPTask.o:./StreamMedia_PushStream/PushStream_RTMPTask.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./StreamMedia_PushStream/PushStream_RTMPTask.cpp
PushStream_SrtTask.o:./StreamMedia_PushStream/PushStream_SrtTask.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./StreamMedia_PushStream/PushStream_SrtTask.cpp
StreamMedia_HTTPApi.o:./StreamMedia_HTTPApi/StreamMedia_HTTPApi.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./StreamMedia_HTTPApi/StreamMedia_HTTPApi.cpp
XEngine_AVPacket.o:./XEngine_AVPacket.cpp
$(CC) $(DEBUG) $(FLAGS) $(UNICODE) $(PLATVER) $(LOADHDR) ./XEngine_AVPacket.cpp
......
#include "../XEngine_Hdr.h"
/********************************************************************
// Created: 2023/07/31 15:17:45
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_HTTPApi\StreamMedia_HTTPApi.cpp
// File Path: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_HTTPApi
// File Base: StreamMedia_HTTPApi
// File Ext: cpp
// Project: XEngine(网络通信引擎)
// Author: qyt
// Purpose: HTTP管理接口
// History:
*********************************************************************/
bool HTTPApi_Management_Task(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, int nListCount)
{
int nRVLen = 0;
int nSDLen = 0;
XCHAR tszRVBuffer[4096];
XCHAR tszSDBuffer[4096];
XCHAR tszKeyBuffer[MAX_PATH];
XCHAR tszVluBuffer[MAX_PATH];
LPCXSTR lpszAPIPublish = _X("publish");
LPCXSTR lpszAPIPull = _X("pull");
LPCXSTR lpszAPIGet = _X("get");
RFCCOMPONENTS_HTTP_HDRPARAM st_HDRParam;
memset(tszRVBuffer, '\0', sizeof(tszRVBuffer));
memset(tszSDBuffer, '\0', sizeof(tszSDBuffer));
memset(tszKeyBuffer, '\0', sizeof(tszKeyBuffer));
memset(tszVluBuffer, '\0', sizeof(tszVluBuffer));
memset(&st_HDRParam, '\0', sizeof(RFCCOMPONENTS_HTTP_HDRPARAM));
st_HDRParam.nHttpCode = 200; //HTTP CODE码
st_HDRParam.bIsClose = true; //收到回复后就关闭
BaseLib_OperatorString_GetKeyValue((*ppptszListHdr)[0], "=", tszKeyBuffer, tszVluBuffer);
if (0 == _tcsxnicmp(lpszAPIPublish, tszVluBuffer, _tcsxlen(lpszAPIPublish)))
{
//获取发布流:http://127.0.0.1:5600?api?function=publish&method=get
memset(tszKeyBuffer, '\0', sizeof(tszKeyBuffer));
memset(tszVluBuffer, '\0', sizeof(tszVluBuffer));
BaseLib_OperatorString_GetKeyValue((*ppptszListHdr)[1], "=", tszKeyBuffer, tszVluBuffer);
if (0 == _tcsxnicmp(lpszAPIGet, tszVluBuffer, _tcsxlen(lpszAPIGet)))
{
int nListCount = 0;
STREAMMEDIA_PUBLISHINFO** ppSt_ProtocolStream;
ModuleSession_PushStream_GetInfo(&ppSt_ProtocolStream, &nListCount);
ModuleProtocol_Packet_HTTPPublishGet(tszRVBuffer, &nRVLen, &ppSt_ProtocolStream, nListCount);
HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen);
XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP接口:%s,请求获取发布流信息成功,个数:d"), lpszClientAddr, nListCount);
BaseLib_OperatorMemory_Free((XPPPMEM)&ppSt_ProtocolStream, nListCount);
}
}
else if (0 == _tcsxnicmp(lpszAPIPull, tszVluBuffer, _tcsxlen(lpszAPIPull)))
{
//获取订阅流:http://127.0.0.1:5600/api?function=pull&method=get
memset(tszKeyBuffer, '\0', sizeof(tszKeyBuffer));
memset(tszVluBuffer, '\0', sizeof(tszVluBuffer));
BaseLib_OperatorString_GetKeyValue((*ppptszListHdr)[1], "=", tszKeyBuffer, tszVluBuffer);
if (0 == _tcsxnicmp(lpszAPIGet, tszVluBuffer, _tcsxlen(lpszAPIGet)))
{
int nListCount = 0;
STREAMMEDIA_PULLLISTINFO** ppSt_PullList;
ModuleSession_PullStream_GetList(&ppSt_PullList, &nListCount);
ModuleProtocol_Packet_HTTPPullGet(tszRVBuffer, &nRVLen, &ppSt_PullList, nListCount);
HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen);
XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("HTTP接口:%s,请求获取订阅流信息成功,个数:d"), lpszClientAddr, nListCount);
BaseLib_OperatorMemory_Free((XPPPMEM)&ppSt_PullList, nListCount);
}
}
return true;
}
\ No newline at end of file
#pragma once
/********************************************************************
// Created: 2023/07/31 15:17:01
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_HTTPApi\StreamMedia_HTTPApi.h
// File Path: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_HTTPApi
// File Base: StreamMedia_HTTPApi
// File Ext: h
// Project: XEngine(网络通信引擎)
// Author: qyt
// Purpose: HTTP管理接口
// History:
*********************************************************************/
//任务处理相关函数,处理包的内容
bool HTTPApi_Management_Task(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr, int nListCount);
\ No newline at end of file
......@@ -37,14 +37,16 @@ bool PullStream_ClientTask_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr
{
//播放流:http://127.0.0.1:5600/api?stream=play&sms=live/qyt&type=flv
XCHAR tszPushAddr[MAX_PATH];
XCHAR tszSMSAddr[MAX_PATH];
memset(tszPushAddr, '\0', sizeof(tszPushAddr));
memset(tszSMSAddr, '\0', sizeof(tszSMSAddr));
memset(tszKeyBuffer, '\0', sizeof(tszKeyBuffer));
memset(tszVluBuffer, '\0', sizeof(tszVluBuffer));
BaseLib_OperatorString_GetKeyValue((*ppptszListHdr)[1], "=", tszKeyBuffer, tszVluBuffer);
BaseLib_OperatorString_GetKeyValue((*ppptszListHdr)[1], "=", tszKeyBuffer, tszSMSAddr);
if (!ModuleSession_PushStream_FindStream(tszVluBuffer, tszPushAddr))
if (!ModuleSession_PushStream_FindStream(tszSMSAddr, tszPushAddr))
{
ModuleProtocol_Packet_Comm(tszRVBuffer, &nRVLen, NULL, 404, "not found");
HttpProtocol_Server_SendMsgEx(xhHttpPacket, tszSDBuffer, &nSDLen, &st_HDRParam, tszRVBuffer, nRVLen);
......@@ -76,7 +78,7 @@ bool PullStream_ClientTask_Handle(LPCXSTR lpszClientAddr, XCHAR*** ppptszListHdr
ModuleSession_PushStream_GetHDRBuffer(tszPushAddr, tszSDBuffer, &nSDLen, enStreamType);
XEngine_Network_Send(lpszClientAddr, tszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP);
ModuleSession_PullStream_Insert(lpszClientAddr, tszVluBuffer, tszPushAddr, enStreamType);
ModuleSession_PullStream_Insert(lpszClientAddr, tszSMSAddr, tszPushAddr, enStreamType);
ModuleSession_PushStream_ClientInsert(tszPushAddr, lpszClientAddr, enStreamType);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("拉流端:%s,请求拉流数据成功:%s"), lpszClientAddr, tszVluBuffer);
}
......
......@@ -237,7 +237,7 @@ bool PushStream_RTMPTask_Handle(XENGINE_RTMPHDR* pSt_RTMPHdr, LPCXSTR lpszClient
//////////////////////////////////////////////////////////////////////////
//创建流
XEngine_AVPacket_AVCreate(lpszClientAddr);
ModuleSession_PushStream_Create(lpszClientAddr, tszSMSAddr);
ModuleSession_PushStream_Create(lpszClientAddr, tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP);
//释放内存
BaseLib_OperatorMemory_Free((XPPPMEM)&st_RTMPCommand.ppSt_CMDProperty, st_RTMPCommand.nProCount);
BaseLib_OperatorMemory_Free((XPPPMEM)&st_RTMPCommand.ppSt_CMDObject, st_RTMPCommand.nObCount);
......@@ -297,11 +297,6 @@ bool PushStream_RTMPTask_Handle(XENGINE_RTMPHDR* pSt_RTMPHdr, LPCXSTR lpszClient
BaseLib_OperatorMemory_Free((XPPPMEM)&st_RTMPCommand.ppSt_CMDObject, st_RTMPCommand.nObCount);
st_RTMPCommand.nProCount = 0;
st_RTMPCommand.nObCount = 0;
XEngine_AVPacket_AVDelete(lpszClientAddr);
RTMPProtocol_Parse_Delete(lpszClientAddr);
ModuleSession_PushStream_Destroy(lpszClientAddr);
RTMPProtocol_Help_PKTCommand(ptszSDBuffer, &nSDLen, 5, &st_RTMPCommand);
XEngine_Network_Send(lpszClientAddr, ptszSDBuffer, nSDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP);
}
......@@ -404,7 +399,7 @@ bool PushStream_RTMPTask_Handle(XENGINE_RTMPHDR* pSt_RTMPHdr, LPCXSTR lpszClient
XENGINE_RTMPAUDIO st_RTMPAudio;
memset(&st_RTMPAudio, '\0', sizeof(XENGINE_RTMPAUDIO));
RTMPProtocol_Help_ParseAudio(&st_RTMPAudio, ptszRVBuffer, &nRVLen, lpszMsgBuffer, nMsgLen);
memcpy(&st_RTMPAudio, lpszMsgBuffer, sizeof(XENGINE_RTMPAUDIO));
if (0 == st_RTMPAudio.byPKTType)
{
XEngine_AVPacket_AVHdr(lpszClientAddr, lpszMsgBuffer, nMsgLen, 1, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP);
......@@ -417,7 +412,7 @@ bool PushStream_RTMPTask_Handle(XENGINE_RTMPHDR* pSt_RTMPHdr, LPCXSTR lpszClient
XENGINE_RTMPVIDEO st_RTMPVideo;
memset(&st_RTMPVideo, '\0', sizeof(XENGINE_RTMPVIDEO));
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, ptszRVBuffer, &nRVLen, lpszMsgBuffer, nMsgLen);
memcpy(&st_RTMPVideo, lpszMsgBuffer, sizeof(XENGINE_RTMPVIDEO));
if (0 == st_RTMPVideo.byAVCType)
{
XEngine_AVPacket_AVHdr(lpszClientAddr, lpszMsgBuffer, nMsgLen, 0, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP);
......
#include "../XEngine_Hdr.h"
/********************************************************************
// Created: 2023/07/28 16:12:02
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_PushStream\PushStream_SrtTask.cpp
// File Path: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_PushStream
// File Base: PushStream_SrtTask
// File Ext: cpp
// Project: XEngine(网络通信引擎)
// Author: qyt
// Purpose: SRT推拉流代码
// History:
*********************************************************************/
bool PushStream_SrtTask_Connct(LPCXSTR lpszClientAddr, SRTSOCKET hSocket)
{
bool bPublish = false;
XCHAR tszSMSAddr[MAX_PATH];
memset(tszSMSAddr, '\0', sizeof(tszSMSAddr));
if (!ModuleHelp_SrtCore_GetStreamID(hSocket, tszSMSAddr, &bPublish))
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("SRT客户端:获取流ID信息失败,错误码:%lX,错误信息:%s"), ModuleHelp_GetLastError(), srt_getlasterror_str());
return false;
}
if (bPublish)
{
//创建会话
ModuleSession_PushStream_Create(lpszClientAddr, tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT);
//need to parse ts stream
ModuleSession_PushStream_SetHDRBuffer(lpszClientAddr, NULL, 0, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_SRT);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("SRT客户端:%s,创建流成功,推流地址:%s,类型:推流端"), lpszClientAddr, tszSMSAddr);
}
else
{
XCHAR tszPushAddr[128];
memset(tszPushAddr, '\0', sizeof(tszPushAddr));
//得到推流地址
if (!ModuleSession_PushStream_FindStream(tszSMSAddr, tszPushAddr))
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("SRT客户端:%s,请求拉流的参数不正确:%s,错误:%lX"), lpszClientAddr, tszSMSAddr, ModuleSession_GetLastError());
return false;
}
ModuleSession_PullStream_Insert(lpszClientAddr, tszSMSAddr, tszPushAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_SRT);
ModuleSession_PushStream_ClientInsert(tszPushAddr, lpszClientAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_SRT);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("SRT客户端:%s,拉取流成功,拉流地址:%s,类型:拉流端"), lpszClientAddr, tszSMSAddr);
}
return true;
}
bool PushStream_SrtTask_Handle(LPCXSTR lpszClientAddr, SRTSOCKET hSocket, LPCXSTR lpszMsgBuffer, int nMsgLen)
{
list<STREAMMEDIA_SESSIONCLIENT> stl_ListClient;
ModuleSession_PushStream_ClientList(lpszClientAddr, &stl_ListClient);
for (auto stl_ListIteratorClient = stl_ListClient.begin(); stl_ListIteratorClient != stl_ListClient.end(); ++stl_ListIteratorClient)
{
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_SRT == stl_ListIteratorClient->enClientType)
{
XEngine_Network_Send(stl_ListIteratorClient->tszClientID, lpszMsgBuffer, nMsgLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT);
break;
}
}
return true;
}
\ No newline at end of file
#pragma once
/********************************************************************
// Created: 2023/07/28 16:11:23
// File Name: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_PushStream\PushStream_SrtTask.h
// File Path: D:\XEngine_StreamMedia\XEngine_Source\XEngine_ServiceApp\XEngine_StreamMediaApp\StreamMedia_PushStream
// File Base: PushStream_SrtTask
// File Ext: h
// Project: XEngine(网络通信引擎)
// Author: qyt
// Purpose: SRT推拉流代码
// History:
*********************************************************************/
bool PushStream_SrtTask_Connct(LPCXSTR lpszClientAddr, SRTSOCKET hSocket);
//任务处理相关函数,处理包的内容
bool PushStream_SrtTask_Handle(LPCXSTR lpszClientAddr, SRTSOCKET hSocket, LPCXSTR lpszMsgBuffer, int nMsgLen);
\ No newline at end of file
......@@ -50,6 +50,7 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
{
if (st_ServiceConfig.st_XPull.st_PullFlv.bEnable)
{
//启用了FLV,把所有流转为FLV
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM == enClientType)
{
XENGINE_PROTOCOLSTREAM st_ProtocolStream;
......@@ -81,7 +82,7 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
nHLen += nPLen;
}
//创建会话
ModuleSession_PushStream_Create(lpszClientAddr, st_ProtocolStream.tszSMSAddr);
ModuleSession_PushStream_Create(lpszClientAddr, st_ProtocolStream.tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM);
ModuleSession_PushStream_SetHDRBuffer(lpszClientAddr, tszHDRBuffer, nHLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_FLV);
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP == enClientType)
......@@ -107,7 +108,7 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
memset(&st_RTMPVParam, '\0', sizeof(XENGINE_RTMPVIDEOPARAM));
memcpy(&st_RTMPVideo, lpszMsgBuffer, sizeof(XENGINE_RTMPVIDEO));
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, st_AVInfo.st_VideoInfo.tszVInfo, &st_AVInfo.st_VideoInfo.nVLen, lpszMsgBuffer, nMsgLen, &st_RTMPVParam);
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, st_AVInfo.st_VideoInfo.tszVInfo, &st_AVInfo.st_VideoInfo.nVLen, lpszMsgBuffer + sizeof(XENGINE_RTMPVIDEO), nMsgLen - sizeof(XENGINE_RTMPVIDEO), &st_RTMPVParam);
ModuleSession_PushStream_SetAVInfo(lpszClientAddr, &st_AVInfo);
}
//是否全部设置完毕
......@@ -166,8 +167,41 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
}
if (st_ServiceConfig.st_XPull.st_PullRtmp.bEnable)
{
//rtmp可用
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP == enClientType)
//启用了RTMP,把所有流转RTMP
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM == enClientType)
{
XENGINE_PROTOCOLSTREAM st_ProtocolStream;
memset(&st_ProtocolStream, '\0', sizeof(XENGINE_PROTOCOLSTREAM));
memcpy(&st_ProtocolStream, lpszMsgBuffer, sizeof(XENGINE_PROTOCOLSTREAM));
//创建流
RTMPProtocol_Packet_Insert(lpszClientAddr);
int nPLen = 0;
int nHLen = 0;
XCHAR tszHDRBuffer[1024];
memset(tszHDRBuffer, '\0', sizeof(tszHDRBuffer));
//打包FLV
st_ProtocolStream.st_AVInfo.st_VideoInfo.enAVCodec = 7;
_tcsxcpy(st_ProtocolStream.st_AVInfo.tszPktName, _X("Lavf58.76.100"));
RTMPProtocol_Packet_SetTime(lpszClientAddr, st_ProtocolStream.st_AVInfo.st_VideoInfo.nFrameRate, st_ProtocolStream.st_AVInfo.st_AudioInfo.nSampleRate);
RTMPProtocol_Packet_FrameAVScript(tszHDRBuffer + nHLen, &nPLen, &st_ProtocolStream.st_AVInfo);
nHLen += nPLen;
if (st_ProtocolStream.st_AVInfo.st_VideoInfo.bEnable)
{
RTMPProtocol_Packet_FrameAVCConfigure(tszHDRBuffer + nHLen, &nPLen, &st_ProtocolStream.st_AVInfo);
nHLen += nPLen;
}
if (st_ProtocolStream.st_AVInfo.st_AudioInfo.bEnable)
{
RTMPProtocol_Packet_FrameAACConfigure(tszHDRBuffer + nHLen, &nPLen, &st_ProtocolStream.st_AVInfo);
nHLen += nPLen;
}
//创建会话
ModuleSession_PushStream_Create(lpszClientAddr, st_ProtocolStream.tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM);
ModuleSession_PushStream_SetHDRBuffer(lpszClientAddr, tszHDRBuffer, nHLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTMP);
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP == enClientType)
{
//推流端类型是rtmp
int nHLen = 0;
......@@ -190,7 +224,7 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
memset(&st_RTMPVParam, '\0', sizeof(XENGINE_RTMPVIDEOPARAM));
memcpy(&st_RTMPVideo, lpszMsgBuffer, sizeof(XENGINE_RTMPVIDEO));
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, st_AVInfo.st_VideoInfo.tszVInfo, &st_AVInfo.st_VideoInfo.nVLen, lpszMsgBuffer, nMsgLen, &st_RTMPVParam);
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, st_AVInfo.st_VideoInfo.tszVInfo, &st_AVInfo.st_VideoInfo.nVLen, lpszMsgBuffer + sizeof(XENGINE_RTMPVIDEO), nMsgLen - sizeof(XENGINE_RTMPVIDEO), &st_RTMPVParam);
ModuleSession_PushStream_SetAVInfo(lpszClientAddr, &st_AVInfo);
}
//是否全部设置完毕
......@@ -252,7 +286,7 @@ bool XEngine_AVPacket_AVHdr(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int n
memcpy(&st_ProtocolStream, lpszMsgBuffer, sizeof(XENGINE_PROTOCOLSTREAM));
//创建会话
ModuleSession_PushStream_Create(lpszClientAddr, st_ProtocolStream.tszSMSAddr);
ModuleSession_PushStream_Create(lpszClientAddr, st_ProtocolStream.tszSMSAddr, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM);
ModuleSession_PushStream_SetHDRBuffer(lpszClientAddr, (LPCXSTR)&st_ProtocolStream.st_AVInfo, sizeof(XENGINE_PROTOCOL_AVINFO), ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_XSTREAM);
}
}
......@@ -303,7 +337,7 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR
ModuleSession_PushStream_ClientList(lpszClientAddr, &stl_ListClient);
for (auto stl_ListIteratorClient = stl_ListClient.begin(); stl_ListIteratorClient != stl_ListClient.end(); ++stl_ListIteratorClient)
{
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_XSTREAM == stl_ListIteratorClient->enClientType)
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_FLV == stl_ListIteratorClient->enClientType)
{
XEngine_Network_Send(stl_ListIteratorClient->tszClientID, ptszSDBuffer, *pInt_SDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP);
break;
......@@ -312,29 +346,49 @@ bool XEngine_AVPacket_AVFrame(XCHAR* ptszSDBuffer, int* pInt_SDLen, XCHAR* ptszR
}
if (st_ServiceConfig.st_XPull.st_PullRtmp.bEnable)
{
if (0 == byAVType)
{
RTMPProtocol_Packet_FrameVideo(lpszClientAddr, ptszSDBuffer, pInt_SDLen, lpszMsgBuffer + sizeof(XENGINE_PROTOCOL_AVDATA), nMsgLen - sizeof(XENGINE_PROTOCOL_AVDATA), nTimeStamp);
}
else
{
RTMPProtocol_Packet_FrameAudio(lpszClientAddr, ptszSDBuffer, pInt_SDLen, lpszMsgBuffer + sizeof(XENGINE_PROTOCOL_AVDATA), nMsgLen - sizeof(XENGINE_PROTOCOL_AVDATA), nTimeStamp);
}
//是否有客户端需要发送XStream流
list<STREAMMEDIA_SESSIONCLIENT> stl_ListClient;
ModuleSession_PushStream_ClientList(lpszClientAddr, &stl_ListClient);
for (auto stl_ListIteratorClient = stl_ListClient.begin(); stl_ListIteratorClient != stl_ListClient.end(); ++stl_ListIteratorClient)
{
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTMP == stl_ListIteratorClient->enClientType)
{
XEngine_Network_Send(stl_ListIteratorClient->tszClientID, ptszSDBuffer, *pInt_SDLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP);
break;
}
}
}
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP == enClientType)
{
if (st_ServiceConfig.st_XPull.st_PullXStream.bEnable)
{
int nPos = 0;
XENGINE_RTMPVIDEO st_RTMPVideo;
XENGINE_RTMPVIDEOPARAM st_RTMPVideoParam;
XENGINE_PROTOCOL_AVDATA st_ProtocolAVData;
memset(&st_RTMPVideo, '\0', sizeof(XENGINE_RTMPVIDEO));
memset(&st_RTMPVideoParam, '\0', sizeof(XENGINE_RTMPVIDEOPARAM));
memset(&st_ProtocolAVData, '\0', sizeof(XENGINE_PROTOCOL_AVDATA));
memcpy(&st_RTMPVideo, lpszClientAddr, sizeof(XENGINE_RTMPVIDEO));
memcpy(&st_RTMPVideo, lpszMsgBuffer, sizeof(XENGINE_RTMPVIDEO));
st_ProtocolAVData.byAVType = 0;
st_ProtocolAVData.byAVType = byAVType;
st_ProtocolAVData.nTimeStamp = nTimeStamp;
st_ProtocolAVData.byFrameType = st_RTMPVideo.byFrameType;
memcpy(ptszRVBuffer, &st_ProtocolAVData, sizeof(XENGINE_PROTOCOL_AVDATA));
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, ptszRVBuffer + sizeof(XENGINE_PROTOCOL_AVDATA), pInt_RVLen, lpszMsgBuffer, nMsgLen, &st_RTMPVideoParam);
*pInt_RVLen += sizeof(XENGINE_PROTOCOL_AVDATA);
nPos += sizeof(XENGINE_PROTOCOL_AVDATA);
RTMPProtocol_Help_ParseVideo(&st_RTMPVideo, ptszRVBuffer + nPos, pInt_RVLen, lpszMsgBuffer + sizeof(XENGINE_RTMPVIDEO), nMsgLen - sizeof(XENGINE_RTMPVIDEO));
*pInt_RVLen += nPos;
*pInt_SDLen = _xstprintf(ptszSDBuffer, _X("%x\r\n"), *pInt_RVLen);
memcpy(ptszSDBuffer + *pInt_SDLen, ptszRVBuffer, *pInt_RVLen);
......
......@@ -8,6 +8,7 @@
#include <thread>
#include <list>
#include <string>
#include <srt/srt.h>
#ifdef _MSC_BUILD
#include <Windows.h>
#include <tchar.h>
......@@ -59,9 +60,11 @@ using namespace std;
#include "XEngine_Network.h"
#include "XEngine_HttpTask.h"
#include "XEngine_AVPacket.h"
#include "./StreamMedia_HTTPApi/StreamMedia_HTTPApi.h"
#include "./StreamMedia_PushStream/PushStream_XStreamTask.h"
#include "./StreamMedia_PushStream/PushStream_JT1078Task.h"
#include "./StreamMedia_PushStream/PushStream_RTMPTask.h"
#include "./StreamMedia_PushStream/PushStream_SrtTask.h"
#include "./StreamMedia_PullStream/PullStream_ClientTask.h"
/********************************************************************
// Created: 2023/06/04 10:35:46
......
......@@ -112,8 +112,7 @@ bool XEngine_HTTPTask_Handle(RFCCOMPONENTS_HTTP_REQPARAM* pSt_HTTPParam, LPCXSTR
}
else if (0 == _tcsxnicmp(lpszMethodGet, pSt_HTTPParam->tszHttpMethod, _tcsxlen(lpszMethodGet)))
{
HTTPApi_Management_Task(lpszClientAddr, &pptszList, nListCount);
}
}
else if (0 == _tcsxnicmp(lpszStreamStr, tszKey, _tcsxlen(lpszStreamStr)))
......
......@@ -122,9 +122,43 @@ void CALLBACK Network_Callback_JT1078HBLeave(LPCXSTR lpszClientAddr, XSOCKET hSo
{
XEngine_Network_Close(lpszClientAddr, hSocket, true, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_JT1078);
}
//////////////////////////////////////////////////////////////////////////SRT
bool CALLBACK Network_Callback_SRTLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam)
{
PushStream_SrtTask_Connct(lpszClientAddr, hSocket);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("SRT客户端:%s,进入了服务器"), lpszClientAddr);
return true;
}
void CALLBACK Network_Callback_SRTRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam)
{
PushStream_SrtTask_Handle(lpszClientAddr, hSocket, lpszRecvMsg, nMsgLen);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_DEBUG, _X("SRT客户端:%s,接受到数据,数据大小:%d"), lpszClientAddr, nMsgLen);
}
void CALLBACK Network_Callback_SRTLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam)
{
XEngine_Network_Close(lpszClientAddr, hSocket, false, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("SRT客户端:%s,离开了服务器"), lpszClientAddr);
}
//////////////////////////////////////////////////////////////////////////网络IO关闭操作
void XEngine_Network_Close(LPCXSTR lpszClientAddr, XSOCKET hSocket, bool bHeart, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enClientType)
{
XCHAR tszSMSAddr[MAX_PATH];
XCHAR tszPushAddr[MAX_PATH];
memset(tszSMSAddr, '\0', sizeof(tszSMSAddr));
memset(tszPushAddr, '\0', sizeof(tszPushAddr));
//可能是推流也可能是拉流
if (ModuleSession_PullStream_GetPushAddr(lpszClientAddr, tszPushAddr))
{
ModuleSession_PullStream_Delete(lpszClientAddr);
ModuleSession_PushStream_ClientDelete(tszPushAddr, lpszClientAddr);
}
if (ModuleSession_PushStream_GetAddrForAddr(lpszClientAddr, tszSMSAddr))
{
ModuleSession_PullStream_PublishDelete(tszSMSAddr);
ModuleSession_PushStream_Destroy(lpszClientAddr);
}
if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_HTTP == enClientType)
{
//先关闭网络和心跳,他们主动回调的数据我们可以不用主动调用关闭
......@@ -138,19 +172,6 @@ void XEngine_Network_Close(LPCXSTR lpszClientAddr, XSOCKET hSocket, bool bHeart,
}
//需要主动删除与客户端对应的组包器队列中的资源
HttpProtocol_Server_CloseClinetEx(xhHttpPacket, lpszClientAddr);
//停止拉流
XCHAR tszSMSAddr[MAX_PATH];
XCHAR tszPushAddr[MAX_PATH];
memset(tszSMSAddr, '\0', sizeof(tszSMSAddr));
memset(tszPushAddr, '\0', sizeof(tszPushAddr));
ModuleSession_PullStream_GetSMSAddr(lpszClientAddr, tszSMSAddr);
if (ModuleSession_PullStream_GetPushAddr(lpszClientAddr, tszPushAddr))
{
ModuleSession_PullStream_Delete(lpszClientAddr);
ModuleSession_PushStream_ClientDelete(tszPushAddr, lpszClientAddr);
}
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("HTTP客户端:%s,离开服务器"), lpszClientAddr);
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM == enClientType)
......@@ -168,7 +189,6 @@ void XEngine_Network_Close(LPCXSTR lpszClientAddr, XSOCKET hSocket, bool bHeart,
HelpComponents_Datas_DeleteEx(xhXStreamPacket, lpszClientAddr);
//停止推流
XEngine_AVPacket_AVDelete(lpszClientAddr);
ModuleSession_PushStream_Destroy(lpszClientAddr);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("XEngine推流端:%s,离开服务器,心跳标志:%d"), lpszClientAddr, bHeart);
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_JT1078 == enClientType)
......@@ -194,26 +214,14 @@ void XEngine_Network_Close(LPCXSTR lpszClientAddr, XSOCKET hSocket, bool bHeart,
{
SocketOpt_HeartBeat_DeleteAddrEx(xhRTMPHeart, lpszClientAddr);
}
XCHAR tszSMSAddr[MAX_PATH];
XCHAR tszPushAddr[MAX_PATH];
memset(tszSMSAddr, '\0', sizeof(tszSMSAddr));
memset(tszPushAddr, '\0', sizeof(tszPushAddr));
//可能是推流也可能是拉流
ModuleSession_PullStream_GetSMSAddr(lpszClientAddr, tszSMSAddr);
if (ModuleSession_PullStream_GetPushAddr(lpszClientAddr, tszPushAddr))
{
ModuleSession_PullStream_Delete(lpszClientAddr);
ModuleSession_PushStream_ClientDelete(tszPushAddr, lpszClientAddr);
}
else
{
RTMPProtocol_Parse_Delete(lpszClientAddr);
XEngine_AVPacket_AVDelete(lpszClientAddr);
ModuleSession_PushStream_Destroy(lpszClientAddr);
}
RTMPProtocol_Parse_Delete(lpszClientAddr);
XEngine_AVPacket_AVDelete(lpszClientAddr);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("RTMP推流端:%s,离开服务器,心跳标志:%d"), lpszClientAddr, bHeart);
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT == enClientType)
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("SRT客户端:%s,离开服务器,心跳标志:%d"), lpszClientAddr, bHeart);
}
}
bool XEngine_Network_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enClientType)
{
......@@ -261,5 +269,13 @@ bool XEngine_Network_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMs
//发送成功激活一次心跳
SocketOpt_HeartBeat_ActiveAddrEx(xhRTMPHeart, lpszClientAddr);
}
else if (ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT == enClientType)
{
if (!ModuleHelp_SrtCore_Send(lpszClientAddr, lpszMsgBuffer, nMsgLen))
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("SRT服务端:%s,发送数据失败,错误:%lX"), lpszClientAddr, ModuleHelp_GetLastError());
return false;
}
}
return true;
}
\ No newline at end of file
......@@ -30,6 +30,10 @@ bool CALLBACK Network_Callback_JT1078Login(LPCXSTR lpszClientAddr, XSOCKET hSock
void CALLBACK Network_Callback_JT1078Recv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam);
void CALLBACK Network_Callback_JT1078Leave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
void CALLBACK Network_Callback_JT1078HBLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, int nStatus, XPVOID lParam);
//SRT
bool CALLBACK Network_Callback_SRTLogin(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
void CALLBACK Network_Callback_SRTRecv(LPCXSTR lpszClientAddr, XSOCKET hSocket, LPCXSTR lpszRecvMsg, int nMsgLen, XPVOID lParam);
void CALLBACK Network_Callback_SRTLeave(LPCXSTR lpszClientAddr, XSOCKET hSocket, XPVOID lParam);
//关闭与发送
void XEngine_Network_Close(LPCXSTR lpszClientAddr, XSOCKET hSocket, bool bHeart, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enClientType);
bool XEngine_Network_Send(LPCXSTR lpszClientAddr, LPCXSTR lpszMsgBuffer, int nMsgLen, ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE enClientType);
\ No newline at end of file
......@@ -37,7 +37,6 @@ XENGINE_SERVICECONFIG st_ServiceConfig;
FILE* pSt_VFile = NULL;
FILE* pst_AFile = NULL;
void ServiceApp_Stop(int signo)
{
if (bIsRun)
......@@ -65,6 +64,9 @@ void ServiceApp_Stop(int signo)
ManagePool_Thread_NQDestroy(xhRTMPPool);
ManagePool_Thread_NQDestroy(xhJT1078Pool);
//销毁其他资源
ModuleHelp_SrtCore_Destory();
srt_cleanup();
HelpComponents_XLog_Destroy(xhLog);
if (NULL != pst_AFile)
{
......@@ -113,6 +115,8 @@ static int ServiceApp_Deamon()
int main(int argc, char** argv)
{
srt_startup();
srt_setloglevel(srt_logging::LogLevel::fatal);
#ifdef _MSC_BUILD
WSADATA st_WSAData;
WSAStartup(MAKEWORD(2, 2), &st_WSAData);
......@@ -130,6 +134,8 @@ int main(int argc, char** argv)
memset(&st_XLogConfig, '\0', sizeof(HELPCOMPONENTS_XLOG_CONFIGURE));
memset(&st_ServiceConfig, '\0', sizeof(XENGINE_SERVICECONFIG));
//pSt_VFile = fopen("./1.ts", "wb");
st_XLogConfig.XLog_MaxBackupFile = 10;
st_XLogConfig.XLog_MaxSize = 1024000;
_tcsxcpy(st_XLogConfig.tszFileName, lpszLogFile);
......@@ -386,7 +392,16 @@ int main(int argc, char** argv)
}
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,启动实时端处理线程池成功,线程个数:%d"), st_ServiceConfig.st_XMax.nJT1078Thread);
}
if (st_ServiceConfig.nSrtPort > 0)
{
if (!ModuleHelp_SrtCore_Start(st_ServiceConfig.nSrtPort))
{
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_ERROR, _X("启动服务中,启动SRT服务失败,错误:%s"), srt_getlasterror_str());
goto XENGINE_SERVICEAPP_EXIT;
}
ModuleHelp_SrtCore_SetCallback(Network_Callback_SRTLogin, Network_Callback_SRTRecv, Network_Callback_SRTLeave);
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("启动服务中,启动SRT服务成功,绑定的端口:%d"), st_ServiceConfig.nSrtPort);
}
XLOG_PRINT(xhLog, XENGINE_HELPCOMPONENTS_XLOG_IN_LOGLEVEL_INFO, _X("所有服务成功启动,服务运行中,XEngine版本:%s,服务版本:%s,发行次数;%d。。。"), BaseLib_OperatorVer_XNumberStr(), st_ServiceConfig.st_XVer.pStl_ListVer->front().c_str(), st_ServiceConfig.st_XVer.pStl_ListVer->size());
while (true)
......@@ -420,6 +435,9 @@ XENGINE_SERVICEAPP_EXIT:
ManagePool_Thread_NQDestroy(xhRTMPPool);
ManagePool_Thread_NQDestroy(xhJT1078Pool);
//销毁其他资源
ModuleHelp_SrtCore_Destory();
srt_cleanup();
HelpComponents_XLog_Destroy(xhLog);
if (NULL != pst_AFile)
{
......
......@@ -143,7 +143,9 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="StreamMedia_HTTPApi\StreamMedia_HTTPApi.cpp" />
<ClCompile Include="StreamMedia_PullStream\PullStream_ClientTask.cpp" />
<ClCompile Include="StreamMedia_PushStream\PushStream_SrtTask.cpp" />
<ClCompile Include="StreamMedia_PushStream\PushStream_XStreamTask.cpp" />
<ClCompile Include="StreamMedia_PushStream\PushStream_JT1078Task.cpp" />
<ClCompile Include="StreamMedia_PushStream\PushStream_RTMPTask.cpp" />
......@@ -154,7 +156,9 @@
<ClCompile Include="XEngine_StreamMediaApp.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="StreamMedia_HTTPApi\StreamMedia_HTTPApi.h" />
<ClInclude Include="StreamMedia_PullStream\PullStream_ClientTask.h" />
<ClInclude Include="StreamMedia_PushStream\PushStream_SrtTask.h" />
<ClInclude Include="StreamMedia_PushStream\PushStream_XStreamTask.h" />
<ClInclude Include="StreamMedia_PushStream\PushStream_JT1078Task.h" />
<ClInclude Include="StreamMedia_PushStream\PushStream_RTMPTask.h" />
......
......@@ -25,6 +25,12 @@
<Filter Include="源文件\StreamMedia_PushStream">
<UniqueIdentifier>{483f3dbf-574e-40d3-926c-7800af8128d4}</UniqueIdentifier>
</Filter>
<Filter Include="头文件\StreamMedia_HTTPApi">
<UniqueIdentifier>{ce9678cb-e92a-466c-8b48-a5799850482a}</UniqueIdentifier>
</Filter>
<Filter Include="源文件\StreamMedia_HTTPApi">
<UniqueIdentifier>{0f6d4989-e2ae-4f8f-9dc9-359762306774}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="XEngine_StreamMediaApp.cpp">
......@@ -54,6 +60,12 @@
<ClCompile Include="XEngine_AVPacket.cpp">
<Filter>源文件</Filter>
</ClCompile>
<ClCompile Include="StreamMedia_PushStream\PushStream_SrtTask.cpp">
<Filter>源文件\StreamMedia_PushStream</Filter>
</ClCompile>
<ClCompile Include="StreamMedia_HTTPApi\StreamMedia_HTTPApi.cpp">
<Filter>源文件\StreamMedia_HTTPApi</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="XEngine_Configure.h">
......@@ -83,5 +95,11 @@
<ClInclude Include="XEngine_AVPacket.h">
<Filter>头文件</Filter>
</ClInclude>
<ClInclude Include="StreamMedia_PushStream\PushStream_SrtTask.h">
<Filter>头文件\StreamMedia_PushStream</Filter>
</ClInclude>
<ClInclude Include="StreamMedia_HTTPApi\StreamMedia_HTTPApi.h">
<Filter>头文件\StreamMedia_HTTPApi</Filter>
</ClInclude>
</ItemGroup>
</Project>
\ No newline at end of file
......@@ -21,9 +21,11 @@ typedef enum
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_XSTREAM = 0x01,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_JT1078 = 0x02,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_RTMP = 0x03,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PUSH_SRT = 0x04,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_XSTREAM = 0x10,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_FLV = 0x11,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTMP = 0x12
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_RTMP = 0x12,
ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE_PULL_SRT = 0x13
}ENUM_XENGINE_STREAMMEDIA_CLIENT_TYPE;
/*********************************************************************
操作类型定义
......