@brandbrigade/ott-bb-player 1.0.42 → 1.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENCE +29 -0
- package/README.md +266 -215
- package/dist/OTTPlayer.js +272 -0
- package/package.json +21 -7
- package/src/Ads.js +82 -0
- package/src/Augmentor.js +1288 -0
- package/src/Composer3DBase.js +754 -0
- package/src/Composer3DForMainThread.js +131 -0
- package/src/Composer3DForWorker.js +80 -0
- package/src/Composer3DWorker.js +60 -0
- package/src/MetaDataDecoder.js +143 -0
- package/src/MetaDataFetcher.js +88 -0
- package/src/OTTPlayer.js +254 -0
- package/src/Socket.js +44 -0
- package/src/composer_worker.js +30 -0
- package/src/configs/OTT_Dev_Config_Debug.json +8 -0
- package/src/configs/OTT_Dev_Config_Debug_14fps.json +8 -0
- package/src/configs/OTT_Dev_Config_Debug_29fps.json +8 -0
- package/src/configs/OTT_Dev_Config_Debug_General.json +7 -0
- package/src/enums/RenderingMode.js +5 -0
- package/src/enums/SyncMethod.js +5 -0
- package/src/index.js +239 -0
- package/src/meta_worker.js +144 -0
- package/src/shaders/v1.js +87 -0
- package/src/shaders/v1Old.js +174 -0
- package/src/shaders/v2.js +193 -0
- package/src/test-pages/mp4/index.html +63 -0
- package/src/test-pages/mp4/index.js +23 -0
- package/src/test-pages/mp4/style.css +16 -0
- package/src/utils/FPSFetter.js +94 -0
- package/src/utils/MedianCalculator.js +27 -0
- package/src/utils/index.js +5 -0
- package/src/utils/isPowerOf2.js +3 -0
- package/src/utils/platform.js +191 -0
- package/src/utils/timeCodeUtils.js +274 -0
- package/js/OTTPlayer.js +0 -1
- package/mediakind.html +0 -273
|
@@ -0,0 +1,754 @@
|
|
|
1
|
+
import { fragmentShaderSourceV1, vertexShaderSourceV1 } from "./shaders/v1";
|
|
2
|
+
import { fragmentShaderSourceV1Old, vertexShaderSourceV1Old } from "./shaders/v1Old";
|
|
3
|
+
import { createProgramFromSources } from "twgl.js";
|
|
4
|
+
import {
|
|
5
|
+
timeCodeStr2TimeCodeArray,
|
|
6
|
+
timeCodeAddFrames,
|
|
7
|
+
printTimecode,
|
|
8
|
+
isPowerOf2
|
|
9
|
+
} from "./utils";
|
|
10
|
+
|
|
11
|
+
export default class Composer3DBase {
|
|
12
|
+
adTexture = null;
|
|
13
|
+
place2AdTexture = {};
|
|
14
|
+
place2ad = {};
|
|
15
|
+
ad2place = {};
|
|
16
|
+
currentAds2BoundingRect = []; //array of current-frame ads to their bounding rect
|
|
17
|
+
lastTimeReportedIncomingTC = 0;
|
|
18
|
+
autoAddIndex = null;
|
|
19
|
+
digitImg = {};
|
|
20
|
+
sourceFPS = 60000 / 1001;
|
|
21
|
+
metadataArr = [];
|
|
22
|
+
metadataMap = {};
|
|
23
|
+
videoStarted = false;
|
|
24
|
+
advertisementMap = {};
|
|
25
|
+
ad2Url = {};
|
|
26
|
+
videoCopier = null;
|
|
27
|
+
autoAddIndex = null;
|
|
28
|
+
|
|
29
|
+
constructor(options) {
|
|
30
|
+
if (options.renderTimecodes) {
|
|
31
|
+
for (let i = 0; i < 10; ++i) {
|
|
32
|
+
let str1 = i + ".1";
|
|
33
|
+
let str2 = i + ".2";
|
|
34
|
+
this.digitImg[str1] = this.createDigitImg(str1);
|
|
35
|
+
this.digitImg[str2] = this.createDigitImg(str2);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
this.options = Object.assign(
|
|
39
|
+
{ adLoopTime: 5000, isAdLoop: false },
|
|
40
|
+
options || {},
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
onUserClickOnCanvas(e) {
|
|
47
|
+
console.log("fix me");
|
|
48
|
+
return;
|
|
49
|
+
const rect = e.rect;
|
|
50
|
+
let x = e.clientX - rect.left;
|
|
51
|
+
let y = e.clientY - rect.top;
|
|
52
|
+
x = x / (rect.right - rect.left);
|
|
53
|
+
y = y / (rect.bottom - rect.top);
|
|
54
|
+
for (let currentAd of this.currentAds2BoundingRect) {
|
|
55
|
+
if (
|
|
56
|
+
currentAd.rect.l <= x &&
|
|
57
|
+
currentAd.rect.r >= x &&
|
|
58
|
+
currentAd.rect.t <= y &&
|
|
59
|
+
currentAd.rect.b >= y
|
|
60
|
+
) {
|
|
61
|
+
let adNameWithoutThatStupidHashSign = currentAd.name.substring(1);
|
|
62
|
+
if (this.ad2Url[adNameWithoutThatStupidHashSign]) {
|
|
63
|
+
let urlToGo = this.ad2Url[adNameWithoutThatStupidHashSign];
|
|
64
|
+
console.log(
|
|
65
|
+
"Clicked on ad: " +
|
|
66
|
+
adNameWithoutThatStupidHashSign +
|
|
67
|
+
" so should navigate to " +
|
|
68
|
+
urlToGo +
|
|
69
|
+
" !!!!!!!!!!!!!!!!!!!!!!",
|
|
70
|
+
);
|
|
71
|
+
window.open(urlToGo, "_blank");
|
|
72
|
+
}
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
texUnitForGenericAd() {
|
|
79
|
+
return 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
texUnitForAdInPlace(place) {
|
|
83
|
+
let placesArr = Object.keys(this.place2ad);
|
|
84
|
+
for (let i = 0; i < placesArr.length; ++i) {
|
|
85
|
+
if (place == placesArr[i]) return i + 1;
|
|
86
|
+
}
|
|
87
|
+
return 0;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
texUnitForPlaceHolder(placeHolder) {
|
|
91
|
+
let placesArr = Object.keys(this.place2ad);
|
|
92
|
+
for (let i = 0; i < placesArr.length; ++i) {
|
|
93
|
+
let place = placesArr[i]; //wall
|
|
94
|
+
if (placeHolder.name.indexOf(place) >= 0) return i; // + 1;
|
|
95
|
+
}
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
adNameForPlaceHolder(placeHolder) {
|
|
100
|
+
let placesArr = Object.keys(this.place2ad);
|
|
101
|
+
for (let i = 0; i < placesArr.length; ++i) {
|
|
102
|
+
let place = placesArr[i]; //wall
|
|
103
|
+
if (
|
|
104
|
+
placeHolder.name.indexOf(place) >= 0 &&
|
|
105
|
+
this.place2AdTexture &&
|
|
106
|
+
this.place2AdTexture[place] &&
|
|
107
|
+
this.place2AdTexture[place].name
|
|
108
|
+
) {
|
|
109
|
+
return this.place2AdTexture[place].name;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return this.lastAdName;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
texUnitBaseForAlpha() {
|
|
116
|
+
return 1 + Object.keys(this.place2ad).length;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
initGL() {
|
|
120
|
+
const shaders = this.options.maskMP4 ?
|
|
121
|
+
[vertexShaderSourceV1, fragmentShaderSourceV1] :
|
|
122
|
+
[vertexShaderSourceV1Old, fragmentShaderSourceV1Old]
|
|
123
|
+
this.program = createProgramFromSources(this.ctx, shaders);
|
|
124
|
+
|
|
125
|
+
this.ctx.useProgram(this.program);
|
|
126
|
+
this.counter = 0;
|
|
127
|
+
this.cleanGL();
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
cleanGL() {
|
|
131
|
+
this.ctx.clearColor(0.0, 0.0, 0.0, 0.0);
|
|
132
|
+
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
generateTexture(
|
|
136
|
+
imageData,
|
|
137
|
+
textureUnit,
|
|
138
|
+
uniformName,
|
|
139
|
+
internalFormat,
|
|
140
|
+
width,
|
|
141
|
+
height,
|
|
142
|
+
oneByteAlignment,
|
|
143
|
+
flipY = false
|
|
144
|
+
) {
|
|
145
|
+
if (oneByteAlignment) {
|
|
146
|
+
this.ctx.pixelStorei(this.ctx.UNPACK_ALIGNMENT, 1);
|
|
147
|
+
} else {
|
|
148
|
+
this.ctx.pixelStorei(this.ctx.UNPACK_ALIGNMENT, 4);
|
|
149
|
+
}
|
|
150
|
+
this.ctx.pixelStorei(this.ctx.UNPACK_FLIP_Y_WEBGL, flipY);
|
|
151
|
+
const texture = this.ctx.createTexture();
|
|
152
|
+
this.ctx.activeTexture(this.ctx.TEXTURE0 + textureUnit);
|
|
153
|
+
this.ctx.bindTexture(this.ctx.TEXTURE_2D, texture);
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
if (width && height) {
|
|
157
|
+
this.ctx.texImage2D(
|
|
158
|
+
this.ctx.TEXTURE_2D,
|
|
159
|
+
0,
|
|
160
|
+
internalFormat == null ? this.ctx.RGBA : internalFormat,
|
|
161
|
+
width,
|
|
162
|
+
height,
|
|
163
|
+
0,
|
|
164
|
+
internalFormat == null ? this.ctx.RGBA : internalFormat,
|
|
165
|
+
this.ctx.UNSIGNED_BYTE,
|
|
166
|
+
imageData,
|
|
167
|
+
);
|
|
168
|
+
} else {
|
|
169
|
+
this.ctx.texImage2D(
|
|
170
|
+
this.ctx.TEXTURE_2D,
|
|
171
|
+
0,
|
|
172
|
+
internalFormat == null ? this.ctx.RGBA : internalFormat,
|
|
173
|
+
this.ctx.RGBA,
|
|
174
|
+
this.ctx.UNSIGNED_BYTE,
|
|
175
|
+
imageData,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
} catch (ex) {
|
|
179
|
+
console.error(ex);
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
if (this.webGLVersion == 1) {
|
|
183
|
+
let widthToInspect = width || imageData.width;
|
|
184
|
+
let heightToInspect = height || imageData.height;
|
|
185
|
+
if (
|
|
186
|
+
widthToInspect &&
|
|
187
|
+
isPowerOf2(widthToInspect) &&
|
|
188
|
+
heightToInspect &&
|
|
189
|
+
isPowerOf2(heightToInspect)
|
|
190
|
+
) {
|
|
191
|
+
this.ctx.generateMipmap(this.ctx.TEXTURE_2D);
|
|
192
|
+
} else {
|
|
193
|
+
// No, it's not a power of 2. Turn off mips and set
|
|
194
|
+
// wrapping to clamp to edge
|
|
195
|
+
this.ctx.texParameteri(
|
|
196
|
+
this.ctx.TEXTURE_2D,
|
|
197
|
+
this.ctx.TEXTURE_WRAP_S,
|
|
198
|
+
this.ctx.CLAMP_TO_EDGE,
|
|
199
|
+
);
|
|
200
|
+
this.ctx.texParameteri(
|
|
201
|
+
this.ctx.TEXTURE_2D,
|
|
202
|
+
this.ctx.TEXTURE_WRAP_T,
|
|
203
|
+
this.ctx.CLAMP_TO_EDGE,
|
|
204
|
+
);
|
|
205
|
+
this.ctx.texParameteri(
|
|
206
|
+
this.ctx.TEXTURE_2D,
|
|
207
|
+
this.ctx.TEXTURE_MIN_FILTER,
|
|
208
|
+
this.ctx.LINEAR,
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
} else {
|
|
212
|
+
this.ctx.texParameteri(
|
|
213
|
+
this.ctx.TEXTURE_2D,
|
|
214
|
+
this.ctx.TEXTURE_WRAP_S,
|
|
215
|
+
this.ctx.CLAMP_TO_EDGE,
|
|
216
|
+
);
|
|
217
|
+
this.ctx.texParameteri(
|
|
218
|
+
this.ctx.TEXTURE_2D,
|
|
219
|
+
this.ctx.TEXTURE_WRAP_T,
|
|
220
|
+
this.ctx.CLAMP_TO_EDGE,
|
|
221
|
+
);
|
|
222
|
+
this.ctx.texParameteri(
|
|
223
|
+
this.ctx.TEXTURE_2D,
|
|
224
|
+
this.ctx.TEXTURE_MIN_FILTER,
|
|
225
|
+
this.ctx.LINEAR,
|
|
226
|
+
);
|
|
227
|
+
this.ctx.texParameteri(
|
|
228
|
+
this.ctx.TEXTURE_2D,
|
|
229
|
+
this.ctx.TEXTURE_MAG_FILTER,
|
|
230
|
+
this.ctx.LINEAR,
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
let location = this.ctx.getUniformLocation(this.program, uniformName);
|
|
235
|
+
if (location) {
|
|
236
|
+
this.ctx.uniform1i(location, textureUnit);
|
|
237
|
+
}
|
|
238
|
+
return texture;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
_nextAdvertisement() {
|
|
242
|
+
this.autoAddIndex = setTimeout(() => {
|
|
243
|
+
const ads = Object.keys(this.advertisementMap);
|
|
244
|
+
if (ads.length) {
|
|
245
|
+
this.selectAd(ads[Math.floor(Math.random() * ads.length)]);
|
|
246
|
+
this._nextAdvertisement();
|
|
247
|
+
}
|
|
248
|
+
}, this.options.adLoopTime);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
makeSureAdPerPlace() {
|
|
252
|
+
if (this.place2ad) {
|
|
253
|
+
let placesArr = Object.keys(this.place2ad);
|
|
254
|
+
for (let i = 0; i < placesArr.length; ++i) {
|
|
255
|
+
let place = placesArr[i];
|
|
256
|
+
if (!this.place2AdTexture[place] && this.place2ad[place].length > 0) {
|
|
257
|
+
console.log(
|
|
258
|
+
"MakeSureAdPerPlace: Set default image " +
|
|
259
|
+
this.place2ad[place][0] +
|
|
260
|
+
" for place " +
|
|
261
|
+
place,
|
|
262
|
+
);
|
|
263
|
+
this.selectAd("#" + this.place2ad[place][0]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
selectAd(name) {
|
|
270
|
+
console.log("composer::SelectAd: selected ad is " + name);
|
|
271
|
+
let adImage = this.advertisementMap[name];
|
|
272
|
+
if (!adImage) {
|
|
273
|
+
console.error("SelectAd: Failed to find image '" + name + "'");
|
|
274
|
+
} else {
|
|
275
|
+
if (this.ad2place && this.ad2place[name]) {
|
|
276
|
+
let place = this.ad2place[name];
|
|
277
|
+
console.log(
|
|
278
|
+
"composer::SelectAd: The selected ad should be in place " + place,
|
|
279
|
+
);
|
|
280
|
+
let texUnitId = this.texUnitForAdInPlace(place);
|
|
281
|
+
let texName = "ad" + (texUnitId - 1);
|
|
282
|
+
if (this.place2AdTexture[place])
|
|
283
|
+
this.ctx.deleteTexture(this.place2AdTexture[place].tex);
|
|
284
|
+
this.place2AdTexture[place] = {
|
|
285
|
+
tex: this.generateTexture(adImage, texUnitId, texName),
|
|
286
|
+
texUnitId: texUnitId,
|
|
287
|
+
texName: texName,
|
|
288
|
+
name: name,
|
|
289
|
+
};
|
|
290
|
+
} else {
|
|
291
|
+
if (this.adTexture) {
|
|
292
|
+
this.ctx.deleteTexture(this.adTexture);
|
|
293
|
+
}
|
|
294
|
+
this.adTexture = this.generateTexture(
|
|
295
|
+
adImage,
|
|
296
|
+
this.texUnitForGenericAd(),
|
|
297
|
+
"ad0",
|
|
298
|
+
);
|
|
299
|
+
this.lastAd = adImage;
|
|
300
|
+
this.lastAdName = name;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
onMetaData(frameMetaData) {
|
|
306
|
+
this.metadataMap[frameMetaData.timecode] = frameMetaData;
|
|
307
|
+
this.metadataArr.push(frameMetaData.timecode);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
renderFrame() {
|
|
311
|
+
let positionAttributeLocation = this.ctx.getAttribLocation(
|
|
312
|
+
this.program,
|
|
313
|
+
"a_position",
|
|
314
|
+
);
|
|
315
|
+
|
|
316
|
+
let uvAttributeLocation = this.ctx.getAttribLocation(
|
|
317
|
+
this.program,
|
|
318
|
+
"a_uv",
|
|
319
|
+
);
|
|
320
|
+
|
|
321
|
+
let resolutionLocation = this.ctx.getUniformLocation(
|
|
322
|
+
this.program,
|
|
323
|
+
"u_resolution",
|
|
324
|
+
);
|
|
325
|
+
|
|
326
|
+
this.ctx.uniform2f(
|
|
327
|
+
resolutionLocation,
|
|
328
|
+
this.ctx.canvas.width,
|
|
329
|
+
this.ctx.canvas.height,
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
//DELETE THIS WHEN WE DROP OLD MASK SUPPORT
|
|
333
|
+
resolutionLocation = this.ctx.getUniformLocation(
|
|
334
|
+
this.program,
|
|
335
|
+
"u_resolution2",
|
|
336
|
+
);
|
|
337
|
+
this.ctx.uniform2f(
|
|
338
|
+
resolutionLocation,
|
|
339
|
+
this.ctx.canvas.width,
|
|
340
|
+
this.ctx.canvas.height,
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
let positionBuffer = this.ctx.createBuffer();
|
|
344
|
+
|
|
345
|
+
this.ctx.enableVertexAttribArray(positionAttributeLocation);
|
|
346
|
+
|
|
347
|
+
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, positionBuffer);
|
|
348
|
+
|
|
349
|
+
let size = 2;
|
|
350
|
+
let type = this.ctx.FLOAT;
|
|
351
|
+
let normalize = false;
|
|
352
|
+
let stride = 0;
|
|
353
|
+
let offset = 0;
|
|
354
|
+
this.ctx.vertexAttribPointer(
|
|
355
|
+
positionAttributeLocation,
|
|
356
|
+
size,
|
|
357
|
+
type,
|
|
358
|
+
normalize,
|
|
359
|
+
stride,
|
|
360
|
+
offset,
|
|
361
|
+
);
|
|
362
|
+
|
|
363
|
+
let texCoordBuffer = this.ctx.createBuffer();
|
|
364
|
+
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, texCoordBuffer);
|
|
365
|
+
this.ctx.bufferData(
|
|
366
|
+
this.ctx.ARRAY_BUFFER,
|
|
367
|
+
new Float32Array([0,0, 1,0, 0,1, 0,1, 1,0, 1,1]),
|
|
368
|
+
this.ctx.STATIC_DRAW,
|
|
369
|
+
);
|
|
370
|
+
this.ctx.enableVertexAttribArray(uvAttributeLocation);
|
|
371
|
+
size = 2;
|
|
372
|
+
type = this.ctx.FLOAT;
|
|
373
|
+
normalize = false;
|
|
374
|
+
stride = 0;
|
|
375
|
+
offset = 0;
|
|
376
|
+
this.ctx.vertexAttribPointer(uvAttributeLocation, size, type, normalize, stride, offset);
|
|
377
|
+
|
|
378
|
+
this.ctx.viewport(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
|
|
379
|
+
this.ctx.clearColor(0, 0, 0, 0);
|
|
380
|
+
this.ctx.clear(this.ctx.COLOR_BUFFER_BIT | this.ctx.DEPTH_BUFFER_BIT);
|
|
381
|
+
this.ctx.bindBuffer(this.ctx.ARRAY_BUFFER, positionBuffer);
|
|
382
|
+
|
|
383
|
+
this.setRectangle(0, 0, this.canvas.width, this.canvas.height);
|
|
384
|
+
|
|
385
|
+
let primitiveType = this.ctx.TRIANGLES;
|
|
386
|
+
let count = 6;
|
|
387
|
+
this.ctx.drawArrays(primitiveType, offset, count);
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
setRectangle(x, y, width, height) {
|
|
391
|
+
let x1 = x;
|
|
392
|
+
let x2 = x + width;
|
|
393
|
+
let y1 = y;
|
|
394
|
+
let y2 = y + height;
|
|
395
|
+
this.ctx.bufferData(
|
|
396
|
+
this.ctx.ARRAY_BUFFER,
|
|
397
|
+
new Float32Array([x1, y1, x2, y1, x1, y2, x1, y2, x2, y1, x2, y2]),
|
|
398
|
+
this.ctx.STATIC_DRAW,
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
renderAugmentation(nextTimeCode) {
|
|
403
|
+
this.canvas.width = 1280;
|
|
404
|
+
this.canvas.height = 720;
|
|
405
|
+
this.options.maskMP4 ?
|
|
406
|
+
this.renderAugmentationMP4(nextTimeCode) :
|
|
407
|
+
this.renderAugmentationOld(nextTimeCode)
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
renderAugmentationMP4(nextTimeCode) {
|
|
411
|
+
let tc = timeCodeStr2TimeCodeArray(nextTimeCode);
|
|
412
|
+
let tcPlus1 = timeCodeAddFrames(tc, 1, this.sourceFPS);
|
|
413
|
+
let tcPlus2 = timeCodeAddFrames(tc, 2, this.sourceFPS);
|
|
414
|
+
let tcPlus1Str = printTimecode(tcPlus1);
|
|
415
|
+
let tcPlus2Str = printTimecode(tcPlus2);
|
|
416
|
+
|
|
417
|
+
this.videoStarted = true;
|
|
418
|
+
const t1 = performance.now();
|
|
419
|
+
|
|
420
|
+
let frameMetaData = null;
|
|
421
|
+
let next = [];
|
|
422
|
+
if (this.metadataMap[nextTimeCode]) {
|
|
423
|
+
frameMetaData = this.metadataMap[nextTimeCode];
|
|
424
|
+
|
|
425
|
+
if (this.metadataMap[tcPlus1Str]) {
|
|
426
|
+
next.push({
|
|
427
|
+
nextVideo: this.metadataMap[tcPlus1Str],
|
|
428
|
+
nextTimeCode: tcPlus1Str,
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
if (this.metadataMap[tcPlus2Str]) {
|
|
432
|
+
next.push({
|
|
433
|
+
nextVideo: this.metadataMap[tcPlus2Str],
|
|
434
|
+
nextTimeCode: tcPlus2Str,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
const metaArrIndex = this.metadataArr.indexOf(nextTimeCode);
|
|
438
|
+
|
|
439
|
+
if (metaArrIndex > -5)
|
|
440
|
+
this.metadataArr.splice(0, metaArrIndex - 4).forEach((item) => {
|
|
441
|
+
delete this.metadataMap[item];
|
|
442
|
+
});
|
|
443
|
+
} else {
|
|
444
|
+
this.counter++;
|
|
445
|
+
if (this.counter > 60) {
|
|
446
|
+
this.counter = 0;
|
|
447
|
+
console.error("Missing meta data at time code " + nextTimeCode);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
let texturesForThisFrame = [];
|
|
452
|
+
|
|
453
|
+
let placeHolderIndex = 0;
|
|
454
|
+
this.currentAds2BoundingRect = [];
|
|
455
|
+
|
|
456
|
+
if (frameMetaData?.alphaMask) {
|
|
457
|
+
let alphaTextureNum = this.texUnitBaseForAlpha();
|
|
458
|
+
const alphaTexture = this.generateTexture(
|
|
459
|
+
frameMetaData.alphaMask,
|
|
460
|
+
alphaTextureNum,
|
|
461
|
+
"u_alphaMask",
|
|
462
|
+
this.ctx.RGBA,
|
|
463
|
+
null,
|
|
464
|
+
null,
|
|
465
|
+
false,
|
|
466
|
+
true
|
|
467
|
+
)
|
|
468
|
+
texturesForThisFrame.push(alphaTexture);
|
|
469
|
+
|
|
470
|
+
for (const key in frameMetaData.placeholders) {
|
|
471
|
+
const holder = frameMetaData.placeholders[key];
|
|
472
|
+
|
|
473
|
+
let hasLogoUniformName = "hasLogo" + placeHolderIndex;
|
|
474
|
+
let hasLogoLoc = this.ctx.getUniformLocation(
|
|
475
|
+
this.program,
|
|
476
|
+
hasLogoUniformName,
|
|
477
|
+
);
|
|
478
|
+
this.ctx.uniform1i(hasLogoLoc, 1);
|
|
479
|
+
let adForLogoUniformName = "adForLogo" + placeHolderIndex;
|
|
480
|
+
let adForLogoUniform = this.ctx.getUniformLocation(
|
|
481
|
+
this.program,
|
|
482
|
+
adForLogoUniformName,
|
|
483
|
+
);
|
|
484
|
+
this.ctx.uniform1i(
|
|
485
|
+
adForLogoUniform,
|
|
486
|
+
this.texUnitForPlaceHolder(holder),
|
|
487
|
+
);
|
|
488
|
+
|
|
489
|
+
let homographyMatrixUniformName = "u_matrix" + placeHolderIndex;
|
|
490
|
+
let placeHolderHomographyLocation = this.ctx.getUniformLocation(
|
|
491
|
+
this.program,
|
|
492
|
+
homographyMatrixUniformName,
|
|
493
|
+
);
|
|
494
|
+
this.ctx.uniformMatrix3fv(
|
|
495
|
+
placeHolderHomographyLocation,
|
|
496
|
+
false,
|
|
497
|
+
holder.tranform,
|
|
498
|
+
);
|
|
499
|
+
|
|
500
|
+
let boundingRect = { l: -1, t: -1, r: -1, b: -1 };
|
|
501
|
+
for (let corner of holder.corners) {
|
|
502
|
+
if (corner.x < boundingRect.l || boundingRect.l == -1)
|
|
503
|
+
boundingRect.l = corner.x;
|
|
504
|
+
if (corner.x > boundingRect.r || boundingRect.r == -1)
|
|
505
|
+
boundingRect.r = corner.x;
|
|
506
|
+
if (corner.y < boundingRect.t || boundingRect.t == -1)
|
|
507
|
+
boundingRect.t = corner.y;
|
|
508
|
+
if (corner.y > boundingRect.b || boundingRect.b == -1)
|
|
509
|
+
boundingRect.b = corner.y;
|
|
510
|
+
}
|
|
511
|
+
boundingRect.l /= frameMetaData.canvasSize.width;
|
|
512
|
+
boundingRect.r /= frameMetaData.canvasSize.width;
|
|
513
|
+
boundingRect.t /= frameMetaData.canvasSize.height;
|
|
514
|
+
boundingRect.b /= frameMetaData.canvasSize.height;
|
|
515
|
+
this.currentAds2BoundingRect.push({
|
|
516
|
+
name: this.adNameForPlaceHolder(holder),
|
|
517
|
+
rect: boundingRect,
|
|
518
|
+
});
|
|
519
|
+
|
|
520
|
+
|
|
521
|
+
placeHolderIndex++;
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
//@TODO: global object BB contains MAX_LOGOS constant but since this is a base class for somethig that's gonna run in worker
|
|
526
|
+
//we can't get access to it like that. Hardcoded for now
|
|
527
|
+
const MAX_LOGOS = 4;
|
|
528
|
+
for (; placeHolderIndex < MAX_LOGOS; ++placeHolderIndex) {
|
|
529
|
+
let hasLogoUniformName = "hasLogo" + placeHolderIndex;
|
|
530
|
+
let uniformLocation = this.ctx.getUniformLocation(
|
|
531
|
+
this.program,
|
|
532
|
+
hasLogoUniformName,
|
|
533
|
+
);
|
|
534
|
+
this.ctx.uniform1i(uniformLocation, 0);
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
this.renderTimecodes(nextTimeCode)
|
|
538
|
+
this.renderFrame();
|
|
539
|
+
|
|
540
|
+
for (const texture of texturesForThisFrame) {
|
|
541
|
+
this.ctx.deleteTexture(texture);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
renderAugmentationOld(nextTimeCode) {
|
|
546
|
+
let tc = timeCodeStr2TimeCodeArray(nextTimeCode);
|
|
547
|
+
let tcPlus1 = timeCodeAddFrames(tc, 1, this.sourceFPS);
|
|
548
|
+
let tcPlus2 = timeCodeAddFrames(tc, 2, this.sourceFPS);
|
|
549
|
+
let tcPlus1Str = printTimecode(tcPlus1);
|
|
550
|
+
let tcPlus2Str = printTimecode(tcPlus2);
|
|
551
|
+
|
|
552
|
+
this.videoStarted = true;
|
|
553
|
+
const t1 = performance.now();
|
|
554
|
+
|
|
555
|
+
let frameMetaData = null;
|
|
556
|
+
let next = [];
|
|
557
|
+
if (this.metadataMap[nextTimeCode]) {
|
|
558
|
+
frameMetaData = this.metadataMap[nextTimeCode];
|
|
559
|
+
|
|
560
|
+
if (this.metadataMap[tcPlus1Str]) {
|
|
561
|
+
next.push({
|
|
562
|
+
nextVideo: this.metadataMap[tcPlus1Str],
|
|
563
|
+
nextTimeCode: tcPlus1Str,
|
|
564
|
+
});
|
|
565
|
+
}
|
|
566
|
+
if (this.metadataMap[tcPlus2Str]) {
|
|
567
|
+
next.push({
|
|
568
|
+
nextVideo: this.metadataMap[tcPlus2Str],
|
|
569
|
+
nextTimeCode: tcPlus2Str,
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
const metaArrIndex = this.metadataArr.indexOf(nextTimeCode);
|
|
573
|
+
|
|
574
|
+
if (metaArrIndex > -5)
|
|
575
|
+
this.metadataArr.splice(0, metaArrIndex - 4).forEach((item) => {
|
|
576
|
+
delete this.metadataMap[item];
|
|
577
|
+
});
|
|
578
|
+
} else {
|
|
579
|
+
this.counter++;
|
|
580
|
+
if (this.counter > 60) {
|
|
581
|
+
this.counter = 0;
|
|
582
|
+
console.error("Missing meta data at time code " + nextTimeCode);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
let texturesForThisFrame = [];
|
|
587
|
+
|
|
588
|
+
let placeHolderIndex = 0;
|
|
589
|
+
this.currentAds2BoundingRect = [];
|
|
590
|
+
|
|
591
|
+
for (const key in frameMetaData?.placeholders) {
|
|
592
|
+
const holder = frameMetaData.placeholders[key];
|
|
593
|
+
|
|
594
|
+
if (!holder.alphaAsUint8Array) continue;
|
|
595
|
+
let alphaUnfiromName = "alpha" + placeHolderIndex;
|
|
596
|
+
let alphaTextureNum = this.texUnitBaseForAlpha() + placeHolderIndex;
|
|
597
|
+
holder.alphaTex = this.generateTexture(
|
|
598
|
+
holder.alphaAsUint8Array,
|
|
599
|
+
alphaTextureNum,
|
|
600
|
+
alphaUnfiromName,
|
|
601
|
+
this.ctx.ALPHA,
|
|
602
|
+
holder.width,
|
|
603
|
+
holder.height,
|
|
604
|
+
true,
|
|
605
|
+
);
|
|
606
|
+
holder.alphaAsUint8Array = null;
|
|
607
|
+
if (!holder.alphaTex) {
|
|
608
|
+
console.error("Failed to create alpha texture");
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
texturesForThisFrame.push(holder.alphaTex);
|
|
612
|
+
let hasLogoUniformName = "hasLogo" + placeHolderIndex;
|
|
613
|
+
let hasLogoLoc = this.ctx.getUniformLocation(
|
|
614
|
+
this.program,
|
|
615
|
+
hasLogoUniformName,
|
|
616
|
+
);
|
|
617
|
+
this.ctx.uniform1i(hasLogoLoc, 1);
|
|
618
|
+
let adForLogoUniformName = "adForLogo" + placeHolderIndex;
|
|
619
|
+
let adForLogoUniform = this.ctx.getUniformLocation(
|
|
620
|
+
this.program,
|
|
621
|
+
adForLogoUniformName,
|
|
622
|
+
);
|
|
623
|
+
let isBlur = false;
|
|
624
|
+
if (holder.name.indexOf("blur") >= 0) {
|
|
625
|
+
this.ctx.uniform1i(adForLogoUniform, 99);
|
|
626
|
+
isBlur = true;
|
|
627
|
+
} else {
|
|
628
|
+
this.ctx.uniform1i(
|
|
629
|
+
adForLogoUniform,
|
|
630
|
+
this.texUnitForPlaceHolder(holder),
|
|
631
|
+
);
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
let alphaTopLeftUniformName = "u_alpha" + placeHolderIndex + "TopLeft";
|
|
635
|
+
let alphaTopLeftLoc = this.ctx.getUniformLocation(
|
|
636
|
+
this.program,
|
|
637
|
+
alphaTopLeftUniformName,
|
|
638
|
+
);
|
|
639
|
+
this.ctx.uniform2fv(alphaTopLeftLoc, [holder.maskX, holder.maskY]);
|
|
640
|
+
let alphaSizeUniformName = "u_alpha" + placeHolderIndex + "Size";
|
|
641
|
+
let alphaSizeLoc = this.ctx.getUniformLocation(
|
|
642
|
+
this.program,
|
|
643
|
+
alphaSizeUniformName,
|
|
644
|
+
);
|
|
645
|
+
this.ctx.uniform2fv(alphaSizeLoc, [holder.width, holder.height]);
|
|
646
|
+
let homographyMatrixUniformName = "u_matrix" + placeHolderIndex;
|
|
647
|
+
let placeHolderHomographyLocation = this.ctx.getUniformLocation(
|
|
648
|
+
this.program,
|
|
649
|
+
homographyMatrixUniformName,
|
|
650
|
+
);
|
|
651
|
+
this.ctx.uniformMatrix3fv(
|
|
652
|
+
placeHolderHomographyLocation,
|
|
653
|
+
false,
|
|
654
|
+
holder.tranform,
|
|
655
|
+
);
|
|
656
|
+
|
|
657
|
+
if (!isBlur) {
|
|
658
|
+
let boundingRect = { l: -1, t: -1, r: -1, b: -1 };
|
|
659
|
+
for (let corner of holder.corners) {
|
|
660
|
+
if (corner.x < boundingRect.l || boundingRect.l == -1)
|
|
661
|
+
boundingRect.l = corner.x;
|
|
662
|
+
if (corner.x > boundingRect.r || boundingRect.r == -1)
|
|
663
|
+
boundingRect.r = corner.x;
|
|
664
|
+
if (corner.y < boundingRect.t || boundingRect.t == -1)
|
|
665
|
+
boundingRect.t = corner.y;
|
|
666
|
+
if (corner.y > boundingRect.b || boundingRect.b == -1)
|
|
667
|
+
boundingRect.b = corner.y;
|
|
668
|
+
}
|
|
669
|
+
boundingRect.l /= frameMetaData.canvasSize.width;
|
|
670
|
+
boundingRect.r /= frameMetaData.canvasSize.width;
|
|
671
|
+
boundingRect.t /= frameMetaData.canvasSize.height;
|
|
672
|
+
boundingRect.b /= frameMetaData.canvasSize.height;
|
|
673
|
+
this.currentAds2BoundingRect.push({
|
|
674
|
+
name: this.adNameForPlaceHolder(holder),
|
|
675
|
+
rect: boundingRect,
|
|
676
|
+
});
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
placeHolderIndex++;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
//@TODO: global object BB contains MAX_LOGOS constant but since this is a base class for somethig that's gonna run in worker
|
|
683
|
+
//we can't get access to it like that. Hardcoded for now
|
|
684
|
+
const MAX_LOGOS = 4;
|
|
685
|
+
for (; placeHolderIndex < MAX_LOGOS; ++placeHolderIndex) {
|
|
686
|
+
let hasLogoUniformName = "hasLogo" + placeHolderIndex;
|
|
687
|
+
let uniformLocation = this.ctx.getUniformLocation(
|
|
688
|
+
this.program,
|
|
689
|
+
hasLogoUniformName,
|
|
690
|
+
);
|
|
691
|
+
this.ctx.uniform1i(uniformLocation, 0);
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
this.renderTimecodes(nextTimeCode)
|
|
695
|
+
this.renderFrame();
|
|
696
|
+
|
|
697
|
+
for (const texture of texturesForThisFrame) {
|
|
698
|
+
this.ctx.deleteTexture(texture);
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
renderTimecodes(nextTimeCode) {
|
|
703
|
+
if (this.options.renderTimecodes) {
|
|
704
|
+
let framesAndField = nextTimeCode.split(":")[3];
|
|
705
|
+
let field = framesAndField.indexOf(".") >= 0 ? 2 : 1;
|
|
706
|
+
let frameLastDigit = parseInt(framesAndField.split(".")[0]) % 10;
|
|
707
|
+
let debugImgStr = frameLastDigit + "." + field;
|
|
708
|
+
let digitTextureNum = this.texUnitBaseForAlpha() + 5;
|
|
709
|
+
console.log( debugImgStr, this.digitImg,
|
|
710
|
+
digitTextureNum,
|
|
711
|
+
"digitTex")
|
|
712
|
+
let digitTex = this.generateTexture(
|
|
713
|
+
this.digitImg[debugImgStr],
|
|
714
|
+
digitTextureNum,
|
|
715
|
+
"digitTex",
|
|
716
|
+
);
|
|
717
|
+
texturesForThisFrame.push(digitTex);
|
|
718
|
+
let hasDigitUniformName = "hasDigit";
|
|
719
|
+
let hasDigitLoc = this.ctx.getUniformLocation(
|
|
720
|
+
this.program,
|
|
721
|
+
hasDigitUniformName,
|
|
722
|
+
);
|
|
723
|
+
this.ctx.uniform1i(hasDigitLoc, 1);
|
|
724
|
+
let digitTopLeftUniformName = "u_digitTopLeft";
|
|
725
|
+
let digitTopLeftLoc = this.ctx.getUniformLocation(
|
|
726
|
+
this.program,
|
|
727
|
+
digitTopLeftUniformName,
|
|
728
|
+
);
|
|
729
|
+
this.ctx.uniform2fv(digitTopLeftLoc, [0, 0]);
|
|
730
|
+
|
|
731
|
+
let digitSizeUniformName = "u_digitSize";
|
|
732
|
+
let digitSizeLoc = this.ctx.getUniformLocation(
|
|
733
|
+
this.program,
|
|
734
|
+
digitSizeUniformName,
|
|
735
|
+
);
|
|
736
|
+
this.ctx.uniform2fv(digitSizeLoc, [200, 200]);
|
|
737
|
+
} else {
|
|
738
|
+
let hasDigitUniformName = "hasDigit";
|
|
739
|
+
let hasDigitLoc = this.ctx.getUniformLocation(
|
|
740
|
+
this.program,
|
|
741
|
+
hasDigitUniformName,
|
|
742
|
+
);
|
|
743
|
+
this.ctx.uniform1i(hasDigitLoc, 0);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
toggleFullscreen() {
|
|
748
|
+
(this.requestFullscreen || this.webkitRequestFullscreen)
|
|
749
|
+
.call(this)
|
|
750
|
+
.catch((err) => {
|
|
751
|
+
console.error(err);
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
}
|