diff --git a/applications/gui/src/src_window.cpp b/applications/gui/src/src_window.cpp
index bb2105ce95b4b39786d57171430c50eff8b9f65b..baa3a6f4152756f36c71f99f27e793d746f4bee8 100644
--- a/applications/gui/src/src_window.cpp
+++ b/applications/gui/src/src_window.cpp
@@ -83,6 +83,12 @@ SourceWindow::SourceWindow(ftl::gui::Screen *screen)
 		// Request the channels required by current camera configuration
 		interceptor_->select(fs.id, _aggregateChannels());
 
+		/*if (fs.frames[0].hasChannel(Channel::Data)) {
+			int data = 0;
+			fs.frames[0].get(Channel::Data, data);
+			LOG(INFO) << "GOT DATA : " << data;
+		}*/
+
 		const auto *cstream = interceptor_;
 		_createDefaultCameras(fs, cstream->available(fs.id).has(Channel::Depth));
 
diff --git a/applications/reconstruct/src/main.cpp b/applications/reconstruct/src/main.cpp
index 9eabd9e0a6eae0deca2ccb95f604d2b1ad58309d..6d91839dc540386400a0d959246299b1a293e10c 100644
--- a/applications/reconstruct/src/main.cpp
+++ b/applications/reconstruct/src/main.cpp
@@ -188,6 +188,7 @@ static void run(ftl::Configurable *root) {
 			reconstr->setGenerator(gen);
 			reconstr->onFrameSet([sender,i](ftl::rgbd::FrameSet &fs) {
 				fs.id = i;
+				//fs.frames[0].create(Channel::Data, 44);
 				sender->post(fs);
 				return true;
 			});
diff --git a/components/rgbd-sources/include/ftl/rgbd/frame.hpp b/components/rgbd-sources/include/ftl/rgbd/frame.hpp
index eb59f93931d728ad048db4814a6cfbf01716da24..69ed68746f6b9095ed0937fc8b65339506421605 100644
--- a/components/rgbd-sources/include/ftl/rgbd/frame.hpp
+++ b/components/rgbd-sources/include/ftl/rgbd/frame.hpp
@@ -284,6 +284,9 @@ public:
 	 * Obtain a mask of all available channels in the frame.
 	 */
 	inline ftl::codecs::Channels<0> getChannels() const { return channels_; }
+	inline ftl::codecs::Channels<0> getVideoChannels() const { return channels_; }
+
+	inline ftl::codecs::Channels<2048> getDataChannels() const { return data_channels_; }
 
 	/**
 	 * Is the channel data currently located on GPU. This also returns false if
@@ -381,6 +384,13 @@ public:
 	 */
 	std::string getConfigString() const;
 
+	/**
+	 * Access the raw data channel vector object.
+	 */
+	const std::vector<unsigned char> &getRawData(ftl::codecs::Channel c) const;
+
+	void createRawData(ftl::codecs::Channel c, const std::vector<unsigned char> &v);
+
 	/**
 	 * Wrapper to access a config property. If the property does not exist or
 	 * is not of the requested type then the returned optional is false.
diff --git a/components/rgbd-sources/src/frame.cpp b/components/rgbd-sources/src/frame.cpp
index 4ed2b43512a68d0d2ac47e2ed987204db9c0e901..6fb82e19e70a39a7d1e33b8d8fbfef841ac5d071 100644
--- a/components/rgbd-sources/src/frame.cpp
+++ b/components/rgbd-sources/src/frame.cpp
@@ -443,3 +443,15 @@ std::string ftl::rgbd::Frame::getConfigString() const {
 	return get<nlohmann::json>(ftl::codecs::Channel::Configuration).dump();
 }
 
+const std::vector<unsigned char> &ftl::rgbd::Frame::getRawData(ftl::codecs::Channel channel) const {
+	if (static_cast<int>(channel) < static_cast<int>(ftl::codecs::Channel::Data)) throw ftl::exception("Non data channel");
+	if (!hasChannel(channel)) throw ftl::exception("Data channel does not exist");
+
+	return data_data_.at(static_cast<int>(channel));
+}
+
+void ftl::rgbd::Frame::createRawData(ftl::codecs::Channel c, const std::vector<unsigned char> &v) {
+	data_data_.insert({static_cast<int>(c), v});
+	data_channels_ += c;
+}
+
diff --git a/components/streams/src/receiver.cpp b/components/streams/src/receiver.cpp
index ad74db5d72c6b7809e8721949a3dff2df9429589..5e525ea0fdc3e4d061d210a4a942be1ba644dfac 100644
--- a/components/streams/src/receiver.cpp
+++ b/components/streams/src/receiver.cpp
@@ -103,7 +103,11 @@ void Receiver::setStream(ftl::stream::Stream *s) {
 			//return;
 		//}
 
-		if (channum >= 64) {
+		if (channum >= 2048) {
+			InternalStates &frame = _getFrame(spkt);
+			frame.frame.createRawData(spkt.channel, pkt.data);
+			return;
+		} else if (channum >= 64) {
 			for (int i=0; i<pkt.frame_count; ++i) {
 				InternalStates &frame = _getFrame(spkt,i);
 
diff --git a/components/streams/src/sender.cpp b/components/streams/src/sender.cpp
index 261c8b2fec49e6e0ec0e7b066d3df852683c380f..db7bb7c04467ab623c64df93a32d4a2921c8b8bf 100644
--- a/components/streams/src/sender.cpp
+++ b/components/streams/src/sender.cpp
@@ -141,6 +141,25 @@ void Sender::post(const ftl::rgbd::FrameSet &fs) {
 				available += c;
 			}
         }
+
+		// FIXME: Allow data channel selection rather than always send
+		for (auto c : frame.getDataChannels()) {
+			StreamPacket spkt;
+			spkt.version = 4;
+			spkt.timestamp = fs.timestamp;
+			spkt.streamID = 0; //fs.id;
+			spkt.frame_number = i;
+			spkt.channel = c;
+
+			ftl::codecs::Packet pkt;
+			pkt.codec = ftl::codecs::codec_t::MSGPACK;
+			pkt.definition = ftl::codecs::definition_t::Any;
+			pkt.frame_count = 1;
+			pkt.flags = 0;
+			pkt.bitrate = 0;
+			pkt.data = frame.getRawData(c);
+			stream_->post(spkt, pkt);
+		}
     }
 
 	for (auto c : available) {