zoukankan      html  css  js  c++  java
  • 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——收流篇:(四)example代码解析

    --------------------更新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
    ");
    32         printf("SDP: %s
    ", 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
    ");
    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
    ");
    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
    ", size);
    72         }
    73 
    74         printf("start TEARDOWN
    ");
    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
    ");
     7                 return 0;
     8         }
     9         printf("%s
    ", Client.GetResponse().c_str());
    10         /* Check whether server return '200'(OK) */
    11         if(!Client.IsResponse_200_OK()) {
    12                 printf("DoDESCRIBE error
    ");
    13                 return 0;
    14         }
    15         ......
    16         return 0;
    17 }

    OK!以上便是myRTSP的基础内容。

    上一篇              回目录         

  • 相关阅读:
    经典的阿里前端笔试题
    Javascript之浏览器兼容EventUtil
    Javascript之对象的创建
    奇妙的CSS之CSS3新特性总结
    前端优化之无阻塞加载脚本
    正则表达式规则与常见的正则表达式
    全端工程师
    最全前端面试问题及答案总结--《转载》
    奇妙的CSS之布局与定位
    关于在django框架里取已登录用户名字的问题
  • 原文地址:https://www.cnblogs.com/ansersion/p/5081750.html
Copyright © 2011-2022 走看看