当前位置: 首页>移动开发>正文

ios怎么开发一个监控摄像头 ip摄像头开发

前言:

网上对于RTSP协议客户端的表述和实现非常不清晰,在实际使用中,FFMPEG和live555这些软件已经实现了RTSP客户端和服务端的所有功能,但是它们并没有将RTSP协议独立出来,通过看live555或是FFMPEG这些第三方库的源码来学习rtsp协议还是非常吃力。这里根据协议自己现实一个RTSP客户端程序,以便可以更好的应用RTSP协议。系列博客包括:

《ONVIF网络摄像头(IPC)客户端开发—ONVIF介绍》
《ONVIF网络摄像头(IPC)客户端开发—最简RTSP客户端实现》
《ONVIF网络摄像头(IPC)客户端开发—RTSP RTCP RTP加载H264视频流》
《ONVIF网络摄像头(IPC)客户端开发—RTSP RTCP RTP加载AAC音频流》

说明:

(1)大华IPC作为RTSP服务端
(2)在ubuntu16.04中编译实现RTSP客户端
(3)服务端IP: 192.168.1.120
(4)客户端IP: 192.168.1.112

RTSP协议:

RTSP是一个实时传输流协议,是一个应用层的协议。通常说的RTSP包括RTSP协议、RTP协议、RTCP协议。对于这些协议的作用简单的理解如下:

  • RTSP:负责服务器与客户端之间的请求与响应
  • RTP: 负责传输媒体数据
  • RTCP:在RTP传输过程中提供传输信息

rtsp承载在rtp和rtcp之上,rtsp并不会发送媒体数据,而是使用rtp协议传输,rtp并没有规定发送方式,可以选择udp发送或者tcp发送。

1. RTSP数据格式:

RTSP的交互过程就是客户端请求,服务端相应,协议格式与HTTP协议类似。

(1.1)RTSP客户端的请求格式:

method url vesion\r\n
CSeq: x\r\n
xxx\r\n
...
\r\n
  • method:方法,表明这次请求的方法,rtsp定义了很多方法,稍后介绍
  • url:格式一般为rtsp://ip:port/session,ip表主机ip,port表端口好,如果不写那么就是默认端口,rtsp的默认端口为554,session表明请求哪一个会话
  • version:表示rtsp的版本,现在为RTSP/1.0
  • CSeq:序列号,每个RTSP请求和响应都对应一个序列号,序列号是递增的

(1.2)RTSP服务端响应格式

vesion 200 OK\r\n
CSeq: x\r\n
xxx\r\n
...
\r\n
  • version:表示rtsp的版本,现在为RTSP/1.0
  • CSeq:序列号,这个必须与对应请求的序列号相同

2.RTSP请求的常用方法

方法	描述
OPTIONS	获取服务端提供的可用方法
DESCRIBE向服务端获取对应会话的媒体描述信息
SETUP 	向服务端发起建立请求,建立连接会话
PLAY	向服务端发起播放请求
TEARDOWN向服务端发起关闭连接会话请求

3.交互过程实例

使用Wireshark抓包工具抓取一个实际RTSP会话过程的数据流,使用ip.addr==192.168.1.120 && rtsp过滤RTSP协议内容,数据如下:

OPTIONS rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif RTSP/1.0
CSeq: 1
User-Agent: Caibiao_Lee

RTSP/1.0 401 Unauthorized
CSeq: 1
WWW-Authenticate: Digest realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e"

OPTIONS rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif RTSP/1.0
CSeq: 2
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="59a6120145ee2c5adad4552f20a3bad2"

RTSP/1.0 200 OK
CSeq: 2
Public: OPTIONS, DESCRIBE, ANNOUNCE, SETUP, PLAY, PAUSE, TEARDOWN, GET_PARAMETER, SET_PARAMETER, REDIRECT, RECORD
Server: Rtsp Server/3.0

DESCRIBE rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif RTSP/1.0
CSeq: 3
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="0fefc97b4a497566ce815e2f9f48ff4a"
User-Agent: Caibiao_Lee
Accept: application/sdp

RTSP/1.0 200 OK
CSeq: 3
Content-Base: rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/
Content-Type: application/sdp
x-Accept-Dynamic-Rate: 1
Cache-Control: must-revalidate
Content-Length: 566

v=0
o=- 2229913047 2229913047 IN IP4 0.0.0.0
s=Media Server
c=IN IP4 0.0.0.0
t=0 0
a=control:*
a=packetization-supported:DH
a=rtppayload-supported:DH
a=range:npt=now-
m=video 0 RTP/AVP 96
a=control:trackID=0
a=framerate:25.000000
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=64002A;sprop-parameter-sets=Z2QAKqwsaoHgCJ+WbgICAgQA,aO48sAA=
a=recvonly
m=audio 0 RTP/AVP 8
a=control:trackID=1
a=rtpmap:8 PCMA/8000
a=recvonly
m=application 0 RTP/AVP 107
a=control:trackID=4
a=rtpmap:107 vnd.onvif.metadata/90000
a=recvonly
SETUP rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/trackID=0 RTSP/1.0
CSeq: 4
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="c650887dd112d10e0a868510d64088f6"
User-Agent: Caibiao_Lee
Transport:RTP/AVP;unicast;client_port=32766-32767

RTSP/1.0 200 OK
CSeq: 4
Session: 2666913996
Transport: RTP/AVP;unicast;client_port=32766-32767;server_port=2000-2001;ssrc=d6198a00
x-Dynamic-Rate: 1

PLAY rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/ RTSP/1.0
CSeq: 5
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D", nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e", uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif", response="bc9b1026a0ce64b963da457d4e87b6a5"
User-Agent: Caibiao_Lee
Session: 2666913996
Range: npt=0.000-

