Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Camera preview blank screen when using Skia Frame Processors #2935

Open
4 of 5 tasks
zexueteh opened this issue Jun 4, 2024 · 11 comments
Open
4 of 5 tasks

🐛 Camera preview blank screen when using Skia Frame Processors #2935

zexueteh opened this issue Jun 4, 2024 · 11 comments
Labels
🐛 bug Something isn't working

Comments

@zexueteh
Copy link

zexueteh commented Jun 4, 2024

What's happening?

Hi @mrousavy, thank you for the great work with this library.

Example App My App

However, I have been having issues with applying filters using useSkiaFrameProcessors, even when using the boilerplate provided in the docs.
I've tried two implementations

  1. My own app using a grain filter (right)
  2. Example app with an inverted colour filter (left)

The camera preview ends up being just the filter, without any image. Please refer to the code and logs from both cases below.

I'm wondering whether this might be a hardware issue? I'm currently developing on an old Huawei P10 (released in 2017, Android 9). Ive had a friend run the app on a Samsung S23 Ultra and he did not encounter this issue.

Reproduceable Code

// RECIPICS Code
  const grainFilter = Skia.RuntimeEffect.Make(`
  uniform shader image;
  half4 main(vec2 pos) {
    vec4 color = image.eval(pos);
    float grain = fract(sin(dot(pos, vec2(12.9898, 78.233))) * 43758.5453);
    color.rgb += grain * ${color};
    return color;  }`)
  const shaderBuilder = Skia.RuntimeShaderBuilder(grainFilter)
  const imageFilter = Skia.ImageFilter.MakeRuntimeShader(shaderBuilder, null, null)
  const paint = Skia.Paint()
  paint.setImageFilter(imageFilter)
  const frameProcessor = useSkiaFrameProcessor((frame) => {
    'worklet'
    frame.render(paint)
  }, [paint])
        <Camera
          style={{
            flex: 1
          }}
          ref={camera}
          style={{ width: 400, height: 400 }}
          device={device}
          isActive={true}
          frameProcessor={frameProcessor}
          pixelFormat="yuv"
          photo={false}
          format={format}
        />
      }

// Example App Code
  const invertColorsFilter = Skia.RuntimeEffect.Make(`
  uniform shader image;
  half4 main(vec2 pos) {
    vec4 color = image.eval(pos);
    return vec4((1.0 - color).rgb, 1.0);
  }
`)
  const shaderBuilder = Skia.RuntimeShaderBuilder(invertColorsFilter);

  const imageFilter = Skia.ImageFilter.MakeRuntimeShader(shaderBuilder, null, null)
  const paint = Skia.Paint()
  paint.setImageFilter(imageFilter)

  const frameProcessor = useSkiaFrameProcessor((frame) => {
    'worklet'
    frame.render(paint)
  }, [paint])

Relevant log output

2024-06-04 17:21:01.877 30369-30668 CameraView              com.recipics                         I  invokeOnAverageFpsChanged(11.42263759086189)
2024-06-04 17:21:01.921 30369-30680 GRALLOC                 com.recipics                         I  LockFlexLayout: baseFormat: 11, yStride: 640, ySize: 307200, uOffset: 307200,  uStride: 640
2024-06-04 17:21:01.952 30369-30369 GLConsumer              com.recipics                         E  [SurfaceTexture-0-30369-2] checkAndUpdateEglState: invalid current EGLContext
2024-06-04 17:21:01.952 30369-30369 surfaceTexture          com.recipics                         E  Exception updateTexImage
                                                                                                    java.lang.IllegalStateException: Unable to update texture contents (see logcat for details)
                                                                                                    	at android.graphics.SurfaceTexture.nativeUpdateTexImage(Native Method)
                                                                                                    	at android.graphics.SurfaceTexture.updateTexImage(SurfaceTexture.java:249)
                                                                                                    	at com.shopify.reactnative.skia.PlatformContext.notifyDrawLoop(Native Method)
                                                                                                    	at com.shopify.reactnative.skia.PlatformContext.-$$Nest$mnotifyDrawLoop(Unknown Source:0)
                                                                                                    	at com.shopify.reactnative.skia.PlatformContext$1.doFrame(PlatformContext.java:61)
                                                                                                    	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1090)
                                                                                                    	at android.view.Choreographer.doCallbacks(Choreographer.java:893)
                                                                                                    	at android.view.Choreographer.doFrame(Choreographer.java:809)
                                                                                                    	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1078)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:907)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:105)
                                                                                                    	at android.os.Looper.loop(Looper.java:216)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7625)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)


