Updated: April 19, 2023 |
Use callback functions to provide custom code to be executed when a specific sensor event occurs.
In general when you're using callback mode to access sensor data or status, do the following:
As the sensor events that you've registered for occur, the Sensor library invokes your callback functions and processes the data as per your callbacks' implementations.
You can register multiple callback functions up to a maximum of sixteen per sensor handle. You can register callback functions for different sensor events, or for the same sensor event. If you register multiple callback functions for one sensor event, then all registered callbacks are invoked when that sensor event occurs.
You can call sensor_register_data_callback() and sensor_register_status_callback() to register callback functions as long as you have a handle to the sensor (from calling sensor_open()). The sensor doesn't have to be started before you can register your callbacks. However if the sensor hasn't started, it's unlikely that there's data available and status changes occurring, so your callback functions are not likely to be invoked.
If you need to pass user-specific information to the callback function, use arg when you register the callback. The Sensor library, when it invokes your callback function, passes this data to it.
Ensure that you release any resources that you still have access to before you disable your callback functions. Once you disable your callback functions from a specified sensor event, the Sensor library no longer invokes the callbacks when that sensor event occurs.
The Sensor library can invoke callback functions to receive data when the following sensor events occur:
When you are using callback functions to access sensor data, any memory allocated for the buffer may be released when the callback completes its execution. In callback mode, you access one buffer at a time when the callback executes. The next buffer is available only when the callback function is invoked again. If your callback function returns false, you may still have access to previous data buffers. However, the publisher may run out of buffers for processing if you aren't releasing buffers in a timely manner.
Define your data callback functions
The implementation of your callback function should take into consideration that it's executed for a specific sensor event and that it's running in a thread that's owned by the Sensor library.
The Sensor library frees the data buffer upon return of your callback function if it returns true; your application no longer has access to this data buffer. If your callback function returns false, then you continue to have access to the data buffer, but you must ensure that you release the buffer by calling sensor_return_buffer() when you are finished using it.
The callback functions that your application provides must have the signature as defined by the function prototype sensor_data_callback_t. For example:
... #define DEFAULT_BUFFERS_CNT 100 #define DEFAULT_CONSUME_LATENCY_US 50 ... static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t condvar = PTHREAD_COND_INITIALIZER; static uint32_t consumeLatency = DEFAULT_CONSUME_LATENCY_US; static int bufCnt = DEFAULT_BUFFERS_CNT; static int receivedBuffers; ... static bool my_sensor_data_callback(sensor_handle_t handle, sensor_buffer_t* buf, void* arg) { pthread_mutex_lock(&mutex); receivedBuffers++; static int64_t last_time = get_time(); uint64_t new_time = get_time(); printf("Received buffer %d (%" PRIu64 "us since previous): time %jd format %d size %" PRIu64 "\n", receivedBuffers, new_time-last_time, buf->timestamp, buf->format, buf->size); last_time = new_time; if (buf->format == SENSOR_FORMAT_VIDEO_NV12) { printf(" NV12: %d x %d stride %d chroma %" PRId64 ", %" PRId64 "\n", buf->info.video_semiplanar.height, buf->info.video_semiplanar.width, buf->info.video_semiplanar.stride, buf->info.video_semiplanar.chroma_stride, buf->info.video_semiplanar.chroma_offset); } else if (buf->format == SENSOR_FORMAT_VIDEO_ROI) { printf(" ROI: %d x %d type %d roi (%d, %d, %d %d) stride (%d, %d, %d) offset (%d %d %d)\n", buf->info.video_roi.width, buf->info.video_roi.height, buf->info.video_roi.type, buf->info.video_roi.roi_x, buf->info.video_roi.roi_y, buf->info.video_roi.roi_width, buf->info.video_roi.roi_height, buf->info.video_roi.stride[0], buf->info.video_roi.stride[1], buf->info.video_roi.stride[2], buf->info.video_roi.offset[0], buf->info.video_roi.offset[1], buf->info.video_roi.offset[2]); } else if (buf->format == SENSOR_FORMAT_LIDAR_POLAR) { printf(" LIDAR POLAR: data_size %" PRIu64 "\n", buf->info.data.data_size); } else if (buf->format == SENSOR_FORMAT_LIDAR_POINT_CLOUD) { printf(" LIDAR POINT CLOUD: data_size %" PRIu64 "\n", buf->info.data.data_size); } else if (buf->format == SENSOR_FORMAT_RADAR_POLAR) { printf(" RADAR POLAR: data_size %" PRIu64 "\n", buf->info.data.data_size); } usleep(consumeLatency); if (receivedBuffers == bufCnt) { // send signal to stop streaming pthread_cond_signal(&condvar); } pthread_mutex_unlock(&mutex); return true; }
Register your data callback functions
When you register your callback function, you must specify the mode by which you are using the data buffers. You can access the buffers in read-only or read-write modes. The read-only allows you to only read the data from the buffer; you can't modify the data in the buffer. The read-write modes allow you to not only read the data from the buffer, but also to modify the data in the buffer. Specify the mode by which you want access to the buffers as one of the sensor_eventmode_t types in the mode parameter of the sensor_register_data_callback() function.
Register your callback functions with the Sensor library by calling sensor_register_data_callback(). For example:
sensor_error_t err; sensor_handle_t handle = NULL; ... err = sensor_register_data_callback(handle, SENSOR_EVENT_STREAM_DATA, SENSOR_EVENTMODE_READONLY, sensor_data_callback, NULL); ...
Disable your data callback functions
When you no longer need your callback functions invoked on a sensor event, disable your callback functions from the Sensor library by calling sensor_disable_data_callback(). For example:
sensor_error_t err; sensor_handle_t handle = NULL; ... err = sensor_disable_data_callback(handle, SENSOR_EVENT_STREAM_DATA, sensor_data_callback); ...
Ensure that you release any resources that you still have access to before you disable your callback functions. Once you disable your callback functions from a specified sensor event, the Sensor library no longer invokes the callbacks when that sensor event occurs.
The Sensor libarary can invoke callback functions to receive status when the following sensor events occur:
Some statuses may have additional information that's related to the event. For these statuses, the Sensor library specifies the additional information to you in the extra parameter of the callback function.
Define your status callback functions
The callback functions that your application provides must have the signature as defined by the function prototype sensor_status_callback_t. For example:
... static void sensor_status_callback(sensor_handle_t handle, sensor_devstatus_t status, uint16_t extra, void* arg) { switch (status) { case SENSOR_STATUS_CONNECTED: printf("Received CONNECTED status\n"); break; case SENSOR_STATUS_STREAMING: printf("Received STREAMING status\n"); break; case SENSOR_STATUS_QUEUE_OVERFLOW: printf("Received QUEUE_OVERFLOW status with extra %d\n", extra); break; case SENSOR_STATUS_STREAMING_ACTIVE: printf("Received STREAMING_ACTIVE status\n"); break; case SENSOR_STATUS_BUFFER_UNDERFLOW: printf("Received BUFFER_UNDERFLOW status\n"); break; case SENSOR_STATUS_STREAMING_ERROR: printf("Received STREAMING_ERROR status\n"); break; case SENSOR_STATUS_BUFFER_AVAILABLE: printf("Received BUFFER_AVAILABLE status\n"); break; default: // Print others that we do not expect printf("Received status event %d extra %d\n", status, extra); break; } } ...
Register your status callback functions
Register your callback functions with the Sensor library by calling sensor_register_data_callback(). For example:
sensor_error_t err; sensor_handle_t handle = NULL; ... err = sensor_register_status_callback(handle, SENSOR_EVENT_STREAM_STATUS, sensor_status_callback, NULL); ...
Disable your status callback functions
When you no longer need your callback functions invoked on a sensor event, disable your callback functions from the Sensor library by calling sensor_disable_status_callback(). For example:
sensor_error_t err; sensor_handle_t handle = NULL; ... err = sensor_disable_status_callback(handle, SENSOR_EVENT_STREAM_STATUS, sensor_status_callback); ...
Ensure that you release any resources that you still have access to before you disable your callback functions. Once you disable your callback functions from a specified sensor event, the Sensor library no longer invokes the callbacks when that sensor event occurs.