raw-parser.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*********************************************************
  2. * LICENSE: LICENSE-Free_CN.MD
  3. *
  4. * Author: Numberwolf - ChangYanlong
  5. * QQ: 531365872
  6. * QQ Group:925466059
  7. * Wechat: numberwolf11
  8. * Discord: numberwolf#8694
  9. * E-Mail: porschegt23@foxmail.com
  10. * Github: https://github.com/numberwolf/h265web.js
  11. *
  12. * 作者: 小老虎(Numberwolf)(常炎隆)
  13. * QQ: 531365872
  14. * QQ群: 531365872
  15. * 微信: numberwolf11
  16. * Discord: numberwolf#8694
  17. * 邮箱: porschegt23@foxmail.com
  18. * 博客: https://www.jianshu.com/u/9c09c1e00fd1
  19. * Github: https://github.com/numberwolf/h265web.js
  20. *
  21. **********************************************************/
  22. /**
  23. * codecImp Obj
  24. * Video Raw 265 264 Parser
  25. */
  26. const AfterGetNalThenMvLen = 3;
  27. export default class RawParserModule {
  28. constructor() {
  29. this.frameList = [];
  30. this.stream = null;
  31. }
  32. /*
  33. *****************************************************
  34. * *
  35. * *
  36. * HEVC Frames *
  37. * *
  38. * *
  39. *****************************************************
  40. */
  41. pushFrameRet(streamPushInput) {
  42. if (!streamPushInput || streamPushInput == undefined || streamPushInput == null) {
  43. return false;
  44. }
  45. if (!this.frameList || this.frameList == undefined || this.frameList == null) {
  46. this.frameList = [];
  47. this.frameList.push(streamPushInput);
  48. } else {
  49. this.frameList.push(streamPushInput);
  50. }
  51. return true;
  52. }
  53. nextFrame() {
  54. if (!this.frameList && this.frameList == undefined || this.frameList == null && this.frameList.length < 1) {
  55. return null;
  56. }
  57. return this.frameList.shift();
  58. }
  59. clearFrameRet() {
  60. this.frameList = null;
  61. }
  62. /*
  63. *****************************************************
  64. * *
  65. * *
  66. * HEVC stream *
  67. * *
  68. * *
  69. *****************************************************
  70. */
  71. setStreamRet(streamBufInput) {
  72. this.stream = streamBufInput;
  73. }
  74. getStreamRet() {
  75. return this.stream;
  76. }
  77. /**
  78. * push stream nalu, for live, not vod
  79. * @param Uint8Array
  80. * @return bool
  81. */
  82. appendStreamRet(input) {
  83. if (!input || input === undefined || input == null) {
  84. return false;
  85. }
  86. if (!this.stream || this.stream === undefined || this.stream == null) {
  87. this.stream = input;
  88. return true;
  89. }
  90. let lenOld = this.stream.length;
  91. let lenPush = input.length;
  92. let mergeStream = new Uint8Array(lenOld + lenPush);
  93. mergeStream.set(this.stream, 0);
  94. mergeStream.set(input, lenOld);
  95. this.stream = mergeStream;
  96. // let retList = this.nextNaluList(9000);
  97. // if (retList !== false && retList.length > 0) {
  98. // this.frameList.push(...retList);
  99. // }
  100. for (let i = 0; i < 9999; i++) {
  101. let nalBuf = this.nextNalu();
  102. if (nalBuf !== false && nalBuf !== null && nalBuf !== undefined) {
  103. this.frameList.push(nalBuf);
  104. } else {
  105. break;
  106. }
  107. }
  108. return true;
  109. }
  110. /**
  111. * sub nalu stream, and get Nalu unit
  112. */
  113. subBuf(startOpen, endOpen) { // sub block [m,n]
  114. // nal
  115. let returnBuf = new Uint8Array(
  116. this.stream.subarray(startOpen, endOpen + 1)
  117. );
  118. // streamBuf sub
  119. this.stream = new Uint8Array(
  120. this.stream.subarray(endOpen + 1)
  121. );
  122. return returnBuf;
  123. }
  124. /**
  125. * @param onceGetNalCount: once use get nal count, defult 1
  126. * @return uint8array OR false
  127. */
  128. nextNalu(onceGetNalCount=1) {
  129. // check params
  130. if (this.stream == null || this.stream.length <= 4) {
  131. return false;
  132. }
  133. // start nal pos
  134. let startTag = -1;
  135. // return nalBuf
  136. let returnNalBuf = null;
  137. for (let i = 0;i < this.stream.length; i++) {
  138. if (i + 5 >= this.stream.length) {
  139. return false;
  140. // if (startTag == -1) {
  141. // return false;
  142. // } else {
  143. // // 如果结尾不到判断的字节位置 就直接全量输出最后一个nal
  144. // returnNalBuf = this.subBuf(startTag, this.stream.length-1);
  145. // return returnNalBuf;
  146. // }
  147. }
  148. // find nal
  149. if (
  150. ( // 0x00 00 01
  151. this.stream[i] == 0
  152. && this.stream[i+1] == 0
  153. && this.stream[i+2] == 1
  154. ) ||
  155. ( // 0x00 00 00 01
  156. this.stream[i] == 0
  157. && this.stream[i+1] == 0
  158. && this.stream[i+2] == 0
  159. && this.stream[i+3] == 1
  160. )
  161. ) {
  162. // console.log(
  163. // "enter find nal , now startTag:" + startTag
  164. // + ", now pos:" + i
  165. // );
  166. let nowPos = i;
  167. i += AfterGetNalThenMvLen; // 移出去
  168. // begin pos
  169. if (startTag == -1) {
  170. startTag = nowPos;
  171. } else {
  172. if (onceGetNalCount <= 1) {
  173. // startCode - End
  174. // [startTag,nowPos)
  175. // console.log("[===>] last code hex is :" + this.stream[nowPos-1].toString(16))
  176. returnNalBuf = this.subBuf(startTag,nowPos-1);
  177. return returnNalBuf;
  178. } else {
  179. onceGetNalCount -= 1;
  180. }
  181. }
  182. }
  183. } // end for
  184. return false;
  185. }
  186. nextNalu2(onceGetNalCount=1) {
  187. // check params
  188. if (this.stream == null || this.stream.length <= 4) {
  189. return false;
  190. }
  191. // start nal pos
  192. let startTag = -1;
  193. // return nalBuf
  194. let returnNalBuf = null;
  195. for (let i = 0;i < this.stream.length; i++) {
  196. if (i + 5 >= this.stream.length) {
  197. if (startTag == -1) {
  198. return false;
  199. } else {
  200. // 如果结尾不到判断的字节位置 就直接全量输出最后一个nal
  201. returnNalBuf = this.subBuf(startTag,this.stream.length-1);
  202. return returnNalBuf;
  203. }
  204. }
  205. // find nal
  206. let is3BitHeader = this.stream.slice(i, i+3).join(' ') == '0 0 1';
  207. let is4BitHeader = this.stream.slice(i, i+4).join(' ') == '0 0 0 1';
  208. if (
  209. is3BitHeader ||
  210. is4BitHeader
  211. ) {
  212. let nowPos = i;
  213. i += AfterGetNalThenMvLen; // 移出去
  214. // begin pos
  215. if (startTag == -1) {
  216. startTag = nowPos;
  217. } else {
  218. if (onceGetNalCount <= 1) {
  219. // startCode - End
  220. // [startTag,nowPos)
  221. // console.log("[===>] last code hex is :" + this.stream[nowPos-1].toString(16))
  222. returnNalBuf = this.subBuf(startTag, nowPos-1);
  223. return returnNalBuf;
  224. } else {
  225. onceGetNalCount -= 1;
  226. }
  227. }
  228. }
  229. } // end for
  230. return false;
  231. }
  232. /**
  233. * @brief sub nalu stream, and get Nalu unit
  234. * to parse:
  235. * typedef struct {
  236. * uint32_t width;
  237. * uint32_t height;
  238. * uint8_t *dataY;
  239. * uint8_t *dataChromaB;
  240. * uint8_t *dataChromaR;
  241. * } ImageData;
  242. * @params struct_ptr: Module.cwrap('getFrame', 'number', [])
  243. * @return Dict
  244. */
  245. parseYUVFrameStruct(struct_ptr = null) { // sub block [m,n]
  246. if (struct_ptr == null || !struct_ptr || struct_ptr == undefined) {
  247. return null;
  248. }
  249. let width = Module.HEAPU32[struct_ptr / 4];
  250. let height = Module.HEAPU32[struct_ptr / 4 + 1];
  251. // let imgBufferPtr = Module.HEAPU32[ptr / 4 + 2];
  252. // let imageBuffer = Module.HEAPU8.subarray(imgBufferPtr, imgBufferPtr + width * height * 3);
  253. // console.log("width:",width," height:",height);
  254. let sizeWH = width * height;
  255. // let imgBufferYPtr = Module.HEAPU32[ptr / 4 + 2];
  256. // let imageBufferY = Module.HEAPU8.subarray(imgBufferYPtr, imgBufferYPtr + sizeWH);
  257. // let imgBufferBPtr = Module.HEAPU32[ptr/4+ 2 + sizeWH/4 + 1];
  258. // let imageBufferB = Module.HEAPU8.subarray(
  259. // imgBufferBPtr,
  260. // imgBufferBPtr + sizeWH/4
  261. // );
  262. // console.log(imageBufferB);
  263. // let imgBufferRPtr = Module.HEAPU32[imgBufferBPtr + sizeWH/16 + 1];
  264. // let imageBufferR = Module.HEAPU8.subarray(
  265. // imgBufferRPtr,
  266. // imgBufferRPtr + sizeWH/4
  267. // );
  268. let imgBufferPtr = Module.HEAPU32[struct_ptr / 4 + 1 + 1];
  269. let imageBufferY = Module.HEAPU8.subarray(imgBufferPtr, imgBufferPtr + sizeWH);
  270. let imageBufferB = Module.HEAPU8.subarray(
  271. imgBufferPtr + sizeWH + 8,
  272. imgBufferPtr + sizeWH + 8 + sizeWH/4
  273. );
  274. let imageBufferR = Module.HEAPU8.subarray(
  275. imgBufferPtr + sizeWH + 8 + sizeWH/4 + 8,
  276. imgBufferPtr + sizeWH + 8 + sizeWH/2 + 8
  277. );
  278. return {
  279. width : width,
  280. height : height,
  281. sizeWH : sizeWH,
  282. imageBufferY : imageBufferY,
  283. imageBufferB : imageBufferB,
  284. imageBufferR : imageBufferR
  285. };
  286. }
  287. }