decoder.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. var isFinish = false;
  2. var isSwitchSharpness = false;
  3. var h264Queue = [];
  4. var ret;
  5. var maxWidth = 1080;
  6. var maxHeight = 1920;
  7. var globalYuvPtr = undefined;
  8. var golbalYuvData; //全局,只分配一次
  9. var renderCount = 0;
  10. var curFrameWidth = undefined;
  11. var curFrameHeight = undefined;
  12. function doSomeInit() {
  13. var allocSize = maxWidth * maxHeight * 3;
  14. golbalYuvData = new Uint8Array(allocSize);
  15. }
  16. self.importScripts('ffmpeghelper.js');
  17. self.importScripts('spsParser.js');
  18. self.Module.onRuntimeInitialized = function () {
  19. isFinish = true;
  20. doSomeInit();
  21. ret = Module._openDecoder();
  22. if (!ret) {
  23. console.log('打开编码器成功');
  24. }
  25. };
  26. self.addEventListener(
  27. 'message',
  28. function (e) {
  29. var msg = e.data;
  30. if (msg.type == 'rawData') {
  31. var buffer = e.data.data;
  32. if (buffer[0] !== 0xff) {
  33. // 音频解码
  34. var type = buffer[4] & 0x1f;
  35. if (type == 7) {
  36. let info = spsParser(buffer);
  37. if (curFrameWidth != undefined && curFrameHeight != undefined) {
  38. if (info.width != curFrameWidth || info.height != curFrameHeight) {
  39. // 分辨率发生改变,切换
  40. console.log('🚀 ~ file: decoder.js ~ line 44 ~ 分辨率发生改变');
  41. switchNewStream();
  42. }
  43. }
  44. curFrameWidth = info.width;
  45. curFrameHeight = info.height;
  46. h264Queue.push(buffer);
  47. } else {
  48. h264Queue.push(buffer);
  49. }
  50. }
  51. }
  52. },
  53. false,
  54. );
  55. function PrintfLog(str) {
  56. var curTime = new Date().getTime();
  57. var objData = {
  58. cmd: 0,
  59. data: str,
  60. time: curTime,
  61. };
  62. self.postMessage(objData);
  63. }
  64. function doRequestIFrame() {
  65. var objData = {
  66. cmd: 5,
  67. };
  68. self.postMessage(objData);
  69. }
  70. function decodeVideo() {
  71. if (h264Queue.length > 0 && isFinish) {
  72. decodeH264(h264Queue.shift());
  73. }
  74. }
  75. var timeFlag = setInterval(decodeVideo, 1);
  76. //实现C 端到js yuv数据赋值, 并分配给opengl 渲染
  77. /*yuvData, 存放yuv数据的数组
  78. * inputYuvPtr C++
  79. */
  80. function dispatchYuvData(
  81. yuvData,
  82. inputYuvPtr,
  83. videoWidth,
  84. videoHeight,
  85. copyLen,
  86. ) {
  87. for (i = 0; i < copyLen; i++) {
  88. yuvData[i] = Module.HEAPU8[inputYuvPtr + i];
  89. }
  90. var curTime = new Date().getTime();
  91. var objData = {
  92. cmd: 1,
  93. data: yuvData,
  94. time: curTime,
  95. width: videoWidth,
  96. height: videoHeight,
  97. };
  98. self.postMessage(objData);
  99. }
  100. function decodeH264(data) {
  101. var frameWidth = 0;
  102. var frameHeight = 0;
  103. var inputPtr = Module._malloc(data.length); //输入数据
  104. for (var i = 0; i < data.length; i++) {
  105. Module.HEAPU8[inputPtr + i] = data[i]; //转换为堆数据
  106. }
  107. var allocSize = (maxWidth * maxHeight * 3) / 2;
  108. if (globalYuvPtr == undefined) {
  109. globalYuvPtr = Module._malloc(allocSize);
  110. }
  111. var ret = Module._feedData(inputPtr, data.length, globalYuvPtr);
  112. if (ret >= 0) {
  113. //解码成功才考虑渲染
  114. frameWidth = Module._getVideoWidth(); //拿到解码器宽、高
  115. frameHeight = Module._getVideoHeight();
  116. // console.log("🚀 ~ file: decoder.js ~ line 134 ~ decodeH264 ~ frameWidth", frameWidth,frameHeight)
  117. var copyLen = (frameWidth * frameHeight * 3) / 2; //只拷贝必须的长度
  118. if (renderCount > 1) {
  119. //第一帧因为画面时全绿色的不渲染
  120. dispatchYuvData(
  121. golbalYuvData,
  122. globalYuvPtr,
  123. frameWidth,
  124. frameHeight,
  125. copyLen,
  126. );
  127. } else {
  128. renderCount++;
  129. }
  130. }
  131. Module._free(inputPtr);
  132. }
  133. function switchNewStream() {
  134. closeDecoder();
  135. var ret = Module._openDecoder(); //再次开启解码器
  136. var timeFlag = setInterval(decodeVideo, 1);
  137. console.log('切换解码器成功');
  138. }
  139. function closeDecoder() {
  140. clearInterval(timeFlag); //关闭原有定时器
  141. Module._closeDecoder();
  142. renderCount = 0;
  143. if (globalYuvPtr != undefined) {
  144. Module._free(globalYuvPtr);
  145. globalYuvPtr = undefined;
  146. }
  147. console.log('此时buffer长度: %d', h264Queue.length);
  148. while (h264Queue.lengh > 0) {
  149. h264Queue.shift();
  150. }
  151. }