From 7ddbf2010819023feca299ea5d8d3d1480f89f62 Mon Sep 17 00:00:00 2001 From: Peter Johnson Date: Sun, 1 Jan 2017 14:24:13 -0800 Subject: [PATCH] Create VideoCamera base class and move camera settings functions to it. This makes them available for both UsbCamera and HttpCamera / AxisCamera. To avoid virtual functions in the public-facing interface, move the implementation of the camera settings functions to the core library. --- include/cscore_c.h | 14 +++ include/cscore_cpp.h | 13 +++ include/cscore_oo.h | 73 ++++++------- include/cscore_oo.inl | 99 +++++++++-------- java/lib/CameraServerJNI.cpp | 105 +++++++++++++++++++ java/src/edu/wpi/cscore/AxisCamera.java | 4 +- java/src/edu/wpi/cscore/CameraServerJNI.java | 12 +++ java/src/edu/wpi/cscore/HttpCamera.java | 28 ++--- java/src/edu/wpi/cscore/UsbCamera.java | 85 +-------------- java/src/edu/wpi/cscore/VideoCamera.java | 63 +++++++++++ src/CvSourceImpl.cpp | 35 +++++++ src/CvSourceImpl.h | 10 ++ src/HttpCameraImpl.cpp | 33 ++++++ src/HttpCameraImpl.h | 10 ++ src/SourceImpl.h | 10 ++ src/UsbCameraImpl.cpp | 51 +++++++++ src/UsbCameraImpl.h | 10 ++ src/cscore_c.cpp | 35 +++++++ src/cscore_cpp.cpp | 77 ++++++++++++++ 19 files changed, 581 insertions(+), 186 deletions(-) create mode 100644 java/src/edu/wpi/cscore/VideoCamera.java diff --git a/include/cscore_c.h b/include/cscore_c.h index b814f654fd..3377e078ae 100644 --- a/include/cscore_c.h +++ b/include/cscore_c.h @@ -242,6 +242,20 @@ CS_Sink* CS_EnumerateSourceSinks(CS_Source source, int* count, CS_Source CS_CopySource(CS_Source source, CS_Status* status); void CS_ReleaseSource(CS_Source source, CS_Status* status); +// +// Camera Source Common Property Fuctions +// +void CS_SetCameraBrightness(CS_Source source, int brightness, + CS_Status* status); +int CS_GetCameraBrightness(CS_Source source, CS_Status* status); +void CS_SetCameraWhiteBalanceAuto(CS_Source source, CS_Status* status); +void CS_SetCameraWhiteBalanceHoldCurrent(CS_Source source, CS_Status* status); +void CS_SetCameraWhiteBalanceManual(CS_Source source, int value, + CS_Status* status); +void CS_SetCameraExposureAuto(CS_Source source, CS_Status* status); +void CS_SetCameraExposureHoldCurrent(CS_Source source, CS_Status* status); +void CS_SetCameraExposureManual(CS_Source source, int value, CS_Status* status); + // // UsbCamera Source Functions // diff --git a/include/cscore_cpp.h b/include/cscore_cpp.h index b6e2546c6e..3a408e8362 100644 --- a/include/cscore_cpp.h +++ b/include/cscore_cpp.h @@ -203,6 +203,19 @@ llvm::ArrayRef EnumerateSourceSinks( CS_Source CopySource(CS_Source source, CS_Status* status); void ReleaseSource(CS_Source source, CS_Status* status); +// +// Camera Source Common Property Fuctions +// +void SetCameraBrightness(CS_Source source, int brightness, CS_Status* status); +int GetCameraBrightness(CS_Source source, CS_Status* status); +void SetCameraWhiteBalanceAuto(CS_Source source, CS_Status* status); +void SetCameraWhiteBalanceHoldCurrent(CS_Source source, CS_Status* status); +void SetCameraWhiteBalanceManual(CS_Source source, int value, + CS_Status* status); +void SetCameraExposureAuto(CS_Source source, CS_Status* status); +void SetCameraExposureHoldCurrent(CS_Source source, CS_Status* status); +void SetCameraExposureManual(CS_Source source, int value, CS_Status* status); + // // UsbCamera Source Functions // diff --git a/include/cscore_oo.h b/include/cscore_oo.h index a394d69e25..3b12b49b71 100644 --- a/include/cscore_oo.h +++ b/include/cscore_oo.h @@ -191,15 +191,8 @@ class VideoSource { CS_Source m_handle; }; -/// A source that represents a USB camera. -class UsbCamera : public VideoSource { - private: - static constexpr char const* kPropWbAuto = "white_balance_temperature_auto"; - static constexpr char const* kPropWbValue = "white_balance_temperature"; - static constexpr char const* kPropExAuto = "exposure_auto"; - static constexpr char const* kPropExValue = "exposure_absolute"; - static constexpr char const* kPropBrValue = "brightness"; - +/// A source that represents a video camera. +class VideoCamera : public VideoSource { public: enum WhiteBalance { kFixedIndoor = 3000, @@ -209,24 +202,7 @@ class UsbCamera : public VideoSource { kFixedFlourescent2 = 5200 }; - UsbCamera() = default; - - /// Create a source for a USB camera based on device number. - /// @param name Source name (arbitrary unique identifier) - /// @param dev Device number (e.g. 0 for /dev/video0) - UsbCamera(llvm::StringRef name, int dev); - - /// Create a source for a USB camera based on device path. - /// @param name Source name (arbitrary unique identifier) - /// @param path Path to device (e.g. "/dev/video0" on Linux) - UsbCamera(llvm::StringRef name, llvm::StringRef path); - - /// Enumerate USB cameras on the local system. - /// @return Vector of USB camera information (one for each camera) - static std::vector EnumerateUsbCameras(); - - /// Get the path to the device. - std::string GetPath() const; + VideoCamera() = default; /// Set the brightness, as a percentage (0-100). void SetBrightness(int brightness); @@ -251,12 +227,38 @@ class UsbCamera : public VideoSource { /// Set the exposure to manual, as a percentage (0-100). void SetExposureManual(int value); + + protected: + explicit VideoCamera(CS_Source handle) : VideoSource(handle) {} +}; + +/// A source that represents a USB camera. +class UsbCamera : public VideoCamera { + public: + UsbCamera() = default; + + /// Create a source for a USB camera based on device number. + /// @param name Source name (arbitrary unique identifier) + /// @param dev Device number (e.g. 0 for /dev/video0) + UsbCamera(llvm::StringRef name, int dev); + + /// Create a source for a USB camera based on device path. + /// @param name Source name (arbitrary unique identifier) + /// @param path Path to device (e.g. "/dev/video0" on Linux) + UsbCamera(llvm::StringRef name, llvm::StringRef path); + + /// Enumerate USB cameras on the local system. + /// @return Vector of USB camera information (one for each camera) + static std::vector EnumerateUsbCameras(); + + /// Get the path to the device. + std::string GetPath() const; }; /// A source that represents a MJPEG-over-HTTP (IP) camera. -class HttpCamera : public VideoSource { +class HttpCamera : public VideoCamera { public: - enum CameraKind { + enum HttpCameraKind { kUnknown = CS_HTTP_UNKNOWN, kMJPGStreamer = CS_HTTP_MJPGSTREAMER, kCSCore = CS_HTTP_CSCORE, @@ -268,27 +270,28 @@ class HttpCamera : public VideoSource { /// @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg") /// @param kind Camera kind (e.g. kAxis) HttpCamera(llvm::StringRef name, llvm::StringRef url, - CameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown); /// Create a source for a MJPEG-over-HTTP (IP) camera. /// @param name Source name (arbitrary unique identifier) /// @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg") /// @param kind Camera kind (e.g. kAxis) - HttpCamera(llvm::StringRef name, const char* url, CameraKind kind = kUnknown); + HttpCamera(llvm::StringRef name, const char* url, + HttpCameraKind kind = kUnknown); /// Create a source for a MJPEG-over-HTTP (IP) camera. /// @param name Source name (arbitrary unique identifier) /// @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg") /// @param kind Camera kind (e.g. kAxis) HttpCamera(llvm::StringRef name, const std::string& url, - CameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown); /// Create a source for a MJPEG-over-HTTP (IP) camera. /// @param name Source name (arbitrary unique identifier) /// @param urls Array of Camera URLs /// @param kind Camera kind (e.g. kAxis) HttpCamera(llvm::StringRef name, llvm::ArrayRef urls, - CameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown); /// Create a source for a MJPEG-over-HTTP (IP) camera. /// @param name Source name (arbitrary unique identifier) @@ -296,12 +299,12 @@ class HttpCamera : public VideoSource { /// @param kind Camera kind (e.g. kAxis) template HttpCamera(llvm::StringRef name, std::initializer_list urls, - CameraKind kind = kUnknown); + HttpCameraKind kind = kUnknown); /// Get the kind of HTTP camera. /// Autodetection can result in returning a different value than the camera /// was created with. - CameraKind GetCameraKind() const; + HttpCameraKind GetHttpCameraKind() const; /// Change the URLs used to connect to the camera. void SetUrls(llvm::ArrayRef urls); diff --git a/include/cscore_oo.inl b/include/cscore_oo.inl index a2ee883e05..fc63c36149 100644 --- a/include/cscore_oo.inl +++ b/include/cscore_oo.inl @@ -160,6 +160,46 @@ inline std::vector VideoSource::EnumerateVideoModes() const { return EnumerateSourceVideoModes(m_handle, &status); } +inline void VideoCamera::SetBrightness(int brightness) { + m_status = 0; + SetCameraBrightness(m_handle, brightness, &m_status); +} + +inline int VideoCamera::GetBrightness() { + m_status = 0; + return GetCameraBrightness(m_handle, &m_status); +} + +inline void VideoCamera::SetWhiteBalanceAuto() { + m_status = 0; + SetCameraWhiteBalanceAuto(m_handle, &m_status); +} + +inline void VideoCamera::SetWhiteBalanceHoldCurrent() { + m_status = 0; + SetCameraWhiteBalanceHoldCurrent(m_handle, &m_status); +} + +inline void VideoCamera::SetWhiteBalanceManual(int value) { + m_status = 0; + SetCameraWhiteBalanceManual(m_handle, value, &m_status); +} + +inline void VideoCamera::SetExposureAuto() { + m_status = 0; + SetCameraExposureAuto(m_handle, &m_status); +} + +inline void VideoCamera::SetExposureHoldCurrent() { + m_status = 0; + SetCameraExposureHoldCurrent(m_handle, &m_status); +} + +inline void VideoCamera::SetExposureManual(int value) { + m_status = 0; + SetCameraExposureManual(m_handle, value, &m_status); +} + inline UsbCamera::UsbCamera(llvm::StringRef name, int dev) { m_handle = CreateUsbCameraDev(name, dev, &m_status); } @@ -178,71 +218,27 @@ inline std::string UsbCamera::GetPath() const { return ::cs::GetUsbCameraPath(m_handle, &m_status); } -inline void UsbCamera::SetBrightness(int brightness) { - if (brightness > 100) { - brightness = 100; - } else if (brightness < 0) { - brightness = 0; - } - GetProperty(kPropBrValue).Set(brightness); -} - -inline int UsbCamera::GetBrightness() { - return GetProperty(kPropBrValue).Get(); -} - -inline void UsbCamera::SetWhiteBalanceAuto() { - GetProperty(kPropWbAuto).Set(1); // auto -} - -inline void UsbCamera::SetWhiteBalanceHoldCurrent() { - GetProperty(kPropWbAuto).Set(0); // manual -} - -inline void UsbCamera::SetWhiteBalanceManual(int value) { - GetProperty(kPropWbAuto).Set(0); // manual - GetProperty(kPropWbValue).Set(value); -} - -inline void UsbCamera::SetExposureAuto() { - GetProperty(kPropExAuto).Set(0); // auto; yes, this is opposite of WB -} - -inline void UsbCamera::SetExposureHoldCurrent() { - GetProperty(kPropExAuto).Set(1); // manual -} - -inline void UsbCamera::SetExposureManual(int value) { - GetProperty(kPropExAuto).Set(1); // manual - if (value > 100) { - value = 100; - } else if (value < 0) { - value = 0; - } - GetProperty(kPropExValue).Set(value); -} - inline HttpCamera::HttpCamera(llvm::StringRef name, llvm::StringRef url, - CameraKind kind) { + HttpCameraKind kind) { m_handle = CreateHttpCamera( name, url, static_cast(static_cast(kind)), &m_status); } inline HttpCamera::HttpCamera(llvm::StringRef name, const char* url, - CameraKind kind) { + HttpCameraKind kind) { m_handle = CreateHttpCamera( name, url, static_cast(static_cast(kind)), &m_status); } inline HttpCamera::HttpCamera(llvm::StringRef name, const std::string& url, - CameraKind kind) + HttpCameraKind kind) : HttpCamera(name, llvm::StringRef{url}, kind) {} inline HttpCamera::HttpCamera(llvm::StringRef name, llvm::ArrayRef urls, - CameraKind kind) { + HttpCameraKind kind) { m_handle = CreateHttpCamera( name, urls, static_cast(static_cast(kind)), &m_status); @@ -250,7 +246,8 @@ inline HttpCamera::HttpCamera(llvm::StringRef name, template inline HttpCamera::HttpCamera(llvm::StringRef name, - std::initializer_list urls, CameraKind kind) { + std::initializer_list urls, + HttpCameraKind kind) { std::vector vec; vec.reserve(urls.size()); for (const auto& url : urls) vec.emplace_back(url); @@ -259,9 +256,9 @@ inline HttpCamera::HttpCamera(llvm::StringRef name, &m_status); } -inline HttpCamera::CameraKind HttpCamera::GetCameraKind() const { +inline HttpCamera::HttpCameraKind HttpCamera::GetHttpCameraKind() const { m_status = 0; - return static_cast( + return static_cast( static_cast(::cs::GetHttpCameraKind(m_handle, &m_status))); } diff --git a/java/lib/CameraServerJNI.cpp b/java/lib/CameraServerJNI.cpp index 4460caa906..c3171ddc63 100644 --- a/java/lib/CameraServerJNI.cpp +++ b/java/lib/CameraServerJNI.cpp @@ -757,6 +757,111 @@ JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_releaseSource CheckStatus(env, status); } +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraBrightness + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraBrightness + (JNIEnv *env, jclass, jint source, jint brightness) +{ + CS_Status status = 0; + cs::SetCameraBrightness(source, brightness, &status); + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: getCameraBrightness + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_edu_wpi_cscore_CameraServerJNI_getCameraBrightness + (JNIEnv *env, jclass, jint source) +{ + CS_Status status = 0; + auto val = cs::GetCameraBrightness(source, &status); + CheckStatus(env, status); + return val; +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraWhiteBalanceAuto + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraWhiteBalanceAuto + (JNIEnv *env, jclass, jint source) +{ + CS_Status status = 0; + cs::SetCameraWhiteBalanceAuto(source, &status); + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraWhiteBalanceHoldCurrent + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraWhiteBalanceHoldCurrent + (JNIEnv *env, jclass, jint source) +{ + CS_Status status = 0; + cs::SetCameraWhiteBalanceHoldCurrent(source, &status); + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraWhiteBalanceManual + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraWhiteBalanceManual + (JNIEnv *env, jclass, jint source, jint value) +{ + CS_Status status = 0; + cs::SetCameraWhiteBalanceManual(source, value, &status); + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraExposureAuto + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureAuto + (JNIEnv *env, jclass, jint source) +{ + CS_Status status = 0; + cs::SetCameraExposureAuto(source, &status); + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraExposureHoldCurrent + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureHoldCurrent + (JNIEnv *env, jclass, jint source) +{ + CS_Status status = 0; + cs::SetCameraExposureHoldCurrent(source, &status); + CheckStatus(env, status); +} + +/* + * Class: edu_wpi_cscore_CameraServerJNI + * Method: setCameraExposureManual + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_edu_wpi_cscore_CameraServerJNI_setCameraExposureManual + (JNIEnv *env, jclass, jint source, jint value) +{ + CS_Status status = 0; + cs::SetCameraExposureManual(source, value, &status); + CheckStatus(env, status); +} + /* * Class: edu_wpi_cscore_CameraServerJNI * Method: getUsbCameraPath diff --git a/java/src/edu/wpi/cscore/AxisCamera.java b/java/src/edu/wpi/cscore/AxisCamera.java index 0957edf26c..b6c9de7a2f 100644 --- a/java/src/edu/wpi/cscore/AxisCamera.java +++ b/java/src/edu/wpi/cscore/AxisCamera.java @@ -25,13 +25,13 @@ public class AxisCamera extends HttpCamera { /// @param name Source name (arbitrary unique identifier) /// @param host Camera host IP or DNS name (e.g. "10.x.y.11") public AxisCamera(String name, String host) { - super(name, hostToUrl(host), CameraKind.kAxis); + super(name, hostToUrl(host), HttpCameraKind.kAxis); } /// Create a source for an Axis IP camera. /// @param name Source name (arbitrary unique identifier) /// @param hosts Array of Camera host IPs/DNS names public AxisCamera(String name, String[] hosts) { - super(name, hostToUrl(hosts), CameraKind.kAxis); + super(name, hostToUrl(hosts), HttpCameraKind.kAxis); } } diff --git a/java/src/edu/wpi/cscore/CameraServerJNI.java b/java/src/edu/wpi/cscore/CameraServerJNI.java index 2344aa0d2c..bd650c33be 100644 --- a/java/src/edu/wpi/cscore/CameraServerJNI.java +++ b/java/src/edu/wpi/cscore/CameraServerJNI.java @@ -128,6 +128,18 @@ public class CameraServerJNI { public static native int copySource(int source); public static native void releaseSource(int source); + // + // Camera Source Common Property Fuctions + // + public static native void setCameraBrightness(int source, int brightness); + public static native int getCameraBrightness(int source); + public static native void setCameraWhiteBalanceAuto(int source); + public static native void setCameraWhiteBalanceHoldCurrent(int source); + public static native void setCameraWhiteBalanceManual(int source, int value); + public static native void setCameraExposureAuto(int source); + public static native void setCameraExposureHoldCurrent(int source); + public static native void setCameraExposureManual(int source, int value); + // // UsbCamera Source Functions // diff --git a/java/src/edu/wpi/cscore/HttpCamera.java b/java/src/edu/wpi/cscore/HttpCamera.java index 94d3007a78..600ebdab25 100644 --- a/java/src/edu/wpi/cscore/HttpCamera.java +++ b/java/src/edu/wpi/cscore/HttpCamera.java @@ -8,12 +8,12 @@ package edu.wpi.cscore; /// A source that represents a MJPEG-over-HTTP (IP) camera. -public class HttpCamera extends VideoSource { - public enum CameraKind { +public class HttpCamera extends VideoCamera { + public enum HttpCameraKind { kUnknown(0), kMJPGStreamer(1), kCSCore(2), kAxis(3); private int value; - private CameraKind(int value) { + private HttpCameraKind(int value) { this.value = value; } @@ -22,12 +22,12 @@ public class HttpCamera extends VideoSource { } } - public static CameraKind getCameraKindFromInt(int kind) { + public static HttpCameraKind getHttpCameraKindFromInt(int kind) { switch (kind) { - case 1: return CameraKind.kMJPGStreamer; - case 2: return CameraKind.kCSCore; - case 3: return CameraKind.kAxis; - default: return CameraKind.kUnknown; + case 1: return HttpCameraKind.kMJPGStreamer; + case 2: return HttpCameraKind.kCSCore; + case 3: return HttpCameraKind.kAxis; + default: return HttpCameraKind.kUnknown; } } @@ -35,14 +35,14 @@ public class HttpCamera extends VideoSource { /// @param name Source name (arbitrary unique identifier) /// @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg") public HttpCamera(String name, String url) { - super(CameraServerJNI.createHttpCamera(name, url, CameraKind.kUnknown.getValue())); + super(CameraServerJNI.createHttpCamera(name, url, HttpCameraKind.kUnknown.getValue())); } /// Create a source for a MJPEG-over-HTTP (IP) camera. /// @param name Source name (arbitrary unique identifier) /// @param url Camera URL (e.g. "http://10.x.y.11/video/stream.mjpg") /// @param kind Camera kind (e.g. kAxis) - public HttpCamera(String name, String url, CameraKind kind) { + public HttpCamera(String name, String url, HttpCameraKind kind) { super(CameraServerJNI.createHttpCamera(name, url, kind.getValue())); } @@ -50,22 +50,22 @@ public class HttpCamera extends VideoSource { /// @param name Source name (arbitrary unique identifier) /// @param urls Array of Camera URLs public HttpCamera(String name, String[] urls) { - super(CameraServerJNI.createHttpCameraMulti(name, urls, CameraKind.kUnknown.getValue())); + super(CameraServerJNI.createHttpCameraMulti(name, urls, HttpCameraKind.kUnknown.getValue())); } /// Create a source for a MJPEG-over-HTTP (IP) camera. /// @param name Source name (arbitrary unique identifier) /// @param urls Array of Camera URLs /// @param kind Camera kind (e.g. kAxis) - public HttpCamera(String name, String[] urls, CameraKind kind) { + public HttpCamera(String name, String[] urls, HttpCameraKind kind) { super(CameraServerJNI.createHttpCameraMulti(name, urls, kind.getValue())); } /// Get the kind of HTTP camera. /// Autodetection can result in returning a different value than the camera /// was created with. - public CameraKind getCameraKind() { - return getCameraKindFromInt(CameraServerJNI.getHttpCameraKind(m_handle)); + public HttpCameraKind getHttpCameraKind() { + return getHttpCameraKindFromInt(CameraServerJNI.getHttpCameraKind(m_handle)); } /// Change the URLs used to connect to the camera. diff --git a/java/src/edu/wpi/cscore/UsbCamera.java b/java/src/edu/wpi/cscore/UsbCamera.java index b616dbac9f..db67c8ddda 100644 --- a/java/src/edu/wpi/cscore/UsbCamera.java +++ b/java/src/edu/wpi/cscore/UsbCamera.java @@ -8,28 +8,7 @@ package edu.wpi.cscore; /// A source that represents a USB camera. -public class UsbCamera extends VideoSource { - private static final String kPropWbAuto = "white_balance_temperature_auto"; - private static final String kPropWbValue = "white_balance_temperature"; - private static final String kPropExAuto = "exposure_auto"; - private static final String kPropExValue = "exposure_absolute"; - private static final String kPropBrValue = "brightness"; - - public class WhiteBalance { - public static final int kFixedIndoor = 3000; - public static final int kFixedOutdoor1 = 4000; - public static final int kFixedOutdoor2 = 5000; - public static final int kFixedFluorescent1 = 5100; - public static final int kFixedFlourescent2 = 5200; - } - - // Cached to avoid duplicate string lookups - private VideoProperty m_wbAuto; - private VideoProperty m_wbValue; - private VideoProperty m_exAuto; - private VideoProperty m_exValue; - private VideoProperty m_brValue; - +public class UsbCamera extends VideoCamera { /// Create a source for a USB camera based on device number. /// @param name Source name (arbitrary unique identifier) /// @param dev Device number (e.g. 0 for /dev/video0) @@ -54,66 +33,4 @@ public class UsbCamera extends VideoSource { public String getPath() { return CameraServerJNI.getUsbCameraPath(m_handle); } - - /// Set the brightness, as a percentage (0-100). - public synchronized void setBrightness(int brightness) { - if (brightness > 100) { - brightness = 100; - } else if (brightness < 0) { - brightness = 0; - } - if (m_brValue == null) m_brValue = getProperty(kPropBrValue); - m_brValue.set(brightness); - } - - /// Get the brightness, as a percentage (0-100). - public synchronized int getBrightness() { - if (m_brValue == null) m_brValue = getProperty(kPropBrValue); - return m_brValue.get(); - } - - /// Set the white balance to auto. - public synchronized void setWhiteBalanceAuto() { - if (m_wbAuto == null) m_wbAuto = getProperty(kPropWbAuto); - m_wbAuto.set(1); // auto - } - - /// Set the white balance to hold current. - public synchronized void setWhiteBalanceHoldCurrent() { - if (m_wbAuto == null) m_wbAuto = getProperty(kPropWbAuto); - m_wbAuto.set(0); // manual - } - - /// Set the white balance to manual, with specified color temperature. - public synchronized void setWhiteBalanceManual(int value) { - if (m_wbAuto == null) m_wbAuto = getProperty(kPropWbAuto); - m_wbAuto.set(0); // manual - if (m_wbValue == null) m_wbValue = getProperty(kPropWbValue); - m_wbValue.set(value); - } - - /// Set the exposure to auto aperature. - public synchronized void setExposureAuto() { - if (m_exAuto == null) m_exAuto = getProperty(kPropExAuto); - m_exAuto.set(0); // auto; yes, this is opposite of white balance. - } - - /// Set the exposure to hold current. - public synchronized void setExposureHoldCurrent() { - if (m_exAuto == null) m_exAuto = getProperty(kPropExAuto); - m_exAuto.set(1); // manual - } - - /// Set the exposure to manual, as a percentage (0-100). - public synchronized void setExposureManual(int value) { - if (m_exAuto == null) m_exAuto = getProperty(kPropExAuto); - m_exAuto.set(1); // manual - if (value > 100) { - value = 100; - } else if (value < 0) { - value = 0; - } - if (m_exValue == null) m_exValue = getProperty(kPropExValue); - m_exValue.set(value); - } } diff --git a/java/src/edu/wpi/cscore/VideoCamera.java b/java/src/edu/wpi/cscore/VideoCamera.java new file mode 100644 index 0000000000..0e5b92da70 --- /dev/null +++ b/java/src/edu/wpi/cscore/VideoCamera.java @@ -0,0 +1,63 @@ +/*----------------------------------------------------------------------------*/ +/* 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. */ +/*----------------------------------------------------------------------------*/ + +package edu.wpi.cscore; + +/// A source that represents a video camera. +public class VideoCamera extends VideoSource { + public class WhiteBalance { + public static final int kFixedIndoor = 3000; + public static final int kFixedOutdoor1 = 4000; + public static final int kFixedOutdoor2 = 5000; + public static final int kFixedFluorescent1 = 5100; + public static final int kFixedFlourescent2 = 5200; + } + + protected VideoCamera(int handle) { + super(handle); + } + + /// Set the brightness, as a percentage (0-100). + public synchronized void setBrightness(int brightness) { + CameraServerJNI.setCameraBrightness(m_handle, brightness); + } + + /// Get the brightness, as a percentage (0-100). + public synchronized int getBrightness() { + return CameraServerJNI.getCameraBrightness(m_handle); + } + + /// Set the white balance to auto. + public synchronized void setWhiteBalanceAuto() { + CameraServerJNI.setCameraWhiteBalanceAuto(m_handle); + } + + /// Set the white balance to hold current. + public synchronized void setWhiteBalanceHoldCurrent() { + CameraServerJNI.setCameraWhiteBalanceHoldCurrent(m_handle); + } + + /// Set the white balance to manual, with specified color temperature. + public synchronized void setWhiteBalanceManual(int value) { + CameraServerJNI.setCameraWhiteBalanceManual(m_handle, value); + } + + /// Set the exposure to auto aperture. + public synchronized void setExposureAuto() { + CameraServerJNI.setCameraExposureAuto(m_handle); + } + + /// Set the exposure to hold current. + public synchronized void setExposureHoldCurrent() { + CameraServerJNI.setCameraExposureHoldCurrent(m_handle); + } + + /// Set the exposure to manual, as a percentage (0-100). + public synchronized void setExposureManual(int value) { + CameraServerJNI.setCameraExposureManual(m_handle, value); + } +} diff --git a/src/CvSourceImpl.cpp b/src/CvSourceImpl.cpp index c715e09479..b4bd45f111 100644 --- a/src/CvSourceImpl.cpp +++ b/src/CvSourceImpl.cpp @@ -82,6 +82,41 @@ void CvSourceImpl::SetStringProperty(int property, llvm::StringRef value, UpdatePropertyValue(property, true, 0, value); } +// These are only valid for cameras (should never get called) + +void CvSourceImpl::SetBrightness(int brightness, CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + +int CvSourceImpl::GetBrightness(CS_Status* status) const { + *status = CS_INVALID_HANDLE; + return 0; +} + +void CvSourceImpl::SetWhiteBalanceAuto(CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + +void CvSourceImpl::SetWhiteBalanceHoldCurrent(CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + +void CvSourceImpl::SetWhiteBalanceManual(int value, CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + +void CvSourceImpl::SetExposureAuto(CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + +void CvSourceImpl::SetExposureHoldCurrent(CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + +void CvSourceImpl::SetExposureManual(int value, CS_Status* status) { + *status = CS_INVALID_HANDLE; +} + bool CvSourceImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) { // can't set video mode on OpenCV source return false; diff --git a/src/CvSourceImpl.h b/src/CvSourceImpl.h index d0b541c033..d51621cbb5 100644 --- a/src/CvSourceImpl.h +++ b/src/CvSourceImpl.h @@ -28,6 +28,16 @@ class CvSourceImpl : public SourceImpl { void SetStringProperty(int property, llvm::StringRef value, CS_Status* status) override; + // Standard common camera properties + void SetBrightness(int brightness, CS_Status* status) override; + int GetBrightness(CS_Status* status) const override; + void SetWhiteBalanceAuto(CS_Status* status) override; + void SetWhiteBalanceHoldCurrent(CS_Status* status) override; + void SetWhiteBalanceManual(int value, CS_Status* status) override; + void SetExposureAuto(CS_Status* status) override; + void SetExposureHoldCurrent(CS_Status* status) override; + void SetExposureManual(int value, CS_Status* status) override; + bool SetVideoMode(const VideoMode& mode, CS_Status* status) override; void NumSinksChanged() override; diff --git a/src/HttpCameraImpl.cpp b/src/HttpCameraImpl.cpp index 600ce67657..4d134fbbbb 100644 --- a/src/HttpCameraImpl.cpp +++ b/src/HttpCameraImpl.cpp @@ -387,6 +387,39 @@ void HttpCameraImpl::SetStringProperty(int property, llvm::StringRef value, // TODO } +void HttpCameraImpl::SetBrightness(int brightness, CS_Status* status) { + // TODO +} + +int HttpCameraImpl::GetBrightness(CS_Status* status) const { + // TODO + return 0; +} + +void HttpCameraImpl::SetWhiteBalanceAuto(CS_Status* status) { + // TODO +} + +void HttpCameraImpl::SetWhiteBalanceHoldCurrent(CS_Status* status) { + // TODO +} + +void HttpCameraImpl::SetWhiteBalanceManual(int value, CS_Status* status) { + // TODO +} + +void HttpCameraImpl::SetExposureAuto(CS_Status* status) { + // TODO +} + +void HttpCameraImpl::SetExposureHoldCurrent(CS_Status* status) { + // TODO +} + +void HttpCameraImpl::SetExposureManual(int value, CS_Status* status) { + // TODO +} + bool HttpCameraImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) { if (mode.pixelFormat != VideoMode::kMJPEG) return false; std::lock_guard lock(m_mutex); diff --git a/src/HttpCameraImpl.h b/src/HttpCameraImpl.h index 463a97db1f..2cdf203b5d 100644 --- a/src/HttpCameraImpl.h +++ b/src/HttpCameraImpl.h @@ -37,6 +37,16 @@ class HttpCameraImpl : public SourceImpl { void SetStringProperty(int property, llvm::StringRef value, CS_Status* status) override; + // Standard common camera properties + void SetBrightness(int brightness, CS_Status* status) override; + int GetBrightness(CS_Status* status) const override; + void SetWhiteBalanceAuto(CS_Status* status) override; + void SetWhiteBalanceHoldCurrent(CS_Status* status) override; + void SetWhiteBalanceManual(int value, CS_Status* status) override; + void SetExposureAuto(CS_Status* status) override; + void SetExposureHoldCurrent(CS_Status* status) override; + void SetExposureManual(int value, CS_Status* status) override; + bool SetVideoMode(const VideoMode& mode, CS_Status* status) override; void NumSinksChanged() override; diff --git a/src/SourceImpl.h b/src/SourceImpl.h index 198da0319f..ac2b7db347 100644 --- a/src/SourceImpl.h +++ b/src/SourceImpl.h @@ -107,6 +107,16 @@ class SourceImpl { std::vector GetEnumPropertyChoices(int property, CS_Status* status) const; + // Standard common camera properties + virtual void SetBrightness(int brightness, CS_Status* status) = 0; + virtual int GetBrightness(CS_Status* status) const = 0; + virtual void SetWhiteBalanceAuto(CS_Status* status) = 0; + virtual void SetWhiteBalanceHoldCurrent(CS_Status* status) = 0; + virtual void SetWhiteBalanceManual(int value, CS_Status* status) = 0; + virtual void SetExposureAuto(CS_Status* status) = 0; + virtual void SetExposureHoldCurrent(CS_Status* status) = 0; + virtual void SetExposureManual(int value, CS_Status* status) = 0; + // Video mode functions VideoMode GetVideoMode(CS_Status* status) const; virtual bool SetVideoMode(const VideoMode& mode, CS_Status* status) = 0; diff --git a/src/UsbCameraImpl.cpp b/src/UsbCameraImpl.cpp index 70f50aef79..f2d8e1807e 100644 --- a/src/UsbCameraImpl.cpp +++ b/src/UsbCameraImpl.cpp @@ -42,6 +42,12 @@ using namespace cs; +static constexpr char const* kPropWbAuto = "white_balance_temperature_auto"; +static constexpr char const* kPropWbValue = "white_balance_temperature"; +static constexpr char const* kPropExAuto = "exposure_auto"; +static constexpr char const* kPropExValue = "exposure_absolute"; +static constexpr char const* kPropBrValue = "brightness"; + #ifdef __linux__ // Conversions v4l2_fract time per frame from/to frames per second (fps) @@ -1139,6 +1145,51 @@ void UsbCameraImpl::SetStringProperty(int property, llvm::StringRef value, *status = SendAndWait(std::move(msg)); } +void UsbCameraImpl::SetBrightness(int brightness, CS_Status* status) { + if (brightness > 100) { + brightness = 100; + } else if (brightness < 0) { + brightness = 0; + } + SetProperty(GetPropertyIndex(kPropBrValue), brightness, status); +} + +int UsbCameraImpl::GetBrightness(CS_Status* status) const { + return GetProperty(GetPropertyIndex(kPropBrValue), status); +} + +void UsbCameraImpl::SetWhiteBalanceAuto(CS_Status* status) { + SetProperty(GetPropertyIndex(kPropWbAuto), 1, status); // auto +} + +void UsbCameraImpl::SetWhiteBalanceHoldCurrent(CS_Status* status) { + SetProperty(GetPropertyIndex(kPropWbAuto), 0, status); // manual +} + +void UsbCameraImpl::SetWhiteBalanceManual(int value, CS_Status* status) { + SetProperty(GetPropertyIndex(kPropWbAuto), 0, status); // manual + SetProperty(GetPropertyIndex(kPropWbValue), value, status); +} + +void UsbCameraImpl::SetExposureAuto(CS_Status* status) { + // auto; yes, this is opposite of WB + SetProperty(GetPropertyIndex(kPropExAuto), 0, status); +} + +void UsbCameraImpl::SetExposureHoldCurrent(CS_Status* status) { + SetProperty(GetPropertyIndex(kPropExAuto), 1, status); // manual +} + +void UsbCameraImpl::SetExposureManual(int value, CS_Status* status) { + SetProperty(GetPropertyIndex(kPropExAuto), 1, status); // manual + if (value > 100) { + value = 100; + } else if (value < 0) { + value = 0; + } + SetProperty(GetPropertyIndex(kPropExValue), value, status); +} + bool UsbCameraImpl::SetVideoMode(const VideoMode& mode, CS_Status* status) { Message msg{Message::kCmdSetMode}; msg.data[0] = mode.pixelFormat; diff --git a/src/UsbCameraImpl.h b/src/UsbCameraImpl.h index 9b5a8c80d0..7400381c65 100644 --- a/src/UsbCameraImpl.h +++ b/src/UsbCameraImpl.h @@ -39,6 +39,16 @@ class UsbCameraImpl : public SourceImpl { void SetStringProperty(int property, llvm::StringRef value, CS_Status* status) override; + // Standard common camera properties + void SetBrightness(int brightness, CS_Status* status) override; + int GetBrightness(CS_Status* status) const override; + void SetWhiteBalanceAuto(CS_Status* status) override; + void SetWhiteBalanceHoldCurrent(CS_Status* status) override; + void SetWhiteBalanceManual(int value, CS_Status* status) override; + void SetExposureAuto(CS_Status* status) override; + void SetExposureHoldCurrent(CS_Status* status) override; + void SetExposureManual(int value, CS_Status* status) override; + bool SetVideoMode(const VideoMode& mode, CS_Status* status) override; bool SetPixelFormat(VideoMode::PixelFormat pixelFormat, CS_Status* status) override; diff --git a/src/cscore_c.cpp b/src/cscore_c.cpp index 9172f1f1e1..95d4badf38 100644 --- a/src/cscore_c.cpp +++ b/src/cscore_c.cpp @@ -186,6 +186,41 @@ void CS_ReleaseSource(CS_Source source, CS_Status* status) { return cs::ReleaseSource(source, status); } +void CS_SetCameraBrightness(CS_Source source, int brightness, + CS_Status* status) { + return cs::SetCameraBrightness(source, brightness, status); +} + +int CS_GetCameraBrightness(CS_Source source, CS_Status* status) { + return cs::GetCameraBrightness(source, status); +} + +void CS_SetCameraWhiteBalanceAuto(CS_Source source, CS_Status* status) { + return cs::SetCameraWhiteBalanceAuto(source, status); +} + +void CS_SetCameraWhiteBalanceHoldCurrent(CS_Source source, CS_Status* status) { + return cs::SetCameraWhiteBalanceHoldCurrent(source, status); +} + +void CS_SetCameraWhiteBalanceManual(CS_Source source, int value, + CS_Status* status) { + return cs::SetCameraWhiteBalanceManual(source, value, status); +} + +void CS_SetCameraExposureAuto(CS_Source source, CS_Status* status) { + return cs::SetCameraExposureAuto(source, status); +} + +void CS_SetCameraExposureHoldCurrent(CS_Source source, CS_Status* status) { + return cs::SetCameraExposureHoldCurrent(source, status); +} + +void CS_SetCameraExposureManual(CS_Source source, int value, + CS_Status* status) { + return cs::SetCameraExposureManual(source, value, status); +} + CS_SinkKind CS_GetSinkKind(CS_Sink sink, CS_Status* status) { return cs::GetSinkKind(sink, status); } diff --git a/src/cscore_cpp.cpp b/src/cscore_cpp.cpp index 1654108721..ae78fc4296 100644 --- a/src/cscore_cpp.cpp +++ b/src/cscore_cpp.cpp @@ -348,6 +348,83 @@ void ReleaseSource(CS_Source source, CS_Status* status) { } } +// +// Camera Source Common Property Fuctions +// + +void SetCameraBrightness(CS_Source source, int brightness, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetBrightness(brightness, status); +} + +int GetCameraBrightness(CS_Source source, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return 0; + } + return data->source->GetBrightness(status); +} + +void SetCameraWhiteBalanceAuto(CS_Source source, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetWhiteBalanceAuto(status); +} + +void SetCameraWhiteBalanceHoldCurrent(CS_Source source, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetWhiteBalanceHoldCurrent(status); +} + +void SetCameraWhiteBalanceManual(CS_Source source, int value, + CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetWhiteBalanceManual(value, status); +} + +void SetCameraExposureAuto(CS_Source source, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetExposureAuto(status); +} + +void SetCameraExposureHoldCurrent(CS_Source source, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetExposureHoldCurrent(status); +} + +void SetCameraExposureManual(CS_Source source, int value, CS_Status* status) { + auto data = Sources::GetInstance().Get(source); + if (!data) { + *status = CS_INVALID_HANDLE; + return; + } + data->source->SetExposureManual(value, status); +} + // // Sink Functions //