Skip to content

Commit

Permalink
fix: worker unload
Browse files Browse the repository at this point in the history
  • Loading branch information
kybarg committed Aug 24, 2022
1 parent b6d66c6 commit b888906
Showing 1 changed file with 74 additions and 68 deletions.
142 changes: 74 additions & 68 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,134 +1,140 @@
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import PropTypes from 'prop-types'
import WebWorker from 'web-worker:./worker'
import * as React from "react";
import PropTypes from "prop-types";
import WebWorker from "web-worker:./worker";

const createWorker = () => new WebWorker()
const createWorker = () => new WebWorker();

const stopMediaStream = (stream) => {
if (stream) {
if (stream.getVideoTracks && stream.getAudioTracks) {
stream.getVideoTracks().map(track => {
stream.getVideoTracks().forEach((track) => {
stream.removeTrack(track);
track.stop();
});
stream.getAudioTracks().map(track => {
stream.getAudioTracks().forEach((track) => {
stream.removeTrack(track);
track.stop();
});
}
else {
} else {
stream.stop();
}
}
}
};

const Reader = (props) => {
const { constraints, onError, onLoad, onScan, resolution, ...other } = props
const constraintsStr = JSON.stringify(constraints)
const { constraints, onError, onLoad, onScan, resolution, ...other } = props;
const constraintsStr = JSON.stringify(constraints);

const streamRef = useRef(null)
const videoEl = useRef(null)
const canvasEl = useRef(document.createElement('canvas'))
const ctxRef = useRef(null)
const requestRef = useRef()
const [src, setSrc] = useState(null)
const streamRef = React.useRef(null);
const videoEl = React.useRef(null);
const canvasEl = React.useRef(document.createElement("canvas"));
const ctxRef = React.useRef(null);
const requestRef = React.useRef();
const [src, setSrc] = React.useState(null);

const isProcessingRef = useRef(false)
const worker = useMemo(createWorker, [createWorker])
const isProcessingRef = React.useRef(false);
const workerRef = React.useRef();

useEffect(() => {
return () => {
worker.terminate()
}
}, [worker])
React.useEffect(() => {
workerRef.current = createWorker();
const worker = workerRef.current;

useEffect(() => {
worker.onmessage = (e) => {
if (onScan) onScan(e.data ? { ...e.data, canvas: canvasEl.current } : null)
isProcessingRef.current = false
}
}, [onScan, worker])
if (onScan)
onScan(e.data ? { ...e.data, canvas: canvasEl.current } : null);
isProcessingRef.current = false;
};

const check = useCallback(() => {
const videoIsPlaying = videoEl.current && videoEl.current.readyState === videoEl.current.HAVE_ENOUGH_DATA
return () => {
worker.terminate();
};
}, [onScan]);

const check = React.useCallback(() => {
const worker = workerRef.current;

const videoIsPlaying =
videoEl.current &&
videoEl.current.readyState === videoEl.current.HAVE_ENOUGH_DATA;

if (!isProcessingRef.current && videoIsPlaying) {
isProcessingRef.current = true
isProcessingRef.current = true;

// Get image/video dimensions
let width = videoEl.current.videoWidth
let height = videoEl.current.videoHeight
let width = videoEl.current.videoWidth;
let height = videoEl.current.videoHeight;

const greatestSize = width > height ? width : height
const ratio = resolution / greatestSize
const greatestSize = width > height ? width : height;
const ratio = resolution / greatestSize;

height = ratio * height
width = ratio * width
height = ratio * height;
width = ratio * width;

canvasEl.current.width = width
canvasEl.current.height = height
canvasEl.current.width = width;
canvasEl.current.height = height;

ctxRef.current = canvasEl.current.getContext('2d')
ctxRef.current.drawImage(videoEl.current, 0, 0, width, height)
const imageData = ctxRef.current.getImageData(0, 0, width, height)
ctxRef.current = canvasEl.current.getContext("2d");
ctxRef.current.drawImage(videoEl.current, 0, 0, width, height);
const imageData = ctxRef.current.getImageData(0, 0, width, height);
// Send data to web-worker
worker.postMessage(imageData)
worker.postMessage(imageData);
}

requestRef.current = requestAnimationFrame(check)
}, [resolution, worker])
requestRef.current = requestAnimationFrame(check);
}, [resolution]);

useEffect(() => {
const constraints = JSON.parse(constraintsStr)
React.useEffect(() => {
const constraints = JSON.parse(constraintsStr);

let isSubscribed = true
navigator.mediaDevices.getUserMedia(constraints)
let isSubscribed = true;
navigator.mediaDevices
.getUserMedia(constraints)
.then((stream) => {
if (!isSubscribed) {
stopMediaStream(stream)
stopMediaStream(stream);
} else {
streamRef.current = stream
streamRef.current = stream;

try {
if (videoEl.current) {
videoEl.current.srcObject = stream
videoEl.current.setAttribute('playsinline', true) // required to tell iOS safari we don't want fullscreen
videoEl.current.srcObject = stream;
videoEl.current.setAttribute("playsinline", true); // required to tell iOS safari we don't want fullscreen
}
} catch (error) {
setSrc(window.URL.createObjectURL(stream))
setSrc(window.URL.createObjectURL(stream));
}

if (onLoad) onLoad()
if (onLoad) onLoad();

requestRef.current = requestAnimationFrame(check)
requestRef.current = requestAnimationFrame(check);
}
})
.catch(error => (isSubscribed ? onError(error) : null))
.catch((error) => (isSubscribed ? onError(error) : null));

return () => {
cancelAnimationFrame(requestRef.current)
isSubscribed = false
stopMediaStream(streamRef.current)
cancelAnimationFrame(requestRef.current);
isSubscribed = false;
stopMediaStream(streamRef.current);
if (src) {
window.URL.revokeObjectURL(src);
}
}
}, [check, constraintsStr, onError, onLoad])
};
}, [check, constraintsStr, onError, onLoad, src]);

return (<video autoPlay playsInline src={src} ref={videoEl} {...other} />)
}
return <video autoPlay playsInline src={src} ref={videoEl} {...other} />;
};

Reader.propTypes = {
constraints: PropTypes.object,
onError: PropTypes.func.isRequired,
onLoad: PropTypes.func,
onScan: PropTypes.func.isRequired,
resolution: PropTypes.number,
}
};

Reader.defaultProps = {
constraints: { audio: false, video: true },
resolution: 640,
}
};

export default Reader
export default Reader;

0 comments on commit b888906

Please sign in to comment.