|
|
@ -44,6 +44,7 @@ import com.otaliastudios.cameraview.controls.Mode; |
|
|
|
import com.otaliastudios.cameraview.controls.WhiteBalance; |
|
|
|
import com.otaliastudios.cameraview.controls.WhiteBalance; |
|
|
|
import com.otaliastudios.cameraview.engine.action.Action; |
|
|
|
import com.otaliastudios.cameraview.engine.action.Action; |
|
|
|
import com.otaliastudios.cameraview.engine.action.ActionHolder; |
|
|
|
import com.otaliastudios.cameraview.engine.action.ActionHolder; |
|
|
|
|
|
|
|
import com.otaliastudios.cameraview.engine.action.OneShotAction; |
|
|
|
import com.otaliastudios.cameraview.engine.mappers.Camera2Mapper; |
|
|
|
import com.otaliastudios.cameraview.engine.mappers.Camera2Mapper; |
|
|
|
import com.otaliastudios.cameraview.engine.offset.Axis; |
|
|
|
import com.otaliastudios.cameraview.engine.offset.Axis; |
|
|
|
import com.otaliastudios.cameraview.engine.offset.Reference; |
|
|
|
import com.otaliastudios.cameraview.engine.offset.Reference; |
|
|
@ -66,7 +67,6 @@ import java.util.ArrayList; |
|
|
|
import java.util.List; |
|
|
|
import java.util.List; |
|
|
|
import java.util.concurrent.Callable; |
|
|
|
import java.util.concurrent.Callable; |
|
|
|
import java.util.concurrent.ExecutionException; |
|
|
|
import java.util.concurrent.ExecutionException; |
|
|
|
import java.util.concurrent.atomic.AtomicBoolean; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) |
|
|
|
@RequiresApi(Build.VERSION_CODES.LOLLIPOP) |
|
|
|
public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAvailableListener, |
|
|
|
public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAvailableListener, |
|
|
@ -86,7 +86,6 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv |
|
|
|
private CameraCharacteristics mCameraCharacteristics; |
|
|
|
private CameraCharacteristics mCameraCharacteristics; |
|
|
|
private CameraCaptureSession mSession; |
|
|
|
private CameraCaptureSession mSession; |
|
|
|
private CaptureRequest.Builder mRepeatingRequestBuilder; |
|
|
|
private CaptureRequest.Builder mRepeatingRequestBuilder; |
|
|
|
private CameraCaptureSession.CaptureCallback mRepeatingRequestCallback; |
|
|
|
|
|
|
|
private TotalCaptureResult mLastRepeatingResult; |
|
|
|
private TotalCaptureResult mLastRepeatingResult; |
|
|
|
private final Camera2Mapper mMapper = Camera2Mapper.get(); |
|
|
|
private final Camera2Mapper mMapper = Camera2Mapper.get(); |
|
|
|
|
|
|
|
|
|
|
@ -230,21 +229,24 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv |
|
|
|
* {@link #createRepeatingRequestBuilder(int)}. |
|
|
|
* {@link #createRepeatingRequestBuilder(int)}. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
private void applyRepeatingRequestBuilder() { |
|
|
|
private void applyRepeatingRequestBuilder() { |
|
|
|
applyRepeatingRequestBuilder(true, CameraException.REASON_DISCONNECTED, null); |
|
|
|
applyRepeatingRequestBuilder(true, CameraException.REASON_DISCONNECTED); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void applyRepeatingRequestBuilder(boolean checkStarted, int errorReason, @Nullable final Runnable onFirstFrame) { |
|
|
|
private void applyRepeatingRequestBuilder(boolean checkStarted, int errorReason) { |
|
|
|
if (!checkStarted || getPreviewState() == STATE_STARTED) { |
|
|
|
if (!checkStarted || getPreviewState() == STATE_STARTED) { |
|
|
|
try { |
|
|
|
try { |
|
|
|
CaptureRequest repeatingRequest = mRepeatingRequestBuilder.build(); |
|
|
|
mSession.setRepeatingRequest(mRepeatingRequestBuilder.build(), |
|
|
|
final AtomicBoolean firstFrame = new AtomicBoolean(false); |
|
|
|
mRepeatingRequestCallback, null); |
|
|
|
mRepeatingRequestCallback = new CameraCaptureSession.CaptureCallback() { |
|
|
|
} catch (CameraAccessException e) { |
|
|
|
|
|
|
|
throw new CameraException(e, errorReason); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final CameraCaptureSession.CaptureCallback mRepeatingRequestCallback = new CameraCaptureSession.CaptureCallback() { |
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) { |
|
|
|
public void onCaptureStarted(@NonNull CameraCaptureSession session, @NonNull CaptureRequest request, long timestamp, long frameNumber) { |
|
|
|
super.onCaptureStarted(session, request, timestamp, frameNumber); |
|
|
|
super.onCaptureStarted(session, request, timestamp, frameNumber); |
|
|
|
if (firstFrame.compareAndSet(false, true) && onFirstFrame != null) { |
|
|
|
|
|
|
|
onFirstFrame.run(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (mPictureRecorder instanceof Full2PictureRecorder) { |
|
|
|
if (mPictureRecorder instanceof Full2PictureRecorder) { |
|
|
|
((Full2PictureRecorder) mPictureRecorder).onCaptureStarted(request); |
|
|
|
((Full2PictureRecorder) mPictureRecorder).onCaptureStarted(request); |
|
|
|
} |
|
|
|
} |
|
|
@ -324,12 +326,6 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
mSession.setRepeatingRequest(repeatingRequest, mRepeatingRequestCallback, null); |
|
|
|
|
|
|
|
} catch (CameraAccessException e) { |
|
|
|
|
|
|
|
throw new CameraException(e, errorReason); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private String mLastLog; |
|
|
|
private String mLastLog; |
|
|
|
|
|
|
|
|
|
|
@ -583,7 +579,7 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv |
|
|
|
|
|
|
|
|
|
|
|
LOG.i("onStartPreview", "Starting preview."); |
|
|
|
LOG.i("onStartPreview", "Starting preview."); |
|
|
|
addRepeatingRequestBuilderSurfaces(); |
|
|
|
addRepeatingRequestBuilderSurfaces(); |
|
|
|
applyRepeatingRequestBuilder(false, CameraException.REASON_FAILED_TO_START_PREVIEW, null); |
|
|
|
applyRepeatingRequestBuilder(false, CameraException.REASON_FAILED_TO_START_PREVIEW); |
|
|
|
LOG.i("onStartPreview", "Started preview."); |
|
|
|
LOG.i("onStartPreview", "Started preview."); |
|
|
|
|
|
|
|
|
|
|
|
// Start delayed video if needed.
|
|
|
|
// Start delayed video if needed.
|
|
|
@ -774,18 +770,14 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv |
|
|
|
|
|
|
|
|
|
|
|
private void doTakeVideo(@NonNull final VideoResult.Stub stub) { |
|
|
|
private void doTakeVideo(@NonNull final VideoResult.Stub stub) { |
|
|
|
if (!(mVideoRecorder instanceof Full2VideoRecorder)) { |
|
|
|
if (!(mVideoRecorder instanceof Full2VideoRecorder)) { |
|
|
|
throw new IllegalStateException("doTakeVideo called, but video recorder is not a Full2VideoRecorder! " + mVideoRecorder); |
|
|
|
throw new IllegalStateException("doTakeVideo called, but video recorder " + |
|
|
|
|
|
|
|
"is not a Full2VideoRecorder! " + mVideoRecorder); |
|
|
|
} |
|
|
|
} |
|
|
|
Full2VideoRecorder recorder = (Full2VideoRecorder) mVideoRecorder; |
|
|
|
Full2VideoRecorder recorder = (Full2VideoRecorder) mVideoRecorder; |
|
|
|
try { |
|
|
|
try { |
|
|
|
createRepeatingRequestBuilder(CameraDevice.TEMPLATE_RECORD); |
|
|
|
createRepeatingRequestBuilder(CameraDevice.TEMPLATE_RECORD); |
|
|
|
addRepeatingRequestBuilderSurfaces(recorder.getInputSurface()); |
|
|
|
addRepeatingRequestBuilderSurfaces(recorder.getInputSurface()); |
|
|
|
applyRepeatingRequestBuilder(true, CameraException.REASON_DISCONNECTED, new Runnable() { |
|
|
|
applyRepeatingRequestBuilder(true, CameraException.REASON_DISCONNECTED); |
|
|
|
@Override |
|
|
|
|
|
|
|
public void run() { |
|
|
|
|
|
|
|
mVideoRecorder.start(stub); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
} catch (CameraAccessException e) { |
|
|
|
} catch (CameraAccessException e) { |
|
|
|
onVideoResult(null, e); |
|
|
|
onVideoResult(null, e); |
|
|
|
throw createCameraException(e); |
|
|
|
throw createCameraException(e); |
|
|
@ -793,6 +785,13 @@ public class Camera2Engine extends CameraEngine implements ImageReader.OnImageAv |
|
|
|
onVideoResult(null, e); |
|
|
|
onVideoResult(null, e); |
|
|
|
throw e; |
|
|
|
throw e; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Start the video recorder on the first available frame.
|
|
|
|
|
|
|
|
new OneShotAction(new Runnable() { |
|
|
|
|
|
|
|
@Override |
|
|
|
|
|
|
|
public void run() { |
|
|
|
|
|
|
|
mVideoRecorder.start(stub); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}).start(this); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@WorkerThread |
|
|
|
@WorkerThread |
|
|
|