Skip to content

Commit 7b224a9

Browse files
committed
Use InetAddress.localhost() for getting hostname, add test for mat copy
1 parent 86829a7 commit 7b224a9

File tree

2 files changed

+93
-44
lines changed

2 files changed

+93
-44
lines changed

core/src/main/java/edu/wpi/grip/core/operations/composite/PublishVideoOperation.java

+19-44
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import edu.wpi.grip.core.sockets.SocketHints;
88
import edu.wpi.grip.core.util.Icon;
99

10+
import com.google.common.annotations.VisibleForTesting;
1011
import com.google.common.collect.ImmutableList;
1112

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

20-
import org.apache.commons.lang.SystemUtils;
2121
import org.bytedeco.javacpp.opencv_core;
2222
import org.opencv.core.Mat;
2323

24-
import java.io.BufferedReader;
25-
import java.io.IOException;
26-
import java.io.InputStreamReader;
2724
import java.lang.reflect.Field;
28-
import java.util.Arrays;
25+
import java.net.InetAddress;
26+
import java.net.UnknownHostException;
2927
import java.util.Deque;
3028
import java.util.LinkedList;
3129
import java.util.List;
@@ -115,8 +113,16 @@ public PublishVideoOperation(InputSocket.Factory inputSocketFactory) {
115113
server.setSource(serverSource);
116114

117115
ourTable = cameraPublisherTable.getSubTable("GRIP-" + totalStepCount);
118-
ourTable.putStringArray("streams",
119-
new String[]{"mjpeg:http://" + getHostName() + ":" + ourPort + "/?action=stream"});
116+
try {
117+
InetAddress localHost = InetAddress.getLocalHost();
118+
ourTable.putStringArray("streams",
119+
new String[]{
120+
generateStreamUrl(localHost.getHostName(), ourPort),
121+
generateStreamUrl(localHost.getHostAddress(), ourPort)
122+
});
123+
} catch (UnknownHostException e) {
124+
ourTable.putStringArray("streams", new String[0]);
125+
}
120126
} else {
121127
server = null;
122128
serverSource = null;
@@ -177,6 +183,10 @@ public synchronized void cleanUp() {
177183
}
178184
}
179185

186+
private static String generateStreamUrl(String host, int port) {
187+
return String.format("mjpeg:http://%s:%d/?action=stream", host, port);
188+
}
189+
180190
/**
181191
* Copies the data from a JavaCV Mat wrapper object into an OpenCV Mat wrapper object so it's
182192
* usable by the {@link CvSource} for this operation.
@@ -195,7 +205,8 @@ public synchronized void cleanUp() {
195205
* @param openCvMat the OpenCV Mat wrapper object to copy into
196206
* @throws RuntimeException if the OpenCV native pointer could not be set
197207
*/
198-
private static void copyJavaCvToOpenCvMat(opencv_core.Mat javaCvMat, Mat openCvMat)
208+
@VisibleForTesting
209+
static void copyJavaCvToOpenCvMat(opencv_core.Mat javaCvMat, Mat openCvMat)
199210
throws RuntimeException {
200211
// Make the OpenCV Mat object point to the same block of memory as the JavaCV object.
201212
// This requires no data transfers or copies and is O(1) instead of O(n)
@@ -211,40 +222,4 @@ private static void copyJavaCvToOpenCvMat(opencv_core.Mat javaCvMat, Mat openCvM
211222
}
212223
}
213224

