|
|
@@ -5,6 +5,8 @@
|
|
|
#include "texture_renderer.h"
|
|
|
#include "video_encoder.h"
|
|
|
|
|
|
+#include "third_party/scope_guard.hpp"
|
|
|
+
|
|
|
#include <imgui.h>
|
|
|
#include <imgui_impl_glfw.h>
|
|
|
#include <imgui_impl_opengl3.h>
|
|
|
@@ -74,8 +76,8 @@ int main() {
|
|
|
stereo_camera camera;
|
|
|
texture_renderer tex_renderer;
|
|
|
|
|
|
- frame_buffer_helper fbo_helper;
|
|
|
- fbo_helper.initialize(image_width * 2, image_height);
|
|
|
+ frame_buffer_helper output_fbo;
|
|
|
+ output_fbo.initialize(output_frame_width, output_frame_height);
|
|
|
|
|
|
video_encoder encoder;
|
|
|
encoder.initialize();
|
|
|
@@ -89,8 +91,13 @@ int main() {
|
|
|
int camera_fps = default_camera_fps;
|
|
|
float exposure_time_ms = default_camera_exposure_time_ms;
|
|
|
float analog_gain = default_camera_analog_gain;
|
|
|
+ float output_bitrate_mbps = default_video_stream_bitrate / 1e6f;
|
|
|
|
|
|
FILE *video_save_file = nullptr;
|
|
|
+ auto video_save_file_closer = sg::make_scope_guard([&]() {
|
|
|
+ if (video_save_file == nullptr) return;
|
|
|
+ fclose(video_save_file);
|
|
|
+ });
|
|
|
|
|
|
// main loop
|
|
|
while (!glfwWindowShouldClose(main_window)) {
|
|
|
@@ -148,8 +155,8 @@ int main() {
|
|
|
ImGui::PushItemWidth(200);
|
|
|
ImGui::SliderInt("Frame Rate (fps)", &camera_fps, 1, 60);
|
|
|
ImGui::DragFloat("Exposure Time (ms)", &exposure_time_ms,
|
|
|
- 0.1, 1, 1e3f / (float) camera_fps, "%.1f");
|
|
|
- ImGui::DragFloat("Analog Gain (dB)", &analog_gain, 0.1, 0, 24, "%.1f");
|
|
|
+ 0.1, 1, 1e3f / (float) camera_fps, "%.01f");
|
|
|
+ ImGui::DragFloat("Analog Gain (dB)", &analog_gain, 0.1, 0, 24, "%.01f");
|
|
|
ImGui::PopItemWidth();
|
|
|
|
|
|
if (camera.is_capturing()) {
|
|
|
@@ -168,21 +175,33 @@ int main() {
|
|
|
if (!encoder.is_encoding()) {
|
|
|
if (ImGui::Button("Start")) {
|
|
|
// create save file
|
|
|
+ assert(video_save_file == nullptr);
|
|
|
auto file_name = fmt::format("record_{:%Y_%m_%d_%H_%M_%S}.hevc",
|
|
|
std::chrono::system_clock::now());
|
|
|
video_save_file = fopen(file_name.c_str(), "wb");
|
|
|
-
|
|
|
- encoder.start_encode(fbo_helper.tex_width, fbo_helper.tex_height, camera_fps);
|
|
|
- SPDLOG_INFO("Video streamer started.");
|
|
|
+ encoder.start_encode(output_fbo.tex_width, output_fbo.tex_height,
|
|
|
+ camera_fps, (int) (output_bitrate_mbps * 1e6));
|
|
|
}
|
|
|
} else {
|
|
|
if (ImGui::Button("Close")) {
|
|
|
encoder.stop_encode();
|
|
|
fclose(video_save_file);
|
|
|
- SPDLOG_INFO("Video streamer stopped.");
|
|
|
+ video_save_file = nullptr;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (encoder.is_encoding()) {
|
|
|
+ ImGui::BeginDisabled();
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGui::PushItemWidth(200);
|
|
|
+ ImGui::DragFloat("Bitrate (Mbps)", &output_bitrate_mbps, 0.1, 1, 20, "%.01f");
|
|
|
+ ImGui::PopItemWidth();
|
|
|
+
|
|
|
+ if (encoder.is_encoding()) {
|
|
|
+ ImGui::EndDisabled();
|
|
|
+ }
|
|
|
+
|
|
|
ImGui::PopID();
|
|
|
}
|
|
|
|
|
|
@@ -190,40 +209,47 @@ int main() {
|
|
|
ImGui::End();
|
|
|
ImGui::Render();
|
|
|
|
|
|
- int frame_width, frame_height;
|
|
|
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
- glfwGetFramebufferSize(main_window, &frame_width, &frame_height);
|
|
|
- glViewport(0, 0, frame_width, frame_height);
|
|
|
- glClear(GL_COLOR_BUFFER_BIT);
|
|
|
-
|
|
|
+ std::chrono::high_resolution_clock::time_point start_time;
|
|
|
if (camera.is_capturing()) {
|
|
|
camera.retrieve_raw_images();
|
|
|
+ start_time = std::chrono::high_resolution_clock::now();
|
|
|
camera.debayer_images();
|
|
|
-
|
|
|
- // draw frame in the screen
|
|
|
- left_ar.render({-1, 1, 2, -2});
|
|
|
}
|
|
|
|
|
|
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
|
- glfwSwapBuffers(main_window);
|
|
|
-
|
|
|
if (encoder.is_encoding()) {
|
|
|
// draw frame for streaming
|
|
|
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo_helper.fbo);
|
|
|
- glViewport(0, 0, fbo_helper.tex_width, fbo_helper.tex_height);
|
|
|
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, output_fbo.fbo);
|
|
|
+ glViewport(0, 0, output_fbo.tex_width, output_fbo.tex_height);
|
|
|
left_ar.render({-1, -1, 1, 2});
|
|
|
right_ar.render({0, -1, 1, 2});
|
|
|
|
|
|
// encode frame
|
|
|
- fbo_helper.download_pixels();
|
|
|
+ output_fbo.download_pixels();
|
|
|
void *frame_data;
|
|
|
size_t frame_length;
|
|
|
- encoder.encode_frame(fbo_helper.pbo_res, &frame_data, &frame_length);
|
|
|
+ encoder.encode_frame(output_fbo.pbo_res, &frame_data, &frame_length);
|
|
|
+
|
|
|
+ SPDLOG_TRACE("Time used: {}ms", std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
|
+ std::chrono::high_resolution_clock::now() - start_time).count());
|
|
|
|
|
|
// save encoded frame
|
|
|
fwrite(frame_data, frame_length, 1, video_save_file);
|
|
|
}
|
|
|
|
|
|
+ int frame_width, frame_height;
|
|
|
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
|
|
+ glfwGetFramebufferSize(main_window, &frame_width, &frame_height);
|
|
|
+ glViewport(0, 0, frame_width, frame_height);
|
|
|
+ glClear(GL_COLOR_BUFFER_BIT);
|
|
|
+
|
|
|
+ if (camera.is_capturing()) {
|
|
|
+ // draw frame in the screen
|
|
|
+ left_ar.render({-1, 1, 2, -2});
|
|
|
+ }
|
|
|
+
|
|
|
+ ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
|
+ glfwSwapBuffers(main_window);
|
|
|
+
|
|
|
if (camera.is_capturing()) {
|
|
|
glFlush();
|
|
|
}
|