Make computeDuration and getFirstTimestamp have the same implementations across the board

This commit is contained in:
Vanilagy
2026-01-27 16:49:25 +01:00
parent 2ffa692fdd
commit 6004912f3d
13 changed files with 13 additions and 171 deletions
-18
View File
@@ -151,15 +151,6 @@ export class AdtsDemuxer extends Demuxer {
return this.tracks;
}
async computeDuration() {
await this.readMetadata();
const track = this.tracks[0];
assert(track);
return track.computeDuration();
}
async getMetadataTags() {
const release = await this.readingMutex.acquire();
@@ -210,20 +201,11 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
return 1;
}
async getFirstTimestamp() {
return 0;
}
getTimeResolution() {
const sampleRate = this.getSampleRate();
return sampleRate / SAMPLES_PER_AAC_FRAME;
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
getName() {
return null;
}
-13
View File
@@ -26,11 +26,6 @@ export class InputAggregateDemuxer extends Demuxer {
this.subInputs = subInputs;
}
async computeDuration() {
const durations = await Promise.all(this.subInputs.map(x => x.computeDuration()));
return Math.max(0, ...durations);
}
async getMetadataTags(): Promise<MetadataTags> {
return {}; // todo?
}
@@ -112,14 +107,6 @@ class InputAggregateTrackBacking implements InputTrackBacking {
return this.source.getVariant();
}
getFirstTimestamp() {
return this.source.getFirstTimestamp();
}
computeDuration() {
return this.source.computeDuration();
}
getFirstPacket(options: PacketRetrievalOptions): Promise<EncodedPacket | null> {
return this.source.getFirstPacket(options);
}
-1
View File
@@ -17,7 +17,6 @@ export abstract class Demuxer {
this.input = input;
}
abstract computeDuration(): Promise<number>;
abstract getTracks(): Promise<InputTrack[]>;
abstract getMimeType(): Promise<string>;
abstract getMetadataTags(): Promise<MetadataTags>;
-15
View File
@@ -86,12 +86,6 @@ export class FlacDemuxer extends Demuxer {
this.reader = input._reader;
}
override async computeDuration(): Promise<number> {
await this.readMetadata();
assert(this.track);
return this.track.computeDuration();
}
override async getMetadataTags(): Promise<MetadataTags> {
await this.readMetadata();
return this.metadataTags;
@@ -546,11 +540,6 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
return this.demuxer.audioInfo.numberOfChannels;
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
getSampleRate() {
assert(this.demuxer.audioInfo);
return this.demuxer.audioInfo.sampleRate;
@@ -579,10 +568,6 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
return null;
}
async getFirstTimestamp() {
return 0;
}
async getDecoderConfig(): Promise<AudioDecoderConfig | null> {
assert(this.demuxer.audioInfo);
+6 -7
View File
@@ -42,9 +42,6 @@ export interface InputTrackBacking {
getDisposition(): TrackDisposition;
getVariant(): ManifestInputVariant | null;
getFirstTimestamp(): Promise<number>;
computeDuration(): Promise<number>;
getFirstPacket(options: PacketRetrievalOptions): Promise<EncodedPacket | null>;
getPacket(timestamp: number, options: PacketRetrievalOptions): Promise<EncodedPacket | null>;
getNextPacket(packet: EncodedPacket, options: PacketRetrievalOptions): Promise<EncodedPacket | null>;
@@ -158,13 +155,15 @@ export abstract class InputTrack {
* may be positive or even negative. A negative starting timestamp means the track's timing has been offset. Samples
* with a negative timestamp should not be presented.
*/
getFirstTimestamp() {
return this._backing.getFirstTimestamp();
async getFirstTimestamp() {
const firstPacket = await this._backing.getFirstPacket({ metadataOnly: true });
return firstPacket?.timestamp ?? 0;
}
/** Returns the end timestamp of the last packet of this track, in seconds. */
computeDuration() {
return this._backing.computeDuration();
async computeDuration() {
const lastPacket = await this._backing.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
/**
+7 -2
View File
@@ -114,8 +114,13 @@ export class Input<S extends Source = Source> implements Disposable {
* all tracks.
*/
async computeDuration() {
const demuxer = await this._getDemuxer();
return demuxer.computeDuration();
const tracks = await this.getTracks();
if (tracks.length === 0) {
return 0;
}
const tracksDurations = await Promise.all(tracks.map(x => x.computeDuration()));
return Math.max(...tracksDurations);
}
/**
-16
View File
@@ -260,12 +260,6 @@ export class IsobmffDemuxer extends Demuxer {
this.reader = input._reader;
}
override async computeDuration() {
const tracks = await this.getTracks();
const trackDurations = await Promise.all(tracks.map(x => x.computeDuration()));
return Math.max(0, ...trackDurations);
}
override async getTracks() {
await this.readMetadata();
return this.tracks.map(track => track.inputTrack!);
@@ -2382,16 +2376,6 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
return null;
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
async getFirstTimestamp() {
const firstPacket = await this.getFirstPacket({ metadataOnly: true });
return firstPacket?.timestamp ?? 0;
}
async getFirstPacket(options: PacketRetrievalOptions) {
const regularPacket = await this.fetchPacketForSampleIndex(0, options);
if (regularPacket || !this.internalTrack.demuxer.isFragmented) {
-16
View File
@@ -99,12 +99,6 @@ class ManifestInputVariantDemuxer extends Demuxer {
this.variant = variant;
}
async computeDuration(): Promise<number> {
const tracks = await this.getTracks();
const trackDurations = await Promise.all(tracks.map(x => x.computeDuration()));
return Math.max(0, ...trackDurations);
}
async getMetadataTags(): Promise<MetadataTags> {
return {}; // todo?
}
@@ -257,16 +251,6 @@ class ManifestInputVariantInputTrackBacking implements InputTrackBacking {
return this.demuxer.variant;
}
async getFirstTimestamp(): Promise<number> {
const firstPacket = await this.getFirstPacket({ metadataOnly: true });
return firstPacket?.timestamp ?? 0;
}
async computeDuration(): Promise<number> {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
async createAdjustedPacket(packet: EncodedPacket, segment: ManifestInputSegment, track: InputTrack) {
const mediaOffset = await this.demuxer.getMediaOffset(segment, track.input);
-16
View File
@@ -266,12 +266,6 @@ export class MatroskaDemuxer extends Demuxer {
this.reader = input._reader;
}
override async computeDuration() {
const tracks = await this.getTracks();
const trackDurations = await Promise.all(tracks.map(x => x.computeDuration()));
return Math.max(0, ...trackDurations);
}
async getTracks() {
await this.readMetadata();
return this.segments.flatMap(segment => segment.tracks.map(track => track.inputTrack!));
@@ -1888,11 +1882,6 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
return this.internalTrack.codecId;
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
getName() {
return this.internalTrack.name;
}
@@ -1901,11 +1890,6 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
return this.internalTrack.languageCode;
}
async getFirstTimestamp() {
const firstPacket = await this.getFirstPacket({ metadataOnly: true });
return firstPacket?.timestamp ?? 0;
}
getVariant() {
return null;
}
-18
View File
@@ -147,15 +147,6 @@ export class Mp3Demuxer extends Demuxer {
return this.tracks;
}
async computeDuration() {
await this.readMetadata();
const track = this.tracks[0];
assert(track);
return track.computeDuration();
}
async getMetadataTags() {
const release = await this.readingMutex.acquire();
@@ -221,20 +212,11 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
return 1;
}
async getFirstTimestamp() {
return 0;
}
getTimeResolution() {
assert(this.demuxer.firstFrameHeader);
return this.demuxer.firstFrameHeader.sampleRate / this.demuxer.firstFrameHeader.audioSamplesInFrame;
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
getName() {
return null;
}
-16
View File
@@ -485,12 +485,6 @@ export class MpegTsDemuxer extends Demuxer {
return {}; // Nothing for now
}
async computeDuration() {
const tracks = await this.getTracks();
const trackDurations = await Promise.all(tracks.map(x => x.computeDuration()));
return Math.max(0, ...trackDurations);
}
async getMimeType(): Promise<string> {
await this.readMetadata();
@@ -846,16 +840,6 @@ export abstract class MpegTsTrackBacking implements InputTrackBacking {
return null;
}
async computeDuration(): Promise<number> {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
async getFirstTimestamp(): Promise<number> {
const firstPacket = await this.getFirstPacket({ metadataOnly: true });
return firstPacket?.timestamp ?? 0;
}
abstract allPacketsAreKeyPackets(): boolean;
abstract getReorderSize(): number;
-15
View File
@@ -391,12 +391,6 @@ export class OggDemuxer extends Demuxer {
return this.tracks;
}
async computeDuration() {
const tracks = await this.getTracks();
const trackDurations = await Promise.all(tracks.map(x => x.computeDuration()));
return Math.max(0, ...trackDurations);
}
async getMetadataTags() {
await this.readMetadata();
return this.metadataTags;
@@ -487,15 +481,6 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
};
}
async getFirstTimestamp() {
return 0;
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
granulePositionToTimestampInSamples(granulePosition: number) {
if (this.bitstream.codecInfo.codec === 'opus') {
assert(this.bitstream.codecInfo.opusInfo);
-18
View File
@@ -327,15 +327,6 @@ export class WaveDemuxer extends Demuxer {
return 'audio/wav';
}
async computeDuration() {
await this.readMetadata();
const track = this.tracks[0];
assert(track);
return track.computeDuration();
}
async getTracks() {
await this.readMetadata();
return this.tracks;
@@ -383,11 +374,6 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
};
}
async computeDuration() {
const lastPacket = await this.getPacket(Infinity, { metadataOnly: true });
return (lastPacket?.timestamp ?? 0) + (lastPacket?.duration ?? 0);
}
getNumberOfChannels() {
assert(this.demuxer.audioInfo);
return this.demuxer.audioInfo.numberOfChannels;
@@ -421,10 +407,6 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
};
}
async getFirstTimestamp() {
return 0;
}
private async getPacketAtIndex(
packetIndex: number,
options: PacketRetrievalOptions,