org.artoolkit.ar.utils.calib_optical.CameraSurface.java Source code

Java tutorial

Introduction

Here is the source code for org.artoolkit.ar.utils.calib_optical.CameraSurface.java

Source

/*
 *  CameraSurface.java
 *  ARToolKit5
 *
 *  This file is part of ARToolKit.
 *
 *  ARToolKit is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Lesser General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  ARToolKit is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with ARToolKit.  If not, see <http://www.gnu.org/licenses/>.
 *
 *  As a special exception, the copyright holders of this library give you
 *  permission to link this library with independent modules to produce an
 *  executable, regardless of the license terms of these independent modules, and to
 *  copy and distribute the resulting executable under terms of your choice,
 *  provided that you also meet, for each linked independent module, the terms and
 *  conditions of the license of that module. An independent module is a module
 *  which is neither derived from nor based on this library. If you modify this
 *  library, you may extend this exception to your version of the library, but you
 *  are not obligated to do so. If you do not wish to do so, delete this exception
 *  statement from your version.
 *
 *  Copyright 2015 Daqri, LLC.
 *  Copyright 2011-2015 ARToolworks, Inc.
 *
 *  Author(s): Julian Looser, Philip Lamb
 *
 */

package org.artoolkit.ar.utils.calib_optical;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Build;
import android.preference.PreferenceManager;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.Toast;

import java.io.IOException;

