Merge "StreamUseCase new implementation in camera-camera2" into androidx-main
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
index c57a1af..b895158 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/CaptureSessionTest.java
@@ -51,6 +51,7 @@
import android.media.Image;
import android.media.ImageReader;
import android.media.ImageReader.OnImageAvailableListener;
+import android.media.MediaCodec;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
@@ -69,25 +70,25 @@
import androidx.camera.camera2.internal.compat.quirk.ConfigureSurfaceToSecondarySessionFailQuirk;
import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks;
import androidx.camera.camera2.internal.compat.quirk.PreviewOrientationIncorrectQuirk;
+import androidx.camera.core.ImageAnalysis;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
import androidx.camera.core.impl.CameraCaptureCallback;
import androidx.camera.core.impl.CameraCaptureCallbacks;
import androidx.camera.core.impl.CameraCaptureResult;
import androidx.camera.core.impl.CaptureConfig;
import androidx.camera.core.impl.DeferrableSurface;
-import androidx.camera.core.impl.ImageAnalysisConfig;
-import androidx.camera.core.impl.ImageCaptureConfig;
import androidx.camera.core.impl.ImmediateSurface;
import androidx.camera.core.impl.MutableOptionsBundle;
-import androidx.camera.core.impl.PreviewConfig;
import androidx.camera.core.impl.Quirks;
import androidx.camera.core.impl.SessionConfig;
-import androidx.camera.core.impl.UseCaseConfig;
import androidx.camera.core.impl.utils.executor.CameraXExecutors;
import androidx.camera.core.impl.utils.futures.FutureCallback;
import androidx.camera.core.impl.utils.futures.Futures;
import androidx.camera.testing.CameraUtil;
-import androidx.camera.testing.fakes.FakeUseCaseConfig;
+import androidx.camera.testing.fakes.FakeUseCase;
import androidx.concurrent.futures.CallbackToFutureAdapter;
+import androidx.concurrent.futures.ResolvableFuture;
import androidx.core.os.HandlerCompat;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -101,7 +102,6 @@
import org.junit.AssumptionViolatedException;
import org.junit.Before;
import org.junit.BeforeClass;
-import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
@@ -114,10 +114,11 @@
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collection;
import java.util.Collections;
+import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.CancellationException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
@@ -158,6 +159,16 @@
private final List<CaptureSession> mCaptureSessions = new ArrayList<>();
private final List<DeferrableSurface> mDeferrableSurfaces = new ArrayList<>();
+ DeferrableSurface mMockSurface = new DeferrableSurface() {
+ private final ListenableFuture<Surface> mSurfaceFuture = ResolvableFuture.create();
+ @NonNull
+ @Override
+ protected ListenableFuture<Surface> provideSurface() {
+ // Return a never complete future.
+ return mSurfaceFuture;
+ }
+ };
+
@Rule
public TestRule getUseCameraRule() {
if (SDK_INT >= 19) {
@@ -232,6 +243,7 @@
mTestParameters0.tearDown();
mTestParameters1.tearDown();
+ mDeferrableSurfaces.add(mMockSurface);
for (DeferrableSurface deferrableSurface : mDeferrableSurfaces) {
deferrableSurface.close();
}
@@ -300,7 +312,7 @@
}
// Set stream use case is not supported before API 33
- @SdkSuppress(maxSdkVersion = 32)
+ @SdkSuppress(maxSdkVersion = 32, minSdkVersion = 21)
@Test
public void setStreamUseCaseNotSupported() {
ImageReader imageReader0 = ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2);
@@ -327,86 +339,121 @@
== CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW);
}
- @Ignore("b/259932467")
- @SdkSuppress(maxSdkVersion = 32)
+ @SdkSuppress(maxSdkVersion = 32, minSdkVersion = 21)
@Test
- public void getStreamUseCaseFromUseCaseConfigsNotSupported() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- useCaseConfigs.add(new FakeUseCaseConfig.Builder().getUseCaseConfig());
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- new ArrayList<>())
- == OutputConfigurationCompat.STREAM_USE_CASE_NONE);
+ public void getStreamUseCaseFromUseCaseNotSupported() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(Preview.class);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ new ArrayList<>(), streamUseCaseMap);
+ assertTrue(streamUseCaseMap.isEmpty());
}
@SdkSuppress(minSdkVersion = 33)
@Test
- public void getStreamUseCaseFromUseCaseConfigsEmptyUseCase() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- new ArrayList<>())
- == CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+ public void getStreamUseCaseFromUseCaseEmptyUseCase() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ new ArrayList<>(), streamUseCaseMap);
+ assertTrue(streamUseCaseMap.isEmpty());
}
@SdkSuppress(minSdkVersion = 33)
@Test
- public void getStreamUseCaseFromUseCaseConfigsNoPreview() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- useCaseConfigs.add(new FakeUseCaseConfig.Builder().getUseCaseConfig());
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- new ArrayList<>())
- == CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+ public void getStreamUseCaseFromUseCaseNoPreview() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(FakeUseCase.class);
+ SessionConfig sessionConfig =
+ new SessionConfig.Builder()
+ .addSurface(mMockSurface).build();
+ ArrayList<SessionConfig> sessionConfigs = new ArrayList<>();
+ sessionConfigs.add(sessionConfig);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ sessionConfigs, streamUseCaseMap);
+ assertTrue(streamUseCaseMap.isEmpty());
}
@SdkSuppress(minSdkVersion = 33)
@Test
- public void getStreamUseCaseFromUseCaseConfigsPreview() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- PreviewConfig previewConfig = new PreviewConfig(MutableOptionsBundle.create());
- useCaseConfigs.add(previewConfig);
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- new ArrayList<>())
+ public void getStreamUseCaseFromUseCasePreview() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(Preview.class);
+ SessionConfig sessionConfig =
+ new SessionConfig.Builder()
+ .addSurface(mMockSurface).build();
+ ArrayList<SessionConfig> sessionConfigs = new ArrayList<>();
+ sessionConfigs.add(sessionConfig);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ sessionConfigs, streamUseCaseMap);
+ assertTrue(streamUseCaseMap.get(mMockSurface)
== CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW);
}
@SdkSuppress(minSdkVersion = 33)
@Test
- public void getStreamUseCaseFromUseCaseConfigsZSL() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- PreviewConfig previewConfig = new PreviewConfig(MutableOptionsBundle.create());
- useCaseConfigs.add(previewConfig);
- Collection<SessionConfig> sessionConfigs = new ArrayList<>();
- sessionConfigs.add(new SessionConfig.Builder().setTemplateType(
- CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG).build());
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- sessionConfigs)
- == CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+ public void getStreamUseCaseFromUseCaseZSL() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(Preview.class);
+ SessionConfig sessionConfig =
+ new SessionConfig.Builder()
+ .addSurface(mMockSurface)
+ .setTemplateType(
+ CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG).build();
+ ArrayList<SessionConfig> sessionConfigs = new ArrayList<>();
+ sessionConfigs.add(sessionConfig);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ sessionConfigs, streamUseCaseMap);
+ assertTrue(streamUseCaseMap.isEmpty());
}
@SdkSuppress(minSdkVersion = 33)
@Test
- public void getStreamUseCaseFromUseCaseConfigsAnalysis() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- PreviewConfig previewConfig = new PreviewConfig(MutableOptionsBundle.create());
- useCaseConfigs.add(previewConfig);
- ImageAnalysisConfig analysisConfig = new ImageAnalysisConfig(MutableOptionsBundle.create());
- useCaseConfigs.add(analysisConfig);
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- new ArrayList<>())
- == CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT);
+ public void getStreamUseCaseFromUseCaseImageAnalysis() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(ImageAnalysis.class);
+ SessionConfig sessionConfig =
+ new SessionConfig.Builder()
+ .addSurface(mMockSurface).build();
+ ArrayList<SessionConfig> sessionConfigs = new ArrayList<>();
+ sessionConfigs.add(sessionConfig);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ sessionConfigs, streamUseCaseMap);
+ assertTrue(streamUseCaseMap.get(mMockSurface)
+ == CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW);
}
@SdkSuppress(minSdkVersion = 33)
@Test
public void getStreamUseCaseFromUseCaseConfigsImageCapture() {
- Collection<UseCaseConfig<?>> useCaseConfigs = new ArrayList<>();
- ImageCaptureConfig imageCaptureConfig = new ImageCaptureConfig(
- MutableOptionsBundle.create());
- useCaseConfigs.add(imageCaptureConfig);
- assertTrue(StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(useCaseConfigs,
- new ArrayList<>())
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(ImageCapture.class);
+ SessionConfig sessionConfig =
+ new SessionConfig.Builder()
+ .addSurface(mMockSurface).build();
+ ArrayList<SessionConfig> sessionConfigs = new ArrayList<>();
+ sessionConfigs.add(sessionConfig);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ sessionConfigs, streamUseCaseMap);
+ assertTrue(streamUseCaseMap.get(mMockSurface)
== CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE);
}
+ @SdkSuppress(minSdkVersion = 33)
+ @Test
+ public void getStreamUseCaseFromUseCaseConfigsVideoCapture() {
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ mMockSurface.setContainerClass(MediaCodec.class);
+ SessionConfig sessionConfig =
+ new SessionConfig.Builder()
+ .addSurface(mMockSurface).build();
+ ArrayList<SessionConfig> sessionConfigs = new ArrayList<>();
+ sessionConfigs.add(sessionConfig);
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ sessionConfigs, streamUseCaseMap);
+ assertTrue(streamUseCaseMap.get(mMockSurface)
+ == CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD);
+ }
+
// Sharing surface of YUV format is supported since API 28
@SdkSuppress(minSdkVersion = 28)
@Test
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
index 6449428..5c049d2 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/Camera2CameraImpl.java
@@ -36,7 +36,6 @@
import androidx.annotation.OptIn;
import androidx.annotation.RequiresApi;
import androidx.annotation.RestrictTo;
-import androidx.camera.camera2.impl.Camera2ImplConfig;
import androidx.camera.camera2.internal.annotation.CameraExecutor;
import androidx.camera.camera2.internal.compat.ApiCompat;
import androidx.camera.camera2.internal.compat.CameraAccessExceptionCompat;
@@ -78,6 +77,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
@@ -1127,13 +1127,12 @@
return;
}
- if (!validatingBuilder.build().getImplementationOptions().containsOption(
- Camera2ImplConfig.STREAM_USE_CASE_OPTION)) {
- validatingBuilder.addImplementationOption(Camera2ImplConfig.STREAM_USE_CASE_OPTION,
- StreamUseCaseUtil.getStreamUseCaseFromUseCaseConfigs(
- mUseCaseAttachState.getAttachedUseCaseConfigs(),
- mUseCaseAttachState.getAttachedSessionConfigs()));
- }
+ Map<DeferrableSurface, Long> streamUseCaseMap = new HashMap<>();
+ StreamUseCaseUtil.populateSurfaceToStreamUseCaseMapping(
+ mUseCaseAttachState.getAttachedSessionConfigs(),
+ streamUseCaseMap);
+
+ mCaptureSession.setStreamUseCaseMap(streamUseCaseMap);
CaptureSessionInterface captureSession = mCaptureSession;
ListenableFuture<Void> openCaptureSession = captureSession.open(validatingBuilder.build(),
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
index d0553ae..a5d14b5 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSession.java
@@ -129,6 +129,9 @@
@SuppressWarnings("WeakerAccess") /* synthetic accessor */
@GuardedBy("mSessionLock")
CallbackToFutureAdapter.Completer<Void> mReleaseCompleter;
+ @NonNull
+ @GuardedBy("mSessionLock")
+ Map<DeferrableSurface, Long> mStreamUseCaseMap = new HashMap<>();
final StillCaptureFlow mStillCaptureFlow = new StillCaptureFlow();
final TorchStateReset mTorchStateReset = new TorchStateReset();
@@ -140,6 +143,13 @@
mCaptureSessionStateCallback = new StateCallback();
}
+ @Override
+ public void setStreamUseCaseMap(@NonNull Map<DeferrableSurface, Long> streamUseCaseMap) {
+ synchronized (mSessionLock) {
+ mStreamUseCaseMap = streamUseCaseMap;
+ }
+ }
+
/**
* {@inheritDoc}
*/
@@ -314,11 +324,9 @@
outputConfig,
mConfiguredSurfaceMap,
physicalCameraIdForAllStreams);
- if (sessionConfig.getImplementationOptions().containsOption(
- Camera2ImplConfig.STREAM_USE_CASE_OPTION)) {
+ if (mStreamUseCaseMap.containsKey(outputConfig.getSurface())) {
outputConfiguration.setStreamUseCase(
- sessionConfig.getImplementationOptions().retrieveOption(
- Camera2ImplConfig.STREAM_USE_CASE_OPTION));
+ mStreamUseCaseMap.get(outputConfig.getSurface()));
}
outputConfigList.add(outputConfiguration);
}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java
index 73fbb81..351c8f5 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/CaptureSessionInterface.java
@@ -24,11 +24,13 @@
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.camera.core.impl.CaptureConfig;
+import androidx.camera.core.impl.DeferrableSurface;
import androidx.camera.core.impl.SessionConfig;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.List;
+import java.util.Map;
/**
* An interface for manipulating the session to capture images from the camera which is tied to a
@@ -120,4 +122,13 @@
*/
@NonNull
ListenableFuture<Void> release(boolean abortInFlightCaptures);
+
+ /**
+ * Sets the mapping relations between surfaces and the streamUseCases of their associated
+ * streams
+ *
+ * @param streamUseCaseMap the mapping between surfaces and the streamUseCase flag of the
+ * associated streams
+ */
+ void setStreamUseCaseMap(@NonNull Map<DeferrableSurface, Long> streamUseCaseMap);
}
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
index e530e40..f236af6 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/ProcessingCaptureSession.java
@@ -573,6 +573,11 @@
}
}
+ @Override
+ public void setStreamUseCaseMap(@NonNull Map<DeferrableSurface, Long> streamUseCaseMap) {
+ // No-op
+ }
+
private void updateParameters(@NonNull CaptureRequestOptions sessionOptions,
@NonNull CaptureRequestOptions stillCaptureOptions) {
Camera2ImplConfig.Builder builder = new Camera2ImplConfig.Builder();
diff --git a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/StreamUseCaseUtil.java b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/StreamUseCaseUtil.java
index 7af6200..cb1a181 100644
--- a/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/StreamUseCaseUtil.java
+++ b/camera/camera-camera2/src/main/java/androidx/camera/camera2/internal/StreamUseCaseUtil.java
@@ -16,19 +16,28 @@
package androidx.camera.camera2.internal;
+import static androidx.camera.camera2.impl.Camera2ImplConfig.STREAM_USE_CASE_OPTION;
+
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraMetadata;
+import android.media.MediaCodec;
import android.os.Build;
import androidx.annotation.NonNull;
-import androidx.camera.camera2.internal.compat.params.OutputConfigurationCompat;
-import androidx.camera.core.impl.ImageAnalysisConfig;
-import androidx.camera.core.impl.ImageCaptureConfig;
-import androidx.camera.core.impl.PreviewConfig;
+import androidx.annotation.Nullable;
+import androidx.annotation.OptIn;
+import androidx.annotation.RequiresApi;
+import androidx.camera.camera2.interop.ExperimentalCamera2Interop;
+import androidx.camera.core.ImageAnalysis;
+import androidx.camera.core.ImageCapture;
+import androidx.camera.core.Preview;
+import androidx.camera.core.UseCase;
+import androidx.camera.core.impl.DeferrableSurface;
import androidx.camera.core.impl.SessionConfig;
-import androidx.camera.core.impl.UseCaseConfig;
import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
/**
* A class that contains utility methods for stream use case.
@@ -36,79 +45,74 @@
public final class StreamUseCaseUtil {
private StreamUseCaseUtil() {
+
+ }
+
+ private static Map<Class<?>, Long> sUseCaseToStreamUseCaseMapping;
+
+ /**
+ * Populates the mapping between surfaces of a capture session and the Stream Use Case of their
+ * associated stream.
+ *
+ * @param sessionConfigs collection of all session configs for this capture session
+ * @param streamUseCaseMap the mapping between surfaces and Stream Use Case flag
+ */
+ @OptIn(markerClass = ExperimentalCamera2Interop.class)
+ public static void populateSurfaceToStreamUseCaseMapping(
+ @NonNull Collection<SessionConfig> sessionConfigs,
+ @NonNull Map<DeferrableSurface, Long> streamUseCaseMap) {
+ if (Build.VERSION.SDK_INT < 33) {
+ return;
+ }
+ for (SessionConfig sessionConfig : sessionConfigs) {
+ if (sessionConfig.getTemplateType()
+ == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG
+ ) {
+ // If is ZSL, do not populate anything.
+ streamUseCaseMap.clear();
+ return;
+ }
+ for (DeferrableSurface surface : sessionConfig.getSurfaces()) {
+ if (sessionConfig.getImplementationOptions().containsOption(STREAM_USE_CASE_OPTION)
+ &&
+ sessionConfig.getImplementationOptions()
+ .retrieveOption(STREAM_USE_CASE_OPTION) != null
+ ) {
+ streamUseCaseMap.put(
+ surface,
+ sessionConfig.getImplementationOptions()
+ .retrieveOption(STREAM_USE_CASE_OPTION));
+
+ continue;
+ }
+
+ @Nullable Long flag = getUseCaseToStreamUseCaseMapping()
+ .get(surface.getContainerClass());
+ if (flag != null) {
+ streamUseCaseMap.put(surface, flag);
+ }
+ }
+ }
}
/**
- * Returns the appropriate stream use case for a capture session based on the attached
- * CameraX use cases. If API level is below 33, return
- * {@value OutputConfigurationCompat#STREAM_USE_CASE_NONE}. If use cases are empty or is ZSL,
- * return DEFAULT. Otherwise, return PREVIEW_VIDEO_STILL for ImageCapture + VideoCapture;
- * return STILL_CAPTURE for ImageCapture; return VIDEO_RECORD for VideoCapture; return
- * VIEW_FINDER for Preview only.
- *
- * @param useCaseConfigs collection of all attached CameraX use cases for this capture session
- * @param sessionConfigs collection of all session configs for this capture session
- * @return the appropriate stream use case for this capture session
+ * Returns the mapping between the container class of a surface and the StreamUseCase
+ * associated with that class. Refer to {@link UseCase} for the potential UseCase as the
+ * container class for a given surface.
*/
- public static long getStreamUseCaseFromUseCaseConfigs(
- @NonNull Collection<UseCaseConfig<?>> useCaseConfigs,
- @NonNull Collection<SessionConfig> sessionConfigs) {
- if (Build.VERSION.SDK_INT < 33) {
- return OutputConfigurationCompat.STREAM_USE_CASE_NONE;
+ @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
+ private static Map<Class<?>, Long> getUseCaseToStreamUseCaseMapping() {
+ if (sUseCaseToStreamUseCaseMapping == null) {
+ sUseCaseToStreamUseCaseMapping = new HashMap<>();
+ sUseCaseToStreamUseCaseMapping.put(ImageAnalysis.class,
+ Long.valueOf(CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW));
+ sUseCaseToStreamUseCaseMapping.put(Preview.class,
+ Long.valueOf(CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW));
+ sUseCaseToStreamUseCaseMapping.put(ImageCapture.class,
+ Long.valueOf(CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE));
+ sUseCaseToStreamUseCaseMapping.put(MediaCodec.class,
+ Long.valueOf(CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD));
}
- if (useCaseConfigs.isEmpty()) {
- //If the collection is empty, return default case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
- } else {
- for (SessionConfig sessionConfig : sessionConfigs) {
- if (sessionConfig.getTemplateType() == CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG) {
- //If is ZSL, return default case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
- }
- }
- boolean hasImageCapture = false, hasVideoCapture = false, hasPreview = false;
- for (UseCaseConfig<?> useCaseConfig : useCaseConfigs) {
- if (useCaseConfig instanceof ImageAnalysisConfig) {
- //If contains analysis use case, return default case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
- }
-
- if (useCaseConfig instanceof PreviewConfig) {
- hasPreview = true;
- continue;
- }
-
- if (useCaseConfig instanceof ImageCaptureConfig) {
- if (hasVideoCapture) {
- // If has both image and video capture, return preview video still case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW_VIDEO_STILL;
- }
- hasImageCapture = true;
- continue;
-
- }
-
- // TODO: Need to handle "hasVideoCapture". The original statement was removed in
- // aosp/2299682 because it uses the legacy core.VideoCapture API, which means the
- // statement's content will never be run. The new video.VideoCapture API should
- // used.
- }
-
- if (hasImageCapture) {
- // If contains image capture, return still capture case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_STILL_CAPTURE;
- } else if (hasVideoCapture) {
- // If contains video capture, return video record case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_VIDEO_RECORD;
- } else {
- if (!hasPreview) {
- // If doesn't contain preview, we are not sure what's the situation. Return
- // default case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_DEFAULT;
- }
- // If contains only preview, return view finder case.
- return CameraMetadata.SCALER_AVAILABLE_STREAM_USE_CASES_PREVIEW;
- }
- }
+ return sUseCaseToStreamUseCaseMapping;
}
}