@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,144 @@
|
|
|
1
|
+
import MetaDataDecoder from "./MetaDataDecoder";
|
|
2
|
+
import { isTCBigger, getNextTimeCode_TC, getNextTimeCode, addSecondsToTimeCode, timeCode2Str, str2TimeCode } from "./utils";
|
|
3
|
+
|
|
4
|
+
try {
|
|
5
|
+
let started = false;
|
|
6
|
+
let cloudFrontURL = "";
|
|
7
|
+
let folderName = "";
|
|
8
|
+
let lastRequest = {}; //{tc:"00_00_00_00", path:"..."}
|
|
9
|
+
let lastTimeCodeFound = null; //for statistics
|
|
10
|
+
let msecAvg = []; //for statistics
|
|
11
|
+
let maxTimeCode = {}; //don't pass this timecode
|
|
12
|
+
let enabled = true;
|
|
13
|
+
let isWorking = false;
|
|
14
|
+
const decoder = new MetaDataDecoder();
|
|
15
|
+
let isMaskMP4
|
|
16
|
+
|
|
17
|
+
const TryNextFrame = (seconds) => {
|
|
18
|
+
if (!enabled) return;
|
|
19
|
+
//if the required time code exceed the max time code, wait a bit
|
|
20
|
+
if (
|
|
21
|
+
seconds > 0 &&
|
|
22
|
+
isTCBigger(getNextTimeCode_TC(lastRequest.tc, seconds), maxTimeCode)
|
|
23
|
+
) {
|
|
24
|
+
setTimeout(() => {
|
|
25
|
+
TryNextFrame(seconds);
|
|
26
|
+
}, 100);
|
|
27
|
+
} else {
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
lastRequest.tc = getNextTimeCode(lastRequest.tc, seconds);
|
|
30
|
+
GetMetaData();
|
|
31
|
+
}, 0);
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
const getUrl = (request) => {
|
|
36
|
+
const tc = request.tc.replaceAll(":", "_")
|
|
37
|
+
return isMaskMP4 ?
|
|
38
|
+
`${request.path}/manifests/59.94/${tc}.zip` :
|
|
39
|
+
`${request.path}/${tc}.zip`
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const GetMetaData = async () => {
|
|
43
|
+
isWorking = true;
|
|
44
|
+
const item = lastRequest;
|
|
45
|
+
const url = getUrl(item)
|
|
46
|
+
try {
|
|
47
|
+
const t1 = performance.now();
|
|
48
|
+
const res = await fetch(url);
|
|
49
|
+
if (res.status >= 400) {
|
|
50
|
+
let now = performance.now();
|
|
51
|
+
let msecSinceLastTimeDate = now - lastTimeCodeFound;
|
|
52
|
+
let secSinceLastTimeDate = msecSinceLastTimeDate / 1000;
|
|
53
|
+
if (secSinceLastTimeDate > 4) {
|
|
54
|
+
console.error(
|
|
55
|
+
"Didn't find timecode ",
|
|
56
|
+
item.tc,
|
|
57
|
+
", now for " +
|
|
58
|
+
secSinceLastTimeDate.toFixed(2) +
|
|
59
|
+
" seconds - give up !",
|
|
60
|
+
);
|
|
61
|
+
TryNextFrame(2);
|
|
62
|
+
} else {
|
|
63
|
+
console.error(
|
|
64
|
+
"Didn't find timecode ",
|
|
65
|
+
item.tc,
|
|
66
|
+
", now for " + secSinceLastTimeDate.toFixed(2) + " seconds",
|
|
67
|
+
);
|
|
68
|
+
TryNextFrame(0);
|
|
69
|
+
}
|
|
70
|
+
isWorking = false;
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
let now = performance.now();
|
|
75
|
+
let msecSinceLastTimeDate = 0;
|
|
76
|
+
if (lastTimeCodeFound) {
|
|
77
|
+
msecSinceLastTimeDate = now - lastTimeCodeFound;
|
|
78
|
+
msecAvg.push(msecSinceLastTimeDate);
|
|
79
|
+
while (msecAvg.length > 1000) msecAvg.shift();
|
|
80
|
+
}
|
|
81
|
+
lastTimeCodeFound = now;
|
|
82
|
+
const data = await res.arrayBuffer();
|
|
83
|
+
await decoder.handleData(data, item.tc);
|
|
84
|
+
const t2 = performance.now();
|
|
85
|
+
} catch (err) {
|
|
86
|
+
console.error(`Error on url ${url}`, err);
|
|
87
|
+
}
|
|
88
|
+
isWorking = false;
|
|
89
|
+
TryNextFrame(2);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
addEventListener("message", (request) => {
|
|
93
|
+
if (!started && request.data.cloudFrontURL) {
|
|
94
|
+
started = true;
|
|
95
|
+
isMaskMP4 = request.data.maskMP4 ?? false
|
|
96
|
+
cloudFrontURL = request.data.cloudFrontURL;
|
|
97
|
+
folderName = request.data.folderName;
|
|
98
|
+
let timeCode = str2TimeCode(request.data.tc, ':'); //parse the time code string into a real time-code
|
|
99
|
+
maxTimeCode = addSecondsToTimeCode(Object.assign({}, timeCode), 4); //set the max limit (on a clone)
|
|
100
|
+
//set the timecode needed
|
|
101
|
+
timeCode.f = 0;
|
|
102
|
+
timeCode.s = timeCode.s % 2 === 0 ? timeCode.s : timeCode.s - 1;
|
|
103
|
+
lastRequest = { tc: timeCode2Str(timeCode), path: `${cloudFrontURL}/${folderName}` }; //from the lastReqest object
|
|
104
|
+
console.log(
|
|
105
|
+
"Meta-data worker starting from this time-code:",
|
|
106
|
+
lastRequest.tc,
|
|
107
|
+
);
|
|
108
|
+
GetMetaData();
|
|
109
|
+
} else {
|
|
110
|
+
let timeCode = str2TimeCode(request.data.tc, ':');
|
|
111
|
+
timeCode.f = 0;
|
|
112
|
+
timeCode.s = timeCode.s % 2 === 0 ? timeCode.s : timeCode.s - 1;
|
|
113
|
+
if (isTCBigger(timeCode, maxTimeCode)) {
|
|
114
|
+
lastRequest.tc = timeCode2Str(timeCode);
|
|
115
|
+
console.log(
|
|
116
|
+
"Meta-data worker jumps forward to this time-code: ",
|
|
117
|
+
lastRequest.tc,
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
if (
|
|
121
|
+
isTCBigger(
|
|
122
|
+
str2TimeCode(lastRequest.tc, ':'),
|
|
123
|
+
addSecondsToTimeCode(timeCode, 4),
|
|
124
|
+
)
|
|
125
|
+
) {
|
|
126
|
+
lastRequest.tc = timeCode2Str(timeCode);
|
|
127
|
+
console.log(
|
|
128
|
+
"Meta-data worker jumps back to this time-code: ",
|
|
129
|
+
lastRequest.tc,
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
maxTimeCode = addSecondsToTimeCode(timeCode, 4);
|
|
133
|
+
if (!enabled && request.data.enabled) {
|
|
134
|
+
enabled = request.data.enabled;
|
|
135
|
+
if (!isWorking) GetMetaData();
|
|
136
|
+
} else {
|
|
137
|
+
enabled = request.data.enabled;
|
|
138
|
+
}
|
|
139
|
+
//console.log("max time code: ", maxTimeCode);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
} catch (e) {
|
|
143
|
+
console.error(e);
|
|
144
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
export const vertexShaderSourceV1 = `
|
|
2
|
+
precision highp float;
|
|
3
|
+
|
|
4
|
+
uniform vec2 u_resolution;
|
|
5
|
+
attribute vec2 a_position;
|
|
6
|
+
attribute vec2 a_uv;
|
|
7
|
+
|
|
8
|
+
varying vec2 v_uv;
|
|
9
|
+
|
|
10
|
+
void main() {
|
|
11
|
+
v_uv = a_uv;
|
|
12
|
+
|
|
13
|
+
// convert the rectangle from pixels to 0.0 to 1.0
|
|
14
|
+
vec2 clipSpace = 2.0 * (a_position / u_resolution) - 1.0;
|
|
15
|
+
|
|
16
|
+
gl_Position = vec4(clipSpace, 0.0, 1.0);
|
|
17
|
+
}
|
|
18
|
+
`;
|
|
19
|
+
|
|
20
|
+
export const fragmentShaderSourceV1 = `
|
|
21
|
+
precision highp float;
|
|
22
|
+
|
|
23
|
+
uniform vec2 u_resolution;
|
|
24
|
+
uniform sampler2D ad0;
|
|
25
|
+
uniform sampler2D ad1;
|
|
26
|
+
uniform sampler2D u_alphaMask;
|
|
27
|
+
|
|
28
|
+
varying vec2 v_uv;
|
|
29
|
+
|
|
30
|
+
uniform int hasLogo0;
|
|
31
|
+
uniform mat3 u_matrix0;
|
|
32
|
+
|
|
33
|
+
uniform int hasLogo1;
|
|
34
|
+
uniform mat3 u_matrix1;//the reverse homography
|
|
35
|
+
|
|
36
|
+
const float Directions = 16.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
|
|
37
|
+
const float QualityAd = 3.0; // BLUR QUALITY (Default 3.0 - More is better but slower)
|
|
38
|
+
const float QualityAlpha = 5.0; // BLUR QUALITY (Default 3.0 - More is better but slower)
|
|
39
|
+
const float BlurRadiusAd = 10.0;
|
|
40
|
+
const float BlurRadiusAlpha = 10.0;
|
|
41
|
+
const float Pi = 6.28318530718; // Pi*2
|
|
42
|
+
|
|
43
|
+
vec4 BlurAd(sampler2D adTexture, vec2 adTexCoord) {
|
|
44
|
+
vec2 Radius = BlurRadiusAd/u_resolution.xy;
|
|
45
|
+
vec4 res = texture2D(adTexture, adTexCoord);
|
|
46
|
+
|
|
47
|
+
for( float d=0.0; d<Pi; d+=Pi/Directions) {
|
|
48
|
+
for(float i=1.0/QualityAd; i<=1.0; i+=1.0/QualityAd) {
|
|
49
|
+
res += texture2D(adTexture, adTexCoord+vec2(cos(d),sin(d))*Radius*i);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
res /= QualityAd * Directions - 5.0;
|
|
54
|
+
|
|
55
|
+
return res;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
void BlendWithLogo(sampler2D ad, mat3 matrix) {
|
|
59
|
+
vec2 curCoord = gl_FragCoord.xy;
|
|
60
|
+
curCoord.y = u_resolution[1] - curCoord.y;
|
|
61
|
+
|
|
62
|
+
vec2 texCoord;
|
|
63
|
+
texCoord.x = (matrix[0][0]*curCoord.x + matrix[0][1]*curCoord.y + matrix[0][2]) / (matrix[2][0]*curCoord.x + matrix[2][1]*curCoord.y + 1.0);
|
|
64
|
+
texCoord.y = (matrix[1][0]*curCoord.x + matrix[1][1]*curCoord.y + matrix[1][2]) / (matrix[2][0]*curCoord.x + matrix[2][1]*curCoord.y + 1.0);
|
|
65
|
+
texCoord /= u_resolution;
|
|
66
|
+
|
|
67
|
+
vec4 maskAlpha = texture2D(u_alphaMask, v_uv);
|
|
68
|
+
vec4 adColor = BlurAd(ad, texCoord);
|
|
69
|
+
float adAlpha = texture2D(ad0, texCoord).a;
|
|
70
|
+
|
|
71
|
+
float finalAlpha = maskAlpha.r;
|
|
72
|
+
if (finalAlpha < 0.3)
|
|
73
|
+
finalAlpha = 0.0;
|
|
74
|
+
finalAlpha *= adColor.a;
|
|
75
|
+
gl_FragColor = vec4(adColor.rgb, finalAlpha);
|
|
76
|
+
gl_FragColor.rgb *= finalAlpha;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
void main() {
|
|
80
|
+
if (hasLogo0 == 1) {
|
|
81
|
+
BlendWithLogo(ad0, u_matrix0);
|
|
82
|
+
}
|
|
83
|
+
if (hasLogo1 == 1) {
|
|
84
|
+
BlendWithLogo(ad1, u_matrix1);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
`;
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
export const vertexShaderSourceV1Old = `
|
|
2
|
+
|
|
3
|
+
//High precision mode
|
|
4
|
+
precision highp float;
|
|
5
|
+
|
|
6
|
+
// an attribute is an input (in) to a vertex shader.
|
|
7
|
+
// It will receive vertex data from the buffer
|
|
8
|
+
attribute vec2 a_position;
|
|
9
|
+
attribute vec2 a_uv;
|
|
10
|
+
uniform vec2 u_resolution;
|
|
11
|
+
varying vec2 v_texCoord;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
// Main vertex shader
|
|
15
|
+
void main() {
|
|
16
|
+
// convert the rectangle from pixels to 0.0 to 1.0
|
|
17
|
+
vec2 zeroToOne = a_position / u_resolution;
|
|
18
|
+
|
|
19
|
+
// convert from 0->1 to 0->2
|
|
20
|
+
vec2 zeroToTwo = zeroToOne * 2.0;
|
|
21
|
+
|
|
22
|
+
// convert from 0->2 to -1->+1 (clipspace)
|
|
23
|
+
vec2 clipSpace = zeroToTwo - 1.0;
|
|
24
|
+
|
|
25
|
+
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
|
|
26
|
+
|
|
27
|
+
// pass the texCoord to the fragment shader
|
|
28
|
+
// The GPU will interpolate this value between points.
|
|
29
|
+
v_texCoord = a_uv;
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
|
|
33
|
+
export const fragmentShaderSourceV1Old = `
|
|
34
|
+
|
|
35
|
+
//High precision mode
|
|
36
|
+
precision highp float;
|
|
37
|
+
|
|
38
|
+
//The textures
|
|
39
|
+
uniform sampler2D u_image;//video frame's texture2D
|
|
40
|
+
uniform sampler2D ad0;//the ad texture2D
|
|
41
|
+
uniform sampler2D ad1;//the ad texture2D
|
|
42
|
+
uniform sampler2D ad2;//the ad texture2D
|
|
43
|
+
uniform sampler2D ad3;//the ad texture2D
|
|
44
|
+
|
|
45
|
+
uniform vec2 u_resolution2;//resolution of the canvas
|
|
46
|
+
|
|
47
|
+
//v_texCoord from the vertex shader
|
|
48
|
+
varying vec2 v_texCoord;
|
|
49
|
+
|
|
50
|
+
//Logos' staff
|
|
51
|
+
uniform int hasLogo0;//has logo ?
|
|
52
|
+
uniform int adForLogo0;
|
|
53
|
+
uniform sampler2D alpha0;//the alpha's mate
|
|
54
|
+
uniform mat3 u_matrix0;//the reverse homography
|
|
55
|
+
uniform vec2 u_alpha0TopLeft;//the alpha mate's top-left
|
|
56
|
+
uniform vec2 u_alpha0Size;//the alpha mate's size
|
|
57
|
+
|
|
58
|
+
uniform int hasLogo1;//has logo ?
|
|
59
|
+
uniform int adForLogo1;
|
|
60
|
+
uniform sampler2D alpha1;//the alpha's mate
|
|
61
|
+
uniform mat3 u_matrix1;//the reverse homography
|
|
62
|
+
uniform vec2 u_alpha1TopLeft;//the alpha mate's top-left
|
|
63
|
+
uniform vec2 u_alpha1Size;//the alpha mate's size
|
|
64
|
+
|
|
65
|
+
uniform int hasLogo2;//has logo ?
|
|
66
|
+
uniform int adForLogo2;
|
|
67
|
+
uniform sampler2D alpha2;//the alpha's mate
|
|
68
|
+
uniform mat3 u_matrix2;//the reverse homography
|
|
69
|
+
uniform vec2 u_alpha2TopLeft;//the alpha mate's top-left
|
|
70
|
+
uniform vec2 u_alpha2Size;//the alpha mate's size
|
|
71
|
+
|
|
72
|
+
uniform int hasLogo3;//has logo ?
|
|
73
|
+
uniform int adForLogo3;
|
|
74
|
+
uniform sampler2D alpha3;//the alpha's mate
|
|
75
|
+
uniform mat3 u_matrix3;//the reverse homography
|
|
76
|
+
uniform vec2 u_alpha3TopLeft;//the alpha mate's top-left
|
|
77
|
+
uniform vec2 u_alpha3Size;//the alpha mate's size
|
|
78
|
+
|
|
79
|
+
const float Directions = 16.0; // BLUR DIRECTIONS (Default 16.0 - More is better but slower)
|
|
80
|
+
const float QualityAd = 3.0; // BLUR QUALITY (Default 3.0 - More is better but slower)
|
|
81
|
+
const float QualityAlpha = 5.0; // BLUR QUALITY (Default 3.0 - More is better but slower)
|
|
82
|
+
const float BlurRadiusAd = 10.0;
|
|
83
|
+
const float BlurRadiusAlpha = 10.0;
|
|
84
|
+
const float Pi = 6.28318530718; // Pi*2
|
|
85
|
+
|
|
86
|
+
float BlurAlpha(sampler2D alphaTexture, vec2 alphaCoord) {
|
|
87
|
+
float res = texture2D(alphaTexture, alphaCoord).a;
|
|
88
|
+
vec2 Radius = BlurRadiusAlpha/u_resolution2.xy;
|
|
89
|
+
|
|
90
|
+
for( float d=0.0; d<Pi; d+=Pi/Directions) {
|
|
91
|
+
for(float i=1.0/QualityAlpha; i<=1.0; i+=1.0/QualityAlpha) {
|
|
92
|
+
res += texture2D(alphaTexture, alphaCoord+vec2(cos(d),sin(d))*Radius*i).a;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
res /= QualityAlpha * Directions - 15.0;
|
|
97
|
+
|
|
98
|
+
return res;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
vec4 BlurAd(sampler2D adTexture, vec2 adTexCoord) {
|
|
102
|
+
vec2 Radius = BlurRadiusAd/u_resolution2.xy;
|
|
103
|
+
vec4 res = texture2D(adTexture, adTexCoord);
|
|
104
|
+
|
|
105
|
+
for( float d=0.0; d<Pi; d+=Pi/Directions) {
|
|
106
|
+
for(float i=1.0/QualityAd; i<=1.0; i+=1.0/QualityAd) {
|
|
107
|
+
res += texture2D(adTexture, adTexCoord+vec2(cos(d),sin(d))*Radius*i);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
res /= QualityAd * Directions - 5.0;
|
|
112
|
+
|
|
113
|
+
return res;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
bool BlendWithLogo(int adUnit, sampler2D alphaTexture, mat3 matrix, vec2 curCoord, vec2 alphaTopLeft, vec2 alphaSize, vec4 videoImagePix) {
|
|
117
|
+
|
|
118
|
+
vec2 texCoord;
|
|
119
|
+
texCoord.x = (matrix[0][0]*curCoord.x + matrix[0][1]*curCoord.y + matrix[0][2]) / (matrix[2][0]*curCoord.x + matrix[2][1]*curCoord.y + 1.0);
|
|
120
|
+
texCoord.y = (matrix[1][0]*curCoord.x + matrix[1][1]*curCoord.y + matrix[1][2]) / (matrix[2][0]*curCoord.x + matrix[2][1]*curCoord.y + 1.0);
|
|
121
|
+
texCoord /= u_resolution2;
|
|
122
|
+
|
|
123
|
+
//if we're in the bounding rect of the logo
|
|
124
|
+
if (texCoord.x >= 0.0 && texCoord.y >= 0.0 && texCoord.x <= 1.0 && texCoord.y <= 1.0) {
|
|
125
|
+
float maskAlpha = 1.0;
|
|
126
|
+
vec2 alphaCoord = (curCoord - alphaTopLeft)/alphaSize;//get the coordinate on the alpha mate
|
|
127
|
+
if (alphaCoord.x >= 0.0 && alphaCoord.y >= 0.0 && alphaCoord.x <= 1.0 && alphaCoord.y <= 1.0) {
|
|
128
|
+
// maskAlpha = BlurAlpha(alphaTexture, alphaCoord);
|
|
129
|
+
maskAlpha = texture2D(alphaTexture, alphaCoord).a;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
vec4 adColor =
|
|
133
|
+
adUnit == 0 ? BlurAd(ad0, texCoord) :
|
|
134
|
+
adUnit == 1 ? BlurAd(ad1, texCoord) :
|
|
135
|
+
adUnit == 2 ? BlurAd(ad2, texCoord) :
|
|
136
|
+
BlurAd(ad3, texCoord); //get the logo's texel
|
|
137
|
+
|
|
138
|
+
float adAlpha =
|
|
139
|
+
adUnit == 0 ? texture2D(ad0, texCoord).a :
|
|
140
|
+
adUnit == 1 ? texture2D(ad1, texCoord).a :
|
|
141
|
+
adUnit == 2 ? texture2D(ad2, texCoord).a :
|
|
142
|
+
texture2D(ad3, texCoord).a; //get the logo's texel
|
|
143
|
+
|
|
144
|
+
float finalAlpha = maskAlpha * adColor.a;
|
|
145
|
+
gl_FragColor = vec4(adColor.rgb, finalAlpha);
|
|
146
|
+
gl_FragColor.rgb *= finalAlpha;
|
|
147
|
+
return true;
|
|
148
|
+
} else {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
void main()
|
|
153
|
+
{
|
|
154
|
+
//calculate cur-coord (with pixels units)
|
|
155
|
+
vec2 curCoord = gl_FragCoord.xy;
|
|
156
|
+
curCoord.y = u_resolution2[1] - curCoord.y;
|
|
157
|
+
|
|
158
|
+
vec4 videoImagePix = texture2D(u_image, v_texCoord);
|
|
159
|
+
|
|
160
|
+
if (hasLogo0 == 1) {
|
|
161
|
+
BlendWithLogo(adForLogo0,alpha0, u_matrix0, curCoord,u_alpha0TopLeft, u_alpha0Size, videoImagePix);
|
|
162
|
+
return;
|
|
163
|
+
} else if (hasLogo1 == 1) {
|
|
164
|
+
BlendWithLogo(adForLogo1, alpha1, u_matrix1, curCoord,u_alpha1TopLeft, u_alpha1Size, videoImagePix);
|
|
165
|
+
return;
|
|
166
|
+
} else if (hasLogo2 == 1) {
|
|
167
|
+
BlendWithLogo(adForLogo2, alpha2, u_matrix2, curCoord,u_alpha2TopLeft, u_alpha2Size, videoImagePix);
|
|
168
|
+
return;
|
|
169
|
+
} else if (hasLogo3 == 1) {
|
|
170
|
+
BlendWithLogo(adForLogo3, alpha3, u_matrix3, curCoord,u_alpha3TopLeft, u_alpha3Size, videoImagePix);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
`;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
export const vertexShaderSourceV2 = `#version 300 es
|
|
2
|
+
|
|
3
|
+
// an attribute is an input (in) to a vertex shader.
|
|
4
|
+
// It will receive vertex data from the buffer
|
|
5
|
+
in vec2 a_position;
|
|
6
|
+
|
|
7
|
+
//Identity matrix for now
|
|
8
|
+
uniform mat3 u_matrix;
|
|
9
|
+
|
|
10
|
+
//The canvas resolution, to covert to ZeTor
|
|
11
|
+
uniform vec2 u_resolution;
|
|
12
|
+
|
|
13
|
+
//a_texCoord->v_texCoord interpolation
|
|
14
|
+
//in vec2 a_texCoord;
|
|
15
|
+
//out vec2 v_texCoord;
|
|
16
|
+
|
|
17
|
+
// Main vertex shader
|
|
18
|
+
void main() {
|
|
19
|
+
//Translate, rotate, scale by u_matrix:
|
|
20
|
+
vec2 position = (u_matrix * vec3(a_position, 1)).xy;
|
|
21
|
+
|
|
22
|
+
//Convert the position from pixels to ZeTor [0.0,1.0]
|
|
23
|
+
vec2 zeroToOne = position / u_resolution;
|
|
24
|
+
|
|
25
|
+
//Convert from [0,1] to [0,2]
|
|
26
|
+
vec2 zeroToTwo = zeroToOne * 2.0;
|
|
27
|
+
|
|
28
|
+
//Convert from [0,2] to [-1,+1] (clipspace)
|
|
29
|
+
vec2 clipSpace = zeroToTwo - 1.0;
|
|
30
|
+
|
|
31
|
+
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
|
|
32
|
+
|
|
33
|
+
//Pass the texCoord to the fragment shader
|
|
34
|
+
//The GPU will interpolate this value between points.
|
|
35
|
+
//v_texCoord = a_texCoord;
|
|
36
|
+
}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
export const fragmentShaderSourceV2 = `#version 300 es
|
|
40
|
+
|
|
41
|
+
//High precision mode
|
|
42
|
+
precision highp float;
|
|
43
|
+
|
|
44
|
+
//The textures
|
|
45
|
+
//uniform sampler2D u_image;//video frame's texture
|
|
46
|
+
uniform sampler2D ad0;//the ad texture
|
|
47
|
+
uniform sampler2D ad1;//the ad texture
|
|
48
|
+
uniform sampler2D ad2;//the ad texture
|
|
49
|
+
uniform sampler2D ad3;//the ad texture
|
|
50
|
+
|
|
51
|
+
uniform vec2 u_resolution2;//resolution of the canvas
|
|
52
|
+
|
|
53
|
+
//v_texCoord from the vertex shader
|
|
54
|
+
//in vec2 v_texCoord;
|
|
55
|
+
|
|
56
|
+
//Logos' staff
|
|
57
|
+
uniform int hasLogo0;//has logo ?
|
|
58
|
+
uniform int adForLogo0;
|
|
59
|
+
uniform sampler2D alpha0;//the alpha's mate
|
|
60
|
+
uniform mat3 u_matrix0;//the reverse homography
|
|
61
|
+
uniform vec2 u_alpha0TopLeft;//the alpha mate's top-left
|
|
62
|
+
uniform vec2 u_alpha0Size;//the alpha mate's size
|
|
63
|
+
|
|
64
|
+
uniform int hasLogo1;//has logo ?
|
|
65
|
+
uniform int adForLogo1;
|
|
66
|
+
uniform sampler2D alpha1;//the alpha's mate
|
|
67
|
+
uniform mat3 u_matrix1;//the reverse homography
|
|
68
|
+
uniform vec2 u_alpha1TopLeft;//the alpha mate's top-left
|
|
69
|
+
uniform vec2 u_alpha1Size;//the alpha mate's size
|
|
70
|
+
|
|
71
|
+
uniform int hasLogo2;//has logo ?
|
|
72
|
+
uniform int adForLogo2;
|
|
73
|
+
uniform sampler2D alpha2;//the alpha's mate
|
|
74
|
+
uniform mat3 u_matrix2;//the reverse homography
|
|
75
|
+
uniform vec2 u_alpha2TopLeft;//the alpha mate's top-left
|
|
76
|
+
uniform vec2 u_alpha2Size;//the alpha mate's size
|
|
77
|
+
|
|
78
|
+
uniform int hasLogo3;//has logo ?
|
|
79
|
+
uniform int adForLogo3;
|
|
80
|
+
uniform sampler2D alpha3;//the alpha's mate
|
|
81
|
+
uniform mat3 u_matrix3;//the reverse homography
|
|
82
|
+
uniform vec2 u_alpha3TopLeft;//the alpha mate's top-left
|
|
83
|
+
uniform vec2 u_alpha3Size;//the alpha mate's size
|
|
84
|
+
|
|
85
|
+
uniform int hasDigit;//has debug digit texture
|
|
86
|
+
uniform sampler2D digitTex;//the digits's mate
|
|
87
|
+
uniform vec2 u_digitTopLeft;//the digit mate's top-left
|
|
88
|
+
uniform vec2 u_digitTopLeft2;//the digit mate's top-left
|
|
89
|
+
uniform vec2 u_digitSize;//the digit mate's size
|
|
90
|
+
|
|
91
|
+
//Output
|
|
92
|
+
out vec4 outColor;
|
|
93
|
+
bool BlendDigit(in vec2 curCoord) {
|
|
94
|
+
//vec2 texCoord = curCoord;
|
|
95
|
+
//texCoord /= u_resolution2;
|
|
96
|
+
vec2 digitCoord = (curCoord - u_digitTopLeft)/u_digitSize;//get the coordinate on the digit size
|
|
97
|
+
if (digitCoord.x >= 0.0 && digitCoord.y >= 0.0 && digitCoord.x <= 1.0 && digitCoord.y <= 1.0)
|
|
98
|
+
{
|
|
99
|
+
outColor = texture(digitTex, digitCoord);
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
bool BlendDigit2(in vec2 curCoord) {
|
|
105
|
+
//vec2 texCoord = curCoord;
|
|
106
|
+
//texCoord /= u_resolution2;
|
|
107
|
+
vec2 digitCoord = (curCoord - u_digitTopLeft2)/u_digitSize;//get the coordinate on the digit size
|
|
108
|
+
if (digitCoord.x >= 0.0 && digitCoord.y >= 0.0 && digitCoord.x <= 1.0 && digitCoord.y <= 1.0)
|
|
109
|
+
{
|
|
110
|
+
outColor = texture(digitTex, digitCoord);
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
115
|
+
bool BlendWithLogo(
|
|
116
|
+
in int adUnit,
|
|
117
|
+
in sampler2D alphaTexture,
|
|
118
|
+
in mat3 matrix,
|
|
119
|
+
in vec2 curCoord,
|
|
120
|
+
in vec2 alphaTopLeft,
|
|
121
|
+
in vec2 alphaSize)
|
|
122
|
+
{
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
vec2 texCoord;
|
|
127
|
+
texCoord.x = (matrix[0][0]*curCoord.x + matrix[0][1]*curCoord.y + matrix[0][2]) / (matrix[2][0]*curCoord.x + matrix[2][1]*curCoord.y + 1.0);
|
|
128
|
+
texCoord.y = (matrix[1][0]*curCoord.x + matrix[1][1]*curCoord.y + matrix[1][2]) / (matrix[2][0]*curCoord.x + matrix[2][1]*curCoord.y + 1.0);
|
|
129
|
+
texCoord /= u_resolution2;
|
|
130
|
+
|
|
131
|
+
//if we're in the bounding rect of the logo
|
|
132
|
+
if (texCoord.x >= 0.0 && texCoord.y >= 0.0 && texCoord.x <= 1.0 && texCoord.y <= 1.0)
|
|
133
|
+
{
|
|
134
|
+
float alpha = 1.0;
|
|
135
|
+
vec2 alphaCoord = (curCoord - alphaTopLeft)/alphaSize;//get the coordinate on the alpha mate
|
|
136
|
+
if (alphaCoord.x >= 0.0 && alphaCoord.x <= 1.0 &&
|
|
137
|
+
alphaCoord.y >= 0.0 && alphaCoord.y <= 1.0)
|
|
138
|
+
{
|
|
139
|
+
//get the alpha texel:
|
|
140
|
+
alpha *= texture(alphaTexture, alphaCoord).a;//without blur
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
vec4 ad0Pix = texture(ad0, texCoord);
|
|
144
|
+
adUnit == 0 ? texture(ad0, texCoord) :
|
|
145
|
+
adUnit == 1 ? texture(ad1, texCoord) :
|
|
146
|
+
adUnit == 2 ? texture(ad2, texCoord) :
|
|
147
|
+
texture(ad3, texCoord);//get the logo's texel
|
|
148
|
+
|
|
149
|
+
alpha *= ad0Pix.a;//consider the alpha of the logo
|
|
150
|
+
vec3 resultRGB = ad0Pix.rgb;// + videoImagePix.rgb*(1.0-alpha);//blend
|
|
151
|
+
// if (alpha == 0.0) resultRGB = vec3(0,0,0);
|
|
152
|
+
outColor = vec4(resultRGB, alpha);
|
|
153
|
+
return true;
|
|
154
|
+
} else {
|
|
155
|
+
return false;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
void main()
|
|
159
|
+
{
|
|
160
|
+
//calculate cur-coord (with pixels units)
|
|
161
|
+
vec2 curCoord = gl_FragCoord.xy;
|
|
162
|
+
curCoord.y = u_resolution2[1] - curCoord.y;
|
|
163
|
+
//if (hasDigit == 1 && (BlendDigit(curCoord) || BlendDigit2(curCoord))) return;
|
|
164
|
+
if (hasDigit == 1 && (BlendDigit(curCoord))) return;
|
|
165
|
+
else if (hasLogo0 == 1 &&
|
|
166
|
+
BlendWithLogo(adForLogo0,
|
|
167
|
+
alpha0, u_matrix0, curCoord,u_alpha0TopLeft, u_alpha0Size))
|
|
168
|
+
{
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
else if (hasLogo1 == 1 &&
|
|
172
|
+
BlendWithLogo(adForLogo1,
|
|
173
|
+
alpha1, u_matrix1, curCoord,u_alpha1TopLeft, u_alpha1Size))
|
|
174
|
+
{
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
else if (hasLogo2 == 1 &&
|
|
178
|
+
BlendWithLogo(adForLogo2,
|
|
179
|
+
alpha2, u_matrix2, curCoord,u_alpha2TopLeft, u_alpha2Size))
|
|
180
|
+
{
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
else if (hasLogo3 == 1 &&
|
|
184
|
+
BlendWithLogo(adForLogo3,
|
|
185
|
+
alpha3, u_matrix3, curCoord,u_alpha3TopLeft, u_alpha3Size))
|
|
186
|
+
{
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
else {//no logo
|
|
190
|
+
outColor = vec4(0,0,0,0);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
`;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>MP4 Video Player</title>
|
|
7
|
+
<link rel="stylesheet" href="./style.css" />
|
|
8
|
+
<script type="module" src="./index.js"></script>
|
|
9
|
+
</head>
|
|
10
|
+
<body>
|
|
11
|
+
<br />
|
|
12
|
+
<input type="number" id="numberInput" value="2" />
|
|
13
|
+
|
|
14
|
+
<input
|
|
15
|
+
type="checkbox"
|
|
16
|
+
id="plus05CorrectionCheckbox"
|
|
17
|
+
name="plus05CorrectionCheckbox"
|
|
18
|
+
/>
|
|
19
|
+
<label for="plus05CorrectionCheckbox" id="plus05CorrectionLabel"
|
|
20
|
+
>plus05Correction (for 29.97 only):</label
|
|
21
|
+
>
|
|
22
|
+
|
|
23
|
+
<input
|
|
24
|
+
type="checkbox"
|
|
25
|
+
id="doNotRenderAugmentationCheckbox"
|
|
26
|
+
name="doNotRenderAugmentationCheckbox"
|
|
27
|
+
/>
|
|
28
|
+
<label
|
|
29
|
+
for="doNotRenderAugmentationCheckbox"
|
|
30
|
+
id="doNotRenderAugmentationLabel"
|
|
31
|
+
>doNotRenderAugmentation:</label
|
|
32
|
+
>
|
|
33
|
+
|
|
34
|
+
<br />
|
|
35
|
+
<button id="toggleBtn" onclick="toggleBBPlayer()">
|
|
36
|
+
Toggle ott player OFF
|
|
37
|
+
</button>
|
|
38
|
+
<br />
|
|
39
|
+
<div id="forceUpdate" style="font-size: 3px"></div>
|
|
40
|
+
<button id="qualityButton">Get Available Qualities</button>
|
|
41
|
+
<select id="qualitySelect">
|
|
42
|
+
<option value="">Select Quality</option>
|
|
43
|
+
</select>
|
|
44
|
+
<div id="debugText"></div>
|
|
45
|
+
<div id="debugText2"></div>
|
|
46
|
+
<div id="player_container">
|
|
47
|
+
<video
|
|
48
|
+
id="video_element"
|
|
49
|
+
src="22-10-2024-Test10-Home.mp4"
|
|
50
|
+
poster=""
|
|
51
|
+
crossorigin
|
|
52
|
+
controls
|
|
53
|
+
></video>
|
|
54
|
+
</div>
|
|
55
|
+
<canvas
|
|
56
|
+
style="position: absolute; top: 700px"
|
|
57
|
+
width="1280"
|
|
58
|
+
height="720"
|
|
59
|
+
id="test"
|
|
60
|
+
></canvas>
|
|
61
|
+
<script src="https://www.virtualott.com/MK_player_lib/wmc.prod.js"></script>
|
|
62
|
+
</body>
|
|
63
|
+
</html>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import OTTPlayer from "../../OTTPlayer";
|
|
2
|
+
|
|
3
|
+
window.BB = {
|
|
4
|
+
MAX_LOGOS: 4,
|
|
5
|
+
RENDER_IN_WORKER: true,
|
|
6
|
+
OTTPlayer,
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const video = document.getElementById("video_element");
|
|
10
|
+
new OTTPlayer(video, 60000 / 1001, {
|
|
11
|
+
url: "https://nbablpng.akamaized.net/live/hls-itc/bbtestexternal/v7-121.m3u8?stSecret=rj12sw543terw32422334swees",
|
|
12
|
+
cloudFrontURL: "https://db8igqxlbvayn.cloudfront.net",
|
|
13
|
+
mediaIdJsonURL: "test",
|
|
14
|
+
offsetJsonURL: "test",
|
|
15
|
+
gameId: "22-10-2024-Test10-Home",
|
|
16
|
+
debug: false,
|
|
17
|
+
augmentation: {
|
|
18
|
+
channelName: "nba2",
|
|
19
|
+
offset: (28 * 60 * 60 + 49 * 60 + 36) * -59.94
|
|
20
|
+
},
|
|
21
|
+
maskMP4: true
|
|
22
|
+
});
|
|
23
|
+
|