self.Module = { onRuntimeInitialized: function () { onWasmLoaded(); } }; var LOG_LEVEL_JS = 0; var LOG_LEVEL_WASM = 1; var LOG_LEVEL_FFMPEG = 2; var DECODER_H264 = 0; var DECODER_H265 = 1; self.importScripts("common.js"); // self.importScripts("libffmpeg_264_265.js"); // self.importScripts("libffmpeg_265.js") self.importScripts("libffmpeg_265.js") var decoder_type = DECODER_H265; var pts=0; H265Frame =[]; AudioFrame =[]; function Decoder(){ // this.timer=null; this.decodeTimer = null; this.wasmLoaded = false; this.tmpReqQue = []; } Decoder.prototype.cacheReq = function (req) { if (req) { this.tmpReqQue.push(req); } }; Decoder.prototype.onWasmLoaded = function () { console.log("Wasm loaded."); this.wasmLoaded = true; while (this.tmpReqQue.length > 0) { var req = this.tmpReqQue.shift(); this.processReq(req); } } Decoder.prototype.initDecoder = function () { // var ret = Module._initDecoder(fileSize, this.coreLogLevel); var ret=0; console.log("initDecoder return " + ret + "."); // if (0 == ret) { // this.cacheBuffer = Module._malloc(chunkSize); // } // this.frameBuffer.length=0; var objData = { t: kInitDecoderRsp, e: ret }; self.postMessage(objData); }; Decoder.prototype.uninitDecoder = function () { var ret = 0;//Module._uninitDecoder(); console.log("Uninit ffmpeg decoder return " + ret + "."); // if (this.cacheBuffer != null) { // Module._free(this.cacheBuffer); // this.cacheBuffer = null; // } }; const MIN_FRAME_FOR_DECODE=0 var decodet1=new Date().getTime(); Decoder.prototype.decode=function(){ if(H265Frame.length>MIN_FRAME_FOR_DECODE){ // decodet1=new Date().getTime(); // var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]); // var size = typedArray.length // console.log("decode len: " + size) // var cacheBuffer = Module._malloc(size); // Module.HEAPU8.set(typedArray, cacheBuffer); decodet1=new Date().getTime(); var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]); var packet=typedArray.d; var size = typedArray.size; // console.log("decode len: " + size) console.log("decode pts:",typedArray.pts," packet len:",size," H265Frame total",H265Frame.length) var cacheBuffer = Module._malloc(size); Module.HEAPU8.set(packet, cacheBuffer); // totalSize += size // console.log("[" + (++readerIndex) + "] Read len = ", size + ", Total size = " + totalSize) // console.log(typedArray.toString(16)); Module._decodeData(cacheBuffer, size, typedArray.pts) if (cacheBuffer != null) { Module._free(cacheBuffer); cacheBuffer = null; } H265Frame.shift(); } } Decoder.prototype.startDecoding = function (interval) { console.log("Start decoding."); if (this.decodeTimer) { clearInterval(this.decodeTimer); } this.decodeTimer = setInterval(this.decode, 0);//interval); }; Decoder.prototype.pauseDecoding = function () { console.log("Pause decoding."); if (this.decodeTimer) { clearInterval(this.decodeTimer); this.decodeTimer = null; } }; // Decoder.prototype.startdecode=function(){ // // this.timer = requestAnimationFrame(function fn() { // // // if(this.decodertimer++>=60) // // this.decodertimer=0; // // this.decode(); // // requestAnimationFrame(fn); // // }) // // move = parseInt(getComputedStyle(box).left); // // if (move < 800) { // // box.style.left = move + 8 + 'px'; // // requestAnimationFrame(fn); // // } else { // // cancelAnimationFrame(timer); // } Decoder.prototype.displayVideoFrame = function displayVideoFrame(obj){ // var obj = { // data: data, // width, // height // } var objData = { t: kVideoFrame, s: pts, d: obj }; self.postMessage(objData, [objData.d.data.buffer]); const t2 = new Date().getTime()-decodet1; console.log("decode time:"+t2+" len:"+size);//+" data:"+typedArray.toString(16)); // decodet1=new Date().getTime(); // displayVideoFrame(obj); } IsGreyData = function(data) { var isgray=false; var len=data.length<100?data.length:100; for(var i=0; iMAX_FRAME_SIZE){ // H265Frame.shift(); // } if(type==="VIDEO"){ H265Frame.push(typedArray) }else if(type==="AUDIO"){ AUDIOFrame.push(typedArray) } // var size = typedArray.length // var cacheBuffer = Module._malloc(size); // Module.HEAPU8.set(typedArray, cacheBuffer); // // totalSize += size // // console.log("[" + (++readerIndex) + "] Read len = ", size + ", Total size = " + totalSize) // Module._decodeData(cacheBuffer, size, pts++) // if (cacheBuffer != null) { // Module._free(cacheBuffer); // cacheBuffer = null; // } // if(size < CHUNK_SIZE) { // console.log('Flush frame data') // Module._flushDecoder(); // Module._closeDecoder(); // } } Decoder.prototype.closeDecoder = function () { console.log("closeDecoder."); if (this.decodeTimer) { clearInterval(this.decodeTimer); this.decodeTimer = null; console.log("Decode timer stopped."); } // var ret = Module._closeDecoder(); console.log("Close ffmpeg decoder return " + ret + "."); var objData = { t: kCloseDecoderRsp, e: 0 }; self.postMessage(objData); }; Decoder.prototype.processReq = function (req) { // console.log("processReq " + req.t + "."); switch (req.t) { case kInitDecoderReq: this.initDecoder(); break; case kUninitDecoderReq: this.uninitDecoder(); break; case kOpenDecoderReq: this.decode_seq(); break; case kCloseDecoderReq: this.closeDecoder(); break; case kStartDecodingReq: this.startDecoding(req.i); break; case kPauseDecodingReq: this.pauseDecoding(); break; case kFeedDataReq: this.sendFrame(req.d,req.type); // if(req.type==="VIDEO"){ // this.sendVideoFrame(req.d); // }else{ // this.sendAudioFrame(req.d); // } break; // case kSeekToReq: // this.seekTo(req.ms); // break; default: this.logger.logError("Unsupport messsage " + req.t); } }; self.decoder = new Decoder; self.onmessage = function (evt) { if (!self.decoder) { console.log("[ER] Decoder not initialized!"); return; } var req = evt.data; if (!self.decoder.wasmLoaded) { self.decoder.cacheReq(req); console.log("Temp cache req " + req.t + "."); return; } self.decoder.processReq(req); }; function onWasmLoaded() { if (self.decoder) { self.decoder.onWasmLoaded(); } else { console.log("[ER] No decoder!"); } }