| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.media; | 5 package org.chromium.media; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.graphics.ImageFormat; | 9 import android.graphics.ImageFormat; |
| 10 import android.graphics.Rect; | 10 import android.graphics.Rect; |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 private int mPhotoHeight; | 271 private int mPhotoHeight; |
| 272 private int mFocusMode = AndroidMeteringMode.CONTINUOUS; | 272 private int mFocusMode = AndroidMeteringMode.CONTINUOUS; |
| 273 private int mExposureMode = AndroidMeteringMode.CONTINUOUS; | 273 private int mExposureMode = AndroidMeteringMode.CONTINUOUS; |
| 274 private MeteringRectangle mAreaOfInterest; | 274 private MeteringRectangle mAreaOfInterest; |
| 275 private int mExposureCompensation; | 275 private int mExposureCompensation; |
| 276 private int mWhiteBalanceMode = AndroidMeteringMode.CONTINUOUS; | 276 private int mWhiteBalanceMode = AndroidMeteringMode.CONTINUOUS; |
| 277 private int mColorTemperature = -1; | 277 private int mColorTemperature = -1; |
| 278 private int mIso; | 278 private int mIso; |
| 279 private boolean mRedEyeReduction; | 279 private boolean mRedEyeReduction; |
| 280 private int mFillLightMode = AndroidFillLightMode.OFF; | 280 private int mFillLightMode = AndroidFillLightMode.OFF; |
| 281 private boolean mTorch; |
| 281 | 282 |
| 282 // Service function to grab CameraCharacteristics and handle exceptions. | 283 // Service function to grab CameraCharacteristics and handle exceptions. |
| 283 private static CameraCharacteristics getCameraCharacteristics(Context appCon
text, int id) { | 284 private static CameraCharacteristics getCameraCharacteristics(Context appCon
text, int id) { |
| 284 final CameraManager manager = | 285 final CameraManager manager = |
| 285 (CameraManager) appContext.getSystemService(Context.CAMERA_SERVI
CE); | 286 (CameraManager) appContext.getSystemService(Context.CAMERA_SERVI
CE); |
| 286 try { | 287 try { |
| 287 return manager.getCameraCharacteristics(Integer.toString(id)); | 288 return manager.getCameraCharacteristics(Integer.toString(id)); |
| 288 } catch (CameraAccessException ex) { | 289 } catch (CameraAccessException ex) { |
| 289 Log.e(TAG, "getCameraCharacteristics: ", ex); | 290 Log.e(TAG, "getCameraCharacteristics: ", ex); |
| 290 } | 291 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, | 365 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, |
| 365 CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE); | 366 CameraMetadata.CONTROL_AF_MODE_CONTINUOUS_PICTURE); |
| 366 requestBuilder.set( | 367 requestBuilder.set( |
| 367 CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF
_TRIGGER_START); | 368 CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF
_TRIGGER_START); |
| 368 } else if (mFocusMode == AndroidMeteringMode.FIXED) { | 369 } else if (mFocusMode == AndroidMeteringMode.FIXED) { |
| 369 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CO
NTROL_AF_MODE_OFF); | 370 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CameraMetadata.CO
NTROL_AF_MODE_OFF); |
| 370 // TODO(mcasas): Support controlling LENS_FOCUS_DISTANCE in this mod
e, | 371 // TODO(mcasas): Support controlling LENS_FOCUS_DISTANCE in this mod
e, |
| 371 // https://crbug.com/518807. | 372 // https://crbug.com/518807. |
| 372 } | 373 } |
| 373 | 374 |
| 374 // |mExposureMode| and |mFillLightMode| interact to configure the AE and
Flash modes. In a | 375 // |mExposureMode|, |mFillLightMode| and |mTorch| interact to configure
the AE and Flash |
| 375 // nutshell, FLASH_MODE is only effective if the auto-exposure is ON/OFF
, otherwise the | 376 // modes. In a nutshell, FLASH_MODE is only effective if the auto-exposu
re is ON/OFF, |
| 376 // auto-exposure related flash control (ON_{AUTO,ALWAYS}_FLASH{_REDEYE)
takes priority. | 377 // otherwise the auto-exposure related flash control (ON_{AUTO,ALWAYS}_F
LASH{_REDEYE) takes |
| 378 // priority. |mTorch| mode overrides any previous |mFillLightMode| flas
h control. |
| 377 if (mExposureMode == AndroidMeteringMode.NONE | 379 if (mExposureMode == AndroidMeteringMode.NONE |
| 378 || mExposureMode == AndroidMeteringMode.FIXED) { | 380 || mExposureMode == AndroidMeteringMode.FIXED) { |
| 379 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CO
NTROL_AE_MODE_OFF); | 381 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CO
NTROL_AE_MODE_OFF); |
| 380 } else { | 382 } else { |
| 381 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CO
NTROL_AE_MODE_ON); | 383 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CO
NTROL_AE_MODE_ON); |
| 382 requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mAeFp
sRange); | 384 requestBuilder.set(CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE, mAeFp
sRange); |
| 383 } | 385 } |
| 384 switch (mFillLightMode) { | 386 switch (mFillLightMode) { |
| 385 case AndroidFillLightMode.OFF: | 387 case AndroidFillLightMode.OFF: |
| 386 requestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLA
SH_MODE_OFF); | 388 requestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLA
SH_MODE_OFF); |
| 387 break; | 389 break; |
| 388 case AndroidFillLightMode.AUTO: | 390 case AndroidFillLightMode.AUTO: |
| 389 // Setting the AE to CONTROL_AE_MODE_ON_AUTO_FLASH[_REDEYE] over
rides FLASH_MODE. | 391 // Setting the AE to CONTROL_AE_MODE_ON_AUTO_FLASH[_REDEYE] over
rides FLASH_MODE. |
| 390 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, mRedEyeReduct
ion | 392 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, mRedEyeReduct
ion |
| 391 ? CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_R
EDEYE | 393 ? CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_R
EDEYE |
| 392 : CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH); | 394 : CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH); |
| 393 break; | 395 break; |
| 394 case AndroidFillLightMode.FLASH: | 396 case AndroidFillLightMode.FLASH: |
| 395 // Setting the AE to CONTROL_AE_MODE_ON_ALWAYS_FLASH overrides F
LASH_MODE. | 397 // Setting the AE to CONTROL_AE_MODE_ON_ALWAYS_FLASH overrides F
LASH_MODE. |
| 396 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, | 398 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, |
| 397 CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH); | 399 CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH); |
| 398 break; | 400 break; |
| 399 case AndroidFillLightMode.TORCH: | 401 default: |
| 400 requestBuilder.set( | |
| 401 CaptureRequest.CONTROL_AE_MODE, CameraMetadata.CONTROL_A
E_MODE_ON); | |
| 402 requestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLA
SH_MODE_TORCH); | |
| 403 break; | |
| 404 case AndroidFillLightMode.NONE: | |
| 405 // NONE is only used for getting capabilities, to signify "no fl
ash unit". Ignore. | |
| 406 } | 402 } |
| 403 if (mTorch) requestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata
.FLASH_MODE_TORCH); |
| 404 |
| 407 requestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, mExp
osureCompensation); | 405 requestBuilder.set(CaptureRequest.CONTROL_AE_EXPOSURE_COMPENSATION, mExp
osureCompensation); |
| 408 | 406 |
| 409 // White Balance mode AndroidMeteringMode.SINGLE_SHOT is not supported. | 407 // White Balance mode AndroidMeteringMode.SINGLE_SHOT is not supported. |
| 410 if (mWhiteBalanceMode == AndroidMeteringMode.CONTINUOUS) { | 408 if (mWhiteBalanceMode == AndroidMeteringMode.CONTINUOUS) { |
| 411 requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, false); | 409 requestBuilder.set(CaptureRequest.CONTROL_AWB_LOCK, false); |
| 412 requestBuilder.set( | 410 requestBuilder.set( |
| 413 CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_
MODE_AUTO); | 411 CaptureRequest.CONTROL_AWB_MODE, CameraMetadata.CONTROL_AWB_
MODE_AUTO); |
| 414 // TODO(mcasas): support different luminant color temperatures, e.g.
DAYLIGHT, SHADE. | 412 // TODO(mcasas): support different luminant color temperatures, e.g.
DAYLIGHT, SHADE. |
| 415 // https://crbug.com/518807 | 413 // https://crbug.com/518807 |
| 416 } else if (mWhiteBalanceMode == AndroidMeteringMode.NONE) { | 414 } else if (mWhiteBalanceMode == AndroidMeteringMode.NONE) { |
| (...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 792 builder.setMinColorTemperature(COLOR_TEMPERATURES_MAP.keyAt(0)); | 790 builder.setMinColorTemperature(COLOR_TEMPERATURES_MAP.keyAt(0)); |
| 793 builder.setMaxColorTemperature( | 791 builder.setMaxColorTemperature( |
| 794 COLOR_TEMPERATURES_MAP.keyAt(COLOR_TEMPERATURES_MAP.size() - 1))
; | 792 COLOR_TEMPERATURES_MAP.keyAt(COLOR_TEMPERATURES_MAP.size() - 1))
; |
| 795 final int index = COLOR_TEMPERATURES_MAP.indexOfValue(whiteBalanceMode); | 793 final int index = COLOR_TEMPERATURES_MAP.indexOfValue(whiteBalanceMode); |
| 796 if (index >= 0) { | 794 if (index >= 0) { |
| 797 builder.setCurrentColorTemperature(COLOR_TEMPERATURES_MAP.keyAt(inde
x)); | 795 builder.setCurrentColorTemperature(COLOR_TEMPERATURES_MAP.keyAt(inde
x)); |
| 798 } | 796 } |
| 799 builder.setStepColorTemperature(1); | 797 builder.setStepColorTemperature(1); |
| 800 | 798 |
| 801 if (!cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABL
E)) { | 799 if (!cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABL
E)) { |
| 802 builder.setFillLightMode(AndroidFillLightMode.NONE); | 800 builder.setTorch(false); |
| 801 builder.setRedEyeReduction(false); |
| 803 } else { | 802 } else { |
| 804 // CONTROL_AE_MODE overrides FLASH_MODE control unless it's in ON or
OFF states. | 803 // There's no way to query if torch and/or red eye reduction modes a
re available using |
| 805 switch (mPreviewRequest.get(CaptureRequest.CONTROL_AE_MODE)) { | 804 // Camera2 API but since there's a Flash unit, we assume so. |
| 806 case CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH_REDEYE: | 805 builder.setTorch(true); |
| 807 builder.setRedEyeReduction(true); | 806 builder.setRedEyeReduction(true); |
| 808 builder.setFillLightMode(AndroidFillLightMode.AUTO); | 807 |
| 809 break; | 808 final int[] flashModes = |
| 810 case CameraMetadata.CONTROL_AE_MODE_ON_AUTO_FLASH: | 809 cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE_A
VAILABLE_MODES); |
| 811 builder.setFillLightMode(AndroidFillLightMode.AUTO); | 810 ArrayList<Integer> modes = new ArrayList<Integer>(0); |
| 812 break; | 811 for (int flashMode : flashModes) { |
| 813 case CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS_FLASH: | 812 if (flashMode == CameraMetadata.FLASH_MODE_OFF) { |
| 814 builder.setFillLightMode(AndroidFillLightMode.FLASH); | 813 modes.add(Integer.valueOf(AndroidFillLightMode.OFF)); |
| 815 break; | 814 } else if (flashMode == CameraMetadata.CONTROL_AE_MODE_ON_AUTO_F
LASH) { |
| 816 case CameraMetadata.CONTROL_AE_MODE_OFF: | 815 modes.add(Integer.valueOf(AndroidFillLightMode.AUTO)); |
| 817 case CameraMetadata.CONTROL_AE_MODE_ON: | 816 } else if (flashMode == CameraMetadata.CONTROL_AE_MODE_ON_ALWAYS
_FLASH) { |
| 818 final Integer flashMode = mPreviewRequest.get(CaptureRequest
.FLASH_MODE); | 817 modes.add(Integer.valueOf(AndroidFillLightMode.FLASH)); |
| 819 if (flashMode == CameraMetadata.FLASH_MODE_OFF) { | 818 } |
| 820 builder.setFillLightMode(AndroidFillLightMode.OFF); | |
| 821 } else if (flashMode == CameraMetadata.FLASH_MODE_SINGLE) { | |
| 822 builder.setFillLightMode(AndroidFillLightMode.FLASH); | |
| 823 } else if (flashMode == CameraMetadata.FLASH_MODE_TORCH) { | |
| 824 builder.setFillLightMode(AndroidFillLightMode.TORCH); | |
| 825 } | |
| 826 break; | |
| 827 default: | |
| 828 builder.setFillLightMode(AndroidFillLightMode.NONE); | |
| 829 } | 819 } |
| 820 int[] modesAsIntArray = new int[modes.size()]; |
| 821 for (int i = 0; i < modes.size(); i++) modesAsIntArray[i] = modes.ge
t(i).intValue(); |
| 822 builder.setFillLightModes(modesAsIntArray); |
| 830 } | 823 } |
| 831 | 824 |
| 832 return builder.build(); | 825 return builder.build(); |
| 833 } | 826 } |
| 834 | 827 |
| 835 @Override | 828 @Override |
| 836 public void setPhotoOptions(double zoom, int focusMode, int exposureMode, do
uble width, | 829 public void setPhotoOptions(double zoom, int focusMode, int exposureMode, do
uble width, |
| 837 double height, float[] pointsOfInterest2D, boolean hasExposureCompen
sation, | 830 double height, float[] pointsOfInterest2D, boolean hasExposureCompen
sation, |
| 838 double exposureCompensation, int whiteBalanceMode, double iso, | 831 double exposureCompensation, int whiteBalanceMode, double iso, |
| 839 boolean hasRedEyeReduction, boolean redEyeReduction, int fillLightMo
de, | 832 boolean hasRedEyeReduction, boolean redEyeReduction, int fillLightMo
de, |
| 840 double colorTemperature) { | 833 boolean hasTorch, boolean torch, double colorTemperature) { |
| 841 final CameraCharacteristics cameraCharacteristics = getCameraCharacteris
tics(mContext, mId); | 834 final CameraCharacteristics cameraCharacteristics = getCameraCharacteris
tics(mContext, mId); |
| 842 final Rect canvas = | 835 final Rect canvas = |
| 843 cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTI
VE_ARRAY_SIZE); | 836 cameraCharacteristics.get(CameraCharacteristics.SENSOR_INFO_ACTI
VE_ARRAY_SIZE); |
| 844 | 837 |
| 845 if (zoom != 0) { | 838 if (zoom != 0) { |
| 846 final float normalizedZoom = Math.max(1.0f, Math.min((float) zoom, m
MaxZoom)); | 839 final float normalizedZoom = Math.max(1.0f, Math.min((float) zoom, m
MaxZoom)); |
| 847 final float cropFactor = (normalizedZoom - 1) / (2 * normalizedZoom)
; | 840 final float cropFactor = (normalizedZoom - 1) / (2 * normalizedZoom)
; |
| 848 | 841 |
| 849 mCropRect = new Rect(Math.round(canvas.width() * cropFactor), | 842 mCropRect = new Rect(Math.round(canvas.width() * cropFactor), |
| 850 Math.round(canvas.height() * cropFactor), | 843 Math.round(canvas.height() * cropFactor), |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 899 | 892 |
| 900 if (hasExposureCompensation) { | 893 if (hasExposureCompensation) { |
| 901 mExposureCompensation = (int) Math.round(exposureCompensation | 894 mExposureCompensation = (int) Math.round(exposureCompensation |
| 902 / cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE
_COMPENSATION_STEP) | 895 / cameraCharacteristics.get(CameraCharacteristics.CONTROL_AE
_COMPENSATION_STEP) |
| 903 .floatValue()); | 896 .floatValue()); |
| 904 } | 897 } |
| 905 if (iso > 0) mIso = (int) Math.round(iso); | 898 if (iso > 0) mIso = (int) Math.round(iso); |
| 906 if (mWhiteBalanceMode == AndroidMeteringMode.FIXED && colorTemperature >
0) { | 899 if (mWhiteBalanceMode == AndroidMeteringMode.FIXED && colorTemperature >
0) { |
| 907 mColorTemperature = (int) Math.round(colorTemperature); | 900 mColorTemperature = (int) Math.round(colorTemperature); |
| 908 } | 901 } |
| 902 |
| 903 if (hasRedEyeReduction) mRedEyeReduction = redEyeReduction; |
| 909 if (fillLightMode != AndroidFillLightMode.NOT_SET) mFillLightMode = fill
LightMode; | 904 if (fillLightMode != AndroidFillLightMode.NOT_SET) mFillLightMode = fill
LightMode; |
| 905 if (hasTorch) mTorch = torch; |
| 910 | 906 |
| 911 final Handler mainHandler = new Handler(mContext.getMainLooper()); | 907 final Handler mainHandler = new Handler(mContext.getMainLooper()); |
| 912 mainHandler.removeCallbacks(mRestartCapture); | 908 mainHandler.removeCallbacks(mRestartCapture); |
| 913 mainHandler.post(mRestartCapture); | 909 mainHandler.post(mRestartCapture); |
| 914 } | 910 } |
| 915 | 911 |
| 916 @Override | 912 @Override |
| 917 public boolean takePhoto(final long callbackId) { | 913 public boolean takePhoto(final long callbackId) { |
| 918 Log.d(TAG, "takePhoto"); | 914 Log.d(TAG, "takePhoto"); |
| 919 if (mCameraDevice == null || mCameraState != CameraState.STARTED) return
false; | 915 if (mCameraDevice == null || mCameraState != CameraState.STARTED) return
false; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 971 return false; | 967 return false; |
| 972 } | 968 } |
| 973 return true; | 969 return true; |
| 974 } | 970 } |
| 975 | 971 |
| 976 @Override | 972 @Override |
| 977 public void deallocate() { | 973 public void deallocate() { |
| 978 Log.d(TAG, "deallocate"); | 974 Log.d(TAG, "deallocate"); |
| 979 } | 975 } |
| 980 } | 976 } |
| OLD | NEW |