RTSP/1.0 200 OK
CSeq: 5
Session: 2666913996
Range: npt=0.000-
RTP-Info: url=trackID=0;seq=1;rtptime=0

TEARDOWN rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/ RTSP/1.0
CSeq: 6
User-Agent: Caibiao_Lee
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="68f5346f3fea36b7c69be9e8184abc5b"
User-Agent: Caibiao_Lee
Session: 2666913996

RTSP/1.0 200 OK
CSeq: 6
Session: 2666913996

3.1SDP格式分析

sdp格式由多行的type=value组成
sdp会话描述由一个会话级描述和多个媒体级描述组成。会话级描述的作用域是整个会话,媒体级描述描述的是一个视频流或者音频流
会话级描述由v=开始到第一个媒体级描述结束
媒体级描述由m=开始到下一个媒体级描述结束

SDP的具体格式网上有很多,这里不做具体分析。

代码实现:

使用C语言实现RTSP客户端对服务端的请求的功能,实现代码如下:

/************************************************************
*Copyright (C),lcb0281at163.com lcb0281atgmail.com
*FileName: rtsp_client.c
*BlogAddr: 
*Description: RTSP 协议 
*Date:	   2019-06-22
*Author:   Caibiao Lee
*Version:  V1.0
*Others:
*History:
***********************************************************/
#include <string.h>
#include <stdlib.h>  
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "rtsp_client.h"

#define BUF_LEN_1024_BYTE 	 1024	
#define RTSP_DEFAULT_PORT    554	
static int gs_s32CseqCount    = 1;

static unsigned short IPC_RTSP_GetPort(const char *const ps8Rtsp)
{
    char l_as8RTSP[128] = {0};
    char *l_ps8Buf = NULL;
    int i =0;
    unsigned int l_u16RtspPort = 0;
	
    if(NULL == ps8Rtsp)
    {   
        printf("[%s,%d] psTIPCDEV is NULL error\n ",__FILE__,__LINE__);
        return 0;
    }
    memcpy(l_as8RTSP,ps8Rtsp,strlen(ps8Rtsp));
	
    printf("[%s,%d]l_ps8Buf=%s\n",__FUNCTION__,__LINE__,l_as8RTSP);
    l_ps8Buf = strtok(l_as8RTSP,"//");
	
    printf("[%s,%d]l_ps8Buf=%s\n",__FUNCTION__,__LINE__,l_ps8Buf);
	
    if(NULL != l_ps8Buf)
    {
        l_ps8Buf = strtok(NULL,":");
    }
    if(NULL != l_ps8Buf)
    {
        l_ps8Buf = strtok(NULL,"/");
    }
    if(NULL != l_ps8Buf)
    {
        for(i = 0;i < 6 && l_ps8Buf[i] - '0' >= 0 && l_ps8Buf[i] - '0' <= 9;i++)
        {
            l_u16RtspPort *= 10;
            l_u16RtspPort += l_ps8Buf[i] - '0';
        }
    }
    return l_u16RtspPort;
}


static int IPC_RTSP_RecvSelect(int s32RtspFd,char *ps8buf,int s32Len)
{
    int l_s32Ret;
    fd_set l_s4Fdset;
    struct timeval l_stTimeout;
	
    FD_ZERO(&l_s4Fdset);
    FD_SET(s32RtspFd,&l_s4Fdset);
    l_stTimeout.tv_sec = 2;
    l_stTimeout.tv_usec = 0;
	
    l_s32Ret = select(s32RtspFd + 1,&l_s4Fdset,NULL,NULL,&l_stTimeout);
    if(l_s32Ret < 0)
    {
        printf("[%s,%d]slect error\n",__FUNCTION__,__LINE__);
    }
    else if(0 == l_s32Ret)
    {
        printf("[%s,%d] slect timeout\n",__FUNCTION__,__LINE__);
    }
    else
    {
       l_s32Ret = NET_SocketRecvData(s32RtspFd,ps8buf,s32Len); 
    }
    return l_s32Ret;
}

static int IPC_RTSP_CheckReply(char *ps8buf)
{
    char *p = NULL;
    p = strstr(ps8buf,"OK");
    if(NULL == p)
    {
        return -1;
    }
    return 0;
}

