removed swig
It was always kind of a pain to maintain, and nobody has ever used it,
and I doubt if it would work currently after other changes.
diff --git a/aos/linux_code/camera/camera.gyp b/aos/linux_code/camera/camera.gyp
index fabd52f..119d105 100644
--- a/aos/linux_code/camera/camera.gyp
+++ b/aos/linux_code/camera/camera.gyp
@@ -1,44 +1,6 @@
{
'targets': [
{
- 'target_name': 'aos_camera',
- 'type': 'loadable_module',
- 'sources': [
- 'jni.cpp',
- ],
- 'dependencies': [
- '<(AOS)/common/network/network.gyp:socket_so',
- '<(AOS)/common/common.gyp:timing_so',
- 'private_aos_camera_jar',
- '<(EXTERNALS):libjpeg',
- ],
- 'export_dependent_settings': [
- '<(AOS)/common/network/network.gyp:socket_so',
- '<(AOS)/common/common.gyp:timing_so',
- 'private_aos_camera_jar',
- ],
- },
- {
- 'target_name': 'private_aos_camera_jar',
- 'dependencies': [
- '<(EXTERNALS):javacv',
- ],
- 'variables': {
- 'srcdirs': ['java'],
- 'gen_headers': ['aos.Natives'],
- },
- 'export_dependent_settings': [
- '<(EXTERNALS):javacv',
- ],
- 'direct_dependent_settings': {
- 'variables': {
- 'jni_libs': ['aos_camera'],
- },
- },
- 'includes': ['../../build/java.gypi'],
- 'hard_dependency': 1,
- },
- {
'target_name': 'buffers',
'type': 'static_library',
'sources': [
diff --git a/aos/linux_code/camera/java/aos/CameraProcessor.java b/aos/linux_code/camera/java/aos/CameraProcessor.java
deleted file mode 100644
index 4f6c68d..0000000
--- a/aos/linux_code/camera/java/aos/CameraProcessor.java
+++ /dev/null
@@ -1,67 +0,0 @@
-package aos;
-
-import java.io.IOException;
-import java.net.Inet4Address;
-import java.net.InetSocketAddress;
-import java.net.UnknownHostException;
-import java.nio.ByteBuffer;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.SocketChannel;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.googlecode.javacv.cpp.opencv_core;
-
-/**
- * Makes implementing code that processes frames from a camera easy.
- */
-public abstract class CameraProcessor {
- private static final Logger LOG = Logger.getLogger(CameraProcessor.class.getName());
- protected final ImageGetter getter;
- protected final ServableImage start = new ServableImage(ImageGetter.width, ImageGetter.height, opencv_core.IPL_DEPTH_8U, 3);
-
- /**
- * Parses any arguments it recognizes out of {@code args} and initializes stuff appropriately.
- * This includes using {@link QueueLogHandler} for all exceptions and {@link Thread#setDefaultUncaughtExceptionHandler}ing.
- * @param args from {@code main}
- */
- protected CameraProcessor(String[] args) throws UnknownHostException, IOException {
- QueueLogHandler.UseForAll();
- ReadableByteChannel channel = null;
- for (int i = 0; i < args.length; ++i) {
- final String c = args[i];
- if (c.equals("--host")) {
- String host = args[++i];
- final SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(Inet4Address.getByName(host), 9714));
- socketChannel.write(ByteBuffer.wrap(new byte[] {'\r', '\n', '\r', '\n'})); // get it past the read headers stage
- channel = socketChannel;
- } else {
- System.err.println("CameraProcessor: warning: unrecognized argument '" + c + "'. ignoring");
- }
- }
-
- if (channel != null) {
- getter = new ChannelImageGetter(channel);
- } else {
- System.out.println("creating QueueImageGetter");
- getter = new QueueImageGetter();
- System.out.println("done");
- }
-
- LOG.log(Level.INFO, "CameraProcessor is up");
- System.err.println("CameraProcessor is up (on stderr)");
- }
-
- protected abstract void RunIteration();
-
- protected void Run() {
- while (true) {
- if (!getter.get(start.getImage())) {
- LOG.log(Level.WARNING, "getting image failed");
- continue;
- }
- RunIteration();
- start.releaseImage();
- }
- }
-}
diff --git a/aos/linux_code/camera/java/aos/ChannelImageGetter.java b/aos/linux_code/camera/java/aos/ChannelImageGetter.java
deleted file mode 100644
index 511b55b..0000000
--- a/aos/linux_code/camera/java/aos/ChannelImageGetter.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package aos;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.channels.ReadableByteChannel;
-import java.nio.channels.SelectableChannel;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * Retrieves images from a {@link InputChannel}. Expects the images in mjpg form.
- * For now, only accepts streams formatted pretty closely to how aos::camera::HTTPStreamer does it.
- */
-public class ChannelImageGetter extends JPEGImageGetter {
- /**
- * What to multiply each length by when it needs to allocate a larger buffer to fit an image.
- */
- private static final double extraLength = 1.2;
-
- private static final Logger LOG = Logger.getLogger(ChannelImageGetter.class
- .getName());
- private final ReadableByteChannel channel;
- private final Selector selector = Selector.open();
- private String separator = "--boundarydonotcross\r\n";
- private ByteBuffer current;
- private final ByteBuffer headerBuffer = ByteBuffer.allocateDirect(30);
- private final Map<String, String> headers = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
-
- public ChannelImageGetter(ReadableByteChannel channel) throws IOException {
- this.channel = channel;
- if (channel instanceof SelectableChannel) {
- ((SelectableChannel)channel).configureBlocking(false);
- }
- }
-
- @Override
- public ByteBuffer getJPEG() {
- try {
- if (!parseHeaders()) {
- return null;
- }
- LOG.log(Level.FINE, "parsed headers " + headers.toString());
- try {
- final int length = Integer.parseInt(headers.get("Content-Length"));
- if (current == null || current.capacity() < length) {
- LOG.log(Level.INFO, "allocating a new direct buffer of length " + length * extraLength);
- current = ByteBuffer.allocateDirect((int) (length * extraLength));
- } else {
- current.rewind();
- current.limit(length);
- }
- } catch (NumberFormatException e) {
- LOG.log(Level.WARNING, "couldn't parse '" + headers.get("Content-Length") + "' as a number");
- return null;
- }
- current.put(headerBuffer); // copy out any of the image that got buffered with the headers
- while (current.hasRemaining()) {
- channel.read(current);
- }
- current.flip();
- } catch (IOException e) {
- LOG.log(Level.WARNING, "reading the headers and/or image failed", e);
- return null;
- }
- return current;
- }
- // returns success
- private boolean parseHeaders() throws IOException {
- // Reads chunks into headerBuffer and parses out headers.
- // Looks for separator first.
-
- headerBuffer.clear();
- headers.clear();
- final byte[] separatorBytes = separator.getBytes();
- int separatorIndex = 0; // how much of the separator has been matched
- while (headerBuffer.hasRemaining() || headerBuffer.limit() < headerBuffer.capacity()) {
- if (channel instanceof SelectableChannel) {
- ((SelectableChannel)channel).register(selector, SelectionKey.OP_READ);
- selector.select();
- }
- headerBuffer.limit(headerBuffer.capacity());
- channel.read(headerBuffer);
- headerBuffer.flip();
- if (separatorIndex < separatorBytes.length) {
- // make sure we don't get part of the way through
- while (headerBuffer.remaining() >= (separatorBytes.length - separatorIndex)) {
- final byte c = headerBuffer.get();
- if (separatorBytes[separatorIndex++] != c) {
- separatorIndex = 0;
- }
- if (separatorIndex == separatorBytes.length) {
- break;
- }
- }
- headerBuffer.compact();
- } else {
- int keyEnd = 0, valueStart = 0;
- boolean foundEndR = false; // found the end \r
- while (headerBuffer.hasRemaining()) {
- final byte c = headerBuffer.get();
- if (foundEndR) {
- if (c != '\n') {
- LOG.log(Level.WARNING, "found \r\n\r but no \n afterwards");
- } else {
- return true;
- }
- } else if (keyEnd == 0) {
- if (c == ':') {
- keyEnd = headerBuffer.position() - 1;
- } else if (c == '\r') {
- foundEndR = true;
- }
- } else if (valueStart == 0) {
- if (c != ' ') {
- valueStart = headerBuffer.position() - 1;
- }
- } else {
- if (c == '\r') {
- final int valueEnd = headerBuffer.position();
- final byte[] key = new byte[keyEnd];
- headerBuffer.position(0);
- headerBuffer.get(key);
- final byte[] value = new byte[valueEnd - valueStart - 1];
- headerBuffer.position(valueStart);
- headerBuffer.get(value);
- headers.put(new String(key), new String(value));
-
- headerBuffer.get(); // get the \r
- headerBuffer.get(); // get the \n
-
- headerBuffer.compact();
- headerBuffer.flip();
-
- keyEnd = valueStart = 0;
- }
- }
- }
- }
- }
- // if we got here, then it doesn't have space left and we haven't finished
- LOG.log(Level.WARNING, "got a header that was too long. headerBuffer should be made bigger");
- return false;
- }
-
- @Override
- public double getTimestamp() {
- if (headers.containsKey("X-Timestamp")) {
- return Double.parseDouble(headers.get("X-Timestamp"));
- } else {
- throw new UnsupportedOperationException("source stream doesn't have X-Timestamp headers");
- }
- }
-
-}
diff --git a/aos/linux_code/camera/java/aos/DebugServer.java b/aos/linux_code/camera/java/aos/DebugServer.java
deleted file mode 100644
index 398cb11..0000000
--- a/aos/linux_code/camera/java/aos/DebugServer.java
+++ /dev/null
@@ -1,357 +0,0 @@
-package aos;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.channels.ClosedChannelException;
-import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
-import java.nio.channels.ServerSocketChannel;
-import java.nio.channels.SocketChannel;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-/**
- * A server that serves {@link ServableImage}s.
- */
-public class DebugServer {
- private static final String initialHeaderString = "HTTP/1.0 200 OK\r\n"
- + "Connection: close\r\n"
- + "Server: AOS/0.0 Vision Code Debug\r\n"
- + "Cache-Control: no-store, no-cache, must-revalidate, pre-check=0, post-check=0, max-age=0\r\n"
- + "Pragma: no-cache\r\n"
- + "Expires: Mon, 3 Jan 2000 12:34:56 GMT\r\n"
- + "Content-Type: multipart/x-mixed-replace; boundary=boundarydonotcross\r\n";
- private static final String intermediateHeaderFormat = "\r\n--boundarydonotcross\r\n"
- + "Content-Type: image/bmp\r\n"
- + "Content-Length: %d\r\n"
- + "X-Timestamp: %f\r\n"
- + "\r\n";
- private static final ByteBuffer initialHeader;
- private static final Pattern headerPattern;
- static {
- initialHeader = ByteBuffer.wrap(initialHeaderString.getBytes())
- .asReadOnlyBuffer();
- headerPattern = Pattern.compile("^GET ([^? ]+)(?:\\?i=(\\S*))? HTTP/.*\r\n.*$",
- Pattern.DOTALL);
- }
-
- private static final Logger LOG = Logger.getLogger(DebugServer.class
- .getName());
- private final ServerSocketChannel server;
- private final Collection<Client> clients = new ArrayList<Client>();
- private final Map<String, ServableImage> images = new HashMap<String, ServableImage>();
- private final Map<String, Palette> palettes = new HashMap<String, Palette>();
- private double timestamp;
-
- public static class Palette {
- private final ByteArrayOutputStream out = new ByteArrayOutputStream();
- private int entries = 0;
-
- /**
- * Adds a new color. All 4 arguments are unsigned bytes.
- * @param r red
- * @param g green
- * @param b blue
- * @param a alpha (doesn't seem to work)
- * @return this
- */
- public Palette add(int r, int g, int b, int a) {
- out.write(b);
- out.write(g);
- out.write(r);
- out.write(a);
- ++entries;
- return this;
- }
-
- private int entries() {
- return entries;
- }
- private int bytes() {
- return entries * 4;
- }
- private void writeTo(ByteBuffer buffer) {
- buffer.put(out.toByteArray());
- }
- }
-
- private class Client {
- private final int bmpHeaderSize;
- private int bmpType;
- private Palette palette;
-
- private final SocketChannel channel;
- private ServableImage image = null;
- private IplImage img;
- private int index;
- private final ByteBuffer[] buffers;
- private final ByteBuffer initial = initialHeader.duplicate();
- private final ByteBuffer read = ByteBuffer.allocate(1024);
-
- public Client(SocketChannel channel) throws IOException {
- this.channel = channel;
- channel.configureBlocking(false);
-
- if (bmpType == 3) {
- bmpHeaderSize = 122;
- } else if (bmpType == 0) {
- bmpHeaderSize = 54;
- } else {
- throw new AssertionError("unknown bmpType value " + bmpType);
- }
- // [0] gets filled in by createBmpHeader which writes the header into [1]
- // [2] gets set to the image buffer
- buffers = new ByteBuffer[] { null, ByteBuffer.allocate(2048), null };
- }
-
- public void register(Selector selector) throws ClosedChannelException {
- channel.register(
- selector,
- (image == null) ? SelectionKey.OP_READ
- : SelectionKey.OP_WRITE, this);
- }
-
- public void close() {
- if (image != null) {
- image.setDebugging(false);
- }
- if (channel != null) {
- try {
- channel.close();
- } catch (IOException e) {
- LOG.log(Level.WARNING,
- "encountered error when closing channel", e);
- }
- }
- }
-
- private void createBmpHeader(ByteBuffer buffer) {
- // <http://en.wikipedia.org/wiki/BMP_file_format#File_structure>
- // explains what these all are
- // signed/unsigned numbers don't matter because they'd better not be
- // that big
- final int paletteSize = (palette == null) ? 0 : palette.bytes();
- buffers[0] = ByteBuffer.wrap(String.format(intermediateHeaderFormat,
- bmpHeaderSize + paletteSize + image.imageSize(), timestamp).getBytes());
- buffer.order(ByteOrder.LITTLE_ENDIAN);
- buffer.put((byte) 'B').put((byte) 'M');
- buffer.putInt(bmpHeaderSize + paletteSize + image.imageSize());
- buffer.putInt(0); // skip ahead 4 bytes
- buffer.putInt(bmpHeaderSize + paletteSize); // offset to start of image data
- buffer.putInt(bmpHeaderSize - 14); // size of the rest of the header
- // BMPs expect image data bottom to top, so -height to fix that
- buffer.putInt(ImageGetter.width).putInt(-ImageGetter.height);
- buffer.putShort((short) 1).putShort(image.bitsPerPixel());
- buffer.putInt(bmpType);
- buffer.putInt(image.imageSize()); // number of bytes in the actual
- // image
- buffer.putInt(2835).putInt(2835); // physical resolution; don't
- // think it matters
- buffer.putInt((palette == null) ? 0 : palette.entries());
- buffer.putInt(0); // # of important colors (0 means all)
- if (palette != null) {
- palette.writeTo(buffer);
- }
- final int expected;
- if (bmpType == 0) { // BI_RGB
- expected = bmpHeaderSize + paletteSize;
- } else if (bmpType == 3) { // BI_BITFIELDS
- buffer.putInt(0x0000FF00).putInt(0x00FF0000).putInt(0xFF000000)
- .putInt(0); // RGBA bitmasks
- buffer.putInt(0x57696E20); // LCS_WINDOWS_COLOR_SPACE
- expected = bmpHeaderSize - 48;
- } else {
- throw new AssertionError("unknown bmpType value " + bmpType);
- }
- if (buffer.position() != expected) {
- throw new AssertionError(
- "header ended up the wrong size. expected "
- + expected + " but got "
- + buffer.position());
- }
- buffer.limit(bmpHeaderSize + paletteSize);
- buffer.rewind();
- }
-
- /**
- * Does anything that this one can right now.
- *
- * @return whether or not to {@link #close()} and remove this one
- */
- public boolean run() throws IOException {
- if (image == null) {
- final int bytesRead = channel.read(read);
- final String readString = new String(read.array(), 0,
- read.position());
- LOG.log(Level.INFO, "read " + bytesRead
- + " header bytes position=" + read.position()
- + " string='" + readString + "'");
-
- final Matcher matcher = headerPattern.matcher(readString);
- if (matcher.matches()) {
- final String url = matcher.group(1);
- image = images.get(url);
- if (image == null) {
- LOG.log(Level.INFO, "couldn't find an image for url '"
- + url + "'. dropping client");
- return true;
- } else {
- LOG.log(Level.INFO, "found an image for url '"
- + url + "'");
- }
- palette = palettes.get(url);
- bmpType = 0; // could change this in the future
- createBmpHeader(buffers[1]);
- image.setDebugging(true);
- final String indexString = matcher.group(2);
- if (indexString != null) {
- index = Integer.parseInt(indexString);
- } else {
- index = 0;
- }
- LOG.log(Level.INFO, "using index " + index);
- } else if (!read.hasRemaining()) {
- read.flip();
- LOG.log(Level.WARNING,
- "ran out of buffer space reading the header. currently have '"
- + readString + "'. dropping connection");
- return true;
- } else if (bytesRead == -1) {
- read.flip();
- LOG.log(Level.WARNING,
- "reached end of stream for headers without getting anything valid. currently have "
- + read.limit()
- + " bytes ='"
- + readString
- + "'. dropping connection");
- return true;
- }
- } else if (initial.hasRemaining()) {
- channel.write(initial);
- } else {
- if (buffers[2] == null) {
- img = image.getSnapshot(index);
- if (img == null) {
- return false;
- } else {
- buffers[2] = img.getByteBuffer();
- LOG.log(Level.FINE, "got " + buffers[2]
- + " from the image");
- }
- }
- channel.write(buffers);
- boolean remaining = false;
- for (ByteBuffer c : buffers) {
- if (c.hasRemaining()) {
- remaining = true;
- }
- }
- if (!remaining) {
- for (ByteBuffer c : buffers) {
- c.rewind();
- }
- buffers[2] = null;
- image.releaseSnapshot(index, img);
- }
- }
- return false;
- }
- }
-
- public DebugServer(int port) throws IOException {
- server = ServerSocketChannel.open();
- server.configureBlocking(false);
- server.socket().bind(new InetSocketAddress(port), 10);
- new Thread("DebugServer") {
- @Override
- public void run() {
- try {
- loop();
- } catch (Throwable e) {
- LOG.log(Level.SEVERE,
- "trouble running the server loop", e);
- System.exit(1);
- }
- }
- }.start();
- }
-
- public void addImage(String name, ServableImage image) {
- if (image.bitsPerPixel() != 24) {
- throw new IllegalArgumentException("only 24-bit images are supported");
- // could support 16 and 32 bpp images by using bmpType of 3
- }
- images.put(name, image);
- }
- public void addImage(String name, ServableImage image, Palette palette) {
- if (image.bitsPerPixel() != 8) {
- throw new IllegalArgumentException("only 8-bit images are supported");
- // everything should work for 1, 2, and 4 bpp ones too except for padding etc
- }
- if (palette.entries() > (1 << image.bitsPerPixel())) {
- throw new IllegalArgumentException("too many colors in the palette");
- }
- images.put(name, image);
- palettes.put(name, palette);
- }
- /**
- * This timestamp is written out in the debugging images.
- * @param timestamp the current timestamp
- */
- public void setTimestamp(double timestamp) {
- this.timestamp = timestamp;
- }
-
- private void loop() throws IOException {
- final Selector selector = Selector.open();
- server.register(selector, SelectionKey.OP_ACCEPT);
- while (true) {
- try {
- for (Client c : clients) {
- c.register(selector);
- }
- selector.select();
- for (final Iterator<SelectionKey> i = selector.selectedKeys()
- .iterator(); i.hasNext();) {
- final SelectionKey c = i.next();
- if (c.isAcceptable()) {
- // there's only 1 socket there that can accept
- final SocketChannel channel = server.accept();
- if (channel != null) {
- clients.add(new Client(channel));
- }
- } else {
- final Client client = (Client) c.attachment();
- try {
- if (client.run()) {
- client.close();
- clients.remove(client);
- }
- } catch (Exception e) {
- LOG.log(Level.INFO, "dropping client " + client
- + " because it's run() threw an exception",
- e);
- client.close();
- clients.remove(client);
- }
- }
- i.remove();
- }
- } catch (IOException e) {
- LOG.log(Level.WARNING, "trouble running the server loop", e);
- }
- }
- }
-}
diff --git a/aos/linux_code/camera/java/aos/ImageGetter.java b/aos/linux_code/camera/java/aos/ImageGetter.java
deleted file mode 100644
index f0f1063..0000000
--- a/aos/linux_code/camera/java/aos/ImageGetter.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package aos;
-
-import com.googlecode.javacv.cpp.opencv_core;
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-/**
- * An object that can retrieve images from somewhere.
- */
-public interface ImageGetter {
- public static int width = 640, height = 480;
-
- /**
- * Gets an image.
- * @param out Where to write the image to. Must be a 3-channel {@link opencv_core#IPL_DEPTH_8U} image.
- * @return whether it succeeded or not
- */
- public boolean get(IplImage out);
- /**
- * Only valid after a successful {@link #get()}.
- * @return The timestamp from the most recent frame. Will be in seconds with at least ms accuracy.
- */
- public double getTimestamp();
-}
-
diff --git a/aos/linux_code/camera/java/aos/JPEGDecoder.java b/aos/linux_code/camera/java/aos/JPEGDecoder.java
deleted file mode 100644
index 63d12fd..0000000
--- a/aos/linux_code/camera/java/aos/JPEGDecoder.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package aos;
-
-import java.nio.ByteBuffer;
-
-import com.googlecode.javacv.cpp.opencv_core;
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-/**
- * Efficiently decodes a JPEG image from a @{class ByteBuffer} into an @{class IplImage}.
- * Instances are not safe for use from multiple threads.
- * The first use of an instance allocates some largish buffers which are never freed.
- */
-public class JPEGDecoder {
- private final long[] state = new long[1];
-
- /**
- * @param in Must be direct. The {@link ByteBuffer#limit()} of it will be respected.
- * @param out Where to write the decoded image to. Must be a 3-channel {@link opencv_core#IPL_DEPTH_8U} image.
- * Will be written in the RGB color space.
- * @return Whether or not it succeeded. If not, {@code out} is undefined.
- */
- public boolean decode(ByteBuffer in, IplImage out) {
- if (out.nChannels() != 3 || out.depth() != opencv_core.IPL_DEPTH_8U) {
- throw new IllegalArgumentException("out is invalid");
- }
- return Natives.decodeJPEG(state, in, in.limit(), out.getByteBuffer());
- }
-}
-
diff --git a/aos/linux_code/camera/java/aos/JPEGImageGetter.java b/aos/linux_code/camera/java/aos/JPEGImageGetter.java
deleted file mode 100644
index 84296e7..0000000
--- a/aos/linux_code/camera/java/aos/JPEGImageGetter.java
+++ /dev/null
@@ -1,26 +0,0 @@
-package aos;
-
-import java.nio.ByteBuffer;
-
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-/**
- * Helper class for {@link ImageGetter}s that return JPEG images.
- */
-public abstract class JPEGImageGetter implements ImageGetter {
-
- private final JPEGDecoder decoder = new JPEGDecoder();
-
- @Override
- public boolean get(IplImage out) {
- final ByteBuffer jpeg = getJPEG();
- if (jpeg == null) return false;
- final boolean r = decoder.decode(jpeg, out);
- release();
- return r;
- }
-
- protected abstract ByteBuffer getJPEG();
- protected void release() {}
-
-}
diff --git a/aos/linux_code/camera/java/aos/JavaCVImageGetter.java b/aos/linux_code/camera/java/aos/JavaCVImageGetter.java
deleted file mode 100644
index 67398f0..0000000
--- a/aos/linux_code/camera/java/aos/JavaCVImageGetter.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package aos;
-
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import com.googlecode.javacv.FrameGrabber;
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-
-/**
- * Adapts between the JavaCV {@link FrameGrabber} and {@link ImageGetter}.
- * There is (at least) 1 extra copy involved, so this shouldn't be used if you care about speed.
- */
-public class JavaCVImageGetter implements ImageGetter {
- private static final Logger LOG = Logger.getLogger(JavaCVImageGetter.class
- .getName());
- private final FrameGrabber grabber;
-
- public JavaCVImageGetter(FrameGrabber grabber) {
- this.grabber = grabber;
- if (grabber.getImageWidth() != width || grabber.getImageHeight() != height) {
- if (grabber.getImageWidth() == 0 && grabber.getImageHeight() == 0) {
- LOG.log(Level.WARNING, "grabber says it will give 0x0 images at the start. ignoring");
- } else {
- throw new IllegalArgumentException("grabber says it will give images that are the wrong size!!");
- }
- }
- }
-
- @Override
- public boolean get(IplImage out) {
- try {
- final IplImage frame = grabber.grab();
- if (grabber.getImageWidth() != width || grabber.getImageHeight() != height) {
- LOG.log(Level.SEVERE, "grabber says it will give the wrong size images");
- return false;
- }
- if (out.imageSize() != frame.imageSize()) {
- LOG.log(Level.SEVERE, "the grabber gave a " + frame.imageSize() + "-byte image" +
- "but a " + out.imageSize() + "-byte image was passed in");
- return false;
- }
- out.getByteBuffer().put(frame.getByteBuffer());
- return true;
- } catch (FrameGrabber.Exception e) {
- LOG.log(Level.WARNING, "grabber.grab() threw an exception", e);
- return false;
- }
- }
-
- @Override
- public double getTimestamp() {
- // grabber.getTimestamp seems to be in ms (all the implementations are at least)
- return grabber.getTimestamp() / 1000.0;
- }
-}
diff --git a/aos/linux_code/camera/java/aos/NativeBufferError.java b/aos/linux_code/camera/java/aos/NativeBufferError.java
deleted file mode 100644
index 41c794d..0000000
--- a/aos/linux_code/camera/java/aos/NativeBufferError.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package aos;
-
-public class NativeBufferError extends NativeError {
- private static final long serialVersionUID = -5298480149664213316L;
-
- public NativeBufferError() {
- super();
- }
-
- public NativeBufferError(String message, Throwable cause) {
- super(message, cause);
- }
-
- public NativeBufferError(String message) {
- super(message);
- }
-
- public NativeBufferError(Throwable cause) {
- super(cause);
- }
-
-}
diff --git a/aos/linux_code/camera/java/aos/NativeError.java b/aos/linux_code/camera/java/aos/NativeError.java
deleted file mode 100644
index d410234..0000000
--- a/aos/linux_code/camera/java/aos/NativeError.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package aos;
-
-/**
- * Represents an error from native code.
- */
-public class NativeError extends Error {
- private static final long serialVersionUID = 7394872852984037261L;
-
- public NativeError() {
- super();
- }
-
- public NativeError(String message, Throwable cause) {
- super(message, cause);
- }
-
- public NativeError(String message) {
- super(message);
- }
-
- public NativeError(Throwable cause) {
- super(cause);
- }
-
-}
diff --git a/aos/linux_code/camera/java/aos/NativeLoader.java b/aos/linux_code/camera/java/aos/NativeLoader.java
deleted file mode 100644
index d4fe7a8..0000000
--- a/aos/linux_code/camera/java/aos/NativeLoader.java
+++ /dev/null
@@ -1,14 +0,0 @@
-package aos;
-
-/**
- * Provides support for dealing with loading native code.
- */
-public class NativeLoader {
- /**
- * Loads a native library.
- * @param name the name of the gyp shared_library or loadable_module target to load
- */
- public static void load(String name) {
- System.load(System.getProperty("one-jar.expand.dir") + "/so_libs/lib" + name + ".so");
- }
-}
diff --git a/aos/linux_code/camera/java/aos/Natives.java b/aos/linux_code/camera/java/aos/Natives.java
deleted file mode 100644
index 8ea4e01..0000000
--- a/aos/linux_code/camera/java/aos/Natives.java
+++ /dev/null
@@ -1,82 +0,0 @@
-package aos;
-
-import com.googlecode.javacv.cpp.opencv_core;
-
-import java.nio.ByteBuffer;
-import java.util.logging.Level;
-
-/**
- * <p>Package-private class that has all of the native functions in it to make them easier to implement.</p>
- * <p>WARNING: The raw native functions are <b>NOT</b> thread-safe!!!!! Any java functions that need to be thread safe MUST be synchronized in JAVA!</p>
- */
-class Natives {
- static {
- NativeLoader.load("aos_camera");
- nativeInit(ImageGetter.width, ImageGetter.height);
- }
- private static native void nativeInit(int width, int height);
- /**
- * Empty function to make sure the class gets loaded (which means loading the native library).
- */
- public static void ensureLoaded() {}
-
- /**
- * Decodes a JPEG from in into out. Both buffers must be direct.
- * @param state a long[1] for storing thread-local state
- * @param in the JPEG to decode
- * @param inBytes how many bytes long the JPEG is
- * @param out the buffer to write the decoded image into
- * @return Whether or not it succeeded. If not, {@code out} is undefined.
- */
- public static native boolean decodeJPEG(long[] state, ByteBuffer in, int inBytes, ByteBuffer out);
-
- /**
- * Thresholds in into out. Both buffers must be direct.
- * All of the short arguments should be unsigned bytes. The min and max parameters specify what colors to accept.
- * @param in The image to threshold. Must be a 3-channel {@link opencv_core#IPL_DEPTH_8U} image buffer in the HSV color space.
- * @param out Where to write the thresholded image to. Must be a 1-channel {@link opencv_core#IPL_DEPTH_8U} image buffer.
- * @param hoffset An offset to be added to the hue value before comparing it to {@code hmin} and {@code hmax}.
- * The addition will be performed to a {@code uint8_t}, which will wrap around. This means that it must be positive.
- * Useful for finding red values.
- */
- public static native void threshold(ByteBuffer in, ByteBuffer out, short hoffset, char hmin, char hmax,
- char smin, char smax, char vmin, char vmax);
-
- /**
- * Converts the colors from in to the format required for dumping them into a BMP image.
- * @param in The image to convert. Must be a 3-channel {@link opencv_core#IPL_DEPTH_8U} image buffer in the regular (BGR I think...) color space.
- * @param out Where to write the converted image to. Must be a 3-channel {@link opencv_core#IPL_DEPTH_8U} image buffer.
- */
- public static native void convertBGR2BMP(ByteBuffer in, ByteBuffer out);
-
- /**
- * Retrieves a JPEG image from the queue system. Will block until a new one is ready.
- * @param id from {@link #queueInit()}
- * @return Will be direct. This buffer <b>must not EVER</b> be written to.
- */
- public static native ByteBuffer queueGetJPEG(long id);
- /**
- * Retrieves the latest frame timestamp from the queue system. Must only be called between {@link #queueGetJPEG} and {@link #queueReleaseJPEG}.
- * @param id from {@link #queueInit()}
- * @return a timestamp
- */
- public static native double queueGetTimestamp(long id);
- /**
- * Releases the last image retrieved from the queue system. The result of the last {@link #queueGetJPEG()} will now be invalid.
- * @param id from {@link #queueInit()}
- */
- public static native void queueReleaseJPEG(long id);
- /**
- * Prepares to start retrieving JPEGs from the queues.
- * @return the ID to pass to the other queue functions
- */
- public static native long queueInit();
-
- /**
- * Puts the given message into the logging framework.
- * @param message the complete log message
- * @param level the level (from {@link Level#intValue()}
- */
- public static native void LOG(String message, int level);
-}
-
diff --git a/aos/linux_code/camera/java/aos/QueueImageGetter.java b/aos/linux_code/camera/java/aos/QueueImageGetter.java
deleted file mode 100644
index 7ed2f65..0000000
--- a/aos/linux_code/camera/java/aos/QueueImageGetter.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package aos;
-
-import java.nio.ByteBuffer;
-
-/**
- * Retrieves images from the queue system.<br>
- * {@link #getTimestamp()} returns the value from the v4l2 driver,
- * which is a CLOCK_MONOTONIC time for most (all?) of them and definitely uvcvideo.
- */
-public class QueueImageGetter extends JPEGImageGetter {
- private final long nativeID;
- public QueueImageGetter() {
- nativeID = Natives.queueInit();
- }
-
- @Override
- public ByteBuffer getJPEG() {
- final ByteBuffer buf = Natives.queueGetJPEG(nativeID);
- if (buf == null) {
- return null;
- }
- return buf.asReadOnlyBuffer();
- }
-
- @Override
- public void release() {
- Natives.queueReleaseJPEG(nativeID);
- }
-
- @Override
- public double getTimestamp() {
- return Natives.queueGetTimestamp(nativeID);
- }
-}
diff --git a/aos/linux_code/camera/java/aos/QueueLogHandler.java b/aos/linux_code/camera/java/aos/QueueLogHandler.java
deleted file mode 100644
index 3eb8938..0000000
--- a/aos/linux_code/camera/java/aos/QueueLogHandler.java
+++ /dev/null
@@ -1,119 +0,0 @@
-package aos;
-
-import java.lang.Thread.UncaughtExceptionHandler;
-import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
-import java.util.logging.SimpleFormatter;
-
-/**
- * <p>Sends messages to the AOS queue-based logging system. Also sends anything that's at least a {@link Level#WARNING} to {@link System#err}.</p>
- * <p>Writes out each stack frame of exceptions as a separate line after the first one with a \t at the beginning.</p>
- */
-public class QueueLogHandler extends Handler {
- private Formatter defaultFormatter;
-
- /**
- * Sets up the logging framework to use an instance of this class for all logging and returns the newly created instance.
- */
- public static QueueLogHandler UseForAll() {
- Natives.ensureLoaded();
- final Logger top = Logger.getLogger("");
- for (Handler c : top.getHandlers()) {
- top.removeHandler(c);
- }
- QueueLogHandler instance = new QueueLogHandler();
- top.addHandler(instance);
- top.setLevel(Level.ALL);
-
- Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
- @Override
- public void uncaughtException(Thread thread, Throwable e) {
- top.log(Level.SEVERE, "uncaught exception in thread " + thread, e);
- System.exit(1);
- }
- });
-
- return instance;
- }
-
- @Override
- public void close() throws SecurityException {
- }
- @Override
- public void flush() {
- }
-
- private Formatter findFormatter() {
- final Formatter r = getFormatter();
- if (r != null) {
- return r;
- }
- if (defaultFormatter != null) {
- return defaultFormatter;
- }
- return defaultFormatter = new SimpleFormatter();
- }
- @Override
- public void publish(LogRecord record) {
- /*final StringBuilder thrownString = new StringBuilder(0);
- if (record.getThrown() != null) {
- thrownString.append(": ");
- thrownString.append(record.getThrown().toString());
- for (StackTraceElement c : record.getThrown().getStackTrace()) {
- thrownString.append(" > ");
- thrownString.append(c.getClassName());
- thrownString.append('.');
- thrownString.append(c.getMethodName());
- thrownString.append('(');
- thrownString.append(c.getFileName());
- thrownString.append(':');
- thrownString.append(c.getLineNumber());
- thrownString.append(')');
- }
- }
- Natives.LOG(record.getSourceClassName() + ": " + record.getSourceMethodName() + ": " +
- findFormatter().formatMessage(record) + thrownString, record.getLevel().intValue());*/
- if (record.getThrown() instanceof UnsatisfiedLinkError || record.getThrown().getCause() instanceof UnsatisfiedLinkError) {
- record.setThrown(new UnsatisfiedLinkError("are you running a JVM of the correct bitness?").initCause(record.getThrown()));
- }
- Natives.LOG(record.getSourceClassName() + ": " + record.getSourceMethodName() + ": " +
- findFormatter().formatMessage(record), record.getLevel().intValue());
- if (record.getThrown() != null) {
- logException(record.getThrown(), record.getLevel().intValue(), false);
- }
-
- if (record.getLevel().intValue() >= Level.WARNING.intValue()) {
- System.err.println(findFormatter().format(record));
- }
- }
- private void logException(Throwable e, int level, boolean caused_by) {
- final StringBuilder thrownString = new StringBuilder();
- if (caused_by) {
- thrownString.append("Caused by: ");
- }
- thrownString.append(e.getClass().getName());
- thrownString.append(": ");
- thrownString.append(e.getLocalizedMessage());
- Natives.LOG(thrownString.toString(), level);
- for (StackTraceElement c : e.getStackTrace()) {
- thrownString.setLength(0);
- thrownString.append("\t");
- thrownString.append(c.getClassName());
- thrownString.append('.');
- thrownString.append(c.getMethodName());
- thrownString.append('(');
- thrownString.append(c.getFileName());
- thrownString.append(':');
- thrownString.append(c.getLineNumber());
- thrownString.append(')');
- Natives.LOG(thrownString.toString(), level);
- }
- if (e.getCause() != null) {
- logException(e.getCause(), level, true);
- }
- }
-
-}
diff --git a/aos/linux_code/camera/java/aos/ServableImage.java b/aos/linux_code/camera/java/aos/ServableImage.java
deleted file mode 100644
index c5db252..0000000
--- a/aos/linux_code/camera/java/aos/ServableImage.java
+++ /dev/null
@@ -1,145 +0,0 @@
-package aos;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Queue;
-import java.util.logging.Logger;
-
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-/**
- * Provides {@link IplImage}s that can be used with a {@link DebugServer}.
- */
-public class ServableImage {
- @SuppressWarnings("unused")
- private static final Logger LOG = Logger.getLogger(ServableImage.class
- .getName());
- private final int width, height, depth, channels;
- private final ArrayList<Queue<IplImage>> queues = new ArrayList<Queue<IplImage>>();
- private final ArrayList<IplImage> snapshots = new ArrayList<IplImage>();
- private final IplImage current;
- private int debugging = 0;
-
- public ServableImage(int width, int height, int depth, int channels) {
- this.width = width;
- this.height = height;
- this.depth = depth;
- this.channels = channels;
-
- current = IplImage.create(width, height, depth, channels);
- }
-
- /**
- * @return the number of bytes in each image
- */
- public int imageSize() {
- return width * height * depth * channels / 8;
- }
-
- /**
- * @return the number of bits in each pixel
- */
- public short bitsPerPixel() {
- return (short) (depth * channels);
- }
-
- /**
- * Retrieves an image that should be used for debugging. It clears the value
- * when called. {@link #releastSnapshot} MUST be called with the result.
- *
- * @param i
- * Which snapshot to retrieve. 0 means the most recent final
- * image.
- * @return The most recent image at this index. {@code null} if there isn't
- * a new one since last time this function was called. Will be in
- * the correct color space to dump into a BMP image if this is a
- * 3-channel image.
- */
- public synchronized IplImage getSnapshot(int i) {
- if (snapshots.size() > i) {
- return snapshots.get(i);
- } else {
- return null;
- }
- }
-
- public synchronized void releaseSnapshot(int i, IplImage image) {
- queues.get(i).add(image);
- }
-
- /**
- * This function will return the same image if called repeatedly until
- * {@link #releaseImage} is called.
- *
- * @return the current image
- */
- public synchronized IplImage getImage() {
- return current;
- }
-
- /**
- * Releases the current image (to be potentially sent out for debugging and
- * then reused).
- */
- public synchronized void releaseImage() {
- recordSnapshot(0);
- }
-
- /**
- * Records a copy of the current image for debugging. It will be accessible
- * at <{@code <base path>?i=<the value>}>. Does nothing unless
- * {@link #isDebugging()}. This method <i>should</i> get called regardless
- * of {@link #isDebugging()} to avoid outputting old debugging images. Note:
- * 0 is not a valid snapshot number.
- *
- * @param i
- * which snapshot this is
- */
- public synchronized void recordSnapshot(int i) {
- while (queues.size() <= i) {
- queues.add(null);
- }
- if (queues.get(i) == null) {
- queues.set(i, new ArrayDeque<IplImage>());
- }
- while (snapshots.size() <= i) {
- snapshots.add(null);
- }
- if (snapshots.get(i) != null) {
- releaseSnapshot(i, snapshots.get(i));
- }
- if (isDebugging()) {
- IplImage snapshot = queues.get(i).poll();
- if (snapshot == null) {
- snapshot = IplImage.create(width, height, depth, channels);
- }
- if (channels == 3) {
- Natives.convertBGR2BMP(current.getByteBuffer(),
- snapshot.getByteBuffer());
- } else {
- snapshot.getByteBuffer().put(current.getByteBuffer());
- }
- snapshots.set(i, snapshot);
- } else {
- snapshots.set(i, null);
- }
- }
-
- /**
- * @return whether or not to do extra debug work with the current image
- */
- public synchronized boolean isDebugging() {
- return debugging > 0;
- }
-
- /**
- * Whoever turns this on should turn it off when they're done.
- */
- synchronized void setDebugging(boolean debugging) {
- if (debugging) {
- ++this.debugging;
- } else {
- --this.debugging;
- }
- }
-}
diff --git a/aos/linux_code/camera/java/aos/Thresholder.java b/aos/linux_code/camera/java/aos/Thresholder.java
deleted file mode 100644
index adf1b49..0000000
--- a/aos/linux_code/camera/java/aos/Thresholder.java
+++ /dev/null
@@ -1,28 +0,0 @@
-package aos;
-
-import com.googlecode.javacv.cpp.opencv_core;
-import com.googlecode.javacv.cpp.opencv_core.IplImage;
-
-public class Thresholder {
- /**
- * Thresholds in into out.
- * All of the int arguments should be unsigned bytes except hoffset, which should be a signed byte.
- * The min and max parameters specify what colors to accept.
- * @param in The image to threshold. Must be a 3-channel {@link opencv_core#IPL_DEPTH_8U} image in the HSV color space.
- * @param out Where to write the thresholded image to. Must be a 1-channel {@link opencv_core#IPL_DEPTH_8U} image.
- * @param hoffset An offset to be added to the hue value before comparing it to {@code hmin} and {@code hmax}.
- * The addition will be performed to a {@code uint8_t}, which will wrap around. This means that it must be positive.
- * Useful for finding red values.
- */
- public static void threshold(IplImage in, IplImage out, int hoffset, int hmin, int hmax,
- int smin, int smax, int vmin, int vmax) {
- if (in.nChannels() != 3 || in.depth() != opencv_core.IPL_DEPTH_8U) {
- throw new IllegalArgumentException("in is invalid");
- }
- if (out.nChannels() != 1 || out.depth() != opencv_core.IPL_DEPTH_8U) {
- throw new IllegalArgumentException("out is invalid");
- }
- Natives.threshold(in.getByteBuffer(), out.getByteBuffer(), (short)hoffset,
- (char)hmin, (char)hmax, (char)smin, (char)smax, (char)vmin, (char)vmax);
- }
-}
diff --git a/aos/linux_code/camera/jni.cpp b/aos/linux_code/camera/jni.cpp
deleted file mode 100644
index c547a9c..0000000
--- a/aos/linux_code/camera/jni.cpp
+++ /dev/null
@@ -1,259 +0,0 @@
-#include <setjmp.h>
-
-#include "jni/aos_Natives.h"
-#include "aos/linux_code/camera/Buffers.h"
-#include "aos/externals/libjpeg/include/jpeglib.h"
-#include "aos/common/logging/logging_impl.h"
-#include "aos/linux_code/init.h"
-
-using aos::camera::Buffers;
-
-namespace {
-
-jclass nativeError, bufferError, outOfMemoryError;
-bool findClass(JNIEnv *env, const char *name, jclass *out) {
- jclass local = env->FindClass(name);
- if (out == NULL) return true;
- *out = static_cast<jclass>(env->NewGlobalRef(local));
- if (out == NULL) return true;
- env->DeleteLocalRef(local);
- return false;
-}
-
-// Checks that the size is correct and retrieves the address.
-// An expected_size of 0 means don't check it.
-// If this function returns NULL, a java exception will already have been
-// thrown.
-void *getBufferAddress(JNIEnv *env, jobject obj, jlong expected_size) {
- if (obj == NULL) {
- env->ThrowNew(nativeError, "null buffer");
- return NULL;
- }
- if (expected_size != 0 &&
- expected_size != env->GetDirectBufferCapacity(obj)) {
- char *str;
- if (asprintf(&str, "wrong size. expected %lld but got %lld",
- expected_size, env->GetDirectBufferCapacity(obj)) < 0) {
- env->ThrowNew(bufferError, "creating message failed");
- return NULL;
- }
- env->ThrowNew(bufferError, str);
- free(str);
- return NULL;
- }
- void *const r = env->GetDirectBufferAddress(obj);
- if (r == NULL) {
- env->ThrowNew(bufferError, "couldn't get address");
- }
- return r;
-}
-
-const int kImagePixels = Buffers::kWidth * Buffers::kHeight;
-
-void jpeg_log_message(jpeg_common_struct *cinfo, log_level level) {
- char buf[LOG_MESSAGE_LEN];
- cinfo->err->format_message(cinfo, buf);
- log_do(level, "libjpeg: %s\n", buf);
-}
-void jpeg_error_exit(jpeg_common_struct *cinfo) __attribute__((noreturn));
-void jpeg_error_exit(jpeg_common_struct *cinfo) {
- jpeg_log_message(cinfo, ERROR);
- longjmp(*static_cast<jmp_buf *>(cinfo->client_data), 1);
-}
-void jpeg_emit_message(jpeg_common_struct *cinfo, int msg_level) {
- if (msg_level < 0) {
- jpeg_log_message(cinfo, WARNING);
- longjmp(*static_cast<jmp_buf *>(cinfo->client_data), 2);
- }
- // this spews a lot of messages out
- //jpeg_log_message(cinfo, DEBUG);
-}
-
-// The structure used to hold all of the state for the functions that deal with
-// a Buffers. A pointer to this structure is stored java-side.
-struct BuffersHolder {
- Buffers buffers;
- timeval timestamp;
- BuffersHolder() : buffers() {}
-};
-
-} // namespace
-
-void Java_aos_Natives_nativeInit(JNIEnv *env, jclass, jint width, jint height) {
- if (findClass(env, "aos/NativeError", &nativeError)) return;
- if (findClass(env, "aos/NativeBufferError", &bufferError)) return;
- if (findClass(env, "java/lang/OutOfMemoryError", &outOfMemoryError)) return;
-
- aos::InitNRT();
-
- if (width != Buffers::kWidth || height != Buffers::kHeight) {
- env->ThrowNew(nativeError, "dimensions mismatch");
- return;
- }
-
- LOG(INFO, "nativeInit finished\n");
-}
-
-static_assert(sizeof(jlong) >= sizeof(void *),
- "can't stick pointers into jlongs");
-
-jboolean Java_aos_Natives_decodeJPEG(JNIEnv *env, jclass, jlongArray stateArray,
- jobject inobj, jint inLength,
- jobject outobj) {
- unsigned char *const in = static_cast<unsigned char *>(
- getBufferAddress(env, inobj, 0));
- if (in == NULL) return false;
- if (env->GetDirectBufferCapacity(inobj) < inLength) {
- env->ThrowNew(bufferError, "in is too small");
- return false;
- }
- unsigned char *const out = static_cast<unsigned char *>(
- getBufferAddress(env, outobj, kImagePixels * 3));
- if (out == NULL) return false;
-
- jpeg_decompress_struct *volatile cinfo; // volatile because of the setjmp call
-
- jlong state;
- env->GetLongArrayRegion(stateArray, 0, 1, &state);
- if (env->ExceptionCheck()) return false;
- if (state == 0) {
- cinfo = static_cast<jpeg_decompress_struct *>(malloc(sizeof(*cinfo)));
- if (cinfo == NULL) {
- env->ThrowNew(outOfMemoryError, "malloc for jpeg_decompress_struct");
- return false;
- }
- cinfo->err = jpeg_std_error(static_cast<jpeg_error_mgr *>(
- malloc(sizeof(*cinfo->err))));
- cinfo->client_data = malloc(sizeof(jmp_buf));
- cinfo->err->error_exit = jpeg_error_exit;
- cinfo->err->emit_message = jpeg_emit_message;
- // if the error handler sees a failure, it needs to clean up
- // (jpeg_abort_decompress) and then return the failure
- // set cinfo->client_data to the jmp_buf
- jpeg_create_decompress(cinfo);
- state = reinterpret_cast<intptr_t>(cinfo);
- env->SetLongArrayRegion(stateArray, 0, 1, &state);
- if (env->ExceptionCheck()) return false;
- } else {
- cinfo = reinterpret_cast<jpeg_decompress_struct *>(state);
- }
-
- // set up the jump buffer
- // this has to happen each time
- if (setjmp(*static_cast<jmp_buf *>(cinfo->client_data))) {
- jpeg_abort_decompress(cinfo);
- return false;
- }
-
- jpeg_mem_src(cinfo, in, inLength);
- jpeg_read_header(cinfo, TRUE);
- if (cinfo->image_width != static_cast<unsigned int>(Buffers::kWidth) ||
- cinfo->image_height != static_cast<unsigned int>(Buffers::kHeight)) {
- LOG(WARNING, "got (%ux%u) image but expected (%dx%d)\n", cinfo->image_width,
- cinfo->image_height, Buffers::kWidth, Buffers::kHeight);
- jpeg_abort_decompress(cinfo);
- return false;
- }
- cinfo->out_color_space = JCS_RGB;
- jpeg_start_decompress(cinfo);
- if (cinfo->output_components != 3) {
- LOG(WARNING, "libjpeg wants to return %d color components instead of 3\n",
- cinfo->out_color_components);
- jpeg_abort_decompress(cinfo);
- return false;
- }
- if (cinfo->output_width != static_cast<unsigned int>(Buffers::kWidth) ||
- cinfo->output_height != static_cast<unsigned int>(Buffers::kHeight)) {
- LOG(WARNING, "libjpeg wants to return a (%ux%u) image but need (%dx%d)\n",
- cinfo->output_width, cinfo->output_height,
- Buffers::kWidth, Buffers::kHeight);
- jpeg_abort_decompress(cinfo);
- return false;
- }
-
- unsigned char *buffers[Buffers::kHeight];
- for (int i = 0; i < Buffers::kHeight; ++i) {
- buffers[i] = &out[i * Buffers::kWidth * 3];
- }
- while (cinfo->output_scanline < cinfo->output_height) {
- jpeg_read_scanlines(cinfo, &buffers[cinfo->output_scanline],
- Buffers::kHeight - cinfo->output_scanline);
- }
-
- jpeg_finish_decompress(cinfo);
- return true;
-}
-
-void Java_aos_Natives_threshold(JNIEnv *env, jclass, jobject inobj,
- jobject outobj, jshort hoffset, jchar hmin,
- jchar hmax, jchar smin, jchar smax, jchar vmin,
- jchar vmax) {
- const unsigned char *__restrict__ const in = static_cast<unsigned char *>(
- getBufferAddress(env, inobj, kImagePixels * 3));
- if (in == NULL) return;
- char *__restrict__ const out = static_cast<char *>(
- getBufferAddress(env, outobj, kImagePixels));
- if (out == NULL) return;
-
- for (int i = 0; i < kImagePixels; ++i) {
- const uint8_t h = in[i * 3] + static_cast<uint8_t>(hoffset);
- out[i] = h > hmin && h < hmax &&
- in[i * 3 + 1] > smin && in[i * 3 + 1] < smax &&
- in[i * 3 + 2] > vmin && in[i * 3 + 2] < vmax;
- }
-}
-void Java_aos_Natives_convertBGR2BMP(JNIEnv *env, jclass,
- jobject inobj, jobject outobj) {
- const char *__restrict__ const in = static_cast<char *>(
- getBufferAddress(env, inobj, kImagePixels * 3));
- if (in == NULL) return;
- char *__restrict__ const out = static_cast<char *>(
- getBufferAddress(env, outobj, kImagePixels * 3));
- if (out == NULL) return;
-
- for (int i = 0; i < kImagePixels; ++i) {
- out[i * 3 + 0] = in[i * 3 + 2];
- out[i * 3 + 1] = in[i * 3 + 1];
- out[i * 3 + 2] = in[i * 3 + 0];
- }
-}
-
-jlong Java_aos_Natives_queueInit(JNIEnv *, jclass) {
- return reinterpret_cast<intptr_t>(new BuffersHolder());
-}
-void Java_aos_Natives_queueReleaseJPEG(JNIEnv *, jclass, jlong ptr) {
- reinterpret_cast<BuffersHolder *>(ptr)->buffers.Release();
-}
-jobject Java_aos_Natives_queueGetJPEG(JNIEnv *env, jclass, jlong ptr) {
- uint32_t size;
- BuffersHolder *const holder = reinterpret_cast<BuffersHolder *>(ptr);
- const void *const r = holder->buffers.GetNext(true, &size,
- &holder->timestamp, NULL);
- if (r == NULL) return NULL;
- return env->NewDirectByteBuffer(const_cast<void *>(r), size);
-}
-jdouble Java_aos_Natives_queueGetTimestamp(JNIEnv *, jclass, jlong ptr) {
- const BuffersHolder *const holder = reinterpret_cast<BuffersHolder *>(ptr);
- return holder->timestamp.tv_sec + holder->timestamp.tv_usec / 1000000.0;
-}
-
-void Java_aos_Natives_LOG(JNIEnv *env, jclass, jstring message, jint jlevel) {
- log_level level;
- if (jlevel >= 1000) {
- // Don't want to use FATAL because the uncaught java exception that is
- // likely to come next will be useful.
- level = ERROR;
- } else if (jlevel >= 900) {
- level = WARNING;
- } else if (jlevel >= 800) {
- level = INFO;
- } else {
- level = DEBUG;
- }
- // Can't use Get/ReleaseStringCritical because log_do might block waiting to
- // put its message into the queue.
- const char *const message_chars = env->GetStringUTFChars(message, NULL);
- if (message_chars == NULL) return;
- log_do(level, "%s\n", message_chars);
- env->ReleaseStringUTFChars(message, message_chars);
-}
diff --git a/aos/linux_code/queue-tmpl.h b/aos/linux_code/queue-tmpl.h
index 15b8608..84eb02c 100644
--- a/aos/linux_code/queue-tmpl.h
+++ b/aos/linux_code/queue-tmpl.h
@@ -52,7 +52,6 @@
return msg;
}
-#ifndef SWIG
operator bool() {
return msg_ != NULL;
}
@@ -70,7 +69,6 @@
assert(msg != NULL);
return msg;
}
-#endif // SWIG
// Sends the message and removes our reference to it.
// If the queue is full, over-rides the oldest message in it with our new
@@ -114,7 +112,6 @@
reset();
}
-#ifndef SWIG
// Implements a move constructor to take the message pointer from the
// temporary object to save work.
SafeScopedMessagePtr(SafeScopedMessagePtr<T> &&ptr)
@@ -122,7 +119,6 @@
msg_(ptr.msg_) {
ptr.msg_ = NULL;
}
-#endif // SWIG
// Copy constructor actually copies the data.
SafeScopedMessagePtr(const SafeScopedMessagePtr<T> &ptr)
@@ -130,13 +126,11 @@
msg_(NULL) {
reset(new T(*ptr.get()));
}
-#ifndef SWIG
// Equal operator copies the data.
void operator=(const SafeScopedMessagePtr<T> &ptr) {
queue_ = ptr.queue_;
reset(new T(*ptr.get()));
}
-#endif // SWIG
private:
// Provide access to private constructor.
@@ -254,7 +248,7 @@
// This builder uses the safe message pointer so that it can be safely copied
-// and used by SWIG or in places where it could be leaked.
+// in places where it could be leaked.
template <class T>
class SafeMessageBuilder {
public: