Layer1.cpp
资源名称:p2p_vod.rar [点击查看]
上传用户:liguizhu
上传日期:2015-11-01
资源大小:2422k
文件大小:10k
源码类别:
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 "Communicator.h"
- #include "Layer1.h"
- #include "Http_Fetcher.h"
- // 在所有服务器都已经支持切换编码之前,需要从GTV文件中读取媒体类型数据
- //#define READ_GTV_MEDIA
- namespace NPLayer1 {
- Layer1::Layer1() {
- comm = NULL;
- }
- Layer1::~Layer1() {
- delete comm;
- }
- P2P_RETURN_TYPE Layer1::Request(
- LPCSTR url, // in, 要播放的gtv地址或者路径
- const HWND notifyWnd, // in, layer1发送消息的窗口
- const UINT notifyCode, // in, layer1发送消息的msg ID
- const UINT16 channelID //in, layer1发送消息的目标channel ID, , 将附加到WPARAM里面的HIWORD,
- )
- {
- if(comm)
- return PRT_DUP_INIT;
- if(!url || strlen(url) >= MAX_PATH_EX)
- return PRT_BAD_URL;
- string resname;
- string hashcode;
- string spList;
- string trackerList;
- UINT blockSize = BLOCK_SIZE;
- float bitRate = 40.0f;
- char szFinal[MAX_PATH_EX];
- strcpy(szFinal, url);
- #ifdef READ_GTV_MEDIA
- UINT attachDataSize = 0;
- char* attachData = NULL;
- #endif
- // gaov协议格式:gaov://tsip:tsport/spip:spport/res md5/res name(optional)/bitrate(optional)/
- if(strnicmp(szFinal, "gaov://", 7) == 0) {
- string temp = szFinal;
- temp.erase(0, 7);
- size_t index = temp.find('/');
- trackerList = temp.substr(0, index);
- if(index == -1)
- return PRT_BAD_URL;
- temp.erase(0, index+1);
- index = temp.find('/');
- spList = temp.substr(0, index);
- if(index == -1)
- return PRT_BAD_URL;
- temp.erase(0, index+1);
- index = temp.find('/');
- hashcode = temp.substr(0, index);
- if(index != -1) {
- temp.erase(0, index+1);
- index= temp.find('/');
- resname = temp.substr(0, index);
- if(index != -1) {
- temp.erase(0, index +1);
- index = temp.find('/');
- bitRate = static_cast<float>(atof(temp.substr(0, index).data()));
- if(index != -1) {
- temp.erase(0, index+1);
- }
- }
- }
- // 如果协议中没有包含资源名,则显示hashcoder,因为后面会检查resname是否为空 -_-
- if(resname.empty())
- resname = hashcode;
- }
- else {
- // 1. 判断是否GTV文件
- char* index = strrchr(szFinal, '.');
- if(index != NULL) {
- index++;
- if(strnicmp(index, "gtv", 3) != 0)
- return PRT_BAD_URL;
- }
- else
- return PRT_BAD_URL;
- // 2. 下载GTV文件
- bool isHttpGTV = false;
- // 如果是"HTTP://"打头的gtv,就说明需要下载
- if(strnicmp(szFinal, "http://", 7) == 0) {
- // 通过HTTP下载的文件内容保存在这里
- char buf[MAX_PATH_EX];
- if(GetTempPath(MAX_PATH_EX, buf) == 0)
- return PRT_SYS;
- itoa(GetTickCount(), buf+strlen(buf), 10);
- strcat(buf, ".gtv");
- HANDLE localFile = CreateFile(buf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if(localFile == INVALID_HANDLE_VALUE)
- return PRT_SYS;
- // HTTP下载类
- HttpFetcher fetcher;
- UINT fileSize = 0;
- UINT bytesRead = fetcher.http_fetch(szFinal, localFile, fileSize, bytesRead, 0.0f/*no limit*/);
- CloseHandle(localFile);
- if(bytesRead == UINT_MAX || bytesRead == 0)
- return PRT_BAD_URL;
- // 将szFinal设置为下载完毕的GTV文件的路径
- strcpy(szFinal, buf);
- isHttpGTV = true;
- }
- // 3. 读取GTV文件的数据
- char temp[4096];
- HANDLE hFile = CreateFile(szFinal, GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
- if(hFile == INVALID_HANDLE_VALUE)
- return PRT_SYS;
- DWORD TTT = 0;
- if(!ReadFile(hFile, temp, 4096, &TTT, NULL) || TTT == 0) {
- CloseHandle(hFile);
- return PRT_SYS;
- }
- CloseHandle(hFile);
- if(isHttpGTV)
- remove(szFinal); // 删除临时gtv文件
- // 4. 解析数据
- istrstream* is = NULL;
- is = new istrstream(temp);
- if(is->fail())
- return PRT_SYS;
- string line;
- string name;
- string value;
- string inSection;
- size_t posEqual;
- while (getline(*is,line)) {
- if ( !line.length()) continue;
- if ( line[0] == '#') continue; // 注释行
- if ( line[0] == ';') continue; // 注释行
- if ( line[0] == '[') {
- inSection=line.substr(1,line.find(']')-1);
- continue;
- }
- posEqual=line.find('=');
- name = line.substr(0,posEqual);
- value = line.substr(posEqual+1);
- size_t index = value.find('r');
- if(index != -1)
- value = value.substr(0, index);
- index = value.find('n');
- if(index != -1)
- value = value.substr(0, index);
- if(name == "ChannelName")
- resname = value;
- else if(name == "ResourceHash")
- hashcode = value;
- else if(name == "TrackServer")
- trackerList = value;
- else if(name == "SuperPeer")
- spList = value;
- else if(name == "BlockSize")
- blockSize = atoi(value.data());
- else if(name == "BitRate")
- bitRate = static_cast<float>(atof(value.data()));
- #ifdef READ_GTV_MEDIA
- else if(name == "DataLength") {
- attachDataSize = atoi(value.data());
- if(attachDataSize > 1024)
- break;
- attachData = new char[attachDataSize];
- }
- else if(name == "Data") {
- if(attachDataSize > 0) {
- char* index = strstr(temp, "Data=");
- memcpy(attachData, index+5, attachDataSize);
- }
- }
- #endif
- }
- delete is;
- is = NULL;
- }
- // 检查数据
- if(resname.empty() || hashcode.empty() || spList.empty() || trackerList.empty() || blockSize != BLOCK_SIZE)
- return PRT_BAD_URL;
- // 5. 创建实例,并初始化
- comm = new Communicator();
- if(!comm)
- return PRT_ALLOC;
- comm->noitfyWindow = notifyWnd;
- comm->notifyCode = notifyCode;
- comm->channelID = channelID;
- P2P_RETURN_TYPE ret = comm->Init(trackerList);
- if(ret < PRT_OK)
- return ret;
- // 6. 开始下载
- ret = comm->Request(resname.data(), hashcode.data(), spList.data(), bitRate);
- if(ret < PRT_OK)
- return ret;
- #ifdef READ_GTV_MEDIA
- MediaInterval mi;
- mi.start = 0;
- mi.size = 1000000000;
- char* tmpPt = attachData;
- memcpy(&mi.videoType, tmpPt, sizeof(MediaType));
- tmpPt += sizeof(MediaType);
- mi.videoData = new BYTE[mi.videoType.cbFormat];
- if(mi.videoType.cbFormat > 200)
- return PRT_BAD_MEDIAFORMAT;
- memcpy(mi.videoData, tmpPt, mi.videoType.cbFormat);
- tmpPt += mi.videoType.cbFormat;
- memcpy(&mi.audioType, tmpPt, sizeof(MediaType));
- tmpPt += sizeof(MediaType);
- mi.audioData = new BYTE[mi.audioType.cbFormat];
- if(mi.audioType.cbFormat > 200)
- return PRT_BAD_MEDIAFORMAT;
- memcpy(mi.audioData, tmpPt, mi.audioType.cbFormat);
- tmpPt += mi.audioType.cbFormat;
- delete [] attachData;
- comm->currRes->AddMediaInterval(mi);
- #endif
- return PRT_OK;
- }
- // 停止当前下载
- void Layer1::Stop() {
- if(!comm)
- return;
- comm->logFile.StatusOut("Incoming stop...");
- comm->StopCurrentRes();
- }
- // 缓冲完成
- void Layer1::BufferFinished() {
- if(!comm || !comm->currRes)
- return;
- comm->currRes->EnlargeBuffer();
- }
- // 获取当前资源的传输信息
- void Layer1::GetTransferInfo(
- TransferInfo& ti // out, 传输信息
- )
- {
- if(!comm)
- return;
- comm->p2pMgr.GetTransferInfo(ti);
- }
- // 获取当前资源Hash
- BOOL Layer1::GetResourceHash(
- LPTSTR buf, // out, 存储Hash的缓冲区
- UINT& len // in/out, 传入缓冲区的大小,返回Hash的长度
- )
- {
- if(!comm || !comm->currRes)
- return 0;
- if(!buf)
- return FALSE;
- string hashcode = comm->currRes->GetHashCode();
- if(len <= hashcode.length())
- return FALSE;
- len = hashcode.length();
- memcpy(buf, hashcode.data(), len);
- buf[len] = 0;
- return TRUE;
- }
- // 获取当前资源名
- BOOL Layer1::GetFileName(
- LPTSTR buf, // out, 存储名字的缓冲区
- UINT& len // in/out, 传入缓冲区的大小,返回名字的长度
- )
- {
- if(!comm || !comm->currRes)
- return 0;
- if(!buf)
- return FALSE;
- /// 三种不同版本的客户端,能够拿到不同的信息,所以要分别处理
- string resname = comm->currRes->GetResName();
- string programname = comm->currRes->GetProgramName();
- string channelname = comm->currRes->GetChannelName();
- UINT32 progtime = comm->currRes->GetProgramTimeInSeconds();
- if(programname.empty()) {
- if(len <= resname.length())
- return FALSE;
- len = resname.length();
- sprintf(buf, "%s", resname.data());
- return true;
- }
- if(channelname.empty()) {
- if(len <= resname.length()+programname.length()+64)
- return FALSE;
- len = resname.length()+programname.length()+64;
- LONGLONG curTime = comm->currRes->GetOriginTime()/10000000;
- sprintf(buf, "%s -> %s %.2d:%.2d:%.2d", resname.data(), programname.data(),
- (int)curTime/3600, (int)curTime%3600/60, (int)curTime%60);
- return TRUE;
- }
- if(len <= channelname.length()+programname.length()+channelname.length()+64)
- return FALSE;
- len = channelname.length()+programname.length()+channelname.length()+64;
- LONGLONG curTime = comm->currRes->GetOriginTime()/10000000;
- sprintf(buf, "%s -> %s %.2d:%.2d:%.2d", channelname.data(), programname.data(),
- (int)curTime/3600, (int)curTime%3600/60, (int)curTime%60);
- if(progtime)
- sprintf(buf+strlen(buf), "/%.2d:%.2d:%.2d", (int)progtime/3600, (int)progtime%3600/60, (int)progtime%60);
- return TRUE;
- }
- // 获取当前资源的缓冲百分比
- int Layer1::GetBufferPercent() {
- if(!comm || !comm->currRes)
- return -1;
- return comm->currRes->GetBufferPercent();
- }
- // 获取当前频道的码率
- float Layer1::GetChannelBitRate() {
- if(!comm || !comm->currRes)
- return 0.0f;
- return comm->currRes->GetBitRate();
- }
- // 获取Sample,可能得到普通Sample或者MediaType(参考struct SampleHeader的注释)
- P2P_RETURN_TYPE Layer1::GetData(
- SampleHeader& header, // out, 数据头
- PBYTE& pData, // out, 存储数据的缓冲区
- const UINT maxSize, // in, 缓冲区的长度
- const bool bAudio, // in, 获取音频还是视频
- const bool bKeySample // in, 是否寻找关键帧
- )
- {
- if(!comm || !comm->currRes)
- return PRT_NOT_INIT;
- return comm->currRes->GetData(header, pData, maxSize, bAudio, bKeySample);
- }
- }