librtmp 源码结构分析

原文地址:http://blog.csdn.net/gengxt2003/article/details/51610546

感谢原作者的贡献

第一步——握手(Hand Shake)

代码在 handshake.h文件中,

该文件中 HandShake 函数是处理握手的。

第二 步—–建立连接NetConnection  在文件rtmp.cpp 中

RTMP_Connect():

其内部调用了 

RTMP_Connect0() 和  RTMP_Connect1()。

RTMP_Connect0() 主要是建立Socket连接

RTMP_Connect1() 建立RTMP连接.

第三步—–建立流 NetStream  代码也在rtmp.cpp中

RTMP_ConnectStream

在这个函数中调用了

RTMP_ReadPacket()

RTMP_ClientPacket()

第一个函数的作用是读取通过Socket接收下来的消息(Message)包,但是不做任何处理。第二个函数则是处理消息(Message),并做出响应。这两个函数结合,就可以完成接收消息然后响应消息的步骤。

RTMP_ReadPacket 接收下来的是Chunk

RTMP_ClientPacket() 是用来处理消息,根据不同的消息,做不同的调用。

switch (packet->m_packetType)  
 {  
case 0x01:
break;
case 0x02:
break;
case 0x14:  
       
      if (HandleInvoke(r, packet->m_body, packet->m_nBodySize) == 1)  
    bHasMediaPacket = 2;  
      break;  
……
}

消息类型为0x14的消息,即消息类型ID为20的消息,是AMF0编码的命令消息,

依次调用

AMF_Decode(&obj, body, nBodySize, FALSE);  
 
  AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method);  
  
(AVMATCH(&method, &av__result))  

三个命令,

针对不同的method,处理不同的命令。

这些命令有以下这些(不完整)

AVMATCH(&methodInvoked, &av_connect)
AVMATCH(&methodInvoked, &av_createStream)
AVMATCH(&methodInvoked, &av_play)
AVMATCH(&methodInvoked, &av_publish)
AVMATCH(&method, &av_onBWDone)
等等。

第四步——发送消息

消息是如何发送的?

  • 发送connect命令使用函数SendConnectPacket()
  • 发送createstream命令使用RTMP_SendCreateStream()
  • 发送realeaseStream命令使用SendReleaseStream()
  • 发送publish命令使用SendPublish()
  • 发送deleteStream的命令使用SendDeleteStream()
  • 发送pause命令使用RTMP_SendPause()

函数命名有两种规律:RTMP_Send***()或者Send***(),其中*号代表命令的名称


发送消息比较类似:
总体的思路是声明一个RTMPPacket类型的结构体,然后设置各种属性值,最后交给RTMP_SendPacket()进行发送。

RTMPPacket类型的结构体定义如下,一个RTMPPacket对应RTMP协议规范里面的一个块(Chunk)。


//Chunk信息
  typedef struct RTMPPacket
  {
    uint8_t m_headerType;//ChunkMsgHeader的类型(4种)
    uint8_t m_packetType;//Message type ID(1-7协议控制;8,9音视频;10以后为AMF编码消息)
    uint8_t m_hasAbsTimestamp;    /* Timestamp 是绝对值还是相对值? */
    int m_nChannel;            //块流ID
    uint32_t m_nTimeStamp;    // Timestamp
    int32_t m_nInfoField2;    /* last 4 bytes in a long header,消息流ID */
    uint32_t m_nBodySize;    //消息长度
    uint32_t m_nBytesRead;
    RTMPChunk *m_chunk;
    char *m_body;
  } RTMPPacket;

RTMP_SendPacket()
各种的RTMPPacket(即各种Chunk)都需要用这个函数进行发送。
这个函数  按照RTMP规范将数据编码成符合规范的块(Chunk),

在这里需要注意一个函数:WriteN()。该函数完成了将数据发送出去的功能。


