From f363fe50e26eedfc78b238cc8c2bc568efcf08e8 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 5 Jan 2026 11:41:32 +0100 Subject: [PATCH] WIP --- dev/demux.html | 9 ++---- src/input-format.ts | 25 ++++++++++++++++- src/mpeg-ts/mpeg-ts-demuxer.ts | 51 ++++++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/mpeg-ts/mpeg-ts-demuxer.ts diff --git a/dev/demux.html b/dev/demux.html index cab4bd7..cd422de 100644 --- a/dev/demux.html +++ b/dev/demux.html @@ -13,13 +13,8 @@ formats: Mediabunny.ALL_FORMATS, source: new Mediabunny.BlobSource(file), }); - - const videoTrack = await input.getPrimaryVideoTrack(); - const sink = new Mediabunny.EncodedPacketSink(videoTrack); - - for await (const packet of sink.packets()) { - console.log(packet); - } + + console.log(await input.getTracks()); /* diff --git a/src/input-format.ts b/src/input-format.ts index 1748f27..0182f4a 100644 --- a/src/input-format.ts +++ b/src/input-format.ts @@ -30,6 +30,7 @@ import { MAX_FRAME_HEADER_SIZE, MIN_FRAME_HEADER_SIZE, readFrameHeader } from '. import { AdtsDemuxer } from './adts/adts-demuxer'; import { readAscii } from './reader'; import { FlacDemuxer } from './flac/flac-demuxer'; +import { MpegTsDemuxer } from './mpeg-ts/mpeg-ts-demuxer'; /** * Base class representing an input media file format. @@ -476,6 +477,26 @@ export class AdtsInputFormat extends InputFormat { } } +export class MpegTsInputFormat extends InputFormat { + /** @internal */ + async _canReadInput(input: Input) { + return true; // TEMP + } + + /** @internal */ + _createDemuxer(input: Input) { + return new MpegTsDemuxer(input); + } + + get name() { + return 'MPEG Transport Stream'; + } + + get mimeType() { + return 'video/MP2T'; // todo correct? + } +} + /** * MP4 input format singleton. * @group Input formats @@ -532,10 +553,12 @@ export const ADTS = /* #__PURE__ */ new AdtsInputFormat(); */ export const FLAC = /* #__PURE__ */ new FlacInputFormat(); +export const MPEG_TS = /* #__PURE__ */ new MpegTsInputFormat(); + /** * List of all input format singletons. If you don't need to support all input formats, you should specify the * formats individually for better tree shaking. * @group Input formats * @public */ -export const ALL_FORMATS: InputFormat[] = [MP4, QTFF, MATROSKA, WEBM, WAVE, OGG, FLAC, MP3, ADTS]; +export const ALL_FORMATS: InputFormat[] = [MP4, QTFF, MATROSKA, WEBM, WAVE, OGG, FLAC, MP3, ADTS, MPEG_TS]; diff --git a/src/mpeg-ts/mpeg-ts-demuxer.ts b/src/mpeg-ts/mpeg-ts-demuxer.ts new file mode 100644 index 0000000..61c6baf --- /dev/null +++ b/src/mpeg-ts/mpeg-ts-demuxer.ts @@ -0,0 +1,51 @@ +import { Demuxer } from "../demuxer"; +import { Input } from "../input"; +import { InputTrack } from "../input-track"; +import { Bitstream } from "../misc"; +import { readBytes, Reader, readU24Be, readU8 } from "../reader"; + +export class MpegTsDemuxer extends Demuxer { + reader: Reader; + + metadataPromise: Promise | null = null; + + constructor(input: Input) { + super(input); + + this.reader = input._reader; + } + + async readMetadata() { + return this.metadataPromise ??= (async () => { + for (let i = 0; i < 2; i++) { + this.readPacket(188 * i); + } + })(); + } + + async getTracks(): Promise { + await this.readMetadata(); + return []; + } + + async readPacket(pos: number) { + let slice = this.reader.requestSlice(pos, 188); + if (slice instanceof Promise) slice = await slice; + + if (!slice) { + return null; + } + + const bitstream = new Bitstream(readBytes(slice, 3)); + const syncByte = bitstream.readBits(8); + const transportErrorIndicator = bitstream.readBits(1); + const payloadUnitStartIndicator = bitstream.readBits(1); + const transportPriority = bitstream.readBits(1); + const pid = bitstream.readBits(13); + const transportScramblingControl = bitstream.readBits(2); + const adaptationFieldControl = bitstream.readBits(2); + const continuityCounter = bitstream.readBits(4); + + console.log(syncByte, transportErrorIndicator, payloadUnitStartIndicator, transportPriority, pid, transportScramblingControl, adaptationFieldControl, continuityCounter); + } +} \ No newline at end of file