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+ }
0 commit comments