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"); Notify = Module.addFunction(function(Type, Value) { //type 1:播放失败 2:文件播放到末尾 //console.log(Type+" "+Value); if (Type == 1) self.postMessage({ command: "play_failed" }); else if (Type == 2) self.postMessage({ command: "play_end" }); }, "vii"); Module._Initialize( DeliverVideo, DeliverAudio, GetFileLength, ReadFile, CreateVideo, CreateAudio, Notify ); 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; } };