xgplayer-mp4 1.2.4 → 2.0.2
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/browser/index.js +1 -1
- package/browser/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/constants.js +14 -0
- package/src/fmp4/buffer.js +6 -0
- package/src/fmp4/mp4.js +181 -84
- package/src/gap_jump.js +151 -0
- package/src/index.js +550 -315
- package/src/media/mse.js +77 -22
- package/src/media/task.js +68 -17
- package/src/mp4.js +284 -268
- package/src/parse/box/MP4DecConfigDescrTag.js +3 -0
- package/src/parse/box/MP4DecSpecificDescrTag.js +4 -0
- package/src/parse/box/avcC.js +4 -1
- package/src/parse/box/elst.js +0 -13
- package/src/parse/box/esds.js +9 -4
- package/src/parse/box/frma.js +10 -0
- package/src/parse/box/golomb.js +88 -0
- package/src/parse/box/hvc1.js +30 -0
- package/src/parse/box/hvcC.js +55 -0
- package/src/parse/box/pasp.js +2 -3
- package/src/parse/box/schm.js +18 -0
- package/src/parse/box/sps.js +286 -0
- package/src/parse/box/stsz.js +6 -1
- package/src/parse/box/tfhd.js +43 -0
- package/src/parse/box.js +5 -1
- package/src/parse/stream.js +4 -0
- package/src/util/getHeaders.js +18 -0
- package/src/util/index.js +138 -20
- package/src/util/intervalTimer.js +36 -0
- package/src/util/isSupport.js +20 -0
- package/src/util/proxyPromise.js +27 -0
- package/src/util/timer.js +46 -0
- package/src/util/xhr.js +46 -0
- package/version.json +1 -1
- package/webpack.config.js +45 -39
- package/src/util/download.js +0 -13
- package/src/write/box/MP4DecConfigDescrTag.js +0 -21
- package/src/write/box/MP4DecSpecificDescrTag.js +0 -19
- package/src/write/box/MP4ESDescrTag.js +0 -19
- package/src/write/box/SLConfigDescriptor.js +0 -16
- package/src/write/box/avc1.js +0 -33
- package/src/write/box/avcC.js +0 -32
- package/src/write/box/btrt.js +0 -14
- package/src/write/box/co64.js +0 -17
- package/src/write/box/ctts.js +0 -19
- package/src/write/box/dref.js +0 -25
- package/src/write/box/elst.js +0 -27
- package/src/write/box/esds.js +0 -11
- package/src/write/box/ftyp.js +0 -17
- package/src/write/box/hdlr.js +0 -15
- package/src/write/box/iods.js +0 -14
- package/src/write/box/mdat.js +0 -5
- package/src/write/box/mdhd.js +0 -27
- package/src/write/box/mehd.js +0 -12
- package/src/write/box/mfhd.js +0 -12
- package/src/write/box/mfro.js +0 -14
- package/src/write/box/mp4a.js +0 -26
- package/src/write/box/mvhd.js +0 -34
- package/src/write/box/pasp.js +0 -10
- package/src/write/box/smhd.js +0 -17
- package/src/write/box/stco.js +0 -17
- package/src/write/box/stsc.js +0 -19
- package/src/write/box/stsd.js +0 -23
- package/src/write/box/stss.js +0 -17
- package/src/write/box/stsz.js +0 -18
- package/src/write/box/stts.js +0 -18
- package/src/write/box/tfdt.js +0 -16
- package/src/write/box/tfhd.js +0 -18
- package/src/write/box/tfra.js +0 -29
- package/src/write/box/tkhd.js +0 -44
- package/src/write/box/trex.js +0 -16
- package/src/write/box/trun.js +0 -40
- package/src/write/box/udta.js +0 -5
- package/src/write/box/url.js +0 -16
- package/src/write/box/vmhd.js +0 -19
- package/src/write/box/wide.js +0 -12
- package/src/write/box.js +0 -37
- package/src/write/buffer.js +0 -12
- package/src/write/index.js +0 -33
- package/src/write/stream.js +0 -99
- package/webpack.config.test.js +0 -8
package/src/media/mse.js
CHANGED
|
@@ -2,31 +2,53 @@ import EventEmitter from 'event-emitter'
|
|
|
2
2
|
import Errors from '../error'
|
|
3
3
|
|
|
4
4
|
class MSE {
|
|
5
|
-
constructor (codecs = 'video/mp4; codecs="avc1.64001E, mp4a.40.5"') {
|
|
6
|
-
let self = this
|
|
5
|
+
constructor (codecs = 'video/mp4; codecs="avc1.64001E, mp4a.40.5"', mediaType) {
|
|
7
6
|
EventEmitter(this)
|
|
8
7
|
this.codecs = codecs
|
|
9
|
-
this.mediaSource = new window.MediaSource()
|
|
8
|
+
this.mediaSource = new window.MediaSource(mediaType)
|
|
10
9
|
this.url = window.URL.createObjectURL(this.mediaSource)
|
|
11
10
|
this.queue = []
|
|
12
11
|
this.updating = false
|
|
13
|
-
this.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
12
|
+
this._hasDestroyed = false;
|
|
13
|
+
this._hasEndOfStream = false;
|
|
14
|
+
this._hasEndOfStreamSuccess = false;
|
|
15
|
+
this._onSourceOpen = this._onSourceOpen.bind(this);
|
|
16
|
+
this._onMediaSourceClose = this._onMediaSourceClose.bind(this);
|
|
17
|
+
this._onSourceBufferError = this._onSourceBufferError.bind(this);
|
|
18
|
+
this._onSourceBufferUpdateEnd = this._onSourceBufferUpdateEnd.bind(this);
|
|
19
|
+
this.mediaSource.addEventListener('sourceopen', this._onSourceOpen);
|
|
20
|
+
this.mediaSource.addEventListener('sourceclose', this._onMediaSourceClose);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_onSourceOpen(){
|
|
24
|
+
let self = this;
|
|
25
|
+
self.sourceBuffer = self.mediaSource.addSourceBuffer(self.codecs);
|
|
26
|
+
self.sourceBuffer.addEventListener('error', this._onSourceBufferError);
|
|
27
|
+
self.sourceBuffer.addEventListener('updateend', this._onSourceBufferUpdateEnd);
|
|
28
|
+
self.emit('sourceopen')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
_onSourceBufferError(e){
|
|
32
|
+
this.emit('error', new Errors('mse', '', {line: 16, handle: '[MSE] constructor sourceopen', msg: e.message}))
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_onSourceBufferUpdateEnd(){
|
|
36
|
+
let self = this;
|
|
37
|
+
self.emit('updateend');
|
|
38
|
+
if(this._hasEndOfStream && !this._hasEndOfStreamSuccess){
|
|
39
|
+
this._endOfStream();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
let buffer = self.queue.shift()
|
|
43
|
+
if (buffer && self.sourceBuffer && self.sourceBuffer.updating === false && self.state === 'open') {
|
|
44
|
+
self.sourceBuffer.appendBuffer(buffer)
|
|
45
|
+
} else if(buffer) {
|
|
46
|
+
self.queue.unshift(buffer);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
_onMediaSourceClose(){
|
|
51
|
+
this.emit('sourceclose')
|
|
30
52
|
}
|
|
31
53
|
|
|
32
54
|
get state () {
|
|
@@ -42,6 +64,8 @@ class MSE {
|
|
|
42
64
|
}
|
|
43
65
|
|
|
44
66
|
appendBuffer (buffer) {
|
|
67
|
+
if(!buffer) return;
|
|
68
|
+
|
|
45
69
|
let sourceBuffer = this.sourceBuffer
|
|
46
70
|
if (sourceBuffer && !sourceBuffer.updating && this.state === 'open') {
|
|
47
71
|
sourceBuffer.appendBuffer(buffer)
|
|
@@ -53,11 +77,26 @@ class MSE {
|
|
|
53
77
|
}
|
|
54
78
|
|
|
55
79
|
removeBuffer (start, end) {
|
|
56
|
-
this.sourceBuffer
|
|
80
|
+
let sourceBuffer = this.sourceBuffer
|
|
81
|
+
if (sourceBuffer && sourceBuffer.updating === false && this.state === 'open') {
|
|
82
|
+
sourceBuffer.remove(start, end)
|
|
83
|
+
}
|
|
57
84
|
}
|
|
58
85
|
|
|
59
86
|
endOfStream () {
|
|
60
|
-
|
|
87
|
+
this._hasEndOfStream = true;
|
|
88
|
+
if (this.mediaSource.readyState === 'open') {
|
|
89
|
+
if(this.sourceBuffer && !this.sourceBuffer.updating){
|
|
90
|
+
this._hasEndOfStreamSuccess = true;
|
|
91
|
+
this._endOfStream();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
_endOfStream(){
|
|
98
|
+
this.queue = [];
|
|
99
|
+
if(this.mediaSource.readyState === 'open'){
|
|
61
100
|
this.mediaSource.endOfStream()
|
|
62
101
|
}
|
|
63
102
|
}
|
|
@@ -65,6 +104,22 @@ class MSE {
|
|
|
65
104
|
static isSupported (codecs) {
|
|
66
105
|
return window.MediaSource && window.MediaSource.isTypeSupported(codecs)
|
|
67
106
|
}
|
|
107
|
+
|
|
108
|
+
destroy(){
|
|
109
|
+
if(this._hasDestroyed){
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
this._hasDestroyed = true;
|
|
113
|
+
window.URL.revokeObjectURL(this.url);
|
|
114
|
+
if(this.mediaSource) {
|
|
115
|
+
this.mediaSource.removeEventListener('sourceclose', this._onMediaSourceClose);
|
|
116
|
+
this.mediaSource.removeEventListener('sourceopen', this._onSourceOpen);
|
|
117
|
+
}
|
|
118
|
+
if(this.sourceBuffer) {
|
|
119
|
+
this.sourceBuffer.removeEventListener('error', this._onSourceBufferError);
|
|
120
|
+
this.sourceBuffer.removeEventListener('updateend', this._onSourceBufferUpdateEnd);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
68
123
|
}
|
|
69
124
|
|
|
70
125
|
export default MSE
|
package/src/media/task.js
CHANGED
|
@@ -1,25 +1,64 @@
|
|
|
1
1
|
import EventEmitter from 'event-emitter'
|
|
2
2
|
import Errors from '../error'
|
|
3
|
+
import {CUSTOM_EVENTS, TASK_ERROR, TASK_ERROR_TYPES} from '../constants'
|
|
4
|
+
import getResponseHeaders from '../util/getHeaders';
|
|
3
5
|
|
|
4
6
|
class Task {
|
|
5
|
-
constructor (url, range,
|
|
7
|
+
constructor (url, range, xhrSetup, callback, ext = {}) {
|
|
6
8
|
EventEmitter(this)
|
|
9
|
+
window.Task = Task
|
|
7
10
|
this.url = url
|
|
8
11
|
this.range = range
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
this.
|
|
12
|
+
ext.start = range[0]
|
|
13
|
+
ext.end = range[1]
|
|
14
|
+
this.uniqueTag = `${this.url}&range=${range[0]}-${range[1]}`
|
|
15
|
+
this.playerId = ext.playerId;
|
|
16
|
+
//处理重复分片请求,只拦截同一播放器的相同请求
|
|
17
|
+
if (Task.queue.some(item => item.url === url && JSON.stringify(item.range) === JSON.stringify(range) && item.playerId === ext.playerId)) {
|
|
18
|
+
// console.log('task repeat playerid', ext.playerId)
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
this.xhrSetup = xhrSetup
|
|
22
|
+
this.id = this.playerId + range.join('-')
|
|
23
|
+
this.running = false
|
|
24
|
+
this.canceled = false
|
|
25
|
+
this.initialize(url, range, callback);
|
|
26
|
+
}
|
|
27
|
+
initialize(url, range, callback) {
|
|
12
28
|
let xhr = new window.XMLHttpRequest()
|
|
13
29
|
xhr.target = this
|
|
14
30
|
xhr.responseType = 'arraybuffer'
|
|
15
31
|
xhr.withCredentials = this.withCredentials || false
|
|
16
32
|
xhr.open('get', url)
|
|
33
|
+
if(typeof this.xhrSetup === 'function') {
|
|
34
|
+
this.xhrSetup(xhr, url)
|
|
35
|
+
}
|
|
17
36
|
xhr.setRequestHeader('Range', `bytes=${range[0]}-${range[1]}`)
|
|
37
|
+
let self = this;
|
|
38
|
+
xhr.onreadystatechange = function (e) {
|
|
39
|
+
// HEADERS_RECEIVED
|
|
40
|
+
if (xhr.readyState === 2) {
|
|
41
|
+
self.headers = getResponseHeaders(xhr);
|
|
42
|
+
// self.emit('getHeaders', self.headers);
|
|
43
|
+
self.status = xhr.status;
|
|
44
|
+
// self.startDownloadTime = nowTime();
|
|
45
|
+
}
|
|
46
|
+
// OPENED
|
|
47
|
+
if (xhr.readyState === 1) {
|
|
48
|
+
// self.lastTime = nowTime();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
18
51
|
xhr.onload = function () {
|
|
19
52
|
if (xhr.status === 200 || xhr.status === 206) {
|
|
20
53
|
if (callback && callback instanceof Function) {
|
|
21
54
|
callback(xhr.response)
|
|
22
55
|
}
|
|
56
|
+
} else{
|
|
57
|
+
if(xhr.status === 403){
|
|
58
|
+
self.emit(CUSTOM_EVENTS.MEDIA_EXPIRED);
|
|
59
|
+
}else{
|
|
60
|
+
self._emitTaskError(TASK_ERROR_TYPES.CODE_ERROR);
|
|
61
|
+
}
|
|
23
62
|
}
|
|
24
63
|
xhr.target.remove()
|
|
25
64
|
}
|
|
@@ -30,12 +69,20 @@ class Task {
|
|
|
30
69
|
xhr.onabort = function () {
|
|
31
70
|
xhr.target.remove()
|
|
32
71
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
72
|
+
if (!self.canceled) {
|
|
73
|
+
self.xhr = xhr;
|
|
74
|
+
Task.queue.push(self);
|
|
75
|
+
}
|
|
76
|
+
self.update()
|
|
36
77
|
}
|
|
37
78
|
cancel () {
|
|
38
79
|
this.xhr.abort()
|
|
80
|
+
this._emitTaskError(TASK_ERROR_TYPES.CANCEL);
|
|
81
|
+
this.canceled = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
_emitTaskError(code){
|
|
85
|
+
this.emit(TASK_ERROR, {code , url: this.uniqueTag, readyState: this.xhr.readyState, status: this.xhr.status})
|
|
39
86
|
}
|
|
40
87
|
|
|
41
88
|
remove () {
|
|
@@ -52,8 +99,8 @@ class Task {
|
|
|
52
99
|
|
|
53
100
|
update () {
|
|
54
101
|
let Queue = Task.queue
|
|
55
|
-
let sended = Queue.filter((item) => item.
|
|
56
|
-
let wait = Queue.filter(item => !item.
|
|
102
|
+
let sended = Queue.filter((item) => item.running)
|
|
103
|
+
let wait = Queue.filter(item => !item.running)
|
|
57
104
|
let max = Task.limit - sended.length
|
|
58
105
|
wait.forEach((item, idx) => {
|
|
59
106
|
if (idx < max) {
|
|
@@ -64,25 +111,29 @@ class Task {
|
|
|
64
111
|
|
|
65
112
|
run () {
|
|
66
113
|
if (this.xhr.readyState === 1) {
|
|
67
|
-
this.
|
|
114
|
+
this.running = true
|
|
68
115
|
this.xhr.send()
|
|
69
116
|
} else {
|
|
70
117
|
this.remove()
|
|
71
118
|
}
|
|
72
119
|
}
|
|
73
120
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
121
|
+
/***
|
|
122
|
+
* 同时存在多播放器实例,存在问题
|
|
123
|
+
*/
|
|
124
|
+
static clear (playerId) {
|
|
125
|
+
let queue = Task.queue;
|
|
126
|
+
for(let i = queue.length - 1; i > -1; i--){
|
|
127
|
+
let item = queue[i];
|
|
128
|
+
if(item.running && item.playerId === playerId){
|
|
129
|
+
item.cancel();
|
|
78
130
|
}
|
|
79
|
-
|
|
80
|
-
|
|
131
|
+
queue.splice(i, 1)
|
|
132
|
+
}
|
|
81
133
|
}
|
|
82
134
|
}
|
|
83
135
|
|
|
84
136
|
Task.queue = []
|
|
85
137
|
Task.limit = 2
|
|
86
|
-
window.Task = Task
|
|
87
138
|
|
|
88
139
|
export default Task
|