summaryrefslogtreecommitdiff
path: root/extensions/WPIJavaCVVideoExtension/src
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-03-09 05:39:28 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-03-09 05:39:28 -0500
commit42ff123fea0f9fb8ed0c40ce2c3e21b64ff4bbf0 (patch)
tree7a3f3dcba9552aad91e627ed1e47ff93e6e616dd /extensions/WPIJavaCVVideoExtension/src
parent51eefb8b38bd5aa13f7940368317c481dfe7dde4 (diff)
Clean up extensions.
Renaming, code de-duplication
Diffstat (limited to 'extensions/WPIJavaCVVideoExtension/src')
-rw-r--r--extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AbstractVideoExtension.java166
-rw-r--r--extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AxisCameraExtension.java51
-rw-r--r--extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/LaptopCameraExtension.java39
-rw-r--r--extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/Video.java13
-rw-r--r--extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/VideoURLExtension.java50
5 files changed, 319 insertions, 0 deletions
diff --git a/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AbstractVideoExtension.java b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AbstractVideoExtension.java
new file mode 100644
index 0000000..9324232
--- /dev/null
+++ b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AbstractVideoExtension.java
@@ -0,0 +1,166 @@
+package edu.wpi.first.smartdashboard.extensions.wpijavacvvideo;
+
+import edu.wpi.first.smartdashboard.gui.DashboardPrefs;
+import edu.wpi.first.smartdashboard.gui.StaticWidget;
+import edu.wpi.first.smartdashboard.properties.Property;
+import edu.wpi.first.smartdashboard.properties.StringProperty;
+import edu.wpi.first.wpijavacv.WPIColorImage;
+import edu.wpi.first.wpijavacv.WPIFFmpegVideo;
+import edu.wpi.first.wpijavacv.WPIGrayscaleImage;
+import edu.wpi.first.wpijavacv.WPIImage;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.image.BufferedImage;
+
+/**
+ * An extension that displays a video.
+ *
+ * @author Greg Granito
+ * @author Luke Shumaker
+ */
+public abstract class AbstractVideoExtension extends StaticWidget {
+ public static final String NAME = null;
+ protected static final long errorBackoff = -1;
+ abstract protected Video getVideo();
+ abstract protected boolean isVideoProperty(Property property);
+
+ private boolean connected = false;
+
+ public class GCThread extends Thread {
+
+ boolean destroyed = false;
+
+ @Override
+ public void run() {
+ while (!destroyed) {
+ try {
+ Thread.sleep(10000);
+ } catch (InterruptedException ex) {
+ }
+ System.gc();
+ }
+ }
+
+ public void destroy() {
+ destroyed = true;
+ interrupt();
+ }
+ }
+
+ public class BGThread extends Thread {
+
+ boolean destroyed = false;
+
+ public BGThread() {
+ super(NAME+" Background");
+ }
+
+ @Override
+ public void run() {
+ WPIImage image;
+ while (!destroyed) {
+ if (vid == null) {
+ vid = getVideo();
+ }
+ try {
+ image = vid.getImage();
+
+ if (image instanceof WPIColorImage) {
+ drawnImage = processImage((WPIColorImage) image).getBufferedImage();
+ } else if (image instanceof WPIGrayscaleImage) {
+ drawnImage = processImage((WPIGrayscaleImage) image).getBufferedImage();
+ }
+
+ repaint();
+ } catch (final Exception e) {
+ e.printStackTrace();
+ vid.dispose();
+ vid = null;
+ drawnImage = null;
+ repaint();
+ try {
+ Thread.sleep(errorBackoff);
+ } catch (InterruptedException ex) {
+ }
+ }
+ }
+
+ }
+
+ @Override
+ public void destroy() {
+ destroyed = true;
+ }
+ }
+ private boolean resized = false;
+ private Video vid;
+ private BufferedImage drawnImage;
+ private BGThread bgThread = new BGThread();
+ private GCThread gcThread = new GCThread();
+
+ @Override
+ public void init() {
+ setPreferredSize(new Dimension(100, 100));
+ bgThread.start();
+ gcThread.start();
+ revalidate();
+ repaint();
+ }
+
+ @Override
+ public void propertyChanged(Property property) {
+ if (isVideoProperty(property)) {
+ if (vid != null) {
+ vid.dispose();
+ }
+ try {
+ vid = getVideo();
+ } catch (Exception e) {
+ e.printStackTrace();
+ drawnImage = null;
+ setPreferredSize(new Dimension(100, 100));
+ revalidate();
+ repaint();
+ }
+ }
+
+ }
+
+ @Override
+ public void disconnect() {
+ bgThread.destroy();
+ gcThread.destroy();
+ if(vid != null) vid.dispose();
+ super.disconnect();
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ if (drawnImage != null) {
+ if (!resized) {
+ setPreferredSize(new Dimension(drawnImage.getWidth(), drawnImage.getHeight()));
+ revalidate();
+ }
+ int width = getBounds().width;
+ int height = getBounds().height;
+ double scale = Math.min((double) width / (double) drawnImage.getWidth(), (double) height / (double) drawnImage.getHeight());
+ g.drawImage(drawnImage, (int) (width - (scale * drawnImage.getWidth())) / 2, (int) (height - (scale * drawnImage.getHeight())) / 2,
+ (int) ((width + scale * drawnImage.getWidth()) / 2), (int) (height + scale * drawnImage.getHeight()) / 2,
+ 0, 0, drawnImage.getWidth(), drawnImage.getHeight(), null);
+ } else {
+ g.setColor(Color.PINK);
+ g.fillRect(0, 0, getBounds().width, getBounds().height);
+ g.setColor(Color.BLACK);
+ g.drawString("NO CONNECTION", 10, 10);
+ }
+ }
+
+ public WPIImage processImage(WPIColorImage rawImage) {
+ return rawImage;
+ }
+
+ public WPIImage processImage(WPIGrayscaleImage rawImage) {
+ return rawImage;
+ }
+}
diff --git a/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AxisCameraExtension.java b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AxisCameraExtension.java
new file mode 100644
index 0000000..6851dfc
--- /dev/null
+++ b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/AxisCameraExtension.java
@@ -0,0 +1,51 @@
+package edu.wpi.first.smartdashboard.extensions.wpijavacvvideo;
+
+import edu.wpi.first.smartdashboard.gui.DashboardPrefs;
+import edu.wpi.first.smartdashboard.properties.IPAddressProperty;
+import edu.wpi.first.smartdashboard.properties.Property;
+import edu.wpi.first.wpijavacv.WPICamera;
+import edu.wpi.first.wpijavacv.WPIImage;
+
+/**
+ * Exactly like VideoURLExtension, except it forces the Stream URL
+ * to be of the form "http://${IP_address}/mjpg/video.mjpg" and only
+ * lets the user configure the IP address.
+ *
+ * @author Greg Granito
+ */
+public class AxisCameraExtension extends AbstractVideoExtension {
+ public static final String NAME = "Axis Camera";
+ protected static final long errorBackoff = 2000;
+
+ @Override
+ protected Video getVideo() {
+ return new Camera(new WPICamera(ipProperty.getSaveValue()), 5.0);
+ }
+
+ @Override
+ protected boolean isVideoProperty(Property property) {
+ return property == ipProperty;
+ }
+
+ public final IPAddressProperty ipProperty = new IPAddressProperty(this, "Axis Camera IP Address", defaultIPaddress());
+
+ private final int[] defaultIPaddress() {
+ final int team = DashboardPrefs.getInstance().team.getValue();
+ return new int[]{10, team / 100, team % 100, 11};
+ }
+
+ public class Camera implements Video {
+ private final WPICamera vid;
+ private final double timeout;
+ public Camera(WPICamera vid, double timeout){
+ this.vid = vid;
+ this.timeout = timeout;
+ }
+ public WPIImage getImage() throws Exception {
+ return vid.getNewImage(timeout);
+ }
+ public void dispose() {
+ vid.dispose();
+ }
+ }
+}
diff --git a/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/LaptopCameraExtension.java b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/LaptopCameraExtension.java
new file mode 100644
index 0000000..03fa943
--- /dev/null
+++ b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/LaptopCameraExtension.java
@@ -0,0 +1,39 @@
+package edu.wpi.first.smartdashboard.extensions.wpijavacvvideo;
+
+import edu.wpi.first.smartdashboard.properties.Property;
+import edu.wpi.first.wpijavacv.WPIImage;
+import edu.wpi.first.wpijavacv.WPILaptopCamera;
+
+/**
+ * An extension that displays the laptop built-in camera.
+ *
+ * @author Greg Granito
+ * @author Luke Shumaker
+ */
+public class LaptopCameraExtension extends AbstractVideoExtension {
+ public static final String NAME = "Laptop Camera";
+ protected static final long errorBackoff = 500;
+
+ @Override
+ protected Video getVideo() {
+ return new Camera(new WPILaptopCamera());
+ }
+
+ @Override
+ protected boolean isVideoProperty(Property property) {
+ return false;
+ }
+
+ public class Camera implements Video {
+ private final WPILaptopCamera vid;
+ public Camera(WPILaptopCamera vid){
+ this.vid = vid;
+ }
+ public WPIImage getImage() {
+ return vid.getCurrentFrame();
+ }
+ public void dispose() {
+ vid.dispose();
+ }
+ }
+}
diff --git a/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/Video.java b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/Video.java
new file mode 100644
index 0000000..8187701
--- /dev/null
+++ b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/Video.java
@@ -0,0 +1,13 @@
+package edu.wpi.first.smartdashboard.extensions.wpijavacvvideo;
+
+import edu.wpi.first.wpijavacv.WPIImage;
+
+/**
+ * The basics of what you need out of a video source.
+ *
+ * @author Luke Shumaker
+ */
+public interface Video {
+ public WPIImage getImage() throws Exception;
+ public void dispose();
+}
diff --git a/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/VideoURLExtension.java b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/VideoURLExtension.java
new file mode 100644
index 0000000..bbe4d6b
--- /dev/null
+++ b/extensions/WPIJavaCVVideoExtension/src/edu/wpi/first/smartdashboard/extensions/wpijavacvvideo/VideoURLExtension.java
@@ -0,0 +1,50 @@
+package edu.wpi.first.smartdashboard.extensions.wpijavacvvideo;
+
+import edu.wpi.first.smartdashboard.gui.DashboardPrefs;
+import edu.wpi.first.smartdashboard.properties.Property;
+import edu.wpi.first.smartdashboard.properties.StringProperty;
+import edu.wpi.first.wpijavacv.WPIFFmpegVideo;
+import edu.wpi.first.wpijavacv.WPIImage;
+
+/**
+ * An extension that takes a video stream URL and displays the video.
+ *
+ * @author Greg Granito
+ * @author Luke Shumaker
+ */
+public class VideoURLExtension extends AbstractVideoExtension {
+ public static final String NAME = "Video URL Stream";
+ protected static final long errorBackoff = 2000;
+
+ @Override
+ protected Video getVideo() {
+ return new Camera(new WPIFFmpegVideo(pathProperty.getSaveValue()), 5.0);
+ }
+
+ @Override
+ protected boolean isVideoProperty(Property property) {
+ return property == pathProperty;
+ }
+
+ public final StringProperty pathProperty = new StringProperty(this, "Video Path", defaultVideoPath());
+
+ private static String defaultVideoPath() {
+ final int team = DashboardPrefs.getInstance().team.getValue();
+ return "http://10." + (team / 100) + "." + (team % 100) + ".11/mjpg/video.mjpg";
+ }
+
+ public class Camera implements Video {
+ private final WPIFFmpegVideo vid;
+ private final double timeout;
+ public Camera(WPIFFmpegVideo vid, double timeout){
+ this.vid = vid;
+ this.timeout = timeout;
+ }
+ public WPIImage getImage() throws Exception {
+ return vid.getNewImage(timeout);
+ }
+ public void dispose() {
+ vid.dispose();
+ }
+ }
+}