Bläddra i källkod

Streamer supports variable image size.

jcsyshc 1 år sedan
förälder
incheckning
82ca55b961

+ 3 - 0
src/impl/apps/remote_ar/remote_ar.cpp

@@ -31,6 +31,9 @@ app_remote_ar::app_remote_ar(const create_config &_conf) {
     mvs_conf.cameras.push_back({.dev_name = LOAD_STR("left_camera_name"), .img_name = raw_left});
     mvs_conf.cameras.push_back({.dev_name = LOAD_STR("right_camera_name"), .img_name = raw_right});
     mvs_cam = std::make_unique<mvs_camera_ui>(mvs_conf);
+    mvs_cam->cap_info_sig.connect([this](auto info) {
+        out_streamer->change_frame_rate(info.frame_rate);
+    });
 
     auto stereo_info = stereo_camera_info::from_yaml(LOAD_SUB("stereo_info"));
     float view_angle = 0.0f;

+ 2 - 2
src/module/image_streamer.h

@@ -14,8 +14,8 @@ public:
     struct create_config {
         // image must be valid before start
         obj_name_type img_name = invalid_obj_name;
+        std::optional<int> frame_rate;
         io_context *asio_ctx = nullptr;
-        // TODO: add frame rate
 
         // for encoder
         CUcontext *cuda_ctx = nullptr;
@@ -28,7 +28,7 @@ public:
 
     void show();
 
-    // TODO: add change frame rate
+    void change_frame_rate(int fps);
 
     using sig_req_size_type = boost::signals2::signal<void(cv::Size)>;
     sig_req_size_type sig_req_size;

+ 34 - 4
src/module/impl/image_streamer.cpp

@@ -4,11 +4,12 @@
 void image_streamer::impl::create_encoder() {
     switch (chose_encoder_type) {
         case ENCODER_NVENC: {
-            auto img_info = OBJ_QUERY(image_u8c4, conf.img_name)->as_info();
-            int img_freq = std::round(OBJ_STATS(conf.img_name).save_frequency);
-
+            img_size = get_image_size(conf.img_name);
+            if (img_size.empty()) break; // lazy create
+            int img_freq = conf.frame_rate.value_or(
+                    std::round(OBJ_STATS(conf.img_name).save_frequency));
             auto enc_conf = encoder_nvenc::create_config();
-            enc_conf.frame_size = img_info.size;
+            enc_conf.frame_size = img_size;
             enc_conf.frame_rate = img_freq;
             enc_conf.bitrate_mbps = enc_bitrate_mbps;
             enc_conf.save_file = enc_save_file;
@@ -19,6 +20,7 @@ void image_streamer::impl::create_encoder() {
             assert(enc_nvenc == nullptr);
             enc_nvenc = encoder_nvenc::create(enc_conf);
             assert(enc_nvenc != nullptr);
+            SPDLOG_INFO("NvEnc created with size {}x{}.", img_size.width, img_size.height);
             return;
         }
         default: {
@@ -112,6 +114,26 @@ void image_streamer::impl::stop() {
     is_running = false;
 }
 
+void image_streamer::impl::change_frame_rate(int fps) {
+    conf.frame_rate = fps;
+    if (!is_running) return;
+
+    switch (chose_encoder_type) {
+        case ENCODER_NVENC: {
+            auto mod_conf = encoder_nvenc::modifiable_config{
+                    .frame_rate = fps, .bitrate_mbps =enc_bitrate_mbps,
+            };
+            enc_nvenc->change_config(mod_conf);
+            break;
+        }
+        case ENCODER_JPEG: // do nothing
+            break;
+        default: {
+            RET_ERROR;
+        }
+    }
+}
+
 void image_streamer::impl::image_callback(obj_name_type name) {
     assert(name == conf.img_name);
 
@@ -135,6 +157,10 @@ frame_info image_streamer::impl::encode_image() {
     switch (chose_encoder_type) {
         case ENCODER_NVENC: {
             auto img = OBJ_QUERY(image_u8c4, conf.img_name);
+            if (img->size() != img_size) { // recreate encoder
+                enc_nvenc = nullptr;
+                create_encoder();
+            }
             assert(enc_nvenc != nullptr);
             auto frame = enc_nvenc->encode(img, enc_idr_requested);
             enc_idr_requested = false;
@@ -254,4 +280,8 @@ image_streamer::~image_streamer() = default;
 
 void image_streamer::show() {
     pimpl->show();
+}
+
+void image_streamer::change_frame_rate(int fps) {
+    pimpl->change_frame_rate(fps);
 }

+ 3 - 0
src/module/impl/image_streamer_impl.h

@@ -27,6 +27,7 @@ struct image_streamer::impl {
     bool enc_idr_requested = false;
 
     // for NvEnc
+    cv::Size img_size;
     float enc_bitrate_mbps = 5.0f; // 5Mbps
 
     // for NvJpeg
@@ -74,6 +75,8 @@ struct image_streamer::impl {
 
     void start();
 
+    void change_frame_rate(int fps);
+
     void stop();
 
     void create_encoder();