From 8ae0f9d09ebd5b8a26863b1ee47c658782b48b73 Mon Sep 17 00:00:00 2001 From: Vanilagy <1696106+Vanilagy@users.noreply.github.com> Date: Mon, 29 Jun 2026 17:15:10 +0200 Subject: [PATCH] Implement @mediabunny/prores extension, add onError callbacks to custom coders, fix visibleRect bug in VideoSample --- .github/workflows/release.yml | 5 + .gitignore | 3 +- docs/.vitepress/config.mts | 1 + docs/api-config.json | 3 +- docs/guide/extensions/prores.md | 36 ++ docs/guide/supported-formats-and-codecs.md | 13 +- eslint.config.mjs | 1 + examples/file-compression/file-compression.ts | 1 + examples/media-player/media-player.ts | 4 - package-lock.json | 19 + package.json | 2 +- packages/prores-decoder/README.md | 46 --- packages/prores-decoder/build/prores.js | Bin 424875 -> 0 bytes packages/prores-decoder/src/bridge.c | 182 --------- packages/prores-decoder/src/index.ts | 90 ----- packages/prores/LICENSE | 373 ++++++++++++++++++ packages/prores/README.md | 44 +++ packages/prores/api-extractor.json | 37 ++ .../{prores-decoder => prores}/package.json | 38 +- packages/prores/src/index.ts | 212 ++++++++++ .../src => prores}/tsconfig.json | 10 +- packages/prores/tsdoc.json | 4 + packages/server/src/video-encoder.ts | 4 + scripts/build.sh | 5 + scripts/bundle.ts | 19 + scripts/check.sh | 3 + scripts/ensure-license-headers.ts | 1 + src/codec.ts | 7 +- src/custom-coder.ts | 8 + src/encode.ts | 12 +- src/isobmff/isobmff-demuxer.ts | 12 +- src/matroska/matroska-demuxer.ts | 20 +- src/media-sink.ts | 82 ++-- src/media-source.ts | 77 +++- src/mpeg-ts/mpeg-ts-demuxer.ts | 1 + src/sample.ts | 60 ++- test/node/prores.test.ts | 77 ++-- todo.txt | 2 - tsconfig.vite.json | 1 + tsconfig.vitest.json | 2 + vite.config.ts | 6 + vitest.config.ts | 2 + 42 files changed, 1074 insertions(+), 451 deletions(-) create mode 100644 docs/guide/extensions/prores.md delete mode 100644 packages/prores-decoder/README.md delete mode 100644 packages/prores-decoder/build/prores.js delete mode 100644 packages/prores-decoder/src/bridge.c delete mode 100644 packages/prores-decoder/src/index.ts create mode 100644 packages/prores/LICENSE create mode 100644 packages/prores/README.md create mode 100644 packages/prores/api-extractor.json rename packages/{prores-decoder => prores}/package.json (50%) create mode 100644 packages/prores/src/index.ts rename packages/{prores-decoder/src => prores}/tsconfig.json (63%) create mode 100644 packages/prores/tsdoc.json delete mode 100644 todo.txt diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e06b340..c10309d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,6 +93,11 @@ jobs: packages/flac-encoder/dist/bundles/mediabunny-flac-encoder.mjs packages/flac-encoder/dist/bundles/mediabunny-flac-encoder.min.mjs packages/flac-encoder/dist/mediabunny-flac-encoder.d.ts + packages/prores/dist/bundles/mediabunny-prores.js + packages/prores/dist/bundles/mediabunny-prores.min.js + packages/prores/dist/bundles/mediabunny-prores.mjs + packages/prores/dist/bundles/mediabunny-prores.min.mjs + packages/prores/dist/mediabunny-prores.d.ts packages/server/dist/bundles/mediabunny-server.cjs packages/server/dist/bundles/mediabunny-server.min.cjs packages/server/dist/bundles/mediabunny-server.mjs diff --git a/.gitignore b/.gitignore index 10904ca..30c66a0 100644 --- a/.gitignore +++ b/.gitignore @@ -10,4 +10,5 @@ packages/mp3-encoder/dist packages/ac3/dist packages/aac-encoder/dist packages/flac-encoder/dist -packages/server/dist \ No newline at end of file +packages/server/dist +packages/prores/dist \ No newline at end of file diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 7b779a6..d9d6b7b 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -121,6 +121,7 @@ export default withMermaid({ { text: 'aac-encoder', link: '/guide/extensions/aac-encoder' }, { text: 'ac3', link: '/guide/extensions/ac3' }, { text: 'flac-encoder', link: '/guide/extensions/flac-encoder' }, + { text: 'prores', link: '/guide/extensions/prores' }, ], }, ], diff --git a/docs/api-config.json b/docs/api-config.json index 376e45e..b56656e 100644 --- a/docs/api-config.json +++ b/docs/api-config.json @@ -26,5 +26,6 @@ "@mediabunny/mp3-encoder": "Adds MP3 encoder support to Mediabunny.", "@mediabunny/ac3": "Adds AC-3/E-AC-3 decoder and encoder support to Mediabunny.", "@mediabunny/aac-encoder": "Polyfills AAC encoder support to Mediabunny.", - "@mediabunny/flac-encoder": "Adds FLAC encoder support to Mediabunny." + "@mediabunny/flac-encoder": "Adds FLAC encoder support to Mediabunny.", + "@mediabunny/prores": "Adds Apple ProRes decoder support to Mediabunny." } diff --git a/docs/guide/extensions/prores.md b/docs/guide/extensions/prores.md new file mode 100644 index 0000000..c1bf689 --- /dev/null +++ b/docs/guide/extensions/prores.md @@ -0,0 +1,36 @@ +--- +description: The @mediabunny/prores extension provides an extremely fast Apple ProRes decoder for the browser. +--- + +# @mediabunny/prores + +Browsers have no support for Apple ProRes in their WebCodecs implementations. This extension package provides a decoder for use with Mediabunny, allowing you to decode ProRes directly in the browser at unprecedented speed. It is implemented using Mediabunny's [custom coder API](https://mediabunny.dev/guide/supported-formats-and-codecs#custom-coders) and uses [TurboRes](https://github.com/Vanilagy/turbores), an extremely fast WASM-based ProRes decoder, under the hood. + + + GitHub page + + + +## Installation + +This library peer-depends on Mediabunny. Install both using npm: +```bash +npm install mediabunny @mediabunny/prores +``` + +Alternatively, directly include them using a script tag: +```html + + +``` + +This will expose the global objects `Mediabunny` and `MediabunnyProres`. Use `mediabunny-prores.d.ts` to provide types for these globals. You can download the built distribution files from the [releases page](https://github.com/Vanilagy/mediabunny/releases). + +## Usage + +```ts +import { registerProresDecoder } from '@mediabunny/prores'; + +registerProresDecoder(); +``` +That's it - Mediabunny now uses the registered ProRes decoder automatically. diff --git a/docs/guide/supported-formats-and-codecs.md b/docs/guide/supported-formats-and-codecs.md index 1ce556d..780f78b 100644 --- a/docs/guide/supported-formats-and-codecs.md +++ b/docs/guide/supported-formats-and-codecs.md @@ -40,6 +40,7 @@ Mediabunny ships with built-in decoders and encoders for all audio PCM codecs, m - `'vp8'` - VP8 - `'vp9'` - VP9 - `'av1'` - AOMedia Video 1 (AV1) +- `'prores'` - Apple ProRes [^prores] ### Audio codecs @@ -80,6 +81,7 @@ Not all codecs can be used with all containers. The following table specifies th | `'vp8'` | ✓ | ✓ | ✓ | ✓ | | | | | | | | `'vp9'` | ✓ | ✓ | ✓ | ✓ | | | | | | | | `'av1'` | ✓ | ✓ | ✓ | ✓ | | | | | | | +| `'prores'` | ✓ | ✓ | ✓ | | | | | | | | | `'aac'` | ✓ | ✓ | ✓ | | | | | ✓ | | ✓ | | `'opus'` | ✓ | ✓ | ✓ | ✓ | ✓ | | | | | | | `'mp3'` | ✓ | ✓ | ✓ | | | ✓ | | | | ✓ | @@ -105,6 +107,7 @@ Not all codecs can be used with all containers. The following table specifies th For HLS, the supported codecs depend on the segment format chosen. +[^prores]: ProRes is not supported by WebCodecs. To decode it, use the [`@mediabunny/prores`](./extensions/prores) extension package. [^aac]: In some browsers, AAC encoding is not supported by WebCodecs. You can polyfill it with the [`@mediabunny/aac-encoder`](./extensions/aac-encoder) extension package. [^mp3]: MP3 encoding is not supported by WebCodecs. You can polyfill it with the [`@mediabunny/mp3-encoder`](./extensions/mp3-encoder) extension package. [^flac]: FLAC encoding is not supported by WebCodecs. You can polyfill it with the [`@mediabunny/flac-encoder`](./extensions/flac-encoder) extension package. @@ -293,10 +296,13 @@ class { codec: AudioCodec; config: AudioEncoderConfig; onPacket: (packet: EncodedPacket, meta?: EncodedAudioChunkMetadata) => unknown; + + // For both: + onError: (error: unknown) => void; } ``` -`codec` and `config` specify the concrete codec configuration to use, and `onPacket` is a method that your code **must** call for each encoded packet it creates. +`codec` and `config` specify the concrete codec configuration to use, and `onPacket` is a method that your code **must** call for each encoded packet it creates. `onError` is a method you can call to surface any out-of-band errors that occur outside of the regular method calls (such as from an asynchronous background task); these errors would otherwise go uncaught. You **must** implement the following methods in your custom encoder class: ```ts @@ -356,10 +362,13 @@ class { codec: AudioCodec; config: AudioDecoderConfig; onSample: (sample: AudioSample) => unknown; + + // For both: + onError: (error: unknown) => void; } ``` -`codec` and `config` specify the concrete codec configuration to use, and `onSample` is a method that your code **must** call for each video/audio sample it creates. +`codec` and `config` specify the concrete codec configuration to use, and `onSample` is a method that your code **must** call for each video/audio sample it creates. `onError` is a method you can call to surface any out-of-band errors that occur outside of the regular method calls (such as from an asynchronous background task); these errors would otherwise go uncaught. You **must** implement the following methods in your custom decoder class: ```ts diff --git a/eslint.config.mjs b/eslint.config.mjs index b0330c2..6a9caaf 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -47,6 +47,7 @@ export default tseslint.config( 'packages/aac-encoder/build', 'packages/flac-encoder/dist', 'packages/flac-encoder/build', + 'packages/prores/dist', 'packages/server/dist', 'eslint.config.mjs', 'docs/.vitepress/cache', diff --git a/examples/file-compression/file-compression.ts b/examples/file-compression/file-compression.ts index 7c68c05..d4613fa 100644 --- a/examples/file-compression/file-compression.ts +++ b/examples/file-compression/file-compression.ts @@ -68,6 +68,7 @@ const compressFile = async (resource: File | string) => { bitrate: QUALITY_VERY_LOW, }, audio: { + codec: 'opus', bitrate: QUALITY_VERY_LOW, }, }); diff --git a/examples/media-player/media-player.ts b/examples/media-player/media-player.ts index 7d22cdf..30f6040 100644 --- a/examples/media-player/media-player.ts +++ b/examples/media-player/media-player.ts @@ -4,7 +4,6 @@ import { BlobSource, CanvasSink, Input, - registerDecoder, UrlSource, WrappedAudioBuffer, WrappedCanvas, @@ -75,9 +74,6 @@ let volumeMuted = false; /** === INIT LOGIC === */ -import { ProResDecoder } from '../../packages/prores-decoder/src/index.js'; -registerDecoder(ProResDecoder); - const initMediaPlayer = async (resource: File | string) => { try { // First, dispose any ongoing playback: diff --git a/package-lock.json b/package-lock.json index 4fa0b13..7f15975 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1461,6 +1461,10 @@ "resolved": "packages/mp3-encoder", "link": true }, + "node_modules/@mediabunny/prores": { + "resolved": "packages/prores", + "link": true + }, "node_modules/@mediabunny/server": { "resolved": "packages/server", "link": true @@ -12922,6 +12926,21 @@ "mediabunny": "^1.0.0" } }, + "packages/prores": { + "name": "@mediabunny/prores", + "version": "1.25.8", + "license": "MPL-2.0", + "devDependencies": { + "@types/emscripten": "^1.40.1" + }, + "funding": { + "type": "individual", + "url": "https://github.com/sponsors/Vanilagy" + }, + "peerDependencies": { + "mediabunny": "^1.0.0" + } + }, "packages/server": { "name": "@mediabunny/server", "version": "1.49.0", diff --git a/package.json b/package.json index 8e96992..eaf8658 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "docs:dev": "vitepress dev docs", "docs:build": "npm run build && npm run docs:generate && vitepress build docs && npm run examples:build && cp dist/mediabunny.d.ts dist-docs/", "docs:preview": "vitepress preview docs", - "docs:generate": "tsx scripts/generate-api-docs.ts src/index.ts packages/mp3-encoder/src/index.ts packages/ac3/src/index.ts packages/aac-encoder/src/index.ts packages/flac-encoder/src/index.ts packages/server/src/index.ts docs/api-config.json", + "docs:generate": "tsx scripts/generate-api-docs.ts src/index.ts packages/mp3-encoder/src/index.ts packages/ac3/src/index.ts packages/aac-encoder/src/index.ts packages/flac-encoder/src/index.ts packages/prores/src/index.ts packages/server/src/index.ts docs/api-config.json", "dev": "vite", "examples:build": "vite build", "fix-build-import-paths": "tsx scripts/add-import-extensions.ts", diff --git a/packages/prores-decoder/README.md b/packages/prores-decoder/README.md deleted file mode 100644 index 275a5e8..0000000 --- a/packages/prores-decoder/README.md +++ /dev/null @@ -1,46 +0,0 @@ -```bash -emmake make distclean - -emconfigure ./configure \ - --target-os=none \ - --arch=x86_32 \ - --enable-cross-compile \ - --disable-asm \ - --disable-x86asm \ - --disable-inline-asm \ - --disable-stripping \ - --disable-programs \ - --disable-doc \ - --disable-debug \ - --disable-all \ - --disable-everything \ - --disable-pthreads \ - --enable-avcodec \ - --enable-decoder=prores \ - --cc="emcc" \ - --cxx=em++ \ - --ar=emar \ - --ranlib=emranlib \ - --extra-cflags="-DNDEBUG -O3 -msimd128" - -emmake make -``` - -```bash -export FFMPEG_PATH=/path/to/ffmpeg - -emcc src/bridge.c \ - $FFMPEG_PATH/libavcodec/libavcodec.a \ - $FFMPEG_PATH/libavutil/libavutil.a \ - -I$FFMPEG_PATH \ - -s MODULARIZE=1 \ - -s EXPORT_ES6=1 \ - -s SINGLE_FILE=1 \ - -s ALLOW_MEMORY_GROWTH=1 \ - -s ENVIRONMENT=web,worker \ - -s EXPORTED_RUNTIME_METHODS=cwrap,HEAPU8 \ - -s EXPORTED_FUNCTIONS=_malloc,_free \ - -msimd128 \ - -O3 \ - -o build/prores.js -``` \ No newline at end of file diff --git a/packages/prores-decoder/build/prores.js b/packages/prores-decoder/build/prores.js deleted file mode 100644 index ea5911b3ac44f74a7a9e4fc82c93eb273ac4ea52..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 424875 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 EFNr0_y#N3J diff --git a/packages/prores-decoder/src/bridge.c b/packages/prores-decoder/src/bridge.c deleted file mode 100644 index e0976f0..0000000 --- a/packages/prores-decoder/src/bridge.c +++ /dev/null @@ -1,182 +0,0 @@ -#include -#include -#include "libavcodec/avcodec.h" -#include "libavutil/pixdesc.h" -#include "libavutil/imgutils.h" - -typedef struct { - AVCodecContext *codec_ctx; - AVPacket *packet; - AVFrame *frame; - uint8_t *buffer; - int buffer_size; -} DecoderContext; - -EMSCRIPTEN_KEEPALIVE -DecoderContext *init_decoder() { - const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_PRORES); - if (!codec) return NULL; - - AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); - if (!codec_ctx) return NULL; - - if (avcodec_open2(codec_ctx, codec, NULL) < 0) { - avcodec_free_context(&codec_ctx); - return NULL; - } - - AVPacket *packet = av_packet_alloc(); - if (!packet) { - avcodec_free_context(&codec_ctx); - return NULL; - } - - AVFrame *frame = av_frame_alloc(); - if (!frame) { - av_packet_free(&packet); - avcodec_free_context(&codec_ctx); - return NULL; - } - - DecoderContext *ctx = malloc(sizeof(DecoderContext)); - if (!ctx) { - av_frame_free(&frame); - av_packet_free(&packet); - avcodec_free_context(&codec_ctx); - return NULL; - } - - ctx->codec_ctx = codec_ctx; - ctx->packet = packet; - ctx->frame = frame; - ctx->buffer = NULL; - ctx->buffer_size = 0; - - return ctx; -} - -EMSCRIPTEN_KEEPALIVE -uint8_t *configure_packet(DecoderContext *ctx, int size) { - if (av_new_packet(ctx->packet, size) < 0) { - return NULL; - } - - ctx->packet->pts = 0; - ctx->packet->dts = AV_NOPTS_VALUE; - ctx->packet->time_base.num = 1; - ctx->packet->time_base.den = 1; - ctx->packet->flags = AV_PKT_FLAG_KEY; - - return ctx->packet->data; -} - -EMSCRIPTEN_KEEPALIVE -int decode_packet(DecoderContext *ctx) { - double start = emscripten_get_now(); - - int ret = avcodec_send_packet(ctx->codec_ctx, ctx->packet); - if (ret < 0) { - return ret; - } - - double after_send = emscripten_get_now(); - - ret = avcodec_receive_frame(ctx->codec_ctx, ctx->frame); - if (ret < 0) { - return ret; - } - - double after_receive = emscripten_get_now(); - - // Calculate required buffer size - int required_size = av_image_get_buffer_size( - ctx->frame->format, - ctx->frame->width, - ctx->frame->height, - 1 - ); - - if (required_size < 0) { - return required_size; - } - - // Reallocate buffer if needed - if (ctx->buffer_size < required_size) { - free(ctx->buffer); - ctx->buffer = malloc(required_size); - if (!ctx->buffer) { - ctx->buffer_size = 0; - return AVERROR(ENOMEM); - } - ctx->buffer_size = required_size; - } - - double after_alloc = emscripten_get_now(); - - // Copy frame data to contiguous buffer - ret = av_image_copy_to_buffer( - ctx->buffer, - ctx->buffer_size, - (const uint8_t * const *)ctx->frame->data, - ctx->frame->linesize, - ctx->frame->format, - ctx->frame->width, - ctx->frame->height, - 1 - ); - - if (ret < 0) { - return ret; - } - - double after_copy = emscripten_get_now(); - - printf("Timing: send=%.2fms receive=%.2fms alloc=%.2fms copy=%.2fms total=%.2fms\n", - after_send - start, - after_receive - after_send, - after_alloc - after_receive, - after_copy - after_alloc, - after_copy - start); - - return 0; -} - -EMSCRIPTEN_KEEPALIVE -int get_frame_width(DecoderContext *ctx) { - return ctx->frame->width; -} - -EMSCRIPTEN_KEEPALIVE -int get_frame_height(DecoderContext *ctx) { - return ctx->frame->height; -} - -EMSCRIPTEN_KEEPALIVE -int get_frame_format(DecoderContext *ctx) { - return ctx->frame->format; -} - -EMSCRIPTEN_KEEPALIVE -int get_frame_num_planes(DecoderContext *ctx) { - return av_pix_fmt_count_planes(ctx->frame->format); -} - -EMSCRIPTEN_KEEPALIVE -int get_frame_linesize(DecoderContext *ctx, int n) { - return ctx->frame->linesize[n]; -} - -EMSCRIPTEN_KEEPALIVE -uint8_t *get_frame_data(DecoderContext *ctx, int n) { - return ctx->frame->data[n]; -} - -EMSCRIPTEN_KEEPALIVE -uint8_t *get_frame_data_ptr(DecoderContext *ctx) { - return ctx->buffer; -} - -EMSCRIPTEN_KEEPALIVE -int get_frame_data_size(DecoderContext *ctx) { - return ctx->buffer_size; -} \ No newline at end of file diff --git a/packages/prores-decoder/src/index.ts b/packages/prores-decoder/src/index.ts deleted file mode 100644 index e200812..0000000 --- a/packages/prores-decoder/src/index.ts +++ /dev/null @@ -1,90 +0,0 @@ -import { CustomVideoDecoder, EncodedPacket, MaybePromise, VideoCodec } from 'mediabunny'; -import createModule from '../build/prores'; -import { VideoSample } from 'mediabunny'; - -type ExtendedEmscriptenModule = EmscriptenModule & { - cwrap: typeof cwrap; -}; - -export class ProResDecoder extends CustomVideoDecoder { - // eslint-disable-next-line @typescript-eslint/no-unused-vars - static override supports(codec: VideoCodec, config: VideoDecoderConfig): boolean { - return codec === 'prores'; - } - - module!: ExtendedEmscriptenModule; - initDecoder!: () => number; - configurePacket!: (ctx: number, size: number) => number; - decodePacket!: (ctx: number) => number; - getFrameWidth!: (ctx: number) => number; - getFrameHeight!: (ctx: number) => number; - getFrameFormat!: (ctx: number) => number; - getFrameNumPlanes!: (ctx: number) => number; - getFrameLinesize!: (ctx: number, n: number) => number; - getFrameData!: (ctx: number, n: number) => number; - getFrameDataPtr!: (ctx: number) => number; - getFrameDataSize!: (ctx: number) => number; - - decoderContextPtr!: number; - - override async init() { - console.log('THIS IS BEING CALLED'); - - this.module = (await createModule()) as ExtendedEmscriptenModule; - - // Set up the functions - this.initDecoder = this.module.cwrap('init_decoder', 'number', []); - this.configurePacket = this.module.cwrap('configure_packet', 'number', ['number', 'number']); - this.decodePacket = this.module.cwrap('decode_packet', 'number', ['number']); - this.getFrameWidth = this.module.cwrap('get_frame_width', 'number', ['number']); - this.getFrameHeight = this.module.cwrap('get_frame_height', 'number', ['number']); - this.getFrameFormat = this.module.cwrap('get_frame_format', 'number', ['number']); - this.getFrameNumPlanes = this.module.cwrap('get_frame_num_planes', 'number', ['number']); - this.getFrameLinesize = this.module.cwrap('get_frame_linesize', 'number', ['number', 'number']); - this.getFrameData = this.module.cwrap('get_frame_data', 'number', ['number', 'number']); - this.getFrameDataPtr = this.module.cwrap('get_frame_data_ptr', 'number', ['number']); - this.getFrameDataSize = this.module.cwrap('get_frame_data_size', 'number', ['number']); - - this.decoderContextPtr = this.initDecoder(); - } - - override decode(packet: EncodedPacket) { - const dataPtr = this.configurePacket(this.decoderContextPtr, packet.byteLength); - if (dataPtr === 0) { - throw new Error('todo'); - } - - this.module.HEAPU8.set(packet.data, dataPtr); - - console.time(); - const ret = this.decodePacket(this.decoderContextPtr); - console.timeEnd(); - - if (ret === 0) { - const width = this.getFrameWidth(this.decoderContextPtr); - const height = this.getFrameHeight(this.decoderContextPtr); - const format = this.getFrameFormat(this.decoderContextPtr); - const dataPtr = this.getFrameDataPtr(this.decoderContextPtr); - const dataSize = this.getFrameDataSize(this.decoderContextPtr); - - const data = this.module.HEAPU8.subarray(dataPtr, dataPtr + dataSize); - - const sample = new VideoSample(data, { - format: 'I422P10' as VideoPixelFormat, - codedWidth: width, - codedHeight: height, - timestamp: packet.timestamp, - duration: packet.duration, - }); - this.onSample(sample); - } - } - - override flush(): MaybePromise { - // nada - } - - override close(): MaybePromise { - // nada - } -} diff --git a/packages/prores/LICENSE b/packages/prores/LICENSE new file mode 100644 index 0000000..d0a1fa1 --- /dev/null +++ b/packages/prores/LICENSE @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + 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/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/packages/prores/README.md b/packages/prores/README.md new file mode 100644 index 0000000..ee71c31 --- /dev/null +++ b/packages/prores/README.md @@ -0,0 +1,44 @@ +# @mediabunny/prores + +[![](https://img.shields.io/npm/v/@mediabunny/prores)](https://www.npmjs.com/package/@mediabunny/prores) +[![](https://img.shields.io/bundlephobia/minzip/@mediabunny/prores)](https://bundlephobia.com/package/@mediabunny/prores) +[![](https://img.shields.io/npm/dm/@mediabunny/prores)](https://www.npmjs.com/package/@mediabunny/prores) +[![](https://img.shields.io/discord/1390044844285497344?logo=discord&label=Discord)](https://discord.gg/hmpkyYuS4U) + +
+ +
+ +Browsers have no support for Apple ProRes in their WebCodecs implementations. This extension package provides a decoder for use with [Mediabunny](https://github.com/Vanilagy/mediabunny), allowing you to decode ProRes directly in the browser at unprecedented speed. It is implemented using Mediabunny's [custom coder API](https://mediabunny.dev/guide/supported-formats-and-codecs#custom-coders) and uses [TurboRes](https://github.com/Vanilagy/turbores), an extremely fast WASM-based ProRes decoder, under the hood. + +> This package, like the rest of Mediabunny, is enabled by its [sponsors](https://mediabunny.dev/#sponsors) and their donations. If you've derived value from this package, please consider [leaving a donation](https://github.com/sponsors/Vanilagy)! 💘 + +## Installation + +This library peer-depends on Mediabunny. Install both using npm: +```bash +npm install mediabunny @mediabunny/prores +``` + +Alternatively, directly include them using a script tag: +```html + + +``` + +This will expose the global objects `Mediabunny` and `MediabunnyProres`. Use `mediabunny-prores.d.ts` to provide types for these globals. You can download the built distribution files from the [releases page](https://github.com/Vanilagy/mediabunny/releases). + +## Usage + +```ts +import { registerProresDecoder } from '@mediabunny/prores'; + +registerProresDecoder(); +``` +That's it - Mediabunny now uses the registered ProRes decoder automatically. + +For all the ways of using Mediabunny, refer to its [guide](https://mediabunny.dev/guide/introduction). + +## Building and development + +The complete JavaScript package can be built alongside the rest of Mediabunny by running `npm run build` in Mediabunny's root. diff --git a/packages/prores/api-extractor.json b/packages/prores/api-extractor.json new file mode 100644 index 0000000..32669c1 --- /dev/null +++ b/packages/prores/api-extractor.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "mainEntryPointFilePath": "dist/modules/src/index.d.ts", + "bundledPackages": [], + "compiler": {}, + "apiReport": { + "enabled": false + }, + "docModel": { + "enabled": false + }, + "dtsRollup": { + "enabled": true, + "untrimmedFilePath": "dist/mediabunny-prores.d.ts" + }, + "tsdocMetadata": { + "enabled": false + }, + "messages": { + "compilerMessageReporting": { + "default": { + "logLevel": "warning" + } + }, + "extractorMessageReporting": { + "default": { + "logLevel": "warning" + } + }, + "tsdocMessageReporting": { + "default": { + "logLevel": "warning" + } + } + }, + "newlineKind": "lf" +} diff --git a/packages/prores-decoder/package.json b/packages/prores/package.json similarity index 50% rename from packages/prores-decoder/package.json rename to packages/prores/package.json index 1a4e350..1c7ef75 100644 --- a/packages/prores-decoder/package.json +++ b/packages/prores/package.json @@ -1,15 +1,15 @@ { - "name": "@mediabunny/prores-decoder", + "name": "@mediabunny/prores", "author": "Vanilagy", - "version": "1.25.8", - "description": "MP3 encoder extension for Mediabunny, based on LAME.", - "main": "./dist/bundles/mediabunny-mp3-encoder.mjs", - "module": "./dist/bundles/mediabunny-mp3-encoder.mjs", + "version": "1.49.0", + "description": "Apple ProRes decoder extension for Mediabunny, based on TurboRes.", + "main": "./dist/bundles/mediabunny-prores.mjs", + "module": "./dist/bundles/mediabunny-prores.mjs", "types": "./dist/modules/src/index.d.ts", "exports": { "types": "./dist/modules/src/index.d.ts", - "import": "./dist/bundles/mediabunny-mp3-encoder.mjs", - "require": "./dist/bundles/mediabunny-mp3-encoder.mjs" + "import": "./dist/bundles/mediabunny-prores.mjs", + "require": "./dist/bundles/mediabunny-prores.mjs" }, "files": [ "README.md", @@ -19,32 +19,38 @@ "src" ], "sideEffects": false, + "browser": { + "node:worker_threads": false, + "node:os": false + }, "license": "MPL-2.0", "repository": { "type": "git", "url": "git+https://github.com/Vanilagy/mediabunny.git", - "directory": "packages/mp3-encoder" + "directory": "packages/prores" }, "bugs": { "url": "https://github.com/Vanilagy/mediabunny/issues" }, - "homepage": "https://mediabunny.dev/guide/extensions/mp3-encoder", + "homepage": "https://mediabunny.dev/guide/extensions/prores", "funding": { "type": "individual", "url": "https://github.com/sponsors/Vanilagy" }, - "peerDependencies": { - "mediabunny": "^1.0.0" + "dependencies": { + "turbores": "^1.0.0" }, - "devDependencies": { - "@types/emscripten": "^1.40.1" + "peerDependencies": { + "mediabunny": "^1.49.0" }, "keywords": [ - "mp3", - "encoding", + "prores", + "apple-prores", + "decoding", "codec", "mediabunny", - "lame", + "turbores", + "video", "browser", "wasm", "polyfill" diff --git a/packages/prores/src/index.ts b/packages/prores/src/index.ts new file mode 100644 index 0000000..381ec9d --- /dev/null +++ b/packages/prores/src/index.ts @@ -0,0 +1,212 @@ +/*! + * Copyright (c) 2026-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 { CustomVideoDecoder, EncodedPacket, Logging, registerDecoder, VideoCodec, VideoSample } from 'mediabunny'; +import { Decoder, Frame, PixelFormat, PIXEL_FORMATS, FilledFrame } from 'turbores'; +import { + assert, + isWebKit, +} from '../../../src/misc'; +import { type ProresFourCc } from '../../../src/codec'; + +const PRORES_LOADED_SYMBOL = Symbol.for('@mediabunny/prores loaded'); +if ((globalThis as Record)[PRORES_LOADED_SYMBOL]) { + Logging._error( + '[WARNING]\n@mediabunny/prores was loaded twice.' + + ' This will likely cause the decoder not to work correctly.' + + ' Check if multiple dependencies are importing different versions of @mediabunny/prores,' + + ' or if something is being bundled incorrectly.', + ); +} +(globalThis as Record)[PRORES_LOADED_SYMBOL] = true; + +class ProresDecoder extends CustomVideoDecoder { + private decoder: Decoder | null = null; + private framePool: Frame[] = []; + + // eslint-disable-next-line @typescript-eslint/no-unused-vars + static override supports(codec: VideoCodec, config: VideoDecoderConfig): boolean { + return codec === 'prores'; + } + + /** @internal */ + static _supportedVideoFrameFormats: PixelFormat[] | null = null; + + /** @internal */ + static _determineSupportedVideoFrameFormats() { + const result: PixelFormat[] = []; + const data = new Uint8Array(32); + + for (const format of PIXEL_FORMATS) { + try { + const frame = new VideoFrame(data, { + format: format as VideoPixelFormat, + codedWidth: 2, + codedHeight: 2, + timestamp: 0, + duration: 0, + }); + frame.close(); + + result.push(format); + } catch { + // Format is not supported + } + } + + return result; + } + + async init() { + if (typeof VideoFrame !== 'undefined') { + // Not all VideoFrame implementations support all pixel formats, therefore let's determine the supported set + ProresDecoder._supportedVideoFrameFormats ??= ProresDecoder._determineSupportedVideoFrameFormats(); + } + + const decoder = await Decoder.create({ + proresFourCc: this.config.codec as ProresFourCc, + useSharedMemory: Decoder.canUseSharedMemory(), + allowedOutputFormats: ProresDecoder._supportedVideoFrameFormats ?? undefined, + }); + if (decoder instanceof Error) { + throw decoder; + } + + this.decoder = decoder; + } + + async decode(packet: EncodedPacket) { + assert(this.decoder); + + if (this.decoder.useSharedMemory) { + await this.runDecode(packet); + } else { + while (this.decoder.decodeQueueSize >= this.decoder.concurrency) { + await this.decoder.dequeued; + } + + void this.runDecode(packet) + .catch(error => this.onError(error)); + } + } + + private async runDecode(packet: EncodedPacket) { + assert(this.decoder); + + let frame: Frame; + if (this.framePool.length > 0) { + frame = this.framePool.shift()!; + } else { + frame = new Frame(); + } + + const result = await this.decoder.decode(packet.data, frame); + this.framePool.push(frame); + + if (result instanceof Error) { + throw result; + } + + if (result.visibleHeight < result.codedHeight && isWebKit()) { + // WebKit has (had) a bug with displaying height-trimmed YUV frames, so we must compact the frame data a + // little https://bugs.webkit.org/show_bug.cgi?id=317524 + this.trimCodedHeightToVisibleHeight(result); + } + + const sample = new VideoSample(result.frameData, { + format: result.pixelFormat, + codedWidth: result.codedWidth, + codedHeight: result.codedHeight, + visibleRect: { + left: 0, + top: 0, + width: result.visibleWidth, + height: result.visibleHeight, + }, + timestamp: packet.timestamp, + duration: packet.duration, + colorSpace: { + primaries: result.colorPrimariesString as VideoColorPrimaries | undefined, + matrix: result.colorMatrixString as VideoMatrixCoefficients | undefined, + transfer: result.colorTransferString as VideoTransferCharacteristics | undefined, + fullRange: result.colorRangeFull, + }, + }); + this.onSample(sample); + } + + private trimCodedHeightToVisibleHeight(result: FilledFrame) { + const bytesPerSample = result.pixelFormat.includes('P') ? 2 : 1; + const subWidth = result.pixelFormat.includes('444') ? 1 : 2; + const subHeight = result.pixelFormat.includes('420') ? 2 : 1; + + const chromaCodedWidth = result.codedWidth / subWidth; + const chromaCodedHeight = result.codedHeight / subHeight; + const chromaVisibleHeight = Math.ceil(result.visibleHeight / subHeight); + + const lumaCodedPixels = result.codedWidth * result.codedHeight; + const lumaVisiblePixels = result.codedWidth * result.visibleHeight; + const chromaCodedPixels = chromaCodedWidth * chromaCodedHeight; + const chromaVisiblePixels = chromaCodedWidth * chromaVisibleHeight; + + // U + result.frameData.set( + result.frameData.subarray( + bytesPerSample * lumaCodedPixels, + bytesPerSample * (lumaCodedPixels + chromaCodedPixels), + ), + bytesPerSample * lumaVisiblePixels, + ); + // V + result.frameData.set( + result.frameData.subarray( + bytesPerSample * (lumaCodedPixels + chromaCodedPixels), + bytesPerSample * (lumaCodedPixels + 2 * chromaCodedPixels), + ), + bytesPerSample * (lumaVisiblePixels + chromaVisiblePixels), + ); + + result.codedHeight = result.visibleHeight; + } + + async flush() { + assert(this.decoder); + + while (this.decoder.decodeQueueSize > 0) { + await this.decoder.dequeued; + } + } + + async close() { + assert(this.decoder); + + await this.decoder.close(); + + for (const frame of this.framePool) { + frame.clear(); + } + } +} + +let registered = false; + +/** + * Registers an Apple ProRes decoder which Mediabunny will then use automatically when applicable. Make sure to call + * this function before starting any decoding task. + * + * @group \@mediabunny/prores + * @public + */ +export const registerProresDecoder = () => { + if (registered) { + return; + } + registered = true; + + registerDecoder(ProresDecoder); +}; diff --git a/packages/prores-decoder/src/tsconfig.json b/packages/prores/tsconfig.json similarity index 63% rename from packages/prores-decoder/src/tsconfig.json rename to packages/prores/tsconfig.json index 425e6bc..6a0d092 100644 --- a/packages/prores-decoder/src/tsconfig.json +++ b/packages/prores/tsconfig.json @@ -1,7 +1,7 @@ { - "extends": "../../../tsconfig.json", + "extends": "../../tsconfig.json", "compilerOptions": { - "outDir": "../dist/modules", + "outDir": "./dist/modules", "declaration": true, "declarationMap": true, "stripInternal": true, @@ -11,13 +11,13 @@ "module": "nodenext", "allowJs": true, "paths": { - "mediabunny": ["../../../src/index.ts"], + "mediabunny": ["../../src/index.ts"], }, }, "include": [ - "**/*", + "./src/**/*", ], "references": [ - { "path": "../../../src" } + { "path": "../../src" } ] } \ No newline at end of file diff --git a/packages/prores/tsdoc.json b/packages/prores/tsdoc.json new file mode 100644 index 0000000..51d29d3 --- /dev/null +++ b/packages/prores/tsdoc.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json", + "extends": ["../../tsdoc.json"] +} diff --git a/packages/server/src/video-encoder.ts b/packages/server/src/video-encoder.ts index 7c7c4f3..1152f1b 100644 --- a/packages/server/src/video-encoder.ts +++ b/packages/server/src/video-encoder.ts @@ -375,6 +375,7 @@ export class NodeAvVideoEncoder extends CustomVideoEncoder { hevcCodecInfo: null, vp9CodecInfo: null, av1CodecInfo: null, + proresFormat: null, }); if (!expectsAnnexB) { @@ -450,6 +451,7 @@ export class NodeAvVideoEncoder extends CustomVideoEncoder { hevcCodecInfo: null, vp9CodecInfo: null, av1CodecInfo: null, + proresFormat: null, }); } } else if (this.codec === 'vp9') { @@ -467,6 +469,7 @@ export class NodeAvVideoEncoder extends CustomVideoEncoder { hevcCodecInfo: null, vp9CodecInfo, av1CodecInfo: null, + proresFormat: null, }); } } else if (this.codec === 'av1') { @@ -484,6 +487,7 @@ export class NodeAvVideoEncoder extends CustomVideoEncoder { hevcCodecInfo: null, vp9CodecInfo: null, av1CodecInfo, + proresFormat: null, }); } } else { diff --git a/scripts/build.sh b/scripts/build.sh index f33e33a..0ffad0a 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -9,6 +9,7 @@ rm -rf packages/mp3-encoder/dist rm -rf packages/ac3/dist rm -rf packages/aac-encoder/dist rm -rf packages/flac-encoder/dist +rm -rf packages/prores/dist rm -rf packages/server/dist # Ensure license headers on all source files @@ -20,6 +21,7 @@ tsc -p packages/mp3-encoder tsc -p packages/ac3 tsc -p packages/aac-encoder tsc -p packages/flac-encoder +tsc -p packages/prores tsc -p packages/server # Generate the root again, now with internals properly stripped @@ -39,6 +41,7 @@ api-extractor run -c packages/mp3-encoder/api-extractor.json api-extractor run -c packages/ac3/api-extractor.json api-extractor run -c packages/aac-encoder/api-extractor.json api-extractor run -c packages/flac-encoder/api-extractor.json +api-extractor run -c packages/prores/api-extractor.json api-extractor run -c packages/server/api-extractor.json # Checks that all symbols are documented @@ -47,6 +50,7 @@ tsx scripts/check-docblocks.ts packages/mp3-encoder/dist/mediabunny-mp3-encoder. tsx scripts/check-docblocks.ts packages/ac3/dist/mediabunny-ac3.d.ts tsx scripts/check-docblocks.ts packages/aac-encoder/dist/mediabunny-aac-encoder.d.ts tsx scripts/check-docblocks.ts packages/flac-encoder/dist/mediabunny-flac-encoder.d.ts +tsx scripts/check-docblocks.ts packages/prores/dist/mediabunny-prores.d.ts tsx scripts/check-docblocks.ts packages/server/dist/mediabunny-server.d.ts # Checks that API docs are generatable @@ -58,4 +62,5 @@ echo 'export as namespace MediabunnyMp3Encoder;' >> packages/mp3-encoder/dist/me echo 'export as namespace MediabunnyAc3;' >> packages/ac3/dist/mediabunny-ac3.d.ts echo 'export as namespace MediabunnyAacEncoder;' >> packages/aac-encoder/dist/mediabunny-aac-encoder.d.ts echo 'export as namespace MediabunnyFlacEncoder;' >> packages/flac-encoder/dist/mediabunny-flac-encoder.d.ts +echo 'export as namespace MediabunnyProres;' >> packages/prores/dist/mediabunny-prores.d.ts echo 'export as namespace MediabunnyServer;' >> packages/server/dist/mediabunny-server.d.ts diff --git a/scripts/bundle.ts b/scripts/bundle.ts index 0d965eb..f9df856 100644 --- a/scripts/bundle.ts +++ b/scripts/bundle.ts @@ -223,6 +223,24 @@ const flacEncoderVariants = await createVariants( }, ); +const proresVariants = await createVariants( + 'packages/prores/src/index.ts', + 'MediabunnyProres', + 'packages/prores/dist/bundles/mediabunny-prores', + 'js', // The bundles are purely for the browser, not for Node (due to the peer dependecy) + { + plugins: [ + PluginExternalGlobal.externalGlobalPlugin({ + mediabunny: 'Mediabunny', + }), + ], + }, + { + external: ['mediabunny'], + platform: 'node', // To retain the Node imports + }, +); + const serverVariants = await createVariants( 'packages/server/src/index.ts', 'MediabunnyServer', @@ -246,6 +264,7 @@ const contexts = [ ...ac3Variants, ...aacEncoderVariants, ...flacEncoderVariants, + ...proresVariants, ...serverVariants, ]; diff --git a/scripts/check.sh b/scripts/check.sh index bb28006..ed2d185 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -16,6 +16,9 @@ tsc -p packages/aac-encoder rm -rf packages/flac-encoder/dist/modules tsc -p packages/flac-encoder +rm -rf packages/prores/dist/modules +tsc -p packages/prores + rm -rf packages/server/dist/modules tsc -p packages/server diff --git a/scripts/ensure-license-headers.ts b/scripts/ensure-license-headers.ts index 91921dc..44b2dbe 100644 --- a/scripts/ensure-license-headers.ts +++ b/scripts/ensure-license-headers.ts @@ -40,6 +40,7 @@ checkDirectory(path.join(__dirname, '..', 'packages', 'mp3-encoder', 'src')); checkDirectory(path.join(__dirname, '..', 'packages', 'ac3', 'src')); checkDirectory(path.join(__dirname, '..', 'packages', 'flac-encoder', 'src')); checkDirectory(path.join(__dirname, '..', 'packages', 'aac-encoder', 'src')); +checkDirectory(path.join(__dirname, '..', 'packages', 'prores', 'src')); checkDirectory(path.join(__dirname, '..', 'packages', 'server', 'src')); if (missingFiles.length > 0) { diff --git a/src/codec.ts b/src/codec.ts index 8e5bc55..ff72494 100644 --- a/src/codec.ts +++ b/src/codec.ts @@ -224,7 +224,8 @@ export const PRORES_FOURCCS = [ 'apcn', // ProRes 422 Standard Definition 'apcs', // ProRes 422 LT 'apco', // ProRes 422 Proxy -]; +] as const; +export type ProresFourCc = typeof PRORES_FOURCCS[number]; export const buildVideoCodecString = (codec: VideoCodec, width: number, height: number, bitrate: number) => { if (codec === 'avc') { @@ -359,7 +360,7 @@ export const extractVideoCodecString = (trackInfo: { hevcCodecInfo: HevcDecoderConfigurationRecord | null; vp9CodecInfo: Vp9CodecInfo | null; av1CodecInfo: Av1CodecInfo | null; - proresFormat: string | null; + proresFormat: ProresFourCc | null; }) => { const { codec, @@ -946,7 +947,7 @@ export const validateVideoChunkMetadata = (metadata: EncodedVideoChunkMetadata | if (!PRORES_FOURCCS.some(x => metadata.decoderConfig!.codec === x)) { throw new TypeError( - 'Video chunk metadata decoder configuration codec string for ProRes must be one of the valid ProRes' + `Video chunk metadata decoder configuration codec string for ProRes must be one of the valid ProRes` + ` four-character codes: ${PRORES_FOURCCS.join(', ')}.`, ); } diff --git a/src/custom-coder.ts b/src/custom-coder.ts index 0152876..4488a39 100644 --- a/src/custom-coder.ts +++ b/src/custom-coder.ts @@ -27,6 +27,8 @@ export abstract class CustomVideoDecoder { readonly config!: VideoDecoderConfig; /** The callback to call when a decoded VideoSample is available. */ readonly onSample!: (sample: VideoSample) => unknown; + /** The callback to call to surface out-of-band errors that can't be surfaced through the main methods. */ + readonly onError!: (error: unknown) => undefined; /** Returns true if and only if the decoder can decode the given codec configuration. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -57,6 +59,8 @@ export abstract class CustomAudioDecoder { readonly config!: AudioDecoderConfig; /** The callback to call when a decoded AudioSample is available. */ readonly onSample!: (sample: AudioSample) => unknown; + /** The callback to call to surface out-of-band errors that can't be surfaced through the main methods. */ + readonly onError!: (error: unknown) => undefined; /** Returns true if and only if the decoder can decode the given codec configuration. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -87,6 +91,8 @@ export abstract class CustomVideoEncoder { readonly config!: VideoEncoderConfig; /** The callback to call when an EncodedPacket is available. */ readonly onPacket!: (packet: EncodedPacket, meta?: EncodedVideoChunkMetadata) => unknown; + /** The callback to call to surface out-of-band errors that can't be surfaced through the main methods. */ + readonly onError!: (error: unknown) => undefined; /** Returns true if and only if the encoder can encode the given codec configuration. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -117,6 +123,8 @@ export abstract class CustomAudioEncoder { readonly config!: AudioEncoderConfig; /** The callback to call when an EncodedPacket is available. */ readonly onPacket!: (packet: EncodedPacket, meta?: EncodedAudioChunkMetadata) => unknown; + /** The callback to call to surface out-of-band errors that can't be surfaced through the main methods. */ + readonly onError!: (error: unknown) => undefined; /** Returns true if and only if the encoder can encode the given codec configuration. */ // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/encode.ts b/src/encode.ts index 4f52495..b13991b 100644 --- a/src/encode.ts +++ b/src/encode.ts @@ -549,20 +549,20 @@ export class Quality { /** @internal */ _toVideoBitrate(codec: VideoCodec, width: number, height: number) { const pixels = width * height; + const referencePixels = 1920 * 1080; + const referenceBitrate = 3_000_000; + const scaleFactor = Math.pow(pixels / referencePixels, 0.95); // Slight non-linear scaling + const baseBitrate = referenceBitrate * scaleFactor; - const codecEfficiencyFactors = { + const codecEfficiencyFactors: Record = { avc: 1.0, // H.264/AVC (baseline) hevc: 0.6, // H.265/HEVC (~40% more efficient than AVC) vp9: 0.6, // Similar to HEVC av1: 0.4, // ~60% more efficient than AVC vp8: 1.2, // Slightly less efficient than AVC + prores: 220_000_000 / referenceBitrate, // Apple ProRes white paper claims 220 Mbps for 1080p 422 HQ @30Hz }; - const referencePixels = 1920 * 1080; - const referenceBitrate = 3000000; - const scaleFactor = Math.pow(pixels / referencePixels, 0.95); // Slight non-linear scaling - const baseBitrate = referenceBitrate * scaleFactor; - const codecAdjustedBitrate = baseBitrate * codecEfficiencyFactors[codec]; const finalBitrate = codecAdjustedBitrate * this._factor; diff --git a/src/isobmff/isobmff-demuxer.ts b/src/isobmff/isobmff-demuxer.ts index a6f5a87..2d96f9d 100644 --- a/src/isobmff/isobmff-demuxer.ts +++ b/src/isobmff/isobmff-demuxer.ts @@ -19,6 +19,7 @@ import { PCM_AUDIO_CODECS, PcmAudioCodec, PRORES_FOURCCS, + ProresFourCc, VideoCodec, } from '../codec'; import { @@ -148,7 +149,7 @@ type InternalTrack = { hevcCodecInfo: HevcDecoderConfigurationRecord | null; vp9CodecInfo: Vp9CodecInfo | null; av1CodecInfo: Av1CodecInfo | null; - proresFormat: string | null; + proresFormat: ProresFourCc | null; }; } | { info: { @@ -1096,9 +1097,9 @@ export class IsobmffDemuxer extends Demuxer { track.info.codec = 'vp9'; } else if (codecName === 'av01') { track.info.codec = 'av1'; - } else if (PRORES_FOURCCS.includes(lowercaseBoxName)) { + } else if ((PRORES_FOURCCS as readonly string[]).includes(lowercaseBoxName)) { track.info.codec = 'prores'; - track.info.proresFormat = lowercaseBoxName; + track.info.proresFormat = lowercaseBoxName as ProresFourCc; } else if (codecName === null) { Logging._warn(`Unknown encrypted video codec due to missing frma box.`); } else { @@ -3347,7 +3348,10 @@ class IsobmffVideoTrackBacking extends IsobmffTrackBacking implements InputVideo } async canBeTransparent() { - return false; + return this.internalTrack.info.codec === 'prores' && ( + this.internalTrack.info.proresFormat === 'ap4h' + || this.internalTrack.info.proresFormat === 'ap4x' + ); } async getDecoderConfig(): Promise { diff --git a/src/matroska/matroska-demuxer.ts b/src/matroska/matroska-demuxer.ts index 9741da9..27ce186 100644 --- a/src/matroska/matroska-demuxer.ts +++ b/src/matroska/matroska-demuxer.ts @@ -21,6 +21,7 @@ import { MediaCodec, OPUS_SAMPLE_RATE, PRORES_FOURCCS, + ProresFourCc, VideoCodec, } from '../codec'; import { Demuxer } from '../demuxer'; @@ -216,6 +217,7 @@ type InternalTrack = { codecDescription: Uint8Array | null; colorSpace: VideoColorSpaceInit | null; alphaMode: boolean; + proresFormat: ProresFourCc | null; } | { type: 'audio'; @@ -1084,10 +1086,12 @@ export class MatroskaDemuxer extends Demuxer { ? textDecoder.decode(this.currentTrack.codecPrivate) : ''; - if (PRORES_FOURCCS.includes(format)) { + if ((PRORES_FOURCCS as readonly string[]).includes(format)) { this.currentTrack.info.codec = 'prores'; + this.currentTrack.info.proresFormat = format as ProresFourCc; } else { - // We don't support ProRes RAW yet + // Either an invalid string or ProRes RAW, which we don't support yet (it's a + // different codec). } } @@ -1182,6 +1186,7 @@ export class MatroskaDemuxer extends Demuxer { codecDescription: null, colorSpace: null, alphaMode: false, + proresFormat: null, }; } else if (type === 2) { this.currentTrack.info = { @@ -2447,7 +2452,12 @@ class MatroskaVideoTrackBacking extends MatroskaTrackBacking implements InputVid } async canBeTransparent() { - return this.internalTrack.info.alphaMode; + return this.internalTrack.info.alphaMode || ( + this.internalTrack.info.codec === 'prores' && ( + this.internalTrack.info.proresFormat === 'ap4h' + || this.internalTrack.info.proresFormat === 'ap4x' + ) + ); } async getDecoderConfig(): Promise { @@ -2489,9 +2499,7 @@ class MatroskaVideoTrackBacking extends MatroskaTrackBacking implements InputVid av1CodecInfo: this.internalTrack.info.codec === 'av1' && firstPacket ? extractAv1CodecInfoFromPacket(firstPacket.data) : null, - proresFormat: this.internalTrack.info.codec === 'prores' && this.internalTrack.codecPrivate - ? textDecoder.decode(this.internalTrack.codecPrivate) - : null, + proresFormat: this.internalTrack.info.proresFormat, }), codedWidth: this.internalTrack.info.width, codedHeight: this.internalTrack.info.height, diff --git a/src/media-sink.ts b/src/media-sink.ts index 72466ea..3871c81 100644 --- a/src/media-sink.ts +++ b/src/media-sink.ts @@ -333,7 +333,8 @@ export class EncodedPacketSink { // This stores errors that are "out of band" in the sense that they didn't occur in the normal flow of this // method but instead in a different context. This error should not go unnoticed and must be bubbled up to // the consumer. - let outOfBandError = null as Error | null; + let outOfBandError = null as unknown; + let hasOutOfBandError = false; const timestamps: number[] = []; // The queue should always be big enough to hold 1 second worth of packets @@ -364,9 +365,10 @@ export class EncodedPacketSink { ended = true; onQueueNotEmpty(); - })().catch((error: Error) => { - if (!outOfBandError) { + })().catch((error) => { + if (!hasOutOfBandError) { outOfBandError = error; + hasOutOfBandError = true; onQueueNotEmpty(); } }); @@ -380,7 +382,7 @@ export class EncodedPacketSink { throw new InputDisposedError(); } else if (terminated) { return { value: undefined, done: true }; - } else if (outOfBandError) { + } else if (hasOutOfBandError) { throw outOfBandError; } else if (packetQueue.length > 0) { const value = packetQueue.shift()!; @@ -423,7 +425,7 @@ abstract class DecoderWrapper< > { constructor( public onSample: (sample: MediaSample) => unknown, - public onError: (error: Error) => unknown, + public onError: (error: unknown) => unknown, ) {} abstract getDecodeQueueSize(): number; @@ -446,7 +448,7 @@ export abstract class BaseMediaSampleSink< /** @internal */ abstract _createDecoder( onSample: (sample: MediaSample) => unknown, - onError: (error: Error) => unknown + onError: (error: unknown) => unknown ): Promise>; /** @internal */ abstract _createPacketSink(): EncodedPacketSink; @@ -472,7 +474,8 @@ export abstract class BaseMediaSampleSink< // This stores errors that are "out of band" in the sense that they didn't occur in the normal flow of this // method but instead in a different context. This error should not go unnoticed and must be bubbled up to // the consumer. - let outOfBandError = null as Error | null; + let outOfBandError = null as unknown; + let hasOutOfBandError = false; const packetRetrievalOptions: PacketRetrievalOptions = { ...options, @@ -518,8 +521,9 @@ export abstract class BaseMediaSampleSink< ({ promise: queueNotEmpty, resolve: onQueueNotEmpty } = promiseWithResolvers()); } }, (error) => { - if (!outOfBandError) { + if (!hasOutOfBandError) { outOfBandError = error; + hasOutOfBandError = true; onQueueNotEmpty(); } }); @@ -572,9 +576,10 @@ export abstract class BaseMediaSampleSink< decoderIsFlushed = true; onQueueNotEmpty(); // To unstuck the generator - })().catch((error: Error) => { - if (!outOfBandError) { + })().catch((error) => { + if (!hasOutOfBandError) { outOfBandError = error; + hasOutOfBandError = true; onQueueNotEmpty(); } }); @@ -595,7 +600,7 @@ export abstract class BaseMediaSampleSink< throw new InputDisposedError(); } else if (terminated) { return { value: undefined, done: true }; - } else if (outOfBandError) { + } else if (hasOutOfBandError) { closeSamples(); throw outOfBandError; } else if (sampleQueue.length > 0) { @@ -645,7 +650,8 @@ export abstract class BaseMediaSampleSink< // This stores errors that are "out of band" in the sense that they didn't occur in the normal flow of this // method but instead in a different context. This error should not go unnoticed and must be bubbled up to // the consumer. - let outOfBandError = null as Error | null; + let outOfBandError = null as unknown; + let hasOutOfBandError = false; const pushToQueue = (sample: MediaSample | null) => { sampleQueue.push(sample); @@ -687,8 +693,9 @@ export abstract class BaseMediaSampleSink< sample.close(); } }, (error) => { - if (!outOfBandError) { + if (!hasOutOfBandError) { outOfBandError = error; + hasOutOfBandError = true; onQueueNotEmpty(); } }); @@ -792,9 +799,10 @@ export abstract class BaseMediaSampleSink< decoderIsFlushed = true; onQueueNotEmpty(); // To unstuck the generator - })().catch((error: Error) => { - if (!outOfBandError) { + })().catch((error) => { + if (!hasOutOfBandError) { outOfBandError = error; + hasOutOfBandError = true; onQueueNotEmpty(); } }); @@ -814,7 +822,7 @@ export abstract class BaseMediaSampleSink< throw new InputDisposedError(); } else if (terminated) { return { value: undefined, done: true }; - } else if (outOfBandError) { + } else if (hasOutOfBandError) { closeSamples(); throw outOfBandError; } else if (sampleQueue.length > 0) { @@ -882,7 +890,7 @@ class VideoDecoderWrapper extends DecoderWrapper { constructor( onSample: (sample: VideoSample) => unknown, - onError: (error: Error) => unknown, + onError: (error: unknown) => unknown, public codec: VideoCodec, public decoderConfig: VideoDecoderConfig, public rotation: Rotation, @@ -906,8 +914,14 @@ class VideoDecoderWrapper extends DecoderWrapper { this.finalizeAndEmitSample(sample); }; + // @ts-expect-error It's technically readonly + this.customDecoder.onError = (error) => { + onError(error); + }; - void this.customDecoderCallSerializer.call(() => this.customDecoder!.init()); + void this.customDecoderCallSerializer + .call(() => this.customDecoder!.init()) + .catch(error => onError(error)); } else { const colorHandler = (frame: VideoFrame) => { this.frameHandlerSerializer.call(async () => { @@ -920,7 +934,7 @@ class VideoDecoderWrapper extends DecoderWrapper { } else { this.colorQueue.push(frame); } - }).catch((error: Error) => this.onError(error)); + }).catch(error => this.onError(error)); }; if (codec === 'avc' && this.decoderConfig.description && isChromium()) { @@ -946,7 +960,7 @@ class VideoDecoderWrapper extends DecoderWrapper { try { colorHandler(frame); } catch (error) { - this.onError(error as Error); + this.onError(error); } }, error: (error) => { @@ -984,7 +998,8 @@ class VideoDecoderWrapper extends DecoderWrapper { this.customDecoderQueueSize++; void this.customDecoderCallSerializer .call(() => this.customDecoder!.decode(packet)) - .then(() => this.customDecoderQueueSize--); + .catch(error => this.onError(error)) + .finally(() => this.customDecoderQueueSize--); } else { assert(this.decoder); @@ -1074,7 +1089,7 @@ class VideoDecoderWrapper extends DecoderWrapper { } this.alphaDecoderQueueSize--; - }).catch((error: Error) => this.onError(error)); + }).catch(error => this.onError(error)); }; const stack = new Error('Decoding error').stack; @@ -1084,7 +1099,7 @@ class VideoDecoderWrapper extends DecoderWrapper { try { alphaHandler(frame); } catch (error) { - this.onError(error as Error); + this.onError(error); } }, error: (error) => { @@ -1813,7 +1828,7 @@ export class VideoSampleSink extends BaseMediaSampleSink { /** @internal */ async _createDecoder( onSample: (sample: VideoSample) => unknown, - onError: (error: Error) => unknown, + onError: (error: unknown) => unknown, ) { if (!(await this._track.canDecode())) { throw new Error( @@ -2215,7 +2230,7 @@ class AudioDecoderWrapper extends DecoderWrapper { constructor( onSample: (sample: AudioSample) => unknown, - onError: (error: Error) => unknown, + onError: (error: unknown) => unknown, codec: AudioCodec, decoderConfig: AudioDecoderConfig, ) { @@ -2271,8 +2286,14 @@ class AudioDecoderWrapper extends DecoderWrapper { sampleHandler(sample); }; + // @ts-expect-error It's technically readonly + this.customDecoder.onError = (error) => { + onError(error); + }; - void this.customDecoderCallSerializer.call(() => this.customDecoder!.init()); + void this.customDecoderCallSerializer + .call(() => this.customDecoder!.init()) + .catch(error => onError(error)); } else { const stack = new Error('Decoding error').stack; @@ -2281,7 +2302,7 @@ class AudioDecoderWrapper extends DecoderWrapper { try { sampleHandler(new AudioSample(data)); } catch (error) { - this.onError(error as Error); + this.onError(error); } }, error: (error) => { @@ -2307,7 +2328,8 @@ class AudioDecoderWrapper extends DecoderWrapper { this.customDecoderQueueSize++; void this.customDecoderCallSerializer .call(() => this.customDecoder!.decode(packet)) - .then(() => this.customDecoderQueueSize--); + .catch(error => this.onError(error)) + .finally(() => this.customDecoderQueueSize--); } else { assert(this.decoder); @@ -2357,7 +2379,7 @@ class PcmAudioDecoderWrapper extends DecoderWrapper { constructor( onSample: (sample: AudioSample) => unknown, - onError: (error: Error) => unknown, + onError: (error: unknown) => unknown, public decoderConfig: AudioDecoderConfig, ) { super(onSample, onError); @@ -2547,7 +2569,7 @@ export class AudioSampleSink extends BaseMediaSampleSink { /** @internal */ async _createDecoder( onSample: (sample: AudioSample) => unknown, - onError: (error: Error) => unknown, + onError: (error: unknown) => unknown, ) { if (!(await this._track.canDecode())) { throw new Error( diff --git a/src/media-source.ts b/src/media-source.ts index bb7ade9..dfe92f4 100644 --- a/src/media-source.ts +++ b/src/media-source.ts @@ -265,10 +265,18 @@ class VideoEncoderWrapper { * However, we want to surface these errors to the user within the normal control flow, so they don't go uncaught. * So, we keep track of the encoder error and throw it as soon as we get the chance. */ - private error: Error | null = null; - private closed = false; + private error: unknown = null; + private errorSet = false; + + private setError(error: unknown) { + if (!this.errorSet) { + this.error = error; + this.errorSet = true; + } + } private lastMuxerPromise: Promise = Promise.resolve(); + private closed = false; constructor(private source: VideoSource, private encodingConfig: VideoEncodingConfig) {} @@ -492,9 +500,9 @@ class VideoEncoderWrapper { const promise = this.customEncoderCallSerializer .call(() => this.customEncoder!.encode(clonedSample, finalEncodeOptions)) - .then(() => this.customEncoderQueueSize--) - .catch((error: Error) => this.error ??= error) + .catch((error: unknown) => this.setError(error)) .finally(() => { + this.customEncoderQueueSize--; clonedSample.close(); }); @@ -641,9 +649,13 @@ class VideoEncoderWrapper { this.lastMuxerPromise = this.muxer!.addEncodedVideoPacket(this.source._connectedTrack!, packet, meta) .catch((error) => { - this.error ??= error; + this.setError(error); }); }; + // @ts-expect-error It's technically readonly + this.customEncoder.onError = (error) => { + this.setError(error); + }; await this.customEncoder.init(); } else { @@ -746,7 +758,7 @@ class VideoEncoderWrapper { this.lastMuxerPromise = this.muxer!.addEncodedVideoPacket(this.source._connectedTrack!, packet, meta) .catch((error) => { - this.error ??= error; + this.setError(error); }); this.emittedEncoderPackets++; @@ -791,7 +803,7 @@ class VideoEncoderWrapper { }, error: (error) => { error.stack = stack; // Provide a more useful stack trace, the default one sucks - this.error ??= error; + this.setError(error); }, }); this.encoder.configure(encoderConfig); @@ -827,7 +839,7 @@ class VideoEncoderWrapper { }, error: (error) => { error.stack = stack; // Provide a more useful stack trace - this.error ??= error; + this.setError(error); }, }); this.alphaEncoder.configure(encoderConfig); @@ -899,7 +911,7 @@ class VideoEncoderWrapper { } checkForEncoderError() { - if (this.error) { + if (this.errorSet) { throw this.error; } } @@ -2043,7 +2055,16 @@ class AudioEncoderWrapper { * However, we want to surface these errors to the user within the normal control flow, so they don't go uncaught. * So, we keep track of the encoder error and throw it as soon as we get the chance. */ - private error: Error | null = null; + private error: unknown = null; + private errorSet = false; + + private setError(error: unknown) { + if (!this.errorSet) { + this.error = error; + this.errorSet = true; + } + } + private lastMuxerPromise: Promise = Promise.resolve(); private closed = false; @@ -2222,9 +2243,9 @@ class AudioEncoderWrapper { const promise = this.customEncoderCallSerializer .call(() => this.customEncoder!.encode(clonedSample)) - .then(() => this.customEncoderQueueSize--) - .catch((error: Error) => this.error ??= error) + .catch((error: unknown) => this.setError(error)) .finally(() => { + this.customEncoderQueueSize--; clonedSample.close(); }); @@ -2365,9 +2386,13 @@ class AudioEncoderWrapper { this.lastMuxerPromise = this.muxer!.addEncodedAudioPacket(this.source._connectedTrack!, packet, meta) .catch((error) => { - this.error ??= error; + this.setError(error); }); }; + // @ts-expect-error It's technically readonly + this.customEncoder.onError = (error) => { + this.setError(error); + }; await this.customEncoder.init(); } else if ((PCM_AUDIO_CODECS as readonly string[]).includes(this.encodingConfig.codec)) { @@ -2431,12 +2456,12 @@ class AudioEncoderWrapper { this.lastMuxerPromise = this.muxer!.addEncodedAudioPacket(this.source._connectedTrack!, packet, meta) .catch((error) => { - this.error ??= error; + this.setError(error); }); }, error: (error) => { error.stack = stack; // Provide a more useful stack trace - this.error ??= error; + this.setError(error); }, }); this.encoder.configure(encoderConfig); @@ -2587,7 +2612,7 @@ class AudioEncoderWrapper { } checkForEncoderError() { - if (this.error) { + if (this.errorSet) { throw this.error; } } @@ -2959,7 +2984,7 @@ type MediaStreamTrackProcessorWorkerMessage = { } | { type: 'error'; trackId: number; - error: Error; + error: unknown; }; type MediaStreamTrackProcessorControllerMessage = { @@ -3018,7 +3043,7 @@ const mediaStreamTrackProcessorWorkerCode = () => { processor.readable.pipeTo(consumer, { signal: abortController.signal, - }).catch((error: Error) => { + }).catch((error: unknown) => { // Handle AbortError silently if (error instanceof DOMException && error.name === 'AbortError') return; @@ -3138,7 +3163,9 @@ export class TextSubtitleSource extends SubtitleSource { /** @internal */ private _parser: SubtitleParser; /** @internal */ - private _error: Error | null = null; + private _error: unknown = null; + /** @internal */ + private _errorSet = false; /** @internal */ private _lastMuxerPromise: Promise = Promise.resolve(); @@ -3152,7 +3179,7 @@ export class TextSubtitleSource extends SubtitleSource { this._lastMuxerPromise = this._connectedTrack!.output._muxer.addSubtitleCue(this._connectedTrack!, cue, metadata) .catch((error) => { - this._error ??= error; + this._setError(error); }); }, }); @@ -3178,9 +3205,17 @@ export class TextSubtitleSource extends SubtitleSource { return this._lastMuxerPromise; // Allow the writer to apply backpressure } + /** @internal */ + private _setError(error: unknown) { + if (!this._errorSet) { + this._error = error; + this._errorSet = true; + } + } + /** @internal */ _checkForError() { - if (this._error) { + if (this._errorSet) { throw this._error; } } diff --git a/src/mpeg-ts/mpeg-ts-demuxer.ts b/src/mpeg-ts/mpeg-ts-demuxer.ts index f6c281f..f00e2a8 100644 --- a/src/mpeg-ts/mpeg-ts-demuxer.ts +++ b/src/mpeg-ts/mpeg-ts-demuxer.ts @@ -589,6 +589,7 @@ export class MpegTsDemuxer extends Demuxer { hevcCodecInfo: elementaryStream.info.hevcCodecInfo, vp9CodecInfo: null, av1CodecInfo: null, + proresFormat: null, }), codedWidth: elementaryStream.info.width, codedHeight: elementaryStream.info.height, diff --git a/src/sample.ts b/src/sample.ts index 19cd62b..5ea232a 100644 --- a/src/sample.ts +++ b/src/sample.ts @@ -423,16 +423,13 @@ export class VideoSample implements Disposable { ); } - this._data = init._doNotCopy - ? toUint8Array(data) - : toUint8Array(data).slice(); // Copy it - this._layout = init.layout ?? createDefaultPlaneLayout(init.format, init.codedWidth!, init.codedHeight!); - this.format = init.format; this.rotation = init.rotation ?? 0; this.timestamp = init.timestamp!; this.duration = init.duration ?? 0; + const layout = init.layout ?? createDefaultPlaneLayout(init.format, init.codedWidth!, init.codedHeight!); + let colorSpaceInit = init.colorSpace ?? null; if (colorSpaceInit === null) { if ( @@ -457,8 +454,6 @@ export class VideoSample implements Disposable { } } - this.colorSpace = new VideoSampleColorSpace(colorSpaceInit); - this.visibleRect = { left: init.visibleRect?.left ?? 0, top: init.visibleRect?.top ?? 0, @@ -473,6 +468,48 @@ export class VideoSample implements Disposable { this.squarePixelWidth = this.visibleRect.width; this.squarePixelHeight = this.visibleRect.height; } + + // If VideoFrame is available, route through it directly instead of holding onto the buffer. Going + // buffer -> VideoSample -> VideoFrame would copy the data twice (once here, once in toVideoFrame); + // building the VideoFrame now means it's only ever copied once. + if (typeof VideoFrame !== 'undefined' && !init._doNotCopy) { + let videoFrame: VideoFrame | null = null; + + try { + videoFrame = new VideoFrame(toUint8Array(data), { + format: init.format as VideoPixelFormat, + codedWidth: init.codedWidth!, + codedHeight: init.codedHeight!, + layout, + colorSpace: colorSpaceInit, + visibleRect: { + x: this.visibleRect.left, + y: this.visibleRect.top, + width: this.visibleRect.width, + height: this.visibleRect.height, + }, + displayWidth: this.squarePixelWidth, + displayHeight: this.squarePixelHeight, + timestamp: Math.trunc(init.timestamp! * SECOND_TO_MICROSECOND_FACTOR), + // Drag 0 to undefined + duration: Math.trunc((init.duration ?? 0) * SECOND_TO_MICROSECOND_FACTOR) || undefined, + }); + } catch { + // Ignore the error and move on like it didn't happen. We don't want errors caused by the local + // VideoFrame implementation to prevent us from creating the VideoSample. Errors, for example, could + // be caused by an unsupported pixel format. + } + + if (videoFrame) { + return new VideoSample(videoFrame, init); + } + } + + this._data = init._doNotCopy + ? toUint8Array(data) + : toUint8Array(data).slice(); // Copy it + this._layout = layout; + this.colorSpace = new VideoSampleColorSpace(colorSpaceInit); } else if (typeof VideoFrame !== 'undefined' && data instanceof VideoFrame) { if (init?.rotation !== undefined && ![0, 90, 180, 270].includes(init.rotation)) { throw new TypeError('init.rotation, when provided, must be 0, 90, 180, or 270.'); @@ -1036,6 +1073,7 @@ export class VideoSample implements Disposable { timestamp: this.microsecondTimestamp, duration: this.microsecondDuration, colorSpace: this.colorSpace, + visibleRect: this.visibleRect, displayWidth: this.squarePixelWidth, // Not display* since we're not passing rotation displayHeight: this.squarePixelHeight, }); @@ -1045,13 +1083,17 @@ export class VideoSample implements Disposable { duration: this.microsecondDuration || undefined, // Drag 0 duration to undefined, glitches some codecs }); } else if (this._data instanceof Uint8Array) { + assert(this._layout); + return new VideoFrame(this._data, { format: this.format! as VideoPixelFormat, - codedWidth: this.codedWidth, - codedHeight: this.codedHeight, + codedWidth: this.codedWidth, // This is technically wrong! codedWidth is a lie technically. But, since + codedHeight: this.codedHeight, // we pass the layout (which contains the true coded width), we're good. + layout: this._layout, timestamp: this.microsecondTimestamp, duration: this.microsecondDuration || undefined, colorSpace: this.colorSpace, + visibleRect: this.visibleRect, displayWidth: this.squarePixelWidth, // Not display* since we're not passing rotation displayHeight: this.squarePixelHeight, }); diff --git a/test/node/prores.test.ts b/test/node/prores.test.ts index 3fd9444..5342f15 100644 --- a/test/node/prores.test.ts +++ b/test/node/prores.test.ts @@ -1,4 +1,5 @@ import { expect, test } from 'vitest'; +import { registerProresDecoder } from '@mediabunny/prores'; import { Input } from '../../src/input.js'; import { BufferSource, UrlSource } from '../../src/source.js'; import { ALL_FORMATS } from '../../src/input-format.js'; @@ -7,28 +8,29 @@ import { MkvOutputFormat, MovOutputFormat } from '../../src/output-format.js'; import { BufferTarget } from '../../src/target.js'; import { Conversion } from '../../src/conversion.js'; import { VideoSampleSink } from '../../src/media-sink.js'; -import { CustomVideoDecoder, registerDecoder } from '../../src/custom-coder.js'; -import { ProResDecoder } from '../../packages/prores-decoder/src/index.js'; +import { assert } from '../../src/misc.js'; + +const SAMPLE_URL = 'https://pub-1ee78aacb848486482b20a72b55b3121.r2.dev/turbores-sample.mov'; test.concurrent('ProRes MOV file reading', async () => { using input = new Input({ - source: new UrlSource('https://pub-cf9fcfcb5c0a44e9b1bb5ff890e041ae.r2.dev/IMG_0158-prores-log.MOV'), + source: new UrlSource(SAMPLE_URL), formats: ALL_FORMATS, }); const videoTrack = (await input.getPrimaryVideoTrack())!; - expect(videoTrack.codec).toBe('prores'); - expect(videoTrack.codedWidth).toBe(1920); - expect(videoTrack.codedHeight).toBe(1080); + expect(await videoTrack.getCodec()).toBe('prores'); + expect(await videoTrack.getCodedWidth()).toBe(1920); + expect(await videoTrack.getCodedHeight()).toBe(1080); const decoderConfig = (await videoTrack.getDecoderConfig())!; expect(decoderConfig.codec).toBe('apch'); expect(decoderConfig.description).toBeUndefined(); }); -test.concurrent('ProRes transmuxing into MOV', { timeout: 60_000 }, async () => { +test.concurrent('ProRes transmuxing into MOV', { timeout: 10_000 }, async () => { using input = new Input({ - source: new UrlSource('https://pub-cf9fcfcb5c0a44e9b1bb5ff890e041ae.r2.dev/IMG_0158-prores-log.MOV'), + source: new UrlSource(SAMPLE_URL), formats: ALL_FORMATS, }); @@ -55,7 +57,7 @@ test.concurrent('ProRes transmuxing into MOV', { timeout: 60_000 }, async () => }); const videoTrack = (await newInput.getPrimaryVideoTrack())!; - expect(videoTrack.codec).toBe('prores'); + expect(await videoTrack.getCodec()).toBe('prores'); expect((await videoTrack.computePacketStats()).packetCount).toBe(15); const decoderConfig = (await videoTrack.getDecoderConfig())!; @@ -63,9 +65,9 @@ test.concurrent('ProRes transmuxing into MOV', { timeout: 60_000 }, async () => expect(decoderConfig.description).toBeUndefined(); }); -test.concurrent('ProRes transmuxing into MKV', { timeout: 60_000 }, async () => { +test.concurrent('ProRes transmuxing into MKV', { timeout: 10_000 }, async () => { using input = new Input({ - source: new UrlSource('https://pub-cf9fcfcb5c0a44e9b1bb5ff890e041ae.r2.dev/IMG_0158-prores-log.MOV'), + source: new UrlSource(SAMPLE_URL), formats: ALL_FORMATS, }); @@ -77,9 +79,6 @@ test.concurrent('ProRes transmuxing into MKV', { timeout: 60_000 }, async () => const conversion = await Conversion.init({ input, output, - video: { - rotate: 270, // To undo the source rotation metadata so the copy path is taken - }, audio: { discard: true, }, @@ -95,7 +94,7 @@ test.concurrent('ProRes transmuxing into MKV', { timeout: 60_000 }, async () => }); const videoTrack = (await newInput.getPrimaryVideoTrack())!; - expect(videoTrack.codec).toBe('prores'); + expect(await videoTrack.getCodec()).toBe('prores'); expect((await videoTrack.computePacketStats()).packetCount).toBe(15); const decoderConfig = (await videoTrack.getDecoderConfig())!; @@ -103,17 +102,51 @@ test.concurrent('ProRes transmuxing into MKV', { timeout: 60_000 }, async () => expect(decoderConfig.description).toBeUndefined(); }); -test.concurrent.only('ProRes sample ahh', async () => { - registerDecoder(ProResDecoder); - +test('Custom coder registration', { timeout: 10_000 }, async () => { using input = new Input({ - source: new UrlSource('https://pub-cf9fcfcb5c0a44e9b1bb5ff890e041ae.r2.dev/IMG_0158-prores-log.MOV'), + source: new UrlSource(SAMPLE_URL), formats: ALL_FORMATS, }); const videoTrack = (await input.getPrimaryVideoTrack())!; - const sink = new VideoSampleSink(videoTrack); - const sample = await sink.getSample(0); + expect(await videoTrack.getCodec()).toBe('prores'); - console.log(sample); + // Without a registered decoder, there's no way to decode ProRes in this environment + expect(await videoTrack.canDecode()).toBe(false); + + registerProresDecoder(); + + expect(await videoTrack.canDecode()).toBe(true); +}); + +test('ProRes decoding', { timeout: 10_000 }, async () => { + registerProresDecoder(); + + using input = new Input({ + source: new UrlSource(SAMPLE_URL), + formats: ALL_FORMATS, + }); + + const videoTrack = (await input.getPrimaryVideoTrack())!; + const firstTimestamp = await videoTrack.getFirstTimestamp(); + + const sink = new VideoSampleSink(videoTrack); + using sample = await sink.getSample(firstTimestamp); + assert(sample); + + expect(sample.timestamp).toBe(firstTimestamp); + expect(sample.duration).toBeGreaterThan(0); + + expect(sample.displayWidth).toBe(await videoTrack.getDisplayWidth()); + expect(sample.displayHeight).toBe(await videoTrack.getDisplayHeight()); + expect(sample.codedWidth).toBe(1920); + expect(sample.codedHeight).toBe(1080); // Technically a lie but the field is ill-defined + expect(sample.format).toBe('I422P10'); + + const allocationSize = sample.allocationSize(); + expect(allocationSize).toBeGreaterThan(0); + + const pixels = new Uint8Array(allocationSize); + await sample.copyTo(pixels); + expect(pixels.some(byte => byte !== 0)).toBe(true); }); diff --git a/todo.txt b/todo.txt deleted file mode 100644 index 65834c2..0000000 --- a/todo.txt +++ /dev/null @@ -1,2 +0,0 @@ -- different codec strings -- separate out prores and prores raw (?) ffmpeg does this, so probably good reasons. Matroska does not. \ No newline at end of file diff --git a/tsconfig.vite.json b/tsconfig.vite.json index ad7a720..b8dad8d 100644 --- a/tsconfig.vite.json +++ b/tsconfig.vite.json @@ -10,6 +10,7 @@ "@mediabunny/ac3": ["./packages/ac3/src/index.ts"], "@mediabunny/aac-encoder": ["./packages/aac-encoder/src/index.ts"], "@mediabunny/flac-encoder": ["./packages/flac-encoder/src/index.ts"], + "@mediabunny/prores": ["./packages/prores/src/index.ts"], }, "types": ["vite/client"] }, diff --git a/tsconfig.vitest.json b/tsconfig.vitest.json index d665820..9ef6c27 100644 --- a/tsconfig.vitest.json +++ b/tsconfig.vitest.json @@ -11,6 +11,7 @@ "@mediabunny/aac-encoder": ["./packages/aac-encoder/src/index.ts"], "@mediabunny/flac-encoder": ["./packages/flac-encoder/src/index.ts"], "@mediabunny/mp3-encoder": ["./packages/mp3-encoder/src/index.ts"], + "@mediabunny/prores": ["./packages/prores/src/index.ts"], "@mediabunny/server": ["./packages/server/src/index.ts"], }, }, @@ -22,6 +23,7 @@ { "path": "./packages/aac-encoder" }, { "path": "./packages/flac-encoder" }, { "path": "./packages/mp3-encoder" }, + { "path": "./packages/prores" }, { "path": "./packages/server" }, ] } diff --git a/vite.config.ts b/vite.config.ts index f1c5335..df28f91 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -25,6 +25,8 @@ export default defineConfig({ path.resolve(__dirname, './packages/aac-encoder/dist/bundles/mediabunny-aac-encoder.mjs'), '@mediabunny/flac-encoder': path.resolve(__dirname, './packages/flac-encoder/dist/bundles/mediabunny-flac-encoder.mjs'), + '@mediabunny/prores': + path.resolve(__dirname, './packages/prores/dist/bundles/mediabunny-prores.mjs'), }, }, plugins: [ @@ -33,6 +35,10 @@ export default defineConfig({ server: { hmr: false, allowedHosts: true, + headers: { + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'require-corp', + }, }, build: { outDir: 'dist-docs', // Build them directly into the docs build folder diff --git a/vitest.config.ts b/vitest.config.ts index 811875f..5963bbb 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -14,6 +14,8 @@ export default defineConfig({ path.resolve(__dirname, './packages/flac-encoder/dist/bundles/mediabunny-flac-encoder.mjs'), '@mediabunny/mp3-encoder': path.resolve(__dirname, './packages/mp3-encoder/dist/bundles/mediabunny-mp3-encoder.mjs'), + '@mediabunny/prores': + path.resolve(__dirname, './packages/prores/dist/bundles/mediabunny-prores.mjs'), '@mediabunny/server': path.resolve(__dirname, './packages/server/src/index.ts'), },