Merge "Revert "Enable Advanced Extender with use case configurations"" into androidx-main
diff --git a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt
index 602b86b..a35c78f 100644
--- a/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt
+++ b/camera/camera-camera2/src/androidTest/java/androidx/camera/camera2/internal/ProcessingCaptureSessionTest.kt
@@ -27,31 +27,40 @@
import android.hardware.camera2.CaptureRequest
import android.hardware.camera2.TotalCaptureResult
import android.media.ImageReader
+import android.media.ImageWriter
import android.os.Build
import android.os.Handler
import android.os.Looper
+import android.os.SystemClock
import android.util.Size
import android.view.Surface
import androidx.camera.camera2.Camera2Config
import androidx.camera.camera2.internal.compat.CameraManagerCompat
import androidx.camera.camera2.internal.compat.quirk.DeviceQuirks
+import androidx.camera.camera2.internal.util.RequestProcessorRequest
import androidx.camera.camera2.interop.CaptureRequestOptions
+import androidx.camera.core.CameraInfo
import androidx.camera.core.CameraSelector
import androidx.camera.core.ImageCapture
import androidx.camera.core.Preview
import androidx.camera.core.impl.CameraCaptureCallback
+import androidx.camera.core.impl.CameraCaptureFailure
import androidx.camera.core.impl.CameraCaptureResult
import androidx.camera.core.impl.CaptureConfig
import androidx.camera.core.impl.Config
import androidx.camera.core.impl.DeferrableSurface
import androidx.camera.core.impl.ImmediateSurface
+import androidx.camera.core.impl.OptionsBundle
+import androidx.camera.core.impl.OutputSurface
+import androidx.camera.core.impl.RequestProcessor
import androidx.camera.core.impl.SessionConfig
+import androidx.camera.core.impl.SessionProcessor
+import androidx.camera.core.impl.SessionProcessorSurface
import androidx.camera.core.impl.TagBundle
import androidx.camera.core.impl.utils.executor.CameraXExecutors
import androidx.camera.testing.CameraUtil
import androidx.camera.testing.CameraUtil.CameraDeviceHolder
import androidx.camera.testing.CameraUtil.PreTestCameraIdList
-import androidx.camera.testing.fakes.FakeSessionProcessor
import androidx.concurrent.futures.await
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.LargeTest
@@ -70,6 +79,7 @@
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withTimeout
+import kotlinx.coroutines.withTimeoutOrNull
import org.junit.After
import org.junit.Assume.assumeTrue
import org.junit.Before
@@ -78,6 +88,7 @@
import org.junit.runner.RunWith
import org.junit.runners.Parameterized
+const val FAKE_CAPTURE_SEQUENCE_ID = 1
const val JPEG_ORIENTATION_VALUE = 90
const val JPEG_QUALITY_VALUE: Byte = 50
@@ -94,9 +105,9 @@
@SdkSuppress(minSdkVersion = 23)
class ProcessingCaptureSessionTest(
private var lensFacing: Int,
- // The pair specifies (Output image format to Input image format). SessionProcessor will
- // create the surface even if input format is the same as output format. But if the
- // output format is null, it means no conversion and original surface is used directly.
+ // The pair specifies (Origin image format to Transformed format), SessionProcessor will
+ // create the surface even if transformed format is the same as origin format but if the
+ // transformed format is null, it means no conversion and original surface is used directly.
private var previewFormatConvert: Pair<Int, Int?>,
private var captureFormatConvert: Pair<Int, Int?>,
) {
@@ -133,7 +144,7 @@
private lateinit var cameraDeviceHolder: CameraDeviceHolder
private lateinit var captureSessionRepository: CaptureSessionRepository
private lateinit var captureSessionOpenerBuilder: SynchronizedCaptureSessionOpener.Builder
- private lateinit var sessionProcessor: FakeSessionProcessor
+ private lateinit var sessionProcessor: CustomSessionProcessor
private lateinit var executor: Executor
private lateinit var handler: Handler
private lateinit var sessionConfigParameters: SessionConfigParameters
@@ -151,10 +162,7 @@
handler = Handler(Looper.getMainLooper())
executor = CameraXExecutors.newHandlerExecutor(handler)
- sessionProcessor = FakeSessionProcessor(
- inputFormatPreview = previewFormatConvert.second,
- inputFormatCapture = captureFormatConvert.second
- )
+ sessionProcessor = CustomSessionProcessor()
val cameraId = CameraUtil.getCameraIdWithLensFacing(lensFacing)!!
camera2CameraInfo = Camera2CameraInfoImpl(cameraId, cameraManagerCompat)
@@ -815,7 +823,7 @@
)
captureOutputDeferrableSurface = ImmediateSurface(
captureImageReader.surface, Size(640, 480),
- captureFormat
+ JPEG
)
captureOutputDeferrableSurface.setContainerClass(ImageCapture::class.java)
captureOutputDeferrableSurface.terminationFuture.addListener(
@@ -925,4 +933,297 @@
closeOutputSurfaces()
}
}
+
+ inner class CustomSessionProcessor : SessionProcessor {
+ private lateinit var previewProcessorSurface: DeferrableSurface
+ private lateinit var captureProcessorSurface: DeferrableSurface
+ private var intermediaPreviewImageReader: ImageReader? = null
+ private var intermediaCaptureImageReader: ImageReader? = null
+ private var intermediaPreviewImageWriter: ImageWriter? = null
+ private var intermediaCaptureImageWriter: ImageWriter? = null
+
+ private val previewOutputConfigId = 1
+ private val captureOutputConfigId = 2
+
+ private var requestProcessor: RequestProcessor? = null
+
+ // Values of these Deferred are the timestamp to complete.
+ private val initSessionCalled = CompletableDeferred<Long>()
+ private val deInitSessionCalled = CompletableDeferred<Long>()
+ private val onCaptureSessionStartCalled = CompletableDeferred<Long>()
+ private val onCaptureSessionEndCalled = CompletableDeferred<Long>()
+ private val startRepeatingCalled = CompletableDeferred<Long>()
+ private val startCaptureCalled = CompletableDeferred<Long>()
+ private val setParametersCalled = CompletableDeferred<Config>()
+ private var latestParameters: Config = OptionsBundle.emptyBundle()
+ private var blockRunAfterInitSession: () -> Unit = {}
+
+ fun releaseSurfaces() {
+ intermediaPreviewImageReader?.close()
+ intermediaCaptureImageReader?.close()
+ }
+
+ fun runAfterInitSession(block: () -> Unit) {
+ blockRunAfterInitSession = block
+ }
+
+ override fun initSession(
+ cameraInfo: CameraInfo,
+ previewSurfaceConfig: OutputSurface,
+ imageCaptureSurfaceConfig: OutputSurface,
+ imageAnalysisSurfaceConfig: OutputSurface?
+ ): SessionConfig {
+ initSessionCalled.complete(SystemClock.elapsedRealtimeNanos())
+ val handler = Handler(Looper.getMainLooper())
+
+ var sessionBuilder = SessionConfig.Builder()
+
+ // Preview
+ lateinit var previewTransformedSurface: Surface
+ if (previewFormatConvert.second == null) { // no conversion, use origin surface.
+ previewTransformedSurface = previewSurfaceConfig.surface
+ } else {
+ intermediaPreviewImageReader = ImageReader.newInstance(
+ 640, 480,
+ previewFormatConvert.second!!, 2
+ )
+ previewTransformedSurface = intermediaPreviewImageReader!!.surface
+
+ intermediaPreviewImageWriter = ImageWriter.newInstance(
+ previewSurfaceConfig.surface, 2
+ )
+
+ intermediaPreviewImageReader!!.setOnImageAvailableListener(
+ {
+ it.acquireNextImage().use {
+ val imageDequeued = intermediaPreviewImageWriter!!.dequeueInputImage()
+ intermediaPreviewImageWriter!!.queueInputImage(imageDequeued)
+ }
+ },
+ handler
+ )
+ }
+ previewProcessorSurface =
+ SessionProcessorSurface(previewTransformedSurface, previewOutputConfigId)
+ previewProcessorSurface.terminationFuture.addListener(
+ {
+ intermediaPreviewImageReader?.close()
+ intermediaPreviewImageWriter?.close()
+ },
+ CameraXExecutors.directExecutor()
+ )
+ sessionBuilder.addSurface(previewProcessorSurface)
+
+ // Capture
+ lateinit var captureTransformedSurface: Surface
+ if (captureFormatConvert.second == null) { // no conversion, use origin surface.
+ captureTransformedSurface = imageCaptureSurfaceConfig.surface
+ } else {
+ intermediaCaptureImageReader = ImageReader.newInstance(
+ 640, 480,
+ captureFormatConvert.second!!, 2
+ )
+ captureTransformedSurface = intermediaCaptureImageReader!!.surface
+
+ intermediaCaptureImageWriter = ImageWriter.newInstance(
+ imageCaptureSurfaceConfig.surface, 2
+ )
+
+ intermediaCaptureImageReader!!.setOnImageAvailableListener(
+ {
+ it.acquireNextImage().use {
+ val imageDequeued = intermediaCaptureImageWriter!!.dequeueInputImage()
+ intermediaCaptureImageWriter!!.queueInputImage(imageDequeued)
+ }
+ },
+ handler
+ )
+ }
+ captureProcessorSurface =
+ SessionProcessorSurface(captureTransformedSurface, captureOutputConfigId)
+
+ captureProcessorSurface.terminationFuture.addListener(
+ {
+ intermediaCaptureImageReader?.close()
+ intermediaCaptureImageWriter?.close()
+ },
+ CameraXExecutors.directExecutor()
+ )
+ sessionBuilder.addSurface(captureProcessorSurface)
+
+ sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG)
+ val sessionConfig = sessionBuilder.build()
+ blockRunAfterInitSession()
+ return sessionConfig
+ }
+
+ override fun deInitSession() {
+ deInitSessionCalled.complete(SystemClock.elapsedRealtimeNanos())
+ previewProcessorSurface.close()
+ captureProcessorSurface.close()
+ }
+
+ override fun setParameters(config: Config) {
+ setParametersCalled.complete(config)
+ latestParameters = config
+ }
+
+ override fun onCaptureSessionStart(_requestProcessor: RequestProcessor) {
+ onCaptureSessionStartCalled.complete(SystemClock.elapsedRealtimeNanos())
+ requestProcessor = _requestProcessor
+ }
+
+ override fun onCaptureSessionEnd() {
+ onCaptureSessionEndCalled.complete(SystemClock.elapsedRealtimeNanos())
+ }
+
+ fun getLatestParameters(): Config {
+ return latestParameters
+ }
+
+ override fun startRepeating(callback: SessionProcessor.CaptureCallback): Int {
+ startRepeatingCalled.complete(SystemClock.elapsedRealtimeNanos())
+ val builder = RequestProcessorRequest.Builder().apply {
+ addTargetOutputConfigId(previewOutputConfigId)
+ setParameters(latestParameters)
+ setTemplateId(CameraDevice.TEMPLATE_PREVIEW)
+ }
+
+ requestProcessor!!.setRepeating(
+ builder.build(),
+ object : RequestProcessor.Callback {
+ override fun onCaptureStarted(
+ request: RequestProcessor.Request,
+ frameNumber: Long,
+ timestamp: Long
+ ) {}
+
+ override fun onCaptureProgressed(
+ request: RequestProcessor.Request,
+ captureResult: CameraCaptureResult
+ ) {}
+
+ override fun onCaptureCompleted(
+ request: RequestProcessor.Request,
+ captureResult: CameraCaptureResult
+ ) {
+ callback.onCaptureSequenceCompleted(1)
+ }
+
+ override fun onCaptureFailed(
+ request: RequestProcessor.Request,
+ captureFailure: CameraCaptureFailure
+ ) {}
+
+ override fun onCaptureBufferLost(
+ request: RequestProcessor.Request,
+ frameNumber: Long,
+ outputConfigId: Int
+ ) {}
+
+ override fun onCaptureSequenceCompleted(
+ sequenceId: Int,
+ frameNumber: Long
+ ) {}
+
+ override fun onCaptureSequenceAborted(sequenceId: Int) {
+ }
+ }
+ )
+ return FAKE_CAPTURE_SEQUENCE_ID
+ }
+
+ override fun stopRepeating() {
+ }
+
+ override fun startCapture(callback: SessionProcessor.CaptureCallback): Int {
+ startCaptureCalled.complete(SystemClock.elapsedRealtimeNanos())
+ val request = RequestProcessorRequest.Builder().apply {
+ addTargetOutputConfigId(captureOutputConfigId)
+ setTemplateId(CameraDevice.TEMPLATE_STILL_CAPTURE)
+ }.build()
+
+ requestProcessor!!.submit(
+ request,
+ object : RequestProcessor.Callback {
+ override fun onCaptureCompleted(
+ request: RequestProcessor.Request,
+ captureResult: CameraCaptureResult
+ ) {
+ callback.onCaptureSequenceCompleted(1)
+ }
+
+ override fun onCaptureStarted(
+ request: RequestProcessor.Request,
+ frameNumber: Long,
+ timestamp: Long
+ ) {}
+
+ override fun onCaptureProgressed(
+ request: RequestProcessor.Request,
+ captureResult: CameraCaptureResult
+ ) {}
+
+ override fun onCaptureFailed(
+ request: RequestProcessor.Request,
+ captureFailure: CameraCaptureFailure
+ ) {
+ callback.onCaptureFailed(1)
+ }
+
+ override fun onCaptureBufferLost(
+ request: RequestProcessor.Request,
+ frameNumber: Long,
+ outputConfigId: Int
+ ) {}
+
+ override fun onCaptureSequenceCompleted(sequenceId: Int, frameNumber: Long) {}
+
+ override fun onCaptureSequenceAborted(sequenceId: Int) {}
+ }
+ )
+ return FAKE_CAPTURE_SEQUENCE_ID
+ }
+
+ override fun abortCapture(captureSequenceId: Int) {
+ }
+
+ suspend fun assertInitSessionInvoked(): Long {
+ return initSessionCalled.awaitWithTimeout(3000)
+ }
+
+ suspend fun wasInitSessionInvoked(): Boolean {
+ val result = withTimeoutOrNull(3000) { initSessionCalled.await() }
+ return result != null
+ }
+
+ suspend fun assertDeInitSessionInvoked(): Long {
+ return deInitSessionCalled.awaitWithTimeout(3000)
+ }
+
+ suspend fun assertOnCaptureSessionStartInvoked(): Long {
+ return onCaptureSessionStartCalled.awaitWithTimeout(3000)
+ }
+
+ suspend fun wasOnCaptureSessionStartInvoked(): Boolean {
+ val result = withTimeoutOrNull(3000) { onCaptureSessionStartCalled.await() }
+ return result != null
+ }
+
+ suspend fun assertOnCaptureEndInvoked(): Long {
+ return onCaptureSessionEndCalled.awaitWithTimeout(3000)
+ }
+
+ suspend fun assertStartRepeatingInvoked(): Long {
+ return startRepeatingCalled.awaitWithTimeout(3000)
+ }
+
+ suspend fun assertStartCaptureInvoked(): Long {
+ return startCaptureCalled.awaitWithTimeout(3000)
+ }
+
+ suspend fun assertSetParametersInvoked(): Config {
+ return setParametersCalled.awaitWithTimeout(3000)
+ }
+ }
}
\ No newline at end of file
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 b3dd1ee..203c4dc 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
@@ -17,7 +17,6 @@
package androidx.camera.camera2.internal;
import android.hardware.camera2.CameraDevice;
-import android.hardware.camera2.CaptureRequest;
import android.util.Size;
import androidx.annotation.NonNull;
@@ -344,25 +343,9 @@
break;
case ON_CAPTURE_SESSION_STARTED:
mIsExecutingStillCaptureRequest = true;
- CaptureRequestOptions.Builder builder =
- CaptureRequestOptions.Builder.from(
- captureConfig.getImplementationOptions());
-
- if (captureConfig.getImplementationOptions().containsOption(
- CaptureConfig.OPTION_ROTATION)) {
- builder.setCaptureRequestOption(CaptureRequest.JPEG_ORIENTATION,
- captureConfig.getImplementationOptions().retrieveOption(
- CaptureConfig.OPTION_ROTATION));
- }
-
- if (captureConfig.getImplementationOptions().containsOption(
- CaptureConfig.OPTION_JPEG_QUALITY)) {
- builder.setCaptureRequestOption(CaptureRequest.JPEG_QUALITY,
- captureConfig.getImplementationOptions().retrieveOption(
- CaptureConfig.OPTION_JPEG_QUALITY).byteValue());
- }
-
- mStillCaptureOptions = builder.build();
+ mStillCaptureOptions =
+ CaptureRequestOptions.Builder.from(captureConfig.getImplementationOptions())
+ .build();
updateParameters(mSessionOptions, mStillCaptureOptions);
mSessionProcessor.startCapture(new SessionProcessor.CaptureCallback() {
@Override
diff --git a/camera/camera-core/lint-baseline.xml b/camera/camera-core/lint-baseline.xml
index aaff45e..4aba0fb 100644
--- a/camera/camera-core/lint-baseline.xml
+++ b/camera/camera-core/lint-baseline.xml
@@ -128,6 +128,116 @@
errorLine1=" @Override"
errorLine2=" ^">
<location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="53"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="76"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="103"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="108"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="113"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="118"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="123"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Nullable"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="128"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="134"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
+ file="src/main/java/androidx/camera/core/AndroidImageReaderProxy.java"
+ line="146"
+ column="5"/>
+ </issue>
+
+ <issue
+ id="BanSynchronizedMethods"
+ message="Use of synchronized methods is not recommended"
+ errorLine1=" @Override"
+ errorLine2=" ^">
+ <location
file="src/main/java/androidx/camera/core/ForwardingImageProxy.java"
line="65"
column="5"/>
diff --git a/camera/camera-core/src/androidTest/java/androidx/camera/core/ModifiableImageReaderProxyTest.kt b/camera/camera-core/src/androidTest/java/androidx/camera/core/ModifiableImageReaderProxyTest.kt
deleted file mode 100644
index be57eaf..0000000
--- a/camera/camera-core/src/androidTest/java/androidx/camera/core/ModifiableImageReaderProxyTest.kt
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core
-
-import android.graphics.ImageFormat
-import android.graphics.Matrix
-import android.media.ImageReader
-import android.media.ImageWriter
-import android.os.Handler
-import androidx.camera.core.impl.ImageReaderProxy
-import androidx.camera.core.impl.MutableTagBundle
-import androidx.camera.core.impl.utils.executor.CameraXExecutors
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SdkSuppress
-import androidx.test.filters.SmallTest
-import com.google.common.truth.Truth.assertThat
-import org.junit.After
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Mockito
-import org.mockito.Mockito.spy
-
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-@SdkSuppress(minSdkVersion = 23) // This test uses ImageWriter which is supported from api 23.
-class ModifiableImageReaderProxyTest {
- private lateinit var imageReader: ImageReader
- private lateinit var imageReaderProxy: ModifiableImageReaderProxy
- private var imageWriter: ImageWriter? = null
-
- @Before
- fun setUp() {
- imageReader = spy(ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2))
- imageReaderProxy = ModifiableImageReaderProxy(imageReader)
- }
-
- @After
- fun tearDown() {
- imageReaderProxy.close()
- imageWriter?.close()
- }
-
- @Test
- fun canModifyImageTagBundle_acquireNext() {
- generateImage(imageReader)
-
- val tagBundle = MutableTagBundle.create()
- imageReaderProxy.setImageTagBundle(tagBundle)
- val imageProxy = imageReaderProxy.acquireNextImage()
- assertThat(imageProxy!!.imageInfo.tagBundle).isEqualTo(tagBundle)
- }
-
- @Test
- fun canModifyImageTagBundle_acquireLatest() {
- generateImage(imageReader)
-
- val tagBundle = MutableTagBundle.create()
- imageReaderProxy.setImageTagBundle(tagBundle)
- val imageProxy = imageReaderProxy.acquireLatestImage()
- assertThat(imageProxy!!.imageInfo.tagBundle).isEqualTo(tagBundle)
- imageProxy.close()
- }
-
- @Test
- fun canModifyImageTimestamp_acquireNext() {
- generateImage(imageReader)
-
- imageReaderProxy.setImageTimeStamp(1000)
- val imageProxy = imageReaderProxy.acquireNextImage()
- assertThat(imageProxy!!.imageInfo.timestamp).isEqualTo(1000)
- imageProxy.close()
- }
-
- @Test
- fun canModifyImageTimestamp_acquireLatest() {
- generateImage(imageReader)
-
- imageReaderProxy.setImageTimeStamp(1000)
- val imageProxy = imageReaderProxy.acquireLatestImage()
- assertThat(imageProxy!!.imageInfo.timestamp).isEqualTo(1000)
- imageProxy.close()
- }
-
- @Test
- fun canModifyImageRotationDegrees_acquireNext() {
- generateImage(imageReader)
-
- imageReaderProxy.setImageRotationDegrees(90)
- val imageProxy = imageReaderProxy.acquireNextImage()
- assertThat(imageProxy!!.imageInfo.rotationDegrees).isEqualTo(90)
- imageProxy.close()
- }
-
- @Test
- fun canModifyImageRotationDegress_acquireLatest() {
- generateImage(imageReader)
-
- imageReaderProxy.setImageRotationDegrees(90)
- val imageProxy = imageReaderProxy.acquireLatestImage()
- assertThat(imageProxy!!.imageInfo.rotationDegrees).isEqualTo(90)
- imageProxy.close()
- }
-
- @Test
- fun canModifyImageMatrix_acquireNext() {
- generateImage(imageReader)
-
- val matrix = Matrix()
- imageReaderProxy.setImageSensorToBufferTransformaMatrix(matrix)
- val imageProxy = imageReaderProxy.acquireNextImage()
- assertThat(imageProxy!!.imageInfo.sensorToBufferTransformMatrix).isSameInstanceAs(matrix)
- imageProxy.close()
- }
-
- @Test
- fun canModifyImageMatrix_acquireLatest() {
- generateImage(imageReader)
-
- val matrix = Matrix()
- imageReaderProxy.setImageSensorToBufferTransformaMatrix(matrix)
- val imageProxy = imageReaderProxy.acquireLatestImage()
- assertThat(imageProxy!!.imageInfo.sensorToBufferTransformMatrix).isSameInstanceAs(matrix)
- imageProxy.close()
- }
-
- private fun generateImage(imageReader: ImageReader) {
- imageWriter = ImageWriter.newInstance(imageReader.surface, 2)
- val image = imageWriter!!.dequeueInputImage()
- imageWriter!!.queueInputImage(image)
- }
-
- @Test
- fun parametersMatchesInnerImageReader() {
- assertThat(imageReaderProxy.width).isEqualTo(640)
- assertThat(imageReaderProxy.height).isEqualTo(480)
- assertThat(imageReaderProxy.imageFormat).isEqualTo(ImageFormat.YUV_420_888)
- assertThat(imageReaderProxy.maxImages).isEqualTo(2)
- assertThat(imageReaderProxy.surface).isEqualTo(imageReader.surface)
- }
-
- @Test
- fun setOnImageAvailableListener_innerReaderIsInvoked() {
- val listener = Mockito.mock(
- ImageReaderProxy.OnImageAvailableListener::class.java
- )
-
- imageReaderProxy.setOnImageAvailableListener(
- listener,
- CameraXExecutors.directExecutor()
- )
-
- val transformedListenerCaptor = ArgumentCaptor.forClass(
- ImageReader.OnImageAvailableListener::class.java
- )
- val handlerCaptor = ArgumentCaptor.forClass(
- Handler::class.java
- )
- Mockito.verify(imageReader, Mockito.times(1))
- .setOnImageAvailableListener(
- transformedListenerCaptor.capture(), handlerCaptor.capture()
- )
-
- transformedListenerCaptor.value.onImageAvailable(imageReader)
- Mockito.verify(listener, Mockito.times(1)).onImageAvailable(imageReaderProxy)
- }
-}
\ No newline at end of file
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/AndroidImageReaderProxy.java b/camera/camera-core/src/main/java/androidx/camera/core/AndroidImageReaderProxy.java
index 92efe7d..ea2a97e 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/AndroidImageReaderProxy.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/AndroidImageReaderProxy.java
@@ -36,10 +36,9 @@
* ImageReader}.
*/
@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-class AndroidImageReaderProxy implements ImageReaderProxy {
- @GuardedBy("mLock")
+final class AndroidImageReaderProxy implements ImageReaderProxy {
+ @GuardedBy("this")
private final ImageReader mImageReader;
- private final Object mLock = new Object();
/**
* Creates a new instance which wraps the given image reader.
@@ -53,52 +52,48 @@
@Override
@Nullable
- public ImageProxy acquireLatestImage() {
- synchronized (mLock) {
- Image image;
- try {
- image = mImageReader.acquireLatestImage();
- } catch (RuntimeException e) {
+ public synchronized ImageProxy acquireLatestImage() {
+ Image image;
+ try {
+ image = mImageReader.acquireLatestImage();
+ } catch (RuntimeException e) {
/* In API level 23 or below, it will throw "java.lang.RuntimeException:
ImageReaderContext is not initialized" when ImageReader is closed. To make the
behavior consistent as newer API levels, we make it return null Image instead.*/
- if (isImageReaderContextNotInitializedException(e)) {
- image = null;
- } else {
- throw e; // only catch RuntimeException:ImageReaderContext is not initialized
- }
+ if (isImageReaderContextNotInitializedException(e)) {
+ image = null;
+ } else {
+ throw e; // only catch RuntimeException:ImageReaderContext is not initialized
}
-
- if (image == null) {
- return null;
- }
- return new AndroidImageProxy(image);
}
+
+ if (image == null) {
+ return null;
+ }
+ return new AndroidImageProxy(image);
}
@Override
@Nullable
- public ImageProxy acquireNextImage() {
- synchronized (mLock) {
- Image image;
- try {
- image = mImageReader.acquireNextImage();
- } catch (RuntimeException e) {
+ public synchronized ImageProxy acquireNextImage() {
+ Image image;
+ try {
+ image = mImageReader.acquireNextImage();
+ } catch (RuntimeException e) {
/* In API level 23 or below, it will throw "java.lang.RuntimeException:
ImageReaderContext is not initialized" when ImageReader is closed. To make the
behavior consistent as newer API levels, we make it return null Image instead.*/
- if (isImageReaderContextNotInitializedException(e)) {
- image = null;
- } else {
- throw e; // only catch RuntimeException:ImageReaderContext is not initialized
- }
+ if (isImageReaderContextNotInitializedException(e)) {
+ image = null;
+ } else {
+ throw e; // only catch RuntimeException:ImageReaderContext is not initialized
}
-
- if (image == null) {
- return null;
- }
- return new AndroidImageProxy(image);
}
+
+ if (image == null) {
+ return null;
+ }
+ return new AndroidImageProxy(image);
}
private boolean isImageReaderContextNotInitializedException(RuntimeException e) {
@@ -106,66 +101,50 @@
}
@Override
- public void close() {
- synchronized (mLock) {
- mImageReader.close();
- }
+ public synchronized void close() {
+ mImageReader.close();
}
@Override
- public int getHeight() {
- synchronized (mLock) {
- return mImageReader.getHeight();
- }
+ public synchronized int getHeight() {
+ return mImageReader.getHeight();
}
@Override
- public int getWidth() {
- synchronized (mLock) {
- return mImageReader.getWidth();
- }
+ public synchronized int getWidth() {
+ return mImageReader.getWidth();
}
@Override
- public int getImageFormat() {
- synchronized (mLock) {
- return mImageReader.getImageFormat();
- }
+ public synchronized int getImageFormat() {
+ return mImageReader.getImageFormat();
}
@Override
- public int getMaxImages() {
- synchronized (mLock) {
- return mImageReader.getMaxImages();
- }
+ public synchronized int getMaxImages() {
+ return mImageReader.getMaxImages();
}
@Nullable
@Override
- public Surface getSurface() {
- synchronized (mLock) {
- return mImageReader.getSurface();
- }
+ public synchronized Surface getSurface() {
+ return mImageReader.getSurface();
}
@Override
- public void setOnImageAvailableListener(
+ public synchronized void setOnImageAvailableListener(
@NonNull OnImageAvailableListener listener,
@NonNull Executor executor) {
- synchronized (mLock) {
- // ImageReader does not accept an executor. As a workaround, the callback is run on main
- // handler then immediately posted to the executor.
- ImageReader.OnImageAvailableListener transformedListener = (imageReader) ->
- executor.execute(() -> listener.onImageAvailable(AndroidImageReaderProxy.this));
- mImageReader.setOnImageAvailableListener(transformedListener,
- MainThreadAsyncHandler.getInstance());
- }
+ // ImageReader does not accept an executor. As a workaround, the callback is run on main
+ // handler then immediately posted to the executor.
+ ImageReader.OnImageAvailableListener transformedListener = (imageReader) ->
+ executor.execute(() -> listener.onImageAvailable(AndroidImageReaderProxy.this));
+ mImageReader.setOnImageAvailableListener(transformedListener,
+ MainThreadAsyncHandler.getInstance());
}
@Override
- public void clearOnImageAvailableListener() {
- synchronized (mLock) {
- mImageReader.setOnImageAvailableListener(null, null);
- }
+ public synchronized void clearOnImageAvailableListener() {
+ mImageReader.setOnImageAvailableListener(null, null);
}
}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
index b1b4c0c..053af09 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ImageCapture.java
@@ -31,7 +31,6 @@
import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_MAX_CAPTURE_STAGES;
import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_MAX_RESOLUTION;
import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_SESSION_CONFIG_UNPACKER;
-import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_SESSION_PROCESSOR_ENABLED;
import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_SUPPORTED_RESOLUTIONS;
import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
import static androidx.camera.core.impl.ImageCaptureConfig.OPTION_TARGET_ASPECT_RATIO;
@@ -91,7 +90,6 @@
import androidx.camera.core.impl.ImmediateSurface;
import androidx.camera.core.impl.MutableConfig;
import androidx.camera.core.impl.MutableOptionsBundle;
-import androidx.camera.core.impl.MutableTagBundle;
import androidx.camera.core.impl.OptionsBundle;
import androidx.camera.core.impl.SessionConfig;
import androidx.camera.core.impl.UseCaseConfig;
@@ -312,11 +310,6 @@
*/
private boolean mUseSoftwareJpeg = false;
- /**
- * Whether SessionProcessor is enabled.
- */
- private boolean mIsSessionProcessorEnabled = true;
-
////////////////////////////////////////////////////////////////////////////////////////////
// [UseCase attached dynamic] - Can change but is only available when the UseCase is attached.
////////////////////////////////////////////////////////////////////////////////////////////
@@ -390,54 +383,6 @@
resolution.getHeight(), getImageFormat(), MAX_IMAGES, 0));
mMetadataMatchingCaptureCallback = new CameraCaptureCallback() {
};
- } else if (mIsSessionProcessorEnabled) {
- ImageReaderProxy imageReader;
- if (getImageFormat() == ImageFormat.JPEG) {
- imageReader =
- new AndroidImageReaderProxy(ImageReader.newInstance(resolution.getWidth(),
- resolution.getHeight(), getImageFormat(), MAX_IMAGES));
- } else if (getImageFormat() == ImageFormat.YUV_420_888) { // convert it into Jpeg
- if (Build.VERSION.SDK_INT >= 26) {
- // Jpeg rotation / quality will be set to softwareJpegProcessor later in
- // ImageCaptureRequestProcessor.
- mYuvToJpegProcessor =
- new YuvToJpegProcessor(getJpegQualityInternal(), MAX_IMAGES);
-
- ModifiableImageReaderProxy inputReader =
- new ModifiableImageReaderProxy(
- ImageReader.newInstance(resolution.getWidth(),
- resolution.getHeight(),
- ImageFormat.YUV_420_888,
- MAX_IMAGES));
-
- CaptureBundle captureBundle = CaptureBundles.singleDefaultCaptureBundle();
- ProcessingImageReader processingImageReader = new ProcessingImageReader.Builder(
- inputReader,
- captureBundle,
- mYuvToJpegProcessor
- ).setPostProcessExecutor(mExecutor).setOutputFormat(ImageFormat.JPEG).build();
-
- // Ensure the ImageProxy contains the same capture stage id expected from the
- // ProcessingImageReader.
- MutableTagBundle tagBundle = MutableTagBundle.create();
- tagBundle.putTag(processingImageReader.getTagBundleKey(),
- captureBundle.getCaptureStages().get(0).getId());
- inputReader.setImageTagBundle(tagBundle);
-
- YuvToJpegProcessor processorToClose = mYuvToJpegProcessor;
- processingImageReader.getCloseFuture().addListener(() -> {
- processorToClose.close();
- }, CameraXExecutors.directExecutor());
-
- imageReader = processingImageReader;
- } else {
- throw new UnsupportedOperationException("Does not support API level < 26");
- }
- } else {
- throw new IllegalArgumentException("Unsupported image format:" + getImageFormat());
- }
- mMetadataMatchingCaptureCallback = new CameraCaptureCallback() {};
- mImageReader = new SafeCloseImageReaderProxy(imageReader);
} else if (mCaptureProcessor != null || mUseSoftwareJpeg) {
// Capture processor set from configuration takes precedence over software JPEG.
CaptureProcessor captureProcessor = mCaptureProcessor;
@@ -468,14 +413,11 @@
}
// TODO: To allow user to use an Executor for the image processing.
- mProcessingImageReader = new ProcessingImageReader.Builder(
- resolution.getWidth(),
- resolution.getHeight(),
- inputFormat,
- mMaxCaptureStages,
+ mProcessingImageReader = new ProcessingImageReader.Builder(resolution.getWidth(),
+ resolution.getHeight(), inputFormat, mMaxCaptureStages,
getCaptureBundle(CaptureBundles.singleDefaultCaptureBundle()),
- captureProcessor
- ).setPostProcessExecutor(mExecutor).setOutputFormat(outputFormat).build();
+ captureProcessor).setPostProcessExecutor(mExecutor).setOutputFormat(
+ outputFormat).build();
mMetadataMatchingCaptureCallback = mProcessingImageReader.getCameraCaptureCallback();
mImageReader = new SafeCloseImageReaderProxy(mProcessingImageReader);
@@ -712,21 +654,7 @@
builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT,
ImageFormat.YUV_420_888);
} else {
- List<Pair<Integer, Size[]>> supportedSizes =
- builder.getMutableConfig().retrieveOption(OPTION_SUPPORTED_RESOLUTIONS,
- null);
- if (supportedSizes == null) {
- builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT, ImageFormat.JPEG);
- } else {
- // Use Jpeg first if supported.
- if (isImageFormatSupported(supportedSizes, ImageFormat.JPEG)) {
- builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT,
- ImageFormat.JPEG);
- } else if (isImageFormatSupported(supportedSizes, ImageFormat.YUV_420_888)) {
- builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT,
- ImageFormat.YUV_420_888);
- }
- }
+ builder.getMutableConfig().insertOption(OPTION_INPUT_FORMAT, ImageFormat.JPEG);
}
}
@@ -737,18 +665,6 @@
return builder.getUseCaseConfig();
}
- private static boolean isImageFormatSupported(List<Pair<Integer, Size[]>> supportedSizes,
- int imageFormat) {
- if (supportedSizes == null) {
- return false;
- }
- for (Pair<Integer, Size[]> supportedSize : supportedSizes) {
- if (supportedSize.first.equals(imageFormat)) {
- return true;
- }
- }
- return false;
- }
/**
* Configures flash mode to CameraControlInternal once it is ready.
*
@@ -1638,7 +1554,6 @@
// This will only be set to true if software JPEG was requested and
// enforceSoftwareJpegConstraints() hasn't removed the request.
mUseSoftwareJpeg = useCaseConfig.isSoftwareJpegEncoderRequested();
- mIsSessionProcessorEnabled = useCaseConfig.isSessionProcessorEnabled();
CameraInternal camera = getCamera();
Preconditions.checkNotNull(camera, "Attached camera cannot be null");
@@ -2591,17 +2506,6 @@
}
/**
- * Set the flag to indicate whether SessionProcessor is enabled.
- * @hide
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @NonNull
- public Builder setSessionProcessorEnabled(boolean enabled) {
- getMutableConfig().insertOption(OPTION_SESSION_PROCESSOR_ENABLED, enabled);
- return this;
- }
-
- /**
* Sets the max number of {@link CaptureStage}.
*
* @param maxCaptureStages The max CaptureStage number.
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ModifiableImageReaderProxy.java b/camera/camera-core/src/main/java/androidx/camera/core/ModifiableImageReaderProxy.java
deleted file mode 100644
index 4d9250b..0000000
--- a/camera/camera-core/src/main/java/androidx/camera/core/ModifiableImageReaderProxy.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.core;
-
-import android.graphics.Matrix;
-import android.media.ImageReader;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-import androidx.camera.core.impl.TagBundle;
-
-/**
- * An ImageReaderProxy implementation that allows to modify the ImageInfo data of the images
- * retrieved.
- */
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-class ModifiableImageReaderProxy extends AndroidImageReaderProxy {
- private volatile TagBundle mTagBundle = null;
- private volatile Long mTimestamp = null;
- private volatile Integer mRotationDegrees = null;
- private volatile Matrix mSensorToBufferTransformMatrix = null;
-
- ModifiableImageReaderProxy(@NonNull ImageReader imageReader) {
- super(imageReader);
- }
-
- void setImageTagBundle(@NonNull TagBundle tagBundle) {
- mTagBundle = tagBundle;
- }
-
- void setImageTimeStamp(long timestamp) {
- mTimestamp = timestamp;
- }
-
- void setImageRotationDegrees(int rotationDegrees) {
- mRotationDegrees = rotationDegrees;
- }
-
- void setImageSensorToBufferTransformaMatrix(@NonNull Matrix matrix) {
- mSensorToBufferTransformMatrix = matrix;
- }
-
- @Nullable
- @Override
- public ImageProxy acquireLatestImage() {
- return modifyImage(super.acquireNextImage());
- }
-
- @Nullable
- @Override
- public ImageProxy acquireNextImage() {
- return modifyImage(super.acquireNextImage());
- }
-
- private ImageProxy modifyImage(ImageProxy imageProxy) {
- ImageInfo origin = imageProxy.getImageInfo();
- ImageInfo imageInfo = ImmutableImageInfo.create(
- mTagBundle != null ? mTagBundle : origin.getTagBundle(),
- mTimestamp != null ? mTimestamp.longValue() : origin.getTimestamp(),
- mRotationDegrees != null ? mRotationDegrees.intValue() :
- origin.getRotationDegrees(),
- mSensorToBufferTransformMatrix != null ? mSensorToBufferTransformMatrix :
- origin.getSensorToBufferTransformMatrix());
- return new SettableImageProxy(imageProxy, imageInfo);
- }
-}
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
index bf4d35b..9a92907 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/Preview.java
@@ -26,7 +26,6 @@
import static androidx.camera.core.impl.PreviewConfig.OPTION_DEFAULT_SESSION_CONFIG;
import static androidx.camera.core.impl.PreviewConfig.OPTION_MAX_RESOLUTION;
import static androidx.camera.core.impl.PreviewConfig.OPTION_PREVIEW_CAPTURE_PROCESSOR;
-import static androidx.camera.core.impl.PreviewConfig.OPTION_RGBA8888_SURFACE_REQUIRED;
import static androidx.camera.core.impl.PreviewConfig.OPTION_SESSION_CONFIG_UNPACKER;
import static androidx.camera.core.impl.PreviewConfig.OPTION_SUPPORTED_RESOLUTIONS;
import static androidx.camera.core.impl.PreviewConfig.OPTION_SURFACE_OCCUPANCY_PRIORITY;
@@ -205,9 +204,8 @@
mSessionDeferrableSurface.close();
}
- boolean isRGBA8888SurfaceRequired = config.isRgba8888SurfaceRequired(false);
final SurfaceRequest surfaceRequest = new SurfaceRequest(resolution, getCamera(),
- isRGBA8888SurfaceRequired);
+ captureProcessor != null);
mCurrentSurfaceRequest = surfaceRequest;
if (sendSurfaceRequestIfReady()) {
@@ -1033,18 +1031,6 @@
return this;
}
- /**
- * Sets if the surface requires RGBA8888 format.
- * @hide
- */
- @RestrictTo(Scope.LIBRARY_GROUP)
- @NonNull
- public Builder setIsRgba8888SurfaceRequired(boolean isRgba8888SurfaceRequired) {
- getMutableConfig().insertOption(
- OPTION_RGBA8888_SURFACE_REQUIRED, isRgba8888SurfaceRequired);
- return this;
- }
-
/** @hide */
@RestrictTo(Scope.LIBRARY_GROUP)
@NonNull
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java b/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java
index 406ba95..e702f3b 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/ProcessingImageReader.java
@@ -144,7 +144,7 @@
boolean mProcessing = false;
@GuardedBy("mLock")
- final ImageReaderProxy mInputImageReader;
+ final MetadataImageReader mInputImageReader;
@GuardedBy("mLock")
final ImageReaderProxy mOutputImageReader;
@@ -403,11 +403,7 @@
@Nullable
CameraCaptureCallback getCameraCaptureCallback() {
synchronized (mLock) {
- if (mInputImageReader instanceof MetadataImageReader) {
- return ((MetadataImageReader) mInputImageReader).getCameraCaptureCallback();
- } else {
- return new CameraCaptureCallback() {};
- }
+ return mInputImageReader.getCameraCaptureCallback();
}
}
@@ -458,7 +454,7 @@
*/
static final class Builder {
@NonNull
- protected final ImageReaderProxy mInputImageReader;
+ protected final MetadataImageReader mInputImageReader;
@NonNull
protected final CaptureBundle mCaptureBundle;
@NonNull
@@ -477,7 +473,7 @@
* @param captureProcessor The {@link CaptureProcessor} to be invoked when the Images are
* ready
*/
- Builder(@NonNull ImageReaderProxy imageReader, @NonNull CaptureBundle captureBundle,
+ Builder(@NonNull MetadataImageReader imageReader, @NonNull CaptureBundle captureBundle,
@NonNull CaptureProcessor captureProcessor) {
mInputImageReader = imageReader;
mCaptureBundle = captureBundle;
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java
index fc37406..0f233fb 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/ImageCaptureConfig.java
@@ -62,8 +62,6 @@
Option.create("camerax.core.imageCapture.flashType", int.class);
public static final Option<Integer> OPTION_JPEG_COMPRESSION_QUALITY =
Option.create("camerax.core.imageCapture.jpegCompressionQuality", int.class);
- public static final Option<Boolean> OPTION_SESSION_PROCESSOR_ENABLED =
- Option.create("camerax.core.imageCapture.sessionProcessorEnabled", boolean.class);
// *********************************************************************************************
@@ -290,13 +288,6 @@
return retrieveOption(OPTION_JPEG_COMPRESSION_QUALITY);
}
- /**
- * Returns if the SessionProcessor is enabled.
- */
- public boolean isSessionProcessorEnabled() {
- return retrieveOption(OPTION_SESSION_PROCESSOR_ENABLED, false);
- }
-
// Implementations of IO default methods
/**
diff --git a/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java b/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java
index 6d235ab..146c52a 100644
--- a/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java
+++ b/camera/camera-core/src/main/java/androidx/camera/core/impl/PreviewConfig.java
@@ -37,8 +37,6 @@
"camerax.core.preview.imageInfoProcessor", ImageInfoProcessor.class);
public static final Option<CaptureProcessor> OPTION_PREVIEW_CAPTURE_PROCESSOR =
Option.create("camerax.core.preview.captureProcessor", CaptureProcessor.class);
- public static final Option<Boolean> OPTION_RGBA8888_SURFACE_REQUIRED =
- Option.create("camerax.core.preview.isRgba8888SurfaceRequired", Boolean.class);
private final OptionsBundle mConfig;
/** Creates a new configuration instance. */
@@ -91,12 +89,6 @@
}
/**
- * Returns if the preview surface requires RGBA8888 format.
- */
- public boolean isRgba8888SurfaceRequired(boolean valueIfMissing) {
- return retrieveOption(OPTION_RGBA8888_SURFACE_REQUIRED, valueIfMissing);
- }
- /**
* Retrieves the format of the image that is fed as input.
*
* <p>This should be YUV_420_888, when processing is run on the image. Otherwise it is PRIVATE.
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java
index b7927fb..4204cc3 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/ExtensionsInfo.java
@@ -17,6 +17,9 @@
package androidx.camera.extensions;
+import android.content.Context;
+import android.hardware.camera2.CameraCharacteristics;
+import android.util.Pair;
import android.util.Range;
import android.util.Size;
@@ -42,7 +45,9 @@
import androidx.camera.extensions.internal.VendorExtender;
import androidx.camera.extensions.internal.Version;
+import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* A class for querying extensions related information.
@@ -227,6 +232,11 @@
private static VendorExtender getVendorExtender(int mode) {
boolean isAdvancedExtenderSupported = isAdvancedExtenderSupported();
+ // Disable Advanced Extender until it is well tested.
+ if (isAdvancedExtenderSupported) {
+ return new DisabledVendorExtender();
+ }
+
VendorExtender vendorExtender;
if (isAdvancedExtenderSupported) {
vendorExtender = new AdvancedVendorExtender(mode);
@@ -270,4 +280,47 @@
}
return id;
}
+
+ static class DisabledVendorExtender implements VendorExtender {
+ @Override
+ public boolean isExtensionAvailable(@NonNull String cameraId,
+ @NonNull Map<String, CameraCharacteristics> characteristicsMap) {
+ return false;
+ }
+
+ @Override
+ public void init(@NonNull CameraInfo cameraInfo) {
+
+ }
+
+ @Nullable
+ @Override
+ public Range<Long> getEstimatedCaptureLatencyRange(@Nullable Size size) {
+ return null;
+ }
+
+ @NonNull
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPreviewOutputResolutions() {
+ return Collections.emptyList();
+ }
+
+ @NonNull
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedCaptureOutputResolutions() {
+ return Collections.emptyList();
+ }
+
+ @NonNull
+ @Override
+ public Size[] getSupportedYuvAnalysisResolutions() {
+ return new Size[0];
+ }
+
+ @Nullable
+ @Override
+ public SessionProcessor createSessionProcessor(@NonNull Context context) {
+ return null;
+ }
+ }
}
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java
index a11ff2b..72a78cf 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/BasicVendorExtender.java
@@ -180,11 +180,16 @@
return map.getOutputSizes(imageFormat);
}
- private int getPreviewOutputImageFormat() {
- return ImageFormat.PRIVATE;
+ private int getPreviewInputImageFormat() {
+ if (mPreviewExtenderImpl != null && mPreviewExtenderImpl.getProcessorType()
+ == PreviewExtenderImpl.ProcessorType.PROCESSOR_TYPE_IMAGE_PROCESSOR) {
+ return ImageFormat.YUV_420_888;
+ } else {
+ return ImageFormat.PRIVATE;
+ }
}
- private int getCaptureOutputImageFormat() {
+ private int getCaptureInputImageFormat() {
if (mImageCaptureExtenderImpl != null
&& mImageCaptureExtenderImpl.getCaptureProcessor() != null) {
return ImageFormat.YUV_420_888;
@@ -213,7 +218,7 @@
// Returns output sizes from stream configuration map if OEM returns null or OEM does not
// implement the function. It is required to return all supported sizes so it must fetch
// all sizes from the stream configuration map here.
- int imageformat = getPreviewOutputImageFormat();
+ int imageformat = getPreviewInputImageFormat();
return Arrays.asList(new Pair<>(imageformat, getOutputSizes(imageformat)));
}
@@ -237,7 +242,7 @@
// Returns output sizes from stream configuration map if OEM returns null or OEM does not
// implement the function. It is required to return all supported sizes so it must fetch
// all sizes from the stream configuration map here.
- int imageFormat = getCaptureOutputImageFormat();
+ int imageFormat = getCaptureInputImageFormat();
return Arrays.asList(new Pair<>(imageFormat, getOutputSizes(imageFormat)));
}
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java
index a09bf72..c280363 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/ImageCaptureConfigProvider.java
@@ -118,8 +118,6 @@
} else {
Logger.e(TAG, "ImageCaptureExtenderImpl is null!");
}
- } else { // Advanced vendor interface
- builder.setSessionProcessorEnabled(true);
}
builder.getMutableConfig().insertOption(OPTION_IMAGE_CAPTURE_CONFIG_PROVIDER_MODE,
diff --git a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java
index 9fa8a86..3da8a12 100644
--- a/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java
+++ b/camera/camera-extensions/src/main/java/androidx/camera/extensions/internal/PreviewConfigProvider.java
@@ -105,7 +105,6 @@
AdaptingPreviewProcessor(
(PreviewImageProcessorImpl) previewExtenderImpl.getProcessor());
builder.setCaptureProcessor(adaptingPreviewProcessor);
- builder.setIsRgba8888SurfaceRequired(true);
previewEventAdapter = new PreviewEventAdapter(previewExtenderImpl, context,
adaptingPreviewProcessor);
break;
@@ -119,10 +118,6 @@
} else {
Logger.e(TAG, "PreviewExtenderImpl is null!");
}
- } else { // Advanced extensions interface.
- // Set RGB8888 = true always since we have no way to tell if the OEM implementation does
- // the processing or not.
- builder.setIsRgba8888SurfaceRequired(true);
}
builder.getMutableConfig().insertOption(OPTION_PREVIEW_CONFIG_PROVIDER_MODE, effectMode);
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/SurfaceTextureProvider.java b/camera/camera-testing/src/main/java/androidx/camera/testing/SurfaceTextureProvider.java
index 110695c..e9443ca 100644
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/SurfaceTextureProvider.java
+++ b/camera/camera-testing/src/main/java/androidx/camera/testing/SurfaceTextureProvider.java
@@ -101,30 +101,6 @@
}
/**
- * Creates a {@link Preview.SurfaceProvider} that is backed by a {@link SurfaceTexture} which
- * is suitable to be used in testing that doesn't actually show camera preview but just need
- * a surface for preview.
- *
- * <p> The {@link SurfaceTexture} will be released when it is no longer needed.
- *
- */
- @NonNull
- public static Preview.SurfaceProvider createSurfaceTextureProvider() {
- return createSurfaceTextureProvider(new SurfaceTextureCallback() {
- @Override
- public void onSurfaceTextureReady(@NonNull SurfaceTexture surfaceTexture,
- @NonNull Size resolution) {
- // no op
- }
-
- @Override
- public void onSafeToRelease(@NonNull SurfaceTexture surfaceTexture) {
- surfaceTexture.release();
- }
- });
- }
-
- /**
* Creates a {@link Preview.SurfaceProvider} that is backed by a {@link SurfaceTexture}.
*
* <p>This method also creates a backing OpenGL thread that will automatically drain frames
diff --git a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSessionProcessor.kt b/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSessionProcessor.kt
deleted file mode 100644
index f862765..0000000
--- a/camera/camera-testing/src/main/java/androidx/camera/testing/fakes/FakeSessionProcessor.kt
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.camera.testing.fakes
-
-import android.hardware.camera2.CameraDevice
-import android.media.ImageReader
-import android.media.ImageWriter
-import android.os.Handler
-import android.os.Looper
-import android.os.SystemClock
-import android.view.Surface
-import androidx.annotation.RequiresApi
-import androidx.camera.core.CameraInfo
-import androidx.camera.core.impl.CameraCaptureFailure
-import androidx.camera.core.impl.CameraCaptureResult
-import androidx.camera.core.impl.Config
-import androidx.camera.core.impl.DeferrableSurface
-import androidx.camera.core.impl.OptionsBundle
-import androidx.camera.core.impl.OutputSurface
-import androidx.camera.core.impl.RequestProcessor
-import androidx.camera.core.impl.SessionConfig
-import androidx.camera.core.impl.SessionProcessor
-import androidx.camera.core.impl.SessionProcessorSurface
-import androidx.camera.core.impl.utils.executor.CameraXExecutors
-import kotlinx.coroutines.CompletableDeferred
-import kotlinx.coroutines.Deferred
-import kotlinx.coroutines.withTimeout
-import kotlinx.coroutines.withTimeoutOrNull
-
-const val FAKE_CAPTURE_SEQUENCE_ID = 1
-
-@RequiresApi(23)
-class FakeSessionProcessor(
- val inputFormatPreview: Int?,
- val inputFormatCapture: Int?
-) : SessionProcessor {
- private lateinit var previewProcessorSurface: DeferrableSurface
- private lateinit var captureProcessorSurface: DeferrableSurface
- private var intermediaPreviewImageReader: ImageReader? = null
- private var intermediaCaptureImageReader: ImageReader? = null
- private var intermediaPreviewImageWriter: ImageWriter? = null
- private var intermediaCaptureImageWriter: ImageWriter? = null
-
- private val previewOutputConfigId = 1
- private val captureOutputConfigId = 2
-
- private var requestProcessor: RequestProcessor? = null
-
- // Values of these Deferred are the timestamp to complete.
- private val initSessionCalled = CompletableDeferred<Long>()
- private val deInitSessionCalled = CompletableDeferred<Long>()
- private val onCaptureSessionStartCalled = CompletableDeferred<Long>()
- private val onCaptureSessionEndCalled = CompletableDeferred<Long>()
- private val startRepeatingCalled = CompletableDeferred<Long>()
- private val startCaptureCalled = CompletableDeferred<Long>()
- private val setParametersCalled = CompletableDeferred<Config>()
- private var latestParameters: Config = OptionsBundle.emptyBundle()
- private var blockRunAfterInitSession: () -> Unit = {}
-
- fun releaseSurfaces() {
- intermediaPreviewImageReader?.close()
- intermediaCaptureImageReader?.close()
- }
-
- fun runAfterInitSession(block: () -> Unit) {
- blockRunAfterInitSession = block
- }
-
- override fun initSession(
- cameraInfo: CameraInfo,
- previewSurfaceConfig: OutputSurface,
- imageCaptureSurfaceConfig: OutputSurface,
- imageAnalysisSurfaceConfig: OutputSurface?
- ): SessionConfig {
- initSessionCalled.complete(SystemClock.elapsedRealtimeNanos())
- val handler = Handler(Looper.getMainLooper())
-
- var sessionBuilder = SessionConfig.Builder()
-
- // Preview
- lateinit var previewTransformedSurface: Surface
- if (inputFormatPreview == null) { // no conversion, use origin surface.
- previewTransformedSurface = previewSurfaceConfig.surface
- } else {
- intermediaPreviewImageReader = ImageReader.newInstance(
- 640, 480,
- inputFormatPreview, 2
- )
- previewTransformedSurface = intermediaPreviewImageReader!!.surface
-
- intermediaPreviewImageWriter = ImageWriter.newInstance(
- previewSurfaceConfig.surface, 2
- )
-
- intermediaPreviewImageReader!!.setOnImageAvailableListener(
- {
- it.acquireNextImage().use {
- val imageDequeued = intermediaPreviewImageWriter!!.dequeueInputImage()
- intermediaPreviewImageWriter!!.queueInputImage(imageDequeued)
- }
- },
- handler
- )
- }
- previewProcessorSurface =
- SessionProcessorSurface(previewTransformedSurface, previewOutputConfigId)
- previewProcessorSurface.terminationFuture.addListener(
- {
- intermediaPreviewImageReader?.close()
- intermediaPreviewImageWriter?.close()
- },
- CameraXExecutors.directExecutor()
- )
- sessionBuilder.addSurface(previewProcessorSurface)
-
- // Capture
- lateinit var captureTransformedSurface: Surface
- if (inputFormatCapture == null) { // no conversion, use origin surface.
- captureTransformedSurface = imageCaptureSurfaceConfig.surface
- } else {
- intermediaCaptureImageReader = ImageReader.newInstance(
- 640, 480,
- inputFormatCapture, 2
- )
- captureTransformedSurface = intermediaCaptureImageReader!!.surface
-
- intermediaCaptureImageWriter = ImageWriter.newInstance(
- imageCaptureSurfaceConfig.surface, 2
- )
-
- intermediaCaptureImageReader!!.setOnImageAvailableListener(
- {
- it.acquireNextImage().use {
- val imageDequeued = intermediaCaptureImageWriter!!.dequeueInputImage()
- intermediaCaptureImageWriter!!.queueInputImage(imageDequeued)
- }
- },
- handler
- )
- }
- captureProcessorSurface =
- SessionProcessorSurface(captureTransformedSurface, captureOutputConfigId)
-
- captureProcessorSurface.terminationFuture.addListener(
- {
- intermediaCaptureImageReader?.close()
- intermediaCaptureImageWriter?.close()
- },
- CameraXExecutors.directExecutor()
- )
- sessionBuilder.addSurface(captureProcessorSurface)
-
- sessionBuilder.setTemplateType(CameraDevice.TEMPLATE_ZERO_SHUTTER_LAG)
- val sessionConfig = sessionBuilder.build()
- blockRunAfterInitSession()
- return sessionConfig
- }
-
- override fun deInitSession() {
- deInitSessionCalled.complete(SystemClock.elapsedRealtimeNanos())
- previewProcessorSurface.close()
- captureProcessorSurface.close()
- }
-
- override fun setParameters(config: Config) {
- setParametersCalled.complete(config)
- latestParameters = config
- }
-
- override fun onCaptureSessionStart(_requestProcessor: RequestProcessor) {
- onCaptureSessionStartCalled.complete(SystemClock.elapsedRealtimeNanos())
- requestProcessor = _requestProcessor
- }
-
- override fun onCaptureSessionEnd() {
- onCaptureSessionEndCalled.complete(SystemClock.elapsedRealtimeNanos())
- }
-
- fun getLatestParameters(): Config {
- return latestParameters
- }
-
- override fun startRepeating(callback: SessionProcessor.CaptureCallback): Int {
- startRepeatingCalled.complete(SystemClock.elapsedRealtimeNanos())
- val builder = RequestProcessorRequest.Builder().apply {
- addTargetOutputConfigId(previewOutputConfigId)
- setParameters(latestParameters)
- setTemplateId(CameraDevice.TEMPLATE_PREVIEW)
- }
-
- requestProcessor!!.setRepeating(
- builder.build(),
- object : RequestProcessor.Callback {
- override fun onCaptureStarted(
- request: RequestProcessor.Request,
- frameNumber: Long,
- timestamp: Long
- ) {}
-
- override fun onCaptureProgressed(
- request: RequestProcessor.Request,
- captureResult: CameraCaptureResult
- ) {}
-
- override fun onCaptureCompleted(
- request: RequestProcessor.Request,
- captureResult: CameraCaptureResult
- ) {
- callback.onCaptureSequenceCompleted(1)
- }
-
- override fun onCaptureFailed(
- request: RequestProcessor.Request,
- captureFailure: CameraCaptureFailure
- ) {}
-
- override fun onCaptureBufferLost(
- request: RequestProcessor.Request,
- frameNumber: Long,
- outputConfigId: Int
- ) {}
-
- override fun onCaptureSequenceCompleted(
- sequenceId: Int,
- frameNumber: Long
- ) {}
-
- override fun onCaptureSequenceAborted(sequenceId: Int) {
- }
- }
- )
- return FAKE_CAPTURE_SEQUENCE_ID
- }
-
- override fun stopRepeating() {
- }
-
- override fun startCapture(callback: SessionProcessor.CaptureCallback): Int {
- startCaptureCalled.complete(SystemClock.elapsedRealtimeNanos())
- val request = RequestProcessorRequest.Builder().apply {
- addTargetOutputConfigId(captureOutputConfigId)
- setParameters(latestParameters)
- setTemplateId(CameraDevice.TEMPLATE_STILL_CAPTURE)
- }.build()
-
- requestProcessor!!.submit(
- request,
- object : RequestProcessor.Callback {
- override fun onCaptureCompleted(
- request: RequestProcessor.Request,
- captureResult: CameraCaptureResult
- ) {
- callback.onCaptureSequenceCompleted(1)
- }
-
- override fun onCaptureStarted(
- request: RequestProcessor.Request,
- frameNumber: Long,
- timestamp: Long
- ) {}
-
- override fun onCaptureProgressed(
- request: RequestProcessor.Request,
- captureResult: CameraCaptureResult
- ) {}
-
- override fun onCaptureFailed(
- request: RequestProcessor.Request,
- captureFailure: CameraCaptureFailure
- ) {
- callback.onCaptureFailed(1)
- }
-
- override fun onCaptureBufferLost(
- request: RequestProcessor.Request,
- frameNumber: Long,
- outputConfigId: Int
- ) {}
-
- override fun onCaptureSequenceCompleted(sequenceId: Int, frameNumber: Long) {}
-
- override fun onCaptureSequenceAborted(sequenceId: Int) {}
- }
- )
- return FAKE_CAPTURE_SEQUENCE_ID
- }
-
- override fun abortCapture(captureSequenceId: Int) {
- }
-
- suspend fun assertInitSessionInvoked(): Long {
- return initSessionCalled.awaitWithTimeout(3000)
- }
-
- suspend fun wasInitSessionInvoked(): Boolean {
- val result = withTimeoutOrNull(3000) { initSessionCalled.await() }
- return result != null
- }
-
- suspend fun assertDeInitSessionInvoked(): Long {
- return deInitSessionCalled.awaitWithTimeout(3000)
- }
-
- suspend fun assertOnCaptureSessionStartInvoked(): Long {
- return onCaptureSessionStartCalled.awaitWithTimeout(3000)
- }
-
- suspend fun wasOnCaptureSessionStartInvoked(): Boolean {
- val result = withTimeoutOrNull(3000) { onCaptureSessionStartCalled.await() }
- return result != null
- }
-
- suspend fun assertOnCaptureEndInvoked(): Long {
- return onCaptureSessionEndCalled.awaitWithTimeout(3000)
- }
-
- suspend fun assertStartRepeatingInvoked(): Long {
- return startRepeatingCalled.awaitWithTimeout(3000)
- }
-
- suspend fun assertStartCaptureInvoked(): Long {
- return startCaptureCalled.awaitWithTimeout(3000)
- }
-
- suspend fun assertSetParametersInvoked(): Config {
- return setParametersCalled.awaitWithTimeout(3000)
- }
-
- private suspend fun <T> Deferred<T>.awaitWithTimeout(timeMillis: Long): T {
- return withTimeout(timeMillis) {
- await()
- }
- }
-}
-
-@RequiresApi(21) // TODO(b/200306659): Remove and replace with annotation on package-info.java
-internal class RequestProcessorRequest(
- private val targetOutputConfigIds: List<Int>,
- private val parameters: Config,
- private val templateId: Int
-) : RequestProcessor.Request {
- override fun getTargetOutputConfigIds(): List<Int> {
- return targetOutputConfigIds
- }
-
- override fun getParameters(): Config {
- return parameters
- }
-
- override fun getTemplateId(): Int {
- return templateId
- }
-
- class Builder {
- private var targetOutputConfigIds: MutableList<Int> = ArrayList()
- private var parameters: Config = OptionsBundle.emptyBundle()
- private var templateId = CameraDevice.TEMPLATE_PREVIEW
-
- fun addTargetOutputConfigId(targetOutputConfigId: Int): Builder {
- targetOutputConfigIds.add(targetOutputConfigId)
- return this
- }
-
- fun setParameters(parameters: Config): Builder {
- this.parameters = parameters
- return this
- }
-
- fun setTemplateId(templateId: Int): Builder {
- this.templateId = templateId
- return this
- }
-
- fun build(): RequestProcessorRequest {
- return RequestProcessorRequest(
- targetOutputConfigIds.toList(),
- OptionsBundle.from(parameters),
- templateId
- )
- }
- }
-}
diff --git a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
index 342ffd0..b06614e 100644
--- a/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
+++ b/camera/integration-tests/coretestapp/src/androidTest/java/androidx/camera/integration/core/ImageCaptureTest.kt
@@ -41,37 +41,26 @@
import androidx.camera.camera2.pipe.integration.CameraPipeConfig
import androidx.camera.core.AspectRatio
import androidx.camera.core.Camera
-import androidx.camera.core.CameraFilter
-import androidx.camera.core.CameraInfo
import androidx.camera.core.CameraSelector
import androidx.camera.core.CameraXConfig
import androidx.camera.core.ImageCapture
import androidx.camera.core.ImageCaptureException
import androidx.camera.core.ImageProxy
-import androidx.camera.core.Preview
import androidx.camera.core.UseCaseGroup
import androidx.camera.core.ViewPort
-import androidx.camera.core.impl.CameraConfig
import androidx.camera.core.impl.CaptureBundle
import androidx.camera.core.impl.CaptureConfig
import androidx.camera.core.impl.CaptureProcessor
import androidx.camera.core.impl.CaptureStage
-import androidx.camera.core.impl.Config
-import androidx.camera.core.impl.ExtendedCameraConfigProviderStore
-import androidx.camera.core.impl.Identifier
import androidx.camera.core.impl.ImageCaptureConfig
import androidx.camera.core.impl.ImageOutputConfig
import androidx.camera.core.impl.ImageProxyBundle
-import androidx.camera.core.impl.MutableOptionsBundle
-import androidx.camera.core.impl.SessionProcessor
import androidx.camera.core.impl.utils.CameraOrientationUtil
import androidx.camera.core.impl.utils.Exif
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.camera.testing.CameraUtil
-import androidx.camera.testing.SurfaceTextureProvider
import androidx.camera.testing.fakes.FakeCaptureStage
import androidx.camera.testing.fakes.FakeLifecycleOwner
-import androidx.camera.testing.fakes.FakeSessionProcessor
import androidx.core.content.ContextCompat
import androidx.test.core.app.ApplicationProvider
import androidx.test.filters.LargeTest
@@ -1414,139 +1403,6 @@
simpleCaptureProcessor.close()
}
- @Test
- @SdkSuppress(minSdkVersion = 29)
- fun returnJpegImage_whenSessionProcessorIsSet_outputFormantYuv() = runBlocking {
- skipTestOnCameraPipeConfig()
-
- val builder = ImageCapture.Builder()
- val sessionProcessor = FakeSessionProcessor(
- inputFormatPreview = null, // null means using the same output surface
- inputFormatCapture = ImageFormat.YUV_420_888
- )
-
- val imageCapture = builder
- .setSessionProcessorEnabled(true)
- .setSupportedResolutions(
- listOf(android.util.Pair(ImageFormat.YUV_420_888, arrayOf(Size(640, 480)))))
- .build()
-
- val preview = Preview.Builder().build()
-
- var camera: Camera
- withContext(Dispatchers.Main) {
- preview.setSurfaceProvider(SurfaceTextureProvider.createSurfaceTextureProvider())
- val cameraSelector =
- getCameraSelectorWithSessionProcessor(BACK_SELECTOR, sessionProcessor)
- camera = cameraProvider.bindToLifecycle(
- fakeLifecycleOwner, cameraSelector, imageCapture, preview)
- }
-
- val callback = FakeImageCaptureCallback(capturesCount = 1)
- imageCapture.takePicture(mainExecutor, callback)
-
- // Wait for the signal that the image has been captured.
- callback.awaitCapturesAndAssert(capturedImagesCount = 1)
-
- val imageProperties = callback.results.first()
-
- // Check the output image rotation degrees value is correct.
- assertThat(imageProperties.rotationDegrees).isEqualTo(
- camera.cameraInfo.getSensorRotationDegrees(imageCapture.targetRotation)
- )
- // Check the output format is correct.
- assertThat(imageProperties.format).isEqualTo(ImageFormat.JPEG)
- }
-
- @Test
- @SdkSuppress(minSdkVersion = 29)
- fun returnJpegImage_whenSessionProcessorIsSet_outputFormantJpeg() = runBlocking {
- assumeFalse(
- "Cuttlefish does not correctly handle Jpeg exif. Unable to test.",
- Build.MODEL.contains("Cuttlefish")
- )
- skipTestOnCameraPipeConfig()
-
- val builder = ImageCapture.Builder()
- val sessionProcessor = FakeSessionProcessor(
- inputFormatPreview = null, // null means using the same output surface
- inputFormatCapture = null
- )
-
- val imageCapture = builder
- .setSessionProcessorEnabled(true)
- .setSupportedResolutions(
- listOf(android.util.Pair(ImageFormat.JPEG, arrayOf(Size(640, 480)))))
- .build()
-
- val preview = Preview.Builder().build()
-
- withContext(Dispatchers.Main) {
- preview.setSurfaceProvider(SurfaceTextureProvider.createSurfaceTextureProvider())
- val cameraSelector =
- getCameraSelectorWithSessionProcessor(BACK_SELECTOR, sessionProcessor)
- cameraProvider.bindToLifecycle(
- fakeLifecycleOwner, cameraSelector, imageCapture, preview)
- }
-
- val callback = FakeImageCaptureCallback(capturesCount = 1)
- imageCapture.takePicture(mainExecutor, callback)
-
- // Wait for the signal that the image has been captured.
- callback.awaitCapturesAndAssert(capturedImagesCount = 1)
-
- val imageProperties = callback.results.first()
-
- // Check the output image rotation degrees value is correct.
- assertThat(imageProperties.rotationDegrees).isEqualTo(imageProperties.exif!!.rotation)
-
- // Check the output format is correct.
- assertThat(imageProperties.format).isEqualTo(ImageFormat.JPEG)
- }
-
- private fun getCameraSelectorWithSessionProcessor(
- cameraSelector: CameraSelector,
- sessionProcessor: SessionProcessor
- ): CameraSelector {
- val identifier = Identifier.create("idStr")
- ExtendedCameraConfigProviderStore.addConfig(identifier) { _, _ ->
- object : CameraConfig {
- override fun getConfig(): Config {
- return MutableOptionsBundle.create()
- }
-
- override fun getCompatibilityId(): Identifier {
- return Identifier.create(0)
- }
-
- override fun getSessionProcessor(
- valueIfMissing: SessionProcessor?
- ): SessionProcessor? {
- return sessionProcessor
- }
-
- override fun getSessionProcessor(): SessionProcessor {
- return sessionProcessor
- }
- }
- }
-
- val builder = CameraSelector.Builder.fromSelector(cameraSelector)
- builder.addCameraFilter(object : CameraFilter {
- override fun filter(cameraInfos: MutableList<CameraInfo>): MutableList<CameraInfo> {
- val newCameraInfos = mutableListOf<CameraInfo>()
- newCameraInfos.addAll(cameraInfos)
- return newCameraInfos
- }
-
- override fun getIdentifier(): Identifier {
- return identifier
- }
- })
-
- return builder.build()
- }
-
// Output JPEG format image when setting a CaptureProcessor is only enabled for devices that
// API level is at least 29.
@Test