Parcourir la source

Deactivate the `CameraServer` by default.
Add `monitoring_feeds` property to `CameraServer`.
This saves resources for games that don't use a physical camera.

Lukas Tenbrink il y a 4 mois
Parent
commit
54685c3037

+ 6 - 0
doc/classes/CameraServer.xml

@@ -45,6 +45,12 @@
 			</description>
 		</method>
 	</methods>
+	<members>
+		<member name="monitoring_feeds" type="bool" setter="set_monitoring_feeds" getter="is_monitoring_feeds" default="false">
+			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.
+		</member>
+	</members>
 	<signals>
 		<signal name="camera_feed_added">
 			<param index="0" name="id" type="int" />

+ 17 - 3
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();
+	}
 }

+ 3 - 1
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;
 };

+ 2 - 1
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;
 };

+ 15 - 5
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;
+	}
+
+	CameraServer::set_monitoring_feeds(p_monitoring_feeds);
+	if (p_monitoring_feeds) {
+		// Find available cameras we have at this time.
+		update_feeds();
 
-	// should only have one of these....
-	device_notifications = [[MyDeviceNotifications alloc] initForServer:this];
+		// Get notified on feed changes.
+		device_notifications = [[MyDeviceNotifications alloc] initForServer:this];
+	} else {
+		// Stop monitoring feed changes.
+		device_notifications = nil;
+	}
 }

+ 16 - 0
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<CameraFeed> 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<CameraFeed> &p_feed) {
 }
 
 Ref<CameraFeed> 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<CameraFeed> CameraServer::get_feeds() {
+	ERR_FAIL_COND_V_MSG(!monitoring_feeds, {}, "CameraServer is not actively monitoring feeds; call set_monitoring_feeds(true) first.");
 	TypedArray<CameraFeed> return_feeds;
 	int cc = get_feed_count();
 	return_feeds.resize(cc);
@@ -151,6 +166,7 @@ TypedArray<CameraFeed> 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());
 

+ 4 - 0
servers/camera_server.h

@@ -64,6 +64,7 @@ private:
 protected:
 	static CreateFunc create_func;
 
+	bool monitoring_feeds = false;
 	Vector<Ref<CameraFeed>> 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();