decoder.js 43 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373
  1. var decoder = `/* eslint-disable no-inner-declarations */
  2. /* eslint-disable default-case */
  3. /* eslint-disable no-restricted-globals */
  4. // import { arrayBuffer } from "stream/consumers"
  5. // import { addSyntheticLeadingComment, textChangeRangeIsUnchanged } from "typescript"
  6. /* eslint-disable no-undef */
  7. const CACHE_BUF_LENGTH = 16
  8. const YUV_BUF_LENGTH = 16
  9. if ('function' === typeof importScripts) {
  10. const startTime = Date.now()
  11. // self.importScripts('https://static.xverse.cn/wasm/zx_test_exclusive/v2/libxv265dec.js')
  12. // printConsole.log('Decoder update time is 2021/10/14 12:13 ')
  13. const YUVArray = []
  14. const mediaArray = []
  15. let IframesReceived = 0
  16. let IframesDecoded = 0
  17. let lastReceivePts = 0
  18. let lastProcessPts = 0
  19. let framesReturned = 0
  20. let send_out_buffer = 0
  21. let lastPoc = 0
  22. let cachedFirstFrame = undefined
  23. let cachedPanoramaFirstFrame = undefined
  24. const printConsole = {
  25. log: (msg) => self.postMessage({ t: MessageEvent.ConsoleLog, printMsg: msg }),
  26. error: (msg, code) => self.postMessage({ t: MessageEvent.ConsoleError, printMsg: msg, code: code }),
  27. }
  28. const MessageEvent = {
  29. DecodeMessage: 0,
  30. UpdateStats: 1,
  31. WASMReady: 2,
  32. CacheFrame: 3,
  33. RecordVideo: 4,
  34. OnlyEmitSignal: 5,
  35. WASMReadyCost: 6,
  36. PanoramaMessage: 7,
  37. RequestIFrame: 8,
  38. ConsoleLog: 9,
  39. ConsoleError: 10,
  40. }
  41. let lastReceiveContentPts = 0
  42. let saveMediaBytes = 0 // Just for test use
  43. const IFrameCacheBuffer = {}
  44. for (var i = 0; i < CACHE_BUF_LENGTH; ++i) {
  45. mediaArray.push({
  46. pts: -1,
  47. receive_ts: 0,
  48. decode_ts: 0,
  49. yuv_ts: 0,
  50. render_ts: 0,
  51. media: null,
  52. meta: null,
  53. isIDR: false,
  54. })
  55. }
  56. let downloadBlob = (data, fileName, mimeType) => {
  57. const blob = new Blob([data], {
  58. type: mimeType,
  59. })
  60. const url = URL.createObjectURL(blob)
  61. self.postMessage({ t: MessageEvent.RecordVideo, fileObj: blob, link: url })
  62. //downloadURL(url, fileName)
  63. setTimeout(function () {
  64. return URL.revokeObjectURL(url)
  65. }, 3000)
  66. }
  67. function Decoder() {
  68. this.expected_frameCnt = 1
  69. this.inited = false
  70. this.wasminited = false
  71. this.cacheMap = new Map()
  72. this.receivedMedia = 0
  73. this.receivedFrame = 0
  74. this.receivedYUV = 0
  75. this.receivedEmit = 0
  76. this.lastReceivedEmit = 0
  77. this.mediaBytesReceived = 0
  78. this.metaBytesReceived = 0
  79. this.prevSeq = 0
  80. this.packetsLost = 0
  81. this.packetsDrop = 0
  82. this.dtpf = 0
  83. this.dtmf = 0
  84. this.getFrameInterval = 10
  85. this.jumpI = false
  86. this.startEmit = false
  87. this.JankTimes = 0
  88. this.bigJankTimes = 0
  89. this.mediaCacheBuffer = new Uint8Array(1024 * 1024 * 10) // 10MB for video recording
  90. this.errorCacheBuffer = new Uint8Array(1024 * 1024 * 10) // 10MB for error stream recording
  91. this.mediaCacheSize = 0
  92. this.errorCacheSize = 0
  93. this.startRecord = false
  94. this.saveRecord = false
  95. this.requestingIFrame = false
  96. this.decoderId = 0 // 0 for 720p, 1 for 480p.
  97. this.DecodablePts = 0
  98. this.BlockedFrames = []
  99. this.decodeTimeCircular = Array(120).fill(-1)
  100. this.dtcPtr = 0
  101. this.readPtr = 1
  102. this.writePtr = 1
  103. this.cntBufInc = 0
  104. this.prevBufNum = 0
  105. this.MAX_TRY_TO_DEC_BUFNUM = 3
  106. this.skipFrameUntilI = true
  107. this.enable_logging = false
  108. this.framesReceivedBetweenTimerInterval = 0
  109. this.maxFramesReceivedBetweenTimerInterval = 0
  110. this.isFirstFrame = 1
  111. this.consumerPrevPts = -1
  112. this.consumerCurrPts = -1
  113. this.consumerWaitingIDR = false
  114. this.lastObj = null
  115. this.bufferIFrame = 0
  116. this.passiveJitterLength = 0
  117. }
  118. //refactor:
  119. Decoder.prototype.isBufEmpty = function () {
  120. return this.readPtr == this.writePtr
  121. }
  122. Decoder.prototype.isBufFull = function () {
  123. return (this.writePtr + 1) % CACHE_BUF_LENGTH == this.readPtr
  124. }
  125. Decoder.prototype.getNumOfPktToBeDec = function () {
  126. return (this.writePtr + CACHE_BUF_LENGTH - this.readPtr) % CACHE_BUF_LENGTH
  127. }
  128. Decoder.prototype.getNumOfEmptySlot = function () {
  129. return CACHE_BUF_LENGTH - this.getNumOfPktToBeDec() - 1
  130. }
  131. Decoder.prototype.aheadof = function (a, b) {
  132. return (a - b + 65536) % 65536 > 65536 / 2
  133. }
  134. Decoder.prototype.distance = function (a, b) {
  135. var res
  136. if (this.aheadof(a, b)) {
  137. res = this.seqDiff(b, a, 65536)
  138. } else {
  139. res = this.seqDiff(a, b, 65536)
  140. }
  141. return res
  142. }
  143. Decoder.prototype.isSeqJump = function (a, b) {
  144. return this.distance(a, b) >= CACHE_BUF_LENGTH - 1
  145. }
  146. Decoder.prototype.seqDiff = function (a, b, mod) {
  147. return (a + mod - b) % mod
  148. }
  149. //notice: n could be nagative
  150. Decoder.prototype.seqAdd = function (seq, n, mod) {
  151. return (seq + mod + n) % mod
  152. }
  153. //end refactor
  154. Decoder.prototype.resetDecoder = function () {
  155. this.isFirstFrame = 1
  156. this.expected_frameCnt = 1
  157. this.receivedMedia = 0
  158. this.receivedYUV = 0
  159. this.receivedEmit = 0
  160. this.lastReceivedEmit = 0
  161. this.mediaBytesReceived = 0
  162. this.metaBytesReceived = 0
  163. this.prevSeq = 0
  164. this.packetsLost = 0
  165. this.packetsDrop = 0
  166. this.dtpf = 0
  167. this.dtmf = 0
  168. this.JankTimes = 0
  169. this.bigJankTimes = 0
  170. this.getFrameInterval = 10
  171. this.jumpI = false
  172. IframesReceived = 0
  173. IframesDecoded = 0
  174. lastReceivePts = 0
  175. lastProcessPts = 0
  176. lastReceiveContentPts = 0
  177. this.requestingIFrame = false
  178. this.DecodablePts = 0
  179. this.BlockedFrames = []
  180. this.decodeTimeCircular.fill(-1)
  181. this.dtcPtr = 0
  182. for (var i = 0; i < CACHE_BUF_LENGTH; ++i) {
  183. mediaArray[i].media = null
  184. mediaArray[i].meta = null
  185. mediaArray[i] = {
  186. pts: -1,
  187. receive_ts: 0,
  188. decode_ts: 0,
  189. yuv_ts: 0,
  190. render_ts: 0,
  191. media: null,
  192. meta: null,
  193. isIDR: false,
  194. }
  195. }
  196. //refactor:
  197. this.readPtr = this.writePtr = 1
  198. this.cntBufInc = 0
  199. this.prevBufNum = 0
  200. this.MAX_TRY_TO_DEC_BUFNUM = 3
  201. this.skipFrameUntilI = true
  202. this.consumerPrevPts = -1
  203. this.consumerCurrPts = -1
  204. this.consumerWaitingIDR = false
  205. this.lastObj = null
  206. this.bufferIFrame = 0
  207. //end refactor
  208. }
  209. //refactor:
  210. Decoder.prototype.changeLogSwitch = function (status) {
  211. this.enable_logging = status
  212. }
  213. const MAX_LOG_NUM = 128
  214. logBufQueue = []
  215. Decoder.prototype.dumpLogBuf = function () {
  216. while (logBufQueue.length > 0) {
  217. console.log(logBufQueue.shift())
  218. }
  219. }
  220. Decoder.prototype.dumpJitterBufInfo = function (label, pts = -1) {
  221. // if (!this.enable_logging) {
  222. // return
  223. // }
  224. logInfo =
  225. 'WritePtr: ' +
  226. this.writePtr +
  227. ', ReadPtr: ' +
  228. this.readPtr +
  229. '\\n' +
  230. ', Producer Prev/Curr: ' +
  231. this.prevSeq +
  232. '/' +
  233. pts +
  234. '\\n' +
  235. ', Consumer Prev/Curr: ' +
  236. this.consumerPrevPts +
  237. '/' +
  238. this.consumerCurrPts +
  239. '\\n' +
  240. 'awaitingBuf: ' +
  241. this.getNumOfPktToBeDec() +
  242. ', emptySlotNum: ' +
  243. this.getNumOfEmptySlot() +
  244. ', skipFrameUntilI: ' +
  245. this.skipFrameUntilI +
  246. '\\n' +
  247. ' framesReceivedBetweenTimerInterval: ' +
  248. this.framesReceivedBetweenTimerInterval +
  249. ', maxFramesReceivedBetweenTimerInterval: ' +
  250. this.maxFramesReceivedBetweenTimerInterval +
  251. '\\n' +
  252. ' label: ' +
  253. label +
  254. '\\n'
  255. if (pts != -1) {
  256. logInfo += ' this.notEnoughSlots(' + pts + '): ' + this.notEnoughSlots(pts) + '\\n'
  257. }
  258. if (this.enable_logging) {
  259. console.log(logInfo)
  260. } else {
  261. logBufQueue.push(logInfo)
  262. if (logBufQueue.length > MAX_LOG_NUM) {
  263. logBufQueue.shift()
  264. }
  265. }
  266. }
  267. Decoder.prototype.resetBufItem = function (index) {
  268. mediaArray[index].media = null
  269. mediaArray[index].meta = null
  270. if (mediaArray[index].isIDR == true) {
  271. this.bufferIFrame -= 1
  272. }
  273. mediaArray[index] = {
  274. pts: -1,
  275. receive_ts: 0,
  276. decode_ts: 0,
  277. yuv_ts: 0,
  278. render_ts: 0,
  279. media: null,
  280. meta: null,
  281. isIDR: false,
  282. }
  283. this.readPtr = this.seqAdd(this.readPtr, 1, CACHE_BUF_LENGTH)
  284. }
  285. Decoder.prototype.checkPktOrderInConsumer = function (index) {
  286. if (this.consumerPrevPts == -1) {
  287. if (!this.isSlotEmpty(index)) {
  288. this.consumerPrevPts = mediaArray[index].pts
  289. }
  290. return true
  291. }
  292. if (this.isSlotEmpty(index)) {
  293. //lost
  294. // debugger
  295. // console.log("[xmedia] return on SLOT EMPTY, prev: %s", prev)
  296. this.consumerWaitingIDR = true
  297. this.consumerPrevPts = this.seqAdd(this.consumerPrevPts, 1, 65536)
  298. return true
  299. }
  300. if (!this.slotHasMedia(index)) {
  301. // pure meta
  302. // debugger
  303. // console.log("[xmedia] return on meta, prev: %s, cur: %s", this., mediaArray[index].pts)
  304. this.consumerPrevPts = mediaArray[index].pts
  305. return true
  306. }
  307. this.consumerCurrPts = mediaArray[index].pts
  308. if (this.consumerWaitingIDR || this.seqDiff(this.consumerCurrPts, this.consumerPrevPts, 65536) != 1) {
  309. // if (!mediaArray[index].isIDR && mediaArray[index].media.byteLength!=0) {
  310. if (this.isPFrame(mediaArray[index].isIDR, mediaArray[index].media.byteLength)) {
  311. console.error('[INFO][XMEDIA] optimize to further reduce clutter chance. copy console log to developer')
  312. this.dumpLogBuf()
  313. this.dumpJitterBufInfo('go away.')
  314. // debugger
  315. this.consumerPrevPts = -1
  316. // this.resetDecoder()
  317. return false
  318. }
  319. }
  320. // console.log("[xmedia] return finally, prev: %s, cur: %s", prev, cur)
  321. this.consumerPrevPts = this.consumerCurrPts
  322. this.consumerWaitingIDR = false
  323. return true
  324. }
  325. Decoder.prototype.slotHasMedia = function (index) {
  326. return mediaArray[index].media != null && mediaArray[index].media.byteLength != 0
  327. }
  328. Decoder.prototype.slotHasContent = function (index) {
  329. return mediaArray[index].media != null && mediaArray[index].meta != null && mediaArray[index].pts != -1
  330. }
  331. Decoder.prototype.procBufItem = function (index) {
  332. this.dumpJitterBufInfo('Entering Decoder.prototype.procBufItem')
  333. // console.log('[][Core][WASM], pts: %s, isIDR: %s, length: %s', mediaArray[index].pts, mediaArray[index].isIDR, mediaArray[index].media.length)
  334. // var loginfo = 'pts: %s, isIDR: %s, length: %s', mediaArray[index].pts, mediaArray[index].isIDR, mediaArray[index].media.length
  335. needToSkip = this.skipFrameUntilI && !mediaArray[index].isIDR
  336. var loginfo =
  337. 'pts: ' +
  338. mediaArray[index].pts +
  339. ', isidr: ' +
  340. mediaArray[index].isIDR +
  341. ', slotHasMedia: ' +
  342. this.slotHasMedia(index) +
  343. ', slotHasMeta: ' +
  344. (mediaArray[index].meta != null) +
  345. ', needToSkip: ' +
  346. needToSkip
  347. if (this.slotHasContent(index) && !needToSkip) {
  348. // console.log("[xmedia] %s ------------ 001", mediaArray[index].pts)
  349. let objData = {
  350. media: mediaArray[index].media,
  351. frameCnt: mediaArray[index].pts,
  352. meta: mediaArray[index].meta,
  353. metadata: mediaArray[index].metadata,
  354. isIDR: mediaArray[index].isIDR,
  355. }
  356. // -------------------
  357. if (this.checkPktOrderInConsumer(index)) {
  358. // console.log("[xmedia] %s ------------ 002", mediaArray[index].pts)
  359. this.decodeFrame(objData)
  360. }
  361. if (mediaArray[index].isIDR) {
  362. // console.log("[xmedia] %s ------------ 003", mediaArray[index].pts)
  363. // console.log("mediaArray[index].isIDR: this.skipFrameUntilI = false")
  364. this.skipFrameUntilI = false
  365. }
  366. } else {
  367. // console.log("[xmedia] %s ------------ 004", mediaArray[index].pts)
  368. if (this.slotHasMedia(index)) {
  369. // console.log("[xmedia] %s ------------ 005", mediaArray[index].pts)
  370. //need to skip, waiting I Frame
  371. //dropCache++
  372. this.dropPkt += 1
  373. // MARKER META1META2
  374. // self.postMessage({ t: MessageEvent.OnlyEmitSignal, meta_only: true, meta: mediaArray[index].meta, metadata: mediaArray[index].metadata })
  375. } else {
  376. // console.log("[xmedia] %s ------------ 006", mediaArray[index].pts)
  377. // no media
  378. if (mediaArray[index].meta != null) {
  379. this.checkPktOrderInConsumer(index)
  380. // console.log("[xmedia] %s ------------ 007", mediaArray[index].pts)
  381. // Still frame
  382. // console.log('[send signal]', mediaArray[index].pts)
  383. self.postMessage({
  384. t: MessageEvent.OnlyEmitSignal,
  385. meta_only: true,
  386. meta: mediaArray[index].meta,
  387. metadata: mediaArray[index].metadata,
  388. })
  389. } else {
  390. // console.log("[xmedia] %s ------------ 008", mediaArray[index].pts)
  391. // Lost_rcv++
  392. // console.log("lost_rcv++: this.skipFrameUntilI = true")
  393. // console.info('[xmedia] FFFFF This code should not be executed!!!!')
  394. console.info('[xmedia] null pkt sneaked into profBufItem without harm')
  395. this.skipFrameUntilI = true
  396. }
  397. }
  398. }
  399. this.dumpJitterBufInfo('Leaving Decoder.prototype.procBufItem, ' + loginfo)
  400. this.lastObj = mediaArray[index]
  401. this.resetBufItem(index)
  402. }
  403. Decoder.prototype.flushBuffer = function (untilIDR) {
  404. this.dumpJitterBufInfo('Entering Decoder.prototype.flushBuffer')
  405. this.skipFrameUntilI = true
  406. var breakWhenIDR = false
  407. while (this.getNumOfPktToBeDec() > 0) {
  408. index = this.readPtr
  409. if (this.slotHasMedia(index)) {
  410. // dropMedia until IDR // \u6765\u4E0D\u53CA\u89E3\u7801\u4E22\u5E27
  411. this.packetsDrop += 1
  412. if (untilIDR) {
  413. if (mediaArray[index].isIDR == true) {
  414. breakWhenIDR = true
  415. break
  416. }
  417. }
  418. } else if (mediaArray[index].meta != null) {
  419. self.postMessage({
  420. t: MessageEvent.OnlyEmitSignal,
  421. meta_only: true,
  422. meta: mediaArray[index].meta,
  423. metadata: mediaArray[index].metadata,
  424. })
  425. }
  426. this.resetBufItem(index)
  427. }
  428. if (!breakWhenIDR) {
  429. this.isFirstFrame = true
  430. }
  431. this.dumpJitterBufInfo('Leaving Decoder.prototype.flushBuffer')
  432. return this.isFirstFrame
  433. }
  434. // var cnt = 0
  435. Decoder.prototype.getFrameToDecode = function () {
  436. this.dumpJitterBufInfo('Entering Decoder.prototype.getFrameToDecode')
  437. if (this.getNumOfPktToBeDec() == 0) {
  438. return false
  439. }
  440. //bufNum awaiting increase counter
  441. // while (this.getNumOfPktToBeDec() > CACHE_BUF_LENGTH / 2) {
  442. // needToCheck = true
  443. // if (this.cntBufInc > this.MAX_TRY_TO_DEC_BUFNUM) {
  444. // console.log('ringbuffer is deteriorating, flush until IDR')
  445. // var untilIDR = true
  446. // this.flushBuffer(untilIDR)
  447. // this.cntBufInc = 0
  448. // break
  449. // }
  450. // this.procBufItem(this.readPtr)
  451. // }
  452. // if (this.getNumOfPktToBeDec() == 0) {
  453. // return false
  454. // }
  455. let IFrmInBuffer = 0
  456. let frmInBuffer = 0
  457. for (var i = 0; i < CACHE_BUF_LENGTH; ++i) {
  458. if (mediaArray[i].isIDR) {
  459. IFrmInBuffer += 1
  460. }
  461. if (this.slotHasMedia(i)) {
  462. frmInBuffer += 1
  463. }
  464. }
  465. if (!this.slotHasContent(this.readPtr) && IFrmInBuffer == 0) {
  466. if (frmInBuffer > 0) {
  467. // There is P frame in buffer but cannot be decoded.
  468. // Due to ordered data channel, this is packet loss.
  469. // So request for I frame here.
  470. printConsole.log('detect packet lost. Request for I frame.')
  471. self.postMessage({ t: MessageEvent.RequestIFrame })
  472. }
  473. return false
  474. }
  475. this.procBufItem(this.readPtr)
  476. // if (this.getNumOfPktToBeDec() > this.prevBufNum) {
  477. // this.cntBufInc++
  478. // } else {
  479. // if (this.cntBufInc > 2) {
  480. // // aimd
  481. // this.cntBufInc / 2
  482. // }
  483. // }
  484. // this.prevBufNum = this.getNumOfPktToBeDec()
  485. this.dumpJitterBufInfo('Leaving Decoder.prototype.getFrameToDecode')
  486. return true
  487. }
  488. //refactor end:
  489. var cacheBuffer
  490. var resultBuffer
  491. Decoder.prototype.startDecoding = function () {
  492. function iterative_getFrameToDecode() {
  493. self.decoder.framesReceivedBetweenTimerInterval = 0
  494. self.decoder.dumpJitterBufInfo('Entering Decoder.prototype.iterative_getFrameToDecode')
  495. var start_ts = Date.now()
  496. let hasDecodeFrame = self.decoder.getFrameToDecode()
  497. var end_ts = Date.now()
  498. // refactor
  499. let expect_interval =
  500. 1000 / (30 + Math.max(self.decoder.getNumOfPktToBeDec() - self.decoder.passiveJitterLength, 0))
  501. //let expect_interval = 1000 / (Decoder.prototype.getNumOfPktToBeDec() + 30)
  502. if (hasDecodeFrame) {
  503. let usedTime = end_ts - start_ts
  504. self.decoder.getFrameInterval = expect_interval - Math.max(usedTime, self.decoder.dtpf)
  505. if (self.decoder.getFrameInterval < 1) {
  506. self.decoder.getFrameInterval = 0
  507. }
  508. } else {
  509. self.decoder.getFrameInterval = 5
  510. }
  511. // let usedTime = end_ts - start_ts
  512. // FPS = 30
  513. // if (usedTime * FPS < 1000) {
  514. // self.decoder.getFrameInterval = 1000 / (FPS + Decoder.prototype.getNumOfPktToBeDec())
  515. // } else {
  516. // self.decoder.getFrameInterval = 1 //ms
  517. // }
  518. // if (Decoder.prototype.getNumOfPktToBeDec() == 0) {
  519. // //Hinse: have to get buf to send asap.
  520. // self.decoder.getFrameInterval = 5 //ms
  521. // }
  522. setTimeout(iterative_getFrameToDecode, self.decoder.getFrameInterval)
  523. self.decoder.dumpJitterBufInfo('Leaving Decoder.prototype.iterative_getFrameToDecode')
  524. // refactor end
  525. }
  526. function postStats() {
  527. function add(accumulator, a) {
  528. if (a == -1) {
  529. a = 0
  530. }
  531. return accumulator + a
  532. }
  533. function count_valid(accumulator, a) {
  534. let non_zero = 0
  535. if (a != -1) {
  536. non_zero = 1
  537. }
  538. return accumulator + non_zero
  539. }
  540. function max(maxer, a) {
  541. return Math.max(maxer, a)
  542. }
  543. const dtpf =
  544. self.decoder.decodeTimeCircular.reduce(add, 0) / self.decoder.decodeTimeCircular.reduce(count_valid, 0) || 0
  545. const dtmf = self.decoder.decodeTimeCircular.reduce(max, 0)
  546. let objData = {
  547. t: MessageEvent.UpdateStats,
  548. mediaBytesReceived: self.decoder.mediaBytesReceived,
  549. metaBytesReceived: self.decoder.metaBytesReceived,
  550. packetsLost: self.decoder.packetsLost, // \u7F51\u7EDC\u4E22\u5E27
  551. packetsDrop: self.decoder.packetsDrop, // \u6765\u4E0D\u53CA\u89E3\u7801\u4E22\u5E27
  552. framesReceived: self.decoder.receivedMedia,
  553. framesDecoded: self.decoder.receivedYUV,
  554. framesRendered: self.decoder.receivedEmit,
  555. framesReturned: framesReturned,
  556. // framesAwait: leastReceivePts - lastProcessPts,
  557. framesAwait: self.decoder.getNumOfPktToBeDec(), // \u7B49\u5F85\u89E3\u7801\u7684\u5E27
  558. decodeTimePerFrame: dtpf,
  559. decodeTimeMaxFrame: dtmf,
  560. sendOutBuffer: send_out_buffer,
  561. JankTimes: self.decoder.JankTimes,
  562. bigJankTimes: self.decoder.bigJankTimes,
  563. receivedIframe: self.decoder.IframesReceived,
  564. decodedIframe: self.decoder.IframesDecoded,
  565. }
  566. self.postMessage(objData)
  567. self.decoder.dtmf = 0
  568. }
  569. setTimeout(iterative_getFrameToDecode, this.getFrameInterval)
  570. setInterval(postStats, 1000)
  571. }
  572. Decoder.prototype.initAll = function (config) {
  573. if (typeof wasmSource != 'undefined') {
  574. if (wasmSource == 0) {
  575. // Load from indexedDB
  576. // console.log('Load WASM from indexedDB')
  577. printConsole.log('Load WASM from indexedDB')
  578. wasmSource = undefined
  579. } else if (wasmSource == 1) {
  580. // Load by fetch
  581. // console.log('Load WASM by fetch')
  582. printConsole.log('Load WASM by fetch')
  583. wasmSource = undefined
  584. } else {
  585. printConsole.log('WASM not ready now, wait for 200 ms.')
  586. }
  587. } else {
  588. printConsole.log('wasm variable is not defined. Probably libffmpeg.js file is not loaded properly.')
  589. }
  590. if (typeof wasmTable === 'undefined') {
  591. setTimeout(self.decoder.initAll, 200, config)
  592. return 0
  593. }
  594. cacheBuffer = Module._malloc(1024 * 1024)
  595. resultBuffer = Module._malloc(64)
  596. self.postMessage({
  597. t: MessageEvent.WASMReadyCost,
  598. type: 'report',
  599. data: {
  600. metric: 'wasmDownloadCost',
  601. value: Date.now() - startTime,
  602. group: 'costs',
  603. },
  604. })
  605. // WASM already initialized. Now we open decoder.
  606. const LOG_LEVEL_WASM = 2
  607. const DECODER_H264 = 0
  608. const decoder_type = DECODER_H264
  609. for (var j = 0; j < YUV_BUF_LENGTH; ++j) {
  610. YUVArray.push({ status: 0, buffer: new Uint8Array((config.width * config.height * 3) / 2) })
  611. }
  612. printConsole.log('Going to open decoder ' + String(Date.now()))
  613. var ret0 = Module._openDecoder(0, decoder_type, LOG_LEVEL_WASM)
  614. if (ret0 == 0) {
  615. self.decoder.startDecoding()
  616. self.postMessage({ t: MessageEvent.WASMReady, wasm_ready: true, updateStats: false })
  617. } else {
  618. printConsole.error('openDecoder failed with error ' + String(ret0), '5001')
  619. return 1
  620. }
  621. return 0
  622. }
  623. Decoder.prototype.cacheFrame = function (data) {
  624. if (data.position != undefined) {
  625. var media = data.data.subarray(data.metaLen, data.metaLen + data.mediaLen)
  626. if (IFrameCacheBuffer[JSON.stringify(data.position)] == undefined) {
  627. for (var key in IFrameCacheBuffer) delete IFrameCacheBuffer[key] // Clear Frame Cache
  628. IFrameCacheBuffer[JSON.stringify(data.position)] = {}
  629. }
  630. IFrameCacheBuffer[JSON.stringify(data.position)][data.cachedKey] = media
  631. self.postMessage({
  632. t: MessageEvent.CacheFrame,
  633. cacheFrame: true,
  634. cachedKey: data.cachedKey,
  635. metadata: data.metadata,
  636. })
  637. }
  638. }
  639. Decoder.prototype.updateMediaMetaStats = function (data) {
  640. this.metaBytesReceived += data.metaLen
  641. this.mediaBytesReceived += data.mediaLen
  642. if (data.mediaLen != 0) {
  643. this.receivedMedia++
  644. }
  645. }
  646. Decoder.prototype.isIFrame = function (isIDR, mediaLen) {
  647. // return data.isIDR && media.byteLength !=0
  648. return isIDR && mediaLen != 0
  649. }
  650. Decoder.prototype.isPFrame = function (isIDR, mediaLen) {
  651. // return !data.isIDR && media.byteLength !=0
  652. return !isIDR && mediaLen != 0
  653. }
  654. Decoder.prototype.isPureMeta = function (metaLen, mediaLen) {
  655. // return media.byteLength == 0 && meta.byteLength !=0
  656. return mediaLen == 0 && metaLen != 0
  657. }
  658. Decoder.prototype.isInvalidPkt = function (isIDR, mediaLen, metaLen) {
  659. return !this.isIFrame(isIDR, mediaLen) && !this.isPFrame(isIDR, mediaLen) && !this.isPureMeta(metaLen, mediaLen)
  660. }
  661. Decoder.prototype.isSlotEmpty = function (index) {
  662. return !this.slotHasMedia(index) && mediaArray[index].meta == null
  663. }
  664. Decoder.prototype.handleNewPktOnFlush = function (isIDR, mediaLen) {
  665. var dropPkt = false
  666. // console.log("[xmedia] 000-1 isFirstFrame %s", this.isFirstFrame)
  667. if (this.isFirstFrame) {
  668. // let IDR/meta pass
  669. // console.log("[xmedia] 000-2 isIDR: %s, mediaLen: %s", isIDR, mediaLen)
  670. // console.log("[xmedia] 000-3 this.isPFrame(isIDR, mediaLen): %s", this.isPFrame(isIDR, mediaLen))
  671. if (this.isPFrame(isIDR, mediaLen)) {
  672. // console.log("[xmedia] 001: isPFrame TRUE")
  673. this.packetsDrop += 1
  674. // MARKER META1META2
  675. dropPkt = true
  676. }
  677. if (this.isIFrame(isIDR, mediaLen)) {
  678. // console.log("[xmedia] 002: isIFrame TRUE")
  679. this.isFirstFrame = false
  680. }
  681. }
  682. // console.log("[xmedia] 003: dropPkt: %s", dropPkt)
  683. return dropPkt
  684. }
  685. Decoder.prototype.notEnoughSlots = function (pts) {
  686. return this.isBufFull() || this.seqDiff(pts, this.prevSeq, CACHE_BUF_LENGTH) > this.getNumOfEmptySlot()
  687. }
  688. Decoder.prototype.receiveFrame = function (data) {
  689. var key = data.cachedKey
  690. var pts = data.frameCnt
  691. var meta = data.data.subarray(0, data.metaLen)
  692. var media
  693. if (data.cached) {
  694. media = IFrameCacheBuffer[JSON.stringify(data.position)][key]
  695. } else if (data.cacheRequest) {
  696. media = data.data.subarray(data.metaLen, data.metaLen + data.mediaLen)
  697. self.decoder.cacheFrame(data)
  698. } else {
  699. media = data.data.subarray(data.metaLen, data.metaLen + data.mediaLen)
  700. }
  701. this.updateMediaMetaStats(data)
  702. if (this.isFirstFrame) {
  703. // console.log('[xmedia] isFirstFrame = true. pts:%s', pts)
  704. if (this.isPFrame(data.isIDR, media.byteLength)) {
  705. // MARKER META1META2
  706. this.packetsDrop += 1
  707. return
  708. }
  709. this.prevSeq = this.seqDiff(pts, 1, 65536)
  710. this.readPtr = this.writePtr = pts % CACHE_BUF_LENGTH
  711. if (data.isIDR) {
  712. this.isFirstFrame = false
  713. }
  714. }
  715. if (pts !== this.seqAdd(this.prevSeq, 1, 65536) && pts !== this.prevSeq) {
  716. this.packetsLost += 1
  717. }
  718. const index = pts % CACHE_BUF_LENGTH
  719. if (this.startRecord) {
  720. this.mediaCacheBuffer.set(media, this.mediaCacheSize)
  721. this.mediaCacheSize += media.byteLength
  722. }
  723. if (this.saveRecord) {
  724. downloadBlob(this.mediaCacheBuffer.subarray(0, this.mediaCacheSize), 'test.264', 'application/octet-stream')
  725. this.mediaCacheSize = 0
  726. this.saveRecord = false
  727. this.startRecord = false
  728. }
  729. //refactor:
  730. // Step 1, big jump detected. we cannot handle it, flush all.
  731. var untilIDR, pktDrop
  732. if (this.isSeqJump(this.prevSeq, pts)) {
  733. // console.log('[resetdecoder] Fatal: decoder seq jump from ' + this.prevSeq + ' to ' + pts)
  734. untilIDR = false
  735. this.flushBuffer(untilIDR)
  736. pktDrop = this.handleNewPktOnFlush(data.isIDR, media.byteLength)
  737. if (pktDrop) return
  738. }
  739. this.dumpJitterBufInfo('Entering Decoder.prototype.receiveFrame', pts)
  740. // console.log("--->> this.notEnoughSlots(pts): %s", this.notEnoughSlots(pts))
  741. // Step 2,
  742. if (this.aheadof(pts, this.prevSeq)) {
  743. // pts before prevSeq
  744. // pkts in wrong order
  745. if (this.packetsLost > 0) {
  746. this.packetsLost -= 1
  747. // this.packetdisorder +=1
  748. }
  749. // console.log("[xmedia] disorder frame received. preSeq: %s, pts: %s", this.prevSeq, pts)
  750. if (this.seqDiff(this.prevSeq, pts, 65536) < this.getNumOfPktToBeDec()) {
  751. // slot for pts is not handled yet. just put it back:
  752. // console.log('put disorder frame to enc_queue, pkt:%s, prevPts: %s, numOfPktToBeDec: %s', pts, this.prevSeq, this.getNumOfPktToBeDec())
  753. } else {
  754. //dropDisorder++
  755. console.error(
  756. 'drop disorder pkt:%s, prevPts: %s, numOfPktToBeDec: %s',
  757. pts,
  758. this.prevSeq,
  759. this.getNumOfPktToBeDec(),
  760. )
  761. this.packetsDrop += 1
  762. // ---------------------
  763. // Note:
  764. //
  765. // Three principles for meta data:
  766. // step 1 step 2
  767. // 1. backend -----> frontend (decoder.js) -----> frontend (worker.js), meta pkts must be kept in order in the whole pipeline
  768. // 2. if media presents and needs to be dropped, the meta companion needs to be dropped together.
  769. // 3. if media is absent (media.bytelength == 0), send meta anyway
  770. // ---------------------
  771. // According to rule 1, drop meta at this point is reasonable.
  772. return
  773. }
  774. } else {
  775. // pts after prevSeq
  776. // make sure the ringbuffer has empty slot for new pkt
  777. if (this.notEnoughSlots(pts)) {
  778. this.dumpJitterBufInfo('Fatal: decoder buf is full', pts)
  779. //dropIncoming
  780. untilIDR = true
  781. this.flushBuffer(untilIDR)
  782. if (this.notEnoughSlots(pts)) {
  783. untilIDR = false
  784. this.flushBuffer(untilIDR)
  785. }
  786. pktDrop = this.handleNewPktOnFlush(data.isIDR, media.byteLength)
  787. if (pktDrop) return
  788. }
  789. }
  790. mediaArray[index] = {
  791. pts: pts,
  792. receive_ts: Date.now(),
  793. decode_ts: 0,
  794. yuv_ts: 0,
  795. render_ts: 0,
  796. media: media,
  797. meta: meta,
  798. metadata: data.metadata,
  799. isIDR: data.isIDR,
  800. }
  801. if (data.isIDR == true) {
  802. this.bufferIFrame += 1
  803. }
  804. this.framesReceivedBetweenTimerInterval += 1
  805. if (this.framesReceivedBetweenTimerInterval > this.maxFramesReceivedBetweenTimerInterval) {
  806. this.maxFramesReceivedBetweenTimerInterval = this.framesReceivedBetweenTimerInterval
  807. }
  808. if (!this.aheadof(pts, this.prevSeq)) {
  809. // writePtr += (cur - prev)
  810. this.writePtr = this.seqAdd(this.writePtr, this.seqDiff(pts, this.prevSeq, CACHE_BUF_LENGTH), CACHE_BUF_LENGTH)
  811. if (this.seqAdd(index, 1, CACHE_BUF_LENGTH) != this.writePtr) {
  812. this.dumpJitterBufInfo('dec worker internal info: index (' + index + ') != write_ptr (' + this.writePtr + ')')
  813. // debugger
  814. }
  815. this.prevSeq = pts
  816. }
  817. this.dumpJitterBufInfo('Leaving Decoder.prototype.receiveFrame')
  818. //refactor end
  819. }
  820. Decoder.prototype.startEmiter = function () {
  821. self.decoder.startEmit = true
  822. if (cachedFirstFrame != undefined) {
  823. self.postMessage(cachedFirstFrame, [cachedFirstFrame.data.buffer])
  824. send_out_buffer += 1
  825. this.receivedEmit++
  826. cachedFirstFrame = undefined
  827. }
  828. if (cachedPanoramaFirstFrame != undefined) {
  829. self.postMessage(cachedPanoramaFirstFrame)
  830. send_out_buffer += 1
  831. this.receivedEmit++
  832. cachedPanoramaFirstFrame = undefined
  833. }
  834. }
  835. Decoder.prototype.decodePanorama = function (data) {
  836. console.log('upload pano data')
  837. var content = data.data.data
  838. var content_size = data.data.mediaLen
  839. // var cacheBuffer = Module._malloc(content_size)
  840. // var resultBuffer = Module._malloc(64)
  841. Module.HEAPU8.set(content, cacheBuffer)
  842. let ret = 0
  843. try {
  844. ret = Module._decodeData(0, 0, cacheBuffer, content_size, resultBuffer)
  845. // // console.log('[][Core][WASM] return value %s',ret)
  846. // if(ret!=0){
  847. // // console.log('[][Core][WASM],-abcdefg-----> ', ret)
  848. // var ret_close = Module._closeDecoder(0)
  849. // // eslint-disable-next-line no-empty
  850. // if (ret_close === 0) {
  851. // // console.log('[][Core][WASM] decoder closed for restart')
  852. // } else {
  853. // printConsole.error('close decoder failed after decode pano.')
  854. // return 1
  855. // }
  856. // var ret0 = Module._openDecoder(0, 0, 2)
  857. // // console.log('[][Core][WASM] decoder restart success')
  858. // // var ret1 = Module._openDecoder(1, decoder_type, LOG_LEVEL_WASM)
  859. // if (ret0 === 0) {
  860. // ret = Module._decodeData(0, 0, cacheBuffer, content_size, resultBuffer)
  861. // } else {
  862. // printConsole.error('openDecoder failed with error ' + String(ret0) , '5001')
  863. // return 1
  864. // }
  865. // }
  866. } catch (e) {
  867. console.log('catch error ', e)
  868. printConsole.error(e.message, '5002')
  869. }
  870. // let ret = Module._decodeData(0, 0, cacheBuffer, content_size, resultBuffer)
  871. var width = Module.getValue(resultBuffer, 'i32')
  872. var height = Module.getValue(resultBuffer + 4, 'i32')
  873. var stride_y = Module.getValue(resultBuffer + 20, 'i32')
  874. var stride_u = Module.getValue(resultBuffer + 24, 'i32')
  875. var stride_v = Module.getValue(resultBuffer + 28, 'i32')
  876. var addr_y = Module.getValue(resultBuffer + 8, 'i32')
  877. var addr_u = Module.getValue(resultBuffer + 12, 'i32')
  878. var addr_v = Module.getValue(resultBuffer + 16, 'i32')
  879. var poc = Module.getValue(resultBuffer + 32, 'i32')
  880. if (ret != 0) {
  881. printConsole.log(
  882. 'Decode Data error for panorama, ret value is ' + String(ret) + ', frame content size: ' + String(content_size),
  883. )
  884. return
  885. }
  886. var yuv_data = new Uint8Array((width * height * 3) / 2)
  887. let pos = 0
  888. for (let i = 0; i < height; i++) {
  889. let src = addr_y + i * stride_y
  890. let tmp = HEAPU8.subarray(src, src + width)
  891. tmp = new Uint8Array(tmp)
  892. yuv_data.set(tmp, pos)
  893. pos += tmp.length
  894. }
  895. for (let i = 0; i < height / 2; i++) {
  896. let src = addr_u + i * stride_u
  897. let tmp = HEAPU8.subarray(src, src + width / 2)
  898. tmp = new Uint8Array(tmp)
  899. yuv_data.set(tmp, pos)
  900. pos += tmp.length
  901. let src2 = addr_v + i * stride_v
  902. let tmp2 = HEAPU8.subarray(src2, src2 + width / 2)
  903. tmp2 = new Uint8Array(tmp2)
  904. yuv_data.set(tmp2, pos)
  905. pos += tmp2.length
  906. }
  907. const objData = {
  908. t: MessageEvent.PanoramaMessage,
  909. tileId: data.data.tileId,
  910. uuid: data.data.uuid,
  911. data: yuv_data,
  912. x: data.data.x,
  913. y: data.data.y,
  914. z: data.data.z,
  915. }
  916. //TODO: remove debug
  917. if (this.startEmit) {
  918. self.postMessage(objData)
  919. } else {
  920. cachedPanoramaFirstFrame = objData
  921. }
  922. // console.log('upload pano data with dataLength:', len(yuv_data))
  923. var ret_close = Module._closeDecoder(0)
  924. // eslint-disable-next-line no-empty
  925. if (ret_close === 0) {
  926. // console.log('[][Core][WASM] decoder closed for restart')
  927. } else {
  928. printConsole.error('close decoder failed after decode pano.')
  929. return 1
  930. }
  931. var ret0 = Module._openDecoder(0, 0, 2)
  932. // var ret1 = Module._openDecoder(1, decoder_type, LOG_LEVEL_WASM)
  933. if (ret0 === 0) {
  934. // console.log('[][Core][WASM] decoder restart success')
  935. self.decoder.startDecoding()
  936. self.postMessage({ t: MessageEvent.WASMReady, wasm_ready: true, updateStats: false })
  937. } else {
  938. printConsole.error('openDecoder failed with error ' + String(ret0), '5001')
  939. return 1
  940. }
  941. }
  942. Decoder.prototype.decodeFrame = function (data) {
  943. //printConsole.log('decodeFrame'+JSON.stringify(data))
  944. var content = data.media
  945. if (typeof content == 'undefined') {
  946. printConsole.error('null content in decoder', '5999')
  947. return
  948. }
  949. var content_size = content.byteLength
  950. // var cacheBuffer = Module._malloc(content_size)
  951. // var resultBuffer = Module._malloc(64)
  952. Module.HEAPU8.set(content, cacheBuffer)
  953. const index = data.frameCnt % CACHE_BUF_LENGTH
  954. mediaArray[index].decode_ts = Date.now()
  955. var objData
  956. if (content_size != 0) {
  957. // var date = Date.now()
  958. // var curDate = Date.now()
  959. // while (curDate - date < 100) {
  960. // curDate = Date.now()
  961. // }
  962. // TODO: Enable/Disable it by config
  963. if (data.isIDR) {
  964. this.errorCacheSize = 0
  965. }
  966. // Guarantee that stream start from I frame
  967. if (this.errorCacheSize != 0 || data.isIDR) {
  968. this.errorCacheBuffer.set(content, this.mediaCacheSize)
  969. this.errorCacheSize += content.byteLength
  970. }
  971. let start_ts = Date.now()
  972. let ret = 0
  973. try {
  974. ret = Module._decodeData(0, data.frameCnt, cacheBuffer, content_size, resultBuffer)
  975. // if(ret==8){
  976. // // console.log('[][Core][WASM],-abcdefg-----> ', ret)
  977. // var ret_close = Module._closeDecoder(0)
  978. // // eslint-disable-next-line no-empty
  979. // if (ret_close === 0) {
  980. // // console.log('[][Core][WASM] decoder closed for restart')
  981. // } else {
  982. // printConsole.error('close decoder failed after decode pano.')
  983. // return 1
  984. // }
  985. // var ret0 = Module._openDecoder(0, 0, 2)
  986. // // console.log('[][Core][WASM] decoder restart success')
  987. // // var ret1 = Module._openDecoder(1, decoder_type, LOG_LEVEL_WASM)
  988. // if (ret0 === 0) {
  989. // ret = Module._decodeData(0, data.frameCnt, cacheBuffer, content_size, resultBuffer)
  990. // } else {
  991. // printConsole.error('openDecoder failed with error ' + String(ret0) , '5001')
  992. // return 1
  993. // }
  994. // }
  995. } catch (e) {
  996. console.log('catch error ', e)
  997. if (this.errorCacheSize > 0) {
  998. downloadBlob(this.errorCacheBuffer.subarray(0, this.errorCacheSize), 'error.264', 'application/octet-stream')
  999. this.errorCacheSize = 0
  1000. }
  1001. printConsole.error(e.message, '5002')
  1002. }
  1003. var width = Module.getValue(resultBuffer, 'i32')
  1004. var height = Module.getValue(resultBuffer + 4, 'i32')
  1005. var stride_y = Module.getValue(resultBuffer + 20, 'i32')
  1006. var stride_u = Module.getValue(resultBuffer + 24, 'i32')
  1007. var stride_v = Module.getValue(resultBuffer + 28, 'i32')
  1008. var addr_y = Module.getValue(resultBuffer + 8, 'i32')
  1009. var addr_u = Module.getValue(resultBuffer + 12, 'i32')
  1010. var addr_v = Module.getValue(resultBuffer + 16, 'i32')
  1011. var poc = Module.getValue(resultBuffer + 32, 'i32')
  1012. var pts = data.frameCnt
  1013. if (ret != 0) {
  1014. printConsole.log(
  1015. 'Decode Data error for video stream, ret value is ' +
  1016. String(ret) +
  1017. ', frame content size: ' +
  1018. String(content_size),
  1019. )
  1020. if (this.errorCacheSize > 0) {
  1021. downloadBlob(this.errorCacheBuffer.subarray(0, this.errorCacheSize), 'error.264', 'application/octet-stream')
  1022. this.errorCacheSize = 0
  1023. }
  1024. printConsole.log('current poc is ' + String(poc) + ', last poc is ' + String(lastPoc))
  1025. return
  1026. }
  1027. lastPoc = poc
  1028. this.receivedYUV++
  1029. let end_ts = Date.now()
  1030. fdt = end_ts - start_ts
  1031. if (fdt + self.decoder.getFrameInterval > 84) {
  1032. this.JankTimes++
  1033. }
  1034. if (fdt + self.decoder.getFrameInterval > 125) {
  1035. this.bigJankTimes++
  1036. }
  1037. self.decoder.dtpf = self.decoder.dtpf * 0.9 + fdt * 0.1
  1038. // if (fdt > self.decoder.dtmf) {
  1039. // self.decoder.dtmf = fdt
  1040. // }
  1041. self.decoder.decodeTimeCircular[self.decoder.dtcPtr] = fdt
  1042. self.decoder.dtcPtr = (self.decoder.dtcPtr + 1) % self.decoder.decodeTimeCircular.length
  1043. if (YUVArray.length <= 0) {
  1044. // printConsole.error('No buffer to save YUV after decoding, pts is ' + String(pts), '5002')
  1045. return
  1046. }
  1047. var first_available_buffer = YUVArray.shift()
  1048. var yuv_data = first_available_buffer.buffer
  1049. let pos = 0
  1050. for (let i = 0; i < height; i++) {
  1051. let src = addr_y + i * stride_y
  1052. let tmp = HEAPU8.subarray(src, src + width)
  1053. tmp = new Uint8Array(tmp)
  1054. yuv_data.set(tmp, pos)
  1055. pos += tmp.length
  1056. }
  1057. for (let i = 0; i < height / 2; i++) {
  1058. let src = addr_u + i * stride_u
  1059. let tmp = HEAPU8.subarray(src, src + width / 2)
  1060. tmp = new Uint8Array(tmp)
  1061. yuv_data.set(tmp, pos)
  1062. pos += tmp.length
  1063. let src2 = addr_v + i * stride_v
  1064. let tmp2 = HEAPU8.subarray(src2, src2 + width / 2)
  1065. tmp2 = new Uint8Array(tmp2)
  1066. yuv_data.set(tmp2, pos)
  1067. pos += tmp2.length
  1068. }
  1069. objData = {
  1070. t: MessageEvent.DecodeMessage,
  1071. data: yuv_data,
  1072. width: width,
  1073. height: height,
  1074. pts: data.frameCnt,
  1075. yuv_ts: Date.now(),
  1076. meta: data.meta,
  1077. metadata: data.metadata,
  1078. }
  1079. } else {
  1080. objData = {
  1081. t: MessageEvent.DecodeMessage,
  1082. data: null,
  1083. width: 0,
  1084. height: 0,
  1085. pts: data.frameCnt,
  1086. yuv_ts: Date.now(),
  1087. meta: data.meta,
  1088. metadata: data.metadata,
  1089. }
  1090. }
  1091. if (this.startEmit) {
  1092. if (objData.data != null) {
  1093. self.postMessage(objData, [objData.data.buffer])
  1094. send_out_buffer += 1
  1095. this.receivedEmit++
  1096. } else {
  1097. self.postMessage(objData)
  1098. this.receivedEmit++
  1099. }
  1100. } else {
  1101. if (objData.data != null) {
  1102. cachedFirstFrame = objData
  1103. }
  1104. }
  1105. // if (cacheBuffer != null) {
  1106. // Module._free(cacheBuffer)
  1107. // cacheBuffer = null
  1108. // }
  1109. // if (resultBuffer != null) {
  1110. // Module._free(resultBuffer)
  1111. // resultBuffer = null
  1112. // }
  1113. return
  1114. }
  1115. Decoder.prototype.receiveBuffer = function (data) {
  1116. framesReturned++
  1117. send_out_buffer -= 1
  1118. YUVArray.push({ status: 0, buffer: data.buffer })
  1119. }
  1120. Decoder.prototype.setPassiveJitter = function (len) {
  1121. this.passiveJitterLength = len
  1122. }
  1123. Decoder.prototype.uninitDecoder = function () {
  1124. printConsole.log('Going to uninit decoder.')
  1125. }
  1126. Decoder.prototype.StartRecord = function () {
  1127. printConsole.log('Start Record')
  1128. this.startRecord = true
  1129. }
  1130. Decoder.prototype.SaveRecord = function () {
  1131. printConsole.log('Save Record')
  1132. this.saveRecord = true
  1133. }
  1134. Decoder.prototype.ReceivePanorama = function (data) {
  1135. self.decoder.resetDecoder()
  1136. self.decoder.decodePanorama(data)
  1137. }
  1138. Decoder.prototype.LoadWASM = function (url) {
  1139. printConsole.log('Load WASM from ' + String(url))
  1140. try {
  1141. self.importScripts(url)
  1142. } catch (e) {
  1143. console.log('catch error ', e)
  1144. printConsole.error(e.message, '5003')
  1145. }
  1146. }
  1147. // self.incoming_pkt_queue = new array()
  1148. function getRandomInt(max) {
  1149. return Math.floor(Math.random() * max)
  1150. }
  1151. // console.log(getRandomInt(30));
  1152. self.decoder = new Decoder()
  1153. netArray = []
  1154. var gTmpIdx = 0
  1155. var gLossCnt = 0
  1156. self.onmessage = function (evt) {
  1157. switch (evt.data.t) {
  1158. case 1: // Init Message
  1159. self.decoder.initAll(evt.data.config)
  1160. break
  1161. case 0: // Decode Message
  1162. // console.log('[][Core][WASM],------> ', evt.data)
  1163. gTmpIdx += 1
  1164. randLen = 16
  1165. // randLen = getRandomInt(30)
  1166. // eslint-disable-next-line no-constant-condition
  1167. if (gTmpIdx > 100 && false) {
  1168. var test_jitter_buffer = true
  1169. if (test_jitter_buffer == true) {
  1170. if (netArray.length % 5 == 4) {
  1171. // netArray.insert(netArray.length -1, evt.data)
  1172. netArray.splice(netArray.length - 1, 0, evt.data)
  1173. } else {
  1174. netArray.push(evt.data)
  1175. }
  1176. if (netArray.length > randLen) {
  1177. // 1. jitter
  1178. while (netArray.length > 0) {
  1179. // console.log("[xmedia] array len: %s", netArray.length)
  1180. gLossCnt += 1
  1181. var pkt = netArray.shift()
  1182. // lose pkt
  1183. var dropInterval = 50
  1184. var dropContinousPkts = 3
  1185. if (gLossCnt % dropInterval < dropContinousPkts) {
  1186. if (gLossCnt == dropInterval + dropContinousPkts - 1) {
  1187. gLossCnt = 0
  1188. }
  1189. } else {
  1190. self.decoder.receiveFrame(pkt)
  1191. }
  1192. }
  1193. // // 2. disorder
  1194. // if (incoming_pkt_queue.length % 3) {
  1195. // in[0]
  1196. // in[2]
  1197. // in[1]
  1198. // }
  1199. }
  1200. } else {
  1201. self.decoder.receiveFrame(evt.data)
  1202. }
  1203. } else {
  1204. self.decoder.receiveFrame(evt.data)
  1205. }
  1206. break
  1207. case 2: // Receive used buffer
  1208. self.decoder.receiveBuffer(evt.data)
  1209. break
  1210. case 3: // Unint Message
  1211. self.decoder.uninitDecoder()
  1212. break
  1213. case 4: // Reset status
  1214. self.decoder.resetDecoder()
  1215. break
  1216. case 5: // Start emit
  1217. self.decoder.startEmiter()
  1218. break
  1219. case 6: // Start Record
  1220. self.decoder.StartRecord()
  1221. break
  1222. case 7: // Save Record
  1223. self.decoder.SaveRecord()
  1224. break
  1225. case 8: // Panorama Decode Message
  1226. self.decoder.ReceivePanorama(evt.data)
  1227. break
  1228. case 9: // Select WASM Version
  1229. self.decoder.setPassiveJitter(evt.data.jitterLength)
  1230. self.decoder.LoadWASM(evt.data.url)
  1231. break
  1232. case 100: // change decoder worker status
  1233. self.decoder.changeLogSwitch(evt.data.status)
  1234. break
  1235. }
  1236. }
  1237. }
  1238. `;