|
@@ -1,16 +1,27 @@
|
|
|
var isFinish = false;
|
|
|
-var decodeCount = 0;
|
|
|
+var isSwitchSharpness = false;
|
|
|
var h264Queue = [];
|
|
|
-var isFirst = true;
|
|
|
-var ret = ''
|
|
|
-var parameters = GetRequest();
|
|
|
-var videoWidth = parameters['width'];
|
|
|
-var videoHeight = parameters['height'];
|
|
|
+var ret;
|
|
|
+
|
|
|
+var maxWidth = 1080;
|
|
|
+var maxHeight = 1920;
|
|
|
+var globalYuvPtr = undefined;
|
|
|
+var golbalYuvData;//全局,只分配一次
|
|
|
+var renderCount = 0;
|
|
|
+
|
|
|
+function doSomeInit() {
|
|
|
+ var allocSize = maxWidth * maxHeight * 3;
|
|
|
+ golbalYuvData = new Uint8Array(allocSize);
|
|
|
+}
|
|
|
+
|
|
|
self.Module = {
|
|
|
onRuntimeInitialized: function () {
|
|
|
- ret = Module._openDecoder(videoWidth, videoHeight);
|
|
|
+ isFinish = true;
|
|
|
+ doSomeInit();
|
|
|
+ ret = Module._openDecoder();
|
|
|
+
|
|
|
if (!ret) {
|
|
|
- isFinish = true;
|
|
|
+ console.log("打开编码器成功");
|
|
|
}
|
|
|
}
|
|
|
};
|
|
@@ -18,7 +29,32 @@ self.Module = {
|
|
|
self.importScripts("ffmpeghelper.js");
|
|
|
|
|
|
self.addEventListener('message', function (e) {
|
|
|
- h264Queue.push(e.data);
|
|
|
+ var msg = e.data;
|
|
|
+ if (msg.type == "rawData") {
|
|
|
+ var buffer = e.data.data;
|
|
|
+
|
|
|
+ if (buffer[0] !== 0xff) { // 音频解码
|
|
|
+ if (isSwitchSharpness) {
|
|
|
+ var type = buffer[4] & 0x1f;
|
|
|
+ if (type == 7 || type == 8) {
|
|
|
+ console.log("视频类型:" + type);
|
|
|
+ isSwitchSharpness = false;
|
|
|
+ h264Queue.push(buffer);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ h264Queue.push(buffer);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (msg.type == "switchSharpness") { // 分辨率切换实现
|
|
|
+ isSwitchSharpness = true;
|
|
|
+ closeDecoder();
|
|
|
+ var ret = Module._openDecoder();//再次开启解码器
|
|
|
+ var timeFlag = setInterval(decodeVideo, 1);
|
|
|
+ console.log("切换解码器成功");
|
|
|
+ }
|
|
|
}, false);
|
|
|
|
|
|
function PrintfLog(str) {
|
|
@@ -31,76 +67,90 @@ function PrintfLog(str) {
|
|
|
self.postMessage(objData);
|
|
|
}
|
|
|
|
|
|
-setInterval(
|
|
|
- function () {
|
|
|
- if (h264Queue.length > 0 && isFinish) {
|
|
|
- if (isFirst) {
|
|
|
- PrintfLog("当前队列大小 :" + h264Queue.length);
|
|
|
- isFirst = false;
|
|
|
- }
|
|
|
+function doRequestIFrame() {
|
|
|
+ var objData = {
|
|
|
+ cmd: 5,
|
|
|
+ };
|
|
|
+ self.postMessage(objData);
|
|
|
+}
|
|
|
|
|
|
- if (h264Queue.length > 10 && isFinish) {
|
|
|
- PrintfLog("解不过来 " + h264Queue.length);
|
|
|
- return;
|
|
|
- }
|
|
|
|
|
|
- decodeH264(h264Queue.shift());
|
|
|
- }
|
|
|
- }, 1);
|
|
|
+function decodeVideo() {
|
|
|
+ if (h264Queue.length > 0 && isFinish) {
|
|
|
+ decodeH264(h264Queue.shift());
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
|
|
|
+var timeFlag = setInterval(decodeVideo, 1);
|
|
|
+
|
|
|
+//实现C 端到js yuv数据赋值, 并分配给opengl 渲染
|
|
|
+/*yuvData, 存放yuv数据的数组
|
|
|
+* inputYuvPtr C++
|
|
|
+*/
|
|
|
+function dispatchYuvData(yuvData, inputYuvPtr, videoWidth, videoHeight, copyLen) {
|
|
|
+ for (i = 0; i < copyLen; i++) {
|
|
|
+ yuvData[i] = Module.HEAPU8[(inputYuvPtr) + i];
|
|
|
+ }
|
|
|
+
|
|
|
+ var curTime = new Date().getTime();
|
|
|
+ var objData = {
|
|
|
+ cmd: 1,
|
|
|
+ data: yuvData,
|
|
|
+ time: curTime,
|
|
|
+ width: videoWidth,
|
|
|
+ height: videoHeight
|
|
|
+ };
|
|
|
+ self.postMessage(objData);
|
|
|
+}
|
|
|
|
|
|
function decodeH264(data) {
|
|
|
- var size = videoWidth * videoHeight *3;
|
|
|
- var retPtr = Module._malloc(size); //接收的数据
|
|
|
+ var frameWidth = 0;
|
|
|
+ var frameHeight = 0;
|
|
|
var inputPtr = Module._malloc(data.length); //输入数据
|
|
|
|
|
|
- for (var i = 0; i < data.length; i++) {
|
|
|
+ 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) {
|
|
|
- if (decodeCount > 50) {
|
|
|
- var curCost = new Date().getTime() - time;
|
|
|
- PrintfLog("解码耗时 " + curCost + " ms");
|
|
|
- decodeCount = 0;
|
|
|
- }
|
|
|
- decodeCount++;
|
|
|
+ var allocSize = maxWidth * maxHeight * 3 / 2;
|
|
|
+ if (globalYuvPtr == undefined) {
|
|
|
+ globalYuvPtr = Module._malloc(allocSize);
|
|
|
}
|
|
|
|
|
|
- var yuvData = new Uint8Array(size);
|
|
|
- for (var i = 0; i < yuvData.length; i++) {
|
|
|
- yuvData[i] = Module.HEAPU8[(retPtr) + i];
|
|
|
+ var ret = Module._feedData(inputPtr, data.length, globalYuvPtr);
|
|
|
+
|
|
|
+ if (ret >= 0)//解码成功才考虑渲染
|
|
|
+ {
|
|
|
+ frameWidth = Module._getVideoWidth();//拿到解码器宽、高
|
|
|
+ frameHeight = Module._getVideoHeight();
|
|
|
+ var curCost = new Date().getTime() - time;
|
|
|
+ var copyLen = frameWidth * frameHeight * 3 / 2;//只拷贝必须的长度
|
|
|
+
|
|
|
+ if (renderCount > 1)//第一帧因为画面时全绿色的不渲染
|
|
|
+ {
|
|
|
+ dispatchYuvData(golbalYuvData, globalYuvPtr, frameWidth, frameHeight, copyLen);
|
|
|
+ } else {
|
|
|
+ renderCount++;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- var curTime = new Date().getTime();
|
|
|
- var objData = {
|
|
|
- cmd: 1,
|
|
|
- data: yuvData,
|
|
|
- time: curTime
|
|
|
- };
|
|
|
- self.postMessage(objData);
|
|
|
Module._free(inputPtr);
|
|
|
- Module._free(retPtr);
|
|
|
}
|
|
|
|
|
|
|
|
|
function closeDecoder() {
|
|
|
- Module._destroyDecoder();
|
|
|
-}
|
|
|
+ clearInterval(timeFlag);//关闭原有定时器
|
|
|
+ Module._closeDecoder();
|
|
|
+ renderCount = 0;
|
|
|
|
|
|
-// 获取url中"?"符后的字串
|
|
|
-function GetRequest() {
|
|
|
- var url = location.search;
|
|
|
- var obj = new Object();
|
|
|
- if (url.indexOf("?") != -1) {
|
|
|
- var str = url.substring(1);
|
|
|
- strs = str.split("&");
|
|
|
- for (var i = 0; i < strs.length; i++) {
|
|
|
- obj[strs[i].split("=")[0]] = (strs[i].split("=")[1]);
|
|
|
- }
|
|
|
+ if (globalYuvPtr != undefined) {
|
|
|
+ Module._free(globalYuvPtr);
|
|
|
+ globalYuvPtr = undefined;
|
|
|
}
|
|
|
- return obj;
|
|
|
-}
|
|
|
+ console.log("此时buffer长度: %d", h264Queue.length);
|
|
|
+ while (h264Queue.lengh > 0) {
|
|
|
+ h264Queue.shift();
|
|
|
+ }
|
|
|
+}
|