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),是技術研發快速迭代的工具,也是安防運維人員進行現場問題排查的得力幫手。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章