Merge "Camera: Add support for client requests&results for advanced extensions" into tm-dev

This commit is contained in:
Emilian Peev
2022-04-20 22:36:16 +00:00
committed by Android (Google) Code Review
9 changed files with 282 additions and 97 deletions

View File

@@ -824,24 +824,34 @@ public final class CameraExtensionCharacteristics {
if (!isExtensionSupported(mCameraId, extension, mChars)) {
throw new IllegalArgumentException("Unsupported extension");
}
Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
initializeExtension(extension);
extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
extenders.second.init(mCameraId, mChars.getNativeMetadata());
CameraMetadataNative captureRequestMeta =
extenders.second.getAvailableCaptureRequestKeys();
CameraMetadataNative captureRequestMeta = null;
if (areAdvancedExtensionsSupported()) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId);
captureRequestMeta = extender.getAvailableCaptureRequestKeys(mCameraId);
} else {
Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
initializeExtension(extension);
extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
extenders.second.init(mCameraId, mChars.getNativeMetadata());
captureRequestMeta = extenders.second.getAvailableCaptureRequestKeys();
extenders.second.onDeInit();
}
if (captureRequestMeta != null) {
int[] requestKeys = captureRequestMeta.get(
CameraCharacteristics.REQUEST_AVAILABLE_REQUEST_KEYS);
if (requestKeys == null) {
throw new AssertionError("android.request.availableRequestKeys must be non-null"
+ " in the characteristics");
throw new AssertionError(
"android.request.availableRequestKeys must be non-null"
+ " in the characteristics");
}
CameraCharacteristics requestChars = new CameraCharacteristics(captureRequestMeta);
CameraCharacteristics requestChars = new CameraCharacteristics(
captureRequestMeta);
Object crKey = CaptureRequest.Key.class;
Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>)crKey;
Class<CaptureRequest.Key<?>> crKeyTyped = (Class<CaptureRequest.Key<?>>) crKey;
ret.addAll(requestChars.getAvailableKeyList(CaptureRequest.class, crKeyTyped,
requestKeys, /*includeSynthetic*/ false));
@@ -854,7 +864,6 @@ public final class CameraExtensionCharacteristics {
if (!ret.contains(CaptureRequest.JPEG_ORIENTATION)) {
ret.add(CaptureRequest.JPEG_ORIENTATION);
}
extenders.second.onDeInit();
} catch (RemoteException e) {
throw new IllegalStateException("Failed to query the available capture request keys!");
} finally {
@@ -894,12 +903,19 @@ public final class CameraExtensionCharacteristics {
throw new IllegalArgumentException("Unsupported extension");
}
Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
initializeExtension(extension);
extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
extenders.second.init(mCameraId, mChars.getNativeMetadata());
CameraMetadataNative captureResultMeta =
extenders.second.getAvailableCaptureResultKeys();
CameraMetadataNative captureResultMeta = null;
if (areAdvancedExtensionsSupported()) {
IAdvancedExtenderImpl extender = initializeAdvancedExtension(extension);
extender.init(mCameraId);
captureResultMeta = extender.getAvailableCaptureResultKeys(mCameraId);
} else {
Pair<IPreviewExtenderImpl, IImageCaptureExtenderImpl> extenders =
initializeExtension(extension);
extenders.second.onInit(mCameraId, mChars.getNativeMetadata());
extenders.second.init(mCameraId, mChars.getNativeMetadata());
captureResultMeta = extenders.second.getAvailableCaptureResultKeys();
extenders.second.onDeInit();
}
if (captureResultMeta != null) {
int[] resultKeys = captureResultMeta.get(
@@ -926,7 +942,6 @@ public final class CameraExtensionCharacteristics {
ret.add(CaptureResult.SENSOR_TIMESTAMP);
}
}
extenders.second.onDeInit();
} catch (RemoteException e) {
throw new IllegalStateException("Failed to query the available capture result keys!");
} finally {

View File

@@ -265,8 +265,8 @@ public abstract class CameraExtensionSession implements AutoCloseable {
* from the camera device, to produce a single high-quality output result.
*
* <p>Note that single capture requests currently do not support
* client parameters except for {@link CaptureRequest#JPEG_ORIENTATION orientation} and
* {@link CaptureRequest#JPEG_QUALITY quality} in case of ImageFormat.JPEG output target.
* client parameters except for controls advertised in
* {@link CameraExtensionCharacteristics#getAvailableCaptureRequestKeys}.
* The rest of the settings included in the request will be entirely overridden by
* the device-specific extension. </p>
*
@@ -275,6 +275,11 @@ public abstract class CameraExtensionSession implements AutoCloseable {
* arguments that include further targets will cause
* IllegalArgumentException to be thrown. </p>
*
* <p>Starting with Android {@link android.os.Build.VERSION_CODES#TIRAMISU} single capture
* requests will also support the preview {@link android.graphics.ImageFormat#PRIVATE} target
* surface. These can typically be used for enabling AF/AE triggers. Do note, that single
* capture requests referencing both output surfaces remain unsupported.</p>
*
* <p>Each request will produce one new frame for one target Surface, set
* with the CaptureRequest builder's
* {@link CaptureRequest.Builder#addTarget} method.</p>
@@ -319,8 +324,10 @@ public abstract class CameraExtensionSession implements AutoCloseable {
* rate possible.</p>
*
* <p>Note that repeating capture requests currently do not support
* client parameters. Settings included in the request will
* be completely overridden by the device-specific extension.</p>
* client parameters except for controls advertised in
* {@link CameraExtensionCharacteristics#getAvailableCaptureRequestKeys}.
* The rest of the settings included in the request will be entirely overridden by
* the device-specific extension. </p>
*
* <p>The {@link CaptureRequest.Builder#addTarget} supports only one
* target surface. {@link CaptureRequest} arguments that include further

View File

@@ -19,6 +19,7 @@ import android.hardware.camera2.extension.ISessionProcessorImpl;
import android.hardware.camera2.extension.LatencyRange;
import android.hardware.camera2.extension.Size;
import android.hardware.camera2.extension.SizeList;
import android.hardware.camera2.impl.CameraMetadataNative;
/** @hide */
interface IAdvancedExtenderImpl
@@ -30,4 +31,6 @@ interface IAdvancedExtenderImpl
@nullable List<SizeList> getSupportedPreviewOutputResolutions(in String cameraId);
@nullable List<SizeList> getSupportedCaptureOutputResolutions(in String cameraId);
ISessionProcessorImpl getSessionProcessor();
CameraMetadataNative getAvailableCaptureRequestKeys(in String cameraId);
CameraMetadataNative getAvailableCaptureResultKeys(in String cameraId);
}

View File

@@ -16,6 +16,7 @@
package android.hardware.camera2.extension;
import android.hardware.camera2.extension.Request;
import android.hardware.camera2.impl.CameraMetadataNative;
/** @hide */
interface ICaptureCallback
@@ -25,4 +26,5 @@ interface ICaptureCallback
void onCaptureFailed(int captureSequenceId);
void onCaptureSequenceCompleted(int captureSequenceId);
void onCaptureSequenceAborted(int captureSequenceId);
void onCaptureCompleted(long shutterTimestamp, int requestId, in CameraMetadataNative results);
}

View File

@@ -15,6 +15,7 @@
*/
package android.hardware.camera2.extension;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.extension.CameraSessionConfig;
import android.hardware.camera2.extension.ICaptureCallback;
import android.hardware.camera2.extension.IRequestProcessorImpl;
@@ -30,5 +31,7 @@ interface ISessionProcessorImpl
void onCaptureSessionEnd();
int startRepeating(in ICaptureCallback callback);
void stopRepeating();
int startCapture(in ICaptureCallback callback, int jpegRotation, int jpegQuality);
int startCapture(in ICaptureCallback callback);
void setParameters(in CaptureRequest captureRequest);
int startTrigger(in CaptureRequest captureRequest, in ICaptureCallback callback);
}

View File

@@ -86,6 +86,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
// maps camera extension output ids to camera registered image readers
private final HashMap<Integer, ImageReader> mReaderMap = new HashMap<>();
private final RequestProcessor mRequestProcessor = new RequestProcessor();
private final int mSessionId;
private Surface mClientRepeatingRequestSurface;
private Surface mClientCaptureSurface;
@@ -175,7 +176,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
CameraAdvancedExtensionSessionImpl ret = new CameraAdvancedExtensionSessionImpl(clientId,
extender, cameraDevice, repeatingRequestSurface, burstCaptureSurface,
config.getStateCallback(), config.getExecutor());
config.getStateCallback(), config.getExecutor(), sessionId);
ret.initialize();
return ret;
@@ -184,7 +185,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
private CameraAdvancedExtensionSessionImpl(long extensionClientId,
@NonNull IAdvancedExtenderImpl extender, @NonNull CameraDevice cameraDevice,
@Nullable Surface repeatingRequestSurface, @Nullable Surface burstCaptureSurface,
@NonNull CameraExtensionSession.StateCallback callback, @NonNull Executor executor) {
@NonNull CameraExtensionSession.StateCallback callback, @NonNull Executor executor,
int sessionId) {
mExtensionClientId = extensionClientId;
mAdvancedExtender = extender;
mCameraDevice = cameraDevice;
@@ -197,6 +199,7 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
mHandler = new Handler(mHandlerThread.getLooper());
mInitialized = false;
mInitializeHandler = new InitializeSessionHandler();
mSessionId = sessionId;
}
/**
@@ -367,6 +370,8 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
}
try {
mSessionProcessor.setParameters(request);
seqId = mSessionProcessor.startRepeating(new RequestCallbackHandler(request,
executor, listener));
} catch (RemoteException e) {
@@ -388,35 +393,33 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
throw new IllegalStateException("Uninitialized component");
}
if (mClientCaptureSurface == null) {
throw new IllegalArgumentException("No output surface registered for single"
+ " requests!");
if (request.getTargets().size() != 1) {
throw new IllegalArgumentException("Single capture to both preview & still" +
" capture outputs target is not supported!");
}
if (!request.containsTarget(mClientCaptureSurface) ||
(request.getTargets().size() != 1)) {
if ((mClientCaptureSurface != null) && request.containsTarget(mClientCaptureSurface)) {
try {
mSessionProcessor.setParameters(request);
seqId = mSessionProcessor.startCapture(new RequestCallbackHandler(request,
executor, listener));
} catch (RemoteException e) {
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR, "Failed " +
" to submit capture request, extension service failed to respond!");
}
} else if ((mClientRepeatingRequestSurface != null) &&
request.containsTarget(mClientRepeatingRequestSurface)) {
try {
seqId = mSessionProcessor.startTrigger(request,
new RequestCallbackHandler(request, executor, listener));
} catch (RemoteException e) {
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR, "Failed " +
" to submit trigger request, extension service failed to respond!");
}
} else {
throw new IllegalArgumentException("Invalid single capture output target!");
}
try {
// This will override the extension capture stage jpeg parameters with the user set
// jpeg quality and rotation. This will guarantee that client configured jpeg
// parameters always have highest priority.
Integer jpegRotation = request.get(CaptureRequest.JPEG_ORIENTATION);
if (jpegRotation == null) {
jpegRotation = CameraExtensionUtils.JPEG_DEFAULT_ROTATION;
}
Byte jpegQuality = request.get(CaptureRequest.JPEG_QUALITY);
if (jpegQuality == null) {
jpegQuality = CameraExtensionUtils.JPEG_DEFAULT_QUALITY;
}
seqId = mSessionProcessor.startCapture(new RequestCallbackHandler(request,
executor, listener), jpegRotation, jpegQuality);
} catch (RemoteException e) {
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR,
"Failed to submit capture request, extension service failed to respond!");
}
}
return seqId;
@@ -661,6 +664,28 @@ public final class CameraAdvancedExtensionSessionImpl extends CameraExtensionSes
Binder.restoreCallingIdentity(ident);
}
}
@Override
public void onCaptureCompleted(long timestamp, int requestId, CameraMetadataNative result) {
if (result == null) {
Log.e(TAG,"Invalid capture result!");
return;
}
result.set(CaptureResult.SENSOR_TIMESTAMP, timestamp);
TotalCaptureResult totalResult = new TotalCaptureResult(mCameraDevice.getId(), result,
mClientRequest, requestId, timestamp, new ArrayList<>(), mSessionId,
new PhysicalCaptureResultInfo[0]);
final long ident = Binder.clearCallingIdentity();
try {
mExecutor.execute(
() -> mClientCallbacks.onCaptureResultAvailable(
CameraAdvancedExtensionSessionImpl.this, mClientRequest,
totalResult));
} finally {
Binder.restoreCallingIdentity(ident);
}
}
}
private final class CaptureCallbackHandler extends CameraCaptureSession.CaptureCallback {

View File

@@ -303,6 +303,7 @@ public class CameraExtensionJpegProcessor implements ICaptureProcessorImpl {
jpegBuffer, jpegCapacity, jpegParams.mQuality,
0, 0, yuvImage.getWidth(), yuvImage.getHeight(),
jpegParams.mRotation);
jpegImage.setTimestamp(yuvImage.getTimestamp());
yuvImage.close();
try {

View File

@@ -475,8 +475,8 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
mInternalRepeatingRequestEnabled = false;
try {
return setRepeatingRequest(mPreviewExtender.getCaptureStage(),
new RepeatingRequestHandler(request, executor, listener,
mRepeatingRequestImageCallback));
new PreviewRequestHandler(request, executor, listener,
mRepeatingRequestImageCallback), request);
} catch (RemoteException e) {
Log.e(TAG, "Failed to set repeating request! Extension service does not "
+ "respond");
@@ -530,7 +530,9 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
CaptureRequest request = requestBuilder.build();
CameraMetadataNative.update(request.getNativeMetadata(), captureStage.parameters);
ret.add(request);
captureMap.put(request, captureStage.id);
if (captureMap != null) {
captureMap.put(request, captureStage.id);
}
}
return ret;
@@ -583,33 +585,57 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
throw new IllegalStateException("Uninitialized component");
}
if (mClientCaptureSurface == null) {
throw new IllegalArgumentException("No output surface registered for single requests!");
if (request.getTargets().size() != 1) {
throw new IllegalArgumentException("Single capture to both preview & still capture " +
"outputs target is not supported!");
}
if (!request.containsTarget(mClientCaptureSurface) || (request.getTargets().size() != 1)) {
throw new IllegalArgumentException("Invalid single capture output target!");
int seqId = -1;
if ((mClientCaptureSurface != null) && request.containsTarget(mClientCaptureSurface)) {
HashMap<CaptureRequest, Integer> requestMap = new HashMap<>();
List<CaptureRequest> burstRequest;
try {
burstRequest = createBurstRequest(mCameraDevice,
mImageExtender.getCaptureStages(), request, mCameraBurstSurface,
CameraDevice.TEMPLATE_STILL_CAPTURE, requestMap);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize internal burst request! Extension service does"
+ " not respond!");
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR);
}
if (burstRequest == null) {
throw new UnsupportedOperationException(
"Failed to create still capture burst request");
}
seqId = mCaptureSession.captureBurstRequests(burstRequest,
new CameraExtensionUtils.HandlerExecutor(mHandler),
new BurstRequestHandler(request, executor, listener, requestMap,
mBurstCaptureImageCallback));
} else if ((mClientRepeatingRequestSurface != null) &&
request.containsTarget(mClientRepeatingRequestSurface)) {
CaptureRequest captureRequest = null;
try {
ArrayList<CaptureStageImpl> captureStageList = new ArrayList<>();
captureStageList.add(mPreviewExtender.getCaptureStage());
captureRequest = createRequest(mCameraDevice, captureStageList,
mCameraRepeatingSurface, CameraDevice.TEMPLATE_PREVIEW, request);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize capture request! Extension service does"
+ " not respond!");
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR);
}
seqId = mCaptureSession.capture(captureRequest, new PreviewRequestHandler(request,
executor, listener, mRepeatingRequestImageCallback, true /*singleCapture*/),
mHandler);
} else {
throw new IllegalArgumentException("Capture request to unknown output surface!");
}
HashMap<CaptureRequest, Integer> requestMap = new HashMap<>();
List<CaptureRequest> burstRequest;
try {
burstRequest = createBurstRequest(mCameraDevice,
mImageExtender.getCaptureStages(), request, mCameraBurstSurface,
CameraDevice.TEMPLATE_STILL_CAPTURE, requestMap);
} catch (RemoteException e) {
Log.e(TAG, "Failed to initialize internal burst request! Extension service does"
+ " not respond!");
throw new CameraAccessException(CameraAccessException.CAMERA_ERROR);
}
if (burstRequest == null) {
throw new UnsupportedOperationException("Failed to create still capture burst request");
}
return mCaptureSession.captureBurstRequests(burstRequest,
new CameraExtensionUtils.HandlerExecutor(mHandler),
new BurstRequestHandler(request, executor, listener, requestMap,
mBurstCaptureImageCallback));
return seqId;
}
@Override
@@ -847,7 +873,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
} else {
try {
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
new RepeatingRequestHandler(null, null, null,
new PreviewRequestHandler(null, null, null,
mRepeatingRequestImageCallback));
} catch (CameraAccessException | RemoteException e) {
Log.e(TAG,
@@ -1010,7 +1036,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
if (timestamp != null) {
if (mCaptureResultsSupported && (mCaptureResultHandler == null)) {
mCaptureResultHandler = new CaptureResultHandler(mClientRequest, mExecutor,
mCallbacks, result.getSessionId());
mCallbacks, result.getSequenceId());
}
if (mImageProcessor != null) {
if (mCapturePendingMap.indexOfKey(timestamp) >= 0) {
@@ -1179,7 +1205,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
*/
try {
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
new RepeatingRequestHandler(null, null, null,
new PreviewRequestHandler(null, null, null,
mImageCallback));
} catch (CameraAccessException | RemoteException e) {
Log.e(TAG, "Failed to start the internal repeating request!");
@@ -1320,17 +1346,20 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
}
}
// This handler can operate in two modes:
// This handler can operate in three modes:
// 1) Using valid client callbacks, which means camera buffers will be propagated the
// registered output surfaces and clients will be notified accordingly.
// 2) Without any client callbacks where an internal repeating request is kept active
// to satisfy the extensions continuous preview/(repeating request) requirement.
private class RepeatingRequestHandler extends CameraCaptureSession.CaptureCallback {
// 3) Single capture mode, where internal repeating requests are ignored and the preview
// logic is only triggered for the image processor case.
private class PreviewRequestHandler extends CameraCaptureSession.CaptureCallback {
private final Executor mExecutor;
private final ExtensionCaptureCallback mCallbacks;
private final CaptureRequest mClientRequest;
private final boolean mClientNotificationsEnabled;
private final CameraOutputImageCallback mRepeatingImageCallback;
private final boolean mSingleCapture;
private OnImageAvailableListener mImageCallback = null;
private LongSparseArray<Pair<Image, TotalCaptureResult>> mPendingResultMap =
new LongSparseArray<>();
@@ -1338,15 +1367,22 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
private boolean mRequestUpdatedNeeded = false;
public RepeatingRequestHandler(@Nullable CaptureRequest clientRequest,
public PreviewRequestHandler(@Nullable CaptureRequest clientRequest,
@Nullable Executor executor, @Nullable ExtensionCaptureCallback listener,
@NonNull CameraOutputImageCallback imageCallback) {
this(clientRequest, executor, listener, imageCallback, false /*singleCapture*/);
}
public PreviewRequestHandler(@Nullable CaptureRequest clientRequest,
@Nullable Executor executor, @Nullable ExtensionCaptureCallback listener,
@NonNull CameraOutputImageCallback imageCallback, boolean singleCapture) {
mClientRequest = clientRequest;
mExecutor = executor;
mCallbacks = listener;
mClientNotificationsEnabled =
(mClientRequest != null) && (mExecutor != null) && (mCallbacks != null);
mRepeatingImageCallback = imageCallback;
mSingleCapture = singleCapture;
}
@Override
@@ -1393,7 +1429,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
public void onCaptureSequenceAborted(@NonNull CameraCaptureSession session,
int sequenceId) {
synchronized (mInterfaceLock) {
if (mInternalRepeatingRequestEnabled) {
if (mInternalRepeatingRequestEnabled && !mSingleCapture) {
resumeInternalRepeatingRequest(true);
}
}
@@ -1420,10 +1456,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
long frameNumber) {
synchronized (mInterfaceLock) {
if (mRequestUpdatedNeeded) {
if (mRequestUpdatedNeeded && !mSingleCapture) {
mRequestUpdatedNeeded = false;
resumeInternalRepeatingRequest(false);
} else if (mInternalRepeatingRequestEnabled) {
} else if (mInternalRepeatingRequestEnabled && !mSingleCapture) {
resumeInternalRepeatingRequest(true);
}
}
@@ -1471,10 +1507,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
if (mCaptureResultsSupported && mClientNotificationsEnabled &&
(mCaptureResultHandler == null)) {
mCaptureResultHandler = new CaptureResultHandler(mClientRequest, mExecutor,
mCallbacks, result.getSessionId());
mCallbacks, result.getSequenceId());
}
if (mPreviewProcessorType ==
IPreviewExtenderImpl.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY) {
if ((!mSingleCapture) && (mPreviewProcessorType ==
IPreviewExtenderImpl.PROCESSOR_TYPE_REQUEST_UPDATE_ONLY)) {
CaptureStageImpl captureStage = null;
try {
captureStage = mPreviewRequestUpdateProcessor.process(
@@ -1582,10 +1618,10 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
try {
if (internal) {
setRepeatingRequest(mPreviewExtender.getCaptureStage(),
new RepeatingRequestHandler(null, null, null,
new PreviewRequestHandler(null, null, null,
mRepeatingImageCallback));
} else {
setRepeatingRequest(mPreviewExtender.getCaptureStage(), this);
setRepeatingRequest(mPreviewExtender.getCaptureStage(), this, mClientRequest);
}
} catch (RemoteException e) {
Log.e(TAG, "Failed to resume internal repeating request, extension service"
@@ -1733,7 +1769,7 @@ public final class CameraExtensionSessionImpl extends CameraExtensionSession {
}
private static Size findSmallestAspectMatchedSize(@NonNull List<Size> sizes,
@NonNull Size arSize) {
@NonNull Size arSize) {
final float TOLL = .01f;
if (arSize.getHeight() == 0) {

View File

@@ -19,6 +19,7 @@ import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Camera;
import android.graphics.GraphicBuffer;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
@@ -752,13 +753,65 @@ public class CameraExtensionsProxyService extends Service {
public ISessionProcessorImpl getSessionProcessor() {
return new SessionProcessorImplStub(mAdvancedExtender.createSessionProcessor());
}
@Override
public CameraMetadataNative getAvailableCaptureRequestKeys(String cameraId) {
if (RESULT_API_SUPPORTED) {
List<CaptureRequest.Key> supportedCaptureKeys =
mAdvancedExtender.getAvailableCaptureRequestKeys();
if ((supportedCaptureKeys != null) && !supportedCaptureKeys.isEmpty()) {
CameraMetadataNative ret = new CameraMetadataNative();
long vendorId = mMetadataVendorIdMap.containsKey(cameraId) ?
mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE;
ret.setVendorId(vendorId);
int requestKeyTags [] = new int[supportedCaptureKeys.size()];
int i = 0;
for (CaptureRequest.Key key : supportedCaptureKeys) {
requestKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId);
}
ret.set(CameraCharacteristics.REQUEST_AVAILABLE_REQUEST_KEYS, requestKeyTags);
return ret;
}
}
return null;
}
@Override
public CameraMetadataNative getAvailableCaptureResultKeys(String cameraId) {
if (RESULT_API_SUPPORTED) {
List<CaptureResult.Key> supportedResultKeys =
mAdvancedExtender.getAvailableCaptureResultKeys();
if ((supportedResultKeys != null) && !supportedResultKeys.isEmpty()) {
CameraMetadataNative ret = new CameraMetadataNative();
long vendorId = mMetadataVendorIdMap.containsKey(cameraId) ?
mMetadataVendorIdMap.get(cameraId) : Long.MAX_VALUE;
ret.setVendorId(vendorId);
int resultKeyTags [] = new int[supportedResultKeys.size()];
int i = 0;
for (CaptureResult.Key key : supportedResultKeys) {
resultKeyTags[i++] = CameraMetadataNative.getTag(key.getName(), vendorId);
}
ret.set(CameraCharacteristics.REQUEST_AVAILABLE_RESULT_KEYS, resultKeyTags);
return ret;
}
}
return null;
}
}
private class CaptureCallbackStub implements SessionProcessorImpl.CaptureCallback {
private final ICaptureCallback mCaptureCallback;
private final String mCameraId;
private CaptureCallbackStub(ICaptureCallback captureCallback) {
private CaptureCallbackStub(ICaptureCallback captureCallback, String cameraId) {
mCaptureCallback = captureCallback;
mCameraId = cameraId;
}
@Override
@@ -820,6 +873,29 @@ public class CameraExtensionsProxyService extends Service {
}
}
}
@Override
public void onCaptureCompleted(long timestamp, int requestId,
Map<CaptureResult.Key, Object> result) {
if (result == null) {
Log.e(TAG, "Invalid capture result received!");
}
CameraMetadataNative captureResults = new CameraMetadataNative();
if (mMetadataVendorIdMap.containsKey(mCameraId)) {
captureResults.setVendorId(mMetadataVendorIdMap.get(mCameraId));
}
for (Map.Entry<CaptureResult.Key, Object> entry : result.entrySet()) {
captureResults.set(entry.getKey(), entry.getValue());
}
try {
mCaptureCallback.onCaptureCompleted(timestamp, requestId, captureResults);
} catch (RemoteException e) {
Log.e(TAG, "Failed to notify capture complete due to remote exception!");
}
}
}
private class RequestCallbackStub extends IRequestCallback.Stub {
@@ -1124,7 +1200,7 @@ public class CameraExtensionsProxyService extends Service {
@Override
public int startRepeating(ICaptureCallback callback) {
return mSessionProcessor.startRepeating(new CaptureCallbackStub(callback));
return mSessionProcessor.startRepeating(new CaptureCallbackStub(callback, mCameraId));
}
@Override
@@ -1133,12 +1209,29 @@ public class CameraExtensionsProxyService extends Service {
}
@Override
public int startCapture(ICaptureCallback callback, int jpegRotation, int jpegQuality) {
public void setParameters(CaptureRequest captureRequest) {
HashMap<CaptureRequest.Key<?>, Object> paramMap = new HashMap<>();
paramMap.put(CaptureRequest.JPEG_ORIENTATION, jpegRotation);
paramMap.put(CaptureRequest.JPEG_QUALITY, jpegQuality);
for (CaptureRequest.Key captureRequestKey : captureRequest.getKeys()) {
paramMap.put(captureRequestKey, captureRequest.get(captureRequestKey));
}
mSessionProcessor.setParameters(paramMap);
return mSessionProcessor.startCapture(new CaptureCallbackStub(callback));
}
@Override
public int startTrigger(CaptureRequest captureRequest, ICaptureCallback callback) {
HashMap<CaptureRequest.Key<?>, Object> triggerMap = new HashMap<>();
for (CaptureRequest.Key captureRequestKey : captureRequest.getKeys()) {
triggerMap.put(captureRequestKey, captureRequest.get(captureRequestKey));
}
return mSessionProcessor.startTrigger(triggerMap,
new CaptureCallbackStub(callback, mCameraId));
}
@Override
public int startCapture(ICaptureCallback callback) {
return mSessionProcessor.startCapture(new CaptureCallbackStub(callback, mCameraId));
}
}