--------------------更新2018.08.20-------------------
添加http_tunnel_example.cpp作為RtspOverHttp示例程序。
--------------------更新2018.08.20結束-------------------
一、example邏輯偽碼
myRTSPClient附帶3個example程序:simple_example、complete_example、common_example。后兩個example都是從simple_example中衍生出來的,以下將以simple_example為主進行解析,並且會在最后說明一下另兩個example與simple_example的差別。
以下是simple_example簡化后的偽代碼,以便理解:
1. main():
2. myRtspClient Client;
3. Client.SetURI("rtsp://127.0.0.1/ansersion");
4. Client.SendDESCRIBE();
5. Client.SendSETUP();
6. Client.SendPLAY();
7. Write 1000 RTP Data to file "test_packet_recv.h264";
8. Client.SendTEARDOWN();
9. return;
二、simple_example.cpp代碼注釋
1 #include <iostream> 2 #include "rtspClient.h" 3 #include <stdio.h> 4 #include <sys/types.h> 5 #include <sys/stat.h> 6 #include <unistd.h> 7 #include <fcntl.h> 8 9 using std::cout; 10 using std::endl; 11 12 int main(int argc, char *argv[]) 13 { 14 string RtspUri("rtsp://127.0.0.1/ansersion"); 15 // string RtspUri("rtsp://192.168.81.145/ansersion"); 16 RtspClient Client; 17 18 /* Set up rtsp server resource URI */ 19 Client.SetURI(RtspUri); 20 21 /* Send DESCRIBE command to server */ 22 Client.DoDESCRIBE(); 23 24 /* Parse SDP message after sending DESCRIBE command */ 25 Client.ParseSDP(); // 解析RTSP服務端受理DESCRIBE命令后返回的SDP信息 26 27 /* Send SETUP command to set up all 'audio' and 'video' 28 * sessions which SDP refers. */ 29 Client.DoSETUP(); 30 31 printf("start PLAY\n"); 32 printf("SDP: %s\n", Client.GetSDP().c_str()); 33 34 /* Send PLAY command to play only the 35 * 'video' sessions.*/ 36 Client.DoPLAY("video"); 37 38 /* Receive 1000 RTP 'video' packets 39 * note(FIXME): 40 * if there are several 'video' session 41 * refered in SDP, only receive packets of the first 42 * 'video' session, the same as 'audio'.*/ 43 int packet_num = 0; 44 uint8_t buf[65534]; 45 size_t size = 0; 46 47 /* Write h264 video data to file "test_packet_recv.h264" 48 * Then it could be played by ffplay */ 49 int fd = open("test_packet_recv.h264", O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); 50 if(Client.GetSPSNalu(buf, &size)) { // 解碼SDP中關於H264的SPS的數據 51 if(write(fd, buf, size) < 0) { // 將SPS寫入文件 52 perror("write"); 53 } 54 } else { 55 printf("SPS error\n"); 56 } 57 58 if(Client.GetPPSNalu(buf, &size)) { // 解碼SDP中關於H264的PPS的數據 59 if(write(fd, buf, size) < 0) { // 將PPS寫入文件 60 perror("write"); 61 } 62 } else { 63 printf("PPS error\n"); 64 } 65 66 while(++packet_num < 1000) { // 接收1000個H264的數據包(確切的說是1000個NALU) 67 if(!Client.GetMediaData("video", buf, &size)) continue; 68 if(write(fd, buf, size) < 0) { 69 perror("write"); 70 } 71 printf("recv %lu\n", size); 72 } 73 74 printf("start TEARDOWN\n"); 75 /* Send TEARDOWN command to teardown all of the sessions */ 76 Client.DoTEARDOWN(); 77 78 return 0; 79 } 80
三、common_example.cpp和complete_example.cpp
common_example.cpp不同於simple_example.cpp的地方只有開頭幾行,這些代碼是為了可以用參數指定RTSP URI。
1 int main(int argc, char *argv[]) 2 { 3 if(argc != 2) { 4 cout << "Usage: " << argv[0] << " <URL>" << endl; 5 cout << "For example: " << endl; 6 cout << argv[0] << " rtsp://127.0.0.1/ansersion" << endl; 7 return 1; 8 } 9 cout << "Start play " << argv[1] << endl; 10 cout << "Then put video data into test_packet_recv.h264" << endl; 11 string RtspUri(argv[1]); 12 // string RtspUri("rtsp://192.168.81.145/ansersion"); 13 RtspClient Client; 14 15 /* Set up rtsp server resource URI */ 16 Client.SetURI(RtspUri); 17 ...... 18 return 0; 19 }
complete_example.cpp不同於simple_example.cpp的地方,就在於每次發送RTSP命令時, 它都會檢查命令發送是否成功,並且檢驗返回信息是否是“200 OK”。
1 int main(int argc, char * argv[]) 2 { 3 ...... 4 /* Send DESCRIBE command to server */ 5 if(Client.DoDESCRIBE() != RTSP_NO_ERROR) { 6 printf("DoDESCRIBE error\n"); 7 return 0; 8 } 9 printf("%s\n", Client.GetResponse().c_str()); 10 /* Check whether server return '200'(OK) */ 11 if(!Client.IsResponse_200_OK()) { 12 printf("DoDESCRIBE error\n"); 13 return 0; 14 } 15 ...... 16 return 0; 17 }
OK!以上便是myRTSP的基礎內容。
