@mediabunny/server 1.45.4 → 1.45.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundles/mediabunny-server.cjs +19 -7
- package/dist/bundles/mediabunny-server.min.cjs +2 -2
- package/dist/bundles/mediabunny-server.min.mjs +2 -2
- package/dist/bundles/mediabunny-server.mjs +19 -7
- package/dist/modules/src/audio-decoder.d.ts +1 -1
- package/dist/modules/src/audio-decoder.d.ts.map +1 -1
- package/dist/modules/src/audio-decoder.js +8 -1
- package/dist/modules/src/audio-encoder.d.ts +3 -3
- package/dist/modules/src/audio-encoder.d.ts.map +1 -1
- package/dist/modules/src/audio-encoder.js +6 -2
- package/dist/modules/src/index.d.ts.map +1 -1
- package/dist/modules/src/index.js +4 -0
- package/dist/modules/src/video-decoder.d.ts.map +1 -1
- package/dist/modules/src/video-decoder.js +2 -1
- package/dist/modules/src/video-encoder.d.ts +3 -3
- package/dist/modules/src/video-encoder.d.ts.map +1 -1
- package/dist/modules/src/video-encoder.js +7 -3
- package/dist/modules/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/audio-decoder.ts +8 -2
- package/src/audio-encoder.ts +7 -3
- package/src/index.ts +4 -0
- package/src/video-decoder.ts +4 -1
- package/src/video-encoder.ts +11 -10
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mediabunny/server",
|
|
3
3
|
"author": "Vanilagy",
|
|
4
|
-
"version": "1.45.
|
|
4
|
+
"version": "1.45.5",
|
|
5
5
|
"description": "Adds full video and audio decoder and encoder support to Mediabunny for use in server-side environments (Node, Bun, Deno). Based on NodeAV.",
|
|
6
6
|
"main": "./dist/bundles/mediabunny-server.cjs",
|
|
7
7
|
"module": "./dist/bundles/mediabunny-server.mjs",
|
package/src/audio-decoder.ts
CHANGED
|
@@ -15,7 +15,7 @@ import { AvFrameAudioSampleResource } from './audio-sample';
|
|
|
15
15
|
export class NodeAvAudioDecoder extends CustomAudioDecoder {
|
|
16
16
|
frame!: NodeAv.Frame;
|
|
17
17
|
packet!: NodeAv.Packet;
|
|
18
|
-
codecContext
|
|
18
|
+
codecContext: NodeAv.CodecContext | null = null;
|
|
19
19
|
|
|
20
20
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
21
21
|
static override supports(codec: AudioCodec, config: AudioDecoderConfig): boolean {
|
|
@@ -61,6 +61,8 @@ export class NodeAvAudioDecoder extends CustomAudioDecoder {
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
async decode(packet: EncodedPacket): Promise<void> {
|
|
64
|
+
assert(this.codecContext);
|
|
65
|
+
|
|
64
66
|
this.packet.isKeyframe = packet.type === 'key';
|
|
65
67
|
this.packet.data = Buffer.from(packet.data);
|
|
66
68
|
this.packet.timeBase = { num: 1, den: this.config.sampleRate };
|
|
@@ -71,6 +73,8 @@ export class NodeAvAudioDecoder extends CustomAudioDecoder {
|
|
|
71
73
|
const ret = await this.codecContext.sendPacket(this.packet);
|
|
72
74
|
NodeAv.FFmpegError.throwIfError(ret, 'Send packet');
|
|
73
75
|
|
|
76
|
+
this.packet.unref(); // Don't need the data again, so just unref it
|
|
77
|
+
|
|
74
78
|
while (true) {
|
|
75
79
|
const receiveRet = await this.codecContext.receiveFrame(this.frame);
|
|
76
80
|
if (receiveRet === NodeAv.AVERROR_EAGAIN || receiveRet === NodeAv.AVERROR_EOF) {
|
|
@@ -94,6 +98,8 @@ export class NodeAvAudioDecoder extends CustomAudioDecoder {
|
|
|
94
98
|
}
|
|
95
99
|
|
|
96
100
|
async flush(): Promise<void> {
|
|
101
|
+
assert(this.codecContext);
|
|
102
|
+
|
|
97
103
|
// Send null packet to signal flush
|
|
98
104
|
const ret = await this.codecContext.sendPacket(null);
|
|
99
105
|
NodeAv.FFmpegError.throwIfError(ret, 'Flush decoder');
|
|
@@ -113,7 +119,7 @@ export class NodeAvAudioDecoder extends CustomAudioDecoder {
|
|
|
113
119
|
}
|
|
114
120
|
|
|
115
121
|
close(): MaybePromise<void> {
|
|
116
|
-
this.codecContext
|
|
122
|
+
this.codecContext?.freeContext();
|
|
117
123
|
this.frame.free();
|
|
118
124
|
this.packet.free();
|
|
119
125
|
}
|
package/src/audio-encoder.ts
CHANGED
|
@@ -35,16 +35,16 @@ const FRAME_SIZE_FALLBACK = 1024; // Just 'cause
|
|
|
35
35
|
export class NodeAvAudioEncoder extends CustomAudioEncoder {
|
|
36
36
|
frame!: NodeAv.Frame;
|
|
37
37
|
packet!: NodeAv.Packet;
|
|
38
|
-
avCodec!: NodeAv.Codec;
|
|
39
38
|
codecContext: NodeAv.CodecContext | null = null;
|
|
39
|
+
resampler: NodeAv.SoftwareResampleContext | null = null;
|
|
40
|
+
dstFrame: NodeAv.Frame | null = null;
|
|
41
|
+
avCodec!: NodeAv.Codec;
|
|
40
42
|
firstExpectedTimestamp: number | null = null;
|
|
41
43
|
outputTimestampOffset = 0;
|
|
42
44
|
|
|
43
|
-
resampler: NodeAv.SoftwareResampleContext | null = null;
|
|
44
45
|
inputParametersKey: string | null = null;
|
|
45
46
|
resamplerInputSampleRate: number | null = null;
|
|
46
47
|
nextResamplerPts: bigint | null = null;
|
|
47
|
-
dstFrame: NodeAv.Frame | null = null;
|
|
48
48
|
packetEmitted = false;
|
|
49
49
|
adtsHeaderTemplate: AdtsHeaderTemplate | null = null;
|
|
50
50
|
|
|
@@ -134,6 +134,10 @@ export class NodeAvAudioEncoder extends CustomAudioEncoder {
|
|
|
134
134
|
this.firstExpectedTimestamp ??= audioSample.timestamp;
|
|
135
135
|
|
|
136
136
|
if (audioSample._data instanceof AvFrameAudioSampleResource) {
|
|
137
|
+
// Release any buffers still referenced from the previous encode before reffing the new frame, otherwise
|
|
138
|
+
// av_frame_ref leaks them
|
|
139
|
+
// https://github.com/Vanilagy/mediabunny/issues/392
|
|
140
|
+
this.frame.unref();
|
|
137
141
|
this.frame.ref(audioSample._data.frame);
|
|
138
142
|
} else {
|
|
139
143
|
copyAudioSampleToAvFrame(audioSample, this.frame);
|
package/src/index.ts
CHANGED
|
@@ -78,6 +78,8 @@ export { AvFrameAudioSampleResource } from './audio-sample';
|
|
|
78
78
|
export const toAvFrame = async (sample: VideoSample | AudioSample, frame: NodeAv.Frame) => {
|
|
79
79
|
if (sample instanceof VideoSample) {
|
|
80
80
|
if (sample._data instanceof AvFrameVideoSampleResource) {
|
|
81
|
+
// We're overriding the frame, so release whatever it referenced before, otherwise av_frame_ref leaks it
|
|
82
|
+
frame.unref();
|
|
81
83
|
frame.ref(sample._data.frame);
|
|
82
84
|
} else {
|
|
83
85
|
if (sample.format === null) {
|
|
@@ -92,6 +94,8 @@ export const toAvFrame = async (sample: VideoSample | AudioSample, frame: NodeAv
|
|
|
92
94
|
frame.timeBase = new NodeAv.Rational(1, 1e6);
|
|
93
95
|
} else {
|
|
94
96
|
if (sample._data instanceof AvFrameAudioSampleResource) {
|
|
97
|
+
// We're overriding the frame, so release whatever it referenced before, otherwise av_frame_ref leaks it
|
|
98
|
+
frame.unref();
|
|
95
99
|
frame.ref(sample._data.frame);
|
|
96
100
|
} else {
|
|
97
101
|
copyAudioSampleToAvFrame(sample, frame);
|
package/src/video-decoder.ts
CHANGED
|
@@ -91,9 +91,10 @@ export class NodeAvVideoDecoder extends CustomVideoDecoder {
|
|
|
91
91
|
async decode(packet: EncodedPacket) {
|
|
92
92
|
if (this.codecContext === null) {
|
|
93
93
|
await this.initCodecContext(packet);
|
|
94
|
-
assert(this.codecContext);
|
|
95
94
|
}
|
|
96
95
|
|
|
96
|
+
assert(this.codecContext);
|
|
97
|
+
|
|
97
98
|
this.packet.isKeyframe = packet.type === 'key';
|
|
98
99
|
this.packet.data = Buffer.from(packet.data);
|
|
99
100
|
this.packet.timeBase = { num: 1, den: 1e6 };
|
|
@@ -144,6 +145,8 @@ export class NodeAvVideoDecoder extends CustomVideoDecoder {
|
|
|
144
145
|
const ret = await this.codecContext.sendPacket(this.packet);
|
|
145
146
|
NodeAv.FFmpegError.throwIfError(ret, 'Send packet');
|
|
146
147
|
|
|
148
|
+
this.packet.unref(); // Don't need the data again, so just unref it
|
|
149
|
+
|
|
147
150
|
while (true) {
|
|
148
151
|
const receiveRet = await this.codecContext.receiveFrame(this.frame);
|
|
149
152
|
if (receiveRet === NodeAv.AVERROR_EAGAIN || receiveRet === NodeAv.AVERROR_EOF) {
|
package/src/video-encoder.ts
CHANGED
|
@@ -44,14 +44,13 @@ import { assert, binarySearchLessOrEqual, simplifyRational, toUint8Array } from
|
|
|
44
44
|
export class NodeAvVideoEncoder extends CustomVideoEncoder {
|
|
45
45
|
frame!: NodeAv.Frame;
|
|
46
46
|
packet!: NodeAv.Packet;
|
|
47
|
-
avCodec!: NodeAv.Codec;
|
|
48
47
|
codecContext: NodeAv.CodecContext | null = null;
|
|
48
|
+
scaler: NodeAv.SoftwareScaleContext | null = null;
|
|
49
|
+
dstFrame: NodeAv.Frame | null = null;
|
|
50
|
+
avCodec!: NodeAv.Codec;
|
|
49
51
|
lastBuffer: Buffer | null = null;
|
|
50
52
|
packetEmitted = false;
|
|
51
|
-
|
|
52
|
-
scaler: NodeAv.SoftwareScaleContext | null = null;
|
|
53
53
|
lastScalerKey: string | null = null;
|
|
54
|
-
dstFrame: NodeAv.Frame | null = null;
|
|
55
54
|
|
|
56
55
|
// Bookkeeping to restore the original timing information
|
|
57
56
|
preciseTimings: {
|
|
@@ -183,10 +182,14 @@ export class NodeAvVideoEncoder extends CustomVideoEncoder {
|
|
|
183
182
|
async encode(videoSample: VideoSample, options: VideoEncoderEncodeOptions): Promise<void> {
|
|
184
183
|
if (this.codecContext === null) {
|
|
185
184
|
await this.createCodecContext();
|
|
186
|
-
assert(this.codecContext);
|
|
187
185
|
}
|
|
186
|
+
assert(this.codecContext);
|
|
188
187
|
|
|
189
188
|
if (videoSample._data instanceof AvFrameVideoSampleResource) {
|
|
189
|
+
// Release any buffers still referenced from the previous encode before reffing the new frame, otherwise
|
|
190
|
+
// av_frame_ref leaks them
|
|
191
|
+
// https://github.com/Vanilagy/mediabunny/issues/392
|
|
192
|
+
this.frame.unref();
|
|
190
193
|
this.frame.ref(videoSample._data.frame);
|
|
191
194
|
} else {
|
|
192
195
|
if (videoSample.format === null) {
|
|
@@ -513,12 +516,10 @@ export class NodeAvVideoEncoder extends CustomVideoEncoder {
|
|
|
513
516
|
displayAspectHeight: this.config.displayHeight ?? this.codecContext.height,
|
|
514
517
|
description: decoderConfigDescription ?? undefined,
|
|
515
518
|
colorSpace: {
|
|
516
|
-
primaries:
|
|
517
|
-
|
|
518
|
-
matrix:
|
|
519
|
-
unmapMatrixCoefficients(this.codecContext.colorSpace) as VideoMatrixCoefficients,
|
|
519
|
+
primaries: unmapColorPrimaries(this.codecContext.colorPrimaries) as VideoColorPrimaries,
|
|
520
|
+
matrix: unmapMatrixCoefficients(this.codecContext.colorSpace) as VideoMatrixCoefficients,
|
|
520
521
|
transfer:
|
|
521
|
-
|
|
522
|
+
unmapTransferCharacteristics(this.codecContext.colorTrc) as VideoTransferCharacteristics,
|
|
522
523
|
fullRange: this.codecContext.colorRange === NodeAv.AVCOL_RANGE_JPEG
|
|
523
524
|
? true
|
|
524
525
|
: this.codecContext.colorRange === NodeAv.AVCOL_RANGE_MPEG
|