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.52k stars 770 forks source link

My device starts the camera in an inverted way #1576

Open tiomurray opened 6 days ago

tiomurray commented 6 days ago

I have a device which seems to start the camera in an inverted way: if I start the activity in portrait mode, this loads the camera with a landscape resolution, and if I start it in landscape mode, the camera starts with a portrait resolution, Is there any way to open the camera inverting the width and the height? I tried playing with rotation, width and height but didn't achieve what I want. Here is some pictures of the issue, my goal is to get the inverted result: the portrait preview in portrait mode and landscape preview in landscape mode. I could get this result but output video is stretched, as initial width and height of the signal of the camera is inverted as I said.

My current code is working fine with all devices except this one, so I guess is software issue or something related at the time of starting the camera, even before the surface is created.

WhatsApp Image 2024-09-11 at 20 34 20 WhatsApp Image 2024-09-11 at 20 34 38

pedroSG94 commented 6 days ago

Hello,

You will need to handle the orientation manually to fix it. If you have autohandleOrientation, set it to false: https://github.com/pedroSG94/RootEncoder/blob/master/app/src/main/java/com/pedro/streamer/rotation/CameraFragment.kt#L77 Now, create a sensor class to handle the orientation manually:

  private val sensorRotationManager = SensorRotationManager(context, true, true, object: SensorRotationManager.RotationChangedListener {
    override fun onRotationChanged(rotation: Int, isPortrait: Boolean) {
      genericStream.getGlInterface().setCameraOrientation(rotation)
      genericStream.getGlInterface().setIsPortrait(!isPortrait)
    }
  })

In this case, I did !isPortrait in setIsPortrait because I think that the fail is related with that parameters because the orientation seems fine. Remember start and stop the sensor in onResume and in onPause methods or similar depend of your lifecycle:

sensorRotationManager.start()
sensorRotationManager.stop()
tiomurray commented 6 days ago

Its not working with that code, I tried several options. What's happening is that the camera in portrait mode is opening like if it was recording with native camera in landscape mode, this is, 1920x1080 so at the time of converting that 1920x1080 in the portrait mode is getting stretched because portrait mode expects video data of 1080x1920.

I tried the setCameraOrientation and setIsPortrait with all the combinations but the result was the same in every case.

EDIT: setCameraOrientation() and setIsPortrait() work after call startPreview(mCameraView), anyway I can't find the way to open the camera in the right way, I think is an initial issue, before prepareVideo()

pedroSG94 commented 5 days ago

Hello,

prepareVideo could change orientation depend of the rotation value. Using 0 you have landscape and using 90 you have portrait but the preview should be correct in both cases. This only should affect to the stream result rotating the resolution depend of the value. For example:

Try add this:

genericStream.getGlInterface().forceOrientation(OrientationForced.LANDSCAPE)
genericStream.getGlInterface().forceOrientation(OrientationForced.PORTRAIT)
genericStream.getGlInterface().forceOrientation(OrientationForced.NONE) //this is used to disable this mode

Try using one of that for landscape or portrait. Test all combinations

tiomurray commented 5 days ago

Ok so I was able to draw in the surface the correct preview, but the issue is that the streaming output is inverted. a 1080x1920 preview is streaming in 1920x1080, and viceversa. I add the code and pictures of the output:

@Override
    public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
        genericStream = new GenericStream(requireContext(), this);

        genericStream.getGlInterface().setAspectRatioMode(AspectRatioMode.Fill);

        Size cameraSize = getCameraSize();

        genericStream.prepareVideo(
                cameraSize.getWidth(),
                cameraSize.getHeight(),
                1200 * 1000,
                30,
                2,
                getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT ? 90 : 0
        );
        genericStream.prepareAudio(32000, true, 128 * 1000);

        genericStream.startPreview(mCameraView);

        boolean isPortrait = getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
        genericStream.getGlInterface().setCameraOrientation(isPortrait ? 0 : 270);
        genericStream.getGlInterface().setIsPortrait(!isPortrait);
    }

Pictures:

Portrait preview: 1

Portrait streaming result: 2

Landscape preview: 3

Landscape streaming result: 4

All these results were obtained using width=1920, height=1080.

If I use width=1080,height=1920, all is the same except portrait streaming result, which is this:

2

pedroSG94 commented 5 days ago

Was the streaming result working fine before that changes?

Can you tell me the values of SensorManager in all orientations? I want know your values to create an enviroment to test it and try a fix for it. Use the code of my previous comment