RTMPdump 源代码分析 1: main()函数

RTMPdump (libRTMP) 源代码分析4: 连接第一步——握手 (HandShake)

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

RTMPdump (libRTMP) 源代码分析10: 处理各种消息 (Message)

函数调用结构图

 

 

上回说到,有两个函数尤为重要:

 

[cpp]  view plain  copy
 
  1. //处理接收到的Chunk  
  2. int  
  3. RTMP_ClientPacket(RTMP *r, RTMPPacket *packet)  
  4. {  
  5.   int bHasMediaPacket = 0;  
  6.   switch (packet->m_packetType)  
  7.     {  
  8.     //RTMP消息类型ID=1,设置块大小  
  9.     case 0x01:  
  10.       /* chunk size */  
  11.         //----------------  
  12.         r->dlg->AppendCInfo("处理收到的数据。消息 Set Chunk Size (typeID=1)。");  
  13.         //-----------------------------  
  14.         RTMP_LogPrintf("处理消息 Set Chunk Size (typeID=1)\n");  
  15.       HandleChangeChunkSize(r, packet);  
  16.       break;  
  17.     //RTMP消息类型ID=3,致谢  
  18.     case 0x03:  
  19.       /* bytes read report */  
  20.       RTMP_Log(RTMP_LOGDEBUG, "%s, received: bytes read report", __FUNCTION__);  
  21.       break;  
  22.     //RTMP消息类型ID=4,用户控制  
  23.     case 0x04:  
  24.       /* ctrl */  
  25.         //----------------  
  26.         r->dlg->AppendCInfo("处理收到的数据。消息 User Control (typeID=4)。");  
  27.         //-----------------------------  
  28.         RTMP_LogPrintf("处理消息 User Control (typeID=4)\n");  
  29.       HandleCtrl(r, packet);  
  30.       break;  
  31.     //RTMP消息类型ID=5  
  32.     case 0x05:  
  33.       /* server bw */  
  34.         //----------------  
  35.         r->dlg->AppendCInfo("处理收到的数据。消息 Window Acknowledgement Size (typeID=5)。");  
  36.         //-----------------------------  
  37.         RTMP_LogPrintf("处理消息 Window Acknowledgement Size (typeID=5)\n");  
  38.       HandleServerBW(r, packet);  
  39.       break;  
  40.     //RTMP消息类型ID=6  
  41.     case 0x06:  
  42.       /* client bw */  
  43.         //----------------  
  44.         r->dlg->AppendCInfo("处理收到的数据。消息 Set Peer Bandwidth (typeID=6)。");  
  45.         //-----------------------------  
  46.         RTMP_LogPrintf("处理消息 Set Peer Bandwidth (typeID=6)\n");  
  47.       HandleClientBW(r, packet);  
  48.       break;  
  49.     //RTMP消息类型ID=8,音频数据  
  50.     case 0x08:  
  51.       /* audio data */  
  52.       /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: audio %lu bytes", __FUNCTION__, packet.m_nBodySize); */  
  53.       HandleAudio(r, packet);  
  54.       bHasMediaPacket = 1;  
  55.       if (!r->m_mediaChannel)  
  56.     r->m_mediaChannel = packet->m_nChannel;  
  57.       if (!r->m_pausing)  
  58.     r->m_mediaStamp = packet->m_nTimeStamp;  
  59.       break;  
  60.     //RTMP消息类型ID=9,视频数据  
  61.     case 0x09:  
  62.       /* video data */  
  63.       /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: video %lu bytes", __FUNCTION__, packet.m_nBodySize); */  
  64.       HandleVideo(r, packet);  
  65.       bHasMediaPacket = 1;  
  66.       if (!r->m_mediaChannel)  
  67.     r->m_mediaChannel = packet->m_nChannel;  
  68.       if (!r->m_pausing)  
  69.     r->m_mediaStamp = packet->m_nTimeStamp;  
  70.       break;  
  71.     //RTMP消息类型ID=15,AMF3编码,忽略  
  72.     case 0x0F:          /* flex stream send */  
  73.       RTMP_Log(RTMP_LOGDEBUG,  
  74.       "%s, flex stream send, size %lu bytes, not supported, ignoring",  
  75.       __FUNCTION__, packet->m_nBodySize);  
  76.       break;  
  77.     //RTMP消息类型ID=16,AMF3编码,忽略  
  78.     case 0x10:          /* flex shared object */  
  79.       RTMP_Log(RTMP_LOGDEBUG,  
  80.       "%s, flex shared object, size %lu bytes, not supported, ignoring",  
  81.       __FUNCTION__, packet->m_nBodySize);  
  82.       break;  
  83.     //RTMP消息类型ID=17,AMF3编码,忽略  
  84.     case 0x11:          /* flex message */  
  85.       {  
  86.     RTMP_Log(RTMP_LOGDEBUG,  
  87.         "%s, flex message, size %lu bytes, not fully supported",  
  88.         __FUNCTION__, packet->m_nBodySize);  
  89.     /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */  
  90.   
  91.     /* some DEBUG code */  
  92. #if 0  
  93.        RTMP_LIB_AMFObject obj;  
  94.        int nRes = obj.Decode(packet.m_body+1, packet.m_nBodySize-1);  
  95.        if(nRes < 0) {  
  96.        RTMP_Log(RTMP_LOGERROR, "%s, error decoding AMF3 packet", __FUNCTION__);  
  97.        /*return; */  
  98.        }  
  99.   
  100.        obj.Dump();  
  101. #endif  
  102.   
  103.     if (HandleInvoke(r, packet->m_body + 1, packet->m_nBodySize - 1) == 1)  
  104.       bHasMediaPacket = 2;  
  105.     break;  
  106.       }  
  107.     //RTMP消息类型ID=18,AMF0编码,数据消息  
  108.     case 0x12:  
  109.       /* metadata (notify) */  
  110.   
  111.       RTMP_Log(RTMP_LOGDEBUG, "%s, received: notify %lu bytes", __FUNCTION__,  
  112.       packet->m_nBodySize);  
  113.       //处理元数据,暂时注释  
  114.       /* 
  115.       if (HandleMetadata(r, packet->m_body, packet->m_nBodySize)) 
  116.     bHasMediaPacket = 1; 
  117.       break; 
  118.       */  
  119.     //RTMP消息类型ID=19,AMF0编码,忽略  
  120.     case 0x13:  
  121.       RTMP_Log(RTMP_LOGDEBUG, "%s, shared object, not supported, ignoring",  
  122.       __FUNCTION__);  
  123.       break;  
  124.     //RTMP消息类型ID=20,AMF0编码,命令消息  
  125.     //处理命令消息!  
  126.     case 0x14:  
  127.         //----------------  
  128.         r->dlg->AppendCInfo("处理收到的数据。消息 命令 (AMF0编码) (typeID=20)。");  
  129.         //-----------------------------  
  130.       /* invoke */  
  131.       RTMP_Log(RTMP_LOGDEBUG, "%s, received: invoke %lu bytes", __FUNCTION__,  
  132.       packet->m_nBodySize);  
  133.       RTMP_LogPrintf("处理命令消息 (typeID=20,AMF0编码)\n");  
  134.       /*RTMP_LogHex(packet.m_body, packet.m_nBodySize); */  
  135.   
  136.       if (HandleInvoke(r, packet->m_body, packet->m_nBodySize) == 1)  
  137.     bHasMediaPacket = 2;  
  138.       break;  
  139.     //RTMP消息类型ID=22  
  140.     case 0x16:  
  141.       {  
  142.     /* go through FLV packets and handle metadata packets */  
  143.     unsigned int pos = 0;  
  144.     uint32_t nTimeStamp = packet->m_nTimeStamp;  
  145.   
  146.     while (pos + 11 < packet->m_nBodySize)  
  147.       {  
  148.         uint32_t dataSize = AMF_DecodeInt24(packet->m_body + pos + 1);   /* size without header (11) and prevTagSize (4) */  
  149.   
  150.         if (pos + 11 + dataSize + 4 > packet->m_nBodySize)  
  151.           {  
  152.         RTMP_Log(RTMP_LOGWARNING, "Stream corrupt?!");  
  153.         break;  
  154.           }  
  155.         if (packet->m_body[pos] == 0x12)  
  156.           {  
  157.         HandleMetadata(r, packet->m_body + pos + 11, dataSize);  
  158.           }  
  159.         else if (packet->m_body[pos] == 8 || packet->m_body[pos] == 9)  
  160.           {  
  161.         nTimeStamp = AMF_DecodeInt24(packet->m_body + pos + 4);  
  162.         nTimeStamp |= (packet->m_body[pos + 7] << 24);  
  163.           }  
  164.         pos += (11 + dataSize + 4);  
  165.       }  
  166.     if (!r->m_pausing)  
  167.       r->m_mediaStamp = nTimeStamp;  
  168.   
  169.     /* FLV tag(s) */  
  170.     /*RTMP_Log(RTMP_LOGDEBUG, "%s, received: FLV tag(s) %lu bytes", __FUNCTION__, packet.m_nBodySize); */  
  171.     bHasMediaPacket = 1;  
  172.     break;  
  173.       }  
  174.     default:  
  175.       RTMP_Log(RTMP_LOGDEBUG, "%s, unknown packet type received: 0x%02x", __FUNCTION__,  
  176.       packet->m_packetType);  
  177. #ifdef _DEBUG  
  178.       RTMP_LogHex(RTMP_LOGDEBUG, (const uint8_t *)packet->m_body, packet->m_nBodySize);  
  179. #endif  
  180.     }  
  181.   
  182.   return bHasMediaPacket;  
  183. }  

 

