Skip to content

Conversation

@shiena
Copy link
Contributor

@shiena shiena commented Sep 20, 2025

Stride-aligned plane handling:

  • Adjust CameraFeed's AIMAGE_FORMAT_YUV_420_888 path to copy Y and UV planes while honoring their row/pixel strides.
  • Allocate plane buffers by logical dimensions (not raw byte counts) and branch for packed vs. planar UV layouts.
  • Reference the Android YV12 docs (https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12) to explain the stride-aware copy logic and expected fix for padded-stride devices.

Camera feed synchronization fixes:

  • Make callback structures instance members instead of static to ensure correct this pointer is captured for each camera feed instance

  • Fix resource leaks for session outputs and camera output target

  • Synchronize camera session closure before device close using semaphore to prevent "Device is closed but session is not notified" warning

  • Fix image buffer stall when switching camera feeds by acquiring and discarding pending images when feed is not active

  • Add atomic flags (is_deactivating, session_close_pending, device_error_occurred) for proper synchronization during deactivation

  • Deactivate feeds in update_feeds() and remove_all_feeds() before removing them to prevent resource leaks

  • Improved Android camera preview rotation so that feed transforms stay in sync with both sensor orientation and the current display rotation, ensuring the correct angle (and mirroring) is applied for front and back cameras without redundant updates.

  • Fix race condition in camera feed deactivation by adding mutex protection and correcting resource cleanup order

  • Add Android lifecycle management for camera rotation and pause/resume events

  • Implement horizontal mirroring for front camera to provide mirror-like experience

  • Add comprehensive safety checks for metadata, formats, and array bounds

  • Implement metadata refresh mechanism to handle configuration changes

Bugsquad edit:

@shiena shiena requested a review from a team as a code owner September 20, 2025 12:08
@j20001970
Copy link
Contributor

After applying the patch, I run into problems that acquiring image from image reader does not succeed.

