wuyongxiang 4 éve%!(EXTRA string=óta)
szülő
commit
972ce2c3aa

BIN
static/img/jia_bu_icon2x.png


BIN
static/img/jia_ke_icon2x.png


BIN
static/img/jian_bu_icon2x.png


BIN
static/img/jian_ke_icon2x.png


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1 - 0
wasm/ffmpeghelper.js


BIN
wasm/ffmpeghelper.wasm


A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 185 - 0
wasm/helper.js


+ 163 - 0
wasm/index.html

@@ -0,0 +1,163 @@
+<html>
+	<head>
+		<link rel="shortcut icon" href="#">
+	</head>
+	
+	<canvas id="playCanvas" width="450" height="800"></canvas>
+	
+	<script type="text/javascript" src="pcm-player.js"></script>
+	<script type="text/javascript" src="webgl.js"></script>
+	<script type="text/javascript" src="helper.js"></script>
+	<script src="https://cdn.bootcss.com/vConsole/3.2.0/vconsole.min.js"></script>
+	<script>
+
+		var decodeCount = 1;
+	    var isFinish = false;
+		var socketURL = "ws://192.168.11.66:9101";
+		
+		var player = new PCMPlayer({
+        encoding: '16bitInt',
+        channels: 2,
+        sampleRate: 44100,
+        flushingTime: 22,
+		debug:false
+		});
+	
+		 this.canvas =  document.getElementById("playCanvas");
+		 var webglPlayer = new WebGLPlayer(this.canvas, {
+            preserveDrawingBuffer: false
+        });
+		
+		let vConsole = new VConsole();
+		
+		Module = {};
+		Module.onRuntimeInitialized = function() 
+		{
+			console.log("Wasm 加载成功!")
+			isFinish = true;
+			
+			var ret = Module._openDecoder(720, 1280);
+			if(!ret)
+			{
+				console.log("打开编码器成功");
+			}
+		}
+		
+		function closeDecoder()
+		{
+			Module._destroyDecoder();
+		}
+		
+		function decodeH264(data)
+		{
+			console.log("调用h264");
+			var retPtr = Module._malloc(2457600);//接收的数据
+			var inputPtr = Module._malloc(data.length);//输入数据
+			
+			for( i =0;i < data.length;i++)
+			{
+				Module.HEAPU8[(inputPtr)+i] = data[i];//转换为堆数据
+			}
+			
+			var time = new Date().getTime();
+			var ret = Module._feedData(inputPtr, data.length, retPtr);
+			if(ret == 0)
+			{
+				console.log("解码成功 %d, 耗时 %d ms", ret, new Date().getTime() - time);
+			}
+			else
+			{
+				console.log("解码识别 %d", ret);
+			}
+			
+			var yuvData = new Uint8Array(2457600);
+			for(i = 0;i < yuvData.length;i++)
+			{
+				yuvData[i] = Module.HEAPU8[(retPtr)+i];
+			}
+			webglPlayer.renderFrame(yuvData, 720, 1280, 720*1280, (720/2)*(1280/2));
+			Module._free(inputPtr);
+			Module._free(retPtr);
+		}
+		
+		function decodeAAC(data)
+		{
+			var retPtr = Module._malloc(4 * 5 * 1024);//接收的数据
+			var inputPtr = Module._malloc(4 * data.length);//输入数据
+			
+			for( i =0;i < data.length;i++)
+			{
+				Module.HEAPU8[(inputPtr)+i] = data[i];//转换为堆数据
+			}
+			
+			var pcmLen = Module._feedData(retPtr, inputPtr, data.length);
+			
+			if(pcmLen > 0)
+			{
+				//console.log("%d帧 aac 解码成功, %d", decodeCount, pcmLen);
+				var pcmData = new Uint8Array(pcmLen);		
+				for(i = 0;i < pcmLen;i++)
+				{
+					pcmData[i] = Module.HEAPU8[(retPtr)+i]
+				}
+				
+				player.feed(pcmData);
+			}
+			else
+			{
+				console.log("%d帧 aac 解码失败, %d", decodeCount, pcmLen);
+			}
+			
+			decodeCount++;
+			Module._free(inputPtr);
+			Module._free(retPtr);
+		}
+		
+		function closeDecoder()
+		{
+		
+		}
+	
+		var ws = new WebSocket(socketURL);
+		ws.binaryType = 'arraybuffer';
+		
+		ws.addEventListener('open', function (event) 
+		{
+			console.log("发送配置帧");
+			ws.send(ConfigChannel("RK3923C1201900139"));
+		});
+		
+		
+		ws.addEventListener('message',function(event) 
+		{	
+			var input = new Uint8Array(event.data);
+			PrintArry(input);
+			
+			if(input[0] == 0xff)
+			{
+				//console.log("音频数据");
+				if(isFinish)
+				{
+					var time = new Date().getTime();
+					//decodeAAC(input);
+					//console.log("音频解码耗时:%d ms", new Date().getTime() - time);
+				}
+				
+			}
+			else
+			{
+				if(isFinish)
+				{
+					decodeH264(input);
+				}
+				
+				//console.log("视频数据");
+			}
+			
+		}
+		);
+	
+		console.log("-----Hello Moile----");
+	</script>
+	<script type="text/javascript" src="ffmpeghelper.js"></script>
+</html>

