diff --git a/doc/classes/CameraServer.xml b/doc/classes/CameraServer.xml
index f30edb1d361..c9a423efe62 100644
--- a/doc/classes/CameraServer.xml
+++ b/doc/classes/CameraServer.xml
@@ -45,6 +45,12 @@
+
+
+ If [code]true[/code], the server is actively monitoring available camera feeds.
+ This has a performance cost, so only set it to [code]true[/code] when you're actively accessing the camera.
+
+
diff --git a/modules/camera/camera_linux.cpp b/modules/camera/camera_linux.cpp
index a1b0b5b49e5..c95069442e0 100644
--- a/modules/camera/camera_linux.cpp
+++ b/modules/camera/camera_linux.cpp
@@ -162,11 +162,25 @@ bool CameraLinux::_can_query_format(int p_file_descriptor, int p_type) {
return ioctl(p_file_descriptor, VIDIOC_G_FMT, &format) != -1;
}
-CameraLinux::CameraLinux() {
- camera_thread.start(CameraLinux::camera_thread_func, this);
+inline void CameraLinux::set_monitoring_feeds(bool p_monitoring_feeds) {
+ if (p_monitoring_feeds == monitoring_feeds) {
+ return;
+ }
+
+ CameraServer::set_monitoring_feeds(p_monitoring_feeds);
+ if (p_monitoring_feeds) {
+ camera_thread.start(CameraLinux::camera_thread_func, this);
+ } else {
+ exit_flag.set();
+ if (camera_thread.is_started()) {
+ camera_thread.wait_to_finish();
+ }
+ }
}
CameraLinux::~CameraLinux() {
exit_flag.set();
- camera_thread.wait_to_finish();
+ if (camera_thread.is_started()) {
+ camera_thread.wait_to_finish();
+ }
}
diff --git a/modules/camera/camera_linux.h b/modules/camera/camera_linux.h
index 4b362eb5d80..10710943900 100644
--- a/modules/camera/camera_linux.h
+++ b/modules/camera/camera_linux.h
@@ -52,6 +52,8 @@ private:
bool _can_query_format(int p_file_descriptor, int p_type);
public:
- CameraLinux();
+ CameraLinux() = default;
~CameraLinux();
+
+ void set_monitoring_feeds(bool p_monitoring_feeds) override;
};
diff --git a/modules/camera/camera_macos.h b/modules/camera/camera_macos.h
index ba9723a99b8..1b0ad294e6b 100644
--- a/modules/camera/camera_macos.h
+++ b/modules/camera/camera_macos.h
@@ -37,7 +37,8 @@
class CameraMacOS : public CameraServer {
public:
- CameraMacOS();
+ CameraMacOS() = default;
void update_feeds();
+ void set_monitoring_feeds(bool p_monitoring_feeds) override;
};
diff --git a/modules/camera/camera_macos.mm b/modules/camera/camera_macos.mm
index 3d0e08045bf..87e3d397b0b 100644
--- a/modules/camera/camera_macos.mm
+++ b/modules/camera/camera_macos.mm
@@ -359,10 +359,20 @@ void CameraMacOS::update_feeds() {
};
}
-CameraMacOS::CameraMacOS() {
- // Find available cameras we have at this time
- update_feeds();
+void CameraMacOS::set_monitoring_feeds(bool p_monitoring_feeds) {
+ if (p_monitoring_feeds == monitoring_feeds) {
+ return;
+ }
- // should only have one of these....
- device_notifications = [[MyDeviceNotifications alloc] initForServer:this];
+ CameraServer::set_monitoring_feeds(p_monitoring_feeds);
+ if (p_monitoring_feeds) {
+ // Find available cameras we have at this time.
+ update_feeds();
+
+ // Get notified on feed changes.
+ device_notifications = [[MyDeviceNotifications alloc] initForServer:this];
+ } else {
+ // Stop monitoring feed changes.
+ device_notifications = nil;
+ }
}
diff --git a/servers/camera_server.cpp b/servers/camera_server.cpp
index b78a0c44e75..3d01399a84e 100644
--- a/servers/camera_server.cpp
+++ b/servers/camera_server.cpp
@@ -39,6 +39,10 @@
CameraServer::CreateFunc CameraServer::create_func = nullptr;
void CameraServer::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_monitoring_feeds", "is_monitoring_feeds"), &CameraServer::set_monitoring_feeds);
+ ClassDB::bind_method(D_METHOD("is_monitoring_feeds"), &CameraServer::is_monitoring_feeds);
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "monitoring_feeds"), "set_monitoring_feeds", "is_monitoring_feeds");
+
ClassDB::bind_method(D_METHOD("get_feed", "index"), &CameraServer::get_feed);
ClassDB::bind_method(D_METHOD("get_feed_count"), &CameraServer::get_feed_count);
ClassDB::bind_method(D_METHOD("feeds"), &CameraServer::get_feeds);
@@ -61,6 +65,10 @@ CameraServer *CameraServer::get_singleton() {
return singleton;
}
+void CameraServer::set_monitoring_feeds(bool p_monitoring_feeds) {
+ monitoring_feeds = p_monitoring_feeds;
+}
+
int CameraServer::get_free_id() {
bool id_exists = true;
int newid = 0;
@@ -80,6 +88,8 @@ int CameraServer::get_free_id() {
}
int CameraServer::get_feed_index(int p_id) {
+ ERR_FAIL_COND_V_MSG(!monitoring_feeds, -1, "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
+
for (int i = 0; i < feeds.size(); i++) {
if (feeds[i]->get_id() == p_id) {
return i;
@@ -90,6 +100,8 @@ int CameraServer::get_feed_index(int p_id) {
}
Ref CameraServer::get_feed_by_id(int p_id) {
+ ERR_FAIL_COND_V_MSG(!monitoring_feeds, nullptr, "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
+
int index = get_feed_index(p_id);
if (index == -1) {
@@ -129,16 +141,19 @@ void CameraServer::remove_feed(const Ref &p_feed) {
}
Ref CameraServer::get_feed(int p_index) {
+ ERR_FAIL_COND_V_MSG(!monitoring_feeds, nullptr, "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
ERR_FAIL_INDEX_V(p_index, feeds.size(), nullptr);
return feeds[p_index];
}
int CameraServer::get_feed_count() {
+ ERR_FAIL_COND_V_MSG(!monitoring_feeds, 0, "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
return feeds.size();
}
TypedArray CameraServer::get_feeds() {
+ ERR_FAIL_COND_V_MSG(!monitoring_feeds, {}, "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
TypedArray return_feeds;
int cc = get_feed_count();
return_feeds.resize(cc);
@@ -151,6 +166,7 @@ TypedArray CameraServer::get_feeds() {
}
RID CameraServer::feed_texture(int p_id, CameraServer::FeedImage p_texture) {
+ ERR_FAIL_COND_V_MSG(!monitoring_feeds, RID(), "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
int index = get_feed_index(p_id);
ERR_FAIL_COND_V(index == -1, RID());
diff --git a/servers/camera_server.h b/servers/camera_server.h
index 406d7b6aadb..bb34229dade 100644
--- a/servers/camera_server.h
+++ b/servers/camera_server.h
@@ -64,6 +64,7 @@ private:
protected:
static CreateFunc create_func;
+ bool monitoring_feeds = false;
Vector[> feeds;
static CameraServer *singleton;
@@ -88,6 +89,9 @@ public:
return server;
}
+ virtual void set_monitoring_feeds(bool p_monitoring_feeds);
+ _FORCE_INLINE_ bool is_monitoring_feeds() const { return monitoring_feeds; }
+
// Right now we identify our feed by it's ID when it's used in the background.
// May see if we can change this to purely relying on CameraFeed objects or by name.
int get_free_id();
]