OnPreviewFrame camera is not called on some devices

I expect LogCat to register #onPreviewFrame() several times, but it only works on selected devices, such as:

  • Samsung Galaxy S6 (7.0)
  • Samsung Galaxy S6 (6.0.1)
  • LG Leon (5.0.1)

But not on the following devices:

  • LG G4 (6.0)
  • Huawei 6X (7.0)
  • Nexus 6P (7.0)

The following is a snippet of code:

 public CameraSurfaceView(Context context, AttributeSet set) { super(context, set); Log.d(TAG, "CameraSurfaceView(context, set)"); // Get the Surface Holder this.holder = this.getHolder(); this.holder.addCallback(this); this.holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } @Override public void surfaceCreated(SurfaceHolder holder) { try { // Turn on the Camera this.camera = Camera.open(); } catch (Exception ex) { Log.e(TAG, "#surfaceCreated() error=" + ex.getMessage(), ex); } } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { Log.d(TAG, "#surfaceChanged()"); if (holder.getSurface() == null) { // preview surface does not exist return; } if (camera == null) { // camera does not exist return; } // This allows us to make our own draw calls to this canvas this.setWillNotDraw(false); // Initialize canvas variables previewPaint = new Paint(); // Initialize preview variables deviceWidth = width; deviceHeight = height; Camera.Size previewSize = this.camera.getParameters().getPreviewSize(); previewWidth = previewSize.width; previewHeight = previewSize.height; previewBitmap = Bitmap.createBitmap(previewWidth, previewHeight, Bitmap.Config.ARGB_8888); // Initialize Scale Variables previewScaleMatrix = new Matrix(); previewScaleMatrix.setScale(deviceWidth / (float) previewWidth, deviceHeight / (float) previewHeight, deviceWidth / 2.0f, deviceHeight / 2.0f); // Initialize RenderScript variables rs = RenderScript.create(getContext()); // RenderScript YUV to RGB yuvToRgbScript = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs)); Type.Builder previewRgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(previewWidth).setY(previewHeight); yuvToRgbOut = Allocation.createTyped(rs, previewRgbaType.create(), Allocation.USAGE_SCRIPT); // RenderScript Invert invertScript = new ScriptC_invert(rs); invertOut = Allocation.createTyped(rs, yuvToRgbOut.getType(), Allocation.USAGE_SCRIPT); // Set color effect to none parameters.setColorEffect(Camera.Parameters.EFFECT_NONE); camera.setParameters(parameters); // Set the preview callback Log.d(TAG, "#surfaceChanged() camera.setPreviewCallback()"); camera.setPreviewCallback(new Camera.PreviewCallback() { @Override public void onPreviewFrame(byte[] data, Camera camera) { Log.d(TAG, "#onPreviewFrame()"); } }); // Start the camera preview Log.d(TAG, "#surfaceChanged() camera.startPreview()"); camera.startPreview(); } @Override public void surfaceDestroyed(SurfaceHolder holder) { // Surface will be destroyed when replaced with a new screen // Always make sure to release the Camera instance if (camera != null) { camera.setPreviewCallback(null); camera.stopPreview(); camera.release(); camera = null; } } 

My LogCat is displayed as follows:

 D/CameraSurfaceView: #surfaceChanged() D/CameraSurfaceView: #surfaceChanged() camera.setPreviewCallback() D/CameraSurfaceView: #surfaceChanged() camera.startPreview() 

ScriptC_invert is from the RenderScript sample at https://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel

And even if I delete all RenderScript materials, the same problem.

I also tried the following:

Note:

For one fix, you will need camera.setPreviewDisplay(holder) in my surfaceChanged() method. But this will create another problem for me, since I will need to do holder.lockCanvas() in onPreviewFrame() and encounter the following exception:

 E/SurfaceHolder: Exception locking surface java.lang.IllegalArgumentException at android.view.Surface.nativeLockCanvas(Native Method) at android.view.Surface.lockCanvas(Surface.java:264) at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:842) at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:830) at com.arcanys.ar.CameraSurfaceView.onPreviewFrame(CameraSurfaceView.java:204) 

There may be some things that I missed or misconfigured.

+5
source share
1 answer

Currently, I have not found a fix for this problem, rather I have a workaround.

Since we cannot use both camera.setPreviewDisplay(surfaceHolder) and camera.setPreviewCallback(previewCallback) , while expecting to use surfaceHolder.lockCanvas() in onPreviewFrame() for some devices, I transferred my preview to another SurfaceView and process onPreviewFrame() from there and use your own SufraceHolder .

+1
source

Source: https://habr.com/ru/post/1271530/


All Articles