hls.js 1.6.0-beta.2.0.canary.10871 → 1.6.0-beta.2.0.canary.10876
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/dist/hls.js +74 -60
- package/dist/hls.js.map +1 -1
- package/dist/hls.light.js +65 -131
- 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 +67 -133
- 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 +76 -62
- 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 +1 -1
- package/src/demux/audio/base-audio-demuxer.ts +6 -6
- package/src/demux/tsdemuxer.ts +2 -3
- package/src/demux/video/hevc-video-parser.ts +12 -12
- package/src/remux/mp4-generator.ts +99 -45
- package/src/remux/mp4-remuxer.ts +24 -38
- package/src/types/demuxer.ts +41 -1
- package/src/types/remuxer.ts +25 -0
- package/src/utils/fetch-loader.ts +12 -8
- package/src/utils/xhr-loader.ts +4 -11
package/package.json
CHANGED
@@ -18,8 +18,8 @@ import { dummyTrack } from '../dummy-demuxed-track';
|
|
18
18
|
import type { RationalTimestamp } from '../../utils/timescale-conversion';
|
19
19
|
|
20
20
|
class BaseAudioDemuxer implements Demuxer {
|
21
|
-
protected _audioTrack
|
22
|
-
protected _id3Track
|
21
|
+
protected _audioTrack?: DemuxedAudioTrack;
|
22
|
+
protected _id3Track?: DemuxedMetadataTrack;
|
23
23
|
protected frameIndex: number = 0;
|
24
24
|
protected cachedData: Uint8Array | null = null;
|
25
25
|
protected basePTS: number | null = null;
|
@@ -74,8 +74,8 @@ class BaseAudioDemuxer implements Demuxer {
|
|
74
74
|
let id3Data: Uint8Array | undefined = getId3Data(data, 0);
|
75
75
|
let offset = id3Data ? id3Data.length : 0;
|
76
76
|
let lastDataIndex;
|
77
|
-
const track = this._audioTrack;
|
78
|
-
const id3Track = this._id3Track;
|
77
|
+
const track = this._audioTrack as DemuxedAudioTrack;
|
78
|
+
const id3Track = this._id3Track as DemuxedMetadataTrack;
|
79
79
|
const timestamp = id3Data ? getId3Timestamp(id3Data) : undefined;
|
80
80
|
const length = data.length;
|
81
81
|
|
@@ -167,9 +167,9 @@ class BaseAudioDemuxer implements Demuxer {
|
|
167
167
|
}
|
168
168
|
|
169
169
|
return {
|
170
|
-
audioTrack: this._audioTrack,
|
170
|
+
audioTrack: this._audioTrack as DemuxedAudioTrack,
|
171
171
|
videoTrack: dummyTrack() as DemuxedVideoTrackBase,
|
172
|
-
id3Track: this._id3Track,
|
172
|
+
id3Track: this._id3Track as DemuxedMetadataTrack,
|
173
173
|
textTrack: dummyTrack() as DemuxedUserdataTrack,
|
174
174
|
};
|
175
175
|
}
|
package/src/demux/tsdemuxer.ts
CHANGED
@@ -774,8 +774,8 @@ function parsePMT(
|
|
774
774
|
audioPid: -1,
|
775
775
|
videoPid: -1,
|
776
776
|
id3Pid: -1,
|
777
|
-
segmentVideoCodec: 'avc',
|
778
|
-
segmentAudioCodec: 'aac',
|
777
|
+
segmentVideoCodec: 'avc' as 'avc' | 'hevc',
|
778
|
+
segmentAudioCodec: 'aac' as 'aac' | 'ac3' | 'mp3',
|
779
779
|
};
|
780
780
|
const sectionLength = ((data[offset + 1] & 0x0f) << 8) | data[offset + 2];
|
781
781
|
const tableEnd = offset + 3 + sectionLength - 4;
|
@@ -822,7 +822,6 @@ function parsePMT(
|
|
822
822
|
// logger.log('AVC PID:' + pid);
|
823
823
|
if (result.videoPid === -1) {
|
824
824
|
result.videoPid = pid;
|
825
|
-
result.segmentVideoCodec = 'avc';
|
826
825
|
}
|
827
826
|
|
828
827
|
break;
|
@@ -158,12 +158,7 @@ class HevcVideoParser extends BaseVideoParser {
|
|
158
158
|
track.params[prop] = config.params[prop];
|
159
159
|
}
|
160
160
|
}
|
161
|
-
|
162
|
-
(!track.vps && !track.sps.length) ||
|
163
|
-
(track.vps && track.vps[0] === this.initVPS)
|
164
|
-
) {
|
165
|
-
track.sps.push(unit.data);
|
166
|
-
}
|
161
|
+
this.pushParameterSet(track.sps, unit.data, track.vps);
|
167
162
|
if (!VideoSample) {
|
168
163
|
VideoSample = this.VideoSample = this.createVideoSample(
|
169
164
|
true,
|
@@ -185,12 +180,7 @@ class HevcVideoParser extends BaseVideoParser {
|
|
185
180
|
track.params[prop] = config[prop];
|
186
181
|
}
|
187
182
|
}
|
188
|
-
|
189
|
-
(!track.vps && !track.pps.length) ||
|
190
|
-
(track.vps && track.vps[0] === this.initVPS)
|
191
|
-
) {
|
192
|
-
track.pps.push(unit.data);
|
193
|
-
}
|
183
|
+
this.pushParameterSet(track.pps, unit.data, track.vps);
|
194
184
|
}
|
195
185
|
break;
|
196
186
|
|
@@ -227,6 +217,16 @@ class HevcVideoParser extends BaseVideoParser {
|
|
227
217
|
}
|
228
218
|
}
|
229
219
|
|
220
|
+
private pushParameterSet(
|
221
|
+
parameterSets: Uint8Array[],
|
222
|
+
data: Uint8Array,
|
223
|
+
vps: Uint8Array[] | undefined,
|
224
|
+
) {
|
225
|
+
if ((vps && vps[0] === this.initVPS) || (!vps && !parameterSets.length)) {
|
226
|
+
parameterSets.push(data);
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
230
|
protected getNALuType(data: Uint8Array, offset: number): number {
|
231
231
|
return (data[offset] & 0x7e) >>> 1;
|
232
232
|
}
|
@@ -3,7 +3,21 @@
|
|
3
3
|
*/
|
4
4
|
|
5
5
|
import { appendUint8Array } from '../utils/mp4-tools';
|
6
|
-
import type {
|
6
|
+
import type {
|
7
|
+
DemuxedAC3,
|
8
|
+
DemuxedAudioTrack,
|
9
|
+
DemuxedAVC1,
|
10
|
+
DemuxedHEVC,
|
11
|
+
DemuxedVideoTrack,
|
12
|
+
} from '../types/demuxer';
|
13
|
+
import type {
|
14
|
+
Mp4SampleFlags,
|
15
|
+
RemuxedAudioTrackSamples,
|
16
|
+
RemuxedVideoTrackSamples,
|
17
|
+
} from '../types/remuxer';
|
18
|
+
|
19
|
+
type MediaTrackType = DemuxedAudioTrack | DemuxedVideoTrack;
|
20
|
+
type RemuxedTrackType = RemuxedAudioTrackSamples | RemuxedVideoTrackSamples;
|
7
21
|
|
8
22
|
type HdlrTypes = {
|
9
23
|
video: Uint8Array;
|
@@ -266,7 +280,7 @@ class MP4 {
|
|
266
280
|
MP4.DINF = MP4.box(MP4.types.dinf, MP4.box(MP4.types.dref, dref));
|
267
281
|
}
|
268
282
|
|
269
|
-
static box(type, ...payload: Uint8Array[]) {
|
283
|
+
static box(type: number[], ...payload: Uint8Array[]) {
|
270
284
|
let size = 8;
|
271
285
|
let i = payload.length;
|
272
286
|
const len = i;
|
@@ -290,15 +304,15 @@ class MP4 {
|
|
290
304
|
return result;
|
291
305
|
}
|
292
306
|
|
293
|
-
static hdlr(type) {
|
307
|
+
static hdlr(type: keyof HdlrTypes) {
|
294
308
|
return MP4.box(MP4.types.hdlr, MP4.HDLR_TYPES[type]);
|
295
309
|
}
|
296
310
|
|
297
|
-
static mdat(data) {
|
311
|
+
static mdat(data: Uint8Array) {
|
298
312
|
return MP4.box(MP4.types.mdat, data);
|
299
313
|
}
|
300
314
|
|
301
|
-
static mdhd(timescale, duration) {
|
315
|
+
static mdhd(timescale: number, duration: number) {
|
302
316
|
duration *= timescale;
|
303
317
|
const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));
|
304
318
|
const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));
|
@@ -345,16 +359,16 @@ class MP4 {
|
|
345
359
|
);
|
346
360
|
}
|
347
361
|
|
348
|
-
static mdia(track) {
|
362
|
+
static mdia(track: MediaTrackType) {
|
349
363
|
return MP4.box(
|
350
364
|
MP4.types.mdia,
|
351
|
-
MP4.mdhd(track.timescale, track.duration),
|
365
|
+
MP4.mdhd(track.timescale || 0, track.duration || 0),
|
352
366
|
MP4.hdlr(track.type),
|
353
367
|
MP4.minf(track),
|
354
368
|
);
|
355
369
|
}
|
356
370
|
|
357
|
-
static mfhd(sequenceNumber) {
|
371
|
+
static mfhd(sequenceNumber: number) {
|
358
372
|
return MP4.box(
|
359
373
|
MP4.types.mfhd,
|
360
374
|
new Uint8Array([
|
@@ -370,7 +384,7 @@ class MP4 {
|
|
370
384
|
);
|
371
385
|
}
|
372
386
|
|
373
|
-
static minf(track) {
|
387
|
+
static minf(track: MediaTrackType) {
|
374
388
|
if (track.type === 'audio') {
|
375
389
|
return MP4.box(
|
376
390
|
MP4.types.minf,
|
@@ -388,7 +402,11 @@ class MP4 {
|
|
388
402
|
}
|
389
403
|
}
|
390
404
|
|
391
|
-
static moof(
|
405
|
+
static moof(
|
406
|
+
sn: number,
|
407
|
+
baseMediaDecodeTime: number,
|
408
|
+
track: RemuxedTrackType,
|
409
|
+
) {
|
392
410
|
return MP4.box(
|
393
411
|
MP4.types.moof,
|
394
412
|
MP4.mfhd(sn),
|
@@ -396,7 +414,7 @@ class MP4 {
|
|
396
414
|
);
|
397
415
|
}
|
398
416
|
|
399
|
-
static moov(tracks) {
|
417
|
+
static moov(tracks: MediaTrackType[]) {
|
400
418
|
let i = tracks.length;
|
401
419
|
const boxes: Uint8Array[] = [];
|
402
420
|
|
@@ -406,13 +424,16 @@ class MP4 {
|
|
406
424
|
|
407
425
|
return MP4.box.apply(
|
408
426
|
null,
|
409
|
-
[
|
427
|
+
[
|
428
|
+
MP4.types.moov,
|
429
|
+
MP4.mvhd(tracks[0].timescale || 0, tracks[0].duration || 0),
|
430
|
+
]
|
410
431
|
.concat(boxes)
|
411
432
|
.concat(MP4.mvex(tracks)),
|
412
433
|
);
|
413
434
|
}
|
414
435
|
|
415
|
-
static mvex(tracks) {
|
436
|
+
static mvex(tracks: MediaTrackType[]) {
|
416
437
|
let i = tracks.length;
|
417
438
|
const boxes: Uint8Array[] = [];
|
418
439
|
|
@@ -423,7 +444,7 @@ class MP4 {
|
|
423
444
|
return MP4.box.apply(null, [MP4.types.mvex, ...boxes]);
|
424
445
|
}
|
425
446
|
|
426
|
-
static mvhd(timescale, duration) {
|
447
|
+
static mvhd(timescale: number, duration: number) {
|
427
448
|
duration *= timescale;
|
428
449
|
const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));
|
429
450
|
const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));
|
@@ -544,11 +565,11 @@ class MP4 {
|
|
544
565
|
return MP4.box(MP4.types.mvhd, bytes);
|
545
566
|
}
|
546
567
|
|
547
|
-
static sdtp(track) {
|
568
|
+
static sdtp(track: RemuxedTrackType) {
|
548
569
|
const samples = track.samples || [];
|
549
570
|
const bytes = new Uint8Array(4 + samples.length);
|
550
|
-
let i;
|
551
|
-
let flags;
|
571
|
+
let i: number;
|
572
|
+
let flags: Mp4SampleFlags;
|
552
573
|
// leave the full box header (4 bytes) all zero
|
553
574
|
// write the sample table
|
554
575
|
for (i = 0; i < samples.length; i++) {
|
@@ -562,7 +583,7 @@ class MP4 {
|
|
562
583
|
return MP4.box(MP4.types.sdtp, bytes);
|
563
584
|
}
|
564
585
|
|
565
|
-
static stbl(track) {
|
586
|
+
static stbl(track: MediaTrackType) {
|
566
587
|
return MP4.box(
|
567
588
|
MP4.types.stbl,
|
568
589
|
MP4.stsd(track),
|
@@ -573,7 +594,7 @@ class MP4 {
|
|
573
594
|
);
|
574
595
|
}
|
575
596
|
|
576
|
-
static avc1(track) {
|
597
|
+
static avc1(track: DemuxedAVC1) {
|
577
598
|
let sps: number[] = [];
|
578
599
|
let pps: number[] = [];
|
579
600
|
let i;
|
@@ -781,8 +802,8 @@ class MP4 {
|
|
781
802
|
]);
|
782
803
|
}
|
783
804
|
|
784
|
-
static audioStsd(track) {
|
785
|
-
const samplerate = track.samplerate;
|
805
|
+
static audioStsd(track: DemuxedAudioTrack) {
|
806
|
+
const samplerate = track.samplerate || 0;
|
786
807
|
return new Uint8Array([
|
787
808
|
0x00,
|
788
809
|
0x00,
|
@@ -801,7 +822,7 @@ class MP4 {
|
|
801
822
|
0x00,
|
802
823
|
0x00, // reserved
|
803
824
|
0x00,
|
804
|
-
track.channelCount, // channelcount
|
825
|
+
track.channelCount || 0, // channelcount
|
805
826
|
0x00,
|
806
827
|
0x10, // sampleSize:16bits
|
807
828
|
0x00,
|
@@ -815,7 +836,7 @@ class MP4 {
|
|
815
836
|
]);
|
816
837
|
}
|
817
838
|
|
818
|
-
static mp4a(track) {
|
839
|
+
static mp4a(track: DemuxedAudioTrack) {
|
819
840
|
return MP4.box(
|
820
841
|
MP4.types.mp4a,
|
821
842
|
MP4.audioStsd(track),
|
@@ -823,39 +844,69 @@ class MP4 {
|
|
823
844
|
);
|
824
845
|
}
|
825
846
|
|
826
|
-
static mp3(track) {
|
847
|
+
static mp3(track: DemuxedAudioTrack) {
|
827
848
|
return MP4.box(MP4.types['.mp3'], MP4.audioStsd(track));
|
828
849
|
}
|
829
850
|
|
830
|
-
static ac3(track) {
|
851
|
+
static ac3(track: DemuxedAudioTrack) {
|
831
852
|
return MP4.box(
|
832
853
|
MP4.types['ac-3'],
|
833
854
|
MP4.audioStsd(track),
|
834
|
-
MP4.box(MP4.types.dac3, track.config),
|
855
|
+
MP4.box(MP4.types.dac3, track.config as Uint8Array),
|
835
856
|
);
|
836
857
|
}
|
837
858
|
|
838
|
-
static stsd(track) {
|
859
|
+
static stsd(track: MediaTrackType | DemuxedAC3): Uint8Array {
|
860
|
+
const { segmentCodec } = track;
|
839
861
|
if (track.type === 'audio') {
|
840
|
-
if (
|
841
|
-
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.
|
862
|
+
if (segmentCodec === 'aac') {
|
863
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp4a(track));
|
842
864
|
}
|
843
|
-
if (
|
865
|
+
if (
|
866
|
+
__USE_M2TS_ADVANCED_CODECS__ &&
|
867
|
+
segmentCodec === 'ac3' &&
|
868
|
+
track.config
|
869
|
+
) {
|
844
870
|
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.ac3(track));
|
845
871
|
}
|
846
|
-
|
847
|
-
|
848
|
-
|
872
|
+
if (segmentCodec === 'mp3' && track.codec === 'mp3') {
|
873
|
+
return MP4.box(MP4.types.stsd, MP4.STSD, MP4.mp3(track));
|
874
|
+
}
|
849
875
|
} else {
|
850
|
-
|
876
|
+
if (track.pps && track.sps) {
|
877
|
+
if (segmentCodec === 'avc') {
|
878
|
+
return MP4.box(
|
879
|
+
MP4.types.stsd,
|
880
|
+
MP4.STSD,
|
881
|
+
MP4.avc1(track as DemuxedAVC1),
|
882
|
+
);
|
883
|
+
}
|
884
|
+
if (
|
885
|
+
__USE_M2TS_ADVANCED_CODECS__ &&
|
886
|
+
segmentCodec === 'hevc' &&
|
887
|
+
track.vps
|
888
|
+
) {
|
889
|
+
return MP4.box(
|
890
|
+
MP4.types.stsd,
|
891
|
+
MP4.STSD,
|
892
|
+
MP4.hvc1(track as DemuxedHEVC),
|
893
|
+
);
|
894
|
+
}
|
895
|
+
} else {
|
896
|
+
throw new Error(`video track missing pps or sps`);
|
897
|
+
}
|
851
898
|
}
|
899
|
+
|
900
|
+
throw new Error(
|
901
|
+
`unsupported ${track.type} segment codec (${segmentCodec}/${track.codec})`,
|
902
|
+
);
|
852
903
|
}
|
853
904
|
|
854
|
-
static tkhd(track) {
|
905
|
+
static tkhd(track: MediaTrackType) {
|
855
906
|
const id = track.id;
|
856
|
-
const duration = track.duration * track.timescale;
|
857
|
-
const width = track.width;
|
858
|
-
const height = track.height;
|
907
|
+
const duration = (track.duration || 0) * (track.timescale || 0);
|
908
|
+
const width = (track as any).width || 0;
|
909
|
+
const height = (track as any).height || 0;
|
859
910
|
const upperWordDuration = Math.floor(duration / (UINT32_MAX + 1));
|
860
911
|
const lowerWordDuration = Math.floor(duration % (UINT32_MAX + 1));
|
861
912
|
return MP4.box(
|
@@ -961,7 +1012,7 @@ class MP4 {
|
|
961
1012
|
);
|
962
1013
|
}
|
963
1014
|
|
964
|
-
static traf(track, baseMediaDecodeTime) {
|
1015
|
+
static traf(track: RemuxedTrackType, baseMediaDecodeTime: number) {
|
965
1016
|
const sampleDependencyTable = MP4.sdtp(track);
|
966
1017
|
const id = track.id;
|
967
1018
|
const upperWordBaseMediaDecodeTime = Math.floor(
|
@@ -1020,12 +1071,12 @@ class MP4 {
|
|
1020
1071
|
* Generate a track box.
|
1021
1072
|
* @param track a track definition
|
1022
1073
|
*/
|
1023
|
-
static trak(track) {
|
1074
|
+
static trak(track: MediaTrackType) {
|
1024
1075
|
track.duration = track.duration || 0xffffffff;
|
1025
1076
|
return MP4.box(MP4.types.trak, MP4.tkhd(track), MP4.mdia(track));
|
1026
1077
|
}
|
1027
1078
|
|
1028
|
-
static trex(track) {
|
1079
|
+
static trex(track: MediaTrackType) {
|
1029
1080
|
const id = track.id;
|
1030
1081
|
return MP4.box(
|
1031
1082
|
MP4.types.trex,
|
@@ -1058,7 +1109,7 @@ class MP4 {
|
|
1058
1109
|
);
|
1059
1110
|
}
|
1060
1111
|
|
1061
|
-
static trun(track, offset) {
|
1112
|
+
static trun(track: MediaTrackType, offset: number) {
|
1062
1113
|
const samples = track.samples || [];
|
1063
1114
|
const len = samples.length;
|
1064
1115
|
const arraylen = 12 + 16 * len;
|
@@ -1121,7 +1172,7 @@ class MP4 {
|
|
1121
1172
|
return MP4.box(MP4.types.trun, array);
|
1122
1173
|
}
|
1123
1174
|
|
1124
|
-
static initSegment(tracks) {
|
1175
|
+
static initSegment(tracks: MediaTrackType[]) {
|
1125
1176
|
if (!MP4.types) {
|
1126
1177
|
MP4.init();
|
1127
1178
|
}
|
@@ -1131,9 +1182,12 @@ class MP4 {
|
|
1131
1182
|
return result;
|
1132
1183
|
}
|
1133
1184
|
|
1134
|
-
static hvc1(track) {
|
1185
|
+
static hvc1(track: DemuxedHEVC) {
|
1186
|
+
if (!__USE_M2TS_ADVANCED_CODECS__) {
|
1187
|
+
return new Uint8Array();
|
1188
|
+
}
|
1135
1189
|
const ps = track.params;
|
1136
|
-
const units = [track.vps, track.sps, track.pps];
|
1190
|
+
const units: Uint8Array[][] = [track.vps, track.sps, track.pps];
|
1137
1191
|
const NALuLengthSize = 4;
|
1138
1192
|
const config = new Uint8Array([
|
1139
1193
|
0x01,
|
package/src/remux/mp4-remuxer.ts
CHANGED
@@ -17,6 +17,7 @@ import type {
|
|
17
17
|
} from '../types/demuxer';
|
18
18
|
import type {
|
19
19
|
InitSegmentData,
|
20
|
+
Mp4Sample,
|
20
21
|
RemuxedMetadata,
|
21
22
|
RemuxedTrack,
|
22
23
|
RemuxedUserdata,
|
@@ -36,6 +37,26 @@ const AC3_SAMPLES_PER_FRAME = 1536;
|
|
36
37
|
let chromeVersion: number | null = null;
|
37
38
|
let safariWebkitVersion: number | null = null;
|
38
39
|
|
40
|
+
function createMp4Sample(
|
41
|
+
isKeyframe: boolean,
|
42
|
+
duration: number,
|
43
|
+
size: number,
|
44
|
+
cts: number,
|
45
|
+
): Mp4Sample {
|
46
|
+
return {
|
47
|
+
duration,
|
48
|
+
size,
|
49
|
+
cts,
|
50
|
+
flags: {
|
51
|
+
isLeading: 0,
|
52
|
+
isDependedOn: 0,
|
53
|
+
hasRedundancy: 0,
|
54
|
+
degradPrio: 0,
|
55
|
+
dependsOn: isKeyframe ? 2 : 1,
|
56
|
+
isNonSync: isKeyframe ? 0 : 1,
|
57
|
+
},
|
58
|
+
};
|
59
|
+
}
|
39
60
|
export default class MP4Remuxer implements Remuxer {
|
40
61
|
private readonly logger: ILogger;
|
41
62
|
private readonly observer: HlsEventEmitter;
|
@@ -718,7 +739,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
718
739
|
maxPtsDelta = Math.max(maxPtsDelta, ptsDelta);
|
719
740
|
|
720
741
|
outputSamples.push(
|
721
|
-
|
742
|
+
createMp4Sample(
|
722
743
|
VideoSample.key,
|
723
744
|
mp4SampleDuration,
|
724
745
|
mp4SampleLength,
|
@@ -776,7 +797,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
776
797
|
const moof = MP4.moof(
|
777
798
|
track.sequenceNumber++,
|
778
799
|
firstDTS,
|
779
|
-
Object.assign(
|
800
|
+
Object.assign(track, {
|
780
801
|
samples: outputSamples,
|
781
802
|
}),
|
782
803
|
);
|
@@ -1027,7 +1048,7 @@ export default class MP4Remuxer implements Remuxer {
|
|
1027
1048
|
// Default the sample's duration to the computed mp4SampleDuration, which will either be 1024 for AAC or 1152 for MPEG
|
1028
1049
|
// In the case that we have 1 sample, this will be the duration. If we have more than one sample, the duration
|
1029
1050
|
// becomes the PTS diff with the previous sample
|
1030
|
-
outputSamples.push(
|
1051
|
+
outputSamples.push(createMp4Sample(true, mp4SampleDuration, unitLen, 0));
|
1031
1052
|
lastPTS = pts;
|
1032
1053
|
}
|
1033
1054
|
|
@@ -1167,38 +1188,3 @@ export function flushTextTrackUserdataCueSamples(
|
|
1167
1188
|
samples,
|
1168
1189
|
};
|
1169
1190
|
}
|
1170
|
-
|
1171
|
-
type Mp4SampleFlags = {
|
1172
|
-
isLeading: 0;
|
1173
|
-
isDependedOn: 0;
|
1174
|
-
hasRedundancy: 0;
|
1175
|
-
degradPrio: 0;
|
1176
|
-
dependsOn: 1 | 2;
|
1177
|
-
isNonSync: 0 | 1;
|
1178
|
-
};
|
1179
|
-
|
1180
|
-
class Mp4Sample {
|
1181
|
-
public size: number;
|
1182
|
-
public duration: number;
|
1183
|
-
public cts: number;
|
1184
|
-
public flags: Mp4SampleFlags;
|
1185
|
-
|
1186
|
-
constructor(
|
1187
|
-
isKeyframe: boolean,
|
1188
|
-
duration: number,
|
1189
|
-
size: number,
|
1190
|
-
cts: number,
|
1191
|
-
) {
|
1192
|
-
this.duration = duration;
|
1193
|
-
this.size = size;
|
1194
|
-
this.cts = cts;
|
1195
|
-
this.flags = {
|
1196
|
-
isLeading: 0,
|
1197
|
-
isDependedOn: 0,
|
1198
|
-
hasRedundancy: 0,
|
1199
|
-
degradPrio: 0,
|
1200
|
-
dependsOn: isKeyframe ? 2 : 1,
|
1201
|
-
isNonSync: isKeyframe ? 0 : 1,
|
1202
|
-
};
|
1203
|
-
}
|
1204
|
-
}
|
package/src/types/demuxer.ts
CHANGED
@@ -59,15 +59,21 @@ export interface PassthroughTrack extends DemuxedTrack {
|
|
59
59
|
codec: string;
|
60
60
|
}
|
61
61
|
export interface DemuxedAudioTrack extends DemuxedTrack {
|
62
|
+
type: 'audio';
|
63
|
+
segmentCodec: 'aac' | 'ac3' | 'mp3';
|
62
64
|
config?: number[] | Uint8Array;
|
63
65
|
samplerate?: number;
|
64
|
-
segmentCodec?: string;
|
65
66
|
channelCount?: number;
|
66
67
|
manifestCodec?: string;
|
67
68
|
parsedCodec?: string;
|
68
69
|
samples: AudioSample[];
|
69
70
|
}
|
70
71
|
|
72
|
+
export type DemuxedAC3 = DemuxedAudioTrack & {
|
73
|
+
segmentCodec: 'ac3';
|
74
|
+
config: Uint8Array;
|
75
|
+
};
|
76
|
+
|
71
77
|
export interface DemuxedVideoTrackBase extends DemuxedTrack {
|
72
78
|
width?: number;
|
73
79
|
height?: number;
|
@@ -84,9 +90,43 @@ export interface DemuxedVideoTrackBase extends DemuxedTrack {
|
|
84
90
|
}
|
85
91
|
|
86
92
|
export interface DemuxedVideoTrack extends DemuxedVideoTrackBase {
|
93
|
+
type: 'video';
|
94
|
+
segmentCodec: 'avc' | 'hevc';
|
87
95
|
samples: VideoSample[];
|
96
|
+
pixelRatio: [number, number];
|
97
|
+
width: number;
|
98
|
+
height: number;
|
88
99
|
}
|
89
100
|
|
101
|
+
export type DemuxedAVC1 = DemuxedVideoTrack & {
|
102
|
+
segmentCodec: 'avc';
|
103
|
+
pps: Uint8Array[];
|
104
|
+
sps: Uint8Array[];
|
105
|
+
};
|
106
|
+
|
107
|
+
export type DemuxedHEVC = DemuxedVideoTrack & {
|
108
|
+
segmentCodec: 'hevc';
|
109
|
+
params: {
|
110
|
+
general_profile_space: number;
|
111
|
+
general_tier_flag: number;
|
112
|
+
general_profile_idc: number;
|
113
|
+
general_profile_compatibility_flags: number[];
|
114
|
+
general_constraint_indicator_flags: number[];
|
115
|
+
general_level_idc: number;
|
116
|
+
min_spatial_segmentation_idc: number;
|
117
|
+
parallelismType: number;
|
118
|
+
chroma_format_idc: number;
|
119
|
+
bit_depth_luma_minus8: number;
|
120
|
+
bit_depth_chroma_minus8: number;
|
121
|
+
frame_rate: { fps: string; fixed: boolean };
|
122
|
+
temporal_id_nested: number;
|
123
|
+
num_temporal_layers: number;
|
124
|
+
};
|
125
|
+
pps: Uint8Array[];
|
126
|
+
sps: Uint8Array[];
|
127
|
+
vps: Uint8Array;
|
128
|
+
};
|
129
|
+
|
90
130
|
export interface DemuxedMetadataTrack extends DemuxedTrack {
|
91
131
|
samples: MetadataSample[];
|
92
132
|
}
|
package/src/types/remuxer.ts
CHANGED
@@ -3,6 +3,7 @@ import type {
|
|
3
3
|
DemuxedAudioTrack,
|
4
4
|
DemuxedMetadataTrack,
|
5
5
|
DemuxedUserdataTrack,
|
6
|
+
DemuxedVideoTrack,
|
6
7
|
DemuxedVideoTrackBase,
|
7
8
|
MetadataSample,
|
8
9
|
UserdataSample,
|
@@ -61,6 +62,30 @@ export interface RemuxedUserdata {
|
|
61
62
|
samples: UserdataSample[];
|
62
63
|
}
|
63
64
|
|
65
|
+
export type Mp4SampleFlags = {
|
66
|
+
isLeading: 0;
|
67
|
+
isDependedOn: 0;
|
68
|
+
hasRedundancy: 0;
|
69
|
+
degradPrio: 0;
|
70
|
+
dependsOn: 1 | 2;
|
71
|
+
isNonSync: 0 | 1;
|
72
|
+
};
|
73
|
+
|
74
|
+
export type Mp4Sample = {
|
75
|
+
size: number;
|
76
|
+
duration: number;
|
77
|
+
cts: number;
|
78
|
+
flags: Mp4SampleFlags;
|
79
|
+
};
|
80
|
+
|
81
|
+
export type RemuxedAudioTrackSamples = DemuxedAudioTrack & {
|
82
|
+
samples: Mp4Sample[];
|
83
|
+
};
|
84
|
+
|
85
|
+
export type RemuxedVideoTrackSamples = DemuxedVideoTrack & {
|
86
|
+
samples: Mp4Sample[];
|
87
|
+
};
|
88
|
+
|
64
89
|
export interface RemuxerResult {
|
65
90
|
audio?: RemuxedTrack;
|
66
91
|
video?: RemuxedTrack;
|