Start implementation.

This commit is contained in:
Peter Johnson
2016-09-05 12:00:04 -07:00
parent 9dd5bea7a5
commit 85be299da1
11 changed files with 881 additions and 37 deletions

14
src/Frame.cpp Normal file
View File

@@ -0,0 +1,14 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "Frame.h"
#include "SourceImpl.h"
using namespace cs;
void Frame::ReleaseFrame() { m_source->ReleaseFrame(m_data); }

83
src/Frame.h Normal file
View File

@@ -0,0 +1,83 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef CAMERASERVER_FRAME_H_
#define CAMERASERVER_FRAME_H_
#include <atomic>
#include <chrono>
#include "llvm/SmallVector.h"
#include "Image.h"
namespace cs {
class SourceImpl;
class Frame {
friend class SourceImpl;
struct Data {
std::atomic_int refcount{0};
std::chrono::system_clock::time_point timestamp;
llvm::SmallVector<Image, 4> images;
};
public:
Frame(SourceImpl& source, Data* data) : m_source(&source), m_data(data) {
if (m_data) ++(m_data->refcount);
}
Frame(const Frame& frame) : m_source(frame.m_source), m_data(frame.m_data) {
if (m_data) ++(m_data->refcount);
}
Frame(Frame&& frame) : m_source(frame.m_source), m_data(frame.m_data) {
frame.m_data = nullptr;
}
~Frame() { DecRef(); }
Frame& operator=(const Frame& frame) {
DecRef();
m_source = frame.m_source;
m_data = frame.m_data;
if (m_data) ++(m_data->refcount);
return *this;
}
explicit operator bool() const { return m_data; }
std::size_t size(std::size_t channel) const {
if (!m_data || channel >= m_data->images.size()) return 0;
return m_data->images[channel].size();
}
const char* data(std::size_t channel) const {
if (!m_data || channel >= m_data->images.size()) return nullptr;
return m_data->images[channel].data();
}
std::chrono::system_clock::time_point time() const {
if (!m_data) return std::chrono::system_clock::time_point{};
return m_data->timestamp;
}
private:
void DecRef() {
if (m_data && --(m_data->refcount) == 0) ReleaseFrame();
}
void ReleaseFrame();
SourceImpl* m_source;
Data* m_data;
};
} // namespace cs
#endif // CAMERASERVER_FRAME_H_

13
src/Handle.cpp Normal file
View File

@@ -0,0 +1,13 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "Handle.h"
using namespace cs;
ATOMIC_STATIC_INIT(Sources)
ATOMIC_STATIC_INIT(Sinks)

107
src/Handle.h Normal file
View File

@@ -0,0 +1,107 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef CAMERASERVER_HANDLE_H_
#define CAMERASERVER_HANDLE_H_
#include <atomic>
#include "llvm/StringRef.h"
#include "cameraserver_c.h"
#include "UnlimitedHandleResource.h"
namespace cs {
class SinkImpl;
class SourceImpl;
// Handle data layout:
// Bits 0-15: Handle index
// Bits 16-23: Subindex (property only)
// Bits 24-30: Type
class Handle {
public:
enum Type {
kUndefined = 0,
kProperty = 0x40,
kSource,
kSink,
kListener
};
enum { kIndexMax = 0xffff };
Handle(CS_Handle handle) : m_handle(handle) {}
operator CS_Handle() const { return m_handle; }
Handle(int index, Type type) {
if (index < 0) {
m_handle = 0;
return;
}
m_handle = ((static_cast<int>(type) & 0x7f) << 24) | (index & 0xffff);
}
Handle(int index, int property, Type type) {
if (index < 0 || property < 0) {
m_handle = 0;
return;
}
m_handle = ((static_cast<int>(type) & 0x7f) << 24) |
((property & 0xff) << 16) | (index & 0xffff);
}
int GetIndex() const { return static_cast<int>(m_handle) & 0xffff; }
Type GetType() const {
return static_cast<Type>((static_cast<int>(m_handle) >> 24) & 0xff);
}
bool IsType(Type type) const { return type == GetType(); }
int GetTypedIndex(Type type) const { return IsType(type) ? GetIndex() : -1; }
int GetSubIndex() const { return (static_cast<int>(m_handle) >> 16) & 0xff; }
private:
CS_Handle m_handle;
};
struct SourceData {
enum Type {
kUnknown = 0,
kUSB,
kHTTP,
kCv
};
SourceData(Type type_, std::shared_ptr<SourceImpl> source_)
: type{type_}, refCount{0}, source{source_} {}
Type type;
std::atomic_int refCount;
std::shared_ptr<SourceImpl> source;
};
typedef StaticUnlimitedHandleResource<Handle, SourceData, Handle::kSource>
Sources;
struct SinkData {
enum Type {
kUnknown = 0,
kHTTP,
kCv
};
explicit SinkData(Type type_, std::shared_ptr<SinkImpl> sink_)
: type{type_}, refCount{0}, sourceHandle{0}, sink{sink_} {}
Type type;
std::atomic_int refCount;
std::atomic<CS_Source> sourceHandle;
std::shared_ptr<SinkImpl> sink;
};
typedef StaticUnlimitedHandleResource<Handle, SinkData, Handle::kSink> Sinks;
} // namespace cs
#endif // CAMERASERVER_HANDLE_H_

