mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-03 13:53:53 +02:00
Name call serializers differently
This commit is contained in:
+2
-2
@@ -14,7 +14,7 @@ import {
|
|||||||
assert,
|
assert,
|
||||||
AsyncMutex,
|
AsyncMutex,
|
||||||
AsyncMutexLock,
|
AsyncMutexLock,
|
||||||
CallSerializer2,
|
ForgivingCallSerializer,
|
||||||
defer,
|
defer,
|
||||||
isFirefox,
|
isFirefox,
|
||||||
last,
|
last,
|
||||||
@@ -255,7 +255,7 @@ export class PacketCursor<T extends InputTrack = InputTrack> {
|
|||||||
private _reader: PacketReader<T>;
|
private _reader: PacketReader<T>;
|
||||||
private _options: PacketRetrievalOptions;
|
private _options: PacketRetrievalOptions;
|
||||||
private _nextIsFirst = true;
|
private _nextIsFirst = true;
|
||||||
private _callSerializer = new CallSerializer2();
|
private _callSerializer = new ForgivingCallSerializer();
|
||||||
|
|
||||||
constructor(track: T, options: PacketRetrievalOptions = {}) {
|
constructor(track: T, options: PacketRetrievalOptions = {}) {
|
||||||
if (!(track instanceof InputTrack)) {
|
if (!(track instanceof InputTrack)) {
|
||||||
|
|||||||
+3
-3
@@ -20,7 +20,7 @@ import {
|
|||||||
} from './codec-data';
|
} from './codec-data';
|
||||||
import { CustomAudioDecoder, customAudioDecoders, CustomVideoDecoder, customVideoDecoders } from './custom-coder';
|
import { CustomAudioDecoder, customAudioDecoders, CustomVideoDecoder, customVideoDecoders } from './custom-coder';
|
||||||
import {
|
import {
|
||||||
CallSerializer,
|
NaiveCallSerializer,
|
||||||
Rotation,
|
Rotation,
|
||||||
isChromium,
|
isChromium,
|
||||||
toUint8Array,
|
toUint8Array,
|
||||||
@@ -57,7 +57,7 @@ export class VideoDecoderWrapper extends DecoderWrapper<VideoSample> {
|
|||||||
decoder: VideoDecoder | null = null;
|
decoder: VideoDecoder | null = null;
|
||||||
|
|
||||||
customDecoder: CustomVideoDecoder | null = null;
|
customDecoder: CustomVideoDecoder | null = null;
|
||||||
customDecoderCallSerializer = new CallSerializer();
|
customDecoderCallSerializer = new NaiveCallSerializer();
|
||||||
customDecoderQueueSize = 0;
|
customDecoderQueueSize = 0;
|
||||||
customDecoderClosed = false;
|
customDecoderClosed = false;
|
||||||
|
|
||||||
@@ -645,7 +645,7 @@ export class AudioDecoderWrapper extends DecoderWrapper<AudioSample> {
|
|||||||
decoder: AudioDecoder | null = null;
|
decoder: AudioDecoder | null = null;
|
||||||
|
|
||||||
customDecoder: CustomAudioDecoder | null = null;
|
customDecoder: CustomAudioDecoder | null = null;
|
||||||
customDecoderCallSerializer = new CallSerializer();
|
customDecoderCallSerializer = new NaiveCallSerializer();
|
||||||
customDecoderQueueSize = 0;
|
customDecoderQueueSize = 0;
|
||||||
customDecoderClosed = false;
|
customDecoderClosed = false;
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -23,7 +23,7 @@ import { OutputAudioTrack, OutputSubtitleTrack, OutputTrack, OutputVideoTrack }
|
|||||||
import {
|
import {
|
||||||
assert,
|
assert,
|
||||||
assertNever,
|
assertNever,
|
||||||
CallSerializer,
|
NaiveCallSerializer,
|
||||||
clamp,
|
clamp,
|
||||||
isFirefox,
|
isFirefox,
|
||||||
last,
|
last,
|
||||||
@@ -214,7 +214,7 @@ class VideoEncoderWrapper {
|
|||||||
private resizeCanvas: HTMLCanvasElement | OffscreenCanvas | null = null;
|
private resizeCanvas: HTMLCanvasElement | OffscreenCanvas | null = null;
|
||||||
|
|
||||||
private customEncoder: CustomVideoEncoder | null = null;
|
private customEncoder: CustomVideoEncoder | null = null;
|
||||||
private customEncoderCallSerializer = new CallSerializer();
|
private customEncoderCallSerializer = new NaiveCallSerializer();
|
||||||
private customEncoderQueueSize = 0;
|
private customEncoderQueueSize = 0;
|
||||||
|
|
||||||
// Alpha stuff
|
// Alpha stuff
|
||||||
@@ -1342,7 +1342,7 @@ class AudioEncoderWrapper {
|
|||||||
private writeOutputValue: ((view: DataView, byteOffset: number, value: number) => void) | null = null;
|
private writeOutputValue: ((view: DataView, byteOffset: number, value: number) => void) | null = null;
|
||||||
|
|
||||||
private customEncoder: CustomAudioEncoder | null = null;
|
private customEncoder: CustomAudioEncoder | null = null;
|
||||||
private customEncoderCallSerializer = new CallSerializer();
|
private customEncoderCallSerializer = new NaiveCallSerializer();
|
||||||
private customEncoderQueueSize = 0;
|
private customEncoderQueueSize = 0;
|
||||||
|
|
||||||
private lastEndSampleIndex: number | null = null;
|
private lastEndSampleIndex: number | null = null;
|
||||||
|
|||||||
+24
-15
@@ -675,20 +675,6 @@ export const computeRationalApproximation = (x: number, maxDenominator: number)
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export class CallSerializer {
|
|
||||||
currentPromise = Promise.resolve();
|
|
||||||
errored = false;
|
|
||||||
|
|
||||||
call(fn: () => Promise<void> | void) {
|
|
||||||
return this.currentPromise = this.currentPromise
|
|
||||||
.then(fn)
|
|
||||||
.catch((error) => {
|
|
||||||
this.errored = true;
|
|
||||||
throw error;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let isWebKitCache: boolean | null = null;
|
let isWebKitCache: boolean | null = null;
|
||||||
export const isWebKit = () => {
|
export const isWebKit = () => {
|
||||||
if (isWebKitCache !== null) {
|
if (isWebKitCache !== null) {
|
||||||
@@ -938,7 +924,30 @@ export class AsyncMutexLock implements Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CallSerializer2 {
|
/**
|
||||||
|
* A simple call serializer that works by chaining promises. When one callback throws, the serializer becomes bricked,
|
||||||
|
* meaning all future calls will also throw.
|
||||||
|
*/
|
||||||
|
export class NaiveCallSerializer {
|
||||||
|
currentPromise = Promise.resolve();
|
||||||
|
errored = false;
|
||||||
|
|
||||||
|
call(fn: () => Promise<void> | void) {
|
||||||
|
return this.currentPromise = this.currentPromise
|
||||||
|
.then(fn)
|
||||||
|
.catch((error) => {
|
||||||
|
this.errored = true;
|
||||||
|
throw error;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A more complex call serializer implementation that works with optionally asynchronous functions. It is forgiving
|
||||||
|
* in the sense that when a call throws, the error is surfaced but subsequent calls will go through again. So, it
|
||||||
|
* recovers.
|
||||||
|
*/
|
||||||
|
export class ForgivingCallSerializer {
|
||||||
private currentPromise: Promise<unknown> | null = null;
|
private currentPromise: Promise<unknown> | null = null;
|
||||||
private queuedCalls = 0;
|
private queuedCalls = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { expect, test } from 'vitest';
|
import { expect, test } from 'vitest';
|
||||||
import { CallSerializer2 } from '../../src/misc.js';
|
import { ForgivingCallSerializer } from '../../src/misc.js';
|
||||||
|
|
||||||
const executeDelayed = async <T>(fn: () => T) => {
|
const executeDelayed = async <T>(fn: () => T) => {
|
||||||
await new Promise(resolve => setTimeout(resolve, 10));
|
await new Promise(resolve => setTimeout(resolve, 10));
|
||||||
@@ -8,7 +8,7 @@ const executeDelayed = async <T>(fn: () => T) => {
|
|||||||
|
|
||||||
test('Call serialization and return values', async () => {
|
test('Call serialization and return values', async () => {
|
||||||
const numbers: number[] = [];
|
const numbers: number[] = [];
|
||||||
const serializer = new CallSerializer2();
|
const serializer = new ForgivingCallSerializer();
|
||||||
|
|
||||||
const first = serializer.call(() => numbers.push(1));
|
const first = serializer.call(() => numbers.push(1));
|
||||||
const second = serializer.call(() => executeDelayed(() => numbers.push(2)));
|
const second = serializer.call(() => executeDelayed(() => numbers.push(2)));
|
||||||
@@ -25,7 +25,7 @@ test('Call serialization and return values', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Synchronous return value', async () => {
|
test('Synchronous return value', async () => {
|
||||||
const serializer = new CallSerializer2();
|
const serializer = new ForgivingCallSerializer();
|
||||||
|
|
||||||
const first = serializer.call(() => {});
|
const first = serializer.call(() => {});
|
||||||
expect(first).not.toBeInstanceOf(Promise);
|
expect(first).not.toBeInstanceOf(Promise);
|
||||||
@@ -42,7 +42,7 @@ test('Synchronous return value', async () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Error handling', async () => {
|
test('Error handling', async () => {
|
||||||
const serializer = new CallSerializer2();
|
const serializer = new ForgivingCallSerializer();
|
||||||
|
|
||||||
expect(() => serializer.call(() => {
|
expect(() => serializer.call(() => {
|
||||||
throw new Error('yo');
|
throw new Error('yo');
|
||||||
Reference in New Issue
Block a user