@havue/solutions 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bc-connect/package.json +1 -1
- package/dist/solutions.full.js +213 -73
- package/dist/solutions.full.min.js +4 -4
- package/dist/solutions.full.min.js.map +1 -1
- package/dist/types/ws-video-manager/src/render/index.d.ts +16 -4
- package/dist/types/ws-video-manager/src/render/mp4box.d.ts +2 -0
- package/package.json +4 -4
- package/ws-video-manager/dist/types/src/render/index.d.ts +16 -4
- package/ws-video-manager/dist/types/src/render/mp4box.d.ts +2 -0
- package/ws-video-manager/dist/ws-video-manager.mjs +213 -73
- package/ws-video-manager/dist/ws-video-manager.umd.js +213 -73
- package/ws-video-manager/package.json +1 -1
- package/ws-video-manager/src/render/index.ts +201 -101
- package/ws-video-manager/src/render/mp4box.ts +58 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import MP4Box from 'mp4box'
|
|
1
|
+
import MP4Box from './mp4box'
|
|
2
2
|
import { EventBus } from '@havue/shared'
|
|
3
3
|
|
|
4
4
|
// #region typedefine
|
|
@@ -54,24 +54,34 @@ export type RenderEvents = {
|
|
|
54
54
|
export class Render extends EventBus<RenderEvents> {
|
|
55
55
|
/** video元素 */
|
|
56
56
|
private _videoEl: HTMLVideoElement | undefined = undefined
|
|
57
|
-
/** pixi.js 实例 */
|
|
58
|
-
// private _pixiApp: Application | null = null
|
|
59
57
|
/** mp4box 实例 */
|
|
60
58
|
private _mp4box: MP4Box = MP4Box.createFile()
|
|
61
|
-
/**
|
|
62
|
-
private
|
|
59
|
+
/** mp4box onFragment获取的视频数据buffer数组 */
|
|
60
|
+
private _audioBufsQueue: ArrayBuffer[] = []
|
|
61
|
+
private _videoBufsQueue: ArrayBuffer[] = []
|
|
63
62
|
/** MediaSource 实例 */
|
|
64
63
|
private _mediaSource: MediaSource | undefined
|
|
65
64
|
/** SourceBuffer 实例 */
|
|
66
|
-
private
|
|
65
|
+
private _audioSourceBuffer: SourceBuffer | undefined
|
|
66
|
+
private _videoSourceBuffer: SourceBuffer | undefined
|
|
67
|
+
|
|
68
|
+
private _audioTrackId: number | undefined
|
|
69
|
+
private _videoTrackId: number | undefined
|
|
67
70
|
/** 用于MediaSource的mimeType */
|
|
68
71
|
private _mimeType: string = ''
|
|
72
|
+
private _audioMimeType: string = ''
|
|
73
|
+
private _videoMimeType: string = ''
|
|
69
74
|
/** 是否暂停播放 */
|
|
70
75
|
private _paused: boolean = false
|
|
71
76
|
private _options: RenderConstructorOptionType
|
|
72
77
|
|
|
73
78
|
private _cacheAnimationID: number | undefined = undefined
|
|
74
79
|
|
|
80
|
+
/** fmp4初始化片段是否已经添加 */
|
|
81
|
+
private _isAudioInitSegmentAdded: boolean = false
|
|
82
|
+
private _isVideoInitSegmentAdded: boolean = false
|
|
83
|
+
private _offset: number = 0
|
|
84
|
+
|
|
75
85
|
// 调试代码
|
|
76
86
|
// private divID = ''
|
|
77
87
|
|
|
@@ -81,6 +91,7 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
81
91
|
? Object.assign({}, WS_VIDEO_RENDER_DEFAULT_OPTIONS, options)
|
|
82
92
|
: WS_VIDEO_RENDER_DEFAULT_OPTIONS
|
|
83
93
|
this._mp4box.onReady = this._onMp4boxReady.bind(this)
|
|
94
|
+
this._mp4box.onSegment = this._onSegment.bind(this)
|
|
84
95
|
this._setupVideo()
|
|
85
96
|
}
|
|
86
97
|
|
|
@@ -126,30 +137,12 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
126
137
|
if (this._paused) {
|
|
127
138
|
return
|
|
128
139
|
}
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this._mp4box.appendBuffer(
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (this._sourceBuffer && !this._videoEl?.paused && this._bufsQueue.length > 2) {
|
|
137
|
-
const len = this._bufsQueue.length
|
|
138
|
-
const maxTotal = this._options.maxCacheBufByte
|
|
139
|
-
let lastIndex = len - 1
|
|
140
|
-
let total = 0
|
|
141
|
-
for (let i = len - 1; i > 0; i--) {
|
|
142
|
-
total += this._bufsQueue[i].byteLength
|
|
143
|
-
lastIndex = i
|
|
144
|
-
if (total >= maxTotal) {
|
|
145
|
-
this._bufsQueue = this._bufsQueue.slice(lastIndex)
|
|
146
|
-
break
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
this._cacheAnimationID && cancelAnimationFrame(this._cacheAnimationID)
|
|
151
|
-
this._cacheAnimationID = undefined
|
|
152
|
-
this._cache()
|
|
140
|
+
bufs.forEach((b) => {
|
|
141
|
+
b.fileStart = this._offset
|
|
142
|
+
this._offset += b.byteLength
|
|
143
|
+
this._mp4box.appendBuffer(b)
|
|
144
|
+
})
|
|
145
|
+
return
|
|
153
146
|
}
|
|
154
147
|
|
|
155
148
|
/**
|
|
@@ -158,7 +151,6 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
158
151
|
*/
|
|
159
152
|
private _onMp4boxReady(info: any) {
|
|
160
153
|
console.log('onMp4boxReady', info)
|
|
161
|
-
this._mp4box.flush()
|
|
162
154
|
if (!info.isFragmented) {
|
|
163
155
|
console.error('not fragmented mp4')
|
|
164
156
|
return
|
|
@@ -171,12 +163,70 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
171
163
|
width,
|
|
172
164
|
height
|
|
173
165
|
})
|
|
166
|
+
const audioTrack = info.audioTracks[0]
|
|
167
|
+
const videoTrack = info.videoTracks[0]
|
|
168
|
+
|
|
169
|
+
if (audioTrack) {
|
|
170
|
+
this._audioMimeType = `audio/mp4; codecs="${audioTrack.codec}"`
|
|
171
|
+
this._audioTrackId = audioTrack.id
|
|
172
|
+
this._mp4box.setSegmentOptions(audioTrack.id, undefined, {
|
|
173
|
+
nbSamples: 100
|
|
174
|
+
})
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (videoTrack) {
|
|
178
|
+
this._videoMimeType = `video/mp4; codecs="${videoTrack.codec}"`
|
|
179
|
+
this._videoTrackId = videoTrack.id
|
|
180
|
+
this._mp4box.setSegmentOptions(videoTrack.id, undefined, {
|
|
181
|
+
nbSamples: 100
|
|
182
|
+
})
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const initSegments = this._mp4box.initializeSegmentation()
|
|
186
|
+
for (const seg of initSegments) {
|
|
187
|
+
if (audioTrack && seg.id === audioTrack.id) {
|
|
188
|
+
this._audioBufsQueue.push(seg.buffer)
|
|
189
|
+
} else if (videoTrack && seg.id === videoTrack.id) {
|
|
190
|
+
this._videoBufsQueue.push(seg.buffer)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
174
193
|
} catch (error) {
|
|
175
194
|
console.error(error)
|
|
176
195
|
}
|
|
177
|
-
// this._setupVideo()
|
|
178
|
-
// this.setupPixi()
|
|
179
196
|
this._setupMSE()
|
|
197
|
+
this._mp4box.start()
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
private _onSegment(id: number, __: any, buffer: ArrayBuffer, sampleNumber: number) {
|
|
201
|
+
const isAudio = id === this._audioTrackId
|
|
202
|
+
const isVideo = id === this._videoTrackId
|
|
203
|
+
const bufQueue = isAudio ? this._audioBufsQueue : isVideo ? this._videoBufsQueue : null
|
|
204
|
+
if (!bufQueue) {
|
|
205
|
+
return
|
|
206
|
+
}
|
|
207
|
+
const sourceBuffer = isVideo ? this._videoSourceBuffer : this._audioSourceBuffer
|
|
208
|
+
bufQueue.push(buffer)
|
|
209
|
+
// 清除已使用的samples
|
|
210
|
+
this._mp4box.releaseUsedSamples(id, sampleNumber)
|
|
211
|
+
this._mp4box.removeUsedSamples(id)
|
|
212
|
+
const segmentAdded = isAudio ? this._isAudioInitSegmentAdded : this._isVideoInitSegmentAdded
|
|
213
|
+
if (segmentAdded && sourceBuffer && !this._videoEl?.paused && bufQueue.length > 2) {
|
|
214
|
+
const len = bufQueue.length
|
|
215
|
+
const maxTotal = this._options.maxCacheBufByte
|
|
216
|
+
let lastIndex = len - 1
|
|
217
|
+
let total = 0
|
|
218
|
+
for (let i = len - 1; i > 0; i--) {
|
|
219
|
+
total += bufQueue[i].byteLength
|
|
220
|
+
lastIndex = i
|
|
221
|
+
if (total >= maxTotal) {
|
|
222
|
+
bufQueue.splice(0, lastIndex)
|
|
223
|
+
break
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
this._cacheAnimationID && cancelAnimationFrame(this._cacheAnimationID)
|
|
228
|
+
this._cacheAnimationID = undefined
|
|
229
|
+
this._cache(isVideo)
|
|
180
230
|
}
|
|
181
231
|
|
|
182
232
|
/**
|
|
@@ -292,55 +342,75 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
292
342
|
this._videoEl.src = URL.createObjectURL(this._mediaSource)
|
|
293
343
|
|
|
294
344
|
this._mediaSource.addEventListener('sourceopen', () => {
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
if (
|
|
299
|
-
!this._videoEl ||
|
|
300
|
-
!sourceBuffer ||
|
|
301
|
-
this._mediaSource?.readyState !== 'open' ||
|
|
302
|
-
![...this._mediaSource.sourceBuffers].includes(sourceBuffer)
|
|
303
|
-
) {
|
|
304
|
-
return
|
|
305
|
-
}
|
|
306
|
-
const currentTime = this._videoEl.currentTime
|
|
307
|
-
// 调试代码
|
|
308
|
-
// const div = document.getElementById(this.divID)
|
|
309
|
-
// let innerHTML = `len:${sourceBuffer.buffered.length}`
|
|
310
|
-
|
|
311
|
-
if (sourceBuffer.buffered.length > 0) {
|
|
312
|
-
let bufferedLen = sourceBuffer.buffered.length
|
|
313
|
-
/** 是否需要删除sourceBuffer中的buffer段 */
|
|
314
|
-
const needDelBuf = bufferedLen > 1
|
|
315
|
-
/**
|
|
316
|
-
* sourceBuffer中有多个buffered,时间不连续
|
|
317
|
-
* 导致视频播放到其中一个buffer最后就暂停了
|
|
318
|
-
* 如果出现多个buffered,删除之前有的buffer
|
|
319
|
-
* 使用最新的视频buffer进行播放
|
|
320
|
-
*/
|
|
321
|
-
if (needDelBuf && currentTime) {
|
|
322
|
-
const lastIndex = bufferedLen - 1
|
|
323
|
-
if (currentTime < sourceBuffer.buffered.start(lastIndex)) {
|
|
324
|
-
this._videoEl.currentTime = sourceBuffer.buffered.start(lastIndex)
|
|
325
|
-
}
|
|
345
|
+
if (!this._mediaSource) {
|
|
346
|
+
return
|
|
347
|
+
}
|
|
326
348
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
349
|
+
// 音频轨
|
|
350
|
+
if (this._audioMimeType) {
|
|
351
|
+
this._audioSourceBuffer = this._mediaSource.addSourceBuffer(this._audioMimeType)
|
|
352
|
+
this._audioSourceBuffer.mode = 'sequence'
|
|
353
|
+
this._setupSourceBuffer(this._audioSourceBuffer, false)
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// 视频轨
|
|
357
|
+
if (this._videoMimeType) {
|
|
358
|
+
this._videoSourceBuffer = this._mediaSource.addSourceBuffer(this._videoMimeType)
|
|
359
|
+
this._videoSourceBuffer.mode = 'sequence'
|
|
360
|
+
this._setupSourceBuffer(this._videoSourceBuffer, true)
|
|
361
|
+
}
|
|
362
|
+
})
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private _setupSourceBuffer(sourceBuffer: SourceBuffer, isVideo: boolean = false) {
|
|
366
|
+
sourceBuffer.onupdateend = () => {
|
|
367
|
+
if (
|
|
368
|
+
!this._videoEl ||
|
|
369
|
+
!sourceBuffer ||
|
|
370
|
+
this._mediaSource?.readyState !== 'open' ||
|
|
371
|
+
![...this._mediaSource.sourceBuffers].includes(sourceBuffer)
|
|
372
|
+
) {
|
|
373
|
+
return
|
|
374
|
+
}
|
|
375
|
+
const currentTime = this._videoEl.currentTime
|
|
376
|
+
// 调试代码
|
|
377
|
+
// const div = document.getElementById(this.divID)
|
|
378
|
+
// let innerHTML = `len:${sourceBuffer.buffered.length}`
|
|
379
|
+
|
|
380
|
+
if (sourceBuffer.buffered.length > 0) {
|
|
381
|
+
let bufferedLen = sourceBuffer.buffered.length
|
|
382
|
+
/** 是否需要删除sourceBuffer中的buffer段 */
|
|
383
|
+
const needDelBuf = bufferedLen > 1
|
|
384
|
+
/**
|
|
385
|
+
* sourceBuffer中有多个buffered,时间不连续
|
|
386
|
+
* 导致视频播放到其中一个buffer最后就暂停了
|
|
387
|
+
* 如果出现多个buffered,删除之前有的buffer
|
|
388
|
+
* 使用最新的视频buffer进行播放
|
|
389
|
+
*/
|
|
390
|
+
if (needDelBuf && currentTime) {
|
|
391
|
+
const lastIndex = bufferedLen - 1
|
|
392
|
+
if (currentTime < sourceBuffer.buffered.start(lastIndex)) {
|
|
393
|
+
this._videoEl.currentTime = sourceBuffer.buffered.start(lastIndex)
|
|
331
394
|
}
|
|
332
395
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
396
|
+
const delBufEnd = sourceBuffer.buffered.end(lastIndex - 1)
|
|
397
|
+
if (!sourceBuffer!.updating && currentTime > delBufEnd) {
|
|
398
|
+
sourceBuffer?.remove(0, delBufEnd)
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// 调试代码
|
|
403
|
+
// innerHTML += ` - start:${sourceBuffer.buffered.start(
|
|
404
|
+
// sourceBuffer.buffered.length - 1
|
|
405
|
+
// )} - end:${sourceBuffer.buffered.end(sourceBuffer.buffered.length - 1)} <br/>`
|
|
406
|
+
// innerHTML += ` - currentTime: ${currentTime}`
|
|
407
|
+
// div && (div.innerHTML = innerHTML)
|
|
339
408
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
409
|
+
bufferedLen = sourceBuffer.buffered.length
|
|
410
|
+
const start = sourceBuffer.buffered.start(bufferedLen - 1)
|
|
411
|
+
const end = sourceBuffer.buffered.end(bufferedLen - 1)
|
|
343
412
|
|
|
413
|
+
if (isVideo) {
|
|
344
414
|
// 设置开始时间
|
|
345
415
|
if (!currentTime && start) {
|
|
346
416
|
this._videoEl.currentTime = start
|
|
@@ -354,43 +424,48 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
354
424
|
this._videoEl.currentTime = end - 0.1
|
|
355
425
|
}
|
|
356
426
|
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// 移除当前时间之前的buffer
|
|
430
|
+
if (!sourceBuffer!.updating && currentTime - start > this._options.maxCache) {
|
|
431
|
+
sourceBuffer?.remove(0, currentTime - this._options.maxCache / 2)
|
|
361
432
|
}
|
|
362
433
|
}
|
|
363
|
-
}
|
|
434
|
+
}
|
|
364
435
|
}
|
|
365
436
|
|
|
366
437
|
/**
|
|
367
438
|
* 将_bufsQueue中的数据添加到SourceBuffer中
|
|
368
439
|
* @returns
|
|
369
440
|
*/
|
|
370
|
-
private _cache() {
|
|
441
|
+
private _cache(isVideo: boolean = false) {
|
|
371
442
|
if (!this._videoEl) {
|
|
372
443
|
return
|
|
373
444
|
}
|
|
445
|
+
const queue = isVideo ? this._videoBufsQueue : this._audioBufsQueue
|
|
446
|
+
const sourceBuffer = isVideo ? this._videoSourceBuffer : this._audioSourceBuffer
|
|
374
447
|
if (
|
|
375
448
|
!this._mediaSource ||
|
|
376
|
-
!
|
|
377
|
-
|
|
378
|
-
!
|
|
449
|
+
!sourceBuffer ||
|
|
450
|
+
sourceBuffer.updating ||
|
|
451
|
+
!queue.length ||
|
|
379
452
|
this._mediaSource.readyState !== 'open'
|
|
380
453
|
) {
|
|
381
|
-
this._cacheAnimationID === undefined &&
|
|
454
|
+
this._cacheAnimationID === undefined &&
|
|
455
|
+
(this._cacheAnimationID = requestAnimationFrame(() => this._cache(isVideo)))
|
|
382
456
|
return
|
|
383
457
|
}
|
|
384
458
|
if (this._videoEl.error) {
|
|
385
459
|
this._setupMSE()
|
|
386
460
|
return (
|
|
387
|
-
this._cacheAnimationID === undefined &&
|
|
461
|
+
this._cacheAnimationID === undefined &&
|
|
462
|
+
(this._cacheAnimationID = requestAnimationFrame(() => this._cache(isVideo)))
|
|
388
463
|
)
|
|
389
464
|
}
|
|
390
465
|
this._cacheAnimationID = undefined
|
|
391
466
|
let frame: Uint8Array
|
|
392
|
-
if (
|
|
393
|
-
const freeBuffer =
|
|
467
|
+
if (queue.length > 1) {
|
|
468
|
+
const freeBuffer = queue.splice(0, queue.length)
|
|
394
469
|
const length = freeBuffer.map((e) => e.byteLength).reduce((a, b) => a + b, 0)
|
|
395
470
|
const buffer = new Uint8Array(length)
|
|
396
471
|
let offset = 0
|
|
@@ -401,11 +476,16 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
401
476
|
}
|
|
402
477
|
frame = buffer
|
|
403
478
|
} else {
|
|
404
|
-
frame = new Uint8Array(
|
|
479
|
+
frame = new Uint8Array(queue.shift() || [])
|
|
405
480
|
}
|
|
406
481
|
|
|
407
482
|
if (frame) {
|
|
408
|
-
|
|
483
|
+
if (isVideo) {
|
|
484
|
+
!this._isVideoInitSegmentAdded && (this._isVideoInitSegmentAdded = true)
|
|
485
|
+
} else {
|
|
486
|
+
!this._isAudioInitSegmentAdded && (this._isAudioInitSegmentAdded = true)
|
|
487
|
+
}
|
|
488
|
+
sourceBuffer.appendBuffer(frame)
|
|
409
489
|
}
|
|
410
490
|
}
|
|
411
491
|
|
|
@@ -421,13 +501,14 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
421
501
|
|
|
422
502
|
/** 重置解析的视频mime type */
|
|
423
503
|
public resetMimeType() {
|
|
504
|
+
this.destroyMp4box()
|
|
424
505
|
this.destroyMediaSource()
|
|
425
506
|
if (this._videoEl) {
|
|
426
507
|
this._videoEl.src = ''
|
|
427
508
|
}
|
|
428
509
|
this._mp4box = MP4Box.createFile()
|
|
429
510
|
this._mp4box.onReady = this._onMp4boxReady.bind(this)
|
|
430
|
-
this.
|
|
511
|
+
this._mp4box.onSegment = this._onSegment.bind(this)
|
|
431
512
|
}
|
|
432
513
|
|
|
433
514
|
private destroyMediaSource() {
|
|
@@ -437,23 +518,44 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
437
518
|
this._videoEl.src = ''
|
|
438
519
|
}
|
|
439
520
|
if (this._mediaSource.readyState === 'open') {
|
|
440
|
-
if (this.
|
|
441
|
-
this.
|
|
442
|
-
this._mediaSource.removeSourceBuffer(this.
|
|
521
|
+
if (this._audioSourceBuffer) {
|
|
522
|
+
this._audioSourceBuffer.abort()
|
|
523
|
+
this._mediaSource.removeSourceBuffer(this._audioSourceBuffer)
|
|
524
|
+
}
|
|
525
|
+
if (this._videoSourceBuffer) {
|
|
526
|
+
this._videoSourceBuffer.abort()
|
|
527
|
+
this._mediaSource.removeSourceBuffer(this._videoSourceBuffer)
|
|
443
528
|
}
|
|
444
529
|
this._mediaSource.endOfStream()
|
|
445
530
|
}
|
|
446
531
|
|
|
447
532
|
this._mediaSource = undefined
|
|
448
|
-
this.
|
|
533
|
+
this._audioSourceBuffer = undefined
|
|
534
|
+
this._videoSourceBuffer = undefined
|
|
449
535
|
}
|
|
450
536
|
}
|
|
451
537
|
|
|
538
|
+
public destroyMp4box() {
|
|
539
|
+
this._audioTrackId = undefined
|
|
540
|
+
this._videoTrackId = undefined
|
|
541
|
+
this._mimeType = ''
|
|
542
|
+
this._audioMimeType = ''
|
|
543
|
+
this._videoMimeType = ''
|
|
544
|
+
this._isAudioInitSegmentAdded = false
|
|
545
|
+
this._isVideoInitSegmentAdded = false
|
|
546
|
+
this._audioBufsQueue.length = 0
|
|
547
|
+
this._videoBufsQueue.length = 0
|
|
548
|
+
this._offset = 0
|
|
549
|
+
this._mp4box.stop()
|
|
550
|
+
this._mp4box.flush()
|
|
551
|
+
this._mp4box.destroy()
|
|
552
|
+
this._mp4box = null
|
|
553
|
+
}
|
|
554
|
+
|
|
452
555
|
/**
|
|
453
556
|
* 销毁
|
|
454
557
|
*/
|
|
455
558
|
public destroy() {
|
|
456
|
-
this._bufsQueue = []
|
|
457
559
|
if (this._videoEl) {
|
|
458
560
|
this._videoEl.pause()
|
|
459
561
|
this._videoEl.currentTime = 0
|
|
@@ -465,11 +567,9 @@ export class Render extends EventBus<RenderEvents> {
|
|
|
465
567
|
this._videoEl = undefined
|
|
466
568
|
}
|
|
467
569
|
|
|
468
|
-
this._mimeType = ''
|
|
469
|
-
|
|
470
570
|
this._cacheAnimationID && cancelAnimationFrame(this._cacheAnimationID)
|
|
471
571
|
this._cacheAnimationID = undefined
|
|
472
|
-
|
|
572
|
+
this.destroyMp4box()
|
|
473
573
|
this.destroyMediaSource()
|
|
474
574
|
}
|
|
475
575
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import MP4Box from 'mp4box'
|
|
2
|
+
|
|
3
|
+
function ExtendMp4box() {
|
|
4
|
+
const MP4BoxFile = MP4Box.createFile().constructor
|
|
5
|
+
// 清空samples
|
|
6
|
+
MP4BoxFile.prototype.removeUsedSamples = function (id: number) {
|
|
7
|
+
const track = this.getTrackById(id)
|
|
8
|
+
const samples = track.samples
|
|
9
|
+
const lastSample = samples[samples.length - 1]
|
|
10
|
+
lastSample.data = null
|
|
11
|
+
lastSample.description = null
|
|
12
|
+
lastSample.alreadyRead = 0
|
|
13
|
+
track.samples = []
|
|
14
|
+
track.samples.push(lastSample)
|
|
15
|
+
track.nextSample = track.samples.length
|
|
16
|
+
this.boxes = []
|
|
17
|
+
this.mdats = []
|
|
18
|
+
this.moofs = []
|
|
19
|
+
this.lastMoofIndex = 0
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
MP4BoxFile.prototype.destroy = function () {
|
|
23
|
+
if (this.stream) {
|
|
24
|
+
this.stream.buffers = []
|
|
25
|
+
this.stream.bufferIndex = -1
|
|
26
|
+
this.stream = null
|
|
27
|
+
}
|
|
28
|
+
this.boxes = []
|
|
29
|
+
this.mdats = []
|
|
30
|
+
this.moofs = []
|
|
31
|
+
this.isProgressive = false
|
|
32
|
+
this.moovStartFound = false
|
|
33
|
+
this.onMoovStart = null
|
|
34
|
+
this.moovStartSent = false
|
|
35
|
+
this.onReady = null
|
|
36
|
+
this.readySent = false
|
|
37
|
+
this.onSegment = null
|
|
38
|
+
this.onSamples = null
|
|
39
|
+
this.onError = null
|
|
40
|
+
this.sampleListBuilt = false
|
|
41
|
+
this.fragmentedTracks = []
|
|
42
|
+
this.extractedTracks = []
|
|
43
|
+
this.isFragmentationInitialized = false
|
|
44
|
+
this.sampleProcessingStarted = false
|
|
45
|
+
this.nextMoofNumber = 0
|
|
46
|
+
this.itemListBuilt = false
|
|
47
|
+
this.onSidx = null
|
|
48
|
+
this.sidxSent = false
|
|
49
|
+
this.moov = null
|
|
50
|
+
this.ftyp = null
|
|
51
|
+
this.items = []
|
|
52
|
+
this.entity_groups = []
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
ExtendMp4box()
|
|
57
|
+
|
|
58
|
+
export default MP4Box
|