Skip to content

Commit 9a717ae

Browse files
committed
Fix libusb crash on macOS
1 parent 9bee16a commit 9a717ae

File tree

12 files changed

+418
-14
lines changed

12 files changed

+418
-14
lines changed

doc/installation_osx.md

100644100755
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,21 @@
22

33
**Note:** macOS support for the full range of functionality offered by the SDK is not yet complete. If you need support for R200 or the ZR300, [legacy librealsense](https://github.com/IntelRealSense/librealsense/tree/legacy) offers a subset of SDK functionality.
44

5+
## macOS 12+ (Monterey) and newer
6+
7+
**sudo** required for USB access. On macOS 12+ most librealsense tools that use libusb must be run with elevated privileges. This is due to macOS USB security changes and overriding the default UVC driver.
8+
```bash
9+
# examples
10+
sudo examples/rs-multicam
11+
sudo examples/rs-enumerate-devices
12+
sudo examples/rs-hello-realsense
13+
sudo examples/rs-depth
14+
```
15+
16+
**Current Limitations:**
17+
- **RealSense Viewer is not supported** on macOS in the current release
18+
- **Motion sensors (IMU) are disabled** on macOS in the current release
19+
520
## Building from Source
621

722
1. Install CommandLineTools `sudo xcode-select --install` or download XCode 6.0+ via the AppStore

examples/C/infrared/CMakeLists.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# License: Apache 2.0. See LICENSE file in root directory.
2+
# Copyright(c) 2024 Intel Corporation. All Rights Reserved.
3+
cmake_minimum_required(VERSION 3.8)
4+
5+
project(RealsenseExamples-Infrared)
6+
7+
# Save the command line compile commands in the build output
8+
set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
9+
10+
add_executable(rs-infrared rs-infrared.c ../example.h)
11+
include_directories(../../C)
12+
target_link_libraries(rs-infrared ${DEPENDENCIES})
13+
set_target_properties (rs-infrared PROPERTIES
14+
FOLDER "Examples/C"
15+
)
16+
17+
install(TARGETS rs-infrared RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

examples/C/infrared/readme.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# rs-infrared Sample
2+
3+
## Overview
4+
This sample demonstrates how to use C API to stream infrared data from both left and right IR cameras and prints a simple text-based representation of the IR images, by breaking them into pixel regions and approximating the intensity levels.
5+
6+
## Key Points
7+
* Demonstrates how to enumerate and differentiate between IR1 (left) and IR2 (right) streams
8+
* Shows how to configure and start infrared streaming with Y8 format
9+
* Provides text-based visualization of IR intensity levels
10+
* Handles multiple IR streams from stereo cameras
11+
12+
## Expected Output
13+
The program will display two text-based representations side by side:
14+
- Left IR camera view
15+
- Right IR camera view
16+
17+
Each view shows intensity levels using ASCII characters where brighter characters represent higher IR intensity.

examples/C/infrared/rs-infrared.c

Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
// License: Apache 2.0. See LICENSE file in root directory.
2+
// Copyright(c) 2017-24 Intel Corporation. All Rights Reserved.
3+
4+
/* Include the librealsense C header files */
5+
#include <librealsense2/rs.h>
6+
#include <librealsense2/h/rs_pipeline.h>
7+
#include <librealsense2/h/rs_option.h>
8+
#include <librealsense2/h/rs_frame.h>
9+
#include "example.h"
10+
11+
#include <stdlib.h>
12+
#include <stdint.h>
13+
#include <stdio.h>
14+
#include <string.h>
15+
#include <signal.h>
16+
17+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
18+
// These parameters are reconfigurable //
19+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
20+
#define STREAM RS2_STREAM_INFRARED // rs2_stream is a types of data provided by RealSense device //
21+
#define FORMAT RS2_FORMAT_Y8 // rs2_format identifies how binary data is encoded within a frame //
22+
#define WIDTH 640 // Defines the number of columns for each frame or zero for auto resolve//
23+
#define HEIGHT 0 // Defines the number of lines for each frame or zero for auto resolve //
24+
#define FPS 30 // Defines the rate of frames per second //
25+
#define STREAM_INDEX_1 1 // Left IR camera index //
26+
#define STREAM_INDEX_2 2 // Right IR camera index //
27+
#define HEIGHT_RATIO 20 // Defines the height ratio between the original frame to the new frame//
28+
#define WIDTH_RATIO 10 // Defines the width ratio between the original frame to the new frame //
29+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
30+
31+
// Global flag to control the main loop
32+
static volatile int running = 1;
33+
34+
// Signal handler for Ctrl+C
35+
void signal_handler(int sig)
36+
{
37+
printf("\nReceived signal %d, stopping stream...\n", sig);
38+
running = 0;
39+
}
40+
41+
int main(void)
42+
{
43+
rs2_error* e = 0;
44+
45+
// Register signal handler for Ctrl+C
46+
signal(SIGINT, signal_handler);
47+
48+
// Create a context object. This object owns the handles to all connected realsense devices.
49+
// The returned object should be released with rs2_delete_context(...)
50+
rs2_context* ctx = rs2_create_context(RS2_API_VERSION, &e);
51+
check_error(e);
52+
53+
/* Get a list of all the connected devices. */
54+
// The returned object should be released with rs2_delete_device_list(...)
55+
rs2_device_list* device_list = rs2_query_devices(ctx, &e);
56+
check_error(e);
57+
58+
int dev_count = rs2_get_device_count(device_list, &e);
59+
check_error(e);
60+
printf("There are %d connected RealSense devices.\n", dev_count);
61+
if (0 == dev_count)
62+
return EXIT_FAILURE;
63+
64+
// Get the first connected device
65+
// The returned object should be released with rs2_delete_device(...)
66+
rs2_device* dev = rs2_create_device(device_list, 0, &e);
67+
check_error(e);
68+
69+
print_device_info(dev);
70+
71+
// Create a pipeline to configure, start and stop camera streaming
72+
// The returned object should be released with rs2_delete_pipeline(...)
73+
rs2_pipeline* pipeline = rs2_create_pipeline(ctx, &e);
74+
check_error(e);
75+
76+
// Create a config instance, used to specify hardware configuration
77+
// The returned object should be released with rs2_delete_config(...)
78+
rs2_config* config = rs2_create_config(&e);
79+
check_error(e);
80+
81+
// Request IR streams - both left (index 1) and right (index 2)
82+
rs2_config_enable_stream(config, STREAM, STREAM_INDEX_1, WIDTH, HEIGHT, FORMAT, FPS, &e);
83+
check_error(e);
84+
rs2_config_enable_stream(config, STREAM, STREAM_INDEX_2, WIDTH, HEIGHT, FORMAT, FPS, &e);
85+
check_error(e);
86+
87+
// Start the pipeline streaming
88+
// The returned object should be released with rs2_delete_pipeline_profile(...)
89+
rs2_pipeline_profile* pipeline_profile = rs2_pipeline_start_with_config(pipeline, config, &e);
90+
if (e)
91+
{
92+
printf("The connected device doesn't support infrared streaming!\n");
93+
exit(EXIT_FAILURE);
94+
}
95+
96+
rs2_stream_profile_list* stream_profile_list = rs2_pipeline_profile_get_streams(pipeline_profile, &e);
97+
if (e)
98+
{
99+
printf("Failed to create stream profile list!\n");
100+
exit(EXIT_FAILURE);
101+
}
102+
103+
// Get stream profiles for both IR cameras
104+
int num_profiles = rs2_get_stream_profiles_count(stream_profile_list, &e);
105+
check_error(e);
106+
107+
printf("Found %d stream profiles\n", num_profiles);
108+
109+
int width = 0, height = 0;
110+
int i;
111+
for (i = 0; i < num_profiles; i++)
112+
{
113+
rs2_stream_profile* stream_profile = (rs2_stream_profile*)rs2_get_stream_profile(stream_profile_list, i, &e);
114+
check_error(e);
115+
116+
rs2_stream stream; rs2_format format; int index; int unique_id; int framerate;
117+
rs2_get_stream_profile_data(stream_profile, &stream, &format, &index, &unique_id, &framerate, &e);
118+
check_error(e);
119+
120+
if (stream == RS2_STREAM_INFRARED)
121+
{
122+
rs2_get_video_stream_resolution(stream_profile, &width, &height, &e);
123+
check_error(e);
124+
printf("IR Stream %d: %dx%d @ %d fps\n", index, width, height, framerate);
125+
}
126+
}
127+
128+
if (width == 0 || height == 0)
129+
{
130+
printf("Failed to get IR stream resolution!\n");
131+
exit(EXIT_FAILURE);
132+
}
133+
134+
int rows = height / HEIGHT_RATIO;
135+
int row_length = width / WIDTH_RATIO;
136+
int display_size = (rows + 1) * (row_length + 1);
137+
138+
char* buffer_left = calloc(display_size, sizeof(char));
139+
char* buffer_right = calloc(display_size, sizeof(char));
140+
141+
printf("Starting IR streaming... Press Ctrl+C to stop\n\n");
142+
143+
while (running) // Until user presses Ctrl+C
144+
{
145+
// This call waits until a new composite_frame is available
146+
// composite_frame holds a set of frames. It is used to prevent frame drops
147+
// The returned object should be released with rs2_release_frame(...)
148+
rs2_frame* frames = rs2_pipeline_wait_for_frames(pipeline, RS2_DEFAULT_TIMEOUT, &e);
149+
check_error(e);
150+
151+
// Returns the number of frames embedded within the composite frame
152+
int num_of_frames = rs2_embedded_frames_count(frames, &e);
153+
check_error(e);
154+
155+
// Process each frame
156+
for (i = 0; i < num_of_frames; ++i)
157+
{
158+
// The returned object should be released with rs2_release_frame(...)
159+
rs2_frame* frame = rs2_extract_frame(frames, i, &e);
160+
check_error(e);
161+
162+
// Get frame profile information
163+
rs2_stream_profile* profile = (rs2_stream_profile*)rs2_get_frame_stream_profile(frame, &e);
164+
check_error(e);
165+
166+
rs2_stream stream; rs2_format format; int index; int unique_id; int framerate;
167+
rs2_get_stream_profile_data(profile, &stream, &format, &index, &unique_id, &framerate, &e);
168+
check_error(e);
169+
170+
// Process only infrared frames
171+
if (stream == RS2_STREAM_INFRARED)
172+
{
173+
/* Retrieve IR data, configured as 8-bit grayscale values */
174+
const uint8_t* ir_frame_data = (const uint8_t*)(rs2_get_frame_data(frame, &e));
175+
check_error(e);
176+
177+
char* buffer = (index == STREAM_INDEX_1) ? buffer_left : buffer_right;
178+
char* out = buffer;
179+
180+
/* Print a simple text-based representation of the IR image */
181+
int x, y, j;
182+
int* intensity = calloc(row_length, sizeof(int));
183+
184+
for (y = 0; y < height; ++y)
185+
{
186+
for (x = 0; x < width; ++x)
187+
{
188+
// Create an intensity histogram for each row
189+
int intensity_index = x / WIDTH_RATIO;
190+
int ir_value = *ir_frame_data++;
191+
intensity[intensity_index] += ir_value;
192+
}
193+
194+
if ((y % HEIGHT_RATIO) == (HEIGHT_RATIO-1))
195+
{
196+
for (j = 0; j < row_length; ++j)
197+
{
198+
// Map intensity to ASCII characters (darker to brighter)
199+
static const char pixels[] = " .:-=+*#%@";
200+
int avg_intensity = intensity[j] / (HEIGHT_RATIO * WIDTH_RATIO);
201+
int pixel_index = (avg_intensity * (sizeof(pixels) - 2)) / 255;
202+
if (pixel_index >= (int)sizeof(pixels) - 1) pixel_index = (int)sizeof(pixels) - 2;
203+
*out++ = pixels[pixel_index];
204+
intensity[j] = 0;
205+
}
206+
*out++ = '\n';
207+
}
208+
}
209+
*out++ = 0;
210+
211+
// Display side by side when we have both frames
212+
if (index == STREAM_INDEX_2) // Right IR frame
213+
{
214+
printf("\033[H\033[J"); // Clear screen
215+
printf("Left IR (Index %d)%*sRight IR (Index %d)\n",
216+
STREAM_INDEX_1, row_length - 15, "", STREAM_INDEX_2);
217+
printf("%s", "=");
218+
for (j = 0; j < row_length; j++) printf("=");
219+
printf("%*s", 5, "");
220+
for (j = 0; j < row_length; j++) printf("=");
221+
printf("\n");
222+
223+
// Print both buffers side by side
224+
char* left_line = buffer_left;
225+
char* right_line = buffer_right;
226+
char* left_next, * right_next;
227+
228+
while (*left_line && *right_line)
229+
{
230+
left_next = strchr(left_line, '\n');
231+
right_next = strchr(right_line, '\n');
232+
233+
if (left_next) *left_next = 0;
234+
if (right_next) *right_next = 0;
235+
236+
printf("%-*s %s\n", row_length, left_line, right_line);
237+
238+
if (left_next)
239+
{
240+
*left_next = '\n';
241+
left_line = left_next + 1;
242+
}
243+
else break;
244+
245+
if (right_next)
246+
{
247+
*right_next = '\n';
248+
right_line = right_next + 1;
249+
}
250+
else break;
251+
}
252+
}
253+
254+
free(intensity);
255+
}
256+
257+
rs2_release_frame(frame);
258+
}
259+
260+
rs2_release_frame(frames);
261+
}
262+
263+
printf("Stopping pipeline...\n");
264+
rs2_pipeline_stop(pipeline, &e);
265+
check_error(e);
266+
267+
free(buffer_left);
268+
free(buffer_right);
269+
270+
// Cleanup
271+
rs2_delete_config(config);
272+
rs2_delete_pipeline(pipeline);
273+
rs2_delete_pipeline_profile(pipeline_profile);
274+
rs2_delete_device(dev);
275+
rs2_delete_device_list(device_list);
276+
rs2_delete_context(ctx);
277+
278+
return EXIT_SUCCESS;
279+
}

examples/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ add_subdirectory(measure)
4747
add_subdirectory(C/depth)
4848
add_subdirectory(C/color)
4949
add_subdirectory(C/distance)
50+
add_subdirectory(C/infrared)
5051
add_subdirectory(post-processing)
5152
add_subdirectory(record-playback)
5253
add_subdirectory(motion)

src/ds/d400/d400-factory.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -791,9 +791,11 @@ namespace librealsense
791791
, firmware_logger_device( dev_info, d400_device::_hw_monitor, get_firmware_logs_command(), get_flash_logs_command() )
792792
{
793793
ds_advanced_mode_base::initialize_advanced_mode( this );
794-
794+
#if !defined(__APPLE__) // Motion sensors not supported on macOS
795795
if( _fw_version >= firmware_version( 5, 16, 0, 0 ) )
796-
register_feature( std::make_shared< gyro_sensitivity_feature >( get_raw_motion_sensor(), get_motion_sensor() ) );
796+
register_feature(
797+
std::make_shared< gyro_sensitivity_feature >( get_raw_motion_sensor(), get_motion_sensor() ) );
798+
#endif
797799
}
798800

799801

@@ -1002,9 +1004,11 @@ namespace librealsense
10021004
, ds_thermal_tracking( d400_device::_thermal_monitor )
10031005
{
10041006
ds_advanced_mode_base::initialize_advanced_mode( this );
1005-
1007+
#if !defined(__APPLE__) // Motion sensors not supported on macOS
10061008
if( _fw_version >= firmware_version( 5, 16, 0, 0 ) )
1007-
register_feature( std::make_shared< gyro_sensitivity_feature >( get_raw_motion_sensor(), get_motion_sensor() ) );
1009+
register_feature(
1010+
std::make_shared< gyro_sensitivity_feature >( get_raw_motion_sensor(), get_motion_sensor() ) );
1011+
#endif
10081012
}
10091013

10101014
std::shared_ptr<matcher> create_matcher(const frame_holder& frame) const override;

0 commit comments

Comments
 (0)