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