zoukankan      html  css  js  c++  java
  • 一个基于JRTPLIB的轻量级RTSP客户端(myRTSPClient)——实现篇:(三)用户接口层之RTSP命令

    截至版本1.2.3,myRtspClient函数库共支持以下6个RTSP命令(RFC 2326):

    (1)OPTIONS

    (2)DESCRIBE

    (3)SETUP

    (4)PLAY

    (5)PAUSE

    (6)TEARDOWN

    对应的接口函数都以“Do”开头,如“DoOPTIONS”。各个接口函数写法相似,大同小异,差异部分会在后续章节做说明,现以DoOPTIONS()和DoPLAY()举例。

    一、ErrorType RtspClient::DoOPTIONS(string uri)

     1 ErrorType RtspClient::DoOPTIONS(string uri)
     2 {   
     3     string RtspUri("");
     4     int Sockfd = -1;
     5     
     6     if(uri.length() != 0) {
     7         RtspUri.assign(uri);
     8         RtspURI.assign(uri);
     9     }
    10     else if(RtspURI.length() != 0) RtspUri.assign(RtspURI);
    11     else return RTSP_INVALID_URI;
    12 
    13     Sockfd = CreateTcpSockfd(RtspUri);
    14     if(Sockfd < 0) return RTSP_INVALID_URI;
    15         
    16     string Cmd("OPTIONS");
    17     stringstream Msg("");
    18     Msg << Cmd << " " << RtspUri << " " << "RTSP/" << VERSION_RTSP << "
    ";
    19     Msg << "CSeq: " << ++RtspCSeq << "
    ";
    20     Msg << "
    ";
    21 
    22     if(!SendRTSP(Sockfd, Msg.str())) {
    23         Close(Sockfd);
    24         return RTSP_SEND_ERROR;
    25     }
    26     if(!RecvRTSP(Sockfd, &RtspResponse)) {
    27         Close(Sockfd);
    28         return RTSP_RECV_ERROR;
    29     }
    30     return RTSP_NO_ERROR;
    31 }

    第6-11行,获取RTSP的URI(如rtsp://127.0.0.1/ansersion)。先检查DoOPTIONS参数传入的URI,如果不存在就使用类成员变量RtspURI(更多说明见“实现篇(二)二、RtspClient::RtspClient(string uri)”),若RtspURI也不存在则返回失败。如果参数传入URI,该URI同时会保存至类成员变量RtspURI从而记忆住该URI,以便后续调用“DoXXX”RTSP命令函数时,不必再重复传入URI。

    第13-14行,根据URI创建socket,用于和RTSP服务端通信(注:CreateTcpSockfd会根据URI中的IP创建socket,如果以前创建过socket且未关闭,则继续沿用旧有socket。截至版本1.2.3,仅支持使用IPv4的URI)。

    第16-20行,组建OPTIONS报文(参见RFC2326 10.1)。

    第22-25行,向服务端发送OPTIONS报文。

    第26-29行,接收服务端返回报文,并将报文赋值给类成员变量RtspResponse(可以通过GetResponse()获取该值)。

    第30行,返回成功。

    二、ErrorType RtspClient::DoPLAY(MediaSession * media_session)

     1 ErrorType RtspClient::DoPLAY(MediaSession * media_session)
     2 {
     3     if(!media_session) {
     4         return RTSP_INVALID_MEDIA_SESSION;
     5     }
     6 
     7     ErrorType Err = RTSP_NO_ERROR;
     8     int Sockfd = -1;
     9     Sockfd = CreateTcpSockfd();
    10     if(Sockfd < 0) return RTSP_INVALID_URI;
    11 
    12     string Cmd("PLAY");
    13     stringstream Msg("");
    14     Msg << Cmd << " " << RtspURI << " " << "RTSP/" << VERSION_RTSP << "
    ";
    15     Msg << "CSeq: " << ++RtspCSeq << "
    ";
    16     Msg << "Session: " << media_session->SessionID << "
    ";
    17     if(Realm.length() > 0 && Nonce.length() > 0) {
    18         string RealmTmp = Realm;
    19         string NonceTmp = Nonce;
    20         string Md5Response  = MakeMd5DigestResp(RealmTmp, Cmd, RtspURI,  NonceTmp);
    21         if(Md5Response.length() != MD5_SIZE) {
    22             cout << "Make MD5 digest response error" << endl;
    23             return RTSP_RESPONSE_401;
    24         }
    25         Msg << "Authorization: Digest username="" << Username << "", realm=""
    26             << RealmTmp << "", nonce="" << NonceTmp << "", uri="" << RtspURI
    27             << "", response="" << Md5Response << ""
    ";
    28     }
    29     Msg << "
    ";
    30 
    31     if(RTSP_NO_ERROR == Err && !SendRTSP(Sockfd, Msg.str())) {
    32         Close(Sockfd);
    33         Sockfd = -1;
    34         Err = RTSP_SEND_ERROR;
    35     }
    36     if(RTSP_NO_ERROR == Err && !RecvRTSP(Sockfd, &RtspResponse)) {
    37         Close(Sockfd);
    38         Sockfd = -1;
    39         Err = RTSP_RECV_ERROR;
    40     }
    41     return RTSP_NO_ERROR;
    42 }

    第3-5行,判断media_session是否有效(MediaSession类存有音频或视频相关信息,后续章节将做说明)。

    第9-10行,创建socket。

    第12-29行,组建PLAY报文(参见RFC2326 10.5),其中第17-28行在报文中加入鉴权信息(参见RFC2069),如果不需要鉴权则可略去。

    第31-35行,向服务端发送PLAY报文。

    第36-40行,接收服务端返回报文。

    example代码中使用的是ErrorType RtspClient::DoPLAY(string media_type),是该函数的封装,参数media_type取“video”或“audio”。

    上一篇                       回目录                      下一篇

  • 相关阅读:
    Hive分桶bucket
    Error: java.io.IOException: org.apache.hadoop.hdfs.BlockMissingException: Could not obtain block
    接上一篇嵌套循环问题之解决
    RPA自动化机器人uibot之循环嵌套坑
    Chrom谷歌浏览器没网之最全解决办法之一
    (语法糖)列表生成式之怪诞--(暂时无法理解)
    浅析scrapy与scrapy-redis的区别
    浅谈Python中函数式编程、面向对象编程以及古怪的PythonIC
    OpenCV+TensorFlow图片手写数字识别(附源码)
    TensorFlow Object Detection API中的Faster R-CNN /SSD模型参数调整
  • 原文地址:https://www.cnblogs.com/ansersion/p/7143760.html
Copyright © 2011-2022 走看看