130 lines
4.1 KiB
JavaScript
130 lines
4.1 KiB
JavaScript
/*
|
|
* Author: Liu Ninggang
|
|
* File Created: Monday, 27th September 2021 10:28:13 am
|
|
* Last Modified: Wednesday, 29th September 2021 5:36:21 pm
|
|
* Modified By: Liu Ninggang
|
|
* Copyright (c) 2021 TP-LINK
|
|
*/
|
|
|
|
/* eslint-disable */
|
|
|
|
let inputBuffer;
|
|
let outputBuffer;
|
|
let has_init = 0;
|
|
let width, height;
|
|
let dataSeq;
|
|
let decoderType;
|
|
let videoDecoder;
|
|
let dataParams = {};
|
|
var Module = {};
|
|
|
|
postMessage({ hasInstalled: true });
|
|
|
|
const initVideoDecoder = () => {
|
|
videoDecoder = new VideoDecoder({
|
|
output: async (frame) => {
|
|
let { timestamp, format, codedWidth, codedHeight } = frame;
|
|
let param = dataParams[timestamp] || {};
|
|
postMessage({ data: frame, width: codedWidth, height: codedHeight, timestamp, seq: param.seq, format }, [frame]);
|
|
frame.close();
|
|
delete dataParams[timestamp];
|
|
},
|
|
error: (err) => {
|
|
console.log('video decoder error: ', err);
|
|
postMessage({ decodeError: err, state: videoDecoder.state });
|
|
}
|
|
});
|
|
has_init = 1;
|
|
};
|
|
|
|
const initWasmDecoder = (scripts = [], wasmBinary) => {
|
|
Module.wasmBinary = wasmBinary;
|
|
self.importScripts(...scripts);
|
|
|
|
Module.onRuntimeInitialized = function () {
|
|
Module._hevc_decoder_init();
|
|
this.bufferLen = 2304 * 1296 * 8;
|
|
inputBuffer = Module._malloc(this.bufferLen);
|
|
outputBuffer = Module._malloc(this.bufferLen);
|
|
width = Module._malloc(4);
|
|
height = Module._malloc(4);
|
|
has_init = 1;
|
|
postMessage({ hasInit: true });
|
|
};
|
|
};
|
|
|
|
this.onmessage = async function (event) {
|
|
let { cmd } = event.data;
|
|
if (cmd === 'init') {
|
|
decoderType = event.data.decoderType;
|
|
let { scripts, wasmBinary } = event.data;
|
|
|
|
if (decoderType === 'wasm') {
|
|
initWasmDecoder(scripts, wasmBinary);
|
|
} else if (decoderType === 'webcodecs') {
|
|
postMessage({ hasInit: true });
|
|
} else {
|
|
initVideoDecoder();
|
|
initWasmDecoder(scripts, wasmBinary);
|
|
}
|
|
} else if (cmd === 'webcodecs_config') {
|
|
initVideoDecoder();
|
|
|
|
let { data } = event;
|
|
let config = {
|
|
codec: data.codec,
|
|
codeWidth: data.width,
|
|
codeHeight: data.height
|
|
};
|
|
videoDecoder.configure(config);
|
|
width = data.width;
|
|
height = data.height;
|
|
postMessage({ hasWebcodecsConfig: true });
|
|
} else if (cmd === 'decode') {
|
|
if (!has_init) {
|
|
return;
|
|
}
|
|
|
|
let chunk = new Uint8Array(event.data.data);
|
|
let { code_type, pts, timestamp, seq, type } = event.data;
|
|
|
|
if (decoderType === 'webcodecs') {
|
|
if (videoDecoder.state === 'unconfigured' || videoDecoder.state === 'closed') return;
|
|
|
|
let encodedVideoChunk = new EncodedVideoChunk({
|
|
type,
|
|
timestamp,
|
|
data: chunk
|
|
});
|
|
videoDecoder.decode(encodedVideoChunk);
|
|
dataParams[timestamp] = { timestamp, seq, type };
|
|
} else {
|
|
Module.HEAP8.set(chunk, inputBuffer);
|
|
if (seq) {
|
|
dataSeq = seq;
|
|
}
|
|
|
|
let len = Module._hevc_to_yuv(code_type, inputBuffer, chunk.length, outputBuffer, width, height);
|
|
if (len > 0) {
|
|
let data1 = Module.HEAPU8.subarray(width, width + 4);
|
|
let result_width = data1[0] + data1[1] * 256;
|
|
let data2 = Module.HEAPU8.subarray(height, height + 4);
|
|
let result_height = data2[0] + data2[1] * 256;
|
|
|
|
let outArray = Module.HEAPU8.subarray(outputBuffer, outputBuffer + len);
|
|
let outputData = new Uint8Array(outArray);
|
|
if (dataSeq) {
|
|
seq = dataSeq;
|
|
dataSeq = 0;
|
|
}
|
|
postMessage({ data: outputData, pts: pts, width: result_width, height: result_height, timestamp, seq }, [outputData.buffer]);
|
|
}
|
|
}
|
|
} else if (cmd === 'close') {
|
|
if (videoDecoder && videoDecoder.state === 'configured') {
|
|
videoDecoder.close();
|
|
}
|
|
close();
|
|
}
|
|
};
|