mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-03 13:53:53 +02:00
Reorder stuff, rename stuff, add license header
This commit is contained in:
@@ -20,7 +20,7 @@ import {
|
|||||||
UNDETERMINED_LANGUAGE,
|
UNDETERMINED_LANGUAGE,
|
||||||
} from '../misc';
|
} from '../misc';
|
||||||
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
|
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
|
||||||
import { readBytes, Reader } from '../reader2';
|
import { readBytes, Reader } from '../reader';
|
||||||
import { FrameHeader, MAX_FRAME_HEADER_SIZE, MIN_FRAME_HEADER_SIZE, readFrameHeader } from './adts-reader';
|
import { FrameHeader, MAX_FRAME_HEADER_SIZE, MIN_FRAME_HEADER_SIZE, readFrameHeader } from './adts-reader';
|
||||||
|
|
||||||
const SAMPLES_PER_AAC_FRAME = 1024;
|
const SAMPLES_PER_AAC_FRAME = 1024;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { Bitstream } from '../misc';
|
import { Bitstream } from '../misc';
|
||||||
import { FileSlice, readBytes } from '../reader2';
|
import { FileSlice, readBytes } from '../reader';
|
||||||
|
|
||||||
export const MIN_FRAME_HEADER_SIZE = 7;
|
export const MIN_FRAME_HEADER_SIZE = 7;
|
||||||
export const MAX_FRAME_HEADER_SIZE = 9;
|
export const MAX_FRAME_HEADER_SIZE = 9;
|
||||||
|
|||||||
+1
-1
@@ -27,7 +27,7 @@ import { OggDemuxer } from './ogg/ogg-demuxer';
|
|||||||
import { WaveDemuxer } from './wave/wave-demuxer';
|
import { WaveDemuxer } from './wave/wave-demuxer';
|
||||||
import { MAX_FRAME_HEADER_SIZE, MIN_FRAME_HEADER_SIZE, readFrameHeader } from './adts/adts-reader';
|
import { MAX_FRAME_HEADER_SIZE, MIN_FRAME_HEADER_SIZE, readFrameHeader } from './adts/adts-reader';
|
||||||
import { AdtsDemuxer } from './adts/adts-demuxer';
|
import { AdtsDemuxer } from './adts/adts-demuxer';
|
||||||
import { readAscii } from './reader2';
|
import { readAscii } from './reader';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class representing an input media file format.
|
* Base class representing an input media file format.
|
||||||
|
|||||||
+1
-1
@@ -9,7 +9,7 @@
|
|||||||
import { Demuxer } from './demuxer';
|
import { Demuxer } from './demuxer';
|
||||||
import { InputFormat } from './input-format';
|
import { InputFormat } from './input-format';
|
||||||
import { assert } from './misc';
|
import { assert } from './misc';
|
||||||
import { Reader } from './reader2';
|
import { Reader } from './reader';
|
||||||
import { Source } from './source';
|
import { Source } from './source';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ import {
|
|||||||
readU64Be,
|
readU64Be,
|
||||||
readU8,
|
readU8,
|
||||||
readAscii,
|
readAscii,
|
||||||
} from '../reader2';
|
} from '../reader';
|
||||||
|
|
||||||
type InternalTrack = {
|
type InternalTrack = {
|
||||||
id: number;
|
id: number;
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FileSlice, readAscii, readI32Be, readU32Be, readU64Be, readU8 } from '../reader2';
|
import { FileSlice, readAscii, readI32Be, readU32Be, readU64Be, readU8 } from '../reader';
|
||||||
|
|
||||||
export const MIN_BOX_HEADER_SIZE = 8;
|
export const MIN_BOX_HEADER_SIZE = 8;
|
||||||
export const MAX_BOX_HEADER_SIZE = 16;
|
export const MAX_BOX_HEADER_SIZE = 16;
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import { MediaCodec } from '../codec';
|
import { MediaCodec } from '../codec';
|
||||||
import { assertNever, textDecoder, textEncoder } from '../misc';
|
import { assertNever, textDecoder, textEncoder } from '../misc';
|
||||||
import { FileSlice, readBytes, Reader, readF32Be, readF64Be, readU8 } from '../reader2';
|
import { FileSlice, readBytes, Reader, readF32Be, readF64Be, readU8 } from '../reader';
|
||||||
import { Writer } from '../writer';
|
import { Writer } from '../writer';
|
||||||
|
|
||||||
export interface EBMLElement {
|
export interface EBMLElement {
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ import {
|
|||||||
searchForNextElementId,
|
searchForNextElementId,
|
||||||
} from './ebml';
|
} from './ebml';
|
||||||
import { buildMatroskaMimeType } from './matroska-misc';
|
import { buildMatroskaMimeType } from './matroska-misc';
|
||||||
import { FileSlice, readBytes, Reader, readI16Be, readU8 } from '../reader2';
|
import { FileSlice, readBytes, Reader, readI16Be, readU8 } from '../reader';
|
||||||
|
|
||||||
type Segment = {
|
type Segment = {
|
||||||
seekHeadSeen: boolean;
|
seekHeadSeen: boolean;
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import { assert, AsyncMutex, binarySearchExact, binarySearchLessOrEqual, UNDETER
|
|||||||
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';
|
||||||
import { readId3, readNextFrameHeader } from './mp3-reader';
|
import { readId3, readNextFrameHeader } from './mp3-reader';
|
||||||
import { readBytes, Reader, readU32Be } from '../reader2';
|
import { readBytes, Reader, readU32Be } from '../reader';
|
||||||
|
|
||||||
type Sample = {
|
type Sample = {
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
|
|||||||
@@ -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 { FileSlice, readAscii, Reader, readU32Be } from '../reader2';
|
import { FileSlice, readAscii, Reader, readU32Be } from '../reader';
|
||||||
|
|
||||||
export const readId3 = (slice: FileSlice) => {
|
export const readId3 = (slice: FileSlice) => {
|
||||||
const tag = readAscii(slice, 3);
|
const tag = readAscii(slice, 3);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { InputAudioTrack, InputAudioTrackBacking } from '../input-track';
|
|||||||
import { PacketRetrievalOptions } from '../media-sink';
|
import { PacketRetrievalOptions } from '../media-sink';
|
||||||
import { assert, findLast, roundToPrecision, toDataView, UNDETERMINED_LANGUAGE } from '../misc';
|
import { assert, findLast, roundToPrecision, toDataView, UNDETERMINED_LANGUAGE } from '../misc';
|
||||||
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
|
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
|
||||||
import { readBytes, Reader } from '../reader2';
|
import { readBytes, Reader } from '../reader';
|
||||||
import { buildOggMimeType, computeOggPageCrc, extractSampleMetadata, OggCodecInfo } from './ogg-misc';
|
import { buildOggMimeType, computeOggPageCrc, extractSampleMetadata, OggCodecInfo } from './ogg-misc';
|
||||||
import {
|
import {
|
||||||
findNextPageHeader,
|
findNextPageHeader,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FileSlice, readI64Le, readU32Le, readU8 } from '../reader2';
|
import { FileSlice, readI64Le, readU32Le, readU8 } from '../reader';
|
||||||
import { OGGS } from './ogg-misc';
|
import { OGGS } from './ogg-misc';
|
||||||
|
|
||||||
export const MIN_PAGE_HEADER_SIZE = 27;
|
export const MIN_PAGE_HEADER_SIZE = 27;
|
||||||
|
|||||||
@@ -1,3 +1,11 @@
|
|||||||
|
/*!
|
||||||
|
* Copyright (c) 2025-present, Vanilagy and contributors
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
import { clamp, MaybePromise, toDataView } from './misc';
|
import { clamp, MaybePromise, toDataView } from './misc';
|
||||||
import { Source } from './source';
|
import { Source } from './source';
|
||||||
|
|
||||||
+159
-159
@@ -93,165 +93,6 @@ export class BufferSource extends Source {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Options for defining a StreamSource.
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export type StreamSourceOptions = {
|
|
||||||
/**
|
|
||||||
* Called when data is requested. Must return or resolve to the bytes from the specified byte range, or a stream
|
|
||||||
* that yields these bytes.
|
|
||||||
*/
|
|
||||||
read: (start: number, end: number) => MaybePromise<Uint8Array | ReadableStream<Uint8Array>>;
|
|
||||||
|
|
||||||
/** Called when the size of the entire file is requested. Must return or resolve to the size in bytes. */
|
|
||||||
getSize: () => MaybePromise<number>;
|
|
||||||
|
|
||||||
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 8 MiB. */
|
|
||||||
maxCacheSize?: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies the prefetch profile that the reader should use with this source. A prefetch propfile specifies the
|
|
||||||
* pattern with which bytes outside of the requested range are preloaded to reduce latency for future reads.
|
|
||||||
*
|
|
||||||
* - `'none'` (default): No prefetching; only the data needed in the moment is requested.
|
|
||||||
* - `'fileSystem'`: File system-optimized prefetching: a small amount of data is prefetched bidirectionally.
|
|
||||||
* - `'network'`: Network-optimized prefetching, or more generally, prefetching optimized for any high-latency
|
|
||||||
* environment: tries to minimize the amount of read calls and aggressively prefetches data when sequential access
|
|
||||||
* patterns are detected.
|
|
||||||
*/
|
|
||||||
prefetchProfile?: 'none' | 'fileSystem' | 'network';
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A general-purpose, callback-driven source that can get its data from anywhere.
|
|
||||||
* @public
|
|
||||||
*/
|
|
||||||
export class StreamSource extends Source {
|
|
||||||
/** @internal */
|
|
||||||
_options: StreamSourceOptions;
|
|
||||||
/** @internal */
|
|
||||||
_orchestrator: ReadOrchestrator;
|
|
||||||
|
|
||||||
constructor(options: StreamSourceOptions) {
|
|
||||||
if (!options || typeof options !== 'object') {
|
|
||||||
throw new TypeError('options must be an object.');
|
|
||||||
}
|
|
||||||
if (typeof options.read !== 'function') {
|
|
||||||
throw new TypeError('options.read must be a function.');
|
|
||||||
}
|
|
||||||
if (typeof options.getSize !== 'function') {
|
|
||||||
throw new TypeError('options.getSize must be a function.');
|
|
||||||
}
|
|
||||||
if (
|
|
||||||
options.maxCacheSize !== undefined
|
|
||||||
&& (!Number.isInteger(options.maxCacheSize) || options.maxCacheSize < 0)
|
|
||||||
) {
|
|
||||||
throw new TypeError('options.maxCacheSize, when provided, must be a non-negative integer.');
|
|
||||||
}
|
|
||||||
if (options.prefetchProfile && !['none', 'fileSystem', 'network'].includes(options.prefetchProfile)) {
|
|
||||||
throw new TypeError(
|
|
||||||
'options.prefetchProfile, when provided, must be one of \'none\', \'fileSystem\' or \'network\'.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
super();
|
|
||||||
|
|
||||||
this._options = options;
|
|
||||||
|
|
||||||
this._orchestrator = new ReadOrchestrator({
|
|
||||||
maxCacheSize: options.maxCacheSize ?? (8 * 2 ** 20 /* 8 MiB */),
|
|
||||||
maxWorkerCount: 2, // Fixed for now, *should* be fine
|
|
||||||
prefetchProfile: PREFETCH_PROFILES[options.prefetchProfile ?? 'none'],
|
|
||||||
runWorker: this._runWorker.bind(this),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
_retrieveSize(): MaybePromise<number> {
|
|
||||||
const result = this._options.getSize();
|
|
||||||
|
|
||||||
if (result instanceof Promise) {
|
|
||||||
return result.then((size) => {
|
|
||||||
if (!Number.isInteger(size) || size < 0) {
|
|
||||||
throw new TypeError('options.getSize must return or resolve to a non-negative integer.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._orchestrator.fileSize = size;
|
|
||||||
return size;
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (!Number.isInteger(result) || result < 0) {
|
|
||||||
throw new TypeError('options.getSize must return or resolve to a non-negative integer.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this._orchestrator.fileSize = result;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @internal */
|
|
||||||
_read(start: number, end: number): MaybePromise<ReadResult> {
|
|
||||||
return this._orchestrator.read(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async _runWorker(worker: ReadWorker) {
|
|
||||||
while (worker.currentPos < worker.targetPos && !worker.aborted) {
|
|
||||||
const originalCurrentPos = worker.currentPos;
|
|
||||||
const originalTargetPos = worker.targetPos;
|
|
||||||
|
|
||||||
let data = this._options.read(worker.currentPos, originalTargetPos);
|
|
||||||
if (data instanceof Promise) data = await data;
|
|
||||||
|
|
||||||
if (data instanceof Uint8Array) {
|
|
||||||
if (data.length !== originalTargetPos - worker.currentPos) {
|
|
||||||
// Yes, we're that strict
|
|
||||||
throw new Error(
|
|
||||||
`options.read returned a Uint8Array with unexpected length: Requested ${
|
|
||||||
originalTargetPos - worker.currentPos
|
|
||||||
} bytes, but got ${data.length}.`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onread?.(worker.currentPos, worker.currentPos + data.length);
|
|
||||||
this._orchestrator.supplyWorkerData(worker, data);
|
|
||||||
} else if (data instanceof ReadableStream) {
|
|
||||||
const reader = data.getReader();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
const { done, value } = await reader.read();
|
|
||||||
if (done) {
|
|
||||||
if (worker.currentPos < originalTargetPos) {
|
|
||||||
// Yes, we're *that* strict
|
|
||||||
throw new Error(
|
|
||||||
`ReadableStream returned by options.read ended before supplying enough data.`
|
|
||||||
+ ` Requested ${originalTargetPos - originalCurrentPos} bytes, but got ${
|
|
||||||
worker.currentPos - originalCurrentPos
|
|
||||||
}`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(value instanceof Uint8Array)) {
|
|
||||||
throw new TypeError('ReadableStream returned by options.read must yield Uint8Array chunks.');
|
|
||||||
}
|
|
||||||
|
|
||||||
this.onread?.(worker.currentPos, worker.currentPos + value.length);
|
|
||||||
this._orchestrator.supplyWorkerData(worker, value);
|
|
||||||
|
|
||||||
if (worker.currentPos >= originalTargetPos || worker.aborted) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new TypeError('options.read must return or resolve to a Uint8Array or a ReadableStream.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export type BlobSourceOptions = {
|
export type BlobSourceOptions = {
|
||||||
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 8 MiB. */
|
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 8 MiB. */
|
||||||
maxCacheSize?: number;
|
maxCacheSize?: number;
|
||||||
@@ -566,6 +407,165 @@ export class UrlSource extends Source {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Options for defining a StreamSource.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export type StreamSourceOptions = {
|
||||||
|
/**
|
||||||
|
* Called when data is requested. Must return or resolve to the bytes from the specified byte range, or a stream
|
||||||
|
* that yields these bytes.
|
||||||
|
*/
|
||||||
|
read: (start: number, end: number) => MaybePromise<Uint8Array | ReadableStream<Uint8Array>>;
|
||||||
|
|
||||||
|
/** Called when the size of the entire file is requested. Must return or resolve to the size in bytes. */
|
||||||
|
getSize: () => MaybePromise<number>;
|
||||||
|
|
||||||
|
/** The maximum number of bytes the cache is allowed to hold in memory. Defaults to 8 MiB. */
|
||||||
|
maxCacheSize?: number;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the prefetch profile that the reader should use with this source. A prefetch propfile specifies the
|
||||||
|
* pattern with which bytes outside of the requested range are preloaded to reduce latency for future reads.
|
||||||
|
*
|
||||||
|
* - `'none'` (default): No prefetching; only the data needed in the moment is requested.
|
||||||
|
* - `'fileSystem'`: File system-optimized prefetching: a small amount of data is prefetched bidirectionally.
|
||||||
|
* - `'network'`: Network-optimized prefetching, or more generally, prefetching optimized for any high-latency
|
||||||
|
* environment: tries to minimize the amount of read calls and aggressively prefetches data when sequential access
|
||||||
|
* patterns are detected.
|
||||||
|
*/
|
||||||
|
prefetchProfile?: 'none' | 'fileSystem' | 'network';
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A general-purpose, callback-driven source that can get its data from anywhere.
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export class StreamSource extends Source {
|
||||||
|
/** @internal */
|
||||||
|
_options: StreamSourceOptions;
|
||||||
|
/** @internal */
|
||||||
|
_orchestrator: ReadOrchestrator;
|
||||||
|
|
||||||
|
constructor(options: StreamSourceOptions) {
|
||||||
|
if (!options || typeof options !== 'object') {
|
||||||
|
throw new TypeError('options must be an object.');
|
||||||
|
}
|
||||||
|
if (typeof options.read !== 'function') {
|
||||||
|
throw new TypeError('options.read must be a function.');
|
||||||
|
}
|
||||||
|
if (typeof options.getSize !== 'function') {
|
||||||
|
throw new TypeError('options.getSize must be a function.');
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
options.maxCacheSize !== undefined
|
||||||
|
&& (!Number.isInteger(options.maxCacheSize) || options.maxCacheSize < 0)
|
||||||
|
) {
|
||||||
|
throw new TypeError('options.maxCacheSize, when provided, must be a non-negative integer.');
|
||||||
|
}
|
||||||
|
if (options.prefetchProfile && !['none', 'fileSystem', 'network'].includes(options.prefetchProfile)) {
|
||||||
|
throw new TypeError(
|
||||||
|
'options.prefetchProfile, when provided, must be one of \'none\', \'fileSystem\' or \'network\'.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
super();
|
||||||
|
|
||||||
|
this._options = options;
|
||||||
|
|
||||||
|
this._orchestrator = new ReadOrchestrator({
|
||||||
|
maxCacheSize: options.maxCacheSize ?? (8 * 2 ** 20 /* 8 MiB */),
|
||||||
|
maxWorkerCount: 2, // Fixed for now, *should* be fine
|
||||||
|
prefetchProfile: PREFETCH_PROFILES[options.prefetchProfile ?? 'none'],
|
||||||
|
runWorker: this._runWorker.bind(this),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
_retrieveSize(): MaybePromise<number> {
|
||||||
|
const result = this._options.getSize();
|
||||||
|
|
||||||
|
if (result instanceof Promise) {
|
||||||
|
return result.then((size) => {
|
||||||
|
if (!Number.isInteger(size) || size < 0) {
|
||||||
|
throw new TypeError('options.getSize must return or resolve to a non-negative integer.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._orchestrator.fileSize = size;
|
||||||
|
return size;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (!Number.isInteger(result) || result < 0) {
|
||||||
|
throw new TypeError('options.getSize must return or resolve to a non-negative integer.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this._orchestrator.fileSize = result;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @internal */
|
||||||
|
_read(start: number, end: number): MaybePromise<ReadResult> {
|
||||||
|
return this._orchestrator.read(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async _runWorker(worker: ReadWorker) {
|
||||||
|
while (worker.currentPos < worker.targetPos && !worker.aborted) {
|
||||||
|
const originalCurrentPos = worker.currentPos;
|
||||||
|
const originalTargetPos = worker.targetPos;
|
||||||
|
|
||||||
|
let data = this._options.read(worker.currentPos, originalTargetPos);
|
||||||
|
if (data instanceof Promise) data = await data;
|
||||||
|
|
||||||
|
if (data instanceof Uint8Array) {
|
||||||
|
if (data.length !== originalTargetPos - worker.currentPos) {
|
||||||
|
// Yes, we're that strict
|
||||||
|
throw new Error(
|
||||||
|
`options.read returned a Uint8Array with unexpected length: Requested ${
|
||||||
|
originalTargetPos - worker.currentPos
|
||||||
|
} bytes, but got ${data.length}.`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onread?.(worker.currentPos, worker.currentPos + data.length);
|
||||||
|
this._orchestrator.supplyWorkerData(worker, data);
|
||||||
|
} else if (data instanceof ReadableStream) {
|
||||||
|
const reader = data.getReader();
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
const { done, value } = await reader.read();
|
||||||
|
if (done) {
|
||||||
|
if (worker.currentPos < originalTargetPos) {
|
||||||
|
// Yes, we're *that* strict
|
||||||
|
throw new Error(
|
||||||
|
`ReadableStream returned by options.read ended before supplying enough data.`
|
||||||
|
+ ` Requested ${originalTargetPos - originalCurrentPos} bytes, but got ${
|
||||||
|
worker.currentPos - originalCurrentPos
|
||||||
|
}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(value instanceof Uint8Array)) {
|
||||||
|
throw new TypeError('ReadableStream returned by options.read must yield Uint8Array chunks.');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.onread?.(worker.currentPos, worker.currentPos + value.length);
|
||||||
|
this._orchestrator.supplyWorkerData(worker, value);
|
||||||
|
|
||||||
|
if (worker.currentPos >= originalTargetPos || worker.aborted) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new TypeError('options.read must return or resolve to a Uint8Array or a ReadableStream.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type PrefetchProfile = (start: number, end: number, workers: ReadWorker[]) => {
|
type PrefetchProfile = (start: number, end: number, workers: ReadWorker[]) => {
|
||||||
start: number;
|
start: number;
|
||||||
end: number;
|
end: number;
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { InputAudioTrack, InputAudioTrackBacking } from '../input-track';
|
|||||||
import { PacketRetrievalOptions } from '../media-sink';
|
import { PacketRetrievalOptions } from '../media-sink';
|
||||||
import { assert, UNDETERMINED_LANGUAGE } from '../misc';
|
import { assert, UNDETERMINED_LANGUAGE } from '../misc';
|
||||||
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
|
import { EncodedPacket, PLACEHOLDER_DATA } from '../packet';
|
||||||
import { readAscii, readBytes, Reader, readU16, readU32, readU64 } from '../reader2';
|
import { readAscii, readBytes, Reader, readU16, readU32, readU64 } from '../reader';
|
||||||
|
|
||||||
export enum WaveFormat {
|
export enum WaveFormat {
|
||||||
PCM = 0x0001,
|
PCM = 0x0001,
|
||||||
|
|||||||
Reference in New Issue
Block a user