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.
600 lines
17 KiB
600 lines
17 KiB
//https://juejin.cn/post/7050496511288803336
|
|
// mergeInto(LibraryManager.library,{
|
|
// onHeader: function(header){
|
|
// return jsonHeader(header);
|
|
// },
|
|
|
|
// onMediaInfo: function(mediaInfo) {
|
|
// console.log("onMediaInfo"+mediaInfo.toString(16));
|
|
// //Module.postMessage({ type: "mediaInfo", data: mediaInfo });
|
|
// },
|
|
// onAudioDataSize: function(data) {
|
|
// // Module.audioBufferSize = data.size;
|
|
// // Module.audioBuffer = Module._malloc(Module.audioBufferSize);
|
|
// // Module._codecSetAudioBuffer(Module.audioBuffer);
|
|
// },
|
|
// onAudioData: function(data) {
|
|
// // var timestamp = data.timestamp;
|
|
// // Module.audioTimestamps.push(timestamp);
|
|
|
|
// // var u8s = Module.HEAPU8.subarray(
|
|
// // Module.audioBuffer,
|
|
// // Module.audioBuffer + Module.audioBufferSize
|
|
// // );
|
|
|
|
// // var output = null;
|
|
// // if (supportSharedBuffer) {
|
|
// // output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
|
|
// // output.set(u8s);
|
|
// // } else {
|
|
// // output = new Uint8Array(u8s);
|
|
// // }
|
|
|
|
// // Module._free(Module.audioBuffer);
|
|
// // Module.audioBuffer = null;
|
|
// // Module.postMessage(
|
|
// // {
|
|
// // type: "audio",
|
|
// // data: {
|
|
// // buffer: output.buffer,
|
|
// // timestamp: timestamp
|
|
// // }
|
|
// // },
|
|
// // supportSharedBuffer ? undefined : [output.buffer]
|
|
// // );
|
|
// },
|
|
// onVideoDataSize: function(data) {
|
|
// console.log("onVideoDataSize"+data.toString(16));
|
|
// // if (Module.videoBuffer == null) {
|
|
// // Module.videoBufferSize = data.size;
|
|
// // Module.videoBuffer = Module._malloc(Module.videoBufferSize);
|
|
// // if (supportSharedBuffer) {
|
|
// // Module.videoSharedBuffer = new SharedArrayBuffer(data.size);
|
|
// // }
|
|
// // }
|
|
// // Module._codecSetVideoBuffer(Module.videoBuffer);
|
|
// },
|
|
// onVideoData: function(data) {
|
|
// console.log("onVideoData"+data.toString(16));
|
|
// // var timestamp = data.timestamp;
|
|
// // Module.videoTimestamps.push(timestamp);
|
|
|
|
// // var u8s = Module.HEAPU8.subarray(
|
|
// // Module.videoBuffer,
|
|
// // Module.videoBuffer + Module.videoBufferSize
|
|
// // );
|
|
|
|
// // var output = null;
|
|
// // if (supportSharedBuffer) {
|
|
// // output = new Uint8Array(Module.videoSharedBuffer);
|
|
// // output.set(u8s);
|
|
// // } else {
|
|
// // output = new Uint8Array(u8s);
|
|
// // }
|
|
|
|
// // Module.postMessage(
|
|
// // {
|
|
// // type: "video",
|
|
// // data: {
|
|
// // buffer: output.buffer,
|
|
// // timestamp: timestamp,
|
|
// // width: data.width,
|
|
// // height: data.height,
|
|
// // stride0: data.stride0,
|
|
// // stride1: data.stride1
|
|
// // }
|
|
// // },
|
|
// // supportSharedBuffer ? undefined : [output.buffer]
|
|
// // );
|
|
// },
|
|
// onComplete: function() {
|
|
// console.log("onComplete");
|
|
// // Module.postMessage({ type: "complete" });
|
|
// }
|
|
// })
|
|
var Module = {};
|
|
self.importScripts("common.js");
|
|
self.importScripts("videodec_wx_h265.js");
|
|
self.importScripts("raw-parser.js");
|
|
|
|
var isWorker = typeof importScripts == "function";
|
|
var bridgeName = "__CODE_BRIDGE__" + +new Date();
|
|
(isWorker ? self : window)[bridgeName] = {
|
|
onHeader: function(header) {
|
|
onHeader(header);
|
|
// Module.postMessage({ type: "header", data: header });
|
|
},
|
|
onMediaInfo: function(mediaInfo) {
|
|
onMediaInfo(mediaInfo);
|
|
// Module.postMessage({ type: "mediaInfo", data: mediaInfo });
|
|
},
|
|
onAudioDataSize: function(data) {
|
|
onAudioDataSize(data);
|
|
// Module.audioBufferSize = data.size;
|
|
// Module.audioBuffer = Module._malloc(Module.audioBufferSize);
|
|
// Module._codecSetAudioBuffer(Module.audioBuffer);
|
|
},
|
|
onAudioData: function(data) {
|
|
onVideoData(data);
|
|
// var timestamp = data.timestamp;
|
|
// Module.audioTimestamps.push(timestamp);
|
|
|
|
// var u8s = Module.HEAPU8.subarray(
|
|
// Module.audioBuffer,
|
|
// Module.audioBuffer + Module.audioBufferSize
|
|
// );
|
|
|
|
// var output = null;
|
|
// if (supportSharedBuffer) {
|
|
// output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
|
|
// output.set(u8s);
|
|
// } else {
|
|
// output = new Uint8Array(u8s);
|
|
// }
|
|
|
|
// Module._free(Module.audioBuffer);
|
|
// Module.audioBuffer = null;
|
|
// Module.postMessage(
|
|
// {
|
|
// type: "audio",
|
|
// data: {
|
|
// buffer: output.buffer,
|
|
// timestamp: timestamp
|
|
// }
|
|
// },
|
|
// supportSharedBuffer ? undefined : [output.buffer]
|
|
// );
|
|
},
|
|
onVideoDataSize: function(data) {
|
|
onAudioDataSize(data);
|
|
// if (Module.videoBuffer == null) {
|
|
// Module.videoBufferSize = data.size;
|
|
// Module.videoBuffer = Module._malloc(Module.videoBufferSize);
|
|
// if (supportSharedBuffer) {
|
|
// Module.videoSharedBuffer = new SharedArrayBuffer(data.size);
|
|
// }
|
|
// }
|
|
// Module._codecSetVideoBuffer(Module.videoBuffer);
|
|
},
|
|
onVideoData: function(data) {
|
|
onVideoData(data);
|
|
// var timestamp = data.timestamp;
|
|
// Module.videoTimestamps.push(timestamp);
|
|
|
|
// var u8s = Module.HEAPU8.subarray(
|
|
// Module.videoBuffer,
|
|
// Module.videoBuffer + Module.videoBufferSize
|
|
// );
|
|
|
|
// var output = null;
|
|
// if (supportSharedBuffer) {
|
|
// output = new Uint8Array(Module.videoSharedBuffer);
|
|
// output.set(u8s);
|
|
// } else {
|
|
// output = new Uint8Array(u8s);
|
|
// }
|
|
|
|
// Module.postMessage(
|
|
// {
|
|
// type: "video",
|
|
// data: {
|
|
// buffer: output.buffer,
|
|
// timestamp: timestamp,
|
|
// width: data.width,
|
|
// height: data.height,
|
|
// stride0: data.stride0,
|
|
// stride1: data.stride1
|
|
// }
|
|
// },
|
|
// supportSharedBuffer ? undefined : [output.buffer]
|
|
// );
|
|
},
|
|
onComplete: function() {
|
|
onComplete();
|
|
// Module.postMessage({ type: "complete" });
|
|
}
|
|
};
|
|
// var decoder_type = DECODER_H265;
|
|
var ptsIdx=0;
|
|
|
|
H265Frame =[];
|
|
function Decoder(){
|
|
// this.timer=null;
|
|
this.decodeTimer = null;
|
|
this.rawParserObj = null;
|
|
this.wasmLoaded = false;
|
|
this.tmpReqQue = [];
|
|
this.destroied = false;
|
|
// this.poddecoder = null;
|
|
this.supportSharedBuffer = false;
|
|
this.bridgeName = "__CODE_BRIDGE__" + +new Date();
|
|
this.audioTimestamps = []
|
|
this.videoTimestamps = []
|
|
this.audioBufferSize = 0
|
|
this.videoBufferSize = 0
|
|
this.audioBuffer = null
|
|
this.videoBuffer = null
|
|
this.videoSharedBuffer =null;
|
|
// var supportSharedBuffer = false;
|
|
try {
|
|
this.supportSharedBuffer = !!new SharedArrayBuffer(0);
|
|
} catch (e) {
|
|
// nothing to do...
|
|
}
|
|
// this.token = "base64:QXV0aG9yOmNoYW5neWFubG9uZ3xudW1iZXJ3b2xmLEdpdGh1YjpodHRwczovL2dpdGh1Yi5jb20vbnVtYmVyd29sZixFbWFpbDpwb3JzY2hlZ3QyM0Bmb3htYWlsLmNvbSxRUTo1MzEzNjU4NzIsSG9tZVBhZ2U6aHR0cDovL3h2aWRlby52aWRlbyxEaXNjb3JkOm51bWJlcndvbGYjODY5NCx3ZWNoYXI6bnVtYmVyd29sZjExLEJlaWppbmcsV29ya0luOkJhaWR1";
|
|
// this.version = '100.2.0';
|
|
}
|
|
|
|
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 + ".");
|
|
try {
|
|
this.supportSharedBuffer = !!new SharedArrayBuffer(0);
|
|
} catch (e) {
|
|
// nothing to do...
|
|
}
|
|
// this.bridgeName = "__CODE_BRIDGE__" + +new Date();
|
|
Module._codecInit();
|
|
var callbackStr = bridgeName.split("");
|
|
callbackStr = callbackStr
|
|
.map(function(v) {
|
|
return v.charCodeAt(0);
|
|
})
|
|
.concat(0);
|
|
|
|
var callbackStrData = Module._malloc(callbackStr.length - 1);
|
|
Module.HEAPU8.set(callbackStr, callbackStrData);
|
|
Module._codecSetBridgeName(callbackStrData);
|
|
|
|
var objData = {
|
|
t: kInitDecoderRsp,
|
|
e: ret
|
|
};
|
|
self.postMessage(objData);
|
|
};
|
|
|
|
Decoder.prototype.openDecoder = function () {
|
|
|
|
var objData = {
|
|
t: kOpenDecoderRsp,
|
|
e: 0
|
|
};
|
|
self.postMessage(objData);
|
|
|
|
}
|
|
Decoder.prototype.uninitDecoder = function () {
|
|
var ret = 0;//Module._uninitDecoder();
|
|
Module._codecFree();
|
|
console.log("Uninit ffmpeg decoder return " + ret + ".");
|
|
|
|
};
|
|
|
|
Decoder.prototype.onHeader = function(header) {
|
|
console.log("onHeader",header);
|
|
// Module.postMessage({ type: "header", data: header });
|
|
};
|
|
Decoder.prototype.onMediaInfo = function(mediaInfo) {
|
|
console.log("onMediaInfo",mediaInfo);
|
|
// Module.postMessage({ type: "mediaInfo", data: mediaInfo });
|
|
};
|
|
Decoder.prototype.onAudioDataSize = function(data) {
|
|
console.log("onAudioDataSize",data);
|
|
this.audioBufferSize = data.size;
|
|
this.audioBuffer = Module._malloc(this.audioBufferSize);
|
|
Module._codecSetAudioBuffer(this.audioBuffer);
|
|
};
|
|
Decoder.prototype.onAudioData = function(data) {
|
|
var timestamp = data.timestamp;
|
|
this.audioTimestamps.push(timestamp);
|
|
|
|
var u8s = Module.HEAPU8.subarray(
|
|
this.audioBuffer,
|
|
this.audioBuffer +this.audioBufferSize
|
|
);
|
|
|
|
var output = null;
|
|
if (supportSharedBuffer) {
|
|
output = new Uint8Array(new SharedArrayBuffer(u8s.byteLength));
|
|
output.set(u8s);
|
|
} else {
|
|
output = new Uint8Array(u8s);
|
|
}
|
|
|
|
Module._free(this.audioBuffer);
|
|
this.audioBuffer = null;
|
|
// Module.postMessage(
|
|
// {
|
|
// type: "audio",
|
|
// data: {
|
|
// buffer: output.buffer,
|
|
// timestamp: timestamp
|
|
// }
|
|
// },
|
|
// supportSharedBuffer ? undefined : [output.buffer]
|
|
// );
|
|
};
|
|
Decoder.prototype.onVideoDataSize = function(data){
|
|
console.log("onAudioDataSize",data);
|
|
if (this.videoBuffer == null) {
|
|
this.videoBufferSize = data.size;
|
|
this.videoBuffer = Module._malloc(this.videoBufferSize);
|
|
if (this.supportSharedBuffer) {
|
|
this.videoSharedBuffer = new SharedArrayBuffer(data.size);
|
|
}
|
|
}
|
|
Module._codecSetVideoBuffer(this.videoBuffer);
|
|
}
|
|
Decoder.prototype.onVideoData = function(data) {
|
|
var timestamp = data.timestamp;
|
|
this.videoTimestamps.push(timestamp);
|
|
|
|
var u8s = Module.HEAPU8.subarray(
|
|
this.videoBuffer,
|
|
this.videoBuffer + this.videoBufferSize
|
|
);
|
|
|
|
var output = null;
|
|
if (this.supportSharedBuffer) {
|
|
output = new Uint8Array(this.videoSharedBuffer);
|
|
output.set(u8s);
|
|
} else {
|
|
output = new Uint8Array(u8s);
|
|
}
|
|
|
|
// Module.postMessage(
|
|
// {
|
|
// type: "video",
|
|
// data: {
|
|
// buffer: output.buffer,
|
|
// timestamp: timestamp,
|
|
// width: data.width,
|
|
// height: data.height,
|
|
// stride0: data.stride0,
|
|
// stride1: data.stride1
|
|
// }
|
|
// },
|
|
// supportSharedBuffer ? undefined : [output.buffer]
|
|
// );
|
|
var obj = {
|
|
data: output,
|
|
width: data.width,
|
|
height: data.height,
|
|
}
|
|
var objData = {
|
|
t: kprodVideoFrame,
|
|
s: timestamp,
|
|
stride0: data.stride0,
|
|
stride1: data.stride1,
|
|
d: obj
|
|
};
|
|
self.postMessage(objData, [objData.d.data.buffer]);
|
|
};
|
|
|
|
Decoder.prototype.onComplete=function() {
|
|
console.log("onComplete");
|
|
// Module.postMessage({ type: "complete" });
|
|
}
|
|
var decodet1=new Date().getTime();
|
|
Decoder.prototype.decodeVideo=function(){
|
|
if(H265Frame.length>0){
|
|
decodet1=new Date().getTime();
|
|
// var typedArray= H265Frame.shift();//H265Frame[0];//new Uint8Array(H265Frame[0]);
|
|
var typedArray=H265Frame[0];//new Uint8Array(H265Frame[0]);
|
|
var packet=typedArray.d;
|
|
var size = typedArray.size;
|
|
console.log("decode len: " + size)
|
|
var cacheBuffer = Module._malloc(size);
|
|
Module.HEAPU8.set(packet, cacheBuffer);
|
|
// var size = typedArray.length
|
|
// var cacheBuffer = Module._malloc(size);
|
|
// Module.HEAPU8.set(typedArray, cacheBuffer);
|
|
|
|
// this.audioTimestamps = [];
|
|
// this.videoTimestamps = [];
|
|
Module._codecDecode(cacheBuffer, size);
|
|
// this.decode(cacheBuffer)
|
|
|
|
if (cacheBuffer != null) {
|
|
Module._free(cacheBuffer);
|
|
cacheBuffer = null;
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
// Decoder.prototype.decodeVideo = function(){ // 对外api,解码一段数据
|
|
|
|
// }
|
|
|
|
// Decoder.prototype.decode = function(buffer){ // 对外api,解码一段数据
|
|
// var buffer = new Uint8Array(data.buffer);
|
|
// var data = Module._malloc(buffer.length);
|
|
// Module.HEAPU8.set(buffer, data);
|
|
|
|
// var now = +new Date();
|
|
// Module.audioTimestamps = [];
|
|
// Module.videoTimestamps = [];
|
|
// Module._codecDecode(data, buffer.length);
|
|
// // h265decode(buffer);
|
|
// // if(Module){
|
|
|
|
// // // Module.postMessage({
|
|
// // // type: 'decode',
|
|
// // // buffer: buffer,
|
|
// // // });
|
|
// // }
|
|
// }
|
|
|
|
Decoder.prototype.destroy = function(){ // 对外api,销毁解码器
|
|
this.destroied = true;
|
|
// if(Module){
|
|
// // window.URL.revokeObjectURL(this.url);
|
|
// Module.postMessage({type: 'destroy'});
|
|
// }
|
|
}
|
|
|
|
|
|
Decoder.prototype.startDecoding = function (interval) {
|
|
console.log("Start decoding.");
|
|
if (this.decodeTimer) {
|
|
clearInterval(this.decodeTimer);
|
|
}
|
|
this.decodeTimer = setInterval(this.decodeVideo, 0);//interval);
|
|
};
|
|
|
|
Decoder.prototype.pauseDecoding = function () {
|
|
console.log("Pause decoding.");
|
|
if (this.decodeTimer) {
|
|
clearInterval(this.decodeTimer);
|
|
this.decodeTimer = null;
|
|
}
|
|
};
|
|
|
|
Decoder.prototype.sendVideoFrame = function(data,len){
|
|
|
|
var typedArray = new Uint8Array(data);
|
|
if(H265Frame.length>MAX_FRAME_SIZE){
|
|
H265Frame.shift();
|
|
}
|
|
H265Frame.push(typedArray)
|
|
|
|
}
|
|
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.openDecoder();
|
|
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!");
|
|
}
|
|
}
|
|
function onHeader(header){
|
|
if (self.decoder) {
|
|
self.decoder.onHeader(header);
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|
|
function onMediaInfo(mediaInfo){
|
|
if (self.decoder) {
|
|
self.decoder.onMediaInfo(mediaInfo);
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|
|
function onVideoDataSize(data) {
|
|
if (self.decoder) {
|
|
self.decoder.onVideoDataSize(data);
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|
|
function onVideoData(data) {
|
|
if (self.decoder) {
|
|
self.decoder.onVideoData(data);
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|
|
function onAudioDataSize(data) {
|
|
if (self.decoder) {
|
|
self.decoder.onAudioDataSize(data);
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|
|
function onAudioData(data) {
|
|
if (self.decoder) {
|
|
self.decoder.onAudioData(data);
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|
|
function onComplete() {
|
|
if (self.decoder) {
|
|
self.decoder.onComplete();
|
|
} else {
|
|
console.log("[ER] No decoder!");
|
|
}
|
|
}
|