1
+ /* *************************************************************************/
2
+ /* camera_web.cpp */
3
+ /* *************************************************************************/
4
+ /* This file is part of: */
5
+ /* GODOT ENGINE */
6
+ /* https://godotengine.org */
7
+ /* *************************************************************************/
8
+ /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
+ /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
+ /* */
11
+ /* Permission is hereby granted, free of charge, to any person obtaining */
12
+ /* a copy of this software and associated documentation files (the */
13
+ /* "Software"), to deal in the Software without restriction, including */
14
+ /* without limitation the rights to use, copy, modify, merge, publish, */
15
+ /* distribute, sublicense, and/or sell copies of the Software, and to */
16
+ /* permit persons to whom the Software is furnished to do so, subject to */
17
+ /* the following conditions: */
18
+ /* */
19
+ /* The above copyright notice and this permission notice shall be */
20
+ /* included in all copies or substantial portions of the Software. */
21
+ /* */
22
+ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
+ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
+ /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
+ /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
+ /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
+ /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
+ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
+ /* *************************************************************************/
30
+
31
+ #include " camera_web.h"
32
+
33
+ #include " core/io/json.h"
34
+
35
+ void CameraFeedWeb::_on_get_pixeldata (void *context, const uint8_t *rawdata, const int length, const int p_width, const int p_height, const char *error) {
36
+ String error_json_str = String::utf8 (error);
37
+ if (!error_json_str.is_empty ()) {
38
+ Variant json_variant = JSON::parse_string (error_json_str);
39
+ if (json_variant.get_type () == Variant::DICTIONARY) {
40
+ Dictionary json_dict = json_variant;
41
+ String error_str = json_dict.get (KEY_ERROR, String ());
42
+ if (!error_str.is_empty ()) {
43
+ ERR_PRINT (vformat (" Camera feed error from JS: %s" , error_str));
44
+ }
45
+ } else {
46
+ ERR_PRINT (" Camera feed error: Failed to parse JSON response or response is not a Dictionary." );
47
+ }
48
+ }
49
+
50
+ CameraFeedWeb *feed = reinterpret_cast <CameraFeedWeb *>(context);
51
+ Vector<uint8_t > data = feed->data ;
52
+ Ref<Image> image = feed->image ;
53
+
54
+ if (length != data.size ()) {
55
+ int64_t size = Image::get_image_data_size (p_width, p_height, Image::FORMAT_RGBA8, false );
56
+ data.resize (length > size ? length : size);
57
+ }
58
+ memcpy (data.ptrw (), rawdata, length);
59
+
60
+ image->initialize_data (p_width, p_height, false , Image::FORMAT_RGBA8, data);
61
+ feed->set_rgb_image (image);
62
+ feed->emit_signal (SNAME (" frame_changed" ));
63
+ }
64
+
65
+ bool CameraFeedWeb::activate_feed () {
66
+ ERR_FAIL_COND_V_MSG (selected_format == -1 , false , " CameraFeed format needs to be set before activating." );
67
+ if (is_active ()) {
68
+ deactivate_feed ();
69
+ };
70
+
71
+ CameraFeed::FeedFormat f = formats[selected_format];
72
+ CameraDriverWeb::get_singleton ()->get_pixel_data (this , device_id, f.width , f.height , &_on_get_pixeldata);
73
+ return true ;
74
+ }
75
+
76
+ void CameraFeedWeb::deactivate_feed () {
77
+ CameraDriverWeb::get_singleton ()->stop_stream (device_id);
78
+ }
79
+
80
+ bool CameraFeedWeb::set_format (int p_index, const Dictionary &p_parameters) {
81
+ ERR_FAIL_COND_V_MSG (active, false , " Feed is active." );
82
+ ERR_FAIL_INDEX_V_MSG (p_index, formats.size (), false , " Invalid format index." );
83
+
84
+ selected_format = p_index;
85
+ return true ;
86
+ }
87
+
88
+ Array CameraFeedWeb::get_formats () const {
89
+ Array result;
90
+ for (const FeedFormat &feed_format : formats) {
91
+ Dictionary dictionary;
92
+ dictionary[" width" ] = feed_format.width ;
93
+ dictionary[" height" ] = feed_format.height ;
94
+ dictionary[" format" ] = feed_format.format ;
95
+ result.push_back (dictionary);
96
+ }
97
+ return result;
98
+ }
99
+
100
+ CameraFeed::FeedFormat CameraFeedWeb::get_format () const {
101
+ CameraFeed::FeedFormat feed_format = {};
102
+ return selected_format == -1 ? feed_format : formats[selected_format];
103
+ }
104
+
105
+ CameraFeedWeb::CameraFeedWeb (const CameraInfo &info) {
106
+ name = info.label ;
107
+ device_id = info.device_id ;
108
+
109
+ Vector<CapabilityInfo> capabilities;
110
+ CameraDriverWeb::get_singleton ()->get_capabilities (&capabilities, device_id);
111
+ for (int i = 0 ; i < capabilities.size (); i++) {
112
+ CapabilityInfo capability = capabilities[i];
113
+ FeedFormat feed_format;
114
+ feed_format.width = capability.width ;
115
+ feed_format.height = capability.height ;
116
+ feed_format.format = String (" RGBA" );
117
+ formats.append (feed_format);
118
+ }
119
+
120
+ image.instantiate ();
121
+ }
122
+
123
+ CameraFeedWeb::~CameraFeedWeb () {
124
+ if (is_active ()) {
125
+ deactivate_feed ();
126
+ }
127
+ }
128
+
129
+ void CameraWeb::_update_feeds () {
130
+ for (int i = feeds.size () - 1 ; i >= 0 ; i--) {
131
+ remove_feed (feeds[i]);
132
+ }
133
+
134
+ Vector<CameraInfo> camera_info;
135
+ camera_driver_web->get_cameras (&camera_info);
136
+ for (int i = 0 ; i < camera_info.size (); i++) {
137
+ CameraInfo info = camera_info[i];
138
+ Ref<CameraFeedWeb> feed = memnew (CameraFeedWeb (info));
139
+ add_feed (feed);
140
+ }
141
+ }
142
+
143
+ void CameraWeb::_cleanup () {
144
+ if (camera_driver_web != nullptr ) {
145
+ camera_driver_web->stop_stream ();
146
+ memdelete (camera_driver_web);
147
+ camera_driver_web = nullptr ;
148
+ }
149
+ }
150
+
151
+ void CameraWeb::set_monitoring_feeds (bool p_monitoring_feeds) {
152
+ if (p_monitoring_feeds == monitoring_feeds) {
153
+ return ;
154
+ }
155
+
156
+ CameraServer::set_monitoring_feeds (p_monitoring_feeds);
157
+ if (p_monitoring_feeds) {
158
+ if (camera_driver_web == nullptr ) {
159
+ camera_driver_web = new CameraDriverWeb ();
160
+ }
161
+ camera_driver_web->initialize_camera ();
162
+ _update_feeds ();
163
+ } else {
164
+ _cleanup ();
165
+ }
166
+ }
167
+
168
+ CameraWeb::~CameraWeb () {
169
+ _cleanup ();
170
+ }
0 commit comments