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.
 
 
 
 
 
 

326 lines
10 KiB

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 =[];
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;
// }
};
var decodet1=new Date().getTime();
Decoder.prototype.decode=function(){
if(H265Frame.length>0){
decodet1=new Date().getTime();
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)
Module._decodeData(cacheBuffer, size, 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);
// }
Decode.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);
}
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)
let out_y = HEAPU8.subarray(addr_y, addr_y + stride_y * height)
let out_u = HEAPU8.subarray(addr_u, addr_u + (stride_u * height) / 2)
let out_v = HEAPU8.subarray(addr_v, addr_v + (stride_v * height) / 2)
let buf_y = new Uint8Array(out_y)
let buf_u = new Uint8Array(out_u)
let buf_v = new Uint8Array(out_v)
let data = new Uint8Array(buf_y.length + buf_u.length + buf_v.length)
data.set(buf_y, 0)
data.set(buf_u, buf_y.length)
data.set(buf_v, buf_y.length + buf_u.length)
var obj = {
data: data,
width,
height
}
this.displayVideoFrame(obj);
},'viiiiiiiii');
// 'v': void type
// 'i': 32-bit integer type
// 'j': 64-bit integer type (currently does not exist in JavaScript)
// 'f': 32-bit float type
// 'd': 64-bit float type
// ————————————————
// 版权声明:本文为CSDN博主「xw-何妨吟啸且徐行」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
// 原文链接:https://blog.csdn.net/xuw_xy/article/details/117787294
// var videoSize = 0;
// // typedef void(*VideoCallback)(unsigned char* data_y, unsigned char* data_u, unsigned char* data_v, int line1, int line2, int line3, int width, int height, long pts);
// 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]);
// const t2 = new Date().getTime()-decodet1;
// console.log("decode time:"+t2+" len:"+size);//+" data:"+typedArray.toString(16));
// // decodet1=new Date().getTime();
// // displayVideoFrame(obj);
// });
var ret = Module._openDecoder(decoder_type, videoCallback, LOG_LEVEL_FFMPEG);//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);
if(H265Frame.length>MAX_FRAME_SIZE){
H265Frame.shift();
}
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!");
}
}