@meframe/core
Version:
Next generation media processing framework based on WebCodecs
131 lines (130 loc) • 3.31 kB
JavaScript
class BaseDecoder {
decoder;
config;
controller = null;
constructor(config) {
this.config = config;
}
async initialize() {
if (this.decoder?.state === "configured") {
return;
}
const isSupported = await this.isConfigSupported(this.config);
if (!isSupported.supported) {
throw new Error(
`Codec not supported: ${this.config.codecString || this.config.codec}`
);
}
this.decoder = this.createDecoder({
output: this.handleOutput.bind(this),
error: this.handleError.bind(this)
});
await this.configureDecoder(this.config);
}
async reconfigure(config) {
this.config = { ...this.config, ...config };
if (!this.decoder) {
await this.initialize();
return;
}
if (this.decoder.state === "configured") {
await this.decoder.flush();
}
const isSupported = await this.isConfigSupported(this.config);
if (!isSupported.supported) {
throw new Error(
`New configuration not supported: ${this.config.codecString || this.config.codec}`
);
}
await this.configureDecoder(this.config);
}
async flush() {
if (!this.decoder) return;
await this.decoder.flush();
}
async reset() {
if (!this.decoder) return;
this.decoder.reset();
this.onReset();
}
async close() {
if (!this.decoder) return;
if (this.decoder.state === "configured") {
await this.decoder.flush();
}
this.decoder.close();
this.decoder = void 0;
}
get isReady() {
return this.decoder?.state === "configured";
}
get queueSize() {
return this.decoder?.decodeQueueSize ?? 0;
}
handleOutput(data) {
if (!this.controller) {
this.closeIfPossible(data);
return;
}
try {
this.controller.enqueue(data);
} catch (error) {
if (error instanceof TypeError) {
this.closeIfPossible(data);
return;
}
throw error;
}
}
handleError(error) {
console.error(`${this.getDecoderType()} decoder error:`, error);
this.controller?.error(error);
}
closeIfPossible(data) {
data?.close?.();
data?.frame?.close?.();
}
onReset() {
}
createStream() {
return new TransformStream(
{
start: async (controller) => {
this.controller = controller;
if (!this.isReady) {
await this.initialize();
}
},
transform: async (input) => {
if (!this.decoder || this.decoder.state !== "configured") {
throw new Error("Decoder not configured");
}
if (this.decoder.decodeQueueSize >= this.decodeQueueThreshold) {
await new Promise((resolve) => {
const check = () => {
if (!this.decoder || this.decoder.decodeQueueSize < this.decodeQueueThreshold - 1) {
resolve();
} else {
setTimeout(check, 10);
}
};
check();
});
}
this.decode(input);
},
flush: async () => {
await this.flush();
}
},
{
highWaterMark: this.highWaterMark,
size: () => 1
}
);
}
}
export {
BaseDecoder as B
};
//# sourceMappingURL=BaseDecoder.js.map