static int IPC_RTSP_HandleRTSPStr(RTSP_STATUS_S *pstRTSPClient)
{
    char l_arrs8Buf[256]={0};
    int l_s32Len;
	
    memcpy(l_arrs8Buf,pstRTSPClient->arrs8RTSPUrl,strlen(pstRTSPClient->arrs8RTSPUrl));
    l_s32Len = strlen(l_arrs8Buf)-1;
    while(l_s32Len >20)
    {
        if(' ' == l_arrs8Buf[l_s32Len] || '&' == l_arrs8Buf[l_s32Len])
        {
            l_arrs8Buf[l_s32Len] = 'biao@ubuntu:~/test/vlc_camara$ sudo ./test 
[IPC_RTSP_GetPort,39]l_ps8Buf=rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif
[IPC_RTSP_GetPort,42]l_ps8Buf=rtsp:
RTSP Server IP=192.168.1.120,ServerPort=554 
s32Type =  0 
[RTSP_Client_OPTIONS 645:] Send data:
OPTIONS rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif RTSP/1.0
CSeq: 1
User-Agent: Caibiao_Lee


l_s32Ret=140
[RTSP_Client_OPTIONS 657:] Recv Data: RTSP/1.0 401 Unauthorized
CSeq: 1
WWW-Authenticate: Digest realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e"

 
biao debug [RTSP_Client_OPTIONS 663:] l_s32Ret = -1  
s32Type =  1 
[RTSP_Client_OPTIONS 645:] Send data:
OPTIONS rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif RTSP/1.0
CSeq: 2
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="59a6120145ee2c5adad4552f20a3bad2"


l_s32Ret=371
[RTSP_Client_OPTIONS 657:] Recv Data: RTSP/1.0 200 OK
CSeq: 2
Public: OPTIONS, DESCRIBE, ANNOUNCE, SETUP, PLAY, PAUSE, TEARDOWN, GET_PARAMETER, SET_PARAMETER, REDIRECT, RECORD
Server: Rtsp Server/3.0

 
biao debug [RTSP_Client_OPTIONS 669:] recv OK 
[RTSP_Client_DESCRIBE 728:] Send data:
DESCRIBE rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif RTSP/1.0
CSeq: 3
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="0fefc97b4a497566ce815e2f9f48ff4a"
User-Agent: Caibiao_Lee
Accept: application/sdp


l_s32Ret=422
[RTSP_Client_DESCRIBE 740:] Recv Data: RTSP/1.0 200 OK
CSeq: 3
Content-Base: rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/
Content-Type: application/sdp
x-Accept-Dynamic-Rate: 1
Cache-Control: must-revalidate
Content-Length: 566

v=0
o=- 2229913047 2229913047 IN IP4 0.0.0.0
s=Media Server
c=IN IP4 0.0.0.0
t=0 0
a=control:*
a=packetization-supported:DH
a=rtppayload-supported:DH
a=range:npt=now-
m=video 0 RTP/AVP 96
a=control:trackID=0
a=framerate:25.000000
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1;profile-level-id=64002A;sprop-parameter-sets=Z2QAKqwsaoHgCJ+WbgICAgQA,aO48sAA=
a=recvonly
m=audio 0 RTP/AVP 8
a=control:trackID=1
a=rtpmap:8 PCMA/8000
a=recvonly
m=application 0 RTP/AVP 107
a=control:trackID=4
a=rtpmap:107 vnd.onvif.metadata/90000
a=recvonly
 
biao debug [RTSP_Client_DESCRIBE 752:] recv OK 
[RTSP_Client_SETUP 807:] Send data:
SETUP rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/trackID=0 RTSP/1.0
CSeq: 4
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="c650887dd112d10e0a868510d64088f6"
User-Agent: Caibiao_Lee
Transport:RTP/AVP;unicast;client_port=32766-32767


l_s32Ret=455
[RTSP_Client_SETUP 817:] Recv Data: RTSP/1.0 200 OK
CSeq: 4
Session: 2666913996
Transport: RTP/AVP;unicast;client_port=32766-32767;server_port=2000-2001;ssrc=d6198a00
x-Dynamic-Rate: 1

 
biao debug [RTSP_Client_SETUP 828:] recv OK 
[RTSP_Client_PLAY 902:] Send data:
PLAY rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/ RTSP/1.0
CSeq: 5
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D", nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e", uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif", response="bc9b1026a0ce64b963da457d4e87b6a5"
User-Agent: Caibiao_Lee
Session: 2666913996
Range: npt=0.000-


l_s32Ret=437
[RTSP_Client_PLAY 914:] Recv Data: RTSP/1.0 200 OK
CSeq: 5
Session: 2666913996
Range: npt=0.000-
RTP-Info: url=trackID=0;seq=1;rtptime=0

 
biao debug [RTSP_Client_PLAY 925:] recv OK 
[RTSP_Client_TEARDOWN 969:] Send data:
TEARDOWN rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif/ RTSP/1.0
CSeq: 6
User-Agent: Caibiao_Lee
Authorization: Digest username="admin", realm="Login to F8990C5E0599500D",nonce="4e6ea17f-789f-4d89-a1be-aba7340a3b8e",uri="rtsp://192.168.1.120:554/cam/realmonitor?channel=1&subtype=0&unicast=true&proto=Onvif",response="68f5346f3fea36b7c69be9e8184abc5b"
User-Agent: Caibiao_Lee
Session: 2666913996


l_s32Ret=444
[RTSP_Client_TEARDOWN 979:] Recv Data: RTSP/1.0 200 OK
CSeq: 6
Session: 2666913996

biao@ubuntu:~/test/vlc_camara$';
            bzero(pstRTSPClient->arrs8RTSPUrl,strlen(pstRTSPClient->arrs8RTSPUrl));
            memcpy(pstRTSPClient->arrs8RTSPUrl,l_arrs8Buf,strlen(l_arrs8Buf));
            break;
        }
        l_s32Len--;
    }
    return 0;
}