+ 126 - 0
wasm/pcm-player.js

@@ -0,0 +1,126 @@
+function PCMPlayer(option) {
+    this.init(option);
+}
+
+PCMPlayer.prototype.init = function(option) {
+    var defaults = {
+        encoding: '16bitInt',
+        channels: 1,
+        sampleRate: 8000,
+        flushingTime: 1000
+    };
+    this.option = Object.assign({}, defaults, option);
+    this.samples = new Float32Array();
+    this.flush = this.flush.bind(this);
+    this.interval = setInterval(this.flush, this.option.flushingTime);
+    this.maxValue = this.getMaxValue();
+    this.typedArray = this.getTypedArray();
+    this.createContext();
+};
+
+PCMPlayer.prototype.getMaxValue = function () {
+    var encodings = {
+        '8bitInt': 128,
+        '16bitInt': 32768,
+        '32bitInt': 2147483648,
+        '32bitFloat': 1
+    }
+
+    return encodings[this.option.encoding] ? encodings[this.option.encoding] : encodings['16bitInt'];
+};
+
+PCMPlayer.prototype.getTypedArray = function () {
+    var typedArrays = {
+        '8bitInt': Int8Array,
+        '16bitInt': Int16Array,
+        '32bitInt': Int32Array,
+        '32bitFloat': Float32Array
+    }
+
+    return typedArrays[this.option.encoding] ? typedArrays[this.option.encoding] : typedArrays['16bitInt'];
+};
+
+PCMPlayer.prototype.createContext = function() {
+    this.audioCtx = new (window.AudioContext || window.webkitAudioContext)();
+    this.gainNode = this.audioCtx.createGain();
+    this.gainNode.gain.value = 1;
+    this.gainNode.connect(this.audioCtx.destination);
+    this.startTime = this.audioCtx.currentTime;
+};
+
+PCMPlayer.prototype.isTypedArray = function(data) {
+    return (data.byteLength && data.buffer && data.buffer.constructor == ArrayBuffer);
+};
+
+PCMPlayer.prototype.feed = function(data) {
+    if (!this.isTypedArray(data)) return;
+    data = this.getFormatedValue(data);
+    var tmp = new Float32Array(this.samples.length + data.length);
+    tmp.set(this.samples, 0);
+    tmp.set(data, this.samples.length);
+    this.samples = tmp;
+};
+
+PCMPlayer.prototype.getFormatedValue = function(data) {
+    var data = new this.typedArray(data.buffer),
+        float32 = new Float32Array(data.length),
+        i;
+
+    for (i = 0; i < data.length; i++) {
+        float32[i] = data[i] / this.maxValue;
+    }
+    return float32;
+};
+
+PCMPlayer.prototype.volume = function(volume) {
+    this.gainNode.gain.value = volume;
+};
+
+PCMPlayer.prototype.destroy = function() {
+    if (this.interval) {
+        clearInterval(this.interval);
+    }
+    this.samples = null;
+    this.audioCtx.close();
+    this.audioCtx = null;
+};
+
+PCMPlayer.prototype.flush = function() {
+    if (!this.samples.length) return;
+    var bufferSource = this.audioCtx.createBufferSource(),
+        length = this.samples.length / this.option.channels,
+        audioBuffer = this.audioCtx.createBuffer(this.option.channels, length, this.option.sampleRate),
+        audioData,
+        channel,
+        offset,
+        i,
+        decrement;
+
+    for (channel = 0; channel < this.option.channels; channel++) {
+        audioData = audioBuffer.getChannelData(channel);
+        offset = channel;
+        decrement = 50;
+        for (i = 0; i < length; i++) {
+            audioData[i] = this.samples[offset];
+            /* fadein */
+            if (i < 50) {
+                audioData[i] =  (audioData[i] * i) / 50;
+            }
+            /* fadeout*/
+            if (i >= (length - 51)) {
+                audioData[i] =  (audioData[i] * decrement--) / 50;
+            }
+            offset += this.option.channels;
+        }
+    }
+    
+    if (this.startTime < this.audioCtx.currentTime) {
+        this.startTime = this.audioCtx.currentTime;
+    }
+    //console.log('start vs current '+this.startTime+' vs '+this.audioCtx.currentTime+' duration: '+audioBuffer.duration);
+    bufferSource.buffer = audioBuffer;
+    bufferSource.connect(this.gainNode);
+    bufferSource.start(this.startTime);
+    this.startTime += audioBuffer.duration;
+    this.samples = new Float32Array();
+};