在这个函数里根据协议不同,调用相应的函数
  1. if (r->Link.protocol & RTMP_FEATURE_HTTP)  
  2.         nBytes = HTTP_Post(r, RTMPT_SEND, ptr, n);  
  3.       else  
  4.         nBytes = RTMPSockBuf_Send(&r->m_sb, ptr, n);  

其中  RTMPSockBuf_Send()完成了数据发送的功能
在这个RTMPSockBuf_Send()函数中 调用了系统Socket的send()函数完成了数据的发送功能

到此,发送消息能够通过socket发送出去。


第五步——接收消息

RTMPdump中完成视音频数据的接收的函数是:RTMP_Read()。

RTMP_Read()中实际读取数据的函数是Read_1_Packet(),它的功能是从网络上读取一个RTMPPacket的数据,

Read_1_Packet()里面实现从网络中读取视音频数据的函数是RTMP_GetNextMediaPacket()。

RTMP_GetNextMediaPacket 里会调用两个函数:RTMP_ReadPacket()以及RTMP_ClientPacket()。这两个函数中,前一个函数负责从网络上读取数据,后一个负责处理数据。

在RTMP_ReadPacket()函数里完成从Socket中读取数据的函数是ReadN(),

ReadN()中实现从Socket中接收数据的函数是RTMPSockBuf_Fill(),
RTMPSockBuf_Fill()函数中调用了系统Socket的recv()函数接收RTMP连接传输过来的数据。

第六步——处理各种消息

RTMPdump 的函数 RTMP_ClientPacket(), 主要完成了各种消息的处理。



消息ID
功能
调用函数

0x01
设置块(Chunk)大小
HandleChangeChunkSize()

0x03
致谢
无函数

0x04
用户控制
HandleCtrl

