diff --git a/src/encoder/nvidia_encoder.cpp b/src/encoder/nvidia_encoder.cpp
index 63ff2efd29d0847f5b154ad56d1cebbaed20de79..0ab61f0045175303b1c5e205d22431c7f1b9cf6c 100644
--- a/src/encoder/nvidia_encoder.cpp
+++ b/src/encoder/nvidia_encoder.cpp
@@ -424,6 +424,9 @@ bool NvidiaEncoder::apply_config()
 
     else if (this->mode == ENCODER_MODE_CONSTANT_BITRATE)
     {
+        session_config.frameRateNum = this->frame_rate;
+        session_config.frameRateDen = 1;
+
         encode_config.rcParams.rateControlMode = NV_ENC_PARAMS_RC_CBR;
         encode_config.rcParams.averageBitRate = (uint32_t)(this->bitrate * 1000000.0);
         encode_config.rcParams.maxBitRate = this->nvenc_encode_config.rcParams.averageBitRate;
diff --git a/src/headset/remote_headset.cpp b/src/headset/remote_headset.cpp
index cad0012d817b65d105194b04ca4c95ed3ac949a6..ff8c21290c432362fdaab8c5aa046d325847f341 100644
--- a/src/headset/remote_headset.cpp
+++ b/src/headset/remote_headset.cpp
@@ -155,7 +155,7 @@ bool RemoteHeadset::on_interface()
     {
         if (encoder->is_supported(ENCODER_SETTING_BITRATE))
         {
-            if (ImGui::SliderFloat("Bit-Rate (Mbps)", &this->encoder_bit_rate, 0.1f, 100.0f))
+            if (ImGui::SliderFloat("Bit-Rate (Mbps)", &this->encoder_bit_rate, 0.1f, 300.0f))
             {
                 for (Encoder::Ptr encoder : this->encoders)
                 {
diff --git a/src/transport/udp_transport.cpp b/src/transport/udp_transport.cpp
index b07872b458cf12258f444a32d1794e209f3deae4..eaf72173ea11d1b377dcd679bf4064c3fe2c5e56 100644
--- a/src/transport/udp_transport.cpp
+++ b/src/transport/udp_transport.cpp
@@ -207,13 +207,27 @@ bool UDPTransport::send_frame_nal(FrameNumber frame_number, FrameId frame_id, Tr
         return false;
     }
 
-    for (uint32_t offset = 0; offset < content.size();)
+    uint32_t datagram_content_size = DATAGRAM_SIZE - sizeof(UDPPacketFrameNal);
+    uint32_t datagram_count = content.size() / datagram_content_size;
+
+    if (content.size() % datagram_content_size > 0)
     {
-        std::unique_lock<std::mutex> lock(this->worker_mutex);
-        Datagram datagram = this->datagram_pool.acquire_datagram();
-        lock.unlock();
+        datagram_count += 1;   
+    }
+
+    std::vector<Datagram> datagrams;
+    datagrams.reserve(datagram_count);
+
+    std::unique_lock<std::mutex> lock(this->worker_mutex);
+    this->datagram_pool.acquire_datagrams(datagram_count, datagrams);
+    lock.unlock();
 
-        uint32_t content_size = glm::min(datagram.size - (uint32_t)sizeof(UDPPacketFrameNal), (uint32_t) content.size() - offset);
+    for (uint32_t index = 0; index < datagram_count; index++)
+    {
+        Datagram& datagram = datagrams[index];
+        uint32_t offset = index * datagram_content_size;
+
+        uint32_t content_size = glm::min(datagram_content_size, (uint32_t)content.size() - offset);
 
         UDPPacketFrameNal* packet = (UDPPacketFrameNal*)datagram.buffer;
         packet->id = UDP_PACKET_ID_FRAME_NAL;
@@ -225,12 +239,10 @@ bool UDPTransport::send_frame_nal(FrameNumber frame_number, FrameId frame_id, Tr
         packet->payload_size = content.size();
 
         memcpy(datagram.buffer + sizeof(UDPPacketFrameNal), (uint8_t*)content.data() + offset, sizeof(uint8_t) * content_size);
-
-        this->send_datagram(datagram);
-
-        offset += content_size;
     }
 
+    this->send_datagrams(datagrams);
+
     return true;
 }
 
@@ -243,13 +255,27 @@ bool UDPTransport::send_frame_metadata(FrameNumber frame_number, const std::span
         return false;
     }
 
-    for (uint32_t offset = 0; offset < content.size();)
+    uint32_t datagram_content_size = DATAGRAM_SIZE - sizeof(UDPPacketFrameMetadata);
+    uint32_t datagram_count = content.size() / datagram_content_size;
+
+    if (content.size() % datagram_content_size > 0)
     {
-        std::unique_lock<std::mutex> lock(this->worker_mutex);
-        Datagram datagram = this->datagram_pool.acquire_datagram();
-        lock.unlock();
+        datagram_count += 1;
+    }
+
+    std::vector<Datagram> datagrams;
+    datagrams.reserve(datagram_count);
+
+    std::unique_lock<std::mutex> lock(this->worker_mutex);
+    this->datagram_pool.acquire_datagrams(datagram_count, datagrams);
+    lock.unlock();
+
+    for (uint32_t index = 0; index < datagram_count; index++)
+    {
+        Datagram& datagram = datagrams[index];
+        uint32_t offset = index * datagram_content_size;
 
-        uint32_t content_size = glm::min(datagram.size - (uint32_t)sizeof(UDPPacketFrameMetadata), (uint32_t) content.size() - offset);
+        uint32_t content_size = glm::min(datagram_content_size, (uint32_t)content.size() - offset);
 
         UDPPacketFrameMetadata* packet = (UDPPacketFrameMetadata*)datagram.buffer;
         packet->id = UDP_PACKET_ID_FRAME_METADATA;
@@ -259,12 +285,10 @@ bool UDPTransport::send_frame_metadata(FrameNumber frame_number, const std::span
         packet->payload_size = content.size();
 
         memcpy(datagram.buffer + sizeof(UDPPacketFrameMetadata), (uint8_t*)content.data() + offset, sizeof(uint8_t) * content_size);
-
-        this->send_datagram(datagram);
-
-        offset += content_size;
     }
 
+    this->send_datagrams(datagrams);
+
     return true;
 }
 
@@ -546,11 +570,13 @@ void UDPTransport::send_datagram(const Datagram& datagram)
 {
     std::unique_lock<std::mutex> lock(this->worker_mutex);
 
+    this->send_queue.push_back(datagram);
+    
     if (this->max_send_queue_enabled)
     {
         uint32_t bytes = 0;
 
-        for (uint32_t index = 1; index < this->send_queue.size(); index++)
+        for (uint32_t index = 0; index < this->send_queue.size(); index++)
         {
             const Datagram& datagram = this->send_queue[index];
             const UDPPacketHeader* header = (const UDPPacketHeader*)datagram.buffer;
@@ -559,17 +585,54 @@ void UDPTransport::send_datagram(const Datagram& datagram)
 
         while (bytes > this->max_send_queue_size && this->send_queue.size() > 1)
         {
-            const Datagram& datagram = this->send_queue[1];
+            const Datagram& datagram = this->send_queue[0];
             const UDPPacketHeader* header = (const UDPPacketHeader*)datagram.buffer;
             bytes -= header->size;
 
             this->datagram_pool.release_datagram(datagram);
-            this->send_queue.erase(this->send_queue.begin() + 1);
+            this->send_queue.erase(this->send_queue.begin());
+        }
+    }
+
+    if (!this->send_active)
+    {
+        this->process_send_queue();
+    }
+}
+
+void UDPTransport::send_datagrams(const std::vector<Datagram>& datagrams)
+{
+    if (datagrams.empty())
+    {
+        return;
+    }
+
+    std::unique_lock<std::mutex> lock(this->worker_mutex);
+
+    this->send_queue.insert(this->send_queue.end(), datagrams.begin(), datagrams.end());
+
+    if (this->max_send_queue_enabled)
+    {
+        uint32_t bytes = 0;
+
+        for (uint32_t index = 0; index < this->send_queue.size(); index++)
+        {
+            const Datagram& datagram = this->send_queue[index];
+            const UDPPacketHeader* header = (const UDPPacketHeader*)datagram.buffer;
+            bytes += header->size;
+        }
+
+        while (bytes > this->max_send_queue_size && this->send_queue.size() > 1)
+        {
+            const Datagram& datagram = this->send_queue[0];
+            const UDPPacketHeader* header = (const UDPPacketHeader*)datagram.buffer;
+            bytes -= header->size;
+
+            this->datagram_pool.release_datagram(datagram);
+            this->send_queue.erase(this->send_queue.begin());
         }
     }
 
-    this->send_queue.push_back(datagram);
-    
     if (!this->send_active)
     {
         this->process_send_queue();
diff --git a/src/transport/udp_transport.hpp b/src/transport/udp_transport.hpp
index 173cdd6c73274dd3b09495ec238c1bd37d8f5944..86f1ba012d1fc978b12b90bf6ca0886d7bcbcda8 100644
--- a/src/transport/udp_transport.hpp
+++ b/src/transport/udp_transport.hpp
@@ -58,6 +58,7 @@ private:
     void check_state();
 
     void send_datagram(const Datagram& datagram);
+    void send_datagrams(const std::vector<Datagram>& datagrams);
     void receive_datagram();
 
     void process_send_queue();              //NOTE: Protected by worker_mutex
diff --git a/src/utility/datagram.cpp b/src/utility/datagram.cpp
index e04c6275a2d919a2bc6f8410c229e5445b0deca5..9611f86e3bdbf013e9ac112c9410b389f9df5515 100644
--- a/src/utility/datagram.cpp
+++ b/src/utility/datagram.cpp
@@ -1,5 +1,6 @@
 #include "datagram.hpp"
 #include <liblava/lava.hpp>
+#include <glm/glm.hpp>
 
 DatagramPool::~DatagramPool()
 {
@@ -30,6 +31,33 @@ Datagram DatagramPool::acquire_datagram()
     return datagram;
 }
 
+void DatagramPool::acquire_datagrams(uint32_t datagram_count, std::vector<Datagram>& datagrams)
+{
+    datagrams.clear();
+    datagrams.reserve(datagram_count);
+
+    uint32_t reuse_count = glm::min(datagram_count, (uint32_t)this->pool.size());
+    uint32_t allocate_count = datagram_count - reuse_count;
+
+    if (reuse_count > 0)
+    {
+        datagrams.insert(datagrams.begin(), this->pool.end() - reuse_count, this->pool.end());
+        this->pool.erase(this->pool.end() - reuse_count, this->pool.end());
+    }
+
+    if (allocate_count > 0)
+    {
+        uint8_t* datagram_buffer = (uint8_t*)lava::alloc_data(allocate_count * DATAGRAM_SIZE);
+
+        for (uint32_t index = 0; index < allocate_count; index++)
+        {
+            Datagram& datagram = datagrams.emplace_back();
+            datagram.size = DATAGRAM_SIZE;
+            datagram.buffer = datagram_buffer + DATAGRAM_SIZE * index;
+        }
+    }
+}
+
 void DatagramPool::release_datagram(const Datagram& datagram)
 {
     this->pool.push_back(datagram);
diff --git a/src/utility/datagram.hpp b/src/utility/datagram.hpp
index 2f9d9755a6c1b28fffd8d549cad9af172e539dff..15094794cfe54fc30a4c0096ea1d19ee84877f08 100644
--- a/src/utility/datagram.hpp
+++ b/src/utility/datagram.hpp
@@ -20,5 +20,6 @@ public:
     ~DatagramPool();
 
     Datagram acquire_datagram();
+    void acquire_datagrams(uint32_t datagram_count, std::vector<Datagram>& datagrams);
     void release_datagram(const Datagram& datagram);
 };
\ No newline at end of file
diff --git a/src/vr_application.cpp b/src/vr_application.cpp
index 86a8560ddbb04685317ad72c8025a8525ada286d..2a27ed12dfe035bd192e8efd647be81a55bde317 100644
--- a/src/vr_application.cpp
+++ b/src/vr_application.cpp
@@ -526,9 +526,12 @@ void VRApplication::on_destroy()
         this->scene->destroy();
     }
 
-    if (!this->statistic_log->write("statistics"))
+    if (this->statistic_log != nullptr)
     {
-        lava::log()->error("Can't write statistic!");
+        if (!this->statistic_log->write("statistics"))
+        {
+            lava::log()->error("Can't write statistic!");
+        }
     }
 }