| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- #include "config.h"
- #include "cuda_helper.hpp"
- #include "frame_receiver.h"
- #include "frame_receiver2.h"
- #include "nv12_renderer.h"
- #include "third_party/scope_guard.hpp"
- #include "video_decoder.h"
- #include <imgui.h>
- #include <imgui_impl_glfw.h>
- #include <imgui_impl_opengl3.h>
- #include <glad/gl.h>
- #include <GLFW/glfw3.h>
- #include <boost/process/child.hpp>
- #include <spdlog/spdlog.h>
- #include <thread>
- #ifdef _MSC_VER
- #include <format>
- #define fmt std
- #endif
- // for renderer
- int monitor_index = 0;
- char *server_address;
- uint16_t server_port = 5277;
- GLFWwindow *main_window = nullptr;
- // for receiver
- video_decoder decoder;
- void controller_main(const char *this_name) {
- // setup imgui context
- IMGUI_CHECKVERSION();
- ImGui::CreateContext();
- auto io = ImGui::GetIO();
- io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
- ImGui::StyleColorsDark();
- ImGui_ImplGlfw_InitForOpenGL(main_window, true);
- ImGui_ImplOpenGL3_Init();
- static constexpr auto server_address_length = 256;
- server_address = (char *) malloc(server_address_length);
- strcpy(server_address, "127.0.0.1");
- auto closer = sg::make_scope_guard([&]() {
- free(server_address);
- });
- namespace bp = boost::process;
- bp::child *worker = nullptr;
- // main loop
- while (!glfwWindowShouldClose(main_window)) {
- glfwPollEvents();
- ImGui_ImplOpenGL3_NewFrame();
- ImGui_ImplGlfw_NewFrame();
- ImGui::NewFrame();
- // ImGui::ShowDemoWindow();
- if (ImGui::Begin("TinyPlayer Control")) {
- // action
- ImGui::SeparatorText("Actions");
- if (worker == nullptr) {
- if (ImGui::Button("Start")) {
- worker = new bp::child{this_name, std::to_string(monitor_index),
- server_address, std::to_string(server_port)};
- }
- } else {
- if (ImGui::Button("Stop")) {
- worker->terminate();
- worker = nullptr;
- }
- }
- // configs
- ImGui::SeparatorText("Configs");
- ImGui::PushItemWidth(200);
- if (worker != nullptr) {
- ImGui::BeginDisabled();
- }
- // monitor
- int monitor_count;
- auto monitors = glfwGetMonitors(&monitor_count);
- if (monitor_index >= monitor_count) {
- monitor_index = 0;
- }
- auto monitor_name_preview = glfwGetMonitorName(monitors[monitor_index]);
- if (ImGui::BeginCombo("Monitor", monitor_name_preview)) { // let user select monitors
- for (int k = 0; k < monitor_count; ++k) {
- auto is_selected = (monitor_index == k);
- auto monitor_name = fmt::format("{} - {}", k, glfwGetMonitorName(monitors[k]));
- if (ImGui::Selectable(monitor_name.c_str(), is_selected)) {
- monitor_index = k;
- }
- if (is_selected) {
- ImGui::SetItemDefaultFocus();
- }
- }
- ImGui::EndCombo();
- }
- // server address
- ImGui::InputText("Server IP", server_address, server_address_length);
- // server port
- static uint16_t val_one = 1;
- ImGui::InputScalar("Server Port", ImGuiDataType_U16, &server_port, &val_one, nullptr, "%u");
- if (worker != nullptr) {
- ImGui::EndDisabled();
- }
- ImGui::PopItemWidth();
- }
- 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);
- ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
- glfwSwapBuffers(main_window);
- }
- if (worker != nullptr) {
- worker->terminate();
- }
- }
- void render_main() {
- // setup cuda
- cuInit(0);
- CUcontext cuda_ctx;
- get_cuda_primary_context(&cuda_ctx);
- cuCtxPushCurrent(cuda_ctx);
- std::thread receiver_thread{[]() {
- // setup cuda
- CUcontext cuda_ctx;
- get_cuda_primary_context(&cuda_ctx);
- cuCtxPushCurrent(cuda_ctx);
- decoder.start();
- // frame_receiver receiver;
- // receiver.start(server_address, server_port, &decoder);
- auto conf = receiver_config{
- server_address, server_port, &decoder
- };
- auto receiver = std::unique_ptr<frame_receiver2>(frame_receiver2::create(conf));
- receiver->run();
- }};
- nv12_renderer renderer;
- while (!glfwWindowShouldClose(main_window)) {
- glfwPollEvents();
- // retrieve new image
- decoder.retrieve_frame(&renderer);
- // adjust window
- int fbo_width, fbo_height;
- glfwGetFramebufferSize(main_window, &fbo_width, &fbo_height);
- glViewport(0, 0, fbo_width, fbo_height);
- auto fbo_wh_ratio = 1.0f * fbo_width / fbo_height;
- // draw image
- renderer.render(fbo_wh_ratio);
- glfwSwapBuffers(main_window);
- glFinish();
- }
- }
- int main(int argc, char *argv[]) {
- #ifndef NDEBUG
- spdlog::set_level(spdlog::level::trace);
- #endif
- // config options
- bool is_controller = (argc == 1);
- if (!is_controller) {
- assert(argc == 4);
- monitor_index = std::atoi(argv[1]);
- server_address = argv[2];
- server_port = std::atoi(argv[3]);
- }
- // setup glfw
- glfwSetErrorCallback([](int error, const char *desc) {
- SPDLOG_ERROR("GLFW error: code = {}, description = {}", error, desc);
- assert(false);
- });
- auto ret = glfwInit();
- assert(ret == GLFW_TRUE);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 6);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- glfwWindowHint(GLFW_REFRESH_RATE, 60);
- // setup window
- if (is_controller) {
- main_window = glfwCreateWindow(main_window_width, main_window_height, "TinyPlayer Control", nullptr, nullptr);
- } else { // is render
- int monitor_count;
- auto monitors = glfwGetMonitors(&monitor_count);
- assert(monitor_count > monitor_index);
- auto monitor = monitors[monitor_index];
- auto video_mode = glfwGetVideoMode(monitor);
- // main_window = glfwCreateWindow(video_mode->width, video_mode->height, "TinyPlayer", monitor, nullptr);
- main_window = glfwCreateWindow(800, 600, "TinyPlayer", nullptr, nullptr);
- }
- glfwMakeContextCurrent(main_window);
- glfwSwapInterval(1);
- // load opengl functions
- auto version = gladLoadGL(glfwGetProcAddress);
- assert(version > 0);
- SPDLOG_INFO("Loaded OpenGL {}.{}", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version));
- #ifndef NDEBUG
- // log opengl error
- glEnable(GL_DEBUG_OUTPUT);
- glDebugMessageCallback([](GLenum source, GLenum type, GLuint id, GLenum severity,
- GLsizei length, const GLchar *message, const void *user_data) {
- if (type == GL_DEBUG_TYPE_ERROR) {
- SPDLOG_ERROR("OpenGL error: type = {}, severity = {}, message = {}", type, severity, message);
- assert(false);
- }
- }, nullptr);
- #endif
- if (is_controller) {
- controller_main(argv[0]);
- } else {
- render_main();
- }
- return 0;
- }
|