0x05
窗口致谢大小(Window Acknowledgement Size
HandleServerBW()

0x06
设置对等端带宽(Set Peer Bandwidth)
HandleClientBW()

0x08
传输音频


0x09
传输视频


0x0f–11
传输AMF3编码


0x12–14
传输AMF0编码












原文地址:http://blog.csdn.net/gengxt2003/article/details/51610546

感谢原作者的贡献

第一步——握手(Hand Shake)

代码在 handshake.h文件中,

该文件中 HandShake 函数是处理握手的。

第二 步—–建立连接NetConnection  在文件rtmp.cpp 中

RTMP_Connect():

其内部调用了 

RTMP_Connect0() 和  RTMP_Connect1()。

RTMP_Connect0() 主要是建立Socket连接

RTMP_Connect1() 建立RTMP连接.

第三步—–建立流 NetStream  代码也在rtmp.cpp中

RTMP_ConnectStream

在这个函数中调用了

RTMP_ReadPacket()

RTMP_ClientPacket()

第一个函数的作用是读取通过Socket接收下来的消息(Message)包,但是不做任何处理。第二个函数则是处理消息(Message),并做出响应。这两个函数结合,就可以完成接收消息然后响应消息的步骤。

RTMP_ReadPacket 接收下来的是Chunk

RTMP_ClientPacket() 是用来处理消息,根据不同的消息,做不同的调用。

switch (packet->m_packetType)  
 {  
case 0x01:
break;
case 0x02:
break;
case 0x14:  
       
      if (HandleInvoke(r, packet->m_body, packet->m_nBodySize) == 1)  
    bHasMediaPacket = 2;  
      break;  
……
}

消息类型为0x14的消息,即消息类型ID为20的消息,是AMF0编码的命令消息,

依次调用

AMF_Decode(&obj, body, nBodySize, FALSE);  
 
  AMFProp_GetString(AMF_GetProp(&obj, NULL, 0), &method);  
  
(AVMATCH(&method, &av__result))  

三个命令,

针对不同的method,处理不同的命令。

这些命令有以下这些(不完整)

AVMATCH(&methodInvoked, &av_connect)
AVMATCH(&methodInvoked, &av_createStream)
AVMATCH(&methodInvoked, &av_play)
AVMATCH(&methodInvoked, &av_publish)
AVMATCH(&method, &av_onBWDone)
等等。

第四步——发送消息

消息是如何发送的?

  • 发送connect命令使用函数SendConnectPacket()
  • 发送createstream命令使用RTMP_SendCreateStream()
  • 发送realeaseStream命令使用SendReleaseStream()
  • 发送publish命令使用SendPublish()
  • 发送deleteStream的命令使用SendDeleteStream()
  • 发送pause命令使用RTMP_SendPause()

函数命名有两种规律:RTMP_Send***()或者Send***(),其中*号代表命令的名称


发送消息比较类似:
总体的思路是声明一个RTMPPacket类型的结构体,然后设置各种属性值,最后交给RTMP_SendPacket()进行发送。

RTMPPacket类型的结构体定义如下,一个RTMPPacket对应RTMP协议规范里面的一个块(Chunk)。


//Chunk信息
  typedef struct RTMPPacket
  {
    uint8_t m_headerType;//ChunkMsgHeader的类型(4种)
    uint8_t m_packetType;//Message type ID(1-7协议控制;8,9音视频;10以后为AMF编码消息)
    uint8_t m_hasAbsTimestamp;    /* Timestamp 是绝对值还是相对值? */
    int m_nChannel;            //块流ID
    uint32_t m_nTimeStamp;    // Timestamp
    int32_t m_nInfoField2;    /* last 4 bytes in a long header,消息流ID */
    uint32_t m_nBodySize;    //消息长度
    uint32_t m_nBytesRead;
    RTMPChunk *m_chunk;
    char *m_body;
  } RTMPPacket;

RTMP_SendPacket()
各种的RTMPPacket(即各种Chunk)都需要用这个函数进行发送。
这个函数  按照RTMP规范将数据编码成符合规范的块(Chunk),

在这里需要注意一个函数:WriteN()。该函数完成了将数据发送出去的功能。


在这个函数里根据协议不同,调用相应的函数
  1. if (r->Link.protocol & RTMP_FEATURE_HTTP)  
  2.         nBytes = HTTP_Post(r, RTMPT_SEND, ptr, n);  
  3.       else  
  4.         nBytes = RTMPSockBuf_Send(&r->m_sb, ptr, n);  

其中  RTMPSockBuf_Send()完成了数据发送的功能
在这个RTMPSockBuf_Send()函数中 调用了系统Socket的send()函数完成了数据的发送功能

到此,发送消息能够通过socket发送出去。


第五步——接收消息

RTMPdump中完成视音频数据的接收的函数是:RTMP_Read()。

RTMP_Read()中实际读取数据的函数是Read_1_Packet(),它的功能是从网络上读取一个RTMPPacket的数据,

Read_1_Packet()里面实现从网络中读取视音频数据的函数是RTMP_GetNextMediaPacket()。

RTMP_GetNextMediaPacket 里会调用两个函数:RTMP_ReadPacket()以及RTMP_ClientPacket()。这两个函数中,前一个函数负责从网络上读取数据,后一个负责处理数据。

在RTMP_ReadPacket()函数里完成从Socket中读取数据的函数是ReadN(),

ReadN()中实现从Socket中接收数据的函数是RTMPSockBuf_Fill(),
RTMPSockBuf_Fill()函数中调用了系统Socket的recv()函数接收RTMP连接传输过来的数据。

第六步——处理各种消息

RTMPdump 的函数 RTMP_ClientPacket(), 主要完成了各种消息的处理。



消息ID
功能
调用函数

0x01
设置块(Chunk)大小
HandleChangeChunkSize()

0x03
致谢
无函数

0x04
用户控制
HandleCtrl

0x05
窗口致谢大小(Window Acknowledgement Size
HandleServerBW()

0x06
设置对等端带宽(Set Peer Bandwidth)
HandleClientBW()

0x08
传输音频


0x09
传输视频


0x0f–11
传输AMF3编码


0x12–14
传输AMF0编码












猜你喜欢

转载自blog.csdn.net/qinglongzhan/article/details/80612360