camera_android.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696
  1. /**************************************************************************/
  2. /* camera_android.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. #include "camera_android.h"
  31. #include "core/os/os.h"
  32. #include "platform/android/display_server_android.h"
  33. #include "platform/android/java_godot_io_wrapper.h"
  34. #include "platform/android/os_android.h"
  35. //////////////////////////////////////////////////////////////////////////
  36. // Helper functions
  37. //
  38. // The following code enables you to view the contents of a media type while
  39. // debugging.
  40. #ifndef IF_EQUAL_RETURN
  41. #define MAKE_FORMAT_CONST(suffix) AIMAGE_FORMAT_##suffix
  42. #define IF_EQUAL_RETURN(param, val) \
  43. if (MAKE_FORMAT_CONST(val) == param) \
  44. return #val
  45. #endif
  46. String GetFormatName(const int32_t &format) {
  47. IF_EQUAL_RETURN(format, YUV_420_888);
  48. IF_EQUAL_RETURN(format, RGB_888);
  49. IF_EQUAL_RETURN(format, RGBA_8888);
  50. return "Unsupported";
  51. }
  52. //////////////////////////////////////////////////////////////////////////
  53. // CameraFeedAndroid - Subclass for our camera feed on Android
  54. CameraFeedAndroid::CameraFeedAndroid(ACameraManager *manager, ACameraMetadata *metadata, const char *id,
  55. CameraFeed::FeedPosition position, int32_t orientation) :
  56. CameraFeed() {
  57. this->manager = manager;
  58. this->metadata = metadata;
  59. this->orientation = orientation;
  60. _add_formats();
  61. camera_id = id;
  62. set_position(position);
  63. // Position
  64. switch (position) {
  65. case CameraFeed::FEED_BACK:
  66. name = vformat("%s | BACK", id);
  67. break;
  68. case CameraFeed::FEED_FRONT:
  69. name = vformat("%s | FRONT", id);
  70. break;
  71. default:
  72. name = vformat("%s", id);
  73. break;
  74. }
  75. image_y.instantiate();
  76. image_uv.instantiate();
  77. }
  78. CameraFeedAndroid::~CameraFeedAndroid() {
  79. if (is_active()) {
  80. deactivate_feed();
  81. }
  82. if (metadata != nullptr) {
  83. ACameraMetadata_free(metadata);
  84. }
  85. }
  86. void CameraFeedAndroid::refresh_camera_metadata() {
  87. ERR_FAIL_NULL_MSG(manager, vformat("Camera %s: Cannot refresh metadata, manager is null.", camera_id));
  88. if (metadata != nullptr) {
  89. ACameraMetadata_free(metadata);
  90. metadata = nullptr;
  91. }
  92. camera_status_t status = ACameraManager_getCameraCharacteristics(manager, camera_id.utf8().get_data(), &metadata);
  93. if (status != ACAMERA_OK || metadata == nullptr) {
  94. ERR_FAIL_MSG(vformat("Camera %s: Failed to refresh metadata (status: %d).", camera_id, status));
  95. }
  96. ACameraMetadata_const_entry orientation_entry;
  97. status = ACameraMetadata_getConstEntry(metadata, ACAMERA_SENSOR_ORIENTATION, &orientation_entry);
  98. if (status == ACAMERA_OK) {
  99. orientation = orientation_entry.data.i32[0];
  100. print_verbose(vformat("Camera %s: Orientation updated to %d.", camera_id, orientation));
  101. } else {
  102. ERR_PRINT(vformat("Camera %s: Failed to get sensor orientation after refresh (status: %d).", camera_id, status));
  103. }
  104. formats.clear();
  105. _add_formats();
  106. print_verbose(vformat("Camera %s: Metadata refreshed successfully.", camera_id));
  107. }
  108. void CameraFeedAndroid::_set_rotation() {
  109. if (!metadata) {
  110. print_verbose(vformat("Camera %s: Metadata is null in _set_rotation, attempting refresh.", camera_id));
  111. refresh_camera_metadata();
  112. }
  113. float image_rotation = 0.0f;
  114. std::optional<int> result;
  115. if (metadata) {
  116. CameraRotationParams params;
  117. params.sensor_orientation = orientation;
  118. params.camera_facing = (position == CameraFeed::FEED_FRONT) ? CameraFacing::FRONT : CameraFacing::BACK;
  119. params.display_rotation = get_app_orientation();
  120. result = calculate_rotation(params);
  121. } else {
  122. ERR_PRINT(vformat("Camera %s: Cannot update rotation, metadata unavailable after refresh, using fallback.", camera_id));
  123. }
  124. if (result.has_value()) {
  125. image_rotation = static_cast<float>(result.value());
  126. } else {
  127. int display_rotation = DisplayServerAndroid::get_singleton()->get_display_rotation();
  128. switch (display_rotation) {
  129. case 90:
  130. display_rotation = 270;
  131. break;
  132. case 270:
  133. display_rotation = 90;
  134. break;
  135. default:
  136. break;
  137. }
  138. int sign = position == CameraFeed::FEED_FRONT ? 1 : -1;
  139. image_rotation = (orientation - display_rotation * sign + 360) % 360;
  140. }
  141. transform = Transform2D();
  142. transform = transform.rotated(Math::deg_to_rad(image_rotation));
  143. }
  144. void CameraFeedAndroid::_add_formats() {
  145. // Get supported formats
  146. ACameraMetadata_const_entry formats;
  147. camera_status_t status = ACameraMetadata_getConstEntry(metadata, ACAMERA_SCALER_AVAILABLE_STREAM_CONFIGURATIONS, &formats);
  148. if (status == ACAMERA_OK) {
  149. for (uint32_t f = 0; f < formats.count; f += 4) {
  150. // Only support output streams
  151. int32_t input = formats.data.i32[f + 3];
  152. if (input) {
  153. continue;
  154. }
  155. // Get format and resolution
  156. int32_t format = formats.data.i32[f + 0];
  157. if (format == AIMAGE_FORMAT_YUV_420_888 ||
  158. format == AIMAGE_FORMAT_RGBA_8888 ||
  159. format == AIMAGE_FORMAT_RGB_888) {
  160. CameraFeed::FeedFormat feed_format;
  161. feed_format.width = formats.data.i32[f + 1];
  162. feed_format.height = formats.data.i32[f + 2];
  163. feed_format.format = GetFormatName(format);
  164. feed_format.pixel_format = format;
  165. this->formats.append(feed_format);
  166. }
  167. }
  168. }
  169. }
  170. bool CameraFeedAndroid::activate_feed() {
  171. ERR_FAIL_COND_V_MSG(formats.is_empty(), false, "No camera formats available.");
  172. ERR_FAIL_INDEX_V_MSG(selected_format, formats.size(), false,
  173. vformat("CameraFeed format needs to be set before activating. Selected format index: %d (formats size: %d)", selected_format, formats.size()));
  174. if (is_active()) {
  175. deactivate_feed();
  176. };
  177. // Request permission
  178. if (!OS::get_singleton()->request_permission("CAMERA")) {
  179. return false;
  180. }
  181. // Open device
  182. static ACameraDevice_stateCallbacks deviceCallbacks = {
  183. .context = this,
  184. .onDisconnected = onDisconnected,
  185. .onError = onError,
  186. };
  187. camera_status_t c_status = ACameraManager_openCamera(manager, camera_id.utf8().get_data(), &deviceCallbacks, &device);
  188. if (c_status != ACAMERA_OK) {
  189. onError(this, device, c_status);
  190. return false;
  191. }
  192. // Create image reader
  193. const FeedFormat &feed_format = formats[selected_format];
  194. media_status_t m_status = AImageReader_new(feed_format.width, feed_format.height, feed_format.pixel_format, 1, &reader);
  195. if (m_status != AMEDIA_OK) {
  196. onError(this, device, m_status);
  197. return false;
  198. }
  199. // Get image listener
  200. static AImageReader_ImageListener listener{
  201. .context = this,
  202. .onImageAvailable = onImage,
  203. };
  204. m_status = AImageReader_setImageListener(reader, &listener);
  205. if (m_status != AMEDIA_OK) {
  206. onError(this, device, m_status);
  207. return false;
  208. }
  209. // Get image surface
  210. ANativeWindow *surface;
  211. m_status = AImageReader_getWindow(reader, &surface);
  212. if (m_status != AMEDIA_OK) {
  213. onError(this, device, m_status);
  214. return false;
  215. }
  216. // Prepare session outputs
  217. ACaptureSessionOutput *output = nullptr;
  218. c_status = ACaptureSessionOutput_create(surface, &output);
  219. if (c_status != ACAMERA_OK) {
  220. onError(this, device, c_status);
  221. return false;
  222. }
  223. ACaptureSessionOutputContainer *outputs = nullptr;
  224. c_status = ACaptureSessionOutputContainer_create(&outputs);
  225. if (c_status != ACAMERA_OK) {
  226. onError(this, device, c_status);
  227. return false;
  228. }
  229. c_status = ACaptureSessionOutputContainer_add(outputs, output);
  230. if (c_status != ACAMERA_OK) {
  231. onError(this, device, c_status);
  232. return false;
  233. }
  234. // Create capture session
  235. static ACameraCaptureSession_stateCallbacks sessionStateCallbacks{
  236. .context = this,
  237. .onClosed = onSessionClosed,
  238. .onReady = onSessionReady,
  239. .onActive = onSessionActive
  240. };
  241. c_status = ACameraDevice_createCaptureSession(device, outputs, &sessionStateCallbacks, &session);
  242. if (c_status != ACAMERA_OK) {
  243. onError(this, device, c_status);
  244. return false;
  245. }
  246. // Create capture request
  247. c_status = ACameraDevice_createCaptureRequest(device, TEMPLATE_PREVIEW, &request);
  248. if (c_status != ACAMERA_OK) {
  249. onError(this, device, c_status);
  250. return false;
  251. }
  252. // Set capture target
  253. ACameraOutputTarget *imageTarget = nullptr;
  254. c_status = ACameraOutputTarget_create(surface, &imageTarget);
  255. if (c_status != ACAMERA_OK) {
  256. onError(this, device, c_status);
  257. return false;
  258. }
  259. c_status = ACaptureRequest_addTarget(request, imageTarget);
  260. if (c_status != ACAMERA_OK) {
  261. onError(this, device, c_status);
  262. return false;
  263. }
  264. // Start capture
  265. c_status = ACameraCaptureSession_setRepeatingRequest(session, nullptr, 1, &request, nullptr);
  266. if (c_status != ACAMERA_OK) {
  267. onError(this, device, c_status);
  268. return false;
  269. }
  270. return true;
  271. }
  272. bool CameraFeedAndroid::set_format(int p_index, const Dictionary &p_parameters) {
  273. ERR_FAIL_COND_V_MSG(active, false, "Feed is active.");
  274. ERR_FAIL_INDEX_V_MSG(p_index, formats.size(), false, "Invalid format index.");
  275. selected_format = p_index;
  276. return true;
  277. }
  278. Array CameraFeedAndroid::get_formats() const {
  279. Array result;
  280. for (const FeedFormat &feed_format : formats) {
  281. Dictionary dictionary;
  282. dictionary["width"] = feed_format.width;
  283. dictionary["height"] = feed_format.height;
  284. dictionary["format"] = feed_format.format;
  285. result.push_back(dictionary);
  286. }
  287. return result;
  288. }
  289. CameraFeed::FeedFormat CameraFeedAndroid::get_format() const {
  290. CameraFeed::FeedFormat feed_format = {};
  291. ERR_FAIL_INDEX_V_MSG(selected_format, formats.size(), feed_format,
  292. vformat("Invalid format index: %d (formats size: %d)", selected_format, formats.size()));
  293. return formats[selected_format];
  294. }
  295. void CameraFeedAndroid::handle_pause() {
  296. if (is_active()) {
  297. was_active_before_pause = true;
  298. print_verbose(vformat("Camera %s: Pausing (was active).", camera_id));
  299. deactivate_feed();
  300. } else {
  301. was_active_before_pause = false;
  302. }
  303. }
  304. void CameraFeedAndroid::handle_resume() {
  305. if (was_active_before_pause) {
  306. print_verbose(vformat("Camera %s: Resuming.", camera_id));
  307. activate_feed();
  308. was_active_before_pause = false;
  309. }
  310. }
  311. void CameraFeedAndroid::handle_rotation_change() {
  312. if (!is_active()) {
  313. return;
  314. }
  315. print_verbose(vformat("Camera %s: Handling rotation change.", camera_id));
  316. refresh_camera_metadata();
  317. _set_rotation();
  318. }
  319. void CameraFeedAndroid::onImage(void *context, AImageReader *p_reader) {
  320. CameraFeedAndroid *feed = static_cast<CameraFeedAndroid *>(context);
  321. MutexLock lock(feed->callback_mutex);
  322. if (!feed->is_active()) {
  323. AImage *pending_image = nullptr;
  324. if (AImageReader_acquireNextImage(p_reader, &pending_image) == AMEDIA_OK) {
  325. AImage_delete(pending_image);
  326. }
  327. return;
  328. }
  329. Vector<uint8_t> data_y = feed->data_y;
  330. Vector<uint8_t> data_uv = feed->data_uv;
  331. Ref<Image> image_y = feed->image_y;
  332. Ref<Image> image_uv = feed->image_uv;
  333. // Get image
  334. AImage *image = nullptr;
  335. media_status_t status = AImageReader_acquireNextImage(p_reader, &image);
  336. ERR_FAIL_COND(status != AMEDIA_OK);
  337. // Get image data
  338. uint8_t *data = nullptr;
  339. int len = 0;
  340. int32_t pixel_stride, row_stride;
  341. FeedFormat format = feed->get_format();
  342. int width = format.width;
  343. int height = format.height;
  344. switch (format.pixel_format) {
  345. case AIMAGE_FORMAT_YUV_420_888:
  346. AImage_getPlaneData(image, 0, &data, &len);
  347. if (len <= 0) {
  348. return;
  349. }
  350. if (len != data_y.size()) {
  351. int64_t size = Image::get_image_data_size(width, height, Image::FORMAT_R8, false);
  352. data_y.resize(len > size ? len : size);
  353. }
  354. memcpy(data_y.ptrw(), data, len);
  355. AImage_getPlanePixelStride(image, 1, &pixel_stride);
  356. AImage_getPlaneRowStride(image, 1, &row_stride);
  357. AImage_getPlaneData(image, 1, &data, &len);
  358. if (len <= 0) {
  359. return;
  360. }
  361. if (len != data_uv.size()) {
  362. int64_t size = Image::get_image_data_size(width / 2, height / 2, Image::FORMAT_RG8, false);
  363. data_uv.resize(len > size ? len : size);
  364. }
  365. memcpy(data_uv.ptrw(), data, len);
  366. image_y->initialize_data(width, height, false, Image::FORMAT_R8, data_y);
  367. image_uv->initialize_data(width / 2, height / 2, false, Image::FORMAT_RG8, data_uv);
  368. feed->set_ycbcr_images(image_y, image_uv);
  369. break;
  370. case AIMAGE_FORMAT_RGBA_8888:
  371. AImage_getPlaneData(image, 0, &data, &len);
  372. if (len <= 0) {
  373. return;
  374. }
  375. if (len != data_y.size()) {
  376. int64_t size = Image::get_image_data_size(width, height, Image::FORMAT_RGBA8, false);
  377. data_y.resize(len > size ? len : size);
  378. }
  379. memcpy(data_y.ptrw(), data, len);
  380. image_y->initialize_data(width, height, false, Image::FORMAT_RGBA8, data_y);
  381. feed->set_rgb_image(image_y);
  382. break;
  383. case AIMAGE_FORMAT_RGB_888:
  384. AImage_getPlaneData(image, 0, &data, &len);
  385. if (len <= 0) {
  386. return;
  387. }
  388. if (len != data_y.size()) {
  389. int64_t size = Image::get_image_data_size(width, height, Image::FORMAT_RGB8, false);
  390. data_y.resize(len > size ? len : size);
  391. }
  392. memcpy(data_y.ptrw(), data, len);
  393. image_y->initialize_data(width, height, false, Image::FORMAT_RGB8, data_y);
  394. feed->set_rgb_image(image_y);
  395. break;
  396. default:
  397. return;
  398. }
  399. if (!feed->formats.is_empty()) {
  400. if (feed->metadata != nullptr) {
  401. feed->_set_rotation();
  402. } else {
  403. print_verbose(vformat("Camera %s: Metadata invalidated in onImage, attempting refresh.", feed->camera_id));
  404. feed->refresh_camera_metadata();
  405. if (feed->metadata != nullptr && !feed->formats.is_empty()) {
  406. feed->_set_rotation();
  407. }
  408. }
  409. }
  410. // Release image
  411. AImage_delete(image);
  412. }
  413. void CameraFeedAndroid::onSessionReady(void *context, ACameraCaptureSession *session) {
  414. print_verbose("Capture session ready");
  415. }
  416. void CameraFeedAndroid::onSessionActive(void *context, ACameraCaptureSession *session) {
  417. print_verbose("Capture session active");
  418. }
  419. void CameraFeedAndroid::onSessionClosed(void *context, ACameraCaptureSession *session) {
  420. print_verbose("Capture session closed");
  421. }
  422. void CameraFeedAndroid::deactivate_feed() {
  423. // First, remove image listener to prevent new callbacks.
  424. if (reader != nullptr) {
  425. AImageReader_setImageListener(reader, nullptr);
  426. }
  427. // Stop and close capture session.
  428. // These calls may wait for pending callbacks to complete.
  429. if (session != nullptr) {
  430. ACameraCaptureSession_stopRepeating(session);
  431. ACameraCaptureSession_close(session);
  432. session = nullptr;
  433. }
  434. // Now safe to acquire lock and clean up resources.
  435. // No new callbacks will be triggered after this point.
  436. MutexLock lock(callback_mutex);
  437. if (device != nullptr) {
  438. ACameraDevice_close(device);
  439. device = nullptr;
  440. }
  441. if (reader != nullptr) {
  442. AImageReader_delete(reader);
  443. reader = nullptr;
  444. }
  445. if (request != nullptr) {
  446. ACaptureRequest_free(request);
  447. request = nullptr;
  448. }
  449. }
  450. void CameraFeedAndroid::onError(void *context, ACameraDevice *p_device, int error) {
  451. print_error(vformat("Camera error: %d", error));
  452. onDisconnected(context, p_device);
  453. }
  454. void CameraFeedAndroid::onDisconnected(void *context, ACameraDevice *p_device) {
  455. print_verbose("Camera disconnected");
  456. auto *feed = static_cast<CameraFeedAndroid *>(context);
  457. feed->set_active(false);
  458. }
  459. //////////////////////////////////////////////////////////////////////////
  460. // CameraAndroid - Subclass for our camera server on Android
  461. void CameraAndroid::update_feeds() {
  462. ACameraIdList *cameraIds = nullptr;
  463. camera_status_t c_status = ACameraManager_getCameraIdList(cameraManager, &cameraIds);
  464. ERR_FAIL_COND(c_status != ACAMERA_OK);
  465. // remove existing devices
  466. for (int i = feeds.size() - 1; i >= 0; i--) {
  467. remove_feed(feeds[i]);
  468. }
  469. for (int c = 0; c < cameraIds->numCameras; ++c) {
  470. const char *id = cameraIds->cameraIds[c];
  471. ACameraMetadata *metadata = nullptr;
  472. ACameraManager_getCameraCharacteristics(cameraManager, id, &metadata);
  473. if (!metadata) {
  474. continue;
  475. }
  476. // Get sensor orientation
  477. ACameraMetadata_const_entry orientation;
  478. c_status = ACameraMetadata_getConstEntry(metadata, ACAMERA_SENSOR_ORIENTATION, &orientation);
  479. int32_t cameraOrientation;
  480. if (c_status == ACAMERA_OK) {
  481. cameraOrientation = orientation.data.i32[0];
  482. } else {
  483. cameraOrientation = 0;
  484. print_error(vformat("Unable to get sensor orientation: %s", id));
  485. }
  486. // Get position
  487. ACameraMetadata_const_entry lensInfo;
  488. CameraFeed::FeedPosition position = CameraFeed::FEED_UNSPECIFIED;
  489. camera_status_t status;
  490. status = ACameraMetadata_getConstEntry(metadata, ACAMERA_LENS_FACING, &lensInfo);
  491. if (status != ACAMERA_OK) {
  492. ACameraMetadata_free(metadata);
  493. continue;
  494. }
  495. uint8_t lens_facing = static_cast<acamera_metadata_enum_android_lens_facing_t>(lensInfo.data.u8[0]);
  496. if (lens_facing == ACAMERA_LENS_FACING_FRONT) {
  497. position = CameraFeed::FEED_FRONT;
  498. } else if (lens_facing == ACAMERA_LENS_FACING_BACK) {
  499. position = CameraFeed::FEED_BACK;
  500. } else {
  501. ACameraMetadata_free(metadata);
  502. continue;
  503. }
  504. Ref<CameraFeedAndroid> feed = memnew(CameraFeedAndroid(cameraManager, metadata, id, position, cameraOrientation));
  505. add_feed(feed);
  506. }
  507. ACameraManager_deleteCameraIdList(cameraIds);
  508. emit_signal(SNAME(CameraServer::feeds_updated_signal_name));
  509. }
  510. void CameraAndroid::remove_all_feeds() {
  511. // remove existing devices
  512. for (int i = feeds.size() - 1; i >= 0; i--) {
  513. remove_feed(feeds[i]);
  514. }
  515. if (cameraManager != nullptr) {
  516. ACameraManager_delete(cameraManager);
  517. cameraManager = nullptr;
  518. }
  519. }
  520. void CameraAndroid::set_monitoring_feeds(bool p_monitoring_feeds) {
  521. if (p_monitoring_feeds == monitoring_feeds) {
  522. return;
  523. }
  524. CameraServer::set_monitoring_feeds(p_monitoring_feeds);
  525. if (p_monitoring_feeds) {
  526. if (cameraManager == nullptr) {
  527. cameraManager = ACameraManager_create();
  528. }
  529. // Update feeds
  530. update_feeds();
  531. } else {
  532. remove_all_feeds();
  533. }
  534. }
  535. void CameraAndroid::handle_application_pause() {
  536. for (int i = 0; i < feeds.size(); i++) {
  537. Ref<CameraFeedAndroid> feed = feeds[i];
  538. if (feed.is_valid()) {
  539. feed->handle_pause();
  540. }
  541. }
  542. }
  543. void CameraAndroid::handle_application_resume() {
  544. for (int i = 0; i < feeds.size(); i++) {
  545. Ref<CameraFeedAndroid> feed = feeds[i];
  546. if (feed.is_valid()) {
  547. feed->handle_resume();
  548. }
  549. }
  550. }
  551. void CameraAndroid::handle_display_rotation_change(int) {
  552. for (int i = 0; i < feeds.size(); i++) {
  553. Ref<CameraFeedAndroid> feed = feeds[i];
  554. if (feed.is_valid()) {
  555. feed->handle_rotation_change();
  556. }
  557. }
  558. }
  559. CameraAndroid::~CameraAndroid() {
  560. remove_all_feeds();
  561. }
  562. std::optional<int> CameraFeedAndroid::calculate_rotation(const CameraRotationParams &p_params) {
  563. if (p_params.sensor_orientation < 0 || p_params.sensor_orientation > 270 || p_params.sensor_orientation % 90 != 0) {
  564. return std::nullopt;
  565. }
  566. int rotation_angle = p_params.sensor_orientation - p_params.display_rotation;
  567. return normalize_angle(rotation_angle);
  568. }
  569. int CameraFeedAndroid::normalize_angle(int p_angle) {
  570. while (p_angle < 0) {
  571. p_angle += 360;
  572. }
  573. return p_angle % 360;
  574. }
  575. int CameraFeedAndroid::get_display_rotation() {
  576. return DisplayServerAndroid::get_singleton()->get_display_rotation();
  577. }
  578. int CameraFeedAndroid::get_app_orientation() {
  579. GodotIOJavaWrapper *godot_io_java = OS_Android::get_singleton()->get_godot_io_java();
  580. ERR_FAIL_NULL_V(godot_io_java, 0);
  581. int orientation = godot_io_java->get_screen_orientation();
  582. switch (orientation) {
  583. case 0: // SCREEN_LANDSCAPE
  584. return 90;
  585. case 1: // SCREEN_PORTRAIT
  586. return 0;
  587. case 2: // SCREEN_REVERSE_LANDSCAPE
  588. return 270;
  589. case 3: // SCREEN_REVERSE_PORTRAIT
  590. return 180;
  591. case 4: // SCREEN_SENSOR_LANDSCAPE
  592. case 5: // SCREEN_SENSOR_PORTRAIT
  593. case 6: // SCREEN_SENSOR
  594. default:
  595. return get_display_rotation();
  596. }
  597. }