2017-09-05 15 views
5

Tôi hy vọng các LogCat được đăng #onPreviewFrame() nhiều lần, nhưng nó chỉ hoạt động trên các thiết bị được lựa chọn như:Máy ảnh onPreviewFrame không kêu gọi một số thiết bị

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

Nhưng không trên các thiết bị sau:

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

Dưới đây là đoạn mã:

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 màn hình của tôi như sau:

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

ScriptC_invert là từ mẫu RenderScript trong https://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel

Và ngay cả khi tôi xóa tất cả nội dung trên RenderScript, cùng một vấn đề.

Tôi cũng đã thử như sau:

LƯU Ý:

Một sửa chữa sẽ cần một camera.setPreviewDisplay(holder) trong phương pháp surfaceChanged() tôi. Nhưng điều này sẽ tạo ra một vấn đề khác đối với tôi kể từ khi tôi sẽ cần phải làm một holder.lockCanvas() trong onPreviewFrame() và gặp phải ngoại lệ sau đây:

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) 

Có thể có một số điều mà tôi đã bỏ lỡ hoặc cấu hình sai.

Trả lời

1

Hiện tại, tôi chưa tìm thấy bản sửa lỗi cho vấn đề này, thay vào đó tôi có một giải pháp thay thế.

Vì chúng ta không thể sử dụng cả hai camera.setPreviewDisplay(surfaceHolder)camera.setPreviewCallback(previewCallback) đồng thời hy vọng sẽ sử dụng surfaceHolder.lockCanvas() trong onPreviewFrame() cho một số thiết bị, tôi đã chuyển xem trước của tôi để SurfaceView khác và xử lý các onPreviewFrame() từ đó và sử dụng riêng SufraceHolder của nó.

+2

Đây là giải pháp đúng. [setPreviewDisplay hoặc setPreviewTexture] (https://stackoverflow.com/questions/16752454/setpreviewdisplay-vs-setpreviewtexture) là bắt buộc trong Android, nhưng một số thiết bị không thực thi nó. –

+2

BTW, hãy cân nhắc chuyển sang ** camera2 ** API trừ khi hầu hết các thiết bị mục tiêu của bạn ở dưới Lollipop. Và nếu bạn quyết định ở lại với API * không dùng nữa *, hãy đảm bảo bạn mở máy ảnh trong một chuỗi Trình xử lý riêng biệt (để Camera.open() và các cuộc gọi lại không gây tắc nghẽn trên chuỗi giao diện người dùng). –

+0

@AlexCohn cảm ơn lời khuyên của bạn. Có, tôi cũng đang nhắm mục tiêu các thiết bị trước kẹo que, đây là lý do tôi vẫn sử dụng API máy ảnh không dùng nữa. – dhagz

Các vấn đề liên quan