|
|
@@ -2,6 +2,7 @@
|
|
|
#include "config.h"
|
|
|
#include "frame_buffer_helper.hpp"
|
|
|
#include "frame_sender.h"
|
|
|
+#include "raw_file_saver.h"
|
|
|
#include "scene_manager.hpp"
|
|
|
#include "sophiar_connect.h"
|
|
|
#include "stereo_camera.hpp"
|
|
|
@@ -95,12 +96,16 @@ int main() {
|
|
|
frame_sender sender;
|
|
|
std::atomic_flag idr_flag;
|
|
|
|
|
|
- frame_buffer_helper output_fbo;
|
|
|
- output_fbo.initialize(output_frame_width, output_frame_height);
|
|
|
+ std::unique_ptr<frame_buffer_helper> output_fbo;
|
|
|
+// output_fbo.initialize(output_frame_width, output_frame_height);
|
|
|
|
|
|
video_encoder encoder;
|
|
|
encoder.initialize();
|
|
|
|
|
|
+ raw_file_saver raw_saver;
|
|
|
+ raw_saver.start(raw_save_prefix);
|
|
|
+ camera.set_raw_saver(&raw_saver);
|
|
|
+
|
|
|
// config sophiar
|
|
|
using namespace sophiar;
|
|
|
variable_io var_io;
|
|
|
@@ -154,7 +159,12 @@ int main() {
|
|
|
|
|
|
int preview_cam = 0; // left camera
|
|
|
bool save_video = true; // whether encoded bitstream should be saved
|
|
|
- bool save_frame_length = true; // save frame length for tiny player to replay
|
|
|
+ bool save_frame_length = false; // save frame length for tiny player to replay
|
|
|
+ bool full_resolution = false;
|
|
|
+
|
|
|
+ bool auto_save_raw = false;
|
|
|
+ int auto_save_raw_interval = default_raw_save_interval_s;
|
|
|
+ std::chrono::system_clock::time_point last_save_raw_time;
|
|
|
|
|
|
// main loop
|
|
|
while (!glfwWindowShouldClose(main_window)) {
|
|
|
@@ -199,6 +209,12 @@ int main() {
|
|
|
if (ImGui::Button("Stop")) {
|
|
|
camera.stop_capture();
|
|
|
}
|
|
|
+ if (!auto_save_raw) {
|
|
|
+ ImGui::SameLine();
|
|
|
+ if (ImGui::Button("Capture")) {
|
|
|
+ camera.request_save_raw();
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -225,6 +241,40 @@ int main() {
|
|
|
ImGui::RadioButton("Left", &preview_cam, 0);
|
|
|
ImGui::SameLine();
|
|
|
ImGui::RadioButton("Right", &preview_cam, 1);
|
|
|
+
|
|
|
+ // auto save raw config
|
|
|
+ ImGui::SeparatorText("Auto Shoot");
|
|
|
+ ImGui::PushID("Auto Shoot");
|
|
|
+
|
|
|
+ if (!auto_save_raw) {
|
|
|
+ if (ImGui::Button("Start")) {
|
|
|
+ auto_save_raw = true;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (ImGui::Button("Stop")) {
|
|
|
+ auto_save_raw = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (auto_save_raw_interval < 1) {
|
|
|
+ auto_save_raw_interval = 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (auto_save_raw) {
|
|
|
+ ImGui::BeginDisabled();
|
|
|
+ auto now_time = std::chrono::system_clock::now();
|
|
|
+ if (now_time - last_save_raw_time >
|
|
|
+ std::chrono::seconds{auto_save_raw_interval}) {
|
|
|
+ camera.request_save_raw();
|
|
|
+ last_save_raw_time = now_time;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ImGui::InputInt("Shoot Interval (s)", &auto_save_raw_interval, 1, 10);
|
|
|
+ if (auto_save_raw) {
|
|
|
+ ImGui::EndDisabled();
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGui::PopID();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -238,7 +288,13 @@ int main() {
|
|
|
ImGui::SeparatorText("Actions");
|
|
|
if (!encoder.is_encoding()) {
|
|
|
if (ImGui::Button("Start")) {
|
|
|
- encoder.start_encode(output_fbo.tex_width, output_fbo.tex_height,
|
|
|
+ output_fbo = std::make_unique<frame_buffer_helper>();
|
|
|
+ if (full_resolution) {
|
|
|
+ output_fbo->initialize(2 * image_width, image_height);
|
|
|
+ } else {
|
|
|
+ output_fbo->initialize(output_frame_width, output_frame_height);
|
|
|
+ }
|
|
|
+ encoder.start_encode(output_fbo->tex_width, output_fbo->tex_height,
|
|
|
camera_fps, (int) (output_bitrate_mbps * 1e6),
|
|
|
save_video, save_frame_length);
|
|
|
}
|
|
|
@@ -254,6 +310,8 @@ int main() {
|
|
|
}
|
|
|
|
|
|
ImGui::DragFloat("Bitrate (Mbps)", &output_bitrate_mbps, 0.1, 1, 20, "%.01f");
|
|
|
+ ImGui::Checkbox("Full Resolution", &full_resolution);
|
|
|
+ ImGui::SameLine();
|
|
|
ImGui::Checkbox("Save Video", &save_video);
|
|
|
if (save_video) {
|
|
|
ImGui::SameLine();
|
|
|
@@ -334,10 +392,15 @@ int main() {
|
|
|
|
|
|
if (encoder.is_encoding()) {
|
|
|
// draw frame for streaming
|
|
|
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, output_fbo.fbo);
|
|
|
- glViewport(0, 0, output_fbo.tex_width, output_fbo.tex_height);
|
|
|
- left_ar.render({-0.5 - ar_width_normal / 2, -1, ar_width_normal, 2});
|
|
|
- right_ar.render({0.5 - ar_width_normal / 2, -1, ar_width_normal, 2});
|
|
|
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, output_fbo->fbo);
|
|
|
+ glViewport(0, 0, output_fbo->tex_width, output_fbo->tex_height);
|
|
|
+ if (full_resolution) {
|
|
|
+ left_ar.render({-1, -1, 1, 2});
|
|
|
+ right_ar.render({0, -1, 1, 2});
|
|
|
+ } else {
|
|
|
+ left_ar.render({-0.5 - ar_width_normal / 2, -1, ar_width_normal, 2});
|
|
|
+ right_ar.render({0.5 - ar_width_normal / 2, -1, ar_width_normal, 2});
|
|
|
+ }
|
|
|
|
|
|
// send IDR frame occasionally to prevent broken video frame
|
|
|
static int last_p_count = 0;
|
|
|
@@ -346,7 +409,7 @@ int main() {
|
|
|
}
|
|
|
|
|
|
// encode frame
|
|
|
- output_fbo.download_pixels();
|
|
|
+ output_fbo->download_pixels();
|
|
|
frame_sender::frame_info info;
|
|
|
info.is_idr_frame = idr_flag.test();
|
|
|
if (info.is_idr_frame) {
|
|
|
@@ -355,7 +418,7 @@ int main() {
|
|
|
idr_flag.clear();
|
|
|
last_p_count = 0;
|
|
|
}
|
|
|
- encoder.encode_frame(output_fbo.pbo_res, (void **) &info.data, &info.length);
|
|
|
+ encoder.encode_frame(output_fbo->pbo_res, (void **) &info.data, &info.length);
|
|
|
SPDLOG_TRACE("Time used: {}ms, length = {}", std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
std::chrono::high_resolution_clock::now() - start_time).count(), info.length);
|
|
|
|