@alessmicrosystems/mpegts.js 1.8.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 +202 -0
- package/README.md +158 -0
- package/README_ja.md +153 -0
- package/README_zh.md +157 -0
- package/d.ts/mpegts.d.ts +524 -0
- package/d.ts/src/core/mse-events.d.ts +9 -0
- package/d.ts/src/core/transmuxing-events.d.ts +24 -0
- package/d.ts/src/demux/aac.d.ts +44 -0
- package/d.ts/src/demux/ac3.d.ts +70 -0
- package/d.ts/src/demux/av1-parser.d.ts +77 -0
- package/d.ts/src/demux/av1.d.ts +11 -0
- package/d.ts/src/demux/base-demuxer.d.ts +55 -0
- package/d.ts/src/demux/h264.d.ts +40 -0
- package/d.ts/src/demux/h265.d.ts +65 -0
- package/d.ts/src/demux/klv.d.ts +17 -0
- package/d.ts/src/demux/mp3.d.ts +6 -0
- package/d.ts/src/demux/mpeg4-audio.d.ts +28 -0
- package/d.ts/src/demux/pat-pmt-pes.d.ts +106 -0
- package/d.ts/src/demux/patpmt.d.ts +40 -0
- package/d.ts/src/demux/pes-private-data.d.ts +14 -0
- package/d.ts/src/demux/pgs-data.d.ts +9 -0
- package/d.ts/src/demux/scte35.d.ts +250 -0
- package/d.ts/src/demux/sei.d.ts +8 -0
- package/d.ts/src/demux/smpte2038.d.ts +22 -0
- package/d.ts/src/demux/ts-demuxer.d.ts +124 -0
- package/d.ts/src/player/live-latency-chaser.d.ts +10 -0
- package/d.ts/src/player/live-latency-synchronizer.d.ts +10 -0
- package/d.ts/src/player/loading-controller.d.ts +19 -0
- package/d.ts/src/player/mse-player.d.ts +30 -0
- package/d.ts/src/player/player-engine-dedicated-thread-worker.d.ts +2 -0
- package/d.ts/src/player/player-engine-dedicated-thread.d.ts +48 -0
- package/d.ts/src/player/player-engine-main-thread.d.ts +50 -0
- package/d.ts/src/player/player-engine-worker-cmd-def.d.ts +25 -0
- package/d.ts/src/player/player-engine-worker-msg-def.d.ts +54 -0
- package/d.ts/src/player/player-engine-worker.d.ts +2 -0
- package/d.ts/src/player/player-engine.d.ts +16 -0
- package/d.ts/src/player/player-events.d.ts +21 -0
- package/d.ts/src/player/seeking-handler.d.ts +22 -0
- package/d.ts/src/player/startup-stall-jumper.d.ts +14 -0
- package/d.ts/src/utils/typedarray-equality.d.ts +2 -0
- package/dist/mpegts.js +3 -0
- package/dist/mpegts.js.LICENSE.txt +7 -0
- package/dist/mpegts.js.map +1 -0
- package/package.json +53 -0
- package/src/config.js +67 -0
- package/src/core/features.js +88 -0
- package/src/core/media-info.js +127 -0
- package/src/core/media-segment-info.js +230 -0
- package/src/core/mse-controller.js +599 -0
- package/src/core/mse-events.ts +28 -0
- package/src/core/transmuxer.js +346 -0
- package/src/core/transmuxing-controller.js +628 -0
- package/src/core/transmuxing-events.ts +43 -0
- package/src/core/transmuxing-worker.js +286 -0
- package/src/demux/aac.ts +397 -0
- package/src/demux/ac3.ts +335 -0
- package/src/demux/amf-parser.js +243 -0
- package/src/demux/av1-parser.ts +629 -0
- package/src/demux/av1.ts +103 -0
- package/src/demux/base-demuxer.ts +69 -0
- package/src/demux/demux-errors.js +26 -0
- package/src/demux/exp-golomb.js +116 -0
- package/src/demux/flv-demuxer.js +1854 -0
- package/src/demux/h264.ts +187 -0
- package/src/demux/h265-parser.js +501 -0
- package/src/demux/h265.ts +214 -0
- package/src/demux/klv.ts +40 -0
- package/src/demux/mp3.ts +7 -0
- package/src/demux/mpeg4-audio.ts +45 -0
- package/src/demux/pat-pmt-pes.ts +132 -0
- package/src/demux/pes-private-data.ts +16 -0
- package/src/demux/pgs-data.ts +11 -0
- package/src/demux/scte35.ts +723 -0
- package/src/demux/sei.ts +99 -0
- package/src/demux/smpte2038.ts +89 -0
- package/src/demux/sps-parser.js +298 -0
- package/src/demux/ts-demuxer.ts +2405 -0
- package/src/index.js +4 -0
- package/src/io/fetch-stream-loader.js +266 -0
- package/src/io/io-controller.js +647 -0
- package/src/io/loader.js +134 -0
- package/src/io/param-seek-handler.js +85 -0
- package/src/io/range-seek-handler.js +52 -0
- package/src/io/speed-sampler.js +93 -0
- package/src/io/websocket-loader.js +151 -0
- package/src/io/xhr-moz-chunked-loader.js +211 -0
- package/src/io/xhr-msstream-loader.js +307 -0
- package/src/io/xhr-range-loader.js +366 -0
- package/src/mpegts.js +95 -0
- package/src/player/live-latency-chaser.ts +66 -0
- package/src/player/live-latency-synchronizer.ts +79 -0
- package/src/player/loading-controller.ts +142 -0
- package/src/player/mse-player.ts +150 -0
- package/src/player/native-player.js +262 -0
- package/src/player/player-engine-dedicated-thread.ts +479 -0
- package/src/player/player-engine-main-thread.ts +463 -0
- package/src/player/player-engine-worker-cmd-def.ts +62 -0
- package/src/player/player-engine-worker-msg-def.ts +102 -0
- package/src/player/player-engine-worker.ts +370 -0
- package/src/player/player-engine.ts +35 -0
- package/src/player/player-errors.js +39 -0
- package/src/player/player-events.ts +40 -0
- package/src/player/seeking-handler.ts +205 -0
- package/src/player/startup-stall-jumper.ts +86 -0
- package/src/remux/aac-silent.js +56 -0
- package/src/remux/mp4-generator.js +866 -0
- package/src/remux/mp4-remuxer.js +778 -0
- package/src/utils/browser.js +128 -0
- package/src/utils/exception.js +73 -0
- package/src/utils/logger.js +140 -0
- package/src/utils/logging-control.js +165 -0
- package/src/utils/polyfill.js +68 -0
- package/src/utils/typedarray-equality.ts +69 -0
- package/src/utils/utf8-conv.js +84 -0
- package/src/utils/webworkify-webpack.js +202 -0
- package/tsconfig.json +16 -0
- package/tslint.json +1 -0
- package/types/index.d.ts +3 -0
- package/types/test-flv.ts +8 -0
- package/types/tsconfig.json +24 -0
- package/webpack.config.js +55 -0
package/src/demux/sei.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
|
|
2
|
+
export class SEIData {
|
|
3
|
+
type: number;
|
|
4
|
+
size: number;
|
|
5
|
+
uuid: Uint8Array;
|
|
6
|
+
user_data: Uint8Array;
|
|
7
|
+
pts?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function ebsp2rbsp(uint8array: Uint8Array): Uint8Array {
|
|
11
|
+
let src = uint8array;
|
|
12
|
+
let src_length = src.byteLength;
|
|
13
|
+
let dst = new Uint8Array(src_length);
|
|
14
|
+
let dst_idx = 0;
|
|
15
|
+
|
|
16
|
+
for (let i = 0; i < src_length; i++) {
|
|
17
|
+
if (i >= 2) {
|
|
18
|
+
// Unescape: Skip 0x03 after 00 00
|
|
19
|
+
if (src[i] === 0x03 && src[i - 1] === 0x00 && src[i - 2] === 0x00) {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
dst[dst_idx] = src[i];
|
|
24
|
+
dst_idx++;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return new Uint8Array(dst.buffer, 0, dst_idx);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function parseSEI(data: Uint8Array, pts?: number, codec?: 'h264' | 'h265'): SEIData | null {
|
|
31
|
+
if (!data || data.byteLength < 2) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Determine NALU header size based on codec
|
|
36
|
+
let naluHeaderSize = 1; // Default for H.264
|
|
37
|
+
if (codec === 'h265') {
|
|
38
|
+
naluHeaderSize = 2;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Convert EBSP to RBSP (skip NALU header)
|
|
42
|
+
let rbsp_data = ebsp2rbsp(data.subarray(naluHeaderSize));
|
|
43
|
+
let offset = 0;
|
|
44
|
+
|
|
45
|
+
// Check for trailing bits (0x80)
|
|
46
|
+
if (offset === rbsp_data.byteLength - 1 && rbsp_data[offset] === 0x80) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Parse payload type (can be multiple bytes for extended types)
|
|
51
|
+
let payloadType = 0;
|
|
52
|
+
while (offset < rbsp_data.byteLength && rbsp_data[offset] === 0xFF) {
|
|
53
|
+
payloadType += 255;
|
|
54
|
+
offset++;
|
|
55
|
+
}
|
|
56
|
+
if (offset >= rbsp_data.byteLength) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
payloadType += rbsp_data[offset++];
|
|
60
|
+
|
|
61
|
+
// Parse payload size (can be multiple bytes for extended sizes)
|
|
62
|
+
let payloadSize = 0;
|
|
63
|
+
while (offset < rbsp_data.byteLength && rbsp_data[offset] === 0xFF) {
|
|
64
|
+
payloadSize += 255;
|
|
65
|
+
offset++;
|
|
66
|
+
}
|
|
67
|
+
if (offset >= rbsp_data.byteLength) {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
payloadSize += rbsp_data[offset++];
|
|
71
|
+
|
|
72
|
+
// Check if we have enough data
|
|
73
|
+
if (offset + payloadSize > rbsp_data.byteLength) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let sei_data = new SEIData();
|
|
78
|
+
sei_data.type = payloadType;
|
|
79
|
+
sei_data.size = payloadSize;
|
|
80
|
+
|
|
81
|
+
// Extract payload
|
|
82
|
+
let payload = rbsp_data.subarray(offset, offset + payloadSize);
|
|
83
|
+
|
|
84
|
+
// SEI payload type 5 is user_data_unregistered (with UUID)
|
|
85
|
+
// This is the same for both H.264 and H.265
|
|
86
|
+
if (payloadType === 5 && payloadSize >= 16) {
|
|
87
|
+
// First 16 bytes are UUID
|
|
88
|
+
sei_data.uuid = payload.subarray(0, 16);
|
|
89
|
+
sei_data.user_data = payload.subarray(16);
|
|
90
|
+
} else {
|
|
91
|
+
// ignore
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (pts !== undefined) {
|
|
95
|
+
sei_data.pts = pts;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return sei_data;
|
|
99
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import ExpGolomb from "./exp-golomb";
|
|
2
|
+
|
|
3
|
+
export class SMPTE2038Data {
|
|
4
|
+
pid: number;
|
|
5
|
+
stream_id: number;
|
|
6
|
+
pts?: number;
|
|
7
|
+
dts?: number;
|
|
8
|
+
nearest_pts?: number;
|
|
9
|
+
ancillaries: AncillaryData[];
|
|
10
|
+
data: Uint8Array;
|
|
11
|
+
len: number;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
type AncillaryData = {
|
|
15
|
+
yc_indicator: boolean;
|
|
16
|
+
line_number: number;
|
|
17
|
+
horizontal_offset: number;
|
|
18
|
+
did: number;
|
|
19
|
+
sdid: number;
|
|
20
|
+
user_data: Uint8Array;
|
|
21
|
+
description: string;
|
|
22
|
+
information: any;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
export const smpte2038parse = (data: Uint8Array) => {
|
|
27
|
+
let gb = new ExpGolomb(data);
|
|
28
|
+
let readBits = 0;
|
|
29
|
+
|
|
30
|
+
let ancillaries: AncillaryData[] = [];
|
|
31
|
+
while (true) {
|
|
32
|
+
let zero = gb.readBits(6); readBits += 6;
|
|
33
|
+
if (zero !== 0) { break; }
|
|
34
|
+
let YC_indicator = gb.readBool(); readBits += 1;
|
|
35
|
+
let line_number = gb.readBits(11); readBits += 11;
|
|
36
|
+
let horizontal_offset = gb.readBits(12); readBits += 12;
|
|
37
|
+
let data_ID = gb.readBits(10) & 0xFF; readBits += 10;
|
|
38
|
+
let data_SDID = gb.readBits(10) & 0xFF; readBits += 10;
|
|
39
|
+
let data_count = gb.readBits(10) & 0xFF; readBits += 10;
|
|
40
|
+
let user_data = new Uint8Array(data_count);
|
|
41
|
+
for (let i = 0; i < data_count; i++) {
|
|
42
|
+
let user_data_word = gb.readBits(10) & 0xFF; readBits += 10;
|
|
43
|
+
user_data[i] = user_data_word;
|
|
44
|
+
}
|
|
45
|
+
let checksum_word = gb.readBits(10); readBits += 10;
|
|
46
|
+
|
|
47
|
+
let description = 'User Defined';
|
|
48
|
+
let information: any = {};
|
|
49
|
+
if (data_ID === 0x41) {
|
|
50
|
+
if (data_SDID === 0x07) {
|
|
51
|
+
description = 'SCTE-104'
|
|
52
|
+
}
|
|
53
|
+
} else if (data_ID === 0x5F) {
|
|
54
|
+
if (data_SDID === 0xDC) {
|
|
55
|
+
description = 'ARIB STD-B37 (1SEG)';
|
|
56
|
+
} else if (data_SDID === 0xDD) {
|
|
57
|
+
description = 'ARIB STD-B37 (ANALOG)';
|
|
58
|
+
} else if (data_SDID === 0xDE) {
|
|
59
|
+
description = 'ARIB STD-B37 (SD)';
|
|
60
|
+
} else if (data_SDID === 0xDF) {
|
|
61
|
+
description = 'ARIB STD-B37 (HD)';
|
|
62
|
+
}
|
|
63
|
+
} else if (data_ID === 0x61) {
|
|
64
|
+
if (data_SDID === 0x01) {
|
|
65
|
+
description = 'EIA-708';
|
|
66
|
+
} else if (data_SDID === 0x02) {
|
|
67
|
+
description = 'EIA-608';
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
ancillaries.push({
|
|
72
|
+
yc_indicator: YC_indicator,
|
|
73
|
+
line_number,
|
|
74
|
+
horizontal_offset,
|
|
75
|
+
did: data_ID,
|
|
76
|
+
sdid: data_SDID,
|
|
77
|
+
user_data,
|
|
78
|
+
description,
|
|
79
|
+
information
|
|
80
|
+
});
|
|
81
|
+
gb.readBits(8 - (readBits - Math.floor(readBits / 8)) % 8);
|
|
82
|
+
readBits += (8 - (readBits - Math.floor(readBits / 8))) % 8;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
gb.destroy();
|
|
86
|
+
gb = null;
|
|
87
|
+
|
|
88
|
+
return ancillaries;
|
|
89
|
+
}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2016 Bilibili. All Rights Reserved.
|
|
3
|
+
*
|
|
4
|
+
* @author zheng qian <xqq@xqq.im>
|
|
5
|
+
*
|
|
6
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
7
|
+
* you may not use this file except in compliance with the License.
|
|
8
|
+
* You may obtain a copy of the License at
|
|
9
|
+
*
|
|
10
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
11
|
+
*
|
|
12
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
13
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
14
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
|
+
* See the License for the specific language governing permissions and
|
|
16
|
+
* limitations under the License.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import ExpGolomb from './exp-golomb.js';
|
|
20
|
+
|
|
21
|
+
class SPSParser {
|
|
22
|
+
|
|
23
|
+
static _ebsp2rbsp(uint8array) {
|
|
24
|
+
let src = uint8array;
|
|
25
|
+
let src_length = src.byteLength;
|
|
26
|
+
let dst = new Uint8Array(src_length);
|
|
27
|
+
let dst_idx = 0;
|
|
28
|
+
|
|
29
|
+
for (let i = 0; i < src_length; i++) {
|
|
30
|
+
if (i >= 2) {
|
|
31
|
+
// Unescape: Skip 0x03 after 00 00
|
|
32
|
+
if (src[i] === 0x03 && src[i - 1] === 0x00 && src[i - 2] === 0x00) {
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
dst[dst_idx] = src[i];
|
|
37
|
+
dst_idx++;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return new Uint8Array(dst.buffer, 0, dst_idx);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static parseSPS(uint8array) {
|
|
44
|
+
let codec_array = uint8array.subarray(1, 4);
|
|
45
|
+
let codec_mimetype = 'avc1.';
|
|
46
|
+
for (let j = 0; j < 3; j++) {
|
|
47
|
+
let h = codec_array[j].toString(16);
|
|
48
|
+
if (h.length < 2) {
|
|
49
|
+
h = '0' + h;
|
|
50
|
+
}
|
|
51
|
+
codec_mimetype += h;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
let rbsp = SPSParser._ebsp2rbsp(uint8array);
|
|
55
|
+
let gb = new ExpGolomb(rbsp);
|
|
56
|
+
|
|
57
|
+
gb.readByte();
|
|
58
|
+
let profile_idc = gb.readByte(); // profile_idc
|
|
59
|
+
gb.readByte(); // constraint_set_flags[5] + reserved_zero[3]
|
|
60
|
+
let level_idc = gb.readByte(); // level_idc
|
|
61
|
+
gb.readUEG(); // seq_parameter_set_id
|
|
62
|
+
|
|
63
|
+
let profile_string = SPSParser.getProfileString(profile_idc);
|
|
64
|
+
let level_string = SPSParser.getLevelString(level_idc);
|
|
65
|
+
let chroma_format_idc = 1;
|
|
66
|
+
let chroma_format = 420;
|
|
67
|
+
let chroma_format_table = [0, 420, 422, 444];
|
|
68
|
+
let bit_depth_luma = 8;
|
|
69
|
+
let bit_depth_chroma = 8;
|
|
70
|
+
|
|
71
|
+
if (profile_idc === 100 || profile_idc === 110 || profile_idc === 122 ||
|
|
72
|
+
profile_idc === 244 || profile_idc === 44 || profile_idc === 83 ||
|
|
73
|
+
profile_idc === 86 || profile_idc === 118 || profile_idc === 128 ||
|
|
74
|
+
profile_idc === 138 || profile_idc === 144) {
|
|
75
|
+
|
|
76
|
+
chroma_format_idc = gb.readUEG();
|
|
77
|
+
if (chroma_format_idc === 3) {
|
|
78
|
+
gb.readBits(1); // separate_colour_plane_flag
|
|
79
|
+
}
|
|
80
|
+
if (chroma_format_idc <= 3) {
|
|
81
|
+
chroma_format = chroma_format_table[chroma_format_idc];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
bit_depth_luma = gb.readUEG() + 8; // bit_depth_luma_minus8
|
|
85
|
+
bit_depth_chroma = gb.readUEG() + 8; // bit_depth_chroma_minus8
|
|
86
|
+
gb.readBits(1); // qpprime_y_zero_transform_bypass_flag
|
|
87
|
+
if (gb.readBool()) { // seq_scaling_matrix_present_flag
|
|
88
|
+
let scaling_list_count = (chroma_format_idc !== 3) ? 8 : 12;
|
|
89
|
+
for (let i = 0; i < scaling_list_count; i++) {
|
|
90
|
+
if (gb.readBool()) { // seq_scaling_list_present_flag
|
|
91
|
+
if (i < 6) {
|
|
92
|
+
SPSParser._skipScalingList(gb, 16);
|
|
93
|
+
} else {
|
|
94
|
+
SPSParser._skipScalingList(gb, 64);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
gb.readUEG(); // log2_max_frame_num_minus4
|
|
101
|
+
let pic_order_cnt_type = gb.readUEG();
|
|
102
|
+
if (pic_order_cnt_type === 0) {
|
|
103
|
+
gb.readUEG(); // log2_max_pic_order_cnt_lsb_minus_4
|
|
104
|
+
} else if (pic_order_cnt_type === 1) {
|
|
105
|
+
gb.readBits(1); // delta_pic_order_always_zero_flag
|
|
106
|
+
gb.readSEG(); // offset_for_non_ref_pic
|
|
107
|
+
gb.readSEG(); // offset_for_top_to_bottom_field
|
|
108
|
+
let num_ref_frames_in_pic_order_cnt_cycle = gb.readUEG();
|
|
109
|
+
for (let i = 0; i < num_ref_frames_in_pic_order_cnt_cycle; i++) {
|
|
110
|
+
gb.readSEG(); // offset_for_ref_frame
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
let ref_frames = gb.readUEG(); // max_num_ref_frames
|
|
114
|
+
gb.readBits(1); // gaps_in_frame_num_value_allowed_flag
|
|
115
|
+
|
|
116
|
+
let pic_width_in_mbs_minus1 = gb.readUEG();
|
|
117
|
+
let pic_height_in_map_units_minus1 = gb.readUEG();
|
|
118
|
+
|
|
119
|
+
let frame_mbs_only_flag = gb.readBits(1);
|
|
120
|
+
if (frame_mbs_only_flag === 0) {
|
|
121
|
+
gb.readBits(1); // mb_adaptive_frame_field_flag
|
|
122
|
+
}
|
|
123
|
+
gb.readBits(1); // direct_8x8_inference_flag
|
|
124
|
+
|
|
125
|
+
let frame_crop_left_offset = 0;
|
|
126
|
+
let frame_crop_right_offset = 0;
|
|
127
|
+
let frame_crop_top_offset = 0;
|
|
128
|
+
let frame_crop_bottom_offset = 0;
|
|
129
|
+
|
|
130
|
+
let frame_cropping_flag = gb.readBool();
|
|
131
|
+
if (frame_cropping_flag) {
|
|
132
|
+
frame_crop_left_offset = gb.readUEG();
|
|
133
|
+
frame_crop_right_offset = gb.readUEG();
|
|
134
|
+
frame_crop_top_offset = gb.readUEG();
|
|
135
|
+
frame_crop_bottom_offset = gb.readUEG();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
let sar_width = 1, sar_height = 1;
|
|
139
|
+
let fps = 0, fps_fixed = true, fps_num = 0, fps_den = 0;
|
|
140
|
+
|
|
141
|
+
let vui_parameters_present_flag = gb.readBool();
|
|
142
|
+
if (vui_parameters_present_flag) {
|
|
143
|
+
if (gb.readBool()) { // aspect_ratio_info_present_flag
|
|
144
|
+
let aspect_ratio_idc = gb.readByte();
|
|
145
|
+
let sar_w_table = [1, 12, 10, 16, 40, 24, 20, 32, 80, 18, 15, 64, 160, 4, 3, 2];
|
|
146
|
+
let sar_h_table = [1, 11, 11, 11, 33, 11, 11, 11, 33, 11, 11, 33, 99, 3, 2, 1];
|
|
147
|
+
|
|
148
|
+
if (aspect_ratio_idc > 0 && aspect_ratio_idc < 16) {
|
|
149
|
+
sar_width = sar_w_table[aspect_ratio_idc - 1];
|
|
150
|
+
sar_height = sar_h_table[aspect_ratio_idc - 1];
|
|
151
|
+
} else if (aspect_ratio_idc === 255) {
|
|
152
|
+
sar_width = gb.readByte() << 8 | gb.readByte();
|
|
153
|
+
sar_height = gb.readByte() << 8 | gb.readByte();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (gb.readBool()) { // overscan_info_present_flag
|
|
158
|
+
gb.readBool(); // overscan_appropriate_flag
|
|
159
|
+
}
|
|
160
|
+
if (gb.readBool()) { // video_signal_type_present_flag
|
|
161
|
+
gb.readBits(4); // video_format & video_full_range_flag
|
|
162
|
+
if (gb.readBool()) { // colour_description_present_flag
|
|
163
|
+
gb.readBits(24); // colour_primaries & transfer_characteristics & matrix_coefficients
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
if (gb.readBool()) { // chroma_loc_info_present_flag
|
|
167
|
+
gb.readUEG(); // chroma_sample_loc_type_top_field
|
|
168
|
+
gb.readUEG(); // chroma_sample_loc_type_bottom_field
|
|
169
|
+
}
|
|
170
|
+
if (gb.readBool()) { // timing_info_present_flag
|
|
171
|
+
let num_units_in_tick = gb.readBits(32);
|
|
172
|
+
let time_scale = gb.readBits(32);
|
|
173
|
+
fps_fixed = gb.readBool(); // fixed_frame_rate_flag
|
|
174
|
+
|
|
175
|
+
fps_num = time_scale;
|
|
176
|
+
fps_den = num_units_in_tick * 2;
|
|
177
|
+
fps = fps_num / fps_den;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let sarScale = 1;
|
|
182
|
+
if (sar_width !== 1 || sar_height !== 1) {
|
|
183
|
+
sarScale = sar_width / sar_height;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
let crop_unit_x = 0, crop_unit_y = 0;
|
|
187
|
+
if (chroma_format_idc === 0) {
|
|
188
|
+
crop_unit_x = 1;
|
|
189
|
+
crop_unit_y = 2 - frame_mbs_only_flag;
|
|
190
|
+
} else {
|
|
191
|
+
let sub_wc = (chroma_format_idc === 3) ? 1 : 2;
|
|
192
|
+
let sub_hc = (chroma_format_idc === 1) ? 2 : 1;
|
|
193
|
+
crop_unit_x = sub_wc;
|
|
194
|
+
crop_unit_y = sub_hc * (2 - frame_mbs_only_flag);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
let codec_width = (pic_width_in_mbs_minus1 + 1) * 16;
|
|
198
|
+
let codec_height = (2 - frame_mbs_only_flag) * ((pic_height_in_map_units_minus1 + 1) * 16);
|
|
199
|
+
|
|
200
|
+
codec_width -= (frame_crop_left_offset + frame_crop_right_offset) * crop_unit_x;
|
|
201
|
+
codec_height -= (frame_crop_top_offset + frame_crop_bottom_offset) * crop_unit_y;
|
|
202
|
+
|
|
203
|
+
let present_width = Math.ceil(codec_width * sarScale);
|
|
204
|
+
|
|
205
|
+
gb.destroy();
|
|
206
|
+
gb = null;
|
|
207
|
+
|
|
208
|
+
return {
|
|
209
|
+
codec_mimetype,
|
|
210
|
+
profile_idc,
|
|
211
|
+
level_idc,
|
|
212
|
+
profile_string, // baseline, high, high10, ...
|
|
213
|
+
level_string, // 3, 3.1, 4, 4.1, 5, 5.1, ...
|
|
214
|
+
chroma_format_idc,
|
|
215
|
+
bit_depth: bit_depth_luma, // 8bit, 10bit, ...
|
|
216
|
+
bit_depth_luma,
|
|
217
|
+
bit_depth_chroma,
|
|
218
|
+
ref_frames,
|
|
219
|
+
chroma_format, // 4:2:0, 4:2:2, ...
|
|
220
|
+
chroma_format_string: SPSParser.getChromaFormatString(chroma_format),
|
|
221
|
+
|
|
222
|
+
frame_rate: {
|
|
223
|
+
fixed: fps_fixed,
|
|
224
|
+
fps: fps,
|
|
225
|
+
fps_den: fps_den,
|
|
226
|
+
fps_num: fps_num
|
|
227
|
+
},
|
|
228
|
+
|
|
229
|
+
sar_ratio: {
|
|
230
|
+
width: sar_width,
|
|
231
|
+
height: sar_height
|
|
232
|
+
},
|
|
233
|
+
|
|
234
|
+
codec_size: {
|
|
235
|
+
width: codec_width,
|
|
236
|
+
height: codec_height
|
|
237
|
+
},
|
|
238
|
+
|
|
239
|
+
present_size: {
|
|
240
|
+
width: present_width,
|
|
241
|
+
height: codec_height
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
static _skipScalingList(gb, count) {
|
|
247
|
+
let last_scale = 8, next_scale = 8;
|
|
248
|
+
let delta_scale = 0;
|
|
249
|
+
for (let i = 0; i < count; i++) {
|
|
250
|
+
if (next_scale !== 0) {
|
|
251
|
+
delta_scale = gb.readSEG();
|
|
252
|
+
next_scale = (last_scale + delta_scale + 256) % 256;
|
|
253
|
+
}
|
|
254
|
+
last_scale = (next_scale === 0) ? last_scale : next_scale;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
static getProfileString(profile_idc) {
|
|
259
|
+
switch (profile_idc) {
|
|
260
|
+
case 66:
|
|
261
|
+
return 'Baseline';
|
|
262
|
+
case 77:
|
|
263
|
+
return 'Main';
|
|
264
|
+
case 88:
|
|
265
|
+
return 'Extended';
|
|
266
|
+
case 100:
|
|
267
|
+
return 'High';
|
|
268
|
+
case 110:
|
|
269
|
+
return 'High10';
|
|
270
|
+
case 122:
|
|
271
|
+
return 'High422';
|
|
272
|
+
case 244:
|
|
273
|
+
return 'High444';
|
|
274
|
+
default:
|
|
275
|
+
return 'Unknown';
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
static getLevelString(level_idc) {
|
|
280
|
+
return (level_idc / 10).toFixed(1);
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
static getChromaFormatString(chroma) {
|
|
284
|
+
switch (chroma) {
|
|
285
|
+
case 420:
|
|
286
|
+
return '4:2:0';
|
|
287
|
+
case 422:
|
|
288
|
+
return '4:2:2';
|
|
289
|
+
case 444:
|
|
290
|
+
return '4:4:4';
|
|
291
|
+
default:
|
|
292
|
+
return 'Unknown';
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
export default SPSParser;
|