@blockcast/mmt-container 0.1.0-main.dd5ce397d768 → 0.1.0-main.fc44423f1ff9
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/browser-runtime.js +451 -250
- package/dist/browser-runtime.js.map +3 -3
- package/dist/catalog-fec-params.d.ts +15 -0
- package/dist/catalog-fec-params.d.ts.map +1 -1
- package/dist/catalog-fec-params.js +11 -0
- package/dist/catalog-fec-params.js.map +2 -2
- package/dist/cmaf-block-assembler.js.map +1 -1
- package/dist/cmaf-group-batcher.js.map +1 -1
- package/dist/cmcd-producer.d.ts.map +1 -1
- package/dist/cmcd-producer.js.map +2 -2
- package/dist/fec-manager.d.ts +1 -1
- package/dist/fec-manager.d.ts.map +1 -1
- package/dist/fec-manager.js +1 -1
- package/dist/fec-manager.js.map +2 -2
- package/dist/fec-worker-setup.d.ts +8 -0
- package/dist/fec-worker-setup.d.ts.map +1 -1
- package/dist/fec-worker-setup.js +3 -1
- package/dist/fec-worker-setup.js.map +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +2 -2
- package/dist/iso-bmff-timing.d.ts +12 -6
- package/dist/iso-bmff-timing.d.ts.map +1 -1
- package/dist/iso-bmff-timing.js +40 -8
- package/dist/iso-bmff-timing.js.map +2 -2
- package/dist/manifest-auth-plan.js +29 -11
- package/dist/manifest-auth-plan.js.map +2 -2
- package/dist/media-router.js.map +2 -2
- package/dist/mmtp-container-parser.d.ts +101 -0
- package/dist/mmtp-container-parser.d.ts.map +1 -1
- package/dist/mmtp-container-parser.js +332 -199
- package/dist/mmtp-container-parser.js.map +2 -2
- package/dist/mmtp-container-parser.no-modules.js +376 -214
- package/dist/mmtp-container-parser.no-modules.js.map +2 -2
- package/dist/mmtp-decode-pipeline.js +351 -218
- package/dist/mmtp-decode-pipeline.js.map +3 -3
- package/dist/mmtp-router.d.ts.map +1 -1
- package/dist/mmtp-router.js +337 -200
- package/dist/mmtp-router.js.map +2 -2
- package/dist/mmtp-to-cmaf.d.ts +11 -2
- package/dist/mmtp-to-cmaf.d.ts.map +1 -1
- package/dist/mmtp-to-cmaf.js +15 -4
- package/dist/mmtp-to-cmaf.js.map +2 -2
- package/dist/multicast-manager.d.ts +12 -0
- package/dist/multicast-manager.d.ts.map +1 -1
- package/dist/multicast-manager.js +403 -226
- package/dist/multicast-manager.js.map +2 -2
- package/dist/multicast-transport.d.ts.map +1 -1
- package/dist/multicast-transport.js +22 -7
- package/dist/multicast-transport.js.map +2 -2
- package/dist/no-modules.js +376 -214
- package/dist/no-modules.js.map +2 -2
- package/dist/source-auth.js +29 -11
- package/dist/source-auth.js.map +2 -2
- package/dist/track-session.d.ts +17 -1
- package/dist/track-session.d.ts.map +1 -1
- package/dist/track-session.js.map +2 -2
- package/dist/wasm-mmtp-container-parser.js +332 -199
- package/dist/wasm-mmtp-container-parser.js.map +2 -2
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts +1 -1
- package/node_modules/@blockcast/fec-worker/dist/fec-worker-types.d.ts.map +1 -1
- package/node_modules/@blockcast/fec-worker/src/fec-worker-types.ts +1 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts +3 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.d.ts.map +1 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.js +3 -1
- package/node_modules/@blockcast/mmt-fec/dist/block-manager.js.map +1 -1
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.d.ts +2 -2
- package/node_modules/@blockcast/mmt-fec/dist/fec-block-mapper.js +2 -2
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts +5 -7
- package/node_modules/@blockcast/mmt-fec/dist/oti.d.ts.map +1 -1
- package/node_modules/@blockcast/mmt-fec/dist/oti.js +4 -6
- package/node_modules/@blockcast/mmt-fec/dist/oti.js.map +1 -1
- package/node_modules/@blockcast/mmt-fec/src/block-manager.ts +3 -1
- package/node_modules/@blockcast/mmt-fec/src/fec-block-mapper.ts +2 -2
- package/node_modules/@blockcast/mmt-fec/src/oti.ts +5 -7
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts +10 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.d.ts.map +1 -1
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js +40 -10
- package/node_modules/@blockcast/mmt-manifest-verify/dist/verifier.js.map +1 -1
- package/node_modules/@blockcast/mmt-manifest-verify/src/verifier.ts +41 -8
- package/package.json +6 -6
- package/src/catalog-fec-params.ts +28 -0
- package/src/cmcd-producer.ts +5 -0
- package/src/fec-manager.ts +1 -1
- package/src/fec-worker-setup.ts +11 -1
- package/src/index.ts +4 -0
- package/src/iso-bmff-timing.ts +62 -7
- package/src/mmtp-container-parser.ts +284 -48
- package/src/mmtp-router.ts +5 -1
- package/src/mmtp-to-cmaf.ts +24 -2
- package/src/multicast-manager.ts +102 -29
- package/src/multicast-transport.ts +19 -4
- package/src/track-session.ts +17 -1
package/dist/browser-runtime.js
CHANGED
|
@@ -7719,16 +7719,26 @@ var MmtpToCmaf = class {
|
|
|
7719
7719
|
return __privateGet(this, _audioInitSegment);
|
|
7720
7720
|
}
|
|
7721
7721
|
/** Convert a raw video sample to an fMP4 moof+mdat segment. */
|
|
7722
|
-
wrapVideoSample(data, timestamp, keyframe, duration) {
|
|
7723
|
-
return this.wrapVideoSampleWithTiming(data, timestamp, keyframe, duration).segment;
|
|
7722
|
+
wrapVideoSample(data, timestamp, keyframe, duration, compositionTimeOffset) {
|
|
7723
|
+
return this.wrapVideoSampleWithTiming(data, timestamp, keyframe, duration, compositionTimeOffset).segment;
|
|
7724
7724
|
}
|
|
7725
7725
|
/**
|
|
7726
7726
|
* Convert a raw video sample and return the exact browser media interval
|
|
7727
7727
|
* encoded into tfdt/trun. Consumers that correlate SourceBuffer appends with
|
|
7728
7728
|
* requestVideoFrameCallback must use this rebased timestamp, not the wire or
|
|
7729
7729
|
* caller-owned timestamp passed above.
|
|
7730
|
+
*
|
|
7731
|
+
* `compositionTimeOffset` is the signed authored PTS-DTS delta, in the same
|
|
7732
|
+
* #videoTimescale units as `timestamp` and `duration` — unlike wrapAudioSample,
|
|
7733
|
+
* which takes microseconds and rescales, because every other quantity on this
|
|
7734
|
+
* path is already denominated in #videoTimescale (see setVideoTrackParams).
|
|
7735
|
+
* Passing it therefore needs no conversion here; rescaling would double-convert.
|
|
7736
|
+
* Absent leaves the trun at version 0 with no offset field; a declared 0 is an
|
|
7737
|
+
* authored value and still promotes to version 1. Never reconstruct it from
|
|
7738
|
+
* arrival time.
|
|
7730
7739
|
*/
|
|
7731
|
-
wrapVideoSampleWithTiming(data, timestamp, keyframe, duration) {
|
|
7740
|
+
wrapVideoSampleWithTiming(data, timestamp, keyframe, duration, compositionTimeOffset) {
|
|
7741
|
+
assertCompositionTimeOffsets([{ compositionTimeOffset }]);
|
|
7732
7742
|
if (duration !== void 0 && Number.isFinite(duration) && duration > 0) {
|
|
7733
7743
|
__privateSet(this, _frameDuration, Math.round(duration));
|
|
7734
7744
|
} else if (__privateGet(this, _lastVideoTimestamp) > 0 && timestamp > __privateGet(this, _lastVideoTimestamp)) {
|
|
@@ -7746,7 +7756,8 @@ var MmtpToCmaf = class {
|
|
|
7746
7756
|
frameDuration,
|
|
7747
7757
|
keyframe,
|
|
7748
7758
|
__privateWrapper(this, _videoSeq)._++,
|
|
7749
|
-
__privateGet(this, _videoTrackId)
|
|
7759
|
+
__privateGet(this, _videoTrackId),
|
|
7760
|
+
compositionTimeOffset
|
|
7750
7761
|
),
|
|
7751
7762
|
mediaTimestamp: relTs,
|
|
7752
7763
|
duration: frameDuration
|
|
@@ -10017,7 +10028,7 @@ var FECManager = class {
|
|
|
10017
10028
|
symbolSizeForPacket(packetId) {
|
|
10018
10029
|
return __privateMethod(this, _FECManager_instances, resolveTrackConfig_fn).call(this, packetId).symbolSize;
|
|
10019
10030
|
}
|
|
10020
|
-
/** FEC
|
|
10031
|
+
/** FEC block span in milliseconds (0 = no interleaving). */
|
|
10021
10032
|
get interleaveDepthMs() {
|
|
10022
10033
|
return __privateGet(this, _fecInterleaveDepthMs);
|
|
10023
10034
|
}
|
|
@@ -11577,7 +11588,7 @@ function sameTrack(a, b) {
|
|
|
11577
11588
|
function sameSample(a, b) {
|
|
11578
11589
|
return a.decodeTime === b.decodeTime && a.presentationTime === b.presentationTime && a.duration === b.duration && a.timescale === b.timescale && a.size === b.size && a.bytePosition === b.bytePosition;
|
|
11579
11590
|
}
|
|
11580
|
-
var _track, _fragments, _pendingSamples, _lastMovieFragmentRejection, _IsoBmffTimingResolver_instances, clearSlot_fn;
|
|
11591
|
+
var _track, _fragments, _pendingSamples, _evictedSamples, _lastMovieFragmentRejection, _IsoBmffTimingResolver_instances, evictOldestFragment_fn, clearSlot_fn;
|
|
11581
11592
|
var IsoBmffTimingResolver = class {
|
|
11582
11593
|
constructor(maxPendingSamples) {
|
|
11583
11594
|
this.maxPendingSamples = maxPendingSamples;
|
|
@@ -11585,6 +11596,7 @@ var IsoBmffTimingResolver = class {
|
|
|
11585
11596
|
__privateAdd(this, _track, null);
|
|
11586
11597
|
__privateAdd(this, _fragments, /* @__PURE__ */ new Map());
|
|
11587
11598
|
__privateAdd(this, _pendingSamples, 0);
|
|
11599
|
+
__privateAdd(this, _evictedSamples, 0);
|
|
11588
11600
|
__privateAdd(this, _lastMovieFragmentRejection, null);
|
|
11589
11601
|
if (!Number.isInteger(maxPendingSamples) || maxPendingSamples <= 0) {
|
|
11590
11602
|
throw new Error("[IsoBmffTimingResolver] maxPendingSamples must be a positive integer");
|
|
@@ -11593,6 +11605,15 @@ var IsoBmffTimingResolver = class {
|
|
|
11593
11605
|
get pendingSampleCount() {
|
|
11594
11606
|
return __privateGet(this, _pendingSamples);
|
|
11595
11607
|
}
|
|
11608
|
+
/**
|
|
11609
|
+
* Slots reclaimed by window displacement rather than by delivery or
|
|
11610
|
+
* abandonment. Deliberately separate from the combiner's own release count:
|
|
11611
|
+
* "nobody ever saw this sample" and "the combiner gave up on it" are
|
|
11612
|
+
* different failures with different owners, and one number cannot say which.
|
|
11613
|
+
*/
|
|
11614
|
+
get evictedSampleCount() {
|
|
11615
|
+
return __privateGet(this, _evictedSamples);
|
|
11616
|
+
}
|
|
11596
11617
|
/** Typed reason for the most recent rejected movie fragment. */
|
|
11597
11618
|
get lastMovieFragmentRejection() {
|
|
11598
11619
|
return __privateGet(this, _lastMovieFragmentRejection);
|
|
@@ -11630,7 +11651,11 @@ var IsoBmffTimingResolver = class {
|
|
|
11630
11651
|
(sample, index) => sample !== null && sameSample(sample, parsed.samples[index])
|
|
11631
11652
|
);
|
|
11632
11653
|
}
|
|
11633
|
-
|
|
11654
|
+
let freed = 0;
|
|
11655
|
+
while (__privateGet(this, _fragments).size > 0 && (__privateGet(this, _pendingSamples) + parsed.samples.length > this.maxPendingSamples || parsed.samples.length - freed > additionalSampleLimit)) {
|
|
11656
|
+
freed += __privateMethod(this, _IsoBmffTimingResolver_instances, evictOldestFragment_fn).call(this);
|
|
11657
|
+
}
|
|
11658
|
+
if (parsed.samples.length - freed > additionalSampleLimit) {
|
|
11634
11659
|
__privateSet(this, _lastMovieFragmentRejection, "budget");
|
|
11635
11660
|
return false;
|
|
11636
11661
|
}
|
|
@@ -11663,12 +11688,11 @@ var IsoBmffTimingResolver = class {
|
|
|
11663
11688
|
* Free the budget slot of a sample that will never be delivered.
|
|
11664
11689
|
*
|
|
11665
11690
|
* `consumeSample` is the delivery path and is the only decrement on a
|
|
11666
|
-
* healthy stream.
|
|
11667
|
-
* delivered
|
|
11668
|
-
*
|
|
11669
|
-
*
|
|
11670
|
-
*
|
|
11671
|
-
* a full track reset clears it.
|
|
11691
|
+
* healthy stream. A sample whose data units never complete is never
|
|
11692
|
+
* delivered; window displacement in `addMovieFragment` eventually reclaims
|
|
11693
|
+
* it, but only after it has aged out of the whole window. This path frees
|
|
11694
|
+
* the slot as soon as the combiner knows the sample is gone, so the budget
|
|
11695
|
+
* tracks what is actually in flight rather than what has merely aged.
|
|
11672
11696
|
*
|
|
11673
11697
|
* The caller is whoever abandoned the sample, so the release is driven by
|
|
11674
11698
|
* the abandonment itself rather than by a timer, an LRU, or an age bound --
|
|
@@ -11692,8 +11716,27 @@ var IsoBmffTimingResolver = class {
|
|
|
11692
11716
|
_track = new WeakMap();
|
|
11693
11717
|
_fragments = new WeakMap();
|
|
11694
11718
|
_pendingSamples = new WeakMap();
|
|
11719
|
+
_evictedSamples = new WeakMap();
|
|
11695
11720
|
_lastMovieFragmentRejection = new WeakMap();
|
|
11696
11721
|
_IsoBmffTimingResolver_instances = new WeakSet();
|
|
11722
|
+
/**
|
|
11723
|
+
* Drop the oldest pending fragment whole and return the slots it held.
|
|
11724
|
+
*
|
|
11725
|
+
* Oldest is insertion order, which for a moof stream is arrival order, so
|
|
11726
|
+
* this is the least-recently-declared timing -- the entries least likely to
|
|
11727
|
+
* still have data units in flight.
|
|
11728
|
+
*/
|
|
11729
|
+
evictOldestFragment_fn = function() {
|
|
11730
|
+
const oldest = __privateGet(this, _fragments).keys().next().value;
|
|
11731
|
+
if (oldest === void 0) return 0;
|
|
11732
|
+
const samples = __privateGet(this, _fragments).get(oldest);
|
|
11733
|
+
let live = 0;
|
|
11734
|
+
for (const sample of samples) if (sample !== null) live++;
|
|
11735
|
+
__privateGet(this, _fragments).delete(oldest);
|
|
11736
|
+
__privateSet(this, _pendingSamples, __privateGet(this, _pendingSamples) - live);
|
|
11737
|
+
__privateSet(this, _evictedSamples, __privateGet(this, _evictedSamples) + live);
|
|
11738
|
+
return live;
|
|
11739
|
+
};
|
|
11697
11740
|
/** Null one slot, decrement the budget, and drop the fragment when empty. */
|
|
11698
11741
|
clearSlot_fn = function(mpuSequenceNumber, movieFragmentSequenceNumber, sampleNumber) {
|
|
11699
11742
|
if (!isU322(mpuSequenceNumber) || !isU322(movieFragmentSequenceNumber) || movieFragmentSequenceNumber === 0 || !isU322(sampleNumber) || sampleNumber === 0) {
|
|
@@ -11872,7 +11915,7 @@ function isFmp4Box(data) {
|
|
|
11872
11915
|
const type = String.fromCharCode(data[4], data[5], data[6], data[7]);
|
|
11873
11916
|
return FMPU_BOX_TYPES.has(type);
|
|
11874
11917
|
}
|
|
11875
|
-
var _tracks, _defaultTrack, _reassembler, _sampleCombiners, _sampleCombinerOptions, _retiredSampleCombinerStats, _timingStreams, _maxPendingTimingSamples, _pendingTimingSamples, _reclaimedTimingSamples, _rejectedMovieFragments, _sequencers, _reorderWindow, _reassemblyPolicy, _frameCb, _initCb, _sourceSymbolCb, _trackFrameCbs, _reorderStats, _reliableMoqStartupGate, _disposed2, _MmtpContainerParser_instances, streamKey_fn2, sampleCombinerFor_fn, releaseTimingSlot_fn, dropSampleCombiner_fn, emitCombinedSample_fn, passReliableMoqStartupGate_fn, timingResolver_fn, dropTimingStream_fn, validateReassemblyPolicy_fn, buildFrameMeta_fn, sequencerFor_fn, flushSequencers_fn, emitFrame_fn2, _MmtpContainerParser_static, scanForKeyframe_fn, scanLengthPrefixedHevcForKeyframe_fn, scanAnnexBForKeyframe_fn;
|
|
11918
|
+
var _tracks, _defaultTrack, _reassembler, _sampleCombiners, _sampleCombinerOptions, _retiredSampleCombinerStats, _timingStreams, _maxPendingTimingSamples, _pendingTimingSamples, _reclaimedTimingSamples, _evictedTimingSamples, _rejectedMovieFragments, _sequencers, _reorderWindow, _reassemblyPolicy, _frameCb, _initCb, _sourceSymbolCb, _trackFrameCbs, _reorderStats, _reliableMoqStartupGate, _disposed2, _fedObjects, _feedOutcomes, _deferredFeedOutcomes, _lastOutcome, _lastOutcomeCount, _MmtpContainerParser_instances, streamKey_fn2, sampleCombinerFor_fn, releaseTimingSlot_fn, dropSampleCombiner_fn, countOutcome_fn, countDeferredOutcome_fn, drop_fn, feed_fn, emitCombinedSample_fn, passReliableMoqStartupGate_fn, timingResolver_fn, dropTimingStream_fn, validateReassemblyPolicy_fn, buildFrameMeta_fn, sequencerFor_fn, flushSequencers_fn, emitFrame_fn2, _MmtpContainerParser_static, scanForKeyframe_fn, scanLengthPrefixedHevcForKeyframe_fn, scanAnnexBForKeyframe_fn;
|
|
11876
11919
|
var _MmtpContainerParser = class _MmtpContainerParser {
|
|
11877
11920
|
constructor(config) {
|
|
11878
11921
|
__privateAdd(this, _MmtpContainerParser_instances);
|
|
@@ -11906,6 +11949,7 @@ var _MmtpContainerParser = class _MmtpContainerParser {
|
|
|
11906
11949
|
__privateAdd(this, _maxPendingTimingSamples);
|
|
11907
11950
|
__privateAdd(this, _pendingTimingSamples, 0);
|
|
11908
11951
|
__privateAdd(this, _reclaimedTimingSamples, 0);
|
|
11952
|
+
__privateAdd(this, _evictedTimingSamples, 0);
|
|
11909
11953
|
__privateAdd(this, _rejectedMovieFragments, 0);
|
|
11910
11954
|
__privateAdd(this, _sequencers, /* @__PURE__ */ new Map());
|
|
11911
11955
|
__privateAdd(this, _reorderWindow, 0);
|
|
@@ -11932,6 +11976,11 @@ var _MmtpContainerParser = class _MmtpContainerParser {
|
|
|
11932
11976
|
* reordering into the parser. */
|
|
11933
11977
|
__privateAdd(this, _reliableMoqStartupGate, /* @__PURE__ */ new Map());
|
|
11934
11978
|
__privateAdd(this, _disposed2, false);
|
|
11979
|
+
__privateAdd(this, _fedObjects, 0);
|
|
11980
|
+
__privateAdd(this, _feedOutcomes, /* @__PURE__ */ new Map());
|
|
11981
|
+
__privateAdd(this, _deferredFeedOutcomes, /* @__PURE__ */ new Map());
|
|
11982
|
+
__privateAdd(this, _lastOutcome, null);
|
|
11983
|
+
__privateAdd(this, _lastOutcomeCount, 0);
|
|
11935
11984
|
/** Authored presentation timestamp of the last emitted frame, in microseconds. */
|
|
11936
11985
|
this.lastFrameTimestamp = void 0;
|
|
11937
11986
|
if (config?.reassemblyPolicy && config.mfuTimeoutMs !== void 0) {
|
|
@@ -12034,6 +12083,7 @@ var _MmtpContainerParser = class _MmtpContainerParser {
|
|
|
12034
12083
|
pending: __privateGet(this, _pendingTimingSamples),
|
|
12035
12084
|
capacity: __privateGet(this, _maxPendingTimingSamples),
|
|
12036
12085
|
reclaimed: __privateGet(this, _reclaimedTimingSamples),
|
|
12086
|
+
evicted: __privateGet(this, _evictedTimingSamples),
|
|
12037
12087
|
rejectedMovieFragments: __privateGet(this, _rejectedMovieFragments)
|
|
12038
12088
|
};
|
|
12039
12089
|
}
|
|
@@ -12042,6 +12092,36 @@ var _MmtpContainerParser = class _MmtpContainerParser {
|
|
|
12042
12092
|
for (const { sequencer } of __privateGet(this, _sequencers).values()) bufferedFrames += sequencer.buffered;
|
|
12043
12093
|
return { ...__privateGet(this, _reorderStats), bufferedFrames };
|
|
12044
12094
|
}
|
|
12095
|
+
/**
|
|
12096
|
+
* Feed tallies for this parser. A fresh snapshot per call, not a live view,
|
|
12097
|
+
* so a caller can hold one and compare it against a later read.
|
|
12098
|
+
*
|
|
12099
|
+
* Survives dispose() — the counters are the parser's own state and are not
|
|
12100
|
+
* cleared by teardown, because a wedged receive path is usually read after
|
|
12101
|
+
* the fact.
|
|
12102
|
+
*/
|
|
12103
|
+
get feedStats() {
|
|
12104
|
+
return {
|
|
12105
|
+
fedObjects: __privateGet(this, _fedObjects),
|
|
12106
|
+
outcomes: Object.fromEntries(__privateGet(this, _feedOutcomes)),
|
|
12107
|
+
deferredOutcomes: Object.fromEntries(__privateGet(this, _deferredFeedOutcomes))
|
|
12108
|
+
};
|
|
12109
|
+
}
|
|
12110
|
+
/**
|
|
12111
|
+
* Outcome token of the most recent feed(), or null before the first call.
|
|
12112
|
+
*
|
|
12113
|
+
* Exposed alongside `lastFeedOutcomeCount` as two scalars rather than one
|
|
12114
|
+
* object because a wrapper reads them on every packet, and feedStats()
|
|
12115
|
+
* allocates a fresh snapshot per call.
|
|
12116
|
+
*/
|
|
12117
|
+
get lastFeedOutcome() {
|
|
12118
|
+
return __privateGet(this, _lastOutcome);
|
|
12119
|
+
}
|
|
12120
|
+
/** How many times `lastFeedOutcome` has now been seen. 1 on its first
|
|
12121
|
+
* occurrence, which is what a caller logging once per novel outcome needs. */
|
|
12122
|
+
get lastFeedOutcomeCount() {
|
|
12123
|
+
return __privateGet(this, _lastOutcomeCount);
|
|
12124
|
+
}
|
|
12045
12125
|
get reorderDiagnostics() {
|
|
12046
12126
|
const streams = [];
|
|
12047
12127
|
for (const { packetId, sequencer } of __privateGet(this, _sequencers).values()) {
|
|
@@ -12091,181 +12171,16 @@ var _MmtpContainerParser = class _MmtpContainerParser {
|
|
|
12091
12171
|
}
|
|
12092
12172
|
/** Feed a complete MMTP packet. For two-phase use, call parseHeader() first. */
|
|
12093
12173
|
feed(packet, options) {
|
|
12094
|
-
|
|
12095
|
-
|
|
12096
|
-
this.cleanupTimeouts();
|
|
12097
|
-
const info = this.parseHeader(packet, options);
|
|
12098
|
-
if (!info) return null;
|
|
12099
|
-
if (info.packetType !== PACKET_TYPE_MPU2) {
|
|
12100
|
-
return {
|
|
12101
|
-
kind: info.isRepair ? "repair" : "non-media",
|
|
12102
|
-
packet: info,
|
|
12103
|
-
byteLength: packet.byteLength
|
|
12104
|
-
};
|
|
12105
|
-
}
|
|
12106
|
-
if (info.fecPayloadId !== null && __privateGet(this, _sourceSymbolCb)) {
|
|
12107
|
-
const rawSymbol = packet.subarray(0, packet.length - 4);
|
|
12108
|
-
const altaTrailer = extractAltaTrailer2(packet);
|
|
12109
|
-
const alta = altaTrailer ? { auth: altaTrailer.auth, payloadEnd: altaTrailer.signedEnd } : void 0;
|
|
12110
|
-
try {
|
|
12111
|
-
__privateGet(this, _sourceSymbolCb).call(this, info.packetId, info.fecPayloadId.ssId, rawSymbol, alta);
|
|
12112
|
-
} catch {
|
|
12113
|
-
}
|
|
12114
|
-
}
|
|
12115
|
-
const extraction = extractMFUPayload(packet, {
|
|
12116
|
-
skipFecId: options?.skipFecPayloadId
|
|
12117
|
-
});
|
|
12118
|
-
if (!extraction) return null;
|
|
12119
|
-
const { mpu, fragmentType, data, mfuDuHeader } = extraction;
|
|
12120
|
-
if (mpu.timedFlag !== 1) return null;
|
|
12121
|
-
const streamKey = __privateMethod(this, _MmtpContainerParser_instances, streamKey_fn2).call(this, info.packetId, options?.catalogTrackName);
|
|
12122
|
-
if (fragmentType === 0) {
|
|
12123
|
-
if (mpu.fragmentationIndicator !== 0 || mpu.fragmentCounter !== 0) return null;
|
|
12124
|
-
const normalizedInit = normalizeMmtpInitSegment(data);
|
|
12125
|
-
if (!normalizedInit) return null;
|
|
12126
|
-
const resolver2 = __privateMethod(this, _MmtpContainerParser_instances, timingResolver_fn).call(this, streamKey, info.packetId, true);
|
|
12127
|
-
if (!resolver2?.addInitialization(normalizedInit)) return null;
|
|
12128
|
-
(_a = __privateGet(this, _initCb)) == null ? void 0 : _a.call(this, normalizedInit, info.packetId, options?.catalogTrackName);
|
|
12129
|
-
return {
|
|
12130
|
-
kind: "init",
|
|
12131
|
-
packet: info,
|
|
12132
|
-
data: normalizedInit,
|
|
12133
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12134
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12135
|
-
fragmentCounter: mpu.fragmentCounter
|
|
12136
|
-
};
|
|
12137
|
-
}
|
|
12138
|
-
if (fragmentType === 1) {
|
|
12139
|
-
if (mpu.fragmentationIndicator !== 0 || mpu.fragmentCounter !== 0) return null;
|
|
12140
|
-
const resolver2 = __privateMethod(this, _MmtpContainerParser_instances, timingResolver_fn).call(this, streamKey, info.packetId, false);
|
|
12141
|
-
if (!resolver2) return null;
|
|
12142
|
-
const pendingBefore = resolver2.pendingSampleCount;
|
|
12143
|
-
const remaining = __privateGet(this, _maxPendingTimingSamples) - __privateGet(this, _pendingTimingSamples);
|
|
12144
|
-
if (!resolver2.addMovieFragment(mpu.mpuSequenceNumber, data, remaining)) {
|
|
12145
|
-
if (resolver2.lastMovieFragmentRejection === "budget") {
|
|
12146
|
-
__privateWrapper(this, _rejectedMovieFragments)._++;
|
|
12147
|
-
}
|
|
12148
|
-
return null;
|
|
12149
|
-
}
|
|
12150
|
-
__privateSet(this, _pendingTimingSamples, __privateGet(this, _pendingTimingSamples) + (resolver2.pendingSampleCount - pendingBefore));
|
|
12151
|
-
return {
|
|
12152
|
-
kind: "fragment",
|
|
12153
|
-
packet: info,
|
|
12154
|
-
data,
|
|
12155
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12156
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12157
|
-
fragmentCounter: mpu.fragmentCounter
|
|
12158
|
-
};
|
|
12159
|
-
}
|
|
12160
|
-
if (fragmentType !== 2) return null;
|
|
12161
|
-
const resolver = __privateMethod(this, _MmtpContainerParser_instances, timingResolver_fn).call(this, streamKey, info.packetId, false);
|
|
12162
|
-
if (!resolver) return null;
|
|
12163
|
-
if (!Number.isSafeInteger(data.byteLength) || data.byteLength <= 0) return null;
|
|
12164
|
-
if (mpu.fragmentationIndicator === 0 || mpu.fragmentationIndicator === 1) {
|
|
12165
|
-
if (!mfuDuHeader || mfuDuHeader.movieFragmentSequenceNumber === 0 || mfuDuHeader.sampleNumber === 0) {
|
|
12166
|
-
return null;
|
|
12167
|
-
}
|
|
12168
|
-
const headTiming = resolver.sampleTiming(
|
|
12169
|
-
mpu.mpuSequenceNumber,
|
|
12170
|
-
mfuDuHeader.movieFragmentSequenceNumber,
|
|
12171
|
-
mfuDuHeader.sampleNumber
|
|
12172
|
-
);
|
|
12173
|
-
if (!headTiming) return null;
|
|
12174
|
-
const offset = mfuDuHeader.offset;
|
|
12175
|
-
if (!Number.isSafeInteger(offset) || offset < 0 || offset >= headTiming.size) return null;
|
|
12176
|
-
const remaining = headTiming.size - offset;
|
|
12177
|
-
if (mpu.fragmentationIndicator === 0 && data.byteLength !== remaining) return null;
|
|
12178
|
-
if (mpu.fragmentationIndicator === 1 && data.byteLength >= remaining) return null;
|
|
12179
|
-
const readyOnRegister = __privateMethod(this, _MmtpContainerParser_instances, sampleCombinerFor_fn).call(this, streamKey).registerAuthoredSize(
|
|
12180
|
-
options?.catalogTrackName,
|
|
12181
|
-
mpu.mpuSequenceNumber,
|
|
12182
|
-
mfuDuHeader.movieFragmentSequenceNumber,
|
|
12183
|
-
mfuDuHeader.sampleNumber,
|
|
12184
|
-
headTiming.size
|
|
12185
|
-
);
|
|
12186
|
-
if (readyOnRegister) {
|
|
12187
|
-
__privateMethod(this, _MmtpContainerParser_instances, emitCombinedSample_fn).call(this, readyOnRegister, info, resolver, options?.recovered === true);
|
|
12188
|
-
}
|
|
12189
|
-
}
|
|
12190
|
-
let assembled;
|
|
12191
|
-
try {
|
|
12192
|
-
assembled = __privateGet(this, _reassembler).addFragment({
|
|
12193
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12194
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12195
|
-
fragmentCounter: mpu.fragmentCounter,
|
|
12196
|
-
data,
|
|
12197
|
-
timestamp: info.timestamp,
|
|
12198
|
-
rapFlag: info.rapFlag,
|
|
12199
|
-
priority: mfuDuHeader?.priority,
|
|
12200
|
-
sampleNumber: mfuDuHeader?.sampleNumber,
|
|
12201
|
-
movieFragmentSequenceNumber: mfuDuHeader?.movieFragmentSequenceNumber,
|
|
12202
|
-
sampleOffset: mfuDuHeader?.offset,
|
|
12203
|
-
packetSequenceNumber: info.sequenceNumber,
|
|
12204
|
-
recovered: options?.recovered === true,
|
|
12205
|
-
source: options?.source,
|
|
12206
|
-
deliveryProvenance: options?.deliveryProvenance,
|
|
12207
|
-
catalogTrackName: options?.catalogTrackName,
|
|
12208
|
-
packetId: info.packetId
|
|
12209
|
-
});
|
|
12210
|
-
} catch (error) {
|
|
12211
|
-
if (!isMfuReassemblyError(error)) throw error;
|
|
12212
|
-
console.warn(
|
|
12213
|
-
`[MmtpContainerParser] rejected MFU fragment: code=${error.code} mpu=${mpu.mpuSequenceNumber} fi=${mpu.fragmentationIndicator} counter=${mpu.fragmentCounter}`
|
|
12214
|
-
);
|
|
12215
|
-
return {
|
|
12216
|
-
kind: "rejected",
|
|
12217
|
-
packet: info,
|
|
12218
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12219
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12220
|
-
fragmentCounter: mpu.fragmentCounter,
|
|
12221
|
-
error: { code: error.code, message: error.message }
|
|
12222
|
-
};
|
|
12223
|
-
}
|
|
12224
|
-
if (!assembled) {
|
|
12225
|
-
return {
|
|
12226
|
-
kind: "pending",
|
|
12227
|
-
packet: info,
|
|
12228
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12229
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12230
|
-
fragmentCounter: mpu.fragmentCounter
|
|
12231
|
-
};
|
|
12232
|
-
}
|
|
12233
|
-
const movieFragmentSequenceNumber = assembled.movieFragmentSequenceNumber;
|
|
12234
|
-
const sampleNumber = assembled.sampleNumber;
|
|
12235
|
-
if (movieFragmentSequenceNumber === void 0 || sampleNumber === void 0) return null;
|
|
12236
|
-
if (!resolver.sampleTiming(
|
|
12237
|
-
assembled.mpuSequenceNumber,
|
|
12238
|
-
movieFragmentSequenceNumber,
|
|
12239
|
-
sampleNumber
|
|
12240
|
-
)) return null;
|
|
12241
|
-
if (assembled.mpuSequenceNumber !== mpu.mpuSequenceNumber) return null;
|
|
12242
|
-
let combined;
|
|
12174
|
+
__privateSet(this, _fedObjects, __privateGet(this, _fedObjects) + 1);
|
|
12175
|
+
let record;
|
|
12243
12176
|
try {
|
|
12244
|
-
|
|
12177
|
+
record = __privateMethod(this, _MmtpContainerParser_instances, feed_fn).call(this, packet, options);
|
|
12245
12178
|
} catch (error) {
|
|
12246
|
-
|
|
12247
|
-
|
|
12248
|
-
`[MmtpContainerParser] rejected subsample data unit: code=${error.code} mpu=${assembled.mpuSequenceNumber} sample=${sampleNumber} offset=${assembled.sampleOffset ?? 0}`
|
|
12249
|
-
);
|
|
12250
|
-
return {
|
|
12251
|
-
kind: "rejected",
|
|
12252
|
-
packet: info,
|
|
12253
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12254
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12255
|
-
fragmentCounter: mpu.fragmentCounter,
|
|
12256
|
-
error: { code: error.code, message: error.message }
|
|
12257
|
-
};
|
|
12258
|
-
}
|
|
12259
|
-
if (!combined) {
|
|
12260
|
-
return {
|
|
12261
|
-
kind: "pending",
|
|
12262
|
-
packet: info,
|
|
12263
|
-
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12264
|
-
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12265
|
-
fragmentCounter: mpu.fragmentCounter
|
|
12266
|
-
};
|
|
12179
|
+
__privateMethod(this, _MmtpContainerParser_instances, countOutcome_fn).call(this, "drop:threw");
|
|
12180
|
+
throw error;
|
|
12267
12181
|
}
|
|
12268
|
-
|
|
12182
|
+
if (record) __privateMethod(this, _MmtpContainerParser_instances, countOutcome_fn).call(this, record.kind);
|
|
12183
|
+
return record;
|
|
12269
12184
|
}
|
|
12270
12185
|
onInit(cb) {
|
|
12271
12186
|
__privateSet(this, _initCb, cb);
|
|
@@ -12433,6 +12348,7 @@ _timingStreams = new WeakMap();
|
|
|
12433
12348
|
_maxPendingTimingSamples = new WeakMap();
|
|
12434
12349
|
_pendingTimingSamples = new WeakMap();
|
|
12435
12350
|
_reclaimedTimingSamples = new WeakMap();
|
|
12351
|
+
_evictedTimingSamples = new WeakMap();
|
|
12436
12352
|
_rejectedMovieFragments = new WeakMap();
|
|
12437
12353
|
_sequencers = new WeakMap();
|
|
12438
12354
|
_reorderWindow = new WeakMap();
|
|
@@ -12444,6 +12360,11 @@ _trackFrameCbs = new WeakMap();
|
|
|
12444
12360
|
_reorderStats = new WeakMap();
|
|
12445
12361
|
_reliableMoqStartupGate = new WeakMap();
|
|
12446
12362
|
_disposed2 = new WeakMap();
|
|
12363
|
+
_fedObjects = new WeakMap();
|
|
12364
|
+
_feedOutcomes = new WeakMap();
|
|
12365
|
+
_deferredFeedOutcomes = new WeakMap();
|
|
12366
|
+
_lastOutcome = new WeakMap();
|
|
12367
|
+
_lastOutcomeCount = new WeakMap();
|
|
12447
12368
|
_MmtpContainerParser_instances = new WeakSet();
|
|
12448
12369
|
streamKey_fn2 = function(packetId, catalogTrackName) {
|
|
12449
12370
|
return JSON.stringify([packetId, catalogTrackName ?? null]);
|
|
@@ -12462,12 +12383,12 @@ sampleCombinerFor_fn = function(streamKey) {
|
|
|
12462
12383
|
/**
|
|
12463
12384
|
* Return the timing budget slot of a sample the combiner abandoned.
|
|
12464
12385
|
*
|
|
12465
|
-
* Without this, `#pendingTimingSamples` is
|
|
12466
|
-
*
|
|
12467
|
-
*
|
|
12468
|
-
*
|
|
12469
|
-
*
|
|
12470
|
-
*
|
|
12386
|
+
* Without this, `#pendingTimingSamples` is charged for every sample a moof
|
|
12387
|
+
* declares but credited only when that sample is delivered, so each sample
|
|
12388
|
+
* lost to eviction or timeout burns a slot until the window displaces it.
|
|
12389
|
+
* Window displacement bounds that leak but only reclaims the OLDEST entries;
|
|
12390
|
+
* this path returns a slot the moment the combiner knows the sample is gone,
|
|
12391
|
+
* which keeps the live window as wide as the stream actually needs.
|
|
12471
12392
|
*
|
|
12472
12393
|
* The parser total is decremented only when the resolver reports it
|
|
12473
12394
|
* actually freed a slot, so a resolver already dropped by a track reset, or
|
|
@@ -12499,11 +12420,232 @@ dropSampleCombiner_fn = function(streamKey) {
|
|
|
12499
12420
|
__privateGet(this, _retiredSampleCombinerStats).evictedSamples += stats.evictedSamples;
|
|
12500
12421
|
__privateGet(this, _sampleCombiners).delete(streamKey);
|
|
12501
12422
|
};
|
|
12423
|
+
countOutcome_fn = function(token) {
|
|
12424
|
+
const count = (__privateGet(this, _feedOutcomes).get(token) ?? 0) + 1;
|
|
12425
|
+
__privateGet(this, _feedOutcomes).set(token, count);
|
|
12426
|
+
__privateSet(this, _lastOutcome, token);
|
|
12427
|
+
__privateSet(this, _lastOutcomeCount, count);
|
|
12428
|
+
};
|
|
12429
|
+
countDeferredOutcome_fn = function(reason) {
|
|
12430
|
+
__privateGet(this, _deferredFeedOutcomes).set(
|
|
12431
|
+
reason,
|
|
12432
|
+
(__privateGet(this, _deferredFeedOutcomes).get(reason) ?? 0) + 1
|
|
12433
|
+
);
|
|
12434
|
+
};
|
|
12435
|
+
/**
|
|
12436
|
+
* Count a feed() drop and return null in one expression, so every early
|
|
12437
|
+
* return inside feed() states the reason it took instead of collapsing into
|
|
12438
|
+
* a single failure bucket. Returns null so call sites stay `return this.#drop(...)`.
|
|
12439
|
+
*/
|
|
12440
|
+
drop_fn = function(reason) {
|
|
12441
|
+
__privateMethod(this, _MmtpContainerParser_instances, countOutcome_fn).call(this, `drop:${reason}`);
|
|
12442
|
+
return null;
|
|
12443
|
+
};
|
|
12444
|
+
feed_fn = function(packet, options) {
|
|
12445
|
+
var _a;
|
|
12446
|
+
if (__privateGet(this, _disposed2)) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "disposed");
|
|
12447
|
+
this.cleanupTimeouts();
|
|
12448
|
+
const info = this.parseHeader(packet, options);
|
|
12449
|
+
if (!info) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "header-parse-failed");
|
|
12450
|
+
if (info.packetType !== PACKET_TYPE_MPU2) {
|
|
12451
|
+
return {
|
|
12452
|
+
kind: info.isRepair ? "repair" : "non-media",
|
|
12453
|
+
packet: info,
|
|
12454
|
+
byteLength: packet.byteLength
|
|
12455
|
+
};
|
|
12456
|
+
}
|
|
12457
|
+
if (info.fecPayloadId !== null && __privateGet(this, _sourceSymbolCb)) {
|
|
12458
|
+
const rawSymbol = packet.subarray(0, packet.length - 4);
|
|
12459
|
+
const altaTrailer = extractAltaTrailer2(packet);
|
|
12460
|
+
const alta = altaTrailer ? { auth: altaTrailer.auth, payloadEnd: altaTrailer.signedEnd } : void 0;
|
|
12461
|
+
try {
|
|
12462
|
+
__privateGet(this, _sourceSymbolCb).call(this, info.packetId, info.fecPayloadId.ssId, rawSymbol, alta);
|
|
12463
|
+
} catch {
|
|
12464
|
+
}
|
|
12465
|
+
}
|
|
12466
|
+
const extraction = extractMFUPayload(packet, {
|
|
12467
|
+
skipFecId: options?.skipFecPayloadId
|
|
12468
|
+
});
|
|
12469
|
+
if (!extraction) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-extract-failed");
|
|
12470
|
+
const { mpu, fragmentType, data, mfuDuHeader } = extraction;
|
|
12471
|
+
if (mpu.timedFlag !== 1) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "untimed-mpu");
|
|
12472
|
+
const streamKey = __privateMethod(this, _MmtpContainerParser_instances, streamKey_fn2).call(this, info.packetId, options?.catalogTrackName);
|
|
12473
|
+
if (fragmentType === 0) {
|
|
12474
|
+
if (mpu.fragmentationIndicator !== 0 || mpu.fragmentCounter !== 0)
|
|
12475
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "init-unexpected-fragmentation");
|
|
12476
|
+
const normalizedInit = normalizeMmtpInitSegment(data);
|
|
12477
|
+
if (!normalizedInit) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "init-normalize-failed");
|
|
12478
|
+
const resolver2 = __privateMethod(this, _MmtpContainerParser_instances, timingResolver_fn).call(this, streamKey, info.packetId, true);
|
|
12479
|
+
if (!resolver2?.addInitialization(normalizedInit)) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "init-timing-refused");
|
|
12480
|
+
(_a = __privateGet(this, _initCb)) == null ? void 0 : _a.call(this, normalizedInit, info.packetId, options?.catalogTrackName);
|
|
12481
|
+
return {
|
|
12482
|
+
kind: "init",
|
|
12483
|
+
packet: info,
|
|
12484
|
+
data: normalizedInit,
|
|
12485
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12486
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12487
|
+
fragmentCounter: mpu.fragmentCounter
|
|
12488
|
+
};
|
|
12489
|
+
}
|
|
12490
|
+
if (fragmentType === 1) {
|
|
12491
|
+
if (mpu.fragmentationIndicator !== 0 || mpu.fragmentCounter !== 0)
|
|
12492
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "fragment-unexpected-fragmentation");
|
|
12493
|
+
const resolver2 = __privateMethod(this, _MmtpContainerParser_instances, timingResolver_fn).call(this, streamKey, info.packetId, false);
|
|
12494
|
+
if (!resolver2) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "fragment-no-resolver");
|
|
12495
|
+
const pendingBefore = resolver2.pendingSampleCount;
|
|
12496
|
+
const evictedBefore = resolver2.evictedSampleCount;
|
|
12497
|
+
const remaining = __privateGet(this, _maxPendingTimingSamples) - __privateGet(this, _pendingTimingSamples);
|
|
12498
|
+
const admitted = resolver2.addMovieFragment(mpu.mpuSequenceNumber, data, remaining);
|
|
12499
|
+
__privateSet(this, _pendingTimingSamples, __privateGet(this, _pendingTimingSamples) + (resolver2.pendingSampleCount - pendingBefore));
|
|
12500
|
+
__privateSet(this, _evictedTimingSamples, __privateGet(this, _evictedTimingSamples) + (resolver2.evictedSampleCount - evictedBefore));
|
|
12501
|
+
if (!admitted) {
|
|
12502
|
+
if (resolver2.lastMovieFragmentRejection === "budget") {
|
|
12503
|
+
__privateWrapper(this, _rejectedMovieFragments)._++;
|
|
12504
|
+
}
|
|
12505
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "fragment-timing-refused");
|
|
12506
|
+
}
|
|
12507
|
+
return {
|
|
12508
|
+
kind: "fragment",
|
|
12509
|
+
packet: info,
|
|
12510
|
+
data,
|
|
12511
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12512
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12513
|
+
fragmentCounter: mpu.fragmentCounter
|
|
12514
|
+
};
|
|
12515
|
+
}
|
|
12516
|
+
if (fragmentType !== 2) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "unknown-fragment-type");
|
|
12517
|
+
const resolver = __privateMethod(this, _MmtpContainerParser_instances, timingResolver_fn).call(this, streamKey, info.packetId, false);
|
|
12518
|
+
if (!resolver) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-no-resolver");
|
|
12519
|
+
if (!Number.isSafeInteger(data.byteLength) || data.byteLength <= 0)
|
|
12520
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-empty-payload");
|
|
12521
|
+
if (mpu.fragmentationIndicator === 0 || mpu.fragmentationIndicator === 1) {
|
|
12522
|
+
if (!mfuDuHeader || mfuDuHeader.movieFragmentSequenceNumber === 0 || mfuDuHeader.sampleNumber === 0) {
|
|
12523
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-du-header-missing");
|
|
12524
|
+
}
|
|
12525
|
+
const headTiming = resolver.sampleTiming(
|
|
12526
|
+
mpu.mpuSequenceNumber,
|
|
12527
|
+
mfuDuHeader.movieFragmentSequenceNumber,
|
|
12528
|
+
mfuDuHeader.sampleNumber
|
|
12529
|
+
);
|
|
12530
|
+
if (!headTiming) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-sample-timing-missing");
|
|
12531
|
+
const offset = mfuDuHeader.offset;
|
|
12532
|
+
if (!Number.isSafeInteger(offset) || offset < 0 || offset >= headTiming.size)
|
|
12533
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-offset-out-of-range");
|
|
12534
|
+
const remaining = headTiming.size - offset;
|
|
12535
|
+
if (mpu.fragmentationIndicator === 0 && data.byteLength !== remaining)
|
|
12536
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-size-mismatch");
|
|
12537
|
+
if (mpu.fragmentationIndicator === 1 && data.byteLength >= remaining)
|
|
12538
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "mfu-size-mismatch");
|
|
12539
|
+
const readyOnRegister = __privateMethod(this, _MmtpContainerParser_instances, sampleCombinerFor_fn).call(this, streamKey).registerAuthoredSize(
|
|
12540
|
+
options?.catalogTrackName,
|
|
12541
|
+
mpu.mpuSequenceNumber,
|
|
12542
|
+
mfuDuHeader.movieFragmentSequenceNumber,
|
|
12543
|
+
mfuDuHeader.sampleNumber,
|
|
12544
|
+
headTiming.size
|
|
12545
|
+
);
|
|
12546
|
+
if (readyOnRegister) {
|
|
12547
|
+
const deferred = __privateMethod(this, _MmtpContainerParser_instances, emitCombinedSample_fn).call(this, readyOnRegister, info, resolver, options?.recovered === true);
|
|
12548
|
+
if (deferred.record === void 0) __privateMethod(this, _MmtpContainerParser_instances, countDeferredOutcome_fn).call(this, deferred.reason);
|
|
12549
|
+
}
|
|
12550
|
+
}
|
|
12551
|
+
let assembled;
|
|
12552
|
+
try {
|
|
12553
|
+
assembled = __privateGet(this, _reassembler).addFragment({
|
|
12554
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12555
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12556
|
+
fragmentCounter: mpu.fragmentCounter,
|
|
12557
|
+
data,
|
|
12558
|
+
timestamp: info.timestamp,
|
|
12559
|
+
rapFlag: info.rapFlag,
|
|
12560
|
+
priority: mfuDuHeader?.priority,
|
|
12561
|
+
sampleNumber: mfuDuHeader?.sampleNumber,
|
|
12562
|
+
movieFragmentSequenceNumber: mfuDuHeader?.movieFragmentSequenceNumber,
|
|
12563
|
+
sampleOffset: mfuDuHeader?.offset,
|
|
12564
|
+
packetSequenceNumber: info.sequenceNumber,
|
|
12565
|
+
recovered: options?.recovered === true,
|
|
12566
|
+
source: options?.source,
|
|
12567
|
+
deliveryProvenance: options?.deliveryProvenance,
|
|
12568
|
+
catalogTrackName: options?.catalogTrackName,
|
|
12569
|
+
packetId: info.packetId
|
|
12570
|
+
});
|
|
12571
|
+
} catch (error) {
|
|
12572
|
+
if (!isMfuReassemblyError(error)) throw error;
|
|
12573
|
+
console.warn(
|
|
12574
|
+
`[MmtpContainerParser] rejected MFU fragment: code=${error.code} mpu=${mpu.mpuSequenceNumber} fi=${mpu.fragmentationIndicator} counter=${mpu.fragmentCounter}`
|
|
12575
|
+
);
|
|
12576
|
+
return {
|
|
12577
|
+
kind: "rejected",
|
|
12578
|
+
packet: info,
|
|
12579
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12580
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12581
|
+
fragmentCounter: mpu.fragmentCounter,
|
|
12582
|
+
error: { code: error.code, message: error.message }
|
|
12583
|
+
};
|
|
12584
|
+
}
|
|
12585
|
+
if (!assembled) {
|
|
12586
|
+
return {
|
|
12587
|
+
kind: "pending",
|
|
12588
|
+
packet: info,
|
|
12589
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12590
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12591
|
+
fragmentCounter: mpu.fragmentCounter
|
|
12592
|
+
};
|
|
12593
|
+
}
|
|
12594
|
+
const movieFragmentSequenceNumber = assembled.movieFragmentSequenceNumber;
|
|
12595
|
+
const sampleNumber = assembled.sampleNumber;
|
|
12596
|
+
if (movieFragmentSequenceNumber === void 0 || sampleNumber === void 0)
|
|
12597
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "assembled-identity-missing");
|
|
12598
|
+
if (!resolver.sampleTiming(
|
|
12599
|
+
assembled.mpuSequenceNumber,
|
|
12600
|
+
movieFragmentSequenceNumber,
|
|
12601
|
+
sampleNumber
|
|
12602
|
+
)) return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "assembled-timing-missing");
|
|
12603
|
+
if (assembled.mpuSequenceNumber !== mpu.mpuSequenceNumber)
|
|
12604
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, "assembled-mpu-mismatch");
|
|
12605
|
+
let combined;
|
|
12606
|
+
try {
|
|
12607
|
+
combined = __privateMethod(this, _MmtpContainerParser_instances, sampleCombinerFor_fn).call(this, streamKey).addMfu(assembled);
|
|
12608
|
+
} catch (error) {
|
|
12609
|
+
if (!(error instanceof SampleCombineError)) throw error;
|
|
12610
|
+
console.warn(
|
|
12611
|
+
`[MmtpContainerParser] rejected subsample data unit: code=${error.code} mpu=${assembled.mpuSequenceNumber} sample=${sampleNumber} offset=${assembled.sampleOffset ?? 0}`
|
|
12612
|
+
);
|
|
12613
|
+
return {
|
|
12614
|
+
kind: "rejected",
|
|
12615
|
+
packet: info,
|
|
12616
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12617
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12618
|
+
fragmentCounter: mpu.fragmentCounter,
|
|
12619
|
+
error: { code: error.code, message: error.message }
|
|
12620
|
+
};
|
|
12621
|
+
}
|
|
12622
|
+
if (!combined) {
|
|
12623
|
+
return {
|
|
12624
|
+
kind: "pending",
|
|
12625
|
+
packet: info,
|
|
12626
|
+
mpuSequenceNumber: mpu.mpuSequenceNumber,
|
|
12627
|
+
fragmentationIndicator: mpu.fragmentationIndicator,
|
|
12628
|
+
fragmentCounter: mpu.fragmentCounter
|
|
12629
|
+
};
|
|
12630
|
+
}
|
|
12631
|
+
const outcome = __privateMethod(this, _MmtpContainerParser_instances, emitCombinedSample_fn).call(this, combined, info, resolver, options?.recovered === true);
|
|
12632
|
+
if (outcome.record !== void 0) return outcome.record;
|
|
12633
|
+
return __privateMethod(this, _MmtpContainerParser_instances, drop_fn).call(this, outcome.reason);
|
|
12634
|
+
};
|
|
12502
12635
|
/**
|
|
12503
12636
|
* Deliver one combined sample: resolve its authored timing, build frame
|
|
12504
12637
|
* metadata, retire the timing entry, and route it. Shared by the ordinary
|
|
12505
12638
|
* completion path and by the rarer completion that falls out of registering
|
|
12506
12639
|
* an authored size for data units that arrived before it.
|
|
12640
|
+
*
|
|
12641
|
+
* Reports a refusal as a reason rather than counting it, because the two
|
|
12642
|
+
* call sites owe different accounting. On `#feed()`'s tail return the
|
|
12643
|
+
* refusal *is* that feed()'s outcome and must be attributed; on the
|
|
12644
|
+
* register-completion path it belongs to an earlier sample while this
|
|
12645
|
+
* packet's own fragment continues to its own outcome, so counting it there
|
|
12646
|
+
* would push `outcomes` past `fedObjects` — the very invariant the
|
|
12647
|
+
* attribution exists to keep readable. Leaving the choice at the call site
|
|
12648
|
+
* is what keeps both true.
|
|
12507
12649
|
*/
|
|
12508
12650
|
emitCombinedSample_fn = function(combined, info, resolver, recovered) {
|
|
12509
12651
|
const timing = resolver.sampleTiming(
|
|
@@ -12511,27 +12653,29 @@ emitCombinedSample_fn = function(combined, info, resolver, recovered) {
|
|
|
12511
12653
|
combined.movieFragmentSequenceNumber,
|
|
12512
12654
|
combined.sampleNumber
|
|
12513
12655
|
);
|
|
12514
|
-
if (!timing) return
|
|
12515
|
-
if (combined.data.byteLength !== timing.size) return
|
|
12656
|
+
if (!timing) return { reason: "combined-timing-missing" };
|
|
12657
|
+
if (combined.data.byteLength !== timing.size) return { reason: "combined-size-mismatch" };
|
|
12516
12658
|
const meta = __privateMethod(this, _MmtpContainerParser_instances, buildFrameMeta_fn).call(this, combined, info.packetId, info.sequenceNumber, timing, recovered);
|
|
12517
|
-
if (!meta) return
|
|
12659
|
+
if (!meta) return { reason: "combined-meta-build-failed" };
|
|
12518
12660
|
if (!resolver.consumeSample(
|
|
12519
12661
|
combined.mpuSequenceNumber,
|
|
12520
12662
|
combined.movieFragmentSequenceNumber,
|
|
12521
12663
|
combined.sampleNumber,
|
|
12522
12664
|
timing
|
|
12523
|
-
)) return
|
|
12665
|
+
)) return { reason: "combined-timing-consume-refused" };
|
|
12524
12666
|
__privateWrapper(this, _pendingTimingSamples)._--;
|
|
12525
12667
|
this.routeFrame(combined.data, meta);
|
|
12526
12668
|
return {
|
|
12527
|
-
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
12531
|
-
|
|
12532
|
-
|
|
12533
|
-
|
|
12534
|
-
|
|
12669
|
+
record: {
|
|
12670
|
+
kind: "frame",
|
|
12671
|
+
packet: info,
|
|
12672
|
+
data: combined.data,
|
|
12673
|
+
meta,
|
|
12674
|
+
mpuSequenceNumber: combined.mpuSequenceNumber,
|
|
12675
|
+
fragmentCount: combined.fragmentCount,
|
|
12676
|
+
rapFlag: combined.rapFlag,
|
|
12677
|
+
...combined.priority === void 0 ? {} : { priority: combined.priority }
|
|
12678
|
+
}
|
|
12535
12679
|
};
|
|
12536
12680
|
};
|
|
12537
12681
|
/** Order-independent reliable-moq startup gate: discard delta frames for a
|
|
@@ -14319,7 +14463,11 @@ admitRecoveredResult_fn = function(blockId, result, ownerPacketId, catalogTrackN
|
|
|
14319
14463
|
__privateMethod(this, _MmtpRouter_instances, routeProcessedFecSymbols_fn).call(this, blockId, { ...result, symbols: [symbol] }, ownerPacketId, catalogTrackName);
|
|
14320
14464
|
}
|
|
14321
14465
|
admitNext(index + 1);
|
|
14322
|
-
}
|
|
14466
|
+
},
|
|
14467
|
+
// A stalled symbol that is later discarded instead of played must still
|
|
14468
|
+
// advance this loop; enforce mode never calls the release callback for
|
|
14469
|
+
// it (BLO-30095).
|
|
14470
|
+
() => admitNext(index + 1)
|
|
14323
14471
|
);
|
|
14324
14472
|
if (admission.action === "drop") admitNext(index + 1);
|
|
14325
14473
|
};
|
|
@@ -15092,12 +15240,16 @@ var driadDiscovery = new DRIADDiscovery();
|
|
|
15092
15240
|
function endpointKey(endpoint) {
|
|
15093
15241
|
return `${endpoint.sourceAddress ?? ""}|${endpoint.groupAddress}|${endpoint.port}`;
|
|
15094
15242
|
}
|
|
15243
|
+
function carriesMedia(endpoint) {
|
|
15244
|
+
return endpoint.carriesMedia !== false;
|
|
15245
|
+
}
|
|
15095
15246
|
function selectMulticastTier(endpoints, estimate) {
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15247
|
+
const media = endpoints.filter(carriesMedia);
|
|
15248
|
+
if (media.length <= 1)
|
|
15249
|
+
return media[0];
|
|
15250
|
+
const ranked = media.filter((endpoint) => typeof endpoint.bandwidth === "number" && endpoint.bandwidth > 0).sort((a, b) => a.bandwidth - b.bandwidth);
|
|
15099
15251
|
if (ranked.length < 2)
|
|
15100
|
-
return
|
|
15252
|
+
return media[0];
|
|
15101
15253
|
if (estimate === void 0)
|
|
15102
15254
|
return ranked[0];
|
|
15103
15255
|
const budget = estimate * 0.8;
|
|
@@ -15346,7 +15498,7 @@ var MulticastOrchestrator = class {
|
|
|
15346
15498
|
const currentBandwidth = __privateGet(this, _current).bandwidth;
|
|
15347
15499
|
if (typeof currentBandwidth !== "number")
|
|
15348
15500
|
return void 0;
|
|
15349
|
-
const desired = this.options.endpoints.filter((endpoint) => typeof endpoint.bandwidth === "number" && endpoint.bandwidth > currentBandwidth).sort((a, b) => a.bandwidth - b.bandwidth)[0];
|
|
15501
|
+
const desired = this.options.endpoints.filter((endpoint) => carriesMedia(endpoint) && typeof endpoint.bandwidth === "number" && endpoint.bandwidth > currentBandwidth).sort((a, b) => a.bandwidth - b.bandwidth)[0];
|
|
15350
15502
|
if (!desired) {
|
|
15351
15503
|
__privateSet(this, _favored, void 0);
|
|
15352
15504
|
return void 0;
|
|
@@ -16277,6 +16429,14 @@ function getMulticastGlobals() {
|
|
|
16277
16429
|
function hasMulticastGateway() {
|
|
16278
16430
|
return typeof getMulticastGlobals().multicast?.subscribe === "function";
|
|
16279
16431
|
}
|
|
16432
|
+
function normalizeBytesEventDetail(detail) {
|
|
16433
|
+
const value = detail && typeof detail === "object" && "data" in detail ? detail.data : detail;
|
|
16434
|
+
if (value instanceof ArrayBuffer) return new Uint8Array(value);
|
|
16435
|
+
if (ArrayBuffer.isView(value)) {
|
|
16436
|
+
return new Uint8Array(value.buffer, value.byteOffset, value.byteLength);
|
|
16437
|
+
}
|
|
16438
|
+
return null;
|
|
16439
|
+
}
|
|
16280
16440
|
var _onPacket, _subscription2, _bytesListener, _resolvedTransport, _videoConfirmed, _audioConfirmed, _watchdog, _failbackWindowMs, _onTakeover, _onFailback, _disposed4, _stats3, _droppedPidCounts, _packetIds, _joinGeneration, _MulticastTransport_instances, releaseSubscription_fn, acceptPacket_fn, recordUnregisteredPidDrop_fn, checkTakeover_fn, resetWatchdog_fn;
|
|
16281
16441
|
var _MulticastTransport = class _MulticastTransport {
|
|
16282
16442
|
constructor(onPacket) {
|
|
@@ -16343,8 +16503,11 @@ var _MulticastTransport = class _MulticastTransport {
|
|
|
16343
16503
|
}
|
|
16344
16504
|
const onBytes = (event) => {
|
|
16345
16505
|
if (__privateGet(this, _disposed4) || generation !== __privateGet(this, _joinGeneration)) return;
|
|
16346
|
-
const
|
|
16347
|
-
|
|
16506
|
+
const packet = normalizeBytesEventDetail(event.detail);
|
|
16507
|
+
if (!packet) {
|
|
16508
|
+
__privateGet(this, _stats3).packetsDroppedUnparseable++;
|
|
16509
|
+
return;
|
|
16510
|
+
}
|
|
16348
16511
|
if (!__privateMethod(this, _MulticastTransport_instances, acceptPacket_fn).call(this, packet)) return;
|
|
16349
16512
|
__privateGet(this, _stats3).packetsReceived++;
|
|
16350
16513
|
__privateGet(this, _stats3).bytesReceived += packet.byteLength;
|
|
@@ -16641,6 +16804,24 @@ function publishFecDiagnostics(packetId, stats) {
|
|
|
16641
16804
|
function altGroupKey(track) {
|
|
16642
16805
|
return track.altGroup === void 0 ? DEFAULT_ALT_GROUP : String(track.altGroup);
|
|
16643
16806
|
}
|
|
16807
|
+
function repairTrackNamesBySource(tracks) {
|
|
16808
|
+
const bySource = /* @__PURE__ */ new Map();
|
|
16809
|
+
const add = (source, repair) => {
|
|
16810
|
+
if (!source || !repair) return;
|
|
16811
|
+
const names = bySource.get(source) ?? /* @__PURE__ */ new Set();
|
|
16812
|
+
names.add(repair);
|
|
16813
|
+
bySource.set(source, names);
|
|
16814
|
+
};
|
|
16815
|
+
for (const track of tracks) {
|
|
16816
|
+
if (track.fec !== void 0 && isFecCatalogConfig(track.fec) && track.fec.repairTrack) {
|
|
16817
|
+
add(track.name, track.fec.repairTrack);
|
|
16818
|
+
}
|
|
16819
|
+
if (track.packaging === "fec-repair" && Array.isArray(track.depends) && track.depends.length === 1) {
|
|
16820
|
+
add(track.depends[0], track.name);
|
|
16821
|
+
}
|
|
16822
|
+
}
|
|
16823
|
+
return bySource;
|
|
16824
|
+
}
|
|
16644
16825
|
var _fec, _router, _transport, _reportedFecDiagnosticsFailure, _streamFecBaseline, _trackFecTiming, _switchingSets, _repairPacketIds, _repairInFlight, _repairLifecycleObservers, _trackResetObservers, _onRepairSubscribeCb, _MulticastManager_instances, configureTrackMapper_fn, applyStreamGlobalFecTiming_fn, _onTrackTypeDiscovered, emitRepairLifecycle_fn;
|
|
16645
16826
|
var MulticastManager = class {
|
|
16646
16827
|
constructor(options) {
|
|
@@ -17101,34 +17282,36 @@ var MulticastManager = class {
|
|
|
17101
17282
|
* a factory returning a distinct decoder per stream.
|
|
17102
17283
|
*/
|
|
17103
17284
|
configureMultiTrack(catalog, wasmDecoderSource) {
|
|
17104
|
-
const
|
|
17285
|
+
const repairNamesBySource = repairTrackNamesBySource(catalog.tracks);
|
|
17286
|
+
const repairOwnerGroup = /* @__PURE__ */ new Map();
|
|
17287
|
+
const repairOwnerAltGroup = /* @__PURE__ */ new Map();
|
|
17288
|
+
for (const track of catalog.tracks) {
|
|
17289
|
+
for (const repairName of repairNamesBySource.get(track.name) ?? []) {
|
|
17290
|
+
repairOwnerGroup.set(repairName, altGroupKey(track));
|
|
17291
|
+
repairOwnerAltGroup.set(repairName, track.altGroup);
|
|
17292
|
+
}
|
|
17293
|
+
}
|
|
17294
|
+
const groupKeyFor = (track) => repairOwnerGroup.get(track.name) ?? altGroupKey(track);
|
|
17105
17295
|
const trackNamesByGroup = /* @__PURE__ */ new Map();
|
|
17106
17296
|
for (const track of catalog.tracks) {
|
|
17107
|
-
const groupKey =
|
|
17297
|
+
const groupKey = groupKeyFor(track);
|
|
17108
17298
|
const groupNames = trackNamesByGroup.get(groupKey) ?? [];
|
|
17109
17299
|
groupNames.push(track.name);
|
|
17110
17300
|
trackNamesByGroup.set(groupKey, groupNames);
|
|
17111
|
-
if (track.fec !== void 0 && isFecCatalogConfig(track.fec) && track.fec.repairTrack) {
|
|
17112
|
-
const explicitRepairNames = explicitRepairNamesByGroup.get(groupKey) ?? /* @__PURE__ */ new Set();
|
|
17113
|
-
explicitRepairNames.add(track.fec.repairTrack);
|
|
17114
|
-
explicitRepairNamesByGroup.set(groupKey, explicitRepairNames);
|
|
17115
|
-
}
|
|
17116
17301
|
}
|
|
17117
17302
|
const hasSwitchingSetByGroup = /* @__PURE__ */ new Map();
|
|
17118
17303
|
for (const [groupKey, trackNames] of trackNamesByGroup) {
|
|
17119
17304
|
hasSwitchingSetByGroup.set(groupKey, hasSwitchingSetRole(trackNames));
|
|
17120
17305
|
}
|
|
17121
17306
|
const resolvedRoles = catalog.tracks.map((track) => {
|
|
17122
|
-
|
|
17123
|
-
const hasSwitchingSet = hasSwitchingSetByGroup.get(
|
|
17124
|
-
const explicitRepairNames = explicitRepairNamesByGroup.get(groupKey);
|
|
17125
|
-
if (explicitRepairNames?.has(track.name)) return "repair";
|
|
17307
|
+
if (repairOwnerGroup.has(track.name)) return "repair";
|
|
17308
|
+
const hasSwitchingSet = hasSwitchingSetByGroup.get(altGroupKey(track)) ?? false;
|
|
17126
17309
|
if (!hasSwitchingSet) return "single";
|
|
17127
17310
|
return parseTrackRole(track.name);
|
|
17128
17311
|
});
|
|
17129
17312
|
const resolvedRolesByGroup = /* @__PURE__ */ new Map();
|
|
17130
17313
|
for (let i = 0; i < catalog.tracks.length; i++) {
|
|
17131
|
-
const groupKey =
|
|
17314
|
+
const groupKey = groupKeyFor(catalog.tracks[i]);
|
|
17132
17315
|
const roles = resolvedRolesByGroup.get(groupKey) ?? [];
|
|
17133
17316
|
roles.push(resolvedRoles[i]);
|
|
17134
17317
|
resolvedRolesByGroup.set(groupKey, roles);
|
|
@@ -17191,10 +17374,11 @@ var MulticastManager = class {
|
|
|
17191
17374
|
for (let i = 0; i < catalog.tracks.length; i++) {
|
|
17192
17375
|
const track = catalog.tracks[i];
|
|
17193
17376
|
const role = resolvedRoles[i];
|
|
17194
|
-
|
|
17195
|
-
|
|
17377
|
+
const altGroup = repairOwnerAltGroup.has(track.name) ? repairOwnerAltGroup.get(track.name) : track.altGroup;
|
|
17378
|
+
if (altGroup !== void 0) {
|
|
17379
|
+
const existing = __privateGet(this, _switchingSets).get(altGroup) ?? [];
|
|
17196
17380
|
existing.push(track.name);
|
|
17197
|
-
__privateGet(this, _switchingSets).set(
|
|
17381
|
+
__privateGet(this, _switchingSets).set(altGroup, existing);
|
|
17198
17382
|
}
|
|
17199
17383
|
if (track.packetId !== void 0) {
|
|
17200
17384
|
__privateGet(this, _router).setPacketIdRole(track.packetId, role);
|
|
@@ -17207,9 +17391,13 @@ var MulticastManager = class {
|
|
|
17207
17391
|
}
|
|
17208
17392
|
if (track.fec !== void 0) {
|
|
17209
17393
|
const fecCfg = track.fec;
|
|
17210
|
-
|
|
17211
|
-
|
|
17212
|
-
|
|
17394
|
+
if (track.packetId !== void 0) {
|
|
17395
|
+
for (const repairName of repairNamesBySource.get(track.name) ?? []) {
|
|
17396
|
+
const repairTrack = catalogTracksByName.get(repairName);
|
|
17397
|
+
if (repairTrack?.packetId !== void 0) {
|
|
17398
|
+
__privateGet(this, _router).setRepairPacketIdOwner(repairTrack.packetId, track.packetId);
|
|
17399
|
+
}
|
|
17400
|
+
}
|
|
17213
17401
|
}
|
|
17214
17402
|
const wasmDecoder = fecDecoders.get(i);
|
|
17215
17403
|
if (track.packetId !== void 0 && wasmDecoder !== void 0) {
|
|
@@ -17499,7 +17687,9 @@ async function setupFecWorkerForTrack(opts) {
|
|
|
17499
17687
|
sampleRate: opts.sampleRate,
|
|
17500
17688
|
algorithm: "raptor",
|
|
17501
17689
|
k: opts.fecK,
|
|
17502
|
-
|
|
17690
|
+
// P as this receiver joined it, not the catalog total: the worker snapshot
|
|
17691
|
+
// and CMCD `x-bc-fec-p` are read from this. Identity on a single layer.
|
|
17692
|
+
repairCount: opts.joinedRepairCount ?? opts.fecRepairCount,
|
|
17503
17693
|
symbolSize: opts.fecSymbolSize,
|
|
17504
17694
|
interleaveDepth: interleaveDepthBlocks,
|
|
17505
17695
|
interleaveMs: opts.fecInterleaveMs,
|
|
@@ -18422,7 +18612,7 @@ _readIndex = new WeakMap();
|
|
|
18422
18612
|
_stalled = new WeakMap();
|
|
18423
18613
|
|
|
18424
18614
|
// src/mmtp-decode-pipeline.ts
|
|
18425
|
-
var _parser2, _fecClient, _frameCb2, _initCb2, _needsKeyframe, _codec, _trackType, _gateDropped, _gateEmitted,
|
|
18615
|
+
var _parser2, _fecClient, _frameCb2, _initCb2, _needsKeyframe, _codec, _trackType, _gateDropped, _gateEmitted, _fedObjects2, _warnedNoParser, _feedOutcomes2, _MmtpDecodePipeline_instances, tag_fn, gatedEmit_fn;
|
|
18426
18616
|
var MmtpDecodePipeline = class {
|
|
18427
18617
|
constructor() {
|
|
18428
18618
|
__privateAdd(this, _MmtpDecodePipeline_instances);
|
|
@@ -18442,7 +18632,7 @@ var MmtpDecodePipeline = class {
|
|
|
18442
18632
|
* emitted. Bounded logging only — these gate nothing. */
|
|
18443
18633
|
__privateAdd(this, _gateDropped, 0);
|
|
18444
18634
|
__privateAdd(this, _gateEmitted, 0);
|
|
18445
|
-
__privateAdd(this,
|
|
18635
|
+
__privateAdd(this, _fedObjects2, 0);
|
|
18446
18636
|
/** Warned-once latch for feeds arriving with no parser. Kept separate from
|
|
18447
18637
|
* #fedObjects so that counter stays a pure monotonic count. */
|
|
18448
18638
|
__privateAdd(this, _warnedNoParser, false);
|
|
@@ -18451,16 +18641,16 @@ var MmtpDecodePipeline = class {
|
|
|
18451
18641
|
* so a packet that fails header parse, fails MFU extraction, or accumulates
|
|
18452
18642
|
* forever as an unreassembled fragment is indistinguishable from one that
|
|
18453
18643
|
* produced a frame. Tally the kinds instead of guessing. */
|
|
18454
|
-
__privateAdd(this,
|
|
18644
|
+
__privateAdd(this, _feedOutcomes2, /* @__PURE__ */ new Map());
|
|
18455
18645
|
}
|
|
18456
18646
|
/** Configure the inner parser. Call before feedMoqObject(). */
|
|
18457
18647
|
configure(config) {
|
|
18458
18648
|
__privateGet(this, _parser2)?.flush();
|
|
18459
18649
|
__privateGet(this, _parser2)?.dispose();
|
|
18460
|
-
__privateSet(this,
|
|
18650
|
+
__privateSet(this, _fedObjects2, 0);
|
|
18461
18651
|
__privateSet(this, _gateDropped, 0);
|
|
18462
18652
|
__privateSet(this, _gateEmitted, 0);
|
|
18463
|
-
__privateGet(this,
|
|
18653
|
+
__privateGet(this, _feedOutcomes2).clear();
|
|
18464
18654
|
__privateSet(this, _warnedNoParser, false);
|
|
18465
18655
|
__privateSet(this, _codec, config.codec);
|
|
18466
18656
|
const trackType = isVideoCodec(config.codec) ? "video" : "audio";
|
|
@@ -18520,10 +18710,10 @@ var MmtpDecodePipeline = class {
|
|
|
18520
18710
|
return {
|
|
18521
18711
|
trackType: __privateGet(this, _trackType),
|
|
18522
18712
|
codec: __privateGet(this, _codec),
|
|
18523
|
-
fedObjects: __privateGet(this,
|
|
18713
|
+
fedObjects: __privateGet(this, _fedObjects2),
|
|
18524
18714
|
emitted: __privateGet(this, _gateEmitted),
|
|
18525
18715
|
gateDropped: __privateGet(this, _gateDropped),
|
|
18526
|
-
outcomes: Object.fromEntries(__privateGet(this,
|
|
18716
|
+
outcomes: Object.fromEntries(__privateGet(this, _feedOutcomes2))
|
|
18527
18717
|
};
|
|
18528
18718
|
}
|
|
18529
18719
|
/**
|
|
@@ -18538,8 +18728,8 @@ var MmtpDecodePipeline = class {
|
|
|
18538
18728
|
}
|
|
18539
18729
|
return;
|
|
18540
18730
|
}
|
|
18541
|
-
__privateSet(this,
|
|
18542
|
-
if (__privateGet(this,
|
|
18731
|
+
__privateSet(this, _fedObjects2, __privateGet(this, _fedObjects2) + 1);
|
|
18732
|
+
if (__privateGet(this, _fedObjects2) === 1) {
|
|
18543
18733
|
console.log(`[mmtp-pipeline] first object fed ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} bytes=${packet.length}`);
|
|
18544
18734
|
}
|
|
18545
18735
|
let outcomeKind = "threw";
|
|
@@ -18553,18 +18743,18 @@ var MmtpDecodePipeline = class {
|
|
|
18553
18743
|
const record = __privateGet(this, _parser2).feed(packet);
|
|
18554
18744
|
outcomeKind = record?.kind ?? "null(parse-or-extract-failed)";
|
|
18555
18745
|
} finally {
|
|
18556
|
-
const seen = (__privateGet(this,
|
|
18557
|
-
__privateGet(this,
|
|
18746
|
+
const seen = (__privateGet(this, _feedOutcomes2).get(outcomeKind) ?? 0) + 1;
|
|
18747
|
+
__privateGet(this, _feedOutcomes2).set(outcomeKind, seen);
|
|
18558
18748
|
if (seen === 1) {
|
|
18559
18749
|
console.log(
|
|
18560
|
-
`[mmtp-pipeline] feed outcome FIRST '${outcomeKind}' ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} at object #${__privateGet(this,
|
|
18750
|
+
`[mmtp-pipeline] feed outcome FIRST '${outcomeKind}' ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} at object #${__privateGet(this, _fedObjects2)} bytes=${packet.length}`
|
|
18561
18751
|
);
|
|
18562
18752
|
}
|
|
18563
18753
|
}
|
|
18564
|
-
if (__privateGet(this,
|
|
18565
|
-
const hist = [...__privateGet(this,
|
|
18754
|
+
if (__privateGet(this, _fedObjects2) % 200 === 0) {
|
|
18755
|
+
const hist = [...__privateGet(this, _feedOutcomes2)].map(([k, v]) => `${k}=${v}`).join(" ");
|
|
18566
18756
|
console.log(
|
|
18567
|
-
`[mmtp-pipeline] feed histogram ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} @${__privateGet(this,
|
|
18757
|
+
`[mmtp-pipeline] feed histogram ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} @${__privateGet(this, _fedObjects2)}: ${hist} | emitted=${__privateGet(this, _gateEmitted)} gateDropped=${__privateGet(this, _gateDropped)}`
|
|
18568
18758
|
);
|
|
18569
18759
|
}
|
|
18570
18760
|
}
|
|
@@ -18631,9 +18821,9 @@ _codec = new WeakMap();
|
|
|
18631
18821
|
_trackType = new WeakMap();
|
|
18632
18822
|
_gateDropped = new WeakMap();
|
|
18633
18823
|
_gateEmitted = new WeakMap();
|
|
18634
|
-
|
|
18824
|
+
_fedObjects2 = new WeakMap();
|
|
18635
18825
|
_warnedNoParser = new WeakMap();
|
|
18636
|
-
|
|
18826
|
+
_feedOutcomes2 = new WeakMap();
|
|
18637
18827
|
_MmtpDecodePipeline_instances = new WeakSet();
|
|
18638
18828
|
/** Identity prefix for diagnostics: one pipeline per track means two
|
|
18639
18829
|
* instances write to the same console, and unlabelled lines interleave into
|
|
@@ -18649,7 +18839,7 @@ gatedEmit_fn = function(data, meta) {
|
|
|
18649
18839
|
__privateSet(this, _gateDropped, __privateGet(this, _gateDropped) + 1);
|
|
18650
18840
|
if (__privateGet(this, _gateDropped) <= 3 || __privateGet(this, _gateDropped) % 200 === 0) {
|
|
18651
18841
|
console.warn(
|
|
18652
|
-
`[mmtp-pipeline] keyframe gate DROP #${__privateGet(this, _gateDropped)} ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} bytes=${data.length} fed=${__privateGet(this,
|
|
18842
|
+
`[mmtp-pipeline] keyframe gate DROP #${__privateGet(this, _gateDropped)} ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} bytes=${data.length} fed=${__privateGet(this, _fedObjects2)} emitted=${__privateGet(this, _gateEmitted)}`
|
|
18653
18843
|
);
|
|
18654
18844
|
}
|
|
18655
18845
|
return;
|
|
@@ -18657,7 +18847,7 @@ gatedEmit_fn = function(data, meta) {
|
|
|
18657
18847
|
__privateSet(this, _needsKeyframe, false);
|
|
18658
18848
|
sourceDiscontinuity = true;
|
|
18659
18849
|
console.log(
|
|
18660
|
-
`[mmtp-pipeline] keyframe gate OPENED ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} after ${__privateGet(this, _gateDropped)} drops, fed=${__privateGet(this,
|
|
18850
|
+
`[mmtp-pipeline] keyframe gate OPENED ${__privateMethod(this, _MmtpDecodePipeline_instances, tag_fn).call(this)} after ${__privateGet(this, _gateDropped)} drops, fed=${__privateGet(this, _fedObjects2)}`
|
|
18661
18851
|
);
|
|
18662
18852
|
}
|
|
18663
18853
|
__privateSet(this, _gateEmitted, __privateGet(this, _gateEmitted) + 1);
|
|
@@ -19361,6 +19551,16 @@ var NO_FEC = {
|
|
|
19361
19551
|
fecSymbolSize: 0,
|
|
19362
19552
|
fecInterleaveMs: 0
|
|
19363
19553
|
};
|
|
19554
|
+
function joinedRepairSymbolCount(params, joinedRepairTrackNames) {
|
|
19555
|
+
const layers = params.repairLayers;
|
|
19556
|
+
if (layers === void 0 || layers.length === 0) return params.fecRepairCount;
|
|
19557
|
+
const joined = new Set(joinedRepairTrackNames);
|
|
19558
|
+
let total = 0;
|
|
19559
|
+
for (const layer of layers) {
|
|
19560
|
+
if (joined.has(layer.repairTrackName)) total += layer.repairSymbols;
|
|
19561
|
+
}
|
|
19562
|
+
return total;
|
|
19563
|
+
}
|
|
19364
19564
|
function recordOf(value) {
|
|
19365
19565
|
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
19366
19566
|
}
|
|
@@ -19790,6 +19990,7 @@ export {
|
|
|
19790
19990
|
isSignalingPacket,
|
|
19791
19991
|
isSourcePacket,
|
|
19792
19992
|
isTrackTimingConfig,
|
|
19993
|
+
joinedRepairSymbolCount,
|
|
19793
19994
|
mergeOverrideIntoCmsfTracks,
|
|
19794
19995
|
mergeOverrideIntoHangRenditions,
|
|
19795
19996
|
mfuReassemblyTimeoutMs,
|