mirror of
https://github.com/obsproject/obs-studio.git
synced 2024-07-14 23:34:08 +00:00
Merge pull request #7814 from jpark37/decklink-preview-rescale
decklink: Move preview output rescaling to GPU
This commit is contained in:
commit
0a9ed4569b
|
@ -29,6 +29,7 @@ struct preview_output {
|
||||||
obs_output_t *output;
|
obs_output_t *output;
|
||||||
|
|
||||||
video_t *video_queue;
|
video_t *video_queue;
|
||||||
|
gs_texrender_t *texrender_premultiplied;
|
||||||
gs_texrender_t *texrender;
|
gs_texrender_t *texrender;
|
||||||
gs_stagesurf_t *stagesurfaces[STAGE_BUFFER_COUNT];
|
gs_stagesurf_t *stagesurfaces[STAGE_BUFFER_COUNT];
|
||||||
bool surf_written[STAGE_BUFFER_COUNT];
|
bool surf_written[STAGE_BUFFER_COUNT];
|
||||||
|
@ -120,6 +121,8 @@ static void preview_tick(void *param, float sec)
|
||||||
|
|
||||||
auto ctx = (struct preview_output *)param;
|
auto ctx = (struct preview_output *)param;
|
||||||
|
|
||||||
|
if (ctx->texrender_premultiplied)
|
||||||
|
gs_texrender_reset(ctx->texrender_premultiplied);
|
||||||
if (ctx->texrender)
|
if (ctx->texrender)
|
||||||
gs_texrender_reset(ctx->texrender);
|
gs_texrender_reset(ctx->texrender);
|
||||||
}
|
}
|
||||||
|
@ -135,9 +138,14 @@ void preview_output_stop()
|
||||||
obs_source_release(context.current_source);
|
obs_source_release(context.current_source);
|
||||||
|
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
for (gs_stagesurf_t *surf : context.stagesurfaces)
|
for (gs_stagesurf_t *&surf : context.stagesurfaces) {
|
||||||
gs_stagesurface_destroy(surf);
|
gs_stagesurface_destroy(surf);
|
||||||
|
surf = nullptr;
|
||||||
|
}
|
||||||
gs_texrender_destroy(context.texrender);
|
gs_texrender_destroy(context.texrender);
|
||||||
|
context.texrender = nullptr;
|
||||||
|
gs_texrender_destroy(context.texrender_premultiplied);
|
||||||
|
context.texrender_premultiplied = nullptr;
|
||||||
obs_leave_graphics();
|
obs_leave_graphics();
|
||||||
|
|
||||||
video_output_close(context.video_queue);
|
video_output_close(context.video_queue);
|
||||||
|
@ -161,10 +169,14 @@ void preview_output_start()
|
||||||
|
|
||||||
obs_get_video_info(&context.ovi);
|
obs_get_video_info(&context.ovi);
|
||||||
|
|
||||||
uint32_t width = context.ovi.base_width;
|
const struct video_scale_info *const conversion =
|
||||||
uint32_t height = context.ovi.base_height;
|
obs_output_get_video_conversion(context.output);
|
||||||
|
const uint32_t width = conversion->width;
|
||||||
|
const uint32_t height = conversion->height;
|
||||||
|
|
||||||
obs_enter_graphics();
|
obs_enter_graphics();
|
||||||
|
context.texrender_premultiplied =
|
||||||
|
gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||||
context.texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
context.texrender = gs_texrender_create(GS_BGRA, GS_ZS_NONE);
|
||||||
for (gs_stagesurf_t *&surf : context.stagesurfaces)
|
for (gs_stagesurf_t *&surf : context.stagesurfaces)
|
||||||
surf = gs_stagesurface_create(width, height, GS_BGRA);
|
surf = gs_stagesurface_create(width, height, GS_BGRA);
|
||||||
|
@ -257,10 +269,17 @@ void render_preview_source(void *param, uint32_t cx, uint32_t cy)
|
||||||
if (!ctx->current_source)
|
if (!ctx->current_source)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
uint32_t width = obs_source_get_base_width(ctx->current_source);
|
const uint32_t width = obs_source_get_base_width(ctx->current_source);
|
||||||
uint32_t height = obs_source_get_base_height(ctx->current_source);
|
const uint32_t height = obs_source_get_base_height(ctx->current_source);
|
||||||
|
|
||||||
if (gs_texrender_begin(ctx->texrender, width, height)) {
|
const struct video_scale_info *const conversion =
|
||||||
|
obs_output_get_video_conversion(context.output);
|
||||||
|
const uint32_t scaled_width = conversion->width;
|
||||||
|
const uint32_t scaled_height = conversion->height;
|
||||||
|
|
||||||
|
gs_texrender_t *const texrender_premultiplied =
|
||||||
|
ctx->texrender_premultiplied;
|
||||||
|
if (gs_texrender_begin(texrender_premultiplied, width, height)) {
|
||||||
struct vec4 background;
|
struct vec4 background;
|
||||||
vec4_zero(&background);
|
vec4_zero(&background);
|
||||||
|
|
||||||
|
@ -274,7 +293,30 @@ void render_preview_source(void *param, uint32_t cx, uint32_t cy)
|
||||||
obs_source_video_render(ctx->current_source);
|
obs_source_video_render(ctx->current_source);
|
||||||
|
|
||||||
gs_blend_state_pop();
|
gs_blend_state_pop();
|
||||||
|
gs_texrender_end(texrender_premultiplied);
|
||||||
|
|
||||||
|
if (gs_texrender_begin(ctx->texrender, scaled_width,
|
||||||
|
scaled_height)) {
|
||||||
|
const bool previous = gs_framebuffer_srgb_enabled();
|
||||||
|
gs_enable_framebuffer_srgb(true);
|
||||||
|
gs_enable_blending(false);
|
||||||
|
|
||||||
|
gs_texture_t *const tex = gs_texrender_get_texture(
|
||||||
|
texrender_premultiplied);
|
||||||
|
gs_effect_t *const effect =
|
||||||
|
obs_get_base_effect(OBS_EFFECT_DEFAULT);
|
||||||
|
gs_effect_set_texture_srgb(
|
||||||
|
gs_effect_get_param_by_name(effect, "image"),
|
||||||
|
tex);
|
||||||
|
while (gs_effect_loop(effect, "DrawAlphaDivide")) {
|
||||||
|
gs_draw_sprite(tex, 0, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
gs_enable_blending(true);
|
||||||
|
gs_enable_framebuffer_srgb(previous);
|
||||||
|
|
||||||
gs_texrender_end(ctx->texrender);
|
gs_texrender_end(ctx->texrender);
|
||||||
|
}
|
||||||
|
|
||||||
const size_t write_stage_index = ctx->stage_index;
|
const size_t write_stage_index = ctx->stage_index;
|
||||||
gs_stage_texture(ctx->stagesurfaces[write_stage_index],
|
gs_stage_texture(ctx->stagesurfaces[write_stage_index],
|
||||||
|
@ -295,8 +337,8 @@ void render_preview_source(void *param, uint32_t cx, uint32_t cy)
|
||||||
&ctx->video_linesize)) {
|
&ctx->video_linesize)) {
|
||||||
uint32_t linesize =
|
uint32_t linesize =
|
||||||
output_frame.linesize[0];
|
output_frame.linesize[0];
|
||||||
for (uint32_t i = 0;
|
for (uint32_t i = 0; i < scaled_height;
|
||||||
i < ctx->ovi.base_height; i++) {
|
i++) {
|
||||||
uint32_t dst_offset =
|
uint32_t dst_offset =
|
||||||
linesize * i;
|
linesize * i;
|
||||||
uint32_t src_offset =
|
uint32_t src_offset =
|
||||||
|
|
|
@ -741,9 +741,10 @@ Functions used by outputs
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
.. function:: void obs_output_set_video_conversion(obs_output_t *output, const struct video_scale_info *conversion)
|
.. function:: void obs_output_set_video_conversion(obs_output_t *output, const struct video_scale_info *conversion)
|
||||||
|
const struct video_scale_info *obs_output_get_video_conversion(obs_output_t *output)
|
||||||
|
|
||||||
Optionally sets the video conversion information. Only used by raw
|
Optionally sets/gets the video conversion information. Only used by
|
||||||
outputs.
|
raw outputs.
|
||||||
|
|
||||||
Relevant data types used with this function:
|
Relevant data types used with this function:
|
||||||
|
|
||||||
|
|
|
@ -1099,8 +1099,8 @@ static inline bool has_scaling(const struct obs_output *output)
|
||||||
video_height != output->scaled_height);
|
video_height != output->scaled_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline struct video_scale_info *
|
const struct video_scale_info *
|
||||||
get_video_conversion(struct obs_output *output)
|
obs_output_get_video_conversion(struct obs_output *output)
|
||||||
{
|
{
|
||||||
if (output->video_conversion_set) {
|
if (output->video_conversion_set) {
|
||||||
if (!output->video_conversion.width)
|
if (!output->video_conversion.width)
|
||||||
|
@ -1991,7 +1991,7 @@ static void hook_data_capture(struct obs_output *output, bool encoded,
|
||||||
} else {
|
} else {
|
||||||
if (has_video)
|
if (has_video)
|
||||||
start_raw_video(output->video,
|
start_raw_video(output->video,
|
||||||
get_video_conversion(output),
|
obs_output_get_video_conversion(output),
|
||||||
default_raw_video_callback, output);
|
default_raw_video_callback, output);
|
||||||
if (has_audio)
|
if (has_audio)
|
||||||
start_raw_audio(output);
|
start_raw_audio(output);
|
||||||
|
|
|
@ -2230,6 +2230,10 @@ EXPORT const char *obs_get_output_supported_audio_codecs(const char *id);
|
||||||
|
|
||||||
EXPORT void *obs_output_get_type_data(obs_output_t *output);
|
EXPORT void *obs_output_get_type_data(obs_output_t *output);
|
||||||
|
|
||||||
|
/** Gets the video conversion info. Used only for raw output */
|
||||||
|
EXPORT const struct video_scale_info *
|
||||||
|
obs_output_get_video_conversion(obs_output_t *output);
|
||||||
|
|
||||||
/** Optionally sets the video conversion info. Used only for raw output */
|
/** Optionally sets the video conversion info. Used only for raw output */
|
||||||
EXPORT void
|
EXPORT void
|
||||||
obs_output_set_video_conversion(obs_output_t *output,
|
obs_output_set_video_conversion(obs_output_t *output,
|
||||||
|
|
|
@ -25,6 +25,22 @@ static void *decklink_output_create(obs_data_t *settings, obs_output_t *output)
|
||||||
decklinkOutput->modeID = obs_data_get_int(settings, MODE_ID);
|
decklinkOutput->modeID = obs_data_get_int(settings, MODE_ID);
|
||||||
decklinkOutput->keyerMode = (int)obs_data_get_int(settings, KEYER);
|
decklinkOutput->keyerMode = (int)obs_data_get_int(settings, KEYER);
|
||||||
|
|
||||||
|
ComPtr<DeckLinkDevice> device;
|
||||||
|
device.Set(deviceEnum->FindByHash(decklinkOutput->deviceHash));
|
||||||
|
if (device) {
|
||||||
|
DeckLinkDeviceMode *mode =
|
||||||
|
device->FindOutputMode(decklinkOutput->modeID);
|
||||||
|
|
||||||
|
struct video_scale_info to = {};
|
||||||
|
to.format = VIDEO_FORMAT_BGRA;
|
||||||
|
to.width = mode->GetWidth();
|
||||||
|
to.height = mode->GetHeight();
|
||||||
|
to.range = VIDEO_RANGE_FULL;
|
||||||
|
to.colorspace = VIDEO_CS_709;
|
||||||
|
|
||||||
|
obs_output_set_video_conversion(output, &to);
|
||||||
|
}
|
||||||
|
|
||||||
return decklinkOutput;
|
return decklinkOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,15 +96,6 @@ static bool decklink_output_start(void *data)
|
||||||
|
|
||||||
decklink->SetSize(mode->GetWidth(), mode->GetHeight());
|
decklink->SetSize(mode->GetWidth(), mode->GetHeight());
|
||||||
|
|
||||||
struct video_scale_info to = {};
|
|
||||||
to.format = VIDEO_FORMAT_BGRA;
|
|
||||||
to.width = mode->GetWidth();
|
|
||||||
to.height = mode->GetHeight();
|
|
||||||
to.range = VIDEO_RANGE_FULL;
|
|
||||||
to.colorspace = VIDEO_CS_709;
|
|
||||||
|
|
||||||
obs_output_set_video_conversion(decklink->GetOutput(), &to);
|
|
||||||
|
|
||||||
device->SetKeyerMode(decklink->keyerMode);
|
device->SetKeyerMode(decklink->keyerMode);
|
||||||
|
|
||||||
if (!decklink->Activate(device, decklink->modeID))
|
if (!decklink->Activate(device, decklink->modeID))
|
||||||
|
|
Loading…
Reference in a new issue