RTSP协议转RTMP协议的行业视频接入网关EasyRTSPLive之跨平台ini配置及通道的方法

视频网关是一种协议转换器,又称为网间连接器,视频网关就是在网络层以上实现网络相互连接,也就是网络互连。是最复杂的网络互连设备,用于两个高层协议不同的网络互连。视频网关既可以用于广域网互连,也可以用于局域网互连。网关是一种充当转换重任的计算机系统或设备。使用在不同的通信协议、数据格式或语言,甚至体系结构完全不同的两种系统之间。

视频网关是一款高性能的嵌入式多功能媒体网关设备,集流媒体协议转换、流媒体分发服务、多路视频解码、视频画面分割等核心功能于一体。

青犀团队研发和运维的EasyRTSPLive就是一个完善的行业视频接入网关,今天着重为大家分享EasyRTSPLive支持跨平台ini配置文件配置通道的方法使用。

EasyRTSPLive控制台程序要输入通道信息需要在控制台程序启动时手动输入比较麻烦,而且多路通道配置通过手动输入的方式效率很低而且实际生产环境中也是不现实的,所以,我们需要读取配置文件来配置通道信息。

分析问题

在windows平台系统有为我们封装一套基于ini配置文件的读取sdk,不过收操作系统的限制只能在windows平台上使用,而linux或者其他系统平台是无法读取的,所以,我们需要自行封装一套读取ini配置文件的代码以实现对ini配置文件的读取。

解决问题

首先,我们声明两个方法实现对ini配置文件的键值对的读取:

//从INI文件读取字符串类型数据  
extern char *GetIniKeyString(char *title,char *key,char *filename);

//从INI文件读取整类型数据  
extern int GetIniKeyInt(char *title,char *key,char *filename);

实现代码如下:

//从INI文件读取字符串类型数据  
char *GetIniKeyString(char *title,char *key,char *filename)   
{   
    FILE *fp;   
    char szLine[1024];  
    static char tmpstr[1024];  
    int rtnval;  
    int i = 0;   
    int flag = 0;   
    char *tmp;  
  
    if((fp = fopen(filename, "r")) == NULL)   
    {   
        printf("have   no   such   file \n");  
        return "";   
    }  
    while(!feof(fp))   
    {   
        rtnval = fgetc(fp);   
        if(rtnval == EOF)   
        {   
            break;   
        }   
        else   
        {   
            szLine[i++] = rtnval;   
        }   
        if(rtnval == '\n' || rtnval == '\r')   
        {   
#ifndef WIN32  
            //i--;  
#endif    
            szLine[--i] = '\0';  
            i = 0;   
            tmp = strchr(szLine, '=');   
  
            if(( tmp != NULL )&&(flag == 1))   
            {   
                if(strstr(szLine,key)!=NULL)   
                {   
                    //注释行  
                    if ('#' == szLine[0])  
                    {  
                    }  
                    else if ( '\/' == szLine[0] && '\/' == szLine[1] )  
                    {  
                          
                    }  
                    else  
                    {  
                        //找打key对应变量  
                        strcpy(tmpstr,tmp+1);   
                        fclose(fp);  

						while(tmpstr[strlen(tmpstr) - 1] == ' ' || tmpstr[strlen(tmpstr) - 1] == '\t')
							tmpstr[strlen(tmpstr) - 1] = '\0';

                        return tmpstr;   
                    }  
                }   
            }  
            else   
            {   
                strcpy(tmpstr,"[");   
                strcat(tmpstr,title);   
                strcat(tmpstr,"]");  
                if( strncmp(tmpstr,szLine,strlen(tmpstr)) == 0 )   
                {  
                    //找到title  
                    flag = 1;   
                }  
            }  
        }  
    }  
    fclose(fp);   
    return "";   
}  
  
//从INI文件读取整类型数据  
int GetIniKeyInt(char *title,char *key,char *filename)  
{  
	int ret = 0;
	char* strValue = GetIniKeyString(title,key,filename);
	if(strlen(strValue) <= 0)
	{
		return ret;
	}
	else
	{
		ret = atoi(strValue);
	}

    return ret;  
}  

