1c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams/* 2c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * Copyright (C) 2012 The Android Open Source Project 3c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * 4c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * Licensed under the Apache License, Version 2.0 (the "License"); 5c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * you may not use this file except in compliance with the License. 6c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * You may obtain a copy of the License at 7c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * 8c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * http://www.apache.org/licenses/LICENSE-2.0 9c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * 10c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * Unless required by applicable law or agreed to in writing, software 11c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * distributed under the License is distributed on an "AS IS" BASIS, 12c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * See the License for the specific language governing permissions and 14c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams * limitations under the License. 15c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams */ 16c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 17c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 18c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samspackage com.example.android.rs.sto; 19c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 20c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samsimport android.graphics.SurfaceTexture; 21c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samsimport android.hardware.Camera; 22c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samsimport android.os.SystemClock; 23c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samsimport android.util.Log; 24c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 25c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samsimport java.io.IOException; 26c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samsimport java.util.List; 27c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 28c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Samspublic class CameraCapture { 29c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 30c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public interface CameraFrameListener { 31c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public void onNewCameraFrame(); 32c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 33c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 34c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams static final int FRAMES_PER_SEC = 30; 35c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 36c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private Camera mCamera; 37c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private SurfaceTexture mSurfaceTexture; 38c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 39c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mProgram; 40c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 41c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mCameraTransformHandle; 42c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mTexSamplerHandle; 43c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mTexCoordHandle; 44c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mPosCoordHandle; 45c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 46c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private float[] mCameraTransform = new float[16]; 47c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 48c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mCameraId = 0; 49c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mWidth; 50c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int mHeight; 51c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 52c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private long mStartCaptureTime = 0; 53c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 54c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private boolean mNewFrameAvailable = false; 55c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private boolean mIsOpen = false; 56c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 57c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private CameraFrameListener mListener; 58c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 59c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public synchronized void beginCapture(int cameraId, int width, int height, 60c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams SurfaceTexture st) { 61c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCameraId = cameraId; 62c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mSurfaceTexture = st; 63c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 64c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Open the camera 65c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams openCamera(width, height); 66c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 67c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Start the camera 68c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mStartCaptureTime = SystemClock.elapsedRealtime(); 69c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCamera.startPreview(); 70c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mIsOpen = true; 71c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 72c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 73c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public void getCurrentFrame() { 74c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (checkNewFrame()) { 75c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (mStartCaptureTime > 0 && SystemClock.elapsedRealtime() - mStartCaptureTime > 2000) { 76c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Lock white-balance and exposure for effects 77c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams Log.i("CC", "Locking white-balance and exposure!"); 78c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams Camera.Parameters params = mCamera.getParameters(); 79c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams params.setAutoWhiteBalanceLock(true); 80c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams params.setAutoExposureLock(true); 81c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams //mCamera.setParameters(params); 82c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mStartCaptureTime = 0; 83c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 84c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 85c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mSurfaceTexture.updateTexImage(); 86c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mSurfaceTexture.getTransformMatrix(mCameraTransform); 87c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 88c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // display it here 89c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 90c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 91c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 92c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public synchronized boolean hasNewFrame() { 93c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return mNewFrameAvailable; 94c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 95c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 96c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public synchronized void endCapture() { 97c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mIsOpen = false; 98c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (mCamera != null) { 99c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCamera.release(); 100c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCamera = null; 101c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mSurfaceTexture = null; 102c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 103c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 104c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 105c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public synchronized boolean isOpen() { 106c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return mIsOpen; 107c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 108c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 109c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public int getWidth() { 110c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return mWidth; 111c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 112c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 113c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public int getHeight() { 114c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return mHeight; 115c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 116c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 117c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public void setCameraFrameListener(CameraFrameListener listener) { 118c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mListener = listener; 119c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 120c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 121c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private void openCamera(int width, int height) { 122c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Setup camera 123c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCamera = Camera.open(mCameraId); 124c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCamera.setParameters(calcCameraParameters(width, height)); 125c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 126c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Create camera surface texture 127c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams try { 128c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mCamera.setPreviewTexture(mSurfaceTexture); 129c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } catch (IOException e) { 130c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams throw new RuntimeException("Could not bind camera surface texture: " + 131c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams e.getMessage() + "!"); 132c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 133c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 134c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Connect SurfaceTexture to callback 135c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mSurfaceTexture.setOnFrameAvailableListener(onCameraFrameAvailableListener); 136c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 137c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 138c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private Camera.Parameters calcCameraParameters(int width, int height) { 139c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams Camera.Parameters params = mCamera.getParameters(); 140c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams params.setPreviewSize(mWidth, mHeight); 141c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 142c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Find closest size 143c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int closestSize[] = findClosestSize(width, height, params); 144c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mWidth = closestSize[0]; 145c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mHeight = closestSize[1]; 146c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams params.setPreviewSize(mWidth, mHeight); 147c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 148c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Find closest FPS 149c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int closestRange[] = findClosestFpsRange(FRAMES_PER_SEC, params); 150c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 151c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams params.setPreviewFpsRange(closestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX], 152c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams closestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); 153c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 154c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return params; 155c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 156c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 157c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int[] findClosestSize(int width, int height, Camera.Parameters parameters) { 158c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams List<Camera.Size> previewSizes = parameters.getSupportedPreviewSizes(); 159c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int closestWidth = -1; 160c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int closestHeight = -1; 161c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int smallestWidth = previewSizes.get(0).width; 162c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int smallestHeight = previewSizes.get(0).height; 163c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams for (Camera.Size size : previewSizes) { 164c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Best match defined as not being larger in either dimension than 165c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // the requested size, but as close as possible. The below isn't a 166c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // stable selection (reording the size list can give different 167c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // results), but since this is a fallback nicety, that's acceptable. 168c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if ( size.width <= width && 169c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams size.height <= height && 170c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams size.width >= closestWidth && 171c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams size.height >= closestHeight) { 172c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams closestWidth = size.width; 173c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams closestHeight = size.height; 174c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 175c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if ( size.width < smallestWidth && 176c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams size.height < smallestHeight) { 177c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams smallestWidth = size.width; 178c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams smallestHeight = size.height; 179c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 180c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 181c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (closestWidth == -1) { 182c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams // Requested size is smaller than any listed size; match with smallest possible 183c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams closestWidth = smallestWidth; 184c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams closestHeight = smallestHeight; 185c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 186c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int[] closestSize = {closestWidth, closestHeight}; 187c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return closestSize; 188c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 189c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 190c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private int[] findClosestFpsRange(int fps, Camera.Parameters params) { 191c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams List<int[]> supportedFpsRanges = params.getSupportedPreviewFpsRange(); 192c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int[] closestRange = supportedFpsRanges.get(0); 193c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int fpsk = fps * 1000; 194c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int minDiff = 1000000; 195c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams for (int[] range : supportedFpsRanges) { 196c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int low = range[Camera.Parameters.PREVIEW_FPS_MIN_INDEX]; 197c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int high = range[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]; 198c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (low <= fpsk && high >= fpsk) { 199c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams int diff = (fpsk - low) + (high - fpsk); 200c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (diff < minDiff) { 201c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams closestRange = range; 202c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams minDiff = diff; 203c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 204c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 205c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 206c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams Log.i("CC", "Found closest range: " 207c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams + closestRange[Camera.Parameters.PREVIEW_FPS_MIN_INDEX] + " - " 208c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams + closestRange[Camera.Parameters.PREVIEW_FPS_MAX_INDEX]); 209c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return closestRange; 210c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 211c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 212c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private synchronized void signalNewFrame() { 213c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mNewFrameAvailable = true; 214c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (mListener != null) { 215c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mListener.onNewCameraFrame(); 216c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 217c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 218c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 219c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private synchronized boolean checkNewFrame() { 220c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams if (mNewFrameAvailable) { 221c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams mNewFrameAvailable = false; 222c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return true; 223c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 224c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams return false; 225c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 226c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams 227c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams private SurfaceTexture.OnFrameAvailableListener onCameraFrameAvailableListener = 228c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams new SurfaceTexture.OnFrameAvailableListener() { 229c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams @Override 230c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams public void onFrameAvailable(SurfaceTexture surfaceTexture) { 231c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams signalNewFrame(); 232c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams } 233c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams }; 234c5f519c5ec57400f04f1d0bdc69f7bfddf47f8cbJason Sams} 235