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.
Files changed (52) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/dist/{avi-EQE6AR75.cjs → avi-32UABODO.cjs} +12 -4
  3. package/dist/avi-32UABODO.cjs.map +1 -0
  4. package/dist/{avi-Y3N325WZ.cjs → avi-5BPR6QUX.cjs} +12 -4
  5. package/dist/avi-5BPR6QUX.cjs.map +1 -0
  6. package/dist/{avi-NNHH4AAA.js → avi-BLIH7KKV.js} +12 -4
  7. package/dist/avi-BLIH7KKV.js.map +1 -0
  8. package/dist/{avi-S7EY54YA.js → avi-GX2H34IQ.js} +12 -4
  9. package/dist/avi-GX2H34IQ.js.map +1 -0
  10. package/dist/{chunk-2LNXMGT6.js → chunk-5CX7BVVV.js} +5 -5
  11. package/dist/{chunk-2LNXMGT6.js.map → chunk-5CX7BVVV.js.map} +1 -1
  12. package/dist/{chunk-5Y5BTB5D.js → chunk-B76QWPFM.js} +3 -3
  13. package/dist/{chunk-5Y5BTB5D.js.map → chunk-B76QWPFM.js.map} +1 -1
  14. package/dist/{chunk-Z26PXRUY.js → chunk-BN7BRTLY.js} +137 -26
  15. package/dist/chunk-BN7BRTLY.js.map +1 -0
  16. package/dist/{chunk-GJBNLPGI.cjs → chunk-E5MAM2P4.cjs} +9 -9
  17. package/dist/{chunk-GJBNLPGI.cjs.map → chunk-E5MAM2P4.cjs.map} +1 -1
  18. package/dist/{chunk-7EF4VTUS.cjs → chunk-UM6WCSGL.cjs} +141 -30
  19. package/dist/chunk-UM6WCSGL.cjs.map +1 -0
  20. package/dist/{chunk-HBHSUGNI.cjs → chunk-VLI3Y6IJ.cjs} +5 -5
  21. package/dist/{chunk-HBHSUGNI.cjs.map → chunk-VLI3Y6IJ.cjs.map} +1 -1
  22. package/dist/element-browser.js +144 -25
  23. package/dist/element-browser.js.map +1 -1
  24. package/dist/element.cjs +3 -3
  25. package/dist/element.js +2 -2
  26. package/dist/index.cjs +18 -18
  27. package/dist/index.js +6 -6
  28. package/dist/player.cjs +207 -41
  29. package/dist/player.cjs.map +1 -1
  30. package/dist/player.d.cts +1 -0
  31. package/dist/player.d.ts +1 -0
  32. package/dist/player.js +207 -41
  33. package/dist/player.js.map +1 -1
  34. package/dist/{remux-VPKCLHHM.cjs → remux-NSBJFMLG.cjs} +9 -9
  35. package/dist/{remux-VPKCLHHM.cjs.map → remux-NSBJFMLG.cjs.map} +1 -1
  36. package/dist/{remux-7TA4FKTY.js → remux-PHUHO3VV.js} +4 -4
  37. package/dist/{remux-7TA4FKTY.js.map → remux-PHUHO3VV.js.map} +1 -1
  38. package/package.json +1 -1
  39. package/src/element/avbridge-player.ts +87 -15
  40. package/src/probe/avi.ts +34 -2
  41. package/src/strategies/fallback/decoder.ts +148 -19
  42. package/src/strategies/fallback/video-renderer.ts +41 -3
  43. package/src/strategies/hybrid/decoder.ts +34 -9
  44. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.mjs +1 -1
  45. package/vendor/libav/avbridge/libav-6.8.8.0-avbridge.wasm.wasm +0 -0
  46. package/vendor/libav/avbridge/libav-avbridge.mjs +1 -1
  47. package/dist/avi-EQE6AR75.cjs.map +0 -1
  48. package/dist/avi-NNHH4AAA.js.map +0 -1
  49. package/dist/avi-S7EY54YA.js.map +0 -1
  50. package/dist/avi-Y3N325WZ.cjs.map +0 -1
  51. package/dist/chunk-7EF4VTUS.cjs.map +0 -1
  52. 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
- // eslint-disable-next-line no-console
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
- // eslint-disable-next-line no-console
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) { out.push(pkt); continue; }
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
- await libav.av_bsf_send_packet(bsfCtx, 0);
210
- while (true) {
211
- const err = await libav.av_bsf_receive_packet(bsfCtx, bsfPkt);
212
- if (err < 0) break;
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>;