diff --git a/applications/vision/src/main.cpp b/applications/vision/src/main.cpp
index a172d8e78f3b5c037ca5c8d7fc68256106266da6..a406e5af4c1e61200bb829b8db09a491f2e1ec2b 100644
--- a/applications/vision/src/main.cpp
+++ b/applications/vision/src/main.cpp
@@ -154,7 +154,7 @@ static void run(ftl::Configurable *root) {
 	grp->addSource(source);*/
 
 	ftl::data::Pool pool(2,5);
-	auto creator = pool.creator<ftl::data::IntervalFrameCreator>(0, source);
+	auto creator = pool.creator<ftl::data::IntervalFrameCreator>(ftl::data::FrameID(0,0), source);
 
 	// Listen for any flush events for frameset 0
 	/*auto flushh = pool.group(0).onFlush([](ftl::data::Frame &f, ftl::codecs::Channel c) {
diff --git a/components/streams/src/builder.cpp b/components/streams/src/builder.cpp
index b5b8b134387dcd35f585376169aec8ff6fec8e4e..78a5593034f51e44c7f64d7b8b38607c360d6607 100644
--- a/components/streams/src/builder.cpp
+++ b/components/streams/src/builder.cpp
@@ -93,7 +93,7 @@ ftl::data::Frame &Builder::get(int64_t timestamp, size_t ix) {
 	//if (ix >= fs->frames.size()) {
 		//throw FTL_Error("Frame index out-of-bounds - " << ix << "(" << fs->frames.size() << ")");
 		while (fs->frames.size() < size_) {
-			fs->frames.push_back(std::move(pool_->allocate((fs->frameset() << 8) + fs->frames.size(), fs->timestamp())));
+			fs->frames.push_back(std::move(pool_->allocate(ftl::data::FrameID(fs->frameset(), + fs->frames.size()), fs->timestamp())));
 		}
 	//}
 
@@ -313,9 +313,9 @@ ftl::data::FrameSet *Builder::_addFrameset(int64_t timestamp) {
 		framesets_.clear();
 	}
 
-	FrameSet *newf = new FrameSet(pool_, id_, timestamp);
+	FrameSet *newf = new FrameSet(pool_, ftl::data::FrameID(id_,255), timestamp);
 	for (size_t i=0; i<size_; ++i) {
-		newf->frames.push_back(std::move(pool_->allocate((id_ << 8)+i, timestamp)));
+		newf->frames.push_back(std::move(pool_->allocate(ftl::data::FrameID(id_, i), timestamp)));
 	}
 
 	newf->count = 0;
diff --git a/components/streams/test/builder_unit.cpp b/components/streams/test/builder_unit.cpp
index ab72a378cf44fcefa72622a181c3bd7308961e68..6e530464fdb60171534cb6e517d5b3299078a029 100644
--- a/components/streams/test/builder_unit.cpp
+++ b/components/streams/test/builder_unit.cpp
@@ -10,12 +10,13 @@ using ftl::streams::Builder;
 TEST_CASE("ftl::streams::Builder can obtain a frameset", "[]") {
 	SECTION("with one frame allocated") {
 		Pool pool(2,5);
-		Builder builder(pool, 44);
+		Builder builder(&pool, 44);
 
 		builder.get(100, 0);
 		auto *fs = builder.get(100);
 
-		REQUIRE( fs->id() == 44 );
+		REQUIRE( fs->frameset() == 44 );
+		REQUIRE( fs->source() == 255);
 		REQUIRE( fs->timestamp() == 100 );
 		REQUIRE( fs->frames.size() == 1 );
 		REQUIRE( fs->frames[0].status() == ftl::data::FrameStatus::CREATED );
@@ -25,13 +26,13 @@ TEST_CASE("ftl::streams::Builder can obtain a frameset", "[]") {
 
 	SECTION("with five frames allocated") {
 		Pool pool(2,5);
-		Builder builder(pool, 44);
+		Builder builder(&pool, 44);
 
 		builder.get(100, 4);
 		builder.get(100, 0);
 		auto *fs = builder.get(100);
 
-		REQUIRE( fs->id() == 44 );
+		REQUIRE( fs->frameset() == 44 );
 		REQUIRE( fs->timestamp() == 100 );
 		REQUIRE( fs->frames.size() == 5 );
 		REQUIRE( fs->frames[3].status() == ftl::data::FrameStatus::CREATED );
@@ -43,7 +44,7 @@ TEST_CASE("ftl::streams::Builder can obtain a frameset", "[]") {
 TEST_CASE("ftl::streams::Builder can complete a frame", "[]") {
 	SECTION("with two frames allocated") {
 		Pool pool(2,5);
-		Builder builder(pool, 44);
+		Builder builder(&pool, 44);
 
 		builder.get(100, 1);
 		builder.get(100, 0);
@@ -51,7 +52,7 @@ TEST_CASE("ftl::streams::Builder can complete a frame", "[]") {
 
 		builder.completed(100, 0);
 
-		REQUIRE( fs->id() == 44 );
+		REQUIRE( fs->frameset() == 44 );
 		REQUIRE( fs->timestamp() == 100 );
 		REQUIRE( fs->frames.size() == 2 );
 		//REQUIRE( fs->frames[0].status() == ftl::data::FrameStatus::CREATED );
@@ -63,7 +64,7 @@ TEST_CASE("ftl::streams::Builder can complete a frame", "[]") {
 TEST_CASE("ftl::streams::Builder can complete a frameset", "[]") {
 	SECTION("with one frame allocated and no buffering") {
 		Pool pool(2,5);
-		Builder builder(pool, 44);
+		Builder builder(&pool, 44);
 
 		builder.setBufferSize(0);
 
@@ -73,7 +74,7 @@ TEST_CASE("ftl::streams::Builder can complete a frameset", "[]") {
 		int fsid = 0;
 
 		auto h = builder.onFrameSet([&fsid](ftl::data::FrameSet &fs) {
-			fsid = fs.id();
+			fsid = fs.frameset();
 			return false;
 		});
 
@@ -86,7 +87,7 @@ TEST_CASE("ftl::streams::Builder can complete a frameset", "[]") {
 
 	SECTION("with two frames allocated and no buffering") {
 		Pool pool(2,5);
-		Builder builder(pool, 44);
+		Builder builder(&pool, 44);
 
 		builder.setBufferSize(0);
 
@@ -96,7 +97,7 @@ TEST_CASE("ftl::streams::Builder can complete a frameset", "[]") {
 		int fsid = 0;
 
 		auto h = builder.onFrameSet([&fsid](ftl::data::FrameSet &fs) {
-			fsid = fs.id();
+			fsid = fs.frameset();
 			return false;
 		});
 
@@ -110,7 +111,7 @@ TEST_CASE("ftl::streams::Builder can complete a frameset", "[]") {
 
 	SECTION("does not complete a partial") {
 		Pool pool(2,5);
-		Builder builder(pool, 44);
+		Builder builder(&pool, 44);
 
 		builder.setBufferSize(0);
 
@@ -120,7 +121,7 @@ TEST_CASE("ftl::streams::Builder can complete a frameset", "[]") {
 		int fsid = 0;
 
 		auto h = builder.onFrameSet([&fsid](ftl::data::FrameSet &fs) {
-			fsid = fs.id();
+			fsid = fs.frameset();
 			return false;
 		});
 
diff --git a/components/streams/test/receiver_unit.cpp b/components/streams/test/receiver_unit.cpp
index 45160cae2aad57fea23fac288007b70e6cdd4c4f..567fffeb848b777b66d78746de19c910c7e39cf9 100644
--- a/components/streams/test/receiver_unit.cpp
+++ b/components/streams/test/receiver_unit.cpp
@@ -17,6 +17,7 @@ using ftl::rgbd::FrameSet;
 using ftl::codecs::Channel;
 using ftl::codecs::Channels;
 using ftl::config::json_t;
+using ftl::data::FrameID;
 
 class TestStream : public ftl::stream::Stream {
 	public:
@@ -86,7 +87,7 @@ TEST_CASE( "Receiver generating onFrameSet" ) {
 	spkt.channel = Channel::Colour;
 	spkt.streamID = 0;
 
-	ftl::data::Frame dummy = pool.allocate(0,10);
+	ftl::data::Frame dummy = pool.allocate(FrameID(0,0),10);
 	dummy.store();
 	ftl::rgbd::Frame &state = dummy.cast<ftl::rgbd::Frame>();
 	state.setLeft().width = 1280;
@@ -289,7 +290,7 @@ TEST_CASE( "Receiver sync bugs" ) {
 	spkt.channel = Channel::Colour;
 	spkt.streamID = 0;
 
-	ftl::data::Frame dummy = pool.allocate(0,10);
+	ftl::data::Frame dummy = pool.allocate(FrameID(0,0),10);
 	dummy.store();
 	ftl::rgbd::Frame &state = dummy.cast<ftl::rgbd::Frame>();
 	state.setLeft().width = 1280;
@@ -378,7 +379,7 @@ TEST_CASE( "Receiver non zero buffer" ) {
 	spkt.channel = Channel::Colour;
 	spkt.streamID = 0;
 
-	ftl::data::Frame dummy = pool.allocate(0,10);
+	ftl::data::Frame dummy = pool.allocate(FrameID(0,0),10);
 	dummy.store();
 	ftl::rgbd::Frame &state = dummy.cast<ftl::rgbd::Frame>();
 	state.setLeft().width = 1280;
diff --git a/components/structures/include/ftl/data/creators.hpp b/components/structures/include/ftl/data/creators.hpp
index 17f7e77a9a3b674d8b5bea024d0fd0f3ccff901c..3cd28e4d30362b5d1e56b1049c430d665fcc0052 100644
--- a/components/structures/include/ftl/data/creators.hpp
+++ b/components/structures/include/ftl/data/creators.hpp
@@ -23,11 +23,11 @@ class FrameCreator {
 	inline Pool *pool() const { return pool_; }
 
 	protected:
-	FrameCreator(Pool *p_pool, uint32_t p_id) : pool_(p_pool), id_(p_id) {}
+	FrameCreator(Pool *p_pool, FrameID p_id) : pool_(p_pool), id_(p_id) {}
 
 	private:
 	Pool *pool_;
-	uint32_t id_;
+	FrameID id_;
 };
 
 /**
@@ -48,7 +48,7 @@ class IntervalFrameCreator : public ftl::data::FrameCreator {
 	friend class Pool;
 
 	private:
-	explicit IntervalFrameCreator(Pool *p_pool, uint32_t p_id, DiscreteSource *src);
+	explicit IntervalFrameCreator(Pool *p_pool, FrameID p_id, DiscreteSource *src);
 
 	public:
 
diff --git a/components/structures/include/ftl/data/framepool.hpp b/components/structures/include/ftl/data/framepool.hpp
index 69f2d1cbb2687e3cdba406620e67d0c767dc925c..83041a5c9f4ec92bf10ad579fda95e19d294a01c 100644
--- a/components/structures/include/ftl/data/framepool.hpp
+++ b/components/structures/include/ftl/data/framepool.hpp
@@ -15,18 +15,18 @@ class Pool {
 	explicit Pool(size_t min_n, size_t max_n);
 	~Pool();
 
-	ftl::data::Frame allocate(uint32_t id, int64_t timestamp);
+	ftl::data::Frame allocate(FrameID id, int64_t timestamp);
 	void release(Frame &f);
 
-	ftl::data::Session &session(uint32_t id);
-	inline ftl::data::Session &group(uint32_t id) { return session(id); }
+	ftl::data::Session &session(FrameID id);
+	inline ftl::data::Session &group(FrameID id) { return session(id); }
 
-	size_t size(uint32_t id);
+	size_t size(FrameID id);
 
 	size_t size();
 
 	template <typename T, typename ...ARGS>
-	T creator(uint32_t id, ARGS ...args) {
+	T creator(FrameID id, ARGS ...args) {
 		static_assert(std::is_base_of<ftl::data::FrameCreator, T>::value, "A creator must inherit FrameCreator");
 		return T(this, id, args...);
 	}
@@ -43,7 +43,7 @@ class Pool {
 	size_t max_n_;
 	size_t ideal_n_;
 
-	PoolData &_getPool(uint32_t);
+	PoolData &_getPool(FrameID);
 };
 
 }
diff --git a/components/structures/include/ftl/data/new_frame.hpp b/components/structures/include/ftl/data/new_frame.hpp
index c2ec8b04729b3d233ce1c8307d2ad494b85defd6..ae0938a2566d36b5d52a96b3f268932df9b27e9c 100644
--- a/components/structures/include/ftl/data/new_frame.hpp
+++ b/components/structures/include/ftl/data/new_frame.hpp
@@ -25,6 +25,23 @@ namespace data {
 class Session;
 class Pool;
 
+struct FrameID {
+	uint32_t id;
+
+	inline int frameset() const { return id >> 8; }
+	inline int source() const { return id & 0xff; }
+
+	operator uint32_t() const { return id; }
+
+	/**
+	 * Create a frame ID using a frameset id and a source number.
+	 * @param fs Frameset id
+	 * @param s Source number inside frameset
+	 */
+	FrameID(int fs, int s) : id((fs << 8) + (s & 0xff) ) {}
+	FrameID() : id(0) {}
+};
+
 enum FrameMode {
 	PRIMARY,
 	RESPONSE,
@@ -69,16 +86,16 @@ class Frame {
 
 	protected:
 	// Only Feed class should construct
-	Frame(Pool *ppool, Session *parent, uint32_t pid, int64_t ts) : timestamp_(ts), id_(pid), pool_(ppool), parent_(parent), status_(FrameStatus::CREATED) {};
+	Frame(Pool *ppool, Session *parent, FrameID pid, int64_t ts) : timestamp_(ts), id_(pid), pool_(ppool), parent_(parent), status_(FrameStatus::CREATED) {};
 	int64_t timestamp_=0;
-	uint32_t id_=0;
+	FrameID id_;
 
 	public:
 
 	inline int64_t timestamp() const { return timestamp_; }
-	inline uint32_t id() const { return id_; }
-	inline int frameset() const { return id_ >> 8; }
-	inline int source() const { return id_ & 0xFF; }
+	inline FrameID id() const { return id_; }
+	inline int frameset() const { return id_.frameset(); }
+	inline int source() const { return id_.source(); }
 
 	public:
 	Frame()=delete;
@@ -302,7 +319,7 @@ class Session : public Frame {
 	friend class Frame;
 
 	public:
-	Session() : Frame(nullptr, nullptr,0,0) {
+	Session() : Frame(nullptr, nullptr,FrameID(0,0),0) {
 		status_ = FrameStatus::STORED;
 	}
 
diff --git a/components/structures/include/ftl/data/new_frameset.hpp b/components/structures/include/ftl/data/new_frameset.hpp
index a0ae5e68864afa418516f94c4bb5d33d5eb7ffb8..29e04d38dd4aa9bc5e157c3fee42a9a9f22f9803 100644
--- a/components/structures/include/ftl/data/new_frameset.hpp
+++ b/components/structures/include/ftl/data/new_frameset.hpp
@@ -33,7 +33,7 @@ class FrameSet : public ftl::data::Frame {
 	
 
 	public:
-	FrameSet(Pool *ppool, uint32_t pid, int64_t ts);
+	FrameSet(Pool *ppool, FrameID pid, int64_t ts);
 
 	//int id=0;
 	//int64_t timestamp;				// Millisecond timestamp of all frames
diff --git a/components/structures/src/creators.cpp b/components/structures/src/creators.cpp
index 697139502594dd5ec02ff136d76732808e0d1e21..21f4789bfe48302f33400f7b20a45fd89c9faeae 100644
--- a/components/structures/src/creators.cpp
+++ b/components/structures/src/creators.cpp
@@ -19,7 +19,7 @@ Frame FrameCreator::create(int64_t timestamp) {
 	return f;
 }
 
-IntervalFrameCreator::IntervalFrameCreator(Pool *p_pool, uint32_t p_id, DiscreteSource *src)
+IntervalFrameCreator::IntervalFrameCreator(Pool *p_pool, FrameID p_id, DiscreteSource *src)
 	: FrameCreator(p_pool, p_id), src_(src) {}
 
 void IntervalFrameCreator::start() {
diff --git a/components/structures/src/frameset.cpp b/components/structures/src/frameset.cpp
index 79252d45884529819916c5f9693af2efe710301f..8df74adfb609ece914327010eea361ee659322da 100644
--- a/components/structures/src/frameset.cpp
+++ b/components/structures/src/frameset.cpp
@@ -4,7 +4,7 @@
 using ftl::data::Frame;
 using ftl::data::FrameSet;
 
-FrameSet::FrameSet(Pool *ppool, uint32_t pid, int64_t ts) : Frame(ppool->allocate((pid << 8)| 0xFF, ts)) {
+FrameSet::FrameSet(Pool *ppool, FrameID pid, int64_t ts) : Frame(ppool->allocate(FrameID(pid.frameset(),255), ts)) {
 
 }
 
@@ -59,7 +59,7 @@ void FrameSet::flush(ftl::codecs::Channel c) {
  * timestamp from the frame and creates a wrapping frameset instance.
  */
 std::shared_ptr<FrameSet> FrameSet::fromFrame(Frame &f) {
-	auto sptr = std::make_shared<FrameSet>(f.pool(), f.id()|0xFF, f.timestamp());
+	auto sptr = std::make_shared<FrameSet>(f.pool(), f.id(), f.timestamp());
 	sptr->frames.push_back(std::move(f));
 	sptr->count = 1;
 	sptr->mask = 1;
diff --git a/components/structures/src/new_frame.cpp b/components/structures/src/new_frame.cpp
index 7ed41592af23f8eb3b53f9c54687dc6070edda05..4e9b5b3408feeab79d2febed196ebfac46537243 100644
--- a/components/structures/src/new_frame.cpp
+++ b/components/structures/src/new_frame.cpp
@@ -270,7 +270,7 @@ Frame Frame::response() {
 }
 
 Frame Frame::make_standalone() {
-	Frame f(nullptr, nullptr, 0, 0);
+	Frame f(nullptr, nullptr, FrameID(0,0), 0);
 	f.mode_ = FrameMode::STANDALONE;
 	return f;
 }
diff --git a/components/structures/src/pool.cpp b/components/structures/src/pool.cpp
index 21906fa90c77d4fa71ae27e2f2188f967ce2aba1..9c1839860bb34fe1eaec5960b50ceab116182751 100644
--- a/components/structures/src/pool.cpp
+++ b/components/structures/src/pool.cpp
@@ -17,7 +17,7 @@ Pool::~Pool() {
 	}
 }
 
-Frame Pool::allocate(uint32_t id, int64_t timestamp) {
+Frame Pool::allocate(FrameID id, int64_t timestamp) {
 	auto &pool = _getPool(id);
 
 	if (timestamp < pool.last_timestamp) {
@@ -52,12 +52,12 @@ void Pool::release(Frame &f) {
 	}
 }
 
-ftl::data::Session &Pool::session(uint32_t id) {
+ftl::data::Session &Pool::session(FrameID id) {
 	auto &pool = _getPool(id);
 	return pool.session;
 }
 
-size_t Pool::size(uint32_t id) {
+size_t Pool::size(FrameID id) {
 	auto &pool = _getPool(id);
 	return pool.pool.size();
 }
@@ -70,6 +70,6 @@ size_t Pool::size() {
 	return s;
 }
 
-ftl::data::Pool::PoolData &Pool::_getPool(uint32_t id) {
-	return pool_[id];
+ftl::data::Pool::PoolData &Pool::_getPool(FrameID id) {
+	return pool_[id.id];
 }