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!"); + } } }