|
@@ -1,10 +1,10 @@
|
|
import WorkerManager from './workerManager.js';
|
|
import WorkerManager from './workerManager.js';
|
|
-import {hex_md5} from "./md5.js";
|
|
|
|
|
|
+import { hex_md5 } from "./md5.js";
|
|
|
|
|
|
function WebSocketServer(options) {
|
|
function WebSocketServer(options) {
|
|
let videoElement = null;
|
|
let videoElement = null;
|
|
let canvasElement = null;
|
|
let canvasElement = null;
|
|
- let ROIElement =null;
|
|
|
|
|
|
+ let ROIElement = null;
|
|
let websocket = null;
|
|
let websocket = null;
|
|
let wsURL = null;
|
|
let wsURL = null;
|
|
let rtspURL = null;
|
|
let rtspURL = null;
|
|
@@ -24,7 +24,7 @@ function WebSocketServer(options) {
|
|
let getParameterInterval = null; //保活
|
|
let getParameterInterval = null; //保活
|
|
let AACCodecInfo = null;
|
|
let AACCodecInfo = null;
|
|
|
|
|
|
-//RTP包处理相关
|
|
|
|
|
|
+ //RTP包处理相关
|
|
let rtspinterleave = null;
|
|
let rtspinterleave = null;
|
|
let RTPPacketTotalSize = 0;
|
|
let RTPPacketTotalSize = 0;
|
|
let rtpheader = null;
|
|
let rtpheader = null;
|
|
@@ -50,7 +50,7 @@ function WebSocketServer(options) {
|
|
|
|
|
|
let v = null;
|
|
let v = null;
|
|
|
|
|
|
- function constructor({video, canvas, ROI,wsUrl, rtspUrl,vue} = {options}) {
|
|
|
|
|
|
+ function constructor({ video, canvas, ROI, wsUrl, rtspUrl, vue } = { options }) {
|
|
videoElement = video;
|
|
videoElement = video;
|
|
canvasElement = canvas;
|
|
canvasElement = canvas;
|
|
ROIElement = ROI;
|
|
ROIElement = ROI;
|
|
@@ -61,14 +61,14 @@ function WebSocketServer(options) {
|
|
password = ret[2]
|
|
password = ret[2]
|
|
ip = ret[3]
|
|
ip = ret[3]
|
|
port = ret[4]
|
|
port = ret[4]
|
|
- wsURL = wsUrl+'?tcpaddr='+ encodeURIComponent(username+":"+password+"@"+ip+":"+port);
|
|
|
|
|
|
+ wsURL = wsUrl + '?tcpaddr=' + encodeURIComponent(username + ":" + password + "@" + ip + ":" + port);
|
|
v = vue
|
|
v = vue
|
|
}
|
|
}
|
|
|
|
|
|
constructor.prototype = {
|
|
constructor.prototype = {
|
|
init() {
|
|
init() {
|
|
workerManager = new WorkerManager();
|
|
workerManager = new WorkerManager();
|
|
- workerManager.init(videoElement,canvasElement, ROIElement,v);
|
|
|
|
|
|
+ workerManager.init(videoElement, canvasElement, ROIElement, v);
|
|
},
|
|
},
|
|
connect() {
|
|
connect() {
|
|
websocket = new WebSocket(wsURL);
|
|
websocket = new WebSocket(wsURL);
|
|
@@ -79,8 +79,8 @@ function WebSocketServer(options) {
|
|
websocket.send(option);
|
|
websocket.send(option);
|
|
//console.log('websocket connect')
|
|
//console.log('websocket connect')
|
|
};
|
|
};
|
|
- websocket.onerror = ()=> {
|
|
|
|
- if(connectFailCallback) {
|
|
|
|
|
|
+ websocket.onerror = () => {
|
|
|
|
+ if (connectFailCallback) {
|
|
connectFailCallback('websocket connect fail');
|
|
connectFailCallback('websocket connect fail');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -90,20 +90,20 @@ function WebSocketServer(options) {
|
|
clearInterval(getStreamInterval);
|
|
clearInterval(getStreamInterval);
|
|
SendRtspCommand(CommandConstructor("TEARDOWN", null));
|
|
SendRtspCommand(CommandConstructor("TEARDOWN", null));
|
|
websocket.close();
|
|
websocket.close();
|
|
- if(workerManager) {
|
|
|
|
|
|
+ if (workerManager) {
|
|
workerManager.terminate();
|
|
workerManager.terminate();
|
|
}
|
|
}
|
|
},
|
|
},
|
|
setCallBack(event, callback) {
|
|
setCallBack(event, callback) {
|
|
switch (event) {
|
|
switch (event) {
|
|
case 'error':
|
|
case 'error':
|
|
- connectFailCallback = ()=>{
|
|
|
|
|
|
+ connectFailCallback = () => {
|
|
callback();
|
|
callback();
|
|
this.close();
|
|
this.close();
|
|
};
|
|
};
|
|
break;
|
|
break;
|
|
case 'noStream':
|
|
case 'noStream':
|
|
- noStreamCallback = ()=>{
|
|
|
|
|
|
+ noStreamCallback = () => {
|
|
callback();
|
|
callback();
|
|
this.close();
|
|
this.close();
|
|
};
|
|
};
|
|
@@ -227,14 +227,14 @@ function WebSocketServer(options) {
|
|
//console.log(stringMessage)
|
|
//console.log(stringMessage)
|
|
//let seekPoint = stringMessage.search("CSeq: ") + 5;
|
|
//let seekPoint = stringMessage.search("CSeq: ") + 5;
|
|
let rtspResponseMsg = parseRtsp(stringMessage);
|
|
let rtspResponseMsg = parseRtsp(stringMessage);
|
|
-//console.log(rtspResponseMsg)
|
|
|
|
|
|
+ //console.log(rtspResponseMsg)
|
|
if (rtspResponseMsg.ResponseCode === RTSP_STATE.UNAUTHORIZED && Authentication === "\r\n") { //需要鉴权
|
|
if (rtspResponseMsg.ResponseCode === RTSP_STATE.UNAUTHORIZED && Authentication === "\r\n") { //需要鉴权
|
|
- if(currentState === "Describe") {
|
|
|
|
|
|
+ if (currentState === "Describe") {
|
|
IsDescribe = false;
|
|
IsDescribe = false;
|
|
describekey = false;
|
|
describekey = false;
|
|
}
|
|
}
|
|
- // username= getUser(rtspURL).username;//用url里覆盖配置
|
|
|
|
- // password = getUser(rtspURL).password;
|
|
|
|
|
|
+ // username= getUser(rtspURL).username;//用url里覆盖配置
|
|
|
|
+ // password = getUser(rtspURL).password;
|
|
//console.log(rtspResponseMsg)
|
|
//console.log(rtspResponseMsg)
|
|
SendRtspCommand(formDigest(rtspResponseMsg));
|
|
SendRtspCommand(formDigest(rtspResponseMsg));
|
|
Authentication = "\r\n";
|
|
Authentication = "\r\n";
|
|
@@ -253,7 +253,7 @@ function WebSocketServer(options) {
|
|
//console.log(rtspSDPData.Sessions)
|
|
//console.log(rtspSDPData.Sessions)
|
|
for (let idx = 0; idx < rtspSDPData.Sessions.length; idx++) {
|
|
for (let idx = 0; idx < rtspSDPData.Sessions.length; idx++) {
|
|
let sdpInfoObj = {};
|
|
let sdpInfoObj = {};
|
|
- if (rtspSDPData.Sessions[idx].CodecMime === "H264" ) { //暂时只支持H264
|
|
|
|
|
|
+ if (rtspSDPData.Sessions[idx].CodecMime === "H264") { //暂时只支持H264
|
|
sdpInfoObj.codecName = rtspSDPData.Sessions[idx].CodecMime;
|
|
sdpInfoObj.codecName = rtspSDPData.Sessions[idx].CodecMime;
|
|
//sdpInfoObj.trackID = rtspSDPData.Sessions[idx].ControlURL;
|
|
//sdpInfoObj.trackID = rtspSDPData.Sessions[idx].ControlURL;
|
|
sdpInfoObj.trackID = rtspSDPData.Sessions[idx].trackID;
|
|
sdpInfoObj.trackID = rtspSDPData.Sessions[idx].trackID;
|
|
@@ -262,7 +262,7 @@ function WebSocketServer(options) {
|
|
if (typeof rtspSDPData.Sessions[idx].Framerate !== "undefined") {
|
|
if (typeof rtspSDPData.Sessions[idx].Framerate !== "undefined") {
|
|
sdpInfoObj.Framerate = parseInt(rtspSDPData.Sessions[idx].Framerate)
|
|
sdpInfoObj.Framerate = parseInt(rtspSDPData.Sessions[idx].Framerate)
|
|
}
|
|
}
|
|
- if(typeof rtspSDPData.Sessions[idx].SPS !== "undefined") {
|
|
|
|
|
|
+ if (typeof rtspSDPData.Sessions[idx].SPS !== "undefined") {
|
|
sdpInfoObj.SPS = rtspSDPData.Sessions[idx].SPS;
|
|
sdpInfoObj.SPS = rtspSDPData.Sessions[idx].SPS;
|
|
}
|
|
}
|
|
SDPinfo.push(sdpInfoObj)
|
|
SDPinfo.push(sdpInfoObj)
|
|
@@ -300,8 +300,8 @@ function WebSocketServer(options) {
|
|
SendRtspCommand(CommandConstructor("GET_PARAMETER", null))
|
|
SendRtspCommand(CommandConstructor("GET_PARAMETER", null))
|
|
}, SEND_GETPARM_INTERVAL);
|
|
}, SEND_GETPARM_INTERVAL);
|
|
|
|
|
|
- getStreamInterval = setInterval(()=>{
|
|
|
|
- if(!getBitStream()) {
|
|
|
|
|
|
+ getStreamInterval = setInterval(() => {
|
|
|
|
+ if (!getBitStream()) {
|
|
console.log('超时!');
|
|
console.log('超时!');
|
|
noStreamCallback && noStreamCallback();
|
|
noStreamCallback && noStreamCallback();
|
|
}
|
|
}
|
|
@@ -353,31 +353,31 @@ function WebSocketServer(options) {
|
|
function CommandConstructor(method, trackID, interleaved) {
|
|
function CommandConstructor(method, trackID, interleaved) {
|
|
let sendMessage;
|
|
let sendMessage;
|
|
switch (method) {
|
|
switch (method) {
|
|
- case"OPTIONS":
|
|
|
|
- case"TEARDOWN":
|
|
|
|
- case"SET_PARAMETERS":
|
|
|
|
- case"DESCRIBE":
|
|
|
|
|
|
+ case "OPTIONS":
|
|
|
|
+ case "TEARDOWN":
|
|
|
|
+ case "SET_PARAMETERS":
|
|
|
|
+ case "DESCRIBE":
|
|
//TODO: 保活
|
|
//TODO: 保活
|
|
sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\n" + Authentication;
|
|
sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\n" + Authentication;
|
|
break;
|
|
break;
|
|
- case"SETUP":
|
|
|
|
|
|
+ case "SETUP":
|
|
//console.log(trackID)
|
|
//console.log(trackID)
|
|
//TODO 多trackID的时候测试一下
|
|
//TODO 多trackID的时候测试一下
|
|
sendMessage = method + " " + rtspURL + "/" + trackID + " RTSP/1.0\r\nCSeq: " + CSeq + Authentication + "Transport:RTP/AVP/TCP;unicast;interleaved=" + 2 * interleaved + "-" + (2 * interleaved + 1) + "\r\n";
|
|
sendMessage = method + " " + rtspURL + "/" + trackID + " RTSP/1.0\r\nCSeq: " + CSeq + Authentication + "Transport:RTP/AVP/TCP;unicast;interleaved=" + 2 * interleaved + "-" + (2 * interleaved + 1) + "\r\n";
|
|
- if(sessionID == 0) {
|
|
|
|
|
|
+ if (sessionID == 0) {
|
|
sendMessage += "\r\n";
|
|
sendMessage += "\r\n";
|
|
} else {
|
|
} else {
|
|
sendMessage += "Session: " + sessionID + "\r\n\r\n";
|
|
sendMessage += "Session: " + sessionID + "\r\n\r\n";
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
- case"PLAY":
|
|
|
|
|
|
+ case "PLAY":
|
|
sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\nSession: " + sessionID + "\r\n" + "Range: npt=0.000-\r\n" + Authentication;
|
|
sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\nSession: " + sessionID + "\r\n" + "Range: npt=0.000-\r\n" + Authentication;
|
|
break;
|
|
break;
|
|
- case"PAUSE":
|
|
|
|
|
|
+ case "PAUSE":
|
|
sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\nSession: " + sessionID + "\r\n\r\n";
|
|
sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\nSession: " + sessionID + "\r\n\r\n";
|
|
break;
|
|
break;
|
|
- case"GET_PARAMETER":
|
|
|
|
- sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\nSession: " + sessionID + "\r\n" + Authentication;
|
|
|
|
|
|
+ case "GET_PARAMETER":
|
|
|
|
+ sendMessage = method + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\nSession: " + sessionID + "\r\n" + Authentication;
|
|
break;
|
|
break;
|
|
default:
|
|
default:
|
|
console.log('暂不支持的RTSP信令');
|
|
console.log('暂不支持的RTSP信令');
|
|
@@ -513,7 +513,7 @@ function WebSocketServer(options) {
|
|
let SDPLineTokens = TokenziedDescribe[cnt].split("=");
|
|
let SDPLineTokens = TokenziedDescribe[cnt].split("=");
|
|
if (SDPLineTokens.length > 0) {
|
|
if (SDPLineTokens.length > 0) {
|
|
switch (SDPLineTokens[0]) {
|
|
switch (SDPLineTokens[0]) {
|
|
- case"a":
|
|
|
|
|
|
+ case "a":
|
|
let aLineToken = SDPLineTokens[1].split(":");
|
|
let aLineToken = SDPLineTokens[1].split(":");
|
|
if (aLineToken.length > 1) {
|
|
if (aLineToken.length > 1) {
|
|
if (aLineToken[0] === "control") {
|
|
if (aLineToken[0] === "control") {
|
|
@@ -594,7 +594,7 @@ function WebSocketServer(options) {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
- case"m":
|
|
|
|
|
|
+ case "m":
|
|
let mLineToken = SDPLineTokens[1].split(" ");
|
|
let mLineToken = SDPLineTokens[1].split(" ");
|
|
let Session = {};
|
|
let Session = {};
|
|
Session.Type = mLineToken[0];
|
|
Session.Type = mLineToken[0];
|
|
@@ -603,7 +603,7 @@ function WebSocketServer(options) {
|
|
SDPData.Sessions.push(Session);
|
|
SDPData.Sessions.push(Session);
|
|
mediaFound = true;
|
|
mediaFound = true;
|
|
break;
|
|
break;
|
|
- case"b":
|
|
|
|
|
|
+ case "b":
|
|
if (mediaFound === true) {
|
|
if (mediaFound === true) {
|
|
let bLineToken = SDPLineTokens[1].split(":");
|
|
let bLineToken = SDPLineTokens[1].split(":");
|
|
SDPData.Sessions[SDPData.Sessions.length - 1].Bitrate = bLineToken[1]
|
|
SDPData.Sessions[SDPData.Sessions.length - 1].Bitrate = bLineToken[1]
|
|
@@ -616,7 +616,7 @@ function WebSocketServer(options) {
|
|
};
|
|
};
|
|
|
|
|
|
function formDigest(message) {
|
|
function formDigest(message) {
|
|
- let {Nonce, Realm} = message;
|
|
|
|
|
|
+ let { Nonce, Realm } = message;
|
|
//Realm = '54c415830ec4';
|
|
//Realm = '54c415830ec4';
|
|
//Nonce = 'fb01c51948704e59eb5a474b33caff8b';
|
|
//Nonce = 'fb01c51948704e59eb5a474b33caff8b';
|
|
let user = {
|
|
let user = {
|
|
@@ -629,18 +629,18 @@ function WebSocketServer(options) {
|
|
let responce = hex_md5(hex1 + ":" + Nonce + ":" + hex2);
|
|
let responce = hex_md5(hex1 + ":" + Nonce + ":" + hex2);
|
|
Authentication = 'Authorization: Digest username="' + user.username + '", realm="' + Realm + '", nonce="' + Nonce + '",uri="' + rtspURL + '", response="' + responce + '"\r\n' + "Accept: application/sdp\r\n" + '\r\n';
|
|
Authentication = 'Authorization: Digest username="' + user.username + '", realm="' + Realm + '", nonce="' + Nonce + '",uri="' + rtspURL + '", response="' + responce + '"\r\n' + "Accept: application/sdp\r\n" + '\r\n';
|
|
|
|
|
|
- return currentState.toUpperCase() + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\n" + Authentication;
|
|
|
|
|
|
+ return currentState.toUpperCase() + " " + rtspURL + " RTSP/1.0\r\nCSeq: " + CSeq + "\r\n" + Authentication;
|
|
}
|
|
}
|
|
|
|
|
|
function getUser(rtspUrl) {
|
|
function getUser(rtspUrl) {
|
|
let user = rtspUrl.split('rtsp://')[1].split('@')[0];
|
|
let user = rtspUrl.split('rtsp://')[1].split('@')[0];
|
|
let username = user.split(':')[0],
|
|
let username = user.split(':')[0],
|
|
password = user.split(':')[1];
|
|
password = user.split(':')[1];
|
|
- return {username, password};
|
|
|
|
|
|
+ return { username, password };
|
|
}
|
|
}
|
|
|
|
|
|
function getBitStream() {
|
|
function getBitStream() {
|
|
- if(lastStreamTime === null) {
|
|
|
|
|
|
+ if (lastStreamTime === null) {
|
|
lastStreamTime = Date.now();
|
|
lastStreamTime = Date.now();
|
|
} else {
|
|
} else {
|
|
//console.log(Date.now() - lastStreamTime)
|
|
//console.log(Date.now() - lastStreamTime)
|