summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRavneet Dhanjal <rdhanjal@google.com>2022-12-01 19:50:01 +0000
committerRavneet Dhanjal <rdhanjal@google.com>2022-12-16 07:00:46 +0000
commit8e874f79e1a83b1492fe1b78dc658323c3c7e79e (patch)
tree18d13ecc1c62761f8e85d902dc8f2efd1e6fd4d1
parent3b33dca1352e43728d64249818d43d904f4104ad (diff)
downloadex-8e874f79e1a83b1492fe1b78dc658323c3c7e79e.tar.gz
Camera Extensions: Add Postview to sample
- Enable postview in extension samples - Add sample postview feature to the basic extension sample Test: Camera CTS Bug: 258295487 Change-Id: I98506f0edd6c2e7f2da0740a243bb564db82274d
-rwxr-xr-xcamera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java10
-rwxr-xr-xcamera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java10
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java10
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java50
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java10
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java26
-rwxr-xr-xcamera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java10
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java22
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java28
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java2
-rw-r--r--camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java20
-rwxr-xr-xcamera2/extensions/sample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java35
-rwxr-xr-xcamera2/extensions/sample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java35
-rw-r--r--camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java125
-rw-r--r--camera2/extensions/sample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java50
-rw-r--r--camera2/extensions/sample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java35
-rw-r--r--camera2/extensions/sample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java26
-rwxr-xr-xcamera2/extensions/sample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java35
18 files changed, 536 insertions, 3 deletions
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
index 49a5a0ef..bd605708 100755
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
@@ -95,6 +95,11 @@ public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderI
throw new RuntimeException("Stub, replace with implementation.");
}
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
@Nullable
@Override
public Range<Long> getEstimatedCaptureLatencyRange(@NonNull Size captureOutputSize) {
@@ -127,4 +132,9 @@ public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderI
public Pair<Long, Long> getRealtimeCaptureLatency() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
index 4a7f9203..50c80407 100755
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
@@ -95,6 +95,11 @@ public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtende
throw new RuntimeException("Stub, replace with implementation.");
}
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
@Nullable
@Override
public Range<Long> getEstimatedCaptureLatencyRange(@NonNull Size captureOutputSize) {
@@ -127,4 +132,9 @@ public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtende
public Pair<Long, Long> getRealtimeCaptureLatency() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
index 576029c0..ee777cf9 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
@@ -95,6 +95,11 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
throw new RuntimeException("Stub, replace with implementation.");
}
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
@Nullable
@Override
public Range<Long> getEstimatedCaptureLatencyRange(@NonNull Size captureOutputSize) {
@@ -127,4 +132,9 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
public Pair<Long, Long> getRealtimeCaptureLatency() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
index 3eee146a..f4719b8b 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
@@ -21,6 +21,7 @@ import android.graphics.ImageFormat;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.util.Pair;
+import android.util.Size;
import android.view.Surface;
import java.util.Map;
@@ -46,6 +47,29 @@ public interface CaptureProcessorImpl extends ProcessorImpl {
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
/**
+ * Informs the CaptureProcessorImpl where it should write the postview output to.
+ * This will only be invoked once if a valid postview surface was set.
+ *
+ * @param surface A valid {@link ImageFormat#YUV_420_888} {@link Surface}
+ * that the CaptureProcessorImpl should write data into.
+ * @since 1.4
+ */
+ void onPostviewOutputSurface(Surface surface);
+
+ /**
+ * Invoked when the Camera Framework changes the configured output resolution for
+ * still capture and postview.
+ *
+ * <p>After this call, {@link CaptureProcessorImpl} should expect any {@link Image} received as
+ * input for still capture and postview to be at the specified resolutions.
+ *
+ * @param size for the surface for still capture.
+ * @param postviewSize for the surface for postview.
+ * @since 1.4
+ */
+ void onResolutionUpdate(Size size, Size postviewSize);
+
+ /**
* Process a set images captured that were requested.
*
* <p> The result of the processing step should be written to the {@link Surface} that was
@@ -63,4 +87,30 @@ public interface CaptureProcessorImpl extends ProcessorImpl {
*/
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor);
+
+ /**
+ * Process a set images captured that were requested for both postview and
+ * still capture.
+ *
+ * <p> This processing method will be called if a postview was requested, therefore the
+ * processed postview should be written to the
+ * {@link Surface} received by {@link #onPostviewOutputSurface(Surface, int)}.
+ * The final result of the processing step should be written to the {@link Surface} that was
+ * received by {@link #onOutputSurface(Surface, int)}. Since postview should be available
+ * before the capture, it should be processed and written to the surface before
+ * the final capture is processed.
+ *
+ * @param results The map of {@link ImageFormat#YUV_420_888} format images and
+ * metadata to process. The {@link Image} that are contained within
+ * the map will become invalid after this method completes, so no
+ * references to them should be kept.
+ * @param resultCallback Capture result callback to be called once the capture result
+ * values of the processed image are ready.
+ * @param executor The executor to run the callback on. If null then the callback
+ * will run on any arbitrary executor.
+ * @throws RuntimeException if postview feature is not supported
+ * @since 1.4
+ */
+ void processWithPostview(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor);
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
index a505cb8b..f3fd2f3b 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
@@ -95,6 +95,11 @@ public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderIm
throw new RuntimeException("Stub, replace with implementation.");
}
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
@Nullable
@Override
public Range<Long> getEstimatedCaptureLatencyRange(@NonNull Size captureOutputSize) {
@@ -127,4 +132,9 @@ public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderIm
public Pair<Long, Long> getRealtimeCaptureLatency() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
index cfc23b11..70c1804e 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
@@ -85,6 +85,21 @@ public interface ImageCaptureExtenderImpl extends ExtenderStateListener {
List<Pair<Integer, Size[]>> getSupportedResolutions();
/**
+ * Returns the customized supported postview resolutions for a still capture using
+ * its size.
+ *
+ * <p>Pair list composed with {@link ImageFormat} and {@link Size} array will be returned.
+ *
+ * <p>The returned resolutions should be subset of the supported sizes retrieved from
+ * {@link android.hardware.camera2.params.StreamConfigurationMap} for the camera device.
+ *
+ * @return the customized supported resolutions, or null to support all sizes retrieved from
+ * {@link android.hardware.camera2.params.StreamConfigurationMap}.
+ * @since 1.4
+ */
+ List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize);
+
+ /**
* Returns the estimated capture latency range in milliseconds for the target capture
* resolution.
*
@@ -188,4 +203,15 @@ public interface ImageCaptureExtenderImpl extends ExtenderStateListener {
* @since 1.4
*/
Pair<Long, Long> getRealtimeCaptureLatency();
+
+ /**
+ * Indicates whether the extension supports the postview for still capture feature.
+ * If the extension is using HAL processing, false should be returned since the
+ * postview feature is not currently supported for this case.
+ *
+ * @return {@code true} in case postview for still capture is supported
+ * {@code false} otherwise.
+ * @since 1.4
+ */
+ boolean isPostviewAvailable();
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
index 829c8a09..6f0eaef9 100755
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
@@ -95,6 +95,11 @@ public final class NightImageCaptureExtenderImpl implements ImageCaptureExtender
throw new RuntimeException("Stub, replace with implementation.");
}
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
+
@Nullable
@Override
public Range<Long> getEstimatedCaptureLatencyRange(@NonNull Size captureOutputSize) {
@@ -127,4 +132,9 @@ public final class NightImageCaptureExtenderImpl implements ImageCaptureExtender
public Pair<Long, Long> getRealtimeCaptureLatency() {
throw new RuntimeException("Stub, replace with implementation.");
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ throw new RuntimeException("Stub, replace with implementation.");
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
index fcda9bee..abcbf5fd 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/AdvancedExtenderImpl.java
@@ -124,6 +124,17 @@ public interface AdvancedExtenderImpl {
Map<Integer, List<Size>> getSupportedCaptureOutputResolutions(String cameraId);
/**
+ * Returns supported output format/size map for postview image. OEM is required to support
+ * both JPEG and YUV_420_888 format output.
+ *
+ * <p>The surface created with this supported format/size could configure
+ * intermediate surfaces(YUV/RAW..) and write the output to the output surface.</p>
+ *
+ * @since 1.4
+ */
+ Map<Integer, List<Size>> getSupportedPostviewResolutions(Size captureSize);
+
+ /**
* Returns supported output sizes for Image Analysis (YUV_420_888 format).
*
* <p>OEM can optionally support a YUV surface for ImageAnalysis along with Preview/ImageCapture
@@ -194,4 +205,15 @@ public interface AdvancedExtenderImpl {
* @since 1.4
*/
boolean isCaptureProcessProgressAvailable();
+
+ /**
+ * Indicates whether the extension supports the postview for still capture feature.
+ * If the extension is using HAL processing, false should be returned since the
+ * postview feature is not currently supported for this case.
+ *
+ * @return {@code true} in case postview for still capture is supported
+ * {@code false} otherwise.
+ * @since 1.4
+ */
+ boolean isPostviewAvailable();
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
index 7041dae5..00b57058 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/BaseAdvancedExtenderImpl.java
@@ -116,6 +116,11 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
}
@Override
+ public Map<Integer, List<Size>> getSupportedPostviewResolutions(Size captureSize) {
+ return new HashMap<>();
+ }
+
+ @Override
public List<Size> getSupportedYuvAnalysisResolutions(
String cameraId) {
return null;
@@ -217,7 +222,8 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
// called. This is just a sample for earlier versions if wanting to redirect this call.
OutputSurfaceConfigurationImplImpl surfaceConfigs =
new OutputSurfaceConfigurationImplImpl(previewSurfaceConfig,
- imageCaptureSurfaceConfig, imageAnalysisSurfaceConfig);
+ imageCaptureSurfaceConfig, imageAnalysisSurfaceConfig,
+ null /*postviewSurfaceConfig*/);
return initSession(cameraId, cameraCharacteristicsMap, context, surfaceConfigs);
}
@@ -452,6 +458,11 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
}
@Override
+ public int startCaptureWithPostview(@NonNull CaptureCallback captureCallback) {
+ return startCapture(captureCallback);
+ }
+
+ @Override
public int startCapture(@NonNull CaptureCallback captureCallback) {
List<RequestProcessorImpl.Request> requestList = new ArrayList<>();
addCaptureRequestParameters(requestList);
@@ -626,13 +637,16 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
private OutputSurfaceImpl mOutputPreviewSurfaceImpl;
private OutputSurfaceImpl mOutputImageCaptureSurfaceImpl;
private OutputSurfaceImpl mOutputImageAnalysisSurfaceImpl;
+ private OutputSurfaceImpl mOutputPostviewSurfaceImpl;
public OutputSurfaceConfigurationImplImpl(OutputSurfaceImpl previewSurfaceConfig,
OutputSurfaceImpl imageCaptureSurfaceConfig,
- OutputSurfaceImpl imageAnalysisSurfaceConfig) {
+ OutputSurfaceImpl imageAnalysisSurfaceConfig,
+ OutputSurfaceImpl postviewSurfaceConfig) {
mOutputPreviewSurfaceImpl = previewSurfaceConfig;
mOutputImageCaptureSurfaceImpl = imageCaptureSurfaceConfig;
mOutputImageAnalysisSurfaceImpl = imageAnalysisSurfaceConfig;
+ mOutputPostviewSurfaceImpl = postviewSurfaceConfig;
}
@Override
@@ -649,6 +663,11 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
public OutputSurfaceImpl getImageAnalysisOutputSurface() {
return mOutputImageAnalysisSurfaceImpl;
}
+
+ @Override
+ public OutputSurfaceImpl getPostviewOutputSurface() {
+ return mOutputPostviewSurfaceImpl;
+ }
}
@Override
@@ -672,4 +691,9 @@ public abstract class BaseAdvancedExtenderImpl implements AdvancedExtenderImpl {
public boolean isCaptureProcessProgressAvailable() {
return true;
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ return false;
+ }
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
index 8e470139..ca3832e3 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/OutputSurfaceConfigurationImpl.java
@@ -30,4 +30,6 @@ public interface OutputSurfaceConfigurationImpl {
public OutputSurfaceImpl getImageCaptureOutputSurface();
public OutputSurfaceImpl getImageAnalysisOutputSurface();
+
+ public OutputSurfaceImpl getPostviewOutputSurface();
}
diff --git a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
index 11e63956..8dbfadc2 100644
--- a/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
+++ b/camera2/extensions/advancedSample/src/java/androidx/camera/extensions/impl/advanced/SessionProcessorImpl.java
@@ -224,6 +224,26 @@ public interface SessionProcessorImpl {
void stopRepeating();
/**
+ * Start a multi-frame capture with a postview. {@link #startCapture(CaptureCallback)}
+ * will be used for captures without a postview request.
+ *
+ * Postview will be available before the capture. Upon postview completion,
+ * {@code OnImageAvailableListener#onImageAvailable} will be called on the ImageReader
+ * that creates the postview output surface. When the capture is completed,
+ * {@link CaptureCallback#onCaptureSequenceCompleted} is called and
+ * {@code OnImageAvailableListener#onImageAvailable} will also be called on the ImageReader
+ * that creates the image capture output surface.
+ *
+ * <p>Only one capture can perform at a time. Starting a capture when another capture is
+ * running will cause onCaptureFailed to be called immediately.
+ *
+ * @param callback a callback to report the status.
+ * @return the id of the capture sequence.
+ * @since 1.4
+ */
+ int startCaptureWithPostview(CaptureCallback callback);
+
+ /**
* Start a multi-frame capture.
*
* When the capture is completed, {@link CaptureCallback#onCaptureSequenceCompleted}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
index fa19a03a..30a79a6b 100755
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/AutoImageCaptureExtenderImpl.java
@@ -117,6 +117,26 @@ public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderI
}
@Override
+ public void onPostviewOutputSurface(Surface surface) {
+
+ }
+
+ @Override
+ public void processWithPostview(
+ Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor) {
+ if (!isPostviewAvailable()) {
+ throw new RuntimeException("The extension doesn't support postview");
+ }
+
+ if (resultCallback != null) {
+ process(results, resultCallback, executor);
+ } else {
+ process(results);
+ }
+ }
+
+ @Override
public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor) {
throw new RuntimeException("The extension doesn't support capture " +
@@ -165,6 +185,11 @@ public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderI
}
@Override
+ public void onResolutionUpdate(Size size, Size postviewSize) {
+
+ }
+
+ @Override
public void onImageFormatUpdate(int imageFormat) {
}
@@ -245,6 +270,11 @@ public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderI
}
@Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ return new ArrayList<>();
+ }
+
+ @Override
public Range<Long> getEstimatedCaptureLatencyRange(Size captureOutputSize) {
return null;
}
@@ -273,4 +303,9 @@ public final class AutoImageCaptureExtenderImpl implements ImageCaptureExtenderI
public Pair<Long, Long> getRealtimeCaptureLatency() {
return null;
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ return false;
+ }
}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
index f769549b..c9b24206 100755
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BeautyImageCaptureExtenderImpl.java
@@ -119,6 +119,26 @@ public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtende
}
@Override
+ public void onPostviewOutputSurface(Surface surface) {
+
+ }
+
+ @Override
+ public void processWithPostview(
+ Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor) {
+ if (!isPostviewAvailable()) {
+ throw new RuntimeException("The extension doesn't support postview");
+ }
+
+ if (resultCallback != null) {
+ process(results, resultCallback, executor);
+ } else {
+ process(results);
+ }
+ }
+
+ @Override
public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor) {
throw new RuntimeException("The extension doesn't support capture " +
@@ -167,6 +187,11 @@ public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtende
}
@Override
+ public void onResolutionUpdate(Size size, Size postviewSize) {
+
+ }
+
+ @Override
public void onImageFormatUpdate(int imageFormat) {
}
@@ -268,6 +293,11 @@ public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtende
}
@Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ return new ArrayList<>();
+ }
+
+ @Override
public Range<Long> getEstimatedCaptureLatencyRange(Size captureOutputSize) {
return null;
}
@@ -296,4 +326,9 @@ public final class BeautyImageCaptureExtenderImpl implements ImageCaptureExtende
public Pair<Long, Long> getRealtimeCaptureLatency() {
return null;
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ return false;
+ }
}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
index d3412eb0..a72deef6 100644
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/BokehImageCaptureExtenderImpl.java
@@ -16,11 +16,13 @@
package androidx.camera.extensions.impl;
import android.content.Context;
+import android.graphics.ImageFormat;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.hardware.camera2.params.SessionConfiguration;
+import android.hardware.camera2.params.StreamConfigurationMap;
import android.media.Image;
import android.media.ImageWriter;
import android.os.Build;
@@ -52,6 +54,8 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
private static final int SESSION_STAGE_ID = 101;
private static final int MODE = CaptureRequest.CONTROL_AWB_MODE_SHADE;
+ private CameraCharacteristics mCameraCharacteristics;
+
/**
* @hide
*/
@@ -63,6 +67,7 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
*/
@Override
public void init(String cameraId, CameraCharacteristics cameraCharacteristics) {
+ mCameraCharacteristics = cameraCharacteristics;
}
/**
@@ -105,6 +110,7 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
CaptureProcessorImpl captureProcessor =
new CaptureProcessorImpl() {
private ImageWriter mImageWriter;
+ private ImageWriter mImageWriterPostview;
@Override
public void onOutputSurface(Surface surface, int imageFormat) {
@@ -114,6 +120,61 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
}
@Override
+ public void onPostviewOutputSurface(Surface surface) {
+ if ((Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) &&
+ mImageWriterPostview == null) {
+ mImageWriterPostview = ImageWriter.newInstance(surface, 1);
+ }
+ }
+
+ @Override
+ public void processWithPostview(
+ Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor) {
+
+ Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
+ if (result == null) {
+ Log.w(TAG,
+ "Unable to process since images does not contain all " +
+ "stages.");
+ return;
+ } else {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
+ Image image = mImageWriterPostview.dequeueInputImage();
+
+ // Postview processing here
+ ByteBuffer yByteBuffer = image.getPlanes()[0].getBuffer();
+ ByteBuffer uByteBuffer = image.getPlanes()[2].getBuffer();
+ ByteBuffer vByteBuffer = image.getPlanes()[1].getBuffer();
+
+ // For sample, allocate empty buffer to match postview size
+ yByteBuffer.put(ByteBuffer.allocate(image.getPlanes()[0]
+ .getBuffer().capacity()));
+ uByteBuffer.put(ByteBuffer.allocate(image.getPlanes()[2]
+ .getBuffer().capacity()));
+ vByteBuffer.put(ByteBuffer.allocate(image.getPlanes()[1]
+ .getBuffer().capacity()));
+ Long sensorTimestamp =
+ result.second.get(CaptureResult.SENSOR_TIMESTAMP);
+ if (sensorTimestamp != null) {
+ image.setTimestamp(sensorTimestamp);
+ } else {
+ Log.e(TAG, "Sensor timestamp absent using default!");
+ }
+
+ mImageWriterPostview.queueInputImage(image);
+ }
+ }
+
+ // Process still capture
+ if (resultCallback != null) {
+ process(results, resultCallback, executor);
+ } else {
+ process(results);
+ }
+ }
+
+ @Override
public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor) {
Pair<Image, TotalCaptureResult> result = results.get(DEFAULT_STAGE_ID);
@@ -242,6 +303,11 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
}
@Override
+ public void onResolutionUpdate(Size size, Size postviewSize) {
+
+ }
+
+ @Override
public void onImageFormatUpdate(int imageFormat) {
}
@@ -318,7 +384,59 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
*/
@Override
public List<Pair<Integer, Size[]>> getSupportedResolutions() {
- return null;
+ List<Pair<Integer, Size[]>> formatResolutionsPairList = new ArrayList<>();
+
+ StreamConfigurationMap map =
+ mCameraCharacteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
+
+ if (map != null) {
+ // The sample implementation only retrieves originally supported resolutions from
+ // CameraCharacteristics for JPEG and YUV_420_888 formats to return.
+ Size[] outputSizes = map.getOutputSizes(ImageFormat.JPEG);
+
+ if (outputSizes != null) {
+ formatResolutionsPairList.add(Pair.create(ImageFormat.JPEG, outputSizes));
+ }
+
+ outputSizes = map.getOutputSizes(ImageFormat.YUV_420_888);
+
+ if (outputSizes != null) {
+ formatResolutionsPairList.add(Pair.create(ImageFormat.YUV_420_888, outputSizes));
+ }
+ }
+
+ return formatResolutionsPairList;
+ }
+
+ @Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ // Sample for supported postview sizes, returns subset of supported resolutions for
+ // still capture that are less than its size and match the aspect ratio
+ List<Pair<Integer, Size[]>> res = new ArrayList<>();
+ List<Pair<Integer, Size[]>> captureSupportedResolutions = getSupportedResolutions();
+ float targetAr = ((float) captureSize.getWidth()) / captureSize.getHeight();
+
+ for (Pair<Integer, Size[]> elem : captureSupportedResolutions) {
+ Integer currFormat = elem.first;
+ Size[] currFormatSizes = elem.second;
+ List<Size> postviewSizes = new ArrayList<>();
+
+ for (Size s : currFormatSizes) {
+ if ((s.equals(captureSize)) || (s.getWidth() > captureSize.getWidth())
+ || (s.getHeight() > captureSize.getHeight())) continue;
+ float currentAr = ((float) s.getWidth()) / s.getHeight();
+ if (Math.abs(targetAr - currentAr) < 0.01) {
+ postviewSizes.add(s);
+ }
+ }
+
+ if (!postviewSizes.isEmpty()) {
+ res.add(new Pair<Integer, Size[]>(currFormat,
+ postviewSizes.toArray(new Size[postviewSizes.size()])));
+ }
+ }
+
+ return res;
}
@Override
@@ -357,4 +475,9 @@ public final class BokehImageCaptureExtenderImpl implements ImageCaptureExtender
public Pair<Long, Long> getRealtimeCaptureLatency() {
return null;
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ return true;
+ }
}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
index 3eee146a..f4719b8b 100644
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/CaptureProcessorImpl.java
@@ -21,6 +21,7 @@ import android.graphics.ImageFormat;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.util.Pair;
+import android.util.Size;
import android.view.Surface;
import java.util.Map;
@@ -46,6 +47,29 @@ public interface CaptureProcessorImpl extends ProcessorImpl {
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results);
/**
+ * Informs the CaptureProcessorImpl where it should write the postview output to.
+ * This will only be invoked once if a valid postview surface was set.
+ *
+ * @param surface A valid {@link ImageFormat#YUV_420_888} {@link Surface}
+ * that the CaptureProcessorImpl should write data into.
+ * @since 1.4
+ */
+ void onPostviewOutputSurface(Surface surface);
+
+ /**
+ * Invoked when the Camera Framework changes the configured output resolution for
+ * still capture and postview.
+ *
+ * <p>After this call, {@link CaptureProcessorImpl} should expect any {@link Image} received as
+ * input for still capture and postview to be at the specified resolutions.
+ *
+ * @param size for the surface for still capture.
+ * @param postviewSize for the surface for postview.
+ * @since 1.4
+ */
+ void onResolutionUpdate(Size size, Size postviewSize);
+
+ /**
* Process a set images captured that were requested.
*
* <p> The result of the processing step should be written to the {@link Surface} that was
@@ -63,4 +87,30 @@ public interface CaptureProcessorImpl extends ProcessorImpl {
*/
void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor);
+
+ /**
+ * Process a set images captured that were requested for both postview and
+ * still capture.
+ *
+ * <p> This processing method will be called if a postview was requested, therefore the
+ * processed postview should be written to the
+ * {@link Surface} received by {@link #onPostviewOutputSurface(Surface, int)}.
+ * The final result of the processing step should be written to the {@link Surface} that was
+ * received by {@link #onOutputSurface(Surface, int)}. Since postview should be available
+ * before the capture, it should be processed and written to the surface before
+ * the final capture is processed.
+ *
+ * @param results The map of {@link ImageFormat#YUV_420_888} format images and
+ * metadata to process. The {@link Image} that are contained within
+ * the map will become invalid after this method completes, so no
+ * references to them should be kept.
+ * @param resultCallback Capture result callback to be called once the capture result
+ * values of the processed image are ready.
+ * @param executor The executor to run the callback on. If null then the callback
+ * will run on any arbitrary executor.
+ * @throws RuntimeException if postview feature is not supported
+ * @since 1.4
+ */
+ void processWithPostview(Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor);
}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
index e0f59558..25232635 100644
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/HdrImageCaptureExtenderImpl.java
@@ -132,6 +132,26 @@ public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderIm
}
@Override
+ public void onPostviewOutputSurface(Surface surface) {
+
+ }
+
+ @Override
+ public void processWithPostview(
+ Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor) {
+ if (!isPostviewAvailable()) {
+ throw new RuntimeException("The extension doesn't support postview");
+ }
+
+ if (resultCallback != null) {
+ process(results, resultCallback, executor);
+ } else {
+ process(results);
+ }
+ }
+
+ @Override
public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor) {
Pair<Image, TotalCaptureResult> result = results.get(NORMAL_STAGE_ID);
@@ -279,6 +299,11 @@ public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderIm
}
@Override
+ public void onResolutionUpdate(Size size, Size postviewSize) {
+
+ }
+
+ @Override
public void onImageFormatUpdate(int imageFormat) {
}
@@ -347,6 +372,11 @@ public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderIm
}
@Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ return new ArrayList<>();
+ }
+
+ @Override
public Range<Long> getEstimatedCaptureLatencyRange(Size captureOutputSize) {
return null;
}
@@ -382,4 +412,9 @@ public final class HdrImageCaptureExtenderImpl implements ImageCaptureExtenderIm
public Pair<Long, Long> getRealtimeCaptureLatency() {
return null;
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ return false;
+ }
}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
index 8cb64ea2..37e7baf3 100644
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/ImageCaptureExtenderImpl.java
@@ -91,6 +91,21 @@ public interface ImageCaptureExtenderImpl extends ExtenderStateListener {
List<Pair<Integer, Size[]>> getSupportedResolutions();
/**
+ * Returns the customized supported postview resolutions for a still capture using
+ * its size.
+ *
+ * <p>Pair list composed with {@link ImageFormat} and {@link Size} array will be returned.
+ *
+ * <p>The returned resolutions should be subset of the supported sizes retrieved from
+ * {@link android.hardware.camera2.params.StreamConfigurationMap} for the camera device.
+ *
+ * @return the customized supported resolutions, or null to support all sizes retrieved from
+ * {@link android.hardware.camera2.params.StreamConfigurationMap}.
+ * @since 1.4
+ */
+ List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize);
+
+ /**
* Returns the estimated capture latency range in milliseconds for the target capture
* resolution.
*
@@ -167,4 +182,15 @@ public interface ImageCaptureExtenderImpl extends ExtenderStateListener {
* @since 1.4
*/
Pair<Long, Long> getRealtimeCaptureLatency();
+
+ /**
+ * Indicates whether the extension supports the postview for still capture feature.
+ * If the extension is using HAL processing, false should be returned since the
+ * postview feature is not currently supported for this case.
+ *
+ * @return {@code true} in case postview for still capture is supported
+ * {@code false} otherwise.
+ * @since 1.4
+ */
+ boolean isPostviewAvailable();
}
diff --git a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
index c233ef8f..e3317d94 100755
--- a/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
+++ b/camera2/extensions/sample/src/java/androidx/camera/extensions/impl/NightImageCaptureExtenderImpl.java
@@ -117,6 +117,26 @@ public final class NightImageCaptureExtenderImpl implements ImageCaptureExtender
}
@Override
+ public void onPostviewOutputSurface(Surface surface) {
+
+ }
+
+ @Override
+ public void processWithPostview(
+ Map<Integer, Pair<Image, TotalCaptureResult>> results,
+ ProcessResultImpl resultCallback, Executor executor) {
+ if (!isPostviewAvailable()) {
+ throw new RuntimeException("The extension doesn't support postview");
+ }
+
+ if (resultCallback != null) {
+ process(results, resultCallback, executor);
+ } else {
+ process(results);
+ }
+ }
+
+ @Override
public void process(Map<Integer, Pair<Image, TotalCaptureResult>> results,
ProcessResultImpl resultCallback, Executor executor) {
throw new RuntimeException("The extension doesn't support capture " +
@@ -165,6 +185,11 @@ public final class NightImageCaptureExtenderImpl implements ImageCaptureExtender
}
@Override
+ public void onResolutionUpdate(Size size, Size postviewSize) {
+
+ }
+
+ @Override
public void onImageFormatUpdate(int imageFormat) {
}
@@ -245,6 +270,11 @@ public final class NightImageCaptureExtenderImpl implements ImageCaptureExtender
}
@Override
+ public List<Pair<Integer, Size[]>> getSupportedPostviewResolutions(Size captureSize) {
+ return new ArrayList<>();
+ }
+
+ @Override
public Range<Long> getEstimatedCaptureLatencyRange(Size captureOutputSize) {
return null;
}
@@ -273,4 +303,9 @@ public final class NightImageCaptureExtenderImpl implements ImageCaptureExtender
public Pair<Long, Long> getRealtimeCaptureLatency() {
return null;
}
+
+ @Override
+ public boolean isPostviewAvailable() {
+ return false;
+ }
}