diff --git a/include/camera_runner.h b/include/camera_runner.h index b22d79f..da065ec 100644 --- a/include/camera_runner.h +++ b/include/camera_runner.h @@ -40,6 +40,10 @@ struct MatPair { int64_t captureTimestamp; // In libcamera time units, hopefully uS? TODO // actually implement int32_t frameProcessingType; // enum value of shader run on the image + // Per-frame exposure integration time in microseconds, as reported by + // libcamera::controls::ExposureTime. 0 means the metadata was not + // available for this frame; consumers should leave timestamps uncorrected. + int32_t exposureTimeUs; MatPair() = default; explicit MatPair(int width, int height) @@ -79,6 +83,7 @@ class CameraRunner { int fd; ProcessType type; uint64_t captureTimestamp; + int32_t exposureTimeUs; }; std::thread m_threshold; diff --git a/include/libcamera_jni.hpp b/include/libcamera_jni.hpp index 671190e..66f37f4 100644 --- a/include/libcamera_jni.hpp +++ b/include/libcamera_jni.hpp @@ -125,6 +125,10 @@ JNIEXPORT jlong JNICALL Java_org_photonvision_raspi_LibCameraJNI_getFrameCaptureTime(JNIEnv *, jclass, jlong); +JNIEXPORT jlong JNICALL +Java_org_photonvision_raspi_LibCameraJNI_getFrameExposureTimeUs(JNIEnv *, + jclass, jlong); + /* * Class: org_photonvision_raspi_LibCameraJNI * Method: grabFrame diff --git a/src/camera_runner.cpp b/src/camera_runner.cpp index f9b6eb9..c5ec1ce 100644 --- a/src/camera_runner.cpp +++ b/src/camera_runner.cpp @@ -132,7 +132,13 @@ bool CameraRunner::start() { .get(libcamera::controls::SensorTimestamp) .value_or(0)); - gpu_queue.push({out, type, sensorTimestamp}); + // https://libcamera.org/api-html/namespacelibcamera_1_1controls.html#a4e1ca45653b62cd969d4d67a741076eb + int32_t exposureTimeUs = static_cast( + request->metadata() + .get(libcamera::controls::ExposureTime) + .value_or(0)); + + gpu_queue.push({out, type, sensorTimestamp, exposureTimeUs}); } std::chrono::duration elapsedMillis = @@ -181,6 +187,7 @@ bool CameraRunner::start() { // Save the current shader idx mat_pair.frameProcessingType = static_cast(data.type); mat_pair.captureTimestamp = data.captureTimestamp; + mat_pair.exposureTimeUs = data.exposureTimeUs; uint8_t *processed_out_buf = mat_pair.processed.data; uint8_t *color_out_buf = mat_pair.color.data; @@ -262,7 +269,7 @@ void CameraRunner::stop() { threshold.join(); // push sentinel value to stop display thread - gpu_queue.push({-1, ProcessType::None, 0}); + gpu_queue.push({-1, ProcessType::None, 0, 0}); display.join(); std::printf("stopped all\n"); diff --git a/src/libcamera_jni.cpp b/src/libcamera_jni.cpp index dd41ea3..a2fd9aa 100644 --- a/src/libcamera_jni.cpp +++ b/src/libcamera_jni.cpp @@ -427,6 +427,23 @@ Java_org_photonvision_raspi_LibCameraJNI_getFrameCaptureTime return pair->captureTimestamp; } +/* + * Class: org_photonvision_raspi_LibCameraJNI + * Method: getFrameExposureTimeUs + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL +Java_org_photonvision_raspi_LibCameraJNI_getFrameExposureTimeUs + (JNIEnv *, jclass, jlong pair_) +{ + MatPair *pair = reinterpret_cast(pair_); + if (!pair) { + return 0; + } + + return static_cast(pair->exposureTimeUs); +} + /* * Class: org_photonvision_raspi_LibCameraJNI * Method: releasePair diff --git a/src/main/java/org/photonvision/raspi/LibCameraJNI.java b/src/main/java/org/photonvision/raspi/LibCameraJNI.java index 57c535c..8f7c833 100644 --- a/src/main/java/org/photonvision/raspi/LibCameraJNI.java +++ b/src/main/java/org/photonvision/raspi/LibCameraJNI.java @@ -126,6 +126,14 @@ public static native boolean setThresholds( */ public static native long getFrameCaptureTime(long p_ptr); + /** + * Get the integration time (exposure window length) for this frame, as reported by libcamera's + * ExposureTime control. Units are microseconds. Returns 0 when libcamera did not populate the + * metadata for this frame; consumers should treat 0 as "unknown" and leave timestamps + * uncorrected. + */ + public static native long getFrameExposureTimeUs(long p_ptr); + /** * Get the current time, in the same timebase as libcamera gives the frame capture time. Units are * nanoseconds.