2024-06-04 16:49:16.970  8524-8776  CameraView              com.mrousavy.camera.example          I  invokeOnAverageFpsChanged(4.060913705583756)
2024-06-04 16:49:17.091  8524-8863  GRALLOC                 com.mrousavy.camera.example          I  LockFlexLayout: baseFormat: 11, yStride: 3840, ySize: 8294400, uOffset: 8294400,  uStride: 3840
2024-06-04 16:49:17.123  8524-8609  <no-tag>                com.mrousavy.camera.example          E  [ZeroHung]zrhung_get_config: Get config failed for wp[0x0102]
2024-06-04 16:49:17.184  8524-8524  GLConsumer              com.mrousavy.camera.example          E  [SurfaceTexture-0-8524-1] checkAndUpdateEglState: invalid current EGLContext
2024-06-04 16:49:17.185  8524-8524  surfaceTexture          com.mrousavy.camera.example          E  Exception updateTexImage
                                                                                                    java.lang.IllegalStateException: Unable to update texture contents (see logcat for details)
                                                                                                    	at android.graphics.SurfaceTexture.nativeUpdateTexImage(Native Method)
                                                                                                    	at android.graphics.SurfaceTexture.updateTexImage(SurfaceTexture.java:249)
                                                                                                    	at com.shopify.reactnative.skia.PlatformContext.notifyDrawLoop(Native Method)
                                                                                                    	at com.shopify.reactnative.skia.PlatformContext.-$$Nest$mnotifyDrawLoop(Unknown Source:0)
                                                                                                    	at com.shopify.reactnative.skia.PlatformContext$1.doFrame(PlatformContext.java:61)
                                                                                                    	at android.view.Choreographer$CallbackRecord.run(Choreographer.java:1090)
                                                                                                    	at android.view.Choreographer.doCallbacks(Choreographer.java:893)
                                                                                                    	at android.view.Choreographer.doFrame(Choreographer.java:809)
                                                                                                    	at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:1078)
                                                                                                    	at android.os.Handler.handleCallback(Handler.java:907)
                                                                                                    	at android.os.Handler.dispatchMessage(Handler.java:105)
                                                                                                    	at android.os.Looper.loop(Looper.java:216)
                                                                                                    	at android.app.ActivityThread.main(ActivityThread.java:7625)
                                                                                                    	at java.lang.reflect.Method.invoke(Native Method)
                                                                                                    	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
                                                                                                    	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:987)

Camera Device

[
  {
    "sensorOrientation": "landscape-left",
    "hardwareLevel": "limited",
    "maxZoom": 6,
    "minZoom": 1,
    "maxExposure": 4,
    "supportsLowLightBoost": false,
    "neutralZoom": 1,
    "physicalDevices": [
      "wide-angle-camera"
    ],
    "supportsFocus": true,
    "supportsRawCapture": false,
    "isMultiCam": false,
    "minFocusDistance": 10,
    "minExposure": -4,
    "name": "0 (BACK) androidx.camera.camera2",
    "hasFlash": true,
    "hasTorch": true,
    "position": "back",
    "id": "0"
  },
  {
    "sensorOrientation": "landscape-right",
    "hardwareLevel": "limited",
    "maxZoom": 6,
    "minZoom": 1,
    "maxExposure": 4,
    "supportsLowLightBoost": false,
    "neutralZoom": 1,
    "physicalDevices": [
      "wide-angle-camera"
    ],
    "supportsFocus": true,
    "supportsRawCapture": false,
    "isMultiCam": false,
    "minFocusDistance": 0,
    "minExposure": -4,
    "name": "1 (FRONT) androidx.camera.camera2",
    "hasFlash": false,
    "hasTorch": false,
    "position": "front",
    "id": "1"
  }
]

Device

Huawei P10 (Android 9.0)

VisionCamera Version

4.0.5

Can you reproduce this issue in the VisionCamera Example app?

Yes, I can reproduce the same issue in the Example app here

Additional information

@zexueteh zexueteh added the 🐛 bug Something isn't working label Jun 4, 2024
@mrousavy
Copy link
Owner

mrousavy commented Jun 4, 2024

Can you try setting your pixelFormat to rgb or yuv to see if there's a difference?

@zexueteh
Copy link
Author

zexueteh commented Jun 4, 2024

Trying in the Example App pixelFormat to yuv produces similar results

however rgb turns the filter grey, as seen here

yuv app

@mrousavy
Copy link
Owner

mrousavy commented Jun 4, 2024

Does it render if you do not pass a paint to the render(..) function?

@zexueteh
Copy link
Author

zexueteh commented Jun 5, 2024

Yup, it does render, but theres definitely some overhead due to the frameprocessor.

