@livedesk/client 0.1.93 → 0.1.95

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.
@@ -17,7 +17,9 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
17
17
  private let writeLock = NSLock()
18
18
  private var stream: SCStream?
19
19
  private var compressionSession: VTCompressionSession?
20
+ private var sampleCount: Int = 0
20
21
  private var frameCount: Int = 0
22
+ private var skippedCount: Int = 0
21
23
  private var encodedCount: Int = 0
22
24
 
23
25
  init(displayIndex: Int, width: Int, height: Int, fps: Int, bitrateKbps: Int) {
@@ -52,7 +54,7 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
52
54
  configuration.width = width
53
55
  configuration.height = height
54
56
  configuration.minimumFrameInterval = CMTime(value: 1, timescale: CMTimeScale(fps))
55
- configuration.queueDepth = 1
57
+ configuration.queueDepth = 3
56
58
  configuration.showsCursor = false
57
59
  configuration.pixelFormat = kCVPixelFormatType_32BGRA
58
60
 
@@ -69,12 +71,15 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
69
71
 
70
72
  private func createCompressionSession() throws {
71
73
  var session: VTCompressionSession?
74
+ let encoderSpecification: [CFString: Any] = [
75
+ kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder: true
76
+ ]
72
77
  let status = VTCompressionSessionCreate(
73
78
  allocator: kCFAllocatorDefault,
74
79
  width: Int32(width),
75
80
  height: Int32(height),
76
81
  codecType: kCMVideoCodecType_H264,
77
- encoderSpecification: nil,
82
+ encoderSpecification: encoderSpecification as CFDictionary,
78
83
  imageBufferAttributes: nil,
79
84
  compressedDataAllocator: nil,
80
85
  outputCallback: Self.compressionCallback,
@@ -87,6 +92,7 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
87
92
 
88
93
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanTrue)
89
94
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowFrameReordering, value: kCFBooleanFalse)
95
+ VTSessionSetProperty(session, key: kVTCompressionPropertyKey_MaxFrameDelayCount, value: NSNumber(value: 1))
90
96
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_ProfileLevel, value: kVTProfileLevel_H264_Baseline_AutoLevel)
91
97
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_MaxKeyFrameInterval, value: NSNumber(value: fps))
92
98
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, value: NSNumber(value: 1.0))
@@ -111,12 +117,18 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
111
117
  func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) {
112
118
  guard type == .screen,
113
119
  CMSampleBufferDataIsReady(sampleBuffer),
114
- isCompleteFrame(sampleBuffer),
115
120
  let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer),
116
121
  let session = compressionSession else {
117
122
  return
118
123
  }
119
124
 
125
+ sampleCount += 1
126
+ guard isCompleteFrame(sampleBuffer) else {
127
+ skippedCount += 1
128
+ logCaptureProgressIfNeeded()
129
+ return
130
+ }
131
+
120
132
  frameCount += 1
121
133
  let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
122
134
  let duration = CMTime(value: 1, timescale: CMTimeScale(fps))
@@ -139,6 +151,7 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
139
151
  if status != noErr && (frameCount == 1 || frameCount % 120 == 0) {
140
152
  fputs("LiveDeskSCK encode status=\(status) frames=\(frameCount)\n", stderr)
141
153
  }
154
+ logCaptureProgressIfNeeded()
142
155
  }
143
156
 
144
157
  func stream(_ stream: SCStream, didStopWithError error: Error) {
@@ -155,12 +168,20 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
155
168
  return rawStatus == SCFrameStatus.complete.rawValue
156
169
  }
157
170
 
171
+ private func logCaptureProgressIfNeeded() {
172
+ let interval = max(1, fps * 5)
173
+ if sampleCount == 1 || sampleCount % interval == 0 {
174
+ fputs("LiveDeskSCK capture samples=\(sampleCount) complete=\(frameCount) skipped=\(skippedCount)\n", stderr)
175
+ }
176
+ }
177
+
158
178
  private func writeEncodedSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
159
179
  guard let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else {
160
180
  return
161
181
  }
162
182
 
163
183
  var output = Data()
184
+ appendAccessUnitDelimiter(to: &output)
164
185
  if isKeyFrame(sampleBuffer), let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) {
165
186
  appendParameterSet(formatDescription, index: 0, to: &output)
166
187
  appendParameterSet(formatDescription, index: 1, to: &output)
@@ -241,6 +262,11 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
241
262
  private func appendStartCode(to output: inout Data) {
242
263
  output.append(contentsOf: [0, 0, 0, 1])
243
264
  }
265
+
266
+ private func appendAccessUnitDelimiter(to output: inout Data) {
267
+ appendStartCode(to: &output)
268
+ output.append(contentsOf: [0x09, 0xF0])
269
+ }
244
270
  }
245
271
 
246
272
  enum LiveDeskSCKError: Error {
@@ -17,7 +17,9 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
17
17
  private let writeLock = NSLock()
18
18
  private var stream: SCStream?
19
19
  private var compressionSession: VTCompressionSession?
20
+ private var sampleCount: Int = 0
20
21
  private var frameCount: Int = 0
22
+ private var skippedCount: Int = 0
21
23
  private var encodedCount: Int = 0
22
24
 
23
25
  init(displayIndex: Int, width: Int, height: Int, fps: Int, bitrateKbps: Int) {
@@ -52,7 +54,7 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
52
54
  configuration.width = width
53
55
  configuration.height = height
54
56
  configuration.minimumFrameInterval = CMTime(value: 1, timescale: CMTimeScale(fps))
55
- configuration.queueDepth = 1
57
+ configuration.queueDepth = 3
56
58
  configuration.showsCursor = false
57
59
  configuration.pixelFormat = kCVPixelFormatType_32BGRA
58
60
 
@@ -69,12 +71,15 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
69
71
 
70
72
  private func createCompressionSession() throws {
71
73
  var session: VTCompressionSession?
74
+ let encoderSpecification: [CFString: Any] = [
75
+ kVTVideoEncoderSpecification_EnableHardwareAcceleratedVideoEncoder: true
76
+ ]
72
77
  let status = VTCompressionSessionCreate(
73
78
  allocator: kCFAllocatorDefault,
74
79
  width: Int32(width),
75
80
  height: Int32(height),
76
81
  codecType: kCMVideoCodecType_H264,
77
- encoderSpecification: nil,
82
+ encoderSpecification: encoderSpecification as CFDictionary,
78
83
  imageBufferAttributes: nil,
79
84
  compressedDataAllocator: nil,
80
85
  outputCallback: Self.compressionCallback,
@@ -87,6 +92,7 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
87
92
 
88
93
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_RealTime, value: kCFBooleanTrue)
89
94
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_AllowFrameReordering, value: kCFBooleanFalse)
95
+ VTSessionSetProperty(session, key: kVTCompressionPropertyKey_MaxFrameDelayCount, value: NSNumber(value: 1))
90
96
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_ProfileLevel, value: kVTProfileLevel_H264_Baseline_AutoLevel)
91
97
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_MaxKeyFrameInterval, value: NSNumber(value: fps))
92
98
  VTSessionSetProperty(session, key: kVTCompressionPropertyKey_MaxKeyFrameIntervalDuration, value: NSNumber(value: 1.0))
@@ -111,12 +117,18 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
111
117
  func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) {
112
118
  guard type == .screen,
113
119
  CMSampleBufferDataIsReady(sampleBuffer),
114
- isCompleteFrame(sampleBuffer),
115
120
  let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer),
116
121
  let session = compressionSession else {
117
122
  return
118
123
  }
119
124
 
125
+ sampleCount += 1
126
+ guard isCompleteFrame(sampleBuffer) else {
127
+ skippedCount += 1
128
+ logCaptureProgressIfNeeded()
129
+ return
130
+ }
131
+
120
132
  frameCount += 1
121
133
  let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
122
134
  let duration = CMTime(value: 1, timescale: CMTimeScale(fps))
@@ -139,6 +151,7 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
139
151
  if status != noErr && (frameCount == 1 || frameCount % 120 == 0) {
140
152
  fputs("LiveDeskSCK encode status=\(status) frames=\(frameCount)\n", stderr)
141
153
  }
154
+ logCaptureProgressIfNeeded()
142
155
  }
143
156
 
144
157
  func stream(_ stream: SCStream, didStopWithError error: Error) {
@@ -155,12 +168,20 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
155
168
  return rawStatus == SCFrameStatus.complete.rawValue
156
169
  }
157
170
 
171
+ private func logCaptureProgressIfNeeded() {
172
+ let interval = max(1, fps * 5)
173
+ if sampleCount == 1 || sampleCount % interval == 0 {
174
+ fputs("LiveDeskSCK capture samples=\(sampleCount) complete=\(frameCount) skipped=\(skippedCount)\n", stderr)
175
+ }
176
+ }
177
+
158
178
  private func writeEncodedSampleBuffer(_ sampleBuffer: CMSampleBuffer) {
159
179
  guard let blockBuffer = CMSampleBufferGetDataBuffer(sampleBuffer) else {
160
180
  return
161
181
  }
162
182
 
163
183
  var output = Data()
184
+ appendAccessUnitDelimiter(to: &output)
164
185
  if isKeyFrame(sampleBuffer), let formatDescription = CMSampleBufferGetFormatDescription(sampleBuffer) {
165
186
  appendParameterSet(formatDescription, index: 0, to: &output)
166
187
  appendParameterSet(formatDescription, index: 1, to: &output)
@@ -241,6 +262,11 @@ final class LiveDeskScreenCaptureKitEncoder: NSObject, SCStreamOutput, SCStreamD
241
262
  private func appendStartCode(to output: inout Data) {
242
263
  output.append(contentsOf: [0, 0, 0, 1])
243
264
  }
265
+
266
+ private func appendAccessUnitDelimiter(to output: inout Data) {
267
+ appendStartCode(to: &output)
268
+ output.append(contentsOf: [0x09, 0xF0])
269
+ }
244
270
  }
245
271
 
246
272
  enum LiveDeskSCKError: Error {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@livedesk/client",
3
- "version": "0.1.93",
3
+ "version": "0.1.95",
4
4
  "description": "LiveDesk local remote client",
5
5
  "type": "module",
6
6
  "bin": {