-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathlib-browser.ts
99 lines (86 loc) · 2.84 KB
/
lib-browser.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import { dlib, Array2D, CorrelationTracker } from './lib';
const binding = require('./dist/binding-browser');
let lib: dlib;
let videoKeyInHeap: string | undefined;
let cachedArray: Array2D | undefined;
let canvas: HTMLCanvasElement | undefined;
const videoKey = (video: HTMLVideoElement, pointer: number) => pointer + video.src + video.currentTime;
function videoToArray2D(video: HTMLVideoElement, pointer: number): Array2D {
const key = videoKey(video, pointer);
if (key === videoKeyInHeap && cachedArray) return cachedArray;
if (!canvas) canvas = document.createElement('canvas');
const { videoWidth: width, videoHeight: height } = video;
canvas.width = width;
canvas.height = height;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
ctx.drawImage(video, 0, 0);
const pixels = ctx.getImageData(0, 0, width, height).data;
lib.HEAP8.set(pixels, pointer);
videoKeyInHeap = key;
cachedArray = lib.readImageData(pointer, width, height);
return cachedArray;
}
interface Rectangle {
x: number;
y: number;
width: number;
height: number;
}
export class VideoCorrelationTracker {
video: HTMLVideoElement;
rect: Rectangle;
tracker: CorrelationTracker | undefined;
private static ptr: number | undefined;
static freeMemory() {
if (!lib) return;
if (this.ptr) {
lib._free(this.ptr);
this.ptr = undefined;
}
}
static reserveMemory(video: HTMLVideoElement) {
if (this.ptr) this.freeMemory();
const makePtr = () => this.ptr = lib._malloc(video.videoWidth * video.videoHeight * 4);
if (!lib) {
lib = binding();
lib.then(makePtr);
} else {
makePtr();
}
}
private get videoArray2D() {
if (!VideoCorrelationTracker.ptr) VideoCorrelationTracker.reserveMemory(this.video);
return videoToArray2D(this.video, VideoCorrelationTracker.ptr as number);
}
get prediction(): Rectangle {
if (!this.tracker) return { x: 0, y: 0, width: 0, height: 0 };
const rect = this.tracker.predict(this.videoArray2D);
return {
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height,
};
}
constructor(video: HTMLVideoElement, rect: Rectangle) {
this.video = video;
this.rect = rect;
const loadWithLib = () => {
if (!VideoCorrelationTracker.ptr) VideoCorrelationTracker.reserveMemory(video);
const _rect = new lib.Rectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height);
this.tracker = new lib.CorrelationTracker();
this.tracker.startTrack(this.videoArray2D, _rect);
}
if (!lib) {
lib = binding();
lib.then(loadWithLib);
} else {
loadWithLib();
}
}
update(rect: Rectangle) {
if (!this.tracker) return;
const _rect = new lib.Rectangle(rect.x, rect.y, rect.x + rect.width, rect.y + rect.height)
this.tracker.update(this.videoArray2D, _rect);
}
}