Skip to content

Commit

Permalink
Use InetAddress.localhost() for getting hostname, add test for mat copy
Browse files Browse the repository at this point in the history
  • Loading branch information
SamCarlberg committed Nov 9, 2017
1 parent 86829a7 commit a65ffd2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import edu.wpi.grip.core.sockets.SocketHints;
import edu.wpi.grip.core.util.Icon;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
Expand All @@ -17,15 +18,12 @@
import edu.wpi.first.wpilibj.networktables.NetworkTable;
import edu.wpi.first.wpilibj.tables.ITable;

import org.apache.commons.lang.SystemUtils;
import org.bytedeco.javacpp.opencv_core;
import org.opencv.core.Mat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
Expand Down Expand Up @@ -115,8 +113,16 @@ public PublishVideoOperation(InputSocket.Factory inputSocketFactory) {
server.setSource(serverSource);

ourTable = cameraPublisherTable.getSubTable("GRIP-" + totalStepCount);
ourTable.putStringArray("streams",
new String[]{"mjpeg:http://" + getHostName() + ":" + ourPort + "/?action=stream"});
try {
InetAddress localHost = InetAddress.getLocalHost();
ourTable.putStringArray("streams",
new String[]{
generateStreamUrl(localHost.getHostName(), ourPort),
generateStreamUrl(localHost.getHostAddress(), ourPort)
});
} catch (UnknownHostException e) {
ourTable.putStringArray("streams", new String[0]);
}
} else {
server = null;
serverSource = null;
Expand Down Expand Up @@ -177,6 +183,10 @@ public synchronized void cleanUp() {
}
}

private static String generateStreamUrl(String host, int port) {
return String.format("mjpeg:http://%s:%d/?action=stream", host, port);
}

/**
* Copies the data from a JavaCV Mat wrapper object into an OpenCV Mat wrapper object so it's
* usable by the {@link CvSource} for this operation.
Expand All @@ -195,7 +205,8 @@ public synchronized void cleanUp() {
* @param openCvMat the OpenCV Mat wrapper object to copy into
* @throws RuntimeException if the OpenCV native pointer could not be set
*/
private static void copyJavaCvToOpenCvMat(opencv_core.Mat javaCvMat, Mat openCvMat)
@VisibleForTesting
static void copyJavaCvToOpenCvMat(opencv_core.Mat javaCvMat, Mat openCvMat)
throws RuntimeException {
// Make the OpenCV Mat object point to the same block of memory as the JavaCV object.
// This requires no data transfers or copies and is O(1) instead of O(n)
Expand All @@ -211,40 +222,4 @@ private static void copyJavaCvToOpenCvMat(opencv_core.Mat javaCvMat, Mat openCvM
}
}

/**
* Multi platform method for getting the hostname of the local computer. cscore's
* {@link CameraServerJNI#getHostname() getHostName() function} only works on Linux, so we need to
* implement the method for Windows and Mac ourselves.
*/
private static String getHostName() {
if (SystemUtils.IS_OS_WINDOWS) {
// Use the Windows `hostname` command-line utility
// This will return a single line of text containing the hostname, no parsing required
ProcessBuilder builder = new ProcessBuilder("hostname");
Process hostname;
try {
hostname = builder.start();
} catch (IOException e) {
logger.log(Level.WARNING, "Could not start hostname process", e);
return "";
}
try (BufferedReader in =
new BufferedReader(new InputStreamReader(hostname.getInputStream()))) {
return in.readLine() + ".local";
} catch (IOException e) {
logger.log(Level.WARNING, "Could not read the hostname process output", e);
return "";
}
} else if (SystemUtils.IS_OS_LINUX) {
// cscore already defines it for linux
return CameraServerJNI.getHostname();
} else if (SystemUtils.IS_OS_MAC) {
// todo
return "TODO-MAC";
} else {
throw new UnsupportedOperationException(
"Unsupported operating system " + System.getProperty("os.name"));
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package edu.wpi.grip.core.operations.composite;

import edu.wpi.grip.util.Files;

import org.bytedeco.javacpp.opencv_core;
import org.junit.BeforeClass;
import org.junit.Test;
import org.opencv.core.Mat;

import java.nio.ByteBuffer;

import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class PublishVideoOperationTest {

@BeforeClass
public static void initialize() {
// Make sure the OpenCV JNI is loaded
blackHole(PublishVideoOperation.DESCRIPTION);
}

@Test
public void testCopyJavaCvToOpenCvMat() {
// given
final Mat openCvMat = new Mat();

// then (with the GRIP logo)
test(Files.imageFile.createMat(), openCvMat);

// and again (with gompei) to confirm that changing the input will be cleanly copied to the
// output image and cleanly overwrite any existing data
test(Files.gompeiJpegFile.createMat(), openCvMat);
}

private static void test(opencv_core.Mat javaCvMat, Mat openCvMat) {
// when
PublishVideoOperation.copyJavaCvToOpenCvMat(javaCvMat, openCvMat);

// then

// test the basic properties (same size, type, etc.)
assertEquals("Wrong width", javaCvMat.cols(), openCvMat.cols());
assertEquals("Wrong height", javaCvMat.rows(), openCvMat.rows());
assertEquals("Wrong type", javaCvMat.type(), openCvMat.type());
assertEquals("Wrong channel amount", javaCvMat.channels(), openCvMat.channels());
assertEquals("Wrong bit depth", javaCvMat.depth(), openCvMat.depth());

// test the raw data bytes - they should be identical
final int width = javaCvMat.cols();
final int height = javaCvMat.rows();
final int channels = javaCvMat.channels();

final ByteBuffer buffer = javaCvMat.createBuffer();
assertThat("JavaCV byte buffer is smaller than expected!",
buffer.capacity(), greaterThanOrEqualTo(width * height * channels));

final byte[] javaCvData = new byte[width * height * channels];
buffer.get(javaCvData);

final byte[] openCvData = new byte[width * height * channels];
openCvMat.get(0, 0, openCvData);

assertArrayEquals("Wrong data bytes", javaCvData, openCvData);
}

// workaround for FindBugs reporting unused variables
private static void blackHole(Object ignore) {
// nop
}

}

0 comments on commit a65ffd2

Please sign in to comment.