Merge "Adds support for hardware buffers in ImageWriter Images." into pi-dev

This commit is contained in:
Marius Renn
2018-05-23 01:35:11 +00:00
committed by Android (Google) Code Review
3 changed files with 56 additions and 24 deletions

View File

@@ -207,8 +207,9 @@ public abstract class Image implements AutoCloseable {
* after {@link Image#close Image.close()} has been called.
* </p>
* @return the HardwareBuffer associated with this Image or null if this Image doesn't support
* this feature (e.g. {@link android.media.ImageWriter ImageWriter} or
* {@link android.media.MediaCodec MediaCodec} don't).
* this feature. (Unsupported use cases include Image instances obtained through
* {@link android.media.MediaCodec MediaCodec}, and on versions prior to Android P,
* {@link android.media.ImageWriter ImageWriter}).
*/
@Nullable
public HardwareBuffer getHardwareBuffer() {

View File

@@ -20,6 +20,7 @@ import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.camera2.utils.SurfaceUtils;
import android.hardware.HardwareBuffer;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -58,12 +59,17 @@ import java.util.concurrent.CopyOnWriteArrayList;
* </p>
* <p>
* If the application already has an Image from {@link ImageReader}, the
* application can directly queue this Image into ImageWriter (via
* {@link #queueInputImage}), potentially with zero buffer copies. For the
* {@link ImageFormat#PRIVATE PRIVATE} format Images produced by
* {@link ImageReader}, this is the only way to send Image data to ImageWriter,
* as the Image data aren't accessible by the application.
* application can directly queue this Image into the ImageWriter (via
* {@link #queueInputImage}), potentially with zero buffer copies. This
* even works if the image format of the ImageWriter is
* {@link ImageFormat#PRIVATE PRIVATE}, and prior to Android P is the only
* way to enqueue images into such an ImageWriter. Starting in Android P
* private images may also be accessed through their hardware buffers
* (when available) through the {@link Image#getHardwareBuffer()} method.
* Attempting to access the planes of a private image, will return an
* empty array.
* </p>
* <p>
* Once new input Images are queued into an ImageWriter, it's up to the
* downstream components (e.g. {@link ImageReader} or
* {@link android.hardware.camera2.CameraDevice}) to consume the Images. If the
@@ -257,29 +263,26 @@ public class ImageWriter implements AutoCloseable {
* <p>
* If the format of ImageWriter is {@link ImageFormat#PRIVATE PRIVATE} (
* {@link ImageWriter#getFormat()} == {@link ImageFormat#PRIVATE}), the
* image buffer is inaccessible to the application, and calling this method
* will result in an {@link IllegalStateException}. Instead, the application
* should acquire images from some other component (e.g. an
* image buffer is accessible to the application only through the hardware
* buffer obtained through {@link Image#getHardwareBuffer()}. (On Android
* versions prior to P, dequeueing private buffers will cause an
* {@link IllegalStateException} to be thrown). Alternatively,
* the application can acquire images from some other component (e.g. an
* {@link ImageReader}), and queue them directly to this ImageWriter via the
* {@link ImageWriter#queueInputImage queueInputImage()} method.
* </p>
*
* @return The next available input Image from this ImageWriter.
* @throws IllegalStateException if {@code maxImages} Images are currently
* dequeued, or the ImageWriter format is
* {@link ImageFormat#PRIVATE PRIVATE}, or the input
* {@link android.view.Surface Surface} has been abandoned by the
* consumer component that provided the {@link android.view.Surface Surface}.
* dequeued, or the input {@link android.view.Surface Surface}
* has been abandoned by the consumer component that provided
* the {@link android.view.Surface Surface}. Prior to Android
* P, throws if the ImageWriter format is
* {@link ImageFormat#PRIVATE PRIVATE}.
* @see #queueInputImage
* @see Image#close
*/
public Image dequeueInputImage() {
if (mWriterFormat == ImageFormat.PRIVATE) {
throw new IllegalStateException(
"PRIVATE format ImageWriter doesn't support this operation since the images are"
+ " inaccessible to the application!");
}
if (mDequeuedImages.size() >= mMaxImages) {
throw new IllegalStateException("Already dequeued max number of Images " + mMaxImages);
}
@@ -742,6 +745,13 @@ public class ImageWriter implements AutoCloseable {
mTimestamp = timestamp;
}
@Override
public HardwareBuffer getHardwareBuffer() {
throwISEIfImageIsInvalid();
return nativeGetHardwareBuffer();
}
@Override
public Plane[] getPlanes() {
throwISEIfImageIsInvalid();
@@ -863,6 +873,8 @@ public class ImageWriter implements AutoCloseable {
private synchronized native int nativeGetHeight();
private synchronized native int nativeGetFormat();
private synchronized native HardwareBuffer nativeGetHardwareBuffer();
}
// Native implemented ImageWriter methods.

View File

@@ -25,11 +25,14 @@
#include <gui/Surface.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <jni.h>
#include <nativehelper/JNIHelp.h>
#include <stdint.h>
#include <inttypes.h>
#include <android/hardware_buffer_jni.h>
#define IMAGE_BUFFER_JNI_ID "mNativeBuffer"
#define IMAGE_FORMAT_UNKNOWN 0 // This is the same value as ImageFormat#UNKNOWN.
@@ -701,6 +704,20 @@ static jint Image_getFormat(JNIEnv* env, jobject thiz) {
return static_cast<jint>(publicFmt);
}
static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {
GraphicBuffer* buffer;
Image_getNativeContext(env, thiz, &buffer, NULL);
if (buffer == NULL) {
jniThrowException(env, "java/lang/IllegalStateException",
"Image is not initialized");
return NULL;
}
AHardwareBuffer* b = AHardwareBuffer_from_GraphicBuffer(buffer);
// don't user the public AHardwareBuffer_toHardwareBuffer() because this would force us
// to link against libandroid.so
return android_hardware_HardwareBuffer_createFromAHardwareBuffer(env, b);
}
static void Image_setFenceFd(JNIEnv* env, jobject thiz, int fenceFd) {
ALOGV("%s:", __FUNCTION__);
env->SetIntField(thiz, gSurfaceImageClassInfo.mNativeFenceFd, reinterpret_cast<jint>(fenceFd));
@@ -818,10 +835,12 @@ static JNINativeMethod gImageWriterMethods[] = {
static JNINativeMethod gImageMethods[] = {
{"nativeCreatePlanes", "(II)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
(void*)Image_createSurfacePlanes },
{"nativeGetWidth", "()I", (void*)Image_getWidth },
{"nativeGetHeight", "()I", (void*)Image_getHeight },
{"nativeGetFormat", "()I", (void*)Image_getFormat },
(void*)Image_createSurfacePlanes },
{"nativeGetWidth", "()I", (void*)Image_getWidth },
{"nativeGetHeight", "()I", (void*)Image_getHeight },
{"nativeGetFormat", "()I", (void*)Image_getFormat },
{"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
(void*)Image_getHardwareBuffer },
};
int register_android_media_ImageWriter(JNIEnv *env) {