diff --git a/include/cameraserver_c.h b/include/cameraserver_c.h index 53c8bb7a42..1bc9921761 100644 --- a/include/cameraserver_c.h +++ b/include/cameraserver_c.h @@ -194,16 +194,16 @@ typedef struct CS_USBCameraInfo { } CS_USBCameraInfo; CS_USBCameraInfo* CS_EnumerateUSBCameras(int* count, CS_Status* status); -void CS_FreeEnumeratedUSBCameras(CS_USBCameraInfo* cameras); +void CS_FreeEnumeratedUSBCameras(CS_USBCameraInfo* cameras, int count); CS_Source* CS_EnumerateSources(int* count, CS_Status* status); -void CS_FreeEnumeratedSources(CS_Source* sources); +void CS_ReleaseEnumeratedSources(CS_Source* sources, int count); CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status); -void CS_FreeEnumeratedSinks(CS_Sink* sinks); +void CS_ReleaseEnumeratedSinks(CS_Sink* sinks, int count); void CS_FreeString(char* str); -void CS_FreeEnumPropertyChoices(char** choices); +void CS_FreeEnumPropertyChoices(char** choices, int count); #ifdef __cplusplus } diff --git a/include/cameraserver_cpp.h b/include/cameraserver_cpp.h index 5b28493dd7..4d48cdf02f 100644 --- a/include/cameraserver_cpp.h +++ b/include/cameraserver_cpp.h @@ -31,6 +31,19 @@ namespace cs { // in applications such as JNI which require handle-based access. // +/// USB camera information +struct USBCameraInfo { + /// Device number (e.g. N in '/dev/videoN' on Linux) + int dev; + /// Path to device if available (e.g. '/dev/video0' on Linux) + std::string path; + /// Vendor/model name of the camera as provided by the USB driver + std::string name; + /// Number of channels the camera provides (usually 1, but some cameras such + /// as stereo or depth cameras may provide multiple channels). + int channels; +}; + // // Property Functions // @@ -139,7 +152,7 @@ uint64_t SinkWaitForFrame(CS_Sink sink, CS_Status* status); bool GetSinkImage(CS_Sink sink, int channel, cv::Mat* image, CS_Status* status); uint64_t GrabSinkFrame(CS_Sink sink, cv::Mat* image, CS_Status* status); std::string GetSinkError(CS_Sink sink, CS_Status* status); -void GetSinkError(CS_Sink sink, llvm::SmallVectorImpl msg, +void GetSinkError(CS_Sink sink, llvm::SmallVectorImpl& msg, CS_Status* status); void SetSinkEnabled(CS_Sink sink, bool enabled, CS_Status* status); @@ -162,10 +175,11 @@ void RemoveSinkListener(CS_Listener handle, CS_Status* status); // // Utility Functions // -void EnumerateSourceHandles(llvm::SmallVectorImpl& handles, - CS_Status* status); -void EnumerateSinkHandles(llvm::SmallVectorImpl& handles, - CS_Status* status); +std::vector EnumerateUSBCameras(CS_Status* status); + +void EnumerateSources(llvm::SmallVectorImpl& handles, + CS_Status* status); +void EnumerateSinks(llvm::SmallVectorImpl& handles, CS_Status* status); } // namespace cs diff --git a/include/cameraserver_oo.h b/include/cameraserver_oo.h index da94593d55..b820292257 100644 --- a/include/cameraserver_oo.h +++ b/include/cameraserver_oo.h @@ -130,19 +130,6 @@ class VideoSource { CS_Source m_handle; }; -/// USB camera information -struct USBCameraInfo { - /// Device number (e.g. N in '/dev/videoN' on Linux) - int dev; - /// Path to device if available (e.g. '/dev/video0' on Linux) - std::string path; - /// Vendor/model name of the camera as provided by the USB driver - std::string name; - /// Number of channels the camera provides (usually 1, but some cameras such - /// as stereo or depth cameras may provide multiple channels). - int channels; -}; - /// A source that represents a USB camera. class USBCamera : public VideoSource { public: diff --git a/include/cameraserver_oo.inl b/include/cameraserver_oo.inl index 7bb384ccbe..7f421dd075 100644 --- a/include/cameraserver_oo.inl +++ b/include/cameraserver_oo.inl @@ -139,6 +139,11 @@ inline USBCamera::USBCamera(llvm::StringRef name, llvm::StringRef path) { m_handle = CreateUSBSourcePath(name, path, &m_status); } +inline std::vector USBCamera::EnumerateUSBCameras() { + CS_Status status = 0; + return ::cs::EnumerateUSBCameras(&status); +} + inline HTTPCamera::HTTPCamera(llvm::StringRef name, llvm::StringRef url) { m_handle = CreateHTTPSource(name, url, &m_status); } diff --git a/src/cameraserver_c.cpp b/src/cameraserver_c.cpp index 88462cd2cb..890ae07b62 100644 --- a/src/cameraserver_c.cpp +++ b/src/cameraserver_c.cpp @@ -7,12 +7,24 @@ #include "cameraserver_c.h" -#include +#include +#include #include "llvm/SmallString.h" #include "cameraserver_cpp.h" +// +// Conversion helpers +// + +static char* ConvertToC(llvm::StringRef in) { + char* out = static_cast(std::malloc(in.size() + 1)); + std::memmove(out, in.data(), in.size()); + out[in.size()] = '\0'; + return out; +} + extern "C" { CS_PropertyType CS_GetPropertyType(CS_Property property, CS_Status* status) { @@ -46,7 +58,10 @@ double CS_GetDoublePropertyMax(CS_Property property, CS_Status* status) { } char* CS_GetStringProperty(CS_Property property, CS_Status* status) { - return nullptr; // TODO + llvm::SmallString<128> str; + cs::GetStringProperty(property, str, status); + if (*status != 0) return nullptr; + return ConvertToC(str); } void CS_SetStringProperty(CS_Property property, const char* value, @@ -64,7 +79,12 @@ void CS_SetEnumProperty(CS_Property property, int value, CS_Status* status) { char** CS_GetEnumPropertyChoices(CS_Property property, int* count, CS_Status* status) { - return nullptr; // TODO + auto choices = cs::GetEnumPropertyChoices(property, status); + char** out = static_cast(std::malloc(choices.size() * sizeof(char*))); + *count = choices.size(); + for (std::size_t i = 0; i < choices.size(); ++i) + out[i] = ConvertToC(choices[i]); + return out; } CS_Property CS_GetSourceProperty(CS_Source handle, const char* name, @@ -92,11 +112,17 @@ CS_Source CS_CreateCvSource(const char* name, int numChannels, } char* CS_GetSourceName(CS_Source source, CS_Status* status) { - return nullptr; // TODO + llvm::SmallString<128> str; + cs::GetSourceName(source, str, status); + if (*status != 0) return nullptr; + return ConvertToC(str); } char* CS_GetSourceDescription(CS_Source source, CS_Status* status) { - return nullptr; // TODO + llvm::SmallString<128> str; + cs::GetSourceDescription(source, str, status); + if (*status != 0) return nullptr; + return ConvertToC(str); } uint64_t CS_GetSourceLastFrameTime(CS_Source source, CS_Status* status) { @@ -189,11 +215,17 @@ CS_Sink CS_CreateCvSinkCallback(const char* name, void* data, } char* CS_GetSinkName(CS_Sink sink, CS_Status* status) { - return nullptr; // TODO + llvm::SmallString<128> str; + cs::GetSinkName(sink, str, status); + if (*status != 0) return nullptr; + return ConvertToC(str); } char* CS_GetSinkDescription(CS_Sink sink, CS_Status* status) { - return nullptr; // TODO + llvm::SmallString<128> str; + cs::GetSinkDescription(sink, str, status); + if (*status != 0) return nullptr; + return ConvertToC(str); } void CS_SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status) { @@ -231,7 +263,10 @@ uint64_t CS_GrabSinkFrame(CS_Sink sink, struct CvMat* image, } char* CS_GetSinkError(CS_Sink sink, CS_Status* status) { - return nullptr; // TODO + llvm::SmallString<128> str; + cs::GetSinkError(sink, str, status); + if (*status != 0) return nullptr; + return ConvertToC(str); } void CS_SetSinkEnabled(CS_Sink sink, CS_Bool enabled, CS_Status* status) { @@ -281,35 +316,74 @@ void CS_RemoveSinkListener(CS_Listener handle, CS_Status* status) { } CS_USBCameraInfo* CS_EnumerateUSBCameras(int* count, CS_Status* status) { - return nullptr; // TODO + auto cameras = cs::EnumerateUSBCameras(status); + CS_USBCameraInfo* out = static_cast( + std::malloc(cameras.size() * sizeof(CS_USBCameraInfo))); + *count = cameras.size(); + for (std::size_t i = 0; i < cameras.size(); ++i) { + out[i].dev = cameras[i].dev; + out[i].path = ConvertToC(cameras[i].path); + out[i].name = ConvertToC(cameras[i].name); + out[i].channels = cameras[i].channels; + } + return out; } -void CS_FreeEnumeratedUSBCameras(CS_USBCameraInfo* cameras) { - // TODO +void CS_FreeEnumeratedUSBCameras(CS_USBCameraInfo* cameras, int count) { + if (!cameras) return; + for (int i = 0; i < count; ++i) { + std::free(cameras[i].path); + std::free(cameras[i].name); + } + std::free(cameras); } CS_Source* CS_EnumerateSources(int* count, CS_Status* status) { - return nullptr; // TODO + llvm::SmallVector handles; + cs::EnumerateSources(handles, status); + CS_Source* sources = + static_cast(std::malloc(handles.size() * sizeof(CS_Source))); + *count = handles.size(); + std::copy(handles.begin(), handles.end(), sources); + return sources; } -void CS_FreeEnumeratedSources(CS_Source* sources) { - // TODO +void CS_ReleaseEnumeratedSources(CS_Source* sources, int count) { + if (!sources) return; + for (int i = 0; i < count; ++i) { + CS_Status status = 0; + if (sources[i] != 0) cs::ReleaseSource(sources[i], &status); + } + std::free(sources); } CS_Sink* CS_EnumerateSinks(int* count, CS_Status* status) { - return nullptr; // TODO + llvm::SmallVector handles; + cs::EnumerateSinks(handles, status); + CS_Sink* sinks = + static_cast(std::malloc(handles.size() * sizeof(CS_Sink))); + *count = handles.size(); + std::copy(handles.begin(), handles.end(), sinks); + return sinks; } -void CS_FreeEnumeratedSinks(CS_Sink* sinks) { - // TODO +void CS_ReleaseEnumeratedSinks(CS_Sink* sinks, int count) { + if (!sinks) return; + for (int i = 0; i < count; ++i) { + CS_Status status = 0; + if (sinks[i] != 0) cs::ReleaseSink(sinks[i], &status); + } + std::free(sinks); } void CS_FreeString(char* str) { - // TODO + std::free(str); } -void CS_FreeEnumPropertyChoices(char** choices) { - // TODO +void CS_FreeEnumPropertyChoices(char** choices, int count) { + if (!choices) return; + for (int i = 0; i < count; ++i) std::free(choices[i]); + std::free(choices); } } // extern "C" diff --git a/src/cameraserver_cpp.cpp b/src/cameraserver_cpp.cpp index 51bb0ca335..e65bd11c52 100644 --- a/src/cameraserver_cpp.cpp +++ b/src/cameraserver_cpp.cpp @@ -274,7 +274,7 @@ std::string GetSinkError(CS_Sink sink, CS_Status* status) { return ""; // TODO } -void GetSinkError(CS_Sink sink, llvm::SmallVectorImpl msg, +void GetSinkError(CS_Sink sink, llvm::SmallVectorImpl& msg, CS_Status* status) { // TODO } @@ -312,6 +312,10 @@ void RemoveSinkListener(CS_Listener handle, CS_Status* status) { // Utility Functions // +std::vector EnumerateUSBCameras(CS_Status* status) { + return std::vector{}; // TODO +} + void EnumerateSourceHandles(llvm::SmallVectorImpl& handles, CS_Status* status) { // TODO diff --git a/src/cameraserver_oo.cpp b/src/cameraserver_oo.cpp index 83a2f93855..13ade5c525 100644 --- a/src/cameraserver_oo.cpp +++ b/src/cameraserver_oo.cpp @@ -13,7 +13,7 @@ std::vector VideoSource::EnumerateSources() { std::vector sources; llvm::SmallVector handles; CS_Status status = 0; - EnumerateSourceHandles(handles, &status); + ::cs::EnumerateSources(handles, &status); sources.reserve(handles.size()); for (int handle : handles) sources.emplace_back(VideoSource{handle}); @@ -24,7 +24,7 @@ std::vector VideoSink::EnumerateSinks() { std::vector sinks; llvm::SmallVector handles; CS_Status status = 0; - EnumerateSinkHandles(handles, &status); + ::cs::EnumerateSinks(handles, &status); sinks.reserve(handles.size()); for (int handle : handles) sinks.emplace_back(VideoSink{handle});