Skip to content

Commit 54a0a94

Browse files
committed
Merge pull request #109594 from j20001970/camera-feeds-deferred-frame-changed
Defer `format_changed` and `frame_changed` signal for all camera feeds
2 parents 17fb6e3 + 257176e commit 54a0a94

File tree

1 file changed

+21
-7
lines changed

1 file changed

+21
-7
lines changed

servers/camera/camera_feed.cpp

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -196,13 +196,17 @@ void CameraFeed::set_rgb_image(const Ref<Image> &p_rgb_img) {
196196
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_rgb_img);
197197
RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_RGBA_IMAGE], new_texture);
198198

199-
emit_signal(format_changed_signal_name);
199+
// Defer `format_changed` signals to ensure they are emitted on Godot's main thread.
200+
// This also makes sure the datatype of the feed is updated before the emission.
201+
call_deferred("emit_signal", format_changed_signal_name);
200202
} else {
201203
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_RGBA_IMAGE], p_rgb_img);
202204
}
203205

204206
datatype = CameraFeed::FEED_RGB;
205-
emit_signal(frame_changed_signal_name);
207+
// Most of the time the pixel data of camera devices comes from threads outside Godot.
208+
// Defer `frame_changed` signals to ensure they are emitted on Godot's main thread.
209+
call_deferred("emit_signal", frame_changed_signal_name);
206210
}
207211
}
208212

@@ -220,13 +224,17 @@ void CameraFeed::set_ycbcr_image(const Ref<Image> &p_ycbcr_img) {
220224
RID new_texture = RenderingServer::get_singleton()->texture_2d_create(p_ycbcr_img);
221225
RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_RGBA_IMAGE], new_texture);
222226

223-
emit_signal(format_changed_signal_name);
227+
// Defer `format_changed` signals to ensure they are emitted on Godot's main thread.
228+
// This also makes sure the datatype of the feed is updated before the emission.
229+
call_deferred("emit_signal", format_changed_signal_name);
224230
} else {
225231
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_RGBA_IMAGE], p_ycbcr_img);
226232
}
227233

228234
datatype = CameraFeed::FEED_YCBCR;
229-
emit_signal(frame_changed_signal_name);
235+
// Most of the time the pixel data of camera devices comes from threads outside Godot.
236+
// Defer `frame_changed` signals to ensure they are emitted on Godot's main thread.
237+
call_deferred("emit_signal", frame_changed_signal_name);
230238
}
231239
}
232240

@@ -254,14 +262,18 @@ void CameraFeed::set_ycbcr_images(const Ref<Image> &p_y_img, const Ref<Image> &p
254262
RenderingServer::get_singleton()->texture_replace(texture[CameraServer::FEED_CBCR_IMAGE], new_texture);
255263
}
256264

257-
emit_signal(format_changed_signal_name);
265+
// Defer `format_changed` signals to ensure they are emitted on Godot's main thread.
266+
// This also makes sure the datatype of the feed is updated before the emission.
267+
call_deferred("emit_signal", format_changed_signal_name);
258268
} else {
259269
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_Y_IMAGE], p_y_img);
260270
RenderingServer::get_singleton()->texture_2d_update(texture[CameraServer::FEED_CBCR_IMAGE], p_cbcr_img);
261271
}
262272

263273
datatype = CameraFeed::FEED_YCBCR_SEP;
264-
emit_signal(frame_changed_signal_name);
274+
// Most of the time the pixel data of camera devices comes from threads outside Godot.
275+
// Defer `frame_changed` signals to ensure they are emitted on Godot's main thread.
276+
call_deferred("emit_signal", frame_changed_signal_name);
265277
}
266278
}
267279

@@ -276,7 +288,9 @@ void CameraFeed::set_external(int p_width, int p_height) {
276288
}
277289

278290
datatype = CameraFeed::FEED_EXTERNAL;
279-
emit_signal(frame_changed_signal_name);
291+
// Most of the time the pixel data of camera devices comes from threads outside Godot.
292+
// Defer `frame_changed` signals to ensure they are emitted on Godot's main thread.
293+
call_deferred("emit_signal", frame_changed_signal_name);
280294
}
281295

282296
bool CameraFeed::activate_feed() {

0 commit comments

Comments
 (0)