hls.js 1.5.11 → 1.5.12-0.canary.10340
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/README.md +4 -3
- package/dist/hls-demo.js +41 -38
- package/dist/hls-demo.js.map +1 -1
- package/dist/hls.js +3477 -2195
- package/dist/hls.js.d.ts +108 -85
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +2401 -1754
- package/dist/hls.light.js.map +1 -1
- package/dist/hls.light.min.js +1 -1
- package/dist/hls.light.min.js.map +1 -1
- package/dist/hls.light.mjs +2148 -1476
- package/dist/hls.light.mjs.map +1 -1
- package/dist/hls.min.js +1 -1
- package/dist/hls.min.js.map +1 -1
- package/dist/hls.mjs +2863 -1558
- package/dist/hls.mjs.map +1 -1
- package/dist/hls.worker.js +1 -1
- package/dist/hls.worker.js.map +1 -1
- package/package.json +36 -36
- package/src/config.ts +3 -2
- package/src/controller/abr-controller.ts +24 -20
- package/src/controller/audio-stream-controller.ts +68 -74
- package/src/controller/audio-track-controller.ts +1 -1
- package/src/controller/base-playlist-controller.ts +27 -10
- package/src/controller/base-stream-controller.ts +160 -38
- package/src/controller/buffer-controller.ts +230 -92
- package/src/controller/buffer-operation-queue.ts +16 -19
- package/src/controller/cap-level-controller.ts +3 -2
- package/src/controller/cmcd-controller.ts +51 -14
- package/src/controller/content-steering-controller.ts +29 -15
- package/src/controller/eme-controller.ts +10 -23
- package/src/controller/error-controller.ts +6 -8
- package/src/controller/fps-controller.ts +8 -3
- package/src/controller/fragment-tracker.ts +15 -11
- package/src/controller/gap-controller.ts +43 -16
- package/src/controller/id3-track-controller.ts +7 -7
- package/src/controller/latency-controller.ts +9 -11
- package/src/controller/level-controller.ts +37 -19
- package/src/controller/stream-controller.ts +37 -32
- package/src/controller/subtitle-stream-controller.ts +28 -40
- package/src/controller/subtitle-track-controller.ts +5 -3
- package/src/controller/timeline-controller.ts +19 -21
- package/src/crypt/aes-crypto.ts +21 -2
- package/src/crypt/decrypter-aes-mode.ts +4 -0
- package/src/crypt/decrypter.ts +32 -16
- package/src/crypt/fast-aes-key.ts +28 -5
- package/src/demux/audio/aacdemuxer.ts +2 -2
- package/src/demux/audio/ac3-demuxer.ts +4 -3
- package/src/demux/audio/adts.ts +9 -4
- package/src/demux/audio/base-audio-demuxer.ts +16 -14
- package/src/demux/audio/mp3demuxer.ts +4 -3
- package/src/demux/audio/mpegaudio.ts +1 -1
- package/src/demux/mp4demuxer.ts +7 -7
- package/src/demux/sample-aes.ts +2 -0
- package/src/demux/transmuxer-interface.ts +4 -12
- package/src/demux/transmuxer-worker.ts +4 -4
- package/src/demux/transmuxer.ts +16 -3
- package/src/demux/tsdemuxer.ts +75 -38
- package/src/demux/video/avc-video-parser.ts +208 -119
- package/src/demux/video/base-video-parser.ts +147 -18
- package/src/demux/video/exp-golomb.ts +0 -208
- package/src/demux/video/hevc-video-parser.ts +749 -0
- package/src/events.ts +8 -1
- package/src/exports-named.ts +1 -1
- package/src/hls.ts +61 -38
- package/src/loader/fragment-loader.ts +10 -3
- package/src/loader/key-loader.ts +3 -1
- package/src/loader/level-key.ts +10 -9
- package/src/loader/playlist-loader.ts +4 -5
- package/src/remux/mp4-generator.ts +196 -1
- package/src/remux/mp4-remuxer.ts +24 -8
- package/src/task-loop.ts +5 -2
- package/src/types/component-api.ts +3 -1
- package/src/types/demuxer.ts +4 -0
- package/src/types/events.ts +4 -0
- package/src/types/remuxer.ts +1 -1
- package/src/utils/buffer-helper.ts +12 -31
- package/src/utils/cea-608-parser.ts +1 -3
- package/src/utils/codecs.ts +34 -5
- package/src/utils/encryption-methods-util.ts +21 -0
- package/src/utils/fetch-loader.ts +1 -1
- package/src/utils/imsc1-ttml-parser.ts +1 -1
- package/src/utils/keysystem-util.ts +1 -6
- package/src/utils/logger.ts +58 -23
- package/src/utils/mp4-tools.ts +5 -3
- package/src/utils/utf8-utils.ts +18 -0
- package/src/utils/webvtt-parser.ts +1 -1
- package/src/demux/id3.ts +0 -411
package/src/demux/tsdemuxer.ts
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
* highly optimized TS demuxer:
|
3
3
|
* parse PAT, PMT
|
4
4
|
* extract PES packet from audio and video PIDs
|
5
|
-
* extract AVC/H264 NAL units and AAC/ADTS samples from PES packet
|
5
|
+
* extract AVC/H264 (or HEVC/H265) NAL units and AAC/ADTS samples from PES packet
|
6
6
|
* trigger the remuxer upon parsing completion
|
7
7
|
* it also tries to workaround as best as it can audio codec switch (HE-AAC to AAC and vice versa), without having to restart the MediaSource.
|
8
8
|
* it also controls the remuxing process :
|
@@ -12,7 +12,9 @@
|
|
12
12
|
import * as ADTS from './audio/adts';
|
13
13
|
import * as MpegAudio from './audio/mpegaudio';
|
14
14
|
import * as AC3 from './audio/ac3-demuxer';
|
15
|
+
import BaseVideoParser from './video/base-video-parser';
|
15
16
|
import AvcVideoParser from './video/avc-video-parser';
|
17
|
+
import HevcVideoParser from './video/hevc-video-parser';
|
16
18
|
import SampleAesDecrypter from './sample-aes';
|
17
19
|
import { Events } from '../events';
|
18
20
|
import { appendUint8Array, RemuxerTrackIdConfig } from '../utils/mp4-tools';
|
@@ -20,20 +22,21 @@ import { logger } from '../utils/logger';
|
|
20
22
|
import { ErrorTypes, ErrorDetails } from '../errors';
|
21
23
|
import type { HlsConfig } from '../config';
|
22
24
|
import type { HlsEventEmitter } from '../events';
|
25
|
+
import type { TypeSupported } from '../utils/codecs';
|
23
26
|
import {
|
24
|
-
DemuxedVideoTrack,
|
25
|
-
DemuxedAudioTrack,
|
26
|
-
DemuxedTrack,
|
27
|
-
Demuxer,
|
28
|
-
DemuxerResult,
|
29
|
-
VideoSample,
|
30
|
-
DemuxedMetadataTrack,
|
31
|
-
DemuxedUserdataTrack,
|
32
|
-
ElementaryStreamData,
|
33
|
-
KeyData,
|
34
27
|
MetadataSchema,
|
28
|
+
type DemuxedVideoTrack,
|
29
|
+
type DemuxedAudioTrack,
|
30
|
+
type DemuxedTrack,
|
31
|
+
type Demuxer,
|
32
|
+
type DemuxerResult,
|
33
|
+
type VideoSample,
|
34
|
+
type DemuxedMetadataTrack,
|
35
|
+
type DemuxedUserdataTrack,
|
36
|
+
type ElementaryStreamData,
|
37
|
+
type KeyData,
|
35
38
|
} from '../types/demuxer';
|
36
|
-
import { AudioFrame } from '../types/demuxer';
|
39
|
+
import type { AudioFrame } from '../types/demuxer';
|
37
40
|
|
38
41
|
export type ParsedTimestamp = {
|
39
42
|
pts?: number;
|
@@ -48,12 +51,6 @@ export type PES = ParsedTimestamp & {
|
|
48
51
|
export type ParsedVideoSample = ParsedTimestamp &
|
49
52
|
Omit<VideoSample, 'pts' | 'dts'>;
|
50
53
|
|
51
|
-
export interface TypeSupported {
|
52
|
-
mpeg: boolean;
|
53
|
-
mp3: boolean;
|
54
|
-
ac3: boolean;
|
55
|
-
}
|
56
|
-
|
57
54
|
const PACKET_LENGTH = 188;
|
58
55
|
|
59
56
|
class TSDemuxer implements Demuxer {
|
@@ -74,7 +71,7 @@ class TSDemuxer implements Demuxer {
|
|
74
71
|
private _txtTrack?: DemuxedUserdataTrack;
|
75
72
|
private aacOverFlow: AudioFrame | null = null;
|
76
73
|
private remainderData: Uint8Array | null = null;
|
77
|
-
private videoParser:
|
74
|
+
private videoParser: BaseVideoParser | null;
|
78
75
|
|
79
76
|
constructor(
|
80
77
|
observer: HlsEventEmitter,
|
@@ -84,7 +81,7 @@ class TSDemuxer implements Demuxer {
|
|
84
81
|
this.observer = observer;
|
85
82
|
this.config = config;
|
86
83
|
this.typeSupported = typeSupported;
|
87
|
-
this.videoParser =
|
84
|
+
this.videoParser = null;
|
88
85
|
}
|
89
86
|
|
90
87
|
static probe(data: Uint8Array) {
|
@@ -292,13 +289,27 @@ class TSDemuxer implements Demuxer {
|
|
292
289
|
case videoPid:
|
293
290
|
if (stt) {
|
294
291
|
if (videoData && (pes = parsePES(videoData))) {
|
295
|
-
this.videoParser
|
296
|
-
videoTrack
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
292
|
+
if (this.videoParser === null) {
|
293
|
+
switch (videoTrack.segmentCodec) {
|
294
|
+
case 'avc':
|
295
|
+
this.videoParser = new AvcVideoParser();
|
296
|
+
break;
|
297
|
+
case 'hevc':
|
298
|
+
if (__USE_M2TS_ADVANCED_CODECS__) {
|
299
|
+
this.videoParser = new HevcVideoParser();
|
300
|
+
}
|
301
|
+
break;
|
302
|
+
}
|
303
|
+
}
|
304
|
+
if (this.videoParser !== null) {
|
305
|
+
this.videoParser.parsePES(
|
306
|
+
videoTrack,
|
307
|
+
textTrack,
|
308
|
+
pes,
|
309
|
+
false,
|
310
|
+
this._duration,
|
311
|
+
);
|
312
|
+
}
|
302
313
|
}
|
303
314
|
|
304
315
|
videoData = { data: [], size: 0 };
|
@@ -467,14 +478,28 @@ class TSDemuxer implements Demuxer {
|
|
467
478
|
// try to parse last PES packets
|
468
479
|
let pes: PES | null;
|
469
480
|
if (videoData && (pes = parsePES(videoData))) {
|
470
|
-
this.videoParser
|
471
|
-
videoTrack
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
481
|
+
if (this.videoParser === null) {
|
482
|
+
switch (videoTrack.segmentCodec) {
|
483
|
+
case 'avc':
|
484
|
+
this.videoParser = new AvcVideoParser();
|
485
|
+
break;
|
486
|
+
case 'hevc':
|
487
|
+
if (__USE_M2TS_ADVANCED_CODECS__) {
|
488
|
+
this.videoParser = new HevcVideoParser();
|
489
|
+
}
|
490
|
+
break;
|
491
|
+
}
|
492
|
+
}
|
493
|
+
if (this.videoParser !== null) {
|
494
|
+
this.videoParser.parsePES(
|
495
|
+
videoTrack as DemuxedVideoTrack,
|
496
|
+
textTrack as DemuxedUserdataTrack,
|
497
|
+
pes,
|
498
|
+
true,
|
499
|
+
this._duration,
|
500
|
+
);
|
501
|
+
videoTrack.pesData = null;
|
502
|
+
}
|
478
503
|
} else {
|
479
504
|
// either avcData null or PES truncated, keep it for next frag parsing
|
480
505
|
videoTrack.pesData = videoData;
|
@@ -864,9 +889,21 @@ function parsePMT(
|
|
864
889
|
emitParsingError(observer, new Error('Unsupported EC-3 in M2TS found'));
|
865
890
|
return result;
|
866
891
|
|
867
|
-
case 0x24:
|
868
|
-
|
869
|
-
|
892
|
+
case 0x24: // ITU-T Rec. H.265 and ISO/IEC 23008-2 (HEVC)
|
893
|
+
if (__USE_M2TS_ADVANCED_CODECS__) {
|
894
|
+
if (result.videoPid === -1) {
|
895
|
+
result.videoPid = pid;
|
896
|
+
result.segmentVideoCodec = 'hevc';
|
897
|
+
logger.log('HEVC in M2TS found');
|
898
|
+
}
|
899
|
+
} else {
|
900
|
+
emitParsingError(
|
901
|
+
observer,
|
902
|
+
new Error('Unsupported HEVC in M2TS found'),
|
903
|
+
);
|
904
|
+
return result;
|
905
|
+
}
|
906
|
+
break;
|
870
907
|
|
871
908
|
default:
|
872
909
|
// logger.log('unknown stream type:' + data[offset]);
|
@@ -1,25 +1,23 @@
|
|
1
1
|
import BaseVideoParser from './base-video-parser';
|
2
|
-
import {
|
2
|
+
import type {
|
3
3
|
DemuxedVideoTrack,
|
4
4
|
DemuxedUserdataTrack,
|
5
|
-
VideoSampleUnit,
|
6
5
|
} from '../../types/demuxer';
|
7
|
-
import {
|
8
|
-
|
9
|
-
parseSEIMessageFromNALu,
|
10
|
-
} from '../../utils/mp4-tools';
|
11
|
-
import ExpGolomb from './exp-golomb';
|
6
|
+
import { parseSEIMessageFromNALu } from '../../utils/mp4-tools';
|
7
|
+
|
12
8
|
import type { PES } from '../tsdemuxer';
|
13
9
|
|
10
|
+
import ExpGolomb from './exp-golomb';
|
11
|
+
|
14
12
|
class AvcVideoParser extends BaseVideoParser {
|
15
|
-
public
|
13
|
+
public parsePES(
|
16
14
|
track: DemuxedVideoTrack,
|
17
15
|
textTrack: DemuxedUserdataTrack,
|
18
16
|
pes: PES,
|
19
17
|
last: boolean,
|
20
18
|
duration: number,
|
21
19
|
) {
|
22
|
-
const units = this.
|
20
|
+
const units = this.parseNALu(track, pes.data, last);
|
23
21
|
const debug = false;
|
24
22
|
let VideoSample = this.VideoSample;
|
25
23
|
let push: boolean;
|
@@ -49,7 +47,7 @@ class AvcVideoParser extends BaseVideoParser {
|
|
49
47
|
// only check slice type to detect KF in case SPS found in same packet (any keyframe is preceded by SPS ...)
|
50
48
|
if (spsfound && data.length > 4) {
|
51
49
|
// retrieve slice type by parsing beginning of NAL unit (follow H264 spec, slice_header definition) to detect keyframe embedded in NDR
|
52
|
-
const sliceType =
|
50
|
+
const sliceType = this.readSliceType(data);
|
53
51
|
// 2 : I slice, 4 : SI slice, 7 : I slice, 9: SI slice
|
54
52
|
// SI slice : A slice that is coded using intra prediction only and using quantisation of the prediction samples.
|
55
53
|
// An SI slice can be coded such that its decoded samples can be constructed identically to an SP slice.
|
@@ -138,9 +136,7 @@ class AvcVideoParser extends BaseVideoParser {
|
|
138
136
|
VideoSample.debug += 'SPS ';
|
139
137
|
}
|
140
138
|
const sps = unit.data;
|
141
|
-
const
|
142
|
-
const config = expGolombDecoder.readSPS();
|
143
|
-
|
139
|
+
const config = this.readSPS(sps);
|
144
140
|
if (
|
145
141
|
!track.sps ||
|
146
142
|
track.width !== config.width ||
|
@@ -165,7 +161,6 @@ class AvcVideoParser extends BaseVideoParser {
|
|
165
161
|
}
|
166
162
|
track.codec = codecstring;
|
167
163
|
}
|
168
|
-
|
169
164
|
break;
|
170
165
|
}
|
171
166
|
// PPS
|
@@ -217,123 +212,217 @@ class AvcVideoParser extends BaseVideoParser {
|
|
217
212
|
}
|
218
213
|
}
|
219
214
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
): Array<{
|
224
|
-
data: Uint8Array;
|
225
|
-
type: number;
|
226
|
-
state?: number;
|
227
|
-
}> {
|
228
|
-
const len = array.byteLength;
|
229
|
-
let state = track.naluState || 0;
|
230
|
-
const lastState = state;
|
231
|
-
const units: VideoSampleUnit[] = [];
|
232
|
-
let i = 0;
|
233
|
-
let value: number;
|
234
|
-
let overflow: number;
|
235
|
-
let unitType: number;
|
236
|
-
let lastUnitStart = -1;
|
237
|
-
let lastUnitType: number = 0;
|
238
|
-
// logger.log('PES:' + Hex.hexDump(array));
|
215
|
+
protected getNALuType(data: Uint8Array, offset: number): number {
|
216
|
+
return data[offset] & 0x1f;
|
217
|
+
}
|
239
218
|
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
219
|
+
readSliceType(data: Uint8Array) {
|
220
|
+
const eg = new ExpGolomb(data);
|
221
|
+
// skip NALu type
|
222
|
+
eg.readUByte();
|
223
|
+
// discard first_mb_in_slice
|
224
|
+
eg.readUEG();
|
225
|
+
// return slice_type
|
226
|
+
return eg.readUEG();
|
227
|
+
}
|
248
228
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
229
|
+
/**
|
230
|
+
* The scaling list is optionally transmitted as part of a sequence parameter
|
231
|
+
* set and is not relevant to transmuxing.
|
232
|
+
* @param count the number of entries in this scaling list
|
233
|
+
* @see Recommendation ITU-T H.264, Section 7.3.2.1.1.1
|
234
|
+
*/
|
235
|
+
skipScalingList(count: number, reader: ExpGolomb): void {
|
236
|
+
let lastScale = 8;
|
237
|
+
let nextScale = 8;
|
238
|
+
let deltaScale;
|
239
|
+
for (let j = 0; j < count; j++) {
|
240
|
+
if (nextScale !== 0) {
|
241
|
+
deltaScale = reader.readEG();
|
242
|
+
nextScale = (lastScale + deltaScale + 256) % 256;
|
259
243
|
}
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
244
|
+
lastScale = nextScale === 0 ? lastScale : nextScale;
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
/**
|
249
|
+
* Read a sequence parameter set and return some interesting video
|
250
|
+
* properties. A sequence parameter set is the H264 metadata that
|
251
|
+
* describes the properties of upcoming video frames.
|
252
|
+
* @returns an object with configuration parsed from the
|
253
|
+
* sequence parameter set, including the dimensions of the
|
254
|
+
* associated video frames.
|
255
|
+
*/
|
256
|
+
readSPS(sps: Uint8Array): {
|
257
|
+
width: number;
|
258
|
+
height: number;
|
259
|
+
pixelRatio: [number, number];
|
260
|
+
} {
|
261
|
+
const eg = new ExpGolomb(sps);
|
262
|
+
let frameCropLeftOffset = 0;
|
263
|
+
let frameCropRightOffset = 0;
|
264
|
+
let frameCropTopOffset = 0;
|
265
|
+
let frameCropBottomOffset = 0;
|
266
|
+
let numRefFramesInPicOrderCntCycle;
|
267
|
+
let scalingListCount;
|
268
|
+
let i;
|
269
|
+
const readUByte = eg.readUByte.bind(eg);
|
270
|
+
const readBits = eg.readBits.bind(eg);
|
271
|
+
const readUEG = eg.readUEG.bind(eg);
|
272
|
+
const readBoolean = eg.readBoolean.bind(eg);
|
273
|
+
const skipBits = eg.skipBits.bind(eg);
|
274
|
+
const skipEG = eg.skipEG.bind(eg);
|
275
|
+
const skipUEG = eg.skipUEG.bind(eg);
|
276
|
+
const skipScalingList = this.skipScalingList.bind(this);
|
277
|
+
|
278
|
+
readUByte();
|
279
|
+
const profileIdc = readUByte(); // profile_idc
|
280
|
+
readBits(5); // profileCompat constraint_set[0-4]_flag, u(5)
|
281
|
+
skipBits(3); // reserved_zero_3bits u(3),
|
282
|
+
readUByte(); // level_idc u(8)
|
283
|
+
skipUEG(); // seq_parameter_set_id
|
284
|
+
// some profiles have more optional data we don't need
|
285
|
+
if (
|
286
|
+
profileIdc === 100 ||
|
287
|
+
profileIdc === 110 ||
|
288
|
+
profileIdc === 122 ||
|
289
|
+
profileIdc === 244 ||
|
290
|
+
profileIdc === 44 ||
|
291
|
+
profileIdc === 83 ||
|
292
|
+
profileIdc === 86 ||
|
293
|
+
profileIdc === 118 ||
|
294
|
+
profileIdc === 128
|
295
|
+
) {
|
296
|
+
const chromaFormatIdc = readUEG();
|
297
|
+
if (chromaFormatIdc === 3) {
|
298
|
+
skipBits(1);
|
299
|
+
} // separate_colour_plane_flag
|
292
300
|
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
301
|
+
skipUEG(); // bit_depth_luma_minus8
|
302
|
+
skipUEG(); // bit_depth_chroma_minus8
|
303
|
+
skipBits(1); // qpprime_y_zero_transform_bypass_flag
|
304
|
+
if (readBoolean()) {
|
305
|
+
// seq_scaling_matrix_present_flag
|
306
|
+
scalingListCount = chromaFormatIdc !== 3 ? 8 : 12;
|
307
|
+
for (i = 0; i < scalingListCount; i++) {
|
308
|
+
if (readBoolean()) {
|
309
|
+
// seq_scaling_list_present_flag[ i ]
|
310
|
+
if (i < 6) {
|
311
|
+
skipScalingList(16, eg);
|
312
|
+
} else {
|
313
|
+
skipScalingList(64, eg);
|
300
314
|
}
|
301
315
|
}
|
302
316
|
}
|
303
|
-
// check if we can read unit type
|
304
|
-
if (i < len) {
|
305
|
-
unitType = array[i] & 0x1f;
|
306
|
-
// logger.log('find NALU @ offset:' + i + ',type:' + unitType);
|
307
|
-
lastUnitStart = i;
|
308
|
-
lastUnitType = unitType;
|
309
|
-
state = 0;
|
310
|
-
} else {
|
311
|
-
// not enough byte to read unit type. let's read it on next PES parsing
|
312
|
-
state = -1;
|
313
|
-
}
|
314
|
-
} else {
|
315
|
-
state = 0;
|
316
317
|
}
|
317
318
|
}
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
319
|
+
skipUEG(); // log2_max_frame_num_minus4
|
320
|
+
const picOrderCntType = readUEG();
|
321
|
+
if (picOrderCntType === 0) {
|
322
|
+
readUEG(); // log2_max_pic_order_cnt_lsb_minus4
|
323
|
+
} else if (picOrderCntType === 1) {
|
324
|
+
skipBits(1); // delta_pic_order_always_zero_flag
|
325
|
+
skipEG(); // offset_for_non_ref_pic
|
326
|
+
skipEG(); // offset_for_top_to_bottom_field
|
327
|
+
numRefFramesInPicOrderCntCycle = readUEG();
|
328
|
+
for (i = 0; i < numRefFramesInPicOrderCntCycle; i++) {
|
329
|
+
skipEG();
|
330
|
+
} // offset_for_ref_frame[ i ]
|
331
|
+
}
|
332
|
+
skipUEG(); // max_num_ref_frames
|
333
|
+
skipBits(1); // gaps_in_frame_num_value_allowed_flag
|
334
|
+
const picWidthInMbsMinus1 = readUEG();
|
335
|
+
const picHeightInMapUnitsMinus1 = readUEG();
|
336
|
+
const frameMbsOnlyFlag = readBits(1);
|
337
|
+
if (frameMbsOnlyFlag === 0) {
|
338
|
+
skipBits(1);
|
339
|
+
} // mb_adaptive_frame_field_flag
|
340
|
+
|
341
|
+
skipBits(1); // direct_8x8_inference_flag
|
342
|
+
if (readBoolean()) {
|
343
|
+
// frame_cropping_flag
|
344
|
+
frameCropLeftOffset = readUEG();
|
345
|
+
frameCropRightOffset = readUEG();
|
346
|
+
frameCropTopOffset = readUEG();
|
347
|
+
frameCropBottomOffset = readUEG();
|
326
348
|
}
|
327
|
-
|
328
|
-
if (
|
329
|
-
//
|
330
|
-
|
331
|
-
|
332
|
-
|
349
|
+
let pixelRatio: [number, number] = [1, 1];
|
350
|
+
if (readBoolean()) {
|
351
|
+
// vui_parameters_present_flag
|
352
|
+
if (readBoolean()) {
|
353
|
+
// aspect_ratio_info_present_flag
|
354
|
+
const aspectRatioIdc = readUByte();
|
355
|
+
switch (aspectRatioIdc) {
|
356
|
+
case 1:
|
357
|
+
pixelRatio = [1, 1];
|
358
|
+
break;
|
359
|
+
case 2:
|
360
|
+
pixelRatio = [12, 11];
|
361
|
+
break;
|
362
|
+
case 3:
|
363
|
+
pixelRatio = [10, 11];
|
364
|
+
break;
|
365
|
+
case 4:
|
366
|
+
pixelRatio = [16, 11];
|
367
|
+
break;
|
368
|
+
case 5:
|
369
|
+
pixelRatio = [40, 33];
|
370
|
+
break;
|
371
|
+
case 6:
|
372
|
+
pixelRatio = [24, 11];
|
373
|
+
break;
|
374
|
+
case 7:
|
375
|
+
pixelRatio = [20, 11];
|
376
|
+
break;
|
377
|
+
case 8:
|
378
|
+
pixelRatio = [32, 11];
|
379
|
+
break;
|
380
|
+
case 9:
|
381
|
+
pixelRatio = [80, 33];
|
382
|
+
break;
|
383
|
+
case 10:
|
384
|
+
pixelRatio = [18, 11];
|
385
|
+
break;
|
386
|
+
case 11:
|
387
|
+
pixelRatio = [15, 11];
|
388
|
+
break;
|
389
|
+
case 12:
|
390
|
+
pixelRatio = [64, 33];
|
391
|
+
break;
|
392
|
+
case 13:
|
393
|
+
pixelRatio = [160, 99];
|
394
|
+
break;
|
395
|
+
case 14:
|
396
|
+
pixelRatio = [4, 3];
|
397
|
+
break;
|
398
|
+
case 15:
|
399
|
+
pixelRatio = [3, 2];
|
400
|
+
break;
|
401
|
+
case 16:
|
402
|
+
pixelRatio = [2, 1];
|
403
|
+
break;
|
404
|
+
case 255: {
|
405
|
+
pixelRatio = [
|
406
|
+
(readUByte() << 8) | readUByte(),
|
407
|
+
(readUByte() << 8) | readUByte(),
|
408
|
+
];
|
409
|
+
break;
|
410
|
+
}
|
411
|
+
}
|
333
412
|
}
|
334
413
|
}
|
335
|
-
|
336
|
-
|
414
|
+
return {
|
415
|
+
width: Math.ceil(
|
416
|
+
(picWidthInMbsMinus1 + 1) * 16 -
|
417
|
+
frameCropLeftOffset * 2 -
|
418
|
+
frameCropRightOffset * 2,
|
419
|
+
),
|
420
|
+
height:
|
421
|
+
(2 - frameMbsOnlyFlag) * (picHeightInMapUnitsMinus1 + 1) * 16 -
|
422
|
+
(frameMbsOnlyFlag ? 2 : 4) *
|
423
|
+
(frameCropTopOffset + frameCropBottomOffset),
|
424
|
+
pixelRatio: pixelRatio,
|
425
|
+
};
|
337
426
|
}
|
338
427
|
}
|
339
428
|
|