Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

onPreviewFrame and Exception locking surface

I'm trying to lockCanvas() because I want to modify camera picture before preview. I do it in onPreviewFrame.

Code is here:

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    

Unfortunately I always got this error in a loop, problem is with 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)

Whole code is here: http://pastebin.com/WJs1kyfq

Using Android 4.0.4 on GT-S7562 device.

I already tried to search here on StackOverflow and used google as well, but didn't find anything what could help me. Thank you for your time!

like image 410
Petr Avatar asked Dec 20 '22 09:12

Petr


1 Answers

You can't do that.

A Surface isn't a buffer, it's a queue of buffers in a producer-consumer arrangement. There can only be one producer at a time, and that's the Camera, so you can't lock the Surface for software rendering. There's no way to read data back out of a Surface unless your app is also the consumer, so there's no way to modify the frame with your current arrangement.

The most efficient way to go about this depends on what it is you're trying to do. If you just want to put an overlay on the preview, you can do that with a custom View with a transparent background. If you want to modify the image before saving it as a still image, then also modify the single still frame before you save it to disk. If you want to modify it for video recording, you can use a SurfaceTexture as the preview target (which gives you both producer and consumer ends in the app), and then use GLES to modify the image. The "show + capture camera" activity in Grafika demonstrates the latter.

See also the Android System-Level Graphics Architecture doc.

like image 85
fadden Avatar answered Jan 06 '23 14:01

fadden