I am expecting the LogCat to be logging #onPreviewFrame() multiple times, but it only works on selected devices like:
But does not on the following devices:
Below is the code snippet:
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 displays as follows:
D/CameraSurfaceView: #surfaceChanged()
D/CameraSurfaceView: #surfaceChanged() camera.setPreviewCallback()
D/CameraSurfaceView: #surfaceChanged() camera.startPreview()
The ScriptC_invert is from the RenderScript sample in https://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel
And even if I remove all RenderScript stuff, the same problem.
I've also tried the following:
NOTE:
One fix would need a camera.setPreviewDisplay(holder) in my surfaceChanged() method. But this will create another issue for me since I would need to do a 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 might be some things that I've missed or misconfigured.
As for the time being, I haven't found a fix for this issue, rather I have a workaround.
Since we cannot use both camera.setPreviewDisplay(surfaceHolder) and camera.setPreviewCallback(previewCallback) at the same time expect to use the surfaceHolder.lockCanvas() in onPreviewFrame() for some devices, I have transferred my preview to another SurfaceView and handle the onPreviewFrame() from there and use its own SufraceHolder.
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