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.cannylive; 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.cannylive.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 CameraView(Context context, AttributeSet attrs)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 } 99 100 @Override 101 public String getErrorString(CameraAccessException e) { 102 switch (e.getReason()) { 103 case CameraAccessException.CAMERA_DISABLED: 104 return mContext.getString(R.string.camera_disabled); 105 case CameraAccessException.CAMERA_DISCONNECTED: 106 return mContext.getString(R.string.camera_disconnected); 107 case CameraAccessException.CAMERA_ERROR: 108 return mContext.getString(R.string.camera_error); 109 default: 110 return mContext.getString(R.string.camera_unknown, e.getReason()); 111 112 } 113 } 114 }; 115 116 CameraOps.CameraReadyListener cameraReadyListener = new CameraOps.CameraReadyListener() { 117 @Override 118 public void onCameraReady() { 119 mCameraOps.setUpCamera(mProcessingNormalSurface); 120 } 121 }; 122 setOnTouchListener(new View.OnTouchListener() { 123 @Override 124 public boolean onTouch(View v, MotionEvent event) { 125 return touchScreen(event); 126 } 127 }); 128 mCameraOps = new CameraOps(mCameraManager, 129 errorDisplayer, 130 cameraReadyListener); 131 } 132 resume(Activity activity)133 public void resume(Activity activity) { 134 mActivity = activity; 135 136 String errorMessage = mCameraOps.resume(); 137 if (errorMessage != null) { 138 if (mErrorCallback != null) { 139 mErrorCallback.showError(errorMessage); 140 } 141 } else { 142 143 Size outputSize = mCameraOps.getBestSize(); 144 mProcessor = new ViewfinderProcessor(mRS, outputSize); 145 // Configure the output view - this will fire surfaceChanged 146 setAspectRatio((float) outputSize.getWidth() / outputSize.getHeight()); 147 getHolder().setFixedSize(outputSize.getWidth(), outputSize.getHeight()); 148 } 149 } 150 pause()151 public void pause() { 152 mProcessor.close(); 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 */ setupProcessor()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 takePicture(int mode)167 public void takePicture(int mode) { 168 // Orientation 169 Log.v(TAG,"Taking picture"); 170 int rotation = mActivity.getWindowManager().getDefaultDisplay().getRotation(); 171 int jpegRotation = Surface.ROTATION_0; 172 switch (rotation) { 173 case 90: 174 jpegRotation = Surface.ROTATION_0; 175 break; 176 case 0: 177 jpegRotation = Surface.ROTATION_90; 178 break; 179 case 180: 180 jpegRotation = Surface.ROTATION_270; 181 break; 182 case 270: 183 jpegRotation = Surface.ROTATION_180; 184 break; 185 } 186 String name = "Simple" + System.currentTimeMillis() + ".jpg"; 187 mCameraOps.captureStillPicture(jpegRotation, name, mContext, mode); 188 } 189 190 private CameraCaptureSession.CaptureCallback mPhotoCallback 191 = new CameraCaptureSession.CaptureCallback() { 192 193 public void onCaptureCompleted(CameraCaptureSession session, CaptureRequest request, 194 TotalCaptureResult result) { 195 Log.v(TAG, "onCaptureCompleted " + result.toString()); 196 } 197 }; 198 199 float mDownY; 200 long mExposureDown; 201 float mFocusDistDown; 202 touchScreen(MotionEvent event)203 public boolean touchScreen(MotionEvent event) { 204 if (event.getAction() == MotionEvent.ACTION_DOWN) { 205 mDownY = event.getY(); 206 mExposureDown = mCameraOps.getExposure(); 207 mFocusDistDown = mCameraOps.getFocusDistance(); 208 if (mFocusDistDown == 0.0) { 209 mFocusDistDown = 0.01f; 210 } 211 } 212 float distanceY = event.getY() - mDownY; 213 float width = getWidth(); 214 float height = getHeight(); 215 216 float yDistNorm = distanceY / height; 217 218 float ACCELERATION_FACTOR = 8; 219 float scaleFactor = (float) Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR); 220 221 switch (mode) { 222 case MODE_SPEED: 223 long exp = (long) (mExposureDown * scaleFactor); 224 exp = Math.min(mCameraOps.getExpMax(), exp); 225 mCameraOps.setExposure(Math.max(mCameraOps.getExpMin(), exp)); 226 Log.v(TAG, "mExposure =" + mCameraOps.getExposure()); 227 break; 228 case MODE_FOCUS: 229 float focusDist = mFocusDistDown * scaleFactor; 230 focusDist = Math.max(0.0f, Math.min(mCameraOps.getFocusMin(), focusDist)); 231 if (focusDist < 0.01) focusDist = 0; 232 mCameraOps.setFocusDistance(focusDist); 233 Log.v(TAG, "mFocusDist =" + focusDist); 234 break; 235 case MODE_ISO: 236 ACCELERATION_FACTOR = 2; 237 scaleFactor = (float) Math.pow(2.f, yDistNorm * ACCELERATION_FACTOR); 238 int iso = (int) (getIso() * scaleFactor); 239 iso = Math.min(mCameraOps.getIsoMax(), iso); 240 mCameraOps.setIso(Math.max(mCameraOps.getIsoMin(), iso)); 241 break; 242 } 243 244 if (mParametersChangedCallback != null) { 245 mParametersChangedCallback.parametersChanged(); 246 } 247 mCameraOps.setParameters(); 248 249 return true; 250 } 251 setMode(byte mode)252 public void setMode(byte mode) { 253 this.mode = mode; 254 } 255 getMode()256 public byte getMode() { 257 return mode; 258 } 259 getIso()260 public int getIso() { 261 return mCameraOps.getIso(); 262 } 263 setIso(int iso)264 public void setIso(int iso) { 265 mCameraOps.setIso(iso); 266 if (mParametersChangedCallback != null) { 267 mParametersChangedCallback.parametersChanged(); 268 } 269 mCameraOps.setParameters(); 270 } 271 getExposure()272 public long getExposure() { 273 return mCameraOps.getExposure(); 274 } 275 setExposure(long exposure)276 public void setExposure(long exposure) { 277 mCameraOps.setExposure(exposure); 278 if (mParametersChangedCallback != null) { 279 mParametersChangedCallback.parametersChanged(); 280 } 281 mCameraOps.setParameters(); 282 } 283 getFocusDist()284 public float getFocusDist() { 285 return mCameraOps.getFocusDistance(); 286 } 287 setFocusInMeters(float dist)288 public void setFocusInMeters(float dist) { 289 float min = mCameraOps.getFocusMin(); 290 float d = 10 / (dist + 10 / min); 291 setFocusDist(d); 292 } 293 setFocusDist(float dist)294 public void setFocusDist(float dist) { 295 mCameraOps.setFocusDistance(dist); 296 mCameraOps.setParameters(); 297 } changeEffectMode()298 public void changeEffectMode() { 299 mProcessor.changeEffectMode(); 300 } getMinFocusDistance()301 public float getMinFocusDistance() { 302 return mCameraOps.getFocusMin(); 303 } 304 setAutofocus(boolean autofocus)305 public void setAutofocus(boolean autofocus) { 306 mCameraOps.setAutoFocus(autofocus); 307 mCameraOps.setParameters(); 308 } 309 isAutoExposure()310 public boolean isAutoExposure() { 311 return mCameraOps.isAutoExposure(); 312 } 313 isAutofocus()314 public boolean isAutofocus() { 315 return mCameraOps.isAutoFocus(); 316 } 317 setAutoExposure(boolean autoExposure)318 public void setAutoExposure(boolean autoExposure) { 319 mCameraOps.setAutoExposure(autoExposure); 320 mCameraOps.setParameters(); 321 } 322 getEffect()323 public int getEffect() { 324 return mProcessor.getMode(); 325 } 326 327 328 public static interface ErrorCallback { showError(String errorMessage)329 public void showError(String errorMessage); 330 } 331 setErrorCallback(ErrorCallback errorCallback)332 public void setErrorCallback(ErrorCallback errorCallback) { 333 mErrorCallback = errorCallback; 334 } 335 336 public static interface ParametersChangedCallback { parametersChanged()337 public void parametersChanged(); 338 } 339 setParametersChangedCallback(ParametersChangedCallback parametersChangedCallback)340 public void setParametersChangedCallback(ParametersChangedCallback parametersChangedCallback) { 341 mParametersChangedCallback = parametersChangedCallback; 342 } 343 getFps()344 float getFps() { 345 if (mProcessor==null) { 346 return 0.0f; 347 } 348 return mProcessor.getmFps(); 349 } 350 } 351