CameraNDK: fill in more NDK API documents
This change adds document for ACaptureRequest, ACameraMetadata,
AImage and AImageReader.
Bug: 27102995
Change-Id: I79d88f73258c01ebeabcd5b4e3b90996759cb021
diff --git a/camera/ndk/impl/ACameraMetadata.h b/camera/ndk/impl/ACameraMetadata.h
index ab651a1..8d050c4 100644
--- a/camera/ndk/impl/ACameraMetadata.h
+++ b/camera/ndk/impl/ACameraMetadata.h
@@ -79,9 +79,15 @@
Mutex::Autolock _l(mLock);
- // Here we have to use reinterpret_cast because the NDK data type is
- // exact copy of internal data type but they do not inherit from each other
- status_t ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
+ status_t ret = OK;
+ if (count == 0 && data == nullptr) {
+ ret = mData.erase(tag);
+ } else {
+ // Here we have to use reinterpret_cast because the NDK data type is
+ // exact copy of internal data type but they do not inherit from each other
+ ret = mData.update(tag, reinterpret_cast<const INTERNAL_T*>(data), count);
+ }
+
if (ret == OK) {
mTags.clear();
return ACAMERA_OK;
diff --git a/include/camera/ndk/NdkCameraCaptureSession.h b/include/camera/ndk/NdkCameraCaptureSession.h
index 68eff7a..7b314e9 100644
--- a/include/camera/ndk/NdkCameraCaptureSession.h
+++ b/include/camera/ndk/NdkCameraCaptureSession.h
@@ -177,7 +177,8 @@
* capture request sent by application, so the address is different to what
* application sent but the content will match. This request will be freed by
* framework immediately after this callback returns.
- * @param result The capture result metadata reported by camera device
+ * @param result The capture result metadata reported by camera device. The memory is managed by
+ * camera framework. Do not access this pointer after this callback returns.
*/
typedef void (*ACameraCaptureSession_captureCallback_result)(
void* context, ACameraCaptureSession* session,
@@ -193,7 +194,9 @@
* capture request sent by application, so the address is different to what
* application sent but the content will match. This request will be freed by
* framework immediately after this callback returns.
- * @param failure The {@link ACameraCaptureFailure} desribes the capture failure.
+ * @param failure The {@link ACameraCaptureFailure} desribes the capture failure. The memory is
+ * managed by camera framework. Do not access this pointer after this callback
+ * returns.
*/
typedef void (*ACameraCaptureSession_captureCallback_failed)(
void* context, ACameraCaptureSession* session,
diff --git a/include/camera/ndk/NdkCameraMetadata.h b/include/camera/ndk/NdkCameraMetadata.h
index 8a8865d..d929854 100644
--- a/include/camera/ndk/NdkCameraMetadata.h
+++ b/include/camera/ndk/NdkCameraMetadata.h
@@ -43,35 +43,78 @@
extern "C" {
#endif
+/**
+ * ACameraMetadata is opaque type that provides access to read-only camera metadata like camera
+ * characteristics (via {@link ACameraManager_getCameraCharacteristics}) or capture results (via
+ * {@link ACameraCaptureSession_captureCallback_result}).
+ */
typedef struct ACameraMetadata ACameraMetadata;
-// Keep in sync with system/media/include/system/camera_metadata.h
+/**
+ * Possible data types of a metadata entry.
+ *
+ * Keep in sync with system/media/include/system/camera_metadata.h
+ */
enum {
- // Unsigned 8-bit integer (uint8_t)
+ /// Unsigned 8-bit integer (uint8_t)
ACAMERA_TYPE_BYTE = 0,
- // Signed 32-bit integer (int32_t)
+ /// Signed 32-bit integer (int32_t)
ACAMERA_TYPE_INT32 = 1,
- // 32-bit float (float)
+ /// 32-bit float (float)
ACAMERA_TYPE_FLOAT = 2,
- // Signed 64-bit integer (int64_t)
+ /// Signed 64-bit integer (int64_t)
ACAMERA_TYPE_INT64 = 3,
- // 64-bit float (double)
+ /// 64-bit float (double)
ACAMERA_TYPE_DOUBLE = 4,
- // A 64-bit fraction (ACameraMetadata_rational)
+ /// A 64-bit fraction (ACameraMetadata_rational)
ACAMERA_TYPE_RATIONAL = 5,
- // Number of type fields
+ /// Number of type fields
ACAMERA_NUM_TYPES
};
+/**
+ * Definition of rational data type in {@link ACameraMetadata}.
+ */
typedef struct ACameraMetadata_rational {
int32_t numerator;
int32_t denominator;
} ACameraMetadata_rational;
+/**
+ * A single camera metadata entry.
+ *
+ * <p>Each entry is an array of values, though many metadata fields may only have 1 entry in the
+ * array.</p>
+ */
typedef struct ACameraMetadata_entry {
+ /**
+ * The tag identifying the entry.
+ *
+ * <p> It is one of the values defined in {@link NdkCameraMetadataTags.h}, and defines how the
+ * entry should be interpreted and which parts of the API provide it.
+ * See {@link NdkCameraMetadataTags.h} for more details. </p>
+ */
uint32_t tag;
+
+ /**
+ * The data type of this metadata entry.
+ *
+ * <p>Must be one of ACAMERA_TYPE_* enum values defined above. A particular tag always has the
+ * same type.</p>
+ */
uint8_t type;
+
+ /**
+ * Count of elements (NOT count of bytes) in this metadata entry.
+ */
uint32_t count;
+
+ /**
+ * Pointer to the data held in this metadata entry.
+ *
+ * <p>The type field above defines which union member pointer is valid. The count field above
+ * defines the length of the data in number of elements.</p>
+ */
union {
uint8_t *u8;
int32_t *i32;
@@ -82,10 +125,41 @@
} data;
} ACameraMetadata_entry;
+/**
+ * A single read-only camera metadata entry.
+ *
+ * <p>Each entry is an array of values, though many metadata fields may only have 1 entry in the
+ * array.</p>
+ */
typedef struct ACameraMetadata_const_entry {
+ /**
+ * The tag identifying the entry.
+ *
+ * <p> It is one of the values defined in {@link NdkCameraMetadataTags.h}, and defines how the
+ * entry should be interpreted and which parts of the API provide it.
+ * See {@link NdkCameraMetadataTags.h} for more details. </p>
+ */
uint32_t tag;
+
+ /**
+ * The data type of this metadata entry.
+ *
+ * <p>Must be one of ACAMERA_TYPE_* enum values defined above. A particular tag always has the
+ * same type.</p>
+ */
uint8_t type;
+
+ /**
+ * Count of elements (NOT count of bytes) in this metadata entry.
+ */
uint32_t count;
+
+ /**
+ * Pointer to the data held in this metadata entry.
+ *
+ * <p>The type field above defines which union member pointer is valid. The count field above
+ * defines the length of the data in number of elements.</p>
+ */
union {
const uint8_t *u8;
const int32_t *i32;
@@ -96,32 +170,61 @@
} data;
} ACameraMetadata_const_entry;
-/*
- * Get a metadata entry
+/**
+ * Get a metadata entry from an input {@link ACameraMetadata}.
+ *
+ * <p>The memory of the data field in the returned entry is managed by camera framework. Do not
+ * attempt to free it.</p>
+ *
+ * @param metadata the {@link ACameraMetadata} of interest.
+ * @param tag the tag value of the camera metadata entry to be get.
+ * @param entry the output {@link ACameraMetadata_const_entry} will be filled here if the method
+ * call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata or entry is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_METADATA_NOT_FOUND} if input metadata does not contain an entry
+ * of input tag value.</li></ul>
*/
camera_status_t ACameraMetadata_getConstEntry(
- const ACameraMetadata*, uint32_t tag, ACameraMetadata_const_entry* entry);
-
-/*
- * List all the entry tags in this metadata.
- * The memory of tags is managed by ACameraMetadata itself and must NOT be free/delete
- * by application. Do NOT access tags after calling ACameraMetadata_free
- */
-camera_status_t ACameraMetadata_getAllTags(
- const ACameraMetadata*, /*out*/int32_t* numTags, /*out*/const uint32_t** tags);
+ const ACameraMetadata* metadata, uint32_t tag, /*out*/ACameraMetadata_const_entry* entry);
/**
- * Copy a metadata. Duplicates a metadata structure.
- * The destination ACameraMetadata must be freed by the application with ACameraMetadata_free
- * after application is done using it.
- * Returns NULL when src cannot be copied
+ * List all the entry tags in input {@link ACameraMetadata}.
+ *
+ * @param metadata the {@link ACameraMetadata} of interest.
+ * @param numEntries number of metadata entries in input {@link ACameraMetadata}
+ * @param tags the tag values of the metadata entries. Length of tags is returned in numEntries
+ * argument. The memory is managed by ACameraMetadata itself and must NOT be free/delete
+ * by application. Do NOT access tags after calling ACameraMetadata_free.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata, numEntries or tags is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ */
+camera_status_t ACameraMetadata_getAllTags(
+ const ACameraMetadata* metadata, /*out*/int32_t* numEntries, /*out*/const uint32_t** tags);
+
+/**
+ * Create a copy of input {@link ACameraMetadata}.
+ *
+ * <p>The returned ACameraMetadata must be freed by the application by {@link ACameraMetadata_free}
+ * after application is done using it.</p>
+ *
+ * @param src the input {@link ACameraMetadata} to be copied.
+ *
+ * @return a valid ACameraMetadata pointer or NULL if the input metadata cannot be copied.
*/
ACameraMetadata* ACameraMetadata_copy(const ACameraMetadata* src);
/**
- * Frees a metadata structure.
+ * Free a {@link ACameraMetadata} structure.
+ *
+ * @param metadata the {@link ACameraMetadata} to be freed.
*/
-void ACameraMetadata_free(ACameraMetadata*);
+void ACameraMetadata_free(ACameraMetadata* metadata);
#ifdef __cplusplus
} // extern "C"
diff --git a/include/camera/ndk/NdkCaptureRequest.h b/include/camera/ndk/NdkCaptureRequest.h
index e278196..cd97f4d 100644
--- a/include/camera/ndk/NdkCaptureRequest.h
+++ b/include/camera/ndk/NdkCaptureRequest.h
@@ -49,54 +49,255 @@
// Container for a single output target
typedef struct ACameraOutputTarget ACameraOutputTarget;
+/**
+ * ACaptureRequest is an opaque type that contains settings and output targets needed to capture
+ * a single image from camera device.
+ *
+ * <p>ACaptureRequest contains the configuration for the capture hardware (sensor, lens, flash),
+ * the processing pipeline, the control algorithms, and the output buffers. Also
+ * contains the list of target {@link ANativeWindow}s to send image data to for this
+ * capture.</p>
+ *
+ * <p>ACaptureRequest is created by {@link ACameraDevice_createCaptureRequest}.
+ *
+ * <p>ACaptureRequest is given to {@link ACameraCaptureSession_capture} or
+ * {@link ACameraCaptureSession_setRepeatingRequest} to capture images from a camera.</p>
+ *
+ * <p>Each request can specify a different subset of target {@link ANativeWindow}s for the
+ * camera to send the captured data to. All the {@link ANativeWindow}s used in a request must
+ * be part of the {@link ANativeWindow} list given to the last call to
+ * {@link ACameraDevice_createCaptureSession}, when the request is submitted to the
+ * session.</p>
+ *
+ * <p>For example, a request meant for repeating preview might only include the
+ * {@link ANativeWindow} for the preview SurfaceView or SurfaceTexture, while a
+ * high-resolution still capture would also include a {@link ANativeWindow} from a
+ * {@link AImageReader} configured for high-resolution JPEG images.</p>
+ *
+ * @see ACameraDevice_createCaptureRequest
+ * @see ACameraCaptureSession_capture
+ * @see ACameraCaptureSession_setRepeatingRequest
+ */
typedef struct ACaptureRequest ACaptureRequest;
-camera_status_t ACameraOutputTarget_create(ANativeWindow* window, ACameraOutputTarget** out);
-void ACameraOutputTarget_free(ACameraOutputTarget*);
+/**
+ * Create a ACameraOutputTarget object.
+ *
+ * <p>The ACameraOutputTarget is used in {@link ACaptureRequest_addTarget} method to add an output
+ * {@link ANativeWindow} to ACaptureRequest. Use {@link ACameraOutputTarget_free} to free the object
+ * and its memory after application no longer needs the {@link ACameraOutputTarget}.</p>
+ *
+ * @param window the {@link ANativeWindow} to be associated with the {@link ACameraOutputTarget}
+ * @param output the output {@link ACameraOutputTarget} will be stored here if the
+ * method call succeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds. The created ACameraOutputTarget will
+ * be filled in the output argument.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if window or output is NULL.</li></ul>
+ *
+ * @see ACaptureRequest_addTarget
+ */
+camera_status_t ACameraOutputTarget_create(ANativeWindow* window, ACameraOutputTarget** output);
-camera_status_t ACaptureRequest_addTarget(ACaptureRequest*, const ACameraOutputTarget*);
-camera_status_t ACaptureRequest_removeTarget(ACaptureRequest*, const ACameraOutputTarget*);
-//TODO: do we need API to query added targets?
+/**
+ * Free a ACameraOutputTarget object.
+ *
+ * @param output the {@link ACameraOutputTarget} to be freed.
+ *
+ * @see ACameraOutputTarget_create
+ */
+void ACameraOutputTarget_free(ACameraOutputTarget* output);
-/*
- * Get a metadata entry
+/**
+ * Add an {@link ACameraOutputTarget} object to {@link ACaptureRequest}.
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param output the output {@link ACameraOutputTarget} to be added to capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or output is NULL.</li></ul>
+ */
+camera_status_t ACaptureRequest_addTarget(ACaptureRequest* request,
+ const ACameraOutputTarget* output);
+
+/**
+ * Remove an {@link ACameraOutputTarget} object from {@link ACaptureRequest}.
+ *
+ * <p>This method has no effect if the ACameraOutputTarget does not exist in ACaptureRequest.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param output the output {@link ACameraOutputTarget} to be removed from capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request or output is NULL.</li></ul>
+ */
+camera_status_t ACaptureRequest_removeTarget(ACaptureRequest* request,
+ const ACameraOutputTarget* output);
+
+/**
+ * Get a metadata entry from input {@link ACaptureRequest}.
+ *
+ * <p>The memory of the data field in returned entry is managed by camera framework. Do not
+ * attempt to free it.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be get.
+ * @param entry the output {@link ACameraMetadata_const_entry} will be filled here if the method
+ * call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if metadata or entry is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_METADATA_NOT_FOUND} if the capture request does not contain an
+ * entry of input tag value.</li></ul>
*/
camera_status_t ACaptureRequest_getConstEntry(
- const ACaptureRequest*, uint32_t tag, ACameraMetadata_const_entry* entry);
+ const ACaptureRequest* request, uint32_t tag, ACameraMetadata_const_entry* entry);
/*
- * List all the entry tags in this capture request.
- * The memory of tags is managed by ACaptureRequest itself and must NOT be free/delete
- * by application. Calling ACaptureRequest_setEntry_* API will invalidate previous
- * output of ACaptureRequest_getAllTags. Do not access tags after calling
- * ACaptureRequest_setEntry_*. To get new list of tags after updating capture request,
- * application must call ACaptureRequest_getAllTags again.
- * Do NOT access tags after calling ACaptureRequest_free.
+ * List all the entry tags in input {@link ACaptureRequest}.
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param numEntries number of metadata entries in input {@link ACaptureRequest}
+ * @param tags the tag values of the metadata entries. Length of tags is returned in numEntries
+ * argument. The memory is managed by ACaptureRequest itself and must NOT be free/delete
+ * by application. Calling ACaptureRequest_setEntry_* methods will invalidate previous
+ * output of ACaptureRequest_getAllTags. Do not access tags after calling
+ * ACaptureRequest_setEntry_*. To get new list of tags after updating capture request,
+ * application must call ACaptureRequest_getAllTags again. Do NOT access tags after
+ * calling ACaptureRequest_free.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request, numEntries or tags is NULL.</li>
+ * <li>{@link ACAMERA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
*/
camera_status_t ACaptureRequest_getAllTags(
- const ACaptureRequest*, /*out*/int32_t* numTags, /*out*/const uint32_t** tags);
+ const ACaptureRequest* request, /*out*/int32_t* numTags, /*out*/const uint32_t** tags);
-/*
- * Set an entry of corresponding type.
- * The entry tag's type must match corresponding set API or an
- * ACAMERA_ERROR_INVALID_PARAMETER error will occur.
- * Also, the input ACameraMetadata* must belong to a capture request or an
- * ACAMERA_ERROR_INVALID_PARAMETER error will occur.
+/**
+ * Set/change a camera capture control entry with unsigned 8 bits data type.
+ *
+ * <p>Set count to 0 and data to NULL to remove a tag from the capture request.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be set.
+ * @param count number of elements to be set in data argument
+ * @param data the entries to be set/change in the capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL, count is larger than
+ * zero while data is NULL, the data type of the tag is not unsigned 8 bits, or
+ * the tag is not controllable by application.</li></ul>
*/
camera_status_t ACaptureRequest_setEntry_u8(
- ACaptureRequest*, uint32_t tag, uint32_t count, const uint8_t* data);
-camera_status_t ACaptureRequest_setEntry_i32(
- ACaptureRequest*, uint32_t tag, uint32_t count, const int32_t* data);
-camera_status_t ACaptureRequest_setEntry_float(
- ACaptureRequest*, uint32_t tag, uint32_t count, const float* data);
-camera_status_t ACaptureRequest_setEntry_i64(
- ACaptureRequest*, uint32_t tag, uint32_t count, const int64_t* data);
-camera_status_t ACaptureRequest_setEntry_double(
- ACaptureRequest*, uint32_t tag, uint32_t count, const double* data);
-camera_status_t ACaptureRequest_setEntry_rational(
- ACaptureRequest*, uint32_t tag, uint32_t count, const ACameraMetadata_rational* data);
+ ACaptureRequest* request, uint32_t tag, uint32_t count, const uint8_t* data);
-// free the capture request created by ACameraDevice_createCaptureRequest
+/**
+ * Set/change a camera capture control entry with signed 32 bits data type.
+ *
+ * <p>Set count to 0 and data to NULL to remove a tag from the capture request.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be set.
+ * @param count number of elements to be set in data argument
+ * @param data the entries to be set/change in the capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL, count is larger than
+ * zero while data is NULL, the data type of the tag is not signed 32 bits, or
+ * the tag is not controllable by application.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_i32(
+ ACaptureRequest* request, uint32_t tag, uint32_t count, const int32_t* data);
+
+/**
+ * Set/change a camera capture control entry with float data type.
+ *
+ * <p>Set count to 0 and data to NULL to remove a tag from the capture request.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be set.
+ * @param count number of elements to be set in data argument
+ * @param data the entries to be set/change in the capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL, count is larger than
+ * zero while data is NULL, the data type of the tag is not float, or
+ * the tag is not controllable by application.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_float(
+ ACaptureRequest* request, uint32_t tag, uint32_t count, const float* data);
+
+/**
+ * Set/change a camera capture control entry with signed 64 bits data type.
+ *
+ * <p>Set count to 0 and data to NULL to remove a tag from the capture request.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be set.
+ * @param count number of elements to be set in data argument
+ * @param data the entries to be set/change in the capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL, count is larger than
+ * zero while data is NULL, the data type of the tag is not signed 64 bits, or
+ * the tag is not controllable by application.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_i64(
+ ACaptureRequest* request, uint32_t tag, uint32_t count, const int64_t* data);
+
+/**
+ * Set/change a camera capture control entry with double data type.
+ *
+ * <p>Set count to 0 and data to NULL to remove a tag from the capture request.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be set.
+ * @param count number of elements to be set in data argument
+ * @param data the entries to be set/change in the capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL, count is larger than
+ * zero while data is NULL, the data type of the tag is not double, or
+ * the tag is not controllable by application.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_double(
+ ACaptureRequest* request, uint32_t tag, uint32_t count, const double* data);
+
+/**
+ * Set/change a camera capture control entry with rational data type.
+ *
+ * <p>Set count to 0 and data to NULL to remove a tag from the capture request.</p>
+ *
+ * @param request the {@link ACaptureRequest} of interest.
+ * @param tag the tag value of the camera metadata entry to be set.
+ * @param count number of elements to be set in data argument
+ * @param data the entries to be set/change in the capture request.
+ *
+ * @return <ul>
+ * <li>{@link ACAMERA_OK} if the method call succeeds.</li>
+ * <li>{@link ACAMERA_ERROR_INVALID_PARAMETER} if request is NULL, count is larger than
+ * zero while data is NULL, the data type of the tag is not rational, or
+ * the tag is not controllable by application.</li></ul>
+ */
+camera_status_t ACaptureRequest_setEntry_rational(
+ ACaptureRequest* request, uint32_t tag, uint32_t count,
+ const ACameraMetadata_rational* data);
+
+/**
+ * Free a {@link ACaptureRequest} structure.
+ *
+ * @param request the {@link ACaptureRequest} to be freed.
+ */
void ACaptureRequest_free(ACaptureRequest* request);
#ifdef __cplusplus
diff --git a/include/ndk/NdkImage.h b/include/ndk/NdkImage.h
index eab7ead..cd0b11e 100644
--- a/include/ndk/NdkImage.h
+++ b/include/ndk/NdkImage.h
@@ -42,21 +42,371 @@
extern "C" {
#endif
+/**
+ * AImage is an opaque type that provides access to image generated by {@link AImageReader}.
+ */
typedef struct AImage AImage;
// Formats not listed here will not be supported by AImageReader
-enum {
+enum AIMAGE_FORMATS {
+ /**
+ * Multi-plane Android YUV 420 format.
+ *
+ * <p>This format is a generic YCbCr format, capable of describing any 4:2:0
+ * chroma-subsampled planar or semiplanar buffer (but not fully interleaved),
+ * 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>The order of planes is guaranteed such that plane #0 is always Y, plane #1 is always
+ * U (Cb), and plane #2 is always V (Cr).</p>
+ *
+ * <p>The Y-plane is guaranteed not to be interleaved with the U/V planes
+ * (in particular, pixel stride is always 1 in {@link AImage_getPlanePixelStride}).</p>
+ *
+ * <p>The U/V planes are guaranteed to have the same row stride and pixel stride, that is, the
+ * return value of {@link AImage_getPlaneRowStride} for the U/V plane are guaranteed to be the
+ * same, and the return value of {@link AImage_getPlanePixelStride} for the U/V plane are also
+ * guaranteed to be the same.</p>
+ *
+ * <p>For example, the {@link AImage} object can provide data
+ * in this format from a {@link ACameraDevice} through an {@link AImageReader} object.</p>
+ *
+ * <p>This format is always supported as an output format for the android Camera2 NDK API.</p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see ACameraDevice
+ */
AIMAGE_FORMAT_YUV_420_888 = 0x23,
+
+ /**
+ * Compressed JPEG format.
+ *
+ * <p>This format is always supported as an output format for the android Camera2 NDK API.</p>
+ */
AIMAGE_FORMAT_JPEG = 0x100,
+
+ /**
+ * 16 bits per pixel raw camera sensor image format, usually representing a single-channel
+ * Bayer-mosaic image.
+ *
+ * <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 ACameraDevice} which produced the image.</p>
+ */
AIMAGE_FORMAT_RAW16 = 0x20,
+
+ /**
+ * Private raw camera sensor image format, a single channel image with implementation depedent
+ * pixel layout.
+ *
+ * <p>AIMAGE_FORMAT_RAW_PRIVATE is a format for unprocessed raw image buffers coming from an
+ * image sensor. The actual structure of buffers of this format is implementation-dependent.</p>
+ *
+ */
AIMAGE_FORMAT_RAW_PRIVATE = 0x24,
+
+ /**
+ * Android 10-bit raw format.
+ *
+ * <p>
+ * This is a single-plane, 10-bit per pixel, densely packed (in each row),
+ * unprocessed format, usually representing raw Bayer-pattern images coming
+ * from an image sensor.
+ * </p>
+ * <p>
+ * In an image buffer with this format, starting from the first pixel of
+ * each row, each 4 consecutive pixels are packed into 5 bytes (40 bits).
+ * Each one of the first 4 bytes contains the top 8 bits of each pixel, The
+ * fifth byte contains the 2 least significant bits of the 4 pixels, the
+ * exact layout data for each 4 consecutive pixels is illustrated below
+ * (Pi[j] stands for the jth bit of the ith pixel):
+ * </p>
+ * <table>
+ * <tr>
+ * <th align="center"></th>
+ * <th align="center">bit 7</th>
+ * <th align="center">bit 6</th>
+ * <th align="center">bit 5</th>
+ * <th align="center">bit 4</th>
+ * <th align="center">bit 3</th>
+ * <th align="center">bit 2</th>
+ * <th align="center">bit 1</th>
+ * <th align="center">bit 0</th>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 0:</td>
+ * <td align="center">P0[9]</td>
+ * <td align="center">P0[8]</td>
+ * <td align="center">P0[7]</td>
+ * <td align="center">P0[6]</td>
+ * <td align="center">P0[5]</td>
+ * <td align="center">P0[4]</td>
+ * <td align="center">P0[3]</td>
+ * <td align="center">P0[2]</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 1:</td>
+ * <td align="center">P1[9]</td>
+ * <td align="center">P1[8]</td>
+ * <td align="center">P1[7]</td>
+ * <td align="center">P1[6]</td>
+ * <td align="center">P1[5]</td>
+ * <td align="center">P1[4]</td>
+ * <td align="center">P1[3]</td>
+ * <td align="center">P1[2]</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 2:</td>
+ * <td align="center">P2[9]</td>
+ * <td align="center">P2[8]</td>
+ * <td align="center">P2[7]</td>
+ * <td align="center">P2[6]</td>
+ * <td align="center">P2[5]</td>
+ * <td align="center">P2[4]</td>
+ * <td align="center">P2[3]</td>
+ * <td align="center">P2[2]</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 3:</td>
+ * <td align="center">P3[9]</td>
+ * <td align="center">P3[8]</td>
+ * <td align="center">P3[7]</td>
+ * <td align="center">P3[6]</td>
+ * <td align="center">P3[5]</td>
+ * <td align="center">P3[4]</td>
+ * <td align="center">P3[3]</td>
+ * <td align="center">P3[2]</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 4:</td>
+ * <td align="center">P3[1]</td>
+ * <td align="center">P3[0]</td>
+ * <td align="center">P2[1]</td>
+ * <td align="center">P2[0]</td>
+ * <td align="center">P1[1]</td>
+ * <td align="center">P1[0]</td>
+ * <td align="center">P0[1]</td>
+ * <td align="center">P0[0]</td>
+ * </tr>
+ * </table>
+ * <p>
+ * This format assumes
+ * <ul>
+ * <li>a width multiple of 4 pixels</li>
+ * <li>an even height</li>
+ * </ul>
+ * </p>
+ *
+ * <pre>size = row stride * height</pre> where the row stride is in <em>bytes</em>,
+ * not pixels.
+ *
+ * <p>
+ * Since this is a densely packed format, the pixel stride is always 0. The
+ * application must use the pixel data layout defined in above table to
+ * access each row data. When row stride is equal to (width * (10 / 8)), there
+ * will be no padding bytes at the end of each row, the entire image data is
+ * densely packed. When stride is larger than (width * (10 / 8)), padding
+ * bytes will be present at the end of each row.
+ * </p>
+ * <p>
+ * For example, the {@link AImage} object can provide data in this format from a
+ * {@link ACameraDevice} (if supported) through a {@link AImageReader} object.
+ * The number of planes returned by {@link AImage_getNumberOfPlanes} will always be 1.
+ * The pixel stride is undefined ({@link AImage_getPlanePixelStride} will return
+ * {@link AMEDIA_ERROR_UNSUPPORTED}), and the {@link AImage_getPlaneRowStride} described the
+ * vertical neighboring pixel distance (in bytes) between adjacent rows.
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see ACameraDevice
+ */
AIMAGE_FORMAT_RAW10 = 0x25,
+
+ /**
+ * Android 12-bit raw format.
+ *
+ * <p>
+ * This is a single-plane, 12-bit per pixel, densely packed (in each row),
+ * unprocessed format, usually representing raw Bayer-pattern images coming
+ * from an image sensor.
+ * </p>
+ * <p>
+ * In an image buffer with this format, starting from the first pixel of each
+ * row, each two consecutive pixels are packed into 3 bytes (24 bits). The first
+ * and second byte contains the top 8 bits of first and second pixel. The third
+ * byte contains the 4 least significant bits of the two pixels, the exact layout
+ * data for each two consecutive pixels is illustrated below (Pi[j] stands for
+ * the jth bit of the ith pixel):
+ * </p>
+ * <table>
+ * <tr>
+ * <th align="center"></th>
+ * <th align="center">bit 7</th>
+ * <th align="center">bit 6</th>
+ * <th align="center">bit 5</th>
+ * <th align="center">bit 4</th>
+ * <th align="center">bit 3</th>
+ * <th align="center">bit 2</th>
+ * <th align="center">bit 1</th>
+ * <th align="center">bit 0</th>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 0:</td>
+ * <td align="center">P0[11]</td>
+ * <td align="center">P0[10]</td>
+ * <td align="center">P0[ 9]</td>
+ * <td align="center">P0[ 8]</td>
+ * <td align="center">P0[ 7]</td>
+ * <td align="center">P0[ 6]</td>
+ * <td align="center">P0[ 5]</td>
+ * <td align="center">P0[ 4]</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 1:</td>
+ * <td align="center">P1[11]</td>
+ * <td align="center">P1[10]</td>
+ * <td align="center">P1[ 9]</td>
+ * <td align="center">P1[ 8]</td>
+ * <td align="center">P1[ 7]</td>
+ * <td align="center">P1[ 6]</td>
+ * <td align="center">P1[ 5]</td>
+ * <td align="center">P1[ 4]</td>
+ * </tr>
+ * <tr>
+ * <td align="center">Byte 2:</td>
+ * <td align="center">P1[ 3]</td>
+ * <td align="center">P1[ 2]</td>
+ * <td align="center">P1[ 1]</td>
+ * <td align="center">P1[ 0]</td>
+ * <td align="center">P0[ 3]</td>
+ * <td align="center">P0[ 2]</td>
+ * <td align="center">P0[ 1]</td>
+ * <td align="center">P0[ 0]</td>
+ * </tr>
+ * </table>
+ * <p>
+ * This format assumes
+ * <ul>
+ * <li>a width multiple of 4 pixels</li>
+ * <li>an even height</li>
+ * </ul>
+ * </p>
+ *
+ * <pre>size = row stride * height</pre> where the row stride is in <em>bytes</em>,
+ * not pixels.
+ *
+ * <p>
+ * Since this is a densely packed format, the pixel stride is always 0. The
+ * application must use the pixel data layout defined in above table to
+ * access each row data. When row stride is equal to (width * (12 / 8)), there
+ * will be no padding bytes at the end of each row, the entire image data is
+ * densely packed. When stride is larger than (width * (12 / 8)), padding
+ * bytes will be present at the end of each row.
+ * </p>
+ * <p>
+ * For example, the {@link AImage} object can provide data in this format from a
+ * {@link ACameraDevice} (if supported) through a {@link AImageReader} object.
+ * The number of planes returned by {@link AImage_getNumberOfPlanes} will always be 1.
+ * The pixel stride is undefined ({@link AImage_getPlanePixelStride} will return
+ * {@link AMEDIA_ERROR_UNSUPPORTED}), and the {@link AImage_getPlaneRowStride} described the
+ * vertical neighboring pixel distance (in bytes) between adjacent rows.
+ * </p>
+ *
+ * @see AImage
+ * @see AImageReader
+ * @see ACameraDevice
+ */
AIMAGE_FORMAT_RAW12 = 0x26,
+
+ /**
+ * Android dense depth image format.
+ *
+ * <p>Each pixel is 16 bits, representing a depth ranging measurement from a depth camera or
+ * similar sensor. The 16-bit sample consists of a confidence value and the actual ranging
+ * measurement.</p>
+ *
+ * <p>The confidence value is an estimate of correctness for this sample. It is encoded in the
+ * 3 most significant bits of the sample, with a value of 0 representing 100% confidence, a
+ * value of 1 representing 0% confidence, a value of 2 representing 1/7, a value of 3
+ * representing 2/7, and so on.</p>
+ *
+ * <p>As an example, the following sample extracts the range and confidence from the first pixel
+ * of a DEPTH16-format {@link AImage}, and converts the confidence to a floating-point value
+ * between 0 and 1.f inclusive, with 1.f representing maximum confidence:
+ *
+ * <pre>
+ * uint16_t* data;
+ * int dataLength;
+ * AImage_getPlaneData(image, 0, (uint8_t**)&data, &dataLength);
+ * uint16_t depthSample = data[0];
+ * uint16_t depthRange = (depthSample & 0x1FFF);
+ * uint16_t depthConfidence = ((depthSample >> 13) & 0x7);
+ * float depthPercentage = depthConfidence == 0 ? 1.f : (depthConfidence - 1) / 7.f;
+ * </pre>
+ * </p>
+ *
+ * <p>This format assumes
+ * <ul>
+ * <li>an even width</li>
+ * <li>an even height</li>
+ * <li>a horizontal stride multiple of 16 pixels</li>
+ * </ul>
+ * </p>
+ *
+ * <pre> y_size = stride * height </pre>
+ *
+ * When produced by a camera, the units for the range are millimeters.
+ */
AIMAGE_FORMAT_DEPTH16 = 0x44363159,
+
+ /**
+ * Android sparse depth point cloud format.
+ *
+ * <p>A variable-length list of 3D points plus a confidence value, with each point represented
+ * by four floats; first the X, Y, Z position coordinates, and then the confidence value.</p>
+ *
+ * <p>The number of points is ((size of the buffer in bytes) / 16).
+ *
+ * <p>The coordinate system and units of the position values depend on the source of the point
+ * cloud data. The confidence value is between 0.f and 1.f, inclusive, with 0 representing 0%
+ * confidence and 1.f representing 100% confidence in the measured position values.</p>
+ *
+ * <p>As an example, the following code extracts the first depth point in a DEPTH_POINT_CLOUD
+ * format {@link AImage}:
+ * <pre>
+ * float* data;
+ * int dataLength;
+ * AImage_getPlaneData(image, 0, (uint8_t**)&data, &dataLength);
+ * float x = data[0];
+ * float y = data[1];
+ * float z = data[2];
+ * float confidence = data[3];
+ * </pre>
+ *
+ */
AIMAGE_FORMAT_DEPTH_POINT_CLOUD = 0x101,
- AIMAGE_FORMAT_PRIVATE = 0x22 ///> Not supported by AImageReader yet
+
+ /**
+ * Android private opaque image format.
+ *
+ * <p>This format is not currently supported by {@link AImageReader}.</p>
+ */
+ AIMAGE_FORMAT_PRIVATE = 0x22
};
+/**
+ * Data type describing an cropped rectangle returned by {@link AImage_getCropRect}.
+ *
+ * <p>Note that the right and bottom coordinates are exclusive, so the width of the rectangle is
+ * (right - left) and the height of the rectangle is (bottom - top).</p>
+ */
typedef struct AImageCropRect {
int32_t left;
int32_t top;
@@ -64,40 +414,192 @@
int32_t bottom;
} AImageCropRect;
-// Return the image back to system and delete the AImage from memory
-// Do NOT use `image` after this call
+/**
+ * Return the image back the the system and delete the AImage object from memory.
+ *
+ * <p>Do NOT use the image pointer after this method returns.
+ * Note that if the parent {@link AImageReader} is closed, all the {@link AImage} objects acquired
+ * from the parent reader will be returned to system. All AImage_* methods except this method will
+ * return {@link AMEDIA_ERROR_INVALID_OBJECT}. Application still needs to call this method on those
+ * {@link AImage} objects to fully delete the {@link AImage} object from memory.</p>
+ *
+ * @param image The {@link AImage} to be deleted.
+ */
void AImage_delete(AImage* image);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the width of the input {@link AImage}.
+ *
+ * @param image the {@link AImage} of interest.
+ * @param width the width of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or width is NULL.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getWidth(const AImage* image, /*out*/int32_t* width);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the height of the input {@link AImage}.
+ *
+ * @param image the {@link AImage} of interest.
+ * @param height the height of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or height is NULL.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getHeight(const AImage* image, /*out*/int32_t* height);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the format of the input {@link AImage}.
+ *
+ * <p>The format value will be one of AIMAGE_FORMAT_* enum value.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param format the format of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or format is NULL.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getFormat(const AImage* image, /*out*/int32_t* format);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the cropped rectangle of the input {@link AImage}.
+ *
+ * <p>The crop rectangle specifies the region of valid pixels in the image, using coordinates in the
+ * largest-resolution plane.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param rect the cropped rectangle of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or rect is NULL.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getCropRect(const AImage* image, /*out*/AImageCropRect* rect);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the timestamp of the input {@link AImage}.
+ *
+ * <p>
+ * The timestamp is measured in nanoseconds, and is normally monotonically increasing. The
+ * timestamps for the images from different sources may have different timebases therefore may not
+ * be comparable. The specific meaning and timebase of the timestamp depend on the source providing
+ * images. For images generated by camera, the timestamp value will match
+ * {@link ACAMERA_SENSOR_TIMESTAMP} of the {@link ACameraMetadata} in
+ * {@link ACameraCaptureSession_captureCallbacks#onCaptureStarted} and
+ * {@link ACameraCaptureSession_captureCallbacks#onCaptureCompleted} callback.
+ * </p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param timestampNs the timestamp of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or timestampNs is NULL.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getTimestamp(const AImage* image, /*out*/int64_t* timestampNs);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the number of planes of the input {@link AImage}.
+ *
+ * <p>The number of plane of an {@link AImage} is determined by its format, which can be queried by
+ * {@link AImage_getFormat} method.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param numPlanes the number of planes of the image will be filled here if the method call
+ * succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or numPlanes is NULL.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getNumberOfPlanes(const AImage* image, /*out*/int32_t* numPlanes);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the pixel stride of the input {@link AImage}.
+ *
+ * <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.
+ * Note that pixel stride is undefined for some formats such as {@link AIMAGE_FORMAT_RAW_PRIVATE},
+ * and calling this method on images of these formats will cause {@link AMEDIA_ERROR_UNSUPPORTED}
+ * being returned.
+ * For formats where pixel stride is well defined, the pixel stride is always greater than 0.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param planeIdx the index of the plane. Must be less than the number of planes of input image.
+ * @param pixelStride the pixel stride of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or pixelStride is NULL, or planeIdx
+ * is out of the range of [0, numOfPlanes - 1].</li>
+ * <li>{@link AMEDIA_ERROR_UNSUPPORTED} if pixel stride is undefined for the format of input
+ * image.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getPlanePixelStride(
const AImage* image, int planeIdx, /*out*/int32_t* pixelStride);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
+/**
+ * Query the row stride of the input {@link AImage}.
+ *
+ * <p>This is the distance between the start of two consecutive rows of pixels in the image. Note
+ * that row stried is undefined for some formats such as {@link AIMAGE_FORMAT_RAW_PRIVATE}, and
+ * calling this method on images of these formats will cause {@link AMEDIA_ERROR_UNSUPPORTED}
+ * being returned.
+ * For formats where row stride is well defined, the row stride is always greater than 0.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param planeIdx the index of the plane. Must be less than the number of planes of input image.
+ * @param rowStride the row stride of the image will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image or rowStride is NULL, or planeIdx
+ * is out of the range of [0, numOfPlanes - 1].</li>
+ * <li>{@link AMEDIA_ERROR_UNSUPPORTED} if row stride is undefined for the format of input
+ * image.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getPlaneRowStride(
const AImage* image, int planeIdx, /*out*/int32_t* rowStride);
-// AMEDIA_ERROR_INVALID_OBJECT will be returned if the parent AImageReader is deleted
-// Note that once the AImage or the parent AImageReader is deleted, the `*data` returned from
-// previous AImage_getPlaneData call becomes dangling pointer. Do NOT use it after
-// AImage or AImageReader is deleted
+/**
+ * Get the data pointer of the input image for direct application access.
+ *
+ * <p>Note that once the {@link AImage} or the parent {@link AImageReader} is deleted, the data
+ * pointer from previous AImage_getPlaneData call becomes invalid. Do NOT use it after the
+ * {@link AImage} or the parent {@link AImageReader} is deleted.</p>
+ *
+ * @param image the {@link AImage} of interest.
+ * @param planeIdx the index of the plane. Must be less than the number of planes of input image.
+ * @param data the data pointer of the image will be filled here if the method call succeeeds.
+ * @param dataLength the valid length of data will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if image, data or dataLength is NULL, or
+ * planeIdx is out of the range of [0, numOfPlanes - 1].</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_OBJECT} if the {@link AImageReader} generated this
+ * image has been deleted.</li></ul>
+ */
media_status_t AImage_getPlaneData(
const AImage* image, int planeIdx,
/*out*/uint8_t** data, /*out*/int* dataLength);
diff --git a/include/ndk/NdkImageReader.h b/include/ndk/NdkImageReader.h
index 9e7483d..7c7ec6a 100644
--- a/include/ndk/NdkImageReader.h
+++ b/include/ndk/NdkImageReader.h
@@ -44,38 +44,253 @@
extern "C" {
#endif
+/**
+ * AImage is an opaque type that allows direct application access to image data rendered into a
+ * {@link ANativeWindow}.
+ */
typedef struct AImageReader AImageReader;
+/**
+ * Create a new reader for images of the desired size and format.
+ *
+ * <p>
+ * The maxImages parameter determines the maximum number of {@link AImage} objects that can be
+ * acquired from the {@link AImageReader} 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 default width in pixels of the Images that this reader will produce.
+ * @param height The default 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
+ * AIMAGE_FORMAT_* enum value defined in {@link AIMAGE_FORMATS}. Note that not all
+ * formats are supported, like {@link AIMAGE_FORMAT_PRIVATE}.
+ * @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 {@link AImage} will become
+ * available for access through {@link AImageReader_acquireLatestImage} or
+ * {@link AImageReader_acquireNextImage}. Must be greater than 0.
+ * @param reader The created image reader will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader is NULL, or one or more of width,
+ * height, format, maxImages arguments is not supported.</li>
+ * <li>{@link AMEDIA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ *
+ * @see AImage
+ */
media_status_t AImageReader_new(
int32_t width, int32_t height, int32_t format, int32_t maxImages,
/*out*/AImageReader** reader);
-// Return all images acquired from this AImageReader back to system and delete
-// the AImageReader instance from memory
-// Do NOT use `reader` after this call
+/**
+ * Delete an {@link AImageReader} and return all images generated by this reader to system.
+ *
+ * <p>This method will return all {@link AImage} objects acquired by this reader (via
+ * {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}) to system,
+ * making any of data pointers obtained from {@link AImage_getPlaneData} invalid. Do NOT access
+ * the reader object or any of those data pointers after this method returns.</p>
+ *
+ * @param reader The image reader to be deleted.
+ */
void AImageReader_delete(AImageReader* reader);
-// Do NOT call ANativeWindow_release on the output. Just use AImageReader_delete.
-media_status_t AImageReader_getWindow(AImageReader*, /*out*/ANativeWindow** window);
+/**
+ * Get a {@link ANativeWindow} that can be used to produce {@link AImage} for this image reader.
+ *
+ * @param reader The image reader of interest.
+ * @param window The output {@link ANativeWindow} will be filled here if the method call succeeds.
+ * The {@link ANativeWindow} is managed by this image reader. Do NOT call
+ * {@link ANativeWindow_release} on it. Instead, use {@link AImageReader_delete}.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or window is NULL.</li></ul>
+ */
+media_status_t AImageReader_getWindow(AImageReader* reader, /*out*/ANativeWindow** window);
+/**
+ * Query the default width of the {@link AImage} generated by this reader, in pixels.
+ *
+ * <p>The width may be overridden by the producer sending buffers to this reader's
+ * {@link ANativeWindow}. If so, the actual width of the images can be found using
+ * {@link AImage_getWidth}.</p>
+ *
+ * @param reader The image reader of interest.
+ * @param width the default width of the reader will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or width is NULL.</li></ul>
+ */
media_status_t AImageReader_getWidth(const AImageReader* reader, /*out*/int32_t* width);
+
+/**
+ * Query the default height of the {@link AImage} generated by this reader, in pixels.
+ *
+ * <p>The height may be overridden by the producer sending buffers to this reader's
+ * {@link ANativeWindow}. If so, the actual height of the images can be found using
+ * {@link AImage_getHeight}.</p>
+ *
+ * @param reader The image reader of interest.
+ * @param height the default height of the reader will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or height is NULL.</li></ul>
+ */
media_status_t AImageReader_getHeight(const AImageReader* reader, /*out*/int32_t* height);
+
+/**
+ * Query the format of the {@link AImage} generated by this reader.
+ *
+ * @param reader The image reader of interest.
+ * @param format the fromat of the reader will be filled here if the method call succeeeds. The
+ * value will be one of the AIMAGE_FORMAT_* enum value defiend in {@link NdkImage.h}.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or format is NULL.</li></ul>
+ */
media_status_t AImageReader_getFormat(const AImageReader* reader, /*out*/int32_t* format);
+
+/**
+ * Query the maximum number of concurrently acquired {@link AImage}s of this reader.
+ *
+ * @param reader The image reader of interest.
+ * @param maxImages the maximum number of concurrently acquired images of the reader will be filled
+ * here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or maxImages is NULL.</li></ul>
+ */
media_status_t AImageReader_getMaxImages(const AImageReader* reader, /*out*/int32_t* maxImages);
+/**
+ * Acquire the next {@link AImage} from the image reader's queue.
+ *
+ * <p>Warning: Consider using {@link AImageReader_acquireLatestImage} instead, as it will
+ * automatically release older images, and allow slower-running processing routines to catch
+ * up to the newest frame. Usage of {@link AImageReader_acquireNextImage} is recommended for
+ * batch/background processing. Incorrectly using this method can cause images to appear
+ * with an ever-increasing delay, followed by a complete stall where no new images seem to appear.
+ * </p>
+ *
+ * <p>
+ * This method will fail if {@link AImageReader_getMaxImages maxImages} have been acquired with
+ * {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}. In particular
+ * a sequence of {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}
+ * calls greater than {@link AImageReader_getMaxImages maxImages} without calling
+ * {@link AImage_delete} in-between will exhaust the underlying queue. At such a time,
+ * {@link AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED} will be returned until more images are released with
+ * {@link AImage_delete}.
+ * </p>
+ *
+ * @param reader The image reader of interest.
+ * @param image the acquired {@link AImage} will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or image is NULL.</li>
+ * <li>{@link AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED} if the number of concurrently acquired
+ * images has reached the limit.</li>
+ * <li>{@link AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE} if there is no buffers currently
+ * available in the reader queue.</li>
+ * <li>{@link AMEDIA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ *
+ * @see AImageReader_acquireLatestImage
+ */
media_status_t AImageReader_acquireNextImage(AImageReader* reader, /*out*/AImage** image);
+/**
+
+ * Acquire the latest {@link AImage} from the image reader's queue, dropping older images.
+ *
+ * <p>
+ * This operation will acquire all the images possible from the image reader, but
+ * {@link AImage_delete} all images that aren't the latest. This function is recommended to use over
+ * {@link AImageReader_acquireNextImage} for most use-cases, as it's more suited for real-time
+ * processing.
+ * </p>
+ * <p>
+ * Note that {@link AImageReader_getMaxImages maxImages} should be at least 2 for
+ * {@link AImageReader_acquireLatestImage} to be any different than
+ * {@link AImageReader_acquireNextImage} - discarding all-but-the-newest {@link AImage} requires
+ * temporarily acquiring two {@link AImage}s at once. Or more generally, calling
+ * {@link AImageReader_acquireLatestImage} with less than two images of margin, that is
+ * (maxImages - currentAcquiredImages < 2) will not discard as expected.
+ * </p>
+ * <p>
+ * This method will fail if {@link AImageReader_getMaxImages maxImages} have been acquired with
+ * {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}. In particular
+ * a sequence of {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}
+ * calls greater than {@link AImageReader_getMaxImages maxImages} without calling
+ * {@link AImage_delete} in-between will exhaust the underlying queue. At such a time,
+ * {@link AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED} will be returned until more images are released with
+ * {@link AImage_delete}.
+ * </p>
+ *
+ * @param reader The image reader of interest.
+ * @param image the acquired {@link AImage} will be filled here if the method call succeeeds.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader or image is NULL.</li>
+ * <li>{@link AMEDIA_IMGREADER_MAX_IMAGES_ACQUIRED} if the number of concurrently acquired
+ * images has reached the limit.</li>
+ * <li>{@link AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE} if there is no buffers currently
+ * available in the reader queue.</li>
+ * <li>{@link AMEDIA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
+ *
+ * @see AImageReader_acquireNextImage
+ */
media_status_t AImageReader_acquireLatestImage(AImageReader* reader, /*out*/AImage** image);
-// The callback happens on one dedicated thread per AImageReader instance
-// It's okay to use AImageReader_*/AImage_* APIs within the callback
+
+/**
+ * The definition of {@link AImageReader} new image available callback.
+ *
+ * @param context The optional application context provided by user in
+ * {@link AImageReader_setImageListener}.
+ * @param session The camera capture session whose state is changing.
+ */
typedef void (*AImageReader_ImageCallback)(void* context, AImageReader* reader);
typedef struct AImageReader_ImageListener {
- void* context; // optional application context.
+ /// optional application context.
+ void* context;
+
+ /**
+ * This callback is called when there is a new image available for in the image reader's queue.
+ *
+ * <p>The callback happens on one dedicated thread per {@link AImageReader} instance. It is okay
+ * to use AImageReader_* and AImage_* methods within the callback. Note that it is possible that
+ * calling {@link AImageReader_acquireNextImage} or {@link AImageReader_acquireLatestImage}
+ * returns {@link AMEDIA_IMGREADER_NO_BUFFER_AVAILABLE} within this callback. For example, when
+ * there are multiple images and callbacks queued, if application called
+ * {@link AImageReader_acquireLatestImage}, some images will be returned to system before their
+ * corresponding callback is executed.</p>
+ */
AImageReader_ImageCallback onImageAvailable;
} AImageReader_ImageListener;
+/**
+ * Set the onImageAvailable listener of this image reader.
+ *
+ * <p>Note that calling this method will replace previously registered listeners.</p>
+ *
+ * @param reader The image reader of interest.
+ * @param listener the {@link AImageReader_ImageListener} to be registered. Set this to NULL if
+ * application no longer needs to listen to new images.
+ *
+ * @return <ul>
+ * <li>{@link AMEDIA_OK} if the method call succeeds.</li>
+ * <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader is NULL.</li></ul>
+ */
media_status_t AImageReader_setImageListener(
AImageReader* reader, AImageReader_ImageListener* listener);
diff --git a/media/ndk/NdkImageReader.cpp b/media/ndk/NdkImageReader.cpp
index 387a302..30aa7fb 100644
--- a/media/ndk/NdkImageReader.cpp
+++ b/media/ndk/NdkImageReader.cpp
@@ -95,10 +95,11 @@
AImageReader::FrameListener::setImageListener(AImageReader_ImageListener* listener) {
Mutex::Autolock _l(mLock);
if (listener == nullptr) {
- ALOGE("AImageReader: listener is null!");
- return AMEDIA_ERROR_INVALID_PARAMETER;
+ mListener.context = nullptr;
+ mListener.onImageAvailable = nullptr;
+ } else {
+ mListener = *listener;
}
- mListener = *listener;
return AMEDIA_OK;
}
@@ -575,8 +576,8 @@
media_status_t AImageReader_setImageListener(
AImageReader* reader, AImageReader_ImageListener* listener) {
ALOGV("%s", __FUNCTION__);
- if (reader == nullptr || listener == nullptr) {
- ALOGE("%s: invalid argument! read %p listener %p", __FUNCTION__, reader, listener);
+ if (reader == nullptr) {
+ ALOGE("%s: invalid argument! reader %p", __FUNCTION__, reader);
return AMEDIA_ERROR_INVALID_PARAMETER;
}