09-20 22:26:49.710  2456  2680 E godot   : ERROR: Condition "status != AMEDIA_OK" is true.
09-20 22:26:49.710  2456  2680 E godot   :    at: onImage (modules/camera/camera_android.cpp:294

@MuslimDev-sys
Copy link

After applying the patch, I run into problems that acquiring image from image reader does not succeed.

09-20 22:26:49.710  2456  2680 E godot   : ERROR: Condition "status != AMEDIA_OK" is true.
09-20 22:26:49.710  2456  2680 E godot   :    at: onImage (modules/camera/camera_android.cpp:294

Same here

Test Results for the Patch

Hello! I have tested the new export templates, and this is a very positive update.

Godot version

v4.6.dev.gh-110720 [36d0e1f]

1. The Original Bug is FIXED

Your patch was successful! The original "Expected Image data size" errors are completely gone. This confirms that your fix for the memory stride/padding issue worked correctly. Thank you!

2. A New, Different Error Has Appeared

While the original error is fixed, the screen is still black. A new, different error appeared 8 times in the debugger:

E 0:00:01:896   onImage: Condition "status != AMEDIA_OK" is true.
  <C++ Source>  modules/camera/camera_android.cpp:294 @ onImage()

Analysis

Based on the C++ source file (camera_android.cpp:294), this new error indicates that the AImageReader_acquireNextImage function is now failing.

Summary:

  • FIXED: The app no longer crashes when processing the image data.
  • NEW BUG: The app is now failing one step earlier, when it tries to acquire the image frame from the Android camera system.

This is fantastic progress, and it proves we are on the right track. Please let me know if you have another patch you would like me to test. Thank you again for your hard work on this @shiena

@j20001970
Copy link
Contributor

After applying the patch, I run into problems that acquiring image from image reader does not succeed.

09-20 22:26:49.710  2456  2680 E godot   : ERROR: Condition "status != AMEDIA_OK" is true.
09-20 22:26:49.710  2456  2680 E godot   :    at: onImage (modules/camera/camera_android.cpp:294

The previous problem seems to be fixed in 355c6ed, so it now works as expected, thanks!

packed_y.resize(width * height);
if (y_row_stride == width) {
// No padding, direct copy
memcpy(packed_y.ptrw(), data_y.ptr(), width * height);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are copying the same data twice here, is there any chances that this can be improved?

@shiena
Copy link
Contributor Author

shiena commented Sep 21, 2025

@j20001970
Thank you for the review. After investigating the cause, I found that memory alignment considerations are necessary as explained in https://developer.android.com/reference/android/graphics/ImageFormat.html#YV12 , so I've recreated the diff.

@shiena
Copy link
Contributor Author

shiena commented Sep 21, 2025

@MuslimDev-sys
Thank you for testing the functionality. I fixed it using a different approach, so could you please test it again?
https://github.com/godotengine/godot/actions/runs/17892068593
https://github.com/godotengine/godot/actions/runs/17898213735

@j20001970
Copy link
Contributor

I do not have Android devices that provide full planar YUV format to test, but 4136769 works well for the case of interleaved UV plane.

@MuslimDev-sys
Copy link

Test Results for the Final Patch: Success!

Hello @shiena,

I have tested the new build with your different approach, and it is a complete success.

Godot version

v4.6.dev.gh-110720 [533e77659]

1. The Main Bug is FIXED

Your patch was successful! The camera feed is now working and visible on my device. The black screen is gone, and all the previous C++ errors (Expected Image data size and AImageReader_acquireNextImage) have been resolved. Thank you!

2. Next Steps and Final Observations

Now that the main issue is solved, I can interact with the feed and have observed two new behaviors. I am not sure if these are new engine bugs or issues with your GDScript logic, so I am reporting them here for your review.

  • Rotation: The camera preview is now visible, but it appears to be rotated by -90 degrees.

  • Error When Switching Cameras: When I try to switch to the front camera or select a different resolution, the switch does not happen, and the following error is logged once:

    E 0:00:37:884   set_format: Feed is active.
      <C++ Error>   Condition "active" is true. Returning: false
      <C++ Source>  modules/camera/camera_android.cpp:260 @ set_format()
    

Summary

The fix for the critical blocking bug is complete and successful. You have solved the core engine issue, and the camera is now functional on my device.

Thank you again for all your hard work and persistence on this! @shiena

@shiena
Copy link
Contributor Author

shiena commented Sep 22, 2025

@MuslimDev-sys
Thank you for testing the functionality.
Both the rotation and camera switching errors are suspected to be bugs in godot-camera-demo. So let's check with shiena/godot-camerafeed-demo#3 .

@AThousandShips AThousandShips added this to the 4.6 milestone Sep 22, 2025
@shiena shiena force-pushed the fix/camera_android branch 2 times, most recently from ac850f0 to 2db8a67 Compare September 24, 2025 05:40
@m4gr3d m4gr3d added the cherrypick:4.5 Considered for cherry-picking into a future 4.5.x release label Sep 24, 2025
@shiena shiena force-pushed the fix/camera_android branch 2 times, most recently from 619d046 to 7a00ad0 Compare October 5, 2025 17:32
@shiena shiena changed the title Android: Handle YUV_420_888 strides correctly in CameraFeed Android: Fix YUV_420_888 strides and preview orientation in CameraFeed Oct 5, 2025
@shiena shiena force-pushed the fix/camera_android branch 2 times, most recently from 9a7e698 to 0b372b3 Compare October 5, 2025 17:48
@shiena shiena force-pushed the fix/camera_android branch 2 times, most recently from bf121b7 to c1b5f17 Compare October 14, 2025 20:23
@Alex2782
Copy link
Member

Alex2782 commented Jan 1, 2026

On Samsung Tab S7: Everything seems to be working fine so far, but when I change the format, the screen is almost completely black, and I can see a strip of camera feed at the edge. Only after "Reload" or "Stop/Start" is everything okay again.

On Pixel 4a: The app freezes and becomes unresponsive when I press stop or try to change the camera (front/back).

@shiena shiena force-pushed the fix/camera_android branch from 19527c6 to 31351ba Compare January 1, 2026 21:17
@shiena
Copy link
Contributor Author

shiena commented Jan 1, 2026

@Alex2782 @The-Cyber-Captain
I believe this should be fixed in 31351ba.

@The-Cyber-Captain
Copy link

Sadly, building 31351ba and running my simplified test scene / MRP from #114468 I'm still unable to switch CameraFeed under Android. 😿

@shiena
Copy link
Contributor Author

shiena commented Jan 2, 2026

@The-Cyber-Captain
Could you grab the logcat (filtered by package name) while reproducing the issue?

@shiena shiena force-pushed the fix/camera_android branch from a93341c to 2b1618b Compare January 2, 2026 08:58
@shiena
Copy link
Contributor Author

shiena commented Jan 2, 2026

@Alex2782 @The-Cyber-Captain
I was able to reproduce the freeze on Quest3, so I've added a further fix in 2b1618b.

@The-Cyber-Captain
Copy link

@The-Cyber-Captain Could you grab the logcat (filtered by package name) while reproducing the issue?

Ahhhhh. I'm more a User than a Dev. 🤣 Filtering logcats is about the edge of my skillset / setup. But I gave it a shot and updated the issue with them. Only to see you have a new fix; you absolute machine! 👍

I'll give that new build a test as soon as able, and report back.
PS: related to this
oKEgewjFoA
at all? I have high hopes for the new commit.

Like I say, will test it out and feed back how it goes. Thanks.

@shiena
Copy link
Contributor Author

shiena commented Jan 2, 2026

@The-Cyber-Captain
Thanks for providing the logcat. I've addressed what appears to be the cause of the error based on the log messages.

Copy link
Member

@Alex2782 Alex2782 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks great on both of my devices now!

I can't say much about the code (I'm not very familiar with it)

Except that you should avoid auto.
https://contributing.godotengine.org/en/latest/engine/guidelines/cpp_usage_guidelines.html#auto-keyword

However, a line of code containing auto was already accepted 8 months ago. (CameraFeedAndroid::onDisconnected)

@shiena shiena force-pushed the fix/camera_android branch from 74d6390 to dd93d31 Compare January 6, 2026 07:11
@shiena
Copy link
Contributor Author

shiena commented Jan 6, 2026

Thank you for the review. Fixed by replacing auto * with explicit type CameraFeedAndroid * in both onError() and onDisconnected() callbacks.

Copy link
Contributor

@m4gr3d m4gr3d left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks good. Can you squash the commits.

@shiena shiena force-pushed the fix/camera_android branch from dd93d31 to 9d32ca7 Compare January 6, 2026 17:28
@shiena
Copy link
Contributor Author

shiena commented Jan 6, 2026

Squashed.

Comment on lines 81 to 83
std::atomic<bool> is_deactivating{ false };
std::atomic<bool> session_close_pending{ false };
std::atomic<bool> device_error_occurred{ false };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have our own SafeFlag wrapper for std::atomic that should probably be used here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Replaced std::atomic<bool> with Godot's SafeFlag wrapper.

@syntaxerror247
Copy link
Member

syntaxerror247 commented Jan 6, 2026

I finally tested the PR, using the MRP provided in #110711

Camera now works and I can switch between front and back camera but feed is too zoomed in and also seems like a bit tilted.
I'm testing on moto g45. It might be a seperate issue (maybe issue in demo project) but I can't test previous version because camera feed was completely black on this device.

- Handle stride-aligned YUV planes from camera driver
- Fix callback context to support multiple camera feeds
- Synchronize camera session closure before device close
- Prevent image buffer stall when switching feeds
- Deactivate camera feeds before removal
- Replace auto with explicit type in callbacks

Fixes godotengine#110711
Fixes godotengine#114468
@shiena shiena force-pushed the fix/camera_android branch from 9d32ca7 to 07a9f91 Compare January 6, 2026 18:01
@shiena
Copy link
Contributor Author

shiena commented Jan 6, 2026

@syntaxerror247
Regarding the zoom appearing too zoomed in: The MRP displays the camera to fill the entire screen, cropping any overflow. Switching to a format with a different aspect ratio should change how it appears.

@syntaxerror247
Copy link
Member

@shiena I think I've figured out the issue and it is related to rotation. The camera feed isn't rotating with the device orientation. When I set the device to landscape, everything looks correct. However, when I switch to portrait mode, the camera feed doesn't rotate. So the issue seems to be caused by rotation handling somewhere.

@shiena
Copy link
Contributor Author

shiena commented Jan 6, 2026

@syntaxerror247
I've recently improved the rotation handling. Please give it a try.
https://github.com/shiena/godot-camerafeed-demo

@syntaxerror247
Copy link
Member

@syntaxerror247 I've recently improved the rotation handling. Please give it a try. https://github.com/shiena/godot-camerafeed-demo

Tested with this demo, issue is resolved now!

I was looking at that demo project for the last 30 min trying to fix the rotation, for my understanding, could you share how you fixed the rotation bug? Maybe just drop the commit link?

@shiena
Copy link
Contributor Author

shiena commented Jan 6, 2026

@syntaxerror247
Rotation handling is consolidated in the _update_scene_transform function in camerafeed.gd, so please refer to it.

@Repiteo Repiteo merged commit 8072cc9 into godotengine:master Jan 6, 2026
20 checks passed
@Repiteo
Copy link
Contributor

Repiteo commented Jan 6, 2026

Thanks!

@akien-mga akien-mga removed the cherrypick:4.5 Considered for cherry-picking into a future 4.5.x release label Jan 8, 2026
@shiena shiena deleted the fix/camera_android branch January 8, 2026 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unable to correctly switch CameraFeed on Android apps. Android: CameraServer fails with "Expected Image data size" error on YUV_420_888 stream

10 participants