diff --git a/components/codecs/include/ftl/codecs/channels.hpp b/components/codecs/include/ftl/codecs/channels.hpp
index d2c65328f88a90f58ca02998eecb62acd737efdc..168b8eefa9a65d11caa2f2f56534a6810de8f8e0 100644
--- a/components/codecs/include/ftl/codecs/channels.hpp
+++ b/components/codecs/include/ftl/codecs/channels.hpp
@@ -167,7 +167,7 @@ inline bool isFloatChannel(ftl::codecs::Channel chan) {
 
 MSGPACK_ADD_ENUM(ftl::codecs::Channel);
 
-template <int BASE=0>
+/*template <int BASE=0>
 inline ftl::codecs::Channels<BASE> operator|(ftl::codecs::Channel a, ftl::codecs::Channel b) {
 	return ftl::codecs::Channels<BASE>(a) | b;
 }
@@ -175,6 +175,6 @@ inline ftl::codecs::Channels<BASE> operator|(ftl::codecs::Channel a, ftl::codecs
 template <int BASE=0>
 inline ftl::codecs::Channels<BASE> operator+(ftl::codecs::Channel a, ftl::codecs::Channel b) {
 	return ftl::codecs::Channels<BASE>(a) | b;
-}
+}*/
 
 #endif  // _FTL_RGBD_CHANNELS_HPP_
diff --git a/components/rgbd-sources/CMakeLists.txt b/components/rgbd-sources/CMakeLists.txt
index 4238c5755fdd98d6d8d18114ffa7e049656b3cd0..345d065bc231ae3c1fb9473b21f77cae50ee78f4 100644
--- a/components/rgbd-sources/CMakeLists.txt
+++ b/components/rgbd-sources/CMakeLists.txt
@@ -11,7 +11,7 @@ set(RGBDSRC
 	#src/abr.cpp
 	src/sources/screencapture/screencapture.cpp
 	src/camera.cpp
-	src/init.cpp
+	#src/init.cpp
 )
 
 if (HAVE_REALSENSE)
diff --git a/components/streams/include/ftl/streams/netstream.hpp b/components/streams/include/ftl/streams/netstream.hpp
index 89330c34f20beb1516548e680c6c72b47ac97db1..0ad54061b41ff62a4eb2c12db18d20e415afb365 100644
--- a/components/streams/include/ftl/streams/netstream.hpp
+++ b/components/streams/include/ftl/streams/netstream.hpp
@@ -81,7 +81,7 @@ class Net : public Stream {
 	bool host_;
 	int tally_;
 	std::array<std::atomic<int>,32> reqtally_;
-	ftl::codecs::Channels<0> last_selected_;
+	std::unordered_set<ftl::codecs::Channel> last_selected_;
 
 	static float req_bitrate__;
 	static float sample_count__;
diff --git a/components/streams/include/ftl/streams/stream.hpp b/components/streams/include/ftl/streams/stream.hpp
index 4d70577efb0c1fd7f27186084af186dfd5656f3e..67e3388760fa031849578dcffa909ccf543440d4 100644
--- a/components/streams/include/ftl/streams/stream.hpp
+++ b/components/streams/include/ftl/streams/stream.hpp
@@ -11,6 +11,7 @@
 #include <string>
 #include <vector>
 #include <map>
+#include <unordered_set>
 #include <atomic>
 
 namespace ftl {
@@ -65,18 +66,18 @@ class Stream : public ftl::Configurable {
 	/**
 	 * Query available video channels for a frameset.
 	 */
-	const ftl::codecs::Channels<0> &available(int fs) const;
+	const std::unordered_set<ftl::codecs::Channel> &available(int fs) const;
 
 	/**
 	 * Query selected channels for a frameset. Channels not selected may not
 	 * be transmitted, received or decoded.
 	 */
-	const ftl::codecs::Channels<0> &selected(int fs) const;
+	const std::unordered_set<ftl::codecs::Channel> &selected(int fs) const;
 
 	/**
 	 * Change the video channel selection for a frameset.
 	 */
-	void select(int fs, const ftl::codecs::Channels<0> &, bool make=false);
+	void select(int fs, const std::unordered_set<ftl::codecs::Channel> &, bool make=false);
 
 	/**
 	 * Number of framesets in stream.
@@ -89,12 +90,12 @@ class Stream : public ftl::Configurable {
 	 * Allow modification of available channels. Calling this with an invalid
 	 * fs number will create that frameset and increase the size.
 	 */
-	ftl::codecs::Channels<0> &available(int fs);
+	std::unordered_set<ftl::codecs::Channel> &available(int fs);
 
 	private:
 	struct FSState {
-		ftl::codecs::Channels<0> selected;
-		ftl::codecs::Channels<0> available;
+		std::unordered_set<ftl::codecs::Channel> selected;
+		std::unordered_set<ftl::codecs::Channel> available;
 	};
 
 	std::vector<FSState> state_;
@@ -205,4 +206,34 @@ class Intercept : public Stream {
 }
 }
 
+std::unordered_set<ftl::codecs::Channel> operator&(const std::unordered_set<ftl::codecs::Channel> &a, const std::unordered_set<ftl::codecs::Channel> &b);
+
+std::unordered_set<ftl::codecs::Channel> operator-(const std::unordered_set<ftl::codecs::Channel> &a, const std::unordered_set<ftl::codecs::Channel> &b);
+
+inline std::unordered_set<ftl::codecs::Channel> &operator+=(std::unordered_set<ftl::codecs::Channel> &t, ftl::codecs::Channel c) {
+	t.insert(c);
+	return t;
+}
+
+inline std::unordered_set<ftl::codecs::Channel> &operator-=(std::unordered_set<ftl::codecs::Channel> &t, ftl::codecs::Channel c) {
+	t.erase(c);
+	return t;
+}
+
+inline std::unordered_set<ftl::codecs::Channel> operator+(const std::unordered_set<ftl::codecs::Channel> &t, ftl::codecs::Channel c) {
+	auto r = t;
+	r.insert(c);
+	return r;
+}
+
+inline std::unordered_set<ftl::codecs::Channel> operator+(ftl::codecs::Channel a, ftl::codecs::Channel b) {
+	std::unordered_set<ftl::codecs::Channel> r;
+	r.insert(a);
+	r.insert(b);
+	return r;
+}
+
+bool operator!=(const std::unordered_set<ftl::codecs::Channel> &a, const std::unordered_set<ftl::codecs::Channel> &b);
+
+
 #endif  // _FTL_STREAM_STREAM_HPP_
diff --git a/components/streams/src/builder.cpp b/components/streams/src/builder.cpp
index 78a5593034f51e44c7f64d7b8b38607c360d6607..591485844055a0d780225da6214acc447b2e78a4 100644
--- a/components/streams/src/builder.cpp
+++ b/components/streams/src/builder.cpp
@@ -171,6 +171,7 @@ void Builder::_schedule() {
 			if (static_cast<size_t>(fs->count) < fs->frames.size()) fs->set(ftl::data::FSFlag::PARTIAL);
 
 			for (auto &f : fs->frames) f.store();
+			fs->store();
 
 			try {
 				cb_.trigger(*fs);
diff --git a/components/streams/src/receiver.cpp b/components/streams/src/receiver.cpp
index 296481ce7fc98ea8b6a5c4e5acf1feaf999691a0..3050fdf7750a2d31c7b98c018069f90c86acbdeb 100644
--- a/components/streams/src/receiver.cpp
+++ b/components/streams/src/receiver.cpp
@@ -144,7 +144,7 @@ void Receiver::_processState(const StreamPacket &spkt, const Packet &pkt) {
 	for (int i=0; i<pkt.frame_count; ++i) {
 		InternalVideoStates &frame = _getVideoFrame(spkt,i);
 
-		LOG(INFO) << "GOT STATE " << (int)spkt.channel;
+		LOG(INFO) << "GOT STATE " << (int)spkt.streamID << "," << (int)spkt.frame_number;
 
 		if (spkt.channel == Channel::Calibration) {
 			auto &f = builder(spkt.streamID).get(spkt.timestamp, spkt.frame_number);
@@ -347,7 +347,11 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
 		auto &frame = fs->frames[spkt.frame_number+i];
 
 		const auto *cs = stream_;
-		auto sel = stream_->selected(spkt.frameSetID()) & cs->available(spkt.frameSetID());
+		const auto &sel = stream_->selected(spkt.frameSetID()) & cs->available(spkt.frameSetID());
+
+		for (auto &a : sel) {
+			LOG(INFO) << " -- selected " << (int)a;
+		}
 
 		//frame.create<cv::cuda::GpuMat>(spkt.channel);
 
@@ -362,6 +366,7 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
 			
 			// Complete if all requested channels are found
 			//if ((frame.getChannels() & sel) == sel) {
+			if (frame.hasAll(sel)) {
 				timestamp_ = spkt.timestamp;
 				//frame.reset.clear();
 
@@ -383,7 +388,7 @@ void Receiver::_processVideo(const StreamPacket &spkt, const Packet &pkt) {
 				//frame.reset();
 				//frame.completed.clear();
 				//frame.timestamp = -1;
-			//}
+			}
 		//} else {
 		//	LOG(ERROR) << "Frame timestamps mistmatch";
 		//}
diff --git a/components/streams/src/stream.cpp b/components/streams/src/stream.cpp
index 43c53eae64c7ace22ef9026d2a4148c8889f5628..7e6a4d9cd43486b1c2d7cb7638ec72b34c399184 100644
--- a/components/streams/src/stream.cpp
+++ b/components/streams/src/stream.cpp
@@ -8,26 +8,50 @@ using ftl::stream::Broadcast;
 using ftl::stream::Intercept;
 using ftl::stream::Stream;
 
-const ftl::codecs::Channels<0> &Stream::available(int fs) const {
+std::unordered_set<ftl::codecs::Channel> operator&(const std::unordered_set<ftl::codecs::Channel> &a, const std::unordered_set<ftl::codecs::Channel> &b) {
+	std::unordered_set<ftl::codecs::Channel> result;
+	for (auto &i : a) {
+		if (b.find(i) != b.end()) result.insert(i);
+	}
+	return result;
+}
+
+std::unordered_set<ftl::codecs::Channel> operator-(const std::unordered_set<ftl::codecs::Channel> &a, const std::unordered_set<ftl::codecs::Channel> &b) {
+	std::unordered_set<ftl::codecs::Channel> result;
+	for (auto &i : a) {
+		if (b.find(i) == b.end()) result.insert(i);
+	}
+	return result;
+}
+
+bool operator!=(const std::unordered_set<ftl::codecs::Channel> &a, const std::unordered_set<ftl::codecs::Channel> &b) {
+	if (a.size() != b.size()) return false;
+	for (auto &i : a) {
+		if (b.find(i) == b.end()) return false;
+	}
+	return true;
+}
+
+const std::unordered_set<ftl::codecs::Channel> &Stream::available(int fs) const {
 	SHARED_LOCK(mtx_, lk);
 	if (fs < 0 || static_cast<uint32_t>(fs) >= state_.size()) throw FTL_Error("Frameset index out-of-bounds: " << fs);
 	return state_[fs].available;
 }
 
-const ftl::codecs::Channels<0> &Stream::selected(int fs) const {
+const std::unordered_set<ftl::codecs::Channel> &Stream::selected(int fs) const {
 	SHARED_LOCK(mtx_, lk);
 	if (fs < 0 || static_cast<uint32_t>(fs) >= state_.size()) throw FTL_Error("Frameset index out-of-bounds: " << fs);
 	return state_[fs].selected;
 }
 
-void Stream::select(int fs, const ftl::codecs::Channels<0> &s, bool make) {
+void Stream::select(int fs, const std::unordered_set<ftl::codecs::Channel> &s, bool make) {
 	UNIQUE_LOCK(mtx_, lk);
 	if (fs < 0 || (!make && static_cast<uint32_t>(fs) >= state_.size())) throw FTL_Error("Frameset index out-of-bounds: " << fs);
 	if (static_cast<uint32_t>(fs) >= state_.size()) state_.resize(fs+1);
 	state_[fs].selected = s;
 }
 
-ftl::codecs::Channels<0> &Stream::available(int fs) {
+std::unordered_set<ftl::codecs::Channel> &Stream::available(int fs) {
 	UNIQUE_LOCK(mtx_, lk);
 	if (fs < 0) throw FTL_Error("Frameset index out-of-bounds: " << fs);
 	if (static_cast<uint32_t>(fs) >= state_.size()) state_.resize(fs+1);
diff --git a/components/streams/test/receiver_unit.cpp b/components/streams/test/receiver_unit.cpp
index 240f1d92c5fd631f1a15669bf43638a8e1bdc8c9..0a65d9973295d2cbc08a18a448147428f38e0cdd 100644
--- a/components/streams/test/receiver_unit.cpp
+++ b/components/streams/test/receiver_unit.cpp
@@ -19,8 +19,6 @@ using ftl::codecs::Channels;
 using ftl::config::json_t;
 using ftl::data::FrameID;
 
-extern bool ftl_video_initialised();
-
 class TestStream : public ftl::stream::Stream {
 	public:
 	explicit TestStream(nlohmann::json &config) : ftl::stream::Stream(config) {};
@@ -56,8 +54,6 @@ class TestStream : public ftl::stream::Stream {
 
 
 TEST_CASE( "Receiver generating onFrameSet" ) {
-	ftl_video_initialised();
-
 	//ftl::data::make_channel<ftl::rgbd::Camera>(Channel::Calibration, "calibration", ftl::data::StorageMode::PERSISTENT);
 	json_t global = json_t{{"$id","ftl://test"}};
 	ftl::config::configure(global);
@@ -318,6 +314,8 @@ TEST_CASE( "Receiver sync bugs" ) {
 		auto h = receiver->onFrameSet([&count,&ts,&haswrongchan](ftl::rgbd::FrameSet &fs) {
 			++count;
 
+			LOG(INFO) << "GOT FS " << fs.timestamp() << " " << fs.frameset();
+
 			ts = fs.timestamp();
 			haswrongchan = fs.frames[0].hasChannel(Channel::ColourHighRes);
 
diff --git a/components/streams/test/sender_unit.cpp b/components/streams/test/sender_unit.cpp
index 9a1414f95a8888f3eb76d5aac9eeb089e1547eb4..3ee780a1c99ca75d4be542c3d6c701d4db333802 100644
--- a/components/streams/test/sender_unit.cpp
+++ b/components/streams/test/sender_unit.cpp
@@ -287,7 +287,6 @@ TEST_CASE( "Sender request to control encoding" ) {
 	});
 
 	SECTION("a single colour frame request") {
-		try {
 		//stream.select(0, Channels(Channel::Colour), true);
 
 		stream.post({
@@ -317,8 +316,5 @@ TEST_CASE( "Sender request to control encoding" ) {
 		REQUIRE( pkt.data.size() > 0 );
 		REQUIRE( pkt.frame_count == 1 );
 		REQUIRE( ftl::codecs::hevc::validNAL(pkt.data.data(), pkt.data.size()) );
-		} catch (const ftl::exception &e) {
-			LOG(ERROR) << e.trace();
-		}
 	}
 }
diff --git a/components/structures/include/ftl/data/new_frame.hpp b/components/structures/include/ftl/data/new_frame.hpp
index ae0938a2566d36b5d52a96b3f268932df9b27e9c..51820affcfee983e613726f33e7e12bdf0328285 100644
--- a/components/structures/include/ftl/data/new_frame.hpp
+++ b/components/structures/include/ftl/data/new_frame.hpp
@@ -121,6 +121,8 @@ class Frame {
 
 	bool has(ftl::codecs::Channel c) const;
 
+	bool hasAll(const std::unordered_set<ftl::codecs::Channel> &cs);
+
 	inline bool hasChannel(ftl::codecs::Channel c) const { return has(c); }
 
 	inline bool hasOwn(ftl::codecs::Channel c) const;
diff --git a/components/structures/src/new_frame.cpp b/components/structures/src/new_frame.cpp
index ae56a7a20ab3381797ea3d63845e75cc516d3179..e55d5ab939ab22c611d6926570afc7d25d776f4a 100644
--- a/components/structures/src/new_frame.cpp
+++ b/components/structures/src/new_frame.cpp
@@ -11,49 +11,42 @@ using ftl::data::FrameStatus;
 #define LOGURU_REPLACE_GLOG 1
 #include <loguru.hpp>
 
-static std::unordered_map<ftl::codecs::Channel, ChannelConfig> *reg_channels=nullptr;
+static std::unordered_map<ftl::codecs::Channel, ChannelConfig> reg_channels;
 
 void ftl::data::registerChannel(ftl::codecs::Channel c, const ChannelConfig &config) {
-	if (!reg_channels) reg_channels = new std::unordered_map<ftl::codecs::Channel, ChannelConfig>;
-
-	auto i = reg_channels->find(c);
-	if (i != reg_channels->end()) {
+	auto i = reg_channels.find(c);
+	if (i != reg_channels.end()) {
 		if (i->second.mode == config.mode && i->second.type_id == config.type_id && i->second.name == config.name) {
 			return;
 		}
 		throw FTL_Error("Channel " << static_cast<unsigned int>(c) << " already registered");
 	}
 
-	(*reg_channels)[c] = config;
+	reg_channels[c] = config;
 }
 
 void ftl::data::clearRegistry() {
-	if (!reg_channels) return;
-	reg_channels->clear();
+	reg_channels.clear();
 }
 
 bool ftl::data::isPersistent(ftl::codecs::Channel c) {
-	if (!reg_channels) return false;
-	auto i = reg_channels->find(c);
-	return (i != reg_channels->end()) ? i->second.mode == StorageMode::PERSISTENT : false;
+	auto i = reg_channels.find(c);
+	return (i != reg_channels.end()) ? i->second.mode == StorageMode::PERSISTENT : int(c) >= 64 && int(c) < 2048;
 }
 
 bool ftl::data::isAggregate(ftl::codecs::Channel c) {
-	if (!reg_channels) return false;
-	auto i = reg_channels->find(c);
-	return (i != reg_channels->end()) ? i->second.mode == StorageMode::AGGREGATE : false;
+	auto i = reg_channels.find(c);
+	return (i != reg_channels.end()) ? i->second.mode == StorageMode::AGGREGATE : int(c) >= 32 && int(c) < 64;
 }
 
 size_t ftl::data::getChannelType(ftl::codecs::Channel c) {
-	if (!reg_channels) return 0;
-	auto i = reg_channels->find(c);
-	return (i != reg_channels->end()) ? i->second.type_id : 0;
+	auto i = reg_channels.find(c);
+	return (i != reg_channels.end()) ? i->second.type_id : 0;
 }
 
 std::string ftl::data::getChannelName(ftl::codecs::Channel c) {
-	if (!reg_channels) return "";
-	auto i = reg_channels->find(c);
-	return (i != reg_channels->end()) ? i->second.name : "";
+	auto i = reg_channels.find(c);
+	return (i != reg_channels.end()) ? i->second.name : "";
 }
 
 ftl::codecs::Channel ftl::data::getChannelByName(const std::string &name) {
@@ -68,6 +61,13 @@ Frame::~Frame() {
 	if (status_ != FrameStatus::RELEASED && pool_) pool_->release(*this);
 };
 
+bool ftl::data::Frame::hasAll(const std::unordered_set<ftl::codecs::Channel> &cs) {
+	for (auto &a : cs) {
+		if (!has(a)) return false;
+	}
+	return true;
+}
+
 bool ftl::data::Frame::has(ftl::codecs::Channel c) const {
 	const auto &i = data_.find(c);
 	if (i != data_.end() && i->second.status != ftl::data::ChannelStatus::INVALID) {