Skip to content

Commit

Permalink
perf: process frames in worker thread
Browse files Browse the repository at this point in the history
Do expensive scanning of frames in web worker. Doesn't seem to
improve tracking performance very much but certainly unburdons
the UI thread leading to higher FPS especially on mobile.
  • Loading branch information
gruhn committed Sep 9, 2018
1 parent 0e3f21e commit bc87ba8
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 50 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
"vue-loader": "^10.0.0",
"vue-template-compiler": "^2.1.6",
"webpack": "^2.1.0-beta.28",
"webpack-merge": "^1.1.2"
"webpack-merge": "^1.1.2",
"worker-loader": "^2.0.0"
},
"dependencies": {
"babel-runtime": "^6.26.0",
Expand Down
4 changes: 2 additions & 2 deletions src/components/QrcodeReader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ export default {
async onDropFile (file) {
this.onDetect('file', (async () => {
const imageData = await imageDataFromFile(file)
const scanResult = Scanner.scan(imageData)
const scanResult = await Scanner.scan(imageData)
return scanResult
})())
Expand All @@ -274,7 +274,7 @@ export default {
async onDropUrl (url) {
this.onDetect('url', (async () => {
const imageData = await imageDataFromUrl(url)
const scanResult = Scanner.scan(imageData)
const scanResult = await Scanner.scan(imageData)
return scanResult
})())
Expand Down
62 changes: 39 additions & 23 deletions src/misc/scanner.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import 'webrtc-adapter'
import jsQR from 'jsqr'
import Worker from 'worker-loader?inline=true&fallback=false!./worker.js'

export function scan (imageData) {
const { data, width, height } = imageData
const result = jsQR(data, width, height)
const worker = new Worker()

let content, location
return new Promise(resolve => {
worker.onmessage = event => {
resolve(event.data)

if (result === null) {
content = null
location = null
} else {
content = result.data
location = result.location
}
worker.terminate()
}

return { content, location, imageData }
worker.postMessage(imageData, [imageData.data.buffer])
})
}

/**
Expand All @@ -24,8 +21,8 @@ export function scan (imageData) {
*/
export function keepScanning (camera, options) {
const {
locateHandler,
detectHandler,
locateHandler,
shouldContinue,
minDelay,
} = options
Expand All @@ -34,27 +31,46 @@ export function keepScanning (camera, options) {
let locationBefore = null
let lastScanned = performance.now()

const worker = new Worker()

// If worker can't process frames fast enough, memory will quickly full up.
// Make sure to process only one frame at a time.
let workerBusy = false

worker.onmessage = event => {
workerBusy = false

const { content, location } = event.data

if (content !== null && content !== contentBefore) {
detectHandler(event.data)
}

if (location !== locationBefore) {
locateHandler(location)
}

contentBefore = content || contentBefore
locationBefore = location
}

const processFrame = timeNow => {
if (shouldContinue()) {
window.requestAnimationFrame(processFrame)

if (timeNow - lastScanned >= minDelay) {
lastScanned = timeNow

const imageData = camera.captureFrame()
const { content, location } = scan(imageData)
if (workerBusy === false) {
workerBusy = true

if (content !== contentBefore && content !== null) {
detectHandler({ content, location, imageData })
}
const imageData = camera.captureFrame()

if (location !== locationBefore) {
locateHandler(location)
worker.postMessage(imageData, [imageData.data.buffer])
}

contentBefore = content || contentBefore
locationBefore = location
}
} else {
worker.terminate()
}
}

Expand Down
23 changes: 23 additions & 0 deletions src/misc/worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import jsQR from 'jsqr'

self.addEventListener('message', function (event) {
const imageData = event.data

const result = jsQR(
imageData.data,
imageData.width,
imageData.height
)

let content = null
let location = null

if (result !== null) {
content = result.data
location = result.location
}

const message = { content, location, imageData }

self.postMessage(message, [imageData.data.buffer])
})
75 changes: 51 additions & 24 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,10 @@ ajv-keywords@^1.0.0, ajv-keywords@^1.1.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-1.5.1.tgz#314dd0a4b3368fad3dfcdc54ede6171b886daf3c"

ajv-keywords@^3.1.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.2.0.tgz#e86b819c602cf8821ad637413698f1dec021847a"

ajv@^4.7.0, ajv@^4.9.1:
version "4.11.8"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-4.11.8.tgz#82ffb02b29e662ae53bdc20af15947706739c536"
Expand All @@ -210,6 +214,15 @@ ajv@^5.3.0:
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.3.0"

ajv@^6.1.0:
version "6.5.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.5.3.tgz#71a569d189ecf4f4f321224fecb166f071dd90f9"
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"

align-text@^0.1.1, align-text@^0.1.3:
version "0.1.4"
resolved "https://registry.yarnpkg.com/align-text/-/align-text-0.1.4.tgz#0cd90a561093f35d0a99256c22b7069433fad117"
Expand Down Expand Up @@ -2245,7 +2258,7 @@ [email protected], debug@^3.1.0:
dependencies:
ms "2.0.0"

debuglog@*, debuglog@^1.0.1:
debuglog@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492"

Expand Down Expand Up @@ -3022,6 +3035,10 @@ fast-deep-equal@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.0.0.tgz#96256a3bc975595eb36d82e9929d060d893439ff"

fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"

fast-glob@^2.0.2:
version "2.2.2"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.2.tgz#71723338ac9b4e0e2fff1d6748a2a13d5ed352bf"
Expand Down Expand Up @@ -3931,7 +3948,7 @@ import-lazy@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"

imurmurhash@*, imurmurhash@^0.1.4:
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"

Expand Down Expand Up @@ -4466,6 +4483,10 @@ json-schema-traverse@^0.3.0:
version "0.3.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340"

json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"

[email protected]:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
Expand Down Expand Up @@ -4747,7 +4768,7 @@ loader-utils@^0.2.10, loader-utils@^0.2.15, loader-utils@^0.2.16, loader-utils@^
json5 "^0.5.0"
object-assign "^4.0.1"

loader-utils@^1.0.2:
loader-utils@^1.0.0, loader-utils@^1.0.2:
version "1.1.0"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.1.0.tgz#c98aef488bcceda2ffb5e2de646d6a754429f5cd"
dependencies:
Expand Down Expand Up @@ -4824,36 +4845,22 @@ lodash._basefor@^3.0.0:
version "3.0.3"
resolved "https://registry.yarnpkg.com/lodash._basefor/-/lodash._basefor-3.0.3.tgz#7550b4e9218ef09fad24343b612021c79b4c20c2"

lodash._baseindexof@*:
version "3.1.0"
resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c"

lodash._baseuniq@~4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8"
dependencies:
lodash._createset "~4.0.0"
lodash._root "~3.0.0"

lodash._bindcallback@*, lodash._bindcallback@^3.0.0:
lodash._bindcallback@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e"

lodash._cacheindexof@*:
version "3.0.2"
resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92"

lodash._createcache@*:
version "3.1.2"
resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093"
dependencies:
lodash._getnative "^3.0.0"

lodash._createset@~4.0.0:
version "4.0.3"
resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26"

lodash._getnative@*, lodash._getnative@^3.0.0:
lodash._getnative@^3.0.0:
version "3.9.1"
resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5"

Expand Down Expand Up @@ -4968,10 +4975,6 @@ lodash.rest@^4.0.0:
version "4.0.5"
resolved "https://registry.yarnpkg.com/lodash.rest/-/lodash.rest-4.0.5.tgz#954ef75049262038c96d1fc98b28fdaf9f0772aa"

lodash.restparam@*:
version "3.6.1"
resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805"

lodash.toarray@^4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
Expand Down Expand Up @@ -6778,6 +6781,10 @@ punycode@^1.2.4, punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"

punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"

[email protected], q@^1.1.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/q/-/q-1.4.1.tgz#55705bcd93c5f3673530c2c2cbc0c2b3addc286e"
Expand Down Expand Up @@ -7017,7 +7024,7 @@ readable-stream@~1.0.2:
isarray "0.0.1"
string_decoder "~0.10.x"

readdir-scoped-modules@*, readdir-scoped-modules@^1.0.0:
readdir-scoped-modules@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/readdir-scoped-modules/-/readdir-scoped-modules-1.0.2.tgz#9fafa37d286be5d92cbaebdee030dc9b5f406747"
dependencies:
Expand Down Expand Up @@ -7458,6 +7465,13 @@ schema-utils@^0.3.0:
dependencies:
ajv "^5.0.0"

schema-utils@^0.4.0:
version "0.4.7"
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-0.4.7.tgz#ba74f597d2be2ea880131746ee17d0a093c68187"
dependencies:
ajv "^6.1.0"
ajv-keywords "^3.1.0"

scss-tokenizer@^0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1"
Expand Down Expand Up @@ -8450,6 +8464,12 @@ update-notifier@^2.3.0, update-notifier@^2.5.0:
semver-diff "^2.0.0"
xdg-basedir "^3.0.0"

uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
dependencies:
punycode "^2.1.0"

urix@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72"
Expand Down Expand Up @@ -8738,6 +8758,13 @@ worker-farm@^1.6.0:
dependencies:
errno "~0.1.7"

worker-loader@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/worker-loader/-/worker-loader-2.0.0.tgz#45fda3ef76aca815771a89107399ee4119b430ac"
dependencies:
loader-utils "^1.0.0"
schema-utils "^0.4.0"

wrap-ansi@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85"
Expand Down

0 comments on commit bc87ba8

Please sign in to comment.