diff --git a/src/encoder/encoder.hpp b/src/encoder/encoder.hpp
index a97e2b616e3b44681f8645b2e6773a3fa2d1460e..7afa7c00bac0cde6b5c9c91f3b2431e7b1b03b6a 100644
--- a/src/encoder/encoder.hpp
+++ b/src/encoder/encoder.hpp
@@ -1,5 +1,5 @@
 /*
-  The encoder can be used to create a h264 stream out of a sequence of images.
+  The encoder can be used to create an encoded stream out of a sequence of images.
   In order to be able to use the encoder, it is neccessary to call the function setup_instance_for_encoder(...) during the setup of the vulkan instance.
   Besides that, it is neccessary to call the function setup_device_for_encoder(...) during the setup of the vulkan device.
   A frame can be submitted for encoding using the function encode(...).
@@ -35,6 +35,12 @@
 #include <memory>
 #include <cstdint>
 
+enum EncoderCodec
+{
+    ENCODER_CODEC_H264,
+    ENCODER_CODEC_H265
+};
+
 enum EncoderMode
 {
     ENCODER_MODE_CONSTANT_BITRATE,
@@ -87,7 +93,7 @@ public:
     Encoder() = default;
     virtual ~Encoder() = default;
 
-    virtual bool create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format) = 0;
+    virtual bool create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format, EncoderCodec codec) = 0;
     virtual void destroy() = 0;
 
     // The following functions should be thread safe.
@@ -108,6 +114,7 @@ public:
     virtual void set_frame_rate(uint32_t frame_rate);   // The frame rate is given in frames per second.                           Default: 90
 
     // The following functions should be thread safe.
+    virtual EncoderCodec get_codec() const = 0;
     virtual EncoderMode get_mode() const;
     virtual double get_quality() const;
     virtual double get_bitrate() const;
diff --git a/src/encoder/nvidia_encoder.cpp b/src/encoder/nvidia_encoder.cpp
index 0823eaf8c958f3ea4ed00da107162e7d1b9217d8..f75b02024c6b4ec528c8cd65522e89933fd66e86 100644
--- a/src/encoder/nvidia_encoder.cpp
+++ b/src/encoder/nvidia_encoder.cpp
@@ -31,16 +31,17 @@ NvidiaEncoder::NvidiaEncoder() : worker_pool(1)
 
 }
 
-bool NvidiaEncoder::create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format)
+bool NvidiaEncoder::create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format, EncoderCodec codec)
 {
     this->device = device;
+    this->codec = codec;
 
     if (!this->create_context(device))
     {
         return false;
     }
 
-    if (!this->create_session(size))
+    if (!this->create_session(size, codec))
     {
         return false;
     }
@@ -232,6 +233,11 @@ void NvidiaEncoder::set_frame_rate(uint32_t frame_rate)
     this->config_change = true;
 }
 
+EncoderCodec NvidiaEncoder::get_codec() const
+{
+    return this->codec;
+}
+
 EncoderMode NvidiaEncoder::get_mode() const
 {
     return this->mode;
@@ -500,44 +506,6 @@ void NvidiaEncoder::submit_encode_task(NvidiaEncoderFrame::Ptr frame)
         return;
     }
 
-    NV_ENC_PIC_PARAMS_MVC motion_vector_parameters;
-    motion_vector_parameters.version = NV_ENC_PIC_PARAMS_MVC_VER;
-    motion_vector_parameters.viewID = 0;
-    motion_vector_parameters.temporalID = 0;
-    motion_vector_parameters.priorityID = 0;
-    memset(motion_vector_parameters.reserved1, 0, sizeof(motion_vector_parameters.reserved1));
-    memset(motion_vector_parameters.reserved2, 0, sizeof(motion_vector_parameters.reserved2));
-
-    NV_ENC_PIC_PARAMS_H264_EXT codec_extention_parameters;
-    codec_extention_parameters.mvcPicParams = motion_vector_parameters;
-    memset(codec_extention_parameters.reserved1, 0, sizeof(codec_extention_parameters.reserved1));
-    
-    NV_ENC_PIC_PARAMS_H264 codec_parameters;
-    codec_parameters.displayPOCSyntax = 0;
-    codec_parameters.reserved3 = 0;
-    codec_parameters.refPicFlag = 0;
-    codec_parameters.colourPlaneId = 0;
-    codec_parameters.forceIntraRefreshWithFrameCnt = 0;
-    codec_parameters.constrainedFrame = 1;
-    codec_parameters.sliceModeDataUpdate = 1;
-    codec_parameters.ltrMarkFrame = 0;
-    codec_parameters.ltrUseFrames = 0;
-    codec_parameters.reservedBitFields = 0;
-    codec_parameters.sliceTypeData = 0;
-    codec_parameters.sliceTypeArrayCnt = 0;
-    codec_parameters.seiPayloadArrayCnt = 0;
-    codec_parameters.seiPayloadArray = nullptr;
-    codec_parameters.sliceMode = 3;
-    codec_parameters.sliceModeData = 10;
-    codec_parameters.ltrMarkFrameIdx = 0;
-    codec_parameters.ltrUseFrameBitmap = 0;
-    codec_parameters.ltrUsageMode = 0;
-    codec_parameters.forceIntraSliceCount = 0;
-    codec_parameters.forceIntraSliceIdx = 0;
-    codec_parameters.h264ExtPicParams = codec_extention_parameters;
-    memset(codec_parameters.reserved, 0, sizeof(codec_parameters.reserved));
-    memset(codec_parameters.reserved2, 0, sizeof(codec_parameters.reserved2));
-
     NV_ENC_PIC_PARAMS encode_parameters;
     encode_parameters.version = NV_ENC_PIC_PARAMS_VER;
     encode_parameters.inputWidth = frame->image_size.x;
@@ -553,7 +521,6 @@ void NvidiaEncoder::submit_encode_task(NvidiaEncoderFrame::Ptr frame)
     encode_parameters.bufferFmt = map_info.mappedBufferFmt;
     encode_parameters.pictureStruct = NV_ENC_PIC_STRUCT_FRAME;
     encode_parameters.pictureType = (NV_ENC_PIC_TYPE)0;
-    encode_parameters.codecPicParams.h264PicParams = codec_parameters;
     memset(encode_parameters.meHintCountsPerBlock, 0, sizeof(encode_parameters.meHintCountsPerBlock));
     encode_parameters.meExternalHints = nullptr;
     memset(encode_parameters.reserved1, 0, sizeof(encode_parameters.reserved1));
@@ -566,6 +533,83 @@ void NvidiaEncoder::submit_encode_task(NvidiaEncoderFrame::Ptr frame)
     memset(encode_parameters.reserved3, 0, sizeof(encode_parameters.reserved3));
     memset(encode_parameters.reserved4, 0, sizeof(encode_parameters.reserved4));
 
+    if(this->codec == ENCODER_CODEC_H264)
+    {
+        NV_ENC_PIC_PARAMS_MVC motion_vector_parameters;
+        motion_vector_parameters.version = NV_ENC_PIC_PARAMS_MVC_VER;
+        motion_vector_parameters.viewID = 0;
+        motion_vector_parameters.temporalID = 0;
+        motion_vector_parameters.priorityID = 0;
+        memset(motion_vector_parameters.reserved1, 0, sizeof(motion_vector_parameters.reserved1));
+        memset(motion_vector_parameters.reserved2, 0, sizeof(motion_vector_parameters.reserved2));
+
+        NV_ENC_PIC_PARAMS_H264_EXT codec_extention_parameters;
+        codec_extention_parameters.mvcPicParams = motion_vector_parameters;
+        memset(codec_extention_parameters.reserved1, 0, sizeof(codec_extention_parameters.reserved1));
+    
+        NV_ENC_PIC_PARAMS_H264 codec_parameters;
+        codec_parameters.displayPOCSyntax = 0;
+        codec_parameters.reserved3 = 0;
+        codec_parameters.refPicFlag = 0;
+        codec_parameters.colourPlaneId = 0;
+        codec_parameters.forceIntraRefreshWithFrameCnt = 0;
+        codec_parameters.constrainedFrame = 1;
+        codec_parameters.sliceModeDataUpdate = 1;
+        codec_parameters.ltrMarkFrame = 0;
+        codec_parameters.ltrUseFrames = 0;
+        codec_parameters.reservedBitFields = 0;
+        codec_parameters.sliceTypeData = 0;
+        codec_parameters.sliceTypeArrayCnt = 0;
+        codec_parameters.seiPayloadArrayCnt = 0;
+        codec_parameters.seiPayloadArray = nullptr;
+        codec_parameters.sliceMode = 3;
+        codec_parameters.sliceModeData = 10;
+        codec_parameters.ltrMarkFrameIdx = 0;
+        codec_parameters.ltrUseFrameBitmap = 0;
+        codec_parameters.ltrUsageMode = 0;
+        codec_parameters.forceIntraSliceCount = 0;
+        codec_parameters.forceIntraSliceIdx = 0;
+        codec_parameters.h264ExtPicParams = codec_extention_parameters;
+        memset(codec_parameters.reserved, 0, sizeof(codec_parameters.reserved));
+        memset(codec_parameters.reserved2, 0, sizeof(codec_parameters.reserved2));
+
+        encode_parameters.codecPicParams.h264PicParams = codec_parameters;
+    }
+
+    else if(this->codec == ENCODER_CODEC_H265)
+    {
+        NV_ENC_PIC_PARAMS_HEVC codec_parameters;
+        codec_parameters.displayPOCSyntax = 0;
+        codec_parameters.refPicFlag = 0;
+        codec_parameters.temporalId = 0;
+        codec_parameters.forceIntraRefreshWithFrameCnt = 0;
+        codec_parameters.constrainedFrame = 1;
+        codec_parameters.sliceModeDataUpdate  = 1;
+        codec_parameters.ltrMarkFrame = 0;
+        codec_parameters.ltrUseFrames = 0;
+        codec_parameters.reservedBitFields = 0;
+        codec_parameters.sliceTypeData = 0;
+        codec_parameters.sliceTypeArrayCnt = 0;
+        codec_parameters.sliceMode = 3;
+        codec_parameters.sliceModeData = 10;
+        codec_parameters.ltrMarkFrameIdx = 0;
+        codec_parameters.ltrUseFrameBitmap = 0;
+        codec_parameters.ltrUsageMode = 0;
+        codec_parameters.seiPayloadArrayCnt = 0;
+        codec_parameters.reserved = 0;
+        codec_parameters.seiPayloadArray = nullptr;
+        memset(codec_parameters.reserved2, 0, sizeof(codec_parameters.reserved2));
+        memset(codec_parameters.reserved3, 0, sizeof(codec_parameters.reserved3));
+
+        encode_parameters.codecPicParams.hevcPicParams = codec_parameters;
+    }
+
+    else
+    {
+        lava::log()->error("Nvidia Encoder: Invalid codec!");
+        this->on_encode_error();
+    }
+
     if (nvenc_functions.nvEncEncodePicture(this->nvenc_session, &encode_parameters) != NV_ENC_SUCCESS)
     {
         lava::log()->error("Nvidia Encoder: Can't encoder image!");
@@ -647,7 +691,7 @@ void NvidiaEncoder::destroy_context()
     }
 }
 
-bool NvidiaEncoder::create_session(const glm::uvec2& size)
+bool NvidiaEncoder::create_session(const glm::uvec2& size, EncoderCodec codec)
 {
     NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS session_parameters;
     session_parameters.version = NV_ENC_OPEN_ENCODE_SESSION_EX_PARAMS_VER;
@@ -665,28 +709,46 @@ bool NvidiaEncoder::create_session(const glm::uvec2& size)
         return false;
     }
 
-    if (!this->check_encode_support(NV_ENC_CODEC_H264_GUID))
+    GUID codec_guid;
+    GUID profile_guid;
+
+    switch(codec)
+    {
+    case ENCODER_CODEC_H264:
+        codec_guid = NV_ENC_CODEC_H264_GUID;
+        profile_guid = NV_ENC_H264_PROFILE_HIGH_GUID;
+        break;
+    case ENCODER_CODEC_H265:
+        codec_guid = NV_ENC_CODEC_HEVC_GUID;
+        profile_guid = NV_ENC_HEVC_PROFILE_MAIN_GUID;
+        break;
+    default:
+        lava::log()->error("Nvidia Encoder: Invalid codec!");
+        return false;
+    }
+
+    if (!this->check_encode_support(codec_guid))
     {
         lava::log()->error("Nvidia Encoder: Codec not supported!");
 
         return false;
     }
 
-    if (!this->check_profile_support(NV_ENC_CODEC_H264_GUID, NV_ENC_H264_PROFILE_HIGH_GUID))
+    if (!this->check_profile_support(codec_guid, profile_guid))
     {
         lava::log()->error("Nvidia Encoder: Profile not supported!");
 
         return false;
     }
 
-    if (!this->check_preset_support(NV_ENC_CODEC_H264_GUID, NV_ENC_PRESET_P1_GUID))
+    if (!this->check_preset_support(codec_guid, NV_ENC_PRESET_P1_GUID))
     {
         lava::log()->error("Nvidia Encoder: Preset not supported!");
 
         return false;
     }
 
-    if (!this->check_format_support(NV_ENC_CODEC_H264_GUID, NV_ENC_BUFFER_FORMAT_ABGR))
+    if (!this->check_format_support(codec_guid, NV_ENC_BUFFER_FORMAT_ABGR))
     {
         lava::log()->error("Nvidia Encoder: Input format not supported!");
 
@@ -701,7 +763,7 @@ bool NvidiaEncoder::create_session(const glm::uvec2& size)
     memset(preset_config.reserved1, 0, sizeof(preset_config.reserved1));
     memset(preset_config.reserved2, 0, sizeof(preset_config.reserved2));
 
-    if (nvenc_functions.nvEncGetEncodePresetConfigEx(this->nvenc_session, NV_ENC_CODEC_H264_GUID, NV_ENC_PRESET_P1_GUID, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY, &preset_config) != NV_ENC_SUCCESS)
+    if (nvenc_functions.nvEncGetEncodePresetConfigEx(this->nvenc_session, codec_guid, NV_ENC_PRESET_P1_GUID, NV_ENC_TUNING_INFO_ULTRA_LOW_LATENCY, &preset_config) != NV_ENC_SUCCESS)
     {
         lava::log()->error("Nvidia Encoder: Can't get preset for config!");
 
@@ -709,19 +771,33 @@ bool NvidiaEncoder::create_session(const glm::uvec2& size)
     }
 
     this->nvenc_encode_config = preset_config.presetCfg;
-    this->nvenc_encode_config.profileGUID = NV_ENC_H264_PROFILE_HIGH_GUID;
+    this->nvenc_encode_config.profileGUID = profile_guid;
     this->nvenc_encode_config.rcParams.version = NV_ENC_RC_PARAMS_VER;
     this->nvenc_encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CONSTQP;
-
-    this->nvenc_encode_config.encodeCodecConfig.h264Config.disableSPSPPS = 1;
-    this->nvenc_encode_config.encodeCodecConfig.h264Config.enableIntraRefresh = 1; //NOTE: Can create problems when replayed in VLC
-    this->nvenc_encode_config.encodeCodecConfig.h264Config.intraRefreshPeriod = this->frame_rate * 2;
-    this->nvenc_encode_config.encodeCodecConfig.h264Config.intraRefreshCnt = 10;
     this->nvenc_encode_config.rcParams.enableAQ = 1;
     this->nvenc_encode_config.rcParams.aqStrength = 0;
 
+    switch(codec)
+    {
+    case ENCODER_CODEC_H264:
+        this->nvenc_encode_config.encodeCodecConfig.h264Config.disableSPSPPS = 1;
+        this->nvenc_encode_config.encodeCodecConfig.h264Config.enableIntraRefresh = 1; //NOTE: Can create problems when replayed in VLC
+        this->nvenc_encode_config.encodeCodecConfig.h264Config.intraRefreshPeriod = this->frame_rate * 2;
+        this->nvenc_encode_config.encodeCodecConfig.h264Config.intraRefreshCnt = 10;
+        break;
+    case ENCODER_CODEC_H265:
+        this->nvenc_encode_config.encodeCodecConfig.hevcConfig.disableSPSPPS = 1;
+        this->nvenc_encode_config.encodeCodecConfig.hevcConfig.enableIntraRefresh = 1;
+        this->nvenc_encode_config.encodeCodecConfig.hevcConfig.intraRefreshPeriod = this->frame_rate * 2;
+        this->nvenc_encode_config.encodeCodecConfig.hevcConfig.intraRefreshCnt = 10;
+        break;
+    default:
+        lava::log()->error("Nvidia Encoder: Invalid codec!");
+        return false;
+    }
+
     this->nvenc_session_config.version = NV_ENC_INITIALIZE_PARAMS_VER;
-    this->nvenc_session_config.encodeGUID = NV_ENC_CODEC_H264_GUID;
+    this->nvenc_session_config.encodeGUID = codec_guid;
     this->nvenc_session_config.presetGUID = NV_ENC_PRESET_P1_GUID;
     this->nvenc_session_config.encodeWidth = size.x;
     this->nvenc_session_config.encodeHeight = size.y;
diff --git a/src/encoder/nvidia_encoder.hpp b/src/encoder/nvidia_encoder.hpp
index 4a364f1e940ec323903ab2d1ae0a5f53fb860048..ceb40737b0d68300fd794e7a923864acd3843149 100644
--- a/src/encoder/nvidia_encoder.hpp
+++ b/src/encoder/nvidia_encoder.hpp
@@ -50,7 +50,7 @@ public:
 public:
     NvidiaEncoder();
 
-    bool create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format) override;
+    bool create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format, EncoderCodec codec) override;
     void destroy() override;
 
     EncoderResult encode(VkCommandBuffer command_buffer, lava::renderer& renderer, lava::image::ptr image, VkImageLayout image_layout, OnEncodeComplete function) override;
@@ -62,6 +62,7 @@ public:
     void set_bitrate(double bitrate) override;
     void set_frame_rate(uint32_t frame_rate) override;
 
+    EncoderCodec get_codec() const override;
     EncoderMode get_mode() const override;
     double get_quality() const override;
     double get_bitrate() const override;
@@ -81,7 +82,7 @@ private:
     bool create_context(lava::device_ptr device);
     void destroy_context();
 
-    bool create_session(const glm::uvec2& size);
+    bool create_session(const glm::uvec2& size, EncoderCodec codec);
     void destroy_session();
 
     bool create_input_buffer(NvidiaEncoderFrame::Ptr frame, lava::device_ptr device, const glm::uvec2& size, EncoderFormat format);
@@ -97,6 +98,7 @@ private:
 private:
     OnEncodeError on_encode_error;
 
+    EncoderCodec codec = ENCODER_CODEC_H264;
     EncoderMode mode = ENCODER_MODE_CONSTANT_QUALITY;
     double quality = 0.0;
     double bitrate = 5.0;
diff --git a/src/encoder/vulkan_encoder.cpp b/src/encoder/vulkan_encoder.cpp
index 48a17447effad710a54f7f0e9856513ee2a5a0d3..36da40d2dc9ae8556940eca328f17c1565f8d4ba 100644
--- a/src/encoder/vulkan_encoder.cpp
+++ b/src/encoder/vulkan_encoder.cpp
@@ -7,8 +7,15 @@ VulkanEncoder::VulkanEncoder() : worker_pool(1)
 
 }
 
-bool VulkanEncoder::create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format)
+bool VulkanEncoder::create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format, EncoderCodec codec)
 {
+    if (codec != ENCODER_CODEC_H264)
+    {
+        lava::log()->error("Vulkan encoder only supportes h264 encoding!");
+
+        return false;
+    }
+
     this->frame_count = VULKAN_ENCODER_FRAMES;
     this->frame_index = 0;
 
@@ -334,6 +341,11 @@ void VulkanEncoder::set_frame_rate(uint32_t frame_rate)
     this->control_change = true;
 }
 
+EncoderCodec VulkanEncoder::get_codec() const
+{
+    return ENCODER_CODEC_H264;
+}
+
 EncoderMode VulkanEncoder::get_mode() const
 {
     return this->setting_mode;
diff --git a/src/encoder/vulkan_encoder.hpp b/src/encoder/vulkan_encoder.hpp
index cea0f938b75bbcab1369a64da352ca22a50444ab..126af55968620fb6b191a60f25c2ec5aaec5a5a7 100644
--- a/src/encoder/vulkan_encoder.hpp
+++ b/src/encoder/vulkan_encoder.hpp
@@ -77,7 +77,7 @@ public:
 public:
     VulkanEncoder();
 
-    bool create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format) override;
+    bool create(lava::device_ptr device, const lava::renderer& renderer, const glm::uvec2& size, EncoderFormat format, EncoderCodec codec) override;
     void destroy() override;
 
     EncoderResult encode(VkCommandBuffer command_buffer, lava::renderer& renderer, lava::image::ptr image, VkImageLayout image_layout, OnEncodeComplete function) override;
@@ -90,6 +90,7 @@ public:
     void set_key_rate(uint32_t key_rate) override;
     void set_frame_rate(uint32_t frame_rate) override;
 
+    EncoderCodec get_codec() const override;
     EncoderMode get_mode() const override;
     double get_quality() const override;
     double get_bitrate() const override;
diff --git a/src/headset/remote_headset.cpp b/src/headset/remote_headset.cpp
index f7e4b94c158ac5c15a00fc8dcfbb22ec3ca93ec1..373f3e66d5967c8a06ce8a4e803f537911e969b1 100644
--- a/src/headset/remote_headset.cpp
+++ b/src/headset/remote_headset.cpp
@@ -493,10 +493,11 @@ bool RemoteHeadset::create_encoders()
         encoder->set_key_rate(this->encoder_key_rate);
         encoder->set_frame_rate(this->encoder_frame_rate);
 
+        EncoderCodec codec = this->get_application()->get_command_parser().get_codec();
         lava::device_ptr device = this->get_application()->get_device();
         lava::renderer& renderer = this->get_application()->get_renderer();
         
-        if (!encoder->create(device, renderer, this->resolution, (EncoderFormat)this->get_format()))
+        if (!encoder->create(device, renderer, this->resolution, (EncoderFormat)this->get_format(), codec))
         {
             return false;
         }
@@ -511,11 +512,27 @@ bool RemoteHeadset::create_encoders()
             std::filesystem::create_directory(this->video_directory);
         }
 
+        EncoderCodec codec = this->get_application()->get_command_parser().get_codec();
+        std::string file_extension;
+
+        switch(codec)
+        {
+        case ENCODER_CODEC_H264:
+            file_extension = ".h264";
+            break;
+        case ENCODER_CODEC_H265:
+            file_extension = ".h265";
+            break;
+        default:
+            lava::log()->error("Invalid codec. Can't derive file extension!");
+            return false;
+        }
+
         this->encoder_files.resize(this->frame_id_count);
 
         for (uint32_t index = 0; index < this->encoder_files.size(); index++)
         {
-            std::string file_name = this->video_directory + "/" + build_file_name(index) + ".h264";
+            std::string file_name = this->video_directory + "/" + build_file_name(index) + file_extension;
 
             this->encoder_files[index].open(file_name, std::ios::out | std::ios::binary);
 
@@ -658,7 +675,9 @@ void RemoteHeadset::update_overlay()
 
 void RemoteHeadset::on_setup(const glm::u32vec2& resolution)
 {
-    this->transport->send_setup_complete(this->remote_strategy, this->frame_id_count, this->near_plane, this->far_plane);
+    EncoderCodec codec = this->get_application()->get_command_parser().get_codec();
+
+    this->transport->send_setup_complete(this->remote_strategy, codec, this->frame_id_count, this->near_plane, this->far_plane);
 
     std::unique_lock<std::mutex> lock(this->transport_mutex);
     this->resolution = resolution;
diff --git a/src/transport/transport.hpp b/src/transport/transport.hpp
index eedfcb859ec198cf77306934588bbcd7b108ef3e..580ed5d670b4494bf7e4291ad9790235e2421125 100644
--- a/src/transport/transport.hpp
+++ b/src/transport/transport.hpp
@@ -30,6 +30,7 @@
 #include <span>
 
 #include "types.hpp"
+#include "../encoder/encoder.hpp"
 
 enum TransportState
 {
@@ -112,10 +113,11 @@ public:
     // send_setup_complete: Used to send a setup-complete packet
     //                      This function should be threadsafe and callable by main and worker thread
     //  remote_strategy: The postprocessing method that should be used on the headset
+    //            codec: The codec that is used for the encoding of the images.
     //    max_frame_ids: The number of images that define a frame and that are send in parallel (normaly 2 for left and right eye). The headset application should setup this many decoders
     //       near_plane: The distance to the near plane that should be used for the projection matrices
     //        far_plane: The distance to the far plane that should be used for the projection matrices
-    virtual bool send_setup_complete(RemoteStrategy remote_strategy, uint32_t max_frame_ids, float near_plane, float far_plane) = 0;
+    virtual bool send_setup_complete(RemoteStrategy remote_strategy, EncoderCodec codec, uint32_t max_frame_ids, float near_plane, float far_plane) = 0;
 
     // send_stage_transform: Used to send the current transformation for the origin
     //                       This transformation can change for example if the user moves by pressing a controller button
diff --git a/src/transport/udp_packet.cpp b/src/transport/udp_packet.cpp
index 5500fae49c324f9248af84c179324e6e132d7d37..32f1346560ffd872685dcfcef49350deb3abd996 100644
--- a/src/transport/udp_packet.cpp
+++ b/src/transport/udp_packet.cpp
@@ -19,6 +19,24 @@ bool convert_udp_stereo_strategy(RemoteStrategy remote_strategey, UDPStereoStrat
     return true;
 }
 
+bool convert_udp_codec(EncoderCodec codec, UDPCodec& udp_codec)
+{
+    switch(codec)
+    {
+    case ENCODER_CODEC_H264:
+        udp_codec = UDP_CODEC_H264;
+        break;
+    case ENCODER_CODEC_H265:
+        udp_codec = UDP_CODEC_H265;
+        break;
+    default:
+        lava::log()->error("UDP-Transport: Unkown coded!");
+        return false;
+    }
+
+    return true;
+}
+
 bool convert_udp_controller(UDPControllerId udp_controller, Controller& controller)
 {
     switch (udp_controller)
diff --git a/src/transport/udp_packet.hpp b/src/transport/udp_packet.hpp
index ab19362951827620eb646bb9897709cece83cf62..aa46ccdaeb83cdb475451f647647edbecb966cba 100644
--- a/src/transport/udp_packet.hpp
+++ b/src/transport/udp_packet.hpp
@@ -3,6 +3,7 @@
 #include <cstdint>
 
 #include "types.hpp"
+#include "../encoder/encoder.hpp"
 
 #define UDP_PACKET_PERFORMANCE_SAMPLE_NAME_MAX_LENGTH 128
 #define UDP_PACKET_OVERLAY_TEXT_LABEL_MAX_LENGTH      128
@@ -42,6 +43,12 @@ enum UDPStereoStrategyId : uint32_t
     UDP_STEREO_STRATEGY_ID_MAX_COUNT
 };
 
+enum UDPCodec : uint32_t
+{
+    UDP_CODEC_H264 = 0x00,
+    UDP_CODEC_H265 = 0x01
+};
+
 enum UDPControllerId : uint32_t
 {
     UDP_CONTROLLER_ID_LEFT  = 0x00,
@@ -100,6 +107,7 @@ typedef uint32_t UDPFrameNumber;
 typedef uint32_t UDPTransformId;
 
 bool convert_udp_stereo_strategy(RemoteStrategy remote_strategey, UDPStereoStrategyId& udp_strategy);
+bool convert_udp_codec(EncoderCodec codec, UDPCodec& udp_codec);
 bool convert_udp_controller(UDPControllerId udp_controller, Controller& controller);
 bool convert_udp_controller_state(UDPControllerState udp_controller_state, ControllerState& controller_state);
 bool convert_udp_button(UDPButtonId udp_button, Button& button);
@@ -133,6 +141,7 @@ struct UDPPacketSetupComplete
     uint32_t size = 0;
 
     UDPStereoStrategyId strategy_id;
+    UDPCodec codec;
     uint32_t max_frame_ids;
 
     float near_plane;
diff --git a/src/transport/udp_transport.cpp b/src/transport/udp_transport.cpp
index 311101a55ee025b2f0960709ac85fe491ab34938..e10ac8139a191215173d8e6a19e3abde0a04551e 100644
--- a/src/transport/udp_transport.cpp
+++ b/src/transport/udp_transport.cpp
@@ -98,7 +98,7 @@ bool UDPTransport::wait_connect()
     return this->get_state() == TRANSPORT_STATE_CONNECTED;
 }
 
-bool UDPTransport::send_setup_complete(RemoteStrategy remote_strategy, uint32_t max_frame_ids, float near_plane, float far_plane)
+bool UDPTransport::send_setup_complete(RemoteStrategy remote_strategy, EncoderCodec codec, uint32_t max_frame_ids, float near_plane, float far_plane)
 {
     if (this->get_state() != TRANSPORT_STATE_CONNECTED)
     {
@@ -107,13 +107,19 @@ bool UDPTransport::send_setup_complete(RemoteStrategy remote_strategy, uint32_t
         return false;
     }
 
-    UDPStereoStrategyId strategy_id;
+    UDPStereoStrategyId udp_strategy;
 
-    if (!convert_udp_stereo_strategy(remote_strategy, strategy_id))
+    if (!convert_udp_stereo_strategy(remote_strategy, udp_strategy))
     {
         return false;
     }
 
+    UDPCodec udp_codec;
+
+    if (!convert_udp_codec(codec, udp_codec))
+    {
+        return false;
+    }
 
     std::unique_lock<std::mutex> lock(this->worker_mutex);
     Datagram datagram = this->datagram_pool.acquire_datagram();
@@ -122,7 +128,8 @@ bool UDPTransport::send_setup_complete(RemoteStrategy remote_strategy, uint32_t
     UDPPacketSetupComplete* packet = (UDPPacketSetupComplete*)datagram.buffer;
     packet->id = UDP_PACKET_ID_SETUP_COMPLETE;
     packet->size = sizeof(UDPPacketSetupComplete);
-    packet->strategy_id = strategy_id;
+    packet->strategy_id = udp_strategy;
+    packet->codec = udp_codec;
     packet->max_frame_ids = max_frame_ids;
     packet->near_plane = near_plane;
     packet->far_plane = far_plane;
diff --git a/src/transport/udp_transport.hpp b/src/transport/udp_transport.hpp
index 4a80198c49d7c6cdf3b49307be3a4fd1797ad75a..5628fe137fc5157ec60eaf483a5a899eae950007 100644
--- a/src/transport/udp_transport.hpp
+++ b/src/transport/udp_transport.hpp
@@ -23,7 +23,7 @@ public:
     void destroy() override;
     bool wait_connect() override;
 
-    bool send_setup_complete(RemoteStrategy remote_strategy, uint32_t max_frame_ids, float near_plane, float far_plane) override;
+    bool send_setup_complete(RemoteStrategy remote_strategy, EncoderCodec codec, uint32_t max_frame_ids, float near_plane, float far_plane) override;
     bool send_stage_transform(const glm::mat4& stage_transform) override;
     bool send_frame_config_nal(FrameId frame_id, const std::span<const uint8_t>& content) override;
     bool send_frame_nal(FrameNumber frame_number, FrameId frame_id, TransformId transform_id, const std::span<const uint8_t>& content) override;
diff --git a/src/utility/command_parser.cpp b/src/utility/command_parser.cpp
index 77366016306e1e256fe5f6c1363ea7690299d741..5d134d371ed167b3ed7e0cc755f05ed419610dcd 100644
--- a/src/utility/command_parser.cpp
+++ b/src/utility/command_parser.cpp
@@ -116,6 +116,14 @@ bool CommandParser::parse_command(const argh::parser& cmd_line)
             }
         }
 
+        else if (parameter.first == "codec")
+        {
+            if(!this->set_codec(parameter.second))
+            {
+                return false;
+            }
+        }
+
         else if (parameter.first == "animation")
         {
             this->animation_name = parameter.second;
@@ -242,6 +250,13 @@ bool CommandParser::parse_command(const argh::parser& cmd_line)
         }
     }
 
+    if (this->encoder == ENCODER_TYPE_VULKAN && this->codec == ENCODER_CODEC_H265)
+    {
+        std::cout << "Configuration 'encoder = vulkan' and 'codec = h265' not supported. Use option --help to get more information" << std::endl;
+
+        return false;
+    }
+
     return true;
 }
 
@@ -265,6 +280,11 @@ EncoderType CommandParser::get_encoder() const
     return this->encoder;
 }
 
+EncoderCodec CommandParser::get_codec() const
+{
+    return this->codec;
+}
+
 SceneUnit CommandParser::get_scene_unit() const
 {
     return this->scene_unit;
@@ -355,6 +375,10 @@ void CommandParser::show_help()
     std::cout << "   --encoder={encoder}                  The encoder that should be used when a remote headset is used." << std::endl;
     std::cout << "                                        This parameter should only be used when the parameter headset is set to remote." << std::endl;
     std::cout << "                                        Options: vulkan (default), nvidia" << std::endl;
+    std::cout << "   --codec={codec}                      The codec that should be used by the encoder." << std::endl;
+    std::cout << "                                        This parameter should only be used when the parameter headset is set to remote." << std::endl;
+    std::cout << "                                        The vulkan encoder only supports h264 encoding." << std::endl;
+    std::cout << "                                        Options: h264 (default), h265" << std::endl;
     std::cout << "   --benchmark                          Play animation once and close program after completion." << std::endl;
     std::cout << "                                        If not set, the application runs indefinitely and the interface is enabled." << std::endl;
     std::cout << "   --animation={animation_name}         The name of the animation that should be played." << std::endl;
@@ -481,6 +505,28 @@ bool CommandParser::set_encoder(const std::string& name)
     return true;
 }
 
+bool CommandParser::set_codec(const std::string& name)
+{
+    if (name == "h264")
+    {
+        this->codec = ENCODER_CODEC_H264;
+    }
+
+    else if(name == "h265")
+    {
+        this->codec = ENCODER_CODEC_H265;
+    }
+
+    else
+    {
+        std::cout << "Invalid option set of parameter 'codec'. Use option --help to get more information." << std::endl;
+
+        return false;
+    }
+
+    return true;
+}
+
 bool CommandParser::set_scene_unit(const std::string& name)
 {
     if (name == "meters")
diff --git a/src/utility/command_parser.hpp b/src/utility/command_parser.hpp
index 6507df74bccff6fc01a6092a1964f5b0b8c4e090..6a6df8a80839fe02f0502f628f757eb91065609d 100644
--- a/src/utility/command_parser.hpp
+++ b/src/utility/command_parser.hpp
@@ -25,6 +25,7 @@ public:
     StereoStrategyType get_stereo_strategy() const;
     TransportType get_transport() const;
     EncoderType get_encoder() const;
+    EncoderCodec get_codec() const;
     SceneUnit get_scene_unit() const;
 
     const std::string& get_scene_path() const;
@@ -52,6 +53,7 @@ private:
     bool set_stero_strategy(const std::string& name);
     bool set_transport(const std::string& name);
     bool set_encoder(const std::string& name);
+    bool set_codec(const std::string& name);
     bool set_scene_unit(const std::string& name);
 
 private:
@@ -59,6 +61,7 @@ private:
     StereoStrategyType stereo_strategy = STEREO_STRATEGY_TYPE_NATIVE_FORWARD;
     TransportType transport = TRANSPORT_TYPE_UDP;
     EncoderType encoder = ENCODER_TYPE_VULKAN;
+    EncoderCodec codec = ENCODER_CODEC_H264;
     SceneUnit scene_unit = SCENE_UNIT_METERS;
 
     std::string scene_path = "";