mirror of
https://github.com/arcodange-org/mediabunny.git
synced 2026-09-27 19:03:46 +02:00
Add negative timestamp muxing support to Matroska
This commit is contained in:
@@ -221,11 +221,11 @@ test('Non-zero start timestamp, fragmented MP4', async () => {
|
||||
});
|
||||
|
||||
test('Negative start timestamps, regular MP4', async () => {
|
||||
await testNegativeTimestampRoundTrip([-1, 0, 1, 2, 3], 1, false);
|
||||
await testNegativeTimestampRoundTrip(Array.from({ length: 50 }, (_, index) => (index - 10) / 10), 0.1, false);
|
||||
});
|
||||
|
||||
test('Negative start timestamps, fragmented MP4', async () => {
|
||||
await testNegativeTimestampRoundTrip([-1, 0, 1, 2, 3], 1, true);
|
||||
await testNegativeTimestampRoundTrip(Array.from({ length: 50 }, (_, index) => (index - 10) / 10), 0.1, true);
|
||||
});
|
||||
|
||||
test('Wholly negative timestamps, regular MP4', async () => {
|
||||
@@ -247,7 +247,7 @@ const testNegativeTimestampRoundTrip = async (
|
||||
});
|
||||
|
||||
const source = new EncodedVideoPacketSource('vp8');
|
||||
output.addVideoTrack(source);
|
||||
output.addVideoTrack(source, { frameRate: 10 });
|
||||
|
||||
await output.start();
|
||||
|
||||
@@ -272,23 +272,33 @@ const testNegativeTimestampRoundTrip = async (
|
||||
|
||||
const track = await input.getPrimaryVideoTrack();
|
||||
assert(track);
|
||||
const sink = new EncodedPacketSink(track);
|
||||
|
||||
const outputPackets: EncodedPacket[] = [];
|
||||
for await (const packet of new EncodedPacketSink(track).packets()) {
|
||||
for await (const packet of sink.packets()) {
|
||||
outputPackets.push(packet);
|
||||
}
|
||||
|
||||
expect(outputPackets.map(packet => ({
|
||||
data: packet.data,
|
||||
type: packet.type,
|
||||
timestamp: packet.timestamp,
|
||||
duration: packet.duration,
|
||||
}))).toEqual(inputPackets.map(packet => ({
|
||||
data: packet.data,
|
||||
type: packet.type,
|
||||
timestamp: packet.timestamp,
|
||||
duration: packet.duration,
|
||||
})));
|
||||
|
||||
for (const inputPacket of inputPackets) {
|
||||
const outputPacket = await sink.getPacket(inputPacket.timestamp);
|
||||
assert(outputPacket);
|
||||
|
||||
expect({
|
||||
timestamp: outputPacket.timestamp,
|
||||
duration: outputPacket.duration,
|
||||
}).toEqual({
|
||||
timestamp: inputPacket.timestamp,
|
||||
duration: inputPacket.duration,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
test('PCM audio', async () => {
|
||||
|
||||
@@ -9,6 +9,8 @@ import { BufferTarget } from '../../src/target.js';
|
||||
import { MkvOutputFormat } from '../../src/output-format.js';
|
||||
import { Conversion } from '../../src/conversion.js';
|
||||
import { assert } from '../../src/misc.js';
|
||||
import { EncodedVideoPacketSource } from '../../src/media-source.js';
|
||||
import { EncodedPacket } from '../../src/packet.js';
|
||||
|
||||
const __dirname = new URL('.', import.meta.url).pathname;
|
||||
|
||||
@@ -61,3 +63,76 @@ test('Matroska muxer internally converts ADTS to AAC', async () => {
|
||||
|
||||
expect(count).toBe(4557);
|
||||
});
|
||||
|
||||
test('Negative start timestamps', async () => {
|
||||
await testNegativeTimestampRoundTrip(
|
||||
Array.from({ length: 50 }, (_, index) => (index - 10) / 10),
|
||||
0.1,
|
||||
10,
|
||||
);
|
||||
});
|
||||
|
||||
test('Wholly negative timestamps', async () => {
|
||||
await testNegativeTimestampRoundTrip([-1, -0.9, -0.8, -0.7, -0.6], 0.1, 10);
|
||||
});
|
||||
|
||||
const testNegativeTimestampRoundTrip = async (timestamps: number[], duration: number, frameRate: number) => {
|
||||
const output = new Output({
|
||||
format: new MkvOutputFormat(),
|
||||
target: new BufferTarget(),
|
||||
});
|
||||
|
||||
const source = new EncodedVideoPacketSource('vp8');
|
||||
output.addVideoTrack(source, { frameRate });
|
||||
|
||||
await output.start();
|
||||
|
||||
const meta = { decoderConfig: { codec: 'vp8', codedWidth: 1280, codedHeight: 720 } };
|
||||
const inputPackets = timestamps.map((timestamp, index) => new EncodedPacket(
|
||||
new Uint8Array(1024).fill(index),
|
||||
'key',
|
||||
timestamp,
|
||||
duration,
|
||||
));
|
||||
|
||||
for (let i = 0; i < inputPackets.length; i++) {
|
||||
await source.add(inputPackets[i]!, i === 0 ? meta : undefined);
|
||||
}
|
||||
|
||||
await output.finalize();
|
||||
|
||||
using input = new Input({
|
||||
source: new BufferSource(output.target.buffer!),
|
||||
formats: ALL_FORMATS,
|
||||
});
|
||||
|
||||
const track = await input.getPrimaryVideoTrack();
|
||||
assert(track);
|
||||
const sink = new EncodedPacketSink(track);
|
||||
|
||||
const outputPackets: EncodedPacket[] = [];
|
||||
for await (const packet of sink.packets()) {
|
||||
outputPackets.push(packet);
|
||||
}
|
||||
|
||||
expect(outputPackets.map(packet => ({
|
||||
timestamp: packet.timestamp,
|
||||
duration: packet.duration,
|
||||
}))).toEqual(inputPackets.map(packet => ({
|
||||
timestamp: packet.timestamp,
|
||||
duration: packet.duration,
|
||||
})));
|
||||
|
||||
for (const inputPacket of inputPackets) {
|
||||
const outputPacket = await sink.getPacket(inputPacket.timestamp);
|
||||
assert(outputPacket);
|
||||
|
||||
expect({
|
||||
timestamp: outputPacket.timestamp,
|
||||
duration: outputPacket.duration,
|
||||
}).toEqual({
|
||||
timestamp: inputPacket.timestamp,
|
||||
duration: inputPacket.duration,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user