diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-03-09 05:39:28 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-03-09 05:39:28 -0500 |
commit | 42ff123fea0f9fb8ed0c40ce2c3e21b64ff4bbf0 (patch) | |
tree | 7a3f3dcba9552aad91e627ed1e47ff93e6e616dd /extensions/WPIJavaCVVideoExtension/src | |
parent | 51eefb8b38bd5aa13f7940368317c481dfe7dde4 (diff) |
Clean up extensions.
Renaming, code de-duplication
Diffstat (limited to 'extensions/WPIJavaCVVideoExtension/src')
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(); + } + } +} |