src/demux/mp4demuxer.ts
- /**
- * MP4 demuxer
- */
- import {
- Demuxer,
- DemuxerResult,
- PassthroughVideoTrack,
- DemuxedAudioTrack,
- DemuxedUserdataTrack,
- DemuxedMetadataTrack,
- KeyData,
- } from '../types/demuxer';
- import {
- findBox,
- segmentValidRange,
- appendUint8Array,
- } from '../utils/mp4-tools';
- import { dummyTrack } from './dummy-demuxed-track';
- import type { HlsEventEmitter } from '../events';
- import type { HlsConfig } from '../config';
-
- class MP4Demuxer implements Demuxer {
- static readonly minProbeByteLength = 1024;
- private remainderData: Uint8Array | null = null;
- private config: HlsConfig;
-
- constructor(observer: HlsEventEmitter, config: HlsConfig) {
- this.config = config;
- }
-
- resetTimeStamp() {}
-
- resetInitSegment() {}
-
- resetContiguity(): void {}
-
- static probe(data) {
- // ensure we find a moof box in the first 16 kB
- return (
- findBox({ data: data, start: 0, end: Math.min(data.length, 16384) }, [
- 'moof',
- ]).length > 0
- );
- }
-
- demux(data): DemuxerResult {
- // Load all data into the avc track. The CMAF remuxer will look for the data in the samples object; the rest of the fields do not matter
- let avcSamples = data;
- const avcTrack = dummyTrack() as PassthroughVideoTrack;
- if (this.config.progressive) {
- // Split the bytestream into two ranges: one encompassing all data up until the start of the last moof, and everything else.
- // This is done to guarantee that we're sending valid data to MSE - when demuxing progressively, we have no guarantee
- // that the fetch loader gives us flush moof+mdat pairs. If we push jagged data to MSE, it will throw an exception.
- if (this.remainderData) {
- avcSamples = appendUint8Array(this.remainderData, data);
- }
- const segmentedData = segmentValidRange(avcSamples);
- this.remainderData = segmentedData.remainder;
- avcTrack.samples = segmentedData.valid || new Uint8Array();
- } else {
- avcTrack.samples = avcSamples;
- }
-
- return {
- audioTrack: dummyTrack() as DemuxedAudioTrack,
- avcTrack,
- id3Track: dummyTrack() as DemuxedMetadataTrack,
- textTrack: dummyTrack() as DemuxedUserdataTrack,
- };
- }
-
- flush() {
- const avcTrack = dummyTrack() as PassthroughVideoTrack;
- avcTrack.samples = this.remainderData || new Uint8Array();
- this.remainderData = null;
-
- return {
- audioTrack: dummyTrack() as DemuxedAudioTrack,
- avcTrack,
- id3Track: dummyTrack() as DemuxedMetadataTrack,
- textTrack: dummyTrack() as DemuxedUserdataTrack,
- };
- }
-
- demuxSampleAes(
- data: Uint8Array,
- keyData: KeyData,
- timeOffset: number
- ): Promise<DemuxerResult> {
- return Promise.reject(
- new Error('The MP4 demuxer does not support SAMPLE-AES decryption')
- );
- }
-
- destroy() {}
- }
-
- export default MP4Demuxer;