self.Module = { onRuntimeInitialized: function () { } }; self.importScripts("common.js"); // var USE_MISSILE = false; // var decoder_type; // var DECODER_TYPE = kDecoder_decodeer_js; // var DECODER_TYPE = kDecoder_wx_h265_wasm_combine_js; var webglPlayer, canvas, videoWidth, videoHeight, yLength, uvLength; var LOG_LEVEL_JS = 0; var LOG_LEVEL_WASM = 1; var LOG_LEVEL_FFMPEG = 2; var DECODER_H264 = 0; var DECODER_H265 = 1; function Player(){ this.decoder_type = DECODER_TYPE;//DECODER_H265; this.decoding = false; this.webrtcplayerState = playerStateIdle; this.decodeInterval = 5; //编码定时器 this.urgent = false; this.destroied = false; this.decoderworker=null; this.frameBuffer = []; // this.Module = {}; } Player.prototype.setDecoder=function(type) { this.decoder_type = type; } Player.prototype.startDecoder=function(decoder_type){ var self = this; self.setDecoder(decoder_type); switch(decoder_type){ case kDecoder_simd_decoder_js: self.decoderworker=new Worker("decoder_simd.js"); var req = { t: kInitDecoderReq, }; self.decoderworker.postMessage(req); self.decoderworker.onmessage=function (evt) { var objData = evt.data; switch (objData.t) { case kInitDecoderRsp: self.onInitDecoder(objData); break; case kOpenDecoderRsp: self.onOpenDecoder(objData); break; case kVideoFrame: self.onVideoFrame(objData.d); break; default: console.log("Unsupport messsage " + req.t); } } break; case kDecoder_decodeer_js: self.decoderworker=new Worker("decoder.js"); var req = { t: kInitDecoderReq, }; self.decoderworker.postMessage(req); self.decoderworker.onmessage=function (evt) { var objData = evt.data; switch (objData.t) { case kInitDecoderRsp: self.onInitDecoder(objData); break; case kOpenDecoderRsp: self.onOpenDecoder(objData); break; case kVideoFrame: self.onVideoFrame(objData.d); break; default: console.log("Unsupport messsage " + req.t); } } break; // this.decoderworker=new Worker("decoder_missle.js"); case kDecoder_wx_h265_wasm_combine_js: // this.decoderworker=new Worker("prod_decoder.js"); self.Module = {}; self.decoderworker=new Worker("decoder_wx.js"); // self.SetWxDecoder(self.decoderworker,self); var req = { t: kInitDecoderReq, }; self.decoderworker.postMessage(req); self.decoderworker.onmessage=function (evt) { var objData = evt.data; switch (objData.t) { case kInitDecoderRsp: self.onInitDecoder(objData); break; case kOpenDecoderRsp: self.onOpenDecoder(objData); break; case kVideoFrame: self.onVideoFrame(objData); break; default: console.log("Unsupport messsage " + req.t); } } break; case kDecoder_missile_decoder_js: self.decoderworker=new Worker("decoder_missle.js");//prod.h265.wasm.combine.js"); var req = { t: kInitDecoderReq, }; self.decoderworker.postMessage(req); console.log("InitMissleDecoder"); self.decoderworker.onmessage=function (evt) { var objData = evt.data; switch (objData.t) { case kInitDecoderRsp: self.onInitDecoder(objData); break; case kOpenDecoderRsp: self.onOpenDecoder(objData); // self.displayLoop(); // var req = { // t: kInitPlayerReq, // }; // self.postMessage(req); break; case kVideoFrame_Missle: self.onVideoFrame_Missle(objData); break; default: console.log("Unsupport messsage " + req.t); } } // this.InitMissleDecoder(); break; default: console.error("not supported"); } }; Player.prototype.ReqInitDecoder = function(){ var req = { t: kInitDecoderReq, }; this.decoderworker.postMessage(req); } Player.prototype.InitMissleDecoder =function(){ var req = { t: kInitDecoderReq, }; this.decoderworker.postMessage(req); console.log("InitMissleDecoder"); this.decoderworker.onmessage=function (evt) { var objData = evt.data; switch (objData.t) { case kInitDecoderRsp: self.onInitDecoder(objData); break; case kOpenDecoderRsp: self.onOpenDecoder(objData); // self.displayLoop(); // var req = { // t: kInitPlayerReq, // }; // this.postMessage(req); break; case kVideoFrame_Missle: self.onVideoFrame_Missle(objData); break; default: console.log("Unsupport messsage " + req.t); } } } // Player.prototype.SetDecoder = function (worker,self){ // var req = { // t: kInitDecoderReq, // }; // worker.postMessage(req); // worker.onmessage=function (evt) { // var objData = evt.data; // switch (objData.t) { // case kInitDecoderRsp: // self.onInitDecoder(objData); // break; // case kOpenDecoderRsp: // self.onOpenDecoder(objData); // break; // case kVideoFrame: // self.onVideoFrame(objData); // break; // // case kVideoFrame_Missle: // // self.onVideoFrame_Missle(objData); // // break; // case kprodVideoFrame: // self.onVideoFrame_Prod(objData); // break; // case "decode": // console.log("decode"+objData) // break; // default: // console.log("Unsupport messsage " + req.t); // } // } // } Player.prototype.SetWxDecoder = function (worker,self){ worker.onmessage = function(msg){ // 收到胶水代码返回来的消息的处理方式 var data = msg.data; var decodet1=new Date().getTime(); console.log(decodet1,"->worker.onmessage",data.type,data.data) if(typeof self.onmessage == "function"){ self.onmessage(data); // 收到解码器的事件,如果设置了onmessage函数,透传到上层,processor通过这种方式拿到解码器事件 //data.type if(data.type == 'destroy' && typeof self.onterminate == 'function'){ self.onterminate(); worker.terminate(); worker = null; } } } worker.onterminate = function(){ } this.onmessage = function(data){ console.log("player onmessage",data.type); }; this.onterminate = function(){ console.log("playe onterminate"); }; }; Player.prototype.decode = function(buffer){ // 对外api,解码一段数据 if(this.decoderworker){ this.decoderworker.postMessage({ type: 'decode', buffer: buffer, }); } } Player.prototype.destroy = function(){ // 对外api,销毁解码器 this.destroied = true; if(this.decoderworker){ // window.URL.revokeObjectURL(this.url); this.decoderworker.postMessage({type: 'destroy'}); } } Player.prototype.startDecoding = function () { var req = { t: kStartDecodingReq, i: this.urgent ? 0 : this.decodeInterval, }; this.decoderworker.postMessage(req); this.decoding = true; this.webrtcplayerState = playerStatePlaying; this.displayLoop(); }; Player.prototype.pauseDecoding = function () { var req = { t: kPauseDecodingReq }; this.decoderworker.postMessage(req); this.decoding = false; }; Player.prototype.onOpenDecoder=function(objData){ console.log("reqOpenDecoder response " + objData.e + "."); if(objData.e==0){ this.startDecoding(); } } Player.prototype.onInitDecoder = function (objData) { console.log("Init decoder response " + objData.e + "."); this.reqOpenDecoder(); }; Player.prototype.reqOpenDecoder=function(){ var req = { t: kOpenDecoderReq }; this.decoderworker.postMessage(req); } Player.prototype.onFrameData = function (data, len,type) { // console.log("Got data bytes=" + start + "-" + end + "."); if(this.decoder_type===kDecoder_wx_h265_wasm_combine_js){ this.decode(data); }else{ var objData = { t: kFeedDataReq, type:type, d: data }; this.decoderworker.postMessage(objData, [objData.d.packet.buffer]); //见h265dc.js } } // Player.prototype.onFrameData = function (data, len) { // // console.log("Got data bytes=" + start + "-" + end + "."); // if(this.decoder_type===kDecoder_wx_h265_wasm_combine_js){ // this.decode(data); // }else{ // var objData = { // t: kFeedDataReq, // d: data // }; // this.decoderworker.postMessage(objData, [objData.d.packet]); //见h265.js // } // } Player.prototype.startBuffering = function () { this.buffering = true; this.showLoading(); this.pause(); } Player.prototype.stopBuffering = function () { this.buffering = false; this.hideLoading(); this.resume(); } Player.prototype.displayVideoFrame = function (frame) { var audioTimestamp=0; var delay=0 console.log("displayVideoFrame" );//delay=" + delay + "=" + " " + frame.s + " - (" + audioCurTs + " + " + this.beginTimeOffset + ")" + "->" + audioTimestamp); if (audioTimestamp <= 0 || delay <= 0) { this.renderVideoFrame(frame); return true; } return false; }; Player.prototype.displayLoop = function() { // console.log("displayLoop") if (this.webrtcplayerState !== playerStateIdle) { requestAnimationFrame(this.displayLoop.bind(this)); } if(this.frameBuffer.length>0){ console.log("displayLoop ready to display: ",this.frameBuffer.length) var frame = this.frameBuffer[0]; if (this.displayVideoFrame(frame)) { this.frameBuffer.shift(); } } }; Player.prototype.stopDecoder = function() { var req={ t: kPauseDecodingReq, } this.decoderworker.postMessage(req); var req={ t: kUninitDecoderReq, } this.decoderworker.postMessage(req); // this.stopBuffering(); this.webrtcplayerState=playerStateIdle; }; Player.prototype.renderVideoFrame = function (data) { // var self = this; var playFrame={ t: kplayeVideoFrame, d: data } self.postMessage(playFrame,[playFrame.d.data.buffer]) }; Player.prototype.onNetStatus = function (status){ var playStatus={ t: kplaterNetStatus, s: status } self.postMessage(playStatus) } Player.prototype.getBufferTimerLength = function() { if (!this.frameBuffer || this.frameBuffer.length == 0) { return 0; } let oldest = this.frameBuffer[0]; let newest = this.frameBuffer[this.frameBuffer.length - 1]; return newest.s - oldest.s; }; Player.prototype.bufferFrame = function (frame) { // If not decoding, it may be frame before seeking, should be discarded. this.frameBuffer.push(frame); console.log("bufferFrame pts:" + frame.s+" w:" + frame.width + ", h: " + frame.height); } Player.prototype.onVideoFrame = function (frame) { this.bufferFrame(frame); }; Player.prototype.onVideoFrame_Prod = function (frame) { this.bufferFrame(frame); }; Player.prototype.onVideoFrame_Missle = function (frame) { this.bufferFrame(frame); }; Player.prototype.processReq = function (req) { // console.log("processReq " + req.t + "."); switch (req.t) { case kstartPlayerCoderReq: this.startDecoder(req.decoder_type); break; case kendPlayerCoderReq: this.stopDecoder(); break; case kInitPlayerReq: this.displayLoop(); break; case ksendPlayerVideoFrameReq: this.onFrameData(req.d,req.l,"VIDEO"); break; case ksendPlayerAudioFrameReq: this.onFrameData(req.d,req.l,"AUDIO"); break; case kconnectStatusResponse: this.onNetStatus(req.s); break; default: console.log("Unsupport messsage " + req.t); } }; self.player = new Player; self.onmessage = function (evt) { if (!self.player) { console.log("[ER] Player not initialized!"); return; } var req = evt.data; self.player.processReq(req); };