wrapper: build libk4arecord_v2.so — the library the recorder actually dlopens
The recorder does not load the stock libk4a/libk4arecord. It dlopens a single custom libk4arecord_v2.so: the wrapper's MKV-writing sources linked to a pure-data shim (k4a_shim.cpp) instead of libk4a, so recording has no OrbbecSDK dependency. That target is FTF's own (wrapper/recordv2/), absent from the stock wrapper the Orin carried — so ship it and inject+build it, the same pattern as the recorder in the SDK examples tree. Idempotent; only added when missing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
526d654f68
commit
cabca69c4d
3 files changed
+482
-23
No files matched your search
@@ -1,24 +1,29 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Makes sure the Orbbec K4A wrapper is built for THIS platform, and prints where
|
# Makes sure the Orbbec K4A wrapper is built for THIS platform, INCLUDING FTF's
|
||||||
# it is as K4A_WRAPPER_DIR=... for build_sdk.sh (the recorder example needs its
|
# libk4arecord_v2.so, and prints K4A_WRAPPER_DIR=... for build_sdk.sh (the recorder
|
||||||
# headers) and for the recorder's runtime rpath (its libk4a.so/libk4arecord.so).
|
# example needs the headers) and for the recorder's runtime rpath.
|
||||||
#
|
#
|
||||||
# This is the libk4a provider — Orbbec's own, NOT Microsoft's Azure Kinect SDK.
|
# This is the libk4a provider — Orbbec's own, NOT Microsoft's Azure Kinect SDK. It
|
||||||
# It bundles its own OrbbecSDK internally, so it builds standalone. The recorder
|
# bundles its own OrbbecSDK, so it builds standalone.
|
||||||
# dlopens the libk4a it produces (RTLD_DEEPBIND) rather than link-time linking it,
|
|
||||||
# which is why only its build/lib path matters at runtime, not link time.
|
|
||||||
#
|
#
|
||||||
# Reuses an existing build (leaving a working node untouched) or clones + builds.
|
# The recorder does not dlopen the stock libk4a/libk4arecord. It dlopens a single
|
||||||
|
# custom library, libk4arecord_v2.so: the wrapper's own MKV-writing sources linked
|
||||||
|
# to a pure-data shim (k4a_shim.cpp) instead of libk4a — K4A-compatible recording
|
||||||
|
# with no OrbbecSDK dependency. That target is FTF's (wrapper/recordv2/ in this
|
||||||
|
# repo), not part of the stock wrapper, so it is injected and built here.
|
||||||
|
#
|
||||||
|
# Reuses an existing build; only adds the v2 target if it is missing.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
here=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
||||||
|
repo=$(cd "$here/.." && pwd)
|
||||||
eval "$("$here/detect_platform.sh")"
|
eval "$("$here/detect_platform.sh")"
|
||||||
|
|
||||||
REPO_URL="${OB_K4A_REPO:-https://github.com/orbbec/OrbbecSDK-K4A-Wrapper}"
|
REPO_URL="${OB_K4A_REPO:-https://github.com/orbbec/OrbbecSDK-K4A-Wrapper}"
|
||||||
# The tag the Nano runs. A caller can override to one known to build on a newer
|
|
||||||
# JetPack.
|
|
||||||
REF="${OB_K4A_REF:-v1.10.4}"
|
REF="${OB_K4A_REF:-v1.10.4}"
|
||||||
|
|
||||||
|
# A usable wrapper base: headers and the stock libk4a. The v2 target is ensured
|
||||||
|
# separately, so a wrapper built before this repo existed still qualifies.
|
||||||
find_wrapper() {
|
find_wrapper() {
|
||||||
local d="$1"
|
local d="$1"
|
||||||
[[ -f "$d/include/k4a/k4a.h" ]] || return 1
|
[[ -f "$d/include/k4a/k4a.h" ]] || return 1
|
||||||
@@ -26,42 +31,68 @@ find_wrapper() {
|
|||||||
echo "$d"
|
echo "$d"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Injects FTF's recordv2 sources and builds libk4arecord_v2.so if it is not there.
|
||||||
|
# Idempotent: the add_subdirectory line and the copy are guarded.
|
||||||
|
ensure_recordv2() {
|
||||||
|
local d="$1"
|
||||||
|
[[ -f "$d/build/lib/libk4arecord_v2.so" ]] && return 0
|
||||||
|
|
||||||
|
echo ">> libk4arecord_v2.so absent — injection de recordv2 et compilation…" >&2
|
||||||
|
local dst="$d/src/orbbec/recordv2"
|
||||||
|
mkdir -p "$dst"
|
||||||
|
cp "$repo/wrapper/recordv2/CMakeLists.txt" "$dst/"
|
||||||
|
cp "$repo/wrapper/recordv2/k4a_shim.cpp" "$dst/"
|
||||||
|
|
||||||
|
local ob_cmake="$d/src/orbbec/CMakeLists.txt"
|
||||||
|
if [[ -f "$ob_cmake" ]] && ! grep -q "add_subdirectory(recordv2)" "$ob_cmake"; then
|
||||||
|
echo "add_subdirectory(recordv2)" >> "$ob_cmake"
|
||||||
|
fi
|
||||||
|
|
||||||
|
( cd "$d/build"
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release >&2
|
||||||
|
make -j"$(nproc)" k4arecord_v2 >&2 )
|
||||||
|
|
||||||
|
[[ -f "$d/build/lib/libk4arecord_v2.so" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1 & 2: reuse a wrapper base, then make sure the v2 target is present.
|
||||||
for candidate in "${K4A_WRAPPER_DIR:-}" \
|
for candidate in "${K4A_WRAPPER_DIR:-}" \
|
||||||
"$HOME/OrbbecSDK-K4A-Wrapper" \
|
"$HOME/OrbbecSDK-K4A-Wrapper" \
|
||||||
"$HOME/Downloads/OrbbecSDK-K4A-Wrapper"; do
|
"$HOME/Downloads/OrbbecSDK-K4A-Wrapper"; do
|
||||||
[[ -z "$candidate" ]] && continue
|
[[ -z "$candidate" ]] && continue
|
||||||
if find_wrapper "$candidate" >/dev/null 2>&1; then
|
if find_wrapper "$candidate" >/dev/null 2>&1; then
|
||||||
echo ">> Wrapper K4A deja bati, reutilise: $candidate" >&2
|
echo ">> Wrapper K4A trouve: $candidate" >&2
|
||||||
echo "K4A_WRAPPER_DIR=$candidate"
|
if ensure_recordv2 "$candidate"; then
|
||||||
exit 0
|
echo "K4A_WRAPPER_DIR=$candidate"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
echo "!! libk4arecord_v2.so n'a pas pu etre bati dans $candidate" >&2
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# 3: clone + build the wrapper base, then the v2 target.
|
||||||
dir="${K4A_WRAPPER_DIR:-$HOME/OrbbecSDK-K4A-Wrapper}"
|
dir="${K4A_WRAPPER_DIR:-$HOME/OrbbecSDK-K4A-Wrapper}"
|
||||||
echo ">> Wrapper K4A absent — clone et compilation (JetPack ${JETPACK}, ${SOC})" >&2
|
echo ">> Wrapper K4A absent — clone et compilation (JetPack ${JETPACK}, ${SOC})" >&2
|
||||||
echo ">> ${REPO_URL} @ ${REF} -> ${dir}" >&2
|
echo ">> ${REPO_URL} @ ${REF} -> ${dir}" >&2
|
||||||
|
|
||||||
if [[ ! -d "$dir/.git" ]]; then
|
if [[ ! -d "$dir/.git" ]]; then
|
||||||
# --recursive: the wrapper carries its OrbbecSDK and depth engine as submodules.
|
|
||||||
git clone --recursive --depth 1 --branch "$REF" "$REPO_URL" "$dir" >&2
|
git clone --recursive --depth 1 --branch "$REF" "$REPO_URL" "$dir" >&2
|
||||||
fi
|
fi
|
||||||
|
|
||||||
mkdir -p "$dir/build"
|
mkdir -p "$dir/build"
|
||||||
(
|
( cd "$dir/build"
|
||||||
cd "$dir/build"
|
cmake .. -DCMAKE_BUILD_TYPE=Release >&2
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release >&2
|
make -j"$(nproc)" k4a k4arecord >&2 )
|
||||||
make -j"$(nproc)" k4a k4arecord >&2
|
|
||||||
)
|
|
||||||
|
|
||||||
if ! find_wrapper "$dir" >/dev/null 2>&1; then
|
if ! find_wrapper "$dir" >/dev/null 2>&1 || ! ensure_recordv2 "$dir"; then
|
||||||
cat >&2 <<EOF
|
cat >&2 <<EOF
|
||||||
|
|
||||||
!! La compilation du wrapper K4A ne s'est pas terminee comme attendu
|
!! La compilation du wrapper K4A (ou de libk4arecord_v2.so) a echoue dans $dir.
|
||||||
!! (libk4a.so absent de $dir/build/lib).
|
|
||||||
!! Bâtis-le une fois a la main, puis relance install.sh avec :
|
!! Bâtis-le une fois a la main, puis relance install.sh avec :
|
||||||
!! K4A_WRAPPER_DIR=$dir ./install.sh
|
!! K4A_WRAPPER_DIR=$dir ./install.sh
|
||||||
EOF
|
EOF
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo ">> Wrapper K4A bati: $dir" >&2
|
echo ">> Wrapper K4A + libk4arecord_v2.so batis: $dir" >&2
|
||||||
echo "K4A_WRAPPER_DIR=$dir"
|
echo "K4A_WRAPPER_DIR=$dir"
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Copyright (c) French Touch Factory. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# libk4arecord_v2 : ecriture MKV compatible K4A sans aucune dependance OrbbecSDK.
|
||||||
|
#
|
||||||
|
# Reprend telles quelles les sources d'ecriture du wrapper (record.cpp +
|
||||||
|
# matroska_write.cpp + iocallback.cpp) mais les lie a k4a_shim.cpp au lieu de
|
||||||
|
# libk4a.so, qui implemente k4a_image_t / k4a_capture_t au-dessus d'OrbbecSDK
|
||||||
|
# v1.10.18. playback.cpp est volontairement exclu : c'est lui qui appelle
|
||||||
|
# ob_create_context(), et le recorder n'a pas besoin de relecture.
|
||||||
|
|
||||||
|
set(RECORD_SRC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../record)
|
||||||
|
|
||||||
|
add_library(k4arecord_v2 SHARED
|
||||||
|
${RECORD_SRC_DIR}/sdk/record.cpp
|
||||||
|
${RECORD_SRC_DIR}/sdk/dll_main.c
|
||||||
|
${RECORD_SRC_DIR}/internal/iocallback.cpp
|
||||||
|
${RECORD_SRC_DIR}/internal/matroska_write.cpp
|
||||||
|
k4a_shim.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
# k4arecord_EXPORTS : exporte les k4a_record_* (macro de k4arecord_export.h).
|
||||||
|
# k4a_EXPORTS : idem pour les k4a_image_* / k4a_capture_* du shim, dont la
|
||||||
|
# visibilite est portee par K4A_EXPORT dans k4a.h.
|
||||||
|
target_compile_definitions(k4arecord_v2 PRIVATE k4arecord_EXPORTS k4a_EXPORTS)
|
||||||
|
|
||||||
|
target_include_directories(k4arecord_v2 PRIVATE
|
||||||
|
${K4A_INCLUDE_DIR}
|
||||||
|
${K4A_PRIV_INCLUDE_DIR}
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../include
|
||||||
|
# k4arecord/k4arecord_export.h, genere par la cible k4arecord
|
||||||
|
${CMAKE_BINARY_DIR}/src/orbbec/record/sdk/include
|
||||||
|
)
|
||||||
|
|
||||||
|
# Aucun k4a::k4a, aucun OrbbecSDK : c'est tout l'objet de cette cible.
|
||||||
|
target_link_libraries(k4arecord_v2 PRIVATE
|
||||||
|
k4ainternal::logging
|
||||||
|
ebml::ebml
|
||||||
|
matroska::matroska
|
||||||
|
)
|
||||||
|
|
||||||
|
set_target_properties(k4arecord_v2 PROPERTIES
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
|
||||||
|
)
|
||||||
@@ -0,0 +1,385 @@
|
|||||||
|
// Copyright (c) French Touch Factory. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// k4a_shim — implementation des objets k4a_image_t / k4a_capture_t SANS OrbbecSDK.
|
||||||
|
//
|
||||||
|
// Pourquoi : libk4a.so implemente ces deux types au-dessus d'OrbbecSDK v1.10.18
|
||||||
|
// (k4a_capture_create -> ob_create_frameset, k4a_image_create_from_buffer ->
|
||||||
|
// ob_create_frame_from_buffer). Le recorder capture deja via OrbbecSDK v2, et le
|
||||||
|
// chemin d'ecriture MKV ne fait que relire buffer/size/format/timestamp de ces
|
||||||
|
// objets : l'aller-retour par la v1 n'apporte rien et impose de charger un second
|
||||||
|
// SDK dans le process (d'ou le hack RTLD_DEEPBIND, cf. le recorder).
|
||||||
|
//
|
||||||
|
// Ici les deux types sont de simples conteneurs de donnees comptes par reference.
|
||||||
|
// Semantique reproduite a l'identique de l'API Azure Kinect :
|
||||||
|
// - create* -> refcount = 1, appartient a l'appelant
|
||||||
|
// - capture_set_* -> la capture prend SA propre reference
|
||||||
|
// - capture_get_* -> rend une NOUVELLE reference (l'appelant doit release)
|
||||||
|
// - release -> decremente ; a 0, appelle le buffer_release_cb fourni
|
||||||
|
//
|
||||||
|
// Les quatre fonctions k4a_device_* / k4a_calibration_get_from_raw ne sont
|
||||||
|
// presentes que pour satisfaire l'editeur de liens : record.cpp ne les appelle
|
||||||
|
// que si un k4a_device_t est passe a k4a_record_create(), et le recorder passe
|
||||||
|
// nullptr (il attache lui-meme le JSON de calibration lu via la v2).
|
||||||
|
|
||||||
|
#include <k4a/k4a.h>
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <new>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct ShimImage
|
||||||
|
{
|
||||||
|
std::atomic<int> refcount;
|
||||||
|
k4a_image_format_t format;
|
||||||
|
int width_pixels;
|
||||||
|
int height_pixels;
|
||||||
|
int stride_bytes;
|
||||||
|
uint8_t *buffer;
|
||||||
|
size_t size;
|
||||||
|
k4a_memory_destroy_cb_t *release_cb;
|
||||||
|
void *release_cb_context;
|
||||||
|
uint64_t device_timestamp_usec;
|
||||||
|
uint64_t system_timestamp_nsec;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ShimCapture
|
||||||
|
{
|
||||||
|
std::atomic<int> refcount;
|
||||||
|
ShimImage *color;
|
||||||
|
ShimImage *depth;
|
||||||
|
ShimImage *ir;
|
||||||
|
float temperature_c;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline ShimImage *as_image(k4a_image_t h)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<ShimImage *>(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ShimCapture *as_capture(k4a_capture_t h)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<ShimCapture *>(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void image_add_ref(ShimImage *i)
|
||||||
|
{
|
||||||
|
if (i != nullptr)
|
||||||
|
{
|
||||||
|
i->refcount.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rend la reference. A zero : rend le buffer a son proprietaire via le callback
|
||||||
|
// fourni a la creation, puis detruit le conteneur.
|
||||||
|
void image_dec_ref(ShimImage *i)
|
||||||
|
{
|
||||||
|
if (i == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i->refcount.fetch_sub(1, std::memory_order_acq_rel) == 1)
|
||||||
|
{
|
||||||
|
if (i->release_cb != nullptr)
|
||||||
|
{
|
||||||
|
i->release_cb(i->buffer, i->release_cb_context);
|
||||||
|
}
|
||||||
|
delete i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remplace un des trois emplacements d'une capture en respectant les references :
|
||||||
|
// on prend la nouvelle avant de rendre l'ancienne, au cas ou ce soit la meme.
|
||||||
|
void capture_set_slot(ShimImage **slot, k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *incoming = as_image(image_handle);
|
||||||
|
image_add_ref(incoming);
|
||||||
|
ShimImage *previous = *slot;
|
||||||
|
*slot = incoming;
|
||||||
|
image_dec_ref(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_image_t capture_get_slot(ShimImage *slot)
|
||||||
|
{
|
||||||
|
image_add_ref(slot);
|
||||||
|
return reinterpret_cast<k4a_image_t>(slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// ---- images ----------------------------------------------------------------
|
||||||
|
|
||||||
|
k4a_result_t k4a_image_create_from_buffer(k4a_image_format_t format,
|
||||||
|
int width_pixels,
|
||||||
|
int height_pixels,
|
||||||
|
int stride_bytes,
|
||||||
|
uint8_t *buffer,
|
||||||
|
size_t buffer_size,
|
||||||
|
k4a_memory_destroy_cb_t *buffer_release_cb,
|
||||||
|
void *buffer_release_cb_context,
|
||||||
|
k4a_image_t *image_handle)
|
||||||
|
{
|
||||||
|
if (image_handle == nullptr || buffer == nullptr)
|
||||||
|
{
|
||||||
|
return K4A_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShimImage *i = new (std::nothrow) ShimImage();
|
||||||
|
if (i == nullptr)
|
||||||
|
{
|
||||||
|
return K4A_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
i->refcount.store(1, std::memory_order_relaxed);
|
||||||
|
i->format = format;
|
||||||
|
i->width_pixels = width_pixels;
|
||||||
|
i->height_pixels = height_pixels;
|
||||||
|
i->stride_bytes = stride_bytes;
|
||||||
|
i->buffer = buffer;
|
||||||
|
i->size = buffer_size;
|
||||||
|
i->release_cb = buffer_release_cb;
|
||||||
|
i->release_cb_context = buffer_release_cb_context;
|
||||||
|
i->device_timestamp_usec = 0;
|
||||||
|
i->system_timestamp_nsec = 0;
|
||||||
|
|
||||||
|
*image_handle = reinterpret_cast<k4a_image_t>(i);
|
||||||
|
return K4A_RESULT_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *k4a_image_get_buffer(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->buffer : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t k4a_image_get_size(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->size : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_image_format_t k4a_image_get_format(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->format : K4A_IMAGE_FORMAT_CUSTOM;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k4a_image_get_width_pixels(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->width_pixels : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k4a_image_get_height_pixels(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->height_pixels : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int k4a_image_get_stride_bytes(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->stride_bytes : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t k4a_image_get_device_timestamp_usec(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->device_timestamp_usec : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_image_set_device_timestamp_usec(k4a_image_t image_handle, uint64_t timestamp_usec)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
if (i != nullptr)
|
||||||
|
{
|
||||||
|
i->device_timestamp_usec = timestamp_usec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t k4a_image_get_system_timestamp_nsec(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
return (i != nullptr) ? i->system_timestamp_nsec : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_image_set_system_timestamp_nsec(k4a_image_t image_handle, uint64_t timestamp_nsec)
|
||||||
|
{
|
||||||
|
ShimImage *i = as_image(image_handle);
|
||||||
|
if (i != nullptr)
|
||||||
|
{
|
||||||
|
i->system_timestamp_nsec = timestamp_nsec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_image_reference(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
image_add_ref(as_image(image_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_image_release(k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
image_dec_ref(as_image(image_handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- captures --------------------------------------------------------------
|
||||||
|
|
||||||
|
k4a_result_t k4a_capture_create(k4a_capture_t *capture_handle)
|
||||||
|
{
|
||||||
|
if (capture_handle == nullptr)
|
||||||
|
{
|
||||||
|
return K4A_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
ShimCapture *c = new (std::nothrow) ShimCapture();
|
||||||
|
if (c == nullptr)
|
||||||
|
{
|
||||||
|
return K4A_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
c->refcount.store(1, std::memory_order_relaxed);
|
||||||
|
c->color = nullptr;
|
||||||
|
c->depth = nullptr;
|
||||||
|
c->ir = nullptr;
|
||||||
|
c->temperature_c = 0.0f;
|
||||||
|
|
||||||
|
*capture_handle = reinterpret_cast<k4a_capture_t>(c);
|
||||||
|
return K4A_RESULT_SUCCEEDED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_capture_reference(k4a_capture_t capture_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
c->refcount.fetch_add(1, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_capture_release(k4a_capture_t capture_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
if (c == nullptr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (c->refcount.fetch_sub(1, std::memory_order_acq_rel) == 1)
|
||||||
|
{
|
||||||
|
image_dec_ref(c->color);
|
||||||
|
image_dec_ref(c->depth);
|
||||||
|
image_dec_ref(c->ir);
|
||||||
|
delete c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_capture_set_color_image(k4a_capture_t capture_handle, k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
capture_set_slot(&c->color, image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_capture_set_depth_image(k4a_capture_t capture_handle, k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
capture_set_slot(&c->depth, image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_capture_set_ir_image(k4a_capture_t capture_handle, k4a_image_t image_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
capture_set_slot(&c->ir, image_handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_image_t k4a_capture_get_color_image(k4a_capture_t capture_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
return (c != nullptr) ? capture_get_slot(c->color) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_image_t k4a_capture_get_depth_image(k4a_capture_t capture_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
return (c != nullptr) ? capture_get_slot(c->depth) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_image_t k4a_capture_get_ir_image(k4a_capture_t capture_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
return (c != nullptr) ? capture_get_slot(c->ir) : nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void k4a_capture_set_temperature_c(k4a_capture_t capture_handle, float temperature_c)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
if (c != nullptr)
|
||||||
|
{
|
||||||
|
c->temperature_c = temperature_c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float k4a_capture_get_temperature_c(k4a_capture_t capture_handle)
|
||||||
|
{
|
||||||
|
ShimCapture *c = as_capture(capture_handle);
|
||||||
|
return (c != nullptr) ? c->temperature_c : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---- stubs de lien ---------------------------------------------------------
|
||||||
|
// record.cpp ne touche a un k4a_device_t que si k4a_record_create() en recoit un.
|
||||||
|
// Le recorder passe nullptr, donc ces chemins sont morts. On echoue proprement
|
||||||
|
// plutot que de mentir sur des donnees qu'on ne peut pas fournir.
|
||||||
|
|
||||||
|
k4a_buffer_result_t k4a_device_get_raw_calibration(k4a_device_t device_handle,
|
||||||
|
uint8_t *data,
|
||||||
|
size_t *data_size)
|
||||||
|
{
|
||||||
|
(void)device_handle;
|
||||||
|
(void)data;
|
||||||
|
(void)data_size;
|
||||||
|
return K4A_BUFFER_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_buffer_result_t k4a_device_get_serialnum(k4a_device_t device_handle,
|
||||||
|
char *serial_number,
|
||||||
|
size_t *serial_number_size)
|
||||||
|
{
|
||||||
|
(void)device_handle;
|
||||||
|
(void)serial_number;
|
||||||
|
(void)serial_number_size;
|
||||||
|
return K4A_BUFFER_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_result_t k4a_device_get_version(k4a_device_t device_handle, k4a_hardware_version_t *version)
|
||||||
|
{
|
||||||
|
(void)device_handle;
|
||||||
|
(void)version;
|
||||||
|
return K4A_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
k4a_result_t k4a_calibration_get_from_raw(char *raw_calibration,
|
||||||
|
size_t raw_calibration_size,
|
||||||
|
const k4a_depth_mode_t depth_mode,
|
||||||
|
const k4a_color_resolution_t color_resolution,
|
||||||
|
k4a_calibration_t *calibration)
|
||||||
|
{
|
||||||
|
(void)raw_calibration;
|
||||||
|
(void)raw_calibration_size;
|
||||||
|
(void)depth_mode;
|
||||||
|
(void)color_resolution;
|
||||||
|
(void)calibration;
|
||||||
|
return K4A_RESULT_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
Reference in new issue
Block a user