55
src/Image.h Normal file
View File

@@ -0,0 +1,55 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef CAMERASERVER_IMAGE_H_
#define CAMERASERVER_IMAGE_H_
#include <cstddef>
namespace cs {
class Image {
public:
enum Type {
kUnknown = 0,
kJpeg
};
Image() : m_data(nullptr), m_size(0), m_capacity(0) {}
explicit Image(std::size_t capacity)
: m_data(new char[capacity]), m_capacity(capacity) {}
Image(Image&& image)
: m_data(image.m_data),
m_size(image.m_size),
m_capacity(image.m_capacity) {
image.m_data = nullptr;
image.m_size = 0;
image.m_capacity = 0;
}
~Image() { delete[] m_data; }
Image(const Image&) = delete;
Image& operator=(const Image&) = delete;
char* data() { return m_data; }
const char* data() const { return m_data; }
std::size_t size() const { return m_size; }
std::size_t capacity() const { return m_capacity; }
Type type() const { return m_type; }
void SetSize(std::size_t size) { m_size = size; }
void SetType(Type type) { m_type = type; }
private:
char* m_data;
std::size_t m_size;
std::size_t m_capacity;
Type m_type = kUnknown;
};
} // namespace cs
#endif // CAMERASERVER_IMAGE_H_

14
src/SinkImpl.cpp Normal file
View File

@@ -0,0 +1,14 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "SinkImpl.h"
#include "SourceImpl.h"
using namespace cs;
SinkImpl::SinkImpl(llvm::StringRef name) : m_name{name} {}

50
src/SinkImpl.h Normal file
View File

@@ -0,0 +1,50 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef CAMERASERVER_SINKIMPL_H_
#define CAMERASERVER_SINKIMPL_H_
#include <memory>
#include <mutex>
#include <string>
#include "llvm/StringRef.h"
namespace cs {
class Frame;
class SourceImpl;
class SinkImpl {
public:
SinkImpl(llvm::StringRef name);
virtual ~SinkImpl() = default;
SinkImpl(const SinkImpl& queue) = delete;
SinkImpl& operator=(const SinkImpl& queue) = delete;
llvm::StringRef GetName() const { return m_name; }
virtual void GetDescription(llvm::SmallVectorImpl<char>& desc) const = 0;
void SetSource(std::shared_ptr<SourceImpl> source) {
std::lock_guard<std::mutex> lock(m_mutex);
m_source = source;
}
std::shared_ptr<SourceImpl> GetSource() const {
std::lock_guard<std::mutex> lock(m_mutex);
return m_source;
}
private:
std::string m_name;
mutable std::mutex m_mutex;
std::shared_ptr<SourceImpl> m_source;
};
} // namespace cs
#endif // CAMERASERVER_SINKIMPL_H_

69
src/SourceImpl.cpp Normal file
View File

