├── .gitignore ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json ├── src ├── WebSocketServer.js ├── WorkManager.js ├── browserDetect.js ├── index.html ├── index.js ├── module │ ├── Decode │ │ ├── MjpegDecoder.js │ │ ├── h264Decoder.js │ │ ├── h265Decoder.js │ │ └── jsFFMPEG.js │ ├── Sylvester.js │ ├── WebGLCanvas.js │ ├── h264Session.js │ ├── h265Session.js │ ├── hashMap.js │ ├── ivsSession.js │ ├── mjpegSession.js │ ├── mp4remux.js │ ├── public.js │ ├── public1.js │ └── videoWorker.js ├── mp4remux.js ├── streamdrawer.js └── videoMediaSource.js └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | lerna-debug.log* 8 | 9 | # Diagnostic reports (https://nodejs.org/api/report.html) 10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 11 | 12 | # Runtime data 13 | pids 14 | *.pid 15 | *.seed 16 | *.pid.lock 17 | 18 | # Directory for instrumented libs generated by jscoverage/JSCover 19 | lib-cov 20 | 21 | # Coverage directory used by tools like istanbul 22 | coverage 23 | *.lcov 24 | 25 | # nyc test coverage 26 | .nyc_output 27 | 28 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 29 | .grunt 30 | 31 | # Bower dependency directory (https://bower.io/) 32 | bower_components 33 | 34 | # node-waf configuration 35 | .lock-wscript 36 | 37 | # Compiled binary addons (https://nodejs.org/api/addons.html) 38 | build/Release 39 | 40 | # Dependency directories 41 | node_modules/ 42 | jspm_packages/ 43 | 44 | # TypeScript v1 declaration files 45 | typings/ 46 | 47 | # TypeScript cache 48 | *.tsbuildinfo 49 | 50 | # Optional npm cache directory 51 | .npm 52 | 53 | # Optional eslint cache 54 | .eslintcache 55 | 56 | # Microbundle cache 57 | .rpt2_cache/ 58 | .rts2_cache_cjs/ 59 | .rts2_cache_es/ 60 | .rts2_cache_umd/ 61 | 62 | # Optional REPL history 63 | .node_repl_history 64 | 65 | # Output of 'npm pack' 66 | *.tgz 67 | 68 | # Yarn Integrity file 69 | .yarn-integrity 70 | 71 | # dotenv environment variables file 72 | .env 73 | .env.test 74 | 75 | # parcel-bundler cache (https://parceljs.org/) 76 | .cache 77 | 78 | # Next.js build output 79 | .next 80 | 81 | # Nuxt.js build / generate output 82 | .nuxt 83 | dist 84 | 85 | # Gatsby files 86 | .cache/ 87 | # Comment in the public line in if your project uses Gatsby and *not* Next.js 88 | # https://nextjs.org/blog/next-9-1#public-directory-support 89 | # public 90 | 91 | # vuepress build output 92 | .vuepress/dist 93 | 94 | # Serverless directories 95 | .serverless/ 96 | 97 | # FuseBox cache 98 | .fusebox/ 99 | 100 | # DynamoDB Local files 101 | .dynamodb/ 102 | 103 | # TernJS port file 104 | .tern-port 105 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Dotworld Technologies 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Dahua - Stream video in browser 2 | 3 | **Try the url before using the code below. This will play substream video without much overkill. If this is not working then proceed to next** 4 | ``` 5 | http://host:port/cgi-bin/mjpg/video.cgi?channel=1&subtype=1 6 | ``` 7 | 8 | ### RTSP over WS 9 | Stream RTSP over websocket and use RTSP direclty in web browser. Made possible by new feature in Dahua camera which implements rtspoverwebsocket functionality. This would reduce the need for a server to translate the video stream to HLS or DASH to make RTSP work on web browsers. Kudos to Dahua for this thought. 10 | 11 | NOTE: Need support for /rtspoverwebsocket support for using this feature 12 | ```html 13 | 14 | ``` 15 | 16 | ```js 17 | import PlayerControl from './src/index.js'; 18 | 19 | var options = { 20 | wsURL: "ws://host:port/rtspoverwebsocket", 21 | rtspURL: "rtsp://host:port/cam/realmonitor?channel=1&subtype=0", 22 | username: "", 23 | password: "" 24 | } 25 | 26 | let player = new PlayerControl(options) 27 | player.on("Error", (j) => { if (j) console.log(j.errorCode) }) 28 | player.init(document.querySelector("#videoplayer")) 29 | player.connect() 30 | ``` 31 | 32 | NOTE: Audio is currently not supported. This is a working PoC for video stream. Audio Streaming is also possible. 33 | 34 | ### Snapshots 35 | 36 | Try this url to take snapshots 37 | 38 | ``` 39 | http://username:password@host:port/cgi-bin/snapshot.cgi?0 40 | ``` 41 | 42 | 43 | ### Notice 44 | This project is made possible by using RTSP over WebSocket functionality implemented by Dahua for their IP Cameras. Code available in this project is extracted from an Dahua IP Camera and made to work standalone. We have no intent to commercialize this project. 45 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | import PlayerControl from "./src/index.js"; 2 | 3 | var options = { 4 | wsURL: "ws://host:port/rtspoverwebsocket", 5 | rtspURL: "rtsp://host:port/cam/realmonitor?channel=1&subtype=0", 6 | username: "", 7 | password: "", 8 | }; 9 | 10 | let player = new PlayerControl(options); 11 | player.on("Error", (j) => { 12 | if (j) console.log(j.errorCode); 13 | }); 14 | player.init( 15 | document.querySelector("#canvas"), 16 | document.querySelector("#videoplayer") 17 | ); 18 | 19 | player.connect(); 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rtsp-over-ws", 3 | "version": "1.0.0", 4 | "description": "Use Dahua RTSP over websocket feature to stream video in browsers direclty", 5 | "main": "src/index.js", 6 | "module": "src/index.js", 7 | "scripts": { 8 | "build": "webpack" 9 | }, 10 | "keywords": [ 11 | "dahua", 12 | "rtsp", 13 | "web", 14 | "websocket", 15 | "ws" 16 | ], 17 | "author": "Naveen Sakthivel", 18 | "license": "MIT", 19 | "devDependencies": { 20 | "clean-webpack-plugin": "^3.0.0", 21 | "copy-webpack-plugin": "^7.0.0", 22 | "html-webpack-plugin": "^4.5.1", 23 | "lodash": "^4.17.21", 24 | "webpack": "^5.13.0", 25 | "webpack-cli": "^4.3.1", 26 | "webpack-dev-server": "^3.11.2" 27 | }, 28 | "dependencies": { 29 | "js-md5": "^0.7.3" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/WebSocketServer.js: -------------------------------------------------------------------------------- 1 | import WorkerManager from "./WorkManager.js"; 2 | import md5 from "js-md5"; 3 | 4 | var WebsocketServer = function (a, b) { 5 | function c() {} 6 | function d(a, b, c, d) { 7 | var e = ""; 8 | switch (a) { 9 | case "OPTIONS": 10 | case "TEARDOWN": 11 | case "GET_PARAMETER": 12 | case "SET_PARAMETERS": 13 | e = 14 | a + 15 | " " + 16 | M + 17 | " RTSP/1.0\r\nCSeq: " + 18 | B + 19 | (Q ? "\r\nExtraError: support\r\n" : "\r\n") + 20 | z + 21 | "\r\n"; 22 | break; 23 | case "DESCRIBE": 24 | e = 25 | a + 26 | " " + 27 | M + 28 | " RTSP/1.0\r\nCSeq: " + 29 | B + 30 | (Q ? "\r\nExtraError: support\r\n" : "\r\n") + 31 | z + 32 | "\r\n"; 33 | break; 34 | case "SETUP": 35 | console.log("trackID: " + b), 36 | (e = 37 | a + 38 | " " + 39 | M + 40 | "/trackID=" + 41 | b + 42 | " RTSP/1.0\r\nCSeq: " + 43 | B + 44 | (Q ? "\r\nExtraError: support\r\n" : "\r\n") + 45 | z + 46 | "Transport: DH/AVP/TCP;unicast;interleaved=" + 47 | 2 * b + 48 | "-" + 49 | (2 * b + 1) + 50 | "\r\n"), 51 | (e += 0 != G ? "Session: " + G + "\r\n\r\n" : "\r\n"); 52 | break; 53 | case "PLAY": 54 | (e = 55 | a + 56 | " " + 57 | M + 58 | " RTSP/1.0\r\nCSeq: " + 59 | B + 60 | (Q ? "\r\nExtraError: support\r\n" : "\r\n") + 61 | "Session: " + 62 | G + 63 | "\r\n"), 64 | void 0 != d && 0 != d 65 | ? ((e += "Range: npt=" + d + "-\r\n"), (e += z + "\r\n")) 66 | : (e += z + "\r\n"); 67 | break; 68 | case "PAUSE": 69 | e = 70 | a + 71 | " " + 72 | M + 73 | " RTSP/1.0\r\nCSeq: " + 74 | B + 75 | (Q ? "\r\nExtraError: support\r\n" : "\r\n") + 76 | "Session: " + 77 | G + 78 | "\r\n\r\n"; 79 | break; 80 | case "SCALE": 81 | (e = 82 | "PLAY " + 83 | M + 84 | " RTSP/1.0\r\nCSeq: " + 85 | B + 86 | (Q ? "\r\nExtraError: support\r\n" : "\r\n") + 87 | "Session: " + 88 | G + 89 | "\r\n"), 90 | (e += "Scale: " + d + "\r\n"), 91 | (e += z + "\r\n"); 92 | } 93 | return e; 94 | } 95 | function e(a) { 96 | var b = {}, 97 | e = a.search("CSeq: ") + 5; 98 | if ( 99 | ((B = parseInt(a.slice(e, e + 10)) + 1), 100 | (b = m(a)), 101 | b.ResponseCode === x.UNAUTHORIZED && "" === z) 102 | ) 103 | f(b); 104 | else if (b.ResponseCode === x.OK) { 105 | if ("Options" === E) return (E = "Describe"), d("DESCRIBE", null, null); 106 | if ("Describe" === E) { 107 | (I = !1), 108 | (D = n(a)), 109 | "undefined" != typeof b.ContentBase && 110 | (D.ContentBase = b.ContentBase); 111 | var g = 0; 112 | for (g = 0; g < D.Sessions.length; g += 1) { 113 | var i = {}; 114 | "JPEG" === D.Sessions[g].CodecMime || 115 | "H264" === D.Sessions[g].CodecMime || 116 | "H265" === D.Sessions[g].CodecMime || 117 | "H264-SVC" == D.Sessions[g].CodecMime 118 | ? ((i.codecName = D.Sessions[g].CodecMime), 119 | "H264-SVC" == D.Sessions[g].CodecMime && (i.codecName = "H264"), 120 | "H265" == D.Sessions[g].CodecMime && 121 | c.prototype.setLiveMode("canvas"), 122 | (i.trackID = D.Sessions[g].ControlURL), 123 | (i.ClockFreq = D.Sessions[g].ClockFreq), 124 | (i.Port = parseInt(D.Sessions[g].Port)), 125 | "undefined" != typeof D.Sessions[g].Framerate && 126 | ((i.Framerate = parseInt(D.Sessions[g].Framerate)), 127 | w.setFPS(i.Framerate), 128 | N(i.Framerate)), 129 | A.push(i)) 130 | : "PCMU" === D.Sessions[g].CodecMime || 131 | -1 !== D.Sessions[g].CodecMime.search("G726-16") || 132 | -1 !== D.Sessions[g].CodecMime.search("G726-24") || 133 | -1 !== D.Sessions[g].CodecMime.search("G726-32") || 134 | -1 !== D.Sessions[g].CodecMime.search("G726-40") || 135 | "PCMA" === D.Sessions[g].CodecMime 136 | ? ("PCMU" === D.Sessions[g].CodecMime 137 | ? (i.codecName = "G.711Mu") 138 | : "G726-16" === D.Sessions[g].CodecMime 139 | ? (i.codecName = "G.726-16") 140 | : "G726-24" === D.Sessions[g].CodecMime 141 | ? (i.codecName = "G.726-24") 142 | : "G726-32" === D.Sessions[g].CodecMime 143 | ? (i.codecName = "G.726-32") 144 | : "G726-40" === D.Sessions[g].CodecMime 145 | ? (i.codecName = "G.726-40") 146 | : "PCMA" === D.Sessions[g].CodecMime && 147 | (i.codecName = "G.711A"), 148 | (i.trackID = D.Sessions[g].ControlURL), 149 | (i.ClockFreq = D.Sessions[g].ClockFreq), 150 | (i.Port = parseInt(D.Sessions[g].Port)), 151 | (i.Bitrate = parseInt(D.Sessions[g].Bitrate)), 152 | A.push(i)) 153 | : "mpeg4-generic" === D.Sessions[g].CodecMime || 154 | "MPEG4-GENERIC" === D.Sessions[g].CodecMime 155 | ? ((i.codecName = "mpeg4-generic"), 156 | (i.trackID = D.Sessions[g].ControlURL), 157 | (i.ClockFreq = D.Sessions[g].ClockFreq), 158 | (i.Port = parseInt(D.Sessions[g].Port)), 159 | (i.Bitrate = parseInt(D.Sessions[g].Bitrate)), 160 | A.push(i)) 161 | : "vnd.onvif.metadata" === D.Sessions[g].CodecMime 162 | ? ((i.codecName = "MetaData"), 163 | (i.trackID = D.Sessions[g].ControlURL), 164 | (i.ClockFreq = D.Sessions[g].ClockFreq), 165 | (i.Port = parseInt(D.Sessions[g].Port)), 166 | A.push(i)) 167 | : "stream-assist-frame" === D.Sessions[g].CodecMime 168 | ? ((i.codecName = "stream-assist-frame"), 169 | (i.trackID = D.Sessions[g].ControlURL), 170 | (i.ClockFreq = D.Sessions[g].ClockFreq), 171 | (i.Port = parseInt(D.Sessions[g].Port)), 172 | A.push(i)) 173 | : console.log( 174 | "Unknown codec type:", 175 | D.Sessions[g].CodecMime, 176 | D.Sessions[g].ControlURL 177 | ); 178 | } 179 | return (F = 0), (E = "Setup"), d("SETUP", F); 180 | } 181 | if ("Setup" === E) { 182 | if (((G = b.SessionID), F < A.length)) 183 | return ( 184 | (A[F].RtpInterlevedID = b.RtpInterlevedID), 185 | (A[F].RtcpInterlevedID = b.RtcpInterlevedID), 186 | (F += 1), 187 | F !== A.length 188 | ? d("SETUP", A[F].trackID.split("=")[1] - 0) 189 | : (w.sendSdpInfo(A, L, I), (E = "Play"), d("PLAY", null)) 190 | ); 191 | console.log("Unknown setup SDP index"); 192 | } else if ("Play" === E) { 193 | (G = b.SessionID), 194 | clearInterval(J), 195 | (J = setInterval(function () { 196 | return h(d("GET_PARAMETER", null, null)); 197 | }, y)); 198 | E = "Playing"; 199 | } else "Playing" === E || console.log("unknown rtsp state:" + E); 200 | } else if (b.ResponseCode === x.NOTSERVICE) { 201 | if ("Setup" === E && -1 !== A[F].trackID.search("trackID=t")) 202 | return ( 203 | (A[F].RtpInterlevedID = -1), 204 | (A[F].RtcpInterlevedID = -1), 205 | (F += 1), 206 | (I = !1), 207 | C({ 208 | errorCode: "504", 209 | description: "Talk Service Unavilable", 210 | place: "RtspClient.js", 211 | }), 212 | F < A.length 213 | ? d("SETUP", A[F].trackID) 214 | : ((E = "Play"), d("PLAY", null)) 215 | ); 216 | C({ 217 | errorCode: "503", 218 | description: "Service Unavilable", 219 | }); 220 | } else if (b.ResponseCode === x.NOTFOUND) { 221 | if ("Describe" === E || "Options" === E) 222 | return void C({ 223 | errorCode: 404, 224 | description: "rtsp not found", 225 | }); 226 | } else if (b.ResponseCode === x.INVALID_RANGE) 227 | return ( 228 | ("backup" === H || "playback" === H) && 229 | C({ 230 | errorCode: "457", 231 | description: "Invalid range", 232 | }), 233 | void console.log("RTP disconnection detect!!!") 234 | ); 235 | } 236 | function f(a) { 237 | var b = O.username, 238 | c = O.passWord, 239 | e = { 240 | Method: null, 241 | Realm: null, 242 | Nonce: null, 243 | Uri: null, 244 | }, 245 | f = null; 246 | (e = { 247 | Method: E.toUpperCase(), 248 | Realm: a.Realm, 249 | Nonce: a.Nonce, 250 | Uri: M, 251 | }), 252 | (f = g(b, c, e.Uri, e.Realm, e.Nonce, e.Method)), 253 | (z = 254 | 'Authorization: Digest username="' + b + '", realm="' + e.Realm + '",'), 255 | (z += 256 | ' nonce="' + e.Nonce + '", uri="' + e.Uri + '", response="' + f + '"'), 257 | (z += "\r\n"), 258 | h(d("OPTIONS", null, null)); 259 | } 260 | function g(a, b, c, d, e, f) { 261 | var g = null, 262 | h = null, 263 | i = null; 264 | return ( 265 | (g = md5(a + ":" + d + ":" + b).toLowerCase()), 266 | (h = md5(f + ":" + c).toLowerCase()), 267 | (i = md5(g + ":" + e + ":" + h).toLowerCase()) 268 | ); 269 | } 270 | function h(a) { 271 | if (void 0 != a && null != a && "" != a) 272 | if (null !== o && o.readyState === WebSocket.OPEN) { 273 | if (v === !1) { 274 | var b = a.search("DESCRIBE"); 275 | -1 !== b && ((u = !0), (v = !0)); 276 | } 277 | void 0 != a && o.send(i(a)); 278 | } else console.log("ws未连接"); 279 | } 280 | function i(a) { 281 | for ( 282 | var b = a.length, c = new Uint8Array(new ArrayBuffer(b)), d = 0; 283 | b > d; 284 | d++ 285 | ) 286 | c[d] = a.charCodeAt(d); 287 | return c; 288 | } 289 | function j(a) { 290 | var b = new Uint8Array(), 291 | c = new Uint8Array(a.data); 292 | for (b = new Uint8Array(c.length), b.set(c, 0), s = b.length; s > 0; ) 293 | if (36 !== b[0]) { 294 | var d = String.fromCharCode.apply(null, b), 295 | f = null; 296 | -1 !== d.indexOf("OffLine:File Over"), 297 | -1 !== d.indexOf("OffLine:KmsUnavailable") && 298 | C({ 299 | errorCode: 203, 300 | }), 301 | u === !0 302 | ? ((f = d.lastIndexOf("\r\n")), (u = !1)) 303 | : (f = d.search("\r\n\r\n")); 304 | var g = d.search("RTSP"); 305 | if (-1 === g) return void (b = new Uint8Array()); 306 | if (-1 === f) return void (s = b.length); 307 | (q = b.subarray(g, f + p)), (b = b.subarray(f + p)); 308 | var i = String.fromCharCode.apply(null, q); 309 | h(e(i)), (s = b.length); 310 | } else { 311 | if ( 312 | ((r = b.subarray(0, p)), 313 | (t = (r[2] << 24) | (r[3] << 16) | (r[4] << 8) | r[5]), 314 | !(t + p <= b.length)) 315 | ) 316 | return void (s = b.length); 317 | var j = b.subarray(p, t + p); 318 | l(r, j), (b = b.subarray(t + p)), (s = b.length); 319 | } 320 | } 321 | function k(a) { 322 | K = a; 323 | } 324 | function l(a, b) { 325 | w.parseRTPData(a, b), k(!0); 326 | } 327 | function m(a) { 328 | var b = {}, 329 | c = 0, 330 | d = 0, 331 | e = null, 332 | f = null, 333 | g = null; 334 | if (-1 !== a.search("Content-Type: application/sdp")) { 335 | var h = a.split("\r\n\r\n"); 336 | g = h[0]; 337 | } else g = a; 338 | var i = g.split("\r\n"), 339 | j = i[0].split(" "); 340 | if ( 341 | (j.length > 2 && 342 | ((b.ResponseCode = parseInt(j[1])), (b.ResponseMessage = j[2])), 343 | b.ResponseCode === x.OK) 344 | ) { 345 | for (c = 1; c < i.length; c++) 346 | if (((f = i[c].split(":")), "Public" === f[0])) 347 | b.MethodsSupported = f[1].split(","); 348 | else if ("CSeq" === f[0]) b.CSeq = parseInt(f[1]); 349 | else if ("Content-Type" === f[0]) 350 | (b.ContentType = f[1]), 351 | -1 !== b.ContentType.search("application/sdp") && 352 | (b.SDPData = n(a)); 353 | else if ("Content-Length" === f[0]) b.ContentLength = parseInt(f[1]); 354 | else if ("Content-Base" === f[0]) { 355 | var k = i[c].search("Content-Base:"); 356 | -1 !== k && (b.ContentBase = i[c].substr(k + 13)); 357 | } else if ("Session" === f[0]) { 358 | var l = f[1].split(";"); 359 | b.SessionID = parseInt(l[0]); 360 | } else if ("Transport" === f[0]) { 361 | var m = f[1].split(";"); 362 | for (d = 0; d < m.length; d++) { 363 | var o = m[d].search("interleaved="); 364 | if (-1 !== o) { 365 | var p = m[d].substr(o + 12), 366 | q = p.split("-"); 367 | q.length > 1 && 368 | ((b.RtpInterlevedID = parseInt(q[0])), 369 | (b.RtcpInterlevedID = parseInt(q[1]))); 370 | } 371 | } 372 | } else if ("RTP-Info" === f[0]) { 373 | f[1] = i[c].substr(9); 374 | var r = f[1].split(","); 375 | for (b.RTPInfoList = [], d = 0; d < r.length; d++) { 376 | var s = r[d].split(";"), 377 | t = {}, 378 | u = 0; 379 | for (u = 0; u < s.length; u++) { 380 | var v = s[u].search("url="); 381 | -1 !== v && (t.URL = s[u].substr(v + 4)), 382 | (v = s[u].search("seq=")), 383 | -1 !== v && (t.Seq = parseInt(s[u].substr(v + 4))); 384 | } 385 | b.RTPInfoList.push(t); 386 | } 387 | } 388 | } else if (b.ResponseCode === x.UNAUTHORIZED) 389 | for (c = 1; c < i.length; c++) 390 | if (((f = i[c].split(":")), "CSeq" === f[0])) b.CSeq = parseInt(f[1]); 391 | else if ("WWW-Authenticate" === f[0]) { 392 | var w = f[1].split(","); 393 | for (d = 0; d < w.length; d++) { 394 | var y = w[d].search("Digest realm="); 395 | if (-1 !== y) { 396 | e = w[d].substr(y + 13); 397 | var z = e.split('"'); 398 | b.Realm = z[1]; 399 | } 400 | if (((y = w[d].search("nonce=")), -1 !== y)) { 401 | e = w[d].substr(y + 6); 402 | var A = e.split('"'); 403 | b.Nonce = A[1]; 404 | } 405 | } 406 | } 407 | return b; 408 | } 409 | function n(a) { 410 | var b = {}, 411 | c = []; 412 | b.Sessions = c; 413 | var d = null; 414 | if (-1 !== a.search("Content-Type: application/sdp")) { 415 | var e = a.split("\r\n\r\n"); 416 | d = e[1]; 417 | } else d = a; 418 | var f = d.split("\r\n"), 419 | g = 0, 420 | h = !1; 421 | for (g = 0; g < f.length; g++) { 422 | var i = f[g].split("="); 423 | if (i.length > 0) 424 | switch (i[0]) { 425 | case "a": 426 | var j = i[1].split(":"); 427 | if (j.length > 1) 428 | if ("control" === j[0]) { 429 | var k = f[g].search("control:"); 430 | h === !0 431 | ? -1 !== k && 432 | (b.Sessions[b.Sessions.length - 1].ControlURL = f[g].substr( 433 | k + 8 434 | )) 435 | : -1 !== k && (b.BaseURL = f[g].substr(k + 8)); 436 | } else if ("rtpmap" === j[0]) { 437 | var l = j[1].split(" "); 438 | b.Sessions[b.Sessions.length - 1].PayloadType = l[0]; 439 | var m = l[1].split("/"); 440 | (b.Sessions[b.Sessions.length - 1].CodecMime = m[0]), 441 | m.length > 1 && 442 | (b.Sessions[b.Sessions.length - 1].ClockFreq = m[1]); 443 | } else if ("framesize" === j[0]) { 444 | var n = j[1].split(" "); 445 | if (n.length > 1) { 446 | var o = n[1].split("-"); 447 | (b.Sessions[b.Sessions.length - 1].Width = o[0]), 448 | (b.Sessions[b.Sessions.length - 1].Height = o[1]); 449 | } 450 | } else if ("framerate" === j[0]) 451 | b.Sessions[b.Sessions.length - 1].Framerate = j[1]; 452 | else if ("fmtp" === j[0]) { 453 | var p = f[g].split(" "); 454 | if (p.length < 2) continue; 455 | for (var q = 1; q < p.length; q++) { 456 | var r = p[q].split(";"), 457 | s = 0; 458 | for (s = 0; s < r.length; s++) { 459 | var t = r[s].search("mode="); 460 | if ( 461 | (-1 !== t && 462 | (b.Sessions[b.Sessions.length - 1].mode = r[s].substr( 463 | t + 5 464 | )), 465 | (t = r[s].search("config=")), 466 | -1 !== t && 467 | ((b.Sessions[b.Sessions.length - 1].config = r[ 468 | s 469 | ].substr(t + 7)), 470 | (L.config = b.Sessions[b.Sessions.length - 1].config), 471 | (L.clockFreq = 472 | b.Sessions[b.Sessions.length - 1].ClockFreq), 473 | (L.bitrate = 474 | b.Sessions[b.Sessions.length - 1].Bitrate)), 475 | (t = r[s].search("sprop-vps=")), 476 | -1 !== t && 477 | (b.Sessions[b.Sessions.length - 1].VPS = r[s].substr( 478 | t + 10 479 | )), 480 | (t = r[s].search("sprop-sps=")), 481 | -1 !== t && 482 | (b.Sessions[b.Sessions.length - 1].SPS = r[s].substr( 483 | t + 10 484 | )), 485 | (t = r[s].search("sprop-pps=")), 486 | -1 !== t && 487 | (b.Sessions[b.Sessions.length - 1].PPS = r[s].substr( 488 | t + 10 489 | )), 490 | (t = r[s].search("sprop-parameter-sets=")), 491 | -1 !== t) 492 | ) { 493 | var u = r[s].substr(t + 21), 494 | v = u.split(","); 495 | v.length > 1 && 496 | ((b.Sessions[b.Sessions.length - 1].SPS = v[0]), 497 | (b.Sessions[b.Sessions.length - 1].PPS = v[1])); 498 | } 499 | } 500 | } 501 | } 502 | break; 503 | case "m": 504 | var w = i[1].split(" "), 505 | x = {}; 506 | (x.Type = w[0]), 507 | (x.Port = w[1]), 508 | (x.Payload = w[3]), 509 | b.Sessions.push(x), 510 | (h = !0); 511 | break; 512 | case "b": 513 | if (h === !0) { 514 | var y = i[1].split(":"); 515 | b.Sessions[b.Sessions.length - 1].Bitrate = y[1]; 516 | } 517 | } 518 | } 519 | return b; 520 | } 521 | var a = a, 522 | o = null, 523 | p = 6, 524 | q = null, 525 | r = null, 526 | s = 0, 527 | t = 0, 528 | u = !1, 529 | v = !1, 530 | w = new WorkerManager(), 531 | x = { 532 | OK: 200, 533 | UNAUTHORIZED: 401, 534 | NOTFOUND: 404, 535 | INVALID_RANGE: 457, 536 | NOTSERVICE: 503, 537 | DISCONNECT: 999, 538 | }, 539 | y = 4e4, 540 | z = "", 541 | A = [], 542 | B = 1, 543 | C = null, 544 | D = {}, 545 | E = "Options", 546 | F = null, 547 | G = null, 548 | H = "", 549 | I = !1, 550 | J = null, 551 | K = !1, 552 | L = {}, 553 | M = b, 554 | N = null, 555 | O = {}, 556 | P = "", 557 | Q = !1; 558 | return ( 559 | (c.prototype = { 560 | init: function (a, b) { 561 | w.init(a, b); 562 | }, 563 | setStoreEncrypt: function (a) { 564 | Q = a; 565 | }, 566 | connect: function () { 567 | o || 568 | ((o = new WebSocket(a)), 569 | (o.binaryType = "arraybuffer"), 570 | o.addEventListener("message", j, !1), 571 | (o.onopen = function () { 572 | var a = 573 | "OPTIONS " + 574 | M + 575 | " RTSP/1.0\r\nCSeq: " + 576 | B + 577 | (Q ? "\r\nExtraError: support" : "") + 578 | "\r\n\r\n", 579 | b = i(a); 580 | o.send(b); 581 | }), 582 | (o.onerror = function () { 583 | C({ 584 | errorCode: 202, 585 | description: "Open WebSocket Error", 586 | }); 587 | })); 588 | }, 589 | disconnect: function () { 590 | h(d("TEARDOWN", null, null)), 591 | clearInterval(J), 592 | (J = null), 593 | null !== o && 594 | o.readyState === WebSocket.OPEN && 595 | (o.close(), (o = null), (G = null)), 596 | null !== o && (o.onerror = null), 597 | w.terminate(); 598 | }, 599 | controlPlayer: function (a) { 600 | var b = ""; 601 | switch (((P = a.command), a.command)) { 602 | case "PLAY": 603 | if (((E = "Play"), null != a.range)) { 604 | b = d("PLAY", null, null, a.range); 605 | break; 606 | } 607 | (b = d("PLAY", null, null)), P && w.initStartTime(); 608 | break; 609 | case "PAUSE": 610 | if ("PAUSE" === E) break; 611 | (E = "PAUSE"), (b = d("PAUSE", null, null)); 612 | break; 613 | case "SCALE": 614 | (b = d("SCALE", null, null, a.data)), w.playbackSpeed(a.data); 615 | break; 616 | case "TEARDOWN": 617 | b = d("TEARDOWN", null, null); 618 | break; 619 | case "audioPlay": 620 | case "volumn": 621 | case "audioSamplingRate": 622 | w.controlAudio(a.command, a.data); 623 | break; 624 | default: 625 | console.log("未知指令: " + a.command); 626 | } 627 | "" != b && h(b); 628 | }, 629 | setLiveMode: function (a) { 630 | w.setLiveMode(a); 631 | }, 632 | setRTSPURL: function (a) { 633 | M = a; 634 | }, 635 | setCallback: function (a, b) { 636 | "GetFrameRate" === a ? (N = b) : w.setCallback(a, b), 637 | "Error" == a && (C = b); 638 | }, 639 | setUserInfo: function (a, b) { 640 | (O.username = a), (O.passWord = b); 641 | }, 642 | capture: function (a) { 643 | w.capture(a); 644 | }, 645 | }), 646 | new c() 647 | ); 648 | }; 649 | 650 | export default WebsocketServer; 651 | -------------------------------------------------------------------------------- /src/WorkManager.js: -------------------------------------------------------------------------------- 1 | import { VideoMediaSource } from "./videoMediaSource.js"; 2 | import { BrowserDetect } from "./browserDetect.js"; 3 | import mp4Remux from "./mp4remux.js"; 4 | import { StreamDrawer } from "./streamdrawer"; 5 | 6 | var WorkerManager = function () { 7 | function workManagerA() { 8 | N = !0; 9 | console.log("WorkerManager.constructor"); 10 | console.log(this); 11 | somethingO = this; 12 | } 13 | function b() { 14 | return W; 15 | } 16 | function c() { 17 | null !== z && z(!1); 18 | } 19 | function d(b) { 20 | var c = b.data; 21 | switch (c.type) { 22 | case "WorkerReady": 23 | xb && xb(); 24 | break; 25 | case "canvasRender": 26 | k(0, "currentTime"), 27 | i(c.data), 28 | tb++, 29 | 0 === sb && (sb = performance.now()); 30 | break; 31 | case "initSegment": 32 | (W = c.data), j(); 33 | break; 34 | case "mediaSample": 35 | null === Y.samples && (Y.samples = new Array(ib)), 36 | null === c.data.frame_time_stamp && 37 | (c.data.frameDuration = Math.round(ob / K)), 38 | 1 !== hb && (c.data.frameDuration = ob / Math.abs(hb)), 39 | (Y.samples[Z++] = c.data), 40 | (mb += c.data.frameDuration), 41 | (nb += c.data.frameDuration), 42 | (ib = 43 | Y.samples[0].frameDuration > 500 && 44 | Y.samples[0].frameDuration <= 3e3 45 | ? 1 46 | : 1 === hb 47 | ? gb 48 | : Math.abs(hb)), 49 | jb !== ib && h(1 !== hb), 50 | (jb = ib); 51 | break; 52 | case "videoRender": 53 | var d = new Uint8Array(c.data.length + $); 54 | if ( 55 | (0 !== $ && d.set(_), 56 | d.set(c.data, $), 57 | (_ = d), 58 | ($ = _.length), 59 | Z % ib === 0 && 0 !== Z) 60 | ) { 61 | if ( 62 | (null !== Y.samples[0].frameDuration 63 | ? ((Y.baseMediaDecodeTime = 1 === ab ? 0 : lb), (lb = mb)) 64 | : (Y.baseMediaDecodeTime = Math.round(ob / K) * ib * (ab - 1)), 65 | "chrome" == H && 1 === hb) 66 | ) 67 | for (var e = Y.samples.length, f = nb / ib, g = 0; e > g; g++) 68 | Y.samples[g].frameDuration = f; 69 | (nb = 0), 70 | (X = mp4Remux.mediaSegment(ab, Y, _, Y.baseMediaDecodeTime)), 71 | ab++, 72 | (Z = 0), 73 | (_ = null), 74 | ($ = 0), 75 | null !== V 76 | ? V.setMediaSegment(X) 77 | : kb === !1 && 78 | (console.log("workerManager::videoMS error!! recreate videoMS"), 79 | j()), 80 | null !== p && p.stopRendering(); 81 | } 82 | break; 83 | case "mediasegmentData": 84 | V.setMediaSegment(c.data), 85 | kb === !1 && (console.log("videoMS error!! recreate videoMS"), j()); 86 | break; 87 | case "videoInfo": 88 | I = c.data; 89 | break; 90 | case "time": 91 | break; 92 | case "videoTimeStamp": 93 | (db = c.data), null !== V && null !== db && V.setvideoTimeStamp(db); 94 | break; 95 | case "firstFrame": 96 | p.startRendering(), "undefined" != typeof p.setFPS && p.setFPS(K); 97 | break; 98 | case "drop": 99 | break; 100 | case "codecInfo": 101 | (bb = c.data), null !== V && V.setCodecInfo(bb); 102 | break; 103 | case "stepPlay": 104 | switch (c.data) { 105 | case "needBuffering": 106 | (Q = !0), w("request", S); 107 | break; 108 | case "BufferFull": 109 | if (((Q = !1), w("complete"), Ab)) { 110 | var m = { 111 | type: "stepPlay", 112 | data: "findIFrame", 113 | }; 114 | l.postMessage(m), p.startRendering(), (Ab = !1); 115 | } 116 | } 117 | break; 118 | case "setVideoTagMode": 119 | workManagerA.prototype.setLiveMode(c.data); 120 | break; 121 | case "playbackFlag": 122 | (zb.type = c.data === !0 ? "playback" : "live"), 123 | null !== V && V.setPlaybackFlag(c.data); 124 | break; 125 | case "error": 126 | null !== A && A(c.data); 127 | break; 128 | case "MSEResolutionChanged": 129 | E(c.data); 130 | break; 131 | case "DecodeStart": 132 | var n = c.data.width - 0, 133 | o = c.data.height - 0; 134 | R.setAttribute("width", n), R.setAttribute("height", o), B(c.data); 135 | break; 136 | case "ivsDraw": 137 | G(c.data); 138 | break; 139 | default: 140 | console.log("workerManager::videoWorker unknown data = " + c.data); 141 | } 142 | } 143 | function e(a) { 144 | var b = a.data; 145 | switch (b.type) { 146 | case "render": 147 | if (U === !0) break; 148 | pb !== b.codec && 149 | (null !== q && 150 | ((qb = q.getVolume()), 151 | (rb = q.getInitVideoTimeStamp()), 152 | q.terminate()), 153 | "AAC" === b.codec 154 | ? "edge" === H || "firefox" === H 155 | ? ((q = null), 156 | null !== A && 157 | A({ 158 | errorCode: 201, 159 | })) 160 | : (q = new AudioPlayerAAC()) 161 | : ((q = new AudioPlayerGxx()), q.setSamplingRate(b.samplingRate)), 162 | null !== q && 163 | (q.setInitVideoTimeStamp(rb), q.audioInit(qb) || (q = null)), 164 | (pb = b.codec)), 165 | null !== q && 166 | (null === I || "undefined" == typeof I 167 | ? q.bufferAudio(b.data, b.rtpTimeStamp, null) 168 | : q.bufferAudio(b.data, b.rtpTimeStamp, I.codecType)); 169 | } 170 | } 171 | function f(a) { 172 | var b = a.data; 173 | switch (b.type) { 174 | case "rtpData": 175 | v(b.data); 176 | } 177 | } 178 | function g(a) { 179 | var b = { 180 | type: "getRtpData", 181 | data: a, 182 | }; 183 | n.postMessage(b); 184 | } 185 | function h(a) { 186 | null !== V && (V.close(), (V = null)), 187 | (ib = a === !1 ? gb : Math.abs(hb)), 188 | (Y.samples = new Array(ib)), 189 | (kb = !1), 190 | (ab = 1), 191 | (X = null), 192 | (Z = 0), 193 | (_ = null), 194 | ($ = 0); 195 | } 196 | function i(a) { 197 | null !== a && 198 | null !== p && 199 | ("mjpeg" === I.codecType 200 | ? p.drawMJPEG( 201 | a, 202 | I.width, 203 | I.height, 204 | I.codecType, 205 | I.frameType, 206 | I.timeStamp 207 | ) 208 | : p.draw(a, I.width, I.height, I.codecType, I.frameType, I.timeStamp)); 209 | } 210 | function j() { 211 | (kb = !0), 212 | null === V 213 | ? ((V = VideoMediaSource(somethingO)), 214 | V.setCodecInfo(bb), 215 | V.setInitSegmentFunc(b), 216 | V.setVideoSizeCallback(c), 217 | V.setBeginDrawCallback(t), 218 | V.init(vmSourceInit), 219 | V.setSpeedPlay(hb)) 220 | : (V.getVideoElement(), V.setInitSegment()), 221 | V.setAudioStartCallback(k); 222 | } 223 | function k(a, b) { 224 | null !== q && q.setBufferingFlag(a, b); 225 | } 226 | var l = null, 227 | audioWorker = null, 228 | n = null, 229 | somethingO = null, 230 | p = null, 231 | q = null, 232 | r = null, 233 | s = null, 234 | t = null, 235 | u = null, 236 | v = null, 237 | w = null, 238 | x = null, 239 | y = null, 240 | z = null, 241 | A = null, 242 | B = null, 243 | C = null, 244 | D = null, 245 | E = null, 246 | F = null, 247 | G = null, 248 | H = BrowserDetect(), 249 | I = null, 250 | J = null, 251 | K = 0, 252 | L = null, 253 | M = !1, 254 | N = !0, 255 | O = "canvas", 256 | P = !0, 257 | Q = !1, 258 | R = null, 259 | S = null, 260 | T = null, 261 | U = !1, 262 | V = null, 263 | W = null, 264 | X = null, 265 | Y = { 266 | id: 1, 267 | samples: null, 268 | baseMediaDecodeTime: 0, 269 | }, 270 | Z = 0, 271 | $ = 0, 272 | _ = null, 273 | ab = 1, 274 | bb = "", 275 | vmSourceInit = null, 276 | db = null, 277 | eb = 2, 278 | fb = 4, 279 | gb = "chrome" !== H ? fb : eb, 280 | hb = 1, 281 | ib = gb, 282 | jb = ib, 283 | kb = !1, 284 | lb = 0, 285 | mb = 0, 286 | nb = 0, 287 | ob = 1e3, 288 | pb = null, 289 | qb = 0, 290 | rb = 0, 291 | sb = 0, 292 | tb = 0, 293 | ub = 1e3, 294 | vb = null, 295 | wb = null, 296 | xb = null, 297 | yb = 0, 298 | zb = { 299 | type: "live", 300 | codec: "", 301 | width: 0, 302 | height: 0, 303 | isLimitSpeed: null, 304 | }, 305 | Ab = !1, 306 | Bb = null, 307 | Cb = null, 308 | Db = null, 309 | Eb = { 310 | 5: "MJPEG", 311 | 8: "H264", 312 | 12: "H265", 313 | }, 314 | Fb = { 315 | 1: 4e3, 316 | 2: 8e3, 317 | 3: 11025, 318 | 4: 16e3, 319 | 5: 2e4, 320 | 6: 22050, 321 | 7: 32e3, 322 | 8: 44100, 323 | 9: 48e3, 324 | 10: 96e3, 325 | 11: 128e3, 326 | 12: 192e3, 327 | 13: 64e3, 328 | }; 329 | workManagerA.prototype = { 330 | init: function (a, b) { 331 | (yb = 0), (R = a), (vmSourceInit = b); 332 | window.navigator.userAgent; 333 | (l = new Worker("module/videoWorker.js")), 334 | (l.onmessage = d), 335 | (p = new StreamDrawer(yb, this, R)), 336 | p.setResizeCallback(s), 337 | (wb = document.getElementById("count-fps")), 338 | (vb = document.getElementById("span-fps")); 339 | }, 340 | sendSdpInfo: function (a, b, c) { 341 | var d = { 342 | type: "sdpInfo", 343 | data: { 344 | sdpInfo: a, 345 | aacCodecInfo: b, 346 | decodeMode: O, 347 | govLength: L, 348 | checkDelay: P, 349 | }, 350 | }; 351 | if (((M = c), l.postMessage(d), M)) 352 | try { 353 | (window.AudioContext = 354 | window.AudioContext || 355 | window.webkitAudioContext || 356 | window.mozAudioContext || 357 | window.oAudioContext || 358 | window.msAudioContext), 359 | (n = new Worker("./media/ump/Workers/audioTalkWorker.js")), 360 | (n.onmessage = f), 361 | null === r && 362 | ((r = new Talk()), r.init(), r.setSendAudioTalkBufferCallback(g)); 363 | var e = r.initAudioOut(); 364 | n.postMessage(d), 365 | (d = { 366 | type: "sampleRate", 367 | data: e, 368 | }), 369 | n.postMessage(d); 370 | } catch (h) { 371 | return ( 372 | (M = !1), 373 | void debug.error( 374 | "Web Audio API is not supported in this web browser! : " + h 375 | ) 376 | ); 377 | } 378 | (pb = null), (kb = !1), (J = a); 379 | }, 380 | parseRTPData: function (a, b) { 381 | function c() { 382 | for (var a = b[22] + 24, c = 24; a > c; ) 383 | if (g == b[c]) { 384 | if (c + 4 > a) return console.log("i: " + c), -1; 385 | (M.width = b[c + 2] << 3), (M.height = b[c + 3] << 3), (c += 4); 386 | } else if (h == b[c]) { 387 | if (c + 4 > b.length) return console.log("i: " + c), -1; 388 | (M.I_frame_interval = b[c + 1]), 389 | (M.encode_type = b[c + 2]), 390 | (M.frame_rate = b[c + 3]), 391 | (c += 4); 392 | } else if (i == b[c]) 393 | (M.width = (b[c + 5] << 8) + b[c + 4]), 394 | (M.height = (b[c + 7] << 8) + b[c + 6]), 395 | (c += 8); 396 | else if (j == b[c]) c += 4; 397 | else if (o == b[c]) c += 8; 398 | else if (k == b[c]) { 399 | if (c + 4 > a) return console.log("i: " + c), -1; 400 | var d = (b[c + 2] << 8) + b[c + 3]; 401 | c += d; 402 | } else if (x == b[c]) 403 | (M.h264_svc_flag = !0), (M.svc = b[c + 2]), (c += 4); 404 | else if (q == b[c]) c += 8; 405 | else if (u == b[c]) c += 8; 406 | else if (C == b[c]) { 407 | var e = b[c + 1], 408 | f = b[c + 2]; 409 | (c += 8), (c += e * f * 16); 410 | } else if (E == b[c]) c += 8; 411 | else if (G == b[c]) c += 8; 412 | else if (v == b[c]) c += 8; 413 | else if (w == b[c]) c += 8; 414 | else if (y == b[c]) c += 8; 415 | else if (I <= b[c] && b[c] < J) 416 | (M.timeStampmsw = (b[c + 3] << 8) + b[c + 2]), (c += 4); 417 | else if (J <= b[c] && b[c] < K) c += b[c + 1]; 418 | else if (n == b[c]) c += 4; 419 | else if (p == b[c]) c += 4; 420 | else if (r == b[c]) c += 4; 421 | else if (t == b[c]) c += 8; 422 | else if (A == b[c]) { 423 | var e = b[c + 1]; 424 | (c += 8), (c += 16 * e); 425 | } else if (B == b[c]) c += 4; 426 | else { 427 | if (H != b[c]) 428 | return ( 429 | console.log("parseVideoInfo error ext_type:0x" + b[c]), 430 | console.log("i: " + c), 431 | -1 432 | ); 433 | var a = (b[c + 5] << 8) + b[c + 4]; 434 | (c += 8), (c += a); 435 | } 436 | } 437 | function d() { 438 | M.ChannelCount = 0; 439 | for (var a = b[22] + 24, c = 24; a > c; ) 440 | if (g == b[c]) c += 4; 441 | else if (h == b[c]) c += 4; 442 | else if (i == b[c]) c += 8; 443 | else if (j == b[c]) c += 4; 444 | else if (s == b[c]) c += b[c + 1]; 445 | else if (o == b[c]) c += 8; 446 | else if (k == b[c]) { 447 | var d = b[c + 2] << (8 + b[c + 3]); 448 | c += d; 449 | } else if (z == b[c]) 450 | (M.ChannelCount = b[c + 1]), (M.channel = b[c + 2]), (c += 4); 451 | else if (y == b[c]) c += 8; 452 | else { 453 | if (I != b[c]) 454 | return ( 455 | console.log("parseAudioInfo error ext_type:0x" + b[c]), 456 | console.log("i: " + c), 457 | -1 458 | ); 459 | (M.timeStampmsw = (b[c + 3] << 8) + b[c + 2]), (c += 4); 460 | } 461 | 0 == M.ChannelCount && ((M.ChannelCount = 1), (M.channel = 0)); 462 | for (var a = b[22] + 24, c = 24; a > c; ) 463 | if (b[c] == g) c += 4; 464 | else if (b[c] == h) c += 4; 465 | else if (b[c] == i) c += 8; 466 | else if (b[c] == j) 467 | (M.audio_type = b[c + 2]), 468 | (M.samplingRate = Fb[b[c + 3]]), 469 | (c += 4); 470 | else if (b[c] == s) c += b[c + 1]; 471 | else if (b[c] == o) c += 8; 472 | else if (b[c] == k) { 473 | var d = b[c + 2] << (8 + b[c + 3]); 474 | c += d; 475 | } else if (b[c] == z) c += 4; 476 | else if (b[c] == y) c += 8; 477 | else { 478 | if (I != b[c]) 479 | return ( 480 | console.log("parseAudioInfo error ext_type:0x" + b[c]), 481 | console.log("i: " + c), 482 | -1 483 | ); 484 | c += 4; 485 | } 486 | } 487 | function e() { 488 | for (var a = b[22] + 24, c = 24; a > c; ) 489 | if (I <= b[c] && b[c] < J) 490 | (M.timeStampmsw = (b[c + 3] << 8) + b[c + 2]), (c += 4); 491 | else if (k == b[c]) { 492 | if (c + 4 > a) return console.log("i: " + c), -1; 493 | console.log("智能扩展"); 494 | var d = (b[c + 2] << 8) + b[c + 3]; 495 | c += d; 496 | } else c++; 497 | } 498 | var f = b[4], 499 | g = 128, 500 | h = 129, 501 | i = 130, 502 | j = 131, 503 | k = 132, 504 | n = 133, 505 | o = 136, 506 | p = 137, 507 | q = 138, 508 | r = 139, 509 | s = 140, 510 | t = 144, 511 | u = 145, 512 | v = 146, 513 | w = 147, 514 | x = 148, 515 | y = 149, 516 | z = 150, 517 | A = 151, 518 | B = 152, 519 | C = 153, 520 | E = 154, 521 | G = 155, 522 | H = 156, 523 | I = 160, 524 | J = 176, 525 | K = 255, 526 | L = { 527 | type: "MediaData", 528 | data: { 529 | rtspInterleave: a, 530 | payload: b, 531 | }, 532 | info: null, 533 | }, 534 | M = {}; 535 | if (253 == f || 254 == f || 252 == f || 251 == f) { 536 | if ((c(), null != Bb)) { 537 | if (Bb != M.encode_type) 538 | return (Bb = M.encode_type), void D(Eb[M.encode_type]); 539 | } else Bb = M.encode_type; 540 | switch (M.encode_type + "") { 541 | case "5": 542 | case "8": 543 | case "12": 544 | l && ((L.info = M), l.postMessage(L)); 545 | break; 546 | default: 547 | console.log("encode_type: " + encode_type); 548 | } 549 | } else if (240 == f) { 550 | if ((d(), null != Db)) { 551 | if (Db != M.audio_type) 552 | return (Db = M.audio_type), void F("audioType"); 553 | } else Db = M.audio_type; 554 | if (null != Cb) { 555 | if (Cb != M.samplingRate) 556 | return (Cb = M.samplingRate), void F("samplingRate"); 557 | } else Cb = M.samplingRate; 558 | switch (M.audio_type + "") { 559 | case "10": 560 | case "14": 561 | case "26": 562 | case "27": 563 | case "28": 564 | case "29": 565 | case "30": 566 | audioWorker && ((L.info = M), audioWorker.postMessage(L)); 567 | } 568 | } else 569 | 241 == f 570 | ? (e(), l && ((L.info = M), l.postMessage(L))) 571 | : console.log("mediaType: " + f); 572 | }, 573 | setCallback: function (a, b) { 574 | switch (a) { 575 | case "timeStamp": 576 | u = b; 577 | break; 578 | case "ResolutionChanged": 579 | (s = b), null !== p && p.setResizeCallback(s); 580 | break; 581 | case "audioTalk": 582 | v = b; 583 | break; 584 | case "stepRequest": 585 | w = b; 586 | break; 587 | case "metaEvent": 588 | x = b; 589 | break; 590 | case "videoMode": 591 | y = b; 592 | break; 593 | case "loadingBar": 594 | z = b; 595 | break; 596 | case "Error": 597 | A = b; 598 | break; 599 | case "PlayStart": 600 | (t = b), null !== p && p.setBeginDrawCallback(t); 601 | break; 602 | case "DecodeStart": 603 | B = b; 604 | break; 605 | case "UpdateCanvas": 606 | (C = b), null !== p && p.setupdateCanvasCallback(C); 607 | break; 608 | case "FrameTypeChange": 609 | D = b; 610 | break; 611 | case "MSEResolutionChanged": 612 | E = b; 613 | break; 614 | case "audioChange": 615 | F = b; 616 | break; 617 | case "ivs": 618 | G = b; 619 | break; 620 | case "WorkerReady": 621 | xb = b; 622 | break; 623 | default: 624 | console.log(a), 625 | console.log("workerManager::setCallback() : type is unknown"); 626 | } 627 | }, 628 | capture: function (a) { 629 | "canvas" === O ? p.capture(a) : V.capture(a); 630 | }, 631 | setDeviceInfo: function (a) { 632 | T = a.mode; 633 | }, 634 | setFPS: function (a) { 635 | var b = 30; 636 | (K = 0 === a ? b : a), h(1 !== hb); 637 | }, 638 | setGovLength: function (a) { 639 | L = a; 640 | }, 641 | setLiveMode: function (a) { 642 | null !== y && y(a), 643 | (O = null === a ? "canvas" : a), 644 | "video" === O ? null !== p && p.renewCanvas() : "canvas" === O && h(!1); 645 | }, 646 | controlAudio: function (a, b) { 647 | switch ((console.log(a + " " + b), a)) { 648 | case "audioPlay": 649 | "start" === b 650 | ? null !== q && q.play() 651 | : ((qb = 0), null !== q && q.stop()); 652 | break; 653 | case "volumn": 654 | (qb = b), null !== q && q.controlVolumn(b); 655 | break; 656 | case "audioSamplingRate": 657 | null !== q && q.setSamplingRate(b); 658 | } 659 | }, 660 | controlAudioTalk: function (a, b) { 661 | if (null !== r) 662 | switch (a) { 663 | case "onOff": 664 | "on" === b || r.stopAudioOut(); 665 | break; 666 | case "volumn": 667 | r.controlVolumnOut(b); 668 | } 669 | }, 670 | reassignCanvas: function () { 671 | null !== p && p.reassignCanvas(); 672 | }, 673 | digitalZoom: function (a) { 674 | null !== p && p.digitalZoom(a); 675 | }, 676 | playbackSpeed: function (a) { 677 | (hb = a), p.setFrameInterval(hb); 678 | }, 679 | timeStamp: function () {}, 680 | initVideo: function (a) { 681 | h(a); 682 | }, 683 | setFpsFrame: function (a) { 684 | (ub = a), (tb = 0), (sb = 0); 685 | }, 686 | setCheckDelay: function (a) { 687 | P = a; 688 | }, 689 | initStartTime: function () { 690 | var a = { 691 | type: "initStartTime", 692 | }; 693 | l.postMessage(a), p.stopRendering(), p.startRendering(); 694 | }, 695 | terminate: function () { 696 | "backup" !== T && 697 | (l && (l.terminate(), (l = null)), 698 | audioWorker && (audioWorker.terminate(), (audioWorker = null))), 699 | n && n.terminate(), 700 | r && (r.terminate(), (r = null)), 701 | p && p.terminate(), 702 | q && q.terminate(), 703 | V && V.terminate(), 704 | xb && (xb = null), 705 | (p = null), 706 | (N = !0); 707 | }, 708 | }; 709 | return new workManagerA(); 710 | }; 711 | 712 | export default WorkerManager; 713 | -------------------------------------------------------------------------------- /src/browserDetect.js: -------------------------------------------------------------------------------- 1 | function BrowserDetect() { 2 | var a = navigator.userAgent.toLowerCase(), 3 | b = navigator.appName, 4 | c = null; 5 | return ( 6 | "Microsoft Internet Explorer" === b || 7 | a.indexOf("trident") > -1 || 8 | a.indexOf("edge/") > -1 9 | ? ((c = "ie"), 10 | "Microsoft Internet Explorer" === b 11 | ? ((a = /msie ([0-9]{1,}[\.0-9]{0,})/.exec(a)), (c += parseInt(a[1]))) 12 | : a.indexOf("trident") > -1 13 | ? (c += 11) 14 | : a.indexOf("edge/") > -1 && (c = "edge")) 15 | : a.indexOf("safari") > -1 16 | ? (c = a.indexOf("chrome") > -1 ? "chrome" : "safari") 17 | : a.indexOf("firefox") > -1 && (c = "firefox"), 18 | c 19 | ); 20 | } 21 | 22 | var isDebug = !1, 23 | debug = (function (a) { 24 | return a 25 | ? { 26 | log: function (a) { 27 | console.log(a); 28 | }, 29 | error: function (a) { 30 | console.error(a); 31 | }, 32 | count: function (a) { 33 | console.count(a); 34 | }, 35 | info: function (a) { 36 | console.info(a); 37 | }, 38 | trace: function (a) { 39 | console.trace(a); 40 | }, 41 | } 42 | : { 43 | log: function () {}, 44 | error: function () {}, 45 | count: function () {}, 46 | info: function () {}, 47 | }; 48 | })(isDebug), 49 | Script = (function () { 50 | function a() {} 51 | return ( 52 | (a.createFromElementId = function (b) { 53 | for (var c = document.getElementById(b), d = "", e = c.firstChild; e; ) 54 | 3 === e.nodeType && (d += e.textContent), (e = e.nextSibling); 55 | var f = new a(); 56 | return (f.type = c.type), (f.source = d), f; 57 | }), 58 | (a.createFromSource = function (b, c) { 59 | var d = new a(); 60 | return (d.type = b), (d.source = c), d; 61 | }), 62 | a 63 | ); 64 | })(), 65 | Shader = (function () { 66 | function a(a, b) { 67 | if ("x-shader/x-fragment" === b.type) 68 | this.shader = a.createShader(a.FRAGMENT_SHADER); 69 | else { 70 | if ("x-shader/x-vertex" !== b.type) 71 | return void error("Unknown shader type: " + b.type); 72 | this.shader = a.createShader(a.VERTEX_SHADER); 73 | } 74 | return ( 75 | a.shaderSource(this.shader, b.source), 76 | a.compileShader(this.shader), 77 | a.getShaderParameter(this.shader, a.COMPILE_STATUS) 78 | ? void 0 79 | : void error( 80 | "An error occurred compiling the shaders: " + 81 | a.getShaderInfoLog(this.shader) 82 | ) 83 | ); 84 | } 85 | return a; 86 | })(), 87 | Program = (function () { 88 | function a(a) { 89 | (this.gl = a), (this.program = this.gl.createProgram()); 90 | } 91 | return ( 92 | (a.prototype = { 93 | attach: function (a) { 94 | this.gl.attachShader(this.program, a.shader); 95 | }, 96 | link: function () { 97 | this.gl.linkProgram(this.program); 98 | }, 99 | use: function () { 100 | this.gl.useProgram(this.program); 101 | }, 102 | getAttributeLocation: function (a) { 103 | return this.gl.getAttribLocation(this.program, a); 104 | }, 105 | setMatrixUniform: function (a, b) { 106 | var c = this.gl.getUniformLocation(this.program, a); 107 | this.gl.uniformMatrix4fv(c, !1, b); 108 | }, 109 | }), 110 | a 111 | ); 112 | })(), 113 | Texture = (function () { 114 | function a(a, b, c) { 115 | (this.gl = a), 116 | (this.size = b), 117 | (this.texture = a.createTexture()), 118 | a.bindTexture(a.TEXTURE_2D, this.texture), 119 | (this.format = c ? c : a.LUMINANCE), 120 | a.texImage2D( 121 | a.TEXTURE_2D, 122 | 0, 123 | this.format, 124 | b.w, 125 | b.h, 126 | 0, 127 | this.format, 128 | a.UNSIGNED_BYTE, 129 | null 130 | ), 131 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_MAG_FILTER, a.NEAREST), 132 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_MIN_FILTER, a.NEAREST), 133 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_WRAP_S, a.CLAMP_TO_EDGE), 134 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_WRAP_T, a.CLAMP_TO_EDGE); 135 | } 136 | var b = null; 137 | return ( 138 | (a.prototype = { 139 | fill: function (a, b) { 140 | var c = this.gl; 141 | c.bindTexture(c.TEXTURE_2D, this.texture), 142 | b 143 | ? c.texSubImage2D( 144 | c.TEXTURE_2D, 145 | 0, 146 | 0, 147 | 0, 148 | this.size.w, 149 | this.size.h, 150 | this.format, 151 | c.UNSIGNED_BYTE, 152 | a 153 | ) 154 | : c.texImage2D( 155 | c.TEXTURE_2D, 156 | 0, 157 | this.format, 158 | this.size.w, 159 | this.size.h, 160 | 0, 161 | this.format, 162 | c.UNSIGNED_BYTE, 163 | a 164 | ); 165 | }, 166 | bind: function (a, c, d) { 167 | var e = this.gl; 168 | b || (b = [e.TEXTURE0, e.TEXTURE1, e.TEXTURE2]), 169 | e.activeTexture(b[a]), 170 | e.bindTexture(e.TEXTURE_2D, this.texture), 171 | e.uniform1i(e.getUniformLocation(c.program, d), a); 172 | }, 173 | }), 174 | a 175 | ); 176 | })(), 177 | base64ArrayBuffer = function (a) { 178 | for ( 179 | var b = "", 180 | c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 181 | d = new Uint8Array(a), 182 | e = d.byteLength, 183 | f = e % 3, 184 | g = e - f, 185 | h = 0, 186 | i = 0, 187 | j = 0, 188 | k = 0, 189 | l = 0, 190 | m = 0; 191 | g > m; 192 | m += 3 193 | ) 194 | (l = (d[m] << 16) | (d[m + 1] << 8) | d[m + 2]), 195 | (h = (16515072 & l) >> 18), 196 | (i = (258048 & l) >> 12), 197 | (j = (4032 & l) >> 6), 198 | (k = 63 & l), 199 | (b += c[h] + c[i] + c[j] + c[k]); 200 | return ( 201 | 1 === f 202 | ? ((l = d[g]), 203 | (h = (252 & l) >> 2), 204 | (i = (3 & l) << 4), 205 | (b += c[h] + c[i] + "==")) 206 | : 2 === f && 207 | ((l = (d[g] << 8) | d[g + 1]), 208 | (h = (64512 & l) >> 10), 209 | (i = (1008 & l) >> 4), 210 | (j = (15 & l) << 2), 211 | (b += c[h] + c[i] + c[j] + "=")), 212 | b 213 | ); 214 | }; 215 | 216 | export { BrowserDetect, Texture, Shader, Script, Program, base64ArrayBuffer }; 217 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Dahua - RTSP over Websocket 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import WebsocketServer from "./WebSocketServer.js"; 2 | 3 | let PlayerControl = function (a) { 4 | this.wsURL = a.wsURL; 5 | this.rtspURL = a.rtspURL; 6 | this.decodeMode = "video"; 7 | this.ws = null; 8 | this.supportStoreEncrypt = a.supportStoreEncrypt || !1; 9 | this.events = { 10 | ResolutionChanged: function () {}, 11 | PlayStart: function () {}, 12 | DecodeStart: function () {}, 13 | UpdateCanvas: function () {}, 14 | GetFrameRate: function () {}, 15 | FrameTypeChange: function () {}, 16 | Error: function () {}, 17 | MSEResolutionChanged: function () {}, 18 | audioChange: function () {}, 19 | WorkerReady: function () {}, 20 | }; 21 | this.username = a.username; 22 | this.password = a.password; 23 | }; 24 | PlayerControl.prototype = { 25 | init: function (a, b) { 26 | this.ws = new WebsocketServer(this.wsURL, this.rtspURL); 27 | this.ws.setStoreEncrypt(this.supportStoreEncrypt); 28 | this.ws.init(a, b); 29 | this.ws.setLiveMode(this.decodeMode); 30 | this.ws.setUserInfo(this.username, this.password); 31 | for (var c in this.events) this.ws.setCallback(c, this.events[c]); 32 | this.events = null; 33 | }, 34 | connect: function () { 35 | this.ws.connect(); 36 | }, 37 | play: function () { 38 | this.controlPlayer("PLAY"); 39 | }, 40 | pause: function () { 41 | this.controlPlayer("PAUSE"); 42 | }, 43 | stop: function () { 44 | this.controlPlayer("TEARDOWN"); 45 | }, 46 | close: function () { 47 | this.ws.disconnect(); 48 | }, 49 | playByTime: function (a) { 50 | this.controlPlayer("PLAY", "video", a); 51 | }, 52 | playFF: function (a) { 53 | this.controlPlayer("PAUSE"); 54 | this.controlPlayer("SCALE", a); 55 | }, 56 | playRewind: function () {}, 57 | audioPlay: function () { 58 | this.controlPlayer("audioPlay", "start"); 59 | }, 60 | audioStop: function () { 61 | this.controlPlayer("audioPlay", "stop"); 62 | }, 63 | setAudioSamplingRate: function (a) { 64 | this.controlPlayer("audioSamplingRate", a); 65 | }, 66 | setAudioVolume: function (a) { 67 | this.controlPlayer("volumn", a); 68 | }, 69 | controlPlayer: function (a, b, c) { 70 | var d; 71 | d = 72 | "video" === b 73 | ? { 74 | command: a, 75 | range: c ? c : 0, 76 | } 77 | : { 78 | command: a, 79 | data: b, 80 | }; 81 | this.ws.controlPlayer(d); 82 | }, 83 | setPlayMode: function (a) { 84 | this.ws.setLiveMode(a); 85 | }, 86 | setPlayPath: function (a) { 87 | this.ws.setRTSPURL(a); 88 | }, 89 | capture: function (a) { 90 | this.ws.capture(a); 91 | }, 92 | on: function (a, b) { 93 | this.events[a] = b; 94 | }, 95 | }; 96 | 97 | export default PlayerControl; 98 | -------------------------------------------------------------------------------- /src/module/Decode/MjpegDecoder.js: -------------------------------------------------------------------------------- 1 | function MJPEGDecoder(){function a(){console.log("MJPEG Decoder")}var b,c;return a.prototype={setIsFirstFrame:function(a){isFirstIFrame=a},isFirstFrame:function(){return isFirstIFrame},setResolution:function(a,d){b=a,c=d},decode:function(d){if(!a.prototype.isFirstFrame()){a.prototype.setIsFirstFrame(!0);var e={firstFrame:!0};return e}return{data:d,width:b,height:c,codecType:"mjpeg"}}},new a} -------------------------------------------------------------------------------- /src/module/Decode/h264Decoder.js: -------------------------------------------------------------------------------- 1 | "use strict";function H264Decoder(){function a(){console.log("Construct H264 Codec"),b=Module.cwrap("init_jsFFmpeg","void",[]),c=Module.cwrap("context_jsFFmpeg","number",["number"]),d=Module.cwrap("decode_video_jsFFmpeg","number",["number","array","number","number"]),e=Module.cwrap("get_width","number",["number"]),f=Module.cwrap("get_height","number",["number"]),g=Module.cwrap("close_jsFFmpeg","number",["number"]),b(),a.prototype.init(),a.prototype.setIsFirstFrame(!1)}var b=null,c=null,d=null,e=null,f=null,g=null,h=null,i=null,j=264,k=!1;return a.prototype={init:function(){console.log("H264 Decoder init"),null!==h&&(g(h),h=null),h=c(j)},setOutputSize:function(a){var b=1.5*a,c=Module._malloc(b);i=new Uint8Array(Module.HEAPU8.buffer,c,b)},decode:function(b){var c=null,g=null,j=null,k=null,l=103==b[4]?"I":"P";c=Date.now(),d(h,b,b.length,i.byteOffset),g=Date.now()-c;var m=e(h),n=f(h);if(!a.prototype.isFirstFrame())return a.prototype.setIsFirstFrame(!0),j={firstFrame:!0};if(m>0&&n>0){var o=new Uint8Array(i);return j={data:o,bufferIdx:k,width:m,height:n,codecType:"h264",decodingTime:g,frameType:l}}},setIsFirstFrame:function(a){k=a},isFirstFrame:function(){return k}},new a} -------------------------------------------------------------------------------- /src/module/Decode/h265Decoder.js: -------------------------------------------------------------------------------- 1 | "use strict";function H265Decoder(){function a(){console.log("Construct H265 Codec"),b=Module.cwrap("init_jsFFmpeg","void",[]),c=Module.cwrap("context_jsFFmpeg","number",["number"]),d=Module.cwrap("decode_video_jsFFmpeg","number",["number","array","number","number"]),e=Module.cwrap("get_width","number",["number"]),f=Module.cwrap("get_height","number",["number"]),g=Module.cwrap("close_jsFFmpeg","number",["number"]),b(),a.prototype.init(),a.prototype.setIsFirstFrame(!1)}var b=null,c=null,d=null,e=null,f=null,g=null,h=null,i=new Uint8Array,j=265,k=!1;return a.prototype={init:function(){console.log("H265 Decoder init"),g(h),h=c(j)},setOutputSize:function(a){var b=1.5*a,c=Module._malloc(b);i=new Uint8Array(Module.HEAPU8.buffer,c,b)},decode:function(b,c){var g=null,j=null,k=null,l=c;g=Date.now(),d(h,b,b.length,i.byteOffset),j=Date.now()-g;var m=e(h),n=f(h);if(!a.prototype.isFirstFrame())return a.prototype.setIsFirstFrame(!0),{firstFrame:!0};if(m>0&&n>0){var o=new Uint8Array(i);return k={data:o,width:m,height:n,codecType:"h265",decodingTime:j,frameType:l}}},setIsFirstFrame:function(a){k=a},isFirstFrame:function(){return k}},new a} -------------------------------------------------------------------------------- /src/module/Sylvester.js: -------------------------------------------------------------------------------- 1 | function Vector() {} 2 | function Matrix() {} 3 | function Line() {} 4 | function Plane() {} 5 | var Sylvester = { 6 | version: "0.1.3", 7 | precision: 1e-6 8 | }; 9 | Vector.prototype = { 10 | e: function(a) { 11 | return 1 > a || a > this.elements.length ? null : this.elements[a - 1] 12 | }, 13 | dimensions: function() { 14 | return this.elements.length 15 | }, 16 | modulus: function() { 17 | return Math.sqrt(this.dot(this)) 18 | }, 19 | eql: function(a) { 20 | var b = this.elements.length 21 | , c = a.elements || a; 22 | if (b != c.length) 23 | return !1; 24 | do 25 | if (Math.abs(this.elements[b - 1] - c[b - 1]) > Sylvester.precision) 26 | return !1; 27 | while (--b); 28 | return !0 29 | }, 30 | dup: function() { 31 | return Vector.create(this.elements) 32 | }, 33 | map: function(a) { 34 | var b = []; 35 | return this.each(function(c, d) { 36 | b.push(a(c, d)) 37 | }), 38 | Vector.create(b) 39 | }, 40 | each: function(a) { 41 | var b, c = this.elements.length, d = c; 42 | do 43 | b = d - c, 44 | a(this.elements[b], b + 1); 45 | while (--c) 46 | }, 47 | toUnitVector: function() { 48 | var a = this.modulus(); 49 | return 0 === a ? this.dup() : this.map(function(b) { 50 | return b / a 51 | }) 52 | }, 53 | angleFrom: function(a) { 54 | var b = a.elements || a 55 | , c = this.elements.length; 56 | if (c != b.length) 57 | return null; 58 | var d = 0 59 | , e = 0 60 | , f = 0; 61 | if (this.each(function(a, c) { 62 | d += a * b[c - 1], 63 | e += a * a, 64 | f += b[c - 1] * b[c - 1] 65 | }), 66 | e = Math.sqrt(e), 67 | f = Math.sqrt(f), 68 | e * f === 0) 69 | return null; 70 | var g = d / (e * f); 71 | return -1 > g && (g = -1), 72 | g > 1 && (g = 1), 73 | Math.acos(g) 74 | }, 75 | isParallelTo: function(a) { 76 | var b = this.angleFrom(a); 77 | return null === b ? null : b <= Sylvester.precision 78 | }, 79 | isAntiparallelTo: function(a) { 80 | var b = this.angleFrom(a); 81 | return null === b ? null : Math.abs(b - Math.PI) <= Sylvester.precision 82 | }, 83 | isPerpendicularTo: function(a) { 84 | var b = this.dot(a); 85 | return null === b ? null : Math.abs(b) <= Sylvester.precision 86 | }, 87 | add: function(a) { 88 | var b = a.elements || a; 89 | return this.elements.length != b.length ? null : this.map(function(a, c) { 90 | return a + b[c - 1] 91 | }) 92 | }, 93 | subtract: function(a) { 94 | var b = a.elements || a; 95 | return this.elements.length != b.length ? null : this.map(function(a, c) { 96 | return a - b[c - 1] 97 | }) 98 | }, 99 | multiply: function(a) { 100 | return this.map(function(b) { 101 | return b * a 102 | }) 103 | }, 104 | x: function(a) { 105 | return this.multiply(a) 106 | }, 107 | dot: function(a) { 108 | var b = a.elements || a 109 | , c = 0 110 | , d = this.elements.length; 111 | if (d != b.length) 112 | return null; 113 | do 114 | c += this.elements[d - 1] * b[d - 1]; 115 | while (--d); 116 | return c 117 | }, 118 | cross: function(a) { 119 | var b = a.elements || a; 120 | if (3 != this.elements.length || 3 != b.length) 121 | return null; 122 | var c = this.elements; 123 | return Vector.create([c[1] * b[2] - c[2] * b[1], c[2] * b[0] - c[0] * b[2], c[0] * b[1] - c[1] * b[0]]) 124 | }, 125 | max: function() { 126 | var a, b = 0, c = this.elements.length, d = c; 127 | do 128 | a = d - c, 129 | Math.abs(this.elements[a]) > Math.abs(b) && (b = this.elements[a]); 130 | while (--c); 131 | return b 132 | }, 133 | indexOf: function(a) { 134 | var b, c = null, d = this.elements.length, e = d; 135 | do 136 | b = e - d, 137 | null === c && this.elements[b] == a && (c = b + 1); 138 | while (--d); 139 | return c 140 | }, 141 | toDiagonalMatrix: function() { 142 | return Matrix.Diagonal(this.elements) 143 | }, 144 | round: function() { 145 | return this.map(function(a) { 146 | return Math.round(a) 147 | }) 148 | }, 149 | snapTo: function(a) { 150 | return this.map(function(b) { 151 | return Math.abs(b - a) <= Sylvester.precision ? a : b 152 | }) 153 | }, 154 | distanceFrom: function(a) { 155 | if (a.anchor) 156 | return a.distanceFrom(this); 157 | var b = a.elements || a; 158 | if (b.length != this.elements.length) 159 | return null; 160 | var c, d = 0; 161 | return this.each(function(a, e) { 162 | c = a - b[e - 1], 163 | d += c * c 164 | }), 165 | Math.sqrt(d) 166 | }, 167 | liesOn: function(a) { 168 | return a.contains(this) 169 | }, 170 | liesIn: function(a) { 171 | return a.contains(this) 172 | }, 173 | rotate: function(a, b) { 174 | var c, d, e, f, g; 175 | switch (this.elements.length) { 176 | case 2: 177 | return c = b.elements || b, 178 | 2 != c.length ? null : (d = Matrix.Rotation(a).elements, 179 | e = this.elements[0] - c[0], 180 | f = this.elements[1] - c[1], 181 | Vector.create([c[0] + d[0][0] * e + d[0][1] * f, c[1] + d[1][0] * e + d[1][1] * f])); 182 | case 3: 183 | if (!b.direction) 184 | return null; 185 | var h = b.pointClosestTo(this).elements; 186 | return d = Matrix.Rotation(a, b.direction).elements, 187 | e = this.elements[0] - h[0], 188 | f = this.elements[1] - h[1], 189 | g = this.elements[2] - h[2], 190 | Vector.create([h[0] + d[0][0] * e + d[0][1] * f + d[0][2] * g, h[1] + d[1][0] * e + d[1][1] * f + d[1][2] * g, h[2] + d[2][0] * e + d[2][1] * f + d[2][2] * g]); 191 | default: 192 | return null 193 | } 194 | }, 195 | reflectionIn: function(a) { 196 | if (a.anchor) { 197 | var b = this.elements.slice() 198 | , c = a.pointClosestTo(b).elements; 199 | return Vector.create([c[0] + (c[0] - b[0]), c[1] + (c[1] - b[1]), c[2] + (c[2] - (b[2] || 0))]) 200 | } 201 | var d = a.elements || a; 202 | return this.elements.length != d.length ? null : this.map(function(a, b) { 203 | return d[b - 1] + (d[b - 1] - a) 204 | }) 205 | }, 206 | to3D: function() { 207 | var a = this.dup(); 208 | switch (a.elements.length) { 209 | case 3: 210 | break; 211 | case 2: 212 | a.elements.push(0); 213 | break; 214 | default: 215 | return null 216 | } 217 | return a 218 | }, 219 | inspect: function() { 220 | return "[" + this.elements.join(", ") + "]" 221 | }, 222 | setElements: function(a) { 223 | return this.elements = (a.elements || a).slice(), 224 | this 225 | } 226 | }, 227 | Vector.create = function(a) { 228 | var b = new Vector; 229 | return b.setElements(a) 230 | } 231 | , 232 | Vector.i = Vector.create([1, 0, 0]), 233 | Vector.j = Vector.create([0, 1, 0]), 234 | Vector.k = Vector.create([0, 0, 1]), 235 | Vector.Random = function(a) { 236 | var b = []; 237 | do 238 | b.push(Math.random()); 239 | while (--a); 240 | return Vector.create(b) 241 | } 242 | , 243 | Vector.Zero = function(a) { 244 | var b = []; 245 | do 246 | b.push(0); 247 | while (--a); 248 | return Vector.create(b) 249 | } 250 | , 251 | Matrix.prototype = { 252 | e: function(a, b) { 253 | return 1 > a || a > this.elements.length || 1 > b || b > this.elements[0].length ? null : this.elements[a - 1][b - 1] 254 | }, 255 | row: function(a) { 256 | return a > this.elements.length ? null : Vector.create(this.elements[a - 1]) 257 | }, 258 | col: function(a) { 259 | if (a > this.elements[0].length) 260 | return null; 261 | var b, c = [], d = this.elements.length, e = d; 262 | do 263 | b = e - d, 264 | c.push(this.elements[b][a - 1]); 265 | while (--d); 266 | return Vector.create(c) 267 | }, 268 | dimensions: function() { 269 | return { 270 | rows: this.elements.length, 271 | cols: this.elements[0].length 272 | } 273 | }, 274 | rows: function() { 275 | return this.elements.length 276 | }, 277 | cols: function() { 278 | return this.elements[0].length 279 | }, 280 | eql: function(a) { 281 | var b = a.elements || a; 282 | if ("undefined" == typeof b[0][0] && (b = Matrix.create(b).elements), 283 | this.elements.length != b.length || this.elements[0].length != b[0].length) 284 | return !1; 285 | var c, d, e, f = this.elements.length, g = f, h = this.elements[0].length; 286 | do { 287 | c = g - f, 288 | d = h; 289 | do 290 | if (e = h - d, 291 | Math.abs(this.elements[c][e] - b[c][e]) > Sylvester.precision) 292 | return !1; 293 | while (--d) 294 | } while (--f); 295 | return !0 296 | }, 297 | dup: function() { 298 | return Matrix.create(this.elements) 299 | }, 300 | map: function(a) { 301 | var b, c, d, e = [], f = this.elements.length, g = f, h = this.elements[0].length; 302 | do { 303 | b = g - f, 304 | c = h, 305 | e[b] = []; 306 | do 307 | d = h - c, 308 | e[b][d] = a(this.elements[b][d], b + 1, d + 1); 309 | while (--c) 310 | } while (--f); 311 | return Matrix.create(e) 312 | }, 313 | isSameSizeAs: function(a) { 314 | var b = a.elements || a; 315 | return "undefined" == typeof b[0][0] && (b = Matrix.create(b).elements), 316 | this.elements.length == b.length && this.elements[0].length == b[0].length 317 | }, 318 | add: function(a) { 319 | var b = a.elements || a; 320 | return "undefined" == typeof b[0][0] && (b = Matrix.create(b).elements), 321 | this.isSameSizeAs(b) ? this.map(function(a, c, d) { 322 | return a + b[c - 1][d - 1] 323 | }) : null 324 | }, 325 | subtract: function(a) { 326 | var b = a.elements || a; 327 | return "undefined" == typeof b[0][0] && (b = Matrix.create(b).elements), 328 | this.isSameSizeAs(b) ? this.map(function(a, c, d) { 329 | return a - b[c - 1][d - 1] 330 | }) : null 331 | }, 332 | canMultiplyFromLeft: function(a) { 333 | var b = a.elements || a; 334 | return "undefined" == typeof b[0][0] && (b = Matrix.create(b).elements), 335 | this.elements[0].length == b.length 336 | }, 337 | multiply: function(a) { 338 | if (!a.elements) 339 | return this.map(function(b) { 340 | return b * a 341 | }); 342 | var b = a.modulus ? !0 : !1 343 | , c = a.elements || a; 344 | if ("undefined" == typeof c[0][0] && (c = Matrix.create(c).elements), 345 | !this.canMultiplyFromLeft(c)) 346 | return null; 347 | var d, e, f, g, h, i, j = this.elements.length, k = j, l = c[0].length, m = this.elements[0].length, n = []; 348 | do { 349 | d = k - j, 350 | n[d] = [], 351 | e = l; 352 | do { 353 | f = l - e, 354 | g = 0, 355 | h = m; 356 | do 357 | i = m - h, 358 | g += this.elements[d][i] * c[i][f]; 359 | while (--h); 360 | n[d][f] = g 361 | } while (--e) 362 | } while (--j); 363 | var c = Matrix.create(n); 364 | return b ? c.col(1) : c 365 | }, 366 | x: function(a) { 367 | return this.multiply(a) 368 | }, 369 | minor: function(a, b, c, d) { 370 | var e, f, g, h = [], i = c, j = this.elements.length, k = this.elements[0].length; 371 | do { 372 | e = c - i, 373 | h[e] = [], 374 | f = d; 375 | do 376 | g = d - f, 377 | h[e][g] = this.elements[(a + e - 1) % j][(b + g - 1) % k]; 378 | while (--f) 379 | } while (--i); 380 | return Matrix.create(h) 381 | }, 382 | transpose: function() { 383 | var a, b, c, d = this.elements.length, e = this.elements[0].length, f = [], g = e; 384 | do { 385 | a = e - g, 386 | f[a] = [], 387 | b = d; 388 | do 389 | c = d - b, 390 | f[a][c] = this.elements[c][a]; 391 | while (--b) 392 | } while (--g); 393 | return Matrix.create(f) 394 | }, 395 | isSquare: function() { 396 | return this.elements.length == this.elements[0].length 397 | }, 398 | max: function() { 399 | var a, b, c, d = 0, e = this.elements.length, f = e, g = this.elements[0].length; 400 | do { 401 | a = f - e, 402 | b = g; 403 | do 404 | c = g - b, 405 | Math.abs(this.elements[a][c]) > Math.abs(d) && (d = this.elements[a][c]); 406 | while (--b) 407 | } while (--e); 408 | return d 409 | }, 410 | indexOf: function(a) { 411 | var b, c, d, e = this.elements.length, f = e, g = this.elements[0].length; 412 | do { 413 | b = f - e, 414 | c = g; 415 | do 416 | if (d = g - c, 417 | this.elements[b][d] == a) 418 | return { 419 | i: b + 1, 420 | j: d + 1 421 | }; 422 | while (--c) 423 | } while (--e); 424 | return null 425 | }, 426 | diagonal: function() { 427 | if (!this.isSquare) 428 | return null; 429 | var a, b = [], c = this.elements.length, d = c; 430 | do 431 | a = d - c, 432 | b.push(this.elements[a][a]); 433 | while (--c); 434 | return Vector.create(b) 435 | }, 436 | toRightTriangular: function() { 437 | var a, b, c, d, e = this.dup(), f = this.elements.length, g = f, h = this.elements[0].length; 438 | do { 439 | if (b = g - f, 440 | 0 == e.elements[b][b]) 441 | for (j = b + 1; j < g; j++) 442 | if (0 != e.elements[j][b]) { 443 | a = [], 444 | c = h; 445 | do 446 | d = h - c, 447 | a.push(e.elements[b][d] + e.elements[j][d]); 448 | while (--c); 449 | e.elements[b] = a; 450 | break 451 | } 452 | if (0 != e.elements[b][b]) 453 | for (j = b + 1; j < g; j++) { 454 | var i = e.elements[j][b] / e.elements[b][b]; 455 | a = [], 456 | c = h; 457 | do 458 | d = h - c, 459 | a.push(b >= d ? 0 : e.elements[j][d] - e.elements[b][d] * i); 460 | while (--c); 461 | e.elements[j] = a 462 | } 463 | } while (--f); 464 | return e 465 | }, 466 | toUpperTriangular: function() { 467 | return this.toRightTriangular() 468 | }, 469 | determinant: function() { 470 | if (!this.isSquare()) 471 | return null; 472 | var a, b = this.toRightTriangular(), c = b.elements[0][0], d = b.elements.length - 1, e = d; 473 | do 474 | a = e - d + 1, 475 | c *= b.elements[a][a]; 476 | while (--d); 477 | return c 478 | }, 479 | det: function() { 480 | return this.determinant() 481 | }, 482 | isSingular: function() { 483 | return this.isSquare() && 0 === this.determinant() 484 | }, 485 | trace: function() { 486 | if (!this.isSquare()) 487 | return null; 488 | var a, b = this.elements[0][0], c = this.elements.length - 1, d = c; 489 | do 490 | a = d - c + 1, 491 | b += this.elements[a][a]; 492 | while (--c); 493 | return b 494 | }, 495 | tr: function() { 496 | return this.trace() 497 | }, 498 | rank: function() { 499 | var a, b, c, d = this.toRightTriangular(), e = 0, f = this.elements.length, g = f, h = this.elements[0].length; 500 | do { 501 | a = g - f, 502 | b = h; 503 | do 504 | if (c = h - b, 505 | Math.abs(d.elements[a][c]) > Sylvester.precision) { 506 | e++; 507 | break 508 | } 509 | while (--b) 510 | } while (--f); 511 | return e 512 | }, 513 | rk: function() { 514 | return this.rank() 515 | }, 516 | augment: function(a) { 517 | var b = a.elements || a; 518 | "undefined" == typeof b[0][0] && (b = Matrix.create(b).elements); 519 | var c, d, e, f = this.dup(), g = f.elements[0].length, h = f.elements.length, i = h, j = b[0].length; 520 | if (h != b.length) 521 | return null; 522 | do { 523 | c = i - h, 524 | d = j; 525 | do 526 | e = j - d, 527 | f.elements[c][g + e] = b[c][e]; 528 | while (--d) 529 | } while (--h); 530 | return f 531 | }, 532 | inverse: function() { 533 | if (!this.isSquare() || this.isSingular()) 534 | return null; 535 | var a, b, c, d, e, f, g, h = this.elements.length, i = h, j = this.augment(Matrix.I(h)).toRightTriangular(), k = j.elements[0].length, l = []; 536 | do { 537 | a = h - 1, 538 | e = [], 539 | c = k, 540 | l[a] = [], 541 | f = j.elements[a][a]; 542 | do 543 | d = k - c, 544 | g = j.elements[a][d] / f, 545 | e.push(g), 546 | d >= i && l[a].push(g); 547 | while (--c); 548 | for (j.elements[a] = e, 549 | b = 0; a > b; b++) { 550 | e = [], 551 | c = k; 552 | do 553 | d = k - c, 554 | e.push(j.elements[b][d] - j.elements[a][d] * j.elements[b][a]); 555 | while (--c); 556 | j.elements[b] = e 557 | } 558 | } while (--h); 559 | return Matrix.create(l) 560 | }, 561 | inv: function() { 562 | return this.inverse() 563 | }, 564 | round: function() { 565 | return this.map(function(a) { 566 | return Math.round(a) 567 | }) 568 | }, 569 | snapTo: function(a) { 570 | return this.map(function(b) { 571 | return Math.abs(b - a) <= Sylvester.precision ? a : b 572 | }) 573 | }, 574 | inspect: function() { 575 | var a, b = [], c = this.elements.length, d = c; 576 | do 577 | a = d - c, 578 | b.push(Vector.create(this.elements[a]).inspect()); 579 | while (--c); 580 | return b.join("\n") 581 | }, 582 | setElements: function(a) { 583 | var b, c = a.elements || a; 584 | if ("undefined" != typeof c[0][0]) { 585 | var d, e, f, g = c.length, h = g; 586 | this.elements = []; 587 | do { 588 | b = h - g, 589 | d = c[b].length, 590 | e = d, 591 | this.elements[b] = []; 592 | do 593 | f = e - d, 594 | this.elements[b][f] = c[b][f]; 595 | while (--d) 596 | } while (--g); 597 | return this 598 | } 599 | var i = c.length 600 | , j = i; 601 | this.elements = []; 602 | do 603 | b = j - i, 604 | this.elements.push([c[b]]); 605 | while (--i); 606 | return this 607 | } 608 | }, 609 | Matrix.create = function(a) { 610 | var b = new Matrix; 611 | return b.setElements(a) 612 | } 613 | , 614 | Matrix.I = function(a) { 615 | var b, c, d, e = [], f = a; 616 | do { 617 | b = f - a, 618 | e[b] = [], 619 | c = f; 620 | do 621 | d = f - c, 622 | e[b][d] = b == d ? 1 : 0; 623 | while (--c) 624 | } while (--a); 625 | return Matrix.create(e) 626 | } 627 | , 628 | Matrix.Diagonal = function(a) { 629 | var b, c = a.length, d = c, e = Matrix.I(c); 630 | do 631 | b = d - c, 632 | e.elements[b][b] = a[b]; 633 | while (--c); 634 | return e 635 | } 636 | , 637 | Matrix.Rotation = function(a, b) { 638 | if (!b) 639 | return Matrix.create([[Math.cos(a), -Math.sin(a)], [Math.sin(a), Math.cos(a)]]); 640 | var c = b.dup(); 641 | if (3 != c.elements.length) 642 | return null; 643 | var d = c.modulus() 644 | , e = c.elements[0] / d 645 | , f = c.elements[1] / d 646 | , g = c.elements[2] / d 647 | , h = Math.sin(a) 648 | , i = Math.cos(a) 649 | , j = 1 - i; 650 | return Matrix.create([[j * e * e + i, j * e * f - h * g, j * e * g + h * f], [j * e * f + h * g, j * f * f + i, j * f * g - h * e], [j * e * g - h * f, j * f * g + h * e, j * g * g + i]]) 651 | } 652 | , 653 | Matrix.RotationX = function(a) { 654 | var b = Math.cos(a) 655 | , c = Math.sin(a); 656 | return Matrix.create([[1, 0, 0], [0, b, -c], [0, c, b]]) 657 | } 658 | , 659 | Matrix.RotationY = function(a) { 660 | var b = Math.cos(a) 661 | , c = Math.sin(a); 662 | return Matrix.create([[b, 0, c], [0, 1, 0], [-c, 0, b]]) 663 | } 664 | , 665 | Matrix.RotationZ = function(a) { 666 | var b = Math.cos(a) 667 | , c = Math.sin(a); 668 | return Matrix.create([[b, -c, 0], [c, b, 0], [0, 0, 1]]) 669 | } 670 | , 671 | Matrix.Random = function(a, b) { 672 | return Matrix.Zero(a, b).map(function() { 673 | return Math.random() 674 | }) 675 | } 676 | , 677 | Matrix.Zero = function(a, b) { 678 | var c, d, e, f = [], g = a; 679 | do { 680 | c = a - g, 681 | f[c] = [], 682 | d = b; 683 | do 684 | e = b - d, 685 | f[c][e] = 0; 686 | while (--d) 687 | } while (--g); 688 | return Matrix.create(f) 689 | } 690 | , 691 | Line.prototype = { 692 | eql: function(a) { 693 | return this.isParallelTo(a) && this.contains(a.anchor) 694 | }, 695 | dup: function() { 696 | return Line.create(this.anchor, this.direction) 697 | }, 698 | translate: function(a) { 699 | var b = a.elements || a; 700 | return Line.create([this.anchor.elements[0] + b[0], this.anchor.elements[1] + b[1], this.anchor.elements[2] + (b[2] || 0)], this.direction) 701 | }, 702 | isParallelTo: function(a) { 703 | if (a.normal) 704 | return a.isParallelTo(this); 705 | var b = this.direction.angleFrom(a.direction); 706 | return Math.abs(b) <= Sylvester.precision || Math.abs(b - Math.PI) <= Sylvester.precision 707 | }, 708 | distanceFrom: function(a) { 709 | if (a.normal) 710 | return a.distanceFrom(this); 711 | if (a.direction) { 712 | if (this.isParallelTo(a)) 713 | return this.distanceFrom(a.anchor); 714 | var b = this.direction.cross(a.direction).toUnitVector().elements 715 | , c = this.anchor.elements 716 | , d = a.anchor.elements; 717 | return Math.abs((c[0] - d[0]) * b[0] + (c[1] - d[1]) * b[1] + (c[2] - d[2]) * b[2]) 718 | } 719 | var e = a.elements || a 720 | , c = this.anchor.elements 721 | , f = this.direction.elements 722 | , g = e[0] - c[0] 723 | , h = e[1] - c[1] 724 | , i = (e[2] || 0) - c[2] 725 | , j = Math.sqrt(g * g + h * h + i * i); 726 | if (0 === j) 727 | return 0; 728 | var k = (g * f[0] + h * f[1] + i * f[2]) / j 729 | , l = 1 - k * k; 730 | return Math.abs(j * Math.sqrt(0 > l ? 0 : l)) 731 | }, 732 | contains: function(a) { 733 | var b = this.distanceFrom(a); 734 | return null !== b && b <= Sylvester.precision 735 | }, 736 | liesIn: function(a) { 737 | return a.contains(this) 738 | }, 739 | intersects: function(a) { 740 | return a.normal ? a.intersects(this) : !this.isParallelTo(a) && this.distanceFrom(a) <= Sylvester.precision 741 | }, 742 | intersectionWith: function(a) { 743 | if (a.normal) 744 | return a.intersectionWith(this); 745 | if (!this.intersects(a)) 746 | return null; 747 | var b = this.anchor.elements 748 | , c = this.direction.elements 749 | , d = a.anchor.elements 750 | , e = a.direction.elements 751 | , f = c[0] 752 | , g = c[1] 753 | , h = c[2] 754 | , i = e[0] 755 | , j = e[1] 756 | , k = e[2] 757 | , l = b[0] - d[0] 758 | , m = b[1] - d[1] 759 | , n = b[2] - d[2] 760 | , o = -f * l - g * m - h * n 761 | , p = i * l + j * m + k * n 762 | , q = f * f + g * g + h * h 763 | , r = i * i + j * j + k * k 764 | , s = f * i + g * j + h * k 765 | , t = (o * r / q + s * p) / (r - s * s); 766 | return Vector.create([b[0] + t * f, b[1] + t * g, b[2] + t * h]) 767 | }, 768 | pointClosestTo: function(a) { 769 | if (a.direction) { 770 | if (this.intersects(a)) 771 | return this.intersectionWith(a); 772 | if (this.isParallelTo(a)) 773 | return null; 774 | var b = this.direction.elements 775 | , c = a.direction.elements 776 | , d = b[0] 777 | , e = b[1] 778 | , f = b[2] 779 | , g = c[0] 780 | , h = c[1] 781 | , i = c[2] 782 | , j = f * g - d * i 783 | , k = d * h - e * g 784 | , l = e * i - f * h 785 | , m = Vector.create([j * i - k * h, k * g - l * i, l * h - j * g]) 786 | , n = Plane.create(a.anchor, m); 787 | return n.intersectionWith(this) 788 | } 789 | var n = a.elements || a; 790 | if (this.contains(n)) 791 | return Vector.create(n); 792 | var o = this.anchor.elements 793 | , b = this.direction.elements 794 | , d = b[0] 795 | , e = b[1] 796 | , f = b[2] 797 | , p = o[0] 798 | , q = o[1] 799 | , r = o[2] 800 | , j = d * (n[1] - q) - e * (n[0] - p) 801 | , k = e * ((n[2] || 0) - r) - f * (n[1] - q) 802 | , l = f * (n[0] - p) - d * ((n[2] || 0) - r) 803 | , s = Vector.create([e * j - f * l, f * k - d * j, d * l - e * k]) 804 | , t = this.distanceFrom(n) / s.modulus(); 805 | return Vector.create([n[0] + s.elements[0] * t, n[1] + s.elements[1] * t, (n[2] || 0) + s.elements[2] * t]) 806 | }, 807 | rotate: function(a, b) { 808 | "undefined" == typeof b.direction && (b = Line.create(b.to3D(), Vector.k)); 809 | var c = Matrix.Rotation(a, b.direction).elements 810 | , d = b.pointClosestTo(this.anchor).elements 811 | , e = this.anchor.elements 812 | , f = this.direction.elements 813 | , g = d[0] 814 | , h = d[1] 815 | , i = d[2] 816 | , j = e[0] 817 | , k = e[1] 818 | , l = e[2] 819 | , m = j - g 820 | , n = k - h 821 | , o = l - i; 822 | return Line.create([g + c[0][0] * m + c[0][1] * n + c[0][2] * o, h + c[1][0] * m + c[1][1] * n + c[1][2] * o, i + c[2][0] * m + c[2][1] * n + c[2][2] * o], [c[0][0] * f[0] + c[0][1] * f[1] + c[0][2] * f[2], c[1][0] * f[0] + c[1][1] * f[1] + c[1][2] * f[2], c[2][0] * f[0] + c[2][1] * f[1] + c[2][2] * f[2]]) 823 | }, 824 | reflectionIn: function(a) { 825 | if (a.normal) { 826 | var b = this.anchor.elements 827 | , c = this.direction.elements 828 | , d = b[0] 829 | , e = b[1] 830 | , f = b[2] 831 | , g = c[0] 832 | , h = c[1] 833 | , i = c[2] 834 | , j = this.anchor.reflectionIn(a).elements 835 | , k = d + g 836 | , l = e + h 837 | , m = f + i 838 | , n = a.pointClosestTo([k, l, m]).elements 839 | , o = [n[0] + (n[0] - k) - j[0], n[1] + (n[1] - l) - j[1], n[2] + (n[2] - m) - j[2]]; 840 | return Line.create(j, o) 841 | } 842 | if (a.direction) 843 | return this.rotate(Math.PI, a); 844 | var p = a.elements || a; 845 | return Line.create(this.anchor.reflectionIn([p[0], p[1], p[2] || 0]), this.direction) 846 | }, 847 | setVectors: function(a, b) { 848 | if (a = Vector.create(a), 849 | b = Vector.create(b), 850 | 2 == a.elements.length && a.elements.push(0), 851 | 2 == b.elements.length && b.elements.push(0), 852 | a.elements.length > 3 || b.elements.length > 3) 853 | return null; 854 | var c = b.modulus(); 855 | return 0 === c ? null : (this.anchor = a, 856 | this.direction = Vector.create([b.elements[0] / c, b.elements[1] / c, b.elements[2] / c]), 857 | this) 858 | } 859 | }, 860 | Line.create = function(a, b) { 861 | var c = new Line; 862 | return c.setVectors(a, b) 863 | } 864 | , 865 | Line.X = Line.create(Vector.Zero(3), Vector.i), 866 | Line.Y = Line.create(Vector.Zero(3), Vector.j), 867 | Line.Z = Line.create(Vector.Zero(3), Vector.k), 868 | Plane.prototype = { 869 | eql: function(a) { 870 | return this.contains(a.anchor) && this.isParallelTo(a) 871 | }, 872 | dup: function() { 873 | return Plane.create(this.anchor, this.normal) 874 | }, 875 | translate: function(a) { 876 | var b = a.elements || a; 877 | return Plane.create([this.anchor.elements[0] + b[0], this.anchor.elements[1] + b[1], this.anchor.elements[2] + (b[2] || 0)], this.normal) 878 | }, 879 | isParallelTo: function(a) { 880 | var b; 881 | return a.normal ? (b = this.normal.angleFrom(a.normal), 882 | Math.abs(b) <= Sylvester.precision || Math.abs(Math.PI - b) <= Sylvester.precision) : a.direction ? this.normal.isPerpendicularTo(a.direction) : null 883 | }, 884 | isPerpendicularTo: function(a) { 885 | var b = this.normal.angleFrom(a.normal); 886 | return Math.abs(Math.PI / 2 - b) <= Sylvester.precision 887 | }, 888 | distanceFrom: function(a) { 889 | if (this.intersects(a) || this.contains(a)) 890 | return 0; 891 | if (a.anchor) { 892 | var b = this.anchor.elements 893 | , c = a.anchor.elements 894 | , d = this.normal.elements; 895 | return Math.abs((b[0] - c[0]) * d[0] + (b[1] - c[1]) * d[1] + (b[2] - c[2]) * d[2]) 896 | } 897 | var e = a.elements || a 898 | , b = this.anchor.elements 899 | , d = this.normal.elements; 900 | return Math.abs((b[0] - e[0]) * d[0] + (b[1] - e[1]) * d[1] + (b[2] - (e[2] || 0)) * d[2]) 901 | }, 902 | contains: function(a) { 903 | if (a.normal) 904 | return null; 905 | if (a.direction) 906 | return this.contains(a.anchor) && this.contains(a.anchor.add(a.direction)); 907 | var b = a.elements || a 908 | , c = this.anchor.elements 909 | , d = this.normal.elements 910 | , e = Math.abs(d[0] * (c[0] - b[0]) + d[1] * (c[1] - b[1]) + d[2] * (c[2] - (b[2] || 0))); 911 | return e <= Sylvester.precision 912 | }, 913 | intersects: function(a) { 914 | return "undefined" == typeof a.direction && "undefined" == typeof a.normal ? null : !this.isParallelTo(a) 915 | }, 916 | intersectionWith: function(a) { 917 | if (!this.intersects(a)) 918 | return null; 919 | if (a.direction) { 920 | var b = a.anchor.elements 921 | , c = a.direction.elements 922 | , d = this.anchor.elements 923 | , e = this.normal.elements 924 | , f = (e[0] * (d[0] - b[0]) + e[1] * (d[1] - b[1]) + e[2] * (d[2] - b[2])) / (e[0] * c[0] + e[1] * c[1] + e[2] * c[2]); 925 | return Vector.create([b[0] + c[0] * f, b[1] + c[1] * f, b[2] + c[2] * f]) 926 | } 927 | if (a.normal) { 928 | for (var g = this.normal.cross(a.normal).toUnitVector(), e = this.normal.elements, b = this.anchor.elements, h = a.normal.elements, i = a.anchor.elements, j = Matrix.Zero(2, 2), k = 0; j.isSingular(); ) 929 | k++, 930 | j = Matrix.create([[e[k % 3], e[(k + 1) % 3]], [h[k % 3], h[(k + 1) % 3]]]); 931 | for (var l = j.inverse().elements, m = e[0] * b[0] + e[1] * b[1] + e[2] * b[2], n = h[0] * i[0] + h[1] * i[1] + h[2] * i[2], o = [l[0][0] * m + l[0][1] * n, l[1][0] * m + l[1][1] * n], p = [], q = 1; 3 >= q; q++) 932 | p.push(k == q ? 0 : o[(q + (5 - k) % 3) % 3]); 933 | return Line.create(p, g) 934 | } 935 | }, 936 | pointClosestTo: function(a) { 937 | var b = a.elements || a 938 | , c = this.anchor.elements 939 | , d = this.normal.elements 940 | , e = (c[0] - b[0]) * d[0] + (c[1] - b[1]) * d[1] + (c[2] - (b[2] || 0)) * d[2]; 941 | return Vector.create([b[0] + d[0] * e, b[1] + d[1] * e, (b[2] || 0) + d[2] * e]) 942 | }, 943 | rotate: function(a, b) { 944 | var c = Matrix.Rotation(a, b.direction).elements 945 | , d = b.pointClosestTo(this.anchor).elements 946 | , e = this.anchor.elements 947 | , f = this.normal.elements 948 | , g = d[0] 949 | , h = d[1] 950 | , i = d[2] 951 | , j = e[0] 952 | , k = e[1] 953 | , l = e[2] 954 | , m = j - g 955 | , n = k - h 956 | , o = l - i; 957 | return Plane.create([g + c[0][0] * m + c[0][1] * n + c[0][2] * o, h + c[1][0] * m + c[1][1] * n + c[1][2] * o, i + c[2][0] * m + c[2][1] * n + c[2][2] * o], [c[0][0] * f[0] + c[0][1] * f[1] + c[0][2] * f[2], c[1][0] * f[0] + c[1][1] * f[1] + c[1][2] * f[2], c[2][0] * f[0] + c[2][1] * f[1] + c[2][2] * f[2]]) 958 | }, 959 | reflectionIn: function(a) { 960 | if (a.normal) { 961 | var b = this.anchor.elements 962 | , c = this.normal.elements 963 | , d = b[0] 964 | , e = b[1] 965 | , f = b[2] 966 | , g = c[0] 967 | , h = c[1] 968 | , i = c[2] 969 | , j = this.anchor.reflectionIn(a).elements 970 | , k = d + g 971 | , l = e + h 972 | , m = f + i 973 | , n = a.pointClosestTo([k, l, m]).elements 974 | , o = [n[0] + (n[0] - k) - j[0], n[1] + (n[1] - l) - j[1], n[2] + (n[2] - m) - j[2]]; 975 | return Plane.create(j, o) 976 | } 977 | if (a.direction) 978 | return this.rotate(Math.PI, a); 979 | var p = a.elements || a; 980 | return Plane.create(this.anchor.reflectionIn([p[0], p[1], p[2] || 0]), this.normal) 981 | }, 982 | setVectors: function(a, b, c) { 983 | if (a = Vector.create(a), 984 | a = a.to3D(), 985 | null === a) 986 | return null; 987 | if (b = Vector.create(b), 988 | b = b.to3D(), 989 | null === b) 990 | return null; 991 | if ("undefined" == typeof c) 992 | c = null; 993 | else if (c = Vector.create(c), 994 | c = c.to3D(), 995 | null === c) 996 | return null; 997 | var d, e, f = a.elements[0], g = a.elements[1], h = a.elements[2], i = b.elements[0], j = b.elements[1], k = b.elements[2]; 998 | if (null !== c) { 999 | var l = c.elements[0] 1000 | , m = c.elements[1] 1001 | , n = c.elements[2]; 1002 | if (d = Vector.create([(j - g) * (n - h) - (k - h) * (m - g), (k - h) * (l - f) - (i - f) * (n - h), (i - f) * (m - g) - (j - g) * (l - f)]), 1003 | e = d.modulus(), 1004 | 0 === e) 1005 | return null; 1006 | d = Vector.create([d.elements[0] / e, d.elements[1] / e, d.elements[2] / e]) 1007 | } else { 1008 | if (e = Math.sqrt(i * i + j * j + k * k), 1009 | 0 === e) 1010 | return null; 1011 | d = Vector.create([b.elements[0] / e, b.elements[1] / e, b.elements[2] / e]) 1012 | } 1013 | return this.anchor = a, 1014 | this.normal = d, 1015 | this 1016 | } 1017 | }, 1018 | Matrix.Translation = function(a) { 1019 | var b; 1020 | if (2 === a.elements.length) 1021 | return b = Matrix.I(3), 1022 | b.elements[2][0] = a.elements[0], 1023 | b.elements[2][1] = a.elements[1], 1024 | b; 1025 | if (3 === a.elements.length) 1026 | return b = Matrix.I(4), 1027 | b.elements[0][3] = a.elements[0], 1028 | b.elements[1][3] = a.elements[1], 1029 | b.elements[2][3] = a.elements[2], 1030 | b; 1031 | throw "Invalid length for Translation" 1032 | } 1033 | , 1034 | Matrix.prototype.flatten = function() { 1035 | var a = []; 1036 | if (0 === this.elements.length) 1037 | return []; 1038 | for (var b = 0; b < this.elements[0].length; b++) 1039 | for (var c = 0; c < this.elements.length; c++) 1040 | a.push(this.elements[c][b]); 1041 | return a 1042 | } 1043 | , 1044 | Matrix.prototype.ensure4x4 = function() { 1045 | var a; 1046 | if (4 === this.elements.length && 4 === this.elements[0].length) 1047 | return this; 1048 | if (this.elements.length > 4 || this.elements[0].length > 4) 1049 | return null; 1050 | for (a = 0; a < this.elements.length; a++) 1051 | for (var b = this.elements[a].length; 4 > b; b++) 1052 | this.elements[a].push(a === b ? 1 : 0); 1053 | for (a = this.elements.length; 4 > a; a++) 1054 | 0 === a ? this.elements.push([1, 0, 0, 0]) : 1 === a ? this.elements.push([0, 1, 0, 0]) : 2 === a ? this.elements.push([0, 0, 1, 0]) : 3 === a && this.elements.push([0, 0, 0, 1]); 1055 | return this 1056 | } 1057 | , 1058 | Matrix.prototype.make3x3 = function() { 1059 | return 4 !== this.elements.length || 4 !== this.elements[0].length ? null : Matrix.create([[this.elements[0][0], this.elements[0][1], this.elements[0][2]], [this.elements[1][0], this.elements[1][1], this.elements[1][2]], [this.elements[2][0], this.elements[2][1], this.elements[2][2]]]) 1060 | } 1061 | , 1062 | Plane.create = function(a, b, c) { 1063 | var d = new Plane; 1064 | return d.setVectors(a, b, c) 1065 | } 1066 | , 1067 | Plane.XY = Plane.create(Vector.Zero(3), Vector.k), 1068 | Plane.YZ = Plane.create(Vector.Zero(3), Vector.i), 1069 | Plane.ZX = Plane.create(Vector.Zero(3), Vector.j), 1070 | Plane.YX = Plane.XY, 1071 | Plane.ZY = Plane.YZ, 1072 | Plane.XZ = Plane.ZX; 1073 | 1074 | var $V = Vector.create 1075 | , $M = Matrix.create 1076 | , $L = Line.create 1077 | , $P = Plane.create; 1078 | -------------------------------------------------------------------------------- /src/module/h264Session.js: -------------------------------------------------------------------------------- 1 | "use strict";function H264SPSParser(){function a(){x=0,y=new Map}function b(a,b){var c=b,d=x+c>>l;return c=x+b&i,a[d]>>j-(c&j)&1}function c(a){var b=x>>l,c=8*(b+1),d=c-x;if(8>d)for(var e=0;3>e;e++){var f=a[b+e];f=0==e?f>>d<>8-d|1<g;g++)f=b(a,g),e=(e<<1)+f;return x+=c,e}function e(a,c){for(var d=0,e=0,f=0,g=c;x+g<8*a.length&&!(e=b(a,g++));)d++;if(0===d)return x+=1,0;f=1<=0;h--,g++)e=b(a,g),f|=e<=h;h++)c[h]=e(a,0),f[h]=e(a,0),g[h]=d(a,1);y.put("bit_rate_value_minus1",c),y.put("cpb_size_value_minus1",f),y.put("cbr_flag",g),y.put("initial_cpb_removal_delay_length_minus1",d(a,n)),y.put("cpb_removal_delay_length_minus1",d(a,n)),y.put("dpb_output_delay_length_minus1",d(a,n)),y.put("time_offset_length",d(a,n))}function h(a){y.put("aspect_ratio_info_present_flag",d(a,1)),y.get("aspect_ratio_info_present_flag")&&(y.put("aspect_ratio_idc",d(a,p)),y.get("aspect_ratio_idc")===v&&(c(a,s),y.put("sar_width",d(a,s)),c(a,s),y.put("sar_height",d(a,s)))),y.put("overscan_info_present_flag",d(a,1)),y.get("overscan_info_present_flag")&&y.put("overscan_appropriate_flag",d(a,1)),y.put("video_signal_type_present_flag",d(a,1)),y.get("video_signal_type_present_flag")&&(y.put("video_format",d(a,l)),y.put("video_full_range_flag",d(a,1)),y.put("colour_description_present_flag",d(a,1)),y.get("colour_description_present_flag")&&(y.put("colour_primaries",d(a,p)),y.put("transfer_characteristics",d(a,p)),y.put("matrix_coefficients",d(a,p)))),y.put("chroma_loc_info_present_flag",d(a,1)),y.get("chroma_loc_info_present_flag")&&(y.put("chroma_sample_loc_type_top_field",e(a,0)),y.put("chroma_sample_loc_type_bottom_field",e(a,0))),y.put("timing_info_present_flag",d(a,1)),y.get("timing_info_present_flag")&&(y.put("num_units_in_tick",d(a,t)),y.put("time_scale",d(a,t)),y.put("fixed_frame_rate_flag",d(a,1))),y.put("nal_hrd_parameters_present_flag",d(a,1)),y.get("nal_hrd_parameters_present_flag")&&g(a),y.put("vcl_hrd_parameters_present_flag",d(a,1)),y.get("vcl_hrd_parameters_present_flag")&&g(a),(y.get("nal_hrd_parameters_present_flag")||y.get("vcl_hrd_parameters_present_flag"))&&y.put("low_delay_hrd_flag",d(a,1)),y.put("pic_struct_present_flag",d(a,1)),y.put("bitstream_restriction_flag",d(a,1)),y.get("bitstream_restriction_flag")&&(y.put("motion_vectors_over_pic_boundaries_flag",d(a,1)),y.put("max_bytes_per_pic_denom",e(a,0)),y.put("max_bits_per_mb_denom",e(a,0)))}var i=7,j=7,k=2,l=3,m=4,n=5,o=6,p=8,q=12,r=15,s=16,t=32,u=64,v=255,w=256,x=0,y=null;return a.prototype={parse:function(a){x=0,y.clear(),y.put("forbidden_zero_bit",d(a,1)),y.put("nal_ref_idc",d(a,k)),y.put("nal_unit_type",d(a,n)),y.put("profile_idc",d(a,p)),y.put("profile_compatibility",d(a,p)),y.put("level_idc",d(a,p)),y.put("seq_parameter_set_id",e(a,0));var b=y.get("profile_idc"),c=100,g=110,i=122,j=244,m=44,r=83,t=86,v=118,z=128,A=138,B=139,C=134;if((b===c||b===g||b===i||b===j||b===m||b===r||b===t||b===v||b===z||b===A||b===B||b===C)&&(y.put("chroma_format_idc",e(a,0)),y.get("chroma_format_idc")===l&&y.put("separate_colour_plane_flag",d(a,1)),y.put("bit_depth_luma_minus8",e(a,0)),y.put("bit_depth_chroma_minus8",e(a,0)),y.put("qpprime_y_zero_transform_bypass_flag",d(a,1)),y.put("seq_scaling_matrix_present_flag",d(a,1)),y.get("seq_scaling_matrix_present_flag"))){for(var D=y.get("chroma_format_idc")!==l?p:q,E=new Array(D),F=0;D>F;F++)if(E[F]=d(a,1),E[F])for(var G=o>F?s:u,H=8,I=8,J=0,K=0;G>K;K++)I&&(J=f(a,0),I=(H+J+w)%w),H=0===I?H:I;y.put("seq_scaling_list_present_flag",E)}if(y.put("log2_max_frame_num_minus4",e(a,0)),y.put("pic_order_cnt_type",e(a,0)),0===y.get("pic_order_cnt_type"))y.put("log2_max_pic_order_cnt_lsb_minus4",e(a,0));else if(1===y.get("pic_order_cnt_type")){y.put("delta_pic_order_always_zero_flag",d(a,1)),y.put("offset_for_non_ref_pic",f(a,0)),y.put("offset_for_top_to_bottom_field",f(a,0)),y.put("num_ref_frames_in_pic_order_cnt_cycle",e(a,0));for(var L=0;L>>0},appendBuffer:function(a,b,c){var d=1048576;if(c+b.length>=a.length){var e=new Uint8Array(a.length+d);e.set(a,0),a=e}return a.set(b,c),a},getFramerate:function(){return L},setGovLength:function(a){I=a},getGovLength:function(){return I},setDecodingTime:function(a){this.decodingTime=a},getDropPercent:function(){return J},getDropCount:function(){return K},initStartTime:function(){this.firstDiffTime=0,this.calcGov=0},setCheckDelay:function(a){this.checkDelay=a},init:function(a){u=!1,g=!1,H=a,this.decoder.setIsFirstFrame(!1),this.videoBufferList=new VideoBufferList,this.firstDiffTime=0,this.checkDelay=!0,this.timeData=null},setFramerate:function(a){a>0&&"undefined"!=typeof a&&(L=a,null!==this.videoBufferList&&(this.videoBufferList.setMaxLength(6*L),this.videoBufferList.setBUFFERING(4*L)))},parseRTPData:function(b,f,I,J,K){{var L=null,O={},P=(f[19]<<24)+(f[18]<<16)+(f[17]<<8)+f[16]>>>0,Q=Date.UTC("20"+(P>>26),(P>>22&15)-1,P>>17&31,P>>12&31,P>>6&63,63&P)/1e3;K.timeStampmsw}if(Q-=28800,0==this.firstTime)this.firstTime=Q,this.lastMSW=0,F=(f[21]<<8)+f[20],q={timestamp:this.firstTime,timestamp_usec:0};else{var R,S=(f[21]<<8)+f[20];R=S>F?S-F:S+65535-F,this.lastMSW+=R,Q>this.firstTime&&(this.lastMSW-=1e3),this.firstTime=Q,q={timestamp:Q,timestamp_usec:this.lastMSW},F=S}0!==this.getFramerate()&&"undefined"!=typeof this.getFramerate()||"undefined"==typeof this.getTimeStamp()||(this.setFramerate(Math.round(1e3/((q.timestamp-this.getTimeStamp().timestamp===0?0:1e3)+(q.timestamp_usec-this.getTimeStamp().timestamp_usec)))),console.log("setFramerate"+Math.round(1e3/((q.timestamp-this.getTimeStamp().timestamp===0?0:1e3)+(q.timestamp_usec-this.getTimeStamp().timestamp_usec))))),this.setTimeStamp(q);for(var T=f[22],U=f.subarray(24+T,f.length-8),V=f.subarray(f.length-8,f.length),W=((V[7]<<24)+(V[6]<<16)+(V[5]<<8)+V[4],[]),X=0;X<=U.length;)if(0==U[X])if(0==U[X+1])if(1==U[X+2]){if(W.push(X),X+=3,5==(31&U[X])||1==(31&U[X]))break}else 0==U[X+2]?X++:X+=3;else X+=2;else X+=1;var Y="P";c=(f[21]<<8)+f[20];for(var Z,$=0,X=0;Xab-D&&(this.firstDiffTime=l+(Date.now()-ab).toFixed(0)),l=Date.now()-ab-this.firstDiffTime,0>l&&(this.firstDiffTime=0,l=0),l>m&&(O.error={errorCode:101},this.rtpReturnCallback(O))),D=ab,e!==i&&(console.log("outputSize: "+e),e=i,this.decoder.setOutputSize(e)),n===!0&&"P"===Y)return void(d=0);n===!0&&(n=!1),"I"===Y&&2>o&&o++,p.frameData=null,(I!==!0||g!==!0)&&(p.frameData=this.decoder.decode(U)),p.timeStamp=null,d=0,q=null===q.timestamp?this.getTimeStamp():q,p.timeStamp=q}else{var bb=null;if(u)p.initSegmentData=null;else{u=!0;var K={id:1,width:w,height:x,type:"video",profileIdc:h.getSpsValue("profile_idc"),profileCompatibility:0,levelIdc:h.getSpsValue("level_idc"),sps:[s],pps:[t],timescale:1e3,fps:this.getFramerate()};console.log(JSON.stringify(K)),p.initSegmentData=mp4Remux.initSegment(K),p.codecInfo=h.getCodecInfo()}if($||console.log("11111111111111111111111111111111111111111"),"I"===Y){var cb=$;bb=U.subarray(cb,U.length)}else bb=U.subarray($,U.length);var db=bb.length-4;bb[0]=(4278190080&db)>>>24,bb[1]=(16711680&db)>>>16,bb[2]=(65280&db)>>>8,bb[3]=255&db;var eb=this.getFramerate(),fb={duration:Math.round(1/eb*1e3),size:bb.length,frame_time_stamp:null,frameDuration:null};if(g)fb.frame_time_stamp=c,p.frameData=new Uint8Array(bb),p.mediaSample=fb;else{if(I===!1){if(fb.frame_time_stamp=1e3*q.timestamp+q.timestamp_usec-M,v===!1)fb.frame_time_stamp=0,M=1e3*q.timestamp+q.timestamp_usec,fb.frameDuration=0,r=fb,v=!0;else{var gb=r.frame_time_stamp,hb=fb.frame_time_stamp;fb.frameDuration=Math.abs(hb-gb),fb.frameDuration>3e3&&(fb.frameDuration=0),r=fb}p.frameData=new Uint8Array(bb),p.mediaSample=fb}q=null===q.timestamp?this.getTimeStamp():q,p.timeStamp=q}d=0}var ib=z*A;if(g===!0){var jb=(G/E*100).toFixed(0)<60;ib>y?5e3>E?(a("video"),O.decodeMode="video"):jb===!0?(a("video"),O.decodeMode="video"):(a("canvas"),O.decodeMode="canvas"):(a("canvas"),O.decodeMode="canvas")}return p.playback=g,O.decodedData=p,B===!0?("I"===Y&&C++,2===C&&(C=0,B=!1),void debug.info("H264Session::stop")):void this.rtpReturnCallback(O)},findIFrame:function(){if(null!==this.videoBufferList){var a=this.videoBufferList.findIFrame();if(null===a||"undefined"==typeof a)return!1;var b={};return this.setTimeStamp(a.timeStamp),b.frameData=this.decoder.decode(a.buffer),b.timeStamp=a.timeStamp,b}},setInitSegment:function(){u=!1,j=null,k=null}},new b}; -------------------------------------------------------------------------------- /src/module/h265Session.js: -------------------------------------------------------------------------------- 1 | function H265SPSParser(){function a(){g=0,h=new Map}function b(){if(l>=k)return 0;var a=j[l++];return 0==a?(o++,k>l&&2==o&&3==j[l]&&(l++,o=0)):o=0,a}function c(){return 0==m&&(n=b(),m=8),m--,n>>m&1}function d(a,b){for(var d=0;b>0;)d<<=1,d|=c(),b--;return d}function e(){for(var a=0;k>l&&0==c();)a++;return d(null,a)+((1<e;e++)c[e]=d(i,1);h.put("general_progressive_source_flag",d(i,1)),h.put("general_interlaced_source_flag",d(i,1)),h.put("general_non_packed_constraint_flag",d(i,1)),h.put("general_frame_only_constraint_flag",d(i,1));var f=h.get("general_profile_idc");4===f||c[4]||5===f||c[5]||6===f||c[6]||7===f||c[7]||8===f||c[8]||9===f||c[9]||10===f||c[10]?(h.put("general_max_12bit_constraint_flag",d(i,1)),h.put("general_max_10bit_constraint_flag",d(i,1)),h.put("general_max_8bit_constraint_flag",d(i,1)),h.put("general_max_422chroma_constraint_flag",d(i,1)),h.put("general_max_420chroma_constraint_flag",d(i,1)),h.put("general_max_monochrome_constraint_flag",d(i,1)),h.put("general_intra_constraint_flag",d(i,1)),h.put("general_one_picture_only_constraint_flag",d(i,1)),h.put("general_lower_bit_rate_constraint_flag",d(i,1)),5===f||c[5]||9===f||c[9]||10===f||c[10]?(h.put("general_max_14bit_constraint_flag",d(i,1)),h.put("general_reserved_zero_33bits",d(i,33))):h.put("general_reserved_zero_34bits",d(i,34))):h.put("general_reserved_zero_43bits",d(i,43)),f>=1&&5>=f||c[1]||c[2]||c[3]||c[4]||c[5]||c[9]?h.put("general_inbld_flag",d(i,1)):h.put("general_reserved_zero_bit",d(i,1))}h.put("general_level_idc",d(i,8));var g=new Array(b),j=new Array(b);for(q=0;b>q;q++)g[q]=d(i,1),j[q]=d(i,1);var k=new Array(8),l=new Array(b),m=new Array(b),n=new Array(b),o=[],p=new Array(b);if(b>0)for(var q=b;8>q;q++)k[q]=d(i,2);for(var q=0;b>q;q++){if(g[q]){m[q]=d(i,2),n[q]=d(i,1),l[q]=d(i,5);for(var e=0;32>e;e++)o[q][e]=d(i,1);h.put("sub_layer_progressive_source_flag",d(i,1)),h.put("sub_layer_interlaced_source_flag",d(i,1)),h.put("sub_layer_non_packed_constraint_flag",d(i,1)),h.put("sub_layer_frame_only_constraint_flag",d(i,1)),4===l[q]||o[q][4]||5===l[q]||o[q][5]||6===l[q]||o[q][6]||7===l[q]||o[q][7]||8===l[q]||o[q][8]||9===l[q]||o[q][9]||10===l[q]||o[q][10]?(h.put("sub_layer_max_12bit_constraint_flag",d(i,1)),h.put("sub_layer_max_10bit_constraint_flag",d(i,1)),h.put("sub_layer_max_8bit_constraint_flag",d(i,1)),h.put("sub_layer_max_422chroma_constraint_flag",d(i,1)),h.put("sub_layer_max_420chroma_constraint_flag",d(i,1)),h.put("sub_layer_max_monochrome_constraint_flag",d(i,1)),h.put("sub_layer_intra_constraint_flag",d(i,1)),h.put("sub_layer_one_picture_only_constraint_flag",d(i,1)),h.put("sub_layer_lower_bit_rate_constraint_flag",d(i,1)),5===l[q]||o[q][5]?(h.put("sub_layer_max_14bit_constraint_flag",d(i,1)),h.put("sub_layer_lower_bit_rate_constraint_flag",d(i,1)),p[q]=d(i,33)):p[q]=d(i,34)):h.put("sub_layer_reserved_zero_43bits",d(i,43)),l[q]>=1&&l[q]<=5||9==l[q]||o[1]||o[2]||o[3]||o[4]||o[5]||o[9]?h.put("sub_layer_inbld_flag",d(i,1)):h.put("sub_layer_reserved_zero_bit",d(i,1))}j[q]&&h.put("sub_layer_level_idc",d(i,8))}}var g=0,h=null,i=null,j=null,k=0,l=0,m=0,n=0,o=0;return a.prototype={parse:function(a){i=a,g=0,h.clear(),h.put("forbidden_zero_bit",d(i,1)),h.put("nal_unit_type",d(i,6)),h.put("nuh_layer_id",d(i,6)),h.put("nuh_temporal_id_plus1",d(i,3)),h.put("sps_video_parameter_set_id",d(i,4)),0===h.get("nuh_layer_id")?h.put("sps_max_sub_layers_minus1",d(i,3)):h.put("sps_ext_or_max_sub_layers_minus1",d(i,3));var b=0!==h.get("nuh_layer_id")&&7===h.get("sps_ext_or_max_sub_layers_minus1");return b||(h.put("sps_max_sub_layers_minus1",d(i,1)),f(1,h.get("sps_max_sub_layers_minus1"))),d(i,84),h.put("sps_seq_parameter_set_id",e(i,0)),b?(h.put("update_rep_format_flag",d(i,1)),h.get("update_rep_format_flag")&&h.put("sps_rep_format_idx",d(i,8))):(h.put("chroma_format_idc",e(i,0)),3===h.get("chroma_format_idc")&&h.put("separate_colour_plane_flag",d(i,1)),h.put("pic_width_in_luma_samples",e(i,0)),h.put("pic_height_in_luma_samples",e(i,0)),h.put("conformance_window_flag",d(i,1)),h.get("conformance_window_flag")&&(h.put("conf_win_left_offset",e(i,0)),h.put("conf_win_right_offset",e(i,0)),h.put("conf_win_top_offset",e(i,0)),h.put("conf_win_bottom_offset",e(i,0)))),!0},parse2:function(a){var b=a.length;if(i=a,j=a,k=a.length,l=0,m=0,n=0,o=0,g=0,h.clear(),20>b)return!1;d(i,16),d(i,4);var c=d(i,3);if(h.put("sps_max_sub_layers_minus1",c),c>6)return!1;d(i,1),d(i,2),d(i,1);d(i,5);d(i,32),d(i,1),d(i,1),d(i,1),d(i,1),d(i,43),d(i,1),h.put("general_level_idc",d(i,8));for(var f=[],p=[],q=0;c>q;q++)f[q]=d(i,1),p[q]=d(i,1);if(c>0)for(var q=c;8>q;q++){d(i,2)}for(var q=0;c>q;q++)f[q]&&(d(i,2),d(i,1),d(i,5),d(i,32),d(i,1),d(i,1),d(i,1),d(i,1),d(i,44)),p[q]&&d(i,8);var r=e(i,0);if(h.put("sps_seq_parameter_set_id",r),r>15)return!1;var s=e(i,0);if(h.put("chroma_format_idc",s),r>3)return!1;3==s&&d(i,1),h.put("pic_width_in_luma_samples",e(i,0)),h.put("pic_height_in_luma_samples",e(i,0)),d(i,1)&&(e(i,0),e(i,0),e(i,0),e(i,0));var t=e(i,0),u=e(i,0);return t!=u?!1:!0},getSizeInfo:function(){var a=h.get("pic_width_in_luma_samples"),b=h.get("pic_height_in_luma_samples");if(h.get("conformance_window_flag")){var c=h.get("chroma_format_idc"),d=h.get("separate_colour_plane_flag");"undefined"==typeof d&&(d=0);var e=1!==c&&2!==c||0!==d?1:2,f=1===c&&0===d?2:1;a-=e*h.get("conf_win_right_offset")+e*h.get("conf_win_left_offset"),b-=f*h.get("conf_win_bottom_offset")+f*h.get("conf_win_top_offset")}var g=a*b,i={width:a,height:b,decodeSize:g};return i},getSpsValue:function(a){return h.get(a)}},new a}var H265Session=function(){"use strict";function a(){this.decoder=H265Decoder(),this.firstTime=0,this.lastMSW=0}var b,c=0,d=0,e=0,f=!1,g=0,h=0,i=new H265SPSParser,j={frameData:null,timeStamp:null},k={timestamp:null,timezone:null},l=0,m=0,n=null,o=0,p=0,q=0,r=0,s={width:0,height:0},t=0,u=8e3,v=0;return a.prototype={setReturnCallback:function(a){this.rtpReturnCallback=a},setBufferfullCallback:function(a){null!==this.videoBufferList&&this.videoBufferList.setBufferFullCallback(a)},getVideoBuffer:function(a){return null!==this.videoBufferList?this.videoBufferList.searchNodeAt(a):void 0},clearBuffer:function(){null!==this.videoBufferList&&this.videoBufferList.clear()},findCurrent:function(){null!==this.videoBufferList&&this.videoBufferList.searchTimestamp(this.getTimeStamp())},ntohl:function(a){return(a[0]<<24)+(a[1]<<16)+(a[2]<<8)+a[3]>>>0},appendBuffer:function(a,b,c){var d=1048576;if(c+b.length>=a.length){var e=new Uint8Array(a.length+d);e.set(a,0),a=e}return a.set(b,c),a},setGovLength:function(a){n=a},getGovLength:function(){return n},setDecodingTime:function(a){this.decodingTime=a},getDropPercent:function(){return o},getDropCount:function(){return p},initStartTime:function(){this.firstDiffTime=0,this.calcGov=0},setCheckDelay:function(a){this.checkDelay=a},init:function(){this.decoder.setIsFirstFrame(!1),this.videoBufferList=new VideoBufferList,this.firstDiffTime=0,this.checkDelay=!0,this.timeData=null},parseRTPData:function(a,n,o,p,q){var w=null,x={},y=(n[19]<<24)+(n[18]<<16)+(n[17]<<8)+n[16]>>>0,z=Date.UTC("20"+(y>>26),(y>>22&15)-1,y>>17&31,y>>12&31,y>>6&63,63&y)/1e3;if(z-=28800,0==this.firstTime)this.firstTime=z,this.lastMSW=0,d=(n[21]<<8)+n[20],k={timestamp:this.firstTime,timestamp_usec:0};else{var A,B=(n[21]<<8)+n[20];A=B>d?B-d:B+65535-d,this.lastMSW+=A,z>this.firstTime&&(this.lastMSW-=1e3),this.firstTime=z,k={timestamp:z,timestamp_usec:this.lastMSW},d=B}0!==this.getFramerate()&&"undefined"!=typeof this.getFramerate()||"undefined"==typeof this.getTimeStamp()||(this.setFramerate(Math.round(1e3/((k.timestamp-this.getTimeStamp().timestamp===0?0:1e3)+(k.timestamp_usec-this.getTimeStamp().timestamp_usec)))),console.log("setFramerate"+Math.round(1e3/((k.timestamp-this.getTimeStamp().timestamp===0?0:1e3)+(k.timestamp_usec-this.getTimeStamp().timestamp_usec))))),this.setTimeStamp(k);var C=n[22];b=n.subarray(24+C,n.length-8),c=(n[21]<<8)+n[20];for(var D=[],E=0;E<=b.length;)if(0==b[E])if(0==b[E+1])if(1==b[E+2]){if(D.push(E),E+=3,5==(31&b[E])||1==(31&b[E]))break}else 0==b[E+2]?E++:E+=3;else E+=2;else E+=1;for(var F,G="P",E=0;E>1&63){default:break;case 33:G="I",i.parse2(w);var H=q;h=i.getSizeInfo().decodeSize,l=H.width,m=H.height,(s.width!=H.width||s.height!=H.height)&&(0!=s.width?(s.width=H.width,s.height=H.height):(s.width=H.width,s.height=H.height,x.decodeStart=s))}var I=1e3*k.timestamp+k.timestamp_usec;0==this.firstDiffTime?(t=0,this.firstDiffTime=Date.now()-I,console.log("firstDiff: "+r)):(0>I-v&&(this.firstDiffTime=t+(Date.now()-I).toFixed(0)),t=Date.now()-I-this.firstDiffTime,0>t&&(this.firstDiffTime=0,t=0),t>u&&(x.error={errorCode:101},this.rtpReturnCallback(x))),v=I,j.frameData=null,g!==h&&(g=h,this.decoder.setOutputSize(g)),(o!==!0||f!==!0)&&(j.frameData=this.decoder.decode(b),j.frameData.frameType=G),j.timeStamp=null,e=0,k=null===k.timestamp?this.getTimeStamp():k,j.timeStamp=k,o&&(x.backupData={stream:b,frameType:G,width:l,height:m,codecType:"h265"},null!==k.timestamp&&"undefined"!=typeof k.timestamp?x.backupData.timestamp_usec=k.timestamp_usec:x.backupData.timestamp=(c/90).toFixed(0)),x.decodedData=j,this.rtpReturnCallback(x)},findIFrame:function(){if(null!==this.videoBufferList){var a=this.videoBufferList.findIFrame();if(null===a||"undefined"==typeof a)return!1;var b={};return this.setTimeStamp(a.timeStamp),b.frameData=this.decoder.decode(a.buffer),b.timeStamp=a.timeStamp,b}},getFramerate:function(){return q},setFramerate:function(a){a>0&&"undefined"!=typeof a&&(q=a,null!==this.videoBufferList&&(this.videoBufferList.setMaxLength(6*q),this.videoBufferList.setBUFFERING(4*q)))},getTimeStamp:function(){return this.timeData},setTimeStamp:function(a){this.timeData=a}},new a}; -------------------------------------------------------------------------------- /src/module/hashMap.js: -------------------------------------------------------------------------------- 1 | var Map=function(){this.map={}};Map.prototype={put:function(a,b){this.map[a]=b},get:function(a){return this.map[a]},containsKey:function(a){return a in this.map},containsValue:function(a){for(var b in this.map)if(this.map[b]===a)return!0;return!1},isEmpty:function(){return 0===this.size()},clear:function(){for(var a in this.map)delete this.map[a]},remove:function(a){delete this.map[a]},keys:function(){var a=new Array;for(var b in this.map)a.push(b);return a},values:function(){var a=new Array;for(var b in this.map)a.push(this.map[b]);return a},size:function(){var a=0;for(var b in this.map)a++;return a}}; -------------------------------------------------------------------------------- /src/module/ivsSession.js: -------------------------------------------------------------------------------- 1 | var IvsSession=function(){function a(){}function b(a){var b={result:!0,type:0};return b.params=JSON.parse(String.fromCharCode.apply(null,a)),b}function c(a){var b={result:!1},c=0,d=(a[c+1]<<8)+a[c];if(1!==d&&2!==d)return b;b.result=!0,b.type=5,b.params=null,c+=2;var e=a[c];if(0===e)return b;c+=1;var f=a[c];c+=1,b.params={},b.params.coordinate=128&f?8192:1024,b.params.isTrack=127&f?!0:!1,b.params.object=[];for(var g=0;e>g;g++){var h={};h.objectId=(a[c+3]<<24)+(a[c+2]<<16)+(a[c+1]<<8)+a[c],c+=4,h.operateType=a[c],c+=1;var i=a[c];c+=1,h.objectType=a[c],c+=1;var j=a[c];c+=1,c+=1,c+=1,h.classID=a[c],c+=1,h.subType=a[c],c+=1,j>0&&(h.fatherId=[]);for(var k=0;j>k;k++)h.fatherId.push((a[c+3]<<24)+(a[c+2]<<16)+(a[c+1]<<8)+a[c]),c+=4;i>0&&(h.track=[]);for(var l=0;i>l;l++){var m=(a[c+1]<<8)+a[c];c+=2;var n=(a[c+1]<<8)+a[c];c+=2;var o=(a[c+1]<<8)+a[c];c+=2;var p=(a[c+1]<<8)+a[c];c+=2,h.track.push([m-o,n-p,m+o,n+p])}b.params.object.push(h)}return b}function d(a,b){b.hasOwnProperty("attribute80")||(b.attribute80=[]);var c=1,d=a[c];c+=1;var e={};e.color={},e.color.valid=a[c],c+=1,e.carModel=a[c],c+=1,e.color.red=a[c],c+=1,e.color.green=a[c],c+=1,e.color.blue=a[c],c+=1,e.color.alpha=a[c],c+=1,e.brand=(a[c+1]<<8)+a[c],c+=2,e.subBrand=(a[c+1]<<8)+a[c],c+=2,e.year=(a[c+1]<<8)+a[c],c+=2,e.reliability=a[c],c+=1,c+=1;var f=(a[c+1]<<8)+a[c];c+=2;var g=(a[c+1]<<8)+a[c];c+=2;var h=(a[c+1]<<8)+a[c];c+=2;var i=(a[c+1]<<8)+a[c];return c+=2,e.windowPosition=[f-h,g-i,f+h,g+i],b.attribute80.push(e),d}function e(a,b){b.hasOwnProperty("attribute81")||(b.attribute81=[]);var c={},d=1,e=a[d];d+=1;var f=(a[d+1]<<8)+a[d];d+=2;var g=(a[d+1]<<8)+a[d];d+=2;var h=(a[d+1]<<8)+a[d];d+=2;var i=(a[d+1]<<8)+a[d];return d+=2,c.mainPosition=[f-h,g-i,f+h,g+i],f=(a[d+1]<<8)+a[d],d+=2,g=(a[d+1]<<8)+a[d],d+=2,h=(a[d+1]<<8)+a[d],d+=2,i=(a[d+1]<<8)+a[d],d+=2,c.coPosition=[f-h,g-i,f+h,g+i],c.mainSafetyBelt=a[d]>>2&3,c.coSafetyBelt=3&a[d],d+=1,c.mainSunvisor=a[d]>>2&3,c.coSunvisor=3&a[d],d+=1,b.attribute81.push(c),e}function f(a,b){b.hasOwnProperty("attribute82")||(b.attribute82=[]);var c={},d=1,e=a[d];return d+=1,c.plateEncode=a[d],d+=1,c.plateInfoLen=a[d],d+=1,c.plateInfo=a.subarray(d,c.plateInfoLen),b.attribute82.push(c),e}function g(a,b){b.hasOwnProperty("attribute83")||(b.attribute83=[]);var c={},d=1,e=a[d];return d+=1,c.color={},c.color.valid=a[d],d+=1,c.color.red=a[d],d+=1,c.color.green=a[d],d+=1,c.color.blue=a[d],d+=1,c.color.alpha=a[d],d+=1,c.country=String.fromCharCode.apply(null,a.subarray(d,4)),d+=4,c.plateType=(a[d+1]<<8)+a[d],d+=2,d+=1,c.plateWidth=(a[d+1]<<8)+a[d],b.attribute83.push(c),e}function h(a,b){b.hasOwnProperty("attribute84")||(b.attribute84=[]);var c={},d=1,e=a[d];d+=1,c.fatherCount=a[d],d+=1,c.trackCount=a[d],d+=1,c.trackType=a[d],d+=1,d+=3,c.fatherCount>0&&(c.fatherID=[]);for(var f=0;f0&&(c.track=[]);for(var g=0;g0&&(c.mainColorInfo=[]);for(var f=0;f>2&3,c.beard=3&a[d],b.attribute88.push(c),len}function m(a,b){b.hasOwnProperty("attribute89")||(b.attribute89=[]);var c={},d=1,e=a[d];d+=1,c.yawAngle=parseInt((a[d+1]<<8)+a[d]),d+=2,c.rollAngle=parseInt((a[d+1]<<8)+a[d]),d+=2,c.pitchAngle=parseInt((a[d+1]<<8)+a[d]),d+=2;var f=(a[d+1]<<8)+a[d];d+=2;var g=(a[d+1]<<8)+a[d];d+=2,c.lEyePos=[f,g],f=(a[d+1]<<8)+a[d],d+=2,g=(a[d+1]<<8)+a[d],d+=2,c.rEyePos=[f,g],f=(a[d+1]<<8)+a[d],d+=2,g=(a[d+1]<<8)+a[d],d+=2,c.nosePos=[f,g],f=(a[d+1]<<8)+a[d],d+=2,g=(a[d+1]<<8)+a[d],d+=2,c.lMouthPos=[f,g],f=(a[d+1]<<8)+a[d],d+=2,g=(a[d+1]<<8)+a[d],d+=2,c.rMouthPos=[f,g];var h=a[d];d+=3,h>0&&(c.featurePos=[]);for(var i=0;h>i;i++)f=(a[d+1]<<8)+a[d],d+=2,g=(a[d+1]<<8)+a[d],d+=2,c.featurePos.push([f,g]);return b.attribute89.push(c),e}function n(a,b){b.hasOwnProperty("attribute8C")||(b.attribute8C=[]);var c={},d=1,e=a[d];d+=1,c.hangingCount=a[d],d+=1,c.tissueCount=a[d],d+=1,c.sunVisorCount=a[d],d+=1,c.annualInspectionCount=a[d],d+=1,d+=6,c.hangingCount>0&&(c.hangingCount=[]);for(var f=0;f0&&(c.tissueCount=[]);for(var f=0;f0&&(c.sunVisorCount=[]);for(var f=0;f0&&(c.annualInspectionCount=[]);for(var f=0;fe?0:(d+=2,c.objectId=(a[d+3]<<24)+(a[d+2]<<16)+(a[d+1]<<8)+a[d],d+=4,c.version=a[d],d+=1,d+=3,c.faceData=a.subarray(d,e-d),b.faceObject.push(c),e)}function s(a,b){b.hasOwnProperty("commonObject")||(b.commonObject=[]);var c={},d=0;c.type=a[d],d+=1,d+=1;var e=(a[d+1]<<8)+a[d];d+=2,c.objectId=(a[d+3]<<24)+(a[d+2]<<16)+(a[d+1]<<8)+a[d],d+=4,c.operateType=a[d],d+=1,d+=3;var f=a.subarray(d,e-d);p(f,c),b.commonObject.push(c)}function t(a,b,c){var d=0,e=(a[d+3]<<24)+(a[d+2]<<16)+(a[d+1]<<8)+a[d];d+=4;var f=a[d];if(d+=1,d+=3,0==f)return d;b.params.groupId=e,b.params.object={};for(var g=0;f>g;g++){var h=a[d],i=a.subarray(d,a.length-d),j=0;switch(h){case 2:case 5:j=q(i,b.params.object);break;case 15:j=r(i,b.params.object);break;default:j=s(i,b.params.object)}if(0==j)return 0;d+=j}return c({ivsDraw:b}),d}function u(a,b,c){var d={result:!1,type:14,params:null};if(b.length<32)return d.result=!0,c({ivsDraw:d}),!1;var e=0;d.params.classID=a;var f=b[e];if(0==f)return c({ivsDraw:d}),!0;d.params.groupCount=f,e+=1,e+=7,d.params.cameral=[];for(var g=0;20>g;g++)d.params.cameral.push(b[e+g]);e+=20;for(var h=0;h=j)break;e+=j}}function v(a,b){for(var c=a.length,d=0;c>d+4;){var e=a[d],f=(a[d+1],(a[d+3]<<8)+a[d+2]),g=a.subarray(d,f-4);if(d+=f,161!==e&&!u(z[e-64],g,b))break}}function w(a,d,e){var f=d[22],g=d.subarray(24+f,d.length-8);switch(a){case 0:e({ivsDraw:b(g)});break;case 5:e({ivsDraw:c(g)});break;case 6:break;case 14:v(g,e)}}var x,y,z={1:"VideoSynopsis",2:"TrafficGate",3:"ElectronicPolice",4:"SinglePtzParking",5:"PtzParking",6:"Traffic",7:"Normal",8:"Prison",9:"ATM",10:"MetroIVS",11:"FaceDetection",12:"FaceRecognition",13:"NumberStat",14:"HeatMap",15:"VideoDiagnosis",16:"VideoEnhance",17:"SmokeFireDetect",18:"VehicleAnalyse",19:"PersonFeature",20:"SDFaceDetect",21:"HeatMapPlan",22:"ATMFD",23:"SCR",24:"NumberStatPlan",25:"CourseRecord",26:"Highway",27:"City",28:"LeTrack",29:"ObjectStruct",30:"Stereo",31:"StereoPc",32:"HumanDetect",33:"SDPedestrain",34:"FaceAnalysis",35:"FaceAttribute",36:"FacePicAnalyse",37:"SDEP",38:"XRayDetect",39:"ObjectDetect",40:"CrowdDistriMap",41:"StereoBehavior"};return a.prototype={init:function(){console.log("init")},parseRTPData:function(a,b,c,d,e){var f=(b[19]<<24)+(b[18]<<16)+(b[17]<<8)+b[16]>>>0,g=Date.UTC("20"+(f>>26),(f>>22&15)-1,f>>17&31,f>>12&31,f>>6&63,63&f)/1e3,h=e.timeStampmsw;y={timestamp:g-28800,timestamp_usec:h},x=b[5],w(x,b,this.rtpReturnCallback)},setBufferfullCallback:function(){},setReturnCallback:function(a){this.rtpReturnCallback=a}},new a}; -------------------------------------------------------------------------------- /src/module/mjpegSession.js: -------------------------------------------------------------------------------- 1 | "use strict";var MjpegSession=function(){function a(){this.decoder=new MJPEGDecoder,this.firstTime=0,this.lastMSW=0}var b=0,c=0,d=0,e={frameData:null,timeStamp:null},f={timestamp:null,timezone:null},g=0,h=0,i=0,j=0,k=0,l=0,m=!1,n=null,o=null,p=null,q=null,r=0,s=0,t=0,u=0,v=8e3,w=0,x={width:0,height:0};return a.prototype={init:function(){this.decoder.setIsFirstFrame(!1),this.videoBufferList=new VideoBufferList,d=0,this.timeData=null},parseRTPData:function(a,d,q,r,s){var t=new Uint8Array(1048576);b=s.width,c=s.height,n={},o={};var y=d[22],z=d.subarray(24+y,d.length-8);p=z.length;var A=(d[19]<<24)+(d[18]<<16)+(d[17]<<8)+d[16]>>>0,B=Date.UTC("20"+(A>>26),(A>>22&15)-1,A>>17&31,A>>12&31,A>>6&63,63&A)/1e3;if(B-=28800,0==this.firstTime)this.firstTime=B,this.lastMSW=0,l=(d[21]<<8)+d[20],f={timestamp:this.firstTime,timestamp_usec:0};else{var C,D=(d[21]<<8)+d[20];C=D>l?D-l:D+65535-l,this.lastMSW+=C,B>this.firstTime&&(this.lastMSW-=1e3),this.firstTime=B,f={timestamp:B,timestamp_usec:this.lastMSW},l=D}0!==this.getFramerate()&&"undefined"!=typeof this.getFramerate()||"undefined"==typeof this.getTimeStamp()||this.setFramerate(Math.round(1e3/((f.timestamp-this.getTimeStamp().timestamp===0?0:1e3)+(f.timestamp_usec-this.getTimeStamp().timestamp_usec)))),this.setTimeStamp(f),k=(d[21]<<8)+d[20],h=p,j=h,t=this.appendBuffer(t,z,g),g+=p,t[g+j-2]=255,t[g+j-1]=217,i++,(x.width!=b||x.height!=c)&&(0!=x.width?(x.width=b,x.height=c):(x.width=b,x.height=c,o.decodeStart=x));var E=1e3*f.timestamp+f.timestamp_usec;0==this.firstDiffTime?(u=0,this.firstDiffTime=Date.now()-E,console.log("firstDiff: "+this.firstTime)):(0>E-w&&(this.firstDiffTime=u+(Date.now()-E).toFixed(0)),u=Date.now()-E-this.firstDiffTime,0>u&&(this.firstDiffTime=0,u=0),u>v&&(o.error={errorCode:101},this.rtpReturnCallback(o))),w=E,e.frameData=null,(q!==!0||m!==!0)&&(this.decoder.setResolution(b,c),e.frameData=this.decoder.decode(t.subarray(0,g))),e.timeStamp=null,f=null===f.timestamp?this.getTimeStamp():f,e.timeStamp=f,q===!0&&(o.backupData={stream:t.subarray(0,g),width:b,height:c,codecType:"mjpeg"},null!==f.timestamp&&"undefined"!=typeof f.timestamp?o.backupData.timestamp_usec=f.timestamp_usec:o.backupData.timestamp=(k/90).toFixed(0)),g=0,e.playback=m,o.decodedData=e,"canvas"!==decodeMode&&(o.decodeMode="canvas"),this.rtpReturnCallback(o)},getVideoBuffer:function(a){return null!==this.videoBufferList?this.videoBufferList.searchNodeAt(a):void 0},clearBuffer:function(){null!==this.videoBufferList&&this.videoBufferList.clear()},findCurrent:function(){null!==this.videoBufferList&&this.videoBufferList.searchTimestamp(this.getTimeStamp())},findIFrame:function(){null!==this.videoBufferList&&this.videoBufferList.findIFrame()},SetRtpInterlevedID:function(a){this.interleavedID=a},setTimeStamp:function(a){this.timeData=a},getTimeStamp:function(){return this.timeData},getRTPPacket:function(){},calculatePacketTime:function(){},ntohl:function(a){return(a[0]<<24)+(a[1]<<16)+(a[2]<<8)+a[3]>>>0},appendBuffer:function(a,b,c){var d=1048576;if(c+b.length>=a.length){var e=new Uint8Array(a.length+d);e.set(a,0),a=e}return a.set(b,c),a},setFramerate:function(a){a>0&&"undefined"!=typeof a&&(t=a,null!==this.videoBufferList&&(this.videoBufferList.setMaxLength(6*t),this.videoBufferList.setBUFFERING(4*t)))},getFramerate:function(){return t},setReturnCallback:function(a){this.rtpReturnCallback=a},setBufferfullCallback:function(a){null!==this.videoBufferList&&this.videoBufferList.setBufferFullCallback(a)},setGovLength:function(a){q=a},getGovLength:function(){return q},setDecodingTime:function(a){this.decodingTime=a},getDropPercent:function(){return r},getDropCount:function(){return s},initStartTime:function(){this.firstDiffTime=0,this.calcGov=0},setCheckDelay:function(a){this.checkDelay=a}},new a}; -------------------------------------------------------------------------------- /src/module/mp4remux.js: -------------------------------------------------------------------------------- 1 | var MP4Remux=function(){function a(){for(var a in c)c[a]=[a.charCodeAt(0),a.charCodeAt(1),a.charCodeAt(2),a.charCodeAt(3)];b=0,d.FTYP=new Uint8Array([105,115,111,109,0,0,0,1,105,115,111,109,97,118,99,49]),d.STSD_PREFIX=new Uint8Array([0,0,0,0,0,0,0,1]),d.STTS=new Uint8Array([0,0,0,0,0,0,0,0]),d.STSC=d.STCO=d.STTS,d.STSZ=new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0]),d.HDLR_VIDEO=new Uint8Array([0,0,0,0,0,0,0,0,118,105,100,101,0,0,0,0,0,0,0,0,0,0,0,0,86,105,100,101,111,72,97,110,100,108,101,114,0]),d.HDLR_AUDIO=new Uint8Array([0,0,0,0,0,0,0,0,115,111,117,110,0,0,0,0,0,0,0,0,0,0,0,0,83,111,117,110,100,72,97,110,100,108,101,114,0]),d.DREF=new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,12,117,114,108,32,0,0,0,1]),d.SMHD=new Uint8Array([0,0,0,0,0,0,0,0]),d.VMHD=new Uint8Array([0,0,0,1,0,0,0,0,0,0,0,0])}var b,c=[],d={};c={avc1:[],avcC:[],btrt:[],dinf:[],dref:[],esds:[],ftyp:[],hdlr:[],mdat:[],mdhd:[],mdia:[],mfhd:[],minf:[],moof:[],moov:[],mp4a:[],mvex:[],mvhd:[],sdtp:[],stbl:[],stco:[],stsc:[],stsd:[],stsz:[],stts:[],tfdt:[],tfhd:[],traf:[],trak:[],trun:[],trex:[],tkhd:[],vmhd:[],smhd:[]};var e=function(a){for(var b=8,c=Array.prototype.slice.call(arguments,1),d=0;d>>24&255,e[f++]=b>>>16&255,e[f++]=b>>>8&255,e[f++]=255&b,e.set(a,f),f+=4;for(var d=0;d>8,255&a.channelcount,(65280&a.samplesize)>>8,255&a.samplesize,0,0,0,0,(65280&a.samplerate)>>8,255&a.samplerate,0,0]),f(a))},h=function(a){var b=a.sps||[],d=a.pps||[],f=[],g=[],h=0;for(h=0;h>>8),f.push(255&b[h].byteLength),f=f.concat(Array.prototype.slice.call(b[h]));for(h=0;h>>8),g.push(255&d[h].byteLength),g=g.concat(Array.prototype.slice.call(d[h]));return e(c.avc1,new Uint8Array([0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,(65280&a.width)>>8,255&a.width,(65280&a.height)>>8,255&a.height,0,72,0,0,0,72,0,0,0,0,0,0,0,1,19,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,24,17,17]),e(c.avcC,new Uint8Array([1,a.profileIdc,a.profileCompatibility,a.levelIdc,255].concat([b.length]).concat(f).concat([d.length]).concat(g))))},i=function(a){return"audio"===a.type?e(c.stsd,d.STSD_PREFIX,g(a)):e(c.stsd,d.STSD_PREFIX,h(a))},j=function(){return e(c.dinf,e(c.dref,d.DREF))},k=function(a){var b=e(c.stbl,i(a),e(c.stts,d.STTS),e(c.stsc,d.STSC),e(c.stsz,d.STSZ),e(c.stco,d.STCO));return b},l=function(a){var b=a.timescale,d=a.duration;return e(c.mdhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,b>>>24&255,b>>>16&255,b>>>8&255,255&b,d>>>24&255,d>>>16&255,d>>>8&255,255&d,85,196,0,0]))},m=function(a){var b=null;return b="audio"===a.type?d.HDLR_AUDIO:d.HDLR_VIDEO,e(c.hdlr,b)},n=function(a){var b=null;return b="audio"===a.type?e(c.smhd,d.SMHD):e(c.vmhd,d.VMHD),e(c.minf,b,j(),k(a))},o=function(a){var b=a.id,d=a.duration,f=a.width,g=a.height;return e(c.tkhd,new Uint8Array([0,0,0,7,0,0,0,0,0,0,0,0,b>>>24&255,b>>>16&255,b>>>8&255,255&b,0,0,0,0,d>>>24&255,d>>>16&255,d>>>8&255,255&d,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,f>>>8&255,255&f,0,0,g>>>8&255,255&g,0,0]))},p=function(a){return e(c.mdia,l(a),m(a),n(a))},q=function(a){var b=a.id,d=new Uint8Array([0,0,0,0,b>>>24&255,b>>>16&255,b>>>8&255,255&b,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,1]);return e(c.trex,d)},r=function(a,b){return console.log("mvhd: timescale: "+a+" duration: "+b),e(c.mvhd,new Uint8Array([0,0,0,0,0,0,0,0,0,0,0,0,a>>>24&255,a>>>16&255,a>>>8&255,255&a,b>>>24&255,b>>>16&255,b>>>8&255,255&b,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,255,255,255,255]))},s=function(a){return e(c.trak,o(a),p(a))},t=function(a){return e(c.mvex,q(a))},u=function(a){var b=r(a.timescale,a.duration),d=s(a),f=t(a);return e(c.moov,b,d,f)},v=function(a,b){return[0,0,3,5,(4278190080&a.length)>>>24,(16711680&a.length)>>>16,(65280&a.length)>>>8,255&a.length,(4278190080&b)>>>24,(16711680&b)>>>16,(65280&b)>>>8,255&b,0,0,0,0]},w=function(a,b){var d=null,f=null,g=null,h=0,i=b;if(f=a.samples||[],null===f[0].frameDuration)for(i+=24+4*f.length,d=trunHeader(f,i),h=0;h>>24,(16711680&g.size)>>>16,(65280&g.size)>>>8,255&g.size]);else for(i+=24+4*f.length+4*f.length,d=v(f,i),h=0;h>>24,(16711680&g.frameDuration)>>>16,(65280&g.frameDuration)>>>8,255&g.frameDuration,(4278190080&g.size)>>>24,(16711680&g.size)>>>16,(65280&g.size)>>>8,255&g.size]);return e(c.trun,new Uint8Array(d))},x=function(a,b){return"audio"===a.type?audioTrun(a,b):w(a,b)},y=function(a){var b=new Uint8Array([0,0,0,0,a>>>24&255,a>>>16&255,a>>>8&255,255&a]);return e(c.mfhd,b)},z=function(a){var b=null,d=null,f=null,g=null;return b=e(c.tfhd,new Uint8Array([0,2,0,0,0,0,0,1])),d=e(c.tfdt,new Uint8Array([0,0,0,0,a.baseMediaDecodeTime>>>24&255,a.baseMediaDecodeTime>>>16&255,a.baseMediaDecodeTime>>>8&255,255&a.baseMediaDecodeTime])),g=72,f=x(a,g),e(c.traf,b,d,f)},A=function(a,b){return e(c.moof,y(a),z(b))},B=function(a){return e(c.mdat,a)};return a.prototype={initSegment:function(a){var b=e(c.ftyp,d.FTYP);var f=u(a),g=new Uint8Array(b.byteLength+f.byteLength);return g.set(b,0),g.set(f,b.byteLength),g},mediaSegment:function(a,b,c){var d=A(a,b),e=B(c),f=null;return f=new Uint8Array(d.byteLength+e.byteLength),f.set(d),f.set(e,d.byteLength),f}},new a},mp4Remux=new MP4Remux; -------------------------------------------------------------------------------- /src/module/public.js: -------------------------------------------------------------------------------- 1 | function BrowserDetect() { 2 | var a = navigator.userAgent.toLowerCase(), 3 | b = navigator.appName, 4 | c = null; 5 | return ( 6 | "Microsoft Internet Explorer" === b || 7 | a.indexOf("trident") > -1 || 8 | a.indexOf("edge/") > -1 9 | ? ((c = "ie"), 10 | "Microsoft Internet Explorer" === b 11 | ? ((a = /msie ([0-9]{1,}[\.0-9]{0,})/.exec(a)), (c += parseInt(a[1]))) 12 | : a.indexOf("trident") > -1 13 | ? (c += 11) 14 | : a.indexOf("edge/") > -1 && (c = "edge")) 15 | : a.indexOf("safari") > -1 16 | ? (c = a.indexOf("chrome") > -1 ? "chrome" : "safari") 17 | : a.indexOf("firefox") > -1 && (c = "firefox"), 18 | c 19 | ); 20 | } 21 | 22 | var Script = (function () { 23 | function a() {} 24 | return ( 25 | (a.createFromElementId = function (b) { 26 | for (var c = document.getElementById(b), d = "", e = c.firstChild; e; ) 27 | 3 === e.nodeType && (d += e.textContent), (e = e.nextSibling); 28 | var f = new a(); 29 | return (f.type = c.type), (f.source = d), f; 30 | }), 31 | (a.createFromSource = function (b, c) { 32 | var d = new a(); 33 | return (d.type = b), (d.source = c), d; 34 | }), 35 | a 36 | ); 37 | })(), 38 | Shader = (function () { 39 | function a(a, b) { 40 | if ("x-shader/x-fragment" === b.type) 41 | this.shader = a.createShader(a.FRAGMENT_SHADER); 42 | else { 43 | if ("x-shader/x-vertex" !== b.type) 44 | return void error("Unknown shader type: " + b.type); 45 | this.shader = a.createShader(a.VERTEX_SHADER); 46 | } 47 | return ( 48 | a.shaderSource(this.shader, b.source), 49 | a.compileShader(this.shader), 50 | a.getShaderParameter(this.shader, a.COMPILE_STATUS) 51 | ? void 0 52 | : void error( 53 | "An error occurred compiling the shaders: " + 54 | a.getShaderInfoLog(this.shader) 55 | ) 56 | ); 57 | } 58 | return a; 59 | })(), 60 | Program = (function () { 61 | function a(a) { 62 | (this.gl = a), (this.program = this.gl.createProgram()); 63 | } 64 | return ( 65 | (a.prototype = { 66 | attach: function (a) { 67 | this.gl.attachShader(this.program, a.shader); 68 | }, 69 | link: function () { 70 | this.gl.linkProgram(this.program); 71 | }, 72 | use: function () { 73 | this.gl.useProgram(this.program); 74 | }, 75 | getAttributeLocation: function (a) { 76 | return this.gl.getAttribLocation(this.program, a); 77 | }, 78 | setMatrixUniform: function (a, b) { 79 | var c = this.gl.getUniformLocation(this.program, a); 80 | this.gl.uniformMatrix4fv(c, !1, b); 81 | }, 82 | }), 83 | a 84 | ); 85 | })(), 86 | Texture = (function () { 87 | function a(a, b, c) { 88 | (this.gl = a), 89 | (this.size = b), 90 | (this.texture = a.createTexture()), 91 | a.bindTexture(a.TEXTURE_2D, this.texture), 92 | (this.format = c ? c : a.LUMINANCE), 93 | a.texImage2D( 94 | a.TEXTURE_2D, 95 | 0, 96 | this.format, 97 | b.w, 98 | b.h, 99 | 0, 100 | this.format, 101 | a.UNSIGNED_BYTE, 102 | null 103 | ), 104 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_MAG_FILTER, a.NEAREST), 105 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_MIN_FILTER, a.NEAREST), 106 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_WRAP_S, a.CLAMP_TO_EDGE), 107 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_WRAP_T, a.CLAMP_TO_EDGE); 108 | } 109 | var b = null; 110 | return ( 111 | (a.prototype = { 112 | fill: function (a, b) { 113 | var c = this.gl; 114 | c.bindTexture(c.TEXTURE_2D, this.texture), 115 | b 116 | ? c.texSubImage2D( 117 | c.TEXTURE_2D, 118 | 0, 119 | 0, 120 | 0, 121 | this.size.w, 122 | this.size.h, 123 | this.format, 124 | c.UNSIGNED_BYTE, 125 | a 126 | ) 127 | : c.texImage2D( 128 | c.TEXTURE_2D, 129 | 0, 130 | this.format, 131 | this.size.w, 132 | this.size.h, 133 | 0, 134 | this.format, 135 | c.UNSIGNED_BYTE, 136 | a 137 | ); 138 | }, 139 | bind: function (a, c, d) { 140 | var e = this.gl; 141 | b || (b = [e.TEXTURE0, e.TEXTURE1, e.TEXTURE2]), 142 | e.activeTexture(b[a]), 143 | e.bindTexture(e.TEXTURE_2D, this.texture), 144 | e.uniform1i(e.getUniformLocation(c.program, d), a); 145 | }, 146 | }), 147 | a 148 | ); 149 | })(), 150 | base64ArrayBuffer = function (a) { 151 | for ( 152 | var b = "", 153 | c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 154 | d = new Uint8Array(a), 155 | e = d.byteLength, 156 | f = e % 3, 157 | g = e - f, 158 | h = 0, 159 | i = 0, 160 | j = 0, 161 | k = 0, 162 | l = 0, 163 | m = 0; 164 | g > m; 165 | m += 3 166 | ) 167 | (l = (d[m] << 16) | (d[m + 1] << 8) | d[m + 2]), 168 | (h = (16515072 & l) >> 18), 169 | (i = (258048 & l) >> 12), 170 | (j = (4032 & l) >> 6), 171 | (k = 63 & l), 172 | (b += c[h] + c[i] + c[j] + c[k]); 173 | return ( 174 | 1 === f 175 | ? ((l = d[g]), 176 | (h = (252 & l) >> 2), 177 | (i = (3 & l) << 4), 178 | (b += c[h] + c[i] + "==")) 179 | : 2 === f && 180 | ((l = (d[g] << 8) | d[g + 1]), 181 | (h = (64512 & l) >> 10), 182 | (i = (1008 & l) >> 4), 183 | (j = (15 & l) << 2), 184 | (b += c[h] + c[i] + c[j] + "=")), 185 | b 186 | ); 187 | }; 188 | -------------------------------------------------------------------------------- /src/module/public1.js: -------------------------------------------------------------------------------- 1 | function BrowserDetect() { 2 | var a = navigator.userAgent.toLowerCase(), 3 | b = navigator.appName, 4 | c = null; 5 | return ( 6 | "Microsoft Internet Explorer" === b || 7 | a.indexOf("trident") > -1 || 8 | a.indexOf("edge/") > -1 9 | ? ((c = "ie"), 10 | "Microsoft Internet Explorer" === b 11 | ? ((a = /msie ([0-9]{1,}[\.0-9]{0,})/.exec(a)), (c += parseInt(a[1]))) 12 | : a.indexOf("trident") > -1 13 | ? (c += 11) 14 | : a.indexOf("edge/") > -1 && (c = "edge")) 15 | : a.indexOf("safari") > -1 16 | ? (c = a.indexOf("chrome") > -1 ? "chrome" : "safari") 17 | : a.indexOf("firefox") > -1 && (c = "firefox"), 18 | c 19 | ); 20 | } 21 | 22 | var Script = (function () { 23 | function a() {} 24 | return ( 25 | (a.createFromElementId = function (b) { 26 | for (var c = document.getElementById(b), d = "", e = c.firstChild; e; ) 27 | 3 === e.nodeType && (d += e.textContent), (e = e.nextSibling); 28 | var f = new a(); 29 | return (f.type = c.type), (f.source = d), f; 30 | }), 31 | (a.createFromSource = function (b, c) { 32 | var d = new a(); 33 | return (d.type = b), (d.source = c), d; 34 | }), 35 | a 36 | ); 37 | })(), 38 | Shader = (function () { 39 | function a(a, b) { 40 | if ("x-shader/x-fragment" === b.type) 41 | this.shader = a.createShader(a.FRAGMENT_SHADER); 42 | else { 43 | if ("x-shader/x-vertex" !== b.type) 44 | return void error("Unknown shader type: " + b.type); 45 | this.shader = a.createShader(a.VERTEX_SHADER); 46 | } 47 | return ( 48 | a.shaderSource(this.shader, b.source), 49 | a.compileShader(this.shader), 50 | a.getShaderParameter(this.shader, a.COMPILE_STATUS) 51 | ? void 0 52 | : void error( 53 | "An error occurred compiling the shaders: " + 54 | a.getShaderInfoLog(this.shader) 55 | ) 56 | ); 57 | } 58 | return a; 59 | })(), 60 | Program = (function () { 61 | function a(a) { 62 | (this.gl = a), (this.program = this.gl.createProgram()); 63 | } 64 | return ( 65 | (a.prototype = { 66 | attach: function (a) { 67 | this.gl.attachShader(this.program, a.shader); 68 | }, 69 | link: function () { 70 | this.gl.linkProgram(this.program); 71 | }, 72 | use: function () { 73 | this.gl.useProgram(this.program); 74 | }, 75 | getAttributeLocation: function (a) { 76 | return this.gl.getAttribLocation(this.program, a); 77 | }, 78 | setMatrixUniform: function (a, b) { 79 | var c = this.gl.getUniformLocation(this.program, a); 80 | this.gl.uniformMatrix4fv(c, !1, b); 81 | }, 82 | }), 83 | a 84 | ); 85 | })(), 86 | Texture = (function () { 87 | function a(a, b, c) { 88 | (this.gl = a), 89 | (this.size = b), 90 | (this.texture = a.createTexture()), 91 | a.bindTexture(a.TEXTURE_2D, this.texture), 92 | (this.format = c ? c : a.LUMINANCE), 93 | a.texImage2D( 94 | a.TEXTURE_2D, 95 | 0, 96 | this.format, 97 | b.w, 98 | b.h, 99 | 0, 100 | this.format, 101 | a.UNSIGNED_BYTE, 102 | null 103 | ), 104 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_MAG_FILTER, a.NEAREST), 105 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_MIN_FILTER, a.NEAREST), 106 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_WRAP_S, a.CLAMP_TO_EDGE), 107 | a.texParameteri(a.TEXTURE_2D, a.TEXTURE_WRAP_T, a.CLAMP_TO_EDGE); 108 | } 109 | var b = null; 110 | return ( 111 | (a.prototype = { 112 | fill: function (a, b) { 113 | var c = this.gl; 114 | c.bindTexture(c.TEXTURE_2D, this.texture), 115 | b 116 | ? c.texSubImage2D( 117 | c.TEXTURE_2D, 118 | 0, 119 | 0, 120 | 0, 121 | this.size.w, 122 | this.size.h, 123 | this.format, 124 | c.UNSIGNED_BYTE, 125 | a 126 | ) 127 | : c.texImage2D( 128 | c.TEXTURE_2D, 129 | 0, 130 | this.format, 131 | this.size.w, 132 | this.size.h, 133 | 0, 134 | this.format, 135 | c.UNSIGNED_BYTE, 136 | a 137 | ); 138 | }, 139 | bind: function (a, c, d) { 140 | var e = this.gl; 141 | b || (b = [e.TEXTURE0, e.TEXTURE1, e.TEXTURE2]), 142 | e.activeTexture(b[a]), 143 | e.bindTexture(e.TEXTURE_2D, this.texture), 144 | e.uniform1i(e.getUniformLocation(c.program, d), a); 145 | }, 146 | }), 147 | a 148 | ); 149 | })(), 150 | base64ArrayBuffer = function (a) { 151 | for ( 152 | var b = "", 153 | c = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", 154 | d = new Uint8Array(a), 155 | e = d.byteLength, 156 | f = e % 3, 157 | g = e - f, 158 | h = 0, 159 | i = 0, 160 | j = 0, 161 | k = 0, 162 | l = 0, 163 | m = 0; 164 | g > m; 165 | m += 3 166 | ) 167 | (l = (d[m] << 16) | (d[m + 1] << 8) | d[m + 2]), 168 | (h = (16515072 & l) >> 18), 169 | (i = (258048 & l) >> 12), 170 | (j = (4032 & l) >> 6), 171 | (k = 63 & l), 172 | (b += c[h] + c[i] + c[j] + c[k]); 173 | return ( 174 | 1 === f 175 | ? ((l = d[g]), 176 | (h = (252 & l) >> 2), 177 | (i = (3 & l) << 4), 178 | (b += c[h] + c[i] + "==")) 179 | : 2 === f && 180 | ((l = (d[g] << 8) | d[g + 1]), 181 | (h = (64512 & l) >> 10), 182 | (i = (1008 & l) >> 4), 183 | (j = (15 & l) << 2), 184 | (b += c[h] + c[i] + c[j] + "=")), 185 | b 186 | ); 187 | }; 188 | 189 | export { Script, Program, Shader, Texture, base64ArrayBuffer }; 190 | -------------------------------------------------------------------------------- /src/module/videoWorker.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function receiveMessage(a) { 4 | var b = a.data; 5 | switch (channelId = a.data.channelId, b.type) { 6 | case "sdpInfo": 7 | sdpInfo = b.data, framerate = 0, setVideoRtpSession(sdpInfo); 8 | break; 9 | case "MediaData": 10 | if (isStepPlay === !0) { 11 | buffering(b); 12 | break 13 | } 14 | videoCHID = b.data.rtspInterleave[1], "undefined" != typeof videoRtpSessionsArray[videoCHID] && videoRtpSessionsArray[videoCHID].parseRTPData(b.data.rtspInterleave, b.data.payload, isBackupCommand, dropout, b.info); 15 | break; 16 | case "initStartTime": 17 | videoRtpSessionsArray[videoCHID].initStartTime() 18 | } 19 | } 20 | 21 | function setVideoRtpSession(a) { 22 | videoRtpSessionsArray = [], isStepPlay = !1; 23 | for (var b = 0; b < a.sdpInfo.length; b++) rtpSession = null, decodeMode = a.decodeMode, "H264" === a.sdpInfo[b].codecName ? (null === h264Session && (h264Session = H264Session()), rtpSession = h264Session, rtpSession.init(a.decodeMode), rtpSession.setFramerate(a.sdpInfo[b].Framerate), rtpSession.setGovLength(a.govLength), rtpSession.setCheckDelay(a.checkDelay)) : "H265" === a.sdpInfo[b].codecName ? (null === h265Session && (h265Session = H265Session()), rtpSession = h265Session, rtpSession.init(), rtpSession.setFramerate(a.sdpInfo[b].Framerate), rtpSession.setGovLength(a.govLength), rtpSession.setCheckDelay(a.checkDelay)) : "JPEG" === a.sdpInfo[b].codecName ? (null === mjpegSession && (mjpegSession = MjpegSession()), rtpSession = mjpegSession, rtpSession.init(), rtpSession.setFramerate(a.sdpInfo[b].Framerate)) : "stream-assist-frame" === a.sdpInfo[b].codecName && (console.log(a.sdpInfo[b]), null === ivsSession && (ivsSession = IvsSession()), rtpSession = ivsSession, rtpSession.init()), "undefined" != typeof a.sdpInfo[b].Framerate && (framerate = a.sdpInfo[b].Framerate), null !== rtpSession && (rtpSession.setBufferfullCallback(BufferFullCallback), rtpSession.setReturnCallback(RtpReturnCallback), videoCHID = a.sdpInfo[b].RtpInterlevedID, videoRtpSessionsArray[videoCHID] = rtpSession) 24 | } 25 | 26 | function buffering(a) { 27 | videoCHID = a.data.rtspInterleave[1], "undefined" != typeof videoRtpSessionsArray[videoCHID] && videoRtpSessionsArray[videoCHID].bufferingRtpData(a.data.rtspInterleave, a.data.header, a.data.payload) 28 | } 29 | 30 | function BufferFullCallback() { 31 | videoRtpSessionsArray[videoCHID].findCurrent(), sendMessage("stepPlay", "BufferFull") 32 | } 33 | 34 | function RtpReturnCallback(a) { 35 | var b = null, 36 | c = null; 37 | if (null === a || "undefined" == typeof a) return b = null, void (c = null); 38 | if ("undefined" != typeof a.error ? (sendMessage("error", a.error), b = a.decodedData) : (b = a.decodedData, null !== a.decodeMode && "undefined" != typeof a.decodeMode && (decodeMode = a.decodeMode, sendMessage("setVideoTagMode", a.decodeMode))), null !== b && "undefined" != typeof b) 39 | if (null !== b.frameData && "canvas" === decodeMode) { 40 | b.frameData.firstFrame === !0 && sendMessage("firstFrame", b.frameData.firstFrame); 41 | var d = { 42 | bufferIdx: b.frameData.bufferIdx, 43 | width: b.frameData.width, 44 | height: b.frameData.height, 45 | codecType: b.frameData.codecType, 46 | frameType: b.frameData.frameType, 47 | timeStamp: null 48 | }; 49 | null !== b.timeStamp && "undefined" != typeof b.timeStamp && (d.timeStamp = b.timeStamp), sendMessage("videoInfo", d), "undefined" != typeof b.frameData.data && null !== b.frameData.data && sendMessage("canvasRender", b.frameData.data) 50 | } else if (null !== b.frameData && "video" === decodeMode) { 51 | null !== b.initSegmentData && (sendMessage("codecInfo", b.codecInfo), sendMessage("initSegment", b.initSegmentData)); 52 | var d = { 53 | codecType: b.frameData.codecType 54 | }; 55 | "undefined" != typeof b.frameData.width && (d.width = b.frameData.width, d.height = b.frameData.height), sendMessage("videoInfo", d), sendMessage("videoTimeStamp", b.timeStamp), b.frameData.length > 0 && (sendMessage("mediaSample", b.mediaSample), sendMessage("videoRender", b.frameData)) 56 | } else sendMessage("drop", a.decodedData); 57 | null != a.resolution && sendMessage("MSEResolutionChanged", a.resolution), null != a.decodeStart && sendMessage("DecodeStart", a.decodeStart), null != a.ivsDraw && sendMessage("ivsDraw", a.ivsDraw) 58 | } 59 | 60 | function sendMessage(a, b) { 61 | var c = { 62 | type: a, 63 | data: b, 64 | channelId: channelId 65 | }; 66 | "canvasRender" === a ? postMessage(c, [b.buffer]) : postMessage(c) 67 | } 68 | 69 | function VideoBufferList() { 70 | function a() { 71 | b = 360, c = 240, d = null, this._length = 0, this.head = null, this.tail = null, this.curIdx = 0 72 | } 73 | var b = 0, 74 | c = 0, 75 | d = null; 76 | return a.prototype = { 77 | push: function (a, b, e, f, g, h) { 78 | var i = new VideoBufferNode(a, b, e, f, g, h); 79 | return this._length > 0 ? (this.tail.next = i, i.previous = this.tail, this.tail = i) : (this.head = i, this.tail = i), this._length += 1, null !== d && this._length >= c ? d() : 0, i 80 | }, 81 | pop: function () { 82 | var a = null; 83 | return this._length > 1 && (a = this.head, this.head = this.head.next, null !== this.head ? this.head.previous = null : this.tail = null, this._length -= 1), a 84 | }, 85 | setMaxLength: function (a) { 86 | b = a, b > 360 ? b = 360 : 30 > b && (b = 30) 87 | }, 88 | setBUFFERING: function (a) { 89 | c = a, c > 240 ? c = 240 : 6 > c && (c = 6) 90 | }, 91 | setBufferFullCallback: function (a) { 92 | d = a 93 | }, 94 | searchTimestamp: function (a) { 95 | var b = this.head, 96 | c = this._length, 97 | d = 1, 98 | e = { 99 | failure: "Failure: non-existent node in this list." 100 | }; 101 | if (0 === c || 0 >= a || null === b) throw new Error(e.failure); 102 | for (; null !== b && (b.timeStamp.timestamp !== a.timestamp || b.timeStamp.timestamp_usec !== a.timestamp_usec);) b = b.next, d++; 103 | return d > c ? b = null : this.curIdx = d, b 104 | }, 105 | findIFrame: function (a) { 106 | var b = this.head, 107 | c = this._length, 108 | d = 1, 109 | e = { 110 | failure: "Failure: non-existent node in this list." 111 | }; 112 | if (0 === c) throw new Error(e.failure); 113 | for (; d < this.curIdx;) b = b.next, d++; 114 | if (a === !0) 115 | for (; 116 | "I" !== b.frameType;) b = b.next, d++; 117 | else 118 | for (; 119 | "I" !== b.frameType;) b = b.previous, d--; 120 | return d > c ? b = null : this.curIdx = d, b 121 | } 122 | }, new a 123 | } 124 | importScripts("public.js", "mp4remux.js", "h264Session.js", "Decode/h264Decoder.js", "h265Session.js", "Decode/h265Decoder.js", "mjpegSession.js", "Decode/MjpegDecoder.js", "ivsSession.js", "Decode/jsFFMPEG.js", "hashMap.js"); 125 | sendMessage("WorkerReady"); 126 | addEventListener("message", receiveMessage, false); 127 | var videoRtpSessionsArray = [], 128 | sdpInfo = null, 129 | rtpSession = null, 130 | decodeMode = "canvas", 131 | isBackupCommand = !1, 132 | isStepPlay = !1, 133 | isForward = !0, 134 | framerate = 0, 135 | backupFrameInfo = null, 136 | videoCHID = -1, 137 | h264Session = null, 138 | h265Session = null, 139 | mjpegSession = null, 140 | ivsSession = null, 141 | channelId = null, 142 | dropout = 1; -------------------------------------------------------------------------------- /src/mp4remux.js: -------------------------------------------------------------------------------- 1 | 2 | var MP4Remux = function () { 3 | function a() { 4 | for (var a in c) c[a] = [a.charCodeAt(0), a.charCodeAt(1), a.charCodeAt(2), a.charCodeAt(3)]; 5 | b = 0, d.FTYP = new Uint8Array([105, 115, 111, 109, 0, 0, 0, 1, 105, 115, 111, 109, 97, 118, 99, 49]), d.STSD_PREFIX = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1]), d.STTS = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]), d.STSC = d.STCO = d.STTS, d.STSZ = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]), d.HDLR_VIDEO = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 118, 105, 100, 101, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 86, 105, 100, 101, 111, 72, 97, 110, 100, 108, 101, 114, 0]), d.HDLR_AUDIO = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 115, 111, 117, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 83, 111, 117, 110, 100, 72, 97, 110, 100, 108, 101, 114, 0]), d.DREF = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 12, 117, 114, 108, 32, 0, 0, 0, 1]), d.SMHD = new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0]), d.VMHD = new Uint8Array([0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]) 6 | } 7 | var b, c = [], 8 | d = {}; 9 | c = { 10 | avc1: [], 11 | avcC: [], 12 | btrt: [], 13 | dinf: [], 14 | dref: [], 15 | esds: [], 16 | ftyp: [], 17 | hdlr: [], 18 | mdat: [], 19 | mdhd: [], 20 | mdia: [], 21 | mfhd: [], 22 | minf: [], 23 | moof: [], 24 | moov: [], 25 | mp4a: [], 26 | mvex: [], 27 | mvhd: [], 28 | sdtp: [], 29 | stbl: [], 30 | stco: [], 31 | stsc: [], 32 | stsd: [], 33 | stsz: [], 34 | stts: [], 35 | tfdt: [], 36 | tfhd: [], 37 | traf: [], 38 | trak: [], 39 | trun: [], 40 | trex: [], 41 | tkhd: [], 42 | vmhd: [], 43 | smhd: [] 44 | }; 45 | var e = function (a) { 46 | for (var b = 8, c = Array.prototype.slice.call(arguments, 1), d = 0; d < c.length; d++) b += c[d].byteLength; 47 | var e = new Uint8Array(b), 48 | f = 0; 49 | e[f++] = b >>> 24 & 255, e[f++] = b >>> 16 & 255, e[f++] = b >>> 8 & 255, e[f++] = 255 & b, e.set(a, f), f += 4; 50 | for (var d = 0; d < c.length; d++) e.set(c[d], f), f += c[d].byteLength; 51 | return e 52 | }, 53 | f = function (a) { 54 | var b = a.config, 55 | d = b.length, 56 | f = new Uint8Array([0, 0, 0, 0, 3, 23 + d, 0, 1, 0, 4, 15 + d, 64, 21, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5].concat([d]).concat(b).concat([6, 1, 2])); 57 | return e(c.esds, f) 58 | }, 59 | g = function (a) { 60 | return e(c.mp4a, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, (65280 & a.channelcount) >> 8, 255 & a.channelcount, (65280 & a.samplesize) >> 8, 255 & a.samplesize, 0, 0, 0, 0, (65280 & a.samplerate) >> 8, 255 & a.samplerate, 0, 0]), f(a)) 61 | }, 62 | h = function (a) { 63 | var b = a.sps || [], 64 | d = a.pps || [], 65 | f = [], 66 | g = [], 67 | h = 0; 68 | for (h = 0; h < b.length; h++) f.push((65280 & b[h].byteLength) >>> 8), f.push(255 & b[h].byteLength), f = f.concat(Array.prototype.slice.call(b[h])); 69 | for (h = 0; h < d.length; h++) g.push((65280 & d[h].byteLength) >>> 8), g.push(255 & d[h].byteLength), g = g.concat(Array.prototype.slice.call(d[h])); 70 | return e(c.avc1, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (65280 & a.width) >> 8, 255 & a.width, (65280 & a.height) >> 8, 255 & a.height, 0, 72, 0, 0, 0, 72, 0, 0, 0, 0, 0, 0, 0, 1, 19, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 17, 17]), e(c.avcC, new Uint8Array([1, a.profileIdc, a.profileCompatibility, a.levelIdc, 255].concat([b.length]).concat(f).concat([d.length]).concat(g)))) 71 | }, 72 | i = function (a) { 73 | return "audio" === a.type ? e(c.stsd, d.STSD_PREFIX, g(a)) : e(c.stsd, d.STSD_PREFIX, h(a)) 74 | }, 75 | j = function () { 76 | return e(c.dinf, e(c.dref, d.DREF)) 77 | }, 78 | k = function (a) { 79 | var b = e(c.stbl, i(a), e(c.stts, d.STTS), e(c.stsc, d.STSC), e(c.stsz, d.STSZ), e(c.stco, d.STCO)); 80 | return b 81 | }, 82 | l = function (a) { 83 | var b = a.timescale, 84 | d = a.duration; 85 | return e(c.mdhd, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, b >>> 24 & 255, b >>> 16 & 255, b >>> 8 & 255, 255 & b, d >>> 24 & 255, d >>> 16 & 255, d >>> 8 & 255, 255 & d, 85, 196, 0, 0])) 86 | }, 87 | m = function (a) { 88 | var b = null; 89 | return b = "audio" === a.type ? d.HDLR_AUDIO : d.HDLR_VIDEO, e(c.hdlr, b) 90 | }, 91 | n = function (a) { 92 | var b = null; 93 | return b = "audio" === a.type ? e(c.smhd, d.SMHD) : e(c.vmhd, d.VMHD), e(c.minf, b, j(), k(a)) 94 | }, 95 | o = function (a) { 96 | var b = a.id, 97 | d = a.duration, 98 | f = a.width, 99 | g = a.height; 100 | return e(c.tkhd, new Uint8Array([0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, b >>> 24 & 255, b >>> 16 & 255, b >>> 8 & 255, 255 & b, 0, 0, 0, 0, d >>> 24 & 255, d >>> 16 & 255, d >>> 8 & 255, 255 & d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, f >>> 8 & 255, 255 & f, 0, 0, g >>> 8 & 255, 255 & g, 0, 0])) 101 | }, 102 | p = function (a) { 103 | return e(c.mdia, l(a), m(a), n(a)) 104 | }, 105 | q = function (a) { 106 | var b = a.id, 107 | d = new Uint8Array([0, 0, 0, 0, b >>> 24 & 255, b >>> 16 & 255, b >>> 8 & 255, 255 & b, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1]); 108 | return e(c.trex, d) 109 | }, 110 | r = function (a, b) { 111 | return console.log("mvhd: timescale: " + a + " duration: " + b), e(c.mvhd, new Uint8Array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a >>> 24 & 255, a >>> 16 & 255, a >>> 8 & 255, 255 & a, b >>> 24 & 255, b >>> 16 & 255, b >>> 8 & 255, 255 & b, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, 255, 255, 255])) 112 | }, 113 | s = function (a) { 114 | return e(c.trak, o(a), p(a)) 115 | }, 116 | t = function (a) { 117 | return e(c.mvex, q(a)) 118 | }, 119 | u = function (a) { 120 | var b = r(a.timescale, a.duration), 121 | d = s(a), 122 | f = t(a); 123 | return e(c.moov, b, d, f) 124 | }, 125 | v = function (a, b) { 126 | return [0, 0, 3, 5, (4278190080 & a.length) >>> 24, (16711680 & a.length) >>> 16, (65280 & a.length) >>> 8, 255 & a.length, (4278190080 & b) >>> 24, (16711680 & b) >>> 16, (65280 & b) >>> 8, 255 & b, 0, 0, 0, 0] 127 | }, 128 | w = function (a, b) { 129 | var d = null, 130 | f = null, 131 | g = null, 132 | h = 0, 133 | i = b; 134 | if (f = a.samples || [], null === f[0].frameDuration) 135 | for (i += 24 + 4 * f.length, d = trunHeader(f, i), h = 0; h < f.length; h++) g = f[h], d = d.concat([(4278190080 & g.size) >>> 24, (16711680 & g.size) >>> 16, (65280 & g.size) >>> 8, 255 & g.size]); 136 | else 137 | for (i += 24 + 4 * f.length + 4 * f.length, d = v(f, i), h = 0; h < f.length; h++) g = f[h], d = d.concat([(4278190080 & g.frameDuration) >>> 24, (16711680 & g.frameDuration) >>> 16, (65280 & g.frameDuration) >>> 8, 255 & g.frameDuration, (4278190080 & g.size) >>> 24, (16711680 & g.size) >>> 16, (65280 & g.size) >>> 8, 255 & g.size]); 138 | return e(c.trun, new Uint8Array(d)) 139 | }, 140 | x = function (a, b) { 141 | return "audio" === a.type ? audioTrun(a, b) : w(a, b) 142 | }, 143 | y = function (a) { 144 | var b = new Uint8Array([0, 0, 0, 0, a >>> 24 & 255, a >>> 16 & 255, a >>> 8 & 255, 255 & a]); 145 | return e(c.mfhd, b) 146 | }, 147 | z = function (a) { 148 | var b = null, 149 | d = null, 150 | f = null, 151 | g = null; 152 | return b = e(c.tfhd, new Uint8Array([0, 2, 0, 0, 0, 0, 0, 1])), d = e(c.tfdt, new Uint8Array([0, 0, 0, 0, a.baseMediaDecodeTime >>> 24 & 255, a.baseMediaDecodeTime >>> 16 & 255, a.baseMediaDecodeTime >>> 8 & 255, 255 & a.baseMediaDecodeTime])), g = 72, f = x(a, g), e(c.traf, b, d, f) 153 | }, 154 | A = function (a, b) { 155 | return e(c.moof, y(a), z(b)) 156 | }, 157 | B = function (a) { 158 | return e(c.mdat, a) 159 | }; 160 | return a.prototype = { 161 | initSegment: function (a) { 162 | var b = e(c.ftyp, d.FTYP); 163 | var f = u(a), 164 | g = new Uint8Array(b.byteLength + f.byteLength); 165 | return g.set(b, 0), g.set(f, b.byteLength), g 166 | }, 167 | mediaSegment: function (a, b, c) { 168 | var d = A(a, b), 169 | e = B(c), 170 | f = null; 171 | return f = new Uint8Array(d.byteLength + e.byteLength), f.set(d), f.set(e, d.byteLength), f 172 | } 173 | }, new a 174 | }; 175 | 176 | let mp4Remux = new MP4Remux; 177 | 178 | export default mp4Remux; -------------------------------------------------------------------------------- /src/streamdrawer.js: -------------------------------------------------------------------------------- 1 | import { 2 | WebGLCanvas, 3 | ImageWebGLCanvas, 4 | YUVWebGLCanvas, 5 | } from "./module/WebGLCanvas"; 6 | 7 | ("use strict"); 8 | function BufferNode(a) { 9 | (this.buffer = a), (this.previous = null), (this.next = null); 10 | } 11 | function StreamDrawer(a, b, c) { 12 | function d() { 13 | function a() { 14 | (this.first = null), (this.size = 0); 15 | } 16 | var b = 15; 17 | return ( 18 | (a.prototype = { 19 | enqueue: function (a, c, d, e, f, g) { 20 | this.size >= b ? this.clear() : 0; 21 | var h = new K(a, c, d, e, f, g); 22 | if (null === this.first) this.first = h; 23 | else { 24 | for (var i = this.first; null !== i.next; ) i = i.next; 25 | i.next = h; 26 | } 27 | return (this.size += 1), h; 28 | }, 29 | dequeue: function () { 30 | var a = null; 31 | return ( 32 | null !== this.first && 33 | ((a = this.first), 34 | (this.first = this.first.next), 35 | (this.size -= 1)), 36 | a 37 | ); 38 | }, 39 | clear: function () { 40 | console.log("BufferQueue clear!"); 41 | for (var a = null; null !== this.first; ) 42 | (a = this.first), 43 | (this.first = this.first.next), 44 | (this.size -= 1), 45 | (a.buffer = null), 46 | (a = null); 47 | (this.size = 0), (this.first = null); 48 | }, 49 | }), 50 | new a() 51 | ); 52 | } 53 | function e() { 54 | (p = "rgb2d"), (r = null), (L = new d()), (q = F), (E = !1); 55 | } 56 | function f(a, b) { 57 | for ( 58 | var c = atob(a.substring("data:image/png;base64,".length)), 59 | d = new Uint8Array(c.length), 60 | e = 0, 61 | f = c.length; 62 | f > e; 63 | ++e 64 | ) 65 | d[e] = c.charCodeAt(e); 66 | var g = new Blob([d.buffer], { 67 | type: "image/png", 68 | }); 69 | N(g, b + ".png"); 70 | } 71 | function g(a) { 72 | return ( 73 | ("undefined" == typeof n || 74 | "undefined" == typeof o || 75 | n !== a.width || 76 | o !== a.height) && 77 | ((p = "ImageWebGL"), 78 | M(a.width, a.height), 79 | (n = a.width), 80 | (o = a.height), 81 | "undefined" != n && 82 | null != n && 83 | 0 != n && 84 | s({ 85 | width: a.width, 86 | height: a.height, 87 | })), 88 | (w = a.time), 89 | null !== w && i.timeStamp(w), 90 | "undefined" != typeof m 91 | ? (m.drawCanvas(a), D && ((D = !1), f(l.toDataURL(), C)), A.free(a), !0) 92 | : (console.log("drawer is undefined in StreamDrawer!"), !1) 93 | ); 94 | } 95 | function h() { 96 | window.requestAnimationFrame(P); 97 | } 98 | var i = b, 99 | j = !0, 100 | k = a, 101 | l = c, 102 | m = null, 103 | n = null, 104 | o = null, 105 | p = null, 106 | q = null, 107 | r = null, 108 | s = null, 109 | t = null, 110 | u = null, 111 | v = 0, 112 | w = null, 113 | x = 0, 114 | y = 0, 115 | z = 0, 116 | A = new ImagePool(), 117 | B = null, 118 | C = "", 119 | D = !1, 120 | E = !1, 121 | F = 16.7, 122 | G = 20, 123 | H = 1e3, 124 | I = null, 125 | J = 0, 126 | K = (function () { 127 | function a(a, b, c, d, e, f) { 128 | BufferNode.call(this, a), 129 | (this.width = b), 130 | (this.height = c), 131 | (this.codecType = d), 132 | (this.frameType = e), 133 | (this.timeStamp = f); 134 | } 135 | return a; 136 | })(), 137 | L = null, 138 | M = function (a, b) { 139 | var c = new Size(a, b); 140 | switch (p) { 141 | case "RGB2d": 142 | m = new RGB2dCanvas(l, c); 143 | break; 144 | case "YUVWebGL": 145 | m = new YUVWebGLCanvas(l, c); 146 | break; 147 | case "ImageWebGL": 148 | m = new ImageWebGLCanvas(l, c); 149 | break; 150 | case "WebGL": 151 | m = new WebGLCanvas(l, c); 152 | } 153 | }, 154 | N = (function (a) { 155 | var b = a.document, 156 | c = function () { 157 | return a.URL || a.webkitURL || a; 158 | }, 159 | d = b.createElementNS("http://www.w3.org/1999/xhtml", "a"), 160 | e = "download" in d, 161 | f = function (a) { 162 | var b = new MouseEvent("click"); 163 | a.dispatchEvent(b); 164 | }, 165 | g = /constructor/i.test(a.HTMLElement), 166 | h = /CriOS\/[\d]+/.test(navigator.userAgent), 167 | i = function (b) { 168 | (a.setImmediate || a.setTimeout)(function () { 169 | throw b; 170 | }, 0); 171 | }, 172 | j = "application/octet-stream", 173 | k = 4e4, 174 | l = function (a) { 175 | var b = function () { 176 | "string" == typeof a ? c().revokeObjectURL(a) : a.remove(); 177 | }; 178 | setTimeout(b, k); 179 | }, 180 | m = function (a, b, c) { 181 | b = [].concat(b); 182 | for (var d = b.length; d--; ) { 183 | var e = a["on" + b[d]]; 184 | if ("function" == typeof e) 185 | try { 186 | e.call(a, c || a); 187 | } catch (f) { 188 | i(f); 189 | } 190 | } 191 | }, 192 | n = function (a) { 193 | return /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test( 194 | a.type 195 | ) 196 | ? new Blob([String.fromCharCode(65279), a], { 197 | type: a.type, 198 | }) 199 | : a; 200 | }, 201 | o = function (b, i, k) { 202 | k || (b = n(b)); 203 | var o, 204 | p = this, 205 | q = b.type, 206 | r = q === j, 207 | s = function () { 208 | m(p, "writestart progress write writeend".split(" ")); 209 | }, 210 | t = function () { 211 | if ((h || (r && g)) && a.FileReader) { 212 | var d = new FileReader(); 213 | return ( 214 | (d.onloadend = function () { 215 | var b = h 216 | ? d.result 217 | : d.result.replace( 218 | /^data:[^;]*;/, 219 | "data:attachment/file;" 220 | ), 221 | c = a.open(b, "_blank"); 222 | c || (a.location.href = b), 223 | (b = void 0), 224 | (p.readyState = p.DONE), 225 | s(); 226 | }), 227 | d.readAsDataURL(b), 228 | void (p.readyState = p.INIT) 229 | ); 230 | } 231 | if ((o || (o = c().createObjectURL(b)), r)) a.location.href = o; 232 | else { 233 | var e = a.open(o, "_blank"); 234 | e || (a.location.href = o); 235 | } 236 | (p.readyState = p.DONE), s(), l(o); 237 | }; 238 | return ( 239 | (p.readyState = p.INIT), 240 | e 241 | ? ((o = c().createObjectURL(b)), 242 | void setTimeout(function () { 243 | (d.href = o), 244 | (d.download = i), 245 | f(d), 246 | s(), 247 | l(o), 248 | (p.readyState = p.DONE); 249 | })) 250 | : void t() 251 | ); 252 | }, 253 | p = o.prototype, 254 | q = function (a, b, c) { 255 | return new o(a, b || a.name || "download", c); 256 | }; 257 | return "undefined" != typeof navigator && navigator.msSaveOrOpenBlob 258 | ? function (a, b, c) { 259 | return ( 260 | (b = b || a.name || "download"), 261 | c || (a = n(a)), 262 | navigator.msSaveOrOpenBlob(a, b) 263 | ); 264 | } 265 | : ((p.readyState = p.INIT = 0), 266 | (p.WRITING = 1), 267 | (p.DONE = 2), 268 | (p.error = 269 | p.onwritestart = 270 | p.onprogress = 271 | p.onwrite = 272 | p.onabort = 273 | p.onerror = 274 | p.onwriteend = 275 | null), 276 | q); 277 | })(window), 278 | O = function () { 279 | if ( 280 | ((B = L.dequeue()), 281 | null !== B && 282 | null !== B.buffer && 283 | ("mjpeg" === B.codecType || B.buffer.length > 0)) 284 | ) { 285 | if ( 286 | (("undefined" == typeof n || 287 | "undefined" == typeof o || 288 | n !== B.width || 289 | o !== B.height || 290 | r !== B.codecType) && 291 | ((p = 292 | "h264" === B.codecType || "h265" === B.codecType 293 | ? "YUVWebGL" 294 | : "ImageWebGL"), 295 | M(B.width, B.height), 296 | "undefined" == n || null == n || 0 == n 297 | ? t("PlayStart") 298 | : "undefined" != typeof s && 299 | null !== s && 300 | s({ 301 | width: B.width, 302 | height: B.height, 303 | }), 304 | (n = B.width), 305 | (o = B.height), 306 | (r = B.codecType)), 307 | (w = B.timeStamp), 308 | i.timeStamp(w), 309 | "undefined" != typeof m) 310 | ) 311 | return ( 312 | m.drawCanvas(B.buffer), 313 | (l.updatedCanvas = !0), 314 | u(w), 315 | D && ((D = !1), f(l.toDataURL(), C)), 316 | "mjpeg" === B.codecType 317 | ? A.free(B.buffer) 318 | : (delete B.buffer, (B.buffer = null)), 319 | (B.previous = null), 320 | (B.next = null), 321 | (B = null), 322 | !0 323 | ); 324 | console.log("drawer is undefined in StreamDrawer!"); 325 | } 326 | return !1; 327 | }, 328 | P = function (a) { 329 | var b = 200; 330 | if (E === !0) { 331 | if (0 === v || b > a - v) 332 | return ( 333 | 0 === v && (v = a), 334 | void (null !== L && window.requestAnimationFrame(P)) 335 | ); 336 | (z += a - x), 337 | z > y && (O() ? (y += q) : 0), 338 | z > H && ((y = 0), (z = 0)), 339 | (x = a), 340 | window.requestAnimationFrame(P); 341 | } 342 | }; 343 | return ( 344 | (e.prototype = { 345 | getDrawingStrategy: function () { 346 | return p; 347 | }, 348 | reassignCanvas: function () { 349 | var a = $('canvas[kind-channel-id="' + k + '"]')[0]; 350 | l !== a && ((n = 0), (o = 0)); 351 | }, 352 | drawMJPEG: function (a, b, c, d, e, f) { 353 | var h = A.alloc(); 354 | (h.width = b), 355 | (h.height = c), 356 | (h.codecType = d), 357 | (h.frameType = e), 358 | (h.time = f), 359 | (h.onload = function () { 360 | j === !1 361 | ? g(this) 362 | : null !== L && 363 | L.enqueue( 364 | this, 365 | this.width, 366 | this.height, 367 | this.codecType, 368 | this.frameType, 369 | this.time 370 | ); 371 | }), 372 | h.setAttribute( 373 | "src", 374 | "data:image/jpeg;base64," + base64ArrayBuffer(a) 375 | ); 376 | }, 377 | draw: function (a, b, c, d, e, g) { 378 | return j === !1 379 | ? (("undefined" == typeof n || 380 | "undefined" == typeof o || 381 | n !== b || 382 | o !== c || 383 | r !== d) && 384 | ((p = "h264" === d || "h265" === d ? "YUVWebGL" : "ImageWebGL"), 385 | M(b, c), 386 | (n = b), 387 | (o = c), 388 | (r = d), 389 | s({ 390 | width: b, 391 | height: c, 392 | })), 393 | (w = g), 394 | null !== w && i.timeStamp(w), 395 | "undefined" != typeof m 396 | ? (m.drawCanvas(a), 397 | (l.updatedCanvas = !0), 398 | D && ((D = !1), f(l.toDataURL(), C)), 399 | !0) 400 | : (console.log("drawer is undefined in StreamDrawer!"), !1)) 401 | : void (null !== L && L.enqueue(a, b, c, d, e, g)); 402 | }, 403 | capture: function (a) { 404 | (C = a), (D = !0); 405 | }, 406 | digitalZoom: function (a) { 407 | "undefined" != typeof m && null !== m && m.updateVertexArray(a); 408 | }, 409 | setResizeCallback: function (a) { 410 | s = a; 411 | }, 412 | getCodecType: function () { 413 | return r; 414 | }, 415 | getFrameTimestamp: function () { 416 | return w; 417 | }, 418 | initStartTime: function () { 419 | 0 === v && j !== !1 && h(); 420 | }, 421 | startRendering: function () { 422 | null !== L && L.clear(), 423 | 0 === v && j !== !1 && ((E = !0), window.requestAnimationFrame(P)); 424 | }, 425 | stopRendering: function () { 426 | (E = !1), (v = 0); 427 | }, 428 | setFPS: function (a) { 429 | "undefined" == typeof a 430 | ? ((q = F), (I = G)) 431 | : 0 === a 432 | ? ((q = F), (I = G)) 433 | : ((q = H / a), (I = 1 * a)), 434 | (J = q); 435 | }, 436 | setFrameInterval: function (a) { 437 | q = a * J; 438 | }, 439 | getCanvas: function () { 440 | return l; 441 | }, 442 | renewCanvas: function () { 443 | M(n, o), "undefined" != typeof m && null !== m && m.initCanvas(); 444 | }, 445 | setBeginDrawCallback: function (a) { 446 | t = a; 447 | }, 448 | setupdateCanvasCallback: function (a) { 449 | u = a; 450 | }, 451 | terminate: function () { 452 | (v = 0), 453 | (w = null), 454 | null !== L && (L.clear(), (L = null)), 455 | m && m.clearCanvas(), 456 | (m = null); 457 | }, 458 | }), 459 | new e() 460 | ); 461 | } 462 | function Size(a, b) { 463 | function c(a, b) { 464 | (c.prototype.w = a), (c.prototype.h = b); 465 | } 466 | return ( 467 | (c.prototype = { 468 | toString: function () { 469 | return "(" + c.prototype.w + ", " + c.prototype.h + ")"; 470 | }, 471 | getHalfSize: function () { 472 | return new Size(c.prototype.w >>> 1, c.prototype.h >>> 1); 473 | }, 474 | length: function () { 475 | return c.prototype.w * c.prototype.h; 476 | }, 477 | }), 478 | new c(a, b) 479 | ); 480 | } 481 | var ImagePool = function () { 482 | (this.metrics = {}), this._clearMetrics(), (this._objpool = []); 483 | }; 484 | (ImagePool.prototype.alloc = function () { 485 | var a = null; 486 | return ( 487 | 0 === this._objpool.length 488 | ? ((a = new Image()), this.metrics.totalalloc++) 489 | : ((a = this._objpool.pop()), this.metrics.totalfree--), 490 | a 491 | ); 492 | }), 493 | (ImagePool.prototype.free = function (a) { 494 | a.length > 0 && 495 | (console.log("It is not zero length = " + a.length), 496 | this._objpool.push(a), 497 | this.metrics.totalfree++); 498 | }), 499 | (ImagePool.prototype.collect = function () { 500 | this._objpool = []; 501 | var a = this.metrics.totalalloc - this.metrics.totalfree; 502 | this._clearMetrics(a); 503 | }), 504 | (ImagePool.prototype._clearMetrics = function (a) { 505 | (this.metrics.totalalloc = a || 0), (this.metrics.totalfree = 0); 506 | }); 507 | 508 | export { StreamDrawer, Size, ImagePool }; 509 | -------------------------------------------------------------------------------- /src/videoMediaSource.js: -------------------------------------------------------------------------------- 1 | import { BrowserDetect } from "./browserDetect.js"; 2 | 3 | function VideoMediaSource(a) { 4 | function unknownB() {} 5 | 6 | function c() { 7 | h(); 8 | } 9 | 10 | function d(a) { 11 | (Q = []), 12 | Q.push({ 13 | type: "error", 14 | function: q, 15 | }), 16 | Q.push({ 17 | type: "updateend", 18 | function: n, 19 | }), 20 | Q.push({ 21 | type: "update", 22 | function: o, 23 | }); 24 | for (var b = 0; b < Q.length; b++) 25 | a.addEventListener(Q[b].type, Q[b]["function"]); 26 | } 27 | 28 | function e(a) { 29 | (R = []), 30 | R.push({ 31 | type: "durationchange", 32 | function: v, 33 | }), 34 | R.push({ 35 | type: "playing", 36 | function: s, 37 | }), 38 | R.push({ 39 | type: "error", 40 | function: r, 41 | }), 42 | R.push({ 43 | type: "pause", 44 | function: t, 45 | }), 46 | R.push({ 47 | type: "timeupdate", 48 | function: u, 49 | }), 50 | R.push({ 51 | type: "resize", 52 | function: w, 53 | }), 54 | R.push({ 55 | type: "seeked", 56 | function: x, 57 | }), 58 | R.push({ 59 | type: "waiting", 60 | function: y, 61 | }), 62 | R.push({ 63 | type: "canplaythrough", 64 | function: A, 65 | }), 66 | R.push({ 67 | type: "canplay", 68 | function: z, 69 | }), 70 | R.push({ 71 | type: "loadedmetadata", 72 | function: B, 73 | }); 74 | for (var b = 0; b < R.length; b++) 75 | a.addEventListener(R[b].type, R[b]["function"]); 76 | } 77 | 78 | function f(a) { 79 | (S = []), 80 | S.push({ 81 | type: "sourceopen", 82 | function: c, 83 | }), 84 | S.push({ 85 | type: "error", 86 | function: p, 87 | }); 88 | for (var b = 0; b < S.length; b++) 89 | a.addEventListener(S[b].type, S[b]["function"]); 90 | } 91 | 92 | function g() { 93 | var a = 0; 94 | if (null !== Q) 95 | for (a = 0; a < Q.length; a++) 96 | ab.removeEventListener(Q[a].type, Q[a]["function"]); 97 | if (null !== S) 98 | for (a = 0; a < S.length; a++) 99 | _.removeEventListener(S[a].type, S[a]["function"]); 100 | if (null !== R) 101 | for (a = 0; a < R.length; a++) 102 | $.removeEventListener(R[a].type, R[a]["function"]); 103 | } 104 | 105 | function h() { 106 | if (null === _ || "ended" === _.readyState) 107 | return ( 108 | (_ = new MediaSource()), f(_), ($.src = window.URL.createObjectURL(_)) 109 | ); 110 | if (0 === _.sourceBuffers.length) { 111 | _.duration = 0; 112 | var a = 'video/mp4;codecs="avc1.' + E + '"'; 113 | ab = _.addSourceBuffer(a); 114 | d(ab); 115 | } 116 | var b = D(); 117 | return null === b ? void _.endOfStream("network") : ab.appendBuffer(b); 118 | } 119 | 120 | function i(a) { 121 | if (null !== ab && "closed" !== _.readyState && "ended" !== _.readyState) 122 | try { 123 | if (Y.length > 0) return Y.push(a); 124 | ab.updating ? Y.push(a) : ab.appendBuffer(a); 125 | } catch (b) { 126 | Y.length = 0; 127 | W.initVideo(!1); 128 | } 129 | } 130 | 131 | function j() { 132 | try { 133 | $.paused && (G(), T || $.play()); 134 | } catch (error) {} 135 | } 136 | 137 | function k() { 138 | $.paused || U || (console.log("pause"), $.pause()); 139 | } 140 | 141 | function l() { 142 | var a = 60, 143 | b = 10, 144 | c = 1 * ab.buffered.start(ab.buffered.length - 1), 145 | d = 1 * ab.buffered.end(ab.buffered.length - 1); 146 | d - c > a && ab.remove(c, d - b); 147 | } 148 | 149 | function m() { 150 | if (null !== _) 151 | try { 152 | if ( 153 | ab && 154 | ab.buffered.length > 0 && 155 | (l(), 156 | T || 157 | ($.duration - $.currentTime > 1.5 && 158 | ($.currentTime = ($.duration - 1).toFixed(3))), 159 | X) 160 | ) { 161 | var a = 1 * ab.buffered.start(ab.buffered.length - 1), 162 | b = 1 * ab.buffered.end(ab.buffered.length - 1), 163 | c = 0; 164 | if ( 165 | ((c = 0 === $.currentTime ? b - a : b - $.currentTime), 166 | c >= Z + 0.1) 167 | ) { 168 | if (ab.updating) return; 169 | var d = b - Z; 170 | $.currentTime = d.toFixed(3); 171 | } 172 | } 173 | } catch (e) { 174 | console.log("sourceBuffer has been removed"); 175 | } 176 | } 177 | 178 | function n() {} 179 | 180 | function o() { 181 | Y.length > 0 && (ab.updating || (ab.appendBuffer(Y[0]), Y.shift())); 182 | } 183 | 184 | function p() { 185 | console.log("videoMediaSource::onSourceError"); 186 | } 187 | 188 | function q() { 189 | console.log("videoMediaSource::onSourceBufferErrormsg"); 190 | } 191 | 192 | function r() { 193 | console.log("videoMediaSource::onError"), k(); 194 | } 195 | 196 | function s() { 197 | (T = !0), 198 | (U = !1), 199 | console.log("playing "), 200 | db || ((db = !0), I("PlayStart")); 201 | } 202 | 203 | function t() { 204 | (T = !1), 205 | (U = !0), 206 | console.log("暂停播放----------------------------------------------"); 207 | } 208 | 209 | function u() { 210 | var a = 4, 211 | b = 4, 212 | c = parseInt(_.duration, 10), 213 | d = parseInt($.currentTime, 10), 214 | e = L.timestamp - K * (c - d + (1 !== K ? 1 : 0)), 215 | f = { 216 | timestamp: e, 217 | timestamp_usec: 0, 218 | timezone: L.timezone, 219 | }; 220 | 0 === d || 221 | isNaN(c) || 222 | (Math.abs(c - d) > b && 1 === K) || 223 | $.paused || 224 | (null === O 225 | ? (O = f) 226 | : ((O.timestamp <= f.timestamp && K >= 1) || 227 | (O.timestamp > f.timestamp && 1 > K)) && 228 | (P && W.timeStamp(f), 229 | (O = f), 230 | V++, 231 | V > a && H(f.timestamp, "currentTime"))); 232 | } 233 | 234 | function v() { 235 | m(); 236 | } 237 | 238 | function w() { 239 | G(); 240 | } 241 | 242 | function x() { 243 | j(); 244 | } 245 | 246 | function y() { 247 | if (((X = !1), 0 == cb)) (bb = Date.now()), cb++; 248 | else { 249 | cb++; 250 | var a = Date.now() - bb; 251 | cb >= 5 && 6e4 > a && 1.8 >= Z && ((Z += 0.1), (cb = 0), (bb = 0)); 252 | } 253 | } 254 | 255 | function z() {} 256 | 257 | function A() { 258 | X = !0; 259 | } 260 | 261 | function B() {} 262 | 263 | function C(a, b) { 264 | for ( 265 | var c = atob(a.substring("data:image/png;base64,".length)), 266 | d = new Uint8Array(c.length), 267 | e = 0, 268 | f = c.length; 269 | f > e; 270 | ++e 271 | ) 272 | d[e] = c.charCodeAt(e); 273 | var g = new Blob([d.buffer], { 274 | type: "image/png", 275 | }); 276 | gb(g, b + ".png"); 277 | } 278 | var D = null, 279 | E = "", 280 | F = null, 281 | G = null, 282 | H = null, 283 | I = null, 284 | J = null, 285 | K = 1, 286 | L = { 287 | timestamp: 0, 288 | timestamp_usec: 0, 289 | timezone: 0, 290 | }, 291 | M = !1, 292 | N = { 293 | timestamp: 0, 294 | timestamp_usec: 0, 295 | timezone: 0, 296 | }, 297 | O = null, 298 | P = !1, 299 | Q = null, 300 | R = null, 301 | S = null, 302 | T = !1, 303 | U = !0, 304 | V = 0, 305 | W = a, 306 | X = !1, 307 | Y = [], 308 | Z = 0.5, 309 | $ = null, 310 | _ = null, 311 | ab = null, 312 | bb = 0, 313 | cb = 0, 314 | db = !1, 315 | eb = null, 316 | fb = BrowserDetect(); 317 | unknownB.prototype = { 318 | init: function (a) { 319 | J = BrowserDetect(); 320 | ($ = a), 321 | ($.autoplay = "safari" === J ? !1 : !0), 322 | ($.controls = !1), 323 | ($.preload = "auto"), 324 | e($), 325 | h(); 326 | }, 327 | setInitSegmentFunc: function (a) { 328 | D = a; 329 | }, 330 | getVideoElement: function () { 331 | return $; 332 | }, 333 | setCodecInfo: function (a) { 334 | E = a; 335 | }, 336 | setMediaSegment: function (a) { 337 | i(a); 338 | }, 339 | capture: function (a) { 340 | eb && clearInterval(eb); 341 | var b = document.createElement("canvas"); 342 | (b.width = $.videoWidth), 343 | (b.height = $.videoHeight), 344 | X || "edge" === fb 345 | ? (b.getContext("2d").drawImage($, 0, 0, b.width, b.height), 346 | C(b.toDataURL(), a)) 347 | : (eb = setInterval(function () { 348 | X && 349 | (b.getContext("2d").drawImage($, 0, 0, b.width, b.height), 350 | C(b.toDataURL(), a), 351 | clearInterval(eb)); 352 | }, 200)); 353 | }, 354 | setInitSegment: function () { 355 | h(); 356 | }, 357 | setTimeStamp: function (a) { 358 | F = a; 359 | }, 360 | setVideoSizeCallback: function (a) { 361 | G = a; 362 | }, 363 | setAudioStartCallback: function (a) { 364 | H = a; 365 | }, 366 | getPlaybackTimeStamp: function () { 367 | return F; 368 | }, 369 | setSpeedPlay: function (a) { 370 | K = a; 371 | }, 372 | setvideoTimeStamp: function (a) { 373 | var b = 3, 374 | c = Math.abs(L.timestamp - a.timestamp) > b; 375 | if (c === !0 && M === !1) { 376 | (M = !0), (V = 0), (N = a), H(N.timestamp, "init"); 377 | var d = parseInt(_.duration, 10), 378 | e = parseInt($.currentTime, 10), 379 | f = d - e; 380 | setTimeout(function () { 381 | (L = a), (M = !1); 382 | }, 1e3 * f); 383 | } else c === !1 && M === !1 && (L = a); 384 | }, 385 | pause: function () { 386 | k(); 387 | }, 388 | play: function () { 389 | j(); 390 | }, 391 | setPlaybackFlag: function (a) { 392 | P = a; 393 | }, 394 | setTimeStampInit: function () { 395 | (O = null), 396 | (N = { 397 | timestamp: 0, 398 | timestamp_usec: 0, 399 | timezone: 0, 400 | }); 401 | }, 402 | close: function () { 403 | g(), k(); 404 | }, 405 | setBeginDrawCallback: function (a) { 406 | I = a; 407 | }, 408 | terminate: function () { 409 | g(), 410 | "open" === _.readyState && ab && _.removeSourceBuffer(ab), 411 | (ab = null), 412 | _.endOfStream(), 413 | (ab = null), 414 | (_ = null), 415 | ($ = null), 416 | eb && (clearInterval(eb), (eb = null)); 417 | }, 418 | getDuration: function () { 419 | return $.duration - $.currentTime; 420 | }, 421 | getNoWaitFlag: function () { 422 | return "edge" !== fb ? X : !0; 423 | }, 424 | }; 425 | var gb = (function (a) { 426 | var b = a.document, 427 | c = function () { 428 | return a.URL || a.webkitURL || a; 429 | }, 430 | d = b.createElementNS("http://www.w3.org/1999/xhtml", "a"), 431 | e = "download" in d, 432 | f = function (a) { 433 | var b = new MouseEvent("click"); 434 | a.dispatchEvent(b); 435 | }, 436 | g = /constructor/i.test(a.HTMLElement), 437 | h = /CriOS\/[\d]+/.test(navigator.userAgent), 438 | i = function (b) { 439 | (a.setImmediate || a.setTimeout)(function () { 440 | throw b; 441 | }, 0); 442 | }, 443 | j = "application/octet-stream", 444 | k = 4e4, 445 | l = function (a) { 446 | var b = function () { 447 | "string" == typeof a ? c().revokeObjectURL(a) : a.remove(); 448 | }; 449 | setTimeout(b, k); 450 | }, 451 | m = function (a, b, c) { 452 | b = [].concat(b); 453 | for (var d = b.length; d--; ) { 454 | var e = a["on" + b[d]]; 455 | if ("function" == typeof e) 456 | try { 457 | e.call(a, c || a); 458 | } catch (f) { 459 | i(f); 460 | } 461 | } 462 | }, 463 | n = function (a) { 464 | return /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test( 465 | a.type 466 | ) 467 | ? new Blob([String.fromCharCode(65279), a], { 468 | type: a.type, 469 | }) 470 | : a; 471 | }, 472 | o = function (b, i, k) { 473 | k || (b = n(b)); 474 | var o, 475 | p = this, 476 | q = b.type, 477 | r = q === j, 478 | s = function () { 479 | m(p, "writestart progress write writeend".split(" ")); 480 | }, 481 | t = function () { 482 | if ((h || (r && g)) && a.FileReader) { 483 | var d = new FileReader(); 484 | return ( 485 | (d.onloadend = function () { 486 | var b = h 487 | ? d.result 488 | : d.result.replace( 489 | /^data:[^;]*;/, 490 | "data:attachment/file;" 491 | ), 492 | c = a.open(b, "_blank"); 493 | c || (a.location.href = b), 494 | (b = void 0), 495 | (p.readyState = p.DONE), 496 | s(); 497 | }), 498 | d.readAsDataURL(b), 499 | void (p.readyState = p.INIT) 500 | ); 501 | } 502 | if ((o || (o = c().createObjectURL(b)), r)) a.location.href = o; 503 | else { 504 | var e = a.open(o, "_blank"); 505 | e || (a.location.href = o); 506 | } 507 | (p.readyState = p.DONE), s(), l(o); 508 | }; 509 | return ( 510 | (p.readyState = p.INIT), 511 | e 512 | ? ((o = c().createObjectURL(b)), 513 | void setTimeout(function () { 514 | (d.href = o), 515 | (d.download = i), 516 | f(d), 517 | s(), 518 | l(o), 519 | (p.readyState = p.DONE); 520 | })) 521 | : void t() 522 | ); 523 | }, 524 | p = o.prototype, 525 | q = function (a, b, c) { 526 | return new o(a, b || a.name || "download", c); 527 | }; 528 | return "undefined" != typeof navigator && navigator.msSaveOrOpenBlob 529 | ? function (a, b, c) { 530 | return ( 531 | (b = b || a.name || "download"), 532 | c || (a = n(a)), 533 | navigator.msSaveOrOpenBlob(a, b) 534 | ); 535 | } 536 | : ((p.readyState = p.INIT = 0), 537 | (p.WRITING = 1), 538 | (p.DONE = 2), 539 | (p.error = 540 | p.onwritestart = 541 | p.onprogress = 542 | p.onwrite = 543 | p.onabort = 544 | p.onerror = 545 | p.onwriteend = 546 | null), 547 | q); 548 | })(window); 549 | return new unknownB(); 550 | } 551 | 552 | export { VideoMediaSource }; 553 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 3 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 4 | const CopyPlugin = require("copy-webpack-plugin"); 5 | 6 | module.exports = { 7 | entry: './index.js', 8 | output: { 9 | path: path.resolve(__dirname, 'dist'), 10 | filename: 'index.js', 11 | }, 12 | devServer: { 13 | contentBase: path.join(__dirname, 'dist'), 14 | compress: true, 15 | port: 9000 16 | }, 17 | plugins: [ 18 | new CleanWebpackPlugin(), 19 | new HtmlWebpackPlugin({ 20 | template: './src/index.html', 21 | inject: 'body' 22 | }), 23 | new CopyPlugin({ 24 | patterns: [ 25 | { from: "./src/module", to: "module" }, 26 | ], 27 | }), 28 | ], 29 | }; --------------------------------------------------------------------------------