@mrousavy
Copy link
Owner

mrousavy commented Jun 5, 2024

Then it surely is the paint (or the shader) that's wrong. I think this is more of a question than a VisionCamera bug report.

Overhead; yea I can see that it only runs at 3 FPS on this Android phone - is that an old phone? @wcandillon I think this is something we might need to investigate - it's either the makeNonTextureImage(), or our makeImageFromPlatformBuffer(...) function that's really slow here... 🤔

@wcandillon
Copy link

I would like to check the performance of the makeImageFromPlatformBuffer function on Android. I would be interesting to know about the phone being used here as well as parameters that would allow me to reproduce the issue (e.g a video file that has the same properties).

@zexueteh
Copy link
Author

zexueteh commented Jun 5, 2024

Hi @mrousavy I dont think its an issue with the paint or shader, as

  1. the Example App uses the inverted colour shader from the docs
  2. These shaders work well on newer hardware (Samsung S23 Ultra)

Granted, the device I'm testing on is very old (Huawei P10 was released 2017). I was wondering if it could be due to these 2 runtime errors as seen in the logs, and would there be any ways to catch them.
2024-06-04 16:49:17.184 8524-8524 GLConsumer com.mrousavy.camera.example E [SurfaceTexture-0-8524-1] checkAndUpdateEglState: invalid current EGLContext

2024-06-04 16:49:17.185 8524-8524 surfaceTexture com.mrousavy.camera.example E Exception updateTexImage java.lang.IllegalStateException: Unable to update texture contents (see logcat for details)

@wcandillon What are some information specifically that i could provide about the phone? Also, how would i be able to check the performance of makeImageFromPlatformBuffer?

@mrousavy
Copy link
Owner

mrousavy commented Jun 5, 2024

Ah interesting - i didnt read those logs my bad. It looks like an error, yep. Not sure if it's RN Skia related or VisionCamera related tho

@mrousavy
Copy link
Owner

mrousavy commented Jun 5, 2024

@wcandillon there's quite a few places in the codebase where RN Skia just swallows errors and logs them to the console (and returns null, or doesnt do anything) - I think throwing an Error (which will be propagated to JS) is better, especially in this case here.

@lucksp
Copy link

lucksp commented Jun 12, 2024

I too get a blank screen, maybe different from OP...when I start my Android device - after running a full build on EAS - I get an error on my device:

Invariant Violation: TurboModuleRegistry.getEnforcing(...): 'RNSkiaModule' could not be found. Verify that a module by this name is registered in the native binary.Bridgeless mode: false. TurboModule interop: false. Modules loaded: {"NativeModules":["PlatformConstants","LogBox","SourceCode","Timing","AppState","BlobModule","WebSocketModule","DevSettings","DevToolsSettingsManager","Networking","Appearance","DevLoadingView","HeadlessJsTaskSupport","DeviceInfo","UIManager","DeviceEventManager","RNCSafeAreaContext","IntentAndroid","NativeAnimatedModule","SoundManager","I18nManager","ImageLoader","RNCAsyncStorage","StatusBarManager","StatusBarManager"],"TurboModules":[],"NotFound":["NativePerformanceCxx","NativePerformanceObserverCxx","RedBox","BugReporting","LinkingManager","PlatformLocalStorage","RNC_AsyncSQLiteDBStorage","FrameRateLogger","KeyboardObserver","ModalManager","Worklets","RNSkiaModule"]}, js engine: hermes

I thought to try my emulator and it complains about minSdkVersion on Android needing to be on 26.

All I get is a white screen for my camera view.

    "react-native": "0.73.6",
    "react-native-vision-camera": "^4.0.1",
    "react-native-worklets-core": "^1.3.0",
    "react-native-fast-tflite": "^1.2.0",
    "vision-camera-resize-plugin": "^3.1.0"

I updated all the packages related to camera/frameprocessor/worklets, and now camera is working.

EDIT: Actually, I am unable to use useSkiaFrameProcessor on my Android device.

ERROR [session/recoverable-error: An unknown error occurred while creating the Camera Session, but the Camera can recover from it.]

@meleffendi
Copy link

meleffendi commented Aug 28, 2024

I'm having a somewhat similar issue on OnePlus5 on 4.0.1. In my case the frame is partially displayed

The camera preview is displayed correctly without any issues if I'm using useFrameProcessor:

Screenshot_20240827-213234 (Custom) (2)

but once I switch to useSkiaFrameProcessor I get this: (notice the white space below and the L shaped black space

Screenshot_20240827-213312 (Custom)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🐛 bug Something isn't working
Projects
None yet
Development

No branches or pull requests

5 participants