diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp
index 896fe285352ab1b8ef798eb000e314b6614076f9..c1afeed96955b310adbc90ea76a2dc07e5473dc7 100644
--- a/applications/reconstruct/src/main.cpp
+++ b/applications/reconstruct/src/main.cpp
@@ -239,10 +239,11 @@ static void run(ftl::Configurable *root) {
 
 	group->setLatency(4);
 	group->setName("ReconGroup");
-	group->sync([splat,virt,&busy,&slave,&scene_A,&scene_B,&align](ftl::rgbd::FrameSet &fs) -> bool {
+	group->sync([splat,virt,&busy,&slave,&scene_A,&scene_B,&align,controls](ftl::rgbd::FrameSet &fs) -> bool {
 		//cudaSetDevice(scene->getCUDADevice());
 
-		if (slave.isPaused()) return true;
+		//if (slave.isPaused()) return true;
+		if (controls->value("paused", false)) return true;
 		
 		if (busy) {
 			LOG(INFO) << "Group frameset dropped: " << fs.timestamp;
diff --git a/components/rgbd-sources/src/sources/ftlfile/player.cpp b/components/rgbd-sources/src/sources/ftlfile/player.cpp
index c78790fc13b01e028376a6edff3bc89616d0f65c..cabbce6425586f6473156cdb6e548add0648d770 100644
--- a/components/rgbd-sources/src/sources/ftlfile/player.cpp
+++ b/components/rgbd-sources/src/sources/ftlfile/player.cpp
@@ -5,11 +5,19 @@ using ftl::rgbd::Player;
 
 Player::Player(std::istream &s) : stream_(&s), reader_(s) {
     auto *c = ftl::config::find("/controls");
+
+    offset_ = 0;
 	
     if (c) {
         paused_ = c->value("paused", false);
         c->on("paused", [this,c](const ftl::config::Event &e) {
+            UNIQUE_LOCK(mtx_, lk);
             paused_ = c->value("paused", false);
+            if (paused_) {
+                pause_time_ = last_ts_;
+            } else {
+                offset_ += last_ts_ - pause_time_;
+            }
         });
 
         looping_ = c->value("looping", true);
@@ -30,18 +38,22 @@ Player::Player(std::istream &s) : stream_(&s), reader_(s) {
 }
 
 Player::~Player() {
-
+    // TODO: Remove callbacks
 }
 
 bool Player::read(int64_t ts) {
+    std::unique_lock<std::mutex> lk(mtx_, std::defer_lock);
+	if (!lk.try_lock()) return true;
+
+    last_ts_ = ts;
     if (paused_) return true;
 
-    int64_t adjusted_ts = int64_t(float(ts - reader_.getStartTime()) * speed_) + reader_.getStartTime();
-    LOG(INFO) << "Adjusted = " << adjusted_ts;
+    int64_t adjusted_ts = int64_t(float(ts - reader_.getStartTime()) * speed_) + reader_.getStartTime() + offset_;
     bool res = reader_.read(adjusted_ts);
 
     if (looping_ && !res) {
         reader_.end();
+        offset_ = 0;
         stream_->clear();
         stream_->seekg(0);
         if (!reader_.begin()) {
diff --git a/components/rgbd-sources/src/sources/ftlfile/player.hpp b/components/rgbd-sources/src/sources/ftlfile/player.hpp
index d1d342352afea061b688f35c9fbef98b28b1e702..f826caabaf6b461cc77b719427381e3b1c5828c4 100644
--- a/components/rgbd-sources/src/sources/ftlfile/player.hpp
+++ b/components/rgbd-sources/src/sources/ftlfile/player.hpp
@@ -3,6 +3,7 @@
 
 #include <iostream>
 #include <ftl/codecs/reader.hpp>
+#include <ftl/threads.hpp>
 
 namespace ftl {
 namespace rgbd {
@@ -32,6 +33,12 @@ class Player {
     bool reversed_;
     bool looping_;
     float speed_;
+
+    int64_t pause_time_;
+    int64_t offset_;
+    int64_t last_ts_;
+
+    MUTEX mtx_;
 };
 
 }