#include "RtspClient.h"
#include "PrintLog.h"
#include <string.h>
#include "NTime.h"
CRtspClient::CRtspClient()
{
m_fun = NULL;
m_user_info = 0;
memset( m_recv_buf, 0, sizeof(m_recv_buf) );
m_recv_len = 0;
m_cseq = 0;
m_rtp_ch = 0;
memset( m_session, 0, sizeof(m_session) );
memset( m_base_url, 0, sizeof(m_base_url) );
m_method = RTSP_METHOD_MAX;
memset( &m_media_info, 0, sizeof(m_media_info) );
m_media_num = 0;
m_media_index = 0;
m_range = -1;
}
CRtspClient::~CRtspClient()
{
Destroy();
WaitExit();
}
int CRtspClient::Start( const char* url, DataCBFun fun, long user_info )
{
m_fun = fun;
m_user_info = user_info;
memset( m_base_url, 0, sizeof(m_base_url) );
strncpy( m_base_url, url, sizeof(m_base_url) );
if( open_sock( url ) < 0 )
return -1;
if( Create( "RtspClientThread", 0 ) < 0 ){
LogError( "create thread RtspClientThread failed\n" );
return -1;
}
return 0;
}
int CRtspClient::GetRange()
{
return m_range;
}
int CRtspClient::Play( int s_sec, int e_sec )
{
return send_play_cmd( s_sec, e_sec );
}
int CRtspClient::Pause()
{
return send_simple_cmd( RTSP_PAUSE );
}
void CRtspClient::Close()
{
send_simple_cmd( RTSP_TEARDOWN );
}
void CRtspClient::thread_proc( long user_info )
{
int ret = 0;
while( IsDestroyed() == false ){
CGuard lock( m_mutex );
fd_set read_fd_set;
fd_set except_fd_set;
FD_ZERO( &read_fd_set ); //WRITE_EVENT
FD_ZERO( &except_fd_set ); //EXCEPT_EVENT
FD_SET( m_sock.GetFd(), &read_fd_set );
FD_SET( m_sock.GetFd(), &except_fd_set );
#ifdef _WIN32
struct timeval tmv_timeout={ 0L, 1000000L };//单位微秒,默认1秒超时
#else
struct timeval tmv_timeout={ 0L, 1000L };//单位毫秒,默认1秒超时
#endif
if( select( m_sock.GetFd()+1, &read_fd_set, NULL, &except_fd_set, &tmv_timeout ) > 0 ){
if( FD_ISSET( m_sock.GetFd(), &read_fd_set ) != 0 ){
if( recv_data() < 0 ){
ret = -1;
break;
}
}
if( FD_ISSET( m_sock.GetFd(), &except_fd_set ) != 0 ){
LogError( "session net exception\n" );
ret = -1;
break;
}
}
}
if( ret < 0 && m_fun != NULL )
m_fun( NULL, 0 );//close client
}
int CRtspClient::open_sock( const char* url )
{
char ip[128] = "";
int port = 554;
const char* start = strstr( url, "rtsp://" );
if( start == NULL ){
LogError( "url format error, url:%s\n", url );
return -1;
}
const char* end = strstr( url+strlen("rtsp://"), ":" );
if( end != NULL )
port = atoi( end+1 );
else{
end = strstr( url+strlen("rtsp://"), "/" );
if( end == NULL ){
LogError( "url format error, url:%s\n", url );
return -1;
}
}
strncpy( ip, url+strlen("rtsp://"), end-start-strlen("rtsp://") );
m_method = RTSP_METHOD_MAX;
m_sock.Close();
if( m_sock.Connect( ip, port ) < 0 ){
LogError( "open sock failed, ip:%s, port:%d\n", ip, port );
return -1;
}
m_method = RTSP_OPTIONS;
if( send_simple_cmd( RTSP_OPTIONS ) < 0 ){
LogError( "send describe request failed\n" );
return -1;
}
return 0;
}
int CRtspClient::recv_data()
{
int recv_len = sizeof(m_recv_buf)-1-m_recv_len;
if( recv_len <= 0 ){
LogError( "recv buf len <=0\n" );
return -1;
}
int ret = m_sock.Recv( m_recv_buf+m_recv_len, recv_len );
if( ret < 0 ){
LogError( "recv data failed\n" );
return -1;
}
m_recv_len += ret;
return handle_data();
}
int CRtspClient::handle_data()
{
char *recv_buf = m_recv_buf;
m_recv_buf[m_recv_len] = '\0';
int ret = -1;
while( m_recv_len > 0 ){
ret = 0;
if( '$' == *recv_buf ){
if( m_recv_len <= sizeof(struct RtpTcpHdr) )
break;
struct RtpTcpHdr* r_t_hd = (struct RtpTcpHdr *)recv_buf;
uint32_t r_t_len = ntohs(r_t_hd->len);
if( m_recv_len < r_t_len + 4 )
break;
if( r_t_hd->channel == m_rtp_ch && m_fun != NULL )
m_fun( recv_buf+4, r_t_len ); // handle rtp
//handle rtcp
m_recv_len -= r_t_len + 4;
recv_buf += r_t_len + 4;
}else{
int parser_ret = parse_data( recv_buf, m_recv_len );
if( parser_ret < 0 )
break;
PRINT_RECV_CMD( recv_buf, parser_ret );
if( handle_cmd( recv_buf, parser_ret ) < 0 )
return -1;
m_recv_len -= parser_ret;
recv_buf += parser_ret;
}
}
if( m_recv_len > 0 )
memmove( m_recv_buf , recv_buf, m_recv_len );
return ret;
}
int CRtspClient::parse_data( const char* data, int len )
{
const char *start = data;
const char *end_mark = "\r\n\r\n";
const char *end = NULL;
if( NULL == (end = strstr(start, end_mark)) )
return -1;
int header_len = end - start + strlen(end_mark);
int content_len = 0;
const char* conten_len_mark = "Content-Length: ";
const char* content_len_pos = strstr(data, conten_len_mark);
if( content_len_pos != NULL && strstr(content_len_pos, "\r\n") != NULL )
content_len = atoi( content_len_pos+strlen(conten_len_mark) );
if( len < (header_len + content_len) )
return -1;
return (header_len + content_len);
}
int CRtspClient::handle_cmd( const char* data, int len )
{
int code = parse_rsp_code( data, len );
if( code != 200 ){
LogError( "response code id not 200 ok, code:%d\n", code );
return -1;
}
int ret = 0;
switch( m_method ){
case RTSP_OPTIONS:
ret = send_describe_cmd();
m_method = RTSP_DESCRIBE;
break;
case RTSP_DESCRIBE:
parser_describe( data, len );
ret = send_setup_cmd();
m_method = RTSP_SETUP;
break;
case RTSP_SETUP:
parser_setup( data, len );
if( m_media_index < m_media_num )
ret = send_setup_cmd();
else{
ret = send_play_cmd( 0, -1 );
m_method = RTSP_METHOD_MAX;
}
break;
default:
break;
}
return ret;
}
int CRtspClient::get_str( const char* data, const char* s_mark, bool with_s_make, const char* e_mark, bool with_e_make, char* dest )
{
const char* satrt = strstr( data, s_mark );
if( satrt != NULL ){
const char* end = strstr( satrt, e_mark );
if( end != NULL ){
int s_pos = with_s_make ? 0 : strlen(s_mark);
int e_pos = with_e_make ? strlen(e_mark) : 0;
strncpy( dest, satrt+s_pos, (end-e_pos) - (satrt+s_pos) );
}
return 0;
}
return -1;
}
int CRtspClient::parse_rsp_code( const char* data, int len )
{
const char* rtsp_pos = strstr( data, "RTSP/" );
if( rtsp_pos != data ){
LogError( "response format error\n" );
return -1;
}
const char* pos = strstr( rtsp_pos+strlen("RTSP/"), " " );
if( pos == NULL ){
LogError( "response format error\n" );
return -1;
}
int code = atoi( pos+1 );
if( code < 100 || code > 999 ){
LogError( "response format error\n" );
return -1;
}
return code;
}
int CRtspClient::send_simple_cmd( RtspMethodT method )
{
char cmd[512] = "";
snprintf( cmd, sizeof(cmd), "%s %s RTSP/1.0\r\nCSeq: %d\r\n%s\r\n", g_method[method].method_str, m_base_url, m_cseq++, m_session );
return send_cmd( cmd, strlen(cmd) );
}
int CRtspClient::send_describe_cmd()
{
char cmd[512] = "";
snprintf( cmd, sizeof(cmd), "DESCRIBE %s RTSP/1.0\r\nCSeq: %d\r\n%sAccept: application/sdp\r\n\r\n", m_base_url, m_cseq++, m_session );
return send_cmd( cmd, strlen(cmd) );
}
int CRtspClient::send_setup_cmd()
{
char cmd[512] = "";
snprintf( cmd, sizeof(cmd), "SETUP %s%s%s RTSP/1.0\r\nCSeq: %d\r\n%sTransport: RTP/AVP/TCP;unicast;interleaved=%d-%d\r\n\r\n",
m_base_url, m_base_url[strlen(m_base_url)-1]=='/'?"":"/", m_media_info[m_media_index++].track_id, m_cseq++, m_session, m_rtp_ch, m_rtp_ch+1 );
return send_cmd( cmd, strlen(cmd) );
}
int CRtspClient::send_play_cmd( int s_sec, int e_sec )
{
char range[64] = "";
if( s_sec != -1 ){
if( e_sec != -1 )
snprintf( range, sizeof(range), "Range: npt=%d.00-%d.00\r\n", s_sec, e_sec );
else
snprintf( range, sizeof(range), "Range: npt=%d.00-\r\n", s_sec );
}
char cmd[512] = "";
snprintf( cmd, sizeof(cmd), "PLAY %s RTSP/1.0\r\nCSeq: %d\r\n%s%s\r\n", m_base_url, m_cseq++, m_session, range );
return send_cmd( cmd, strlen(cmd) );

E_A_S_T
- 粉丝: 21
最新资源
- 卷烟工业控制网络安全技术的研究应用.docx
- 中小学生网络写作问题探究.docx
- 单片机智能小车研究与设计开发书.doc
- 2018届高三数学一轮复习-第十二章-复数、算法、推理与证明-第三节-合情推理与演绎推理-理.ppt
- 利用web技术构建语音多媒体在线练习与测试平台研究与应用申报书.doc
- 对搜索引擎竞价排名引发的商标侵权纠纷的思考.docx
- (源码)基于Java的Flappy Bird游戏.zip
- 第二章-微型计算机结构.ppt
- 软件工程项目之项目计划与质量管理概述.doc
- 疾病预防控制中心档案信息化建设探究.docx
- 网络教学系统在高校计算机教学中的应用方法研究.docx
- 员工费用支出、报销、保险待遇理赔记录表(Excel表格通用模板).xls
- PLC课程设计(电机清洗机).doc
- 学校管理团队信息化领导力模型的构建.pptx
- 电子商务课程研究设计问卷调查.doc
- 基于 PaddleHub 动物识别模型与百度百科的动物百科 AI 老师
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



- 1
- 2
- 3
- 4
- 5
- 6
前往页