Module = { onRuntimeInitialized: function() { onWasmLoaded() }, } importScripts('libffmpeg.js') var MediaName = null var IsStream = true var FileLen = -1 var SocketObj //WebSocket var CPointer_Buffer = null var CPointer_Cap = 0 function onWasmLoaded() { DeliverVideo = Module.addFunction(function(Buf, BufLen, TimeStamp) { var CPointer_Array = Module.HEAPU8.subarray(Buf, Buf + BufLen) var message = { command: 'deliver_video', sample: { time_stamp: TimeStamp, buf: new Uint8Array(CPointer_Array) }, } self.postMessage(message, [message.sample.buf.buffer]) }, 'viii') DeliverAudio = Module.addFunction(function(Buf, BufLen, TimeStamp) { var CPointer_Array = Module.HEAPU8.subarray(Buf, Buf + BufLen) var message = { command: 'deliver_audio', sample: { time_stamp: TimeStamp, buf: new Uint8Array(CPointer_Array) }, } self.postMessage(message, [message.sample.buf.buffer]) }, 'viii') GetFileLength = Module.addFunction(function() { if (FileLen == -1) { var xhr = new XMLHttpRequest() xhr.open('get', MediaName, false) //false: syn mode xhr.send() FileLen = xhr.getResponseHeader('Content-Length') xhr.abort() } return FileLen }, 'i') ReadFile = Module.addFunction(function(Buf, Pos, Size) { var xhr = new XMLHttpRequest() xhr.open('get', MediaName, false) xhr.responseType = 'arraybuffer' xhr.setRequestHeader('Range', 'bytes=' + Pos + '-' + (Pos + Size - 1)) xhr.send() Module.HEAPU8.set(new Uint8Array(xhr.response), Buf) //Uint8Array(xhr.response).length xhr.abort() }, 'viii') CreateVideo = Module.addFunction(function(Duration, Width, Height) { self.postMessage({ command: 'create_video', param: { duration: Duration, width: Width, height: Height }, }) }, 'viii') CreateAudio = Module.addFunction(function(Channel, SampleRate) { self.postMessage({ command: 'create_audio', param: { channel: Channel, sample_rate: SampleRate }, }) }, 'vii') Module._Initialize( DeliverVideo, DeliverAudio, GetFileLength, ReadFile, CreateVideo, CreateAudio ) self.postMessage({ command: 'initialized' }) } function OnTimer() { Module._Turbo0(null, 0) } function requestWebsocket(url, msg, cb_message) { SocketObj = new WebSocket(url) SocketObj.binaryType = 'arraybuffer' SocketObj.onopen = function(evt) { SocketObj.send(msg) } SocketObj.onerror = function(evt) { console.log('Ws connect error ' + evt.data) } SocketObj.onmessage = cb_message SocketObj.onclose = function() { console.log('Ws closed.') } } function downloadFileByWebsocket(ws, payload) { this.requestWebsocket(ws, payload, function(evt) { if (evt.data.byteLength > CPointer_Cap) { if (CPointer_Buffer != null) Module._free(CPointer_Buffer) CPointer_Cap = evt.data.byteLength CPointer_Buffer = Module._malloc(CPointer_Cap) } var typedArray = new Uint8Array(evt.data) Module.HEAPU8.set(typedArray, CPointer_Buffer) //console.log("websocket data: "+typedArray.length); Module._Turbo0(CPointer_Buffer, typedArray.length) }) } self.onmessage = function(evt) { switch (evt.data.command) { case 'play': { MediaName = evt.data.media_name IsStream = evt.data.other if (IsStream) { downloadFileByWebsocket(MediaName, evt.data.payload) } Module._Play(null, !IsStream) TimerID = setInterval(OnTimer, 5) //此值越小,渲染精度越高,且可增强'双线程缓冲平滑机制'可靠性 break } case 'pause': { Module._Pause() clearInterval(TimerID) break } case 'resume': { Module._Resume() TimerID = setInterval(OnTimer, 5) break } case 'stop': { Module._Stop() clearInterval(TimerID) if (IsStream) { SocketObj.close() if (CPointer_Buffer != null) { Module._free(CPointer_Buffer) CPointer_Buffer = null CPointer_Cap = 0 } } close() //exit worker break } case 'seek': { Module._Seek(evt.data.pos) break } default: return } }