blob: 571410bf4d9546f82974b8a3d726a6343cd7929e [file] [log] [blame]
/*
* Copyright (C) 2016 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.
*/
/**
* @addtogroup Media
* @{
*/
/**
* @file NdkImageReader.h
*/
/*
* This file defines an NDK API.
* Do not remove methods.
* Do not change method signatures.
* Do not change the value of constants.
* Do not change the size of any of the classes defined in here.
* Do not reference types that are not part of the NDK.
* Do not #include files that aren't part of the NDK.
*/
#ifndef _NDK_IMAGE_READER_H
#define _NDK_IMAGE_READER_H
#include <sys/cdefs.h>
#include <android/native_window.h>
#include "NdkMediaError.h"
#include "NdkImage.h"
__BEGIN_DECLS
/**
* AImage is an opaque type that allows direct application access to image data rendered into a
* {@link ANativeWindow}.
*/
typedef struct AImageReader AImageReader;
#if __ANDROID_API__ >= 24
/**
* 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. One example is {@link AIMAGE_FORMAT_PRIVATE}, as it is not
* intended to be read by applications directly. That format is supported by
* {@link AImageReader_newWithUsage} introduced in API 26.
* @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);
/**
* 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);
/**
* 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);
/**
* Signature of the callback which is called when a new image is available from {@link AImageReader}.
*
* @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 {
/// Optional application context passed as the first parameter of the callback.
void* context;
/**
* This callback is called when there is a new image available 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.
*
* Calling this method will replace previously registered listeners.
*
* @param reader The image reader of interest.
* @param listener The {@link AImageReader_ImageListener} to be registered. Set this to NULL if
* the 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);
#endif /* __ANDROID_API__ >= 24 */
#if __ANDROID_API__ >= 26
/**
* AImageReader constructor similar to {@link AImageReader_new} that takes an additional parameter
* for the consumer usage. All other parameters and the return values are identical to those passed
* to {@link AImageReader_new}.
*
* <p>If the \c format is {@link AIMAGE_FORMAT_PRIVATE}, the created {@link AImageReader}
* will produce images whose contents are not directly accessible by the application. The application can
* still acquire images from this {@link AImageReader} and access {@link AHardwareBuffer} via
* {@link AImage_getHardwareBuffer()}. The {@link AHardwareBuffer} gained this way can then
* be passed back to hardware (such as GPU or hardware encoder if supported) for future processing.
* For example, you can obtain an {@link EGLClientBuffer} from the {@link AHardwareBuffer} by using
* {@link eglGetNativeClientBufferANDROID} extension and pass that {@link EGLClientBuffer} to {@link
* eglCreateImageKHR} to create an {@link EGLImage} resource type, which may then be bound to a
* texture via {@link glEGLImageTargetTexture2DOES} on supported devices. This can be useful for
* transporting textures that may be shared cross-process.</p>
* <p>In general, when software access to image data is not necessary, an {@link AImageReader}
* created with {@link AIMAGE_FORMAT_PRIVATE} format is more efficient, compared with {@link
* AImageReader}s using other format such as {@link AIMAGE_FORMAT_YUV_420_888}.</p>
*
* <p>Note that not all format and usage flag combination is supported by the {@link AImageReader},
* especially if \c format is {@link AIMAGE_FORMAT_PRIVATE}, \c usage must not include either
* {@link AHARDWAREBUFFER_USAGE_READ_RARELY} or {@link AHARDWAREBUFFER_USAGE_READ_OFTEN}</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}.
* @param usage specifies how the consumer will access the AImage, using combination of the
* AHARDWAREBUFFER_USAGE flags described in {@link hardware_buffer.h}.
* Passing {@link AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN} is equivalent to calling
* {@link AImageReader_new} with the same parameters.
*
* Note that not all format and usage flag combination is supported by the {@link AImageReader}.
* Below are the combinations supported by the {@link AImageReader}.
* <table>
* <tr>
* <th>Format</th>
* <th>Compatible usage flags</th>
* </tr>
* <tr>
* <td>non-{@link AIMAGE_FORMAT_PRIVATE PRIVATE} formats defined in {@link AImage.h}
* </td>
* <td>{@link AHARDWAREBUFFER_USAGE_CPU_READ_RARELY} or
* {@link AHARDWAREBUFFER_USAGE_CPU_READ_OFTEN}</td>
* </tr>
* <tr>
* <td>{@link AIMAGE_FORMAT_RGBA_8888}</td>
* <td>{@link AHARDWAREBUFFER_USAGE_VIDEO_ENCODE} or
* {@link AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE}, or combined</td>
* </tr>
* </table>
* @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, or usage arguments is not supported.</li>
* <li>{@link AMEDIA_ERROR_UNKNOWN} if the method fails for some other reasons.</li></ul>
*
* @see AImage
* @see AImageReader_new
* @see AHardwareBuffer
*/
media_status_t AImageReader_newWithUsage(
int32_t width, int32_t height, int32_t format, uint64_t usage, int32_t maxImages,
/*out*/ AImageReader** reader);
/**
* Acquire the next {@link AImage} from the image reader's queue asynchronously.
*
* <p>AImageReader acquire method similar to {@link AImageReader_acquireNextImage} that takes an
* additional parameter for the sync fence. All other parameters and the return values are
* identical to those passed to {@link AImageReader_acquireNextImage}.</p>
*
* @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the
* buffer is ready to consume. When synchronization fence is not needed, fence will be set
* to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall
* use syscalls such as \c poll(), \c epoll(), \c select() to wait for the
* fence fd to change status before attempting to access the {@link AImage} returned.
*
* @see sync.h
* @see sync_get_fence_info
*/
media_status_t AImageReader_acquireNextImageAsync(
AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd);
/**
* Acquire the latest {@link AImage} from the image reader's queue asynchronously, dropping older
* images.
*
* <p>AImageReader acquire method similar to {@link AImageReader_acquireLatestImage} that takes an
* additional parameter for the sync fence. All other parameters and the return values are
* identical to those passed to {@link AImageReader_acquireLatestImage}.</p>
*
* @param acquireFenceFd A sync fence fd defined in {@link sync.h}, which is used to signal when the
* buffer is ready to consume. When synchronization fence is not needed, fence will be set
* to -1 and the {@link AImage} returned is ready for use immediately. Otherwise, user shall
* use syscalls such as \c poll(), \c epoll(), \c select() to wait for the
* fence fd to change status before attempting to access the {@link AImage} returned.
*
* @see sync.h
* @see sync_get_fence_info
*/
media_status_t AImageReader_acquireLatestImageAsync(
AImageReader* reader, /*out*/AImage** image, /*out*/int* acquireFenceFd);
/**
* Signature of the callback which is called when {@link AImageReader} is about to remove a buffer.
*
* @param context The optional application context provided by user in
* {@link AImageReader_setBufferRemovedListener}.
* @param reader The {@link AImageReader} of interest.
* @param buffer The {@link AHardwareBuffer} that is being removed from this image reader.
*/
typedef void (*AImageReader_BufferRemovedCallback)(void* context,
AImageReader* reader,
AHardwareBuffer* buffer);
typedef struct AImageReader_BufferRemovedListener {
/// Optional application context passed as the first parameter of the callback.
void* context;
/**
* This callback is called when an old {@link AHardwareBuffer} is about to be removed from the
* image reader.
*
* <p>Note that registering this callback is optional unless the user holds on extra reference
* to {@link AHardwareBuffer} returned from {@link AImage_getHardwareBuffer} by calling {@link
* AHardwareBuffer_acquire} or creating external graphic objects, such as EglImage, from it.</p>
*
* <p>If the callback is registered, the {@link AImageReader} will hold on the last of its
* references to the {@link AHardwareBuffer} until this callback returns. User can use the
* callback to get notified that it becomes the last owner of the buffer. It is up to the user
* to decide to either 1) immediately release all of its references to the buffer; or 2) keep
* using the buffer and release it in future. Note that, if option 2 if used, user of this API
* is responsible to deallocate the buffer properly by calling {@link AHardwareBuffer_release}.
* </p>
*
* @see AHardwareBuffer_release
* @see AImage_getHardwareBuffer
*/
AImageReader_BufferRemovedCallback onBufferRemoved;
} AImageReader_BufferRemovedListener;
/**
* Set the onBufferRemoved 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_BufferRemovedListener} to be registered. Set this to
* NULL if application no longer needs to listen to buffer removed events.
*
* @return <ul>
* <li>{@link AMEDIA_OK} if the method call succeeds.</li>
* <li>{@link AMEDIA_ERROR_INVALID_PARAMETER} if reader is NULL.</li></ul>
*
* @see AImage_getHardwareBuffer
*/
media_status_t AImageReader_setBufferRemovedListener(
AImageReader* reader, AImageReader_BufferRemovedListener* listener);
#endif /* __ANDROID_API__ >= 26 */
__END_DECLS
#endif //_NDK_IMAGE_READER_H
/** @} */