Give ResultValue return type proper names, document ResultValue

This commit is contained in:
Vanilagy
2025-12-29 22:05:48 +01:00
parent 87d4c5be5a
commit 72de8da31b
11 changed files with 98 additions and 80 deletions
+7 -7
View File
@@ -15,9 +15,9 @@ import {
AsyncMutex4, AsyncMutex4,
binarySearchLessOrEqual, binarySearchLessOrEqual,
Bitstream, Bitstream,
MaybeRelevantPromise,
ResultValue, ResultValue,
UNDETERMINED_LANGUAGE, UNDETERMINED_LANGUAGE,
Yo,
} from '../misc'; } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { readBytes, Reader } from '../reader'; import { readBytes, Reader } from '../reader';
@@ -72,7 +72,7 @@ export class AdtsDemuxer extends Demuxer {
})(); })();
} }
async advanceReader(res: ResultValue<void>): Promise<Yo> { async advanceReader(res: ResultValue<void>): MaybeRelevantPromise {
let slice = this.reader.requestSliceRange(this.lastLoadedPos, MIN_FRAME_HEADER_SIZE, MAX_FRAME_HEADER_SIZE); let slice = this.reader.requestSliceRange(this.lastLoadedPos, MIN_FRAME_HEADER_SIZE, MAX_FRAME_HEADER_SIZE);
if (slice instanceof Promise) slice = await slice; if (slice instanceof Promise) slice = await slice;
if (!slice) { if (!slice) {
@@ -214,7 +214,7 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
sampleIndex: number, sampleIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
if (sampleIndex === -1) { if (sampleIndex === -1) {
return res.set(null); return res.set(null);
} }
@@ -256,7 +256,7 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
using lock = this.demuxer.readingMutex.lock(); using lock = this.demuxer.readingMutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -284,7 +284,7 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
using lock = this.demuxer.readingMutex.lock(); using lock = this.demuxer.readingMutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -321,7 +321,7 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getPacket(res, timestamp, options); return this.getPacket(res, timestamp, options);
} }
@@ -329,7 +329,7 @@ class AdtsAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getNextPacket(res, packet, options); return this.getNextPacket(res, packet, options);
} }
} }
+6 -6
View File
@@ -24,8 +24,8 @@ import {
ResultValue, ResultValue,
Rotation, Rotation,
AsyncGate, AsyncGate,
Yo,
isNumber, isNumber,
MaybeRelevantPromise,
} from './misc'; } from './misc';
import { EncodedPacket } from './packet'; import { EncodedPacket } from './packet';
import { AudioSample, clampCropRectangle, CropRectangle, validateCropRectangle, VideoSample } from './sample'; import { AudioSample, clampCropRectangle, CropRectangle, validateCropRectangle, VideoSample } from './sample';
@@ -553,7 +553,7 @@ export abstract class SampleCursor<
} }
private _getSample( private _getSample(
callback: (result: ResultValue<TransformedSample | null>) => Promise<Yo>, callback: (result: ResultValue<TransformedSample | null>) => MaybeRelevantPromise,
): MaybePromise<TransformedSample | null> { ): MaybePromise<TransformedSample | null> {
this._ensureWillBeOpen(); this._ensureWillBeOpen();
@@ -860,7 +860,7 @@ export abstract class SampleCursor<
res: ResultValue<TransformedSample | null>, res: ResultValue<TransformedSample | null>,
targetPacketPromise: MaybePromise<EncodedPacket | null>, targetPacketPromise: MaybePromise<EncodedPacket | null>,
lock?: AsyncMutexLock, lock?: AsyncMutexLock,
): Promise<Yo> { ): MaybeRelevantPromise {
this._lazyPump++; this._lazyPump++;
if (!lock) { if (!lock) {
@@ -994,7 +994,7 @@ export abstract class SampleCursor<
return res.set(await request.promise); return res.set(await request.promise);
} }
private async _nextInternal(res: ResultValue<TransformedSample | null>): Promise<Yo> { private async _nextInternal(res: ResultValue<TransformedSample | null>): MaybeRelevantPromise {
using lock = this._mutex.lock(); using lock = this._mutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -1051,7 +1051,7 @@ export abstract class SampleCursor<
return res.set(await request.promise); return res.set(await request.promise);
} }
private async _nextKeyInternal(res: ResultValue<TransformedSample | null>): Promise<Yo> { private async _nextKeyInternal(res: ResultValue<TransformedSample | null>): MaybeRelevantPromise {
using lock = this._mutex.lock(); using lock = this._mutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -1109,7 +1109,7 @@ export abstract class SampleCursor<
return await this._seekToPacket(res, nextKey, lock); return await this._seekToPacket(res, nextKey, lock);
} }
private async _hasNextInternal(res: ResultValue<boolean>): Promise<Yo> { private async _hasNextInternal(res: ResultValue<boolean>): MaybeRelevantPromise {
using lock = this._mutex.lock(); using lock = this._mutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
+9 -9
View File
@@ -15,10 +15,10 @@ import {
AsyncMutex4, AsyncMutex4,
binarySearchLessOrEqual, binarySearchLessOrEqual,
Bitstream, Bitstream,
MaybeRelevantPromise,
ResultValue, ResultValue,
textDecoder, textDecoder,
UNDETERMINED_LANGUAGE, UNDETERMINED_LANGUAGE,
Yo,
} from '../misc'; } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { import {
@@ -266,7 +266,7 @@ export class FlacDemuxer extends Demuxer {
startPos: number; startPos: number;
isFirstPacket: boolean; isFirstPacket: boolean;
}, },
): Promise<Yo> { ): MaybeRelevantPromise {
assert(this.audioInfo); assert(this.audioInfo);
// we expect that there are at least `minimumFrameSize` bytes left in the file // we expect that there are at least `minimumFrameSize` bytes left in the file
@@ -483,7 +483,7 @@ export class FlacDemuxer extends Demuxer {
return { num, blockSize, sampleRate }; return { num, blockSize, sampleRate };
} }
async advanceReader(res: ResultValue<void>): Promise<Yo> { async advanceReader(res: ResultValue<void>): MaybeRelevantPromise {
assert(this.lastLoadedPos !== null); assert(this.lastLoadedPos !== null);
assert(this.audioInfo); assert(this.audioInfo);
const startPos = this.lastLoadedPos; const startPos = this.lastLoadedPos;
@@ -585,7 +585,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
assert(this.demuxer.audioInfo); assert(this.demuxer.audioInfo);
if (timestamp < 0) { if (timestamp < 0) {
throw new Error('Timestamp cannot be negative'); throw new Error('Timestamp cannot be negative');
@@ -640,7 +640,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
using lock = this.demuxer.readingMutex.lock(); using lock = this.demuxer.readingMutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -675,7 +675,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getPacket(res, timestamp, options); return this.getPacket(res, timestamp, options);
} }
@@ -683,7 +683,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getNextPacket(res, packet, options); return this.getNextPacket(res, packet, options);
} }
@@ -691,7 +691,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
sampleIndex: number, sampleIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const rawSample = this.demuxer.loadedSamples[sampleIndex]; const rawSample = this.demuxer.loadedSamples[sampleIndex];
if (!rawSample) { if (!rawSample) {
return res.set(null); return res.set(null);
@@ -731,7 +731,7 @@ class FlacAudioTrackBacking implements InputAudioTrackBacking {
async getFirstPacket( async getFirstPacket(
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const advanceResult = new ResultValue<void>(); const advanceResult = new ResultValue<void>();
// Ensure the next sample exists // Ensure the next sample exists
+6 -6
View File
@@ -10,7 +10,7 @@ import { AudioCodec, MediaCodec, VideoCodec } from './codec';
import { determineVideoPacketType } from './codec-data'; import { determineVideoPacketType } from './codec-data';
import { customAudioDecoders, customVideoDecoders } from './custom-coder'; import { customAudioDecoders, customVideoDecoders } from './custom-coder';
import { Input } from './input'; import { Input } from './input';
import { assert, ResultValue, Rotation, Yo } from './misc'; import { assert, MaybeRelevantPromise, ResultValue, Rotation } from './misc';
import { TrackType } from './output'; import { TrackType } from './output';
import { EncodedPacket, PacketType } from './packet'; import { EncodedPacket, PacketType } from './packet';
import { TrackDisposition } from './metadata'; import { TrackDisposition } from './metadata';
@@ -42,27 +42,27 @@ export interface InputTrackBacking {
getFirstPacket( getFirstPacket(
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo>; ): MaybeRelevantPromise;
getNextPacket( getNextPacket(
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo>; ): MaybeRelevantPromise;
getPacket( getPacket(
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo>; ): MaybeRelevantPromise;
getKeyPacket( getKeyPacket(
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo>; ): MaybeRelevantPromise;
getNextKeyPacket( getNextKeyPacket(
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo>; ): MaybeRelevantPromise;
} }
/** /**
+10 -10
View File
@@ -58,7 +58,7 @@ import {
toDataView, toDataView,
roundIfAlmostInteger, roundIfAlmostInteger,
ResultValue, ResultValue,
Yo, MaybeRelevantPromise,
} from '../misc'; } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { buildIsobmffMimeType } from './isobmff-misc'; import { buildIsobmffMimeType } from './isobmff-misc';
@@ -507,7 +507,7 @@ export class IsobmffDemuxer extends Demuxer {
return sampleTable; return sampleTable;
} }
async readFragment(res: ResultValue<Fragment>, startPos: number): Promise<Yo> { async readFragment(res: ResultValue<Fragment>, startPos: number): MaybeRelevantPromise {
if (this.lastReadFragment?.moofOffset === startPos) { if (this.lastReadFragment?.moofOffset === startPos) {
return res.set(this.lastReadFragment); return res.set(this.lastReadFragment);
} }
@@ -2354,7 +2354,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
return firstPacket?.timestamp ?? 0; return firstPacket?.timestamp ?? 0;
} }
async getFirstPacket(res: ResultValue<EncodedPacket | null>, options: PacketRetrievalOptions): Promise<Yo> { async getFirstPacket(res: ResultValue<EncodedPacket | null>, options: PacketRetrievalOptions): MaybeRelevantPromise {
const result = new ResultValue<EncodedPacket | null>(); const result = new ResultValue<EncodedPacket | null>();
const promise = this.fetchPacketForSampleIndex(result, 0, options); const promise = this.fetchPacketForSampleIndex(result, 0, options);
if (result.pending) await promise; if (result.pending) await promise;
@@ -2398,7 +2398,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const timestampInTimescale = this.mapTimestampIntoTimescale(timestamp); const timestampInTimescale = this.mapTimestampIntoTimescale(timestamp);
const sampleTable = this.internalTrack.demuxer.getSampleTableForTrack(this.internalTrack); const sampleTable = this.internalTrack.demuxer.getSampleTableForTrack(this.internalTrack);
@@ -2438,7 +2438,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const isFromFragment = packet._internal !== undefined; const isFromFragment = packet._internal !== undefined;
if (!isFromFragment) { if (!isFromFragment) {
const sampleIndex = packet.sequenceNumber; // sequenceNumber = sampleIndex in this case const sampleIndex = packet.sequenceNumber; // sequenceNumber = sampleIndex in this case
@@ -2492,7 +2492,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const timestampInTimescale = this.mapTimestampIntoTimescale(timestamp); const timestampInTimescale = this.mapTimestampIntoTimescale(timestamp);
const sampleTable = this.internalTrack.demuxer.getSampleTableForTrack(this.internalTrack); const sampleTable = this.internalTrack.demuxer.getSampleTableForTrack(this.internalTrack);
@@ -2531,7 +2531,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const isFromFragment = packet._internal !== undefined; const isFromFragment = packet._internal !== undefined;
if (!isFromFragment) { if (!isFromFragment) {
const sampleIndex = packet.sequenceNumber; // sequenceNumber = sampleIndex in this case const sampleIndex = packet.sequenceNumber; // sequenceNumber = sampleIndex in this case
@@ -2594,7 +2594,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
sampleIndex: number, sampleIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
if (sampleIndex === -1) { if (sampleIndex === -1) {
return res.set(null); return res.set(null);
} }
@@ -2639,7 +2639,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
fragment: Fragment, fragment: Fragment,
sampleIndex: number, sampleIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
if (sampleIndex === -1) { if (sampleIndex === -1) {
return res.set(null); return res.set(null);
} }
@@ -2691,7 +2691,7 @@ abstract class IsobmffTrackBacking implements InputTrackBacking {
// The timestamp for which we know the correct sample will not come after it // The timestamp for which we know the correct sample will not come after it
latestTimestamp: number, latestTimestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const demuxer = this.internalTrack.demuxer; const demuxer = this.internalTrack.demuxer;
let currentPos = startOffset ?? 0; let currentPos = startOffset ?? 0;
+17 -15
View File
@@ -40,13 +40,13 @@ import {
isIso639Dash2LanguageCode, isIso639Dash2LanguageCode,
last, last,
MATRIX_COEFFICIENTS_MAP_INVERSE, MATRIX_COEFFICIENTS_MAP_INVERSE,
MaybeRelevantPromise,
normalizeRotation, normalizeRotation,
ResultValue, ResultValue,
Rotation, Rotation,
roundIfAlmostInteger, roundIfAlmostInteger,
TRANSFER_CHARACTERISTICS_MAP_INVERSE, TRANSFER_CHARACTERISTICS_MAP_INVERSE,
UNDETERMINED_LANGUAGE, UNDETERMINED_LANGUAGE,
Yo,
} from '../misc'; } from '../misc';
import { EncodedPacket, EncodedPacketSideData, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, EncodedPacketSideData, PLACEHOLDER_DATA } from '../packet';
import { import {
@@ -583,7 +583,7 @@ export class MatroskaDemuxer extends Demuxer {
this.currentSegment = null; this.currentSegment = null;
} }
async readCluster(res: ResultValue<Cluster>, startPos: number, segment: Segment): Promise<Yo> { async readCluster(res: ResultValue<Cluster>, startPos: number, segment: Segment): MaybeRelevantPromise {
if (segment.lastReadCluster?.elementStartPos === startPos) { if (segment.lastReadCluster?.elementStartPos === startPos) {
return res.set(segment.lastReadCluster); return res.set(segment.lastReadCluster);
} }
@@ -1864,7 +1864,10 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
return this.internalTrack.disposition; return this.internalTrack.disposition;
} }
async getFirstPacket(res: ResultValue<EncodedPacket | null>, options: PacketRetrievalOptions): Promise<Yo> { async getFirstPacket(
res: ResultValue<EncodedPacket | null>,
options: PacketRetrievalOptions,
): MaybeRelevantPromise {
return this.performClusterLookup( return this.performClusterLookup(
res, res,
null, null,
@@ -1899,7 +1902,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const timestampInTimescale = this.intoTimescale(timestamp); const timestampInTimescale = this.intoTimescale(timestamp);
return this.performClusterLookup( return this.performClusterLookup(
@@ -1932,7 +1935,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const clusterStartPos = packet._internal; const clusterStartPos = packet._internal;
if (clusterStartPos === undefined) { if (clusterStartPos === undefined) {
throw new Error('Packet was not created from this track.'); throw new Error('Packet was not created from this track.');
@@ -1981,7 +1984,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const timestampInTimescale = this.intoTimescale(timestamp); const timestampInTimescale = this.intoTimescale(timestamp);
return this.performClusterLookup( return this.performClusterLookup(
@@ -2013,7 +2016,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const clusterStartPos = packet._internal; const clusterStartPos = packet._internal;
if (clusterStartPos === undefined) { if (clusterStartPos === undefined) {
throw new Error('Packet was not created from this track.'); throw new Error('Packet was not created from this track.');
@@ -2066,13 +2069,12 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
} }
private fetchPacketInCluster( private fetchPacketInCluster(
res: ResultValue<EncodedPacket | null>,
cluster: Cluster, cluster: Cluster,
blockIndex: number, blockIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Yo { ) {
if (blockIndex === -1) { if (blockIndex === -1) {
return res.set(null); return null;
} }
const trackData = cluster.trackData.get(this.internalTrack.id)!; const trackData = cluster.trackData.get(this.internalTrack.id)!;
@@ -2107,7 +2109,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
packet._internal = cluster.elementStartPos; packet._internal = cluster.elementStartPos;
return res.set(packet); return packet;
} }
/** Looks for a packet in the clusters while trying to load as few clusters as possible to retrieve it. */ /** Looks for a packet in the clusters while trying to load as few clusters as possible to retrieve it. */
@@ -2122,7 +2124,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
// The timestamp for which we know the correct block will not come after it // The timestamp for which we know the correct block will not come after it
latestTimestamp: number, latestTimestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const { demuxer, segment } = this.internalTrack; const { demuxer, segment } = this.internalTrack;
let currentPos = startOffset ?? 0; let currentPos = startOffset ?? 0;
@@ -2135,7 +2137,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
const { blockIndex, correctBlockFound } = getMatchInCluster(startCluster); const { blockIndex, correctBlockFound } = getMatchInCluster(startCluster);
if (correctBlockFound) { if (correctBlockFound) {
return this.fetchPacketInCluster(res, startCluster, blockIndex, options); return res.set(this.fetchPacketInCluster(startCluster, blockIndex, options));
} }
currentPos = startCluster.elementEndPos; // Start reading from the next cluster currentPos = startCluster.elementEndPos; // Start reading from the next cluster
@@ -2237,7 +2239,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
const { blockIndex, correctBlockFound } = getMatchInCluster(currentCluster); const { blockIndex, correctBlockFound } = getMatchInCluster(currentCluster);
if (correctBlockFound) { if (correctBlockFound) {
return this.fetchPacketInCluster(res, currentCluster, blockIndex, options); return res.set(this.fetchPacketInCluster(currentCluster, blockIndex, options));
} }
if (blockIndex !== -1) { if (blockIndex !== -1) {
@@ -2298,7 +2300,7 @@ abstract class MatroskaTrackBacking implements InputTrackBacking {
if (bestCluster) { if (bestCluster) {
// If we finished looping but didn't find a perfect match, still return the best match we found // If we finished looping but didn't find a perfect match, still return the best match we found
return this.fetchPacketInCluster(res, bestCluster, bestBlockIndex, options); return res.set(this.fetchPacketInCluster(bestCluster, bestBlockIndex, options));
} }
return res.set(null); return res.set(null);
+13 -4
View File
@@ -872,16 +872,25 @@ export const isNumber = (x: unknown) => {
return typeof x === 'number' && !Number.isNaN(x); return typeof x === 'number' && !Number.isNaN(x);
}; };
// We use a unique symbol to ensure that any function using the ResultValue system actually returns when setting it,
// instead of simply setting it and continuing on.
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
const yo: unique symbol = Symbol(); const returnSymbol: unique symbol = Symbol();
export type Yo = typeof yo; export type ReturnSymbol = typeof returnSymbol;
export type MaybeRelevantPromise = Promise<ReturnSymbol>;
/**
* Represents a wrapper that holds a function's return value. Instead of the function returning its return value, it
* instead gets passed a ResultValue instance and writes the return value into it. This allows async functions that
* don't hit any async path to synchronously expose their return value, allowing the caller to ignore the returned
* promise if possible. This allows for "optinally-asynchronous code".
*/
export class ResultValue<T> { export class ResultValue<T> {
value!: T; value!: T;
pending = true; pending = true;
// @ts-expect-error Just for the types // @ts-expect-error Return value just for the types
set(value: T): Yo { set(value: T): ReturnSymbol {
this.value = value; this.value = value;
this.pending = false; this.pending = false;
} }
+7 -7
View File
@@ -15,9 +15,9 @@ import {
assert, assert,
AsyncMutex4, AsyncMutex4,
binarySearchLessOrEqual, binarySearchLessOrEqual,
MaybeRelevantPromise,
ResultValue, ResultValue,
UNDETERMINED_LANGUAGE, UNDETERMINED_LANGUAGE,
Yo,
} from '../misc'; } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { FrameHeader, getXingOffset, INFO, XING } from '../../shared/mp3-misc'; import { FrameHeader, getXingOffset, INFO, XING } from '../../shared/mp3-misc';
@@ -77,7 +77,7 @@ export class Mp3Demuxer extends Demuxer {
})(); })();
} }
async advanceReader(res: ResultValue<void>): Promise<Yo> { async advanceReader(res: ResultValue<void>): MaybeRelevantPromise {
if (this.lastLoadedPos === 0) { if (this.lastLoadedPos === 0) {
// Let's skip all ID3v2 tags at the start of the file // Let's skip all ID3v2 tags at the start of the file
while (true) { while (true) {
@@ -271,7 +271,7 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
sampleIndex: number, sampleIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
if (sampleIndex === -1) { if (sampleIndex === -1) {
return res.set(null); return res.set(null);
} }
@@ -313,7 +313,7 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
using lock = this.demuxer.readingMutex.lock(); using lock = this.demuxer.readingMutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -341,7 +341,7 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
using lock = this.demuxer.readingMutex.lock(); using lock = this.demuxer.readingMutex.lock();
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
@@ -378,7 +378,7 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getPacket(res, timestamp, options); return this.getPacket(res, timestamp, options);
} }
@@ -386,7 +386,7 @@ class Mp3AudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getNextPacket(res, packet, options); return this.getNextPacket(res, packet, options);
} }
} }
+2 -2
View File
@@ -7,7 +7,7 @@
*/ */
import { FRAME_HEADER_SIZE, FrameHeader, readFrameHeader } from '../../shared/mp3-misc'; import { FRAME_HEADER_SIZE, FrameHeader, readFrameHeader } from '../../shared/mp3-misc';
import { ResultValue, Yo } from '../misc'; import { MaybeRelevantPromise, ResultValue } from '../misc';
import { Reader, readU32Be } from '../reader'; import { Reader, readU32Be } from '../reader';
export const readNextFrameHeader = async ( export const readNextFrameHeader = async (
@@ -18,7 +18,7 @@ export const readNextFrameHeader = async (
reader: Reader, reader: Reader,
startPos: number, startPos: number,
until: number | null, until: number | null,
): Promise<Yo> => { ): MaybeRelevantPromise => {
let currentPos = startPos; let currentPos = startPos;
while (until === null || currentPos < until) { while (until === null || currentPos < until) {
+14 -7
View File
@@ -19,11 +19,11 @@ import {
binarySearchLessOrEqual, binarySearchLessOrEqual,
findLast, findLast,
last, last,
MaybeRelevantPromise,
ResultValue, ResultValue,
roundIfAlmostInteger, roundIfAlmostInteger,
toDataView, toDataView,
UNDETERMINED_LANGUAGE, UNDETERMINED_LANGUAGE,
Yo,
} from '../misc'; } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { readBytes, Reader } from '../reader'; import { readBytes, Reader } from '../reader';
@@ -280,7 +280,11 @@ export class OggDemuxer extends Demuxer {
readVorbisComments(secondPacket.data.subarray(8), this.metadataTags); // Skip 'OpusTags' readVorbisComments(secondPacket.data.subarray(8), this.metadataTags); // Skip 'OpusTags'
} }
async readPacket(res: ResultValue<Packet | null>, startPage: Page, startSegmentIndex: number): Promise<Yo> { async readPacket(
res: ResultValue<Packet | null>,
startPage: Page,
startSegmentIndex: number,
): MaybeRelevantPromise {
assert(startSegmentIndex < startPage.lacingValues.length); assert(startSegmentIndex < startPage.lacingValues.length);
let startDataOffset = 0; let startDataOffset = 0;
@@ -369,7 +373,7 @@ export class OggDemuxer extends Demuxer {
}); });
} }
async findNextPacketStart(res: ResultValue<PacketStart | null>, lastPacket: Packet): Promise<Yo> { async findNextPacketStart(res: ResultValue<PacketStart | null>, lastPacket: Packet): MaybeRelevantPromise {
// If there's another segment in the same page, return it // If there's another segment in the same page, return it
if (lastPacket.endSegmentIndex < lastPacket.endPage.lacingValues.length - 1) { if (lastPacket.endSegmentIndex < lastPacket.endPage.lacingValues.length - 1) {
return res.set({ startPage: lastPacket.endPage, startSegmentIndex: lastPacket.endSegmentIndex + 1 }); return res.set({ startPage: lastPacket.endPage, startSegmentIndex: lastPacket.endSegmentIndex + 1 });
@@ -540,7 +544,10 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
return encodedPacket; return encodedPacket;
} }
async getFirstPacket(res: ResultValue<EncodedPacket | null>, options: PacketRetrievalOptions): Promise<Yo> { async getFirstPacket(
res: ResultValue<EncodedPacket | null>,
options: PacketRetrievalOptions,
): MaybeRelevantPromise {
assert(this.bitstream.lastMetadataPacket); assert(this.bitstream.lastMetadataPacket);
const positionResult = new ResultValue<PacketStart | null>(); const positionResult = new ResultValue<PacketStart | null>();
@@ -577,7 +584,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
prevPacket: EncodedPacket, prevPacket: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
const prevMetadata = prevPacket._internal as EncodedPacketMetadata | undefined; const prevMetadata = prevPacket._internal as EncodedPacketMetadata | undefined;
if (!prevMetadata) { if (!prevMetadata) {
throw new Error('Packet was not created from this track.'); throw new Error('Packet was not created from this track.');
@@ -612,7 +619,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
if (this.demuxer.reader.fileSize === null) { if (this.demuxer.reader.fileSize === null) {
// No file size known, can't do binary search, but fall back to sequential algo instead // No file size known, can't do binary search, but fall back to sequential algo instead
return this.getPacketSequential(res, timestamp, options); return this.getPacketSequential(res, timestamp, options);
@@ -971,7 +978,7 @@ class OggAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
using lock = this.sequentialScanMutex.lock(); // Requires exclusivity because we write to a cache using lock = this.sequentialScanMutex.lock(); // Requires exclusivity because we write to a cache
if (lock.pending) await lock.ready; if (lock.pending) await lock.ready;
+7 -7
View File
@@ -11,7 +11,7 @@ import { Demuxer } from '../demuxer';
import { Input } from '../input'; import { Input } from '../input';
import { InputAudioTrack, InputAudioTrackBacking } from '../input-track'; import { InputAudioTrack, InputAudioTrackBacking } from '../input-track';
import { DEFAULT_TRACK_DISPOSITION, MetadataTags } from '../metadata'; import { DEFAULT_TRACK_DISPOSITION, MetadataTags } from '../metadata';
import { assert, ResultValue, UNDETERMINED_LANGUAGE, Yo } from '../misc'; import { assert, MaybeRelevantPromise, ResultValue, UNDETERMINED_LANGUAGE } from '../misc';
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet'; import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
import { readAscii, readBytes, Reader, readU16, readU32, readU64 } from '../reader'; import { readAscii, readBytes, Reader, readU16, readU32, readU64 } from '../reader';
import { parseId3V2Tag, readId3V2Header } from '../id3'; import { parseId3V2Tag, readId3V2Header } from '../id3';
@@ -403,7 +403,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packetIndex: number, packetIndex: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
assert(this.demuxer.audioInfo); assert(this.demuxer.audioInfo);
const startOffset = packetIndex * PACKET_SIZE_IN_FRAMES * this.demuxer.audioInfo.blockSizeInBytes; const startOffset = packetIndex * PACKET_SIZE_IN_FRAMES * this.demuxer.audioInfo.blockSizeInBytes;
if (startOffset >= this.demuxer.dataSize) { if (startOffset >= this.demuxer.dataSize) {
@@ -457,7 +457,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
)); ));
} }
getFirstPacket(res: ResultValue<EncodedPacket | null>, options: PacketRetrievalOptions): Promise<Yo> { getFirstPacket(res: ResultValue<EncodedPacket | null>, options: PacketRetrievalOptions): MaybeRelevantPromise {
return this.getPacketAtIndex(res, 0, options); return this.getPacketAtIndex(res, 0, options);
} }
@@ -465,7 +465,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
assert(this.demuxer.audioInfo); assert(this.demuxer.audioInfo);
const packetIndex = Math.floor(Math.min( const packetIndex = Math.floor(Math.min(
@@ -514,7 +514,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
assert(this.demuxer.audioInfo); assert(this.demuxer.audioInfo);
const packetIndex = packet.sequenceNumber; const packetIndex = packet.sequenceNumber;
@@ -529,7 +529,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
timestamp: number, timestamp: number,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getPacket(res, timestamp, options); return this.getPacket(res, timestamp, options);
} }
@@ -537,7 +537,7 @@ class WaveAudioTrackBacking implements InputAudioTrackBacking {
res: ResultValue<EncodedPacket | null>, res: ResultValue<EncodedPacket | null>,
packet: EncodedPacket, packet: EncodedPacket,
options: PacketRetrievalOptions, options: PacketRetrievalOptions,
): Promise<Yo> { ): MaybeRelevantPromise {
return this.getNextPacket(res, packet, options); return this.getNextPacket(res, packet, options);
} }
} }