可以发现它调用了HandleInvoke()函数来处理服务器发来的AMF0编码的命令,来看看细节:

2.调用AMFProp_GetString()获取具体命令的字符串

[cpp]  view plain  copy
 
  1. AVMATCH(&methodInvoked, &av_connect)  
  2. AVMATCH(&methodInvoked, &av_createStream)  
  3. AVMATCH(&methodInvoked, &av_play)  
  4. AVMATCH(&methodInvoked, &av_publish)  
  5. AVMATCH(&method, &av_onBWDone)  


等等,不一一例举了

[cpp]  view plain  copy
 
  1. else if (AVMATCH(&methodInvoked, &av_createStream))  
  2.     {  
  3.         //----------------  
  4.         r->dlg->AppendMLInfo(20,0,"命令消息","Result (CreateStream)");  
  5.         //-----------------------------  
  6.       r->m_stream_id = (int)AMFProp_GetNumber(AMF_GetProp(&obj, NULL, 3));  
  7.   
  8.       if (r->Link.protocol & RTMP_FEATURE_WRITE)  
  9.         {  
  10.           SendPublish(r);  
  11.         }  
  12.       else  
  13.         {  
  14.           if (r->Link.lFlags & RTMP_LF_PLST)  
  15.             SendPlaylist(r);  
  16.           //----------------  
  17.           r->dlg->AppendCInfo("发送数据。消息 命令 (typeID=20) (Play)。");  
  18.           //-----------------------------  
  19.           RTMP_LogPrintf("发送命令消息“play” (typeID=20)\n");  
  20.           SendPlay(r);  
  21.           RTMP_SendCtrl(r, 3, r->m_stream_id, r->m_nBufferMS);  
  22.         }  
  23.     }