-
Notifications
You must be signed in to change notification settings - Fork 8
/
video.js
144 lines (132 loc) · 4.02 KB
/
video.js
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
import yuvCanvas from 'yuv-canvas'
import yuvBuffer from 'yuv-buffer'
import BaseClass from "./base/BaseClass";
import EventsConfig from "./config/EventsConfig";
import DataProcessorController from "./dataProcessorController";
export class Video extends BaseClass {
constructor(canvas, url, wsUrl, worker = 2,cacheCount = 10) {
super()
console.log(canvas, url, wsUrl)
if (!url) {
alert("视频地址错误")
return
}
this.options.worker = worker
this.cacheCount = cacheCount
this.url = url
this.wsUrl = wsUrl || window.location.host
this.started = false
this.workerIndex = 0
this.tps = 0
this.latestPts = -Infinity
this.frameCache = new Map()
this.setCanvas(canvas)
this.setRender()
this.bindEvent()
this.processorController = new DataProcessorController(this.options)
this.processorController.init()
}
bindEvent() {
this.events.on(EventsConfig.DataProcessorReady, () => {
this.startWS()
})
this.events.on(EventsConfig.DecodeDecoded, (data) => {
this.drawFrame(data)
})
}
setCanvas(canvas) {
this.canvas = document.getElementById(canvas)
}
setRender(canvas) {
this.render = yuvCanvas.attach(canvas || this.canvas, null)
}
clear() {
this.render.clear()
}
// 更新帧
drawFrame(data) {
if (data.pts < this.latestPts) {
console.log("drop frame")
return
}
this.frameCache.set(data.pts, data)
if (this.frameCache.size <= this.cacheCount) {
return;
}
let min = -Infinity
let frame = null
this.frameCache.forEach((v, k, m) => {
if (min === -Infinity) {
min = k
frame = v
}
if (k < min) {
min = k
frame = v
}
})
this.frameCache.delete(min)
let {buf_y, buf_u, buf_v, width, height, stride_y, stride_u, stride_v, pts} = frame
this.latestPts = pts
let y, u, v, format, frameDisplay
let width_y = width
let height_y = height
let width_u = width_y / 2
let height_u = height_y / 2
y = {
bytes: buf_y,
stride: stride_y
}
u = {
bytes: buf_u,
stride: stride_u
}
v = {
bytes: buf_v,
stride: stride_v
}
format = yuvBuffer.format({
width: width_y,
height: height_y,
chromaWidth: width_u,
chromaHeight: height_u
})
frameDisplay = yuvBuffer.frame(format, y, u, v)
this.render.drawFrame(frameDisplay)
}
startWS() {
if (this.started) {
return
}
this.started = true
let that = this
this.ws = new WebSocket(this.wsUrl)
this.ws.onopen = function () {
console.log("Connection open ...")
that.ws.send(that.url);
};
this.ws.onmessage = function (evt) {
that.tps += 1
let nType = evt.data.charCodeAt(0)
if (nType === 32) {
that.workerIndex += 1
that.workerIndex %= that.options.worker
}
that.events.emit(EventsConfig.DateIn, {
data: evt.data,
index: that.workerIndex,
pts : that.tps
})
};
this.ws.onclose = function () {
that.events.emit(EventsConfig.DateClose)
console.log("Connection closed.")
};
this.ws.onerror = function () {
that.events.emit(EventsConfig.DateClose)
that.ws.close()
console.log("Connection closed.")
}
}
}
export default Video