Merge "Camera: Don't switch image callbacks during extension sessions" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
5ef41d061b
@@ -61,6 +61,7 @@ import android.util.Pair;
|
|||||||
import android.util.Size;
|
import android.util.Size;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
|
|
||||||
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@@ -90,6 +91,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
private ImageReader mBurstCaptureImageReader = null;
|
private ImageReader mBurstCaptureImageReader = null;
|
||||||
private ImageReader mStubCaptureImageReader = null;
|
private ImageReader mStubCaptureImageReader = null;
|
||||||
private ImageWriter mRepeatingRequestImageWriter = null;
|
private ImageWriter mRepeatingRequestImageWriter = null;
|
||||||
|
private CameraOutputImageCallback mRepeatingRequestImageCallback = null;
|
||||||
|
private CameraOutputImageCallback mBurstCaptureImageCallback = null;
|
||||||
|
|
||||||
private CameraExtensionJpegProcessor mImageJpegProcessor = null;
|
private CameraExtensionJpegProcessor mImageJpegProcessor = null;
|
||||||
private ICaptureProcessorImpl mImageProcessor = null;
|
private ICaptureProcessorImpl mImageProcessor = null;
|
||||||
@@ -400,8 +403,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
PREVIEW_QUEUE_SIZE, repeatingSurfaceInfo.mUsage);
|
PREVIEW_QUEUE_SIZE, repeatingSurfaceInfo.mUsage);
|
||||||
mCameraRepeatingSurface = mRepeatingRequestImageReader.getSurface();
|
mCameraRepeatingSurface = mRepeatingRequestImageReader.getSurface();
|
||||||
}
|
}
|
||||||
|
mRepeatingRequestImageCallback = new CameraOutputImageCallback(
|
||||||
|
mRepeatingRequestImageReader);
|
||||||
mRepeatingRequestImageReader
|
mRepeatingRequestImageReader
|
||||||
.setOnImageAvailableListener(new ImageLoopbackCallback(), mHandler);
|
.setOnImageAvailableListener(mRepeatingRequestImageCallback, mHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeBurstCapturePipeline() throws RemoteException {
|
private void initializeBurstCapturePipeline() throws RemoteException {
|
||||||
@@ -440,6 +445,9 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT);
|
CameraExtensionCharacteristics.PROCESSING_INPUT_FORMAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBurstCaptureImageCallback = new CameraOutputImageCallback(mBurstCaptureImageReader);
|
||||||
|
mBurstCaptureImageReader.setOnImageAvailableListener(mBurstCaptureImageCallback,
|
||||||
|
mHandler);
|
||||||
mCameraBurstSurface = mBurstCaptureImageReader.getSurface();
|
mCameraBurstSurface = mBurstCaptureImageReader.getSurface();
|
||||||
android.hardware.camera2.extension.Size sz =
|
android.hardware.camera2.extension.Size sz =
|
||||||
new android.hardware.camera2.extension.Size();
|
new android.hardware.camera2.extension.Size();
|
||||||
@@ -534,7 +542,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
mInternalRepeatingRequestEnabled = false;
|
mInternalRepeatingRequestEnabled = false;
|
||||||
try {
|
try {
|
||||||
return setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
return setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
||||||
new RepeatingRequestHandler(request, executor, listener));
|
new RepeatingRequestHandler(request, executor, listener,
|
||||||
|
mRepeatingRequestImageCallback));
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
Log.e(TAG, "Failed to set repeating request! Extension service does not "
|
Log.e(TAG, "Failed to set repeating request! Extension service does not "
|
||||||
+ "respond");
|
+ "respond");
|
||||||
@@ -648,7 +657,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return mCaptureSession.captureBurstRequests(burstRequest, new HandlerExecutor(mHandler),
|
return mCaptureSession.captureBurstRequests(burstRequest, new HandlerExecutor(mHandler),
|
||||||
new BurstRequestHandler(request, executor, listener, requestMap));
|
new BurstRequestHandler(request, executor, listener, requestMap,
|
||||||
|
mBurstCaptureImageCallback));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -689,7 +699,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
if (!captureStageList.isEmpty()) {
|
if (!captureStageList.isEmpty()) {
|
||||||
CaptureRequest disableRequest = createRequest(mCameraDevice, captureStageList,
|
CaptureRequest disableRequest = createRequest(mCameraDevice, captureStageList,
|
||||||
mCameraRepeatingSurface, CameraDevice.TEMPLATE_PREVIEW);
|
mCameraRepeatingSurface, CameraDevice.TEMPLATE_PREVIEW);
|
||||||
mCaptureSession.capture(disableRequest, new CloseRequestHandler(), mHandler);
|
mCaptureSession.capture(disableRequest,
|
||||||
|
new CloseRequestHandler(mRepeatingRequestImageCallback), mHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
mCaptureSession.close();
|
mCaptureSession.close();
|
||||||
@@ -735,11 +746,21 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
CameraExtensionCharacteristics.unregisterClient(mExtensionClientId);
|
CameraExtensionCharacteristics.unregisterClient(mExtensionClientId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mRepeatingRequestImageCallback != null) {
|
||||||
|
mRepeatingRequestImageCallback.close();
|
||||||
|
mRepeatingRequestImageCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (mRepeatingRequestImageReader != null) {
|
if (mRepeatingRequestImageReader != null) {
|
||||||
mRepeatingRequestImageReader.close();
|
mRepeatingRequestImageReader.close();
|
||||||
mRepeatingRequestImageReader = null;
|
mRepeatingRequestImageReader = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mBurstCaptureImageCallback != null) {
|
||||||
|
mBurstCaptureImageCallback.close();
|
||||||
|
mBurstCaptureImageCallback = null;
|
||||||
|
}
|
||||||
|
|
||||||
if (mBurstCaptureImageReader != null) {
|
if (mBurstCaptureImageReader != null) {
|
||||||
mBurstCaptureImageReader.close();
|
mBurstCaptureImageReader.close();
|
||||||
mBurstCaptureImageReader = null;
|
mBurstCaptureImageReader = null;
|
||||||
@@ -835,7 +856,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
ArrayList<CaptureStageImpl> initialRequestList = compileInitialRequestList();
|
ArrayList<CaptureStageImpl> initialRequestList = compileInitialRequestList();
|
||||||
if (!initialRequestList.isEmpty()) {
|
if (!initialRequestList.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
setInitialCaptureRequest(initialRequestList, new InitialRequestHandler());
|
setInitialCaptureRequest(initialRequestList,
|
||||||
|
new InitialRequestHandler(mRepeatingRequestImageCallback));
|
||||||
} catch (CameraAccessException e) {
|
} catch (CameraAccessException e) {
|
||||||
Log.e(TAG, "Failed to initialize the initial capture request!");
|
Log.e(TAG, "Failed to initialize the initial capture request!");
|
||||||
status = false;
|
status = false;
|
||||||
@@ -843,7 +865,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
||||||
new RepeatingRequestHandler(null, null, null));
|
new RepeatingRequestHandler(null, null, null,
|
||||||
|
mRepeatingRequestImageCallback));
|
||||||
} catch (CameraAccessException | RemoteException e) {
|
} catch (CameraAccessException | RemoteException e) {
|
||||||
Log.e(TAG, "Failed to initialize internal repeating request!");
|
Log.e(TAG, "Failed to initialize internal repeating request!");
|
||||||
status = false;
|
status = false;
|
||||||
@@ -863,6 +886,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
private final ExtensionCaptureCallback mCallbacks;
|
private final ExtensionCaptureCallback mCallbacks;
|
||||||
private final CaptureRequest mClientRequest;
|
private final CaptureRequest mClientRequest;
|
||||||
private final HashMap<CaptureRequest, Integer> mCaptureRequestMap;
|
private final HashMap<CaptureRequest, Integer> mCaptureRequestMap;
|
||||||
|
private final CameraOutputImageCallback mBurstImageCallback;
|
||||||
|
|
||||||
private HashMap<Integer, Pair<Image, TotalCaptureResult>> mCaptureStageMap =
|
private HashMap<Integer, Pair<Image, TotalCaptureResult>> mCaptureStageMap =
|
||||||
new HashMap<>();
|
new HashMap<>();
|
||||||
@@ -873,12 +897,14 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
private boolean mCaptureFailed = false;
|
private boolean mCaptureFailed = false;
|
||||||
|
|
||||||
public BurstRequestHandler(@NonNull CaptureRequest request, @NonNull Executor executor,
|
public BurstRequestHandler(@NonNull CaptureRequest request, @NonNull Executor executor,
|
||||||
@NonNull ExtensionCaptureCallback callbacks,
|
@NonNull ExtensionCaptureCallback callbacks,
|
||||||
@NonNull HashMap<CaptureRequest, Integer> requestMap) {
|
@NonNull HashMap<CaptureRequest, Integer> requestMap,
|
||||||
|
@Nullable CameraOutputImageCallback imageCallback) {
|
||||||
mClientRequest = request;
|
mClientRequest = request;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mCallbacks = callbacks;
|
mCallbacks = callbacks;
|
||||||
mCaptureRequestMap = requestMap;
|
mCaptureRequestMap = requestMap;
|
||||||
|
mBurstImageCallback = imageCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyCaptureFailed() {
|
private void notifyCaptureFailed() {
|
||||||
@@ -893,6 +919,11 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
} finally {
|
} finally {
|
||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (Pair<Image, TotalCaptureResult> captureStage : mCaptureStageMap.values()) {
|
||||||
|
captureStage.first.close();
|
||||||
|
}
|
||||||
|
mCaptureStageMap.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -905,8 +936,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
boolean initialCallback = false;
|
boolean initialCallback = false;
|
||||||
synchronized (mInterfaceLock) {
|
synchronized (mInterfaceLock) {
|
||||||
if ((mImageProcessor != null) && (mImageCallback == null)) {
|
if ((mImageProcessor != null) && (mImageCallback == null)) {
|
||||||
mImageCallback = new ImageCallback(mBurstCaptureImageReader);
|
mImageCallback = new ImageCallback();
|
||||||
mBurstCaptureImageReader.setOnImageAvailableListener(mImageCallback, mHandler);
|
|
||||||
initialCallback = true;
|
initialCallback = true;
|
||||||
} else if (mImageProcessor == null) {
|
} else if (mImageProcessor == null) {
|
||||||
// No burst expected in this case
|
// No burst expected in this case
|
||||||
@@ -924,6 +954,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((mBurstImageCallback != null) && (mImageCallback != null)) {
|
||||||
|
mBurstImageCallback.registerListener(timestamp, mImageCallback);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1062,70 +1096,62 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ImageCallback implements ImageReader.OnImageAvailableListener {
|
private class ImageCallback implements OnImageAvailableListener {
|
||||||
public ImageCallback(@NonNull ImageReader reader) {
|
|
||||||
//Check for any pending buffers
|
|
||||||
onImageAvailable(reader);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImageAvailable(ImageReader reader) {
|
public void onImageAvailable(ImageReader reader, Image img) {
|
||||||
Image img;
|
if (mCaptureFailed) {
|
||||||
try {
|
img.close();
|
||||||
while ((!mCaptureRequestMap.isEmpty()) &&
|
}
|
||||||
(img = reader.acquireNextImage()) != null) {
|
|
||||||
long timestamp = img.getTimestamp();
|
long timestamp = img.getTimestamp();
|
||||||
reader.detachImage(img);
|
reader.detachImage(img);
|
||||||
if (mCapturePendingMap.indexOfKey(timestamp) >= 0) {
|
if (mCapturePendingMap.indexOfKey(timestamp) >= 0) {
|
||||||
Integer stageId = mCapturePendingMap.get(timestamp).second;
|
Integer stageId = mCapturePendingMap.get(timestamp).second;
|
||||||
Pair<Image, TotalCaptureResult> captureStage =
|
Pair<Image, TotalCaptureResult> captureStage =
|
||||||
mCaptureStageMap.get(stageId);
|
mCaptureStageMap.get(stageId);
|
||||||
if (captureStage != null) {
|
if (captureStage != null) {
|
||||||
mCaptureStageMap.put(stageId,
|
mCaptureStageMap.put(stageId,
|
||||||
new Pair<>(img,
|
new Pair<>(img,
|
||||||
captureStage.second));
|
captureStage.second));
|
||||||
checkAndFireBurstProcessing();
|
checkAndFireBurstProcessing();
|
||||||
} else {
|
} else {
|
||||||
Log.e(TAG,
|
Log.e(TAG,
|
||||||
"Capture stage: " +
|
"Capture stage: " +
|
||||||
mCapturePendingMap.get(timestamp).second +
|
mCapturePendingMap.get(timestamp).second +
|
||||||
" is absent!");
|
" is absent!");
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mCapturePendingMap.put(timestamp,
|
|
||||||
new Pair<>(img,
|
|
||||||
-1));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (IllegalStateException e) {
|
} else {
|
||||||
// This is possible in case the maximum number of images is acquired.
|
mCapturePendingMap.put(timestamp,
|
||||||
|
new Pair<>(img,
|
||||||
|
-1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ImageLoopbackCallback implements ImageReader.OnImageAvailableListener {
|
private class ImageLoopbackCallback implements OnImageAvailableListener {
|
||||||
@Override public void onImageAvailable(ImageReader reader) {
|
@Override
|
||||||
Image img;
|
public void onImageAvailable(ImageReader reader, Image img) {
|
||||||
try {
|
|
||||||
img = reader.acquireNextImage();
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Log.e(TAG, "Failed to acquire and loopback image!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (img == null) {
|
|
||||||
Log.e(TAG,
|
|
||||||
"Invalid image!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
img.close();
|
img.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class InitialRequestHandler extends CameraCaptureSession.CaptureCallback {
|
private class InitialRequestHandler extends CameraCaptureSession.CaptureCallback {
|
||||||
|
private final CameraOutputImageCallback mImageCallback;
|
||||||
|
|
||||||
|
public InitialRequestHandler(CameraOutputImageCallback imageCallback) {
|
||||||
|
mImageCallback = imageCallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCaptureStarted(@NonNull CameraCaptureSession session,
|
||||||
|
@NonNull CaptureRequest request, long timestamp, long frameNumber) {
|
||||||
|
mImageCallback.registerListener(timestamp, new ImageLoopbackCallback());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCaptureSequenceAborted(@NonNull CameraCaptureSession session,
|
public void onCaptureSequenceAborted(@NonNull CameraCaptureSession session,
|
||||||
int sequenceId) {
|
int sequenceId) {
|
||||||
Log.e(TAG, "Initial capture request aborted!");
|
Log.e(TAG, "Initial capture request aborted!");
|
||||||
notifyConfigurationFailure();
|
notifyConfigurationFailure();
|
||||||
}
|
}
|
||||||
@@ -1150,7 +1176,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
||||||
new RepeatingRequestHandler(null, null, null));
|
new RepeatingRequestHandler(null, null, null,
|
||||||
|
mImageCallback));
|
||||||
} catch (CameraAccessException | RemoteException e) {
|
} catch (CameraAccessException | RemoteException e) {
|
||||||
Log.e(TAG, "Failed to start the internal repeating request!");
|
Log.e(TAG, "Failed to start the internal repeating request!");
|
||||||
status = false;
|
status = false;
|
||||||
@@ -1164,16 +1191,92 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private interface OnImageAvailableListener {
|
||||||
|
public void onImageAvailable (ImageReader reader, Image img);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CameraOutputImageCallback implements ImageReader.OnImageAvailableListener,
|
||||||
|
Closeable {
|
||||||
|
private final ImageReader mImageReader;
|
||||||
|
// Map timestamp to specific images and listeners
|
||||||
|
private HashMap<Long, Pair<Image, OnImageAvailableListener>> mImageListenerMap =
|
||||||
|
new HashMap<>();
|
||||||
|
private boolean mOutOfBuffers = false;
|
||||||
|
|
||||||
|
CameraOutputImageCallback(ImageReader imageReader) {
|
||||||
|
mImageReader = imageReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onImageAvailable(ImageReader reader) {
|
||||||
|
Image img;
|
||||||
|
try {
|
||||||
|
img = reader.acquireNextImage();
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
Log.e(TAG, "Failed to acquire image, too many images pending!");
|
||||||
|
mOutOfBuffers = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (img == null) {
|
||||||
|
Log.e(TAG, "Invalid image!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Long timestamp = img.getTimestamp();
|
||||||
|
if (mImageListenerMap.containsKey(timestamp)) {
|
||||||
|
Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.remove(timestamp);
|
||||||
|
if (entry.second != null) {
|
||||||
|
entry.second.onImageAvailable(reader, img);
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "Invalid image listener, dropping frame!");
|
||||||
|
img.close();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mImageListenerMap.put(img.getTimestamp(), new Pair<>(img, null));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerListener(Long timestamp, OnImageAvailableListener listener) {
|
||||||
|
if (mImageListenerMap.containsKey(timestamp)) {
|
||||||
|
Pair<Image, OnImageAvailableListener> entry = mImageListenerMap.remove(timestamp);
|
||||||
|
if (entry.first != null) {
|
||||||
|
listener.onImageAvailable(mImageReader, entry.first);
|
||||||
|
if (mOutOfBuffers) {
|
||||||
|
mOutOfBuffers = false;
|
||||||
|
Log.w(TAG,"Out of buffers, retry!");
|
||||||
|
onImageAvailable(mImageReader);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "No valid image for listener with ts: " +
|
||||||
|
timestamp.longValue());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mImageListenerMap.put(timestamp, new Pair<>(null, listener));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
for (Pair<Image, OnImageAvailableListener> entry : mImageListenerMap.values()) {
|
||||||
|
if (entry.first != null) {
|
||||||
|
entry.first.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mImageListenerMap.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class CloseRequestHandler extends CameraCaptureSession.CaptureCallback {
|
private class CloseRequestHandler extends CameraCaptureSession.CaptureCallback {
|
||||||
|
private final CameraOutputImageCallback mImageCallback;
|
||||||
|
|
||||||
|
public CloseRequestHandler(CameraOutputImageCallback imageCallback) {
|
||||||
|
mImageCallback = imageCallback;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCaptureStarted(@NonNull CameraCaptureSession session,
|
public void onCaptureStarted(@NonNull CameraCaptureSession session,
|
||||||
@NonNull CaptureRequest request,
|
@NonNull CaptureRequest request, long timestamp, long frameNumber) {
|
||||||
long timestamp,
|
mImageCallback.registerListener(timestamp, new ImageLoopbackCallback());
|
||||||
long frameNumber) {
|
|
||||||
synchronized (mInterfaceLock) {
|
|
||||||
mRepeatingRequestImageReader
|
|
||||||
.setOnImageAvailableListener(new ImageLoopbackCallback(), mHandler);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1187,20 +1290,22 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
private final ExtensionCaptureCallback mCallbacks;
|
private final ExtensionCaptureCallback mCallbacks;
|
||||||
private final CaptureRequest mClientRequest;
|
private final CaptureRequest mClientRequest;
|
||||||
private final boolean mClientNotificationsEnabled;
|
private final boolean mClientNotificationsEnabled;
|
||||||
private ImageReader.OnImageAvailableListener mImageCallback = null;
|
private final CameraOutputImageCallback mRepeatingImageCallback;
|
||||||
|
private OnImageAvailableListener mImageCallback = null;
|
||||||
private LongSparseArray<Pair<Image, TotalCaptureResult>> mPendingResultMap =
|
private LongSparseArray<Pair<Image, TotalCaptureResult>> mPendingResultMap =
|
||||||
new LongSparseArray<>();
|
new LongSparseArray<>();
|
||||||
|
|
||||||
private boolean mRequestUpdatedNeeded = false;
|
private boolean mRequestUpdatedNeeded = false;
|
||||||
|
|
||||||
public RepeatingRequestHandler(@Nullable CaptureRequest clientRequest,
|
public RepeatingRequestHandler(@Nullable CaptureRequest clientRequest,
|
||||||
@Nullable Executor executor,
|
@Nullable Executor executor, @Nullable ExtensionCaptureCallback listener,
|
||||||
@Nullable ExtensionCaptureCallback listener) {
|
@NonNull CameraOutputImageCallback imageCallback) {
|
||||||
mClientRequest = clientRequest;
|
mClientRequest = clientRequest;
|
||||||
mExecutor = executor;
|
mExecutor = executor;
|
||||||
mCallbacks = listener;
|
mCallbacks = listener;
|
||||||
mClientNotificationsEnabled =
|
mClientNotificationsEnabled =
|
||||||
(mClientRequest != null) && (mExecutor != null) && (mCallbacks != null);
|
(mClientRequest != null) && (mExecutor != null) && (mCallbacks != null);
|
||||||
|
mRepeatingImageCallback = imageCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1226,8 +1331,6 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
new ImageForwardCallback(mRepeatingRequestImageWriter) :
|
new ImageForwardCallback(mRepeatingRequestImageWriter) :
|
||||||
new ImageLoopbackCallback();
|
new ImageLoopbackCallback();
|
||||||
}
|
}
|
||||||
mRepeatingRequestImageReader
|
|
||||||
.setOnImageAvailableListener(mImageCallback, mHandler);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1241,6 +1344,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
Binder.restoreCallingIdentity(ident);
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mRepeatingImageCallback.registerListener(timestamp, mImageCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1248,8 +1353,6 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
int sequenceId) {
|
int sequenceId) {
|
||||||
synchronized (mInterfaceLock) {
|
synchronized (mInterfaceLock) {
|
||||||
if (mInternalRepeatingRequestEnabled) {
|
if (mInternalRepeatingRequestEnabled) {
|
||||||
mRepeatingRequestImageReader.setOnImageAvailableListener(
|
|
||||||
new ImageLoopbackCallback(), mHandler);
|
|
||||||
resumeInternalRepeatingRequest(true);
|
resumeInternalRepeatingRequest(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1280,12 +1383,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
mRequestUpdatedNeeded = false;
|
mRequestUpdatedNeeded = false;
|
||||||
resumeInternalRepeatingRequest(false);
|
resumeInternalRepeatingRequest(false);
|
||||||
} else if (mInternalRepeatingRequestEnabled) {
|
} else if (mInternalRepeatingRequestEnabled) {
|
||||||
mRepeatingRequestImageReader.setOnImageAvailableListener(
|
|
||||||
new ImageLoopbackCallback(), mHandler);
|
|
||||||
resumeInternalRepeatingRequest(true);
|
resumeInternalRepeatingRequest(true);
|
||||||
} else {
|
|
||||||
mRepeatingRequestImageReader.setOnImageAvailableListener(
|
|
||||||
new ImageLoopbackCallback(), mHandler);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1395,12 +1493,14 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
try {
|
try {
|
||||||
if (processStatus) {
|
if (processStatus) {
|
||||||
mExecutor.execute(() -> mCallbacks
|
mExecutor.execute(() -> mCallbacks
|
||||||
.onCaptureProcessStarted(CameraExtensionSessionImpl.this,
|
.onCaptureProcessStarted(
|
||||||
|
CameraExtensionSessionImpl.this,
|
||||||
mClientRequest));
|
mClientRequest));
|
||||||
} else {
|
} else {
|
||||||
mExecutor.execute(
|
mExecutor.execute(
|
||||||
() -> mCallbacks
|
() -> mCallbacks
|
||||||
.onCaptureFailed(CameraExtensionSessionImpl.this,
|
.onCaptureFailed(
|
||||||
|
CameraExtensionSessionImpl.this,
|
||||||
mClientRequest));
|
mClientRequest));
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
@@ -1422,7 +1522,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
try {
|
try {
|
||||||
if (internal) {
|
if (internal) {
|
||||||
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
|
||||||
new RepeatingRequestHandler(null, null, null));
|
new RepeatingRequestHandler(null, null, null,
|
||||||
|
mRepeatingImageCallback));
|
||||||
} else {
|
} else {
|
||||||
setRepeatingRequest(mPreviewExtender.getCaptureStage(), this);
|
setRepeatingRequest(mPreviewExtender.getCaptureStage(), this);
|
||||||
}
|
}
|
||||||
@@ -1478,26 +1579,20 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ImageForwardCallback implements ImageReader.OnImageAvailableListener {
|
private class ImageForwardCallback implements OnImageAvailableListener {
|
||||||
private final ImageWriter mOutputWriter;
|
private final ImageWriter mOutputWriter;
|
||||||
|
|
||||||
public ImageForwardCallback(@NonNull ImageWriter imageWriter) {
|
public ImageForwardCallback(@NonNull ImageWriter imageWriter) {
|
||||||
mOutputWriter = imageWriter;
|
mOutputWriter = imageWriter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void onImageAvailable(ImageReader reader) {
|
@Override
|
||||||
Image img;
|
public void onImageAvailable(ImageReader reader, Image img) {
|
||||||
try {
|
|
||||||
img = reader.acquireNextImage();
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
Log.e(TAG, "Failed to acquire and propagate repeating request image!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (img == null) {
|
if (img == null) {
|
||||||
Log.e(TAG,
|
Log.e(TAG, "Invalid image!");
|
||||||
"Invalid image!");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mOutputWriter.queueInputImage(img);
|
mOutputWriter.queueInputImage(img);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
@@ -1509,13 +1604,11 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ImageProcessCallback implements ImageReader.OnImageAvailableListener {
|
private class ImageProcessCallback implements OnImageAvailableListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImageAvailable(ImageReader reader) {
|
public void onImageAvailable(ImageReader reader, Image img) {
|
||||||
Image img;
|
if (mPendingResultMap.size() + 1 >= PREVIEW_QUEUE_SIZE) {
|
||||||
try {
|
|
||||||
img = reader.acquireNextImage();
|
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
// We reached the maximum acquired images limit. This is possible in case we
|
// We reached the maximum acquired images limit. This is possible in case we
|
||||||
// have capture failures that result in absent or missing capture results. In
|
// have capture failures that result in absent or missing capture results. In
|
||||||
// such scenario we can prune the oldest pending buffer.
|
// such scenario we can prune the oldest pending buffer.
|
||||||
@@ -1523,15 +1616,13 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
|
|||||||
mPendingResultMap
|
mPendingResultMap
|
||||||
.indexOfKey(calculatePruneThreshold(mPendingResultMap)),
|
.indexOfKey(calculatePruneThreshold(mPendingResultMap)),
|
||||||
mPendingResultMap, true);
|
mPendingResultMap, true);
|
||||||
|
|
||||||
img = reader.acquireNextImage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (img == null) {
|
if (img == null) {
|
||||||
Log.e(TAG,
|
Log.e(TAG,
|
||||||
"Invalid preview buffer!");
|
"Invalid preview buffer!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
reader.detachImage(img);
|
reader.detachImage(img);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -437,13 +437,11 @@ public class ImageWriter implements AutoCloseable {
|
|||||||
// For images from other components that have non-null owner, need to detach first,
|
// For images from other components that have non-null owner, need to detach first,
|
||||||
// then attach. Images without owners must already be attachable.
|
// then attach. Images without owners must already be attachable.
|
||||||
if (!ownedByMe) {
|
if (!ownedByMe) {
|
||||||
if (image.getOwner() == null) {
|
if ((image.getOwner() instanceof ImageReader)) {
|
||||||
|
|
||||||
} else if ((image.getOwner() instanceof ImageReader)) {
|
|
||||||
ImageReader prevOwner = (ImageReader) image.getOwner();
|
ImageReader prevOwner = (ImageReader) image.getOwner();
|
||||||
|
|
||||||
prevOwner.detachImage(image);
|
prevOwner.detachImage(image);
|
||||||
} else {
|
} else if (image.getOwner() != null) {
|
||||||
throw new IllegalArgumentException("Only images from ImageReader can be queued to"
|
throw new IllegalArgumentException("Only images from ImageReader can be queued to"
|
||||||
+ " ImageWriter, other image source is not supported yet!");
|
+ " ImageWriter, other image source is not supported yet!");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user