Remove input track descriptors, add async getters on tracks for everything, deprecate old sync getters

This commit is contained in:
Vanilagy
2026-04-10 16:23:17 +02:00
parent aa810fc433
commit 051578c2ca
42 changed files with 1386 additions and 1504 deletions
+3 -3
View File
@@ -16,9 +16,9 @@ test('ADTS demuxing', async () => {
const audioTrack = await input.getPrimaryAudioTrack();
assert(audioTrack);
expect(audioTrack.codec).toBe('aac');
expect(audioTrack.sampleRate).toBe(44100);
expect(audioTrack.numberOfChannels).toBe(2);
expect(await audioTrack.getCodec()).toBe('aac');
expect(await audioTrack.getSampleRate()).toBe(44100);
expect(await audioTrack.getNumberOfChannels()).toBe(2);
const decoderConfig = await audioTrack.getDecoderConfig();
assert(decoderConfig);
+1 -1
View File
@@ -79,7 +79,7 @@ test('ADTS with metadata over StreamTarget', async () => {
const outputAudioTrack = await outputAsInput.getPrimaryAudioTrack();
assert(outputAudioTrack);
expect(outputAudioTrack.codec).toBe('aac');
expect(await outputAudioTrack.getCodec()).toBe('aac');
});
// Previously, write handler rejections were silently swallowed and surfaced as
+10 -10
View File
@@ -17,11 +17,11 @@ test('Rotation is baked-in when rerendering', async () => {
const ogTrack = await input.getPrimaryVideoTrack();
assert(ogTrack);
expect(ogTrack.rotation).toBe(90);
expect(ogTrack.codedWidth).toBe(1920);
expect(ogTrack.codedHeight).toBe(1080);
expect(ogTrack.displayWidth).toBe(1080);
expect(ogTrack.displayHeight).toBe(1920);
expect(await ogTrack.getRotation()).toBe(90);
expect(await ogTrack.getCodedWidth()).toBe(1920);
expect(await ogTrack.getCodedHeight()).toBe(1080);
expect(await ogTrack.getDisplayWidth()).toBe(1080);
expect(await ogTrack.getDisplayHeight()).toBe(1920);
const output = new Output({
format: new Mp4OutputFormat(),
@@ -41,9 +41,9 @@ test('Rotation is baked-in when rerendering', async () => {
const track = await newInput.getPrimaryVideoTrack();
assert(track);
expect(track.codedWidth).toBe(320);
expect(track.codedHeight).toBe(570);
expect(track.displayWidth).toBe(320);
expect(track.displayHeight).toBe(570);
expect(track.rotation).toBe(0);
expect(await track.getCodedWidth()).toBe(320);
expect(await track.getCodedHeight()).toBe(570);
expect(await track.getDisplayWidth()).toBe(320);
expect(await track.getDisplayHeight()).toBe(570);
expect(await track.getRotation()).toBe(0);
});
+3 -3
View File
@@ -62,7 +62,7 @@ test('can convert a .flac to .wav', async () => {
IPRD: 'Samples files',
ITRK: '4',
});
expect(inputTrack.sampleRate).toBe(outputTrack.sampleRate);
expect(inputTrack.numberOfChannels).toBe(outputTrack.numberOfChannels);
expect(inputTrack.timeResolution).toBe(outputTrack.timeResolution);
expect(await inputTrack.getSampleRate()).toBe(await outputTrack.getSampleRate());
expect(await inputTrack.getNumberOfChannels()).toBe(await outputTrack.getNumberOfChannels());
expect(await inputTrack.getTimeResolution()).toBe(await outputTrack.getTimeResolution());
});
+22 -22
View File
@@ -106,8 +106,8 @@ test(
);
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(100);
expect(track.codedHeight).toBe(100);
expect(await track.getCodedWidth()).toBe(100);
expect(await track.getCodedHeight()).toBe(100);
input.dispose();
}
},
@@ -120,8 +120,8 @@ test('VideoSampleSource, same-sized frames with width and height set', async ()
);
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(50);
expect(track.codedHeight).toBe(80);
expect(await track.getCodedWidth()).toBe(50);
expect(await track.getCodedHeight()).toBe(80);
input.dispose();
});
@@ -132,8 +132,8 @@ test('VideoSampleSource, same-sized frames with rotation set to 90', async () =>
);
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(100);
expect(track.codedHeight).toBe(200);
expect(await track.getCodedWidth()).toBe(100);
expect(await track.getCodedHeight()).toBe(200);
input.dispose();
});
@@ -144,8 +144,8 @@ test('VideoSampleSource, same-sized frames with rotation, width and height', asy
);
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(50);
expect(track.codedHeight).toBe(80);
expect(await track.getCodedWidth()).toBe(50);
expect(await track.getCodedHeight()).toBe(80);
input.dispose();
});
@@ -254,8 +254,8 @@ test('VideoSampleSource, transform.process manual resize', async () => {
);
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(60);
expect(track.codedHeight).toBe(40);
expect(await track.getCodedWidth()).toBe(60);
expect(await track.getCodedHeight()).toBe(40);
input.dispose();
});
@@ -289,8 +289,8 @@ test('VideoSampleSource, transform.process receives pre-transformed frames', asy
}
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(50);
expect(track.codedHeight).toBe(80);
expect(await track.getCodedWidth()).toBe(50);
expect(await track.getCodedHeight()).toBe(80);
input.dispose();
});
@@ -492,8 +492,8 @@ test('VideoSampleSource, transform.frameRate works with process', async () => {
}
const { input, track } = await readBackTrack(buffer);
expect(track.codedWidth).toBe(60);
expect(track.codedHeight).toBe(40);
expect(await track.getCodedWidth()).toBe(60);
expect(await track.getCodedHeight()).toBe(40);
input.dispose();
});
@@ -576,8 +576,8 @@ test('AudioSampleSource, normal usage', async () => {
const buffer = await encodeAudio({ codec: 'pcm-s16' }, sample);
const { input, track } = await readBackAudioTrack(buffer);
expect(track.numberOfChannels).toBe(2);
expect(track.sampleRate).toBe(48000);
expect(await track.getNumberOfChannels()).toBe(2);
expect(await track.getSampleRate()).toBe(48000);
expect(await track.computeDuration()).toBe(1);
input.dispose();
});
@@ -590,8 +590,8 @@ test('AudioSampleSource, remixed to mono', async () => {
);
const { input, track } = await readBackAudioTrack(buffer);
expect(track.numberOfChannels).toBe(1);
expect(track.sampleRate).toBe(48000);
expect(await track.getNumberOfChannels()).toBe(1);
expect(await track.getSampleRate()).toBe(48000);
expect(await track.computeDuration()).toBe(1);
input.dispose();
});
@@ -604,8 +604,8 @@ test('AudioSampleSource, resampled to 44100 Hz', async () => {
);
const { input, track } = await readBackAudioTrack(buffer);
expect(track.numberOfChannels).toBe(2);
expect(track.sampleRate).toBe(44100);
expect(await track.getNumberOfChannels()).toBe(2);
expect(await track.getSampleRate()).toBe(44100);
expect(await track.computeDuration()).toBe(1);
input.dispose();
});
@@ -618,8 +618,8 @@ test('AudioSampleSource, resampled stereo with non-zero start timestamp', async
);
const { input, track } = await readBackAudioTrack(buffer);
expect(track.numberOfChannels).toBe(2);
expect(track.sampleRate).toBe(48000);
expect(await track.getNumberOfChannels()).toBe(2);
expect(await track.getSampleRate()).toBe(48000);
expect(await track.getFirstTimestamp()).toBe(1);
expect(await track.computeDuration()).toBe(2);
+19 -19
View File
@@ -119,9 +119,9 @@ test('MPEG-TS muxing with AVC and AAC', async () => {
assert(videoTrack);
expect(videoTrack.id).toBe(0x100);
expect(videoTrack.codec).toBe('avc');
expect(videoTrack.displayWidth).toBe(640);
expect(videoTrack.displayHeight).toBe(480);
expect(await videoTrack.getCodec()).toBe('avc');
expect(await videoTrack.getDisplayWidth()).toBe(640);
expect(await videoTrack.getDisplayHeight()).toBe(480);
const videoDecoderConfig = await videoTrack.getDecoderConfig();
assert(videoDecoderConfig);
@@ -135,9 +135,9 @@ test('MPEG-TS muxing with AVC and AAC', async () => {
assert(audioTrack);
expect(audioTrack.id).toBe(0x101);
expect(audioTrack.codec).toBe('aac');
expect(audioTrack.numberOfChannels).toBe(2);
expect(audioTrack.sampleRate).toBe(48000);
expect(await audioTrack.getCodec()).toBe('aac');
expect(await audioTrack.getNumberOfChannels()).toBe(2);
expect(await audioTrack.getSampleRate()).toBe(48000);
const audioDecoderConfig = await audioTrack.getDecoderConfig();
assert(audioDecoderConfig);
@@ -289,7 +289,7 @@ test('MPEG-TS muxing with HEVC and MP3', async () => {
assert(videoTrack);
expect(videoTrack.id).toBe(0x100);
expect(videoTrack.codec).toBe('hevc');
expect(await videoTrack.getCodec()).toBe('hevc');
const videoDecoderConfig = await videoTrack.getDecoderConfig();
assert(videoDecoderConfig);
@@ -301,9 +301,9 @@ test('MPEG-TS muxing with HEVC and MP3', async () => {
assert(audioTrack);
expect(audioTrack.id).toBe(0x101);
expect(audioTrack.codec).toBe('mp3');
expect(audioTrack.numberOfChannels).toBe(2);
expect(audioTrack.sampleRate).toBe(24000);
expect(await audioTrack.getCodec()).toBe('mp3');
expect(await audioTrack.getNumberOfChannels()).toBe(2);
expect(await audioTrack.getSampleRate()).toBe(24000);
const audioDecoderConfig = await audioTrack.getDecoderConfig();
assert(audioDecoderConfig);
@@ -407,7 +407,7 @@ test('MPEG-TS muxing with video only', async () => {
const videoTrack = await input.getPrimaryVideoTrack();
assert(videoTrack);
expect(videoTrack.codec).toBe('avc');
expect(await videoTrack.getCodec()).toBe('avc');
const audioTrack = await input.getPrimaryAudioTrack();
expect(audioTrack).toBeNull();
@@ -470,7 +470,7 @@ test('MPEG-TS muxing with audio only', async () => {
const audioTrack = await input.getPrimaryAudioTrack();
assert(audioTrack);
expect(audioTrack.codec).toBe('aac');
expect(await audioTrack.getCodec()).toBe('aac');
const audioSink = new EncodedPacketSink(audioTrack);
let audioPacketCount = 0;
@@ -531,8 +531,8 @@ test('MPEG-TS muxing with two video tracks', async () => {
const videoTracks = tracks.filter(t => t.type === 'video');
expect(videoTracks.length).toBe(2);
expect(videoTracks[0]!.codec).toBe('hevc');
expect(videoTracks[1]!.codec).toBe('hevc');
expect(await videoTracks[0]!.getCodec()).toBe('hevc');
expect(await videoTracks[1]!.getCodec()).toBe('hevc');
expect(videoTracks[0]!.id).toBe(0x100);
expect(videoTracks[1]!.id).toBe(0x101);
});
@@ -599,8 +599,8 @@ test('MPEG-TS muxing with two audio tracks', async () => {
const audioTracks = tracks.filter(t => t.type === 'audio');
expect(audioTracks.length).toBe(2);
expect(audioTracks[0]!.codec).toBe('aac');
expect(audioTracks[1]!.codec).toBe('aac');
expect(await audioTracks[0]!.getCodec()).toBe('aac');
expect(await audioTracks[1]!.getCodec()).toBe('aac');
expect(audioTracks[0]!.id).toBe(0x100);
expect(audioTracks[1]!.id).toBe(0x101);
});
@@ -646,8 +646,8 @@ test('MPEG-TS transmux (Annex B and ADTS passthrough)', async () => {
assert(outputAudioTrack);
// Codecs should match
expect(outputVideoTrack.codec).toBe(inputVideoTrack.codec);
expect(outputAudioTrack.codec).toBe(inputAudioTrack.codec);
expect(await outputVideoTrack.getCodec()).toBe(await inputVideoTrack.getCodec());
expect(await outputAudioTrack.getCodec()).toBe(await inputAudioTrack.getCodec());
// Verify video packets are Annex B
const videoSink = new EncodedPacketSink(outputVideoTrack);
@@ -728,7 +728,7 @@ test('MPEG-TS muxing with StreamTarget', async () => {
const videoTrack = await input.getPrimaryVideoTrack();
assert(videoTrack);
expect(videoTrack.codec).toBe('avc');
expect(await videoTrack.getCodec()).toBe('avc');
const videoSink = new EncodedPacketSink(videoTrack);
let videoPacketCount = 0;
+47 -27
View File
@@ -3,7 +3,7 @@ import { Conversion } from '../../src/conversion.js';
import { ALL_FORMATS, MATROSKA, MP4, MPEG_TS } from '../../src/input-format.js';
import { Input } from '../../src/input.js';
import { VideoSampleSink } from '../../src/media-sink.js';
import { assert } from '../../src/misc.js';
import { assert, Rational } from '../../src/misc.js';
import { Output } from '../../src/output.js';
import { MkvOutputFormat, Mp4OutputFormat, MpegTsOutputFormat } from '../../src/output-format.js';
import { BufferSource, UrlSource } from '../../src/source.js';
@@ -22,13 +22,13 @@ test('Pixel aspect ratio reading', async () => {
const videoTrack = await input.getPrimaryVideoTrack();
assert(videoTrack);
expect(videoTrack.rotation).toBe(0);
expectPar2x1Geometry(videoTrack);
expect(await videoTrack.getRotation()).toBe(0);
expectPar2x1Geometry(await snapshotTrack(videoTrack));
const decoderConfig = await videoTrack.getDecoderConfig();
assert(decoderConfig);
expect(decoderConfig.displayAspectWidth).toBe(videoTrack.squarePixelWidth);
expect(decoderConfig.displayAspectHeight).toBe(videoTrack.squarePixelHeight);
expect(decoderConfig.displayAspectWidth).toBe(await videoTrack.getSquarePixelWidth());
expect(decoderConfig.displayAspectHeight).toBe(await videoTrack.getSquarePixelHeight());
const sink = new VideoSampleSink(videoTrack);
using sample = (await sink.getSample(await videoTrack.getFirstTimestamp()))!;
@@ -36,11 +36,11 @@ test('Pixel aspect ratio reading', async () => {
expect(sample.rotation).toBe(0);
expect(sample.visibleRect.width).toBe(sample.codedWidth);
expect(sample.visibleRect.height).toBe(sample.codedHeight);
expect(sample.codedWidth).toBe(videoTrack.codedWidth);
expect(sample.codedHeight).toBe(videoTrack.codedHeight);
expect(sample.codedWidth).toBe(await videoTrack.getCodedWidth());
expect(sample.codedHeight).toBe(await videoTrack.getCodedHeight());
expectPar2x1Geometry(sample);
expect(sample.squarePixelWidth).toBe(videoTrack.squarePixelWidth);
expect(sample.squarePixelHeight).toBe(videoTrack.squarePixelHeight);
expect(sample.squarePixelWidth).toBe(await videoTrack.getSquarePixelWidth());
expect(sample.squarePixelHeight).toBe(await videoTrack.getSquarePixelHeight());
});
test('Pixel aspect ratio copy conversion', async () => {
@@ -103,7 +103,7 @@ const expectPar2x1Geometry = (value: {
squarePixelHeight: number;
displayWidth: number;
displayHeight: number;
pixelAspectRatio: { num: number; den: number };
pixelAspectRatio: Rational;
}) => {
expect(value.pixelAspectRatio).toEqual({ num: 2, den: 1 });
expect(value.squarePixelWidth).toBe(value.codedWidth * 2);
@@ -113,28 +113,48 @@ const expectPar2x1Geometry = (value: {
};
const snapshotTrack = async (track: {
codedWidth: number;
codedHeight: number;
squarePixelWidth: number;
squarePixelHeight: number;
displayWidth: number;
displayHeight: number;
rotation: number;
pixelAspectRatio: { num: number; den: number };
getCodedWidth(): Promise<number>;
getCodedHeight(): Promise<number>;
getSquarePixelWidth(): Promise<number>;
getSquarePixelHeight(): Promise<number>;
getDisplayWidth(): Promise<number>;
getDisplayHeight(): Promise<number>;
getRotation(): Promise<number>;
getPixelAspectRatio(): Promise<Rational>;
getDecoderConfig(): Promise<VideoDecoderConfig | null>;
}) => {
const decoderConfig = await track.getDecoderConfig();
const [
decoderConfig,
pixelAspectRatio,
codedWidth,
codedHeight,
squarePixelWidth,
squarePixelHeight,
displayWidth,
displayHeight,
rotation,
] = await Promise.all([
track.getDecoderConfig(),
track.getPixelAspectRatio(),
track.getCodedWidth(),
track.getCodedHeight(),
track.getSquarePixelWidth(),
track.getSquarePixelHeight(),
track.getDisplayWidth(),
track.getDisplayHeight(),
track.getRotation(),
]);
assert(decoderConfig);
return {
codedWidth: track.codedWidth,
codedHeight: track.codedHeight,
squarePixelWidth: track.squarePixelWidth,
squarePixelHeight: track.squarePixelHeight,
displayWidth: track.displayWidth,
displayHeight: track.displayHeight,
rotation: track.rotation,
pixelAspectRatio: track.pixelAspectRatio,
codedWidth,
codedHeight,
squarePixelWidth,
squarePixelHeight,
displayWidth,
displayHeight,
rotation,
pixelAspectRatio,
decoderDisplayAspectWidth: decoderConfig.displayAspectWidth,
decoderDisplayAspectHeight: decoderConfig.displayAspectHeight,
};
+1 -1
View File
@@ -367,7 +367,7 @@ test.skip('Can reencode transparent video, keeping alpha', async () => {
const videoTrack = (await outputInput.getPrimaryVideoTrack())!;
expect(await videoTrack.canBeTransparent()).toBe(true);
expect(videoTrack.displayWidth).toBe(320);
expect(await videoTrack.getDisplayWidth()).toBe(320);
const sink = new VideoSampleSink(videoTrack);
using sample = (await sink.getSample(await videoTrack.getFirstTimestamp()))!;