锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 外包精品 / 通信 / 电台直播系统和音频直播系统 / Peercast收听电台的源代码流程分析
服务方向
软件开发
办公财务MIS
股票
设备监控
网页信息采集及控制
多媒体
软件开发培训
Java 安卓移动开发
Java Web开发
HTML5培训
iOS培训
网站前端开发
VC++
C++游戏开发培训
C#软件
C语言(Linux)
ASP.NET网站开发(C#)
C#软件+ASP.NET网站
SOCKET网络通信开发
COMOLE和ActiveX开发
C++(Linux)
汇编和破解
驱动开发
SkinMagicVC++换肤
流媒体开发
MicroStation二次开发
计算机英语翻译
联系方式
固话:0371-63888850
手机:138-0381-0136
Q Q:396806883

Peercast收听电台的源代码流程分析

2007年05月14日 上午 11:42

Play

以收听JOKV-FM(TEST)为例,在YP上点击Play,则其URL地址为
peercast://pls/25838B9F1EAE27079B793C9FBA0E4156?tip=222.148.187.176:7144

case WM_COPYDATA:
    {
     COPYDATASTRUCT *pc = (COPYDATASTRUCT *)lParam;
     LOG_DEBUG("URL request: %s",pc->lpData);
     if (pc->dwData == WM_PLAYCHANNEL)
     {
      ChanInfo info;
      servMgr->procConnectArgs((char *)pc->lpData,info);
      chanMgr->findAndPlayChannel(info,false);
     }
     //sys->callLocalURL((const char *)pc->lpData,servMgr->serverHost.port);
    }
    break;

解析连接参数

// 解析连接参数,str表示相应的频道URL,例65051E037A7A2A3433090065051E037A?tip=211.132.83.9:7144
// 从URL中解析频道的相关信息以初始化info
void ServMgr::procConnectArgs(char *str,ChanInfo &info)
{
char arg[512];
char curr[256];
//使args等于?后面的字符串,即tip=211.132.83.9:7144
char *args = strstr(str,"?");
if (args)
   *args++=0;
info.initNameID(str);
if (args)
{
   //nextCGIarg分解字符串,把"tip"保存到curr中,"211.132.83.9"保存到arg中
   while (args=nextCGIarg(args,curr,arg))
   {
    LOG_DEBUG("cmd: %s, arg: %s",curr,arg);
    if (strcmp(curr,"sip")==0)
    // sip - add network connection to client with channel
    {
     Host h;
     h.fromStrName(arg,DEFAULT_PORT);
     if (addOutgoing(h,servMgr->networkID,true))
      LOG_NETWORK("Added connection: %s",arg);
    }else if (strcmp(curr,"pip")==0)
    // pip - add private network connection to client with channel
    {
     Host h;
     h.fromStrName(arg,DEFAULT_PORT);
     if (addOutgoing(h,info.id,true))
      LOG_NETWORK("Added private connection: %s",arg);
    }else if (strcmp(curr,"ip")==0)
    // ip - add hit
    {
     Host h;
     h.fromStrName(arg,DEFAULT_PORT);
     ChanHit hit;
     hit.init();
     hit.host = h;
     hit.rhost[0] = h;
     hit.rhost[1].init();
     hit.chanID = info.id;
     hit.recv = true;
     chanMgr->addHit(hit);
    }else if (strcmp(curr,"tip")==0)
    // tip - add tracker hit
    {
     Host h;
     h.fromStrName(arg,DEFAULT_PORT);
     chanMgr->addHit(h,info.id,true);
    }

   }
}
}

根据info中的信息寻找和播放频道


void ChanMgr::findAndPlayChannel(ChanInfo &info, bool keep)
{
ChanFindInfo *cfi = new ChanFindInfo;
cfi->info = info;
cfi->keep = keep;
cfi->func = findAndPlayChannelProc;

sys->startThread(cfi);
}

启动线程

THREAD_PROC findAndPlayChannelProc(ThreadInfo *th)
{
ChanFindInfo *cfi = (ChanFindInfo *)th;
ChanInfo info;
info = cfi->info;

Channel *ch = chanMgr->findChannelByNameID(info);
chanMgr->currFindAndPlayChannel = info.id;
if (!ch)
   ch = chanMgr->findAndRelay(info);
if (ch)
{
   // check that a different channel hasn`t be selected already.
   if (chanMgr->currFindAndPlayChannel.isSame(ch->info.id))
    chanMgr->playChannel(ch->info);
   if (cfi->keep)
    ch->stayConnected = cfi->keep;
}
delete cfi;
return 0;
}

创建频道

// 寻找和转播相应频道
Channel *ChanMgr::findAndRelay(ChanInfo &info)
{
char idStr[64];
info.id.toStr(idStr);
LOG_CHANNEL("Searching for: %s (%s)",idStr,info.name.cstr());
peercastApp->notifyMessage(ServMgr::NT_PEERCAST,"Finding channel...");

Channel *c = NULL;
c = findChannelByNameID(info);
//如果当前没有转播该频道,则新创建一个频道
if (!c)
{
   c = chanMgr->createChannel(info,NULL);
   if (c)
   {
    c->setStatus(Channel::S_SEARCHING);   
    c->startGet();
   }
}
for(int i=0; i<600; i++) // search for 1 minute.
{
   c = findChannelByNameID(info);
   if (!c)
   {
    peercastApp->notifyMessage(ServMgr::NT_PEERCAST,"Channel not found");
    return NULL;
   }
  
   if (c->isPlaying() && (c->info.contentType!=ChanInfo::T_UNKNOWN))
    break;
   sys->sleep(100);
}
return c;
}
创建频道

Channel *ChanMgr::createChannel(ChanInfo &info, const char *mount)
{
lock.on();
Channel *nc=NULL;
nc = new Channel();
//将新建的频道加入频道列表
nc->next = channel;
channel = nc;

nc->info = info;
nc->info.lastPlayStart = 0;
nc->info.lastPlayEnd = 0;
nc->info.status = ChanInfo::S_UNKNOWN;
if (mount)
   nc->mount.set(mount);
nc->setStatus(Channel::S_WAIT);
nc->type = Channel::T_ALLOCATED;
nc->info.createdTime = sys->getTime();
LOG_CHANNEL("New channel created");
lock.off();
return nc;
开始获取数据,即新创建一个Source并调用startStream进行实际传输
void Channel::startGet()
{
srcType = SRC_PEERCAST;
type = T_RELAY;
info.srcProtocol = ChanInfo::SP_PCP;

sourceData = new PeercastSource();
startStream();
}
启动传输线程
void Channel::startStream()
{
thread.data = this;
thread.func = stream;
if (!sys->startThread(&thread))
   reset();
}
进行实际的流传输,调用ChannelSource::stream函数
THREAD_PROC Channel::stream(ThreadInfo *thread)
{
// thread->lock();
Channel *ch = (Channel *)thread->data;
while (thread->active && !peercastInst->isQuitting)
{
   LOG_CHANNEL("Channel started");

   ChanHitList *chl = chanMgr->findHitList(ch->info);
   if (!chl)
    chanMgr->addHitList(ch->info);
   ch->sourceData->stream(ch);
   LOG_CHANNEL("Channel stopped");
   if (!ch->stayConnected)
   {
    break;
   }else
   {
    if (!ch->info.lastPlayEnd)
     ch->info.lastPlayEnd = sys->getTime();
    unsigned int diff = (sys->getTime()-ch->info.lastPlayEnd) + 5;
    LOG_DEBUG("Channel sleeping for %d seconds",diff);
    for(unsigned int i=0; i<diff; i++)
    {
     if (!thread->active || peercastInst->isQuitting)
      break;
     sys->sleep(1000);
    }
   }
}
ch->endThread();

return 0;
友情链接
版权所有 Copyright(c)2004-2015 锐英源软件
公司注册号:410105000449586 豫ICP备08007559号 最佳分辨率 1024*768
地址:郑州市文化路47号院1号楼4层(47-1楼位于文化路和红专路十字路口东北角,郑州大学工学院招待所南边,工学院科技报告厅西边。)