CameraServer: auto-increment startAutomaticCapture(). (#468)

Also add GetServer() functions so the automatically created VideoSink can
be retrieved by user code if desired.
This commit is contained in:
Peter Johnson
2017-01-20 01:07:37 -07:00
committed by GitHub
parent ff141ab1ff
commit e375b4a9ff
3 changed files with 83 additions and 6 deletions

View File

@@ -7,6 +7,7 @@
#pragma once
#include <atomic>
#include <memory>
#include <mutex>
#include <string>
@@ -44,8 +45,10 @@ class CameraServer : public ErrorBase {
* If you also want to perform vision processing on the roboRIO, use
* getVideo() to get access to the camera images.
*
* This overload calls {@link #StartAutomaticCapture(int)} with device 0,
* creating a camera named "USB Camera 0".
* The first time this overload is called, it calls
* {@link #StartAutomaticCapture(int)} with device 0, creating a camera
* named "USB Camera 0". Subsequent calls increment the device number
* (e.g. 1, 2, etc).
*/
cs::UsbCamera StartAutomaticCapture();
@@ -241,6 +244,21 @@ class CameraServer : public ErrorBase {
*/
void RemoveServer(llvm::StringRef name);
/**
* Get server for the primary camera feed.
*
* <p>This is only valid to call after a camera feed has been added
* with StartAutomaticCapture() or AddServer().
*/
cs::VideoSink GetServer();
/**
* Gets a server by name.
*
* @param name Server name
*/
cs::VideoSink GetServer(llvm::StringRef name);
/**
* Adds an already created camera.
*
@@ -277,6 +295,7 @@ class CameraServer : public ErrorBase {
static constexpr char const* kPublishName = "/CameraPublisher";
std::mutex m_mutex;
std::atomic<int> m_defaultUsbDevice;
std::string m_primarySourceName;
llvm::StringMap<cs::VideoSource> m_sources;
llvm::StringMap<cs::VideoSink> m_sinks;

View File

@@ -486,7 +486,7 @@ CameraServer::CameraServer()
}
cs::UsbCamera CameraServer::StartAutomaticCapture() {
return StartAutomaticCapture(0);
return StartAutomaticCapture(m_defaultUsbDevice++);
}
cs::UsbCamera CameraServer::StartAutomaticCapture(int dev) {
@@ -659,6 +659,33 @@ void CameraServer::RemoveServer(llvm::StringRef name) {
m_sinks.erase(name);
}
cs::VideoSink CameraServer::GetServer() {
llvm::SmallString<64> name;
{
std::lock_guard<std::mutex> lock(m_mutex);
if (m_primarySourceName.empty()) {
wpi_setWPIErrorWithContext(CameraServerError, "no camera available");
return cs::VideoSink{};
}
name = "serve_";
name += m_primarySourceName;
}
return GetServer(name);
}
cs::VideoSink CameraServer::GetServer(llvm::StringRef name) {
std::lock_guard<std::mutex> lock(m_mutex);
auto it = m_sinks.find(name);
if (it == m_sinks.end()) {
llvm::SmallString<64> buf;
llvm::raw_svector_ostream err{buf};
err << "could not find server " << name;
wpi_setWPIErrorWithContext(CameraServerError, err.str());
return cs::VideoSink{};
}
return it->second;
}
void CameraServer::AddCamera(const cs::VideoSource& camera) {
std::string name = camera.GetName();
std::lock_guard<std::mutex> lock(m_mutex);

View File

@@ -24,6 +24,7 @@ import edu.wpi.cscore.VideoSource;
import edu.wpi.first.wpilibj.networktables.NetworkTable;
import edu.wpi.first.wpilibj.networktables.NetworkTablesJNI;
import edu.wpi.first.wpilibj.tables.ITable;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.regex.Matcher;
@@ -56,6 +57,7 @@ public class CameraServer {
return server;
}
private AtomicInteger m_defaultUsbDevice;
private String m_primarySourceName;
private final Hashtable<String, VideoSource> m_sources;
private final Hashtable<String, VideoSink> m_sinks;
@@ -330,6 +332,7 @@ public class CameraServer {
@SuppressWarnings({"JavadocMethod", "PMD.UnusedLocalVariable"})
private CameraServer() {
m_defaultUsbDevice = new AtomicInteger();
m_sources = new Hashtable<String, VideoSource>();
m_sinks = new Hashtable<String, VideoSink>();
m_tables = new Hashtable<Integer, ITable>();
@@ -513,11 +516,13 @@ public class CameraServer {
* If you also want to perform vision processing on the roboRIO, use
* getVideo() to get access to the camera images.
*
* <p>This overload calls {@link #startAutomaticCapture(int)} with device 0,
* creating a camera named "USB Camera 0".
* <p>The first time this overload is called, it calls
* {@link #startAutomaticCapture(int)} with device 0, creating a camera
* named "USB Camera 0". Subsequent calls increment the device number
* (e.g. 1, 2, etc).
*/
public UsbCamera startAutomaticCapture() {
return startAutomaticCapture(0);
return startAutomaticCapture(m_defaultUsbDevice.getAndIncrement());
}
/**
@@ -745,6 +750,32 @@ public class CameraServer {
}
}
/**
* Get server for the primary camera feed.
*
* <p>This is only valid to call after a camera feed has been added
* with startAutomaticCapture() or addServer().
*/
public VideoSink getServer() {
synchronized (this) {
if (m_primarySourceName == null) {
throw new VideoException("no camera available");
}
return getServer("serve_" + m_primarySourceName);
}
}
/**
* Gets a server by name.
*
* @param name Server name
*/
public VideoSink getServer(String name) {
synchronized (this) {
return m_sinks.get(name);
}
}
/**
* Adds an already created camera.
*