mediabunny 1.25.2 → 1.25.4

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.
@@ -262,19 +262,19 @@ var Mediabunny = (() => {
262
262
  var toUint8Array = (source) => {
263
263
  if (source.constructor === Uint8Array) {
264
264
  return source;
265
- } else if (source instanceof ArrayBuffer) {
266
- return new Uint8Array(source);
267
- } else {
265
+ } else if (ArrayBuffer.isView(source)) {
268
266
  return new Uint8Array(source.buffer, source.byteOffset, source.byteLength);
267
+ } else {
268
+ return new Uint8Array(source);
269
269
  }
270
270
  };
271
271
  var toDataView = (source) => {
272
272
  if (source.constructor === DataView) {
273
273
  return source;
274
- } else if (source instanceof ArrayBuffer) {
275
- return new DataView(source);
276
- } else {
274
+ } else if (ArrayBuffer.isView(source)) {
277
275
  return new DataView(source.buffer, source.byteOffset, source.byteLength);
276
+ } else {
277
+ return new DataView(source);
278
278
  }
279
279
  };
280
280
  var textDecoder = /* @__PURE__ */ new TextDecoder();
@@ -2783,6 +2783,55 @@ var Mediabunny = (() => {
2783
2783
  }
2784
2784
  }
2785
2785
  }
2786
+ const frameWidthBitsMinus1 = bitstream.readBits(4);
2787
+ const frameHeightBitsMinus1 = bitstream.readBits(4);
2788
+ const n1 = frameWidthBitsMinus1 + 1;
2789
+ bitstream.skipBits(n1);
2790
+ const n2 = frameHeightBitsMinus1 + 1;
2791
+ bitstream.skipBits(n2);
2792
+ let frameIdNumbersPresentFlag = 0;
2793
+ if (reducedStillPictureHeader) {
2794
+ frameIdNumbersPresentFlag = 0;
2795
+ } else {
2796
+ frameIdNumbersPresentFlag = bitstream.readBits(1);
2797
+ }
2798
+ if (frameIdNumbersPresentFlag) {
2799
+ bitstream.skipBits(4);
2800
+ bitstream.skipBits(3);
2801
+ }
2802
+ bitstream.skipBits(1);
2803
+ bitstream.skipBits(1);
2804
+ bitstream.skipBits(1);
2805
+ if (!reducedStillPictureHeader) {
2806
+ bitstream.skipBits(1);
2807
+ bitstream.skipBits(1);
2808
+ bitstream.skipBits(1);
2809
+ bitstream.skipBits(1);
2810
+ const enableOrderHint = bitstream.readBits(1);
2811
+ if (enableOrderHint) {
2812
+ bitstream.skipBits(1);
2813
+ bitstream.skipBits(1);
2814
+ }
2815
+ const seqChooseScreenContentTools = bitstream.readBits(1);
2816
+ let seqForceScreenContentTools = 0;
2817
+ if (seqChooseScreenContentTools) {
2818
+ seqForceScreenContentTools = 2;
2819
+ } else {
2820
+ seqForceScreenContentTools = bitstream.readBits(1);
2821
+ }
2822
+ if (seqForceScreenContentTools > 0) {
2823
+ const seqChooseIntegerMv = bitstream.readBits(1);
2824
+ if (!seqChooseIntegerMv) {
2825
+ bitstream.skipBits(1);
2826
+ }
2827
+ }
2828
+ if (enableOrderHint) {
2829
+ bitstream.skipBits(3);
2830
+ }
2831
+ }
2832
+ bitstream.skipBits(1);
2833
+ bitstream.skipBits(1);
2834
+ bitstream.skipBits(1);
2786
2835
  const highBitdepth = bitstream.readBits(1);
2787
2836
  let bitDepth = 8;
2788
2837
  if (seqProfile === 2 && highBitdepth) {
@@ -3700,11 +3749,40 @@ var Mediabunny = (() => {
3700
3749
 
3701
3750
  // src/sample.ts
3702
3751
  polyfillSymbolDispose();
3752
+ var lastVideoGcErrorLog = -Infinity;
3753
+ var lastAudioGcErrorLog = -Infinity;
3754
+ var finalizationRegistry = null;
3755
+ if (typeof FinalizationRegistry !== "undefined") {
3756
+ finalizationRegistry = new FinalizationRegistry((value) => {
3757
+ const now = Date.now();
3758
+ if (value.type === "video") {
3759
+ if (now - lastVideoGcErrorLog >= 1e3) {
3760
+ console.error(
3761
+ `A VideoSample was garbage collected without first being closed. For proper resource management, make sure to call close() on all your VideoSamples as soon as you're done using them.`
3762
+ );
3763
+ lastVideoGcErrorLog = now;
3764
+ }
3765
+ if (typeof VideoFrame !== "undefined" && value.data instanceof VideoFrame) {
3766
+ value.data.close();
3767
+ }
3768
+ } else {
3769
+ if (now - lastAudioGcErrorLog >= 1e3) {
3770
+ console.error(
3771
+ `An AudioSample was garbage collected without first being closed. For proper resource management, make sure to call close() on all your AudioSamples as soon as you're done using them.`
3772
+ );
3773
+ lastAudioGcErrorLog = now;
3774
+ }
3775
+ if (typeof AudioData !== "undefined" && value.data instanceof AudioData) {
3776
+ value.data.close();
3777
+ }
3778
+ }
3779
+ });
3780
+ }
3703
3781
  var VideoSample = class _VideoSample {
3704
3782
  constructor(data, init) {
3705
3783
  /** @internal */
3706
3784
  this._closed = false;
3707
- if (data instanceof ArrayBuffer || ArrayBuffer.isView(data)) {
3785
+ if (data instanceof ArrayBuffer || typeof SharedArrayBuffer !== "undefined" && data instanceof SharedArrayBuffer || ArrayBuffer.isView(data)) {
3708
3786
  if (!init || typeof init !== "object") {
3709
3787
  throw new TypeError("init must be an object.");
3710
3788
  }
@@ -3814,6 +3892,7 @@ var Mediabunny = (() => {
3814
3892
  } else {
3815
3893
  throw new TypeError("Invalid data type: Must be a BufferSource or CanvasImageSource.");
3816
3894
  }
3895
+ finalizationRegistry?.register(this, { type: "video", data: this._data }, this);
3817
3896
  }
3818
3897
  /** The width of the frame in pixels after rotation. */
3819
3898
  get displayWidth() {
@@ -3880,6 +3959,7 @@ var Mediabunny = (() => {
3880
3959
  if (this._closed) {
3881
3960
  return;
3882
3961
  }
3962
+ finalizationRegistry?.unregister(this);
3883
3963
  if (isVideoFrame(this._data)) {
3884
3964
  this._data.close();
3885
3965
  } else {
@@ -4258,6 +4338,7 @@ var Mediabunny = (() => {
4258
4338
  }
4259
4339
  this._data = dataBuffer;
4260
4340
  }
4341
+ finalizationRegistry?.register(this, { type: "audio", data: this._data }, this);
4261
4342
  }
4262
4343
  /** The presentation timestamp of the sample in microseconds. */
4263
4344
  get microsecondTimestamp() {
@@ -4402,7 +4483,7 @@ var Mediabunny = (() => {
4402
4483
  }
4403
4484
  } else {
4404
4485
  const uint8Data = this._data;
4405
- const srcView = new DataView(uint8Data.buffer, uint8Data.byteOffset, uint8Data.byteLength);
4486
+ const srcView = toDataView(uint8Data);
4406
4487
  const srcFormat = this.format;
4407
4488
  const readFn = getReadFunction(srcFormat);
4408
4489
  const srcBytesPerSample = getBytesPerSample(srcFormat);
@@ -4463,6 +4544,7 @@ var Mediabunny = (() => {
4463
4544
  if (this._closed) {
4464
4545
  return;
4465
4546
  }
4547
+ finalizationRegistry?.unregister(this);
4466
4548
  if (isAudioData(this._data)) {
4467
4549
  this._data.close();
4468
4550
  } else {
@@ -4516,7 +4598,8 @@ var Mediabunny = (() => {
4516
4598
  numberOfFrames: this.numberOfFrames,
4517
4599
  numberOfChannels: this.numberOfChannels,
4518
4600
  timestamp: this.microsecondTimestamp,
4519
- data: this._data
4601
+ data: this._data.buffer instanceof ArrayBuffer ? this._data.buffer : this._data.slice()
4602
+ // In the case of SharedArrayBuffer, convert to ArrayBuffer
4520
4603
  });
4521
4604
  }
4522
4605
  }
@@ -15241,10 +15324,13 @@ var Mediabunny = (() => {
15241
15324
  }
15242
15325
  };
15243
15326
  var BufferSource = class extends Source {
15244
- /** Creates a new {@link BufferSource} backed the specified `ArrayBuffer` or `ArrayBufferView`. */
15327
+ /**
15328
+ * Creates a new {@link BufferSource} backed by the specified `ArrayBuffer`, `SharedArrayBuffer`,
15329
+ * or `ArrayBufferView`.
15330
+ */
15245
15331
  constructor(buffer) {
15246
- if (!(buffer instanceof ArrayBuffer) && !ArrayBuffer.isView(buffer)) {
15247
- throw new TypeError("buffer must be an ArrayBuffer or ArrayBufferView.");
15332
+ if (!(buffer instanceof ArrayBuffer) && !(typeof SharedArrayBuffer !== "undefined" && buffer instanceof SharedArrayBuffer) && !ArrayBuffer.isView(buffer)) {
15333
+ throw new TypeError("buffer must be an ArrayBuffer, SharedArrayBuffer, or ArrayBufferView.");
15248
15334
  }
15249
15335
  super();
15250
15336
  /** @internal */
@@ -15325,10 +15411,7 @@ var Mediabunny = (() => {
15325
15411
  const { done, value } = await reader.read();
15326
15412
  if (done) {
15327
15413
  this._orchestrator.forgetWorker(worker);
15328
- if (worker.currentPos < worker.targetPos) {
15329
- throw new Error("Blob reader stopped unexpectedly before all requested data was read.");
15330
- }
15331
- break;
15414
+ throw new Error("Blob reader stopped unexpectedly before all requested data was read.");
15332
15415
  }
15333
15416
  if (worker.aborted) {
15334
15417
  break;
@@ -15431,7 +15514,7 @@ var Mediabunny = (() => {
15431
15514
  let worker;
15432
15515
  let fileSize;
15433
15516
  if (response.status === 206) {
15434
- fileSize = this._getPartialLengthFromRangeResponse(response);
15517
+ fileSize = this._getTotalLengthFromRangeResponse(response);
15435
15518
  worker = this._orchestrator.createWorker(0, Math.min(fileSize, URL_SOURCE_MIN_LOAD_AMOUNT));
15436
15519
  } else {
15437
15520
  const contentLength = response.headers.get("Content-Length");
@@ -15486,13 +15569,6 @@ var Mediabunny = (() => {
15486
15569
  "HTTP server did not respond with 206 Partial Content to a range request. To enable efficient media file streaming across a network, please make sure your server supports range requests."
15487
15570
  );
15488
15571
  }
15489
- const length = this._getPartialLengthFromRangeResponse(response);
15490
- const required = worker.targetPos - worker.currentPos;
15491
- if (length < required) {
15492
- throw new Error(
15493
- `HTTP response unexpectedly too short: Needed at least ${required} bytes, got only ${length}.`
15494
- );
15495
- }
15496
15572
  if (!response.body) {
15497
15573
  throw new Error(
15498
15574
  "Missing HTTP response body stream. The used fetch function must provide the response body as a ReadableStream."
@@ -15526,14 +15602,12 @@ var Mediabunny = (() => {
15526
15602
  }
15527
15603
  const { done, value } = readResult;
15528
15604
  if (done) {
15529
- this._orchestrator.forgetWorker(worker);
15530
- if (worker.currentPos < worker.targetPos) {
15531
- throw new Error(
15532
- "Response stream reader stopped unexpectedly before all requested data was read."
15533
- );
15605
+ if (worker.currentPos >= worker.targetPos) {
15606
+ this._orchestrator.forgetWorker(worker);
15607
+ worker.running = false;
15608
+ return;
15534
15609
  }
15535
- worker.running = false;
15536
- return;
15610
+ break;
15537
15611
  }
15538
15612
  this.onread?.(worker.currentPos, worker.currentPos + value.length);
15539
15613
  this._orchestrator.supplyWorkerData(worker, value);
@@ -15545,24 +15619,21 @@ var Mediabunny = (() => {
15545
15619
  worker.running = false;
15546
15620
  }
15547
15621
  /** @internal */
15548
- _getPartialLengthFromRangeResponse(response) {
15622
+ _getTotalLengthFromRangeResponse(response) {
15549
15623
  const contentRange = response.headers.get("Content-Range");
15550
15624
  if (contentRange) {
15551
15625
  const match = /\/(\d+)/.exec(contentRange);
15552
15626
  if (match) {
15553
15627
  return Number(match[1]);
15554
- } else {
15555
- throw new Error(`Invalid Content-Range header: ${contentRange}`);
15556
15628
  }
15629
+ }
15630
+ const contentLength = response.headers.get("Content-Length");
15631
+ if (contentLength) {
15632
+ return Number(contentLength);
15557
15633
  } else {
15558
- const contentLength = response.headers.get("Content-Length");
15559
- if (contentLength) {
15560
- return Number(contentLength);
15561
- } else {
15562
- throw new Error(
15563
- "Partial HTTP response (status 206) must surface either Content-Range or Content-Length header."
15564
- );
15565
- }
15634
+ throw new Error(
15635
+ "Partial HTTP response (status 206) must surface either Content-Range or Content-Length header."
15636
+ );
15566
15637
  }
15567
15638
  }
15568
15639
  /** @internal */
@@ -25117,7 +25188,10 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
25117
25188
  targetSampleRate,
25118
25189
  startTime: this._startTimestamp,
25119
25190
  endTime: this._endTimestamp,
25120
- onSample: (sample) => this._registerAudioSample(track, trackOptions, source, sample)
25191
+ onSample: async (sample) => {
25192
+ await this._registerAudioSample(track, trackOptions, source, sample);
25193
+ sample.close();
25194
+ }
25121
25195
  });
25122
25196
  const sink = new AudioSampleSink(track);
25123
25197
  const iterator = sink.samples(this._startTimestamp, this._endTimestamp);
@@ -25126,6 +25200,7 @@ The @mediabunny/mp3-encoder extension package provides support for encoding MP3.
25126
25200
  return;
25127
25201
  }
25128
25202
  await resampler.add(sample);
25203
+ sample.close();
25129
25204
  }
25130
25205
  await resampler.finalize();
25131
25206
  source.close();