livedesk 0.1.169 → 0.1.170

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.
@@ -150,6 +150,7 @@ const DUPLICATE_DEVICE_ACTIVE_REJECT_MS = 15000;
150
150
  const DUPLICATE_DEVICE_LOG_THROTTLE_MS = 60000;
151
151
  const DUPLICATE_DEVICE_RETRY_AFTER_MS = 30000;
152
152
  const AGENT_BINARY_INGRESS_QUEUE_PACKETS = 256;
153
+ const MODE5_AGENT_BINARY_INGRESS_QUEUE_PACKETS = 2;
153
154
  const AGENT_BINARY_INGRESS_DRAIN_BUDGET_PACKETS = 64;
154
155
  const SYNTHETIC_FRAME_DATA_URL = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAABCAYAAAD0In+KAAAADElEQVR42mP8z8AAAAMBAQDJ/pLvAAAAAElFTkSuQmCC';
155
156
  const SYNTHETIC_FRAME_PAYLOAD = Buffer.from(SYNTHETIC_FRAME_DATA_URL.split(',')[1], 'base64');
@@ -3132,6 +3133,8 @@ export function createRemoteHub(options = {}) {
3132
3133
  compressMs: readFrameStageMs(message, 'compressMs'),
3133
3134
  deltaTileSize: Number.isFinite(Number(message.deltaTileSize)) ? Number(message.deltaTileSize) : 0,
3134
3135
  deltaTileCount: Number.isFinite(Number(message.deltaTileCount)) ? Number(message.deltaTileCount) : 0,
3136
+ deltaVisualTileCount: Number.isFinite(Number(message.deltaVisualTileCount)) ? Number(message.deltaVisualTileCount) : 0,
3137
+ deltaRefreshTileCount: Number.isFinite(Number(message.deltaRefreshTileCount)) ? Number(message.deltaRefreshTileCount) : 0,
3135
3138
  deltaTotalTiles: Number.isFinite(Number(message.deltaTotalTiles)) ? Number(message.deltaTotalTiles) : 0,
3136
3139
  sameContentStreak,
3137
3140
  payload,
@@ -3330,6 +3333,8 @@ export function createRemoteHub(options = {}) {
3330
3333
  compressMs: readFrameStageMs(message, 'compressMs'),
3331
3334
  deltaTileSize: Number.isFinite(Number(message.deltaTileSize)) ? Number(message.deltaTileSize) : 0,
3332
3335
  deltaTileCount: Number.isFinite(Number(message.deltaTileCount)) ? Number(message.deltaTileCount) : 0,
3336
+ deltaVisualTileCount: Number.isFinite(Number(message.deltaVisualTileCount)) ? Number(message.deltaVisualTileCount) : 0,
3337
+ deltaRefreshTileCount: Number.isFinite(Number(message.deltaRefreshTileCount)) ? Number(message.deltaRefreshTileCount) : 0,
3333
3338
  deltaTotalTiles: Number.isFinite(Number(message.deltaTotalTiles)) ? Number(message.deltaTotalTiles) : 0,
3334
3339
  sameContentStreak,
3335
3340
  payload,
@@ -3500,6 +3505,23 @@ export function createRemoteHub(options = {}) {
3500
3505
  state.binaryQueueDrops = Number(state.binaryQueueDrops || 0) + 1;
3501
3506
  }
3502
3507
 
3508
+ function isMode5BinaryHeader(header) {
3509
+ const mode = safeString(header?.frameMode || header?.mode, 40).toLowerCase();
3510
+ return mode === 'mode5-lzo-delta';
3511
+ }
3512
+
3513
+ function dropQueuedMode5AgentBinaryFrame(state, header) {
3514
+ const streamId = safeString(header?.streamId, 160);
3515
+ const dropIndex = state.binaryQueue.findIndex(item => isMode5BinaryHeader(item?.header)
3516
+ && (!streamId || safeString(item?.header?.streamId, 160) === streamId));
3517
+ if (dropIndex < 0) {
3518
+ return false;
3519
+ }
3520
+ state.binaryQueue.splice(dropIndex, 1);
3521
+ state.binaryQueueDrops = Number(state.binaryQueueDrops || 0) + 1;
3522
+ return true;
3523
+ }
3524
+
3503
3525
  function scheduleAgentBinaryIngress(socket, state) {
3504
3526
  if (!state || state.closed || !socket || socket.destroyed) {
3505
3527
  return;
@@ -3545,6 +3567,17 @@ export function createRemoteHub(options = {}) {
3545
3567
  if (!Array.isArray(state.binaryQueue)) {
3546
3568
  state.binaryQueue = [];
3547
3569
  }
3570
+ if (isMode5BinaryHeader(header)) {
3571
+ const streamId = safeString(header?.streamId, 160);
3572
+ let queuedMode5Packets = state.binaryQueue.filter(item => isMode5BinaryHeader(item?.header)
3573
+ && (!streamId || safeString(item?.header?.streamId, 160) === streamId)).length;
3574
+ while (queuedMode5Packets >= MODE5_AGENT_BINARY_INGRESS_QUEUE_PACKETS) {
3575
+ if (!dropQueuedMode5AgentBinaryFrame(state, header)) {
3576
+ break;
3577
+ }
3578
+ queuedMode5Packets -= 1;
3579
+ }
3580
+ }
3548
3581
  while (state.binaryQueue.length >= AGENT_BINARY_INGRESS_QUEUE_PACKETS) {
3549
3582
  dropQueuedAgentBinaryFrame(state);
3550
3583
  }
package/hub/src/server.js CHANGED
@@ -24,6 +24,8 @@ const httpPort = Number(process.env.LIVEDESK_HUB_HTTP_PORT || process.env.PORT |
24
24
  const frameBackpressureBytes = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_BACKPRESSURE_BYTES', 64 * 1024 * 1024);
25
25
  const frameClientQueuePackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_QUEUE_PACKETS', 256);
26
26
  const frameClientDrainBudgetPackets = readPositiveIntegerEnv('LIVEDESK_FRAME_WS_DRAIN_BUDGET_PACKETS', 64);
27
+ const mode5FrameBackpressureBytes = readPositiveIntegerEnv('LIVEDESK_MODE5_WS_BACKPRESSURE_BYTES', 2 * 1024 * 1024);
28
+ const mode5FrameQueuePackets = readPositiveIntegerEnv('LIVEDESK_MODE5_WS_QUEUE_PACKETS', 2);
27
29
  const frameClients = new Set();
28
30
  const frameClientsByDeviceId = new Map();
29
31
  const frameWildcardClients = new Set();
@@ -538,6 +540,16 @@ function dropQueuedFrameForLane(lane) {
538
540
  }
539
541
  }
540
542
 
543
+ function dropQueuedMode5FrameForLane(lane, deviceId) {
544
+ const dropIndex = lane.queue.findIndex(item => item?.isMode5 && item.deviceId === deviceId);
545
+ if (dropIndex < 0) {
546
+ return false;
547
+ }
548
+ lane.queue.splice(dropIndex, 1);
549
+ lane.dropped += 1;
550
+ return true;
551
+ }
552
+
541
553
  function drainFrameClientSendLane(ws) {
542
554
  const lane = ws.liveDeskFrameSendLane;
543
555
  if (!lane || lane.draining) {
@@ -584,7 +596,8 @@ function enqueueFramePacketForClient(ws, packet, meta) {
584
596
  ws.liveDeskFrameBackpressureDrops = Number(ws.liveDeskFrameBackpressureDrops || 0) + 1;
585
597
  return false;
586
598
  }
587
- if (ws.bufferedAmount > frameBackpressureBytes) {
599
+ const backpressureBytes = meta.isMode5 ? mode5FrameBackpressureBytes : frameBackpressureBytes;
600
+ if (ws.bufferedAmount > backpressureBytes) {
588
601
  ws.liveDeskFrameBackpressured = true;
589
602
  lane.dropped += 1;
590
603
  if (meta.isH264 && meta.deviceId) {
@@ -593,6 +606,16 @@ function enqueueFramePacketForClient(ws, packet, meta) {
593
606
  ws.liveDeskFrameBackpressureDrops = Number(ws.liveDeskFrameBackpressureDrops || 0) + 1;
594
607
  return false;
595
608
  }
609
+ if (meta.isMode5) {
610
+ let queuedMode5Packets = lane.queue.filter(item => item?.isMode5 && item.deviceId === meta.deviceId).length;
611
+ while (queuedMode5Packets >= mode5FrameQueuePackets) {
612
+ if (!dropQueuedMode5FrameForLane(lane, meta.deviceId)) {
613
+ break;
614
+ }
615
+ queuedMode5Packets -= 1;
616
+ ws.liveDeskFrameBackpressureDrops = Number(ws.liveDeskFrameBackpressureDrops || 0) + 1;
617
+ }
618
+ }
596
619
  while (lane.queue.length >= frameClientQueuePackets) {
597
620
  dropQueuedFrameForLane(lane);
598
621
  ws.liveDeskFrameBackpressureDrops = Number(ws.liveDeskFrameBackpressureDrops || 0) + 1;
@@ -602,6 +625,7 @@ function enqueueFramePacketForClient(ws, packet, meta) {
602
625
  deviceId: meta.deviceId,
603
626
  frameSeq: meta.frameSeq,
604
627
  isH264: meta.isH264,
628
+ isMode5: meta.isMode5,
605
629
  isKeyFrame: meta.isKeyFrame
606
630
  });
607
631
  drainFrameClientSendLane(ws);
@@ -795,6 +819,8 @@ function buildRemoteFrameBinaryPacket(frameEvent, diagnostics = {}) {
795
819
  compressMs: Number(frame.compressMs || 0) || 0,
796
820
  deltaTileSize: Number(frame.deltaTileSize || 0) || 0,
797
821
  deltaTileCount: Number(frame.deltaTileCount || 0) || 0,
822
+ deltaVisualTileCount: Number(frame.deltaVisualTileCount || 0) || 0,
823
+ deltaRefreshTileCount: Number(frame.deltaRefreshTileCount || 0) || 0,
798
824
  deltaTotalTiles: Number(frame.deltaTotalTiles || 0) || 0,
799
825
  sameContentStreak: Number(frame.sameContentStreak || 0) || 0,
800
826
  layoutVersion: Number(frame.layoutVersion || 0) || 0,
@@ -854,6 +880,7 @@ function broadcastRemoteBinaryFrame(frameEvent) {
854
880
  const frame = frameEvent.frame || {};
855
881
  const isH264 = String(frame.codec || frame.mimeType || frame.format || '').toLowerCase().includes('h264')
856
882
  || String(frame.frameMode || frame.mode || '').toLowerCase() === 'mode3-h264-hw';
883
+ const isMode5 = String(frame.frameMode || frame.mode || '').toLowerCase() === 'mode5-lzo-delta';
857
884
  const isKeyFrame = frame.isKeyFrame === true || String(frame.chunkType || '').toLowerCase() === 'key';
858
885
  const frameSeq = Number(frame.frameSeq || 0) || 0;
859
886
  for (const client of targetClients) {
@@ -879,7 +906,7 @@ function broadcastRemoteBinaryFrame(frameEvent) {
879
906
  if (!packet) {
880
907
  continue;
881
908
  }
882
- enqueueFramePacketForClient(client, packet, { deviceId, frameSeq, isH264, isKeyFrame });
909
+ enqueueFramePacketForClient(client, packet, { deviceId, frameSeq, isH264, isMode5, isKeyFrame });
883
910
  }
884
911
  }
885
912
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "livedesk",
3
- "version": "0.1.169",
3
+ "version": "0.1.170",
4
4
  "description": "LiveDesk Hub and client launcher",
5
5
  "type": "module",
6
6
  "bin": {
@@ -31,7 +31,7 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
34
- "@livedesk/client": "0.1.109",
34
+ "@livedesk/client": "0.1.110",
35
35
  "cors": "^2.8.5",
36
36
  "express": "^4.21.2",
37
37
  "ffmpeg-static": "^5.3.0",