Restart image_streamer when images are not flowing

Change-Id: Iacf0f1bdfee63ca5335102aee697574fd9eacc93
Signed-off-by: James Kuszmaul <jabukuszmaul+collab@gmail.com>
diff --git a/frc971/image_streamer/image_streamer.cc b/frc971/image_streamer/image_streamer.cc
index 2289df3..6c9a732 100644
--- a/frc971/image_streamer/image_streamer.cc
+++ b/frc971/image_streamer/image_streamer.cc
@@ -208,9 +208,11 @@
  private:
   void OnSample(GstSample *sample);
 
+  aos::ShmEventLoop *event_loop_;
   std::map<::seasocks::WebSocket *, std::unique_ptr<Connection>> connections_;
   ::seasocks::Server *server_;
   std::unique_ptr<GstSampleSource> source_;
+  aos::TimerHandler *manual_restart_handle_;
 
   aos::Sender<frc971::vision::CameraImage> sender_;
 };
@@ -275,7 +277,10 @@
 
 WebsocketHandler::WebsocketHandler(aos::ShmEventLoop *event_loop,
                                    ::seasocks::Server *server)
-    : server_(server) {
+    : event_loop_(event_loop),
+      server_(server),
+      manual_restart_handle_(
+          event_loop_->AddTimer([this]() { event_loop_->Exit(); })) {
   if (FLAGS_listen_on.empty()) {
     if (FLAGS_publish_images) {
       sender_ = event_loop->MakeSender<frc971::vision::CameraImage>("/camera");
@@ -286,6 +291,10 @@
     source_ = std::make_unique<ChannelSource>(
         event_loop, [this](auto sample) { OnSample(sample); });
   }
+  event_loop_->OnRun([this]() {
+    manual_restart_handle_->Schedule(event_loop_->monotonic_now() +
+                                     std::chrono::seconds(10));
+  });
 }
 
 void WebsocketHandler::onConnect(::seasocks::WebSocket *sock) {
@@ -333,6 +342,8 @@
 
     builder.CheckOk(builder.Send(image_builder.Finish()));
   }
+  manual_restart_handle_->Schedule(event_loop_->monotonic_now() +
+                                   std::chrono::seconds(10));
 }
 
 void WebsocketHandler::onDisconnect(::seasocks::WebSocket *sock) {