Home | History | Annotate | Download | only in rscamera
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.example.rscamera;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.hardware.camera2.CameraAccessException;
     22 import android.hardware.camera2.CameraCaptureSession;
     23 import android.hardware.camera2.CameraManager;
     24 import android.hardware.camera2.CaptureRequest;
     25 import android.hardware.camera2.TotalCaptureResult;
     26 import android.renderscript.RenderScript;
     27 import android.util.AttributeSet;
     28 import android.util.Log;
     29 import android.util.Size;
     30 import android.view.MotionEvent;
     31 import android.view.Surface;
     32 import android.view.SurfaceHolder;
     33 import android.view.View;
     34 
     35 import com.android.example.rscamera.rscamera.R;
     36 
     37 import java.util.ArrayList;
     38 import java.util.List;
     39 
     40 /**
     41  * Created by hoford on 2/27/15.
     42  */
     43 public class CameraView extends FixedAspectSurfaceView {
     44     private static final String TAG = "CameraPreView";
     45 
     46     private static final long MICRO_SECOND = 1000;
     47     private static final long MILLI_SECOND = MICRO_SECOND * 1000;
     48     private static final long ONE_SECOND = MILLI_SECOND * 1000;
     49 
     50     private Surface mPreviewSurface;
     51     ViewfinderProcessor mProcessor;
     52     private Surface mProcessingNormalSurface;
     53     CameraOps mCameraOps;
     54     CameraManager mCameraManager;
     55     Activity mActivity;
     56     Context mContext;
     57     byte mode = 0;
     58     public static final byte MODE_NONE = 0;
     59     public static final byte MODE_SPEED = 1;
     60     public static final byte MODE_FOCUS = 2;
     61     public static final byte MODE_ISO = 3;
     62     RenderScript mRS;
     63     ErrorCallback mErrorCallback;
     64     ParametersChangedCallback mParametersChangedCallback;
     65 
     66     public CameraView(Context context, AttributeSet attrs) {
     67         super(context, attrs);
     68         mContext = context;
     69 
     70         mRS = RenderScript.create(mContext);
     71         SurfaceHolder.Callback callback = new SurfaceHolder.Callback() {
     72             @Override
     73             public void surfaceCreated(SurfaceHolder holder) {
     74             }
     75 
     76             @Override
     77             public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
     78                 mPreviewSurface = holder.getSurface();
     79                 setupProcessor();
     80             }
     81 
     82             @Override
     83             public void surfaceDestroyed(SurfaceHolder holder) {
     84                 mPreviewSurface = null;
     85             }
     86         };
     87         getHolder().addCallback(callback);
     88         mCameraManager = (CameraManager) mContext.getSystemService(mContext.CAMERA_SERVICE);
     89 
     90         CameraOps.ErrorDisplayer errorDisplayer = new CameraOps.ErrorDisplayer() {
     91 
     92             @Override
     93             public void showErrorDialog(String errorMessage) {
     94                 Log.v(TAG, "ERROR");
     95                 if (mErrorCallback != null) {
     96                     mErrorCallback.showError(errorMessage);
     97                 }
     98                 //MessageDialogFragment.newInstance(errorMessage).show(getFragmentManager(), FRAGMENT_DIALOG);
     99             }
    100 
    101             @Override
    102             public String getErrorString(CameraAccessException e) {
    103                 switch (e.getReason()) {
    104                     case CameraAccessException.CAMERA_DISABLED:
    105                         return mContext.getString(R.string.camera_disabled);
    106                     case CameraAccessException.CAMERA_DISCONNECTED:
    107                         return mContext.getString(R.string.camera_disconnected);
    108                     case CameraAccessException.CAMERA_ERROR:
    109                         return mContext.getString(R.string.camera_error);
    110                     default:
    111                         return mContext.getString(R.string.camera_unknown, e.getReason());
    112 
    113                 }
    114             }
    115         };
    116 
    117         CameraOps.CameraReadyListener cameraReadyListener = new CameraOps.CameraReadyListener() {
    118             @Override
    119             public void onCameraReady() {
    120                 mCameraOps.setUpCamera(mProcessingNormalSurface);
    121             }
    122         };
    123         setOnTouchListener(new View.OnTouchListener() {
    124             @Override
    125             public boolean onTouch(View v, MotionEvent event) {
    126                 return touchScreen(event);
    127             }
    128         });
    129         mCameraOps = new CameraOps(mCameraManager,
    130                 errorDisplayer,
    131                 cameraReadyListener);
    132     }
    133 
    134     public void resume(Activity activity) {
    135         mActivity = activity;
    136 
    137         String errorMessage = mCameraOps.resume();
    138         if (errorMessage != null) {
    139             if (mErrorCallback != null) {
    140                 mErrorCallback.showError(errorMessage);
    141             }
    142         } else {
    143 
    144             Size outputSize = mCameraOps.getBestSize();
    145             mProcessor = new ViewfinderProcessor(mRS, outputSize);
    146             // Configure the output view - this will fire surfaceChanged
    147             setAspectRatio((float) outputSize.getWidth() / outputSize.getHeight());
    148             getHolder().setFixedSize(outputSize.getWidth(), outputSize.getHeight());
    149         }
    150     }
    151 
    152     public void pause() {
    153         mCameraOps.pause();
    154     }
    155 
    156     /**
    157      * Once camera is open and output surfaces are ready, configure the RS processing
    158      * and the camera device inputs/outputs.
    159      */
    160     private void setupProcessor() {
    161         if (mProcessor == null || mPreviewSurface == null) return;
    162         mProcessor.setOutputSurface(mPreviewSurface);
    163         mProcessingNormalSurface = mProcessor.getInputSurface();
    164         mCameraOps.setSurface(mProcessingNormalSurface);
    165     }
    166 
    167     public void takePicture() {
    168         // Orientation
    169         int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation();
    170         int jpegRotation = Surface.ROTATION_0;
    171         switch (rotation) {
    172             case 90:
    173                 jpegRotation = Surface.ROTATION_0;
    174                 break;
    175             case 0:
    176                 jpegRotation = Surface.ROTATION_90;
    177                 break;
    178             case 180:
    179                 jpegRotation = Surface.ROTATION_270;
    180                 break;
    181             case 270:
    182                 jpegRotation = Surface.ROTATION_180;
    183                 break;
    184         }
    185         String name = "Simple" + System.currentTimeMillis() + ".jpg";
    186         mCameraOps.captureStillPicture(jpegRotation, name, mContext.getContentResolver());
    187     }
    188 
    189     private CameraCaptureSession.CaptureCallback mPhotoCallback
    190             = new CameraCaptureSession.CaptureCallback() {
    191 
    192         public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request,
    193                                        TotalCaptureResult result) {
    194             Log.v(TAG, "onCaptureCompleted " + result.toString());
    195         }
    196     };
    197 
    198     float mDownY;
    199     long mExposureDown;
    200     float mFocusDistDown;
    201 
    202     public boolean touchScreen(MotionEvent event) {
    203         if (event.getAction() == MotionEvent.ACTION_DOWN) {
    204             mDownY = event.getY();
    205             mExposureDown = mCameraOps.getExposure();
    206             mFocusDistDown = mCameraOps.getFocusDistance();
    207             if (mFocusDistDown == 0.0) {
    208                 mFocusDistDown = 0.01f;
    209             }
    210         }
    211         float distanceY = event.getY() - mDownY;
    212         float width = getWidth();
    213         float height = getHeight();
    214 
    215         float yDistNorm = distanceY / height;
    216 
    217         float ACCELERATION_FACTOR = 8;
    218         float scaleFactor = (float) Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR);
    219 
    220         switch (mode) {
    221             case MODE_SPEED:
    222                 long exp = (long) (mExposureDown * scaleFactor);
    223                 exp = Math.min(mCameraOps.getExpMax(), exp);
    224                 mCameraOps.setExposure(Math.max(mCameraOps.getExpMin(), exp));
    225                 Log.v(TAG, "mExposure =" + mCameraOps.getExposure());
    226                 break;
    227             case MODE_FOCUS:
    228                 float focusDist = mFocusDistDown * scaleFactor;
    229                 focusDist = Math.max(0.0f, Math.min(mCameraOps.getFocusMin(), focusDist));
    230                 if (focusDist < 0.01) focusDist = 0;
    231                 mCameraOps.setFocusDistance(focusDist);
    232                 Log.v(TAG, "mFocusDist =" + focusDist);
    233                 break;
    234             case MODE_ISO:
    235                 ACCELERATION_FACTOR = 2;
    236                 scaleFactor = (float) Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR);
    237                 int iso = (int) (getIso() * scaleFactor);
    238                 iso = Math.min(mCameraOps.getIsoMax(), iso);
    239                 mCameraOps.setIso(Math.max(mCameraOps.getIsoMin(), iso));
    240                 break;
    241         }
    242 
    243         if (mParametersChangedCallback != null) {
    244             mParametersChangedCallback.parametersChanged();
    245         }
    246         mCameraOps.setParameters();
    247 
    248         return true;
    249     }
    250 
    251     public void setMode(byte mode) {
    252         this.mode = mode;
    253     }
    254 
    255     public byte getMode() {
    256         return mode;
    257     }
    258 
    259     public int getIso() {
    260         return mCameraOps.getIso();
    261     }
    262 
    263     public void setIso(int iso) {
    264         mCameraOps.setIso(iso);
    265         if (mParametersChangedCallback != null) {
    266             mParametersChangedCallback.parametersChanged();
    267         }
    268         mCameraOps.setParameters();
    269     }
    270 
    271     public long getExposure() {
    272         return mCameraOps.getExposure();
    273     }
    274 
    275     public void setExposure(long exposure) {
    276         mCameraOps.setExposure(exposure);
    277         if (mParametersChangedCallback != null) {
    278             mParametersChangedCallback.parametersChanged();
    279         }
    280         mCameraOps.setParameters();
    281     }
    282 
    283     public float getFocusDist() {
    284         return mCameraOps.getFocusDistance();
    285     }
    286 
    287     public void setFocusInMeters(float dist) {
    288         float min = mCameraOps.getFocusMin();
    289         float d = 10 / (dist + 10 / min);
    290         setFocusDist(d);
    291     }
    292 
    293     public void setFocusDist(float dist) {
    294         mCameraOps.setFocusDistance(dist);
    295         mCameraOps.setParameters();
    296     }
    297 
    298     public float getMinFocusDistance() {
    299         return mCameraOps.getFocusMin();
    300     }
    301 
    302     public void setAutofocus(boolean autofocus) {
    303         mCameraOps.setAutoFocus(autofocus);
    304         mCameraOps.setParameters();
    305     }
    306 
    307     public boolean isAutoExposure() {
    308         return mCameraOps.isAutoExposure();
    309     }
    310 
    311     public boolean isAutofocus() {
    312         return mCameraOps.isAutoFocus();
    313     }
    314 
    315     public void setAutoExposure(boolean autoExposure) {
    316         mCameraOps.setAutoExposure(autoExposure);
    317         mCameraOps.setParameters();
    318     }
    319 
    320     public static interface ErrorCallback {
    321         public void showError(String errorMessage);
    322     }
    323 
    324     public void setErrorCallback(ErrorCallback errorCallback) {
    325         mErrorCallback = errorCallback;
    326     }
    327 
    328     public static interface ParametersChangedCallback {
    329         public void parametersChanged();
    330     }
    331 
    332     public void setParametersChangedCallback(ParametersChangedCallback parametersChangedCallback) {
    333         mParametersChangedCallback = parametersChangedCallback;
    334     }
    335 
    336     float getFps() {
    337         return mProcessor.getmFps();
    338     }
    339 }
    340