@@ -0,0 +1,69 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#include "SourceImpl.h"
#include "llvm/STLExtras.h"
using namespace cs;
SourceImpl::SourceImpl(llvm::StringRef name)
: m_name{name}, m_frame{*this, nullptr} {}
SourceImpl::~SourceImpl() {
// Wake up anyone who is waiting. This also clears the current frame,
// which is good because its destructor will call back into the class.
Wakeup();
// Everything else can clean up itself.
}
Frame SourceImpl::GetNextFrame() {
std::unique_lock<std::mutex> lock{m_frameMutex};
// TODO: handle spurious wakeup by comparing frame timestamps
m_cv.wait(lock);
return m_frame;
}
void SourceImpl::Wakeup() {
{
std::lock_guard<std::mutex> lock{m_frameMutex};
m_frame = Frame{*this, nullptr};
}
m_cv.notify_all();
}
void SourceImpl::StartFrame() {
std::lock_guard<std::mutex> lock{m_mutex};
if (m_frameData) return;
if (m_framesAvail.empty()) {
m_frameData = llvm::make_unique<Frame::Data>();
} else {
m_frameData = std::move(m_framesAvail.back());
m_framesAvail.pop_back();
m_frameData->refcount = 0;
}
}
//TODO: Image& SourceImpl::AddImage(std::size_t channel, std::size_t size) {}
void SourceImpl::FinishFrame() {
{
std::lock_guard<std::mutex> lock{m_mutex};
std::lock_guard<std::mutex> lock2{m_frameMutex};
m_frame = Frame{*this, m_frameData.release()};
}
m_cv.notify_all();
}
void SourceImpl::ReleaseFrame(Frame::Data* data) {
std::lock_guard<std::mutex> lock{m_mutex};
// Return the images to the pool
for (auto&& image : data->images)
m_imagesAvail.emplace_back(std::move(image));
// Return the frame to the pool
m_framesAvail.emplace_back(data);
}

99
src/SourceImpl.h Normal file
View File

@@ -0,0 +1,99 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef CAMERASERVER_SOURCEIMPL_H_
#define CAMERASERVER_SOURCEIMPL_H_
#include <condition_variable>
#include <cstddef>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
#include "llvm/StringRef.h"
#include "cameraserver_c.h"
#include "Frame.h"
namespace cs {
class SourceImpl {
friend class Frame;
public:
SourceImpl(llvm::StringRef name);
virtual ~SourceImpl();
SourceImpl(const SourceImpl& queue) = delete;
SourceImpl& operator=(const SourceImpl& queue) = delete;
llvm::StringRef GetName() const { return m_name; }
virtual void GetDescription(llvm::SmallVectorImpl<char>& desc) const = 0;
int GetNumChannels() const { return m_numChannels; }
bool IsConnected() const { return m_connected; }
// Gets the current frame (without waiting for a new one).
Frame GetCurFrame();
// Blocking function that waits for the next frame and returns it.
Frame GetNextFrame();
// Force a wakeup of all GetNextFrame() callers by sending an empty frame.
void Wakeup();
// Property functions
virtual int GetProperty(llvm::StringRef name) const = 0;
virtual void EnumerateProperties(
llvm::SmallVectorImpl<int>& properties) const = 0;
virtual CS_PropertyType GetPropertyType(int property) const = 0;
virtual void GetPropertyName(int property,
llvm::SmallVectorImpl<char>& name) const = 0;
virtual bool GetBooleanProperty(int property) const = 0;
virtual void SetBooleanProperty(int property, bool value) = 0;
virtual double GetDoubleProperty(int property) const = 0;
virtual void SetDoubleProperty(int property, double value) = 0;
virtual double GetPropertyMin(int property) const = 0;
virtual double GetPropertyMax(int property) const = 0;
virtual void GetStringProperty(int property,
llvm::SmallVectorImpl<char>& value) const = 0;
virtual void SetStringProperty(int property, llvm::StringRef value) = 0;
virtual int GetEnumProperty(int property) const = 0;
virtual void SetEnumProperty(int property, int value) = 0;
virtual std::vector<std::string> GetEnumPropertyChoices(
int property) const = 0;
protected:
void StartFrame();
Image& AddImage(std::size_t channel, std::size_t size);
void FinishFrame();
std::atomic_int m_numChannels{0};
std::atomic_bool m_connected{false};
private:
void ReleaseFrame(Frame::Data* data);
std::string m_name;
std::mutex m_mutex;
std::mutex m_frameMutex;
std::condition_variable m_cv;
// Most recent complete frame (returned to callers of GetNextFrame)
// Access protected by m_frameMutex.
Frame m_frame;
// In-progress frame. Will be moved to m_frame when complete.
std::unique_ptr<Frame::Data> m_frameData;
// Pools of frames and images to reduce malloc traffic.
std::vector<std::unique_ptr<Frame::Data>> m_framesAvail;
std::vector<Image> m_imagesAvail;
};
} // namespace cs
#endif // CAMERASERVER_SOURCEIMPL_H_

View File

