Checking in debug_view, some extra missing utils, and the y2016 target_sender code.
Change-Id: I241947265da8f332c39862f4d0ddcdc2d29c7b68
diff --git a/aos/common/scoped_fd.h b/aos/common/scoped_fd.h
index 57ecdd8..29ccf6e 100644
--- a/aos/common/scoped_fd.h
+++ b/aos/common/scoped_fd.h
@@ -1,7 +1,10 @@
+#ifndef _AOS_COMMON_SCOPED_FD_
+#define _AOS_COMMON_SCOPED_FD_
+
#include <unistd.h>
-#include "aos/common/macros.h"
#include "aos/common/logging/logging.h"
+#include "aos/common/macros.h"
namespace aos {
@@ -9,9 +12,7 @@
class ScopedFD {
public:
explicit ScopedFD(int fd = -1) : fd_(fd) {}
- ~ScopedFD() {
- Close();
- }
+ ~ScopedFD() { Close(); }
int get() const { return fd_; }
int release() {
const int r = fd_;
@@ -25,6 +26,7 @@
}
}
operator bool() const { return fd_ != -1; }
+
private:
int fd_;
void Close() {
@@ -38,3 +40,5 @@
};
} // namespace aos
+
+#endif // _AOS_COMMON_SCOPED_FD_
diff --git a/aos/vision/blob/BUILD b/aos/vision/blob/BUILD
index a024aba..8cb4373 100644
--- a/aos/vision/blob/BUILD
+++ b/aos/vision/blob/BUILD
@@ -93,7 +93,6 @@
],
)
-"""
cc_library(
name = 'stream_view',
hdrs = ['stream_view.h'],
@@ -103,4 +102,3 @@
'//aos/vision/image:image_types',
],
)
-"""
diff --git a/aos/vision/debug/BUILD b/aos/vision/debug/BUILD
new file mode 100644
index 0000000..91111b2
--- /dev/null
+++ b/aos/vision/debug/BUILD
@@ -0,0 +1,22 @@
+#!/usr/bin/python3
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "overlay",
+ hdrs = ["overlay.h"],
+ deps = [
+ '//aos/vision/math:vector',
+ '//aos/vision/math:segment',
+ '//aos/vision/image:image_types',
+ ],
+)
+
+cc_library(name = "debug_viewer",
+ srcs = ["debug_viewer.cc"],
+ hdrs = ["debug_viewer.h"],
+ deps = [
+ '@usr_repo//:gtk+-3.0',
+ "//aos/vision/image:image_types",
+ ":overlay",
+ ]
+)
diff --git a/aos/vision/debug/debug_viewer.cc b/aos/vision/debug/debug_viewer.cc
new file mode 100644
index 0000000..331f733
--- /dev/null
+++ b/aos/vision/debug/debug_viewer.cc
@@ -0,0 +1,166 @@
+#include "aos/vision/debug/debug_viewer.h"
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gtk/gtk.h>
+#include <poll.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "aos/vision/image/image_types.h"
+
+namespace aos {
+namespace vision {
+
+template <typename T, gboolean (T::*DrawMethod)(cairo_t *cr)>
+gboolean DrawCallback(GtkWidget *, cairo_t *cr, gpointer data) {
+ return ((*((T *)data)).*DrawMethod)(cr);
+}
+
+template <typename T, gboolean (T::*DrawMethod)(cairo_t *cr)>
+void g_draw_signal_connect(GtkWidget *widget, T *obj) {
+ gboolean (*fnptr)(GtkWidget *, cairo_t *, gpointer) =
+ DrawCallback<T, DrawMethod>;
+ g_signal_connect(widget, "draw", G_CALLBACK(fnptr), obj);
+}
+
+struct DebugViewer::Internals {
+ Internals(bool flip) : flip_(flip) {}
+
+ gboolean Draw(cairo_t *cr) {
+ needs_draw = false;
+ cairo_scale(cr, scale_factor, scale_factor);
+ if (pixbuf != nullptr) {
+ cairo_save(cr);
+ if (flip_) {
+ cairo_translate(cr, ptr.fmt().w, ptr.fmt().h);
+ cairo_scale(cr, -1, -1);
+ }
+ gdk_cairo_set_source_pixbuf(cr, pixbuf, 0.0, 0.0);
+ cairo_paint(cr);
+ cairo_restore(cr);
+ }
+
+ int w = ptr.fmt().w;
+ int h = ptr.fmt().h;
+ if (overlays) {
+ for (const auto &ov : *overlays) {
+ cairo_save(cr);
+ CairoRender render(cr);
+ // move the drawing to match the window size
+ ov->Draw(&render, w, h);
+ cairo_restore(cr);
+ }
+ }
+
+ return FALSE;
+ }
+
+ GdkPixbuf *pixbuf = nullptr;
+ GtkWidget *drawing_area = nullptr;
+ ImagePtr ptr;
+ bool needs_draw = true;
+ GtkWidget *window;
+ std::vector<OverlayBase *> *overlays = nullptr;
+ double scale_factor;
+
+ // flip the image rows on drawing
+ bool flip_ = false;
+
+ // clear per frame
+ bool clear_per_frame_ = true;
+};
+
+void DebugViewer::SetOverlays(std::vector<OverlayBase *> *overlays) {
+ self->overlays = overlays;
+}
+
+void DebugViewer::Redraw() {
+ if (!self->needs_draw) {
+ gtk_widget_queue_draw(self->drawing_area);
+ self->needs_draw = true;
+ }
+}
+
+void DebugViewer::UpdateImage(ImagePtr ptr) {
+ if (ptr.data() != self->ptr.data()) {
+ int w = ptr.fmt().w;
+ int h = ptr.fmt().h;
+ self->pixbuf = gdk_pixbuf_new_from_data(
+ (const unsigned char *)ptr.data(), GDK_COLORSPACE_RGB, FALSE, 8,
+ ptr.fmt().w, ptr.fmt().h, 3 * ptr.fmt().w, NULL, NULL);
+ self->ptr = ptr;
+
+ gtk_window_set_default_size(GTK_WINDOW(self->window), w * scale_factor,
+ h * scale_factor);
+
+ gtk_widget_set_size_request(self->drawing_area, w * scale_factor,
+ h * scale_factor);
+ window_height_ = h;
+ window_width_ = w;
+ }
+}
+
+void DebugViewer::MoveTo(int x, int y) {
+ gtk_window_move(GTK_WINDOW(self->window), x, y);
+}
+
+void DebugViewer::SetScale(double scale_factor_inp) {
+ int w = window_width_;
+ int h = window_height_;
+
+ scale_factor = scale_factor_inp;
+ self->scale_factor = scale_factor;
+
+ gtk_window_resize(GTK_WINDOW(self->window), w * scale_factor,
+ h * scale_factor);
+
+ gtk_widget_set_size_request(self->drawing_area, w * scale_factor,
+ h * scale_factor);
+}
+
+gboolean debug_viewer_key_press_event(GtkWidget * /*widget*/,
+ GdkEventKey *event, gpointer user_data) {
+ auto &key_press_cb =
+ reinterpret_cast<DebugViewer *>(user_data)->key_press_event;
+ if (key_press_cb) key_press_cb(event->keyval);
+ return FALSE;
+}
+
+DebugViewer::DebugViewer(bool flip) : self(new Internals(flip)) {
+ self->scale_factor = scale_factor;
+ GtkWidget *window;
+ auto drawing_area = self->drawing_area = gtk_drawing_area_new();
+ gtk_widget_set_size_request(drawing_area, window_width_ * scale_factor,
+ window_height_ * scale_factor);
+ gtk_widget_add_events(drawing_area, GDK_KEY_PRESS_MASK);
+
+ g_draw_signal_connect<DebugViewer::Internals, &DebugViewer::Internals::Draw>(
+ drawing_area, self.get());
+
+ window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
+ self->window = window;
+ g_signal_connect(window, "key-press-event",
+ G_CALLBACK(debug_viewer_key_press_event), this);
+ gtk_window_set_title(GTK_WINDOW(window), "Window");
+ gtk_window_set_default_size(GTK_WINDOW(window), window_width_ * scale_factor,
+ window_height_ * scale_factor);
+
+ gtk_container_add(GTK_CONTAINER(window), drawing_area);
+ gtk_widget_show_all(window);
+}
+DebugViewer::~DebugViewer() {}
+
+void CairoRender::Text(int x, int y, int /*text_x*/, int /*text_y*/,
+ const std::string &text) {
+ auto *pango_lay = pango_cairo_create_layout(cr_);
+ cairo_move_to(cr_, x, y);
+ pango_layout_set_text(pango_lay, text.data(), text.size());
+ pango_cairo_show_layout(cr_, pango_lay);
+ g_object_unref(pango_lay);
+}
+
+} // namespace vision
+} // namespace aos
diff --git a/aos/vision/debug/debug_viewer.h b/aos/vision/debug/debug_viewer.h
new file mode 100644
index 0000000..3bada28
--- /dev/null
+++ b/aos/vision/debug/debug_viewer.h
@@ -0,0 +1,78 @@
+#ifndef AOS_VISION_DEBUG_DEBUG_VIEWER_H_
+#define AOS_VISION_DEBUG_DEBUG_VIEWER_H_
+
+#include <cairo.h>
+#include <functional>
+#include "aos/vision/debug/overlay.h"
+#include "aos/vision/image/image_types.h"
+
+namespace aos {
+namespace vision {
+
+// Implement Cairo version of RenderInterface.
+class CairoRender : public RenderInterface {
+ public:
+ explicit CairoRender(cairo_t *cr) : cr_(cr) {}
+ virtual ~CairoRender() {}
+
+ void Translate(double x, double y) override { cairo_translate(cr_, x, y); }
+
+ void SetSourceRGB(double r, double g, double b) override {
+ cairo_set_source_rgb(cr_, r, g, b);
+ }
+
+ void MoveTo(double x, double y) override { cairo_move_to(cr_, x, y); }
+
+ void LineTo(double x, double y) override { cairo_line_to(cr_, x, y); }
+
+ void Circle(double x, double y, double r) override {
+ cairo_arc(cr_, x, y, r, 0.0, 2 * M_PI);
+ }
+
+ void Stroke() override { cairo_stroke(cr_); }
+
+ void Text(int x, int y, int text_x, int text_y,
+ const std::string &text) override;
+
+ private:
+ cairo_t *cr_;
+};
+
+// Simple debug view window.
+class DebugViewer {
+ public:
+ struct Internals;
+ explicit DebugViewer(bool flip);
+ ~DebugViewer();
+ // Explicit redraw queuing (Will not double-queue).
+ void Redraw();
+
+ // This will resize the window as well as updating to draw from the
+ // (not owned) ptr. When you change ptr, you should call Redraw();
+ void UpdateImage(ImagePtr ptr);
+
+ // Sets up the window to draw a list of overlays.
+ // See overlay.h for more info.
+ void SetOverlays(std::vector<OverlayBase *> *overlay);
+
+ // Resizes the window.
+ void SetScale(double scale_factor);
+
+ // Move window.
+ void MoveTo(int x, int y);
+
+ // Set to change the key_press behaviour.
+ // The argument type is a constant that looks like: GDK_KEY_#{key_val_name}
+ std::function<void(uint32_t)> key_press_event;
+
+ private:
+ double scale_factor = 1.0;
+ int window_width_ = 100;
+ int window_height_ = 100;
+ std::unique_ptr<Internals> self;
+};
+
+} // namespace vision
+} // namespace aos
+
+#endif // AOS_VISION_DEBUG_DEBUG_VIEWER_H_
diff --git a/aos/vision/debug/overlay.h b/aos/vision/debug/overlay.h
new file mode 100644
index 0000000..fbd6838
--- /dev/null
+++ b/aos/vision/debug/overlay.h
@@ -0,0 +1,198 @@
+#ifndef _AOS_VISION_IMAGE_DEBUG_OVERLAY_H_
+#define _AOS_VISION_IMAGE_DEBUG_OVERLAY_H_
+
+#include <string>
+#include <vector>
+
+#include "aos/vision/image/image_types.h"
+#include "aos/vision/math/segment.h"
+#include "aos/vision/math/vector.h"
+
+namespace aos {
+namespace vision {
+
+// Abstract away rendering to avoid compiling gtk for arm.
+// This should match a reduced cairo rendering api.
+class RenderInterface {
+ public:
+ RenderInterface() {}
+ RenderInterface(RenderInterface &&other) = delete;
+ RenderInterface(const RenderInterface &other) = delete;
+ ~RenderInterface() {}
+
+ virtual void Translate(double x, double y) = 0;
+ virtual void SetSourceRGB(double r, double g, double b) = 0;
+ virtual void MoveTo(double x, double y) = 0;
+ virtual void LineTo(double x, double y) = 0;
+ virtual void Circle(double x, double y, double r) = 0;
+ // negative in x, y, text_x, text_y measures from max in those value
+ virtual void Text(int x, int y, int text_x, int text_y,
+ const std::string &text) = 0;
+ virtual void Stroke() = 0;
+};
+
+// Interface for a list of overlays to be drawn onto a debug image.
+// These will be passed into the running vision algorithms to output debug info,
+// so they must not have costly side-effects.
+class OverlayBase {
+ public:
+ OverlayBase() {}
+ virtual ~OverlayBase() {}
+
+ // Draws this overlay to the given canvas.
+ virtual void Draw(RenderInterface *render, double /* width */,
+ double /* height */) = 0;
+
+ // Clears the entire overlay.
+ virtual void Reset() = 0;
+
+ PixelRef color = {255, 0, 0};
+ double scale = 1.0;
+};
+
+// A lambda that renders directly to the render interface.
+class LambdaOverlay : public OverlayBase {
+ public:
+ std::function<void(RenderInterface *, double, double)> draw_fn;
+ void Draw(RenderInterface *render, double width, double height) override {
+ if (draw_fn) draw_fn(render, width, height);
+ }
+ void Reset() override {}
+};
+
+// Lines rendered in a coordinate system where the origin is the center
+// of the screen
+class LinesOverlay : public OverlayBase {
+ public:
+ LinesOverlay() : OverlayBase() {}
+ ~LinesOverlay() {}
+
+ // build a segment for this line
+ void add_line(Vector<2> st, Vector<2> ed) { add_line(st, ed, color); }
+
+ // build a segment for this line
+ void add_line(Vector<2> st, Vector<2> ed, PixelRef newColor) {
+ lines_.emplace_back(
+ std::pair<Segment<2>, PixelRef>(Segment<2>(st, ed), newColor));
+ }
+
+ void add_point(Vector<2> pt) { add_point(pt, color); }
+
+ // add a new point connected to the last point in the line
+ void add_point(Vector<2> pt, PixelRef newColor) {
+ if (lines_.empty()) {
+ lines_.emplace_back(
+ std::pair<Segment<2>, PixelRef>(Segment<2>(pt, pt), newColor));
+ } else {
+ Vector<2> st = lines_.back().first.B();
+ lines_.emplace_back(
+ std::pair<Segment<2>, PixelRef>(Segment<2>(st, pt), newColor));
+ }
+ }
+
+ void Draw(RenderInterface *render, double w, double h) override {
+ render->Translate(w / 2.0, h / 2.0);
+ for (const auto &ln : lines_) {
+ PixelRef localColor = ln.second;
+ render->SetSourceRGB(localColor.r / 255.0, localColor.g / 255.0,
+ localColor.b / 255.0);
+ render->MoveTo(scale * ln.first.A().x(), -scale * ln.first.A().y());
+ render->LineTo(scale * ln.first.B().x(), -scale * ln.first.B().y());
+ render->Stroke();
+ }
+ }
+
+ // Empting the list will blank the whole overlay
+ void Reset() override { lines_.clear(); }
+
+ private:
+ // lines in this over lay
+ std::vector<std::pair<Segment<2>, PixelRef>> lines_;
+};
+
+// Lines rendered in pixel coordinates (Should match up with the screen.)
+class PixelLinesOverlay : public OverlayBase {
+ public:
+ PixelLinesOverlay() : OverlayBase() {}
+ ~PixelLinesOverlay() {}
+
+ // build a segment for this line
+ void add_line(Vector<2> st, Vector<2> ed) { add_line(st, ed, color); }
+
+ // build a segment for this line
+ void add_line(Vector<2> st, Vector<2> ed, PixelRef newColor) {
+ lines_.emplace_back(
+ std::pair<Segment<2>, PixelRef>(Segment<2>(st, ed), newColor));
+ }
+
+ void start_new_profile() { start_profile = true; }
+
+ // add a new point connected to the last point in the line
+ void add_point(Vector<2> pt, PixelRef newColor) {
+ if (lines_.empty() || start_profile) {
+ lines_.emplace_back(
+ std::pair<Segment<2>, PixelRef>(Segment<2>(pt, pt), newColor));
+ start_profile = false;
+ } else {
+ Vector<2> st = lines_.back().first.B();
+ lines_.emplace_back(
+ std::pair<Segment<2>, PixelRef>(Segment<2>(st, pt), newColor));
+ }
+ }
+
+ void Draw(RenderInterface *render, double /*width*/,
+ double /*hieght*/) override {
+ for (const auto &ln : lines_) {
+ PixelRef localColor = ln.second;
+ render->SetSourceRGB(localColor.r / 255.0, localColor.g / 255.0,
+ localColor.b / 255.0);
+ render->MoveTo(ln.first.A().x(), ln.first.A().y());
+ render->LineTo(ln.first.B().x(), ln.first.B().y());
+ render->Stroke();
+ }
+ }
+
+ // Empting the list will blank the whole overlay.
+ void Reset() override { lines_.clear(); }
+
+ private:
+ // Lines in this overlay.
+ std::vector<std::pair<Segment<2>, PixelRef>> lines_;
+ bool start_profile = false;
+};
+
+// Circles rendered in a coordinate system where the origin is the center
+// of the screen.
+class CircleOverlay : public OverlayBase {
+ public:
+ CircleOverlay() : OverlayBase() {}
+ ~CircleOverlay() {}
+
+ // build a circle as a point and radius
+ std::pair<Vector<2>, double> *add_circle(Vector<2> center, double radius) {
+ circles_.emplace_back(std::pair<Vector<2>, double>(center, radius));
+ return &(circles_.back());
+ }
+
+ void Draw(RenderInterface *render, double w, double h) {
+ render->Translate(w / 2.0, h / 2.0);
+ render->SetSourceRGB(color.r / 255.0, color.g / 255.0, color.b / 255.0);
+ for (const auto &circle : circles_) {
+ render->Circle(scale * circle.first.x(), -scale * circle.first.y(),
+ scale * circle.second);
+ render->Stroke();
+ }
+ }
+
+ // empting the list will blank the whole overlay
+ void Reset() { circles_.clear(); }
+
+ private:
+ // circles in this overlay
+ std::vector<std::pair<Vector<2>, double>> circles_;
+};
+
+} // vision
+} // aos
+
+#endif // _AOS_VISION_IMAGE_DEBUG_OVERLAY_H_
diff --git a/aos/vision/events/BUILD b/aos/vision/events/BUILD
index c3400fe..e003dc9 100644
--- a/aos/vision/events/BUILD
+++ b/aos/vision/events/BUILD
@@ -11,6 +11,14 @@
],
)
+cc_library(name = "socket_types",
+ hdrs = ["socket_types.h"],
+ deps = [
+ "//aos/vision/events:tcp_server",
+ "//aos/vision/image:image_types",
+ ],
+)
+
cc_library(
name = 'intrusive_free_list',
hdrs = ['intrusive_free_list.h'],
diff --git a/aos/vision/events/socket_types.h b/aos/vision/events/socket_types.h
new file mode 100644
index 0000000..2432cb9
--- /dev/null
+++ b/aos/vision/events/socket_types.h
@@ -0,0 +1,78 @@
+#ifndef _AOS_VISION_EVENTS_SOCKET_TYPES_H_
+#define _AOS_VISION_EVENTS_SOCKET_TYPES_H_
+
+#include <poll.h>
+#include <stdint.h>
+
+#include "aos/vision/events/tcp_server.h"
+#include "aos/vision/image/image_types.h"
+#include "google/protobuf/message.h"
+
+namespace aos {
+namespace events {
+
+// Simple TCP client connection that sends messages prefixed by length.
+// Useful to broadcast to a message all connected clients.
+class DataSocket : public events::SocketConnection {
+ public:
+ // Aliasing cast.
+ union data_len {
+ uint32_t len;
+ char buf[4];
+ };
+
+ DataSocket(events::TCPServerBase *serv, int fd)
+ : events::SocketConnection(serv, fd) {}
+
+ ~DataSocket() { printf("Closed connection on descriptor %d\n", fd()); }
+
+ void ReadEvent() override {
+ // Ignore reads, but don't leave them pending.
+ ssize_t count;
+ char buf[512];
+ while (true) {
+ count = read(fd(), &buf, sizeof buf);
+ if (count <= 0) return;
+ }
+ }
+
+ void Emit(const google::protobuf::Message &data) {
+ std::string d;
+ if (data.SerializeToString(&d)) {
+ Emit(d);
+ }
+ }
+
+ void Emit(vision::DataRef data) {
+ data_len len;
+ len.len = data.size();
+ int res = write(fd(), len.buf, sizeof len.buf);
+ if (res == -1) {
+ printf("Emit Error on write\n");
+ }
+ size_t write_count = 0;
+ while (write_count < data.size()) {
+ int len =
+ write(fd(), &data.data()[write_count], data.size() - write_count);
+ if (len == -1) {
+ if (errno == EAGAIN) {
+ struct pollfd waiting;
+ waiting.fd = fd();
+ waiting.events = POLLOUT;
+ poll(&waiting, 1, -1);
+ } else {
+ close(fd());
+ return;
+ }
+ } else {
+ write_count += len;
+ }
+ if (write_count != data.size()) printf("wrote: %d\n", len);
+ }
+ }
+};
+
+} // namespace events
+} // namespace aos
+
+#endif // _AOS_VISION_EVENTS_SOCKET_TYPES_H_
diff --git a/aos/vision/events/udp.cc b/aos/vision/events/udp.cc
index 2d3d1d1..b5367f6 100644
--- a/aos/vision/events/udp.cc
+++ b/aos/vision/events/udp.cc
@@ -5,24 +5,24 @@
#include "aos/common/logging/logging.h"
namespace aos {
-namespace vision {
+namespace events {
-TXUdpSocket::TXUdpSocket(const char *ip_addr, int port)
+TXUdpSocket::TXUdpSocket(const std::string &ip_addr, int port)
: fd_(PCHECK(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))) {
sockaddr_in destination_in;
memset(&destination_in, 0, sizeof(destination_in));
destination_in.sin_family = AF_INET;
destination_in.sin_port = htons(port);
- if (inet_aton(ip_addr, &destination_in.sin_addr) == 0) {
- LOG(FATAL, "invalid IP address %s\n", ip_addr);
+ if (inet_aton(ip_addr.c_str(), &destination_in.sin_addr) == 0) {
+ LOG(FATAL, "invalid IP address %s\n", ip_addr.c_str());
}
PCHECK(connect(fd_.get(), reinterpret_cast<sockaddr *>(&destination_in),
sizeof(destination_in)));
}
-int TXUdpSocket::Send(const void *data, int size) {
- return PCHECK(send(fd_.get(), static_cast<const char *>(data), size, 0));
+int TXUdpSocket::Send(const char *data, int size) {
+ return PCHECK(send(fd_.get(), data, size, 0));
}
RXUdpSocket::RXUdpSocket(int port)
@@ -42,5 +42,5 @@
return PCHECK(recv(fd_.get(), static_cast<char *>(data), size, 0));
}
-} // namespace vision
+} // namespace events
} // namespace aos
diff --git a/aos/vision/events/udp.h b/aos/vision/events/udp.h
index a12a8bf..ed4a8e7 100644
--- a/aos/vision/events/udp.h
+++ b/aos/vision/events/udp.h
@@ -1,27 +1,28 @@
-#ifndef AOS_VISION_IMAGE_UDP_H_
-#define AOS_VISION_IMAGE_UDP_H_
+#ifndef AOS_VISION_EVENTS_UDP_H_
+#define AOS_VISION_EVENTS_UDP_H_
#include <arpa/inet.h>
-#include <sys/socket.h>
#include <math.h>
+#include <sys/socket.h>
#include <unistd.h>
+#include <string>
#include <vector>
#include "aos/common/macros.h"
#include "aos/common/scoped_fd.h"
namespace aos {
-namespace vision {
+namespace events {
// Simple wrapper around a transmitting UDP socket.
//
// LOG(FATAL)s for all errors, including from Send.
class TXUdpSocket {
public:
- TXUdpSocket(const char *ip_addr, int port);
+ TXUdpSocket(const std::string &ip_addr, int port);
// Returns the number of bytes actually sent.
- int Send(const void *data, int size);
+ int Send(const char *data, int size);
private:
ScopedFD fd_;
@@ -45,7 +46,7 @@
DISALLOW_COPY_AND_ASSIGN(RXUdpSocket);
};
-} // namespace vision
+} // namespace events
} // namespace aos
-#endif // AOS_VISION_IMAGE_UDP_H_
+#endif // AOS_VISION_EVENTS_UDP_H_
diff --git a/aos/vision/events/udp_test.cc b/aos/vision/events/udp_test.cc
index 87046ba..7e77b68 100644
--- a/aos/vision/events/udp_test.cc
+++ b/aos/vision/events/udp_test.cc
@@ -3,7 +3,7 @@
#include "gtest/gtest.h"
namespace aos {
-namespace vision {
+namespace events {
TEST(UDPTest, SendRecv) {
RXUdpSocket rx(1109);
@@ -19,5 +19,5 @@
EXPECT_EQ(txdata[3], rxdata[3]);
}
-} // namespace vision
+} // namespace events
} // namespace aos
diff --git a/aos/vision/image/image_stream.h b/aos/vision/image/image_stream.h
index ca2d8be..bdfbc31 100644
--- a/aos/vision/image/image_stream.h
+++ b/aos/vision/image/image_stream.h
@@ -9,6 +9,8 @@
namespace aos {
namespace vision {
+// Converts a camera reader into a virtual base class that calls ProcessImage
+// on each new image.
class ImageStreamEvent : public ::aos::events::EpollEvent {
public:
static std::unique_ptr<::camera::Reader> GetCamera(
@@ -17,28 +19,28 @@
using namespace std::placeholders;
std::unique_ptr<::camera::Reader> camread(new ::camera::Reader(
fname,
- std::bind(&ImageStreamEvent::ProcessHelper, obj, _1, _2), params);
+ std::bind(&ImageStreamEvent::ProcessHelper, obj, _1, _2), params));
camread->StartAsync();
return camread;
}
explicit ImageStreamEvent(std::unique_ptr<::camera::Reader> reader)
- : ::aos::events::EpollEvent(reader->fd()), reader_(reader) {}
+ : ::aos::events::EpollEvent(reader->fd()), reader_(std::move(reader)) {}
explicit ImageStreamEvent(const std::string &fname,
camera::CameraParams params)
: ImageStreamEvent(GetCamera(fname, this, params)) {}
- void ProcessHelper(DataRef data, uint64_t timestamp) {
+ void ProcessHelper(DataRef data, aos::monotonic_clock::time_point timestamp) {
if (data.size() < 300) {
- LOG(INFO, "got bad img: %d of size(%lu)\n", (int)timestamp, data.size());
+ LOG(INFO, "got bad img of size(%lu)\n", data.size());
return;
}
ProcessImage(data, timestamp);
}
- virtual void ProcessImage(DataRef data, uint64_t timestamp) = 0;
+ virtual void ProcessImage(DataRef data, aos::monotonic_clock::time_point timestamp) = 0;
- void ReadEvent(Context /*ctx*/) override { reader_->HandleFrame(); }
+ void ReadEvent() override { reader_->HandleFrame(); }
private:
std::unique_ptr<::camera::Reader> reader_;