Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting an error on Android 8 on a Samsung device using SCameraCaptureSession

I'm trying to capture a video using SCameraCaptureSession class. While using a function of this class - setRepeatingRequest (which described here), I'm getting the following error:

java.lang.IllegalArgumentException: CaptureRequest contains unconfigured Input/Output Surface!

As I noticed, the problem is occurring because of something in the MediaRecorder's Surface object. However, it is working fine while using Android version older than 8 and the crash happens only on Samsung devices running Android 8. No google search revealed anything useful about that crash, so I believe it is quite new...

Does anyone have any piece of information? How can I make that MediaRecorder's surface work fine on a device like I mentioned?

Important note: Capturing the video works great on any Android version before 8!!!

like image 545
lior_13 Avatar asked Mar 28 '18 11:03

lior_13


2 Answers

Seems like there is an issue with the surface configuration coming from MediaRecorder. If you pass a custom persistent surface, it should work.

  1. Instantiate a surface by calling MediaCodec.createPersistentInputSurface()

  2. Pass it using mediaRecorder.setInputSurface(yourSurface);

  3. call yourSurface.release() after you stop using this surface.

NOTE: Do not use mediaRecorder.getSurface() if you decide to use this approach

REFERENCES:

MediaRecorder : MediaRecorder - Android Docs

MediaCodec: MediaCodec - Android Docs

like image 91
Napoleon Salazar Avatar answered Nov 21 '22 12:11

Napoleon Salazar


I had the same exception and I solved my case. Root cause of my case is I had re-created Surface of TextureView. When I change it not to re-created Surface, The exception was gone.

My code also works good before Android 8.0

My initializing camera is like following.

CameraDevice mCameraDevice;
CameraCaptureSession mCameraCaptureSession;
CaptureRequest mCaptureRequest;
Surface mTextureViewSurface;

public void updateCameraState(boolean run) {
    if (run) {
        if (mTextureView == null || !mTextureView.isAvailable()) {
            // wait until mTextureView is available
            // then call updateCameraState() again via SurfaceTextureListener

            return;
        }
        if (mCameraDevice == null) {
            // open camera and wait until mCameraDevice is obtained.
            // then call updateCameraState() again via CameraDevice.StateCallback

            mCameraManager.openCamera(...);
            return;
        }
        if (mCameraCaptureSession == null) {
            // createCaptureSession and wait until mCameraCaptureSession is obtained.
            // then call updateCameraState() again via CameraCaptureSession.StateCallback

            mTextureViewSurface = new Surface(texture);
            List<Surface> surfaces = Arrays.asList(mTextureViewSurface, mImageReader.getSurface());
            mCameraDevice.createCaptureSession(surfaces, mSessionStateCallback, sHandler);
            return;
        }
        if (mCaptureRequest == null) {
            CaptureRequest.Builder builder = mCameraCaptureSession.getDevice().createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            /* Put some values into builder */

            // *************************************************************************
            // POINT: In my old code, It re-create Surface
            // *************************************************************************
            // Surface surface = new Surface(texture);
            // builder.addTarget(surface);

            builder.addTarget(mTextureViewSurface);
            mCameraCaptureSession.setRepeatingRequest(builder.build(), mCaptureCallback, sHandler);
        }
        // fin
    } else {
        if (mCaptureRequest != null) {
            mCaptureRequest = null;
        }
        // *************************************************************************
        // POINT: I do not know release() is needed. But I add it here.
        // *************************************************************************
        if (mTextureViewSurface != null) {
            mTextureViewSurface.release();
            mTextureViewSurface = null;
        }
        if (mCameraCaptureSession != null) {
            mCameraCaptureSession.close();
            mCameraCaptureSession = null;
        }
        if (mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
    }
}
like image 31
Takao Sumitomo Avatar answered Nov 21 '22 11:11

Takao Sumitomo