Add read/write support for track disposition information

This commit is contained in:
Vanilagy
2025-11-13 11:00:42 +01:00
parent 2c96ec0f1b
commit 217b383f12
27 changed files with 307 additions and 30 deletions
+4
View File
@@ -88,6 +88,10 @@ export enum EBMLId {
FlagEnabled = 0xb9,
FlagDefault = 0x88,
FlagForced = 0x55aa,
FlagOriginal = 0x55ae,
FlagHearingImpaired = 0x55ab,
FlagVisualImpaired = 0x55ac,
FlagCommentary = 0x55af,
FlagLacing = 0x9c,
Name = 0x536e,
Language = 0x22b59c,
+41 -5
View File
@@ -31,7 +31,7 @@ import {
InputVideoTrack,
InputVideoTrackBacking,
} from '../input-track';
import { AttachedFile, MetadataTags } from '../tags';
import { AttachedFile, DEFAULT_TRACK_DISPOSITION, MetadataTags, TrackDisposition } from '../metadata';
import { PacketRetrievalOptions } from '../media-sink';
import {
assert,
@@ -188,7 +188,7 @@ type InternalTrack = {
}[];
cuePoints: CuePoint[];
isDefault: boolean;
disposition: TrackDisposition;
inputTrack: InputTrack | null;
codecId: string | null;
codecPrivate: Uint8Array | null;
@@ -537,7 +537,7 @@ export class MatroskaDemuxer extends Demuxer {
}
// Put default tracks first
this.currentSegment.tracks.sort((a, b) => Number(b.isDefault) - Number(a.isDefault));
this.currentSegment.tracks.sort((a, b) => Number(b.disposition.default) - Number(a.disposition.default));
// Now, let's distribute the cue points to the tracks
const idToTrack = new Map(this.currentSegment.tracks.map(x => [x.id, x]));
@@ -989,7 +989,9 @@ export class MatroskaDemuxer extends Demuxer {
clusterPositionCache: [],
cuePoints: [],
isDefault: false,
disposition: {
...DEFAULT_TRACK_DISPOSITION,
},
inputTrack: null,
codecId: null,
codecPrivate: null,
@@ -1154,7 +1156,37 @@ export class MatroskaDemuxer extends Demuxer {
case EBMLId.FlagDefault: {
if (!this.currentTrack) break;
this.currentTrack.isDefault = !!readUnsignedInt(slice, size);
this.currentTrack.disposition.default = !!readUnsignedInt(slice, size);
}; break;
case EBMLId.FlagForced: {
if (!this.currentTrack) break;
this.currentTrack.disposition.forced = !!readUnsignedInt(slice, size);
}; break;
case EBMLId.FlagOriginal: {
if (!this.currentTrack) break;
this.currentTrack.disposition.original = !!readUnsignedInt(slice, size);
}; break;
case EBMLId.FlagHearingImpaired: {
if (!this.currentTrack) break;
this.currentTrack.disposition.hearingImpaired = !!readUnsignedInt(slice, size);
}; break;
case EBMLId.FlagVisualImpaired: {
if (!this.currentTrack) break;
this.currentTrack.disposition.visuallyImpaired = !!readUnsignedInt(slice, size);
}; break;
case EBMLId.FlagCommentary: {
if (!this.currentTrack) break;
this.currentTrack.disposition.commentary = !!readUnsignedInt(slice, size);
}; break;
case EBMLId.CodecID: {
@@ -1847,6 +1879,10 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
return this.internalTrack.segment.timestampFactor;
}
getDisposition() {
return this.internalTrack.disposition;
}
async getFirstPacket(options: PacketRetrievalOptions) {
return this.performClusterLookup(
null,
+19 -1
View File
@@ -63,7 +63,7 @@ import { Muxer } from '../muxer';
import { Writer } from '../writer';
import { EncodedPacket } from '../packet';
import { parseOpusIdentificationHeader } from '../codec-data';
import { AttachedFile } from '../tags';
import { AttachedFile } from '../metadata';
const MIN_CLUSTER_TIMESTAMP_MS = /* #__PURE__ */ -(2 ** 15);
const MAX_CLUSTER_TIMESTAMP_MS = /* #__PURE__ */ 2 ** 15 - 1;
@@ -304,6 +304,24 @@ export class MatroskaMuxer extends Muxer {
{ id: EBMLId.TrackNumber, data: trackData.track.id },
{ id: EBMLId.TrackUID, data: trackData.track.id },
{ id: EBMLId.TrackType, data: TRACK_TYPE_MAP[trackData.type] },
trackData.track.metadata.disposition?.default === false
? { id: EBMLId.FlagDefault, data: 0 }
: null,
trackData.track.metadata.disposition?.forced
? { id: EBMLId.FlagForced, data: 1 }
: null,
trackData.track.metadata.disposition?.hearingImpaired
? { id: EBMLId.FlagHearingImpaired, data: 1 }
: null,
trackData.track.metadata.disposition?.visuallyImpaired
? { id: EBMLId.FlagVisualImpaired, data: 1 }
: null,
trackData.track.metadata.disposition?.original
? { id: EBMLId.FlagOriginal, data: 1 }
: null,
trackData.track.metadata.disposition?.commentary
? { id: EBMLId.FlagCommentary, data: 1 }
: null,
{ id: EBMLId.FlagLacing, data: 0 },
{ id: EBMLId.Language, data: trackData.track.metadata.languageCode ?? UNDETERMINED_LANGUAGE },
{ id: EBMLId.CodecID, data: codecId },