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

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. #include "stdafx.h"
  20. #include "Communicator.h"
  21. #include "Layer1.h"
  22. #include "Http_Fetcher.h"
  23. // 在所有服务器都已经支持切换编码之前,需要从GTV文件中读取媒体类型数据
  24. //#define READ_GTV_MEDIA
  25. namespace NPLayer1 {
  26. Layer1::Layer1() {
  27. comm = NULL;
  28. }
  29. Layer1::~Layer1() {
  30. delete comm;
  31. }
  32. P2P_RETURN_TYPE Layer1::Request(
  33. LPCSTR url,  // in, 要播放的gtv地址或者路径
  34. const HWND notifyWnd,  // in, layer1发送消息的窗口
  35. const UINT notifyCode, // in, layer1发送消息的msg ID
  36. const UINT16 channelID //in, layer1发送消息的目标channel ID, , 将附加到WPARAM里面的HIWORD,
  37. )
  38. {
  39. if(comm)
  40. return PRT_DUP_INIT;
  41. if(!url || strlen(url) >= MAX_PATH_EX)
  42. return PRT_BAD_URL;
  43. string resname;
  44. string hashcode;
  45. string spList;
  46. string trackerList;
  47. UINT blockSize = BLOCK_SIZE;
  48. float bitRate = 40.0f;
  49. char szFinal[MAX_PATH_EX];
  50.     strcpy(szFinal, url);
  51. #ifdef READ_GTV_MEDIA
  52.     UINT attachDataSize = 0;
  53.     char* attachData = NULL;
  54. #endif
  55. // gaov协议格式:gaov://tsip:tsport/spip:spport/res md5/res name(optional)/bitrate(optional)/
  56. if(strnicmp(szFinal, "gaov://", 7) == 0) {
  57. string temp = szFinal;
  58. temp.erase(0, 7);
  59. size_t index = temp.find('/');
  60. trackerList = temp.substr(0, index);
  61. if(index == -1)
  62. return PRT_BAD_URL;
  63. temp.erase(0, index+1);
  64. index = temp.find('/');
  65. spList = temp.substr(0, index);
  66. if(index == -1)
  67. return PRT_BAD_URL;
  68. temp.erase(0, index+1);
  69. index = temp.find('/');
  70. hashcode = temp.substr(0, index);
  71. if(index != -1) {
  72. temp.erase(0, index+1);
  73. index= temp.find('/');
  74. resname = temp.substr(0, index);
  75. if(index != -1) {
  76. temp.erase(0, index +1);
  77. index = temp.find('/');
  78. bitRate = static_cast<float>(atof(temp.substr(0, index).data()));
  79. if(index != -1) {
  80. temp.erase(0, index+1);
  81. }
  82. }
  83. }
  84. // 如果协议中没有包含资源名,则显示hashcoder,因为后面会检查resname是否为空 -_-
  85. if(resname.empty())
  86. resname = hashcode;
  87. }
  88. else {
  89. // 1. 判断是否GTV文件
  90. char* index = strrchr(szFinal, '.');
  91. if(index != NULL) {
  92. index++;
  93. if(strnicmp(index, "gtv", 3) != 0)
  94. return PRT_BAD_URL;
  95. }
  96. else
  97. return PRT_BAD_URL;
  98. // 2. 下载GTV文件
  99. bool isHttpGTV = false;
  100. // 如果是"HTTP://"打头的gtv,就说明需要下载
  101. if(strnicmp(szFinal, "http://", 7) == 0) {
  102. // 通过HTTP下载的文件内容保存在这里
  103. char buf[MAX_PATH_EX];
  104. if(GetTempPath(MAX_PATH_EX, buf) == 0)
  105. return PRT_SYS;
  106. itoa(GetTickCount(), buf+strlen(buf), 10);
  107. strcat(buf, ".gtv");
  108. HANDLE localFile = CreateFile(buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  109. if(localFile == INVALID_HANDLE_VALUE)
  110. return PRT_SYS;
  111. // HTTP下载类
  112. HttpFetcher fetcher;
  113. UINT fileSize = 0;
  114. UINT bytesRead = fetcher.http_fetch(szFinal, localFile, fileSize, bytesRead, 0.0f/*no limit*/);
  115. CloseHandle(localFile);
  116. if(bytesRead == UINT_MAX || bytesRead == 0)
  117. return PRT_BAD_URL;
  118. // 将szFinal设置为下载完毕的GTV文件的路径
  119. strcpy(szFinal, buf);
  120. isHttpGTV = true;
  121. }
  122. // 3. 读取GTV文件的数据
  123. char temp[4096];
  124. HANDLE hFile = CreateFile(szFinal, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  125. if(hFile == INVALID_HANDLE_VALUE)
  126. return PRT_SYS;
  127. DWORD TTT = 0;
  128. if(!ReadFile(hFile, temp, 4096, &TTT, NULL) || TTT == 0) {
  129. CloseHandle(hFile);
  130. return PRT_SYS;
  131. }
  132. CloseHandle(hFile);
  133. if(isHttpGTV)
  134. remove(szFinal); // 删除临时gtv文件
  135. // 4. 解析数据
  136. istrstream* is = NULL;
  137. is = new istrstream(temp);
  138. if(is->fail())
  139. return PRT_SYS;
  140. string line;
  141. string name;
  142. string value;
  143. string inSection;
  144. size_t posEqual;
  145. while (getline(*is,line)) {
  146. if ( !line.length()) continue;
  147. if ( line[0] == '#') continue; // 注释行
  148. if ( line[0] == ';') continue; // 注释行
  149. if ( line[0] == '[') {
  150. inSection=line.substr(1,line.find(']')-1);
  151. continue;
  152. }
  153. posEqual=line.find('=');
  154. name = line.substr(0,posEqual);
  155. value = line.substr(posEqual+1);
  156. size_t index = value.find('r');
  157. if(index != -1)
  158. value = value.substr(0, index);
  159. index = value.find('n');
  160. if(index != -1)
  161. value = value.substr(0, index);
  162. if(name == "ChannelName")
  163. resname = value;
  164. else if(name == "ResourceHash")
  165. hashcode = value;
  166. else if(name == "TrackServer")
  167. trackerList = value;
  168. else if(name == "SuperPeer")
  169. spList = value;
  170. else if(name == "BlockSize")
  171. blockSize = atoi(value.data());
  172. else if(name == "BitRate")
  173. bitRate = static_cast<float>(atof(value.data()));
  174. #ifdef READ_GTV_MEDIA
  175. else if(name == "DataLength") {
  176. attachDataSize = atoi(value.data());
  177. if(attachDataSize > 1024)
  178. break;
  179. attachData = new char[attachDataSize];
  180. }
  181. else if(name == "Data") {
  182. if(attachDataSize > 0) {
  183. char* index = strstr(temp, "Data=");
  184. memcpy(attachData, index+5, attachDataSize); 
  185. }
  186. }
  187. #endif
  188. }
  189. delete is;
  190. is = NULL;
  191. }
  192. // 检查数据
  193. if(resname.empty() || hashcode.empty() || spList.empty() || trackerList.empty() || blockSize != BLOCK_SIZE)
  194. return PRT_BAD_URL;
  195. // 5. 创建实例,并初始化
  196. comm = new Communicator();
  197. if(!comm)
  198. return PRT_ALLOC;
  199. comm->noitfyWindow = notifyWnd;
  200. comm->notifyCode = notifyCode;
  201. comm->channelID = channelID;
  202. P2P_RETURN_TYPE ret = comm->Init(trackerList);
  203. if(ret < PRT_OK)
  204. return ret;
  205. // 6. 开始下载
  206. ret = comm->Request(resname.data(), hashcode.data(), spList.data(), bitRate);
  207. if(ret < PRT_OK)
  208. return ret;
  209. #ifdef READ_GTV_MEDIA
  210. MediaInterval mi;
  211. mi.start = 0;
  212. mi.size = 1000000000;
  213. char* tmpPt = attachData;
  214.   memcpy(&mi.videoType, tmpPt, sizeof(MediaType));
  215. tmpPt += sizeof(MediaType);
  216. mi.videoData = new BYTE[mi.videoType.cbFormat];
  217. if(mi.videoType.cbFormat > 200)
  218. return PRT_BAD_MEDIAFORMAT;
  219. memcpy(mi.videoData, tmpPt, mi.videoType.cbFormat);
  220. tmpPt += mi.videoType.cbFormat;
  221. memcpy(&mi.audioType, tmpPt, sizeof(MediaType));
  222. tmpPt += sizeof(MediaType);
  223. mi.audioData = new BYTE[mi.audioType.cbFormat];
  224. if(mi.audioType.cbFormat > 200)
  225. return PRT_BAD_MEDIAFORMAT;
  226. memcpy(mi.audioData, tmpPt, mi.audioType.cbFormat);
  227. tmpPt += mi.audioType.cbFormat;
  228. delete [] attachData;
  229. comm->currRes->AddMediaInterval(mi);
  230. #endif
  231. return PRT_OK;
  232. }
  233. // 停止当前下载
  234. void Layer1::Stop() {
  235. if(!comm)
  236. return;
  237. comm->logFile.StatusOut("Incoming stop...");
  238. comm->StopCurrentRes();
  239. }
  240. // 缓冲完成
  241. void Layer1::BufferFinished() {
  242. if(!comm || !comm->currRes)
  243. return;
  244. comm->currRes->EnlargeBuffer();
  245. }
  246. // 获取当前资源的传输信息
  247. void Layer1::GetTransferInfo(
  248.  TransferInfo& ti // out, 传输信息
  249.  )
  250. {
  251. if(!comm)
  252. return;
  253. comm->p2pMgr.GetTransferInfo(ti);
  254. }
  255. // 获取当前资源Hash
  256. BOOL Layer1::GetResourceHash(
  257.  LPTSTR buf,  // out, 存储Hash的缓冲区
  258.  UINT& len // in/out, 传入缓冲区的大小,返回Hash的长度
  259.  )
  260. {
  261. if(!comm || !comm->currRes)
  262. return 0;
  263. if(!buf)
  264. return FALSE;
  265. string hashcode = comm->currRes->GetHashCode();
  266. if(len <= hashcode.length())
  267. return FALSE;
  268. len = hashcode.length();
  269. memcpy(buf, hashcode.data(), len);
  270. buf[len] = 0;
  271. return TRUE;
  272. }
  273. // 获取当前资源名
  274. BOOL Layer1::GetFileName(
  275.  LPTSTR buf,  // out, 存储名字的缓冲区
  276.  UINT& len // in/out, 传入缓冲区的大小,返回名字的长度
  277.  )
  278. {
  279. if(!comm || !comm->currRes)
  280. return 0;
  281. if(!buf)
  282. return FALSE;
  283. /// 三种不同版本的客户端,能够拿到不同的信息,所以要分别处理
  284. string resname = comm->currRes->GetResName();
  285. string programname = comm->currRes->GetProgramName();
  286. string channelname = comm->currRes->GetChannelName();
  287. UINT32 progtime = comm->currRes->GetProgramTimeInSeconds();
  288. if(programname.empty()) {
  289. if(len <= resname.length())
  290. return FALSE;
  291. len = resname.length();
  292. sprintf(buf, "%s", resname.data());
  293. return true;
  294. }
  295. if(channelname.empty()) {
  296. if(len <= resname.length()+programname.length()+64)
  297. return FALSE;
  298. len = resname.length()+programname.length()+64;
  299. LONGLONG curTime = comm->currRes->GetOriginTime()/10000000;
  300. sprintf(buf, "%s -> %s %.2d:%.2d:%.2d", resname.data(), programname.data(), 
  301. (int)curTime/3600, (int)curTime%3600/60, (int)curTime%60);
  302. return TRUE;
  303. }
  304. if(len <= channelname.length()+programname.length()+channelname.length()+64)
  305. return FALSE;
  306. len = channelname.length()+programname.length()+channelname.length()+64;
  307. LONGLONG curTime = comm->currRes->GetOriginTime()/10000000;
  308. sprintf(buf, "%s -> %s %.2d:%.2d:%.2d", channelname.data(), programname.data(), 
  309. (int)curTime/3600, (int)curTime%3600/60, (int)curTime%60);
  310. if(progtime)
  311. sprintf(buf+strlen(buf), "/%.2d:%.2d:%.2d", (int)progtime/3600, (int)progtime%3600/60, (int)progtime%60);
  312. return TRUE;
  313. }
  314. // 获取当前资源的缓冲百分比
  315. int Layer1::GetBufferPercent() {
  316. if(!comm || !comm->currRes)
  317. return -1;
  318. return comm->currRes->GetBufferPercent();
  319. }
  320. // 获取当前频道的码率
  321. float Layer1::GetChannelBitRate() {
  322. if(!comm || !comm->currRes)
  323. return 0.0f;
  324. return comm->currRes->GetBitRate();
  325. }
  326. // 获取Sample,可能得到普通Sample或者MediaType(参考struct SampleHeader的注释)
  327. P2P_RETURN_TYPE Layer1::GetData(
  328. SampleHeader& header, // out, 数据头
  329. PBYTE& pData, // out, 存储数据的缓冲区
  330. const UINT maxSize, // in, 缓冲区的长度
  331. const bool bAudio, // in, 获取音频还是视频
  332. const bool bKeySample // in, 是否寻找关键帧
  333. )
  334. {
  335. if(!comm || !comm->currRes)
  336. return PRT_NOT_INIT;
  337. return comm->currRes->GetData(header, pData, maxSize, bAudio, bKeySample);
  338. }
  339. }