1
Fork 0
mirror of https://github.com/jech/galene.git synced 2024-12-22 07:15:47 +01:00

Move MediaPipe initialisation to filter init.

We used to initialise MediaPipe at worker start, which prevented
us from handling errors.  We now do it at filter init, and stop
the stream with an error message if initialisation fails.
This commit is contained in:
Juliusz Chroboczek 2024-12-14 14:48:50 +01:00
parent 3fbe274785
commit 0a14b78d67
2 changed files with 46 additions and 29 deletions

View file

@ -2,17 +2,15 @@
let imageSegmenter; let imageSegmenter;
async function loadImageSegmenter() { async function loadImageSegmenter(model) {
let module = await import('/third-party/tasks-vision/vision_bundle.mjs'); let module = await import('/third-party/tasks-vision/vision_bundle.mjs');
let vision = await module.FilesetResolver.forVisionTasks( let vision = await module.FilesetResolver.forVisionTasks(
"/third-party/tasks-vision/wasm" "/third-party/tasks-vision/wasm"
); );
imageSegmenter = return await module.ImageSegmenter.createFromOptions(vision, {
await module.ImageSegmenter.createFromOptions(vision, {
baseOptions: { baseOptions: {
modelAssetPath: '/third-party/tasks-vision/models/selfie_segmenter.tflite', modelAssetPath: model,
}, },
outputCategoryMask: true, outputCategoryMask: true,
outputConfidenceMasks: false, outputConfidenceMasks: false,
@ -20,19 +18,24 @@ async function loadImageSegmenter() {
}); });
} }
loadImageSegmenter(); onmessage = async e => {
let data = e.data;
onmessage = e => { if(imageSegmenter == null) {
let bitmap = e.data.bitmap; try {
if(!(bitmap instanceof ImageBitmap)) { imageSegmenter = await loadImageSegmenter(data.model);
postMessage(new Error('Bad type for worker data')); if(imageSegmenter == null)
throw new Error("loadImageSegmenter returned null");
} catch(e) {
postMessage(e);
return;
}
postMessage(null);
return; return;
} }
if(!imageSegmenter) { let bitmap = e.data.bitmap;
// not ready yet if(!(bitmap instanceof ImageBitmap)) {
bitmap.close(); postMessage(new Error('Bad type for worker data'));
postMessage(null);
return; return;
} }

View file

@ -1188,6 +1188,30 @@ async function setFilter(c) {
c.userdata.filter = filter; c.userdata.filter = filter;
} }
/**
* Sends a message to a worker, then waits for a reply.
*
* @param {Worker} worker
* @param {any} message
* @param {any[]} [transfer]
*/
async function workerSendReceive(worker, message, transfer) {
let p = new Promise((resolve, reject) => {
worker.onmessage = e => {
if(e && e.data) {
if(e.data instanceof Error)
reject(e.data);
else
resolve(e.data);
} else {
resolve(null);
}
};
});
worker.postMessage(message, transfer);
return await p
}
/** /**
* @type {Object.<string,filterDefinition>} * @type {Object.<string,filterDefinition>}
*/ */
@ -1242,6 +1266,9 @@ let filters = {
if(this.userdata.worker) if(this.userdata.worker)
throw new Error("Worker already running (this shouldn't happen)") throw new Error("Worker already running (this shouldn't happen)")
this.userdata.worker = new Worker('/background-blur-worker.js'); this.userdata.worker = new Worker('/background-blur-worker.js');
await workerSendReceive(this.userdata.worker, {
model: '/third-party/tasks-vision/models/selfie_segmenter.tflite',
});
}, },
cleanup: async function() { cleanup: async function() {
if(this.userdata.worker.onmessage) { if(this.userdata.worker.onmessage) {
@ -1253,23 +1280,10 @@ let filters = {
draw: async function(src, ctx) { draw: async function(src, ctx) {
let bitmap = await createImageBitmap(src); let bitmap = await createImageBitmap(src);
try { try {
let p = new Promise((resolve, reject) => { let result = await workerSendReceive(this.userdata.worker, {
this.userdata.worker.onmessage = e => {
if(e && e.data) {
if(e.data instanceof Error)
reject(e.data);
else
resolve(e.data);
} else {
resolve(null);
}
};
});
this.userdata.worker.postMessage({
bitmap: bitmap, bitmap: bitmap,
timestamp: performance.now(), timestamp: performance.now(),
}, [bitmap]); }, [bitmap]);
let result = await p;
if(!result) if(!result)
return false; return false;