@@ -0,0 +1,154 @@
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2016. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
#ifndef CAMERASERVER_UNLIMITEDHANDLERESOURCE_H_
#define CAMERASERVER_UNLIMITEDHANDLERESOURCE_H_
#include <memory>
#include <mutex>
#include <vector>
#include "llvm/SmallVector.h"
#include "support/atomic_static.h"
namespace cs {
// The UnlimitedHandleResource class is a way to track handles. This version
// allows an unlimted number of handles that are allocated sequentially. When
// possible, indices are reused to save memory usage and keep the array length
// down.
// However, automatic array management has not been implemented, but might be in
// the future.
// Because we have to loop through the allocator, we must use a global mutex.
//
// THandle needs to have the following attributes:
// Type : enum or typedef
// kIndexMax : static, constexpr, or enum value for the maximum index value
// int GetTypedIndex() const : function that returns the index of the handle
// THandle(int index, HandleType[int] type) : constructor for index and type
//
// @tparam THandle The Handle Type
// @tparam TStruct The struct type held by this resource
// @tparam typeValue The type value stored in the handle
// @tparam TMutex The mutex type to use
template <typename THandle, typename TStruct, int typeValue,
typename TMutex = std::mutex>
class UnlimitedHandleResource {
public:
UnlimitedHandleResource(const UnlimitedHandleResource&) = delete;
UnlimitedHandleResource operator=(const UnlimitedHandleResource&) = delete;
UnlimitedHandleResource() = default;
template <typename... Args>
THandle Allocate(Args&&... args);
THandle Allocate(std::shared_ptr<THandle> structure);
std::shared_ptr<TStruct> Get(THandle handle);
void Free(THandle handle);
template <typename T>
void GetAll(llvm::SmallVectorImpl<T>& handles);
private:
THandle MakeHandle(size_t i) {
return THandle{static_cast<int>(i),
static_cast<typename THandle::Type>(typeValue)};
}
std::vector<std::shared_ptr<TStruct>> m_structures;
TMutex m_handleMutex;
};
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
template <typename... Args>
THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
Args&&... args) {
std::lock_guard<TMutex> sync(m_handleMutex);
size_t i;
for (i = 0; i < m_structures.size(); i++) {
if (m_structures[i] == nullptr) {
m_structures[i] = std::make_shared<TStruct>(std::forward<Args>(args)...);
return MakeHandle(i);
}
}
if (i >= THandle::kIndexMax) return 0;
m_structures.emplace_back(
std::make_shared<TStruct>(std::forward<Args>(args)...));
return MakeHandle(i);
}
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
THandle UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Allocate(
std::shared_ptr<THandle> structure) {
std::lock_guard<TMutex> sync(m_handleMutex);
size_t i;
for (i = 0; i < m_structures.size(); i++) {
if (m_structures[i] == nullptr) {
m_structures[i] = structure;
return MakeHandle(i);
}
}
if (i >= THandle::kIndexMax) return 0;
m_structures.push_back(structure);
return MakeHandle(i);
}
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
std::shared_ptr<TStruct> UnlimitedHandleResource<THandle, TStruct, typeValue,
TMutex>::Get(THandle handle) {
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
if (index < 0) return nullptr;
std::lock_guard<TMutex> sync(m_handleMutex);
if (index >= static_cast<int>(m_structures.size()))
return nullptr;
return m_structures[index];
}
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
void UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::Free(
THandle handle) {
auto index =
handle.GetTypedIndex(static_cast<typename THandle::Type>(typeValue));
if (index < 0) return;
std::lock_guard<TMutex> sync(m_handleMutex);
if (index >= static_cast<int>(m_structures.size())) return;
m_structures[index].reset();
}
template <typename THandle, typename TStruct, int typeValue, typename TMutex>
template <typename T>
void UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex>::GetAll(
llvm::SmallVectorImpl<T>& handles) {
std::lock_guard<TMutex> sync(m_handleMutex);
size_t i;
for (i = 0; i < m_structures.size(); i++) {
if (m_structures[i] != nullptr) handles.push_back(MakeHandle(i));
}
}
template <typename THandle, typename TStruct, int typeValue,
typename TMutex = std::mutex>
class StaticUnlimitedHandleResource
: public UnlimitedHandleResource<THandle, TStruct, typeValue, TMutex> {
public:
static StaticUnlimitedHandleResource& GetInstance() {
ATOMIC_STATIC(StaticUnlimitedHandleResource, instance);
return instance;
}
private:
StaticUnlimitedHandleResource() {}
ATOMIC_STATIC_DECL(StaticUnlimitedHandleResource)
};
} // namespace cs
#endif // CAMERASERVER_UNLIMITEDHANDLERESOURCE_H_

