1 /* 2 * Copyright (C) 2014 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.camera.one.v2; 18 19 import android.annotation.TargetApi; 20 import android.content.Context; 21 import android.graphics.ImageFormat; 22 import android.graphics.Rect; 23 import android.hardware.camera2.CameraAccessException; 24 import android.hardware.camera2.CameraCaptureSession; 25 import android.hardware.camera2.CameraCharacteristics; 26 import android.hardware.camera2.CameraDevice; 27 import android.hardware.camera2.CameraMetadata; 28 import android.hardware.camera2.CaptureRequest; 29 import android.hardware.camera2.CaptureResult; 30 import android.hardware.camera2.CaptureResult.Key; 31 import android.hardware.camera2.TotalCaptureResult; 32 import android.hardware.camera2.params.MeteringRectangle; 33 import android.hardware.camera2.params.StreamConfigurationMap; 34 import android.media.CameraProfile; 35 import android.media.Image; 36 import android.media.ImageReader; 37 import android.media.MediaActionSound; 38 import android.net.Uri; 39 import android.os.Build; 40 import android.os.Handler; 41 import android.os.HandlerThread; 42 import android.os.SystemClock; 43 import android.support.v4.util.Pools; 44 import android.view.Surface; 45 46 import com.android.camera.CaptureModuleUtil; 47 import com.android.camera.app.MediaSaver.OnMediaSavedListener; 48 import com.android.camera.debug.Log; 49 import com.android.camera.debug.Log.Tag; 50 import com.android.camera.exif.ExifInterface; 51 import com.android.camera.exif.ExifTag; 52 import com.android.camera.exif.Rational; 53 import com.android.camera.one.AbstractOneCamera; 54 import com.android.camera.one.OneCamera; 55 import com.android.camera.one.OneCamera.PhotoCaptureParameters.Flash; 56 import com.android.camera.one.Settings3A; 57 import com.android.camera.one.v2.ImageCaptureManager.ImageCaptureListener; 58 import com.android.camera.one.v2.ImageCaptureManager.MetadataChangeListener; 59 import com.android.camera.session.CaptureSession; 60 import com.android.camera.util.CameraUtil; 61 import com.android.camera.util.ConjunctionListenerMux; 62 import com.android.camera.util.JpegUtilNative; 63 import com.android.camera.util.Size; 64 65 import java.nio.ByteBuffer; 66 import java.util.ArrayList; 67 import java.util.List; 68 import java.util.concurrent.LinkedBlockingQueue; 69 import java.util.concurrent.ThreadPoolExecutor; 70 import java.util.concurrent.TimeUnit; 71 import java.util.concurrent.atomic.AtomicLong; 72 73 /** 74 * {@link OneCamera} implementation directly on top of the Camera2 API with zero 75 * shutter lag.<br> 76 * TODO: Determine what the maximum number of full YUV capture frames is. 77 */ 78 @TargetApi(Build.VERSION_CODES.LOLLIPOP) 79 public class OneCameraZslImpl extends AbstractOneCamera { 80 private static final Tag TAG = new Tag("OneCameraZslImpl2"); 81 82 /** Default JPEG encoding quality. */ 83 private static final int JPEG_QUALITY = CameraProfile.getJpegEncodingQualityParameter( 84 CameraProfile.QUALITY_HIGH); 85 /** 86 * The maximum number of images to store in the full-size ZSL ring buffer. 87 * <br> 88 * TODO: Determine this number dynamically based on available memory and the 89 * size of frames. 90 */ 91 private static final int MAX_CAPTURE_IMAGES = 10; 92 /** 93 * True if zero-shutter-lag images should be captured. Some devices produce 94 * lower-quality images for the high-frequency stream, so we may wish to 95 * disable ZSL in that case. 96 */ 97 private static final boolean ZSL_ENABLED = true; 98 99 /** 100 * Tags which may be used in CaptureRequests. 101 */ 102 private static enum RequestTag { 103 /** 104 * Indicates that the request was explicitly sent for a single 105 * high-quality still capture. Unlike other requests, such as the 106 * repeating (ZSL) stream and AF/AE triggers, requests with this tag 107 * should always be saved. 108 */ 109 EXPLICIT_CAPTURE 110 } 111 112 /** 113 * Set to ImageFormat.JPEG to use the hardware encoder, or 114 * ImageFormat.YUV_420_888 to use the software encoder. No other image 115 * formats are supported. 116 */ 117 private static final int sCaptureImageFormat = ImageFormat.YUV_420_888; 118 /** 119 * Token for callbacks posted to {@link #mCameraHandler} to resume 120 * continuous AF. 121 */ 122 private static final String FOCUS_RESUME_CALLBACK_TOKEN = "RESUME_CONTINUOUS_AF"; 123 124 /** Zero weight 3A region, to reset regions per API. */ 125 /*package*/ MeteringRectangle[] ZERO_WEIGHT_3A_REGION = AutoFocusHelper.getZeroWeightRegion(); 126 127 /** 128 * Thread on which high-priority camera operations, such as grabbing preview 129 * frames for the viewfinder, are running. 130 */ 131 private final HandlerThread mCameraThread; 132 /** Handler of the {@link #mCameraThread}. */ 133 private final Handler mCameraHandler; 134 135 /** Thread on which low-priority camera listeners are running. */ 136 private final HandlerThread mCameraListenerThread; 137 private final Handler mCameraListenerHandler; 138 139 /** The characteristics of this camera. */ 140 private final CameraCharacteristics mCharacteristics; 141 /** The underlying Camera2 API camera device. */ 142 private final CameraDevice mDevice; 143 144 /** 145 * The aspect ratio (width/height) of the full resolution for this camera. 146 * Usually the native aspect ratio of this camera. 147 */ 148 private final float mFullSizeAspectRatio; 149 /** The Camera2 API capture session currently active. */ 150 private CameraCaptureSession mCaptureSession; 151 /** The surface onto which to render the preview. */ 152 private Surface mPreviewSurface; 153 /** Whether closing of this device has been requested. */ 154 private volatile boolean mIsClosed = false; 155 /** A callback that is called when the device is fully closed. */ 156 private CloseCallback mCloseCallback = null; 157 158 /** Receives the normal captured images. */ 159 private final ImageReader mCaptureImageReader; 160 161 /** 162 * Maintains a buffer of images and their associated {@link CaptureResult}s. 163 */ 164 private ImageCaptureManager mCaptureManager; 165 166 /** 167 * The sensor timestamp (which may not be relative to the system time) of 168 * the most recently captured image. 169 */ 170 private final AtomicLong mLastCapturedImageTimestamp = new AtomicLong(0); 171 172 /** Thread pool for performing slow jpeg encoding and saving tasks. */ 173 private final ThreadPoolExecutor mImageSaverThreadPool; 174 175 /** Pool of native byte buffers on which to store jpeg-encoded images. */ 176 private final Pools.SynchronizedPool<ByteBuffer> mJpegByteBufferPool = new 177 Pools.SynchronizedPool<ByteBuffer>(64); 178 179 /** Current zoom value. 1.0 is no zoom. */ 180 private float mZoomValue = 1f; 181 /** Current crop region: set from mZoomValue. */ 182 private Rect mCropRegion; 183 /** Current AE, AF, and AWB regions */ 184 private MeteringRectangle[] mAFRegions = ZERO_WEIGHT_3A_REGION; 185 private MeteringRectangle[] mAERegions = ZERO_WEIGHT_3A_REGION; 186 187 private MediaActionSound mMediaActionSound = new MediaActionSound(); 188 189 /** 190 * Ready state (typically displayed by the UI shutter-button) depends on two 191 * things:<br> 192 * <ol> 193 * <li>{@link #mCaptureManager} must be ready.</li> 194 * <li>We must not be in the process of capturing a single, high-quality, 195 * image.</li> 196 * </ol> 197 * See {@link ConjunctionListenerMux} and {@link #mReadyStateManager} for 198 * details of how this is managed. 199 */ 200 private static enum ReadyStateRequirement { 201 CAPTURE_MANAGER_READY, 202 CAPTURE_NOT_IN_PROGRESS 203 } 204 205 /** 206 * Handles the thread-safe logic of dispatching whenever the logical AND of 207 * these constraints changes. 208 */ 209 private final ConjunctionListenerMux<ReadyStateRequirement> 210 mReadyStateManager = new ConjunctionListenerMux<ReadyStateRequirement>( 211 ReadyStateRequirement.class, new ConjunctionListenerMux.OutputChangeListener() { 212 @Override 213 public void onOutputChange(boolean state) { 214 broadcastReadyState(state); 215 } 216 }); 217 218 /** 219 * An {@link ImageCaptureListener} which will compress and save an image to 220 * disk. 221 */ 222 private class ImageCaptureTask implements ImageCaptureListener { 223 private final PhotoCaptureParameters mParams; 224 private final CaptureSession mSession; 225 226 public ImageCaptureTask(PhotoCaptureParameters parameters, 227 CaptureSession session) { 228 mParams = parameters; 229 mSession = session; 230 } 231 232 @Override 233 public void onImageCaptured(Image image, TotalCaptureResult 234 captureResult) { 235 long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP); 236 237 // We should only capture the image if it's more recent than the 238 // latest one. Synchronization is necessary since this method is 239 // called on {@link #mImageSaverThreadPool}. 240 synchronized (mLastCapturedImageTimestamp) { 241 if (timestamp > mLastCapturedImageTimestamp.get()) { 242 mLastCapturedImageTimestamp.set(timestamp); 243 } else { 244 // There was a more recent (or identical) image which has 245 // begun being saved, so abort. 246 return; 247 } 248 } 249 250 mReadyStateManager.setInput( 251 ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, true); 252 253 mSession.startEmpty(); 254 savePicture(image, mParams, mSession); 255 mParams.callback.onPictureTaken(mSession); 256 Log.v(TAG, "Image saved. Frame number = " + captureResult.getFrameNumber()); 257 } 258 } 259 260 /** 261 * Instantiates a new camera based on Camera 2 API. 262 * 263 * @param device The underlying Camera 2 device. 264 * @param characteristics The device's characteristics. 265 * @param pictureSize the size of the final image to be taken. 266 */ 267 OneCameraZslImpl(CameraDevice device, CameraCharacteristics characteristics, Size pictureSize) { 268 Log.v(TAG, "Creating new OneCameraZslImpl"); 269 270 mDevice = device; 271 mCharacteristics = characteristics; 272 mFullSizeAspectRatio = calculateFullSizeAspectRatio(characteristics); 273 274 mCameraThread = new HandlerThread("OneCamera2"); 275 // If this thread stalls, it will delay viewfinder frames. 276 mCameraThread.setPriority(Thread.MAX_PRIORITY); 277 mCameraThread.start(); 278 mCameraHandler = new Handler(mCameraThread.getLooper()); 279 280 mCameraListenerThread = new HandlerThread("OneCamera2-Listener"); 281 mCameraListenerThread.start(); 282 mCameraListenerHandler = new Handler(mCameraListenerThread.getLooper()); 283 284 // TODO: Encoding on multiple cores results in preview jank due to 285 // excessive GC. 286 int numEncodingCores = CameraUtil.getNumCpuCores(); 287 mImageSaverThreadPool = new ThreadPoolExecutor(numEncodingCores, numEncodingCores, 10, 288 TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>()); 289 290 mCaptureManager = new ImageCaptureManager(MAX_CAPTURE_IMAGES, mCameraListenerHandler, 291 mImageSaverThreadPool); 292 mCaptureManager.setCaptureReadyListener(new ImageCaptureManager.CaptureReadyListener() { 293 @Override 294 public void onReadyStateChange(boolean capturePossible) { 295 mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_MANAGER_READY, 296 capturePossible); 297 } 298 }); 299 300 // Listen for changes to auto focus state and dispatch to 301 // mFocusStateListener. 302 mCaptureManager.addMetadataChangeListener(CaptureResult.CONTROL_AF_STATE, 303 new ImageCaptureManager.MetadataChangeListener() { 304 @Override 305 public void onImageMetadataChange(Key<?> key, Object oldValue, Object newValue, 306 CaptureResult result) { 307 mFocusStateListener.onFocusStatusUpdate( 308 AutoFocusHelper.stateFromCamera2State( 309 result.get(CaptureResult.CONTROL_AF_STATE)), 310 result.getFrameNumber()); 311 } 312 }); 313 314 // Allocate the image reader to store all images received from the 315 // camera. 316 if (pictureSize == null) { 317 // TODO The default should be selected by the caller, and 318 // pictureSize should never be null. 319 pictureSize = getDefaultPictureSize(); 320 } 321 mCaptureImageReader = ImageReader.newInstance(pictureSize.getWidth(), 322 pictureSize.getHeight(), 323 sCaptureImageFormat, MAX_CAPTURE_IMAGES); 324 325 mCaptureImageReader.setOnImageAvailableListener(mCaptureManager, mCameraHandler); 326 mMediaActionSound.load(MediaActionSound.SHUTTER_CLICK); 327 } 328 329 /** 330 * @return The largest supported picture size. 331 */ 332 public Size getDefaultPictureSize() { 333 StreamConfigurationMap configs = mCharacteristics.get( 334 CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 335 android.util.Size[] supportedSizes = configs.getOutputSizes(sCaptureImageFormat); 336 337 // Find the largest supported size. 338 android.util.Size largestSupportedSize = supportedSizes[0]; 339 long largestSupportedSizePixels = largestSupportedSize.getWidth() 340 * largestSupportedSize.getHeight(); 341 for (int i = 0; i < supportedSizes.length; i++) { 342 long numPixels = supportedSizes[i].getWidth() * supportedSizes[i].getHeight(); 343 if (numPixels > largestSupportedSizePixels) { 344 largestSupportedSize = supportedSizes[i]; 345 largestSupportedSizePixels = numPixels; 346 } 347 } 348 349 return new Size(largestSupportedSize.getWidth(), 350 largestSupportedSize.getHeight()); 351 } 352 353 private void onShutterInvokeUI(final PhotoCaptureParameters params) { 354 // Tell CaptureModule shutter has occurred so it can flash the screen. 355 params.callback.onQuickExpose(); 356 // Play shutter click sound. 357 mMediaActionSound.play(MediaActionSound.SHUTTER_CLICK); 358 } 359 360 /** 361 * Take a picture. 362 */ 363 @Override 364 public void takePicture(final PhotoCaptureParameters params, final CaptureSession session) { 365 params.checkSanity(); 366 367 mReadyStateManager.setInput( 368 ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, false); 369 370 boolean useZSL = ZSL_ENABLED; 371 372 // We will only capture images from the zsl ring-buffer which satisfy 373 // this constraint. 374 ArrayList<ImageCaptureManager.CapturedImageConstraint> zslConstraints = new ArrayList< 375 ImageCaptureManager.CapturedImageConstraint>(); 376 zslConstraints.add(new ImageCaptureManager.CapturedImageConstraint() { 377 @Override 378 public boolean satisfiesConstraint(TotalCaptureResult captureResult) { 379 Long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP); 380 Integer lensState = captureResult.get(CaptureResult.LENS_STATE); 381 Integer flashState = captureResult.get(CaptureResult.FLASH_STATE); 382 Integer flashMode = captureResult.get(CaptureResult.FLASH_MODE); 383 Integer aeState = captureResult.get(CaptureResult.CONTROL_AE_STATE); 384 Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE); 385 Integer awbState = captureResult.get(CaptureResult.CONTROL_AWB_STATE); 386 387 if (timestamp <= mLastCapturedImageTimestamp.get()) { 388 // Don't save frames older than the most 389 // recently-captured frame. 390 // TODO This technically has a race condition in which 391 // duplicate frames may be saved, but if a user is 392 // tapping at >30Hz, duplicate images may be what they 393 // expect. 394 return false; 395 } 396 397 if (lensState == CaptureResult.LENS_STATE_MOVING) { 398 // If we know the lens was moving, don't use this image. 399 return false; 400 } 401 402 if (aeState == CaptureResult.CONTROL_AE_STATE_SEARCHING 403 || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { 404 return false; 405 } 406 switch (params.flashMode) { 407 case OFF: 408 break; 409 case ON: 410 if (flashState != CaptureResult.FLASH_STATE_FIRED 411 || flashMode != CaptureResult.FLASH_MODE_SINGLE) { 412 return false; 413 } 414 break; 415 case AUTO: 416 if (aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED 417 && flashState != CaptureResult.FLASH_STATE_FIRED) { 418 return false; 419 } 420 break; 421 } 422 423 if (afState == CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN 424 || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN) { 425 return false; 426 } 427 428 if (awbState == CaptureResult.CONTROL_AWB_STATE_SEARCHING) { 429 return false; 430 } 431 432 return true; 433 } 434 }); 435 // This constraint lets us capture images which have been explicitly 436 // requested. See {@link RequestTag.EXPLICIT_CAPTURE}. 437 ArrayList<ImageCaptureManager.CapturedImageConstraint> singleCaptureConstraint = new ArrayList< 438 ImageCaptureManager.CapturedImageConstraint>(); 439 singleCaptureConstraint.add(new ImageCaptureManager.CapturedImageConstraint() { 440 @Override 441 public boolean satisfiesConstraint(TotalCaptureResult captureResult) { 442 Object tag = captureResult.getRequest().getTag(); 443 return tag == RequestTag.EXPLICIT_CAPTURE; 444 } 445 }); 446 447 // If we can use ZSL, try to save a previously-captured frame, if an 448 // acceptable one exists in the buffer. 449 if (useZSL) { 450 boolean capturedPreviousFrame = mCaptureManager.tryCaptureExistingImage( 451 new ImageCaptureTask(params, session), zslConstraints); 452 if (capturedPreviousFrame) { 453 Log.v(TAG, "Saving previous frame"); 454 onShutterInvokeUI(params); 455 } else { 456 Log.v(TAG, "No good image Available. Capturing next available good image."); 457 // If there was no good frame available in the ring buffer 458 // already, capture the next good image. 459 // TODO Disable the shutter button until this image is captured. 460 461 if (params.flashMode == Flash.ON || params.flashMode == Flash.AUTO) { 462 // We must issue a request for a single capture using the 463 // flash, including an AE precapture trigger. 464 465 // The following sets up a sequence of events which will 466 // occur in reverse order to the associated method 467 // calls: 468 // 1. Send a request to trigger the Auto Exposure Precapture 469 // 2. Wait for the AE_STATE to leave the PRECAPTURE state, 470 // and then send a request for a single image, with the 471 // appropriate flash settings. 472 // 3. Capture the next appropriate image, which should be 473 // the one we requested in (2). 474 475 mCaptureManager.captureNextImage(new ImageCaptureTask(params, session), 476 singleCaptureConstraint); 477 478 mCaptureManager.addMetadataChangeListener(CaptureResult.CONTROL_AE_STATE, 479 new MetadataChangeListener() { 480 @Override 481 public void onImageMetadataChange(Key<?> key, Object oldValue, 482 Object newValue, CaptureResult result) { 483 Log.v(TAG, "AE State Changed"); 484 if (oldValue.equals( 485 Integer.valueOf( 486 CaptureResult.CONTROL_AE_STATE_PRECAPTURE))) { 487 mCaptureManager.removeMetadataChangeListener(key, this); 488 sendSingleRequest(params); 489 // TODO: Delay this until onCaptureStarted(). 490 onShutterInvokeUI(params); 491 } 492 } 493 }); 494 495 sendAutoExposureTriggerRequest(params.flashMode); 496 } else { 497 // We may get here if, for example, the auto focus is in the 498 // middle of a scan. 499 // If the flash is off, we should just wait for the next 500 // image that arrives. This will have minimal delay since we 501 // do not need to send a new capture request. 502 mCaptureManager.captureNextImage(new ImageCaptureTask(params, session), 503 zslConstraints); 504 } 505 } 506 } else { 507 // TODO If we can't save a previous frame, create a new capture 508 // request to do what we need (e.g. flash) and call 509 // captureNextImage(). 510 throw new UnsupportedOperationException("Non-ZSL capture not yet supported"); 511 } 512 } 513 514 @Override 515 public void startPreview(Surface previewSurface, CaptureReadyCallback listener) { 516 mPreviewSurface = previewSurface; 517 setupAsync(mPreviewSurface, listener); 518 } 519 520 @Override 521 public void setViewfinderSize(int width, int height) { 522 throw new RuntimeException("Not implemented yet."); 523 } 524 525 @Override 526 public boolean isFlashSupported(boolean enhanced) { 527 throw new RuntimeException("Not implemented yet."); 528 } 529 530 @Override 531 public boolean isSupportingEnhancedMode() { 532 throw new RuntimeException("Not implemented yet."); 533 } 534 535 @Override 536 public void close(CloseCallback closeCallback) { 537 if (mIsClosed) { 538 Log.w(TAG, "Camera is already closed."); 539 return; 540 } 541 try { 542 mCaptureSession.abortCaptures(); 543 } catch (CameraAccessException e) { 544 Log.e(TAG, "Could not abort captures in progress."); 545 } 546 mIsClosed = true; 547 mCloseCallback = closeCallback; 548 mCameraThread.quitSafely(); 549 mDevice.close(); 550 mCaptureManager.close(); 551 } 552 553 @Override 554 public Size[] getSupportedSizes() { 555 StreamConfigurationMap config = mCharacteristics 556 .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); 557 return Size.convert(config.getOutputSizes(sCaptureImageFormat)); 558 } 559 560 @Override 561 public float getFullSizeAspectRatio() { 562 return mFullSizeAspectRatio; 563 } 564 565 @Override 566 public boolean isFrontFacing() { 567 return mCharacteristics.get(CameraCharacteristics.LENS_FACING) 568 == CameraMetadata.LENS_FACING_FRONT; 569 } 570 571 @Override 572 public boolean isBackFacing() { 573 return mCharacteristics.get(CameraCharacteristics.LENS_FACING) 574 == CameraMetadata.LENS_FACING_BACK; 575 } 576 577 private void savePicture(Image image, final PhotoCaptureParameters captureParams, 578 CaptureSession session) { 579 int heading = captureParams.heading; 580 581 int width = image.getWidth(); 582 int height = image.getHeight(); 583 int rotation = 0; 584 ExifInterface exif = null; 585 586 exif = new ExifInterface(); 587 // TODO: Add more exif tags here. 588 589 exif.setTag(exif.buildTag(ExifInterface.TAG_PIXEL_X_DIMENSION, width)); 590 exif.setTag(exif.buildTag(ExifInterface.TAG_PIXEL_Y_DIMENSION, height)); 591 592 // TODO: Handle rotation correctly. 593 594 // Set GPS heading direction based on sensor, if location is on. 595 if (heading >= 0) { 596 ExifTag directionRefTag = exif.buildTag( 597 ExifInterface.TAG_GPS_IMG_DIRECTION_REF, 598 ExifInterface.GpsTrackRef.MAGNETIC_DIRECTION); 599 ExifTag directionTag = exif.buildTag( 600 ExifInterface.TAG_GPS_IMG_DIRECTION, 601 new Rational(heading, 1)); 602 exif.setTag(directionRefTag); 603 exif.setTag(directionTag); 604 } 605 606 session.saveAndFinish(acquireJpegBytes(image), width, height, rotation, exif, 607 new OnMediaSavedListener() { 608 @Override 609 public void onMediaSaved(Uri uri) { 610 captureParams.callback.onPictureSaved(uri); 611 } 612 }); 613 } 614 615 /** 616 * Asynchronously sets up the capture session. 617 * 618 * @param previewSurface the surface onto which the preview should be 619 * rendered. 620 * @param listener called when setup is completed. 621 */ 622 private void setupAsync(final Surface previewSurface, final CaptureReadyCallback listener) { 623 mCameraHandler.post(new Runnable() { 624 @Override 625 public void run() { 626 setup(previewSurface, listener); 627 } 628 }); 629 } 630 631 /** 632 * Configures and attempts to create a capture session. 633 * 634 * @param previewSurface the surface onto which the preview should be 635 * rendered. 636 * @param listener called when the setup is completed. 637 */ 638 private void setup(Surface previewSurface, final CaptureReadyCallback listener) { 639 try { 640 if (mCaptureSession != null) { 641 mCaptureSession.abortCaptures(); 642 mCaptureSession = null; 643 } 644 List<Surface> outputSurfaces = new ArrayList<Surface>(2); 645 outputSurfaces.add(previewSurface); 646 outputSurfaces.add(mCaptureImageReader.getSurface()); 647 648 mDevice.createCaptureSession(outputSurfaces, new CameraCaptureSession.StateCallback() { 649 @Override 650 public void onConfigureFailed(CameraCaptureSession session) { 651 listener.onSetupFailed(); 652 } 653 654 @Override 655 public void onConfigured(CameraCaptureSession session) { 656 mCaptureSession = session; 657 mAFRegions = ZERO_WEIGHT_3A_REGION; 658 mAERegions = ZERO_WEIGHT_3A_REGION; 659 mZoomValue = 1f; 660 mCropRegion = cropRegionForZoom(mZoomValue); 661 boolean success = sendRepeatingCaptureRequest(); 662 if (success) { 663 mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, 664 true); 665 mReadyStateManager.notifyListeners(); 666 listener.onReadyForCapture(); 667 } else { 668 listener.onSetupFailed(); 669 } 670 } 671 672 @Override 673 public void onClosed(CameraCaptureSession session) { 674 super.onClosed(session); 675 if (mCloseCallback != null) { 676 mCloseCallback.onCameraClosed(); 677 } 678 } 679 }, mCameraHandler); 680 } catch (CameraAccessException ex) { 681 Log.e(TAG, "Could not set up capture session", ex); 682 listener.onSetupFailed(); 683 } 684 } 685 686 private void addRegionsToCaptureRequestBuilder(CaptureRequest.Builder builder) { 687 builder.set(CaptureRequest.CONTROL_AE_REGIONS, mAERegions); 688 builder.set(CaptureRequest.CONTROL_AF_REGIONS, mAFRegions); 689 builder.set(CaptureRequest.SCALER_CROP_REGION, mCropRegion); 690 } 691 692 private void addFlashToCaptureRequestBuilder(CaptureRequest.Builder builder, Flash flashMode) { 693 switch (flashMode) { 694 case ON: 695 builder.set(CaptureRequest.CONTROL_AE_MODE, 696 CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH); 697 builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE); 698 break; 699 case OFF: 700 builder.set(CaptureRequest.CONTROL_AE_MODE, 701 CaptureRequest.CONTROL_AE_MODE_ON); 702 builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF); 703 break; 704 case AUTO: 705 builder.set(CaptureRequest.CONTROL_AE_MODE, 706 CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); 707 break; 708 } 709 } 710 711 /** 712 * Request a stream of images. 713 * 714 * @return true if successful, false if there was an error submitting the 715 * capture request. 716 */ 717 private boolean sendRepeatingCaptureRequest() { 718 Log.v(TAG, "sendRepeatingCaptureRequest()"); 719 try { 720 CaptureRequest.Builder builder; 721 if (ZSL_ENABLED) { 722 builder = mDevice. 723 createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); 724 } else { 725 builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 726 } 727 728 builder.addTarget(mPreviewSurface); 729 730 if (ZSL_ENABLED) { 731 builder.addTarget(mCaptureImageReader.getSurface()); 732 } 733 734 builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); 735 736 builder.set(CaptureRequest.CONTROL_AF_MODE, 737 CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); 738 builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 739 740 builder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 741 builder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF); 742 743 addRegionsToCaptureRequestBuilder(builder); 744 745 mCaptureSession.setRepeatingRequest(builder.build(), mCaptureManager, 746 mCameraHandler); 747 return true; 748 } catch (CameraAccessException e) { 749 if (ZSL_ENABLED) { 750 Log.v(TAG, "Could not execute zero-shutter-lag repeating request.", e); 751 } else { 752 Log.v(TAG, "Could not execute preview request.", e); 753 } 754 return false; 755 } 756 } 757 758 /** 759 * Request a single image. 760 * 761 * @return true if successful, false if there was an error submitting the 762 * capture request. 763 */ 764 private boolean sendSingleRequest(OneCamera.PhotoCaptureParameters params) { 765 Log.v(TAG, "sendSingleRequest()"); 766 try { 767 CaptureRequest.Builder builder; 768 builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 769 770 builder.addTarget(mPreviewSurface); 771 772 // Always add this surface for single image capture requests. 773 builder.addTarget(mCaptureImageReader.getSurface()); 774 775 builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); 776 777 addFlashToCaptureRequestBuilder(builder, params.flashMode); 778 addRegionsToCaptureRequestBuilder(builder); 779 780 builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); 781 builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 782 783 // Tag this as a special request which should be saved. 784 builder.setTag(RequestTag.EXPLICIT_CAPTURE); 785 786 if (sCaptureImageFormat == ImageFormat.JPEG) { 787 builder.set(CaptureRequest.JPEG_QUALITY, (byte) (JPEG_QUALITY)); 788 builder.set(CaptureRequest.JPEG_ORIENTATION, 789 CameraUtil.getJpegRotation(params.orientation, mCharacteristics)); 790 } 791 792 mCaptureSession.capture(builder.build(), mCaptureManager, 793 mCameraHandler); 794 return true; 795 } catch (CameraAccessException e) { 796 Log.v(TAG, "Could not execute single still capture request.", e); 797 return false; 798 } 799 } 800 801 private boolean sendAutoExposureTriggerRequest(Flash flashMode) { 802 Log.v(TAG, "sendAutoExposureTriggerRequest()"); 803 try { 804 CaptureRequest.Builder builder; 805 if (ZSL_ENABLED) { 806 builder = mDevice. 807 createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); 808 } else { 809 builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 810 } 811 812 builder.addTarget(mPreviewSurface); 813 814 if (ZSL_ENABLED) { 815 builder.addTarget(mCaptureImageReader.getSurface()); 816 } 817 818 builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); 819 820 builder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, 821 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); 822 823 addRegionsToCaptureRequestBuilder(builder); 824 addFlashToCaptureRequestBuilder(builder, flashMode); 825 826 mCaptureSession.capture(builder.build(), mCaptureManager, 827 mCameraHandler); 828 829 return true; 830 } catch (CameraAccessException e) { 831 Log.v(TAG, "Could not execute auto exposure trigger request.", e); 832 return false; 833 } 834 } 835 836 /** 837 */ 838 private boolean sendAutoFocusTriggerRequest() { 839 Log.v(TAG, "sendAutoFocusTriggerRequest()"); 840 try { 841 CaptureRequest.Builder builder; 842 if (ZSL_ENABLED) { 843 builder = mDevice. 844 createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); 845 } else { 846 builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 847 } 848 849 builder.addTarget(mPreviewSurface); 850 851 if (ZSL_ENABLED) { 852 builder.addTarget(mCaptureImageReader.getSurface()); 853 } 854 855 builder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_AUTO); 856 857 addRegionsToCaptureRequestBuilder(builder); 858 859 builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO); 860 builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_START); 861 862 mCaptureSession.capture(builder.build(), mCaptureManager, 863 mCameraHandler); 864 865 return true; 866 } catch (CameraAccessException e) { 867 Log.v(TAG, "Could not execute auto focus trigger request.", e); 868 return false; 869 } 870 } 871 872 /** 873 * Like {@link #sendRepeatingCaptureRequest()}, but with the focus held 874 * constant. 875 * 876 * @return true if successful, false if there was an error submitting the 877 * capture request. 878 */ 879 private boolean sendAutoFocusHoldRequest() { 880 Log.v(TAG, "sendAutoFocusHoldRequest()"); 881 try { 882 CaptureRequest.Builder builder; 883 if (ZSL_ENABLED) { 884 builder = mDevice. 885 createCaptureRequest(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG); 886 } else { 887 builder = mDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); 888 } 889 890 builder.addTarget(mPreviewSurface); 891 892 if (ZSL_ENABLED) { 893 builder.addTarget(mCaptureImageReader.getSurface()); 894 } 895 896 builder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_AUTO); 897 898 builder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CONTROL_AF_MODE_AUTO); 899 builder.set(CaptureRequest.CONTROL_AF_TRIGGER, CaptureRequest.CONTROL_AF_TRIGGER_IDLE); 900 901 addRegionsToCaptureRequestBuilder(builder); 902 // TODO: This should fire the torch, if appropriate. 903 904 mCaptureSession.setRepeatingRequest(builder.build(), mCaptureManager, mCameraHandler); 905 906 return true; 907 } catch (CameraAccessException e) { 908 Log.v(TAG, "Could not execute auto focus hold request.", e); 909 return false; 910 } 911 } 912 913 /** 914 * Calculate the aspect ratio of the full size capture on this device. 915 * 916 * @param characteristics the characteristics of the camera device. 917 * @return The aspect ration, in terms of width/height of the full capture 918 * size. 919 */ 920 private static float calculateFullSizeAspectRatio(CameraCharacteristics characteristics) { 921 Rect activeArraySize = 922 characteristics.get(CameraCharacteristics.SENSOR_INFO_ACTIVE_ARRAY_SIZE); 923 return ((float) activeArraySize.width()) / activeArraySize.height(); 924 } 925 926 /** 927 * Given an image reader, extracts the JPEG image bytes and then closes the 928 * reader. 929 * 930 * @param img the image from which to extract jpeg bytes or compress to 931 * jpeg. 932 * @return The bytes of the JPEG image. Newly allocated. 933 */ 934 private byte[] acquireJpegBytes(Image img) { 935 ByteBuffer buffer; 936 937 if (img.getFormat() == ImageFormat.JPEG) { 938 Image.Plane plane0 = img.getPlanes()[0]; 939 buffer = plane0.getBuffer(); 940 941 byte[] imageBytes = new byte[buffer.remaining()]; 942 buffer.get(imageBytes); 943 buffer.rewind(); 944 return imageBytes; 945 } else if (img.getFormat() == ImageFormat.YUV_420_888) { 946 buffer = mJpegByteBufferPool.acquire(); 947 if (buffer == null) { 948 buffer = ByteBuffer.allocateDirect(img.getWidth() * img.getHeight() * 3); 949 } 950 951 int numBytes = JpegUtilNative.compressJpegFromYUV420Image(img, buffer, JPEG_QUALITY); 952 953 if (numBytes < 0) { 954 throw new RuntimeException("Error compressing jpeg."); 955 } 956 957 buffer.limit(numBytes); 958 959 byte[] imageBytes = new byte[buffer.remaining()]; 960 buffer.get(imageBytes); 961 962 buffer.clear(); 963 mJpegByteBufferPool.release(buffer); 964 965 return imageBytes; 966 } else { 967 throw new RuntimeException("Unsupported image format."); 968 } 969 } 970 971 private void startAFCycle() { 972 // Clean up any existing AF cycle's pending callbacks. 973 mCameraHandler.removeCallbacksAndMessages(FOCUS_RESUME_CALLBACK_TOKEN); 974 975 // Send a single CONTROL_AF_TRIGGER_START capture request. 976 sendAutoFocusTriggerRequest(); 977 978 // Immediately send a request for a regular preview stream, but with 979 // CONTROL_AF_MODE_AUTO set so that the focus remains constant after the 980 // AF cycle completes. 981 sendAutoFocusHoldRequest(); 982 983 // Waits Settings3A.getFocusHoldMillis() milliseconds before sending 984 // a request for a regular preview stream to resume. 985 mCameraHandler.postAtTime(new Runnable() { 986 @Override 987 public void run() { 988 mAERegions = ZERO_WEIGHT_3A_REGION; 989 mAFRegions = ZERO_WEIGHT_3A_REGION; 990 sendRepeatingCaptureRequest(); 991 } 992 }, FOCUS_RESUME_CALLBACK_TOKEN, 993 SystemClock.uptimeMillis() + Settings3A.getFocusHoldMillis()); 994 } 995 996 /** 997 * @see com.android.camera.one.OneCamera#triggerFocusAndMeterAtPoint(float, 998 * float) 999 */ 1000 @Override 1001 public void triggerFocusAndMeterAtPoint(float nx, float ny) { 1002 int sensorOrientation = mCharacteristics.get( 1003 CameraCharacteristics.SENSOR_ORIENTATION); 1004 mAERegions = AutoFocusHelper.aeRegionsForNormalizedCoord(nx, ny, mCropRegion, sensorOrientation); 1005 mAFRegions = AutoFocusHelper.afRegionsForNormalizedCoord(nx, ny, mCropRegion, sensorOrientation); 1006 1007 startAFCycle(); 1008 } 1009 1010 @Override 1011 public Size pickPreviewSize(Size pictureSize, Context context) { 1012 if (pictureSize == null) { 1013 // TODO The default should be selected by the caller, and 1014 // pictureSize should never be null. 1015 pictureSize = getDefaultPictureSize(); 1016 } 1017 float pictureAspectRatio = pictureSize.getWidth() / (float) pictureSize.getHeight(); 1018 return CaptureModuleUtil.getOptimalPreviewSize(context, getSupportedSizes(), 1019 pictureAspectRatio); 1020 } 1021 1022 @Override 1023 public float getMaxZoom() { 1024 return mCharacteristics.get(CameraCharacteristics.SCALER_AVAILABLE_MAX_DIGITAL_ZOOM); 1025 } 1026 1027 @Override 1028 public void setZoom(float zoom) { 1029 mZoomValue = zoom; 1030 mCropRegion = cropRegionForZoom(zoom); 1031 sendRepeatingCaptureRequest(); 1032 } 1033 1034 private Rect cropRegionForZoom(float zoom) { 1035 return AutoFocusHelper.cropRegionForZoom(mCharacteristics, zoom); 1036 } 1037 } 1038