main.cpp 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. #include "augment_renderer.h"
  2. #include "config.h"
  3. #include "frame_buffer_helper.hpp"
  4. #include "stereo_camera.hpp"
  5. #include "texture_renderer.h"
  6. #include "video_encoder.h"
  7. #include "third_party/scope_guard.hpp"
  8. #include <imgui.h>
  9. #include <imgui_impl_glfw.h>
  10. #include <imgui_impl_opengl3.h>
  11. #include <glad/gl.h>
  12. #include <GLFW/glfw3.h>
  13. #include <fmt/chrono.h>
  14. #include <fmt/format.h>
  15. #include <spdlog/spdlog.h>
  16. #include <cassert>
  17. #include <cstdlib>
  18. CUcontext cuda_ctx;
  19. int main() {
  20. spdlog::set_level(spdlog::level::trace);
  21. // setup glfw and main window
  22. glfwSetErrorCallback([](int error, const char *desc) {
  23. SPDLOG_ERROR("GLFW error: code = {}, description = {}", error, desc);
  24. assert(false);
  25. });
  26. auto ret = glfwInit();
  27. assert(ret == GLFW_TRUE);
  28. glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
  29. glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
  30. glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
  31. auto main_window = glfwCreateWindow(main_window_width, main_window_height, "RemoteAR", nullptr, nullptr);
  32. assert(main_window != nullptr);
  33. glfwMakeContextCurrent(main_window);
  34. // glfwSwapInterval(1);
  35. // load opengl functions
  36. auto version = gladLoadGL(glfwGetProcAddress);
  37. assert(version > 0);
  38. SPDLOG_INFO("Loaded OpenGL {}.{}", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
  39. #ifndef NDEBUG
  40. // log opengl error
  41. glEnable(GL_DEBUG_OUTPUT);
  42. glDebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity,
  43. GLsizei length, const GLchar *message, const void *user_data) {
  44. if (type == GL_DEBUG_TYPE_ERROR) {
  45. SPDLOG_ERROR("OpenGL error: type = {}, severity = {}, message = {}", type, severity, message);
  46. assert(false);
  47. }
  48. }, nullptr);
  49. #endif
  50. // setup imgui context
  51. IMGUI_CHECKVERSION();
  52. ImGui::CreateContext();
  53. auto io = ImGui::GetIO();
  54. io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
  55. ImGui::StyleColorsDark();
  56. ImGui_ImplGlfw_InitForOpenGL(main_window, true);
  57. ImGui_ImplOpenGL3_Init();
  58. // setup cuda context
  59. cuInit(0);
  60. create_cuda_context(&cuda_ctx);
  61. // working staffs
  62. stereo_camera camera;
  63. texture_renderer tex_renderer;
  64. frame_buffer_helper output_fbo;
  65. output_fbo.initialize(output_frame_width, output_frame_height);
  66. video_encoder encoder;
  67. encoder.initialize();
  68. augment_renderer left_ar, right_ar;
  69. left_ar.initialize(&tex_renderer);
  70. right_ar.initialize(&tex_renderer);
  71. left_ar.set_background(&camera.left_rgb_image);
  72. right_ar.set_background(&camera.right_rgb_image);
  73. int camera_fps = default_camera_fps;
  74. float exposure_time_ms = default_camera_exposure_time_ms;
  75. float analog_gain = default_camera_analog_gain;
  76. float output_bitrate_mbps = default_video_stream_bitrate / 1e6f;
  77. FILE *video_save_file = nullptr;
  78. auto video_save_file_closer = sg::make_scope_guard([&]() {
  79. if (video_save_file == nullptr) return;
  80. fclose(video_save_file);
  81. });
  82. // main loop
  83. while (!glfwWindowShouldClose(main_window)) {
  84. glfwPollEvents();
  85. ImGui_ImplOpenGL3_NewFrame();
  86. ImGui_ImplGlfw_NewFrame();
  87. ImGui::NewFrame();
  88. ImGui::ShowDemoWindow();
  89. if (ImGui::Begin("Remote AR Control")) {
  90. // extra actions to make consistency
  91. if (!camera.is_capturing() && encoder.is_encoding()) {
  92. encoder.stop_encode();
  93. }
  94. // camera control
  95. if (ImGui::CollapsingHeader("Camera")) {
  96. ImGui::PushID("Camera");
  97. // camera actions
  98. ImGui::SeparatorText("Actions");
  99. if (!camera.is_opened()) {
  100. if (ImGui::Button("Open")) {
  101. camera.open();
  102. }
  103. } else {
  104. if (ImGui::Button("Close")) {
  105. camera.close();
  106. }
  107. ImGui::SameLine();
  108. if (!camera.is_capturing()) {
  109. if (ImGui::Button("Start")) {
  110. camera.start_capture(1000 * exposure_time_ms, analog_gain, camera_fps);
  111. }
  112. } else {
  113. if (ImGui::Button("Stop")) {
  114. camera.stop_capture();
  115. }
  116. }
  117. }
  118. // camera configs
  119. if (camera.is_opened()) {
  120. ImGui::SeparatorText("Configs");
  121. // don't allow config change wile camera is capturing
  122. if (camera.is_capturing()) {
  123. ImGui::BeginDisabled();
  124. }
  125. ImGui::PushItemWidth(200);
  126. ImGui::SliderInt("Frame Rate (fps)", &camera_fps, 1, 60);
  127. ImGui::DragFloat("Exposure Time (ms)", &exposure_time_ms,
  128. 0.1, 1, 1e3f / (float) camera_fps, "%.01f");
  129. ImGui::DragFloat("Analog Gain (dB)", &analog_gain, 0.1, 0, 24, "%.01f");
  130. ImGui::PopItemWidth();
  131. if (camera.is_capturing()) {
  132. ImGui::EndDisabled();
  133. }
  134. }
  135. ImGui::PopID();
  136. }
  137. // video streamer control
  138. if (camera.is_capturing() && ImGui::CollapsingHeader("Video Streamer")) {
  139. ImGui::PushID("Streamer");
  140. ImGui::SeparatorText("Actions");
  141. if (!encoder.is_encoding()) {
  142. if (ImGui::Button("Start")) {
  143. // create save file
  144. assert(video_save_file == nullptr);
  145. auto file_name = fmt::format("record_{:%Y_%m_%d_%H_%M_%S}.hevc",
  146. std::chrono::system_clock::now());
  147. video_save_file = fopen(file_name.c_str(), "wb");
  148. encoder.start_encode(output_fbo.tex_width, output_fbo.tex_height,
  149. camera_fps, (int) (output_bitrate_mbps * 1e6));
  150. }
  151. } else {
  152. if (ImGui::Button("Close")) {
  153. encoder.stop_encode();
  154. fclose(video_save_file);
  155. video_save_file = nullptr;
  156. }
  157. }
  158. if (encoder.is_encoding()) {
  159. ImGui::BeginDisabled();
  160. }
  161. ImGui::PushItemWidth(200);
  162. ImGui::DragFloat("Bitrate (Mbps)", &output_bitrate_mbps, 0.1, 1, 20, "%.01f");
  163. ImGui::PopItemWidth();
  164. if (encoder.is_encoding()) {
  165. ImGui::EndDisabled();
  166. }
  167. ImGui::PopID();
  168. }
  169. }
  170. ImGui::End();
  171. ImGui::Render();
  172. std::chrono::high_resolution_clock::time_point start_time;
  173. if (camera.is_capturing()) {
  174. camera.retrieve_raw_images();
  175. start_time = std::chrono::high_resolution_clock::now();
  176. camera.debayer_images();
  177. }
  178. if (encoder.is_encoding()) {
  179. // draw frame for streaming
  180. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, output_fbo.fbo);
  181. glViewport(0, 0, output_fbo.tex_width, output_fbo.tex_height);
  182. left_ar.render({-1, -1, 1, 2});
  183. right_ar.render({0, -1, 1, 2});
  184. // encode frame
  185. output_fbo.download_pixels();
  186. void *frame_data;
  187. size_t frame_length;
  188. encoder.encode_frame(output_fbo.pbo_res, &frame_data, &frame_length);
  189. SPDLOG_TRACE("Time used: {}ms", std::chrono::duration_cast<std::chrono::milliseconds>(
  190. std::chrono::high_resolution_clock::now() - start_time).count());
  191. // save encoded frame
  192. fwrite(frame_data, frame_length, 1, video_save_file);
  193. }
  194. int frame_width, frame_height;
  195. glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
  196. glfwGetFramebufferSize(main_window, &frame_width, &frame_height);
  197. glViewport(0, 0, frame_width, frame_height);
  198. glClear(GL_COLOR_BUFFER_BIT);
  199. if (camera.is_capturing()) {
  200. // draw frame in the screen
  201. left_ar.render({-1, 1, 2, -2});
  202. }
  203. ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
  204. glfwSwapBuffers(main_window);
  205. if (camera.is_capturing()) {
  206. glFlush();
  207. }
  208. }
  209. // cleanup
  210. std::atexit([]() {
  211. cuCtxDestroy(cuda_ctx);
  212. });
  213. ImGui_ImplOpenGL3_Shutdown();
  214. ImGui_ImplGlfw_Shutdown();
  215. ImGui::DestroyContext();
  216. glfwDestroyWindow(main_window);
  217. glfwTerminate();
  218. return 0;
  219. }