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);
};