CaptureServer.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:17k
源码类别:
P2P编程
开发平台:
Visual C++
- /*
- * 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));
- }
- if(cfgData.chnlStr.length() >= 64) {
- MessageBox(parentWindow, "配置文件中channelName一项其长度必须小于64字符。", "错误", MB_OK|MB_ICONERROR);
- return FALSE;
- }
- if(cfgData.password.length() != 32) {
- MessageBox(parentWindow, "配置文件中Password一项其长度必须等于32字符。", "错误", MB_OK|MB_ICONERROR);
- return FALSE;
- }
- return TRUE;
- }
- BOOL CaptureServer::SetFormatData(TVMEDIATYPESECTION& tv, BYTE* data, BOOL isAudio)
- {
- if(!data)
- return FALSE;
- // 因为SetAudioOrVideoOnly比SetFormatData先被调用,所以要在这里记录
- bool bIsThisPinOnly = isAudio?audioStruct.bThisPinOnly:videoStruct.bThisPinOnly;
- // 分别复制视频和音频数据
- if(!isAudio) {
- SAFE_ARRAYDELETE(videoData);
- memcpy(&videoStruct, &tv, sizeof(TVMEDIATYPESECTION));
- if(videoStruct.cbFormat > 512)
- return FALSE;
- videoData = new BYTE[videoStruct.cbFormat];
- memcpy(videoData, data, videoStruct.cbFormat);
- // 恢复
- videoStruct.bThisPinOnly = bIsThisPinOnly;
- }
- else {
- SAFE_ARRAYDELETE(audioData);
- memcpy(&audioStruct, &tv, sizeof(TVMEDIATYPESECTION));
- if(audioStruct.cbFormat > 512)
- return FALSE;
- audioData = new BYTE[audioStruct.cbFormat];
- memcpy(audioData, data, audioStruct.cbFormat);
- // 恢复
- audioStruct.bThisPinOnly = bIsThisPinOnly;
- }
- for(UINT i = 0; i < bufferList.size();++i)
- {
- if(!bufferList[i]->AttachMediaDataToCurrentBlock(tv, data, isAudio, logList[i]))
- return FALSE;
- }
- if((audioData&&videoData) || // 如果视频和音频的数据都有了
- (audioData&&audioStruct.bThisPinOnly) || // 如果只有音频
- (videoData&&videoStruct.bThisPinOnly)) { // 如果只有视频
- // 如果需要保存zzl文件,则建立zzl文件
- if(!cfgData.savePath.empty()) {
- if(!m_zzlWriter.Init(cfgData.savePath, cfgData.chnlStr)) {
- //MessageBox(parentWindow, "无法建立节目文件!", "错误", MB_OK);
- return 0;
- }
- if(!m_zzlWriter.SetMediaType(audioStruct, audioData, videoStruct, videoData)) {
- MessageBox(parentWindow, "无法建立节目文件!SetMediaType Error!", "错误", MB_OK);
- }
- }
- }
- return TRUE;
- }
- BOOL CaptureServer::GetFormatData(TVMEDIATYPESECTION& tv, PBYTE& data, BOOL isAudio)
- {
- if(!isAudio)
- {
- if(audioStruct.bThisPinOnly)
- {
- memset(&tv, 0, sizeof(tv));
- data = NULL;
- return TRUE;
- }
- if(!videoData)
- return FALSE;
- memcpy(&tv, &videoStruct, sizeof(TVMEDIATYPESECTION));
- data = new BYTE[videoStruct.cbFormat];
- memcpy(data, videoData, videoStruct.cbFormat);
- }
- else
- {
- if(videoStruct.bThisPinOnly)
- {
- memset(&tv, 0, sizeof(tv));
- data = NULL;
- return TRUE;
- }
- if(!audioData)
- return FALSE;
- memcpy(&tv, &audioStruct, sizeof(TVMEDIATYPESECTION));
- data = new BYTE[audioStruct.cbFormat];
- memcpy(data, audioData, audioStruct.cbFormat);
- }
- return TRUE;
- }
- void CaptureServer::SetAudioOrVideoOnly(BOOL isAudio)
- {
- if(isAudio)
- {
- audioStruct.bThisPinOnly = true;
- }
- else
- {
- videoStruct.bThisPinOnly = true;
- }
- m_bIsOnlyOnePin = TRUE;
- m_zzlWriter.SetIsSingleAudio(isAudio);
- }
- BOOL CaptureServer::PutSample(const SampleHeader& header, BYTE* pData)
- {
- totalBytes += header.size;
- for(UINT i = 0; i < bufferList.size();++i)
- {
- if(!bufferList[i]->PutSample(header, pData, logList[i]))
- return FALSE;
- }
- if(!cfgData.savePath.empty())
- {
- ::EnterCriticalSection(&m_SamQueueCSec);
- //if(!m_bTransDataEnd)
- {
- if(audioStruct.bThisPinOnly || videoStruct.bThisPinOnly)
- {
- if(!m_zzlWriter.PutSample(header, pData))
- {
- ASSERT(FALSE);
- }
- }
- else
- {
- if(header.bAudioSample)
- {
- if(m_llAudioTime >= m_llVideoTime + MAX_AVDELAY)
- {
- BYTE *pSamData = new BYTE[header.size];
- SAMPLEDATA *pSAMPLEDATA = new SAMPLEDATA;
- memset(pSAMPLEDATA, 0, sizeof(SAMPLEDATA));
- memcpy(&(pSAMPLEDATA->samplehr), &header, sizeof(SampleHeader));
- memcpy(pSamData, pData, header.size);
- pSAMPLEDATA->pData = pSamData;
- m_AudioSamQueue.push(pSAMPLEDATA);
- }
- else
- {
- if(m_AudioSamQueue.size() > 0)
- {
- BYTE *pSamData = new BYTE[header.size];
- SAMPLEDATA *pSAMPLEDATA = new SAMPLEDATA;
- memset(pSAMPLEDATA, 0, sizeof(SAMPLEDATA));
- memcpy(&(pSAMPLEDATA->samplehr), &header, sizeof(SampleHeader));
- memcpy(pSamData, pData, header.size);
- pSAMPLEDATA->pData = pSamData;
- m_AudioSamQueue.push(pSAMPLEDATA);
- SAMPLEDATA *pCurrentSampleData = m_AudioSamQueue.front();
- m_AudioSamQueue.pop();
- if(!m_zzlWriter.PutSample(pCurrentSampleData->samplehr, pCurrentSampleData->pData))
- {
- ASSERT(FALSE);
- }
- m_llAudioTime = pCurrentSampleData->samplehr.start;
- delete pCurrentSampleData->pData;
- delete pCurrentSampleData;
- }
- else
- {
- if(!m_zzlWriter.PutSample(header, pData))
- {
- ASSERT(FALSE);
- }
- m_llAudioTime = header.start;
- }
- }
- //以音频的动力拉动视频符合误差范围的Sample
- while(m_VideoSamQueue.size() > 0 && m_VideoSamQueue.front()->samplehr.start <= m_llAudioTime + MAX_AVDELAY)
- {
- SAMPLEDATA *pCurrentSampleData = m_VideoSamQueue.front();
- if(!m_zzlWriter.PutSample(pCurrentSampleData->samplehr, pCurrentSampleData->pData))
- {
- ASSERT(FALSE);
- }
- m_VideoSamQueue.pop();
- m_llVideoTime = pCurrentSampleData->samplehr.start;
- delete pCurrentSampleData->pData;
- delete pCurrentSampleData;
- }
- }
- else
- {
- if(m_llVideoTime >= m_llAudioTime + MAX_AVDELAY)
- {
- BYTE *pSamData = new BYTE[header.size];
- SAMPLEDATA *pSAMPLEDATA = new SAMPLEDATA;
- memset(pSAMPLEDATA, 0, sizeof(SAMPLEDATA));
- memcpy(&(pSAMPLEDATA->samplehr), &header, sizeof(SampleHeader));
- memcpy(pSamData, pData, header.size);
- pSAMPLEDATA->pData = pSamData;
- m_VideoSamQueue.push(pSAMPLEDATA);
- }
- else
- {
- if(m_VideoSamQueue.size() > 0)
- {
- BYTE *pSamData = new BYTE[header.size];
- SAMPLEDATA *pSAMPLEDATA = new SAMPLEDATA;
- memset(pSAMPLEDATA, 0, sizeof(SAMPLEDATA));
- memcpy(&(pSAMPLEDATA->samplehr), &header, sizeof(SampleHeader));
- memcpy(pSamData, pData, header.size);
- pSAMPLEDATA->pData = pSamData;
- m_VideoSamQueue.push(pSAMPLEDATA);
- SAMPLEDATA *pCurrentSampleData = m_VideoSamQueue.front();
- m_VideoSamQueue.pop();
- if(!m_zzlWriter.PutSample(pCurrentSampleData->samplehr, pCurrentSampleData->pData))
- {
- ASSERT(FALSE);
- }
- m_llVideoTime = pCurrentSampleData->samplehr.start;
- delete pCurrentSampleData->pData;
- delete pCurrentSampleData;
- }
- else
- {
- if(!m_zzlWriter.PutSample(header, pData))
- {
- ASSERT(FALSE);
- }
- m_llVideoTime = header.start;
- }
- }
- //以视频的动力拉动音频符合误差范围的Sample
- while(m_AudioSamQueue.size() > 0 && m_AudioSamQueue.front()->samplehr.start <= m_llVideoTime + MAX_AVDELAY)
- {
- SAMPLEDATA *pCurrentSampleData = m_AudioSamQueue.front();
- if(!m_zzlWriter.PutSample(pCurrentSampleData->samplehr, pCurrentSampleData->pData))
- {
- ASSERT(FALSE);
- }
- m_AudioSamQueue.pop();
- m_llAudioTime = pCurrentSampleData->samplehr.start;
- delete pCurrentSampleData->pData;
- delete pCurrentSampleData;
- }
- }
- }
- }
- ::LeaveCriticalSection(&m_SamQueueCSec);
- }
- return TRUE;
- }
- float CaptureServer::GetSpeedInKBPS()
- {
- if(!cfgData.savePath.empty())
- return (float)m_zzlWriter.GetBitRate(); // 由于压缩用的时间可能超过媒体文件的实际长度,所以此处统计的码率更加准确
- SYSTEMTIME stNow;
- GetSystemTime(&stNow);
- LARGE_INTEGER llNow;
- SystemTimeToFileTime(&stNow, (FILETIME*)&llNow);
- LARGE_INTEGER llStart;
- SystemTimeToFileTime(&startTime, (FILETIME*)&llStart);
- if(llNow.QuadPart - llStart.QuadPart > 0) {
- DbgLog((LOG_TRACE, 5, TEXT("Speed: %f"), totalBytes/(double)((llNow.QuadPart-llStart.QuadPart)/10000) ));
- return static_cast<float>(totalBytes/(double)((llNow.QuadPart-llStart.QuadPart)/10000));
- }
- else
- return 0.0;
- }
- // Implementation of CaptureServer }