TeaWeb/web/js/workers/codec/CodecWorker.ts

134 lines
4.3 KiB
TypeScript
Raw Normal View History

2020-03-31 01:27:59 +02:00
import {CodecType} from "tc-backend/web/codec/Codec";
2018-04-11 17:56:09 +02:00
const prefix = "[CodecWorker] ";
2018-04-18 20:12:10 +02:00
2020-03-31 01:27:59 +02:00
export interface CodecWorker {
2018-04-11 17:56:09 +02:00
name();
2018-04-19 18:42:34 +02:00
initialise?() : string;
2018-04-11 17:56:09 +02:00
deinitialise();
decode(data: Uint8Array);
encode(data: Float32Array) : Uint8Array | string;
reset();
}
2020-03-31 01:27:59 +02:00
let supported_types = {};
export function register_codec(type: CodecType, allocator: (options?: any) => Promise<CodecWorker>) {
supported_types[type] = allocator;
}
let initialize_callback: () => Promise<true | string>;
export function set_initialize_callback(callback: () => Promise<true | string>) {
initialize_callback = callback;
}
2018-04-11 17:56:09 +02:00
2020-03-31 02:11:55 +02:00
export let codec_instance: CodecWorker;
2020-03-31 01:27:59 +02:00
let globally_initialized = false;
let global_initialize_result;
/**
* @param command
* @param data
* @return string on error or object on success
*/
async function handle_message(command: string, data: any) : Promise<string | object> {
switch (command) {
case "global-initialize":
try {
const init_result = globally_initialized ? global_initialize_result : await initialize_callback();
globally_initialized = true;
2020-03-31 01:27:59 +02:00
if(typeof init_result === "string")
throw init_result;
} catch (e) {
if(typeof e === "string")
return e;
throw e;
}
2020-03-31 01:27:59 +02:00
return {};
2018-04-11 17:56:09 +02:00
case "initialise":
2020-03-31 02:11:55 +02:00
console.log(prefix + "Initialize for codec %s", CodecType[data.type as CodecType]);
2020-03-31 01:27:59 +02:00
if(!supported_types[data.type])
return "type unsupported";
try {
2020-03-31 02:11:55 +02:00
codec_instance = await supported_types[data.type](data.options);
2020-03-31 01:27:59 +02:00
} catch(ex) {
console.error(prefix + "Failed to allocate codec: %o", ex);
return typeof ex === "string" ? ex : "failed to allocate codec";
2018-04-11 17:56:09 +02:00
}
2020-03-31 02:11:55 +02:00
const error = codec_instance.initialise();
2020-03-31 01:27:59 +02:00
if(error) return error;
return {};
2018-04-11 17:56:09 +02:00
case "encodeSamples":
if(!codec_instance)
return "codec not initialized/initialize failed";
2020-03-31 01:27:59 +02:00
let encodeArray = new Float32Array(data.length);
2018-04-11 17:56:09 +02:00
for(let index = 0; index < encodeArray.length; index++)
encodeArray[index] = data.data[index];
2020-03-31 02:11:55 +02:00
let encodeResult = codec_instance.encode(encodeArray);
2020-03-31 01:27:59 +02:00
if(typeof encodeResult === "string")
return encodeResult;
else
return { data: encodeResult, length: encodeResult.length };
2018-04-11 17:56:09 +02:00
case "decodeSamples":
if(!codec_instance)
return "codec not initialized/initialize failed";
2020-03-31 01:27:59 +02:00
let decodeArray = new Uint8Array(data.length);
2018-04-11 17:56:09 +02:00
for(let index = 0; index < decodeArray.length; index++)
decodeArray[index] = data.data[index];
2020-03-31 02:11:55 +02:00
let decodeResult = codec_instance.decode(decodeArray);
2020-03-31 01:27:59 +02:00
if(typeof decodeResult === "string")
return decodeResult;
else
return { data: decodeResult, length: decodeResult.length };
2018-04-11 17:56:09 +02:00
case "reset":
2020-03-31 02:11:55 +02:00
codec_instance.reset();
2018-04-11 17:56:09 +02:00
break;
default:
2020-03-31 01:27:59 +02:00
return "unknown command";
2018-04-11 17:56:09 +02:00
}
2020-03-31 01:27:59 +02:00
}
2018-04-18 20:12:10 +02:00
2018-04-11 17:56:09 +02:00
2020-03-31 01:27:59 +02:00
const handle_message_event = (e: MessageEvent) => {
const token = e.data.token;
const received = Date.now();
2018-05-07 11:51:50 +02:00
2020-03-31 01:27:59 +02:00
const send_result = result => {
const data = {};
if(typeof result === "object") {
data["result"] = result;
data["success"] = true;
} else if(typeof result === "string") {
data["error"] = result;
data["success"] = false;
} else {
data["error"] = "invalid result";
data["success"] = false;
}
data["token"] = token;
data["timestamp_received"] = received;
data["timestamp_send"] = Date.now();
2020-03-31 02:11:55 +02:00
postMessage(data, undefined);
2020-03-31 01:27:59 +02:00
};
handle_message(e.data.command, e.data.data).then(res => {
if(token) {
send_result(res);
}
}).catch(error => {
console.warn("An error has been thrown while handing command %s: %o", e.data.command, error);
if(token) {
send_result(typeof error === "string" ? error : "unexpected exception has been thrown");
}
});
};
addEventListener("message", handle_message_event);