214-
/**
215-
* Multi platform method for getting the hostname of the local computer. cscore's
216-
* {@link CameraServerJNI#getHostname() getHostName() function} only works on Linux, so we need to
217-
* implement the method for Windows and Mac ourselves.
218-
*/
219-
private static String getHostName() {
220-
if (SystemUtils.IS_OS_WINDOWS) {
221-
// Use the Windows `hostname` command-line utility
222-
// This will return a single line of text containing the hostname, no parsing required
223-
ProcessBuilder builder = new ProcessBuilder("hostname");
224-
Process hostname;
225-
try {
226-
hostname = builder.start();
227-
} catch (IOException e) {
228-
logger.log(Level.WARNING, "Could not start hostname process", e);
229-
return "";
230-
}
231-
try (BufferedReader in =
232-
new BufferedReader(new InputStreamReader(hostname.getInputStream()))) {
233-
return in.readLine() + ".local";
234-
} catch (IOException e) {
235-
logger.log(Level.WARNING, "Could not read the hostname process output", e);
236-
return "";
237-
}
238-
} else if (SystemUtils.IS_OS_LINUX) {
239-
// cscore already defines it for linux
240-
return CameraServerJNI.getHostname();
241-
} else if (SystemUtils.IS_OS_MAC) {
242-
// todo
243-
return "TODO-MAC";
244-
} else {
245-
throw new UnsupportedOperationException(
246-
"Unsupported operating system " + System.getProperty("os.name"));
247-
}
248-
}
249-
250225
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package edu.wpi.grip.core.operations.composite;
2+
3+
import edu.wpi.grip.util.Files;
4+
5+
import org.bytedeco.javacpp.opencv_core;
6+
import org.junit.BeforeClass;
7+
import org.junit.Test;
8+
import org.opencv.core.Mat;
9+
10+
import java.nio.ByteBuffer;
11+
12+
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
13+
import static org.junit.Assert.assertArrayEquals;
14+
import static org.junit.Assert.assertEquals;
15+
import static org.junit.Assert.assertThat;
16+
17+
public class PublishVideoOperationTest {
18+
19+
@BeforeClass
20+
public static void initialize() {
21+
// Make sure the OpenCV JNI is loaded
22+
blackHole(PublishVideoOperation.DESCRIPTION);
23+
}
24+
25+
@Test
26+
public void testCopyJavaCvToOpenCvMat_GompeiImage() {
27+
// given
28+
final Mat openCvMat = new Mat();
29+
30+
// then (with the GRIP logo)
31+
test(Files.imageFile.createMat(), openCvMat);
32+
33+
// and again (with gompei) to confirm that changing the input will be cleanly copied to the
34+
// output image and cleanly overwrite any existing data
35+
test(Files.gompeiJpegFile.createMat(), openCvMat);
36+
}
37+
38+
private static void test(opencv_core.Mat javaCvMat, Mat openCvMat) {
39+
// when
40+
PublishVideoOperation.copyJavaCvToOpenCvMat(javaCvMat, openCvMat);
41+
42+
// then
43+
44+
// test the basic properties (same size, type, etc.)
45+
assertEquals("Wrong width", javaCvMat.cols(), openCvMat.cols());
46+
assertEquals("Wrong height", javaCvMat.rows(), openCvMat.rows());
47+
assertEquals("Wrong type", javaCvMat.type(), openCvMat.type());
48+
assertEquals("Wrong channel amount", javaCvMat.channels(), openCvMat.channels());
49+
assertEquals("Wrong bit depth", javaCvMat.depth(), openCvMat.depth());
50+
51+
// test the raw data bytes - they should be identical
52+
final int width = javaCvMat.cols();
53+
final int height = javaCvMat.rows();
54+
final int channels = javaCvMat.channels();
55+
56+
final ByteBuffer buffer = javaCvMat.createBuffer();
57+
assertThat("JavaCV byte buffer is smaller than expected!",
58+
buffer.capacity(), greaterThanOrEqualTo(width * height * channels));
59+
60+
final byte[] javaCvData = new byte[width * height * channels];
61+
buffer.get(javaCvData);
62+
63+
final byte[] openCvData = new byte[width * height * channels];
64+
openCvMat.get(0, 0, openCvData);
65+
66+
assertArrayEquals("Wrong data bytes", javaCvData, openCvData);
67+
}
68+
69+
// workaround for FindBugs reporting unused variables
70+
private static void blackHole(Object ignore) {
71+
// nop
72+
}
73+
74+
}

0 commit comments

Comments
 (0)