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