|
|
@@ -277,16 +277,16 @@ jsmpeg.prototype.load = function( url ) {
|
|
277
|
277
|
}
|
|
278
|
278
|
};
|
|
279
|
279
|
|
|
280
|
|
- if( !this.gl ) {
|
|
281
|
|
- request.onprogress = this.updateLoader.bind(this);
|
|
282
|
|
- }
|
|
|
280
|
+ request.onprogress = this.gl
|
|
|
281
|
+ ? this.updateLoaderGL.bind(this)
|
|
|
282
|
+ : this.updateLoader2D.bind(this);
|
|
283
|
283
|
|
|
284
|
284
|
request.open('GET', url);
|
|
285
|
285
|
request.responseType = "arraybuffer";
|
|
286
|
286
|
request.send();
|
|
287
|
287
|
};
|
|
288
|
288
|
|
|
289
|
|
-jsmpeg.prototype.updateLoader = function( ev ) {
|
|
|
289
|
+jsmpeg.prototype.updateLoader2D = function( ev ) {
|
|
290
|
290
|
var
|
|
291
|
291
|
p = ev.loaded / ev.total,
|
|
292
|
292
|
w = this.canvas.width,
|
|
|
@@ -298,6 +298,12 @@ jsmpeg.prototype.updateLoader = function( ev ) {
|
|
298
|
298
|
ctx.fillStyle = '#fff';
|
|
299
|
299
|
ctx.fillRect(0, h - h*p, w, h*p);
|
|
300
|
300
|
};
|
|
|
301
|
+
|
|
|
302
|
+jsmpeg.prototype.updateLoaderGL = function( ev ) {
|
|
|
303
|
+ var gl = this.gl;
|
|
|
304
|
+ gl.uniform1f(gl.getUniformLocation(this.loadingProgram, 'loaded'), (ev.loaded / ev.total));
|
|
|
305
|
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
|
306
|
+};
|
|
301
|
307
|
|
|
302
|
308
|
jsmpeg.prototype.loadCallback = function(file) {
|
|
303
|
309
|
var time = Date.now();
|
|
|
@@ -550,7 +556,10 @@ jsmpeg.prototype.initBuffers = function() {
|
|
550
|
556
|
this.canvas.width = this.width;
|
|
551
|
557
|
this.canvas.height = this.height;
|
|
552
|
558
|
|
|
553
|
|
- if( !this.gl ) {
|
|
|
559
|
+ if( this.gl ) {
|
|
|
560
|
+ this.gl.useProgram(this.program);
|
|
|
561
|
+ }
|
|
|
562
|
+ else {
|
|
554
|
563
|
this.currentRGBA = this.canvasContext.getImageData(0, 0, this.width, this.height);
|
|
555
|
564
|
this.fillArray(this.currentRGBA.data, 255);
|
|
556
|
565
|
}
|
|
|
@@ -736,8 +745,8 @@ jsmpeg.prototype.renderFrame2D = function() {
|
|
736
|
745
|
jsmpeg.prototype.gl = null;
|
|
737
|
746
|
jsmpeg.prototype.program = null;
|
|
738
|
747
|
jsmpeg.prototype.YTexture = null;
|
|
739
|
|
-jsmpeg.prototype.UTexture = null;
|
|
740
|
|
-jsmpeg.prototype.VTexture = null;
|
|
|
748
|
+jsmpeg.prototype.CBTexture = null;
|
|
|
749
|
+jsmpeg.prototype.CRTexture = null;
|
|
741
|
750
|
|
|
742
|
751
|
jsmpeg.prototype.createTexture = function(index, name) {
|
|
743
|
752
|
var gl = this.gl;
|
|
|
@@ -777,11 +786,16 @@ jsmpeg.prototype.initWebGL = function() {
|
|
777
|
786
|
if (!gl) {
|
|
778
|
787
|
return false;
|
|
779
|
788
|
}
|
|
780
|
|
-
|
|
781
|
|
- // setup shaders
|
|
|
789
|
+
|
|
|
790
|
+ // init buffers
|
|
|
791
|
+ this.buffer = gl.createBuffer();
|
|
|
792
|
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
|
793
|
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]), gl.STATIC_DRAW);
|
|
|
794
|
+
|
|
|
795
|
+ // The main YCbCrToRGBA Shader
|
|
782
|
796
|
this.program = gl.createProgram();
|
|
783
|
|
- gl.attachShader(this.program, this.compileShader(gl.VERTEX_SHADER, YCBCRTORGBA_VERTEX_SHADER));
|
|
784
|
|
- gl.attachShader(this.program, this.compileShader(gl.FRAGMENT_SHADER, YCBCRTORGBA_FRAGMENT_SHADER));
|
|
|
797
|
+ gl.attachShader(this.program, this.compileShader(gl.VERTEX_SHADER, SHADER_VERTEX_IDENTITY));
|
|
|
798
|
+ gl.attachShader(this.program, this.compileShader(gl.FRAGMENT_SHADER, SHADER_FRAGMENT_YCBCRTORGBA));
|
|
785
|
799
|
gl.linkProgram(this.program);
|
|
786
|
800
|
|
|
787
|
801
|
if( !gl.getProgramParameter(this.program, gl.LINK_STATUS) ) {
|
|
|
@@ -792,17 +806,25 @@ jsmpeg.prototype.initWebGL = function() {
|
|
792
|
806
|
|
|
793
|
807
|
// setup textures
|
|
794
|
808
|
this.YTexture = this.createTexture(0, 'YTexture');
|
|
795
|
|
- this.UTexture = this.createTexture(1, 'UTexture');
|
|
796
|
|
- this.VTexture = this.createTexture(2, 'VTexture');
|
|
797
|
|
-
|
|
798
|
|
- // init buffers
|
|
799
|
|
- this.buffer = gl.createBuffer();
|
|
800
|
|
- gl.bindBuffer(gl.ARRAY_BUFFER, this.buffer);
|
|
801
|
|
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, 0, 1, 1, 0, 1, 1]), gl.STATIC_DRAW);
|
|
|
809
|
+ this.CBTexture = this.createTexture(1, 'CBTexture');
|
|
|
810
|
+ this.CRTexture = this.createTexture(2, 'CRTexture');
|
|
802
|
811
|
|
|
803
|
812
|
var vertexAttr = gl.getAttribLocation(this.program, 'vertex');
|
|
804
|
813
|
gl.enableVertexAttribArray(vertexAttr);
|
|
805
|
814
|
gl.vertexAttribPointer(vertexAttr, 2, gl.FLOAT, false, 0, 0);
|
|
|
815
|
+
|
|
|
816
|
+
|
|
|
817
|
+ // Shader for the loading screen
|
|
|
818
|
+ this.loadingProgram = gl.createProgram();
|
|
|
819
|
+ gl.attachShader(this.loadingProgram, this.compileShader(gl.VERTEX_SHADER, SHADER_VERTEX_IDENTITY));
|
|
|
820
|
+ gl.attachShader(this.loadingProgram, this.compileShader(gl.FRAGMENT_SHADER, SHADER_FRAGMENT_LOADING));
|
|
|
821
|
+ gl.linkProgram(this.loadingProgram);
|
|
|
822
|
+
|
|
|
823
|
+ gl.useProgram(this.loadingProgram);
|
|
|
824
|
+
|
|
|
825
|
+ vertexAttr = gl.getAttribLocation(this.loadingProgram, 'vertex');
|
|
|
826
|
+ gl.enableVertexAttribArray(vertexAttr);
|
|
|
827
|
+ gl.vertexAttribPointer(vertexAttr, 2, gl.FLOAT, false, 0, 0);
|
|
806
|
828
|
|
|
807
|
829
|
return true;
|
|
808
|
830
|
};
|
|
|
@@ -822,11 +844,11 @@ jsmpeg.prototype.renderFrameGL = function() {
|
|
822
|
844
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, this.width, this.height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, uint8Y);
|
|
823
|
845
|
|
|
824
|
846
|
gl.activeTexture(gl.TEXTURE1);
|
|
825
|
|
- gl.bindTexture(gl.TEXTURE_2D, this.UTexture);
|
|
|
847
|
+ gl.bindTexture(gl.TEXTURE_2D, this.CBTexture);
|
|
826
|
848
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, this.halfWidth, this.halfHeight, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, uint8Cr);
|
|
827
|
849
|
|
|
828
|
850
|
gl.activeTexture(gl.TEXTURE2);
|
|
829
|
|
- gl.bindTexture(gl.TEXTURE_2D, this.VTexture);
|
|
|
851
|
+ gl.bindTexture(gl.TEXTURE_2D, this.CRTexture);
|
|
830
|
852
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, this.halfWidth, this.halfHeight, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, uint8Cb);
|
|
831
|
853
|
|
|
832
|
854
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
|
@@ -2288,17 +2310,17 @@ var
|
|
2288
|
2310
|
START_USER_DATA = 0xB2,
|
|
2289
|
2311
|
|
|
2290
|
2312
|
// Shaders for accelerated WebGL YCbCrToRGBA conversion
|
|
2291
|
|
- YCBCRTORGBA_FRAGMENT_SHADER = [
|
|
|
2313
|
+ SHADER_FRAGMENT_YCBCRTORGBA = [
|
|
2292
|
2314
|
'precision highp float;',
|
|
2293
|
2315
|
'uniform sampler2D YTexture;',
|
|
2294
|
|
- 'uniform sampler2D UTexture;',
|
|
2295
|
|
- 'uniform sampler2D VTexture;',
|
|
|
2316
|
+ 'uniform sampler2D CBTexture;',
|
|
|
2317
|
+ 'uniform sampler2D CRTexture;',
|
|
2296
|
2318
|
'varying vec2 texCoord;',
|
|
2297
|
2319
|
|
|
2298
|
2320
|
'void main() {',
|
|
2299
|
2321
|
'float y = texture2D(YTexture, texCoord).r;',
|
|
2300
|
|
- 'float cr = texture2D(UTexture, texCoord).r - 0.5;',
|
|
2301
|
|
- 'float cb = texture2D(VTexture, texCoord).r - 0.5;',
|
|
|
2322
|
+ 'float cr = texture2D(CBTexture, texCoord).r - 0.5;',
|
|
|
2323
|
+ 'float cb = texture2D(CRTexture, texCoord).r - 0.5;',
|
|
2302
|
2324
|
|
|
2303
|
2325
|
'gl_FragColor = vec4(',
|
|
2304
|
2326
|
'y + 1.4 * cr,',
|
|
|
@@ -2308,8 +2330,20 @@ var
|
|
2308
|
2330
|
');',
|
|
2309
|
2331
|
'}'
|
|
2310
|
2332
|
].join('\n'),
|
|
|
2333
|
+
|
|
|
2334
|
+ SHADER_FRAGMENT_LOADING = [
|
|
|
2335
|
+ 'precision highp float;',
|
|
|
2336
|
+ 'uniform float loaded;',
|
|
|
2337
|
+ 'varying vec2 texCoord;',
|
|
|
2338
|
+
|
|
|
2339
|
+ 'void main() {',
|
|
|
2340
|
+ 'float c = ceil(loaded-(1.0-texCoord.y));',
|
|
|
2341
|
+ //'float c = ceil(loaded-(1.0-texCoord.y) +sin((texCoord.x+loaded)*16.0)*0.01);', // Fancy wave anim
|
|
|
2342
|
+ 'gl_FragColor = vec4(c,c,c,1);',
|
|
|
2343
|
+ '}'
|
|
|
2344
|
+ ].join('\n'),
|
|
2311
|
2345
|
|
|
2312
|
|
- YCBCRTORGBA_VERTEX_SHADER = [
|
|
|
2346
|
+ SHADER_VERTEX_IDENTITY = [
|
|
2313
|
2347
|
'attribute vec2 vertex;',
|
|
2314
|
2348
|
'varying vec2 texCoord;',
|
|
2315
|
2349
|
|