View File

@@ -7,10 +7,32 @@
#include "cameraserver_cpp.h"
#include <limits>
#include "llvm/SmallString.h"
#include "SinkImpl.h"
#include "SourceImpl.h"
#include "Handle.h"
using namespace cs;
static std::shared_ptr<SourceImpl> GetPropertySource(CS_Property propertyHandle,
int* propertyIndex,
CS_Status* status) {
Handle handle{propertyHandle};
int i = handle.GetTypedIndex(Handle::kProperty);
if (i < 0) {
*status = CS_INVALID_HANDLE;
return nullptr;
}
auto data = Sources::GetInstance().Get(Handle{i, Handle::kSource});
if (!data) {
*status = CS_INVALID_HANDLE;
return nullptr;
}
*propertyIndex = handle.GetSubIndex();
return data->source;
}
namespace cs {
//
@@ -18,67 +40,116 @@ namespace cs {
//
CS_PropertyType GetPropertyType(CS_Property property, CS_Status* status) {
return CS_PROP_NONE; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return CS_PROP_NONE;
return source->GetPropertyType(propertyIndex);
}
std::string GetPropertyName(CS_Property property, CS_Status* status) {
return ""; // TODO
llvm::SmallString<128> name;
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return std::string{};
source->GetPropertyName(propertyIndex, name);
return name.str();
}
void GetPropertyName(CS_Property property, llvm::SmallVectorImpl<char>& name,
CS_Status* status) {
// TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return;
source->GetPropertyName(propertyIndex, name);
}
bool GetBooleanProperty(CS_Property property, CS_Status* status) {
return false; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return false;
return source->GetBooleanProperty(propertyIndex);
}
void SetBooleanProperty(CS_Property property, bool value, CS_Status* status) {
// TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return;
source->SetBooleanProperty(propertyIndex, value);
}
double GetDoubleProperty(CS_Property property, CS_Status* status) {
return 0.0; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return false;
return source->GetDoubleProperty(propertyIndex);
}
void SetDoubleProperty(CS_Property property, double value, CS_Status* status) {
// TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return;
source->SetDoubleProperty(propertyIndex, value);
}
double GetDoublePropertyMin(CS_Property property, CS_Status* status) {
return 0.0; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return 0.0;
return source->GetPropertyMin(propertyIndex);
}
double GetDoublePropertyMax(CS_Property property, CS_Status* status) {
return 0.0; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return 0.0;
return source->GetPropertyMax(propertyIndex);
}
std::string GetStringProperty(CS_Property property, CS_Status* status) {
return ""; // TODO
llvm::SmallString<128> value;
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return std::string{};
source->GetStringProperty(propertyIndex, value);
return value.str();
}
void GetStringProperty(CS_Property property, llvm::SmallVectorImpl<char>& value,
CS_Status* status) {
// TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return;
source->GetStringProperty(propertyIndex, value);
}
void SetStringProperty(CS_Property property, llvm::StringRef value,
CS_Status* status) {
// TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return;
source->SetStringProperty(propertyIndex, value);
}
int GetEnumProperty(CS_Property property, CS_Status* status) {
return 0; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return 0;
return source->GetEnumProperty(propertyIndex);
}
void SetEnumProperty(CS_Property property, int value, CS_Status* status) {
// TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return;
source->SetEnumProperty(propertyIndex, value);
}
std::vector<std::string> GetEnumPropertyChoices(CS_Property property,
CS_Status* status) {
return std::vector<std::string>{}; // TODO
int propertyIndex;
auto source = GetPropertySource(property, &propertyIndex, status);
if (!source) return std::vector<std::string>{};
return source->GetEnumPropertyChoices(propertyIndex);
}
//
@@ -109,21 +180,44 @@ CS_Source CreateCvSource(llvm::StringRef name, int numChannels,
//
std::string GetSourceName(CS_Source source, CS_Status* status) {
return ""; // TODO
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
return data->source->GetName();
}
void GetSourceName(CS_Source sink, llvm::SmallVectorImpl<char>& name,
void GetSourceName(CS_Source source, llvm::SmallVectorImpl<char>& name,
CS_Status* status) {
// TODO
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
auto str = data->source->GetName();
name.append(str.begin(), str.end());
}
std::string GetSourceDescription(CS_Source source, CS_Status* status) {
return ""; // TODO
llvm::SmallString<128> desc;
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
data->source->GetDescription(desc);
return desc.str();
}
void GetSourceDescription(CS_Source source, llvm::SmallVectorImpl<char>& desc,
CS_Status* status) {
// TODO
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
data->source->GetDescription(desc);
}
uint64_t GetSourceLastFrameTime(CS_Source source, CS_Status* status) {
@@ -131,16 +225,36 @@ uint64_t GetSourceLastFrameTime(CS_Source source, CS_Status* status) {
}
int GetSourceNumChannels(CS_Source source, CS_Status* status) {
return 0; // TODO
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return 0;
}
return data->source->GetNumChannels();
}
bool IsSourceConnected(CS_Source source, CS_Status* status) {
return false; // TODO
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return false;
}
return data->source->IsConnected();
}
CS_Property GetSourceProperty(CS_Source source, llvm::StringRef name,
CS_Status* status) {
return 0; // TODO
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return 0;
}
int property = data->source->GetProperty(name);
if (property < 0) {
*status = CS_INVALID_HANDLE;
return 0;
}
return Handle{source, property, Handle::kProperty};
}
void EnumerateSourceProperties(CS_Source source,
@@ -150,11 +264,25 @@ void EnumerateSourceProperties(CS_Source source,
}
CS_Source CopySource(CS_Source source, CS_Status* status) {
return source; // TODO
if (source == 0) return 0;
auto data = Sources::GetInstance().Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return 0;
}
data->refCount++;
return source;
}
void ReleaseSource(CS_Source source, CS_Status* status) {
// TODO
if (source == 0) return;
auto& inst = Sources::GetInstance();
auto data = inst.Get(source);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
if (--(data->refCount) == 0) inst.Free(source);
}
//
@@ -227,42 +355,100 @@ CS_Sink CreateCvSinkCallback(llvm::StringRef name,
// Sink Functions
//
std::string GetSinkName(CS_Sink sink, CS_Status* status) {
return ""; // TODO
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
return data->sink->GetName();
}
void GetSinkName(CS_Sink sink, llvm::SmallVectorImpl<char>& name,
CS_Status* status) {
// TODO
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
auto str = data->sink->GetName();
name.append(str.begin(), str.end());
}
std::string GetSinkDescription(CS_Sink sink, CS_Status* status) {
return ""; // TODO
llvm::SmallString<128> desc;
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return std::string{};
}
data->sink->GetDescription(desc);
return desc.str();
}
void GetSinkDescription(CS_Sink sink, llvm::SmallVectorImpl<char>& desc,
CS_Status* status) {
// TODO
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
data->sink->GetDescription(desc);
}
void SetSinkSource(CS_Sink sink, CS_Source source, CS_Status* status) {
// TODO
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
auto sourceData = Sources::GetInstance().Get(source);
if (!sourceData) {
*status = CS_INVALID_HANDLE;
return;
}
data->sink->SetSource(sourceData->source);
data->sourceHandle.store(source);
}
CS_Source GetSinkSource(CS_Sink sink, CS_Status* status) {
return 0; // TODO
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return 0;
}
return data->sourceHandle.load();
}
CS_Property GetSinkSourceProperty(CS_Sink sink, llvm::StringRef name,
CS_Status* status) {
return 0; // TODO
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return 0;
}
return GetSourceProperty(data->sourceHandle.load(), name, status);
}
CS_Sink CopySink(CS_Sink sink, CS_Status* status) {
return sink; // TODO
if (sink == 0) return 0;
auto data = Sinks::GetInstance().Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return 0;
}
data->refCount++;
return sink;
}
void ReleaseSink(CS_Sink sink, CS_Status* status) {
// TODO
if (sink == 0) return;
auto& inst = Sinks::GetInstance();
auto data = inst.Get(sink);
if (!data) {
*status = CS_INVALID_HANDLE;
return;
}
if (--(data->refCount) == 0) inst.Free(sink);
}
//
@@ -338,12 +524,12 @@ std::vector<USBCameraInfo> EnumerateUSBCameras(CS_Status* status) {
void EnumerateSourceHandles(llvm::SmallVectorImpl<CS_Source>& handles,
CS_Status* status) {
// TODO
Sources::GetInstance().GetAll(handles);
}
void EnumerateSinkHandles(llvm::SmallVectorImpl<CS_Sink>& handles,
CS_Status* status) {
// TODO
Sinks::GetInstance().GetAll(handles);
}
} // namespace cs