Peercast播放模組分析

來源:互聯網
上載者:User

這裡以YP上的JOKV-FM(TEST)為例
當點擊YP上的一個頻道時,其訪問地址為peercast://pls/25838B9F1EAE27079B793C9FBA0E4156?

tip=222.148.187.176:7144
peercast://指的是peercast協議,由於peercast註冊了此協議,所以在IE中輸入這個地址時會自動啟動

peercast並把這個地址傳送給peercast
25838B9F1EAE27079B793C9FBA0E4156指的是廣播端的ChanID,每廣播一個電台peercast會根據相應演算法生

成一個ID,這個ID可以唯一標識一個頻道。
tip=222.148.187.176:7144表示廣播主機的地址和連接埠號碼。這樣的話本地的peercast會先去和這個主機建

立串連,然後根據這個主機去找8個轉播相同頻道的主機,選擇其中最好的一個作為傳輸者。
建立串連後,產生播放清單play.pls如下
[playlist]

NumberOfEntries=1
File1=http://localhost:7144/stream/25838B9F1EAE27079B793C9FBA0E4156.ogg
Title1=JOKV-FM(TEST)
Length1=-1
Version=2

然後調用播放器(例如winamp)去播放這個列表,這時winamp訪問的url地址為

http://localhost:7144/stream/74F7ECF0508E50E62FD3BEB0624921E4.ogg。即winamp通過http方式從

peercast獲得媒體資料並播放,訪問主機為本機localhost,連接埠為7144。
winamp發送的HTTP請求類似如下:
GET /stream/74F7ECF0508E50E62FD3BEB0624921E4.ogg HTTP/1.1
Host: localhost:7144

Peercast有一個servent監聽7144連接埠,並處理髮來的HTTP請求。
void Servent::handshakeHTTP(HTTP &http, bool isHTTP)
{
 char *in = http.cmdLine;

 if (http.isRequest("GET /"))
 {
  char *fn = in+4;
     if (strncmp(fn,"/stream/",8)==0)
   triggerChannel(fn+8,ChanInfo::SP_HTTP,isPrivate());
 }
}

下面主要分析Peercast如何把資料送往播放器

// 觸發頻道,調用processStream傳送媒體資料給播放器
void Servent::triggerChannel(char *str, ChanInfo::PROTOCOL proto,bool relay) 
{
 outputProtocol = proto;
 processStream(false,info);
}

// outputProtocol為HTTP協議,調用sendRawChannel發送資料
void Servent::processStream(bool doneHandshake,ChanInfo &chanInfo)
{
 if (outputProtocol == ChanInfo::SP_HTTP)
 {
  sendRawChannel(true,true);
 }
}

// 發送頻道資料給播放器
void Servent::sendRawChannel(bool sendHead, bool sendData)
{
 try
 {

  sock->setWriteTimeout(DIRECT_WRITE_TIMEOUT*1000);

  Channel *ch = chanMgr->findChannelByID(chanID);
  if (!ch)
   throw StreamException("Channel not found");

  setStatus(S_CONNECTED);

  //這裡進行最重要的資料轉送,請特別注意
  LOG_DEBUG("Starting Raw stream of %s at %d",ch->info.name.cstr(),streamPos);

  if (sendHead)
  {
   ch->headPack.writeRaw(*sock);
   streamPos = ch->headPack.pos + ch->headPack.len;
   LOG_DEBUG("Sent %d bytes header ",ch->headPack.len);
  }

  if (sendData)
  {

   unsigned int streamIndex = ch->streamIndex;
   unsigned int connectTime = sys->getTime();
   unsigned int lastWriteTime = connectTime;

   while ((thread.active) && sock->active())
   {
    ch = chanMgr->findChannelByID(chanID);

    if (ch)
    {

     if (streamIndex != ch->streamIndex)
     {
      streamIndex = ch->streamIndex;
      streamPos = ch->headPack.pos;
      LOG_DEBUG("sendRaw got new stream index");
     }

     ChanPacket rawPack;
     if (ch->rawData.findPacket(streamPos,rawPack))
     {
      if (syncPos != rawPack.sync)
       LOG_ERROR("Send skip: %

d",rawPack.sync-syncPos);
      syncPos = rawPack.sync+1;

      if ((rawPack.type == ChanPacket::T_DATA) ||

(rawPack.type == ChanPacket::T_HEAD))
      {
       rawPack.writeRaw(*sock);
       lastWriteTime = sys->getTime();
      }

      if (rawPack.pos < streamPos)
       LOG_DEBUG("raw: skip back %

d",rawPack.pos-streamPos);
      streamPos = rawPack.pos+rawPack.len;
     }
    }

    if ((sys->getTime()-lastWriteTime) > DIRECT_WRITE_TIMEOUT)
     throw TimeoutException();
    
    sys->sleepIdle();
   }
  }
 }catch(StreamException &e)
 {
  LOG_ERROR("Stream channel: %s",e.msg);
 }
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.