summaryrefslogtreecommitdiffstats
path: root/core/java/android/hardware/Camera.java
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2013-04-02 15:46:38 -0700
committerEino-Ville Talvala <etalvala@google.com>2013-04-17 18:35:26 -0700
commit7005b67c127d229017840925d2bc1bd84c43aaf5 (patch)
tree4d31440aaf7fcc4d320a9eafecb602a35039f4dc /core/java/android/hardware/Camera.java
parent3b9dd0a95869d93396e3346cb67b19bae50e0432 (diff)
downloadframeworks_base-7005b67c127d229017840925d2bc1bd84c43aaf5.zip
frameworks_base-7005b67c127d229017840925d2bc1bd84c43aaf5.tar.gz
frameworks_base-7005b67c127d229017840925d2bc1bd84c43aaf5.tar.bz2
Camera: Add hidden camera preview to renderscript allocation API
- Camera.createPreviewAllocation() creates YUV allocations for use as a preview buffer destination. - Camera.setPreviewCallbackAllocation() sets such an allocation as the target for preview data from camera. Bug: 8563840 Change-Id: Ie42033976fed825d396550bbc033d434c8206b6b
Diffstat (limited to 'core/java/android/hardware/Camera.java')
-rw-r--r--core/java/android/hardware/Camera.java155
1 files changed, 155 insertions, 0 deletions
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 4e51080..ac42b76 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -31,6 +31,11 @@ import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.renderscript.Allocation;
+import android.renderscript.Element;
+import android.renderscript.RenderScript;
+import android.renderscript.RSIllegalArgumentException;
+import android.renderscript.Type;
import android.util.Log;
import android.text.TextUtils;
import android.view.Surface;
@@ -152,6 +157,7 @@ public class Camera {
private PictureCallback mRawImageCallback;
private PictureCallback mJpegCallback;
private PreviewCallback mPreviewCallback;
+ private boolean mUsingPreviewAllocation;
private PictureCallback mPostviewCallback;
private AutoFocusCallback mAutoFocusCallback;
private AutoFocusMoveCallback mAutoFocusMoveCallback;
@@ -327,6 +333,7 @@ public class Camera {
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
+ mUsingPreviewAllocation = false;
mZoomListener = null;
Looper looper;
@@ -587,6 +594,9 @@ public class Camera {
mPreviewCallback = cb;
mOneShot = false;
mWithBuffer = false;
+ if (cb != null) {
+ mUsingPreviewAllocation = false;
+ }
// Always use one-shot mode. We fake camera preview mode by
// doing one-shot preview continuously.
setHasPreviewCallback(cb != null, false);
@@ -610,6 +620,9 @@ public class Camera {
mPreviewCallback = cb;
mOneShot = true;
mWithBuffer = false;
+ if (cb != null) {
+ mUsingPreviewAllocation = false;
+ }
setHasPreviewCallback(cb != null, false);
}
@@ -645,6 +658,9 @@ public class Camera {
mPreviewCallback = cb;
mOneShot = false;
mWithBuffer = true;
+ if (cb != null) {
+ mUsingPreviewAllocation = false;
+ }
setHasPreviewCallback(cb != null, true);
}
@@ -744,6 +760,134 @@ public class Camera {
private native final void _addCallbackBuffer(
byte[] callbackBuffer, int msgType);
+ /**
+ * <p>Create a {@link android.renderscript RenderScript}
+ * {@link android.renderscript.Allocation Allocation} to use as a
+ * destination of preview callback frames. Use
+ * {@link #setPreviewCallbackAllocation setPreviewCallbackAllocation} to use
+ * the created Allocation as a destination for camera preview frames.</p>
+ *
+ * <p>The Allocation will be created with a YUV type, and its contents must
+ * be accessed within Renderscript with the {@code rsGetElementAtYuv_*}
+ * accessor methods. Its size will be based on the current
+ * {@link Parameters#getPreviewSize preview size} configured for this
+ * camera.</p>
+ *
+ * @param rs the RenderScript context for this Allocation.
+ * @param usage additional usage flags to set for the Allocation. The usage
+ * flag {@link android.renderscript.Allocation#USAGE_IO_INPUT} will always
+ * be set on the created Allocation, but additional flags may be provided
+ * here.
+ * @return a new YUV-type Allocation with dimensions equal to the current
+ * preview size.
+ * @throws RSIllegalArgumentException if the usage flags are not compatible
+ * with an YUV Allocation.
+ * @see #setPreviewCallbackAllocation
+ * @hide
+ */
+ public final Allocation createPreviewAllocation(RenderScript rs, int usage)
+ throws RSIllegalArgumentException {
+ Parameters p = getParameters();
+ Size previewSize = p.getPreviewSize();
+ Type.Builder yuvBuilder = new Type.Builder(rs,
+ Element.createPixel(rs,
+ Element.DataType.UNSIGNED_8,
+ Element.DataKind.PIXEL_YUV));
+ // Use YV12 for wide compatibility. Changing this requires also
+ // adjusting camera service's format selection.
+ yuvBuilder.setYuvFormat(ImageFormat.YV12);
+ yuvBuilder.setX(previewSize.width);
+ yuvBuilder.setY(previewSize.height);
+
+ Allocation a = Allocation.createTyped(rs, yuvBuilder.create(),
+ usage | Allocation.USAGE_IO_INPUT);
+
+ return a;
+ }
+
+ /**
+ * <p>Set an {@link android.renderscript.Allocation Allocation} as the
+ * target of preview callback data. Use this method for efficient processing
+ * of camera preview data with RenderScript. The Allocation must be created
+ * with the {@link #createPreviewAllocation createPreviewAllocation }
+ * method.</p>
+ *
+ * <p>Setting a preview allocation will disable any active preview callbacks
+ * set by {@link #setPreviewCallback setPreviewCallback} or
+ * {@link #setPreviewCallbackWithBuffer setPreviewCallbackWithBuffer}, and
+ * vice versa. Using a preview allocation still requires an active standard
+ * preview target to be set, either with
+ * {@link #setPreviewTexture setPreviewTexture} or
+ * {@link #setPreviewDisplay setPreviewDisplay}.</p>
+ *
+ * <p>To be notified when new frames are available to the Allocation, use
+ * {@link android.renderscript.Allocation#setIoInputNotificationHandler Allocation.setIoInputNotificationHandler}. To
+ * update the frame currently accessible from the Allocation to the latest
+ * preview frame, call
+ * {@link android.renderscript.Allocation#ioReceive Allocation.ioReceive}.</p>
+ *
+ * <p>To disable preview into the Allocation, call this method with a
+ * {@code null} parameter.</p>
+ *
+ * <p>Once a preview allocation is set, the preview size set by
+ * {@link Parameters#setPreviewSize setPreviewSize} cannot be changed. If
+ * you wish to change the preview size, first remove the preview allocation
+ * by calling {@code setPreviewCallbackAllocation(null)}, then change the
+ * preview size, create a new preview Allocation with
+ * {@link #createPreviewAllocation createPreviewAllocation}, and set it as
+ * the new preview callback allocation target.</p>
+ *
+ * <p>If you are using the preview data to create video or still images,
+ * strongly consider using {@link android.media.MediaActionSound} to
+ * properly indicate image capture or recording start/stop to the user.</p>
+ *
+ * @param previewAllocation the allocation to use as destination for preview
+ * @throws IOException if configuring the camera to use the Allocation for
+ * preview fails.
+ * @throws IllegalArgumentException if the Allocation's dimensions or other
+ * parameters don't meet the requirements.
+ * @see #createPreviewAllocation
+ * @see #setPreviewCallback
+ * @see #setPreviewCallbackWithBuffer
+ * @hide
+ */
+ public final void setPreviewCallbackAllocation(Allocation previewAllocation)
+ throws IOException {
+ Surface previewSurface = null;
+ if (previewAllocation != null) {
+ Parameters p = getParameters();
+ Size previewSize = p.getPreviewSize();
+ if (previewSize.width != previewAllocation.getType().getX() ||
+ previewSize.height != previewAllocation.getType().getY()) {
+ throw new IllegalArgumentException(
+ "Allocation dimensions don't match preview dimensions: " +
+ "Allocation is " +
+ previewAllocation.getType().getX() +
+ ", " +
+ previewAllocation.getType().getY() +
+ ". Preview is " + previewSize.width + ", " +
+ previewSize.height);
+ }
+ if ((previewAllocation.getUsage() &
+ Allocation.USAGE_IO_INPUT) == 0) {
+ throw new IllegalArgumentException(
+ "Allocation usage does not include USAGE_IO_INPUT");
+ }
+ if (previewAllocation.getType().getElement().getDataKind() !=
+ Element.DataKind.PIXEL_YUV) {
+ throw new IllegalArgumentException(
+ "Allocation is not of a YUV type");
+ }
+ previewSurface = previewAllocation.getSurface();
+ mUsingPreviewAllocation = true;
+ } else {
+ mUsingPreviewAllocation = false;
+ }
+ setPreviewCallbackSurface(previewSurface);
+ }
+
+ private native final void setPreviewCallbackSurface(Surface s);
+
private class EventHandler extends Handler
{
private Camera mCamera;
@@ -1492,6 +1636,17 @@ public class Camera {
* @see #getParameters()
*/
public void setParameters(Parameters params) {
+ // If using preview allocations, don't allow preview size changes
+ if (mUsingPreviewAllocation) {
+ Size newPreviewSize = params.getPreviewSize();
+ Size currentPreviewSize = getParameters().getPreviewSize();
+ if (newPreviewSize.width != currentPreviewSize.width ||
+ newPreviewSize.height != currentPreviewSize.height) {
+ throw new IllegalStateException("Cannot change preview size" +
+ " while a preview allocation is configured.");
+ }
+ }
+
native_setParameters(params.flatten());
}