+ 148 - 0
wasm/webgl.js

@@ -0,0 +1,148 @@
+function Texture(gl) {
+    this.gl = gl;
+    this.texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, this.texture);
+
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
+
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+}
+
+Texture.prototype.bind = function (n, program, name) {
+    var gl = this.gl;
+    gl.activeTexture([gl.TEXTURE0, gl.TEXTURE1, gl.TEXTURE2][n]);
+    gl.bindTexture(gl.TEXTURE_2D, this.texture);
+    gl.uniform1i(gl.getUniformLocation(program, name), n);
+};
+
+Texture.prototype.fill = function (width, height, data) {
+    var gl = this.gl;
+    gl.bindTexture(gl.TEXTURE_2D, this.texture);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.LUMINANCE, width, height, 0, gl.LUMINANCE, gl.UNSIGNED_BYTE, data);
+};
+
+function WebGLPlayer(canvas, options) {
+    this.canvas = canvas;
+    this.gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
+    this.initGL(options);
+}
+
+WebGLPlayer.prototype.initGL = function (options) {
+    if (!this.gl) {
+        console.log("[ER] WebGL not supported.");
+        return;
+    }
+
+    var gl = this.gl;
+    gl.pixelStorei(gl.UNPACK_ALIGNMENT, 1);
+    var program = gl.createProgram();
+    var vertexShaderSource = [
+        "attribute highp vec4 aVertexPosition;",
+        "attribute vec2 aTextureCoord;",
+        "varying highp vec2 vTextureCoord;",
+        "void main(void) {",
+        " gl_Position = aVertexPosition;",
+        " vTextureCoord = aTextureCoord;",
+        "}"
+    ].join("\n");
+    var vertexShader = gl.createShader(gl.VERTEX_SHADER);
+    gl.shaderSource(vertexShader, vertexShaderSource);
+    gl.compileShader(vertexShader);
+    var fragmentShaderSource = [
+        "precision highp float;",
+        "varying lowp vec2 vTextureCoord;",
+        "uniform sampler2D YTexture;",
+        "uniform sampler2D UTexture;",
+        "uniform sampler2D VTexture;",
+        "const mat4 YUV2RGB = mat4",
+        "(",
+        " 1.1643828125, 0, 1.59602734375, -.87078515625,",
+        " 1.1643828125, -.39176171875, -.81296875, .52959375,",
+        " 1.1643828125, 2.017234375, 0, -1.081390625,",
+        " 0, 0, 0, 1",
+        ");",
+        "void main(void) {",
+        " gl_FragColor = vec4( texture2D(YTexture, vTextureCoord).x, texture2D(UTexture, vTextureCoord).x, texture2D(VTexture, vTextureCoord).x, 1) * YUV2RGB;",
+        "}"
+    ].join("\n");
+
+    var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+    gl.shaderSource(fragmentShader, fragmentShaderSource);
+    gl.compileShader(fragmentShader);
+    gl.attachShader(program, vertexShader);
+    gl.attachShader(program, fragmentShader);
+    gl.linkProgram(program);
+    gl.useProgram(program);
+    if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
+        console.log("[ER] Shader link failed.");
+    }
+    var vertexPositionAttribute = gl.getAttribLocation(program, "aVertexPosition");
+    gl.enableVertexAttribArray(vertexPositionAttribute);
+    var textureCoordAttribute = gl.getAttribLocation(program, "aTextureCoord");
+    gl.enableVertexAttribArray(textureCoordAttribute);
+
+    var verticesBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, verticesBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1.0, 1.0, 0.0, -1.0, 1.0, 0.0, 1.0, -1.0, 0.0, -1.0, -1.0, 0.0]), gl.STATIC_DRAW);
+    gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0);
+    var texCoordBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([1.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0]), gl.STATIC_DRAW);
+    gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0);
+
+    gl.y = new Texture(gl);
+    gl.u = new Texture(gl);
+    gl.v = new Texture(gl);
+    gl.y.bind(0, program, "YTexture");
+    gl.u.bind(1, program, "UTexture");
+    gl.v.bind(2, program, "VTexture");
+}
+
+WebGLPlayer.prototype.renderFrame = function (videoFrame, width, height, uOffset, vOffset) {
+    if (!this.gl) {
+        console.log("[ER] Render frame failed due to WebGL not supported.");
+        return;
+    }
+
+    var gl = this.gl;
+    gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
+    gl.clearColor(0.0, 0.0, 0.0, 0.0);
+    gl.clear(gl.COLOR_BUFFER_BIT);
+
+    gl.y.fill(width, height, videoFrame.subarray(0, uOffset));
+    gl.u.fill(width >> 1, height >> 1, videoFrame.subarray(uOffset, uOffset + vOffset));
+    gl.v.fill(width >> 1, height >> 1, videoFrame.subarray(uOffset + vOffset, videoFrame.length));
+
+    gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+};
+
+WebGLPlayer.prototype.fullscreen = function () {
+	  var canvas = this.canvas;
+    if (canvas.RequestFullScreen) {
+        canvas.RequestFullScreen();
+    } else if (canvas.webkitRequestFullScreen) {
+        canvas.webkitRequestFullScreen();
+    } else if (canvas.mozRequestFullScreen) {
+        canvas.mozRequestFullScreen();
+    } else if (canvas.msRequestFullscreen) {
+        canvas.msRequestFullscreen();
+    } else {
+        alert("This browser doesn't supporter fullscreen");
+    }
+};
+
+WebGLPlayer.prototype.exitfullscreen = function (){
+    if (document.exitFullscreen) {
+        document.exitFullscreen();
+    } else if (document.webkitExitFullscreen) {
+        document.webkitExitFullscreen();
+    } else if (document.mozCancelFullScreen) {
+        document.mozCancelFullScreen();
+    } else if (document.msExitFullscreen) {
+        document.msExitFullscreen();
+    } else {
+        alert("Exit fullscreen doesn't work");
+    }
+}