Ver Fonte

Implemented frame index log.

jcsyshc há 2 anos atrás
pai
commit
95b1de650e

+ 7 - 0
src/frame_encoder/encoder_base.cpp

@@ -3,10 +3,17 @@
 #include <cassert>
 #include <cstring>
 
+namespace video_nal_impl {
+    uint64_t last_frame_id = 0;
+}
+
+using namespace video_nal_impl;
+
 void video_nal::create(void *_ptr, size_t _length, bool _idr) {
     free(ptr);
     length = _length;
     idr = _idr;
+    frame_id = ++last_frame_id;
     ptr = (uint8_t *) malloc(length);
     if (_ptr != nullptr) {
         memcpy(ptr, _ptr, length);

+ 1 - 0
src/frame_encoder/encoder_base.h

@@ -12,6 +12,7 @@ struct video_nal {
     uint8_t *ptr = nullptr;
     size_t length = 0;
     bool idr = false;
+    uint64_t frame_id = 0;
 
     void create(void *ptr, size_t length, bool idr);
 

+ 21 - 0
src/frame_sender/sender_base.cpp

@@ -1,12 +1,15 @@
 #include "sender_base.h"
 #include "simple_mq.h"
 #include "variable_defs.h"
+#include "utility.hpp"
 
 #include <boost/asio/post.hpp>
 
+#include <fmt/chrono.h>
 #include <spdlog/spdlog.h>
 
 #include <deque>
+#include <fstream>
 #include <mutex>
 
 using boost::asio::io_context;
@@ -25,8 +28,17 @@ struct sender_base::impl {
     std::unique_ptr<io_context> ctx;
     bool waiting_idr = false;
 
+    std::ofstream log_file;
+
     impl() {
         ctx = std::make_unique<io_context>();
+
+        // create log file if requested
+        if (mq().query_variable<bool>(SENDER_ENABLE_LOG)) {
+            auto file_name = fmt::format("log_{:%Y_%m_%d_%H_%M_%S}.csv",
+                                         std::chrono::system_clock::now());
+            log_file.open(file_name);
+        }
     }
 
     void clear_frame_list() {
@@ -84,6 +96,11 @@ struct sender_base::impl {
         post(*ctx, [this] { handle_frames(); });
     }
 
+    void log_frame_sent(uint64_t frame_id) {
+        if (!log_file.is_open()) return;
+        log_file << fmt::format("{},{}\n", frame_id, system_timestamp());
+    }
+
 };
 
 sender_base::sender_base()
@@ -112,4 +129,8 @@ void sender_base::run() {
     SPDLOG_INFO("Frame sender started.");
     pimpl->ctx->run();
     SPDLOG_INFO("Frame sender stopped.");
+}
+
+void sender_base::log_frame_sent(uint64_t frame_id) {
+    pimpl->log_frame_sent(frame_id);
 }

+ 2 - 0
src/frame_sender/sender_base.h

@@ -30,6 +30,8 @@ protected:
 
     void request_idr_frame();
 
+    void log_frame_sent(uint64_t frame_id);
+
     virtual void handle_frame(frame_ptr_type &&frame) = 0;
 
     virtual void close_connection() = 0;

+ 13 - 2
src/frame_sender/sender_tcp.cpp

@@ -44,8 +44,16 @@ struct sender_tcp::impl {
     void send_frame(frame_ptr_type &&frame) {
         if (!socket->is_open()) return;
 
-        out_buf.create(frame->length + sizeof(frame->length));
-        auto ptr = write_binary_number(out_buf.ptr, frame->length);
+        uint64_t packet_length = frame->length
+                                 + sizeof(frame->frame_id);
+        auto out_length = packet_length
+                          + sizeof(packet_length);
+        out_buf.create(out_length);
+
+        // fill out buffer
+        auto ptr = out_buf.ptr;
+        ptr = write_binary_number(ptr, packet_length);
+        ptr = write_binary_number(ptr, frame->frame_id);
         memcpy(ptr, frame->ptr, frame->length);
 
         error_code err;
@@ -55,6 +63,9 @@ struct sender_tcp::impl {
             close_connection();
             async_waiting_client();
         }
+
+        q_this->log_frame_sent(frame->frame_id);
+        SPDLOG_TRACE("Frame {} sent.", frame->frame_id);
     }
 
     void async_waiting_client() {

+ 3 - 3
src/frame_sender/sender_udp_fec.cpp

@@ -120,7 +120,6 @@ struct sender_udp_fec::impl {
     uint8_t max_data_block_count; // max_block_count / (1 + parity_rate)
     uint16_t block_size; // conn_mtu - header_size
     uint32_t max_chunk_size; // max_data_block_count * block_size
-    uint32_t frame_id = 1;
     smart_reed_solomon rs;
     smart_buffer<uint8_t> in_buf, out_buf;
     timestamp_type last_confirm_ts = 0;
@@ -190,7 +189,7 @@ struct sender_udp_fec::impl {
 
         frag_header header;
         header.frame_type = frame->idr ? 'I' : 'P';
-        header.frame_id = frame_id;
+        header.frame_id = frame->frame_id;
         header.frame_length = frame->length;
 
         auto chunk_count = (frame->length + max_chunk_size - 1) / max_chunk_size;
@@ -204,7 +203,8 @@ struct sender_udp_fec::impl {
             send_chunk(chunk_data, header.chunk_length, &header);
         }
 
-        SPDLOG_TRACE("Frame {} sent.", frame_id++);
+        q_this->log_frame_sent(frame->frame_id);
+        SPDLOG_TRACE("Frame {} sent.", frame->frame_id);
     }
 
     void async_handle_request() {

+ 5 - 0
src/main_ext.cpp

@@ -111,6 +111,7 @@ sender_type chosen_sender = SENDER_TCP;
 int sender_listen_port;
 uint16_t sender_mtu;
 float sender_parity_rate;
+bool sender_enable_log = false;
 
 std::string sophiar_config_path;
 std::unique_ptr<std::thread> sophiar_thread;
@@ -601,6 +602,7 @@ bool is_sending() {
 
 void start_sender() {
     mq().update_variable(SENDER_SHOULD_STOP, false);
+    mq().update_variable(SENDER_ENABLE_LOG, sender_enable_log);
     sender_thread = std::make_unique<std::thread>(sender_thread_work);
 }
 
@@ -978,6 +980,9 @@ void prepare_imgui_frame() {
                 if (chosen_sender == SENDER_UDP_FEC) {
                     ImGui::DragFloat("Parity Rate", &sender_parity_rate, 0.01, 0, 2, "%.02f");
                 }
+                if (debug_options) {
+                    ImGui::Checkbox("Enable Log", &sender_enable_log);
+                }
             }
 
             ImGui::PopID();

+ 8 - 0
src/utility.hpp

@@ -3,6 +3,8 @@
 
 #include <spdlog/spdlog.h>
 
+#include <chrono>
+
 // https://en.cppreference.com/w/cpp/utility/unreachable
 [[noreturn]] inline void unreachable() {
     // Uses compiler specific extensions if possible.
@@ -58,4 +60,10 @@ extern log_timer global_timer;
 #define RESET_TIMER global_timer.reset()
 #define RECORD_TIME(name) global_timer.record(name)
 
+inline auto system_timestamp() {
+    using namespace std::chrono;
+    auto time_point = high_resolution_clock::now();
+    return duration_cast<microseconds>(time_point.time_since_epoch()).count();
+}
+
 #endif //REMOTEAR3_UTILITY_HPP

+ 1 - 0
src/variable_defs.h

@@ -15,6 +15,7 @@ constexpr auto CUDA_STREAM_OUTPUT = 16;
 constexpr auto REQUEST_IDR = 7;
 constexpr auto SENDER_CONNECTED = 8;
 constexpr auto SENDER_SHOULD_STOP = 9;
+constexpr auto SENDER_ENABLE_LOG = 10;
 
 // global variable declaration