static void IPC_RTSP_SDPAnalyze(RTSP_STATUS_S *pstRTSPClient,char *ps8Buf)
{
    char *p = ps8Buf;
    char *tmp;
    int i,j;
	
	/*********************step 1:control***********************/
    for(i = 0;i< 3;i++)
    {
    	/**取出control的内容**/
        p = strstr(p,"a=control:");
        if(NULL == p)
            break;
		
		/**去掉*的行继续下行检测**/
        if(0 == strncmp(p,"a=control:*",11)) 
        {
            p++;
            continue;
        }
		/**检测control中是否存在rtsp**/
        else if(NULL != (tmp = strstr(p,"rtsp"))) 
        {
            while('\n' != *tmp && '\r' != *tmp && '

用户密码与加解密

' != *tmp) { tmp++; } *tmp = '
  • BASE64的维基百科解析是:Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于 {\displaystyle 2^{6}=64} {\displaystyle 2^{6}=64},所以每6个位元为一个单元,对应某个可打印字符。3个字节有24个位元,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。它可用来作为电子邮件的传输编码。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后BinHex的版本使用不同的64字符集来代表6个二进制数字,但是不被稱為Base64。Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据。
  • '; if(NULL != strstr(p,"track")) { j=0; p+=10; bzero(pstRTSPClient->stSDPPara.arrs8RTSPUrl,sizeof(pstRTSPClient->stSDPPara.arrs8RTSPUrl)); while('\n' != *p && '\r' != *p && '
  • MD5在维基百科中解释是:MD5訊息摘要演算法(英語:MD5 Message-Digest Algorithm),一種被廣泛使用的密碼雜湊函數,可以產生出一個128位元(16位元組)的散列值(hash value),用于确保信息传输完整一致。MD5由美國密碼學家罗纳德·李维斯特(Ronald Linn Rivest)設計,於1992年公開,用以取代MD4演算法。這套演算法的程序在 RFC 1321 中被加以規範。将数据(如一段文字)运算变为另一固定长度值,是雜湊算法的基础原理。
  • ' != *p) { pstRTSPClient->arrs8RTSPUrl[j] = *(p++); j++; } pstRTSPClient->stSDPPara.arrs8Control[0]='

    工程目录:

    '; bzero(pstRTSPClient->arrs8RTSPUrl,128); memcpy(pstRTSPClient->arrs8RTSPUrl,pstRTSPClient->stSDPPara.arrs8RTSPUrl, strlen(pstRTSPClient->stSDPPara.arrs8RTSPUrl)); return ; } p = tmp +1; continue; } else { j=0; p+=10; while('\n' != *p && '\r' != *p && 'biao@ubuntu:~/test/rtsp_client$ tree . ├── include │ ├── common.h │ └── rtsp_client.h ├── lib │ ├── libcrypto.a │ ├── libcrypto.so │ ├── libssl.a │ └── libssl.so ├── Makefile └── src ├── common.c ├── main.c └── rtsp_client.c 3 directories, 10 files biao@ubuntu:~/test/rtsp_client$' != *p) { pstRTSPClient->stSDPPara.arrs8Control[j] = *(p++); j++; } pstRTSPClient->stSDPPara.arrs8Control[j]=''; break; } } p = ps8Buf; /********************************step 2:rtspurl******************************/ p = strstr(p,"rtsp:"); /**出去rtsp**/ if(NULL != p) { tmp = p; while(NULL != p && '\r' != *p && '\n' != *p && '' != *p) { p++; } if(NULL != p) *p = ''; p--; while(' ' == *p) { p--; } if('/' == *p) *p = ''; bzero(pstRTSPClient->stSDPPara.arrs8RTSPUrl,sizeof(pstRTSPClient->stSDPPara.arrs8RTSPUrl)); memcpy(pstRTSPClient->stSDPPara.arrs8RTSPUrl,tmp,strlen(tmp)); } } static int IPC_RTSP_ERRHandle(RTSP_STATUS_S *pstRTSPClient,char *ps8Buf) { char *p; char *tmp; int i; if(NULL == strstr(ps8Buf,"401")) { return 0; } p = strstr(ps8Buf,"realm="); if(NULL == p) { return -1; } tmp = p+7; for(i = 0;NULL != tmp && '"' != tmp[i] && i < 32;i++) { pstRTSPClient->stSDPPara.arrs8Realm[i] = tmp[i]; } p = strstr(ps8Buf,"nonce="); if(NULL == p) { return -1; } tmp = p+7; for(i = 0;NULL != tmp && '"' != tmp[i] && i < 128;i++) { pstRTSPClient->stSDPPara.arrs8Nonce[i] = tmp[i]; } return 0; } static char *IPC_RTSP_StreamHandle(char *ps8Buf,int s32StreamType) { char *sub = NULL; sub = strstr(ps8Buf,"subtype="); if(NULL != sub) { if(SUBSTREAM == s32StreamType) { *(sub + 8) = '1'; } else if(MAINSTREAM == s32StreamType){ *(sub + 8) = '0'; } return ps8Buf; } sub = strstr(ps8Buf,"stream="); if(NULL != sub) { if(SUBSTREAM == s32StreamType) { *(sub + 7) = '1'; } else if(MAINSTREAM == s32StreamType){ *(sub + 7) = '0'; } return ps8Buf; } else if(NULL != (sub = strstr(ps8Buf,"Channels/")) || NULL != (sub = strstr(ps8Buf,"channels/"))) { sub += 9; while('/' != *sub && '' != *sub) { sub++; } if(SUBSTREAM == s32StreamType) { *(--sub) +=1; } } else if(NULL != (sub = strstr(ps8Buf,"stream"))) { if((*(sub + 6) >= '0') && (*(sub + 6) <= '9')) { if(SUBSTREAM == s32StreamType) { *(sub + 6) = '2'; } else if(MAINSTREAM == s32StreamType) { *(sub + 6) = '1'; } } return ps8Buf; } else if(NULL != (sub = strstr(ps8Buf,"/1/1"))) { if(SUBSTREAM == s32StreamType) { sub+=3; *sub +=1; } } return ps8Buf; } static int IPC_RTSP_DESCRIBEHandle(RTSP_STATUS_S *stRTSPClient,char *ps8Buf,int s32Type) { char l_arrs8Author[32]={0}; unsigned char l_arru8Response[33]={0}; bzero(ps8Buf,BUF_LEN_1024_BYTE); switch(s32Type) { case 0: { sprintf(ps8Buf,"DESCRIBE %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nAccept: application/h264\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount); break; } case 1: { COM_authorization_digest(stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord, stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,l_arru8Response,"DESCRIBE", stRTSPClient->arrs8RTSPUrl,NULL,0); sprintf(ps8Buf,"DESCRIBE %s RTSP/1.0\r\nCSeq: %d\r\nAuthorization: Digest username=\"%s\", realm=\"%s\",nonce=\"%s\",uri=\"%s\",response=\"%s\"\r\nUser-Agent: Caibiao_Lee\r\nAccept: application/sdp\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,stRTSPClient->stClientUser.arrs8Name,\ stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,stRTSPClient->arrs8RTSPUrl,l_arru8Response); break; } case 2: { sprintf(ps8Buf,"%s:%s",stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord); COM_base64_bits_to_64((unsigned char *)l_arrs8Author,(unsigned char *)ps8Buf,strlen(ps8Buf)); sprintf(ps8Buf,"DESCRIBE %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nAccept: application/sdp\r\nAuthorization: Basic %s\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,l_arrs8Author); break; } default: s32Type = -1; break; } return s32Type; } static int IPC_RTSP_OPTIONSHandle(RTSP_STATUS_S *stRTSPClient,char *ps8buf,int s32Type) { char l_s32Author[32] = {0}; unsigned char l_s32Response[33] = {0}; bzero(ps8buf,BUF_LEN_1024_BYTE); printf("s32Type = %d \n",s32Type); switch(s32Type) { case 0: { sprintf(ps8buf,"OPTIONS %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount); break; } case 1: { COM_authorization_digest(stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord,\ stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,l_s32Response,"OPTIONS",\ stRTSPClient->arrs8RTSPUrl,NULL,0); sprintf(ps8buf,"OPTIONS %s RTSP/1.0\r\nCSeq: %d\r\nAuthorization: Digest username=\"%s\", realm=\"%s\",nonce=\"%s\",uri=\"%s\",response=\"%s\"\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,stRTSPClient->arrs8RTSPUrl,l_s32Response); break; } case 2: { sprintf(ps8buf,"%s:%s",stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord); printf("name = %s password = %s buf = %s \n", stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord,ps8buf); COM_base64_bits_to_64((unsigned char *)l_s32Author,(unsigned char *)ps8buf,strlen(ps8buf)); sprintf(ps8buf,"OPTIONS %s RTSP/1.0\r\nCSeq: %d\r\nAuthorization: Basic %s\r\n\r\n",stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,l_s32Author); break; } default: s32Type = -1; break; } return s32Type; } static int IPC_RTSP_TEARDOWNHandle(RTSP_STATUS_S *stRTSPClient,char *ps8Buf,int s32tmp,char *pRTSPSessionId) { char l_s32author[32] = {0}; unsigned char l_arru8Response[33]={0}; bzero(ps8Buf,BUF_LEN_1024_BYTE); switch(s32tmp) { case 0: { sprintf(ps8Buf,"TEARDOWN %s/ RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nSession: %s\r\nRange: npt=0.000-\r\n\r\n",stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,pRTSPSessionId); break; } case 1: { COM_authorization_digest(stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord,stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,l_arru8Response,"TEARDOWN",stRTSPClient->arrs8RTSPUrl,NULL,0); sprintf(ps8Buf,"TEARDOWN %s/ RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nAuthorization: Digest username=\"%s\", realm=\"%s\",nonce=\"%s\",uri=\"%s\",response=\"%s\"\r\nUser-Agent: Caibiao_Lee\r\nSession: %s\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,stRTSPClient->stClientUser.arrs8Name,\ stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,stRTSPClient->arrs8RTSPUrl,\ l_arru8Response,pRTSPSessionId); break; } case 2: { sprintf(ps8Buf,"%s:%s",stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord); COM_base64_bits_to_64((unsigned char *)l_s32author,(unsigned char *)ps8Buf,strlen(ps8Buf)); sprintf(ps8Buf,"TEARDOWN %s/ RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nSession: %s\r\nRange: npt=0.000-\r\nAuthorization: Basic %s\r\n\r\n", stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,pRTSPSessionId,l_s32author); break; } default: { printf("%s,%d,switch is default\n",__FUNCTION__,__LINE__); break; s32tmp = -1; } } return s32tmp; } static int IPC_RTSP_SETUPHandle(RTSP_STATUS_S *stRTSPClient,char *ps8Buf,int s32Type,int localport) { char l_arrs8Author[32] = {0}; unsigned char l_arru8Response[33]={0}; bzero(ps8Buf,BUF_LEN_1024_BYTE); switch(s32Type) { case 0: { sprintf(ps8Buf,"SETUP %s/%s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nTransport:RTP/AVP;unicast;client_port=%d-%d\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,stRTSPClient->stSDPPara.arrs8Control,\ gs_s32CseqCount,localport,localport+1); break; } case 1: { COM_authorization_digest(stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord,stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,l_arru8Response,"SETUP",stRTSPClient->arrs8RTSPUrl,NULL,0); sprintf(ps8Buf,"SETUP %s/%s RTSP/1.0\r\nCSeq: %d\r\nAuthorization: Digest username=\"%s\", realm=\"%s\",nonce=\"%s\",uri=\"%s\",response=\"%s\"\r\nUser-Agent: Caibiao_Lee\r\nTransport:RTP/AVP;unicast;client_port=%d-%d\r\n\r\n", stRTSPClient->arrs8RTSPUrl,stRTSPClient->stSDPPara.arrs8Control,\ gs_s32CseqCount,stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stSDPPara.arrs8Realm,\ stRTSPClient->stSDPPara.arrs8Nonce,stRTSPClient->arrs8RTSPUrl,\ l_arru8Response,localport,localport+1); break; } case 2: { sprintf(ps8Buf,"%s:%s",stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord); COM_base64_bits_to_64((unsigned char *)l_arrs8Author,(unsigned char *)ps8Buf,strlen(ps8Buf)); sprintf(ps8Buf,"SETUP %s/%s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nTransport:RTP/AVP;unicast;client_port=%d-%d\r\nAuthorization: Basic %s\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,stRTSPClient->stSDPPara.arrs8Control,\ gs_s32CseqCount,localport,localport+1,l_arrs8Author); break; } default: { s32Type = -1; break; } } return s32Type; } static int IPC_RTSP_PLAYHandle(RTSP_STATUS_S *stRTSPClient,char *ps8Buf,int s32Type,char *RTSPSessionId) { bzero(ps8Buf,BUF_LEN_1024_BYTE); char l_arrs8Author[32] = {0}; unsigned char l_arru8Response[33]={0}; switch(s32Type) { case 0: { sprintf(ps8Buf,"PLAY %s/ RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nSession: %s\r\nRange: npt=0.000-\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,RTSPSessionId); break; } case 1: { COM_authorization_digest(stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord,stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,l_arru8Response,"PLAY",stRTSPClient->arrs8RTSPUrl,NULL,0); sprintf(ps8Buf,"PLAY %s/ RTSP/1.0\r\nCSeq: %d\r\nAuthorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\nUser-Agent: Caibiao_Lee\r\nSession: %s\nRange: npt=0.000-\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,stRTSPClient->stClientUser.arrs8Name,\ stRTSPClient->stSDPPara.arrs8Realm,stRTSPClient->stSDPPara.arrs8Nonce,stRTSPClient->arrs8RTSPUrl,\ l_arru8Response,RTSPSessionId); break; } case 2: { sprintf(ps8Buf,"%s:%s",stRTSPClient->stClientUser.arrs8Name,stRTSPClient->stClientUser.arrs8PassWord); COM_base64_bits_to_64((unsigned char *)l_arrs8Author,(unsigned char *)ps8Buf,strlen(ps8Buf)); sprintf(ps8Buf,"PLAY %s/ RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: Caibiao_Lee\r\nSession: %s\r\nRange: npt=0.000-\r\nAuthorization: Basic %s\r\n\r\n",\ stRTSPClient->arrs8RTSPUrl,gs_s32CseqCount,RTSPSessionId,l_arrs8Author); break; } default: { s32Type = -1; break; } } return s32Type; } int RTSP_Client_Init(RTSP_STATUS_S * stRTSPClient) { memset((unsigned char*)stRTSPClient,0,sizeof(RTSP_STATUS_S)); stRTSPClient->bRTPState = false; return 0; } int RTSP_Client_Release(RTSP_STATUS_S * stRTSPClient) { if(NULL==stRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } if(stRTSPClient->s32SockFd > 0) { close(stRTSPClient->s32SockFd); stRTSPClient->s32SockFd = -1; } return 0; } int RTSP_Client_Session(RTSP_STATUS_S *stRTSPClient) { bool l_bRTSPState; unsigned short l_u16Port = 0; int l_s32Ret = 0; int l_s32RtspSockfd = -1; if(NULL==stRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } l_bRTSPState = stRTSPClient->bRTPState; l_s32RtspSockfd = stRTSPClient->s32SockFd; if(true==stRTSPClient->bRTPState) { printf("%s %d RTSP is already init error \n",__FUNCTION__,__LINE__); return -1; } if(l_s32RtspSockfd > 0) { close(l_s32RtspSockfd); } l_s32RtspSockfd = NET_SocketCreate(SOCK_STREAM); if(l_s32RtspSockfd < 0) { printf("%s %d:create socket is error \n",__FUNCTION__,__LINE__); return -3; } l_u16Port = IPC_RTSP_GetPort(stRTSPClient->arrs8RTSPUrl); l_u16Port = (l_u16Port>0)?(l_u16Port):(RTSP_DEFAULT_PORT); printf("RTSP Server IP=%s,ServerPort=%d \n",stRTSPClient->arrs8ServerIP,l_u16Port); l_s32Ret = NET_SocketConnect(l_s32RtspSockfd,stRTSPClient->arrs8ServerIP,l_u16Port); if(l_s32Ret < 0) { printf("%s %d :connect to Server error \n",__FUNCTION__,__LINE__); return -4; } stRTSPClient->s32SockFd = l_s32RtspSockfd; return 0; } int RTSP_Client_OPTIONS(RTSP_STATUS_S *pstRTSPClient) { int i; int l_s32Ret; int l_s32RtspSocketFd; bool l_bRTSPState; char l_arrs8Buf[BUF_LEN_1024_BYTE]; if(NULL==pstRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } if(true==pstRTSPClient->bRTPState) { printf("%s %d RTSP is already start error \n",__FUNCTION__,__LINE__); return -1; } l_bRTSPState = pstRTSPClient->bRTPState; l_s32RtspSocketFd = pstRTSPClient->s32SockFd; pstRTSPClient->stSDPPara.s32AuthorType = 0; bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); for(i=0;i< 2;i++) { IPC_RTSP_OPTIONSHandle(pstRTSPClient,l_arrs8Buf,i); l_s32Ret = NET_SocketSendData(l_s32RtspSocketFd,l_arrs8Buf,strlen(l_arrs8Buf)); if(l_s32Ret < 0) { printf("%s,%d :Send Data error \n",__FUNCTION__,__LINE__); return -2; } printf("[%s %d:] Send data:\n%s\nl_s32Ret=%d\n",__FUNCTION__,__LINE__,l_arrs8Buf,l_s32Ret); bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); l_s32Ret = IPC_RTSP_RecvSelect(l_s32RtspSocketFd,l_arrs8Buf,BUF_LEN_1024_BYTE); if(l_s32Ret <= 0) { printf("[%s %d:] RTSP recv data error \n",__FUNCTION__,__LINE__); gs_s32CseqCount++; continue; }else { printf("[%s %d:] Recv Data: %s \n",__FUNCTION__,__LINE__,l_arrs8Buf); } l_s32Ret = IPC_RTSP_CheckReply(l_arrs8Buf); if(0 != l_s32Ret) { printf("biao debug [%s %d:] l_s32Ret = %d \n",__FUNCTION__,__LINE__,l_s32Ret); IPC_RTSP_ERRHandle(pstRTSPClient,l_arrs8Buf); gs_s32CseqCount++; continue; }else { printf("biao debug [%s %d:] recv OK \n",__FUNCTION__,__LINE__); } gs_s32CseqCount++; pstRTSPClient->stSDPPara.s32AuthorType = i; return 0; } return -1; } int RTSP_Client_DESCRIBE(RTSP_STATUS_S *pstRTSPClient) { bool l_bRTSPState; char *l_ps8Sub; char l_arrs8Buf[BUF_LEN_1024_BYTE]; int i; int l_s32Ret; int l_s32RtspsocketFd; if(NULL==pstRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } if(true==pstRTSPClient->bRTPState) { printf("%s %d RTSP is already start error \n",__FUNCTION__,__LINE__); return -1; } l_bRTSPState = pstRTSPClient->bRTPState; l_s32RtspsocketFd = pstRTSPClient->s32SockFd; for(i=pstRTSPClient->stSDPPara.s32AuthorType;i < 2;i++) { IPC_RTSP_DESCRIBEHandle(pstRTSPClient,l_arrs8Buf,i); l_ps8Sub = COM_get_substringstart(l_arrs8Buf,"subtype="); if(NULL != l_ps8Sub) { l_ps8Sub += 8; } if(SUBSTREAM==pstRTSPClient->s32StreamType) { *l_ps8Sub = '1'; } else if(MAINSTREAM== pstRTSPClient->s32StreamType) { *l_ps8Sub = '0'; } l_s32Ret = NET_SocketSendData(l_s32RtspsocketFd,l_arrs8Buf,strlen(l_arrs8Buf)); if(l_s32Ret < 0) { printf("%s %d: Send Data Error \n",__FUNCTION__,__LINE__); return -2; } printf("[%s %d:] Send data:\n%s\nl_s32Ret=%d\n",__FUNCTION__,__LINE__,l_arrs8Buf,l_s32Ret); bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); l_s32Ret = IPC_RTSP_RecvSelect(l_s32RtspsocketFd,l_arrs8Buf,BUF_LEN_1024_BYTE); if(l_s32Ret <= 0) { printf("%s %d : Recv Data Error \n",__FUNCTION__,__LINE__); gs_s32CseqCount++; return -3; }else { printf("[%s %d:] Recv Data: %s \n",__FUNCTION__,__LINE__,l_arrs8Buf); } l_s32Ret = IPC_RTSP_CheckReply(l_arrs8Buf); if(0 != l_s32Ret) { IPC_RTSP_ERRHandle(pstRTSPClient,l_arrs8Buf); gs_s32CseqCount++; return -4; } else { printf("biao debug [%s %d:] recv OK \n",__FUNCTION__,__LINE__); } IPC_RTSP_SDPAnalyze(pstRTSPClient,l_arrs8Buf); gs_s32CseqCount++; pstRTSPClient->stSDPPara.s32AuthorType = i; return 0; } return -5; } int RTSP_Client_SETUP(RTSP_STATUS_S *pstRTSPClient) { bool l_bRTSPState; char l_arrs8RTSPSessionId[16]; char l_arrs8RTPPort[12]; char l_arrs8Buf[BUF_LEN_1024_BYTE]; char *l_ps8Sub; char l_s8Flag = ';'; char l_arrs8SPFlagStr[] = "server_port="; int i; int l_s32Len; int localport; int l_s32Ret; int l_s32RtspsocketFd; char *l_ps8RTSPSessionId; if(NULL==pstRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } if(true==pstRTSPClient->bRTPState) { printf("%s %d RTSP is already start error \n",__FUNCTION__,__LINE__); return -1; } l_bRTSPState = pstRTSPClient->bRTPState; l_s32RtspsocketFd = pstRTSPClient->s32SockFd; l_ps8RTSPSessionId = pstRTSPClient->arrs8SessionId; for(i=pstRTSPClient->stSDPPara.s32AuthorType;i <3;i++) { IPC_RTSP_StreamHandle(pstRTSPClient->arrs8RTSPUrl,pstRTSPClient->s32StreamType); IPC_RTSP_SETUPHandle(pstRTSPClient,l_arrs8Buf,i,localport); l_s32Ret = NET_SocketSendData(l_s32RtspsocketFd,l_arrs8Buf,strlen(l_arrs8Buf)); if(l_s32Ret < 0) { printf("%s %d: Send Data Error \n",__FUNCTION__,__LINE__); return -2; } printf("[%s %d:] Send data:\n%s\nl_s32Ret=%d\n",__FUNCTION__,__LINE__,l_arrs8Buf,l_s32Ret); bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); l_s32Ret = IPC_RTSP_RecvSelect(l_s32RtspsocketFd,l_arrs8Buf,BUF_LEN_1024_BYTE); if(l_s32Ret <= 0) { printf("%s %d : Recv Data Error \n",__FUNCTION__,__LINE__); gs_s32CseqCount++; return -3; }else { printf("[%s %d:] Recv Data: %s \n",__FUNCTION__,__LINE__,l_arrs8Buf); } l_s32Ret = IPC_RTSP_CheckReply(l_arrs8Buf); if(0 != l_s32Ret) { gs_s32CseqCount++; return -4; } else { printf("biao debug [%s %d:] recv OK \n",__FUNCTION__,__LINE__); } l_ps8Sub = COM_get_substringstart(l_arrs8Buf,"Session:"); if(NULL != l_ps8Sub) { l_ps8Sub += 8; } while(NULL != l_ps8Sub && ' ' == *l_ps8Sub) { l_ps8Sub++; } bzero(l_arrs8RTSPSessionId,16); COM_get_begingstring(l_ps8Sub,l_arrs8RTSPSessionId,l_s8Flag); l_ps8Sub = COM_get_substringstart(l_arrs8Buf,l_arrs8SPFlagStr); if(NULL != l_ps8Sub) { l_ps8Sub += 12; } bzero(l_arrs8RTPPort,12); COM_get_begingstring(l_ps8Sub,l_arrs8RTPPort,'-'); bzero(pstRTSPClient->arrs8SessionId,16); sprintf(pstRTSPClient->arrs8SessionId,"%s",l_arrs8RTSPSessionId); bzero(pstRTSPClient->arrs8SerRTPPort,12); sprintf(pstRTSPClient->arrs8SerRTPPort,"%s",l_arrs8RTPPort); l_s32Len = strlen(pstRTSPClient->arrs8SerRTPPort); l_s32Len = l_s32Len -1; pstRTSPClient->arrs8SerRTPPort[l_s32Len] = pstRTSPClient->arrs8SerRTPPort[l_s32Len]+1; gs_s32CseqCount++; return 0; } return -5; } int RTSP_Client_PLAY(RTSP_STATUS_S *pstRTSPClient) { char l_arrs8Buf[BUF_LEN_1024_BYTE]; char *l_ps8RTSPSessionId; int i; int l_s32Ret; int l_s32RtspsocketFd; bool l_bRTSPState; if(NULL==pstRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } if(true==pstRTSPClient->bRTPState) { printf("%s %d RTSP is already start error \n",__FUNCTION__,__LINE__); return -2; } l_bRTSPState = pstRTSPClient->bRTPState; l_s32RtspsocketFd = pstRTSPClient->s32SockFd; l_ps8RTSPSessionId = pstRTSPClient->arrs8SessionId; for(i=pstRTSPClient->stSDPPara.s32AuthorType;i < 3;i++) { IPC_RTSP_StreamHandle(pstRTSPClient->arrs8RTSPUrl,pstRTSPClient->s32StreamType); IPC_RTSP_PLAYHandle(pstRTSPClient,l_arrs8Buf,i,l_ps8RTSPSessionId); l_s32Ret = NET_SocketSendData(l_s32RtspsocketFd,l_arrs8Buf,strlen(l_arrs8Buf)); if(l_s32Ret < 0) { printf("%s %d:Send Data Error \n",__FUNCTION__,__LINE__); return -3; } printf("[%s %d:] Send data:\n%s\nl_s32Ret=%d\n",__FUNCTION__,__LINE__,l_arrs8Buf,l_s32Ret); bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); l_s32Ret = IPC_RTSP_RecvSelect(l_s32RtspsocketFd,l_arrs8Buf,BUF_LEN_1024_BYTE); if(l_s32Ret <= 0) { printf("%s %d Recv Select Error\n",__FUNCTION__,__LINE__); gs_s32CseqCount++; return -4; }else { printf("[%s %d:] Recv Data: %s \n",__FUNCTION__,__LINE__,l_arrs8Buf); } l_s32Ret = IPC_RTSP_CheckReply(l_arrs8Buf); if(0 != l_s32Ret) { gs_s32CseqCount++; return -5; } else { printf("biao debug [%s %d:] recv OK \n",__FUNCTION__,__LINE__); } gs_s32CseqCount++; pstRTSPClient->bRTPState = true; return 0; } return -1; } int RTSP_Client_TEARDOWN(RTSP_STATUS_S *pstRTSPClient) { char l_arrs8Buf[BUF_LEN_1024_BYTE]; int l_s32Ret; int i; int l_s32RtspsocketFd; char *l_ps8RTSPSessionId; if(NULL==pstRTSPClient) { printf("%s %d input para error\n",__FUNCTION__,__LINE__); return -1; } l_s32RtspsocketFd = pstRTSPClient->s32SockFd; l_ps8RTSPSessionId = pstRTSPClient->arrs8SessionId; bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); for(i=pstRTSPClient->stSDPPara.s32AuthorType;i<3;i++) { IPC_RTSP_StreamHandle(pstRTSPClient->arrs8RTSPUrl,pstRTSPClient->s32StreamType); IPC_RTSP_TEARDOWNHandle(pstRTSPClient,l_arrs8Buf,i,l_ps8RTSPSessionId); l_s32Ret = NET_SocketSendData(l_s32RtspsocketFd,l_arrs8Buf,strlen(l_arrs8Buf)); if(l_s32Ret < 0) { printf("%s %d:Send Data Error \n",__FUNCTION__,__LINE__); return -2; } printf("[%s %d:] Send data:\n%s\nl_s32Ret=%d\n",__FUNCTION__,__LINE__,l_arrs8Buf,l_s32Ret); bzero(l_arrs8Buf,BUF_LEN_1024_BYTE); l_s32Ret = IPC_RTSP_RecvSelect(l_s32RtspsocketFd,l_arrs8Buf,BUF_LEN_1024_BYTE); if(l_s32Ret <= 0) { printf("%s %d: Recv Select Error\n",__FUNCTION__,__LINE__); return -3; }else { printf("[%s %d:] Recv Data: %s \n",__FUNCTION__,__LINE__,l_arrs8Buf); } l_s32Ret = IPC_RTSP_CheckReply(l_arrs8Buf); if(0 != l_s32Ret) { printf("%s %d Check Replay Error \n",__FUNCTION__,__LINE__); return -4; } gs_s32CseqCount++; pstRTSPClient->bRTPState = true; return 0; } return -1; }

    程序运行结果如下:

    RTSP请求的时候,一般有三种情况,(a)不需要用户密码,直接访问。(b)使用BASE64加密访问。(c)使用MD5加密访问。上面运行的测试程序,因为使用的是大华的IPC摄像头,所以使用的是MD5用户加密交互。

      完整工程文件结构:



      https://www.xamrdz.com/mobile/4jx1934641.html

      相关文章: