Example usage for android.hardware.camera2 CaptureResult SENSOR_TIMESTAMP

List of usage examples for android.hardware.camera2 CaptureResult SENSOR_TIMESTAMP

Introduction

In this page you can find the example usage for android.hardware.camera2 CaptureResult SENSOR_TIMESTAMP.

Prototype

Key SENSOR_TIMESTAMP

To view the source code for android.hardware.camera2 CaptureResult SENSOR_TIMESTAMP.

Click Source Link

Document

Time at start of exposure of first row of the image sensor active array, in nanoseconds.

The timestamps are also included in all image buffers produced for the same capture, and will be identical on all the outputs.

When CameraCharacteristics#SENSOR_INFO_TIMESTAMP_SOURCE android.sensor.info.timestampSource == UNKNOWN, the timestamps measure time since an unspecified starting point, and are monotonically increasing.

Usage

From source file:com.obviousengine.android.focus.ZslFocusCamera.java

/**
 * Take a picture./*  w  w w.  j av a2 s. com*/
 */
@Override
public void takePicture(final PhotoCaptureParameters params, final CaptureSession session) {
    params.checkSanity();

    readyStateManager.setInput(ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, false);

    boolean useZSL = ZSL_ENABLED;

    // We will only capture images from the zsl ring-buffer which satisfy
    // this constraint.
    ArrayList<ImageCaptureManager.CapturedImageConstraint> zslConstraints = new ArrayList<>();
    zslConstraints.add(new ImageCaptureManager.CapturedImageConstraint() {
        @Override
        public boolean satisfiesConstraint(TotalCaptureResult captureResult) {
            Long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
            Integer lensState = captureResult.get(CaptureResult.LENS_STATE);
            Integer flashState = captureResult.get(CaptureResult.FLASH_STATE);
            Integer flashMode = captureResult.get(CaptureResult.FLASH_MODE);
            Integer aeState = captureResult.get(CaptureResult.CONTROL_AE_STATE);
            Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
            Integer awbState = captureResult.get(CaptureResult.CONTROL_AWB_STATE);

            if (timestamp <= lastCapturedImageTimestamp.get()) {
                // Don't save frames older than the most
                // recently-captured frame.
                // TODO This technically has a race condition in which
                // duplicate frames may be saved, but if a user is
                // tapping at >30Hz, duplicate images may be what they
                // expect.
                return false;
            }

            if (lensState == CaptureResult.LENS_STATE_MOVING) {
                // If we know the lens was moving, don't use this image.
                return false;
            }

            if (aeState == CaptureResult.CONTROL_AE_STATE_SEARCHING
                    || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                return false;
            }
            switch (params.flashMode) {
            case OFF:
                break;
            case ON:
                if (flashState != CaptureResult.FLASH_STATE_FIRED
                        || flashMode != CaptureResult.FLASH_MODE_SINGLE) {
                    return false;
                }
                break;
            case AUTO:
                if (aeState == CaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED
                        && flashState != CaptureResult.FLASH_STATE_FIRED) {
                    return false;
                }
                break;
            }

            if (afState == CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN
                    || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN) {
                return false;
            }

            if (awbState == CaptureResult.CONTROL_AWB_STATE_SEARCHING) {
                return false;
            }

            return true;
        }
    });
    // This constraint lets us capture images which have been explicitly
    // requested. See {@link RequestTag.EXPLICIT_CAPTURE}.
    ArrayList<ImageCaptureManager.CapturedImageConstraint> singleCaptureConstraint = new ArrayList<>();
    singleCaptureConstraint.add(new ImageCaptureManager.CapturedImageConstraint() {
        @Override
        public boolean satisfiesConstraint(TotalCaptureResult captureResult) {
            Object tag = captureResult.getRequest().getTag();
            return tag == RequestTag.EXPLICIT_CAPTURE;
        }
    });

    // If we can use ZSL, try to save a previously-captured frame, if an
    // acceptable one exists in the buffer.
    if (useZSL) {
        boolean capturedPreviousFrame = captureManager
                .tryCaptureExistingImage(new ImageCaptureTask(params, session), zslConstraints);
        if (capturedPreviousFrame) {
            Timber.v("Saving previous frame");
            onShutterInvokeUI(params);
        } else {
            Timber.v("No good image Available.  Capturing next available good image.");
            // If there was no good frame available in the ring buffer
            // already, capture the next good image.
            // TODO Disable the shutter button until this image is captured.

            if (params.flashMode == Flash.ON || params.flashMode == Flash.AUTO) {
                // We must issue a request for a single capture using the
                // flash, including an AE precapture trigger.

                // The following sets up a sequence of events which will
                // occur in reverse order to the associated method
                // calls:
                // 1. Send a request to trigger the Auto Exposure Precapture
                // 2. Wait for the AE_STATE to leave the PRECAPTURE state,
                // and then send a request for a single image, with the
                // appropriate flash settings.
                // 3. Capture the next appropriate image, which should be
                // the one we requested in (2).

                captureManager.captureNextImage(new ImageCaptureTask(params, session), singleCaptureConstraint);

                captureManager.addMetadataChangeListener(CaptureResult.CONTROL_AE_STATE,
                        new ImageCaptureManager.MetadataChangeListener() {
                            @Override
                            public void onImageMetadataChange(Key<?> key, Object oldValue, Object newValue,
                                    CaptureResult result) {
                                Timber.v("AE State Changed");
                                if (oldValue
                                        .equals(Integer.valueOf(CaptureResult.CONTROL_AE_STATE_PRECAPTURE))) {
                                    captureManager.removeMetadataChangeListener(key, this);
                                    sendSingleRequest(params);
                                    // TODO: Delay this until onCaptureStarted().
                                    onShutterInvokeUI(params);
                                }
                            }
                        });

                sendAutoExposureTriggerRequest(params.flashMode);
            } else {
                // We may get here if, for example, the auto focus is in the
                // middle of a scan.
                // If the flash is off, we should just wait for the next
                // image that arrives. This will have minimal delay since we
                // do not need to send a new capture request.
                captureManager.captureNextImage(new ImageCaptureTask(params, session), zslConstraints);
            }
        }
    } else {
        // TODO If we can't save a previous frame, create a new capture
        // request to do what we need (e.g. flash) and call
        // captureNextImage().
        throw new UnsupportedOperationException("Non-ZSL capture not yet supported");
    }
}

