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 |