2017-09-05 16 views
5

我期待可以登錄#onPreviewFrame()多次logcat的,但它只能在選定的設備,如:不叫上一些設備攝像機onPreviewFrame

  • 三星Galaxy S6(7.0)
  • 三星Galaxy S6( 6.0.1)
  • LG萊昂(5.0.1)

,但不會對下列設備:

  • LG G4(6.0)
  • 華爲6X(7.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_inverthttps://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel

即使我刪除所有RenderScript的東西,同樣的問題。

我也試過如下:

注:

一個補丁修復需要一個camera.setPreviewDisplay(holder)在我surfaceChanged()方法。但是,這將創造另一個問題對我來說,因爲我需要做的onPreviewFrame()一個holder.lockCanvas()並遇到以下異常:

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

至於目前,我還沒有找到解決這個問題,而是我有一個解決方法。

既然我們不能同時使用這兩種camera.setPreviewDisplay(surfaceHolder)camera.setPreviewCallback(previewCallback)希望使用onPreviewFrame()surfaceHolder.lockCanvas()對於某些設備,我有我的傳送預覽另一個SurfaceView,並從那裏處理onPreviewFrame()和使用自己的SufraceHolder

+2

這是一個正確的解決方法。 [setPreviewDisplay或setPreviewTexture](https://stackoverflow.com/questions/16752454/setpreviewdisplay-vs-setpreviewtexture)在Android中是強制性的,但有些設備不強制執行它。 –

+2

順便說一句,考慮切換到** camera2 ** API,除非你的大多數目標設備低於棒棒糖。如果您決定留在*棄用的* Camera API,請確保您在單獨的處理程序線程中打開相機(以便Camera.open()和回調不會導致UI線程擁塞)。 –

+0

@AlexCohn感謝您的建議。是的,我也瞄準了前棒棒糖設備,這就是爲什麼我還在使用已棄用的相機API。 – dhagz

相關問題