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
|
@@ -4,6 +4,10 @@ Box.MP4DecSpecificDescrTag = function (stream) {
|
|
|
4
4
|
let box = new Box()
|
|
5
5
|
let size, dataSize
|
|
6
6
|
box.type = stream.readUint8()
|
|
7
|
+
if (box.type !== 5) {
|
|
8
|
+
stream.position = stream.position - 1
|
|
9
|
+
return box
|
|
10
|
+
}
|
|
7
11
|
size = stream.readUint8()
|
|
8
12
|
if (size === 0x80) {
|
|
9
13
|
box.extend = true
|
package/src/parse/box/avcC.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import Box from '../box'
|
|
2
2
|
import Stream from '../stream'
|
|
3
|
+
import SpsParser from './sps'
|
|
4
|
+
|
|
3
5
|
Box.avcC = function () {
|
|
4
6
|
let stream = new Stream(this.data)
|
|
5
7
|
this.configVersion = stream.readUint8()
|
|
@@ -12,8 +14,9 @@ Box.avcC = function () {
|
|
|
12
14
|
this.sequenceLength = sequenceLength
|
|
13
15
|
let sequence = []
|
|
14
16
|
for (let i = 0; i < sequenceLength; i++) {
|
|
15
|
-
sequence.push(
|
|
17
|
+
sequence.push(stream.readUint8())
|
|
16
18
|
}
|
|
19
|
+
this.spsInfo = SpsParser.parseSPS(new Uint8Array(sequence))
|
|
17
20
|
this.ppsCount = stream.readUint8()
|
|
18
21
|
let ppsLength = stream.readUint16()
|
|
19
22
|
this.ppsLength = ppsLength
|
package/src/parse/box/elst.js
CHANGED
|
@@ -7,9 +7,6 @@ Box.elst = function () {
|
|
|
7
7
|
this.flag = Stream.readByte(stream.dataview, 3)
|
|
8
8
|
let entries = []
|
|
9
9
|
let entry_count = stream.readUint32()
|
|
10
|
-
this.empty_duration = 0; // empty duration of the first edit list entry
|
|
11
|
-
this.start_time = 0; // start time of the media
|
|
12
|
-
let edit_start_index = 0;
|
|
13
10
|
this.entries = entries
|
|
14
11
|
for (let i = 0; i < entry_count; i++) {
|
|
15
12
|
let entry = {}
|
|
@@ -23,17 +20,7 @@ Box.elst = function () {
|
|
|
23
20
|
}
|
|
24
21
|
entry.media_rate_integer = stream.readInt16()
|
|
25
22
|
entry.media_rate_fraction = stream.readInt16()
|
|
26
|
-
|
|
27
|
-
if (i === 0 && entry.media_time === -1) {
|
|
28
|
-
/* if empty, the first entry is the start time of the stream
|
|
29
|
-
* relative to the presentation itself */
|
|
30
|
-
this.empty_duration = entry.segment_duration;
|
|
31
|
-
edit_start_index = 1;
|
|
32
|
-
} else if (i === edit_start_index && entry.media_time >= 0) {
|
|
33
|
-
this.start_time = entry.media_time;
|
|
34
|
-
}
|
|
35
23
|
}
|
|
36
|
-
|
|
37
24
|
delete this.subBox
|
|
38
25
|
delete this.data
|
|
39
26
|
stream = null
|
package/src/parse/box/esds.js
CHANGED
|
@@ -5,8 +5,13 @@ Box.esds = function () {
|
|
|
5
5
|
let stream = new Stream(this.data)
|
|
6
6
|
this.version = stream.readUint8()
|
|
7
7
|
this.flag = Stream.readByte(stream.dataview, 3)
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
try {
|
|
9
|
+
let box = Box.MP4ESDescrTag(stream)
|
|
10
|
+
this.subBox.push(box)
|
|
11
|
+
delete this.data
|
|
12
|
+
stream = null
|
|
13
|
+
}catch(e) {
|
|
14
|
+
console.error(e)
|
|
15
|
+
}
|
|
16
|
+
|
|
12
17
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
class Golomb {
|
|
2
|
+
constructor (uint8array) {
|
|
3
|
+
this.TAG = 'Golomb'
|
|
4
|
+
this._buffer = uint8array
|
|
5
|
+
this._bufferIndex = 0
|
|
6
|
+
this._totalBytes = uint8array.byteLength
|
|
7
|
+
this._totalBits = uint8array.byteLength * 8
|
|
8
|
+
this._currentWord = 0
|
|
9
|
+
this._currentWordBitsLeft = 0
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
destroy () {
|
|
13
|
+
this._buffer = null
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
_fillCurrentWord () {
|
|
17
|
+
let bufferBytesLeft = this._totalBytes - this._bufferIndex
|
|
18
|
+
if (bufferBytesLeft <= 0) {
|
|
19
|
+
// TODO 异常处理
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let bytesRead = Math.min(4, bufferBytesLeft)
|
|
23
|
+
let word = new Uint8Array(4)
|
|
24
|
+
word.set(this._buffer.subarray(this._bufferIndex, this._bufferIndex + bytesRead))
|
|
25
|
+
this._currentWord = new DataView(word.buffer).getUint32(0)
|
|
26
|
+
|
|
27
|
+
this._bufferIndex += bytesRead
|
|
28
|
+
this._currentWordBitsLeft = bytesRead * 8
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
readBits (size) {
|
|
32
|
+
let bits = Math.min(this._currentWordBitsLeft, size);// :uint
|
|
33
|
+
let valu = this._currentWord >>> (32 - bits);
|
|
34
|
+
if (size > 32) {
|
|
35
|
+
throw new Error('Cannot read more than 32 bits at a time');
|
|
36
|
+
}
|
|
37
|
+
this._currentWordBitsLeft -= bits;
|
|
38
|
+
if (this._currentWordBitsLeft > 0) {
|
|
39
|
+
this._currentWord <<= bits;
|
|
40
|
+
} else if (this._totalBytes - this._bufferIndex > 0) {
|
|
41
|
+
this._fillCurrentWord();
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
bits = size - bits;
|
|
45
|
+
if (bits > 0 && this._currentWordBitsLeft) {
|
|
46
|
+
return valu << bits | this.readBits(bits);
|
|
47
|
+
} else {
|
|
48
|
+
return valu;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
readBool () {
|
|
53
|
+
return this.readBits(1) === 1
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
readByte () {
|
|
57
|
+
return this.readBits(8)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
_skipLeadingZero () {
|
|
61
|
+
let zeroCount
|
|
62
|
+
for (zeroCount = 0; zeroCount < this._currentWordBitsLeft; zeroCount++) {
|
|
63
|
+
if ((this._currentWord & (0x80000000 >>> zeroCount)) !== 0) {
|
|
64
|
+
this._currentWord <<= zeroCount
|
|
65
|
+
this._currentWordBitsLeft -= zeroCount
|
|
66
|
+
return zeroCount
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
this._fillCurrentWord()
|
|
70
|
+
return zeroCount + this._skipLeadingZero()
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
readUEG () { // unsigned exponential golomb
|
|
74
|
+
let leadingZeros = this._skipLeadingZero()
|
|
75
|
+
return this.readBits(leadingZeros + 1) - 1
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
readSEG () { // signed exponential golomb
|
|
79
|
+
let value = this.readUEG()
|
|
80
|
+
if (value & 0x01) {
|
|
81
|
+
return (value + 1) >>> 1
|
|
82
|
+
} else {
|
|
83
|
+
return -1 * (value >>> 1)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export default Golomb
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import Box from '../box'
|
|
2
|
+
import Stream from '../stream'
|
|
3
|
+
|
|
4
|
+
Box.hvc1 = function () {
|
|
5
|
+
let stream = new Stream(this.data)
|
|
6
|
+
let self = this
|
|
7
|
+
stream.skip(6)
|
|
8
|
+
this.dataReferenceIndex = stream.readUint16()
|
|
9
|
+
stream.skip(16)
|
|
10
|
+
this.width = stream.readUint16()
|
|
11
|
+
this.height = stream.readUint16()
|
|
12
|
+
this.horizresolution = stream.readUint32()
|
|
13
|
+
this.vertresolution = stream.readUint32()
|
|
14
|
+
stream.skip(4)
|
|
15
|
+
this.frameCount = stream.readUint16()
|
|
16
|
+
stream.skip(1)
|
|
17
|
+
for (let i = 0; i < 31; i++) {
|
|
18
|
+
String.fromCharCode(stream.readUint8())
|
|
19
|
+
}
|
|
20
|
+
this.depth = stream.readUint16()
|
|
21
|
+
stream.skip(2)
|
|
22
|
+
while (stream.position < stream.buffer.byteLength) {
|
|
23
|
+
let box = new Box()
|
|
24
|
+
box.readHeader(stream)
|
|
25
|
+
self.subBox.push(box)
|
|
26
|
+
box.readBody(stream)
|
|
27
|
+
}
|
|
28
|
+
// delete this.data
|
|
29
|
+
stream = null
|
|
30
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import Box from '../box'
|
|
2
|
+
import Stream from '../stream'
|
|
3
|
+
import SpsParser from './sps'
|
|
4
|
+
|
|
5
|
+
Box.hvcC = function () {
|
|
6
|
+
let stream = new Stream(this.data)
|
|
7
|
+
this.configVersion = stream.readUint8()
|
|
8
|
+
this.profile = stream.readUint8()
|
|
9
|
+
this.profileCompatibility = stream.readUint32()
|
|
10
|
+
this.constraintIndicatorFlags = []
|
|
11
|
+
for (let i = 0; i < 6; i++) {
|
|
12
|
+
this.constraintIndicatorFlags.push(Number(stream.readUint8()).toString(16))
|
|
13
|
+
}
|
|
14
|
+
this.levelIdc = stream.readUint8()
|
|
15
|
+
this.profileCompatibilityIndications = stream.readUint32()
|
|
16
|
+
this.bitDepthLumaMinus8 = stream.readUint8()
|
|
17
|
+
this.bitDepthChromaMinus8 = stream.readUint8()
|
|
18
|
+
this.avgFrameRate = stream.readUint16()
|
|
19
|
+
this.constantFrameRate = stream.readUint8()
|
|
20
|
+
this.numOfArrays = stream.readUint8()
|
|
21
|
+
|
|
22
|
+
this.vpsHeader = stream.readUint24()
|
|
23
|
+
this.vpsLength = stream.readUint16()
|
|
24
|
+
let vps = []
|
|
25
|
+
for (let i = 0; i < this.vpsLength; i++) {
|
|
26
|
+
vps.push(Number(stream.readUint8()).toString(16))
|
|
27
|
+
}
|
|
28
|
+
this.vps = vps
|
|
29
|
+
|
|
30
|
+
this.spsHeader = stream.readUint24()
|
|
31
|
+
this.spsLength = stream.readUint16()
|
|
32
|
+
let sps = []
|
|
33
|
+
for (let i = 0; i < this.spsLength; i++) {
|
|
34
|
+
sps.push(Number(stream.readUint8()).toString(16))
|
|
35
|
+
}
|
|
36
|
+
// this.spsInfo = SpsParser.parseSPS(new Uint8Array(sps))
|
|
37
|
+
this.sequence = sps
|
|
38
|
+
|
|
39
|
+
this.ppsHeader = stream.readUint24()
|
|
40
|
+
this.ppsLength = stream.readUint16()
|
|
41
|
+
let pps = []
|
|
42
|
+
for (let i = 0; i < this.ppsLength; i++) {
|
|
43
|
+
pps.push(Number(stream.readUint8()).toString(16))
|
|
44
|
+
}
|
|
45
|
+
this.pps = pps
|
|
46
|
+
|
|
47
|
+
let last = []; let dataviewLength = stream.dataview.byteLength
|
|
48
|
+
while (stream.position < dataviewLength) {
|
|
49
|
+
last.push(stream.readUint8())
|
|
50
|
+
}
|
|
51
|
+
this.last = last
|
|
52
|
+
delete this.subBox
|
|
53
|
+
// delete this.data
|
|
54
|
+
stream = null
|
|
55
|
+
}
|
package/src/parse/box/pasp.js
CHANGED
|
@@ -2,8 +2,7 @@ import Box from '../box'
|
|
|
2
2
|
import Stream from '../stream'
|
|
3
3
|
Box.pasp = function () {
|
|
4
4
|
let stream = new Stream(this.data)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
delete this.data
|
|
5
|
+
this.hSpacing = stream.readUint32();
|
|
6
|
+
this.vSpacing = stream.readUint32();
|
|
8
7
|
stream = null
|
|
9
8
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import Box from '../box'
|
|
2
|
+
import Stream from '../stream'
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
Box.schm = function () {
|
|
6
|
+
let stream = new Stream(this.data)
|
|
7
|
+
this.scheme_version = stream.readUint32();
|
|
8
|
+
this.scheme_type = '';
|
|
9
|
+
for (var i = 0; i < 4; i++) {
|
|
10
|
+
this.scheme_type += String.fromCharCode(stream.readUint8());
|
|
11
|
+
}
|
|
12
|
+
if (this.flags & 0x000001) {
|
|
13
|
+
this.scheme_uri = '';
|
|
14
|
+
for (var i = 0; i < this.size - this.hdr_size - 8; i++) {
|
|
15
|
+
this.scheme_uri += String.fromCharCode(stream.readUint8());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
2
|
+
/* eslint-disable one-var */
|
|
3
|
+
import Golomb from './golomb'
|
|
4
|
+
|
|
5
|
+
class SPSParser {
|
|
6
|
+
static _ebsp2rbsp (uint8array) {
|
|
7
|
+
let src = uint8array
|
|
8
|
+
let srcLength = src.byteLength
|
|
9
|
+
let dst = new Uint8Array(srcLength)
|
|
10
|
+
let dstIdx = 0
|
|
11
|
+
|
|
12
|
+
for (let i = 0; i < srcLength; i++) {
|
|
13
|
+
if (i >= 2) {
|
|
14
|
+
if (src[i] === 0x03 && src[i - 1] === 0x00 && src[i - 2] === 0x00) {
|
|
15
|
+
continue
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
dst[dstIdx] = src[i]
|
|
19
|
+
dstIdx++
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return new Uint8Array(dst.buffer, 0, dstIdx)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
static parseSPS (uint8array) {
|
|
26
|
+
let rbsp = SPSParser._ebsp2rbsp(uint8array)
|
|
27
|
+
let gb = new Golomb(rbsp)
|
|
28
|
+
|
|
29
|
+
gb.readByte()
|
|
30
|
+
let profileIdc = gb.readByte()
|
|
31
|
+
gb.readByte()
|
|
32
|
+
let levelIdc = gb.readByte()
|
|
33
|
+
gb.readUEG()
|
|
34
|
+
|
|
35
|
+
let profile_string = SPSParser.getProfileString(profileIdc)
|
|
36
|
+
let level_string = SPSParser.getLevelString(levelIdc)
|
|
37
|
+
let chroma_format_idc = 1
|
|
38
|
+
let chroma_format = 420
|
|
39
|
+
let chroma_format_table = [0, 420, 422, 444]
|
|
40
|
+
let bit_depth = 8
|
|
41
|
+
|
|
42
|
+
if (profileIdc === 100 || profileIdc === 110 || profileIdc === 122 ||
|
|
43
|
+
profileIdc === 244 || profileIdc === 44 || profileIdc === 83 ||
|
|
44
|
+
profileIdc === 86 || profileIdc === 118 || profileIdc === 128 ||
|
|
45
|
+
profileIdc === 138 || profileIdc === 144) {
|
|
46
|
+
chroma_format_idc = gb.readUEG()
|
|
47
|
+
if (chroma_format_idc === 3) {
|
|
48
|
+
gb.readBits(1)
|
|
49
|
+
}
|
|
50
|
+
if (chroma_format_idc <= 3) {
|
|
51
|
+
chroma_format = chroma_format_table[chroma_format_idc]
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
bit_depth = gb.readUEG() + 8
|
|
55
|
+
gb.readUEG()
|
|
56
|
+
gb.readBits(1)
|
|
57
|
+
if (gb.readBool()) {
|
|
58
|
+
let scaling_list_count = (chroma_format_idc !== 3) ? 8 : 12
|
|
59
|
+
for (let i = 0; i < scaling_list_count; i++) {
|
|
60
|
+
if (gb.readBool()) {
|
|
61
|
+
if (i < 6) {
|
|
62
|
+
SPSParser._skipScalingList(gb, 16)
|
|
63
|
+
} else {
|
|
64
|
+
SPSParser._skipScalingList(gb, 64)
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
gb.readUEG()
|
|
71
|
+
let pic_order_cnt_type = gb.readUEG()
|
|
72
|
+
if (pic_order_cnt_type === 0) {
|
|
73
|
+
gb.readUEG()
|
|
74
|
+
} else if (pic_order_cnt_type === 1) {
|
|
75
|
+
gb.readBits(1)
|
|
76
|
+
gb.readSEG()
|
|
77
|
+
gb.readSEG()
|
|
78
|
+
let num_ref_frames_in_pic_order_cnt_cycle = gb.readUEG()
|
|
79
|
+
for (let i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
|
|
80
|
+
gb.readSEG()
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
gb.readUEG()
|
|
84
|
+
gb.readBits(1)
|
|
85
|
+
|
|
86
|
+
let pic_width_in_mbs_minus1 = gb.readUEG()
|
|
87
|
+
let pic_height_in_map_units_minus1 = gb.readUEG()
|
|
88
|
+
|
|
89
|
+
let frame_mbs_only_flag = gb.readBits(1)
|
|
90
|
+
if (frame_mbs_only_flag === 0) {
|
|
91
|
+
gb.readBits(1)
|
|
92
|
+
}
|
|
93
|
+
gb.readBits(1)
|
|
94
|
+
|
|
95
|
+
let frame_crop_left_offset = 0
|
|
96
|
+
let frame_crop_right_offset = 0
|
|
97
|
+
let frame_crop_top_offset = 0
|
|
98
|
+
let frame_crop_bottom_offset = 0
|
|
99
|
+
|
|
100
|
+
let frame_cropping_flag = gb.readBool()
|
|
101
|
+
if (frame_cropping_flag) {
|
|
102
|
+
frame_crop_left_offset = gb.readUEG()
|
|
103
|
+
frame_crop_right_offset = gb.readUEG()
|
|
104
|
+
frame_crop_top_offset = gb.readUEG()
|
|
105
|
+
frame_crop_bottom_offset = gb.readUEG()
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let par_width = 1, par_height = 1
|
|
109
|
+
let fps = 0, fps_fixed = true, fps_num = 0, fps_den = 0
|
|
110
|
+
|
|
111
|
+
let vui_parameters_present_flag = gb.readBool()
|
|
112
|
+
if (vui_parameters_present_flag) {
|
|
113
|
+
if (gb.readBool()) { // aspect_ratio_info_present_flag
|
|
114
|
+
let aspect_ratio_idc = gb.readByte()
|
|
115
|
+
let par_w_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2]
|
|
116
|
+
let par_h_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1]
|
|
117
|
+
|
|
118
|
+
if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
|
|
119
|
+
par_width = par_w_table[aspect_ratio_idc - 1]
|
|
120
|
+
par_height = par_h_table[aspect_ratio_idc - 1]
|
|
121
|
+
} else if (aspect_ratio_idc === 255) {
|
|
122
|
+
par_width = gb.readByte() << 8 | gb.readByte()
|
|
123
|
+
par_height = gb.readByte() << 8 | gb.readByte()
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
if (gb.readBool()) {
|
|
128
|
+
gb.readBool()
|
|
129
|
+
}
|
|
130
|
+
if (gb.readBool()) {
|
|
131
|
+
gb.readBits(4)
|
|
132
|
+
if (gb.readBool()) {
|
|
133
|
+
gb.readBits(24)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (gb.readBool()) {
|
|
137
|
+
gb.readUEG()
|
|
138
|
+
gb.readUEG()
|
|
139
|
+
}
|
|
140
|
+
if (gb.readBool()) {
|
|
141
|
+
let num_units_in_tick = gb.readBits(32)
|
|
142
|
+
let time_scale = gb.readBits(32)
|
|
143
|
+
fps_fixed = gb.readBool()
|
|
144
|
+
|
|
145
|
+
fps_num = time_scale
|
|
146
|
+
fps_den = num_units_in_tick * 2
|
|
147
|
+
fps = fps_num / fps_den
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
let parScale = 1
|
|
152
|
+
if (par_width !== 1 || par_height !== 1) {
|
|
153
|
+
parScale = par_width / par_height
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
let crop_unit_x = 0, crop_unit_y = 0
|
|
157
|
+
if (chroma_format_idc === 0) {
|
|
158
|
+
crop_unit_x = 1
|
|
159
|
+
crop_unit_y = 2 - frame_mbs_only_flag
|
|
160
|
+
} else {
|
|
161
|
+
let sub_wc = (chroma_format_idc === 3) ? 1 : 2
|
|
162
|
+
let sub_hc = (chroma_format_idc === 1) ? 2 : 1
|
|
163
|
+
crop_unit_x = sub_wc
|
|
164
|
+
crop_unit_y = sub_hc * (2 - frame_mbs_only_flag)
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
let codec_width = (pic_width_in_mbs_minus1 + 1) * 16
|
|
168
|
+
let codec_height = (2 - frame_mbs_only_flag) * ((pic_height_in_map_units_minus1 + 1) * 16)
|
|
169
|
+
|
|
170
|
+
codec_width -= (frame_crop_left_offset + frame_crop_right_offset) * crop_unit_x
|
|
171
|
+
codec_height -= (frame_crop_top_offset + frame_crop_bottom_offset) * crop_unit_y
|
|
172
|
+
|
|
173
|
+
let present_width = Math.ceil(codec_width * parScale)
|
|
174
|
+
|
|
175
|
+
gb.destroy()
|
|
176
|
+
gb = null
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
profile_string: profile_string,
|
|
180
|
+
level_string: level_string,
|
|
181
|
+
bit_depth: bit_depth,
|
|
182
|
+
chroma_format: chroma_format,
|
|
183
|
+
chroma_format_string: SPSParser.getChromaFormatString(chroma_format),
|
|
184
|
+
|
|
185
|
+
frame_rate: {
|
|
186
|
+
fixed: fps_fixed,
|
|
187
|
+
fps: fps,
|
|
188
|
+
fps_den: fps_den,
|
|
189
|
+
fps_num: fps_num
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
par_ratio: {
|
|
193
|
+
width: par_width,
|
|
194
|
+
height: par_height
|
|
195
|
+
},
|
|
196
|
+
|
|
197
|
+
codec_size: {
|
|
198
|
+
width: codec_width,
|
|
199
|
+
height: codec_height
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
present_size: {
|
|
203
|
+
width: present_width,
|
|
204
|
+
height: codec_height
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
static _skipScalingList (gb, count) {
|
|
210
|
+
let last_scale = 8, next_scale = 8
|
|
211
|
+
let delta_scale = 0
|
|
212
|
+
for (let i = 0; i < count; i++) {
|
|
213
|
+
if (next_scale !== 0) {
|
|
214
|
+
delta_scale = gb.readSEG()
|
|
215
|
+
next_scale = (last_scale + delta_scale + 256) % 256
|
|
216
|
+
}
|
|
217
|
+
last_scale = (next_scale === 0) ? last_scale : next_scale
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
static getProfileString (profileIdc) {
|
|
222
|
+
switch (profileIdc) {
|
|
223
|
+
case 66:
|
|
224
|
+
return 'Baseline'
|
|
225
|
+
case 77:
|
|
226
|
+
return 'Main'
|
|
227
|
+
case 88:
|
|
228
|
+
return 'Extended'
|
|
229
|
+
case 100:
|
|
230
|
+
return 'High'
|
|
231
|
+
case 110:
|
|
232
|
+
return 'High10'
|
|
233
|
+
case 122:
|
|
234
|
+
return 'High422'
|
|
235
|
+
case 244:
|
|
236
|
+
return 'High444'
|
|
237
|
+
default:
|
|
238
|
+
return 'Unknown'
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
static getLevelString (levelIdc) {
|
|
243
|
+
return (levelIdc / 10).toFixed(1)
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
static getChromaFormatString (chroma) {
|
|
247
|
+
switch (chroma) {
|
|
248
|
+
case 420:
|
|
249
|
+
return '4:2:0'
|
|
250
|
+
case 422:
|
|
251
|
+
return '4:2:2'
|
|
252
|
+
case 444:
|
|
253
|
+
return '4:4:4'
|
|
254
|
+
default:
|
|
255
|
+
return 'Unknown'
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
static toVideoMeta (spsConfig) {
|
|
260
|
+
let meta = {}
|
|
261
|
+
if (spsConfig && spsConfig.codec_size) {
|
|
262
|
+
meta.codecWidth = spsConfig.codec_size.width
|
|
263
|
+
meta.codecHeight = spsConfig.codec_size.height
|
|
264
|
+
meta.presentWidth = spsConfig.present_size.width
|
|
265
|
+
meta.presentHeight = spsConfig.present_size.height
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
meta.profile = spsConfig.profile_string
|
|
269
|
+
meta.level = spsConfig.level_string
|
|
270
|
+
meta.bitDepth = spsConfig.bit_depth
|
|
271
|
+
meta.chromaFormat = spsConfig.chroma_format
|
|
272
|
+
|
|
273
|
+
meta.parRatio = {
|
|
274
|
+
width: spsConfig.par_ratio.width,
|
|
275
|
+
height: spsConfig.par_ratio.height
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
meta.frameRate = spsConfig.frame_rate
|
|
279
|
+
|
|
280
|
+
let fpsDen = meta.frameRate.fps_den
|
|
281
|
+
let fpsNum = meta.frameRate.fps_num
|
|
282
|
+
meta.refSampleDuration = Math.floor(meta.timescale * (fpsDen / fpsNum))
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export default SPSParser
|
package/src/parse/box/stsz.js
CHANGED
|
@@ -10,7 +10,12 @@ Box.stsz = function () {
|
|
|
10
10
|
let entries = []
|
|
11
11
|
this.entries = entries
|
|
12
12
|
for (let i = 0, count = this.count; i < count; i++) {
|
|
13
|
-
|
|
13
|
+
if (this.sampleSize) {
|
|
14
|
+
entries.push(this.sampleSize)
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
entries.push(stream.readUint32())
|
|
18
|
+
}
|
|
14
19
|
}
|
|
15
20
|
delete this.subBox
|
|
16
21
|
delete this.data
|
package/src/parse/box/tfhd.js
CHANGED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import Box from '../box'
|
|
2
|
+
import Stream from '../stream'
|
|
3
|
+
|
|
4
|
+
Box.tfhd = function () {
|
|
5
|
+
let stream = new Stream(this.data)
|
|
6
|
+
this.version = stream.readUint8()
|
|
7
|
+
this.flag = Stream.readByte(stream.dataview, 3)
|
|
8
|
+
|
|
9
|
+
// trackId: view.getUint32(4)
|
|
10
|
+
this.track_id = stream.readUint32();
|
|
11
|
+
|
|
12
|
+
let baseDataOffsetPresent = (this.flag & 0xff) & 0x01;
|
|
13
|
+
let sampleDescriptionIndexPresent = (this.flag & 0xff) & 0x02;
|
|
14
|
+
let defaultSampleDurationPresent = (this.flag & 0xff) & 0x08;
|
|
15
|
+
let defaultSampleSizePresent = (this.flag & 0xff) & 0x10;
|
|
16
|
+
let defaultSampleFlagsPresent = (this.flag & 0xff) & 0x20;
|
|
17
|
+
|
|
18
|
+
let i = 8;
|
|
19
|
+
if (baseDataOffsetPresent) {
|
|
20
|
+
i += 4; // truncate top 4 bytes
|
|
21
|
+
this.baseDataOffset = stream.readUint32();
|
|
22
|
+
i += 4;
|
|
23
|
+
}
|
|
24
|
+
if (sampleDescriptionIndexPresent) {
|
|
25
|
+
this.sampleDescriptionIndex = stream.readUint32();
|
|
26
|
+
i += 4;
|
|
27
|
+
}
|
|
28
|
+
if (defaultSampleDurationPresent) {
|
|
29
|
+
this.defaultSampleDuration = stream.readUint32();
|
|
30
|
+
i += 4;
|
|
31
|
+
}
|
|
32
|
+
if (defaultSampleSizePresent) {
|
|
33
|
+
this.defaultSampleSize = stream.readUint32();
|
|
34
|
+
i += 4;
|
|
35
|
+
}
|
|
36
|
+
if (defaultSampleFlagsPresent) {
|
|
37
|
+
this.defaultSampleFlags = stream.readUint32();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
delete this.subBox
|
|
41
|
+
delete this.data
|
|
42
|
+
stream = null
|
|
43
|
+
}
|
package/src/parse/box.js
CHANGED
|
@@ -25,6 +25,10 @@ class Box {
|
|
|
25
25
|
uuid.push(stream.readUint8())
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
+
if (this.type === 'pssh') {
|
|
29
|
+
this.version = stream.readUint8();
|
|
30
|
+
this.flags = stream.readUint8();
|
|
31
|
+
}
|
|
28
32
|
}
|
|
29
33
|
readBody (stream) {
|
|
30
34
|
let end = this.size - stream.position + this.start
|
|
@@ -61,6 +65,6 @@ class Box {
|
|
|
61
65
|
}
|
|
62
66
|
}
|
|
63
67
|
|
|
64
|
-
Box.containerBox = ['moov', 'trak', 'edts', 'mdia', 'minf', 'dinf', 'stbl', 'mvex', 'moof', 'traf', 'mfra']
|
|
68
|
+
Box.containerBox = ['moov', 'trak', 'edts', 'mdia', 'minf', 'dinf', 'stbl', 'mvex', 'moof', 'traf', 'mfra', 'sinf', 'schi']
|
|
65
69
|
|
|
66
70
|
export default Box
|
package/src/parse/stream.js
CHANGED