BufferMgr.cpp
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:13k
源码类别:

P2P编程

开发平台:

Visual C++

  1. /*
  2. *  Openmysee
  3. *
  4. *  This program is free software; you can redistribute it and/or modify
  5. *  it under the terms of the GNU General Public License as published by
  6. *  the Free Software Foundation; either version 2 of the License, or
  7. *  (at your option) any later version.
  8. *
  9. *  This program is distributed in the hope that it will be useful,
  10. *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. *  GNU General Public License for more details.
  13. *
  14. *  You should have received a copy of the GNU General Public License
  15. *  along with this program; if not, write to the Free Software
  16. *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17. *
  18. */
  19. // BufferMgr.cpp: implementation of the BufferMgr class.
  20. //
  21. //////////////////////////////////////////////////////////////////////
  22. #include "stdafx.h"
  23. #include "BufferMgr.h"
  24. #include "CaptureServer.h"
  25. #include "LogMgr.h"
  26. //////////////////////////////////////////////////////////////////////
  27. // Construction/Destruction
  28. //////////////////////////////////////////////////////////////////////
  29. BufferMgr::BufferMgr(CaptureServer* c) : cs(c), blockCount(0), newBlock(0), newBlockSize(0), 
  30. blockArray(0), blockSize(0), maxBlockNum(0), maxBlockID(0), 
  31. firstKeySample(0), sampleBuffer(0), sampleBufferSize(0) {
  32. sampleStartTime = 0;
  33.     bSwitchMedia = false;
  34. // TEST: 检测时光倒退的问题
  35. lastSampleStart = 0;
  36. lastRecvSampleTime = 0;
  37. startseconds = 0;
  38. RemoveOldTmpFile();
  39. bShouldSave = FALSE;
  40. bShouldConnect = FALSE;
  41. char buf[MAX_PATH+1];
  42. DWORD res = GetTempPath(MAX_PATH, buf);
  43. bufferPath = buf;
  44. UINT uni = GetTickCount();
  45. GetTempFileName(bufferPath.data(), "#CD", uni, buf);
  46. bufferPath = buf;
  47. if(!ExCreateFile(hBufferFile, buf, CREATE_ALWAYS))
  48.   return;
  49. ExSetFileSize(hBufferFile, 0);
  50. newBlock = new BYTE[BLOCK_SIZE];
  51. maxBlockNum = BUFFER_SPACE / BLOCK_SIZE;
  52. blockArray = new UINT[maxBlockNum];
  53. for(UINT i = 0; i < maxBlockNum; i++)
  54. blockArray[i] = UINT_MAX;
  55. blockSize = new UINT[maxBlockNum];
  56. }
  57. BufferMgr::~BufferMgr() {
  58. CAutoLock lock(&bufferfile_cs);
  59. StopSave();
  60. CloseHandle(hBufferFile);
  61. DeleteFile(bufferPath.data());
  62. SAFE_ARRAYDELETE(blockArray);
  63. SAFE_ARRAYDELETE(blockSize);
  64. SAFE_ARRAYDELETE(newBlock);
  65. SAFE_ARRAYDELETE(sampleBuffer);
  66. }
  67. void BufferMgr::RemoveOldTmpFile() {
  68. WIN32_FIND_DATA fileData;
  69. char buf[MAX_PATH+1];
  70. DWORD res = GetTempPath(MAX_PATH, buf);
  71. string match = buf;
  72. match.append("#CD*.tmp");
  73. HANDLE hFind = FindFirstFile(match.data(), &fileData);
  74. if(hFind == INVALID_HANDLE_VALUE)
  75. return;
  76. while(1) {
  77. string path = buf;
  78. path.append(fileData.cFileName);
  79. DeleteFile(path.data());
  80. if(!FindNextFile(hFind, &fileData)) {
  81. if(GetLastError() == ERROR_NO_MORE_FILES)
  82. break;
  83. else
  84. return; 
  85. }
  86. }
  87. FindClose(hFind);
  88. }
  89. void BufferMgr::StartSave() {
  90. bShouldSave = TRUE;
  91. }
  92. void BufferMgr::StopSave() {
  93. bShouldSave = FALSE;
  94. if(blockCount > 0) {
  95. // 将已经存储的数据清除
  96. blockCount = 0;
  97. for(UINT i = 0; i < maxBlockNum; i++)
  98. blockArray[i] = UINT_MAX;
  99. }
  100. maxBlockID = 0;
  101. firstKeySample = FALSE;
  102. }
  103. /*
  104.  * block content
  105.  *  |offset of first keysample(int32)|offset of first sample(int32)|list of samples|last uncomplete sample|
  106.  *  |sample data| = |header(SampleHeader)|data(...)|
  107.  */
  108. BOOL BufferMgr::SaveSample(UINT dataOff, const UINT allSize) {
  109. // at the start of new block, write the offset of next sample
  110. if(newBlockSize == 0) {
  111. // 在开头的4个字节写入first keysample offset
  112. *(UINT*)newBlock = 0; // 默认值是0
  113. // 在此后的4个字节写入first sample offset
  114. *((UINT*)newBlock+1) = sizeof(int)*2; // 如果开始保存新的Sample,则first sample offset = 8
  115. if(dataOff > 0)
  116. *((UINT*)newBlock+1) += allSize-dataOff;// 如果保存前一个sample剩下的部分,则要加上其剩下的长度
  117. if(*((UINT*)newBlock+1) >= BLOCK_SIZE) // 如果此sample剩下的部分长度超过当前Block,则用UINT_MAX表示
  118. *((UINT*)newBlock+1) = UINT_MAX;
  119. newBlockSize += sizeof(int)*2;
  120. }
  121. if( *(UINT*)(newBlock) == 0 && // 当前Block尚未记录FirstKeySampleOffset
  122. dataOff == 0 && // 一个新的Sample
  123. firstKeySample && // 这个Sample是KeySample
  124. newBlockSize+sizeof(SampleHeader) < BLOCK_SIZE) // SampleHeader刚好保存在当前Block中
  125. {
  126. // 在开头的4个字节记录FirstKeySampleOffset, sizeof(UINT)*2是start在SampleHeader中的位置
  127. *(UINT*)(newBlock) = newBlockSize+sizeof(UINT)*2;
  128. }
  129. // 比较剩余数据与剩余空间
  130. if(allSize-dataOff >= BLOCK_SIZE-newBlockSize) {
  131. // 剩余数据超过剩余空间,则填满并保存当前Block,并继续存储剩下的数据
  132. memcpy(newBlock+newBlockSize, sampleBuffer+dataOff, BLOCK_SIZE-newBlockSize);
  133. dataOff += BLOCK_SIZE-newBlockSize;
  134. newBlockSize = 0; // 开始新的Block
  135. // 保存旧的Block
  136. if(!SaveNewBlock(newBlock, BLOCK_SIZE))
  137. return FALSE;
  138. // 继续保存剩余的数据
  139. if(allSize-dataOff > 0)
  140. return SaveSample(dataOff, allSize);
  141. }
  142. else {
  143. // 剩余数据小于剩余空间,复制并等待下一个Sample
  144. memcpy(newBlock+newBlockSize, sampleBuffer+dataOff, allSize-dataOff);
  145. newBlockSize += allSize-dataOff;
  146. }
  147. return TRUE;
  148. }
  149. BOOL BufferMgr::PutSample(const SampleHeader& header, BYTE* pData, LogMgr* log) {
  150. CAutoLock lock(&bufferfile_cs);
  151.     if(bSwitchMedia) {
  152.         bSwitchMedia = false;
  153.         // 因为切换编码,首先填入“新节目标志”Sample
  154.         SampleHeader header;
  155.         memset(&header, 0, sizeof(SampleHeader));
  156.         header.size = sizeof(SampleHeader);
  157.         header.length = 0xffffffff;
  158.         header.start = 0xffffffffffffffff;
  159.         header.bSyncPoint = 1;
  160.         // copy sample header into sample buffer
  161.         if(header.size > sampleBufferSize) {
  162.             SAFE_ARRAYDELETE(sampleBuffer);
  163.             sampleBuffer = new BYTE[header.size];
  164.             sampleBufferSize = header.size;
  165.         }
  166.         memcpy(sampleBuffer, &header, sizeof(SampleHeader));
  167.         if(!SaveSample(0, header.size))
  168.             return FALSE;
  169.     }
  170. // 记录接收到Sample的时间
  171. lastRecvSampleTime = time(NULL);
  172. time_t nowtime;
  173. time(&nowtime);
  174. if(startseconds == 0)
  175. startseconds = nowtime;
  176. if((nowtime - startseconds < TIME4WAIT2STORE))
  177. return TRUE;
  178. bShouldConnect = TRUE;
  179. if(!bShouldSave)
  180. return TRUE;
  181. if(!pData || header.size > 1024*1024)
  182. return FALSE;
  183. char tmpStr[96];
  184. _i64toa(header.start, tmpStr, 10);
  185. _i64toa(header.length+header.start, tmpStr+32, 10);
  186.     //log->StatusOut("recv %s sample start: %s end: %s, put at %d", header.bAudioSample?"audio":"video", 
  187.     //    tmpStr, tmpStr+32, newBlockSize);
  188. if(sampleStartTime == 0) {
  189. time_t temp;
  190. time(&temp);
  191. sampleStartTime = (LONGLONG)temp*10000000;
  192. DbgLog((LOG_TRACE, 5, TEXT("此刻 %s!"), ctime(&temp)));
  193. // 校正时间,因为开始录制的时间并不是此刻,而是打在sample中的时间。
  194. sampleStartTime -= header.start;
  195. temp = static_cast<time_t>(sampleStartTime/10000000);
  196. DbgLog((LOG_TRACE, 5, TEXT("实际开始采集的时间 %s!"), ctime(&temp)));
  197. }
  198. if(header.bAudioSample) {
  199. if(header.start+header.length <= lastSampleStart) {
  200. char tmpStr[96];
  201. _i64toa(lastSampleStart, tmpStr, 10);
  202. _i64toa(header.start, tmpStr+32, 10);
  203. _i64toa(header.start+header.length, tmpStr+64, 10);
  204. DbgLog((LOG_TRACE, 5, TEXT("哇!时光倒流,从%s变到了%s->%s!"), tmpStr, tmpStr+32, tmpStr+64));
  205. }
  206. lastSampleStart = header.start;
  207. }
  208. // record time of the frist keysample of current block
  209. if(firstKeySample == FALSE && header.bSyncPoint) 
  210. firstKeySample = TRUE;
  211. if(header.size > sampleBufferSize) {
  212. SAFE_ARRAYDELETE(sampleBuffer);
  213. sampleBuffer = new BYTE[header.size];
  214. sampleBufferSize = header.size;
  215. }
  216. // copy sample header into sample buffer
  217. memcpy(sampleBuffer, &header, sizeof(SampleHeader));
  218. if(!cs->GetIsAudioOnly()) {
  219. ((SampleHeader*)sampleBuffer)->start += sampleStartTime;
  220. }
  221. // copy sample data into sample buffer;
  222. memcpy(sampleBuffer+sizeof(SampleHeader), pData, header.size-sizeof(SampleHeader));
  223. BOOL ret = SaveSample(0, header.size);
  224. return ret;
  225. }
  226. BOOL BufferMgr::SaveNewBlock(BYTE* buf, UINT size) {
  227. if(!buf || size > BLOCK_SIZE)
  228. return FALSE;
  229. BOOL ret = TRUE;
  230. UINT minBlock = UINT_MAX;
  231. UINT minIndex = 0;
  232. for(UINT i = 0; i < maxBlockNum; i++) {
  233. if(blockArray[i] == UINT_MAX) // empty block
  234. break;
  235. if(minBlock > blockArray[i]) {
  236. minBlock = blockArray[i];
  237. minIndex = i;
  238. }
  239. }
  240. if(i == maxBlockNum) {// no empty block found,replace the min block
  241. i = minIndex;
  242. }
  243. if(!ExSetFilePointer(hBufferFile, i*BLOCK_SIZE))
  244. ret = FALSE;
  245. else if(!ExWriteFile(hBufferFile, buf, size))
  246. ret = FALSE;
  247. if(ret) {
  248. blockArray[i] = blockCount; 
  249. blockSize[i] = size;
  250. blockCount++; // blockCount-1 is blockID
  251. // 等待下一个Block的first 可以sample
  252. firstKeySample = FALSE;
  253. maxBlockID = max(blockArray[i], maxBlockID);
  254.         // 如果当前块有编码类型,则保存当前块的编码类型
  255.         if(!currMediaData.IsEmpty()) {
  256.             mediaMap.insert(pair<UINT, MediaData>(blockArray[i], currMediaData));
  257.             memset(&currMediaData.audioType, 0, sizeof(currMediaData.audioType));
  258.             memset(&currMediaData.videoType, 0, sizeof(currMediaData.videoType));
  259.             delete [] currMediaData.audioData;
  260.             currMediaData.audioData = NULL;
  261.             delete [] currMediaData.videoData;
  262.             currMediaData.videoData = NULL;
  263.         }
  264. }
  265. return ret;
  266. }
  267. BOOL BufferMgr::GetBlock(UINT blockID, BYTE* buf, UINT& size) {
  268. CAutoLock lock(&bufferfile_cs);
  269. if(!buf || blockID > GetPlayingBlock())
  270. return FALSE;
  271. BOOL ret = TRUE;
  272. for(UINT i = 0; i < maxBlockNum; i++) {
  273. if(blockArray[i] == blockID && blockArray[i] != UINT_MAX)
  274. break;
  275. }
  276. if(i == maxBlockNum) // not found
  277. ret = FALSE;
  278. if(ret) {
  279. size = blockSize[i];
  280. if(!ExSetFilePointer(hBufferFile, i*BLOCK_SIZE))
  281. ret = FALSE;
  282. else if(!ExReadFile(hBufferFile, buf, size))
  283. ret = FALSE;
  284. }
  285. return ret;
  286. }
  287. // 获取一个块的编码类型
  288. BOOL BufferMgr::GetMediaData(UINT blockID, MediaData& data) {
  289.     map<UINT, MediaData>::const_iterator cit = mediaMap.find(blockID);
  290.     if(cit == mediaMap.end())
  291.         return FALSE;
  292.     if(cit->second.IsEmpty()) {
  293.         ASSERT(0);
  294.         return FALSE;
  295.     }
  296.     data = cit->second;
  297.     return TRUE;
  298. }
  299. // 标志切换编码的Block
  300. BOOL BufferMgr::AttachMediaDataToCurrentBlock(const TVMEDIATYPESECTION& tv, const BYTE* data, BOOL bAudio, LogMgr* log) {
  301. CAutoLock lock(&bufferfile_cs);
  302.     if(bAudio) {
  303.         currMediaData.audioType = tv;
  304.         currMediaData.audioData = new BYTE[currMediaData.audioType.cbFormat];
  305.         memcpy(currMediaData.audioData, data, currMediaData.audioType.cbFormat);
  306.     }
  307.     else {
  308.         currMediaData.videoType = tv;
  309.         currMediaData.videoData = new BYTE[currMediaData.videoType.cbFormat];
  310.         memcpy(currMediaData.videoData, data, currMediaData.videoType.cbFormat);
  311.     }
  312.     // 清空当前block,准备开始保存新的编码方式的block
  313.     newBlockSize = 0;
  314.     bSwitchMedia = true;
  315.     log->StatusOut("attach %s data to block %d.", bAudio?"audio":"video", blockCount);
  316.     return TRUE;
  317. }
  318. BOOL BufferMgr::ExSetFileSize(HANDLE handle, int size) {
  319. BOOL ret = TRUE;
  320. if(!ExSetFilePointer(handle, size))
  321. ret = FALSE;
  322. else if(0 == SetEndOfFile(handle)) {
  323. ret = FALSE;
  324. }
  325. return ret;
  326. }
  327. int BufferMgr::ExReadFile(HANDLE handle, LPVOID buf, int toBeRead) {
  328. int readCount = 0;
  329. DWORD tmpRead;
  330. while(readCount < toBeRead) {
  331. BOOL success = ReadFile(
  332. handle, // file handler
  333. (char*)buf+readCount, // current buffer position
  334. toBeRead - readCount, // remaining bytes to be read
  335. &tmpRead, // read bytes
  336. NULL); // not overlaped
  337. if(!success)
  338. return FALSE;
  339. if(tmpRead == 0) // no more data
  340. return FALSE;
  341. readCount += tmpRead;
  342. }
  343. return readCount;
  344. }
  345. BOOL BufferMgr::ExWriteFile(HANDLE handle, LPVOID buf, int toBeWrite) {
  346. int writeCount = 0;
  347. DWORD tmpWrite;
  348. while(writeCount < toBeWrite) {
  349. BOOL success = WriteFile(
  350. handle, // file handler
  351. (char*)buf+writeCount, // current buffer position
  352. toBeWrite-writeCount, // remaining bytes to be read
  353. &tmpWrite, // written bytes
  354. NULL); // not overlaped
  355. if(!success) {
  356. return FALSE;
  357. }
  358. writeCount += tmpWrite;
  359. }
  360. return writeCount;
  361. }
  362. BOOL BufferMgr::ExSetFilePointer(HANDLE handle, int offset) {
  363. if(-1 == SetFilePointer(handle, 
  364. offset, 
  365. NULL, 
  366. FILE_BEGIN)) {
  367. return FALSE;
  368. }
  369. return TRUE;
  370. }
  371. BOOL BufferMgr::ExCreateFile(HANDLE& handle,
  372. LPCTSTR lpFileName,
  373. DWORD dwDesiredAccess,
  374. DWORD dwShareMode,
  375. LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  376. DWORD dwCreationDisposition,
  377. DWORD dwFlagsAndAttributes,
  378. HANDLE hTemplateFile) {
  379. handle = CreateFile(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, 
  380. dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
  381. if(handle == INVALID_HANDLE_VALUE) {
  382. return FALSE;
  383. }
  384. return TRUE;
  385. }
  386. BOOL BufferMgr::ExCreateFile(HANDLE& handle, LPCTSTR lpFileName, DWORD dwCreationDisposition) {
  387. handle = CreateFile(lpFileName, 
  388. GENERIC_WRITE | GENERIC_READ, 
  389. FILE_SHARE_READ | FILE_SHARE_WRITE, 
  390. NULL, 
  391. dwCreationDisposition, 
  392. FILE_ATTRIBUTE_NORMAL, 
  393. NULL);
  394. if(handle == INVALID_HANDLE_VALUE) {
  395. return FALSE; 
  396. }
  397. return TRUE;
  398. }