代码之家  ›  专栏  ›  技术社区  ›  Dhagz

某些设备上未调用Camera onPreviewFrame

  •  8
  • Dhagz  · 技术社区  · 7 年前

    #onPreviewFrame()

    • 三星Galaxy S6(7.0)
    • 三星Galaxy S6(6.0.1)

    但不适用于以下设备:

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

    下面是代码段:

    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;
      }
    }
    

    我的LogCat显示如下:

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

    这个 ScriptC_invert 来自 RenderScript https://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel

    即使我删除了所有RenderScript的东西,同样的问题。

    我还尝试了以下方法:

    camera.setPreviewDisplay(holder) 在我的 surfaceChanged() 方法但这会给我带来另一个问题,因为我需要做一个 holder.lockCanvas() 在里面 onPreviewFrame() 并遇到以下异常:

    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)
    

    1 回复  |  直到 7 年前
        1
  •  3
  •   Dhagz    7 年前

    因为我们不能两者都用 camera.setPreviewDisplay(surfaceHolder) camera.setPreviewCallback(previewCallback) surfaceHolder.lockCanvas() 在里面 onPreviewFrame() 对于某些设备,我已将预览转移到另一个设备 SurfaceView onPreviewFrame() 从那里使用自己的 SufraceHolder .