Merge branch 'main' into hls

This commit is contained in:
Vanilagy
2026-02-26 15:53:46 +01:00
35 changed files with 935 additions and 76 deletions
+3
View File
@@ -104,6 +104,9 @@ export enum EBMLId {
Video = 0xe0,
PixelWidth = 0xb0,
PixelHeight = 0xba,
DisplayWidth = 0x54b0,
DisplayHeight = 0x54ba,
DisplayUnit = 0x54b2,
AlphaMode = 0x53c0,
Audio = 0xe1,
SamplingFrequency = 0xb5,
+59
View File
@@ -204,6 +204,11 @@ type InternalTrack = {
type: 'video';
width: number;
height: number;
displayWidth: number | null;
displayHeight: number | null;
displayUnit: number | null;
squarePixelWidth: number;
squarePixelHeight: number;
rotation: Rotation;
codec: VideoCodec | null;
codecDescription: Uint8Array | null;
@@ -1036,6 +1041,27 @@ export class MatroskaDemuxer extends Demuxer {
&& this.currentTrack.info.width !== -1
&& this.currentTrack.info.height !== -1
) {
this.currentTrack.info.squarePixelWidth = this.currentTrack.info.width;
this.currentTrack.info.squarePixelHeight = this.currentTrack.info.height;
if (
this.currentTrack.info.displayWidth !== null
&& this.currentTrack.info.displayHeight !== null
) {
const num = this.currentTrack.info.displayWidth * this.currentTrack.info.height;
const den = this.currentTrack.info.displayHeight * this.currentTrack.info.width;
if (num > den) {
this.currentTrack.info.squarePixelWidth = Math.round(
this.currentTrack.info.width * num / den,
);
} else {
this.currentTrack.info.squarePixelHeight = Math.round(
this.currentTrack.info.height * den / num,
);
}
}
if (this.currentTrack.codecId === CODEC_STRING_MAP.avc) {
this.currentTrack.info.codec = 'avc';
this.currentTrack.info.codecDescription = this.currentTrack.codecPrivate;
@@ -1137,6 +1163,11 @@ export class MatroskaDemuxer extends Demuxer {
type: 'video',
width: -1,
height: -1,
displayWidth: null,
displayHeight: null,
displayUnit: null,
squarePixelWidth: -1,
squarePixelHeight: -1,
rotation: 0,
codec: null,
codecDescription: null,
@@ -1273,6 +1304,24 @@ export class MatroskaDemuxer extends Demuxer {
this.currentTrack.info.height = readUnsignedInt(slice, size);
}; break;
case EBMLId.DisplayWidth: {
if (this.currentTrack?.info?.type !== 'video') break;
this.currentTrack.info.displayWidth = readUnsignedInt(slice, size);
}; break;
case EBMLId.DisplayHeight: {
if (this.currentTrack?.info?.type !== 'video') break;
this.currentTrack.info.displayHeight = readUnsignedInt(slice, size);
}; break;
case EBMLId.DisplayUnit: {
if (this.currentTrack?.info?.type !== 'video') break;
this.currentTrack.info.displayUnit = readUnsignedInt(slice, size);
}; break;
case EBMLId.AlphaMode: {
if (this.currentTrack?.info?.type !== 'video') break;
@@ -2325,6 +2374,14 @@ class MatroskaVideoTrackBacking extends MatroskaTrackBacking implements InputVid
return this.internalTrack.info.height;
}
getSquarePixelWidth() {
return this.internalTrack.info.squarePixelWidth;
}
getSquarePixelHeight() {
return this.internalTrack.info.squarePixelHeight;
}
getRotation() {
return this.internalTrack.info.rotation;
}
@@ -2384,6 +2441,8 @@ class MatroskaVideoTrackBacking extends MatroskaTrackBacking implements InputVid
}),
codedWidth: this.internalTrack.info.width,
codedHeight: this.internalTrack.info.height,
displayAspectWidth: this.internalTrack.info.squarePixelWidth,
displayAspectHeight: this.internalTrack.info.squarePixelHeight,
description: this.internalTrack.info.codecDescription ?? undefined,
colorSpace: this.internalTrack.info.colorSpace ?? undefined,
};
+23
View File
@@ -19,7 +19,9 @@ import {
keyValueIterator,
normalizeRotation,
promiseWithResolvers,
Rational,
roundToMultiple,
simplifyRational,
textEncoder,
toUint8Array,
uint8ArraysAreEqual,
@@ -93,6 +95,7 @@ type MatroskaTrackData = {
info: {
width: number;
height: number;
aspectRatio: Rational | null;
decoderConfig: VideoDecoderConfig;
alphaMode: boolean;
};
@@ -368,10 +371,19 @@ export class MatroskaMuxer extends Muxer {
// Convert from clockwise to counter-clockwise
const flippedRotation = rotation ? normalizeRotation(-rotation) : 0;
const hasNonSquarePixelAspectRatio
= !!trackData.info.aspectRatio && (
trackData.info.aspectRatio.num * trackData.info.height
!== trackData.info.aspectRatio.den * trackData.info.width
);
const colorSpace = trackData.info.decoderConfig.colorSpace;
const videoElement: EBMLElement = { id: EBMLId.Video, data: [
{ id: EBMLId.PixelWidth, data: trackData.info.width },
{ id: EBMLId.PixelHeight, data: trackData.info.height },
(hasNonSquarePixelAspectRatio ? { id: EBMLId.DisplayWidth, data: trackData.info.aspectRatio!.num } : null),
(hasNonSquarePixelAspectRatio ? { id: EBMLId.DisplayHeight, data: trackData.info.aspectRatio!.den } : null),
(hasNonSquarePixelAspectRatio ? { id: EBMLId.DisplayUnit, data: 3 } : null), // 3 = display aspect ratio
trackData.info.alphaMode ? { id: EBMLId.AlphaMode, data: 1 } : null,
(colorSpaceIsComplete(colorSpace)
? {
@@ -738,12 +750,23 @@ export class MatroskaMuxer extends Muxer {
assert(meta.decoderConfig.codedWidth !== undefined);
assert(meta.decoderConfig.codedHeight !== undefined);
const displayAspectWidth = meta.decoderConfig.displayAspectWidth;
const displayAspectHeight = meta.decoderConfig.displayAspectHeight;
const aspectRatio = displayAspectWidth === undefined || displayAspectHeight === undefined
? null
: simplifyRational({
num: displayAspectWidth,
den: displayAspectHeight,
});
const newTrackData: MatroskaVideoTrackData = {
track,
type: 'video',
info: {
width: meta.decoderConfig.codedWidth,
height: meta.decoderConfig.codedHeight,
aspectRatio,
decoderConfig: meta.decoderConfig,
alphaMode: !!packet.sideData.alpha, // The first packet determines if this track has alpha or not
},