mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-10-10 09:13:47 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7580935639 | ||
|
|
53824536fa | ||
|
|
8f43086e3d | ||
|
|
9343607fe1 |
@@ -116,6 +116,7 @@ const sponsors = {
|
|||||||
{ image: 'https://avatars.githubusercontent.com/u/2698271', name: 'Matthew Gardner', url: 'https://github.com/spheric' },
|
{ image: 'https://avatars.githubusercontent.com/u/2698271', name: 'Matthew Gardner', url: 'https://github.com/spheric' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/5475819', name: 'AJ Funk', url: 'https://github.com/AJFunk' },
|
{ image: 'https://avatars.githubusercontent.com/u/5475819', name: 'AJ Funk', url: 'https://github.com/AJFunk' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/30229596', name: 'Pablo Bonilla', url: 'https://github.com/devPablo' },
|
{ image: 'https://avatars.githubusercontent.com/u/30229596', name: 'Pablo Bonilla', url: 'https://github.com/devPablo' },
|
||||||
|
{ image: 'https://avatars.githubusercontent.com/u/139718', name: 'Anton Kosiakin', url: 'https://github.com/deil' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/56988069', name: 'SyhabouthAlex', url: 'https://github.com/SyhabouthAlex' },
|
{ image: 'https://avatars.githubusercontent.com/u/56988069', name: 'SyhabouthAlex', url: 'https://github.com/SyhabouthAlex' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/38181164', name: 'wcw', url: 'https://github.com/asd55667' },
|
{ image: 'https://avatars.githubusercontent.com/u/38181164', name: 'wcw', url: 'https://github.com/asd55667' },
|
||||||
{ image: 'https://avatars.githubusercontent.com/u/1836701', name: 'Bean Deng', url: 'https://github.com/HADB' },
|
{ image: 'https://avatars.githubusercontent.com/u/1836701', name: 'Bean Deng', url: 'https://github.com/HADB' },
|
||||||
|
|||||||
Generated
+6
-6
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "mediabunny",
|
"name": "mediabunny",
|
||||||
"version": "1.27.3",
|
"version": "1.27.4",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "mediabunny",
|
"name": "mediabunny",
|
||||||
"version": "1.27.3",
|
"version": "1.27.4",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
@@ -7739,9 +7739,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/mediabunny": {
|
"node_modules/mediabunny": {
|
||||||
"version": "1.27.2",
|
"version": "1.27.3",
|
||||||
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.2.tgz",
|
"resolved": "https://registry.npmjs.org/mediabunny/-/mediabunny-1.27.3.tgz",
|
||||||
"integrity": "sha512-0g/vmb6X0xmnzqW0U44weF9CmzcUFFQRHrjzoVpSL2KXuhWIWcW3u9wIcohHiTY78jfr0SauYKLxjOQReaMxXQ==",
|
"integrity": "sha512-hlzmgzMznp9DhA5fMJKS5yEAyfCUMxAc+DbSPxD4J1J2cYVl1L+pZLndkt5xLlD5aB5eHEnphHMW14ammMlUXg==",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"peer": true,
|
"peer": true,
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
@@ -12065,7 +12065,7 @@
|
|||||||
},
|
},
|
||||||
"packages/mp3-encoder": {
|
"packages/mp3-encoder": {
|
||||||
"name": "@mediabunny/mp3-encoder",
|
"name": "@mediabunny/mp3-encoder",
|
||||||
"version": "1.27.3",
|
"version": "1.27.4",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/emscripten": "^1.40.1"
|
"@types/emscripten": "^1.40.1"
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "mediabunny",
|
"name": "mediabunny",
|
||||||
"author": "Vanilagy",
|
"author": "Vanilagy",
|
||||||
"version": "1.27.3",
|
"version": "1.27.4",
|
||||||
"description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
|
"description": "Pure TypeScript media toolkit for reading, writing, and converting media files, directly in the browser.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@mediabunny/mp3-encoder",
|
"name": "@mediabunny/mp3-encoder",
|
||||||
"author": "Vanilagy",
|
"author": "Vanilagy",
|
||||||
"version": "1.27.3",
|
"version": "1.27.4",
|
||||||
"description": "MP3 encoder extension for Mediabunny, based on LAME.",
|
"description": "MP3 encoder extension for Mediabunny, based on LAME.",
|
||||||
"main": "./dist/bundles/mediabunny-mp3-encoder.mjs",
|
"main": "./dist/bundles/mediabunny-mp3-encoder.mjs",
|
||||||
"module": "./dist/bundles/mediabunny-mp3-encoder.mjs",
|
"module": "./dist/bundles/mediabunny-mp3-encoder.mjs",
|
||||||
|
|||||||
+7
-17
@@ -480,23 +480,13 @@ export abstract class BaseMediaSampleSink<
|
|||||||
|
|
||||||
let currentPacket: EncodedPacket | null = keyPacket;
|
let currentPacket: EncodedPacket | null = keyPacket;
|
||||||
|
|
||||||
let endPacket: EncodedPacket | undefined = undefined;
|
// B-frames make it exceedingly difficult to properly define an upper bound for packet iteration if an end
|
||||||
if (endTimestamp < Infinity) {
|
// timestamp is set, so we just don't do it. The case that makes it especially tricky is when the frames
|
||||||
// When an end timestamp is set, we cannot simply use that for the packet iterator due to out-of-order
|
// following a key frame have a lower timestamp than the keyframe; something that quite frequently happens
|
||||||
// frames (B-frames). Instead, we'll need to keep decoding packets until we get a frame that exceeds
|
// in HEVC streams. The price to pay for not upper-bounding the packet iterator is a slight increase in
|
||||||
// this end time. However, we can still put a bound on it: Since key frames are by definition never
|
// decoder work at the end of the range, but the added correctness and reliability makes this tradeoff worth
|
||||||
// out of order, we can stop at the first key frame after the end timestamp.
|
// it.
|
||||||
const packet = await packetSink.getPacket(endTimestamp);
|
const endPacket = undefined;
|
||||||
const keyPacket = !packet
|
|
||||||
? null
|
|
||||||
: packet.type === 'key' && packet.timestamp === endTimestamp
|
|
||||||
? packet
|
|
||||||
: await packetSink.getNextKeyPacket(packet, { verifyKeyPackets: true });
|
|
||||||
|
|
||||||
if (keyPacket) {
|
|
||||||
endPacket = keyPacket;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const packets = packetSink.packets(keyPacket ?? undefined, endPacket);
|
const packets = packetSink.packets(keyPacket ?? undefined, endPacket);
|
||||||
await packets.next(); // Skip the start packet as we already have it
|
await packets.next(); // Skip the start packet as we already have it
|
||||||
|
|||||||
+10
-14
@@ -446,8 +446,7 @@ export class VideoSample implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of bytes required to hold this video sample's pixel data. Throws if `format` is `null`;
|
* Returns the number of bytes required to hold this video sample's pixel data. Throws if `format` is `null`.
|
||||||
* specify an explicit RGB format in the options in this case.
|
|
||||||
*/
|
*/
|
||||||
allocationSize(options: VideoFrameCopyToOptions = {}): number {
|
allocationSize(options: VideoFrameCopyToOptions = {}): number {
|
||||||
validateVideoFrameCopyToOptions(options);
|
validateVideoFrameCopyToOptions(options);
|
||||||
@@ -455,11 +454,10 @@ export class VideoSample implements Disposable {
|
|||||||
if (this._closed) {
|
if (this._closed) {
|
||||||
throw new Error('VideoSample is closed.');
|
throw new Error('VideoSample is closed.');
|
||||||
}
|
}
|
||||||
if ((options.format ?? this.format) === null) {
|
if (this.format === null) {
|
||||||
throw new Error(
|
// https://github.com/Vanilagy/mediabunny/issues/267
|
||||||
'Cannot get allocation size when format is null. Please manually provide an RGB pixel format in the'
|
// https://github.com/w3c/webcodecs/issues/920
|
||||||
+ ' options instead.',
|
throw new Error('Cannot get allocation size when format is null. Sorry!');
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(this._data !== null);
|
assert(this._data !== null);
|
||||||
@@ -472,6 +470,7 @@ export class VideoSample implements Disposable {
|
|||||||
|| options.rect
|
|| options.rect
|
||||||
) {
|
) {
|
||||||
// Temporarily convert to VideoFrame to get it done
|
// Temporarily convert to VideoFrame to get it done
|
||||||
|
// TODO: Compute this directly without needing to go through VideoFrame
|
||||||
const videoFrame = this.toVideoFrame();
|
const videoFrame = this.toVideoFrame();
|
||||||
const size = videoFrame.allocationSize(options);
|
const size = videoFrame.allocationSize(options);
|
||||||
videoFrame.close();
|
videoFrame.close();
|
||||||
@@ -490,8 +489,7 @@ export class VideoSample implements Disposable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies this video sample's pixel data to an ArrayBuffer or ArrayBufferView. Throws if `format` is `null`;
|
* Copies this video sample's pixel data to an ArrayBuffer or ArrayBufferView. Throws if `format` is `null`.
|
||||||
* specify an explicit RGB format in the options in this case.
|
|
||||||
* @returns The byte layout of the planes of the copied data.
|
* @returns The byte layout of the planes of the copied data.
|
||||||
*/
|
*/
|
||||||
async copyTo(destination: AllowSharedBufferSource, options: VideoFrameCopyToOptions = {}): Promise<PlaneLayout[]> {
|
async copyTo(destination: AllowSharedBufferSource, options: VideoFrameCopyToOptions = {}): Promise<PlaneLayout[]> {
|
||||||
@@ -503,11 +501,8 @@ export class VideoSample implements Disposable {
|
|||||||
if (this._closed) {
|
if (this._closed) {
|
||||||
throw new Error('VideoSample is closed.');
|
throw new Error('VideoSample is closed.');
|
||||||
}
|
}
|
||||||
if ((options.format ?? this.format) === null) {
|
if (this.format === null) {
|
||||||
throw new Error(
|
throw new Error('Cannot copy video sample data when format is null. Sorry!');
|
||||||
'Cannot copy video sample data when format is null. Please manually provide an RGB pixel format in the'
|
|
||||||
+ ' options instead.',
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(this._data !== null);
|
assert(this._data !== null);
|
||||||
@@ -520,6 +515,7 @@ export class VideoSample implements Disposable {
|
|||||||
|| options.rect
|
|| options.rect
|
||||||
) {
|
) {
|
||||||
// Temporarily convert to VideoFrame to get it done
|
// Temporarily convert to VideoFrame to get it done
|
||||||
|
// TODO: Do this directly without needing to go through VideoFrame
|
||||||
const videoFrame = this.toVideoFrame();
|
const videoFrame = this.toVideoFrame();
|
||||||
const layout = await videoFrame.copyTo(destination, options);
|
const layout = await videoFrame.copyTo(destination, options);
|
||||||
videoFrame.close();
|
videoFrame.close();
|
||||||
|
|||||||
@@ -201,6 +201,12 @@ test('null format', async () => {
|
|||||||
expect(() => sample.allocationSize()).toThrow('when format is null');
|
expect(() => sample.allocationSize()).toThrow('when format is null');
|
||||||
await expect(async () => sample.copyTo(new ArrayBuffer())).rejects.toThrow('when format is null');
|
await expect(async () => sample.copyTo(new ArrayBuffer())).rejects.toThrow('when format is null');
|
||||||
|
|
||||||
|
// Even this throws :(
|
||||||
|
// See https://github.com/Vanilagy/mediabunny/issues/267
|
||||||
|
expect(() => sample.allocationSize({ format: 'RGBA' })).toThrow('when format is null');
|
||||||
|
|
||||||
|
// Uncomment this if the RGBA conversion works again:
|
||||||
|
/*
|
||||||
const size = sample.allocationSize({ format: 'RGBA' });
|
const size = sample.allocationSize({ format: 'RGBA' });
|
||||||
expect(size).toBe(1280 * 720 * 4);
|
expect(size).toBe(1280 * 720 * 4);
|
||||||
const buffer = new ArrayBuffer(size);
|
const buffer = new ArrayBuffer(size);
|
||||||
@@ -217,4 +223,5 @@ test('null format', async () => {
|
|||||||
await sample.copyTo(buffer, { format: 'RGBX' });
|
await sample.copyTo(buffer, { format: 'RGBX' });
|
||||||
await sample.copyTo(buffer, { format: 'BGRA' });
|
await sample.copyTo(buffer, { format: 'BGRA' });
|
||||||
await sample.copyTo(buffer, { format: 'BGRX' });
|
await sample.copyTo(buffer, { format: 'BGRX' });
|
||||||
|
*/
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user