Skip to content

Commit d203cd0

Browse files
Fix video mix canvas identity (#720)
* Refined canvases identity. Fixed enhanced broadcasting rendering * Created obs_set_video_render_context helper * Removed the old canvas-only render-context API * Minor comment update * Sync aux mix fps with main canvas
1 parent c8e9cc2 commit d203cd0

8 files changed

Lines changed: 102 additions & 86 deletions

File tree

libobs/media-io/audio-io.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ static void do_audio_output(struct audio_output *audio, size_t mix_idx,
146146

147147
struct obs_encoder *encoder = input->param;
148148
if (encoder && encoder->video &&
149-
encoder->video->ovi != obs_get_audio_rendering_canvas()) {
149+
encoder->video->canvas_ovi != obs_get_audio_rendering_canvas()) {
150150
continue;
151151
}
152152
float(*buf)[AUDIO_OUTPUT_FRAMES] =

libobs/obs-encoder.c

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,12 @@ static void maybe_set_up_gpu_rescale(struct obs_encoder *encoder)
241241
const struct video_output_info *voi = video_output_get_info(current->video);
242242
if (current_mix->view != current->view)
243243
continue;
244+
if (current_mix->canvas_ovi != current->canvas_ovi)
245+
continue;
246+
if (current_mix->rendering_mode != current->rendering_mode)
247+
continue;
244248

245-
if (current->ovi->scale_type != encoder->gpu_scale_type)
249+
if (current->ovi.scale_type != encoder->gpu_scale_type)
246250
continue;
247251

248252
if (voi->width != width || voi->height != height)
@@ -262,26 +266,27 @@ static void maybe_set_up_gpu_rescale(struct obs_encoder *encoder)
262266
if (!create_mix)
263267
return;
264268

265-
struct obs_video_info *ovi = bzalloc(sizeof(struct obs_video_info));
266-
*ovi = *current_mix->ovi;
269+
struct obs_video_info ovi = current_mix->ovi;
267270

268-
ovi->output_format = format;
269-
ovi->colorspace = space;
270-
ovi->range = range;
271+
ovi.output_format = format;
272+
ovi.colorspace = space;
273+
ovi.range = range;
271274

272-
ovi->output_height = height;
273-
ovi->output_width = width;
274-
ovi->scale_type = encoder->gpu_scale_type;
275+
ovi.output_height = height;
276+
ovi.output_width = width;
277+
ovi.scale_type = encoder->gpu_scale_type;
275278

276-
ovi->gpu_conversion = true;
279+
ovi.gpu_conversion = true;
277280

278-
mix = obs_create_video_mix(ovi);
281+
mix = obs_create_video_mix(&ovi);
279282
if (!mix)
280283
return;
281284

282285
mix->encoder_only_mix = true;
283286
mix->encoder_refs = 1;
287+
mix->canvas_ovi = current_mix->canvas_ovi;
284288
mix->view = current_mix->view;
289+
mix->rendering_mode = current_mix->rendering_mode;
285290

286291
pthread_mutex_lock(&obs->video.mixes_mutex);
287292

@@ -291,8 +296,12 @@ static void maybe_set_up_gpu_rescale(struct obs_encoder *encoder)
291296
const struct video_output_info *voi = video_output_get_info(current->video);
292297
if (current->view != current_mix->view)
293298
continue;
299+
if (current->canvas_ovi != current_mix->canvas_ovi)
300+
continue;
301+
if (current->rendering_mode != current_mix->rendering_mode)
302+
continue;
294303

295-
if (current->ovi->scale_type != encoder->gpu_scale_type)
304+
if (current->ovi.scale_type != encoder->gpu_scale_type)
296305
continue;
297306

298307
if (voi->width != width || voi->height != height)
@@ -301,6 +310,7 @@ static void maybe_set_up_gpu_rescale(struct obs_encoder *encoder)
301310
if (voi->format != format || voi->colorspace != space || voi->range != range)
302311
continue;
303312

313+
current->encoder_refs += 1;
304314
obs_encoder_set_video(encoder, current->video);
305315
create_mix = false;
306316
break;

libobs/obs-internal.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,8 @@ struct obs_core_video_mix {
316316
bool gpu_want_destroy_thread;
317317

318318
video_t *video;
319-
struct obs_video_info *ovi;
319+
struct obs_video_info ovi; /* Mix-local render settings. */
320+
struct obs_video_info *canvas_ovi; /* Stable public canvas identity for lookups/routing. */
320321
enum obs_video_rendering_mode rendering_mode;
321322

322323
bool gpu_conversion;
@@ -394,7 +395,7 @@ struct audio_monitor;
394395

395396
struct obs_core_audio {
396397
audio_t *audio;
397-
/* These 3 values are not present in the original OBS code. They serve as a main audio parameters cache,
398+
/* These 3 values are not present in the original OBS code. They serve as a main audio parameters cache,
398399
* allowing audio processing to finish the current iteration even if the global audio object has been destroyed. */
399400
uint32_t samples_per_sec;
400401
enum speaker_layout speakers;
@@ -533,7 +534,11 @@ struct obs_core {
533534
enum obs_replay_buffer_rendering_mode replay_buffer_rendering_mode;
534535
enum obs_video_rendering_mode video_rendering_mode;
535536
enum obs_audio_rendering_mode audio_rendering_mode;
536-
struct obs_video_info *video_rendering_canvas;
537+
538+
/* Active mix for the current video render pass. */
539+
struct obs_core_video_mix *video_rendering_mix;
540+
541+
/* Canvas identity for the current audio render context. */
537542
struct obs_video_info *audio_rendering_canvas;
538543

539544
os_task_queue_t *destruction_task_thread;
@@ -570,6 +575,8 @@ extern void cache_multiple_rendering(void);
570575
extern bool get_cached_multiple_rendering(void);
571576

572577
extern struct obs_core_video_mix *get_mix_for_video(video_t *video);
578+
/* Use to set the active video render context for the current render pass. */
579+
extern void obs_set_video_render_context(struct obs_core_video_mix *mix);
573580

574581
extern void start_raw_video(video_t *video, const struct video_scale_info *conversion, uint32_t frame_rate_divisor,
575582
void (*callback)(void *param, struct video_data *frame), void *param);

libobs/obs-scene.c

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -347,8 +347,8 @@ static inline void get_scene_dimensions(const obs_sceneitem_t *item, float *x, f
347347
{
348348
obs_scene_t *parent = item->parent;
349349
if (!parent || (parent->is_group && !parent->source->canvas)) {
350-
*x = (float)obs->data.main_canvas->mix->ovi->base_width;
351-
*y = (float)obs->data.main_canvas->mix->ovi->base_height;
350+
*x = (float)obs->data.main_canvas->mix->ovi.base_width;
351+
*y = (float)obs->data.main_canvas->mix->ovi.base_height;
352352
} else if (parent->is_group) {
353353
*x = (float)canvas_getwidth(parent->source->canvas);
354354
*y = (float)canvas_getheight(parent->source->canvas);
@@ -620,17 +620,8 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
620620
/* Reset bounds crop */
621621
memset(&item->bounds_crop, 0, sizeof(item->bounds_crop));
622622

623-
// TODO: this code seems to do nothing and can be safely removed
624-
// struct obs_video_info *saved_canvas = NULL;
625-
// if (item->canvas) {
626-
// saved_canvas = obs_get_video_rendering_canvas();
627-
// obs_set_video_rendering_canvas(item->canvas);
628-
// }
629623
width = obs_source_get_width(item->source);
630624
height = obs_source_get_height(item->source);
631-
// if (saved_canvas)
632-
// obs_set_video_rendering_canvas(saved_canvas);
633-
634625

635626
/* Adjust crop on nested scenes (if any) */
636627
if (update_tex && item->is_scene)
@@ -1086,10 +1077,12 @@ static void scene_video_render(void *data, gs_effect_t *effect)
10861077
gs_blend_state_push();
10871078
gs_reset_blend_state();
10881079

1080+
struct obs_video_info *render_canvas = obs && obs->video_rendering_mix
1081+
? obs->video_rendering_mix->canvas_ovi
1082+
: NULL;
10891083
item = scene->first_item;
10901084
while (item) {
1091-
if (obs_get_video_rendering_canvas() != item->canvas &&
1092-
item->canvas != NULL) {
1085+
if (render_canvas != item->canvas && item->canvas != NULL) {
10931086
item = item->next;
10941087
continue;
10951088
}

libobs/obs-video.c

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,8 @@ static inline bool can_reuse_mix_texture(const struct obs_core_video_mix *mix, s
141141
continue;
142142
if (other->render_space != mix->render_space)
143143
continue;
144-
if (other->ovi->base_width != mix->ovi->base_width ||
145-
other->ovi->base_height != mix->ovi->base_height)
144+
if (other->ovi.base_width != mix->ovi.base_width ||
145+
other->ovi.base_height != mix->ovi.base_height)
146146
continue;
147147
if (!other->texture_rendered)
148148
continue;
@@ -179,15 +179,13 @@ static inline void render_main_texture(struct obs_core_video_mix *video)
179179
gs_set_render_target_with_color_space(video->render_texture, NULL, video->render_space);
180180
gs_clear(GS_CLEAR_COLOR, &clear_color, 1.0f, 0);
181181

182-
set_render_size(video->ovi->base_width, video->ovi->base_height);
182+
set_render_size(video->ovi.base_width, video->ovi.base_height);
183183

184184
pthread_mutex_lock(&obs->data.draw_callbacks_mutex);
185185

186186
for (size_t i = obs->data.draw_callbacks.num; i > 0; i--) {
187-
struct draw_callback *const callback =
188-
obs->data.draw_callbacks.array + (i - 1);
189-
callback->draw(callback->param, video->ovi->base_width,
190-
video->ovi->base_height);
187+
struct draw_callback *const callback = obs->data.draw_callbacks.array + (i - 1);
188+
callback->draw(callback->param, video->ovi.base_width, video->ovi.base_height);
191189
}
192190

193191
pthread_mutex_unlock(&obs->data.draw_callbacks_mutex);
@@ -224,12 +222,12 @@ static inline gs_effect_t *get_scale_effect_internal(struct obs_core_video_mix *
224222
/* if the dimension is under half the size of the original image,
225223
* bicubic/lanczos can't sample enough pixels to create an accurate
226224
* image, so use the bilinear low resolution effect instead */
227-
if (info->width < (mix->ovi->base_width / 2) &&
228-
info->height < (mix->ovi->base_height / 2)) {
225+
if (info->width < (mix->ovi.base_width / 2) &&
226+
info->height < (mix->ovi.base_height / 2)) {
229227
return video->bilinear_lowres_effect;
230228
}
231229

232-
switch (mix->ovi->scale_type) {
230+
switch (mix->ovi.scale_type) {
233231
case OBS_SCALE_BILINEAR:
234232
return video->default_effect;
235233
case OBS_SCALE_LANCZOS:
@@ -246,8 +244,8 @@ static inline gs_effect_t *get_scale_effect_internal(struct obs_core_video_mix *
246244
static inline bool resolution_close(struct obs_core_video_mix *video,
247245
uint32_t width, uint32_t height)
248246
{
249-
long width_cmp = (long)video->ovi->base_width - (long)width;
250-
long height_cmp = (long)video->ovi->base_height - (long)height;
247+
long width_cmp = (long)video->ovi.base_width - (long)width;
248+
long height_cmp = (long)video->ovi.base_height - (long)height;
251249

252250
return labs(width_cmp) <= 16 && labs(height_cmp) <= 16;
253251
}
@@ -276,8 +274,7 @@ static gs_texture_t *render_output_texture(struct obs_core_video_mix *mix)
276274
uint32_t width = gs_texture_get_width(target);
277275
uint32_t height = gs_texture_get_height(target);
278276

279-
if ((width == mix->ovi->base_width) &&
280-
(height == mix->ovi->base_height))
277+
if ((width == mix->ovi.base_width) && (height == mix->ovi.base_height))
281278
return texture;
282279

283280
profile_start(render_output_texture_name);
@@ -295,15 +292,13 @@ static gs_texture_t *render_output_texture(struct obs_core_video_mix *mix)
295292

296293
if (bres) {
297294
struct vec2 base;
298-
vec2_set(&base, (float)mix->ovi->base_width,
299-
(float)mix->ovi->base_height);
295+
vec2_set(&base, (float)mix->ovi.base_width, (float)mix->ovi.base_height);
300296
gs_effect_set_vec2(bres, &base);
301297
}
302298

303299
if (bres_i) {
304300
struct vec2 base_i;
305-
vec2_set(&base_i, 1.0f / (float)mix->ovi->base_width,
306-
1.0f / (float)mix->ovi->base_height);
301+
vec2_set(&base_i, 1.0f / (float)mix->ovi.base_width, 1.0f / (float)mix->ovi.base_height);
307302
gs_effect_set_vec2(bres_i, &base_i);
308303
}
309304

@@ -883,7 +878,7 @@ static inline void output_frame(struct obs_core_video_mix *video)
883878
else
884879
return;
885880

886-
obs_set_video_rendering_canvas(video->ovi);
881+
obs_set_video_render_context(video);
887882

888883
const bool raw_active = video->raw_was_active;
889884
const bool gpu_active = video->gpu_was_active;

libobs/obs-view.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ void obs_view_render(obs_view_t *view)
143143
static inline size_t find_mix_for_view(obs_view_t *view)
144144
{
145145
for (size_t i = 0, num = obs->video.mixes.num; i < num; i++) {
146-
if (obs->video.mixes.array[i]->view == view)
146+
if (obs->video.mixes.array[i]->view == view &&
147+
!obs->video.mixes.array[i]->encoder_only_mix)
147148
return i;
148149
}
149150

@@ -154,7 +155,7 @@ video_t *obs_view_add(obs_view_t *view)
154155
{
155156
if (!obs->data.main_canvas->mix)
156157
return NULL;
157-
return obs_view_add2(view, obs->data.main_canvas->mix->ovi);
158+
return obs_view_add2(view, obs->data.main_canvas->mix->canvas_ovi);
158159
}
159160

160161
video_t *obs_view_add2(obs_view_t *view, struct obs_video_info *ovi)
@@ -239,7 +240,9 @@ void obs_view_enum_video_info(obs_view_t *view, bool (*enum_proc)(void *, struct
239240
struct obs_core_video_mix *mix = obs->video.mixes.array[i];
240241
if (mix->view != view)
241242
continue;
242-
if (!enum_proc(param, mix->ovi))
243+
if (mix->encoder_only_mix)
244+
continue;
245+
if (!enum_proc(param, mix->canvas_ovi))
243246
break;
244247
}
245248

@@ -255,7 +258,7 @@ bool obs_view_get_video_info(obs_view_t *view, struct obs_video_info *ovi)
255258

256259
size_t idx = find_mix_for_view(view);
257260
if (idx != DARRAY_INVALID) {
258-
*ovi = *(obs->video.mixes.array[idx]->ovi);
261+
*ovi = obs->video.mixes.array[idx]->ovi;
259262
pthread_mutex_unlock(&obs->video.mixes_mutex);
260263
return true;
261264
}

0 commit comments

Comments
 (0)