Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3aac10af authored by Marius Renn's avatar Marius Renn Committed by android-build-merger
Browse files

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

am: f3703f9e

Change-Id: Icbbfd9a9690cacc74d9cd70302937532a143ccda
parents fb68f388 f3703f9e
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -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() {
+30 −18
Original line number Diff line number Diff line
@@ -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.
+23 −4
Original line number Diff line number Diff line
@@ -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));
@@ -822,6 +839,8 @@ static JNINativeMethod gImageMethods[] = {
    {"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) {