public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback {

    private static final String TAG = "CameraSurface";
    private Camera camera;

    private boolean mustAskPermissionFirst = false;

    public boolean gettingCameraAccessPermissionsFromUser() {
        return mustAskPermissionFirst;
    }

    public void resetGettingCameraAccessPermissionsFromUserState() {
        mustAskPermissionFirst = false;
    }

    @SuppressWarnings("deprecation")
    public CameraSurface(Context context) {
        super(context);

        Log.i(TAG, "CameraSurface(): ctor called");
        Activity activityRef = (Activity) context;

        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(activityRef,
                        Manifest.permission.CAMERA)) {
                    mustAskPermissionFirst = true;
                    if (activityRef.shouldShowRequestPermissionRationale(Manifest.permission.CAMERA)) {
                        // Will drop in here if user denied permissions access camera before.
                        // Or no uses-permission CAMERA element is in the
                        // manifest file. Must explain to the end user why the app wants
                        // permissions to the camera devices.
                        Toast.makeText(activityRef.getApplicationContext(),
                                "App requires access to camera to be granted", Toast.LENGTH_SHORT).show();
                    }
                    // Request permission from the user to access the camera.
                    Log.i(TAG, "CameraSurface(): must ask user for camera access permission");
                    activityRef.requestPermissions(new String[] { Manifest.permission.CAMERA },
                            calib_optical_Activity.REQUEST_CAMERA_PERMISSION_RESULT);
                    return;
                }
            }
        } catch (Exception ex) {
            Log.e(TAG, "CameraSurface(): exception caught, " + ex.getMessage());
            return;
        }

        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // Deprecated in API level 11. Still required for API levels <= 10.
    }

    // SurfaceHolder.Callback methods

    @SuppressLint("NewApi")
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolderInstance) {
        //        Log.i(TAG, "Opening camera.");
        //        try {
        //            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        //                int cameraIndex = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(getContext()).getString("pref_cameraIndex", "0"));
        //                camera = Camera.open(cameraIndex);
        //            } else {
        //                camera = Camera.open();
        //            }
        //        } catch (RuntimeException exception) {
        //            Log.e(TAG, "Cannot open camera. It may be in use by another process.");
        //        }
        //        if (camera != null) {
        //            try {
        //
        //                camera.setPreviewDisplay(holder);
        //                //camera.setPreviewCallback(this);
        //                camera.setPreviewCallbackWithBuffer(this); // API level 8 (Android 2.2)
        //
        //            } catch (IOException exception) {
        //                Log.e(TAG, "Cannot set camera preview display.");
        //                camera.release();
        //                camera = null;
        //            }
        //        }
        int cameraIndex = Integer.parseInt(
                PreferenceManager.getDefaultSharedPreferences(getContext()).getString("pref_cameraIndex", "0"));
        Log.i(TAG, "surfaceCreated(): called, will attempt open camera \"" + cameraIndex
                + "\", set orientation, set preview surface");
        openCamera(surfaceHolderInstance, cameraIndex);
    }

    private void openCamera(SurfaceHolder surfaceHolderInstance, int cameraIndex) {
        Log.i(TAG, "openCamera(): called");
        try {
            camera = Camera.open(cameraIndex);
        } catch (RuntimeException ex) {
            Log.e(TAG, "openCamera(): RuntimeException caught, " + ex.getMessage() + ", abnormal exit");
            return;
        }
        //catch (CameraAccessException ex) {
        //      Log.e(TAG, "openCamera(): CameraAccessException caught, " + ex.getMessage() + ", abnormal exit");
        //      return;
        //  }
        catch (Exception ex) {
            Log.e(TAG, "openCamera()): exception caught, " + ex.getMessage() + ", abnormal exit");
            return;
        }

        if (!SetOrientationAndPreview(surfaceHolderInstance, cameraIndex)) {
            Log.e(TAG, "openCamera(): call to SetOrientationAndPreview() failed, openCamera() failed");
        } else
            Log.i(TAG, "openCamera(): succeeded");
    }

    private boolean SetOrientationAndPreview(SurfaceHolder surfaceHolderInstance, int cameraIndex) {
        Log.i(TAG, "SetOrientationAndPreview(): called");
        boolean success = true;
        try {
            //setCameraDisplayOrientation(cameraIndex, camera);
            camera.setPreviewDisplay(surfaceHolderInstance);
            camera.setPreviewCallbackWithBuffer(this); // API level 8 (Android 2.2)
        } catch (IOException ex) {
            Log.e(TAG, "SetOrientationAndPreview(): IOException caught, " + ex.toString());
            success = false;
        } catch (Exception ex) {
            Log.e(TAG, "SetOrientationAndPreview(): Exception caught, " + ex.toString());
            success = false;
        }
        if (!success) {
            if (null != camera) {
                camera.release();
                camera = null;
            }
            Log.e(TAG, "SetOrientationAndPreview(): released camera due to caught exception");
        }
        return success;
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {

        if (camera != null) {
            Log.i(TAG, "surfaceDestroyed(): closing camera");
            camera.stopPreview();
            camera.setPreviewCallback(null);
            camera.release();
            camera = null;
        }
    }

    @SuppressLint("NewApi") // CameraInfo
    @SuppressWarnings("deprecation") // setPreviewFrameRate
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {

        if (camera != null) {

            String camResolution = PreferenceManager.getDefaultSharedPreferences(getContext()).getString(
                    "pref_cameraResolution", getResources().getString(R.string.pref_defaultValue_cameraResolution));
            String[] dims = camResolution.split("x", 2);
            Camera.Parameters parameters = camera.getParameters();
            parameters.setPreviewSize(Integer.parseInt(dims[0]), Integer.parseInt(dims[1]));
            parameters.setPreviewFrameRate(30);
            camera.setParameters(parameters);

            parameters = camera.getParameters();
            int capWidth = parameters.getPreviewSize().width;
            int capHeight = parameters.getPreviewSize().height;
            int pixelformat = parameters.getPreviewFormat(); // android.graphics.imageformat
            PixelFormat pixelinfo = new PixelFormat();
            PixelFormat.getPixelFormatInfo(pixelformat, pixelinfo);
            int cameraIndex = 0;
            boolean frontFacing = false;
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
                Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
                cameraIndex = Integer.parseInt(PreferenceManager.getDefaultSharedPreferences(getContext())
                        .getString("pref_cameraIndex", "0"));
                Camera.getCameraInfo(cameraIndex, cameraInfo);
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT)
                    frontFacing = true;
            }

            int bufSize = capWidth * capHeight * pixelinfo.bitsPerPixel / 8; // For the default NV21 format, bitsPerPixel = 12.

            for (int i = 0; i < 5; i++)
                camera.addCallbackBuffer(new byte[bufSize]);

            camera.startPreview();

            calib_optical_Activity.nativeVideoInit(capWidth, capHeight, cameraIndex, frontFacing);
        }
    }

    // Camera.PreviewCallback methods.
    @Override
    public void onPreviewFrame(byte[] data, Camera cam) {

        calib_optical_Activity.nativeVideoFrame(data);

        cam.addCallbackBuffer(data);
    }
} // end: public class CameraSurface extends SurfaceView implements SurfaceHolder.Callback, Camera.PreviewCallback