@blockcast/mmt-transport 0.2.0
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/abr-controller.d.ts +94 -0
- package/dist/abr-controller.d.ts.map +1 -0
- package/dist/abr-controller.js +174 -0
- package/dist/abr-controller.js.map +1 -0
- package/dist/amt-gateway.d.ts +160 -0
- package/dist/amt-gateway.d.ts.map +1 -0
- package/dist/amt-gateway.js +390 -0
- package/dist/amt-gateway.js.map +1 -0
- package/dist/clock.d.ts +104 -0
- package/dist/clock.d.ts.map +1 -0
- package/dist/clock.js +183 -0
- package/dist/clock.js.map +1 -0
- package/dist/driad-discovery.d.ts +50 -0
- package/dist/driad-discovery.d.ts.map +1 -0
- package/dist/driad-discovery.js +170 -0
- package/dist/driad-discovery.js.map +1 -0
- package/dist/fec-client.d.ts +442 -0
- package/dist/fec-client.d.ts.map +1 -0
- package/dist/fec-client.js +784 -0
- package/dist/fec-client.js.map +1 -0
- package/dist/fec-client.test.d.ts +8 -0
- package/dist/fec-client.test.d.ts.map +1 -0
- package/dist/fec-client.test.js +112 -0
- package/dist/fec-client.test.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/transport-manager.d.ts +114 -0
- package/dist/transport-manager.d.ts.map +1 -0
- package/dist/transport-manager.js +396 -0
- package/dist/transport-manager.js.map +1 -0
- package/dist/types.d.ts +356 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +85 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
- package/src/abr-controller.ts +227 -0
- package/src/amt-gateway.ts +511 -0
- package/src/clock.ts +212 -0
- package/src/driad-discovery.ts +193 -0
- package/src/fec-client.test.ts +140 -0
- package/src/fec-client.ts +1097 -0
- package/src/index.ts +122 -0
- package/src/transport-manager.ts +460 -0
- package/src/types.ts +420 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @blockcast/transport - AMT Gateway
|
|
3
|
+
*
|
|
4
|
+
* Consolidated AMT (Automatic Multicast Tunneling) implementation
|
|
5
|
+
* supporting both Service Worker and Direct Sockets approaches.
|
|
6
|
+
*
|
|
7
|
+
* RFC 7450: Automatic Multicast Tunneling
|
|
8
|
+
*/
|
|
9
|
+
import { DRIADDiscovery } from "./driad-discovery.js";
|
|
10
|
+
/** Default AMT port (RFC 7450) */
|
|
11
|
+
const DEFAULT_AMT_PORT = 2268;
|
|
12
|
+
/** AMT message types */
|
|
13
|
+
const AMT_MESSAGE_TYPES = {
|
|
14
|
+
RELAY_DISCOVERY: 1,
|
|
15
|
+
RELAY_ADVERTISEMENT: 2,
|
|
16
|
+
REQUEST: 3,
|
|
17
|
+
MEMBERSHIP_QUERY: 4,
|
|
18
|
+
MEMBERSHIP_UPDATE: 5,
|
|
19
|
+
MULTICAST_DATA: 6,
|
|
20
|
+
TEARDOWN: 7,
|
|
21
|
+
};
|
|
22
|
+
/** AMT gateway states */
|
|
23
|
+
const GATEWAY_STATES = {
|
|
24
|
+
IDLE: "idle",
|
|
25
|
+
DISCOVERING: "discovering",
|
|
26
|
+
REQUESTING: "requesting",
|
|
27
|
+
QUERYING: "querying",
|
|
28
|
+
ACTIVE: "active",
|
|
29
|
+
LEAVING: "leaving",
|
|
30
|
+
CLOSED: "closed",
|
|
31
|
+
};
|
|
32
|
+
/** Check if address is IPv4 */
|
|
33
|
+
function isIPv4(address) {
|
|
34
|
+
return /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(address);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* AMT Gateway Manager (Service Worker based)
|
|
38
|
+
*
|
|
39
|
+
* Manages AMT tunnel subscriptions using Service Worker for UDP communication.
|
|
40
|
+
* Handles DRIAD discovery, AMT handshake, and packet decapsulation.
|
|
41
|
+
*/
|
|
42
|
+
export class AMTGatewayManager {
|
|
43
|
+
subscriptions = new Map();
|
|
44
|
+
messageHandler;
|
|
45
|
+
pendingPackets = new Map();
|
|
46
|
+
driad = new DRIADDiscovery();
|
|
47
|
+
constructor() {
|
|
48
|
+
// Set up message handler for packets from service worker
|
|
49
|
+
this.messageHandler = (event) => {
|
|
50
|
+
const data = event.data;
|
|
51
|
+
console.log(`[AMT] SW message received:`, data.type);
|
|
52
|
+
if (data.type === "UDP_PACKET") {
|
|
53
|
+
this.handlePacket(data);
|
|
54
|
+
}
|
|
55
|
+
else if (data.type === "SOCKET_ERROR") {
|
|
56
|
+
this.handleSocketError(data);
|
|
57
|
+
}
|
|
58
|
+
else if (data.type === "DEBUG_LOG") {
|
|
59
|
+
console.log(`[AMT SW Debug] ${data.message}`);
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
// Register message handler
|
|
63
|
+
if (typeof navigator !== "undefined" && navigator.serviceWorker) {
|
|
64
|
+
navigator.serviceWorker.addEventListener("message", this.messageHandler);
|
|
65
|
+
console.log("[AMT] Registered service worker message handler");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.warn("[AMT] Service worker not available");
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Subscribe via AMT tunnel
|
|
73
|
+
*/
|
|
74
|
+
async subscribe(config) {
|
|
75
|
+
const { key } = config;
|
|
76
|
+
const keyStr = this.getKeyString(key);
|
|
77
|
+
if (this.subscriptions.has(keyStr)) {
|
|
78
|
+
throw new Error(`Already subscribed to ${keyStr}`);
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
let relayAddress;
|
|
82
|
+
let discoveryMethod;
|
|
83
|
+
const relayPort = config.relayPort || DEFAULT_AMT_PORT;
|
|
84
|
+
if (config.relayAddress) {
|
|
85
|
+
relayAddress = config.relayAddress;
|
|
86
|
+
discoveryMethod = "manual";
|
|
87
|
+
console.log(`[AMT] Using configured relay ${relayAddress}:${relayPort}`);
|
|
88
|
+
}
|
|
89
|
+
else if (key.source) {
|
|
90
|
+
// DRIAD (RFC 8777) discovers relays based on SOURCE address, not group
|
|
91
|
+
console.log(`[AMT] No relay configured, discovering via DRIAD for source ${key.source}...`);
|
|
92
|
+
const relays = await this.driad.discoverRelays(key.source);
|
|
93
|
+
const bestRelay = await this.driad.selectBestRelay(relays);
|
|
94
|
+
if (!bestRelay) {
|
|
95
|
+
throw new Error(`AMT relay discovery failed for source ${key.source}. ` +
|
|
96
|
+
`Please specify a relay address in the subscription configuration.`);
|
|
97
|
+
}
|
|
98
|
+
relayAddress = bestRelay.host;
|
|
99
|
+
discoveryMethod = "driad";
|
|
100
|
+
console.log(`[AMT] Discovered relay via DRIAD: ${relayAddress}:${relayPort}`);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
throw new Error(`AMT relay discovery requires a source address for SSM (RFC 8777). ` +
|
|
104
|
+
`Please specify either a relay address or source address.`);
|
|
105
|
+
}
|
|
106
|
+
const subscriptionId = keyStr;
|
|
107
|
+
// Initialize packet queue for handshake
|
|
108
|
+
this.pendingPackets.set(subscriptionId, []);
|
|
109
|
+
// Create subscription
|
|
110
|
+
const subscription = {
|
|
111
|
+
key,
|
|
112
|
+
subscriptionId,
|
|
113
|
+
config,
|
|
114
|
+
handshakeComplete: false,
|
|
115
|
+
relay: {
|
|
116
|
+
address: relayAddress,
|
|
117
|
+
port: relayPort,
|
|
118
|
+
discoveryMethod,
|
|
119
|
+
discoveredAt: Date.now(),
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
this.subscriptions.set(keyStr, subscription);
|
|
123
|
+
// Note: Actual UDP socket creation and handshake would require
|
|
124
|
+
// Service Worker communication - this is a simplified version
|
|
125
|
+
console.log(`[AMT] Subscription created for ${keyStr} via ${relayAddress}:${relayPort}`);
|
|
126
|
+
return keyStr;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
const subscription = this.subscriptions.get(keyStr);
|
|
130
|
+
if (subscription) {
|
|
131
|
+
this.subscriptions.delete(keyStr);
|
|
132
|
+
this.pendingPackets.delete(subscription.subscriptionId);
|
|
133
|
+
}
|
|
134
|
+
throw new Error(`Failed to subscribe via AMT: ${error instanceof Error ? error.message : String(error)}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Unsubscribe from AMT tunnel
|
|
139
|
+
*/
|
|
140
|
+
async unsubscribe(handle) {
|
|
141
|
+
const subscription = this.subscriptions.get(handle);
|
|
142
|
+
if (!subscription) {
|
|
143
|
+
throw new Error(`Subscription ${handle} not found`);
|
|
144
|
+
}
|
|
145
|
+
try {
|
|
146
|
+
// Stop keep-alive timer
|
|
147
|
+
if (subscription.keepAliveTimer) {
|
|
148
|
+
clearInterval(subscription.keepAliveTimer);
|
|
149
|
+
}
|
|
150
|
+
console.log(`[AMT] Unsubscribed from ${handle}`);
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
console.error("[AMT] Error during unsubscribe:", error);
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
this.subscriptions.delete(handle);
|
|
157
|
+
this.pendingPackets.delete(subscription.subscriptionId);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get list of active subscriptions
|
|
162
|
+
*/
|
|
163
|
+
getSubscriptions() {
|
|
164
|
+
return Array.from(this.subscriptions.keys());
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Handle packet from service worker
|
|
168
|
+
*/
|
|
169
|
+
handlePacket(message) {
|
|
170
|
+
const { subscriptionId, data } = message;
|
|
171
|
+
if (!subscriptionId)
|
|
172
|
+
return;
|
|
173
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
174
|
+
if (!subscription) {
|
|
175
|
+
console.warn(`[AMT] Received packet for unknown subscription: ${subscriptionId}`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
// During handshake, queue packets
|
|
179
|
+
if (!subscription.handshakeComplete) {
|
|
180
|
+
const queue = this.pendingPackets.get(subscriptionId);
|
|
181
|
+
const packetData = data;
|
|
182
|
+
if (queue) {
|
|
183
|
+
queue.push({
|
|
184
|
+
data: packetData.data,
|
|
185
|
+
remoteAddress: packetData.remoteAddress,
|
|
186
|
+
remotePort: packetData.remotePort,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
// After handshake, forward to callback
|
|
192
|
+
const packetData = data;
|
|
193
|
+
const metadata = {
|
|
194
|
+
sourceAddress: subscription.relay?.address || "unknown",
|
|
195
|
+
sourcePort: subscription.relay?.port || 0,
|
|
196
|
+
transport: "tunnel",
|
|
197
|
+
timestamp: performance.now(),
|
|
198
|
+
};
|
|
199
|
+
subscription.config.onPacket(packetData.data, metadata);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Handle socket error from service worker
|
|
203
|
+
*/
|
|
204
|
+
handleSocketError(message) {
|
|
205
|
+
const { subscriptionId, error } = message;
|
|
206
|
+
if (!subscriptionId)
|
|
207
|
+
return;
|
|
208
|
+
const subscription = this.subscriptions.get(subscriptionId);
|
|
209
|
+
if (!subscription) {
|
|
210
|
+
console.warn(`[AMT] Received error for unknown subscription: ${subscriptionId}`);
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
subscription.config.onError(new Error(error || "Unknown error"));
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Cleanup on destroy
|
|
217
|
+
*/
|
|
218
|
+
destroy() {
|
|
219
|
+
if (this.messageHandler && typeof navigator !== "undefined" && navigator.serviceWorker) {
|
|
220
|
+
navigator.serviceWorker.removeEventListener("message", this.messageHandler);
|
|
221
|
+
}
|
|
222
|
+
const handles = Array.from(this.subscriptions.keys());
|
|
223
|
+
for (const handle of handles) {
|
|
224
|
+
this.unsubscribe(handle).catch((err) => {
|
|
225
|
+
console.error(`[AMT] Error unsubscribing ${handle}:`, err);
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Get key string for HashMap
|
|
231
|
+
*/
|
|
232
|
+
getKeyString(key) {
|
|
233
|
+
const source = key.source ? `@${key.source}` : "";
|
|
234
|
+
return `${key.group}:${key.port}${source}`;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* AMT Gateway Client (Direct Sockets based)
|
|
239
|
+
*
|
|
240
|
+
* Connects to an AMT relay to receive multicast data via unicast tunnel.
|
|
241
|
+
* Implements the gateway side of RFC 7450.
|
|
242
|
+
* Supports multiple (S,G) groups over a single AMT tunnel.
|
|
243
|
+
*/
|
|
244
|
+
export class AMTGateway {
|
|
245
|
+
relayAddress;
|
|
246
|
+
relayPort;
|
|
247
|
+
groups = new Map();
|
|
248
|
+
// Callbacks
|
|
249
|
+
onPacket;
|
|
250
|
+
onStateChange;
|
|
251
|
+
onError;
|
|
252
|
+
onLog;
|
|
253
|
+
// State
|
|
254
|
+
state = GATEWAY_STATES.IDLE;
|
|
255
|
+
nonce = null;
|
|
256
|
+
responseMAC = null;
|
|
257
|
+
relayConfirmedAddress = null;
|
|
258
|
+
lastDataTime = 0;
|
|
259
|
+
// Stats
|
|
260
|
+
stats = {
|
|
261
|
+
packetsReceived: 0,
|
|
262
|
+
bytesReceived: 0,
|
|
263
|
+
queriesReceived: 0,
|
|
264
|
+
updatesSet: 0,
|
|
265
|
+
};
|
|
266
|
+
constructor(options) {
|
|
267
|
+
this.relayAddress = options.relayAddress;
|
|
268
|
+
this.relayPort = options.relayPort || DEFAULT_AMT_PORT;
|
|
269
|
+
this.onPacket = options.onPacket || (() => { });
|
|
270
|
+
this.onStateChange = options.onStateChange || (() => { });
|
|
271
|
+
this.onError = options.onError || ((err) => console.error("AMT Error:", err));
|
|
272
|
+
this.onLog = options.onLog || ((msg) => console.log("AMT:", msg));
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Generate random nonce
|
|
276
|
+
*/
|
|
277
|
+
generateNonce() {
|
|
278
|
+
const nonce = new Uint8Array(4);
|
|
279
|
+
crypto.getRandomValues(nonce);
|
|
280
|
+
return nonce;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Set gateway state
|
|
284
|
+
*/
|
|
285
|
+
setState(newState) {
|
|
286
|
+
const oldState = this.state;
|
|
287
|
+
this.state = newState;
|
|
288
|
+
this.onLog(`State: ${oldState} -> ${newState}`);
|
|
289
|
+
this.onStateChange(newState, oldState);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Join a multicast group
|
|
293
|
+
*/
|
|
294
|
+
async joinGroup(groupAddress, groupPort, sourceAddress = null, onPacket = null) {
|
|
295
|
+
const groupKey = `${sourceAddress || "*"},${groupAddress}`;
|
|
296
|
+
if (this.groups.has(groupKey)) {
|
|
297
|
+
this.onLog(`Group already joined: ${groupKey}`);
|
|
298
|
+
return groupKey;
|
|
299
|
+
}
|
|
300
|
+
this.groups.set(groupKey, {
|
|
301
|
+
groupPort,
|
|
302
|
+
onPacket,
|
|
303
|
+
joinedAt: Date.now(),
|
|
304
|
+
});
|
|
305
|
+
this.onLog(`Joined group: ${groupKey} (port ${groupPort})`);
|
|
306
|
+
return groupKey;
|
|
307
|
+
}
|
|
308
|
+
/**
|
|
309
|
+
* Leave a multicast group
|
|
310
|
+
*/
|
|
311
|
+
async leaveGroup(groupAddress, sourceAddress = null) {
|
|
312
|
+
const groupKey = `${sourceAddress || "*"},${groupAddress}`;
|
|
313
|
+
if (!this.groups.has(groupKey)) {
|
|
314
|
+
this.onLog(`Group not found: ${groupKey}`);
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
this.groups.delete(groupKey);
|
|
318
|
+
this.onLog(`Left group: ${groupKey} (${this.groups.size} remaining)`);
|
|
319
|
+
if (this.groups.size === 0) {
|
|
320
|
+
this.onLog("No groups remaining - closing AMT tunnel");
|
|
321
|
+
await this.close();
|
|
322
|
+
}
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Get list of active groups
|
|
327
|
+
*/
|
|
328
|
+
getGroups() {
|
|
329
|
+
return Array.from(this.groups.entries()).map(([key, info]) => {
|
|
330
|
+
const [source, group] = key.split(",");
|
|
331
|
+
return {
|
|
332
|
+
groupKey: key,
|
|
333
|
+
groupAddress: group,
|
|
334
|
+
sourceAddress: source !== "*" ? source : null,
|
|
335
|
+
groupPort: info.groupPort,
|
|
336
|
+
joinedAt: info.joinedAt,
|
|
337
|
+
};
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Open connection to AMT relay
|
|
342
|
+
*/
|
|
343
|
+
async open() {
|
|
344
|
+
if (this.state !== GATEWAY_STATES.IDLE) {
|
|
345
|
+
throw new Error(`Cannot open in state: ${this.state}`);
|
|
346
|
+
}
|
|
347
|
+
this.setState(GATEWAY_STATES.DISCOVERING);
|
|
348
|
+
this.onLog(`Connecting to AMT relay ${this.relayAddress}:${this.relayPort}`);
|
|
349
|
+
this.onLog(`Active groups: ${this.groups.size}`);
|
|
350
|
+
// Generate session nonce
|
|
351
|
+
this.nonce = this.generateNonce();
|
|
352
|
+
this.onLog(`Generated nonce: ${Array.from(this.nonce).map((b) => b.toString(16).padStart(2, "0")).join("")}`);
|
|
353
|
+
// Note: Actual UDPSocket connection would go here
|
|
354
|
+
// This is a simplified version showing the state machine
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* Close connection
|
|
358
|
+
*/
|
|
359
|
+
async close() {
|
|
360
|
+
if (this.state === GATEWAY_STATES.CLOSED) {
|
|
361
|
+
return;
|
|
362
|
+
}
|
|
363
|
+
this.setState(GATEWAY_STATES.LEAVING);
|
|
364
|
+
// Clear all groups
|
|
365
|
+
this.groups.clear();
|
|
366
|
+
this.setState(GATEWAY_STATES.CLOSED);
|
|
367
|
+
this.onLog("AMT Gateway closed");
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Get current statistics
|
|
371
|
+
*/
|
|
372
|
+
getStats() {
|
|
373
|
+
return { ...this.stats };
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Get current state
|
|
377
|
+
*/
|
|
378
|
+
getState() {
|
|
379
|
+
return this.state;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Check if gateway is active and receiving data
|
|
383
|
+
*/
|
|
384
|
+
isActive() {
|
|
385
|
+
return this.state === GATEWAY_STATES.ACTIVE;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Export singleton manager instance
|
|
389
|
+
export const amtGatewayManager = new AMTGatewayManager();
|
|
390
|
+
//# sourceMappingURL=amt-gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"amt-gateway.js","sourceRoot":"","sources":["../src/amt-gateway.ts"],"names":[],"mappings":"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"}
|
package/dist/clock.d.ts
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @blockcast/transport - SharedClock
|
|
3
|
+
*
|
|
4
|
+
* A/V Synchronization via First Sample Anchor
|
|
5
|
+
*
|
|
6
|
+
* Based on ExoPlayer MMT Plugin implementation:
|
|
7
|
+
* - MMTExtractor.java:46-47 (SystemClockAnchor, MfuClockAnchor)
|
|
8
|
+
* - MMTExtractor.java:625-631 (anchor setting)
|
|
9
|
+
* - SystemClockSynchronizedSimpleDecoderAudioRenderer.java:576 (getPositionUs)
|
|
10
|
+
*
|
|
11
|
+
* This class provides a shared clock anchor across video and audio tracks
|
|
12
|
+
* to ensure A/V synchronization. The anchor is set on the first sample
|
|
13
|
+
* received from ANY track, establishing a common reference point.
|
|
14
|
+
*/
|
|
15
|
+
import type { Micro, SyncDecision } from "./types.js";
|
|
16
|
+
/** Sync tolerance window in microseconds (66ms = ~2 video frames at 30fps) */
|
|
17
|
+
export declare const SYNC_TOLERANCE_US: Micro;
|
|
18
|
+
/** PTS offset for decoder timing (from ExoPlayer MMTExtractor.java:37) */
|
|
19
|
+
export declare const PTS_OFFSET_US: Micro;
|
|
20
|
+
/**
|
|
21
|
+
* Shared clock for A/V synchronization.
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const clock = new SharedClock();
|
|
26
|
+
*
|
|
27
|
+
* // In video/audio source, on first decoded frame:
|
|
28
|
+
* clock.setAnchor(frame.timestamp);
|
|
29
|
+
*
|
|
30
|
+
* // Before rendering each frame:
|
|
31
|
+
* const decision = clock.shouldRender(frame.timestamp);
|
|
32
|
+
* if (decision === "render") { ... }
|
|
33
|
+
* else if (decision === "hold") { await sleep(10); retry(); }
|
|
34
|
+
* else { frame.close(); } // discard
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare class SharedClock {
|
|
38
|
+
#private;
|
|
39
|
+
constructor(bufferDelayMs?: number);
|
|
40
|
+
/**
|
|
41
|
+
* Set the anchor on first sample received from ANY track.
|
|
42
|
+
* This should be called once per session, typically on the first keyframe.
|
|
43
|
+
*
|
|
44
|
+
* @param mediaTimestamp - The presentation timestamp of the first sample (microseconds)
|
|
45
|
+
*/
|
|
46
|
+
setAnchor(mediaTimestamp: Micro): void;
|
|
47
|
+
/**
|
|
48
|
+
* Get the current playback position in microseconds.
|
|
49
|
+
*
|
|
50
|
+
* @returns Current position in microseconds, or 0 if anchor not set
|
|
51
|
+
*/
|
|
52
|
+
getPositionUs(): Micro;
|
|
53
|
+
/**
|
|
54
|
+
* Determine whether a frame should be rendered, held, or discarded.
|
|
55
|
+
*
|
|
56
|
+
* - HOLD: Frame is ahead of clock by more than 66ms (wait for clock)
|
|
57
|
+
* - DISCARD: Frame is behind clock by more than 66ms (too late)
|
|
58
|
+
* - RENDER: Within +/-66ms tolerance window
|
|
59
|
+
*
|
|
60
|
+
* @param frameTimestamp - The presentation timestamp of the frame (microseconds)
|
|
61
|
+
* @returns "render", "hold", or "discard"
|
|
62
|
+
*/
|
|
63
|
+
shouldRender(frameTimestamp: Micro): SyncDecision;
|
|
64
|
+
/**
|
|
65
|
+
* Get how long to wait before a held frame can be rendered.
|
|
66
|
+
*
|
|
67
|
+
* @param frameTimestamp - The presentation timestamp of the frame (microseconds)
|
|
68
|
+
* @returns Wait time in milliseconds, or 0 if frame should be rendered now
|
|
69
|
+
*/
|
|
70
|
+
getWaitTimeMs(frameTimestamp: Micro): number;
|
|
71
|
+
/**
|
|
72
|
+
* Get the delta between a frame timestamp and current position.
|
|
73
|
+
* Positive = frame is ahead, negative = frame is behind.
|
|
74
|
+
*
|
|
75
|
+
* @param frameTimestamp - The presentation timestamp of the frame (microseconds)
|
|
76
|
+
* @returns Delta in microseconds
|
|
77
|
+
*/
|
|
78
|
+
getDeltaUs(frameTimestamp: Micro): number;
|
|
79
|
+
/**
|
|
80
|
+
* Check if the anchor has been set.
|
|
81
|
+
*/
|
|
82
|
+
hasAnchor(): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Get the MFU clock anchor (minimum PTS across all tracks).
|
|
85
|
+
* Used for A/V sync reference point.
|
|
86
|
+
*/
|
|
87
|
+
getMfuClockAnchor(): Micro;
|
|
88
|
+
/**
|
|
89
|
+
* Reset the clock anchor (e.g., on seek or error recovery).
|
|
90
|
+
*/
|
|
91
|
+
reset(): void;
|
|
92
|
+
/**
|
|
93
|
+
* Get debug info about the current clock state.
|
|
94
|
+
*/
|
|
95
|
+
getDebugInfo(): {
|
|
96
|
+
hasAnchor: boolean;
|
|
97
|
+
positionUs: Micro;
|
|
98
|
+
mfuClockAnchor: Micro;
|
|
99
|
+
bufferDelayMs: number;
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
export declare function getSharedClock(bufferDelayMs?: number): SharedClock;
|
|
103
|
+
export declare function resetSharedClock(): void;
|
|
104
|
+
//# sourceMappingURL=clock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../src/clock.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAEtD,8EAA8E;AAC9E,eAAO,MAAM,iBAAiB,EAAY,KAAK,CAAC;AAQhD,0EAA0E;AAC1E,eAAO,MAAM,aAAa,EAAa,KAAK,CAAC;AAE7C;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;;gBAaX,aAAa,GAAE,MAAgC;IAI3D;;;;;OAKG;IACH,SAAS,CAAC,cAAc,EAAE,KAAK,GAAG,IAAI;IAatC;;;;OAIG;IACH,aAAa,IAAI,KAAK;IAYtB;;;;;;;;;OASG;IACH,YAAY,CAAC,cAAc,EAAE,KAAK,GAAG,YAAY;IAgBjD;;;;;OAKG;IACH,aAAa,CAAC,cAAc,EAAE,KAAK,GAAG,MAAM;IAU5C;;;;;;OAMG;IACH,UAAU,CAAC,cAAc,EAAE,KAAK,GAAG,MAAM;IAIzC;;OAEG;IACH,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACH,iBAAiB,IAAI,KAAK;IAI1B;;OAEG;IACH,KAAK,IAAI,IAAI;IAOb;;OAEG;IACH,YAAY,IAAI;QACf,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,KAAK,CAAC;QAClB,cAAc,EAAE,KAAK,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;KACtB;CAQD;AAQD,wBAAgB,cAAc,CAAC,aAAa,CAAC,EAAE,MAAM,GAAG,WAAW,CAKlE;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAGvC"}
|