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
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!");
|
||
|
}
|
||
|
}
|