diff --git a/components/codecs/include/ftl/codecs/nvpipe_encoder.hpp b/components/codecs/include/ftl/codecs/nvpipe_encoder.hpp
index e4496c1f3639c7b5add59a94342a186b488ffd8a..c2fe379dc985488f014e911dd1e096431bdee96e 100644
--- a/components/codecs/include/ftl/codecs/nvpipe_encoder.hpp
+++ b/components/codecs/include/ftl/codecs/nvpipe_encoder.hpp
@@ -34,6 +34,7 @@ class NvPipeEncoder : public ftl::codecs::Encoder {
     definition_t current_definition_;
     bool is_float_channel_;
 	bool was_reset_;
+	ftl::codecs::codec_t preference_;
 
     bool _encoderMatch(const cv::Mat &in, definition_t def);
     bool _createEncoder(const cv::Mat &in, definition_t def, bitrate_t rate);
diff --git a/components/codecs/src/nvpipe_decoder.cpp b/components/codecs/src/nvpipe_decoder.cpp
index 8ee1f06f466105f51412135ddc3fbc76fa607e03..97985cd20c4bd2dea7aa86c829b3b151563c3cfb 100644
--- a/components/codecs/src/nvpipe_decoder.cpp
+++ b/components/codecs/src/nvpipe_decoder.cpp
@@ -50,7 +50,7 @@ void cropAndScaleUp(cv::Mat &in, cv::Mat &out) {
 bool NvPipeDecoder::decode(const ftl::codecs::Packet &pkt, cv::Mat &out) {
 	cudaSetDevice(0);
 	UNIQUE_LOCK(mutex_,lk);
-	if (pkt.codec != codec_t::HEVC) return false;
+	if (pkt.codec != codec_t::HEVC && pkt.codec != codec_t::H264) return false;
 	bool is_float_frame = out.type() == CV_32F;
 
 	// Is the previous decoder still valid for current resolution and type?
@@ -68,7 +68,7 @@ bool NvPipeDecoder::decode(const ftl::codecs::Packet &pkt, cv::Mat &out) {
 	if (nv_decoder_ == nullptr) {
 		nv_decoder_ = NvPipe_CreateDecoder(
 				(is_float_frame) ? NVPIPE_UINT16 : NVPIPE_RGBA32,
-				NVPIPE_HEVC,
+				(pkt.codec == codec_t::HEVC) ? NVPIPE_HEVC : NVPIPE_H264,
 				ftl::codecs::getWidth(pkt.definition),
 				ftl::codecs::getHeight(pkt.definition));
 		if (!nv_decoder_) {
@@ -88,6 +88,7 @@ bool NvPipeDecoder::decode(const ftl::codecs::Packet &pkt, cv::Mat &out) {
 		// Obtain NAL unit type
 		if (ftl::codecs::hevc::isIFrame(pkt.data)) seen_iframe_ = true;
 	}
+	// TODO: Parse H264 for i-frame check
 
 	if (!seen_iframe_) return false;
 
diff --git a/components/codecs/src/nvpipe_encoder.cpp b/components/codecs/src/nvpipe_encoder.cpp
index ad2f19e7276ea103cd044f38be79295e87bbb530..5b4fbdcc5f4c6f9d7345bc45beabfb373a1bd00a 100644
--- a/components/codecs/src/nvpipe_encoder.cpp
+++ b/components/codecs/src/nvpipe_encoder.cpp
@@ -20,6 +20,7 @@ NvPipeEncoder::NvPipeEncoder(definition_t maxdef,
 	current_definition_ = definition_t::HD1080;
 	is_float_channel_ = false;
 	was_reset_ = false;
+	preference_ = codec_t::Any;
 }
 
 NvPipeEncoder::~NvPipeEncoder() {
@@ -33,7 +34,7 @@ void NvPipeEncoder::reset() {
 bool NvPipeEncoder::supports(ftl::codecs::codec_t codec) {
 	switch (codec) {
 	case codec_t::H264:
-	case codec_t::HEVC: return true;
+	case codec_t::HEVC: preference_ = codec; return true;
 	default: return false;
 	}
 }
@@ -125,7 +126,7 @@ bool NvPipeEncoder::encode(const cv::Mat &in, definition_t odefinition, bitrate_
 	//std::swap(tmp, tmp2);
 
 	Packet pkt;
-	pkt.codec = codec_t::HEVC;
+	pkt.codec = (preference_ == codec_t::Any) ? codec_t::HEVC : preference_;
 	pkt.definition = definition;
 	pkt.block_total = 1;
 	pkt.block_number = 0;
@@ -193,7 +194,7 @@ bool NvPipeEncoder::_createEncoder(const cv::Mat &in, definition_t def, bitrate_
 	const int fps = 1000/ftl::timer::getInterval();
 	nvenc_ = NvPipe_CreateEncoder(
 		(is_float_channel_) ? NVPIPE_UINT16 : NVPIPE_RGBA32,
-		NVPIPE_HEVC,
+		(preference_ == codec_t::Any || preference_ == codec_t::HEVC) ? NVPIPE_HEVC : NVPIPE_H264,
 		(is_float_channel_) ? NVPIPE_LOSSLESS : NVPIPE_LOSSY,
 		16*1000*1000,
 		fps,				// FPS