⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 captureserver.cpp

📁 mysee网络直播源代码Mysee Lite是Mysee独立研发的网络视频流媒体播放系统。在应有了P2P技术和一系列先进流媒体技术之后
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*
*  Openmysee
*
*  This program is free software; you can redistribute it and/or modify
*  it under the terms of the GNU General Public License as published by
*  the Free Software Foundation; either version 2 of the License, or
*  (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU General Public License for more details.
*
*  You should have received a copy of the GNU General Public License
*  along with this program; if not, write to the Free Software
*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
*/
#include "stdafx.h"
#include "CaptureServer.h"

// { Implementation of CaptureServer
CaptureServer::CaptureServer()
: parentWindow(0), videoData(0), audioData(0), passwordStatus(2),
  m_llVideoTime(0), m_llAudioTime(0), m_bTransDataEnd(FALSE),m_bIsOnlyOnePin(FALSE)
{
	memset(&videoStruct, 0, sizeof(videoStruct));
	memset(&audioStruct, 0, sizeof(audioStruct));
	cfgData.reconnectSecond = 120;
}

CaptureServer::~CaptureServer()
{
	for(UINT i = 0; i < bufferList.size();++i)
	{
		delete clientList[i];
		delete bufferList[i];
		delete logList[i];
	}

	bufferList.clear();
	clientList.clear();
	logList.clear();

	TE_CleanupLibrary();
	SAFE_ARRAYDELETE(audioData);
	SAFE_ARRAYDELETE(videoData);

	::DeleteCriticalSection(&m_SamQueueCSec);
}

BOOL CaptureServer::Init()
{
	TE_InitLibrary(); 

	if(!LoadConfigFile())
		return FALSE;

	logList.resize(cfgData.spAddress.size());
	bufferList.resize(cfgData.spAddress.size());
	clientList.resize(cfgData.spAddress.size());

	NormalAddress addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(SP4CS_PORT);
	int i = 0;
	for(list<string>::iterator it = cfgData.spAddress.begin(); it != cfgData.spAddress.end(); ++it)
	{
		addr.sin_addr.s_addr = inet_addr(it->data());
		logList[i] = new LogMgr();
		logList[i]->Init();
		logList[i]->PrintTime(TRUE);

		bufferList[i] = new BufferMgr(this);
		if(!bufferList[i])
			return FALSE;

		clientList[i] = new SPClient(this, addr, bufferList[i], logList[i]);
		if(!clientList[i])
			return FALSE;
		i++;
		Sleep(100); // 防止按照时间取得文件名相同
	}

	totalBytes = 0;
	GetSystemTime(&startTime);

	::InitializeCriticalSection(&m_SamQueueCSec);

	//cfgData.savePath = "f:\\";

	return TRUE;
}

void CaptureServer::Stop()
{
	/*此处之所以直接PutSample而不做任何限制是因为
	  CaptureServer的PutSample可以保证当音视频流
	  全部结束时一定能够把队列取空。如果是中途
	  应用层强制停止,有可能会造成某路队列数据
	  非空,但这是没法避免的,此时此处处理或者
	  是把数据丢掉只保留前面的同步后数据,或者
	  把剩余队列中不同步数据也写入,此处采用后者。
	  在依靠底层返回EC_COMPLETE来触发Stop是不会
	  出现此现象的。
	*/
	
	::EnterCriticalSection(&m_SamQueueCSec);
	int ii = m_AudioSamQueue.size();
	int iii = m_VideoSamQueue.size();

	SAMPLEDATA *pSAMPLEDATA = NULL;
	while(m_AudioSamQueue.size() > 0 && m_VideoSamQueue.size() > 0)
	{		
		if (m_AudioSamQueue.front()->samplehr.start >= m_VideoSamQueue.front()->samplehr.start)
		{
			pSAMPLEDATA = m_VideoSamQueue.front();
			m_zzlWriter.PutSample(pSAMPLEDATA->samplehr, pSAMPLEDATA->pData);
			m_VideoSamQueue.pop();
			delete pSAMPLEDATA->pData;
			pSAMPLEDATA->pData = NULL;
			delete pSAMPLEDATA;
			pSAMPLEDATA = NULL;
		}
		else
		{
			pSAMPLEDATA = m_AudioSamQueue.front();
			m_zzlWriter.PutSample(pSAMPLEDATA->samplehr, pSAMPLEDATA->pData);
			m_AudioSamQueue.pop();
			delete pSAMPLEDATA->pData;
			pSAMPLEDATA->pData = NULL;
			delete pSAMPLEDATA;
			pSAMPLEDATA = NULL;
		}	
	}
	
	int iiii = m_VideoSamQueue.size();
	int iiiii = m_AudioSamQueue.size();

	while(m_AudioSamQueue.size() > 0)
	{
		SAMPLEDATA *pSAMPLEDATA = m_AudioSamQueue.front();
		m_zzlWriter.PutSample(pSAMPLEDATA->samplehr, pSAMPLEDATA->pData);
		m_AudioSamQueue.pop();
		delete pSAMPLEDATA->pData;
		delete pSAMPLEDATA;
	}
	
	while(m_VideoSamQueue.size() > 0)
	{
		SAMPLEDATA *pSAMPLEDATA = m_VideoSamQueue.front();
		m_zzlWriter.PutSample(pSAMPLEDATA->samplehr, pSAMPLEDATA->pData);
		m_VideoSamQueue.pop();
		delete pSAMPLEDATA->pData;
		delete pSAMPLEDATA;
	}
	m_bTransDataEnd = TRUE;
	TRACE5("CaptureServer::Stop处理剩余包\n");

	::LeaveCriticalSection(&m_SamQueueCSec);
	/*
	::EnterCriticalSection(&m_SamQueueCSec);
	int ii = m_AudioSamQueue.size();
	while(m_AudioSamQueue.size() > 0)
	{
		SAMPLEDATA *pSAMPLEDATA = m_AudioSamQueue.front();
		m_zzlWriter.PutSample(pSAMPLEDATA->samplehr, pSAMPLEDATA->pData);
		m_AudioSamQueue.pop();
		delete pSAMPLEDATA->pData;
		delete pSAMPLEDATA;
	}
	int iii = m_VideoSamQueue.size();
	while(m_VideoSamQueue.size() > 0)
	{
		SAMPLEDATA *pSAMPLEDATA = m_VideoSamQueue.front();
		m_zzlWriter.PutSample(pSAMPLEDATA->samplehr, pSAMPLEDATA->pData);
		m_VideoSamQueue.pop();
		delete pSAMPLEDATA->pData;
		delete pSAMPLEDATA;
	}
	m_bTransDataEnd = TRUE;
	::LeaveCriticalSection(&m_SamQueueCSec);
	*/
}

BOOL CaptureServer::LoadConfigFile()
{
	char buf[MAX_PATH];
	GetModuleFileName(NULL, buf, MAX_PATH);
	string path = buf;
	int index = path.find_last_of('\\', path.length());
	path.resize(index+1);

	ConfigFile cfgFile(path + "CaptureServer.cfg");
	if(cfgFile.fileNotFound) {
		MessageBox(parentWindow, "无法找到配置文件CaptureServer.cfg。", "错误", MB_OK|MB_ICONERROR);
		return FALSE;
	}
	string strSPList = cfgFile.Value("CaptureServer", "spAddress");
	if(cfgFile.stringNotFound) {
		MessageBox(parentWindow, "配置文件中必须存在spAddress一项。", "错误", MB_OK|MB_ICONERROR);
		return FALSE;
	}
	cfgData.chnlStr = cfgFile.Value("CaptureServer", "channelName");
	if(cfgFile.stringNotFound) {
		MessageBox(parentWindow, "配置文件中必须存在channelName一项。", "错误", MB_OK|MB_ICONERROR);
		return FALSE;
	}
	cfgData.savePath = cfgFile.Value("CaptureServer", "savepath");
	
	if (false == cfgData.savePath.empty())
	{
		//补路径后的斜杠
		string::const_iterator litSavePath = cfgData.savePath.end();
		--litSavePath;
		if ('\\' != static_cast<BYTE>(*litSavePath))
		{
			cfgData.savePath += "\\"; 
		}

		//去除路径前的空格
		while (' ' == *cfgData.savePath.c_str())
		{		
			cfgData.savePath = cfgData.savePath.c_str() + 1;
		}		
	}
	
	
	string lstrOnlyAudio = cfgFile.Value("CaptureServer", "isonlyaudio");
	
	if (false == lstrOnlyAudio.empty())
	{
		//去除路径前的空格
		while (' ' == *lstrOnlyAudio.c_str())
		{		
			lstrOnlyAudio = lstrOnlyAudio.c_str() + 1;
		}	

		//lstrOnlyAudio = lstrOnlyAudio.
		if ("true" == lstrOnlyAudio)
		{
			SetAudioOrVideoOnly(TRUE);				
		}
		else if ("false" != lstrOnlyAudio)
		{
			MessageBox(NULL,"isonlyaudio 项是非法字符","注意", MB_OK|MB_ICONSTOP);
			return FALSE;
		}
	}

	string reconnect = cfgFile.Value("CaptureServer", "ReconnectTime");
	if(!cfgFile.fileNotFound) {
		cfgData.reconnectSecond = atoi(reconnect.data());
	}
	string id = cfgFile.Value("CaptureServer","userID");
	if(cfgFile.fileNotFound){
		MessageBox(parentWindow, "配置文件中必须存在userID一项。", "错误", MB_OK|MB_ICONERROR);
		return FALSE;
	}
	cfgData.userID = atoi(id.data());

	//读入的是32位密码
	cfgData.password = cfgFile.Value("CaptureServer", "password");
	if(cfgFile.fileNotFound){
		MessageBox(parentWindow, "配置文件中必须存在password一项目。", "错误", MB_OK|MB_ICONERROR);
		return FALSE;
	}

	string::const_iterator it = cfgData.chnlStr.begin();

	for(; it != cfgData.chnlStr.end(); it++)
	{
		BYTE tmpChar = static_cast<BYTE>(*it);
		if(isdigit(tmpChar) || isalpha(tmpChar))
			continue;
		if(tmpChar == '[' || tmpChar == ']')
			continue;
		//GB18030-2000编码标准的第一个字节的编码范围在0x81 ~ 0xFE之间;第二个字节的编码范围在0x40 ~ 0x7E和0x80 ~ 0xFE之间。
		//Big5编码标准的第一个字节的编码范围在0xA1 ~ 0xF9 之间;第二个字节的编码范围在0x40 ~ 0x7E 和0xA1 ~ 0xFE之间。
		//两者的并集是第一个字节[0x81, 0xfe],第二个字节[0x40, 0x7e]、[0x80, 0xfe];
		if(tmpChar>=0x81 && tmpChar <= 0xfe && it+1 != cfgData.chnlStr.end()) {
			tmpChar = static_cast<BYTE>(*(it+1));
			if( (tmpChar>=0x40 && tmpChar <= 0x7e) || (tmpChar>=0x80 && tmpChar <= 0xfe))
			{
				it++;	// 跳过一个汉字字符
				continue;
			}
		}
		MessageBox(parentWindow, "配置文件中channelName一项只能由字母、数字、汉字和方括弧组成。", "错误", MB_OK|MB_ICONERROR);
		return FALSE;
	}

	cfgData.canLogin = TRUE;

	istrstream is(strSPList.data());
	string line;
	string ip;
	string port;
	NormalAddress tmpAddr;
	while(getline(is,line, ':')) {
		if(!line.length())
			continue;
		tmpAddr.sin_addr.s_addr = TE_GetIP(line.data(), TRUE);
		if(tmpAddr.sin_addr.s_addr == INADDR_NONE)
			continue;
		cfgData.spAddress.push_back(inet_ntoa(tmpAddr.sin_addr));
	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -