edge-impulse-linux 1.18.3 → 1.20.1
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/build/cli/linux/linux.js +17 -6
- package/build/cli/linux/linux.js.map +1 -1
- package/build/cli/linux/runner-downloader.d.ts +0 -1
- package/build/cli/linux/runner-downloader.js +5 -11
- package/build/cli/linux/runner-downloader.js.map +1 -1
- package/build/cli/linux/runner-profiling.d.ts +6 -4
- package/build/cli/linux/runner-profiling.js +167 -37
- package/build/cli/linux/runner-profiling.js.map +1 -1
- package/build/cli/linux/runner.js +69 -56
- package/build/cli/linux/runner.js.map +1 -1
- package/build/library/sensors/gstreamer.d.ts +10 -3
- package/build/library/sensors/gstreamer.js +219 -52
- package/build/library/sensors/gstreamer.js.map +1 -1
- package/build/library/sensors/icamera.d.ts +21 -1
- package/build/library/sensors/imagesnap.d.ts +3 -2
- package/build/library/sensors/imagesnap.js +18 -1
- package/build/library/sensors/imagesnap.js.map +1 -1
- package/build/library/sensors/prophesee.d.ts +2 -2
- package/build/library/sensors/sensors-helper.d.ts +6 -1
- package/build/library/sensors/sensors-helper.js +32 -9
- package/build/library/sensors/sensors-helper.js.map +1 -1
- package/build/sdk/studio/sdk/api/adminApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/adminApi.js +4782 -4928
- package/build/sdk/studio/sdk/api/adminApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/authApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/authApi.js +88 -56
- package/build/sdk/studio/sdk/api/authApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/cDNApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/cDNApi.js +76 -53
- package/build/sdk/studio/sdk/api/cDNApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/canaryApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/canaryApi.js +79 -53
- package/build/sdk/studio/sdk/api/canaryApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/classifyApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/classifyApi.js +527 -499
- package/build/sdk/studio/sdk/api/classifyApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/dSPApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/dSPApi.js +938 -942
- package/build/sdk/studio/sdk/api/dSPApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/deploymentApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/deploymentApi.js +680 -603
- package/build/sdk/studio/sdk/api/deploymentApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/devicesApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/devicesApi.js +802 -800
- package/build/sdk/studio/sdk/api/devicesApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/emailVerificationApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/emailVerificationApi.js +184 -190
- package/build/sdk/studio/sdk/api/emailVerificationApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/exportApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/exportApi.js +88 -56
- package/build/sdk/studio/sdk/api/exportApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/featureFlagsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/featureFlagsApi.js +76 -52
- package/build/sdk/studio/sdk/api/featureFlagsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/healthApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/healthApi.js +111 -97
- package/build/sdk/studio/sdk/api/healthApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/impulseApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/impulseApi.js +942 -902
- package/build/sdk/studio/sdk/api/impulseApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/integrationsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/integrationsApi.js +136 -106
- package/build/sdk/studio/sdk/api/integrationsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/jobsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/jobsApi.js +2270 -2326
- package/build/sdk/studio/sdk/api/jobsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/learnApi.d.ts +22 -6
- package/build/sdk/studio/sdk/api/learnApi.js +1597 -1424
- package/build/sdk/studio/sdk/api/learnApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/loginApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/loginApi.js +112 -98
- package/build/sdk/studio/sdk/api/loginApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/metricsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/metricsApi.js +148 -144
- package/build/sdk/studio/sdk/api/metricsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/optimizationApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/optimizationApi.js +844 -844
- package/build/sdk/studio/sdk/api/optimizationApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationBlocksApi.d.ts +8 -6
- package/build/sdk/studio/sdk/api/organizationBlocksApi.js +1974 -1548
- package/build/sdk/studio/sdk/api/organizationBlocksApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationCreateProjectApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationCreateProjectApi.js +700 -652
- package/build/sdk/studio/sdk/api/organizationCreateProjectApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationDataApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationDataApi.js +2074 -1985
- package/build/sdk/studio/sdk/api/organizationDataApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationDataCampaignsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationDataCampaignsApi.js +626 -602
- package/build/sdk/studio/sdk/api/organizationDataCampaignsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationJobsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationJobsApi.js +417 -399
- package/build/sdk/studio/sdk/api/organizationJobsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationPipelinesApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationPipelinesApi.js +419 -401
- package/build/sdk/studio/sdk/api/organizationPipelinesApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationPortalsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationPortalsApi.js +372 -352
- package/build/sdk/studio/sdk/api/organizationPortalsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/organizationsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/organizationsApi.js +4024 -4050
- package/build/sdk/studio/sdk/api/organizationsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/performanceCalibrationApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/performanceCalibrationApi.js +586 -560
- package/build/sdk/studio/sdk/api/performanceCalibrationApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/postProcessingApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/postProcessingApi.js +279 -255
- package/build/sdk/studio/sdk/api/postProcessingApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/projectsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/projectsApi.js +2758 -2818
- package/build/sdk/studio/sdk/api/projectsApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/rawDataApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/rawDataApi.js +3055 -3131
- package/build/sdk/studio/sdk/api/rawDataApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/testApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/testApi.js +152 -108
- package/build/sdk/studio/sdk/api/testApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/themesApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/themesApi.js +341 -305
- package/build/sdk/studio/sdk/api/themesApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/thirdPartyAuthApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/thirdPartyAuthApi.js +387 -353
- package/build/sdk/studio/sdk/api/thirdPartyAuthApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/uploadPortalApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/uploadPortalApi.js +375 -355
- package/build/sdk/studio/sdk/api/uploadPortalApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/userApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/userApi.js +2345 -2452
- package/build/sdk/studio/sdk/api/userApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/vlmApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/vlmApi.js +277 -253
- package/build/sdk/studio/sdk/api/vlmApi.js.map +1 -1
- package/build/sdk/studio/sdk/api/whitelabelsApi.d.ts +4 -6
- package/build/sdk/studio/sdk/api/whitelabelsApi.js +408 -398
- package/build/sdk/studio/sdk/api/whitelabelsApi.js.map +1 -1
- package/build/sdk/studio/sdk/model/addOrganizationDeployBlockRequest.d.ts +4 -0
- package/build/sdk/studio/sdk/model/addOrganizationDeployBlockRequest.js +5 -0
- package/build/sdk/studio/sdk/model/addOrganizationDeployBlockRequest.js.map +1 -1
- package/build/sdk/studio/sdk/model/buildOnDeviceModelRequest.d.ts +6 -0
- package/build/sdk/studio/sdk/model/buildOnDeviceModelRequest.js +5 -0
- package/build/sdk/studio/sdk/model/buildOnDeviceModelRequest.js.map +1 -1
- package/build/sdk/studio/sdk/model/buildOrganizationOnDeviceModelRequest.d.ts +6 -0
- package/build/sdk/studio/sdk/model/buildOrganizationOnDeviceModelRequest.js +5 -0
- package/build/sdk/studio/sdk/model/buildOrganizationOnDeviceModelRequest.js.map +1 -1
- package/build/sdk/studio/sdk/model/deployPretrainedModelRequest.d.ts +4 -0
- package/build/sdk/studio/sdk/model/deployPretrainedModelRequest.js +5 -0
- package/build/sdk/studio/sdk/model/deployPretrainedModelRequest.js.map +1 -1
- package/build/sdk/studio/sdk/model/deploymentTarget.d.ts +2 -0
- package/build/sdk/studio/sdk/model/deploymentTarget.js +5 -0
- package/build/sdk/studio/sdk/model/deploymentTarget.js.map +1 -1
- package/build/sdk/studio/sdk/model/models.d.ts +47 -7
- package/build/sdk/studio/sdk/model/models.js +33 -22
- package/build/sdk/studio/sdk/model/models.js.map +1 -1
- package/build/sdk/studio/sdk/model/organizationDeployBlock.d.ts +9 -0
- package/build/sdk/studio/sdk/model/organizationDeployBlock.js +10 -0
- package/build/sdk/studio/sdk/model/organizationDeployBlock.js.map +1 -1
- package/build/sdk/studio/sdk/model/projectDeploymentTarget.d.ts +2 -0
- package/build/sdk/studio/sdk/model/projectDeploymentTarget.js +5 -0
- package/build/sdk/studio/sdk/model/projectDeploymentTarget.js.map +1 -1
- package/build/sdk/studio/sdk/model/transferLearningModel.d.ts +4 -0
- package/build/sdk/studio/sdk/model/transferLearningModel.js +5 -0
- package/build/sdk/studio/sdk/model/transferLearningModel.js.map +1 -1
- package/build/sdk/studio/sdk/model/updateOrganizationDeployBlockRequest.d.ts +4 -0
- package/build/sdk/studio/sdk/model/updateOrganizationDeployBlockRequest.js +5 -0
- package/build/sdk/studio/sdk/model/updateOrganizationDeployBlockRequest.js.map +1 -1
- package/build/sdk/studio/sdk/model/uploadPretrainedModelByUrlRequest.d.ts +47 -0
- package/build/sdk/studio/sdk/model/uploadPretrainedModelByUrlRequest.js +55 -0
- package/build/sdk/studio/sdk/model/uploadPretrainedModelByUrlRequest.js.map +1 -0
- package/build/sdk/studio/sdk/model/uploadPretrainedModelRequest.d.ts +4 -0
- package/build/sdk/studio/sdk/model/uploadPretrainedModelRequest.js +5 -0
- package/build/sdk/studio/sdk/model/uploadPretrainedModelRequest.js.map +1 -1
- package/package.json +4 -2
- package/test/gstreamer.test.ts +984 -3788
- package/test/imx219-csi-on-arduino-unoq-inspect.txt +564 -0
- package/test/imx219-csi-on-arduino-unoq-monitor.txt +285 -0
- package/test/logitech-c920-on-ubuntu-22-parallells.txt +211 -0
- package/test/logitech-c922-on-rpi-bullseye-2.txt +270 -0
- package/test/logitech-c922-on-rpi-bullseye.txt +331 -0
- package/test/macbook-pro-w-internal-and-external-cam-inspect.txt +1496 -0
- package/test/macbook-pro-w-internal-and-external-cam-monitor.txt +209 -0
- package/test/nvidia-jetson-w-csi-camera.txt +94 -0
- package/test/nvidia-jetson-w-logitech-c922-monitor.txt +204 -0
- package/test/nvidia-orin-w-basler-camera-inspect.txt +859 -0
- package/test/nvidia-orin-w-basler-camera-pylonsrc.txt +806 -0
- package/test/rb1-debian-inspect.txt +568 -0
- package/test/rb1-debian-libcamera-monitor.txt +190 -0
- package/test/rpi-cam-v3-c920-webcam-bookworm-no-libcamerasrc.txt +383 -0
- package/test/rpi4-trixie-csi-gst-device-monitor.txt +1110 -0
- package/test/rpi4-trixie-csi-gst-inspect.txt +1379 -0
- package/test/rpi5-with-csi-imx500-camera-monitor.txt +3617 -0
- package/test/rpi5-with-csi-imx708-monitor.txt +2277 -0
- package/test/usb-camera-on-rpi-w-image-jpg.txt +130 -0
- /package/test/{qualcomm-rb3-inspect-qtiqmmfsrc.txt → qualcomm-rb3-gen-2-qimp-linux-1-2-with-logitech-brio-inspect-qtiqmmfsrc.txt} +0 -0
- /package/test/{qualcomm-rb3-inspect.txt → qualcomm-rb3-gen-2-qimp-linux-1-2-with-logitech-brio-inspect.txt} +0 -0
- /package/test/{qualcomm-rb3-monitor-brio.txt → qualcomm-rb3-gen-2-qimp-linux-1-2-with-logitech-brio-monitor.txt} +0 -0
- /package/test/{triple-vision-camera-inspect.txt → triple-vision-ai-industrial-camera-inspect.txt} +0 -0
- /package/test/{triple-vision-camera-monitor.txt → triple-vision-ai-industrial-camera-monitor.txt} +0 -0
|
@@ -27,11 +27,15 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
27
27
|
this._isStarted = false;
|
|
28
28
|
this._isRestarting = false;
|
|
29
29
|
this._emitsOriginalSizeImages = false;
|
|
30
|
+
this._lastGstLaunchCommand = '';
|
|
31
|
+
this._imagesReceived = 0;
|
|
32
|
+
this._offset = 0;
|
|
30
33
|
this._verbose = verbose;
|
|
31
34
|
this._customLaunchCommand = options?.customLaunchCommand;
|
|
32
35
|
this._spawnHelper = options?.spawnHelperOverride || spawn_helper_1.spawnHelper;
|
|
33
36
|
this._modeOverride = options?.modeOverride;
|
|
34
37
|
this._profiling = options?.profiling || false;
|
|
38
|
+
this._overrideColorFormat = options?.colorFormat;
|
|
35
39
|
if (options?.dontRunCleanupLoop === true) {
|
|
36
40
|
// skip cleanup loop
|
|
37
41
|
}
|
|
@@ -57,31 +61,43 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
57
61
|
console.log(PREFIX, 'checking for /etc/os-release');
|
|
58
62
|
osRelease = await fs_1.default.promises.readFile('/etc/os-release', 'utf-8');
|
|
59
63
|
}
|
|
64
|
+
else {
|
|
65
|
+
// so we don't need to check for undefined below
|
|
66
|
+
osRelease = '';
|
|
67
|
+
}
|
|
60
68
|
let firmwareModel;
|
|
61
69
|
// using /proc/device-tree as recommended in user space.
|
|
62
70
|
if (await this.exists('/proc/device-tree/model')) {
|
|
63
71
|
firmwareModel = await fs_1.default.promises.readFile('/proc/device-tree/model', 'utf-8');
|
|
64
72
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (osRelease.indexOf('ID=raspbian') > -1) {
|
|
69
|
-
this._mode = 'rpi';
|
|
70
|
-
}
|
|
71
|
-
if (firmwareModel && firmwareModel.indexOf('Raspberry Pi') > -1) {
|
|
72
|
-
this._mode = 'rpi';
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
if (firmwareModel && firmwareModel.indexOf('Microchip SAMA7G5') > -1) {
|
|
77
|
-
this._mode = 'microchip';
|
|
73
|
+
else {
|
|
74
|
+
// so we don't need to check for undefined below
|
|
75
|
+
firmwareModel = '';
|
|
78
76
|
}
|
|
79
|
-
|
|
77
|
+
if (firmwareModel.indexOf('RB3gen2') > -1 && firmwareModel.indexOf('vision') > -1) {
|
|
80
78
|
this._mode = 'qualcomm-rb3gen2';
|
|
81
79
|
}
|
|
82
|
-
else if (firmwareModel
|
|
80
|
+
else if (firmwareModel.indexOf('Qualcomm') > -1 && firmwareModel.indexOf('Yupik') > -1) {
|
|
83
81
|
this._mode = 'qualcomm-yupik';
|
|
84
82
|
}
|
|
83
|
+
else if (firmwareModel.indexOf('Raspberry Pi') > -1) {
|
|
84
|
+
if (((osRelease.indexOf('bullseye') > -1) || (osRelease.indexOf('bookworm') > -1))
|
|
85
|
+
&& (osRelease.indexOf('ID=raspbian') === -1)) {
|
|
86
|
+
this._mode = 'rpi';
|
|
87
|
+
}
|
|
88
|
+
else if (osRelease.indexOf('trixie') > -1) {
|
|
89
|
+
this._mode = 'rpi';
|
|
90
|
+
}
|
|
91
|
+
// override to rpi5 if needed
|
|
92
|
+
if (firmwareModel.indexOf('Raspberry Pi 5') > -1) {
|
|
93
|
+
this._mode = 'rpi5';
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
else if ((firmwareModel.indexOf('Arduino') > -1 && firmwareModel.indexOf('Imola') > -1) ||
|
|
97
|
+
// this may be incorrect on the another platforms in the future
|
|
98
|
+
(process.env.EI_CLI_ENV === 'arduino')) {
|
|
99
|
+
this._mode = 'unoq';
|
|
100
|
+
}
|
|
85
101
|
this._mode = (this._modeOverride) ? this._modeOverride : this._mode;
|
|
86
102
|
}
|
|
87
103
|
async listDevices() {
|
|
@@ -141,6 +157,8 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
141
157
|
args.push(`-v`);
|
|
142
158
|
}
|
|
143
159
|
args.push(pipeline);
|
|
160
|
+
// for logging purposes
|
|
161
|
+
this._lastGstLaunchCommand = `${command} ${args.join(' ')}`;
|
|
144
162
|
if (this._verbose) {
|
|
145
163
|
console.log(PREFIX, `Starting ${command} ${args.join(' ')}`);
|
|
146
164
|
}
|
|
@@ -154,11 +172,77 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
154
172
|
if (this._verbose) {
|
|
155
173
|
console.log(PREFIX, d.toString('utf-8'));
|
|
156
174
|
}
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
175
|
+
const ts = new Date();
|
|
176
|
+
const parsePtsFromLine = (line) => {
|
|
177
|
+
const m = line.match(/pts: ([\d\.\:]+)/);
|
|
178
|
+
if (m && m.length >= 2) {
|
|
179
|
+
return m[1];
|
|
180
|
+
}
|
|
181
|
+
return null;
|
|
182
|
+
};
|
|
183
|
+
const parseOffsetFromLine = (line) => {
|
|
184
|
+
const m = line.match(/offset: (-?[\d\.\:]+)/);
|
|
185
|
+
if (m && m.length >= 2) {
|
|
186
|
+
return Number(m[1]);
|
|
187
|
+
}
|
|
188
|
+
return null;
|
|
189
|
+
};
|
|
190
|
+
const str = d.toString('utf-8');
|
|
191
|
+
for (const line of str.split('\n')) {
|
|
192
|
+
if (line.trim().startsWith('/GstPipeline:pipeline0/GstIdentity:')) {
|
|
193
|
+
// identity elements
|
|
194
|
+
const pts = parsePtsFromLine(line);
|
|
195
|
+
let offset = parseOffsetFromLine(line);
|
|
196
|
+
const identity = line.replace('/GstPipeline:pipeline0/GstIdentity:', '').split(' ')[0]
|
|
197
|
+
.replace(':', '');
|
|
198
|
+
// no pts -> skip
|
|
199
|
+
if (!pts) {
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
// frame_ready w/o offset -> also skip
|
|
203
|
+
if (identity === 'frame_ready') {
|
|
204
|
+
if (offset === null) {
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
// e.g. qtiqmmfsrc always has offset -1 for frame_ready
|
|
208
|
+
if (offset === -1) {
|
|
209
|
+
offset = ++this._offset;
|
|
210
|
+
}
|
|
211
|
+
this.emit('profilingInfo', {
|
|
212
|
+
type: 'frame_ready',
|
|
213
|
+
ts: ts,
|
|
214
|
+
pts: pts,
|
|
215
|
+
offset: offset,
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
this.emit('profilingInfo', {
|
|
220
|
+
type: 'event-without-filename',
|
|
221
|
+
ts: ts,
|
|
222
|
+
name: identity,
|
|
223
|
+
pts: pts,
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
else if (line.includes('GstMultiFileSink, filename=')) {
|
|
228
|
+
let filenameM = line.match(/filename=\(string\)([\w\.]+)/);
|
|
229
|
+
if (!filenameM || filenameM.length < 2) {
|
|
230
|
+
console.log(PREFIX, `Failed to parse filename from GstMultiFileSink: ` + line.trim());
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
let timestampM = line.match(/timestamp=\(guint64\)(\d+)/);
|
|
234
|
+
if (!timestampM || timestampM.length < 2) {
|
|
235
|
+
console.log(PREFIX, `Failed to parse timestamp from GstMultiFileSink: ` + line.trim());
|
|
236
|
+
continue;
|
|
237
|
+
}
|
|
238
|
+
let filename = filenameM[1];
|
|
239
|
+
let pts = this.timestampNsToPts(timestampM[1]);
|
|
240
|
+
this.emit('profilingInfo', {
|
|
241
|
+
type: 'pts-to-filename',
|
|
242
|
+
pts: pts,
|
|
243
|
+
filename: filename,
|
|
244
|
+
});
|
|
245
|
+
}
|
|
162
246
|
}
|
|
163
247
|
});
|
|
164
248
|
this._captureProcess.stderr.on('data', (d) => {
|
|
@@ -185,6 +269,7 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
185
269
|
return;
|
|
186
270
|
if (this._handledFiles[fileName])
|
|
187
271
|
return;
|
|
272
|
+
this._imagesReceived++;
|
|
188
273
|
// not next frame yet?
|
|
189
274
|
if (this._processing || Date.now() < nextFrame) {
|
|
190
275
|
this._handledFiles[fileName] = true;
|
|
@@ -226,11 +311,12 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
226
311
|
if (this._keepAliveTimeout) {
|
|
227
312
|
clearTimeout(this._keepAliveTimeout);
|
|
228
313
|
}
|
|
314
|
+
const tempDir = this._tempDir;
|
|
229
315
|
try {
|
|
230
316
|
let [imgBuffer, originalImgBuffer] = await Promise.all([
|
|
231
|
-
fs_1.default.promises.readFile(path_1.default.join(
|
|
317
|
+
fs_1.default.promises.readFile(path_1.default.join(tempDir, fileName)),
|
|
232
318
|
this._emitsOriginalSizeImages ?
|
|
233
|
-
fs_1.default.promises.readFile(path_1.default.join(
|
|
319
|
+
fs_1.default.promises.readFile(path_1.default.join(tempDir, originalName)) :
|
|
234
320
|
null,
|
|
235
321
|
]);
|
|
236
322
|
// hash not changed? don't emit another event (streamer does this on Rpi)
|
|
@@ -259,9 +345,8 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
259
345
|
};
|
|
260
346
|
}
|
|
261
347
|
catch (ex) {
|
|
262
|
-
console.error(PREFIX, 'Failed to load file', path_1.default.join(
|
|
348
|
+
console.error(PREFIX, 'Failed to load file', path_1.default.join(tempDir, fileName), ex);
|
|
263
349
|
}
|
|
264
|
-
const tempDir = this._tempDir;
|
|
265
350
|
await Promise.all([
|
|
266
351
|
(async () => {
|
|
267
352
|
await this.safeUnlinkFile(path_1.default.join(tempDir, fileName));
|
|
@@ -304,7 +389,13 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
304
389
|
return;
|
|
305
390
|
}
|
|
306
391
|
else {
|
|
307
|
-
|
|
392
|
+
if (this._imagesReceived === 0 && this._lastGstLaunchCommand) {
|
|
393
|
+
reject(`Capture process failed with code ${code}\n\n` +
|
|
394
|
+
`command: ${this._lastGstLaunchCommand}`);
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
reject('Capture process failed with code ' + code);
|
|
398
|
+
}
|
|
308
399
|
}
|
|
309
400
|
}
|
|
310
401
|
else {
|
|
@@ -358,15 +449,14 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
358
449
|
let customArgs = (0, argv_split_1.split)(this._customLaunchCommand);
|
|
359
450
|
customArgs = customArgs.concat([
|
|
360
451
|
`!`,
|
|
361
|
-
`multifilesink`,
|
|
362
|
-
`location=resized%05d.jpg`
|
|
452
|
+
`multifilesink location=resized%05d.jpg post-messages=true sync=false`,
|
|
363
453
|
]);
|
|
364
454
|
return {
|
|
365
455
|
command: 'gst-launch-1.0',
|
|
366
456
|
pipeline: customArgs.join(' '),
|
|
367
457
|
};
|
|
368
458
|
}
|
|
369
|
-
// now we need to determine the resolution... we want something as close as possible to dimensions.
|
|
459
|
+
// now we need to determine the resolution... we want something as close as possible to dimensions.
|
|
370
460
|
let caps = device.caps.filter(c => {
|
|
371
461
|
return c.width >= dimensions.width && c.height >= dimensions.height;
|
|
372
462
|
}).sort((a, b) => {
|
|
@@ -389,24 +479,50 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
389
479
|
framerate: 30,
|
|
390
480
|
};
|
|
391
481
|
}
|
|
392
|
-
let videoSource = [
|
|
393
|
-
if (
|
|
394
|
-
|
|
482
|
+
let videoSource = [];
|
|
483
|
+
if (this._profiling) {
|
|
484
|
+
videoSource.push('-m');
|
|
485
|
+
}
|
|
486
|
+
videoSource.push(device.videoSource);
|
|
487
|
+
if (device.id) {
|
|
488
|
+
videoSource.push(`device=${device.id}`);
|
|
489
|
+
}
|
|
490
|
+
if ((this._mode === 'rpi') || (this._mode === 'rpi5') || device.videoSource === 'libcamerasrc') {
|
|
491
|
+
// libcamera devices don't have id set (or have some unique on Raspberry Pi or Microchip)
|
|
395
492
|
if ((!device.id)
|
|
396
493
|
|| (device.name.indexOf('unicam') > -1)
|
|
397
494
|
|| (device.name.indexOf('bcm2835-isp') > -1)) {
|
|
398
|
-
videoSource = [
|
|
495
|
+
videoSource = [
|
|
496
|
+
...(this._profiling ? ['-m'] : []),
|
|
497
|
+
'libcamerasrc',
|
|
498
|
+
...device.name ? ['camera-name="' + device.name + '"'] : [],
|
|
499
|
+
];
|
|
399
500
|
const hasPlugin = await this.hasGstPlugin('libcamerasrc');
|
|
400
501
|
if (!hasPlugin) {
|
|
401
502
|
throw new Error('Missing "libcamerasrc" gstreamer element. Install via `sudo apt install -y gstreamer1.0-libcamera`');
|
|
402
503
|
}
|
|
403
504
|
}
|
|
505
|
+
// FIXME: dirty hack for IPASoft on QRB2210
|
|
506
|
+
// Some resolutions reported by camera causes the pipeline to hang. To fix that, it seems
|
|
507
|
+
// we need to increase width and/or height by 8 pixels. This hack should be removed once
|
|
508
|
+
// the hardware driver for ISP on QRB2210 is released.
|
|
509
|
+
if (this._mode === 'unoq') {
|
|
510
|
+
cap.width += 8;
|
|
511
|
+
}
|
|
404
512
|
}
|
|
405
513
|
else if ((this._mode === 'qualcomm-rb3gen2') || (this._mode === 'qualcomm-yupik')) {
|
|
406
|
-
videoSource = [
|
|
514
|
+
videoSource = [
|
|
515
|
+
...(this._profiling ? ['-m'] : []),
|
|
516
|
+
'qtiqmmfsrc',
|
|
517
|
+
'name=camsrc',
|
|
518
|
+
'camera=' + device.id,
|
|
519
|
+
];
|
|
407
520
|
}
|
|
408
521
|
if (device.id === 'pylonsrc') {
|
|
409
|
-
videoSource = [
|
|
522
|
+
videoSource = [
|
|
523
|
+
...(this._profiling ? ['-m'] : []),
|
|
524
|
+
'pylonsrc',
|
|
525
|
+
];
|
|
410
526
|
}
|
|
411
527
|
let cropArgs = [];
|
|
412
528
|
if (inferenceDims) {
|
|
@@ -437,6 +553,23 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
437
553
|
`video/x-raw,width=${cap.width},height=${cap.height},format=YUY2`
|
|
438
554
|
]);
|
|
439
555
|
}
|
|
556
|
+
else if (this._mode === 'rpi5') {
|
|
557
|
+
// on RPi 5 we need to set color format
|
|
558
|
+
let colorFormat = '';
|
|
559
|
+
if (this._overrideColorFormat) {
|
|
560
|
+
colorFormat = this._overrideColorFormat;
|
|
561
|
+
}
|
|
562
|
+
else if (cap.formats && cap.formats.indexOf('YUY2') > -1) {
|
|
563
|
+
colorFormat = 'YUY2';
|
|
564
|
+
}
|
|
565
|
+
else if (cap.formats) {
|
|
566
|
+
throw new Error('Detected RPi 5 camera. Please provide the color format with `--camera-color-format`, supported formats: ' + cap.formats.join(', '));
|
|
567
|
+
}
|
|
568
|
+
videoSource = videoSource.concat([
|
|
569
|
+
`!`,
|
|
570
|
+
`video/x-raw,width=${cap.width},height=${cap.height},format=${colorFormat}`
|
|
571
|
+
]);
|
|
572
|
+
}
|
|
440
573
|
else {
|
|
441
574
|
videoSource = videoSource.concat([
|
|
442
575
|
`!`,
|
|
@@ -454,12 +587,11 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
454
587
|
`jpegenc`,
|
|
455
588
|
...jpgencDoneArgs,
|
|
456
589
|
`!`,
|
|
457
|
-
`multifilesink`,
|
|
458
|
-
`location=resized%05d.jpg`,
|
|
590
|
+
`multifilesink location=resized%05d.jpg post-messages=true sync=false`,
|
|
459
591
|
]);
|
|
460
592
|
}
|
|
461
593
|
else {
|
|
462
|
-
let original = `t. ! queue ! jpegenc ! multifilesink location=original%05d.jpg`;
|
|
594
|
+
let original = `t. ! queue ! jpegenc ! multifilesink location=original%05d.jpg post-messages=true sync=false`;
|
|
463
595
|
let resized = [
|
|
464
596
|
`t. ! queue`,
|
|
465
597
|
...cropArgs,
|
|
@@ -467,8 +599,7 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
467
599
|
`jpegenc`,
|
|
468
600
|
...jpgencDoneArgs,
|
|
469
601
|
`!`,
|
|
470
|
-
`multifilesink`,
|
|
471
|
-
`location=resized%05d.jpg`,
|
|
602
|
+
`multifilesink location=resized%05d.jpg post-messages=true sync=false`,
|
|
472
603
|
];
|
|
473
604
|
args = videoSource.concat([
|
|
474
605
|
...frameReadyArgs,
|
|
@@ -487,15 +618,14 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
487
618
|
`!`,
|
|
488
619
|
`image/jpeg,width=${cap.width},height=${cap.height}`,
|
|
489
620
|
`!`,
|
|
490
|
-
`multifilesink
|
|
491
|
-
`location=resized%05d.jpg`
|
|
621
|
+
`multifilesink location=resized%05d.jpg post-messages=true sync=false`
|
|
492
622
|
]);
|
|
493
623
|
}
|
|
494
624
|
else if (cap.type === 'nvarguscamerasrc') {
|
|
495
625
|
args = [
|
|
496
626
|
`nvarguscamerasrc ! "video/x-raw(memory:NVMM),width=${cap.width},height=${cap.height}" ! ` +
|
|
497
627
|
`nvvidconv flip-method=0 ! video/x-raw,width=${cap.width},height=${cap.height} ! nvvidconv ! ` +
|
|
498
|
-
`jpegenc ! multifilesink location=resized%05d.jpg`
|
|
628
|
+
`jpegenc ! multifilesink location=resized%05d.jpg post-messages=true sync=false`
|
|
499
629
|
];
|
|
500
630
|
}
|
|
501
631
|
else {
|
|
@@ -604,7 +734,8 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
604
734
|
if (!currDevice)
|
|
605
735
|
continue;
|
|
606
736
|
if (l.startsWith('name :')) {
|
|
607
|
-
|
|
737
|
+
// extract name from the l between 'name : ' and '\n', because name may contain colons as well
|
|
738
|
+
currDevice.name = l.split(':').slice(1).join(':').trim();
|
|
608
739
|
continue;
|
|
609
740
|
}
|
|
610
741
|
if (l.startsWith('class :')) {
|
|
@@ -639,6 +770,12 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
639
770
|
if (currDevice.videoSource === 'pipewiresrc') {
|
|
640
771
|
currDevice.videoSource = DEFAULT_GST_VIDEO_SOURCE;
|
|
641
772
|
}
|
|
773
|
+
if (currDevice.videoSource === 'avfvideosrc') {
|
|
774
|
+
const m = l.match(/gst-launch-1.0 avfvideosrc device-index=(\d+) \!/);
|
|
775
|
+
if (m && m.length >= 2) {
|
|
776
|
+
currDevice.videoSource = `avfvideosrc device-index=${m[1]}`;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
642
779
|
}
|
|
643
780
|
}
|
|
644
781
|
}
|
|
@@ -650,6 +787,7 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
650
787
|
let width = (l.match(/width=[^\d]+(\d+)/) || [])[1];
|
|
651
788
|
let height = (l.match(/height=[^\d]+(\d+)/) || [])[1];
|
|
652
789
|
let framerate = (l.match(/framerate=[^\d]+(\d+)/) || [])[1];
|
|
790
|
+
let format = (l.match(/format=([a-zA-Z0-9]+)/) || [])[1];
|
|
653
791
|
// Rpi on bullseye has lines like this..
|
|
654
792
|
// eslint-disable-next-line @stylistic/max-len
|
|
655
793
|
// image/jpeg, width=160, height=120, pixel-aspect-ratio=1/1, framerate={ (fraction)30/1, (fraction)24/1, (fraction)20/1, (fraction)15/1, (fraction)10/1, (fraction)15/2, (fraction)5/1 }
|
|
@@ -667,10 +805,11 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
667
805
|
width: Number(width || '0'),
|
|
668
806
|
height: Number(height || '0'),
|
|
669
807
|
framerate: Number(framerate || '0'),
|
|
808
|
+
formats: format ? [format] : []
|
|
670
809
|
};
|
|
671
810
|
return r;
|
|
672
811
|
});
|
|
673
|
-
if (this._mode === 'rpi' || this._mode === '
|
|
812
|
+
if (this._mode === 'rpi' || this._mode === 'rpi5' || d.videoSource === 'libcamerasrc') { // no framerate here...
|
|
674
813
|
c = c.filter(x => x.width && x.height);
|
|
675
814
|
}
|
|
676
815
|
else if (d.name === 'RZG2L_CRU') {
|
|
@@ -688,14 +827,23 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
688
827
|
else {
|
|
689
828
|
c = c.filter(x => x.width && x.height && x.framerate);
|
|
690
829
|
}
|
|
830
|
+
// get list of all formats form the c list
|
|
831
|
+
const uniqueFormats = Array.from(new Set(c.map(cap => cap.formats).flat()));
|
|
691
832
|
c = c.reduce((curr, o) => {
|
|
692
|
-
// deduplicate caps
|
|
693
|
-
|
|
833
|
+
// deduplicate caps, prioritize 'video/x-raw' type
|
|
834
|
+
const existingIndex = curr.findIndex(obj => obj.framerate === o.framerate &&
|
|
694
835
|
obj.width === o.width &&
|
|
695
|
-
obj.height === o.height
|
|
696
|
-
|
|
836
|
+
obj.height === o.height);
|
|
837
|
+
// store all supported formats (YUY2 etc.)
|
|
838
|
+
if (uniqueFormats) {
|
|
839
|
+
o.formats = uniqueFormats.filter((format) => format !== undefined);
|
|
840
|
+
}
|
|
841
|
+
if (existingIndex === -1) {
|
|
697
842
|
curr.push(o);
|
|
698
843
|
}
|
|
844
|
+
else if (o.type === 'video/x-raw' && curr[existingIndex].type !== 'video/x-raw') {
|
|
845
|
+
curr[existingIndex] = o;
|
|
846
|
+
}
|
|
699
847
|
return curr;
|
|
700
848
|
}, []);
|
|
701
849
|
d.caps = c;
|
|
@@ -712,7 +860,7 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
712
860
|
// Qualcomm has their own plugin, query its too
|
|
713
861
|
// because listQtiqmmsrc* returns hardcoded devices ONLY if a specific gst plugin
|
|
714
862
|
// is available we need to detect device type before, as it may be RubikPi, RB3Gen2 or
|
|
715
|
-
// any other with IMSDK loaded and
|
|
863
|
+
// any other with IMSDK loaded and unknown cameras
|
|
716
864
|
if (this._mode === 'qualcomm-rb3gen2') {
|
|
717
865
|
devices = devices.concat(await this.listQtiqmmsrcDevices());
|
|
718
866
|
}
|
|
@@ -730,10 +878,18 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
730
878
|
videoSource: d.videoSource,
|
|
731
879
|
};
|
|
732
880
|
});
|
|
733
|
-
// deduplicate (by id)
|
|
881
|
+
// deduplicate (by id if present, otherwise by name)
|
|
734
882
|
mapped = mapped.reduce((curr, m) => {
|
|
735
|
-
if (
|
|
736
|
-
|
|
883
|
+
if (m.id) {
|
|
884
|
+
if (curr.find(x => x.id === m.id)) {
|
|
885
|
+
return curr;
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
else if (m.name) {
|
|
889
|
+
if (curr.find(x => x.name === m.name && !x.id)) {
|
|
890
|
+
return curr;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
737
893
|
curr.push(m);
|
|
738
894
|
return curr;
|
|
739
895
|
}, []);
|
|
@@ -1235,6 +1391,17 @@ class GStreamer extends tsee_1.EventEmitter {
|
|
|
1235
1391
|
}
|
|
1236
1392
|
}
|
|
1237
1393
|
}
|
|
1394
|
+
timestampNsToPts(nsStr) {
|
|
1395
|
+
const ns = BigInt(nsStr); // important: avoid precision loss
|
|
1396
|
+
const HOUR = 3600000000000n;
|
|
1397
|
+
const MIN = 60000000000n;
|
|
1398
|
+
const SEC = 1000000000n;
|
|
1399
|
+
const h = ns / HOUR;
|
|
1400
|
+
const m = (ns / MIN) % 60n;
|
|
1401
|
+
const s = (ns / SEC) % 60n;
|
|
1402
|
+
const n = ns % SEC;
|
|
1403
|
+
return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}.${n.toString().padStart(9, '0')}`;
|
|
1404
|
+
}
|
|
1238
1405
|
}
|
|
1239
1406
|
exports.GStreamer = GStreamer;
|
|
1240
1407
|
//# sourceMappingURL=gstreamer.js.map
|