然后,我们需要声明数据结构配置来存放读取的配置文件数据,如下声明:
typedef struct _channel_cfg_struct_t
{
	int channelId;
	int option;
	char channelName[64];
	char srcRtspAddr[512];
	char destRtmpAddr[512];
}_channel_cfg;
static std::list <_channel_info*> gChannelInfoList;

然后,我们读取配置文件easyrtsplive.ini,并将多通道的信息存放在gChannelInfoList列表数据结构中,如下代码所示:

bool InitCfgInfo(void)
{
	int i = 0;
	gChannelInfoList.clear();
	for(i = 0; i < MAX_CHANNEL_INDEX; i++)
	{
		_channel_info* pChannelInfo = new _channel_info();
		if(pChannelInfo)
		{
			memset(pChannelInfo, 0, sizeof(_channel_info));
			pChannelInfo->fCfgInfo.channelId = i;
			pChannelInfo->fHavePrintKeyInfo = false;
			sprintf(pChannelInfo->fCfgInfo.channelName, "channel%d",i);
			strcpy(pChannelInfo->fCfgInfo.srcRtspAddr, GetIniKeyString(pChannelInfo->fCfgInfo.channelName, "rtsp", CONF_FILE_PATH));
			strcpy(pChannelInfo->fCfgInfo.destRtmpAddr, GetIniKeyString(pChannelInfo->fCfgInfo.channelName, "rtmp", CONF_FILE_PATH));
			pChannelInfo->fCfgInfo.option = GetIniKeyInt(pChannelInfo->fCfgInfo.channelName, "option", CONF_FILE_PATH);
			if(strlen(pChannelInfo->fCfgInfo.srcRtspAddr) > 0 && strlen(pChannelInfo->fCfgInfo.destRtmpAddr) > 0)
			{
				gChannelInfoList.push_back(pChannelInfo);
			}
		}
	}
	return true;
}


最后,调用配置函数配置好通道信息,并调用相关接口函数实现流转发,如下代码所示:

InitCfgInfo();

	std::list<_channel_info*>::iterator it;
	for(it = gChannelInfoList.begin(); it != gChannelInfoList.end(); it++)
	{
		_channel_info* pChannel = *it;
		pChannel->fLogHandle = TRACE_OpenLogFile(pChannel->fCfgInfo.channelName);

		TRACE_LOG(pChannel->fLogHandle, "channel[%d] rtsp addr : %s\n", pChannel->fCfgInfo.channelId, pChannel->fCfgInfo.srcRtspAddr);
		TRACE_LOG(pChannel->fLogHandle, "channel[%d] rtmp addr : %s\n", pChannel->fCfgInfo.channelId, pChannel->fCfgInfo.destRtmpAddr);

		EasyRTSP_Init(&(pChannel->fNVSHandle));

		if (NULL == pChannel->fNVSHandle)
		{
			TRACE_LOG(pChannel->fLogHandle, "%s rtsp init error. ret=%d!!!\n", pChannel->fCfgInfo.channelName , iret);
			continue;
		}
		unsigned int mediaType = EASY_SDK_VIDEO_FRAME_FLAG | EASY_SDK_AUDIO_FRAME_FLAG;
	
		EasyRTSP_SetCallback(pChannel->fNVSHandle, __RTSPSourceCallBack);

		EasyRTSP_OpenStream(pChannel->fNVSHandle, pChannel->fCfgInfo.channelId, pChannel->fCfgInfo.srcRtspAddr, EASY_RTP_OVER_TCP, mediaType, 0, 0, pChannel, 1000, 0, pChannel->fCfgInfo.option, 3);
	}

EasyRTSPLive通过拉流IPC摄像机或者NVR硬盘录像机RTSP流转成RTMP推送到阿里云CDN/腾讯云CDN/RTMP流媒体服务器,支持多路RTSP流同时拉取并以RTMP协议推送发布,全平台支持(包括Windows/Linux 32&64,ARM各种平台,Android,iOS),是技术研发快速迭代的工具,也是安防运维人员进行现场问题排查的得力帮手!最新SDK版本、文档及示例代码 :https://github.com/tsingsee/EasyRTSPLive

 

posted on 2019-09-12 16:25  EasyNVR  阅读(475)  评论(0编辑  收藏  举报