From source file:com.android.camera.one.v2.OneCameraZslImpl.java

/**
 * Take a picture./*from  w  w  w .  j  av  a2  s.c  o  m*/
 */
@Override
public void takePicture(final PhotoCaptureParameters params, final CaptureSession session) {
    mReadyStateManager.setInput(ReadyStateRequirement.CAPTURE_NOT_IN_PROGRESS, false);

    boolean useZSL = ZSL_ENABLED;

    // We will only capture images from the zsl ring-buffer which satisfy
    // this constraint.
    ArrayList<ImageCaptureManager.CapturedImageConstraint> zslConstraints = new ArrayList<ImageCaptureManager.CapturedImageConstraint>();
    zslConstraints.add(new ImageCaptureManager.CapturedImageConstraint() {
        @Override
        public boolean satisfiesConstraint(TotalCaptureResult captureResult) {
            Long timestamp = captureResult.get(CaptureResult.SENSOR_TIMESTAMP);
            Integer lensState = captureResult.get(CaptureResult.LENS_STATE);
            Integer flashState = captureResult.get(CaptureResult.FLASH_STATE);
            Integer flashMode = captureResult.get(CaptureResult.FLASH_MODE);
            Integer aeState = captureResult.get(CaptureResult.CONTROL_AE_STATE);
            Integer afState = captureResult.get(CaptureResult.CONTROL_AF_STATE);
            Integer awbState = captureResult.get(CaptureResult.CONTROL_AWB_STATE);

            if (lensState == null) {
                lensState = CaptureResult.LENS_STATE_STATIONARY;
            }
            if (flashState == null) {
                flashState = CaptureResult.FLASH_STATE_UNAVAILABLE;
            }
            if (flashMode == null) {
                flashMode = CaptureResult.FLASH_MODE_OFF;
            }
            if (aeState == null) {
                aeState = CaptureResult.CONTROL_AE_STATE_INACTIVE;
            }
            if (afState == null) {
                afState = CaptureResult.CONTROL_AF_STATE_INACTIVE;
            }
            if (awbState == null) {
                awbState = CaptureResult.CONTROL_AWB_STATE_INACTIVE;
            }

            synchronized (mCapturedImageTimestamps) {
                if (mCapturedImageTimestamps.contains(timestamp)) {
                    // Don't save frames which we've already saved.
                    return false;
                }
            }

            if (lensState == CaptureResult.LENS_STATE_MOVING) {
                // If we know the lens was moving, don't use this image.
                return false;
            }

            if (aeState == CaptureResult.CONTROL_AE_STATE_SEARCHING
                    || aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                return false;
            }

            if (afState == CaptureResult.CONTROL_AF_STATE_ACTIVE_SCAN
                    || afState == CaptureResult.CONTROL_AF_STATE_PASSIVE_SCAN) {
                return false;
            }

            if (awbState == CaptureResult.CONTROL_AWB_STATE_SEARCHING) {
                return false;
            }

            return true;
        }
    });
    // This constraint lets us capture images which have been explicitly
    // requested. See {@link RequestTag.EXPLICIT_CAPTURE}.
    ArrayList<ImageCaptureManager.CapturedImageConstraint> singleCaptureConstraint = new ArrayList<ImageCaptureManager.CapturedImageConstraint>();
    singleCaptureConstraint.add(new ImageCaptureManager.CapturedImageConstraint() {
        @Override
        public boolean satisfiesConstraint(TotalCaptureResult captureResult) {
            Object tag = captureResult.getRequest().getTag();
            return tag == RequestTag.EXPLICIT_CAPTURE;
        }
    });

    // If we can use ZSL, try to save a previously-captured frame, if an
    // acceptable one exists in the buffer.
    if (useZSL) {
        boolean capturedPreviousFrame = mCaptureManager
                .tryCaptureExistingImage(new ImageCaptureTask(params, session), zslConstraints);
        if (capturedPreviousFrame) {
            Log.v(TAG, "Saving previous frame");
            onShutterInvokeUI(params);
        } else {
            Log.v(TAG, "No good image Available.  Capturing next available good image.");
            // If there was no good frame available in the ring buffer
            // already, capture the next good image.
            // TODO Disable the shutter button until this image is captured.

            Flash flashMode = Flash.OFF;

            if (flashMode == Flash.ON || flashMode == Flash.AUTO) {
                // We must issue a request for a single capture using the
                // flash, including an AE precapture trigger.

                // The following sets up a sequence of events which will
                // occur in reverse order to the associated method
                // calls:
                // 1. Send a request to trigger the Auto Exposure Precapture
                // 2. Wait for the AE_STATE to leave the PRECAPTURE state,
                // and then send a request for a single image, with the
                // appropriate flash settings.
                // 3. Capture the next appropriate image, which should be
                // the one we requested in (2).

                mCaptureManager.captureNextImage(new ImageCaptureTask(params, session),
                        singleCaptureConstraint);

                mCaptureManager.addMetadataChangeListener(CaptureResult.CONTROL_AE_STATE,
                        new MetadataChangeListener() {
                            @Override
                            public void onImageMetadataChange(Key<?> key, Object oldValue, Object newValue,
                                    CaptureResult result) {
                                Log.v(TAG, "AE State Changed");
                                if (oldValue
                                        .equals(Integer.valueOf(CaptureResult.CONTROL_AE_STATE_PRECAPTURE))) {
                                    mCaptureManager.removeMetadataChangeListener(key, this);
                                    sendSingleRequest(params);
                                    // TODO: Delay this until
                                    // onCaptureStarted().
                                    onShutterInvokeUI(params);
                                }
                            }
                        });

                sendAutoExposureTriggerRequest(flashMode);
            } else {
                // We may get here if, for example, the auto focus is in the
                // middle of a scan.
                // If the flash is off, we should just wait for the next
                // image that arrives. This will have minimal delay since we
                // do not need to send a new capture request.
                mCaptureManager.captureNextImage(new ImageCaptureTask(params, session), zslConstraints);
            }
        }
    } else {
        // TODO If we can't save a previous frame, create a new capture
        // request to do what we need (e.g. flash) and call
        // captureNextImage().
        throw new UnsupportedOperationException("Non-ZSL capture not yet supported");
    }
}