avbridge 2.12.0 → 2.12.1
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/CHANGELOG.md +76 -0
- package/dist/{avi-EQE6AR75.cjs → avi-32UABODO.cjs} +12 -4
- package/dist/avi-32UABODO.cjs.map +1 -0
- package/dist/{avi-Y3N325WZ.cjs → avi-5BPR6QUX.cjs} +12 -4
- package/dist/avi-5BPR6QUX.cjs.map +1 -0
- package/dist/{avi-NNHH4AAA.js → avi-BLIH7KKV.js} +12 -4
- package/dist/avi-BLIH7KKV.js.map +1 -0
- package/dist/{avi-S7EY54YA.js → avi-GX2H34IQ.js} +12 -4
- package/dist/avi-GX2H34IQ.js.map +1 -0
- package/dist/{chunk-2LNXMGT6.js → chunk-5CX7BVVV.js} +5 -5
- package/dist/{chunk-2LNXMGT6.js.map → chunk-5CX7BVVV.js.map} +1 -1
- package/dist/{chunk-5Y5BTB5D.js → chunk-B76QWPFM.js} +3 -3
- package/dist/{chunk-5Y5BTB5D.js.map → chunk-B76QWPFM.js.map} +1 -1
- package/dist/{chunk-Z26PXRUY.js → chunk-BN7BRTLY.js} +137 -26
- package/dist/chunk-BN7BRTLY.js.map +1 -0
- package/dist/{chunk-GJBNLPGI.cjs → chunk-E5MAM2P4.cjs} +9 -9
- package/dist/{chunk-GJBNLPGI.cjs.map → chunk-E5MAM2P4.cjs.map} +1 -1
- package/dist/{chunk-7EF4VTUS.cjs → chunk-UM6WCSGL.cjs} +141 -30
- package/dist/chunk-UM6WCSGL.cjs.map +1 -0
- package/dist/{chunk-HBHSUGNI.cjs → chunk-VLI3Y6IJ.cjs} +5 -5
- package/dist/{chunk-HBHSUGNI.cjs.map → chunk-VLI3Y6IJ.cjs.map} +1 -1
- package/dist/element-browser.js +144 -25
- package/dist/element-browser.js.map +1 -1
- package/dist/element.cjs +3 -3
- package/dist/element.js +2 -2
- package/dist/index.cjs +18 -18
- package/dist/index.js +6 -6
- package/dist/player.cjs +207 -41
- package/dist/player.cjs.map +1 -1
- package/dist/player.d.cts +1 -0
- package/dist/player.d.ts +1 -0
- package/dist/player.js +207 -41
- package/dist/player.js.map +1 -1
- package/dist/{remux-VPKCLHHM.cjs → remux-NSBJFMLG.cjs} +9 -9
- package/dist/{remux-VPKCLHHM.cjs.map → remux-NSBJFMLG.cjs.map} +1 -1
- package/dist/{remux-7TA4FKTY.js → remux-PHUHO3VV.js} +4 -4
- package/dist/{remux-7TA4FKTY.js.map → remux-PHUHO3VV.js.map} +1 -1
- package/package.json +1 -1
- package/src/element/avbridge-player.ts +87 -15
- package/src/probe/avi.ts +34 -2
- package/src/strategies/fallback/decoder.ts +148 -19
- package/src/strategies/fallback/video-renderer.ts +41 -3
- package/src/strategies/hybrid/decoder.ts +34 -9
- package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.mjs +1 -1
- package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.wasm +0 -0
- package/vendor/libav/avbridge/libav-avbridge.mjs +1 -1
- package/dist/avi-EQE6AR75.cjs.map +0 -1
- package/dist/avi-NNHH4AAA.js.map +0 -1
- package/dist/avi-S7EY54YA.js.map +0 -1
- package/dist/avi-Y3N325WZ.cjs.map +0 -1
- package/dist/chunk-7EF4VTUS.cjs.map +0 -1
- package/dist/chunk-Z26PXRUY.js.map +0 -1
|
@@ -165,6 +165,7 @@ export async function startHybridDecoder(opts: StartHybridDecoderOptions): Promi
|
|
|
165
165
|
// ── Bitstream filter for MPEG-4 Part 2 packed B-frames ───────────────
|
|
166
166
|
let bsfCtx: number | null = null;
|
|
167
167
|
let bsfPkt: number | null = null;
|
|
168
|
+
let bsfRequiredButMissing = false;
|
|
168
169
|
if (videoStream && opts.context.videoTracks[0]?.codec === "mpeg4") {
|
|
169
170
|
try {
|
|
170
171
|
bsfCtx = await libav.av_bsf_list_parse_str_js("mpeg4_unpack_bframes");
|
|
@@ -175,15 +176,23 @@ export async function startHybridDecoder(opts: StartHybridDecoderOptions): Promi
|
|
|
175
176
|
bsfPkt = await libav.av_packet_alloc();
|
|
176
177
|
dbg.info("bsf", "mpeg4_unpack_bframes BSF active (hybrid)");
|
|
177
178
|
} else {
|
|
178
|
-
|
|
179
|
-
console.warn("[avbridge] mpeg4_unpack_bframes BSF not available in hybrid decoder");
|
|
179
|
+
bsfRequiredButMissing = true;
|
|
180
180
|
bsfCtx = null;
|
|
181
181
|
}
|
|
182
182
|
} catch (err) {
|
|
183
|
-
|
|
184
|
-
console.warn("[avbridge] hybrid: failed to init BSF:", (err as Error).message);
|
|
183
|
+
bsfRequiredButMissing = true;
|
|
185
184
|
bsfCtx = null;
|
|
186
185
|
bsfPkt = null;
|
|
186
|
+
dbg.warn("bsf", `hybrid: mpeg4_unpack_bframes BSF init failed: ${(err as Error).message}`);
|
|
187
|
+
}
|
|
188
|
+
if (bsfRequiredButMissing) {
|
|
189
|
+
// eslint-disable-next-line no-console
|
|
190
|
+
console.error(
|
|
191
|
+
"[avbridge] MPEG-4 Part 2 (DivX/Xvid) detected but mpeg4_unpack_bframes " +
|
|
192
|
+
"BSF is unavailable in this libav variant. Files with packed B-frames " +
|
|
193
|
+
"will play with incorrect frame ordering. Rebuild the libav variant " +
|
|
194
|
+
"with the `avbsf` fragment included.",
|
|
195
|
+
);
|
|
187
196
|
}
|
|
188
197
|
}
|
|
189
198
|
|
|
@@ -193,7 +202,13 @@ export async function startHybridDecoder(opts: StartHybridDecoderOptions): Promi
|
|
|
193
202
|
for (const pkt of packets) {
|
|
194
203
|
await libav.ff_copyin_packet(bsfPkt, pkt);
|
|
195
204
|
const sendErr = await libav.av_bsf_send_packet(bsfCtx, bsfPkt);
|
|
196
|
-
if (sendErr < 0) {
|
|
205
|
+
if (sendErr < 0) {
|
|
206
|
+
// BSF rejected — DON'T pass the original through. Its buffer may
|
|
207
|
+
// have been transferred into the worker by ff_copyin_packet, so
|
|
208
|
+
// re-posting it would throw DataCloneError on a detached
|
|
209
|
+
// ArrayBuffer. See fallback/decoder.ts for the full explanation.
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
197
212
|
while (true) {
|
|
198
213
|
const recvErr = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);
|
|
199
214
|
if (recvErr < 0) break;
|
|
@@ -206,10 +221,18 @@ export async function startHybridDecoder(opts: StartHybridDecoderOptions): Promi
|
|
|
206
221
|
async function flushBSF(): Promise<void> {
|
|
207
222
|
if (!bsfCtx || !bsfPkt) return;
|
|
208
223
|
try {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
224
|
+
// Use av_bsf_flush to reset the BSF without putting it in EOF mode.
|
|
225
|
+
// See the matching comment in src/strategies/fallback/decoder.ts —
|
|
226
|
+
// sending NULL as the flush signal puts the BSF into EOF state so
|
|
227
|
+
// subsequent sends fail, which corrupts the post-seek pipeline with
|
|
228
|
+
// detached-buffer DataCloneErrors.
|
|
229
|
+
if (libav.av_bsf_flush) {
|
|
230
|
+
await libav.av_bsf_flush(bsfCtx);
|
|
231
|
+
} else {
|
|
232
|
+
while (true) {
|
|
233
|
+
const err = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);
|
|
234
|
+
if (err < 0) break;
|
|
235
|
+
}
|
|
213
236
|
}
|
|
214
237
|
} catch { /* ignore */ }
|
|
215
238
|
}
|
|
@@ -562,6 +585,7 @@ export async function startHybridDecoder(opts: StartHybridDecoderOptions): Promi
|
|
|
562
585
|
videoChunksFed,
|
|
563
586
|
audioFramesDecoded,
|
|
564
587
|
bsfApplied: bsfCtx ? ["mpeg4_unpack_bframes"] : [],
|
|
588
|
+
bsfMissing: bsfRequiredButMissing ? ["mpeg4_unpack_bframes"] : [],
|
|
565
589
|
videoDecodeQueueSize: videoDecoder?.decodeQueueSize ?? 0,
|
|
566
590
|
// Confirmed transport info — see fallback decoder for the pattern.
|
|
567
591
|
_transport: inputHandle.transport === "http-range" ? "http-range" : "memory",
|
|
@@ -687,6 +711,7 @@ interface LibavRuntime {
|
|
|
687
711
|
av_bsf_init(ctx: number): Promise<number>;
|
|
688
712
|
av_bsf_send_packet(ctx: number, pkt: number): Promise<number>;
|
|
689
713
|
av_bsf_receive_packet(ctx: number, pkt: number): Promise<number>;
|
|
714
|
+
av_bsf_flush?(ctx: number): Promise<void>;
|
|
690
715
|
av_bsf_free(ctx: number): Promise<void>;
|
|
691
716
|
ff_copyin_packet(pktPtr: number, packet: LibavPacket): Promise<void>;
|
|
692
717
|
ff_copyout_packet(pkt: number): Promise<LibavPacket>;
|