mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-03-22 01:44:49 -05:00
132 lines
2.7 KiB
C++
132 lines
2.7 KiB
C++
#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<AdvSSScreenshotObj *>(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++;
|
|
}
|