decoder copy.js 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371
  1. /* 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. var content = data.media
  944. if (typeof content == 'undefined') {
  945. printConsole.error('null content in decoder', '5999')
  946. return
  947. }
  948. var content_size = content.byteLength
  949. // var cacheBuffer = Module._malloc(content_size)
  950. // var resultBuffer = Module._malloc(64)
  951. Module.HEAPU8.set(content, cacheBuffer)
  952. const index = data.frameCnt % CACHE_BUF_LENGTH
  953. mediaArray[index].decode_ts = Date.now()
  954. var objData
  955. if (content_size != 0) {
  956. // var date = Date.now()
  957. // var curDate = Date.now()
  958. // while (curDate - date < 100) {
  959. // curDate = Date.now()
  960. // }
  961. // TODO: Enable/Disable it by config
  962. if (data.isIDR) {
  963. this.errorCacheSize = 0
  964. }
  965. // Guarantee that stream start from I frame
  966. if (this.errorCacheSize != 0 || data.isIDR) {
  967. this.errorCacheBuffer.set(content, this.mediaCacheSize)
  968. this.errorCacheSize += content.byteLength
  969. }
  970. let start_ts = Date.now()
  971. let ret = 0
  972. try {
  973. ret = Module._decodeData(0, data.frameCnt, cacheBuffer, content_size, resultBuffer)
  974. // if(ret==8){
  975. // // console.log('[][Core][WASM],-abcdefg-----> ', ret)
  976. // var ret_close = Module._closeDecoder(0)
  977. // // eslint-disable-next-line no-empty
  978. // if (ret_close === 0) {
  979. // // console.log('[][Core][WASM] decoder closed for restart')
  980. // } else {
  981. // printConsole.error('close decoder failed after decode pano.')
  982. // return 1
  983. // }
  984. // var ret0 = Module._openDecoder(0, 0, 2)
  985. // // console.log('[][Core][WASM] decoder restart success')
  986. // // var ret1 = Module._openDecoder(1, decoder_type, LOG_LEVEL_WASM)
  987. // if (ret0 === 0) {
  988. // ret = Module._decodeData(0, data.frameCnt, cacheBuffer, content_size, resultBuffer)
  989. // } else {
  990. // printConsole.error('openDecoder failed with error ' + String(ret0) , '5001')
  991. // return 1
  992. // }
  993. // }
  994. } catch (e) {
  995. console.log('catch error ', e)
  996. if (this.errorCacheSize > 0) {
  997. downloadBlob(this.errorCacheBuffer.subarray(0, this.errorCacheSize), 'error.264', 'application/octet-stream')
  998. this.errorCacheSize = 0
  999. }
  1000. printConsole.error(e.message, '5002')
  1001. }
  1002. var width = Module.getValue(resultBuffer, 'i32')
  1003. var height = Module.getValue(resultBuffer + 4, 'i32')
  1004. var stride_y = Module.getValue(resultBuffer + 20, 'i32')
  1005. var stride_u = Module.getValue(resultBuffer + 24, 'i32')
  1006. var stride_v = Module.getValue(resultBuffer + 28, 'i32')
  1007. var addr_y = Module.getValue(resultBuffer + 8, 'i32')
  1008. var addr_u = Module.getValue(resultBuffer + 12, 'i32')
  1009. var addr_v = Module.getValue(resultBuffer + 16, 'i32')
  1010. var poc = Module.getValue(resultBuffer + 32, 'i32')
  1011. var pts = data.frameCnt
  1012. if (ret != 0) {
  1013. printConsole.log(
  1014. 'Decode Data error for video stream, ret value is ' +
  1015. String(ret) +
  1016. ', frame content size: ' +
  1017. String(content_size),
  1018. )
  1019. if (this.errorCacheSize > 0) {
  1020. downloadBlob(this.errorCacheBuffer.subarray(0, this.errorCacheSize), 'error.264', 'application/octet-stream')
  1021. this.errorCacheSize = 0
  1022. }
  1023. printConsole.log('current poc is ' + String(poc) + ', last poc is ' + String(lastPoc))
  1024. return
  1025. }
  1026. lastPoc = poc
  1027. this.receivedYUV++
  1028. let end_ts = Date.now()
  1029. fdt = end_ts - start_ts
  1030. if (fdt + self.decoder.getFrameInterval > 84) {
  1031. this.JankTimes++
  1032. }
  1033. if (fdt + self.decoder.getFrameInterval > 125) {
  1034. this.bigJankTimes++
  1035. }
  1036. self.decoder.dtpf = self.decoder.dtpf * 0.9 + fdt * 0.1
  1037. // if (fdt > self.decoder.dtmf) {
  1038. // self.decoder.dtmf = fdt
  1039. // }
  1040. self.decoder.decodeTimeCircular[self.decoder.dtcPtr] = fdt
  1041. self.decoder.dtcPtr = (self.decoder.dtcPtr + 1) % self.decoder.decodeTimeCircular.length
  1042. if (YUVArray.length <= 0) {
  1043. // printConsole.error('No buffer to save YUV after decoding, pts is ' + String(pts), '5002')
  1044. return
  1045. }
  1046. var first_available_buffer = YUVArray.shift()
  1047. var yuv_data = first_available_buffer.buffer
  1048. let pos = 0
  1049. for (let i = 0; i < height; i++) {
  1050. let src = addr_y + i * stride_y
  1051. let tmp = HEAPU8.subarray(src, src + width)
  1052. tmp = new Uint8Array(tmp)
  1053. yuv_data.set(tmp, pos)
  1054. pos += tmp.length
  1055. }
  1056. for (let i = 0; i < height / 2; i++) {
  1057. let src = addr_u + i * stride_u
  1058. let tmp = HEAPU8.subarray(src, src + width / 2)
  1059. tmp = new Uint8Array(tmp)
  1060. yuv_data.set(tmp, pos)
  1061. pos += tmp.length
  1062. let src2 = addr_v + i * stride_v
  1063. let tmp2 = HEAPU8.subarray(src2, src2 + width / 2)
  1064. tmp2 = new Uint8Array(tmp2)
  1065. yuv_data.set(tmp2, pos)
  1066. pos += tmp2.length
  1067. }
  1068. objData = {
  1069. t: MessageEvent.DecodeMessage,
  1070. data: yuv_data,
  1071. width: width,
  1072. height: height,
  1073. pts: data.frameCnt,
  1074. yuv_ts: Date.now(),
  1075. meta: data.meta,
  1076. metadata: data.metadata,
  1077. }
  1078. } else {
  1079. objData = {
  1080. t: MessageEvent.DecodeMessage,
  1081. data: null,
  1082. width: 0,
  1083. height: 0,
  1084. pts: data.frameCnt,
  1085. yuv_ts: Date.now(),
  1086. meta: data.meta,
  1087. metadata: data.metadata,
  1088. }
  1089. }
  1090. if (this.startEmit) {
  1091. if (objData.data != null) {
  1092. self.postMessage(objData, [objData.data.buffer])
  1093. send_out_buffer += 1
  1094. this.receivedEmit++
  1095. } else {
  1096. self.postMessage(objData)
  1097. this.receivedEmit++
  1098. }
  1099. } else {
  1100. if (objData.data != null) {
  1101. cachedFirstFrame = objData
  1102. }
  1103. }
  1104. // if (cacheBuffer != null) {
  1105. // Module._free(cacheBuffer)
  1106. // cacheBuffer = null
  1107. // }
  1108. // if (resultBuffer != null) {
  1109. // Module._free(resultBuffer)
  1110. // resultBuffer = null
  1111. // }
  1112. return
  1113. }
  1114. Decoder.prototype.receiveBuffer = function (data) {
  1115. framesReturned++
  1116. send_out_buffer -= 1
  1117. YUVArray.push({ status: 0, buffer: data.buffer })
  1118. }
  1119. Decoder.prototype.setPassiveJitter = function (len) {
  1120. this.passiveJitterLength = len
  1121. }
  1122. Decoder.prototype.uninitDecoder = function () {
  1123. printConsole.log('Going to uninit decoder.')
  1124. }
  1125. Decoder.prototype.StartRecord = function () {
  1126. printConsole.log('Start Record')
  1127. this.startRecord = true
  1128. }
  1129. Decoder.prototype.SaveRecord = function () {
  1130. printConsole.log('Save Record')
  1131. this.saveRecord = true
  1132. }
  1133. Decoder.prototype.ReceivePanorama = function (data) {
  1134. self.decoder.resetDecoder()
  1135. self.decoder.decodePanorama(data)
  1136. }
  1137. Decoder.prototype.LoadWASM = function (url) {
  1138. printConsole.log('Load WASM from ' + String(url))
  1139. try {
  1140. self.importScripts(url)
  1141. } catch (e) {
  1142. console.log('catch error ', e)
  1143. printConsole.error(e.message, '5003')
  1144. }
  1145. }
  1146. // self.incoming_pkt_queue = new array()
  1147. function getRandomInt(max) {
  1148. return Math.floor(Math.random() * max)
  1149. }
  1150. // console.log(getRandomInt(30));
  1151. self.decoder = new Decoder()
  1152. netArray = []
  1153. var gTmpIdx = 0
  1154. var gLossCnt = 0
  1155. self.onmessage = function (evt) {
  1156. switch (evt.data.t) {
  1157. case 1: // Init Message
  1158. self.decoder.initAll(evt.data.config)
  1159. break
  1160. case 0: // Decode Message
  1161. // console.log('[][Core][WASM],------> ', evt.data)
  1162. gTmpIdx += 1
  1163. randLen = 16
  1164. // randLen = getRandomInt(30)
  1165. // eslint-disable-next-line no-constant-condition
  1166. if (gTmpIdx > 100 && false) {
  1167. var test_jitter_buffer = true
  1168. if (test_jitter_buffer == true) {
  1169. if (netArray.length % 5 == 4) {
  1170. // netArray.insert(netArray.length -1, evt.data)
  1171. netArray.splice(netArray.length - 1, 0, evt.data)
  1172. } else {
  1173. netArray.push(evt.data)
  1174. }
  1175. if (netArray.length > randLen) {
  1176. // 1. jitter
  1177. while (netArray.length > 0) {
  1178. // console.log("[xmedia] array len: %s", netArray.length)
  1179. gLossCnt += 1
  1180. var pkt = netArray.shift()
  1181. // lose pkt
  1182. var dropInterval = 50
  1183. var dropContinousPkts = 3
  1184. if (gLossCnt % dropInterval < dropContinousPkts) {
  1185. if (gLossCnt == dropInterval + dropContinousPkts - 1) {
  1186. gLossCnt = 0
  1187. }
  1188. } else {
  1189. self.decoder.receiveFrame(pkt)
  1190. }
  1191. }
  1192. // // 2. disorder
  1193. // if (incoming_pkt_queue.length % 3) {
  1194. // in[0]
  1195. // in[2]
  1196. // in[1]
  1197. // }
  1198. }
  1199. } else {
  1200. self.decoder.receiveFrame(evt.data)
  1201. }
  1202. } else {
  1203. self.decoder.receiveFrame(evt.data)
  1204. }
  1205. break
  1206. case 2: // Receive used buffer
  1207. self.decoder.receiveBuffer(evt.data)
  1208. break
  1209. case 3: // Unint Message
  1210. self.decoder.uninitDecoder()
  1211. break
  1212. case 4: // Reset status
  1213. self.decoder.resetDecoder()
  1214. break
  1215. case 5: // Start emit
  1216. self.decoder.startEmiter()
  1217. break
  1218. case 6: // Start Record
  1219. self.decoder.StartRecord()
  1220. break
  1221. case 7: // Save Record
  1222. self.decoder.SaveRecord()
  1223. break
  1224. case 8: // Panorama Decode Message
  1225. self.decoder.ReceivePanorama(evt.data)
  1226. break
  1227. case 9: // Select WASM Version
  1228. self.decoder.setPassiveJitter(evt.data.jitterLength)
  1229. self.decoder.LoadWASM(evt.data.url)
  1230. break
  1231. case 100: // change decoder worker status
  1232. self.decoder.changeLogSwitch(evt.data.status)
  1233. break
  1234. }
  1235. }
  1236. }