diff options
-rw-r--r-- | api/current.txt | 164 | ||||
-rw-r--r-- | core/java/android/app/ContextImpl.java | 6 | ||||
-rw-r--r-- | core/java/android/content/Context.java | 10 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CameraAccessException.java | 86 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CameraDevice.java | 555 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CameraManager.java | 138 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CameraMetadata.java | 129 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CameraProperties.java | 247 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CaptureRequest.java | 85 | ||||
-rw-r--r-- | core/java/android/hardware/photography/CaptureResult.java | 189 | ||||
-rw-r--r-- | core/java/android/hardware/photography/Size.java | 45 | ||||
-rw-r--r-- | core/java/android/hardware/photography/package.html | 84 | ||||
-rw-r--r-- | core/java/android/view/SurfaceHolder.java | 3 | ||||
-rw-r--r-- | graphics/java/android/graphics/ImageFormat.java | 39 | ||||
-rw-r--r-- | media/java/android/media/Image.java | 184 | ||||
-rw-r--r-- | media/java/android/media/ImageReader.java | 171 |
16 files changed, 2132 insertions, 3 deletions
diff --git a/api/current.txt b/api/current.txt index 87891b5..3337837 100644 --- a/api/current.txt +++ b/api/current.txt @@ -5735,6 +5735,7 @@ package android.content { field public static final int BIND_NOT_FOREGROUND = 4; // 0x4 field public static final int BIND_WAIVE_PRIORITY = 32; // 0x20 field public static final java.lang.String BLUETOOTH_SERVICE = "bluetooth"; + field public static final java.lang.String CAMERA_SERVICE = "camera"; field public static final java.lang.String CLIPBOARD_SERVICE = "clipboard"; field public static final java.lang.String CONNECTIVITY_SERVICE = "connectivity"; field public static final int CONTEXT_IGNORE_SECURITY = 2; // 0x2 @@ -9002,8 +9003,10 @@ package android.graphics { field public static final int JPEG = 256; // 0x100 field public static final int NV16 = 16; // 0x10 field public static final int NV21 = 17; // 0x11 + field public static final int RAW_SENSOR = 513; // 0x201 field public static final int RGB_565 = 4; // 0x4 field public static final int UNKNOWN = 0; // 0x0 + field public static final int YUV_420_888 = 35; // 0x23 field public static final int YUY2 = 20; // 0x14 field public static final int YV12 = 842094169; // 0x32315659 } @@ -10626,6 +10629,133 @@ package android.hardware.location { } +package android.hardware.photography { + + public class CameraAccessException extends java.lang.Exception { + ctor public CameraAccessException(int); + ctor public CameraAccessException(int, java.lang.String); + ctor public CameraAccessException(int, java.lang.String, java.lang.Throwable); + ctor public CameraAccessException(int, java.lang.Throwable); + method public final int getReason(); + field public static final int CAMERA_DISABLED = 3; // 0x3 + field public static final int CAMERA_DISCONNECTED = 4; // 0x4 + field public static final int CAMERA_IN_USE = 1; // 0x1 + field public static final int MAX_CAMERAS_IN_USE = 2; // 0x2 + } + + public final class CameraDevice implements java.lang.AutoCloseable { + ctor public CameraDevice(); + method public void capture(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException; + method public void captureBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException; + method public void close(); + method public void configureOutputs(java.util.List<android.view.Surface>); + method public android.hardware.photography.CaptureRequest createCaptureRequest(int) throws android.hardware.photography.CameraAccessException; + method public android.hardware.photography.CameraProperties getProperties() throws android.hardware.photography.CameraAccessException; + method public void setErrorListener(android.hardware.photography.CameraDevice.ErrorListener); + method public void setRepeatingBurst(java.util.List<android.hardware.photography.CaptureRequest>, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException; + method public void setRepeatingRequest(android.hardware.photography.CaptureRequest, android.hardware.photography.CameraDevice.CaptureListener) throws android.hardware.photography.CameraAccessException; + method public void stopRepeating() throws android.hardware.photography.CameraAccessException; + method public void waitUntilIdle() throws android.hardware.photography.CameraAccessException; + field public static final int TEMPLATE_MANUAL = 5; // 0x5 + field public static final int TEMPLATE_PREVIEW = 1; // 0x1 + field public static final int TEMPLATE_RECORD = 2; // 0x2 + field public static final int TEMPLATE_STILL_CAPTURE = 3; // 0x3 + field public static final int TEMPLATE_VIDEO_SNAPSHOT = 4; // 0x4 + } + + public static abstract interface CameraDevice.CaptureListener { + method public abstract void onCaptureComplete(android.hardware.photography.CameraDevice, android.hardware.photography.CaptureRequest, android.hardware.photography.CaptureResult); + method public abstract void onCaptureFailed(android.hardware.photography.CameraDevice, android.hardware.photography.CaptureRequest); + } + + public static abstract interface CameraDevice.ErrorListener { + method public abstract void onCameraDeviceError(android.hardware.photography.CameraDevice, int); + field public static final int DEVICE_DISCONNECTED = 1; // 0x1 + field public static final int DEVICE_ERROR = 2; // 0x2 + field public static final int SERVICE_ERROR = 3; // 0x3 + } + + public final class CameraManager { + method public android.hardware.photography.CameraProperties getCameraProperties(java.lang.String) throws android.hardware.photography.CameraAccessException; + method public java.lang.String[] getDeviceIdList(); + method public android.hardware.photography.CameraDevice openCamera(java.lang.String) throws android.hardware.photography.CameraAccessException; + method public void registerCameraListener(android.hardware.photography.CameraManager.CameraListener); + method public void unregisterCameraListener(android.hardware.photography.CameraManager.CameraListener); + } + + public static abstract interface CameraManager.CameraListener { + method public abstract void onCameraAvailable(java.lang.String); + method public abstract void onCameraUnavailable(java.lang.String); + } + + public class CameraMetadata implements android.os.Parcelable { + ctor public CameraMetadata(); + method public int describeContents(); + method public T get(android.hardware.photography.CameraMetadata.Key<T>); + method public void set(android.hardware.photography.CameraMetadata.Key<T>, T); + method public void writeToParcel(android.os.Parcel, int); + field public static final android.os.Parcelable.Creator CREATOR; + } + + public static class CameraMetadata.Key { + ctor public CameraMetadata.Key(java.lang.String); + method public final boolean equals(java.lang.Object); + method public final java.lang.String getName(); + method public final int hashCode(); + } + + public final class CameraProperties extends android.hardware.photography.CameraMetadata { + ctor public CameraProperties(); + field public static final android.hardware.photography.CameraMetadata.Key INFO_IDENTIFIER; + field public static final android.hardware.photography.CameraMetadata.Key INFO_MODEL; + field public static final android.hardware.photography.CameraMetadata.Key INFO_REMOVABLE; + field public static final android.hardware.photography.CameraMetadata.Key INFO_SUPPORTED_HARDWARE_LEVEL; + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; // 0x1 + field public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; // 0x0 + field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_FORMATS; + field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_JPEG_SIZES; + field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_PROCESSED_SIZES; + field public static final android.hardware.photography.CameraMetadata.Key SCALER_AVAILABLE_RAW_SIZES; + field public static final android.hardware.photography.CameraMetadata.Key SENSOR_ACTIVE_ARRAY_SIZE; + field public static final android.hardware.photography.CameraMetadata.Key SENSOR_PIXEL_ARRAY_SIZE; + } + + public final class CaptureRequest extends android.hardware.photography.CameraMetadata { + method public void addTarget(android.view.Surface); + method public void removeTarget(android.view.Surface); + field public static final android.hardware.photography.CameraMetadata.Key SENSOR_EXPOSURE_TIME; + field public static final android.hardware.photography.CameraMetadata.Key SENSOR_SENSITIVITY; + } + + public final class CaptureResult extends android.hardware.photography.CameraMetadata { + field public static final android.hardware.photography.CameraMetadata.Key CONTROL_AE_STATE; + field public static final int CONTROL_AE_STATE_CONVERGED = 2; // 0x2 + field public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4; // 0x4 + field public static final int CONTROL_AE_STATE_INACTIVE = 0; // 0x0 + field public static final int CONTROL_AE_STATE_LOCKED = 3; // 0x3 + field public static final int CONTROL_AE_STATE_PRECAPTURE = 5; // 0x5 + field public static final int CONTROL_AE_STATE_SEARCHING = 1; // 0x1 + field public static final android.hardware.photography.CameraMetadata.Key SENSOR_TIMESTAMP; + field public static final android.hardware.photography.CameraMetadata.Key STATISTICS_DETECTED_FACES; + } + + public static class CaptureResult.Face { + ctor public CaptureResult.Face(); + method public android.graphics.Rect getBounds(); + method public int getId(); + method public android.graphics.Point getLeftEye(); + method public android.graphics.Point getMouth(); + method public android.graphics.Point getRightEye(); + method public int getScore(); + } + + public final class Size { + method public final int getHeight(); + method public final int getWidth(); + } + +} + package android.hardware.usb { public class UsbAccessory implements android.os.Parcelable { @@ -11662,6 +11792,40 @@ package android.media { field public static final int EULER_Z = 2; // 0x2 } + public abstract class Image implements java.lang.AutoCloseable { + ctor public Image(); + method public abstract void close(); + method protected final void finalize(); + method public int getFormat(); + method public int getHeight(); + method public android.media.Image.Plane[] getPlanes(); + method public long getTimestamp(); + method public int getWidth(); + } + + public static final class Image.Plane { + ctor public Image.Plane(); + method public java.nio.ByteBuffer getBuffer(); + method public int getPixelStride(); + method public int getRowStride(); + } + + public final class ImageReader { + ctor public ImageReader(int, int, int, int); + method public int getHeight(); + method public int getImageFormat(); + method public int getMaxImages(); + method public android.media.Image getNextImage(); + method public android.view.Surface getSurface(); + method public int getWidth(); + method public void releaseImage(android.media.Image); + method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener); + } + + public static abstract interface ImageReader.OnImageAvailableListener { + method public abstract void onImageAvailable(android.media.ImageReader); + } + public class JetPlayer { method public boolean clearQueue(); method public java.lang.Object clone() throws java.lang.CloneNotSupportedException; diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java index 459139f..7968431 100644 --- a/core/java/android/app/ContextImpl.java +++ b/core/java/android/app/ContextImpl.java @@ -49,6 +49,7 @@ import android.graphics.drawable.Drawable; import android.hardware.ISerialManager; import android.hardware.SerialManager; import android.hardware.SystemSensorManager; +import android.hardware.photography.CameraManager; import android.hardware.display.DisplayManager; import android.hardware.input.InputManager; import android.hardware.usb.IUsbManager; @@ -540,6 +541,11 @@ class ContextImpl extends Context { IAppOpsService service = IAppOpsService.Stub.asInterface(b); return new AppOpsManager(ctx, service); }}); + + registerService(CAMERA_SERVICE, new StaticServiceFetcher() { + public Object createStaticService() { + return new CameraManager(); + }}); } static ContextImpl getImpl(Context context) { diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java index 81d6f0b..35e51a6 100644 --- a/core/java/android/content/Context.java +++ b/core/java/android/content/Context.java @@ -2284,6 +2284,16 @@ public abstract class Context { public static final String APP_OPS_SERVICE = "appops"; /** + * Use with {@link #getSystemService} to retrieve a + * {@link android.hardware.photography.CameraManager} for interacting with + * camera devices. + * + * @see #getSystemService + * @see android.hardware.camera.CameraManager + */ + public static final String CAMERA_SERVICE = "camera"; + + /** * Determine whether the given permission is allowed for a particular * process and user ID running in the system. * diff --git a/core/java/android/hardware/photography/CameraAccessException.java b/core/java/android/hardware/photography/CameraAccessException.java new file mode 100644 index 0000000..01114df --- /dev/null +++ b/core/java/android/hardware/photography/CameraAccessException.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +/** + * <p><code>CameraAccessException</code> is thrown if a camera device could not + * be queried or opened by the {@link CameraManager}, or if the connection to an + * opened {@link CameraDevice} is no longer valid.</p> + * + * @see CameraManager + * @see CameraDevice + */ +public class CameraAccessException extends Exception { + /** + * The camera device is in use already + */ + public static final int CAMERA_IN_USE = 1; + + /** + * The system-wide limit for number of open cameras has been reached, + * and more camera devices cannot be opened until previous instances are + * closed. + */ + public static final int MAX_CAMERAS_IN_USE = 2; + + /** + * The camera is disabled due to a device policy, and cannot be opened. + * + * @see android.app.admin.DevicePolicyManager#setCameraDisabled(android.content.ComponentName, boolean) + */ + public static final int CAMERA_DISABLED = 3; + + /** + * The camera device is removable and has been disconnected from the Android + * device, or the camera service has shut down the connection due to a + * higher-priority access request for the camera device. + */ + public static final int CAMERA_DISCONNECTED = 4; + + private int mReason; + + /** + * The reason for the failure to access the camera. + * + * @see #CAMERA_IN_USE + * @see #MAX_CAMERAS_IN_USE + * @see #CAMERA_DISABLED + * @see #CAMERA_DISCONNECTED + */ + public final int getReason() { + return mReason; + } + + public CameraAccessException(int problem) { + mReason = problem; + } + + public CameraAccessException(int problem, String message) { + super(message); + mReason = problem; + } + + public CameraAccessException(int problem, String message, Throwable cause) { + super(message, cause); + mReason = problem; + } + + public CameraAccessException(int problem, Throwable cause) { + super(cause); + mReason = problem; + } +} diff --git a/core/java/android/hardware/photography/CameraDevice.java b/core/java/android/hardware/photography/CameraDevice.java new file mode 100644 index 0000000..2062db2 --- /dev/null +++ b/core/java/android/hardware/photography/CameraDevice.java @@ -0,0 +1,555 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +import android.graphics.ImageFormat; +import android.renderscript.Allocation; +import android.renderscript.RenderScript; +import android.view.Surface; + +import java.lang.AutoCloseable; +import java.util.List; + +/** + * <p>The CameraDevice class is an interface to a single camera connected to an + * Android device, allowing for fine-grain control of image capture and + * post-processing at high frame rates.</p> + * + * <p>Your application must declare the + * {@link android.Manifest.permission#CAMERA Camera} permission in its manifest + * in order to access camera devices.</p> + * + * <p>A given camera device may provide support at one of two levels: limited or + * full. If a device only supports the limited level, then Camera2 exposes a + * feature set that is roughly equivalent to the older + * {@link android.hardware.Camera Camera} API, although with a cleaner and more + * efficient interface. Devices that implement the full level of support + * provide substantially improved capabilities over the older camera + * API. Applications that target the limited level devices will run unchanged on + * the full-level devices; if your application requires a full-level device for + * proper operation, declare the "android.hardware.camera2.full" feature in your + * manifest.</p> + * + * @see CameraManager#openCamera + * @see android.Manifest.permission#CAMERA + */ +public final class CameraDevice implements AutoCloseable { + + /** + * Create a request suitable for a camera preview window. Specifically, this + * means that high frame rate is given priority over the highest-quality + * post-processing. These requests would normally be used with the + * {@link #setRepeatingRequest} method. + * + * @see #createCaptureRequest + */ + public static final int TEMPLATE_PREVIEW = 1; + + /** + * Create a request suitable for video recording. Specifically, this means + * that a stable frame rate is used, and post-processing is set for + * recording quality. These requests would commonly be used with the + * {@link #setRepeatingRequest} method. + * + * @see #createCaptureRequest + */ + public static final int TEMPLATE_RECORD = 2; + + /** + * Create a request suitable for still image capture. Specifically, this + * means prioritizing image quality over frame rate. These requests would + * commonly be used with the {@link #capture} method. + * + * @see #createCaptureRequest + */ + public static final int TEMPLATE_STILL_CAPTURE = 3; + + /** + * Create a request suitable for still image capture while recording + * video. Specifically, this means maximizing image quality without + * disrupting the ongoing recording. These requests would commonly be used + * with the {@link #capture} method while a request based on + * {@link #TEMPLATE_RECORD} is is in use with {@link #setRepeatingRequest}. + * + * @see #createCaptureRequest + */ + public static final int TEMPLATE_VIDEO_SNAPSHOT = 4; + + /** + * A basic template for direct application control of capture + * parameters. All automatic control is disabled (auto-exposure, auto-white + * balance, auto-focus), and post-processing parameters are set to preview + * quality. The manual capture parameters (exposure, sensitivity, and so on) + * are set to reasonable defaults, but should be overriden by the + * application depending on the intended use case. + * + * @see #createCaptureRequest + */ + public static final int TEMPLATE_MANUAL = 5; + + /** + * Get the static properties for this camera. These are identical to the + * properties returned by {@link CameraManager#getCameraProperties}. + * + * @return the static properties of the camera. + * + * @throws CameraAccessException if the camera device is no longer connected + * + * @see CameraManager#getCameraProperties + */ + public CameraProperties getProperties() throws CameraAccessException { + return null; + } + + /** + * <p>Set up a new output set of Surfaces for the camera device.</p> + * + * <p>The configuration determines the set of potential output Surfaces for + * the camera device for each capture request. A given request may use all + * or a only some of the outputs. This method must be called before requests + * can be submitted to the camera with {@link #capture capture}, + * {@link #captureBurst captureBurst}, + * {@link #setRepeatingRequest setRepeatingRequest}, or + * {@link #setRepeatingBurst setRepeatingBurst}.</p> + * + * <p>Surfaces suitable for inclusion as a camera output can be created for + * various use cases and targets:</p> + * + * <ul> + * + * <li>For drawing to a {@link android.view.SurfaceView SurfaceView}: Set + * the size of the Surface with + * {@link android.view.SurfaceHolder#setFixedSize} to be one of the + * supported + * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes} + * before calling {@link android.view.SurfaceHolder#getSurface}.</li> + * + * <li>For accessing through an OpenGL texture via a + * {@link android.graphics.SurfaceTexture SurfaceTexture}: Set the size of + * the SurfaceTexture with + * {@link android.graphics.SurfaceTexture#setDefaultBufferSize} to be one + * of the supported + * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes} + * before creating a Surface from the SurfaceTexture with + * {@link Surface#Surface}.</li> + * + * <li>For recording with {@link android.media.MediaCodec}: Call + * {@link android.media.MediaCodec#createInputSurface} after configuring + * the media codec to use one of the + * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes} + * </li> + * + * <li>For recording with {@link android.media.MediaRecorder}: TODO</li> + * + * <li>For efficient YUV processing with {@link android.renderscript}: + * Create a RenderScript + * {@link android.renderscript.Allocation Allocation} with a supported YUV + * type, the IO_INPUT flag, and one of the supported + * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed sizes}. Then + * obtain the Surface with + * {@link android.renderscript.Allocation#getSurface}.</li> + * + * <li>For access to uncompressed, JPEG, or raw sensor data in the + * application: Create a {@link android.media.ImageReader} object with the + * desired {@link CameraProperties#SCALER_AVAILABLE_FORMATS image format}, + * and a size from the matching + * {@link CameraProperties#SCALER_AVAILABLE_PROCESSED_SIZES processed}, + * {@link CameraProperties#SCALER_AVAILABLE_JPEG_SIZES jpeg}, or + * {@link CameraProperties#SCALER_AVAILABLE_RAW_SIZES raw} sizes. Then + * obtain a Surface from it.</li> + * + * </ul> + * + * </p> + * + * <p>This function can take several hundred milliseconds to execute, since + * camera hardware may need to be powered on or reconfigured.</p> + * + * <p>To change the configuration after requests have been submitted to the + * device, the camera device must be idle. To idle the device, stop any + * repeating requests with {@link #stopRepeating stopRepeating}, and then + * call {@link #waitUntilIdle waitUntilIdle}.</p> + * + * <p>Using larger resolution outputs, or more outputs, can result in slower + * output rate from the device.</p> + * + * @param outputs the new set of Surfaces that should be made available as + * targets for captured image data. + * + * @throws IllegalArgumentException if the set of output Surfaces do not + * meet the requirements + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device is not idle, or has + * encountered a fatal error + */ + public void configureOutputs(List<Surface> outputs) { + } + + /** + * <p>Create a {@link CaptureRequest} initialized with template for a target + * use case. The settings are chosen to be the best options for the specific + * camera device, so it is not recommended to reuse the same request for a + * different camera device; create a request for that device and override + * the settings as desired, instead.</p> + * + * @param templateType An enumeration selecting the use case for this + * request; one of the CameraDevice.TEMPLATE_ values. + * @return a filled-in CaptureRequest, except for output streams. + * + * @throws IllegalArgumentException if the templateType is not in the list + * of supported templates. + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed or the + * device has encountered a fatal error. + * + * @see #TEMPLATE_PREVIEW + * @see #TEMPLATE_RECORD + * @see #TEMPLATE_STILL_CAPTURE + * @see #TEMPLATE_VIDEO_SNAPSHOT + * @see #TEMPLATE_MANUAL + */ + public CaptureRequest createCaptureRequest(int templateType) + throws CameraAccessException { + return null; + } + + /** + * <p>Submit a request for an image to be captured by this CameraDevice.</p> + * + * <p>The request defines all the parameters for capturing the single image, + * including sensor, lens, flash, and post-processing settings.</p> + * + * <p>Each request will produce one {@link CaptureResult} and produce new + * frames for one or more target Surfaces, as defined by the request's .</p> + * + * <p>Multiple requests can be in progress at once. They are processed in + * first-in, first-out order, with minimal delays between each + * capture. Requests submitted through this method have higher priority than + * those submitted through {@link #setRepeatingRequest} or + * {@link #setRepeatingBurst}, and will be processed as soon as the current + * repeat/repeatBurst processing completes.</p> + * + * @param request the settings for this capture. + * @param listener the callback object to notify once this request has been + * processed. If null, no metadata will be produced for this capture, + * although image data will still be produced. + * + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed or the + * device has encountered a fatal error. + * + * @see #captureBurst + * @see #setRepeatingRequest + * @see #setRepeatingBurst + */ + public void capture(CaptureRequest request, CaptureListener listener) + throws CameraAccessException { + } + + /** + * <p>Submit a list of requests to be captured in sequence as a burst. The + * burst will be captured in the minimum amount of time possible, and will + * not be interleaved with requests submitted by other capture or repeat + * calls.</p> + * + * <p>The requests will be captured in order, each capture producing one + * {@link CaptureResult} and frames for one or more + * target {@link android.view.Surface surfaces}.</p> + * + * <p>The main difference between this method and simply calling + * {@link #capture} repeatedly is that this method guarantees that no + * other requests will be interspersed with the burst.</p> + * + * @param requests the list of settings for this burst capture. + * @param listener the callback object to notify each time one of the + * requests in the burst has been processed. If null, no metadata will be + * produced for any requests in this burst, although image data will still + * be produced. + * + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed or the + * device has encountered a fatal error. + * + * @see #capture + * @see #setRepeatingRequest + * @see #setRepeatingBurst + */ + public void captureBurst(List<CaptureRequest> requests, + CaptureListener listener) throws CameraAccessException { + } + + /** + * <p>Request endlessly repeating capture of images by this + * CameraDevice.</p> + * + * <p>With this method, the CameraDevice will continually capture + * images using the settings in the provided {@link + * CaptureRequest}, at the maximum rate possible.</p> + * + * <p>Repeat requests have lower priority than those submitted + * through {@link #capture} or {@link #captureBurst}, so if + * capture() is called when a repeating request is active, the + * capture request will be processed before any further repeating + * requests are processed.<p> + * + * <p>Repeating requests are a simple way for an application to maintain a + * preview or other continuous stream of frames, without having to submit + * requests through {@link #capture} at video rates.</p> + * + * <p>To stop the repeating capture, call {@link #stopRepeating}</p> + * + * <p>Calling repeat will replace a burst set up by {@link + * #setRepeatingBurst}, although any in-progress burst will be + * completed before the new repeat request will be used.</p> + * + * @param request the request to repeat indefinitely + * @param listener the callback object to notify every time the + * request finishes processing. If null, no metadata will be + * produced for this stream of requests, although image data will + * still be produced. + * + * @throws CameraAccessException if the camera device is no longer + * connected + * @throws IllegalStateException if the camera device has been closed or the + * device has encountered a fatal error. + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingBurst + */ + public void setRepeatingRequest(CaptureRequest request, CaptureListener listener) + throws CameraAccessException { + } + + /** + * <p>Request endlessly repeating capture of a sequence of images by this + * CameraDevice.</p> + * + * <p>With this method, the CameraDevice will continually capture images, + * cycling through the settings in the provided list of + * {@link CaptureRequest CaptureRequests}, at the maximum rate possible.</p> + * + * <p>If a request is submitted through {@link #capture} or + * {@link #captureBurst}, the current repetition of the request list will be + * completed before the higher-priority request is handled. This guarantees + * that the application always receives a complete repeat burst captured in + * minimal time, instead of bursts interleaved with higher-priority + * captures, or incomplete captures.</p> + * + * <p>Repeating burst requests are a simple way for an application to + * maintain a preview or other continuous stream of frames where each + * request is different in a predicatable way, without having to submit + * requests through {@link #capture} at video rates.</p> + * + * <p>To stop the repeating capture, call {@link #stopRepeating}. Any + * ongoing burst will still be completed, however.</p> + * + * <p>Calling repeatBurst will replace a repeating request set up by + * {@link #setRepeatingRequest}, although any in-progress capture will be completed + * before the new repeat burst will be used.</p> + * + * @param requests the list of requests to cycle through indefinitely. + * @param listener the callback object to notify each time one of the + * requests in the repeating bursts has finished processing. If null, no + * metadata will be produced for this stream of requests, although image + * data will still be produced. + * + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed or the + * device has encountered a fatal error. + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingRequest + */ + public void setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener) + throws CameraAccessException { + } + + /** + * <p>Cancel any ongoing repeating capture set by either + * {@link #setRepeatingRequest setRepeatingRequest} or + * {@link #setRepeatingBurst}. Has no effect on requests submitted through + * {@link #capture capture} or {@link #captureBurst captureBurst}.</p> + * + * <p>Any currently in-flight captures will still complete, as will any + * burst that is mid-capture. To ensure that the device has finished + * processing all of its capture requests and is in idle state, use the + * {@link #waitUntilIdle waitUntilIdle} method.</p> + * + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed or the + * device has encountered a fatal error. + * + * @see #setRepeatingRequest + * @see #setRepeatingBurst + * @see #waitUntilIdle + * + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed, the + * device has encountered a fatal error, or if there is an active repeating + * request or burst. + */ + public void stopRepeating() throws CameraAccessException { + } + + /** + * <p>Wait until all the submitted requests have finished processing</p> + * + * <p>This method blocks until all the requests that have been submitted to + * the camera device, either through {@link #capture capture}, + * {@link #captureBurst captureBurst}, + * {@link #setRepeatingRequest setRepeatingRequest}, or + * {@link #setRepeatingBurst setRepeatingBurst}, have completed their + * processing.</p> + * + * <p>Once this call returns successfully, the device is in an idle state, + * and can be reconfigured with {@link #configureOutputs configureOutputs}.</p> + * + * <p>This method cannot be used if there is an active repeating request or + * burst, set with {@link #setRepeatingRequest setRepeatingRequest} or + * {@link #setRepeatingBurst setRepeatingBurst}. Call + * {@link #stopRepeating stopRepeating} before calling this method.</p> + * + * @throws CameraAccessException if the camera device is no longer connected + * @throws IllegalStateException if the camera device has been closed, the + * device has encountered a fatal error, or if there is an active repeating + * request or burst. + */ + public void waitUntilIdle() throws CameraAccessException { + } + + /** + * Set the error listener object to call when an asynchronous error + * occurs. The errors reported here are only device-wide errors; errors + * about individual requests or frames are reported through + * {@link CaptureListener#onCaptureFailed}. + * + * @param listener the ErrorListener to send asynchronous error + * notifications to. Setting this to null will stop notifications about + * asynchronous errors. + */ + public void setErrorListener(ErrorListener listener) { + } + + /** + * Close the connection to this camera device. After this call, all calls to + * the camera device interface will throw a {@link IllegalStateException}, + * except for calls to close(). + */ + public void close() { + } + + /** + * A listener for receiving metadata about completed image captures. The + * metadata includes, among other things, the final capture settings and the + * state of the control algorithms. + */ + public interface CaptureListener { + /** + * <p>Called when a capture request has been processed by a + * {@link CameraDevice}.</p> + * + * @param camera The CameraDevice sending the callback. + * @param request The request that was given to the CameraDevice + * @param result The output metadata from the capture, including the + * final capture parameters and the state of the camera system during + * capture. + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingRequest + * @see #setRepeatingBurst + */ + public void onCaptureComplete(CameraDevice camera, + CaptureRequest request, CaptureResult result); + + /** + * <p>Called instead of onCaptureComplete when the camera device failed + * to produce a CaptureResult for the request. Other requests are + * unaffected, and some or all image buffers from the capture may have + * been pushed to their respective output streams.</p> + * + * @param camera The CameraDevice sending the callback. + * @param request The request that was given to the CameraDevice + * + * @see #capture + * @see #captureBurst + * @see #setRepeatingRequest + * @see #setRepeatingBurst + */ + public void onCaptureFailed(CameraDevice camera, + CaptureRequest request); + } + + /** + * <p>A listener for asynchronous errors from the camera device. Errors + * about specific {@link CaptureRequest CaptureRequests} are sent through + * the capture {@link CaptureListener#onCaptureFailed listener} + * interface. Errors reported through this listener affect the device as a + * whole.</p> + */ + public interface ErrorListener { + /** + * <p>This camera device has been disconnected by the camera + * service. Any attempt to call methods on this CameraDevice will throw + * a {@link CameraAccessException}. The disconnection could be due to a + * change in security policy or permissions; the physical disconnection + * of a removable camera device; or the camera being needed for a + * higher-priority use case.</p> + * + * <p>There may still be capture completion or camera stream listeners + * that will be called after this error is received.</p> + */ + public static final int DEVICE_DISCONNECTED = 1; + + /** + * <p>The camera device has encountered a fatal error. Any attempt to + * call methods on this CameraDevice will throw a + * {@link java.lang.IllegalStateException}.</p> + * + * <p>There may still be capture completion or camera stream listeners + * that will be called after this error is received.</p> + * + * <p>The application needs to re-open the camera device to use it + * again.</p> + */ + public static final int DEVICE_ERROR = 2; + + /** + * <p>The camera service has encountered a fatal error. Any attempt to + * call methods on this CameraDevice in the future will throw a + * {@link java.lang.IllegalStateException}.</p> + * + * <p>There may still be capture completion or camera stream listeners + * that will be called after this error is received.</p> + * + * <p>The device may need to be shut down and restarted to restore + * camera function, or there may be a persistent hardware problem.</p> + */ + public static final int SERVICE_ERROR = 3; + + /** + * The method to call when a camera device has encountered an error. + * + * @param camera The device reporting the error + * @param error The error code, one of the ErrorListener.ERROR_ values. + */ + public void onCameraDeviceError(CameraDevice camera, int error); + } + +} diff --git a/core/java/android/hardware/photography/CameraManager.java b/core/java/android/hardware/photography/CameraManager.java new file mode 100644 index 0000000..328ba4b --- /dev/null +++ b/core/java/android/hardware/photography/CameraManager.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +/** + * <p>An interface for iterating, listing, and connecting to + * {@link CameraDevice CameraDevices}.</p> + * + * <p>You can get an instance of this class by calling + * {@link android.content.Context#getSystemService(String) Context.getSystemService()}.</p> + * + * <pre>CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);</pre> + * + * <p>For more details about communicating with camera devices, read the Camera + * developer guide or the {@link android.hardware.photography photography} + * package documentation.</p> + */ +public final class CameraManager { + + /** + * @hide + */ + public CameraManager() { + } + + /** + * <p>Return the list of currently connected camera devices by + * identifier. Non-removable cameras use integers starting at 0 for their + * identifiers, while removable cameras have a unique identifier for each + * individual device, even if they are the same model.</p> + * + * @return The list of currently connected camera devices. + */ + public String[] getDeviceIdList() { + return null; + } + + /** + * Register a listener to be notified about camera device availability. + * + * @param listener the new listener to send camera availablity notices to. + */ + public void registerCameraListener(CameraListener listener) { + } + + /** + * Remove a previously-added listener; the listener will no longer receive + * connection and disconnection callbacks. + * + * @param listener the listener to remove from the notification list + */ + public void unregisterCameraListener(CameraListener listener) { + } + + /** + * <p>Query the capabilities of a camera device. These capabilities are + * immutable for a given camera.</p> + * + * @param cameraId The id of the camera device to query + * @return The properties of the given camera + * + * @throws IllegalArgumentException if the cameraId does not match any + * currently connected camera device. + * @throws CameraAccessException if the camera is disabled by device policy. + * @throws SecurityException if the application does not have permission to + * access the camera + * + * @see #getDeviceIdList + * @see android.app.admin.DevicePolicyManager#setCameraDisabled + */ + public CameraProperties getCameraProperties(String cameraId) + throws CameraAccessException { + throw new IllegalArgumentException(); + } + + /** + * Open a connection to a camera with the given ID. Use + * {@link #getDeviceIdList} to get the list of available camera + * devices. Note that even if an id is listed, open may fail if the device + * is disconnected between the calls to {@link #getDeviceIdList} and + * {@link #openCamera}. + * + * @param cameraId The unique identifier of the camera device to open + * + * @throws IllegalArgumentException if the cameraId does not match any + * currently connected camera device. + * @throws CameraAccessException if the camera is disabled by device policy, + * or too many camera devices are already open. + * @throws SecurityException if the application does not have permission to + * access the camera + * + * @see #getDeviceIdList + * @see android.app.admin.DevicePolicyManager#setCameraDisabled + */ + public CameraDevice openCamera(String cameraId) throws CameraAccessException { + throw new IllegalArgumentException(); + } + + /** + * Interface for listening to cameras becoming available or unavailable. + * Cameras become available when they are no longer in use, or when a new + * removable camera is connected. They become unavailable when some + * application or service starts using a camera, or when a removable camera + * is disconnected. + */ + public interface CameraListener { + /** + * A new camera has become available to use. + * + * @param cameraId The unique identifier of the new camera. + */ + public void onCameraAvailable(String cameraId); + + /** + * A previously-available camera has become unavailable for use. If an + * application had an active CameraDevice instance for the + * now-disconnected camera, that application will receive a {@link + * CameraDevice.ErrorListener#DEVICE_DISCONNECTED disconnection error}. + * + * @param cameraId The unique identifier of the disconnected camera. + */ + public void onCameraUnavailable(String cameraId); + } +} diff --git a/core/java/android/hardware/photography/CameraMetadata.java b/core/java/android/hardware/photography/CameraMetadata.java new file mode 100644 index 0000000..385a1b9 --- /dev/null +++ b/core/java/android/hardware/photography/CameraMetadata.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +import android.os.Parcelable; +import android.os.Parcel; +import java.util.HashMap; +import java.util.Map; + +/** + * The base class for camera controls and information. + * + * This class defines the basic key/value map used for querying for camera + * characteristics or capture results, and for setting camera request + * parameters. + * + * @see CameraDevice + * @see CameraManager + * @see CameraProperties + **/ +public class CameraMetadata implements Parcelable { + + public CameraMetadata() { + mMetadataMap = new HashMap<Key<?>, Object>(); + } + + private CameraMetadata(Parcel in) { + + } + + public static final Parcelable.Creator<CameraMetadata> CREATOR = + new Parcelable.Creator<CameraMetadata>() { + public CameraMetadata createFromParcel(Parcel in) { + return new CameraMetadata(in); + } + + public CameraMetadata[] newArray(int size) { + return new CameraMetadata[size]; + } + }; + + /** + * Set a camera metadata field to a value. The field definitions can be + * found in {@link CameraProperties}, {@link CaptureResult}, and + * {@link CaptureRequest}. + * + * @param key the metadata field to write. + * @param value the value to set the field to, which must be of a matching + * type to the key. + */ + public <T> void set(Key<T> key, T value) { + mMetadataMap.put(key, value); + } + + /** + * Get a camera metadata field value. The field definitions can be + * found in {@link CameraProperties}, {@link CaptureResult}, and + * {@link CaptureRequest}. + * + * @param key the metadata field to read. + * @return the value of that key, or {@code null} if the field is not set. + */ + @SuppressWarnings("unchecked") + public <T> T get(Key<T> key) { + return (T) mMetadataMap.get(key); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public void writeToParcel(Parcel dest, int flags) { + + } + + public static class Key<T> { + public Key(String name) { + if (name == null) { + throw new NullPointerException("Key needs a valid name"); + } + mName = name; + } + + public final String getName() { + return mName; + } + + @Override + public final int hashCode() { + return mName.hashCode(); + } + + @Override + @SuppressWarnings("unchecked") + public final boolean equals(Object o) { + if (this == o) { + return true; + } + + if (!(o instanceof Key)) { + return false; + } + + Key lhs = (Key) o; + + return mName.equals(lhs.mName); + } + + private final String mName; + } + + private Map<Key<?>, Object> mMetadataMap; +}
\ No newline at end of file diff --git a/core/java/android/hardware/photography/CameraProperties.java b/core/java/android/hardware/photography/CameraProperties.java new file mode 100644 index 0000000..1bfd712 --- /dev/null +++ b/core/java/android/hardware/photography/CameraProperties.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +import android.graphics.Rect; + +import java.util.List; + +/** + * <p>The properties describing a + * {@link CameraDevice CameraDevice}.</p> + * + * <p>These properties are fixed for a given CameraDevice, and can be queried + * through the {@link CameraManager CameraManager} + * interface in addition to through the CameraDevice interface.</p> + * + * @see CameraDevice + * @see CameraManager + */ +public final class CameraProperties extends CameraMetadata { + /** + * The model name of the camera. For fixed (non-removable) cameras, this is + * the manufacturer's name. For removable cameras, this is a string that + * uniquely identifies the camera model and manufacturer. The + * {@link #INFO_IDENTIFIER} can be used to distinguish between multiple + * removable cameras of the same model. + */ + public static final Key INFO_MODEL = + new Key<String>("android.info.model"); + + /** + * A unique identifier for this camera. For removable cameras, every + * camera will have a unique identifier, including two cameras of the + * same model and manufacturer. For non-removable cameras, the + * identifier is equal to the the device's id. + */ + public static final Key INFO_IDENTIFIER = + new Key<String>("android.info.identifier"); + + /** + * <p>Whether this camera is removable or not.</p> + * + * <p>Applications using a removable camera must be prepared for the camera + * to be disconnected during use. Use the {@link #INFO_IDENTIFIER} field to + * determine if this camera is a match for a camera device seen earlier.</p> + */ + public static final Key INFO_REMOVABLE = + new Key<Boolean>("android.info.isRemovable"); + + /** + * <p>The hardware operational model of this device. One of the + * INFO_SUPPORTED_HARDWARE_LEVEL_* constants.</p> + * + * <p>Limited-capability devices have a number of limitations relative to + * full-capability cameras. Roughly, they have capabilities comparable to + * those provided by the deprecated {@link android.hardware.Camera} + * class.</p> + * + * <p>Specifically, limited-mode devices:</p> + * + * <ol> + * + * <li>Do not provide per-frame result metadata for repeating + * captures. This means that a CaptureListener will not be called for + * captures done through {@link CameraDevice#setRepeatingRequest + * setRepeatingRequest} or {@link CameraDevice#setRepeatingBurst + * setRepeatingBurst}.</li> + * + * <li>Do not support complete result metadata. Only a few fields are + * provided, such as the timestamp (TODO).</li> + * + * <li>Do not support manual capture controls. Only the (TODO) + * ANDROID_CONTROL_* fields and TODO controls are used, and the various + * AE/AF/AWB_OFF control values cannot be used.</li> + * + * <li>Do not support high frame rate captures. To obtain high frame rate, + * the {@link CameraDevice#setRepeatingRequest setRepeatingRequest} method + * must be used. The {@link CameraDevice#capture capture}, + * {@link CameraDevice#captureBurst captureBurst}, and + * {@link CameraDevice#setRepeatingBurst setRepeatingBurst} methods will + * result in slow frame captures.</li> + * + * </ol> + * + * @see #INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED + * @see #INFO_SUPPORTED_HARDWARE_LEVEL_FULL + */ + public static final Key INFO_SUPPORTED_HARDWARE_LEVEL = + new Key<Integer>("android.info.supportedHardwareLevel"); + + /** + * <p>The type reported by limited-capability camera devices.</p> + * + * <p>Limited-capability devices have a number of limitations relative to + * full-capability cameras. Roughly, they have capabilities comparable to + * those provided by the deprecated {@link android.hardware.Camera} + * class.</p> + * + * <p>Specifically, limited-mode devices:</p> + * + * <ol> + * + * <li>Do not provide per-frame result metadata for repeating + * captures. This means that a CaptureListener will not be called for + * captures done through {@link CameraDevice#setRepeatingRequest + * setRepeatingRequest} or {@link CameraDevice#setRepeatingBurst + * setRepeatingBurst}.</li> + * + * <li>Do not support complete result metadata. Only a few fields are + * provided, such as the timestamp (TODO).</li> + * + * <li>Do not support manual capture controls. Only the (TODO) + * ANDROID_CONTROL_* fields and TODO controls are used, and the various + * AE/AF/AWB_OFF control values cannot be used.</li> + * + * <li>Do not support high frame rate captures. To obtain high frame rate, + * the {@link CameraDevice#setRepeatingRequest setRepeatingRequest} method + * must be used. The {@link CameraDevice#capture capture}, + * {@link CameraDevice#captureBurst captureBurst}, and + * {@link CameraDevice#setRepeatingBurst setRepeatingBurst} methods will + * result in slow frame captures.</li> + * + * </ol> + * + * @see #INFO_SUPPORTED_HARDWARE_LEVEL + */ + public static final int INFO_SUPPORTED_HARDWARE_LEVEL_LIMITED = 0; + + /** + * <p>The type reported by full-capability camera devices</p> + * + * <p>Full-capability devices allow for per-frame control of capture + * hardware and post-processing parameters at high frame rates. They also + * provide output data at high resolution in uncompressed formats, in + * addition to compressed JPEG output.</p> + * + * @see #INFO_SUPPORTED_HARDWARE_LEVEL + */ + public static final int INFO_SUPPORTED_HARDWARE_LEVEL_FULL = 1; + + /** + * <p>The available output formats from this camera device. When using a + * {@link android.media.ImageReader} as an output target, the + * ImageReader must be configured to use one of these formats.</p> + * + * <p>The list is a subset of the formats defined in + * {@link android.graphics.ImageFormat}.</p> + * + * <p>The image formats {@link android.graphics.ImageFormat#JPEG}, + * {@link android.graphics.ImageFormat#YUV_420_888} are guaranteed to be + * supported.</p> + */ + public static final Key SCALER_AVAILABLE_FORMATS = + new Key<Integer[]>("android.scaler.availableFormats"); + + /** + * <p>The available output sizes for JPEG buffers from this camera + * device. When using a {@link android.media.ImageReader} as an output + * target, the ImageReader must be configured to use one of these sizes + * when using format {@link android.graphics.ImageFormat#JPEG}.</p> + */ + public static final Key SCALER_AVAILABLE_JPEG_SIZES = + new Key<Size[]>("android.scaler.availableJpegSizes"); + + /** + * <p>The available sizes for output buffers from this camera device, when + * the buffers are neither of the {@link android.graphics.ImageFormat#JPEG} + * or of the {@link android.graphics.ImageFormat#RAW_SENSOR} type.</p> + * + * <p>When using a {@link android.view.SurfaceView}, + * {@link android.graphics.SurfaceTexture}, + * {@link android.media.MediaRecorder}, {@link android.media.MediaCodec}, or + * {@link android.renderscript.Allocation} as an output target, that target + * must be configured to one of these sizes. See + * {@link CameraDevice#configureOutputs} for details. + * + * <p>When using a {@link android.media.ImageReader} as an output + * target, the ImageReader must be configured to use one of these sizes + * when using format {@link android.graphics.ImageFormat#YUV_420_888}.</p> + * + */ + public static final Key SCALER_AVAILABLE_PROCESSED_SIZES = + new Key<Size[]>("android.scaler.availableProcessedSizes"); + + /** + * <p>The available sizes for output buffers from this camera device, when + * the buffers are of the {@link android.graphics.ImageFormat#RAW_SENSOR} type. This type of output may not be + * supported by the device; check {@link #SCALER_AVAILABLE_FORMATS} to + * check. In that case, this list will not exist.</p> + * + * <p>When using a {@link android.media.ImageReader} as an output + * target, the ImageReader must be configured to use one of these sizes + * when using image format {@link android.graphics.ImageFormat#RAW_SENSOR}.</p> + */ + public static final Key SCALER_AVAILABLE_RAW_SIZES = + new Key<Size[]>("android.scaler.availableRawSizes"); + + /** + * <p>The coordinates of the sensor's active pixel array, relative to its + * total pixel array. These are the pixels that are actually used for image + * capture. The active pixel region may be smaller than the total number of + * pixels, if some pixels are used for other tasks such as calibrating the + * sensor's black level. If all pixels available for readout are used for + * imaging, then this rectangle will be + * {@code (0,0) - (SENSOR_PIXEL_ARRAY_SIZE.width, + * SENSOR_PIXEL_ARRAY_SIZE.height)}.</p> + * + * <p>If raw sensor capture is supported by this device, the width and + * height of the active pixel array match up to one of the supported raw + * capture sizes, and using that size will capture just the active pixel + * array region.</p> + * + * <p>Most other coordinates used by the camera device (for example, for + * metering and crop region selection, or for reporting detected faces) use + * a coordinate system based on the active array dimensions, with (0,0) + * being the top-left corner of the active array.</p> + */ + public static final Key SENSOR_ACTIVE_ARRAY_SIZE = + new Key<Rect>("android.sensor.activeArraySize"); + + /** + * <p>The size of the sensor's total pixel array available for readout. Some + * of these pixels may not be used for image capture, in which case + * {@link #SENSOR_ACTIVE_ARRAY_SIZE} will describe a rectangle smaller than + * this. If raw sensor capture is supported by this device, this is one of + * the supported capture sizes.</p> + */ + public static final Key SENSOR_PIXEL_ARRAY_SIZE = + new Key<Size>("android.sensor.activeArraySize"); + + // TODO: Many more of these. + +} diff --git a/core/java/android/hardware/photography/CaptureRequest.java b/core/java/android/hardware/photography/CaptureRequest.java new file mode 100644 index 0000000..a54c743 --- /dev/null +++ b/core/java/android/hardware/photography/CaptureRequest.java @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +import android.view.Surface; + +import java.util.List; + + +/** + * <p>All the settings required to capture a single image from the image sensor.</p> + * + * <p>Contains the configuration for the capture hardware (sensor, lens, flash), + * the processing pipeline, the control algorithms, and the output buffers.</p> + * + * <p>CaptureRequests can be created by calling + * {@link CameraDevice#createCaptureRequest}</p> + * + * <p>CaptureRequests are given to {@link CameraDevice#capture} or + * {@link CameraDevice#setRepeatingRequest} to capture images from a camera.</p> + * + * <p>Each request can specify a different subset of target Surfaces for the + * camera to send the captured data to. All the surfaces used in a request must + * be part of the surface list given to the last call to + * {@link CameraDevice#configureOutputs}.</p> + * + * <p>For example, a request meant for repeating preview might only include the + * Surface for the preview SurfaceView or SurfaceTexture, while a + * high-resolution still capture would also include a Surface from a ImageReader + * configured for high-resolution JPEG images.</p> + * + * @see CameraDevice#capture + * @see CameraDevice#setRepeatingRequest + * @see CameraDevice#createRequest + */ +public final class CaptureRequest extends CameraMetadata { + + /** + * The exposure time for this capture, in nanoseconds. + */ + public static final Key SENSOR_EXPOSURE_TIME = + new Key<Long>("android.sensor.exposureTime"); + + /** + * The sensor sensitivity (gain) setting for this camera. + * This is represented as an ISO sensitivity value + */ + public static final Key SENSOR_SENSITIVITY = + new Key<Integer>("android.sensor.sensitivity"); + + // Many more settings + + CaptureRequest() { + } + + /** + * <p>Add a surface to the list of targets for this request</p> + * + * <p>The Surface added must be one of the surfaces included in the last + * call to {@link CameraDevice#configureOutputs}.</p> + */ + public void addTarget(Surface outputTarget) { + } + + /** + * <p>Remove a surface from the list of targets for this request.</p> + */ + public void removeTarget(Surface outputTarget) { + } + +}
\ No newline at end of file diff --git a/core/java/android/hardware/photography/CaptureResult.java b/core/java/android/hardware/photography/CaptureResult.java new file mode 100644 index 0000000..dd36f1d --- /dev/null +++ b/core/java/android/hardware/photography/CaptureResult.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2012 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 android.hardware.photography; + +import android.graphics.Point; +import android.graphics.Rect; + +/** + * <p>The results of a single image capture from the image sensor.</p> + * + * <p>Contains the final configuration for the capture hardware (sensor, lens, + * flash), the processing pipeline, the control algorithms, and the output + * buffers.</p> + * + * <p>CaptureResults are produced by a {@link CameraDevice} after processing a + * {@link CaptureRequest}. All properties listed for capture requests can also + * be queried on the capture result, to determine the final values used for + * capture. The result also includes additional metadata about the state of the + * camera device during the capture.</p> + * + */ +public final class CaptureResult extends CameraMetadata { + + /** + * The timestamp representing the start of image capture, in nanoseconds. + * This corresponds to the timestamp available through + * {@link android.graphics.SurfaceTexture#getTimestamp SurfaceTexture.getTimestamp()} + * or {@link android.media.Image#getTimestamp Image.getTimestamp()} for this + * capture's image data. + */ + public static final Key SENSOR_TIMESTAMP = + new Key<Long>("android.sensor.timestamp"); + + /** + * The state of the camera device's auto-exposure algorithm. One of the + * CONTROL_AE_STATE_* enumerations. + */ + public static final Key CONTROL_AE_STATE = + new Key<Integer>("android.control.aeState"); + + /** + * The auto-exposure algorithm is inactive. + * @see CONTROL_AE_STATE + */ + public static final int CONTROL_AE_STATE_INACTIVE = 0; + + /** + * The auto-exposure algorithm is currently searching for proper exposure. + * @see CONTROL_AE_STATE + */ + public static final int CONTROL_AE_STATE_SEARCHING = 1; + + /** + * The auto-exposure algorithm has reached proper exposure values for the + * current scene. + * @see CONTROL_AE_STATE + */ + public static final int CONTROL_AE_STATE_CONVERGED = 2; + + /** + * The auto-exposure algorithm has been locked to its current values. + * @see CONTROL_AE_STATE + */ + public static final int CONTROL_AE_STATE_LOCKED = 3; + + /** + * The auto-exposure algorithm has reached proper exposure values as with + * CONTROL_AE_STATE_CONVERGED, but the scene is too dark to take a good + * quality image without firing the camera flash. + * @see CONTROL_AE_STATE + */ + public static final int CONTROL_AE_STATE_FLASH_REQUIRED = 4; + + /** + * The precapture sequence of the auto-exposure algorithm has been triggered, + * and is underway. + * @see CONTROL_AE_STATE + */ + public static final int CONTROL_AE_STATE_PRECAPTURE =5; + + /** + * The list of faces detected in this capture. Available if face detection + * was enabled for this capture + */ + public static final Key STATISTICS_DETECTED_FACES = + new Key<Face[]>("android.statistics.faces"); + + // TODO: Many many more + + CaptureResult() { + } + + /** + * Describes a face detected in an image. + */ + public static class Face { + + /** + * <p>Bounds of the face. A rectangle relative to the sensor's + * {@link CameraProperties#SENSOR_ACTIVE_ARRAY_SIZE}, with (0,0) + * representing the top-left corner of the active array rectangle.</p> + */ + public Rect getBounds() { + return mBounds; + } + + /* <p>The confidence level for the detection of the face. The range is 1 to + * 100. 100 is the highest confidence.</p> + * + * <p>Depending on the device, even very low-confidence faces may be + * listed, so applications should filter out faces with low confidence, + * depending on the use case. For a typical point-and-shoot camera + * application that wishes to display rectangles around detected faces, + * filtering out faces with confidence less than 50 is recommended.</p> + * + */ + public int getScore() { + return mScore; + } + + /** + * An unique id per face while the face is visible to the tracker. If + * the face leaves the field-of-view and comes back, it will get a new + * id. This is an optional field, may not be supported on all devices. + * If not supported, id will always be set to -1. The optional fields + * are supported as a set. Either they are all valid, or none of them + * are. + */ + public int getId() { + return mId; + } + + /** + * The coordinates of the center of the left eye. The coordinates are in + * the same space as the ones for {@link #getBounds}. This is an + * optional field, may not be supported on all devices. If not + * supported, the value will always be set to null. The optional fields + * are supported as a set. Either they are all valid, or none of them + * are. + */ + public Point getLeftEye() { + return mLeftEye; + } + + /** + * The coordinates of the center of the right eye. The coordinates are + * in the same space as the ones for {@link #getBounds}.This is an + * optional field, may not be supported on all devices. If not + * supported, the value will always be set to null. The optional fields + * are supported as a set. Either they are all valid, or none of them + * are. + */ + public Point getRightEye() { + return mRightEye; + } + + /** + * The coordinates of the center of the mouth. The coordinates are in + * the same space as the ones for {@link #getBounds}. This is an optional + * field, may not be supported on all devices. If not supported, the + * value will always be set to null. The optional fields are supported + * as a set. Either they are all valid, or none of them are. + */ + public Point getMouth() { + return mMouth; + } + + private Rect mBounds; + private int mScore; + private int mId; + private Point mLeftEye; + private Point mRightEye; + private Point mMouth; + } +} diff --git a/core/java/android/hardware/photography/Size.java b/core/java/android/hardware/photography/Size.java new file mode 100644 index 0000000..e1115d3 --- /dev/null +++ b/core/java/android/hardware/photography/Size.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 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 android.hardware.photography; + +/** + * A simple immutable class for describing the dimensions of camera image + * buffers. + */ +public final class Size { + /** + * Create a new immutable Size instance + * + * @param w The width to store in the Size instance + * @param h The height to store in the Size instance + */ + Size(int w, int h) { + mWidth = w; + mHeight = h; + } + + public final int getWidth() { + return mWidth; + } + + public final int getHeight() { + return mHeight; + } + + private final int mWidth; + private final int mHeight; +}; diff --git a/core/java/android/hardware/photography/package.html b/core/java/android/hardware/photography/package.html new file mode 100644 index 0000000..578bdf5 --- /dev/null +++ b/core/java/android/hardware/photography/package.html @@ -0,0 +1,84 @@ +<!-- Copyright (C) 2013 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. +--> +<HTML> +<BODY> +<p>The android.hardware.photography package provides an interface to +individual camera devices connected to an Android device. It replaces +the deprecated {@link android.hardware.Camera} class.</p> + +<p>This package models a camera device as a pipeline, which takes in +input requests for capturing a single frame, captures the single image +per the request, and then outputs one capture result metadata packet, +plus a set of output image buffers for the request. The requests are +processed in-order, and multiple requests can be in flight at +once. Since the camera device is a pipeline with multiple stages, +having multiple requests in flight is required to maintain full +framerate on most Android devices.</p> + +<p>To enumerate, query, and open available camera devices, obtain a +{@link android.hardware.photography.CameraManager} instance.</p> + +<p>Individual {@link android.hardware.photography.CameraDevice +CameraDevices} provide a set of static property information that +describes the hardware device and the available settings and output +parameters for the device. This information is provided through the +{@link android.hardware.photography.CameraProperties} object.</p> + +<p>To capture or stream images from a camera device, the application +must first configure a set of output Surfaces for use with the camera +device, with {@link +android.hardware.photography.CameraDevice#configureOutputs}. Each +Surface has to be pre-configured with an appropriate size and format +(if applicable) to match the sizes and formats available from the +camera device. A target Surface can be obtained from a variety of +classes, including {@link android.view.SurfaceView}, {@link +android.graphics.SurfaceTexture} via {@link +android.view.Surface#Surface(SurfaceTexture), {@link +android.media.MediaCodec}, and {@link android.media.ImageReader}. +</p> + +<p>The application then needs to construct a {@link +android.hardware.photography.CaptureRequest}, which defines all the +capture parameters needed by a camera device to capture a single +image. The request also lists which of the configured output Surfaces +should be used as targets for this capture. The CameraDevice has a +{@link android.hardware.photography.CameraDevice#createCaptureRequest +convenience factory method} for creating a request for a given use +case which is optimized for the Android device the application is +running on.</p> + +<p>Once the request has been set up, it can be handed to the +CameraDevice either for a one-shot {@link +android.hardware.photography.CameraDevice#capture} or for an endlessly +{@link android.hardware.photography.CameraDevice#setRepeatingRequest +repeating} use. Both methods also accept a list of requests to use as +a burst capture / repeating burst. Repeating requests have a lower +priority than captures, so a request submitted +through <code>capture()</code> while there's a repeating request +configured will be captured as soon as the current repeat (burst) +capture completes.</p> + +<p>After processing a request, the camera device will produce a {@link +android.hardware.photography.CaptureResult} object, which contains +information about the state of the camera device at time of capture, +and the final settings used. These may vary somewhat from the request, +if rounding or resolving contradictory parameters was necessary. The +camera device will also send a frame of image data into each of the +output streams included in the request. These are produced +asynchronously relative to the output CaptureResult, sometimes +substantially later.</p> + +</BODY> +</HTML> diff --git a/core/java/android/view/SurfaceHolder.java b/core/java/android/view/SurfaceHolder.java index 015a78e..99fa2a4 100644 --- a/core/java/android/view/SurfaceHolder.java +++ b/core/java/android/view/SurfaceHolder.java @@ -277,9 +277,6 @@ public interface SurfaceHolder { * * <p>This method is intended to be used by frameworks which often need * direct access to the Surface object (usually to pass it to native code). - * When designing APIs always use SurfaceHolder to pass surfaces around - * as opposed to the Surface object itself. A rule of thumb is that - * application code should never have to call this method. * * @return Surface The surface. */ diff --git a/graphics/java/android/graphics/ImageFormat.java b/graphics/java/android/graphics/ImageFormat.java index f6b747a..972ce47 100644 --- a/graphics/java/android/graphics/ImageFormat.java +++ b/graphics/java/android/graphics/ImageFormat.java @@ -100,6 +100,41 @@ public class ImageFormat { public static final int JPEG = 0x100; /** + * <p>Multi-plane Android YUV format</p> + * + * <p>This format is a generic YCbCr format, capable of describing any 4:2:0 + * chroma-subsampled planar or semiplanar buffer, with 8 bits per color + * sample.</p> + * + * <p>Images in this format are always represented by three separate buffers + * of data, one for each color plane. Additional information always + * accompanies the buffers, describing the row stride and the pixel stride + * for each plane.</p> + * + * <p>For example, the {@link android.media.Image} object can provide data + * in this format from a {@link android.hardware.photography.CameraDevice} + * through a {@link android.media.ImageReader} object.</p> + * + * @see android.media.Image + * @see android.media.ImageReader + * @see android.hardware.camera.CameraDevice + */ + public static final int YUV_420_888 = 0x23; + + /** + * <p>General raw camera sensor image format, usually representing a + * single-channel Bayer-mosaic image. Each pixel color sample is stored with + * 16 bits of precision.</p> + * + * <p>The layout of the color mosaic, the maximum and minimum encoding + * values of the raw pixel data, the color space of the image, and all other + * needed information to interpret a raw sensor image must be queried from + * the {@link android.hardware.photography.CameraDevice} which produced the + * image.</p> + */ + public static final int RAW_SENSOR = 0x201; + + /** * Raw bayer format used for images, which is 10 bit precision samples * stored in 16 bit words. The filter pattern is RGGB. Whether this format * is supported by the camera hardware can be determined by @@ -129,6 +164,10 @@ public class ImageFormat { return 12; case NV21: return 12; + case YUV_420_888: + return 12; + case RAW_SENSOR: + return 16; case BAYER_RGGB: return 16; } diff --git a/media/java/android/media/Image.java b/media/java/android/media/Image.java new file mode 100644 index 0000000..eb94346 --- /dev/null +++ b/media/java/android/media/Image.java @@ -0,0 +1,184 @@ +/* + * Copyright (C) 2013 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 android.media; + +import android.graphics.ImageFormat; +import java.nio.ByteBuffer; +import java.lang.AutoCloseable; + +/** + * <p>A single complete image buffer to use with a media source such as a + * {@link MediaCodec} or a + * {@link android.hardware.photography.CameraDevice}.</p> + * + * <p>This class allows for efficient direct application access to the pixel + * data of the Image through one or more + * {@link java.nio.ByteBuffer ByteBuffers}. Each buffer is encapsulated in a + * {@link Plane} that describes the layout of the pixel data in that plane. Due + * to this direct access, and unlike the {@link android.graphics.Bitmap} class, + * Images are not directly usable as as UI resources.</p> + * + * <p>Since Images are often directly produced or consumed by hardware + * components, they are a limited resource shared across the system, and should + * be closed as soon as they are no longer needed.</p> + * + * <p>For example, when using the {@link ImageReader} class to read out Images + * from various media sources, not closing old Image objects will prevent the + * availability of new Images once + * {@link ImageReader#getMaxImages the maximum outstanding image count} is + * reached.</p> + * + * @see ImageReader + */ +public abstract class Image implements AutoCloseable { + /** + * Get the format for this image. This format determines the number of + * ByteBuffers needed to represent the image, and the general layout of the + * pixel data in each in ByteBuffer. + * + * The format is one of the values from + * {@link android.graphics.ImageFormat}. The mapping between the formats and + * the planes is as follows: + * + * <table> + * <th> + * <td>Format</td> + * <td>Plane count</td> + * <td>Layout details</td> + * </th> + * <tr> + * <td>{@link android.graphics.ImageFormat#JPEG}</td> + * <td>1</td> + * <td>Compressed data, so row and pixel strides are 0. To uncompress, use + * {@link android.graphics.BitmapFactory#decodeByteArray}.</td> + * </tr> + * <tr> + * <td>{@link android.graphics.ImageFormat#YUV_420_888}</td> + * <td>3</td> + * <td>A luminance plane followed by the Cb and Cr chroma planes. + * The chroma planes have half the width and height of the luminance + * plane (4:2:0 subsampling). Each pixel sample in each plane has 8 bits. + * Each plane has its own row stride and pixel stride.</td> + * </tr> + * <tr> + * <td>{@link android.graphics.ImageFormat#RAW_SENSOR}</td> + * <td>1</td> + * <td>A single plane of raw sensor image data, with 16 bits per color + * sample. The details of the layout need to be queried from the source of + * the raw sensor data, such as + * {@link android.hardware.photography.CameraDevice}. + * </td> + * </tr> + * </table> + * + * @see android.graphics.ImageFormat + */ + public int getFormat() { + return ImageFormat.UNKNOWN; + } + + /** + * The width of the image in pixels. For formats where some color channels + * are subsampled, this is the width of the largest-resolution plane. + */ + public int getWidth() { + return 0; + } + + /** + * The height of the image in pixels. For formats where some color channels + * are subsampled, this is the height of the largest-resolution plane. + */ + public int getHeight() { + return 0; + } + + /** + * Get the timestamp associated with this frame. The timestamp is measured + * in nanoseconds, and is monotonically increasing. However, the zero point + * and whether the timestamp can be compared against other sources of time + * or images depend on the source of this image. + */ + public long getTimestamp() { + return 0; + } + + /** + * Get the array of pixel planes for this Image. The number of planes is + * determined by the format of the Image. + */ + public Plane[] getPlanes() { + return null; + } + + /** + * Free up this frame for reuse. After calling this method, calling any + * methods on this Image will result in an IllegalStateException, and + * attempting to read from ByteBuffers returned by an earlier + * {@code Plane#getBuffer} call will have undefined behavior. + */ + public abstract void close(); + + protected final void finalize() { + close(); + } + + /** + * <p>A single color plane of image data.</p> + * + * <p>The number and meaning of the planes in an Image are determined by the + * format of the Image.</p> + * + * <p>Once the Image has been closed, any access to the the plane's + * ByteBuffer will fail.</p> + * + * @see #getFormat + */ + public static final class Plane { + /** + * <p>The row stride for this color plane, in bytes. + * + * <p>This is the distance between the start of two consecutive rows of + * pixels in the image.</p> + */ + public int getRowStride() { + return 0; + } + + /** + * <p>The distance between adjacent pixel samples, in bytes.</p> + * + * <p>This is the distance between two consecutive pixel values in a row + * of pixels. It may be larger than the size of a single pixel to + * account for interleaved image data or padded formats.</p> + */ + public int getPixelStride() { + return 0; + } + + /** + * <p>Get a set of direct {@link java.nio.ByteBuffer byte buffers} + * containing the frame data.</p> + * + * @return the byte buffer containing the image data for this plane. + */ + public ByteBuffer getBuffer() { + return null; + } + } + +} diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java new file mode 100644 index 0000000..9384c14 --- /dev/null +++ b/media/java/android/media/ImageReader.java @@ -0,0 +1,171 @@ +/* + * Copyright (C) 2013 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 android.media; + +import android.view.Surface; +import java.lang.AutoCloseable; + +/** + * <p>The ImageReader class allows direct application access to image data + * rendered into a {@link android.view.Surface}</p> + * + * <p>Several Android media API classes accept Surface objects as targets to + * render to, including {@link MediaPlayer}, {@link MediaCodec}, + * {@link android.hardware.photography.CameraDevice}, and + * {@link android.renderscript.Allocation RenderScript Allocations}. The image + * sizes and formats that can be used with each source vary, and should be + * checked in the documentation for the specific API.</p> + * + * <p>The image data is encapsulated in {@link Image} objects, and multiple such + * objects can be accessed at the same time, up to the number specified by the + * {@code maxImages} constructor parameter. New images sent to an ImageReader + * through its Surface are queued until accessed through the + * {@link #getNextImage} call. Due to memory limits, an image source will + * eventually stall or drop Images in trying to render to the Surface if the + * ImageReader does not obtain and release Images at a rate equal to the + * production rate.</p> + */ +public final class ImageReader { + + /** + * <p>Create a new reader for images of the desired size and format.</p> + * + * <p>The maxImages parameter determines the maximum number of {@link Image} + * objects that can be be acquired from the ImageReader + * simultaneously. Requesting more buffers will use up more memory, so it is + * important to use only the minimum number necessary for the use case.</p> + * + * <p>The valid sizes and formats depend on the source of the image + * data.</p> + * + * @param width the width in pixels of the Images that this reader will + * produce. + * @param height the height in pixels of the Images that this reader will + * produce. + * @param format the format of the Image that this reader will produce. This + * must be one of the {@link android.graphics.ImageFormat} constants. + * @param maxImages the maximum number of images the user will want to + * access simultaneously. This should be as small as possible to limit + * memory use. Once maxImages Images are obtained by the user, one of them + * has to be released before a new Image will become available for access + * through getImage(). Must be greater than 0. + * + * @see Image + */ + public ImageReader(int width, int height, int format, int maxImages) { + mWidth = width; + mHeight = height; + mFormat = format; + mMaxImages = maxImages; + + if (width < 1 || height < 1) { + throw new IllegalArgumentException( + "The image dimensions must be positive"); + } + if (mMaxImages < 1) { + throw new IllegalArgumentException( + "Maximum outstanding image count must be at least 1"); + } + } + + public int getWidth() { + return mWidth; + } + + public int getHeight() { + return mHeight; + } + + public int getImageFormat() { + return mFormat; + } + + public int getMaxImages() { + return mMaxImages; + } + + /** + * <p>Get a Surface that can be used to produce Images for this + * ImageReader.</p> + * + * <p>Until valid image data is rendered into this Surface, the + * {@link #getNextImage} method will return {@code null}. Only one source + * can be producing data into this Surface at the same time, although the + * same Surface can be reused with a different API once the first source is + * disconnected from the Surface.</p> + * + * @return A Surface to use for a drawing target for various APIs. + */ + public Surface getSurface() { + return null; + } + + /** + * <p>Get the next Image from the ImageReader's queue. Returns {@code null} + * if no new image is available.</p> + * + * @return a new frame of image data, or {@code null} if no image data is + * available. + */ + public Image getNextImage() { + return null; + } + + /** + * <p>Return the frame to the ImageReader for reuse.</p> + */ + public void releaseImage(Image i) { + if (! (i instanceof SurfaceImage) ) { + throw new IllegalArgumentException( + "This image was not produced by an ImageReader"); + } + SurfaceImage si = (SurfaceImage) i; + if (si.getReader() != this) { + throw new IllegalArgumentException( + "This image was not produced by this ImageReader"); + } + } + + public void setOnImageAvailableListener(OnImageAvailableListener l) { + mImageListener = l; + } + + public interface OnImageAvailableListener { + void onImageAvailable(ImageReader reader); + } + + private final int mWidth; + private final int mHeight; + private final int mFormat; + private final int mMaxImages; + + private OnImageAvailableListener mImageListener; + + private class SurfaceImage extends android.media.Image { + public SurfaceImage() { + } + + @Override + public void close() { + ImageReader.this.releaseImage(this); + } + + public ImageReader getReader() { + return ImageReader.this; + } + } +} |