3package org.qtproject.qt.android.multimedia.qffmpeg;
5import android.annotation.SuppressLint;
6import android.annotation.TargetApi;
7import android.content.Context;
8import android.graphics.ImageFormat;
9import android.graphics.Rect;
10import android.hardware.camera2.CameraAccessException;
11import android.hardware.camera2.CameraCaptureSession;
12import android.hardware.camera2.CameraDevice;
13import android.hardware.camera2.CameraMetadata;
14import android.hardware.camera2.CameraManager;
15import android.hardware.camera2.CaptureFailure;
16import android.hardware.camera2.CaptureResult;
17import android.hardware.camera2.CaptureRequest;
18import android.hardware.camera2.params.OutputConfiguration;
19import android.hardware.camera2.params.SessionConfiguration;
20import android.media.Image;
21import android.media.ImageReader;
22import android.os.Handler;
23import android.os.HandlerThread;
24import android.util.Log;
25import android.util.Range;
26import android.view.Surface;
27import java.lang.Thread;
28import java.util.ArrayList;
30import java.util.concurrent.CountDownLatch;
31import java.util.concurrent.TimeUnit;
33import org.qtproject.qt.android.UsedFromNativeCode;
44 native
void onStillPhotoCaptureFailed(
long qAndroidCameraPtr);
49 private long mQAndroidCameraPtr = 0;
50 CameraDevice mCameraDevice =
null;
52 volatile CountDownLatch mDeviceClosedLatch =
null;
53 QtVideoDeviceManager mVideoDeviceManager =
null;
55 HandlerThread mBackgroundThread;
59 ImageReader mPreviewImageReader =
null;
61 ImageReader mStillPhotoImageReader =
null;
62 CameraManager mCameraManager;
63 CameraCaptureSession mCaptureSession;
66 volatile CameraCaptureSessionStateCallback mCurrentSessionCallback;
67 CaptureRequest.Builder mPreviewRequestBuilder;
68 CaptureRequest mPreviewRequest;
70 List<Surface> mTargetSurfaces =
new ArrayList<>();
72 private static int MaxNumberFrames = 12;
86 boolean mStillCaptureDeferred =
false;
93 boolean isTakingStillPhoto() {
94 return mState ==
State.Capturing;
97 void endStillPhoto() {
98 if (mState ==
State.Capturing)
99 mState =
State.Started;
102 private CameraSettings mCameraSettings =
new CameraSettings();
104 final SyncedMembers mSyncedMembers =
new SyncedMembers();
108 public void resetControlProperties() {
109 synchronized (mSyncedMembers) {
110 mSyncedMembers.mCameraSettings =
new CameraSettings();
114 long getQAndroidCameraPtr() {
118 assert(mQAndroidCameraPtr != 0);
119 return mQAndroidCameraPtr;
123 private CameraSettings atomicCameraSettingsCopy() {
124 synchronized (mSyncedMembers) {
125 return new CameraSettings(mSyncedMembers.mCameraSettings);
129 QtExifDataHandler mExifDataHandler =
null;
131 native
void onCameraOpened(
long qAndroidCameraPtr);
132 native
void onCameraDisconnect(
long qAndroidCameraPtr);
133 native
void onCameraError(
long qAndroidCameraPtr,
int error);
135 CameraDeviceStateCallback mStateCallback =
new CameraDeviceStateCallback(
this);
137 native
void onCaptureSessionConfigured(
long qAndroidCameraPtr);
138 native
void onCaptureSessionConfigureFailed(
long qAndroidCameraPtr);
139 native
void onStillReaderSwapFailed(
long qAndroidCameraPtr);
142 native
void onSessionActive(
long qAndroidCameraPtr);
143 native
void onSessionClosed(
long qAndroidCameraPtr);
144 native
void onCaptureSessionFailed(
long qAndroidCameraPtr,
int reason,
long frameNumber);
149 class PreviewCaptureSessionCallback
extends CameraCaptureSession.CaptureCallback {
151 public void onCaptureFailed(
152 CameraCaptureSession session,
154 CaptureFailure failure)
156 super.onCaptureFailed(session,
request, failure);
157 onCaptureSessionFailed(
158 getQAndroidCameraPtr(),
160 failure.getFrameNumber());
167 PreviewCaptureSessionCallback mPreviewCaptureCallback =
new PreviewCaptureSessionCallback();
169 QtCamera2(
long qAndroidCameraPtr,
Context context) {
170 assert(qAndroidCameraPtr != 0);
173 mQAndroidCameraPtr = qAndroidCameraPtr;
174 mCameraManager = (CameraManager)
context.getSystemService(
Context.CAMERA_SERVICE);
175 mVideoDeviceManager =
new QtVideoDeviceManager(context);
176 startBackgroundThread();
179 void startBackgroundThread() {
180 mBackgroundThread =
new HandlerThread(
"CameraBackground");
181 mBackgroundThread.start();
182 mBackgroundHandler =
new Handler(mBackgroundThread.getLooper());
186 void stopBackgroundThread() {
187 mBackgroundThread.quitSafely();
189 mBackgroundThread.join();
190 mBackgroundThread =
null;
191 mBackgroundHandler =
null;
192 }
catch (Exception e) {
197 @SuppressLint(
"MissingPermission")
198 boolean
open(String cameraId) {
200 mCameraId = cameraId;
201 mCameraManager.openCamera(cameraId,mStateCallback,mBackgroundHandler);
203 }
catch (Exception e){
210 native
void onStillPhotoAvailable(
long qAndroidCameraPtr, Image
frame);
213 ImageReader.OnImageAvailableListener mOnStillPhotoAvailableListener =
new ImageReader.OnImageAvailableListener() {
215 public void onImageAvailable(ImageReader reader) {
216 QtCamera2.this.onStillPhotoAvailable(getQAndroidCameraPtr(),
reader.acquireLatestImage());
220 native
void onPreviewFrameAvailable(
long qAndroidCameraPtr, Image
frame);
224 ImageReader.OnImageAvailableListener mOnPreviewImageAvailableListener =
new ImageReader.OnImageAvailableListener() {
226 public void onImageAvailable(ImageReader reader) {
230 QtCamera2.this.onPreviewFrameAvailable(getQAndroidCameraPtr(),
img);
232 }
catch (IllegalStateException e) {
235 Log.e(
LOG_TAG,
"Image processing taking too long. Let's wait 0,5s more " + e);
238 QtCamera2.this.onPreviewFrameAvailable(
239 getQAndroidCameraPtr(),
240 reader.acquireLatestImage());
242 }
catch (IllegalStateException | InterruptedException e2) {
243 Log.e(
LOG_TAG,
"Will not wait anymore. Restart camera session. " + e2);
245 String cameraId = mCameraId;
248 addPreviewImageReader(mPreviewImageReader.getWidth(),
249 mPreviewImageReader.getHeight());
250 if (mStillPhotoImageReader !=
null) {
251 addStillImageReader(mStillPhotoImageReader.getWidth(),
252 mStillPhotoImageReader.getHeight());
261 void prepareCamera(
int width,
int height,
int minFps,
int maxFps,
int stillWidth,
int stillHeight) {
263 setFrameRate(minFps, maxFps);
264 addStillImageReader(stillWidth, stillHeight);
267 private void addPreviewImageReader(
int width,
int height) {
268 if (mPreviewImageReader !=
null)
269 removeSurface(mPreviewImageReader.getSurface());
271 mPreviewImageReader =
272 ImageReader.newInstance(
width,
height, ImageFormat.YUV_420_888, MaxNumberFrames);
273 mPreviewImageReader.setOnImageAvailableListener(mOnPreviewImageAvailableListener, mBackgroundHandler);
274 addSurface(mPreviewImageReader.getSurface());
278 if (mStillPhotoImageReader !=
null)
279 removeSurface(mStillPhotoImageReader.getSurface());
281 mStillPhotoImageReader =
282 ImageReader.newInstance(
width,
height, ImageFormat.JPEG, MaxNumberFrames);
283 mStillPhotoImageReader.setOnImageAvailableListener(mOnStillPhotoAvailableListener, mBackgroundHandler);
284 addSurface(mStillPhotoImageReader.getSurface());
291 boolean updateStillImageReader(
int width,
int height) {
293 if (mCameraDevice ==
null || mStillPhotoImageReader ==
null || handler ==
null)
296 synchronized (mSyncedMembers) {
297 if (mSyncedMembers.isTakingStillPhoto())
299 mSyncedMembers.mState = SyncedMembers.State.Reconfiguring;
303 if (mCameraDevice ==
null || mStillPhotoImageReader ==
null)
306 mCurrentSessionCallback =
null;
307 if (mCaptureSession !=
null) {
308 mCaptureSession.close();
309 mCaptureSession =
null;
313 mStillPhotoImageReader.setOnImageAvailableListener(
null,
null);
316 if (!createSession())
317 onSessionConfigureFailed();
322 void onSessionConfigureFailed() {
323 final boolean isStillReaderSwap;
324 synchronized (mSyncedMembers) {
325 isStillReaderSwap = mSyncedMembers.mState == SyncedMembers.State.Reconfiguring;
327 if (isStillReaderSwap)
328 onStillReaderSwapFailed(getQAndroidCameraPtr());
330 onCaptureSessionConfigureFailed(getQAndroidCameraPtr());
331 onSessionReconfigured(
false);
335 void onSessionReconfigured(
boolean success) {
336 final boolean captureDeferred;
337 synchronized (mSyncedMembers) {
338 if (mSyncedMembers.mState == SyncedMembers.State.Reconfiguring)
339 mSyncedMembers.mState = SyncedMembers.State.Idle;
340 captureDeferred = mSyncedMembers.mStillCaptureDeferred;
341 mSyncedMembers.mStillCaptureDeferred =
false;
343 if (!captureDeferred)
346 beginStillPhotoCapture();
348 onStillPhotoCaptureFailed(getQAndroidCameraPtr());
351 private void setFrameRate(
int minFrameRate,
int maxFrameRate) {
352 synchronized (mSyncedMembers) {
353 if (minFrameRate <= 0 || maxFrameRate <= 0)
354 mSyncedMembers.mCameraSettings.mFpsRange =
null;
356 mSyncedMembers.mCameraSettings.mFpsRange =
new Range<>(minFrameRate, maxFrameRate);
360 boolean addSurface(Surface surface) {
361 if (mTargetSurfaces.contains(surface))
364 return mTargetSurfaces.add(surface);
367 boolean removeSurface(Surface surface) {
368 return mTargetSurfaces.remove(surface);
372 void clearSurfaces() {
373 mTargetSurfaces.clear();
377 boolean createSession() {
378 if (mCameraDevice ==
null)
382 List<OutputConfiguration> outputs =
new ArrayList<>(mTargetSurfaces.size());
383 for (Surface surface : mTargetSurfaces)
386 mCurrentSessionCallback =
new CameraCaptureSessionStateCallback(
this);
387 SessionConfiguration
config =
new SessionConfiguration(
388 SessionConfiguration.SESSION_REGULAR, outputs,
389 mBackgroundHandler::post, mCurrentSessionCallback);
390 mCameraDevice.createCaptureSession(
config);
392 }
catch (Exception exception) {
393 Log.w(
LOG_TAG,
"Failed to create a capture session:" + exception);
400 if (mCameraDevice ==
null)
403 if (mCaptureSession ==
null)
407 synchronized (mSyncedMembers) {
408 setRepeatingRequestToPreview();
409 if (!mSyncedMembers.isTakingStillPhoto())
410 mSyncedMembers.mState = SyncedMembers.State.Started;
413 }
catch (CameraAccessException exception) {
414 Log.w(
LOG_TAG,
"Failed to start preview:" + exception);
420 void stopAndClose() {
423 CountDownLatch closedLatch =
null;
426 boolean abortedStillPhoto =
false;
428 synchronized (mSyncedMembers) {
430 if (mSyncedMembers.isTakingStillPhoto() || mSyncedMembers.mStillCaptureDeferred)
431 abortedStillPhoto =
true;
432 if (
null != mCaptureSession) {
433 mCaptureSession.close();
434 mCaptureSession =
null;
436 if (
null != mCameraDevice) {
437 closedLatch =
new CountDownLatch(1);
438 mDeviceClosedLatch = closedLatch;
439 mCameraDevice.close();
440 mCameraDevice =
null;
443 mTargetSurfaces.clear();
444 }
catch (Exception exception) {
445 Log.w(
LOG_TAG,
"Failed to stop and close:" + exception);
447 mSyncedMembers.mState = SyncedMembers.State.Idle;
448 mSyncedMembers.mStillCaptureDeferred =
false;
451 if (abortedStillPhoto)
452 onStillPhotoCaptureFailed(getQAndroidCameraPtr());
455 if (closedLatch !=
null) {
457 if (!closedLatch.await(2, TimeUnit.SECONDS))
459 Log.w(
LOG_TAG,
"Timed out waiting for camera device to close");
460 }
catch (InterruptedException exception) {
461 Thread.currentThread().interrupt();
470 assert(mBackgroundThread !=
null);
471 assert(Thread.currentThread() != mBackgroundThread);
477 stopBackgroundThread();
478 mQAndroidCameraPtr = 0;
483 void finalizeStillPhoto(CameraSettings cameraSettings)
throws CameraAccessException
485 final CaptureRequest.Builder requestBuilder =
486 mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
487 requestBuilder.addTarget(mStillPhotoImageReader.getSurface());
489 CaptureRequest.CONTROL_CAPTURE_INTENT,
490 CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
492 applyStillPhotoSettingsToCaptureRequestBuilder(
496 mCaptureSession.capture(
497 requestBuilder.build(),
498 new CameraStillPhotoFinalizerCallback(
this),
519 void beginStillPhotoCapture() {
520 boolean abortCapture =
false;
521 synchronized (mSyncedMembers) {
522 if (mSyncedMembers.mState == SyncedMembers.State.Reconfiguring
523 || mSyncedMembers.mStillCaptureDeferred) {
524 mSyncedMembers.mStillCaptureDeferred =
true;
527 if (mSyncedMembers.isTakingStillPhoto()) {
532 "beginStillPhotoCapture() was called on camera backend while there " +
533 "is already a still photo in progress. This is not supported. Likely Qt " +
538 if (!mSyncedMembers.isStarted()) {
539 Log.w(
LOG_TAG,
"Can't begin still photo capture, camera is not started");
542 mSyncedMembers.mState = SyncedMembers.State.Capturing;
547 onStillPhotoCaptureFailed(getQAndroidCameraPtr());
551 final CameraSettings cameraSettings = atomicCameraSettingsCopy();
553 submitNewStillPhotoCapture(cameraSettings);
554 }
catch (Exception e) {
555 Log.w(
LOG_TAG,
"Failed to begin still photo capture: " + e);
557 synchronized (mSyncedMembers) {
558 mSyncedMembers.endStillPhoto();
560 onStillPhotoCaptureFailed(getQAndroidCameraPtr());
566 void submitNewStillPhotoCapture(CameraSettings cameraSettings)
throws CameraAccessException
568 CaptureRequest.Builder requestBuilder = mCameraDevice.createCaptureRequest(
569 CameraDevice.TEMPLATE_STILL_CAPTURE);
572 requestBuilder.addTarget(mPreviewImageReader.getSurface());
574 applyStillPhotoSettingsToCaptureRequestBuilder(
582 final boolean triggerAutoFocus = requestBuilder.get(CaptureRequest.CONTROL_AF_MODE)
583 == CaptureResult.CONTROL_AF_MODE_AUTO;
585 final Integer aeMode = requestBuilder.get(CaptureRequest.CONTROL_AE_MODE);
586 boolean triggerAutoExposure = aeMode !=
null
587 && aeMode != CaptureResult.CONTROL_AE_MODE_OFF;
589 final CameraStillPhotoPrecaptureCallback precaptureCallback =
590 new CameraStillPhotoPrecaptureCallback(
594 triggerAutoExposure);
596 mCaptureSession.setRepeatingRequest(
597 requestBuilder.build(),
604 if (triggerAutoFocus) {
606 CaptureRequest.CONTROL_AF_TRIGGER,
607 CaptureRequest.CONTROL_AF_TRIGGER_START);
609 if (triggerAutoExposure) {
611 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
612 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START);
616 mCaptureSession.capture(requestBuilder.build(),
null, mBackgroundHandler);
620 void saveExifToFile(String
path)
622 if (mExifDataHandler !=
null)
623 mExifDataHandler.save(
path);
628 private Rect getScalerCropRegion(
float zoomFactor)
630 Rect activePixels = mVideoDeviceManager.getActiveArraySize(mCameraId);
631 float zoomRatio = 1.0f;
632 if (zoomFactor != 0.0
f)
633 zoomRatio = 1.0f / zoomFactor;
635 int croppedWidth = activePixels.width() - (int)(activePixels.width() * zoomRatio);
636 int croppedHeight = activePixels.height() - (int)(activePixels.height() * zoomRatio);
637 return new Rect(croppedWidth/2, croppedHeight/2, activePixels.width() - croppedWidth/2,
638 activePixels.height() - croppedHeight/2);
641 private void applyZoomSettingsToRequestBuilder(CaptureRequest.Builder requBuilder,
float zoomFactor)
643 if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R) {
644 requBuilder.set(CaptureRequest.SCALER_CROP_REGION, getScalerCropRegion(zoomFactor));
646 requBuilder.set(CaptureRequest.CONTROL_ZOOM_RATIO, zoomFactor);
651 void zoomTo(
float factor)
653 synchronized (mSyncedMembers) {
654 mSyncedMembers.mCameraSettings.mZoomFactor = factor;
656 if (!mSyncedMembers.isStarted()) {
664 applyZoomSettingsToRequestBuilder(mPreviewRequestBuilder, factor);
665 mPreviewRequest = mPreviewRequestBuilder.build();
667 if (mSyncedMembers.isTakingStillPhoto()) {
673 mCaptureSession.setRepeatingRequest(
675 mPreviewCaptureCallback,
677 }
catch (Exception exception) {
678 Log.w(
LOG_TAG,
"Failed to set zoom:" + exception);
687 void setFocusMode(
int newFocusMode)
696 if (newFocusMode == 0)
697 newAfMode = CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE;
698 else if (newFocusMode == 5)
699 newAfMode = CaptureRequest.CONTROL_AF_MODE_OFF;
703 "received a QCamera::FocusMode from native code that is not recognized. " +
704 "Likely Qt developer bug. Ignoring.");
721 synchronized (mSyncedMembers) {
722 mSyncedMembers.mCameraSettings.mAFMode = newAfMode;
726 if (!mSyncedMembers.isStarted())
729 applyFocusSettingsToCaptureRequestBuilder(
730 mPreviewRequestBuilder,
731 mSyncedMembers.mCameraSettings,
733 mPreviewRequest = mPreviewRequestBuilder.build();
735 if (mSyncedMembers.isTakingStillPhoto()) {
741 mCaptureSession.setRepeatingRequest(
743 mPreviewCaptureCallback,
745 }
catch (Exception exception) {
746 Log.w(
LOG_TAG,
"Failed to set focus mode:" + exception);
752 void setFlashMode(String flashMode)
754 synchronized (mSyncedMembers) {
755 int flashModeValue = mVideoDeviceManager.stringToControlAEMode(flashMode);
756 if (flashModeValue < 0) {
760 mSyncedMembers.mCameraSettings.mStillPhotoFlashMode = flashModeValue;
770 public void setFocusDistance(
float distanceInput)
772 if (distanceInput < 0.f || distanceInput > 1.
f) {
775 "received out-of-bounds value when setting camera focus-distance. " +
776 "Likely Qt developer bug. Ignoring.");
783 synchronized (mSyncedMembers) {
784 mSyncedMembers.mCameraSettings.mFocusDistance = distanceInput;
788 if (!mSyncedMembers.isStarted())
793 if (mSyncedMembers.mCameraSettings.mAFMode == CaptureRequest.CONTROL_AF_MODE_OFF) {
794 applyFocusSettingsToCaptureRequestBuilder(
795 mPreviewRequestBuilder,
796 mSyncedMembers.mCameraSettings,
799 mPreviewRequest = mPreviewRequestBuilder.build();
801 if (mSyncedMembers.isTakingStillPhoto()) {
808 mCaptureSession.setRepeatingRequest(
810 mPreviewCaptureCallback,
812 }
catch (Exception exception) {
813 Log.w(
LOG_TAG,
"Failed to set focus distance:" + exception);
819 private int getTorchModeValue(
boolean mode)
821 return mode ? CameraMetadata.FLASH_MODE_TORCH : CameraMetadata.FLASH_MODE_OFF;
825 void setTorchMode(
boolean torchMode)
827 synchronized (mSyncedMembers) {
828 mSyncedMembers.mCameraSettings.mTorchMode = getTorchModeValue(torchMode);
830 if (mSyncedMembers.isStarted()) {
831 mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, mSyncedMembers.mCameraSettings.mTorchMode);
832 mPreviewRequest = mPreviewRequestBuilder.build();
834 if (mSyncedMembers.isTakingStillPhoto()) {
841 mCaptureSession.setRepeatingRequest(
843 mPreviewCaptureCallback,
845 }
catch (Exception exception) {
846 Log.w(
LOG_TAG,
"Failed to set flash mode:" + exception);
855 void setRepeatingRequestToPreview() throws CameraAccessException {
856 synchronized (mSyncedMembers) {
857 mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_RECORD);
858 mPreviewRequestBuilder.addTarget(mPreviewImageReader.getSurface());
860 applyPreviewSettingsToCaptureRequestBuilder(
861 mPreviewRequestBuilder,
862 mSyncedMembers.mCameraSettings);
864 mPreviewRequest = mPreviewRequestBuilder.build();
865 mCaptureSession.setRepeatingRequest(
867 mPreviewCaptureCallback,
872 private void applyStillPhotoSettingsToCaptureRequestBuilder(
873 CaptureRequest.Builder requestBuilder,
874 CameraSettings cameraSettings)
877 CaptureRequest.CONTROL_CAPTURE_INTENT,
878 CaptureRequest.CONTROL_CAPTURE_INTENT_STILL_CAPTURE);
882 CaptureRequest.CONTROL_MODE,
883 CaptureRequest.CONTROL_MODE_AUTO);
887 CaptureRequest.CONTROL_AE_MODE,
888 CaptureRequest.CONTROL_AE_MODE_ON);
890 applyZoomSettingsToRequestBuilder(requestBuilder, cameraSettings.mZoomFactor);
892 applyFocusSettingsToCaptureRequestBuilder(
900 if (cameraSettings.mStillPhotoFlashMode == CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH) {
902 CaptureRequest.CONTROL_AE_MODE,
903 CaptureRequest.CONTROL_AE_MODE_ON);
909 CaptureRequest.FLASH_MODE,
910 CaptureRequest.FLASH_MODE_TORCH);
911 }
else if (cameraSettings.mStillPhotoFlashMode == CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH) {
913 CaptureRequest.CONTROL_AE_MODE,
914 CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
918 private void applyPreviewSettingsToCaptureRequestBuilder(
919 CaptureRequest.Builder requestBuilder,
920 CameraSettings cameraSettings)
922 requestBuilder.set(CaptureRequest.CONTROL_CAPTURE_INTENT, CameraMetadata.CONTROL_CAPTURE_INTENT_VIDEO_RECORD);
924 applyFocusSettingsToCaptureRequestBuilder(
930 requestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON);
931 requestBuilder.set(CaptureRequest.FLASH_MODE, cameraSettings.mTorchMode);
933 applyZoomSettingsToRequestBuilder(requestBuilder, cameraSettings.mZoomFactor);
934 if (cameraSettings.mFpsRange !=
null) {
936 CaptureRequest.CONTROL_AE_TARGET_FPS_RANGE,
937 cameraSettings.mFpsRange);
942 mPreviewRequestBuilder.set(
943 CaptureRequest.CONTROL_AF_TRIGGER,
944 CameraMetadata.CONTROL_AF_TRIGGER_IDLE);
945 mPreviewRequestBuilder.set(
946 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER,
947 CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_IDLE);
952 void applyFocusSettingsToCaptureRequestBuilder(
953 CaptureRequest.Builder requestBuilder,
954 CameraSettings cameraSettings,
957 int desiredAfMode = cameraSettings.mAFMode;
962 if (stillPhoto && desiredAfMode == CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE) {
963 desiredAfMode = CaptureRequest.CONTROL_AF_MODE_AUTO;
966 if (!isAfModeAvailable(desiredAfMode)) {
971 if (isAfModeAvailable(CaptureRequest.CONTROL_AF_MODE_OFF)) {
973 CaptureRequest.CONTROL_AF_MODE,
974 CaptureRequest.CONTROL_AF_MODE_OFF);
977 requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE,
null);
981 requestBuilder.set(CaptureRequest.CONTROL_AF_MODE, desiredAfMode);
984 if (desiredAfMode == CaptureRequest.CONTROL_AF_MODE_OFF) {
985 final float lensFocusDistance = calcLensFocusDistanceFromQCameraFocusDistance(
986 cameraSettings.mFocusDistance);
987 if (lensFocusDistance < 0) {
990 "Tried to apply FocusModeManual on a camera that doesn't support "
991 +
"setting lens distance. Likely Qt developer bug. Ignoring.");
993 requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, lensFocusDistance);
996 requestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE,
null);
1003 private float calcLensFocusDistanceFromQCameraFocusDistance(
float qCameraFocusDistance) {
1004 float lensMinimumFocusDistance =
1005 mVideoDeviceManager.getLensInfoMinimumFocusDistance(mCameraId);
1006 if (lensMinimumFocusDistance <= 0)
1013 return (1.
f - qCameraFocusDistance) * lensMinimumFocusDistance;
1018 private boolean isAfModeAvailable(
int afMode) {
1019 if (mVideoDeviceManager ==
null || mCameraId ==
null || mCameraId.isEmpty())
1021 return mVideoDeviceManager.isAfModeAvailable(mCameraId, afMode);
1026 static boolean afStateIsReadyForCapture(Integer afState) {
1027 return afState ==
null
1028 || afState == CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED
1029 || afState == CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED;
1032 static boolean aeStateIsReadyForCapture(Integer aeState) {
1033 return aeState ==
null
1034 || aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED
1035 || aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED;
Catch::Generators::GeneratorWrapper< T > handler(Catch::Generators::GeneratorWrapper< T > &&generator)
Returns a generator wrapping generator that ensures that changes its semantics so that the first call...
QImageReader reader("image.png")
[1]
DBusConnection const char DBusError * error
GLsizei const GLchar *const * path
file open(QIODevice::ReadOnly)
QNetworkRequest request(url)
[0]