onPreviewFrame和Exception锁定表面

时间:2014-11-05 14:19:40

标签: android android-camera android-canvas

我正在尝试lockCanvas(),因为我想在预览前修改相机图片。我做到了 onPreviewFrame。

代码在这里:

public class MyPreview implements Camera.PreviewCallback {

        @Override
        public void onPreviewFrame(byte[] data, Camera camera) {
            Log.d("Camera", "Got a camera frame");

            Canvas c = null;

            try {
                    c = mCamSH.lockCanvas(null);

                    Log.d("SOMETHING", "Got Bitmap");
            } finally {
                if (c != null) {
                    mCamSH.unlockCanvasAndPost(c);
                }
            }
        }

    } //public class MyPreview implements Camera.PreviewCallback    

不幸的是我总是在循环中遇到这个错误,问题是c = mCamSH.lockCanvas(null); :

E/SurfaceHolder﹕ Exception locking surface
    java.lang.IllegalArgumentException
            at android.view.Surface.lockCanvasNative(Native Method)
            at android.view.Surface.lockCanvas(Surface.java:76)
            at android.view.SurfaceView$4.internalLockCanvas(SurfaceView.java:831)
            at android.view.SurfaceView$4.lockCanvas(SurfaceView.java:811)
            at cz.mrp.camera.CamActivity$MyPreview.onPreviewFrame(CamActivity.java:100)
            at android.hardware.Camera$EventHandler.handleMessage(Camera.java:773)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4517)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:993)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:760)
            at dalvik.system.NativeStart.main(Native Method)

整个代码在这里:http://pastebin.com/WJs1kyfq

在GT-S7562设备上使用Android 4.0.4。

我已经尝试在这里搜索StackOverflow并使用谷歌,但没有找到任何可以帮助我的东西。谢谢你的时间!

3 个答案:

答案 0 :(得分:8)

你不能这样做。

Surface不是缓冲区,它是生产者 - 消费者安排中的缓冲区队列。一次只能有一个制作人,这就是相机,因此您无法锁定Surface以进行软件渲染。除非您的应用也是消费者,否则无法从Surface读取数据,因此无法使用您当前的安排修改框架。

最有效的方法取决于您尝试做什么。如果您只想在预览上添加叠加层,则可以使用透明背景的自定义视图执行此操作。如果要在将图像另存为静止图像之前修改图像,则在将其保存到磁盘之前还要修改单个静止帧。如果要修改视频录制,可以使用SurfaceTexture作为预览目标(在应用程序中为您提供生产者和消费者端),然后使用GLES修改图像。 "显示+捕捉相机" Grafika中的活动表明了后者。

另请参阅Android System-Level Graphics Architecture doc。

答案 1 :(得分:2)

我找到了解决方案。

您必须删除此代码,因为画布已被相机锁定。

mCam.setPreviewDisplay(mCamSH);

为了显示相机预览,您必须使用画布上的变量(byte []数据)手动绘制它。

答案 2 :(得分:1)

为什么使用

c = mCamSH.lockCanvas(null);

试试这个:

c = mCamSH.lockCanvas();

<强> @Edit 您正尝试在mCamSH持有者上调用lockCanvas。 然而,这个支架被相机使用,因此画布已被它锁定。

保持简短:我不认为你可以在onPreviewFrame中调用lockCanvas