首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > PowerDesigner >

RTMPdump 源代码分析 六: 建立一个流媒体连接 (NetStream部分 1)

2013-10-23 
RTMPdump 源代码分析 6: 建立一个流媒体连接 (NetStream部分 1)前文已经分析了 RTMPdump中建立一个NetConn

RTMPdump 源代码分析 6: 建立一个流媒体连接 (NetStream部分 1)

前文已经分析了 RTMPdump中建立一个NetConnection的过程:RTMPdump 源代码分析 5: 建立一个流媒体连接 (NetConnection部分)

多余的话不多说,下面先来看看RTMP_ConnectStream(),该函数主要用于在NetConnection基础上建立一个NetStream。

RTMP_ConnectStream()

//读取收下来的ChunkintRTMP_ReadPacket(RTMP *r, RTMPPacket *packet){//packet 存读取完后的的数据//Chunk Header最大值18  uint8_t hbuf[RTMP_MAX_HEADER_SIZE] = { 0 };//header 指向的是从Socket中收下来的数据  char *header = (char *)hbuf;  int nSize, hSize, nToRead, nChunk;  int didAlloc = FALSE;  RTMP_Log(RTMP_LOGDEBUG2, "%s: fd=%d", __FUNCTION__, r->m_sb.sb_socket);  //收下来的数据存入hbuf  if (ReadN(r, (char *)hbuf, 1) == 0)    {      RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header", __FUNCTION__);      return FALSE;    }  //块类型fmt  packet->m_headerType = (hbuf[0] & 0xc0) >> 6;  //块流ID(2-63)  packet->m_nChannel = (hbuf[0] & 0x3f);  header++;  //块流ID第1字节为0时,块流ID占2个字节  if (packet->m_nChannel == 0)    {      if (ReadN(r, (char *)&hbuf[1], 1) != 1){  RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header 2nd byte",      __FUNCTION__);  return FALSE;}  //计算块流ID(64-319)      packet->m_nChannel = hbuf[1];      packet->m_nChannel += 64;      header++;    }  //块流ID第1字节为0时,块流ID占3个字节  else if (packet->m_nChannel == 1)    {      int tmp;      if (ReadN(r, (char *)&hbuf[1], 2) != 2){  RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header 3nd byte",      __FUNCTION__);  return FALSE;}      tmp = (hbuf[2] << 8) + hbuf[1];  //计算块流ID(64-65599)      packet->m_nChannel = tmp + 64;      RTMP_Log(RTMP_LOGDEBUG, "%s, m_nChannel: %0x", __FUNCTION__, packet->m_nChannel);      header += 2;    }  //ChunkHeader的大小(4种)  nSize = packetSize[packet->m_headerType];  if (nSize == RTMP_LARGE_HEADER_SIZE)/* if we get a full header the timestamp is absolute */    packet->m_hasAbsTimestamp = TRUE;//11字节的完整ChunkMsgHeader的TimeStamp是绝对值  else if (nSize < RTMP_LARGE_HEADER_SIZE)    {/* using values from the last message of this channel */      if (r->m_vecChannelsIn[packet->m_nChannel])memcpy(packet, r->m_vecChannelsIn[packet->m_nChannel],       sizeof(RTMPPacket));    }  nSize--;  if (nSize > 0 && ReadN(r, header, nSize) != nSize)    {      RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet header. type: %x",  __FUNCTION__, (unsigned int)hbuf[0]);      return FALSE;    }  hSize = nSize + (header - (char *)hbuf);  if (nSize >= 3)    {//TimeStamp(注意 BigEndian to SmallEndian)(11,7,3字节首部都有)      packet->m_nTimeStamp = AMF_DecodeInt24(header);      /*RTMP_Log(RTMP_LOGDEBUG, "%s, reading RTMP packet chunk on channel %x, headersz %i, timestamp %i, abs timestamp %i", __FUNCTION__, packet.m_nChannel, nSize, packet.m_nTimeStamp, packet.m_hasAbsTimestamp); *///消息长度(11,7字节首部都有)      if (nSize >= 6){  packet->m_nBodySize = AMF_DecodeInt24(header + 3);  packet->m_nBytesRead = 0;  RTMPPacket_Free(packet);//(11,7字节首部都有)  if (nSize > 6)    {  //Msg type ID      packet->m_packetType = header[6];  //Msg Stream ID      if (nSize == 11)packet->m_nInfoField2 = DecodeInt32LE(header + 7);    }}  //Extend TimeStamp      if (packet->m_nTimeStamp == 0xffffff){  if (ReadN(r, header + nSize, 4) != 4)    {      RTMP_Log(RTMP_LOGERROR, "%s, failed to read extended timestamp",  __FUNCTION__);      return FALSE;    }  packet->m_nTimeStamp = AMF_DecodeInt32(header + nSize);  hSize += 4;}    }  RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)hbuf, hSize);  if (packet->m_nBodySize > 0 && packet->m_body == NULL)    {      if (!RTMPPacket_Alloc(packet, packet->m_nBodySize)){  RTMP_Log(RTMP_LOGDEBUG, "%s, failed to allocate packet", __FUNCTION__);  return FALSE;}      didAlloc = TRUE;      packet->m_headerType = (hbuf[0] & 0xc0) >> 6;    }  nToRead = packet->m_nBodySize - packet->m_nBytesRead;  nChunk = r->m_inChunkSize;  if (nToRead < nChunk)    nChunk = nToRead;  /* Does the caller want the raw chunk? */  if (packet->m_chunk)    {      packet->m_chunk->c_headerSize = hSize;      memcpy(packet->m_chunk->c_header, hbuf, hSize);      packet->m_chunk->c_chunk = packet->m_body + packet->m_nBytesRead;      packet->m_chunk->c_chunkSize = nChunk;    }  if (ReadN(r, packet->m_body + packet->m_nBytesRead, nChunk) != nChunk)    {      RTMP_Log(RTMP_LOGERROR, "%s, failed to read RTMP packet body. len: %lu",  __FUNCTION__, packet->m_nBodySize);      return FALSE;    }  RTMP_LogHexString(RTMP_LOGDEBUG2, (uint8_t *)packet->m_body + packet->m_nBytesRead, nChunk);  packet->m_nBytesRead += nChunk;  /* keep the packet as ref for other packets on this channel */  if (!r->m_vecChannelsIn[packet->m_nChannel])    r->m_vecChannelsIn[packet->m_nChannel] = (RTMPPacket *) malloc(sizeof(RTMPPacket));  memcpy(r->m_vecChannelsIn[packet->m_nChannel], packet, sizeof(RTMPPacket));  //读取完毕  if (RTMPPacket_IsReady(packet))    {      /* make packet's timestamp absolute */      if (!packet->m_hasAbsTimestamp)packet->m_nTimeStamp += r->m_channelTimestamp[packet->m_nChannel];/* timestamps seem to be always relative!! */      r->m_channelTimestamp[packet->m_nChannel] = packet->m_nTimeStamp;      /* reset the data from the stored packet. we keep the header since we may use it later if a new packet for this channel */      /* arrives and requests to re-use some info (small packet header) */      r->m_vecChannelsIn[packet->m_nChannel]->m_body = NULL;      r->m_vecChannelsIn[packet->m_nChannel]->m_nBytesRead = 0;      r->m_vecChannelsIn[packet->m_nChannel]->m_hasAbsTimestamp = FALSE;/* can only be false if we reuse header */    }  else    {      packet->m_body = NULL;/* so it won't be erased on free */    }  return TRUE;}

在这里要注意的是,接收下来的实际上是块(Chunk)而不是消息(Message),因为消息(Message)在网络上传播的时候,实际上要分割成块(Chunk)。

这里解析的就是块(Chunk)

可参考:RTMP规范简单分析

具体的解析代码我就不多说了,直接参考RTMP协议规范就可以了,一个字节一个字节的解析就OK了。



热点排行