From 6a070a9a64f454393e35c8fe985b6eaa8c5ef9e4 Mon Sep 17 00:00:00 2001 From: kyxlx550 Date: Mon, 20 Apr 2020 21:34:18 +0800 Subject: [PATCH] support sip ptz cmd --- trunk/research/players/srs_gb28181.html | 74 +++++++++- trunk/src/app/srs_app_gb28181.cpp | 12 ++ trunk/src/app/srs_app_gb28181.hpp | 1 + trunk/src/app/srs_app_gb28181_sip.cpp | 122 ++++++++++++++-- trunk/src/app/srs_app_gb28181_sip.hpp | 3 + trunk/src/app/srs_app_http_api.cpp | 20 +++ trunk/src/kernel/srs_kernel_error.hpp | 3 + trunk/src/protocol/srs_sip_stack.cpp | 182 ++++++++++++++++++++---- trunk/src/protocol/srs_sip_stack.hpp | 13 ++ 9 files changed, 387 insertions(+), 43 deletions(-) diff --git a/trunk/research/players/srs_gb28181.html b/trunk/research/players/srs_gb28181.html index 2962b4d4a..080ad0173 100644 --- a/trunk/research/players/srs_gb28181.html +++ b/trunk/research/players/srs_gb28181.html @@ -318,11 +318,21 @@
+
+ + + + + + +
+ [注意] !!! 云台控制需要启用内部sip功能
@PST
+ @@ -335,6 +345,17 @@ @@ -963,9 +984,13 @@ }); + var time_query = function(){ + $("#btn_sip_query_session").click(); + setTimeout(function () {$("#btn_sip_query_session").click()}, 1000); + } + $("#btn_sip_unregister").click(function(){ var id = $("#sipSessionId").text(); - alert(id); if (id.indexOf("id:") != -1) { var str = id.split(":") @@ -977,7 +1002,7 @@ $('#sipSessionMessage').html(syntaxHighlight(ret)); if (ret != undefined && ret.code == 0){ - $("#btn_sip_query_session").click(); + time_query(); } } }); @@ -996,7 +1021,7 @@ $('#sipSessionMessage').html(syntaxHighlight(ret)); if (ret != undefined && ret.code == 0){ - $("#btn_sip_query_session").click(); + time_query(); } } }); @@ -1015,7 +1040,7 @@ $('#sipSessionMessage').html(syntaxHighlight(ret)); if (ret != undefined && ret.code == 0){ - $("#btn_sip_query_session").click(); + time_query(); } } }); @@ -1033,7 +1058,7 @@ var ret = http_get(apiurl); $('#sipSessionMessage').html(syntaxHighlight(ret)); if (ret != undefined && ret.code == 0){ - $("#btn_sip_query_session").click(); + time_query(); } } }); @@ -1060,6 +1085,44 @@ } }); + var call_ptz_cmd = function(cmd) { + var str = $("#gb28181ChannelId").text(); + var str_array = str.split("@") + var chid = ""; + var id = ""; + if (str_array.length < 1){ + return; + } + + var speed = "136"; + + id = str_array[0]; + chid = str_array[1]; + + url = $("#txt_api_url").val(); + var apiurl = url + "/api/v1/gb28181?action=sip_ptz&id=" + id + "&chid="+chid+ "&ptzcmd="+cmd + "&speed=" + speed; + var ret = http_get(apiurl); + $('#gb28181ChannelMessage').html(syntaxHighlight(ret)); + }; + + var ptz_cmd = ["up", "down", "right", "left", "zoomin", "zoomout"] + for (var i=0; isend_bye(&req, chid); } +srs_error_t SrsGb28181Manger::notify_sip_ptz(std::string id, std::string chid, std::string cmd, + uint8_t speed, int priority) +{ + if (!sip_service){ + return srs_error_new(ERROR_GB28181_SIP_NOT_RUN, "sip not run"); + } + + SrsSipRequest req; + req.sip_auth_id = id; + return sip_service->send_ptz(&req, chid, cmd, speed, priority); +} + srs_error_t SrsGb28181Manger::notify_sip_raw_data(std::string id, std::string data) { if (!sip_service){ diff --git a/trunk/src/app/srs_app_gb28181.hpp b/trunk/src/app/srs_app_gb28181.hpp index 777e334eb..9f551a26a 100644 --- a/trunk/src/app/srs_app_gb28181.hpp +++ b/trunk/src/app/srs_app_gb28181.hpp @@ -422,6 +422,7 @@ public: srs_error_t notify_sip_raw_data(std::string id, std::string data); srs_error_t notify_sip_unregister(std::string id); srs_error_t notify_sip_query_catalog(std::string id); + srs_error_t notify_sip_ptz(std::string id, std::string chid, std::string cmd, uint8_t speed, int priority); srs_error_t query_sip_session(std::string id, SrsJsonArray* arr); private: diff --git a/trunk/src/app/srs_app_gb28181_sip.cpp b/trunk/src/app/srs_app_gb28181_sip.cpp index 36616cd4f..169cd1fca 100644 --- a/trunk/src/app/srs_app_gb28181_sip.cpp +++ b/trunk/src/app/srs_app_gb28181_sip.cpp @@ -100,6 +100,7 @@ SrsGb28181SipSession::SrsGb28181SipSession(SrsGb28181SipService *c, SrsSipReques _peer_port = 0; _fromlen = 0; + _sip_cseq = 100; } SrsGb28181SipSession::~SrsGb28181SipSession() @@ -485,23 +486,30 @@ srs_error_t SrsGb28181SipService::on_udp_sip(string peer_ip, int peer_port, }else if (req->is_message()) { SrsGb28181SipSession* sip_session = fetch(session_id); + + if (!sip_session){ + sip_session = fetch_session_by_callid(req->call_id); + } + if (!sip_session || sip_session->register_status() == SrsGb28181SipSessionUnkonw){ srs_trace("gb28181: %s client not registered", req->sip_auth_id.c_str()); return err; } //reponse status - send_status(req, from, fromlen); - sip_session->set_alive_status(SrsGb28181SipSessionAliveOk); - sip_session->set_alive_time(srs_get_system_time()); - sip_session->set_sockaddr((sockaddr)*from); - sip_session->set_sockaddr_len(fromlen); - sip_session->set_peer_port(peer_port); - sip_session->set_peer_ip(peer_ip); - - //update device list - if (req->device_list_map.size() > 0){ - sip_session->update_device_list(req->device_list_map); + if (req->cmdtype == SrsSipCmdRequest){ + send_status(req, from, fromlen); + sip_session->set_alive_status(SrsGb28181SipSessionAliveOk); + sip_session->set_alive_time(srs_get_system_time()); + sip_session->set_sockaddr((sockaddr)*from); + sip_session->set_sockaddr_len(fromlen); + sip_session->set_peer_port(peer_port); + sip_session->set_peer_ip(peer_ip); + + //update device list + if (req->device_list_map.size() > 0){ + sip_session->update_device_list(req->device_list_map); + } } }else if (req->is_invite()) { @@ -675,6 +683,7 @@ srs_error_t SrsGb28181SipService::send_invite(SrsSipRequest *req, string ip, i req->realm = config->sip_realm; req->serial = config->sip_serial; req->chid = chid; + req->seq = sip_session->sip_cseq(); SrsSipRequest register_req = sip_session->request(); req->to_realm = register_req.to_realm; @@ -730,6 +739,7 @@ srs_error_t SrsGb28181SipService::send_bye(SrsSipRequest *req, std::string chid) req->realm = config->sip_realm; req->serial = config->sip_serial; req->chid = chid; + req->seq = sip_session->sip_cseq(); SrsSipRequest register_req = sip_session->request(); req->to_realm = register_req.to_realm; @@ -774,11 +784,22 @@ srs_error_t SrsGb28181SipService::send_sip_raw_data(SrsSipRequest *req, std::st srs_error_t SrsGb28181SipService::send_query_catalog(SrsSipRequest *req) { + srs_error_t err = srs_success; + + srs_assert(req); + + SrsGb28181SipSession *sip_session = fetch(req->sip_auth_id); + + if (!sip_session){ + return srs_error_new(ERROR_GB28181_SESSION_IS_NOTEXIST, "sip session not exist"); + } + req->host = config->host; req->host_port = config->sip_port; req->realm = config->sip_realm; req->serial = config->sip_serial; req->chid = req->sip_auth_id; + req->seq = sip_session->sip_cseq(); //get protocol stack std::stringstream ss; @@ -787,6 +808,85 @@ srs_error_t SrsGb28181SipService::send_query_catalog(SrsSipRequest *req) return send_sip_raw_data(req, ss.str()); } +srs_error_t SrsGb28181SipService::send_ptz(SrsSipRequest *req, std::string chid, std::string cmd, + uint8_t speed, int priority) +{ + srs_error_t err = srs_success; + + srs_assert(req); + + SrsGb28181SipSession *sip_session = fetch(req->sip_auth_id); + + if (!sip_session){ + return srs_error_new(ERROR_GB28181_SESSION_IS_NOTEXIST, "sip session not exist"); + } + + SrsGb28181Device *device = sip_session->get_device_info(chid); + if (!device){ + return srs_error_new(ERROR_GB28181_SIP_CH_NOTEXIST, "sip device channel not exist"); + } + + if (device->invite_status != SrsGb28181SipSessionInviteOk){ + return srs_error_new(ERROR_GB28181_SIP_NOT_INVITE, "sip device channel not inviting"); + } + + //prame branch, from_tag, to_tag, call_id, + //The parameter of 'bye' must be the same as 'invite' + //SrsSipRequest r = sip_session->request(); + req->copy(&device->req_inivate); + + req->host = config->host; + req->host_port = config->sip_port; + req->realm = config->sip_realm; + req->serial = config->sip_serial; + req->chid = chid; + req->seq = sip_session->sip_cseq(); + + SrsSipPtzCmdType ptzcmd = SrsSipPtzCmdRight; + const char *ss_cmd = cmd.c_str(); + if (!strcasecmp(ss_cmd, "stop")){ + ptzcmd = SrsSipPtzCmdStop; + }else if (!strcasecmp(ss_cmd, "right")){ + ptzcmd = SrsSipPtzCmdRight; + }else if (!strcasecmp(ss_cmd, "left")){ + ptzcmd = SrsSipPtzCmdLeft; + }else if (!strcasecmp(ss_cmd, "down")){ + ptzcmd = SrsSipPtzCmdDown; + }else if (!strcasecmp(ss_cmd, "up")){ + ptzcmd = SrsSipPtzCmdUp; + }else if (!strcasecmp(ss_cmd, "zoomout")){ + ptzcmd = SrsSipPtzCmdZoomOut; + }else if (!strcasecmp(ss_cmd, "zoomin")){ + ptzcmd = SrsSipPtzCmdZoomIn; + }else{ + return srs_error_new(ERROR_GB28181_SIP_PTZ_CMD_INVALID, "sip ptz cmd no support"); + } + + if (speed < 0 || speed > 0xFF){ + return srs_error_new(ERROR_GB28181_SIP_PTZ_CMD_INVALID, "sip ptz cmd speed out of range"); + } + + if (priority <= 0 ){ + priority = 5; + } + + //get protocol stack + std::stringstream ss; + sip->req_ptz(ss, req, ptzcmd, speed, priority); + + sockaddr addr = sip_session->sockaddr_from(); + if (send_message(&addr, sip_session->sockaddr_fromlen(), ss) <= 0) + { + return srs_error_new(ERROR_GB28181_SIP_PTZ_FAILED, "sip ptz failed"); + } + + //call_id map sip_session + sip_session_map_by_callid(sip_session, req->call_id); + + return err; + +} + srs_error_t SrsGb28181SipService::query_sip_session(std::string sid, SrsJsonArray* arr) { srs_error_t err = srs_success; diff --git a/trunk/src/app/srs_app_gb28181_sip.hpp b/trunk/src/app/srs_app_gb28181_sip.hpp index 952fd7a3c..10d180ee8 100644 --- a/trunk/src/app/srs_app_gb28181_sip.hpp +++ b/trunk/src/app/srs_app_gb28181_sip.hpp @@ -92,6 +92,7 @@ private: std::map _device_list; //std::map _device_status; + int _sip_cseq; public: SrsGb28181SipSession(SrsGb28181SipService *c, SrsSipRequest* r); @@ -128,6 +129,7 @@ public: sockaddr sockaddr_from() { return _from;} int sockaddr_fromlen() { return _fromlen;} SrsSipRequest request() { return *req;} + int sip_cseq(){ return _sip_cseq++;} std::string session_id() { return _session_id;} public: @@ -175,6 +177,7 @@ public: srs_error_t send_invite(SrsSipRequest *req, std::string ip, int port, uint32_t ssrc, std::string chid); srs_error_t send_bye(SrsSipRequest *req, std::string chid); srs_error_t send_query_catalog(SrsSipRequest *req); + srs_error_t send_ptz(SrsSipRequest *req, std::string chid, std::string cmd, uint8_t speed, int priority); // The SIP command is transmitted through HTTP API, // and the body content is transmitted to the device, diff --git a/trunk/src/app/srs_app_http_api.cpp b/trunk/src/app/srs_app_http_api.cpp index d0be9042c..da5ab0ad2 100644 --- a/trunk/src/app/srs_app_http_api.cpp +++ b/trunk/src/app/srs_app_http_api.cpp @@ -1774,6 +1774,26 @@ srs_error_t SrsGoApiGb28181::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessa return srs_api_response_code(w, r, code); } + else if(action == "sip_ptz"){ + string chid = r->query_get("chid"); + string ptzcmd = r->query_get("ptzcmd"); + string speed = r->query_get("speed"); + string priority = r->query_get("priority"); + if (id.empty() || chid.empty() || ptzcmd.empty() || speed.empty()){ + return srs_api_response_code(w, r, ERROR_GB28181_VALUE_EMPTY); + } + + uint8_t _speed = (uint8_t)(strtoul(speed.c_str(), NULL, 10)); + int _priority = (int)(strtoul(priority.c_str(), NULL, 10)); + + err = _srs_gb28181->notify_sip_ptz(id, chid, ptzcmd, _speed, _priority); + int code = srs_error_code(err); + if (err != srs_success) { + srs_error_reset(err); + } + + return srs_api_response_code(w, r, code); + } else if(action == "sip_raw_data"){ if (id.empty()){ return srs_api_response_code(w, r, ERROR_GB28181_VALUE_EMPTY); diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index 9b0e0578e..a60130a58 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -367,6 +367,9 @@ #define ERROR_GB28181_SIP_CH_NOTEXIST 6013 #define ERROR_GB28181_SIP_RAW_DATA_FAILED 6014 #define ERROR_GB28181_SIP_PRASE_FAILED 6015 +#define ERROR_GB28181_SIP_PTZ_FAILED 6016 +#define ERROR_GB28181_SIP_NOT_INVITE 6017 +#define ERROR_GB28181_SIP_PTZ_CMD_INVALID 6018 /////////////////////////////////////////////////////// // HTTP API error. diff --git a/trunk/src/protocol/srs_sip_stack.cpp b/trunk/src/protocol/srs_sip_stack.cpp index 466c69b2e..19d959723 100644 --- a/trunk/src/protocol/srs_sip_stack.cpp +++ b/trunk/src/protocol/srs_sip_stack.cpp @@ -45,10 +45,51 @@ using namespace std; unsigned int srs_sip_random(int min,int max) { - srand(int(time(0))); + //it is possible to duplicate data with time(0) + srand(unsigned(srs_update_system_time())); return rand() % (max - min + 1) + min; } +std::string srs_sip_generate_branch() +{ + int rand = srs_sip_random(10000000, 99999999); + std::stringstream branch; + branch << "SrsGbB" << rand; + return branch.str(); +} + +std::string srs_sip_generate_to_tag() +{ + uint32_t rand = srs_sip_random(10000000, 99999999); + std::stringstream branch; + branch << "SrsGbT" << rand; + return branch.str(); +} + +std::string srs_sip_generate_from_tag() +{ + uint32_t rand = srs_sip_random(10000000, 99999999); + std::stringstream branch; + branch << "SrsGbF" << rand; + return branch.str(); +} + +std::string srs_sip_generate_call_id() +{ + uint32_t rand = srs_sip_random(10000000, 99999999); + std::stringstream branch; + branch << "2020" << rand; + return branch.str(); +} + +std::string srs_sip_generate_sn() +{ + uint32_t rand = srs_sip_random(10000000, 99999999); + std::stringstream sn; + sn << rand; + return sn.str(); +} + std::string srs_sip_get_form_to_uri(std::string msg) { //;tag=536961166 @@ -897,15 +938,13 @@ void SrsSipStack::req_invite(stringstream& ss, SrsSipRequest *req, string ip, in << "y=" << _ssrc << SRS_RTSP_CRLF; - int rand = srs_sip_random(1000, 9999); - std::stringstream from, to, uri, branch, from_tag, call_id; + std::stringstream from, to, uri; //"INVITE sip:34020000001320000001@3402000000 SIP/2.0\r\n uri << "sip:" << req->chid << "@" << req->realm; //From: ;tag=500485%d\r\n from << req->serial << "@" << req->realm; to << req->chid << "@" << req->realm; - call_id << "2020" << rand ; - + req->from = from.str(); req->to = to.str(); @@ -918,19 +957,17 @@ void SrsSipStack::req_invite(stringstream& ss, SrsSipRequest *req, string ip, in } req->uri = uri.str(); - req->call_id = call_id.str(); - branch << "z9hG4bK3420" << rand; - from_tag << "51235" << rand; - req->branch = branch.str(); - req->from_tag = from_tag.str(); + req->call_id = srs_sip_generate_call_id(); + req->branch = srs_sip_generate_branch(); + req->from_tag = srs_sip_generate_from_tag(); ss << "INVITE " << req->uri << " " << SRS_SIP_VERSION << SRS_RTSP_CRLF << "Via: " << SRS_SIP_VERSION << "/UDP "<< req->host << ":" << req->host_port << ";rport;branch=" << req->branch << SRS_RTSP_CRLF << "From: " << get_sip_from(req) << SRS_RTSP_CRLF << "To: " << get_sip_to(req) << SRS_RTSP_CRLF << "Call-ID: " << req->call_id <seq << " INVITE" << SRS_RTSP_CRLF << "Content-Type: Application/SDP" << SRS_RTSP_CRLF << "Contact: to << ">" << SRS_RTSP_CRLF << "Max-Forwards: 70" << SRS_RTSP_CRLF @@ -1039,7 +1076,6 @@ void SrsSipStack::req_bye(std::stringstream& ss, SrsSipRequest *req) req->uri = uri.str(); - int seq = srs_sip_random(22, 99); ss << "BYE " << req->uri << " "<< SRS_SIP_VERSION << SRS_RTSP_CRLF //<< "Via: "<< SRS_SIP_VERSION << "/UDP "<< req->host << ":" << req->host_port << ";rport" << branch << SRS_RTSP_CRLF << "Via: " << SRS_SIP_VERSION << "/UDP " << req->host << ":" << req->host_port << ";rport;branch=" << req->branch << SRS_RTSP_CRLF @@ -1047,7 +1083,7 @@ void SrsSipStack::req_bye(std::stringstream& ss, SrsSipRequest *req) << "To: " << get_sip_to(req) << SRS_RTSP_CRLF //bye callid is inivte callid << "Call-ID: " << req->call_id << SRS_RTSP_CRLF - << "CSeq: "<< seq <<" BYE" << SRS_RTSP_CRLF + << "CSeq: "<< req->seq <<" BYE" << SRS_RTSP_CRLF << "Max-Forwards: 70" << SRS_RTSP_CRLF << "User-Agent: " << SRS_SIP_USER_AGENT << SRS_RTSP_CRLF << "Content-Length: 0" << SRS_RTSP_CRLFCRLF; @@ -1149,40 +1185,134 @@ void SrsSipStack::req_query_catalog(std::stringstream& ss, SrsSipRequest *req) std::stringstream xml; std::string xmlbody; - int sn = srs_sip_random(10000000, 99999999); xml << "" << SRS_RTSP_CRLF << "" << SRS_RTSP_CRLF << "Catalog" << SRS_RTSP_CRLF - << "" << sn << "" << SRS_RTSP_CRLF + << "" << srs_sip_generate_sn() << "" << SRS_RTSP_CRLF << "" << req->sip_auth_id << "" << SRS_RTSP_CRLF << "" << SRS_RTSP_CRLF; xmlbody = xml.str(); - int rand = srs_sip_random(1000, 9999); - std::stringstream from, to, uri, branch, from_tag, call_id; + std::stringstream from, to, uri; //"INVITE sip:34020000001320000001@3402000000 SIP/2.0\r\n uri << "sip:" << req->sip_auth_id << "@" << req->realm; //From: ;tag=500485%d\r\n from << req->serial << "@" << req->host << ":" << req->host_port; to << req->sip_auth_id << "@" << req->realm; - call_id << "2020" << rand; - + req->from = from.str(); req->to = to.str(); req->uri = uri.str(); - req->call_id = call_id.str(); - - branch << "z9hG4bK3420" << rand; - from_tag << "51235" << rand; - req->branch = branch.str(); - req->from_tag = from_tag.str(); + + req->call_id = srs_sip_generate_call_id(); + req->branch = srs_sip_generate_branch(); + req->from_tag = srs_sip_generate_from_tag(); ss << "MESSAGE " << req->uri << " " << SRS_SIP_VERSION << SRS_RTSP_CRLF << "Via: " << SRS_SIP_VERSION << "/UDP "<< req->host << ":" << req->host_port << ";rport;branch=" << req->branch << SRS_RTSP_CRLF << "From: " << get_sip_from(req) << SRS_RTSP_CRLF << "To: " << get_sip_to(req) << SRS_RTSP_CRLF << "Call-ID: " << req->call_id << SRS_RTSP_CRLF - << "CSeq: 25 MESSAGE" << SRS_RTSP_CRLF + << "CSeq: " << req->seq << " MESSAGE" << SRS_RTSP_CRLF + << "Content-Type: Application/MANSCDP+xml" << SRS_RTSP_CRLF + << "Max-Forwards: 70" << SRS_RTSP_CRLF + << "User-Agent: " << SRS_SIP_USER_AGENT << SRS_RTSP_CRLF + << "Content-Length: " << xmlbody.length() << SRS_RTSP_CRLFCRLF + << xmlbody; + +} + +void SrsSipStack::req_ptz(std::stringstream& ss, SrsSipRequest *req, uint8_t cmd, uint8_t speed, int priority) +{ + + /* + + + DeviceControl + 11 + 34020000001310000053 + A50F01021F0000D6 + + */ + + uint8_t ptz_cmd[8] = {0}; + ptz_cmd[0] = SRS_SIP_PTZ_START; + ptz_cmd[1] = 0x0F; + ptz_cmd[2] = 0x01; + ptz_cmd[3] = cmd; + switch(cmd){ + case SrsSipPtzCmdStop: // = 0x00 + ptz_cmd[4] = 0; + ptz_cmd[5] = 0; + ptz_cmd[6] = 0; + break; + case SrsSipPtzCmdRight: // = 0x01, + case SrsSipPtzCmdLeft: // = 0x02, + ptz_cmd[4] = speed; + break; + case SrsSipPtzCmdDown: // = 0x04, + case SrsSipPtzCmdUp: // = 0x08, + ptz_cmd[5] = speed; + break; + case SrsSipPtzCmdZoomOut: // = 0x10, + case SrsSipPtzCmdZoomIn: // = 0x20 + ptz_cmd[6] = (speed & 0x0F) << 4; + break; + default: + return; + } + + uint32_t check = 0; + for (int i = 0; i < 7; i++){ + check += ptz_cmd[i]; + } + + ptz_cmd[7] = (uint8_t)(check % 256); + + std::stringstream ss_ptzcmd; + for (int i = 0; i < 8; i++){ + char hex_cmd[3] = {0}; + sprintf(hex_cmd, "%02X", ptz_cmd[i]); + ss_ptzcmd << hex_cmd; + } + + std::stringstream xml; + std::string xmlbody; + + xml << "" << SRS_RTSP_CRLF + << "" << SRS_RTSP_CRLF + << "DeviceControl" << SRS_RTSP_CRLF + << "" << srs_sip_generate_sn() << "" << SRS_RTSP_CRLF + << "" << req->sip_auth_id << "" << SRS_RTSP_CRLF + << "" << ss_ptzcmd.str() << "" << SRS_RTSP_CRLF + << "" << SRS_RTSP_CRLF + << "" << priority << "" << SRS_RTSP_CRLF + << "" << SRS_RTSP_CRLF + << "" << SRS_RTSP_CRLF; + xmlbody = xml.str(); + + std::stringstream from, to, uri, call_id; + //"INVITE sip:34020000001320000001@3402000000 SIP/2.0\r\n + uri << "sip:" << req->sip_auth_id << "@" << req->realm; + //From: ;tag=500485%d\r\n + from << req->serial << "@" << req->host << ":" << req->host_port; + to << req->sip_auth_id << "@" << req->realm; + + req->from = from.str(); + req->to = to.str(); + req->uri = uri.str(); + + req->call_id = srs_sip_generate_call_id(); + req->branch = srs_sip_generate_branch(); + req->from_tag = srs_sip_generate_from_tag(); + + ss << "MESSAGE " << req->uri << " "<< SRS_SIP_VERSION << SRS_RTSP_CRLF + //<< "Via: "<< SRS_SIP_VERSION << "/UDP "<< req->host << ":" << req->host_port << ";rport" << branch << SRS_RTSP_CRLF + << "Via: " << SRS_SIP_VERSION << "/UDP " << req->host << ":" << req->host_port << ";rport;branch=" << req->branch << SRS_RTSP_CRLF + << "From: " << get_sip_from(req) << SRS_RTSP_CRLF + << "To: " << get_sip_to(req) << SRS_RTSP_CRLF + << "Call-ID: " << req->call_id << SRS_RTSP_CRLF + << "CSeq: "<< req->seq <<" MESSAGE" << SRS_RTSP_CRLF << "Content-Type: Application/MANSCDP+xml" << SRS_RTSP_CRLF << "Max-Forwards: 70" << SRS_RTSP_CRLF << "User-Agent: " << SRS_SIP_USER_AGENT << SRS_RTSP_CRLF diff --git a/trunk/src/protocol/srs_sip_stack.hpp b/trunk/src/protocol/srs_sip_stack.hpp index 141a289ec..a91897d18 100644 --- a/trunk/src/protocol/srs_sip_stack.hpp +++ b/trunk/src/protocol/srs_sip_stack.hpp @@ -50,12 +50,24 @@ class SrsAudioFrame; #define SRS_SIP_VERSION "SIP/2.0" #define SRS_SIP_USER_AGENT RTMP_SIG_SRS_SERVER +#define SRS_SIP_PTZ_START 0xA5 + enum SrsSipCmdType{ SrsSipCmdRequest=0, SrsSipCmdRespone=1 }; +enum SrsSipPtzCmdType{ + SrsSipPtzCmdStop = 0x00, + SrsSipPtzCmdRight = 0x01, + SrsSipPtzCmdLeft = 0x02, + SrsSipPtzCmdDown = 0x04, + SrsSipPtzCmdUp = 0x08, + SrsSipPtzCmdZoomIn = 0x10, + SrsSipPtzCmdZoomOut = 0x20 +}; + std::string srs_sip_get_utc_date(); class SrsSipRequest @@ -162,6 +174,7 @@ public: virtual void req_bye(std::stringstream& ss, SrsSipRequest *req); virtual void req_401_unauthorized(std::stringstream& ss, SrsSipRequest *req); virtual void req_query_catalog(std::stringstream& ss, SrsSipRequest *req); + virtual void req_ptz(std::stringstream& ss, SrsSipRequest *req, uint8_t cmd, uint8_t speed, int priority); };