From dad36689c42409b55be22c9a67aec927893e5f65 Mon Sep 17 00:00:00 2001 From: WarmUpTill Date: Mon, 3 May 2021 22:10:29 +0200 Subject: [PATCH] Move AdvSSScreenshotObj to separate files --- CMakeLists.txt | 2 + src/headers/screenshot-helper.hpp | 29 +++++++ src/headers/switch-video.hpp | 25 +----- src/screenshot-helper.cpp | 131 ++++++++++++++++++++++++++++++ src/switch-video.cpp | 130 ----------------------------- 5 files changed, 163 insertions(+), 154 deletions(-) create mode 100644 src/headers/screenshot-helper.hpp create mode 100644 src/screenshot-helper.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 512ae392..eba2f56a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ set(advanced-scene-switcher_HEADERS src/headers/switch-video.hpp src/headers/switch-generic.hpp src/headers/curl-helper.hpp + src/headers/screenshot-helper.hpp src/headers/duration-control.hpp src/headers/volume-control.hpp src/headers/version.h @@ -112,6 +113,7 @@ set(advanced-scene-switcher_SOURCES src/switch-video.cpp src/switch-generic.cpp src/curl-helper.cpp + src/screenshot-helper.cpp src/duration-control.cpp src/volume-control.cpp src/version.cpp diff --git a/src/headers/screenshot-helper.hpp b/src/headers/screenshot-helper.hpp new file mode 100644 index 00000000..72909cc6 --- /dev/null +++ b/src/headers/screenshot-helper.hpp @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include +#include + +class AdvSSScreenshotObj { +public: + AdvSSScreenshotObj(obs_source_t *source); + ~AdvSSScreenshotObj(); + + void Screenshot(); + void Download(); + void Copy(); + void MarkDone(); + + gs_texrender_t *texrender = nullptr; + gs_stagesurf_t *stagesurf = nullptr; + OBSWeakSource weakSource; + std::string path; + QImage image; + uint32_t cx = 0; + uint32_t cy = 0; + + int stage = 0; + + bool done = false; + std::chrono::high_resolution_clock::time_point time; +}; diff --git a/src/headers/switch-video.hpp b/src/headers/switch-video.hpp index 8740294a..aca632f2 100644 --- a/src/headers/switch-video.hpp +++ b/src/headers/switch-video.hpp @@ -2,6 +2,7 @@ #include #include "switch-generic.hpp" +#include "screenshot-helper.hpp" constexpr auto video_func = 9; constexpr auto default_priority_9 = video_func; @@ -13,30 +14,6 @@ enum class videoSwitchType { HAS_CHANGED, }; -class AdvSSScreenshotObj { -public: - AdvSSScreenshotObj(obs_source_t *source); - ~AdvSSScreenshotObj(); - - void Screenshot(); - void Download(); - void Copy(); - void MarkDone(); - - gs_texrender_t *texrender = nullptr; - gs_stagesurf_t *stagesurf = nullptr; - OBSWeakSource weakSource; - std::string path; - QImage image; - uint32_t cx = 0; - uint32_t cy = 0; - - int stage = 0; - - bool done = false; - std::chrono::high_resolution_clock::time_point time; -}; - struct VideoSwitch : virtual SceneSwitcherEntry { static bool pause; diff --git a/src/screenshot-helper.cpp b/src/screenshot-helper.cpp new file mode 100644 index 00000000..cfe6ecc3 --- /dev/null +++ b/src/screenshot-helper.cpp @@ -0,0 +1,131 @@ +#include "headers/screenshot-helper.hpp" + +static void ScreenshotTick(void *param, float); + +AdvSSScreenshotObj::AdvSSScreenshotObj(obs_source_t *source) + : weakSource(OBSGetWeakRef(source)) +{ + obs_add_tick_callback(ScreenshotTick, this); +} + +AdvSSScreenshotObj::~AdvSSScreenshotObj() +{ + obs_enter_graphics(); + gs_stagesurface_destroy(stagesurf); + gs_texrender_destroy(texrender); + obs_leave_graphics(); + + obs_remove_tick_callback(ScreenshotTick, this); +} + +void AdvSSScreenshotObj::Screenshot() +{ + OBSSource source = OBSGetStrongRef(weakSource); + + if (source) { + cx = obs_source_get_base_width(source); + cy = obs_source_get_base_height(source); + } else { + obs_video_info ovi; + obs_get_video_info(&ovi); + cx = ovi.base_width; + cy = ovi.base_height; + } + + if (!cx || !cy) { + blog(LOG_WARNING, "Cannot screenshot, invalid target size"); + obs_remove_tick_callback(ScreenshotTick, this); + done = true; + return; + } + + texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); + stagesurf = gs_stagesurface_create(cx, cy, GS_RGBA); + + gs_texrender_reset(texrender); + if (gs_texrender_begin(texrender, cx, cy)) { + vec4 zero; + vec4_zero(&zero); + + gs_clear(GS_CLEAR_COLOR, &zero, 0.0f, 0); + gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f); + + gs_blend_state_push(); + gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); + + if (source) { + obs_source_inc_showing(source); + obs_source_video_render(source); + obs_source_dec_showing(source); + } else { + obs_render_main_texture(); + } + + gs_blend_state_pop(); + gs_texrender_end(texrender); + } +} + +void AdvSSScreenshotObj::Download() +{ + gs_stage_texture(stagesurf, gs_texrender_get_texture(texrender)); +} + +void AdvSSScreenshotObj::Copy() +{ + uint8_t *videoData = nullptr; + uint32_t videoLinesize = 0; + + image = QImage(cx, cy, QImage::Format::Format_RGBX8888); + + if (gs_stagesurface_map(stagesurf, &videoData, &videoLinesize)) { + int linesize = image.bytesPerLine(); + for (int y = 0; y < (int)cy; y++) + memcpy(image.scanLine(y), + videoData + (y * videoLinesize), linesize); + + gs_stagesurface_unmap(stagesurf); + } +} + +void AdvSSScreenshotObj::MarkDone() +{ + time = std::chrono::high_resolution_clock::now(); + done = true; +} + +#define STAGE_SCREENSHOT 0 +#define STAGE_DOWNLOAD 1 +#define STAGE_COPY_AND_SAVE 2 +#define STAGE_FINISH 3 + +static void ScreenshotTick(void *param, float) +{ + AdvSSScreenshotObj *data = + reinterpret_cast(param); + + if (data->stage == STAGE_FINISH) { + return; + } + + obs_enter_graphics(); + + switch (data->stage) { + case STAGE_SCREENSHOT: + data->Screenshot(); + break; + case STAGE_DOWNLOAD: + data->Download(); + break; + case STAGE_COPY_AND_SAVE: + data->Copy(); + data->MarkDone(); + + obs_remove_tick_callback(ScreenshotTick, data); + break; + } + + obs_leave_graphics(); + + data->stage++; +} diff --git a/src/switch-video.cpp b/src/switch-video.cpp index 155c8b36..95ef3041 100644 --- a/src/switch-video.cpp +++ b/src/switch-video.cpp @@ -9,136 +9,6 @@ bool VideoSwitch::pause = false; static QMetaObject::Connection addPulse; -static void ScreenshotTick(void *param, float); - -AdvSSScreenshotObj::AdvSSScreenshotObj(obs_source_t *source) - : weakSource(OBSGetWeakRef(source)) -{ - obs_add_tick_callback(ScreenshotTick, this); -} - -AdvSSScreenshotObj::~AdvSSScreenshotObj() -{ - obs_enter_graphics(); - gs_stagesurface_destroy(stagesurf); - gs_texrender_destroy(texrender); - obs_leave_graphics(); - - obs_remove_tick_callback(ScreenshotTick, this); -} - -void AdvSSScreenshotObj::Screenshot() -{ - OBSSource source = OBSGetStrongRef(weakSource); - - if (source) { - cx = obs_source_get_base_width(source); - cy = obs_source_get_base_height(source); - } else { - obs_video_info ovi; - obs_get_video_info(&ovi); - cx = ovi.base_width; - cy = ovi.base_height; - } - - if (!cx || !cy) { - blog(LOG_WARNING, "Cannot screenshot, invalid target size"); - obs_remove_tick_callback(ScreenshotTick, this); - done = true; - return; - } - - texrender = gs_texrender_create(GS_RGBA, GS_ZS_NONE); - stagesurf = gs_stagesurface_create(cx, cy, GS_RGBA); - - gs_texrender_reset(texrender); - if (gs_texrender_begin(texrender, cx, cy)) { - vec4 zero; - vec4_zero(&zero); - - gs_clear(GS_CLEAR_COLOR, &zero, 0.0f, 0); - gs_ortho(0.0f, (float)cx, 0.0f, (float)cy, -100.0f, 100.0f); - - gs_blend_state_push(); - gs_blend_function(GS_BLEND_ONE, GS_BLEND_ZERO); - - if (source) { - obs_source_inc_showing(source); - obs_source_video_render(source); - obs_source_dec_showing(source); - } else { - obs_render_main_texture(); - } - - gs_blend_state_pop(); - gs_texrender_end(texrender); - } -} - -void AdvSSScreenshotObj::Download() -{ - gs_stage_texture(stagesurf, gs_texrender_get_texture(texrender)); -} - -void AdvSSScreenshotObj::Copy() -{ - uint8_t *videoData = nullptr; - uint32_t videoLinesize = 0; - - image = QImage(cx, cy, QImage::Format::Format_RGBX8888); - - if (gs_stagesurface_map(stagesurf, &videoData, &videoLinesize)) { - int linesize = image.bytesPerLine(); - for (int y = 0; y < (int)cy; y++) - memcpy(image.scanLine(y), - videoData + (y * videoLinesize), linesize); - - gs_stagesurface_unmap(stagesurf); - } -} - -void AdvSSScreenshotObj::MarkDone() -{ - time = std::chrono::high_resolution_clock::now(); - done = true; -} - -#define STAGE_SCREENSHOT 0 -#define STAGE_DOWNLOAD 1 -#define STAGE_COPY_AND_SAVE 2 -#define STAGE_FINISH 3 - -static void ScreenshotTick(void *param, float) -{ - AdvSSScreenshotObj *data = - reinterpret_cast(param); - - if (data->stage == STAGE_FINISH) { - return; - } - - obs_enter_graphics(); - - switch (data->stage) { - case STAGE_SCREENSHOT: - data->Screenshot(); - break; - case STAGE_DOWNLOAD: - data->Download(); - break; - case STAGE_COPY_AND_SAVE: - data->Copy(); - data->MarkDone(); - - obs_remove_tick_callback(ScreenshotTick, data); - break; - } - - obs_leave_graphics(); - - data->stage++; -} - void AdvSceneSwitcher::on_videoAdd_clicked() { std::lock_guard lock(switcher->m);