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!!!
Seems like there is an issue with the surface configuration coming from MediaRecorder. If you pass a custom persistent surface, it should work.
Instantiate a surface by calling MediaCodec.createPersistentInputSurface()
Pass it using mediaRecorder.setInputSurface(yourSurface);
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
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;
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With