Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/tcxAzureKinect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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() {
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
9 changes: 9 additions & 0 deletions src/tcxAzureKinect.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down