From 44c0f1eaf67f4966d79def6862e3a9e56cbc038d Mon Sep 17 00:00:00 2001 From: Yi donghoon Date: Mon, 29 Jun 2026 14:14:42 +0900 Subject: [PATCH] feat: expose current k4a_capture via getNativeCapture() Retain the per-frame k4a_capture as an Impl member (released on the next successful capture or in closeDevice) and add getNativeCapture() alongside the existing native-handle escape hatch. This lets a separate addon feed the same capture into k4abt_tracker_enqueue_capture() for (i.e. body tracking), sharing the single capture instead of opening the device twice. No behavior change for existing depth/color/IR/point-cloud use; verified example-basic still renders the live point cloud on a Femto Bolt (via the Orbbec K4A Wrapper). --- src/tcxAzureKinect.cpp | 17 +++++++++++++++-- src/tcxAzureKinect.h | 9 +++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/tcxAzureKinect.cpp b/src/tcxAzureKinect.cpp index fc4229e..cf97e36 100644 --- a/src/tcxAzureKinect.cpp +++ b/src/tcxAzureKinect.cpp @@ -26,6 +26,7 @@ struct AzureKinect::Impl { k4a_transformation_t transformation = nullptr; k4a_calibration_t calibration{}; k4a_device_configuration_t config{}; + k4a_capture_t capture = nullptr; // most recent frame, held for getNativeCapture() }; AzureKinect::AzureKinect(uint32_t deviceIndex) @@ -38,6 +39,7 @@ AzureKinect::~AzureKinect() = default; k4a_device_t AzureKinect::getNativeDevice() const { return impl_->device; } const k4a_calibration_t& AzureKinect::getNativeCalibration() const { return impl_->calibration; } k4a_transformation_t AzureKinect::getNativeTransformation() const { return impl_->transformation; } +k4a_capture_t AzureKinect::getNativeCapture() const { return impl_->capture; } // ----------------------------------------------------------------------------- bool AzureKinect::openDevice() { @@ -105,6 +107,10 @@ bool AzureKinect::openDevice() { } void AzureKinect::closeDevice() { + if (impl_->capture) { + k4a_capture_release(impl_->capture); + impl_->capture = nullptr; + } if (impl_->transformation) { k4a_transformation_destroy(impl_->transformation); impl_->transformation = nullptr; @@ -124,9 +130,14 @@ StreamFreshness AzureKinect::captureInto(DepthFrame& dst) { if (k4a_device_get_capture(impl_->device, &cap, kCaptureTimeoutMs) != K4A_WAIT_RESULT_SUCCEEDED) { if (cap) k4a_capture_release(cap); - return fresh; // timeout / no frame + return fresh; // timeout / no frame; keep the previously held capture } + // Retain this capture for getNativeCapture() (e.g. k4abt body tracking shares + // the single capture). Release the one held from the previous frame first. + if (impl_->capture) k4a_capture_release(impl_->capture); + impl_->capture = cap; + k4a_image_t depthImg = k4a_capture_get_depth_image(cap); if (depthImg) { const int w = k4a_image_get_width_pixels(depthImg); @@ -206,7 +217,9 @@ StreamFreshness AzureKinect::captureInto(DepthFrame& dst) { k4a_image_release(irImg); } - k4a_capture_release(cap); + // cap is NOT released here — it is retained as impl_->capture and freed on the + // next successful capture or in closeDevice(), so getNativeCapture() can hand + // it to k4abt for the current frame. return fresh; } diff --git a/src/tcxAzureKinect.h b/src/tcxAzureKinect.h index 43c7119..7fe6b9d 100644 --- a/src/tcxAzureKinect.h +++ b/src/tcxAzureKinect.h @@ -54,6 +54,15 @@ class AzureKinect : public DepthCamera { const k4a_calibration_t& getNativeCalibration() const; k4a_transformation_t getNativeTransformation() const; + // The k4a_capture behind the most recent successful frame, retained until the + // next one is grabbed — e.g. to feed k4abt_tracker_enqueue_capture() for body + // tracking, sharing the single capture instead of opening the device twice. + // Null before the first frame / after closeDevice(); the backend owns it, do + // NOT release it. In threaded mode (setThreaded(true)) it is swapped on the + // grab thread, so read it on the thread that drives update() — or run + // non-threaded when handing it to the body tracker. + k4a_capture_t getNativeCapture() const; + protected: bool openDevice() override; void closeDevice() override;