2017-09-05 9 views
5

私は#onPreviewFrame()複数回ログインするLogCatを期待していますが、それは唯一のように、選択したデバイス上で動作します:カメラonPreviewFrameは

  • サムスンギャラクシーS6(7.0)
  • サムスンギャラクシーS6( 6.0.1)
  • LGレオン(5.0.1)

しかし、しないの次のデバイス上:

次のように

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ディスプレイ:

  • LG G4(6.0)
  • Huaweiで6X(7.0)
  • ネクサスは以下

6P(7.0)コードスニペットである

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

ScriptC_invertRenderScriptのサンプルhttps://developer.android.com/guide/topics/renderscript/compute.html#writing-an-rs-kernel

また、すべてのRenderScriptのものを削除しても同じ問題が発生します。

私はまた、次のことを試してみた:

注:

一つの修正は私のsurfaceChanged()方法でcamera.setPreviewDisplay(holder)が必要になります。しかし、私は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

当面はこの問題の修正が見つからず、回避策があります。

我々はいくつかのデバイスのためにonPreviewFrame()surfaceHolder.lockCanvas()を使用することを期待同時にcamera.setPreviewDisplay(surfaceHolder)camera.setPreviewCallback(previewCallback)の両方を使用することはできませんので、私は別のSurfaceViewに私のプレビューを移して、そこからonPreviewFrame()を処理し、SufraceHolder独自のを使用しています。

+2

これは正しい回避策です。 [setPreviewDisplay or setPreviewTexture](https://stackoverflow.com/questions/16752454/setpreviewdisplay-vs-setpreviewtexture)はAndroidでは必須ですが、一部のデバイスでは強制しません。 –

+2

ところで、ターゲットデバイスのほとんどがLollipop以下でない限り、** camera2 ** APIに切り替えることを検討してください。また、非推奨の* Camera APIを使用する場合は、別のHandlerスレッドでCamera.open()とコールバックがUIスレッドで輻輳を起こさないように、カメラを開いてください。 –

+0

@AlexCohnご助言ありがとうございます。はい、私はまだロリポップ前のデバイスをターゲットにしています。なぜなら、私は引き続き非推奨のカメラAPIを使用しているからです。 – dhagz

関連する問題