pedroSG94 / RootEncoder

RootEncoder for Android (rtmp-rtsp-stream-client-java) is a stream encoder to push video/audio to media servers using protocols RTMP, RTSP, SRT and UDP with all code written in Java/Kotlin
Apache License 2.0
2.54k stars 771 forks source link

Wrong camera selected - Pixel 4 - grayscale image #566

Closed marcin-adamczewski closed 4 years ago

marcin-adamczewski commented 4 years ago

Hi @pedroSG94 , I encountered an issue that camera image is in grayscale, there are no colors. It turned out that Pixel 4 have two front cameras and one of them is probably for face detection. Using such camera result in image with only black and white colors. Here is how it looks like https://cl.ly/5ac4fa45ad95

We discovered that issue is related to how a camera is being selected in Camera2ApiManager

     if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING) == facing) {
        openCameraId(0);
      } else {
        openCameraId(cameraManager.getCameraIdList().length - 1);

More precisely this line openCameraId(cameraManager.getCameraIdList().length - 1) So on Pixel4 getCameraIdList returns a list like [0, 1, 2]. Using this code it will get last id which is 2. Basically 1 and 2 are both Front cameras. I'm not sure how to decide which front camera is the correct one, but it looks like we'd need to pick first from the list which is 1. Maybe there is a better way to recognize whether the camera is for commercial use :D It may be also a bug in Pixel 4 and they shouldn't let us use this camera.

Anyways please have a look at my PR https://github.com/pedroSG94/rtmp-rtsp-stream-client-java/pull/565

I have also some concerns about how cameraCharacteristics is being assigned in Camera2ApiManager.

It's done in many places like getCameraResolutionsBack. So when you call this method then camera characteristics is being changed to back camera characteristics and later on you use the same characteristics to use check various things like isLanternSupported. But in fact you may be using front camera and not back camera. Let me know if I was clear enough. I think that it would be better to always depends on cameraId and whenever you want to check something from characteristics you could call cameraManager.getCameraCharacteristics(cameraId). That way we have characteristics for currently selected camera. I'm not sure but knowing that there may be more than 2 cameras it may be risky to assume that if back cameraId is equal to 0 then front is equal to 1, like in this code

Camera2ApiManager.getCameraResolutionsBack()

   cameraCharacteristics = cameraManager.getCameraCharacteristics("0");
      if (cameraCharacteristics.get(CameraCharacteristics.LENS_FACING)
          != CameraCharacteristics.LENS_FACING_BACK) {
        cameraCharacteristics = cameraManager.getCameraCharacteristics("1");
      }

Maybe it would be safer to create helper functions like, getFrontCameraCharacteristic and getBackCameraCharacteristic it would iterate through available cameras and based on facing it would pick the first one from the list that matches facing.

What do you think Pedro?

pedroSG94 commented 4 years ago

Yes, you are totally right. When I developed this code I never got a device with more than a camera and that code work for it cause if you only have 2 camera this reduce the logic but your code is better for that reason if merged it. Thank your for your PR :D