You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

271 lines
7.8 KiB

2 years ago
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");
var decoder_type = DECODER_H265;
var pts=0;
H265Frame =[];
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 = Module._uninitDecoder();
console.log("Uninit ffmpeg decoder return " + ret + ".");
// if (this.cacheBuffer != null) {
// Module._free(this.cacheBuffer);
// this.cacheBuffer = null;
// }
};
var decodet1=new Date().getTime();
Decoder.prototype.decode=function(){
if(H265Frame.length>0){
var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]);
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)
const t2 = new Date().getTime()-decodet1;
console.log("decode time:"+t2+" len:"+size);//+" data:"+typedArray.toString(16));
Module._decodeData(cacheBuffer, size, pts++)
if (cacheBuffer != null) {
Module._free(cacheBuffer);
cacheBuffer = null;
}
H265Frame.shift();
decodet1=new Date().getTime();
}
}
Decoder.prototype.startDecoding = function (interval) {
console.log("Start decoding.");
if (this.decodeTimer) {
clearInterval(this.decodeTimer);
}
this.decodeTimer = setInterval(this.decode, 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.decode_seq=function() {
var start_time = new Date();
var videoSize = 0;
var videoCallback = Module.addFunction(function (addr_y, addr_u, addr_v, stride_y, stride_u, stride_v, width, height, pts) {
console.log("[%d]In video callback, size = %d * %d, pts = %d", ++videoSize, width, height, pts)
// if (pts===2147483647){
// return;
// }
let size = width * height + (width / 2) * (height / 2) + (width / 2) * (height / 2)
let data = new Uint8Array(size)
let pos = 0
for(let i=0; i< height; i++) {
let src = addr_y + i * stride_y
let tmp = HEAPU8.subarray(src, src + width)
tmp = new Uint8Array(tmp)
data.set(tmp, pos)
pos += tmp.length
}
for(let i=0; i< height / 2; i++) {
let src = addr_u + i * stride_u
let tmp = HEAPU8.subarray(src, src + width / 2)
tmp = new Uint8Array(tmp)
data.set(tmp, pos)
pos += tmp.length
}
for(let i=0; i< height / 2; i++) {
let src = addr_v + i * stride_v
let tmp = HEAPU8.subarray(src, src + width / 2)
tmp = new Uint8Array(tmp)
data.set(tmp, pos)
pos += tmp.length
}
var obj = {
data: data,
width,
height
}
var objData = {
t: kVideoFrame,
s: pts,
d: obj
};
self.postMessage(objData, [objData.d.data.buffer]);
// displayVideoFrame(obj);
});
var ret = Module._openDecoder(decoder_type, videoCallback, LOG_LEVEL_WASM)
if(ret == 0) {
console.log("openDecoder success");
} else {
console.error("openDecoder failed with error", ret);
// return;
}
var objData = {
t: kOpenDecoderRsp,
e: ret
};
self.postMessage(objData);
}
Decoder.prototype.sendVideoFrame = function(data,len){
var typedArray = new Uint8Array(data);
H265Frame.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.sendVideoFrame(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!");
}
}