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

Commit fbd31095 authored by Sally Qi's avatar Sally Qi Committed by Android (Google) Code Review
Browse files

Merge "Fix ImageWriter builder pattern APIs"

parents eb59ea4c d26f4f0d
Loading
Loading
Loading
Loading
+68 −31
Original line number Diff line number Diff line
@@ -102,11 +102,10 @@ public class ImageWriter implements AutoCloseable {
    private int mWidth;
    private int mHeight;
    private final int mMaxImages;
    private @Usage long mUsage = HardwareBuffer.USAGE_CPU_WRITE_OFTEN;
    private long mUsage = HardwareBuffer.USAGE_CPU_WRITE_OFTEN;
    private @HardwareBuffer.Format int mHardwareBufferFormat;
    private @NamedDataSpace long mDataSpace;
    private boolean mUseLegacyImageFormat;
    private boolean mUseSurfaceImageFormatInfo;

    // Field below is used by native code, do not access or modify.
    private int mWriterFormat;
@@ -255,17 +254,21 @@ public class ImageWriter implements AutoCloseable {
                + ", maxImages: " + maxImages);
        }

        mUseSurfaceImageFormatInfo = useSurfaceImageFormatInfo;
        mUseLegacyImageFormat = useLegacyImageFormat;
        // Note that the underlying BufferQueue is working in synchronous mode
        // to avoid dropping any buffers.
        mNativeContext = nativeInit(new WeakReference<>(this), surface, maxImages, width, height,
            useSurfaceImageFormatInfo, hardwareBufferFormat, dataSpace, usage);

        // if useSurfaceImageFormatInfo is true, imageformat should be read from the surface.
        if (useSurfaceImageFormatInfo) {
            // nativeInit internally overrides UNKNOWN format. So does surface format query after
            // nativeInit and before getEstimatedNativeAllocBytes().
            imageFormat = SurfaceUtils.getSurfaceFormat(surface);
            mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
            mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
        }

        // Several public formats use the same native HAL_PIXEL_FORMAT_BLOB. The native
        // allocation estimation sequence depends on the public formats values. To avoid
        // possible errors, convert where necessary.
@@ -284,7 +287,6 @@ public class ImageWriter implements AutoCloseable {
                default:
                    imageFormat = ImageFormat.JPEG;
            }
            }
            mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
            mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);
        }
@@ -307,7 +309,6 @@ public class ImageWriter implements AutoCloseable {
    private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo,
            int imageFormat, int width, int height) {
        mMaxImages = maxImages;
        // update hal format and dataspace only if image format is overridden by producer.
        mHardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat);
        mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat);

@@ -566,6 +567,9 @@ public class ImageWriter implements AutoCloseable {
    /**
     * Get the ImageWriter usage flag.
     *
     * <p>It is not recommended to use this function if {@link Builder#setUsage} is not called.
     * Invalid usage value will be returned if so.</p>
     *
     * @return The ImageWriter usage flag.
     */
    public @Usage long getUsage() {
@@ -873,7 +877,7 @@ public class ImageWriter implements AutoCloseable {
        private int mHeight = -1;
        private int mMaxImages = 1;
        private int mImageFormat = ImageFormat.UNKNOWN;
        private @Usage long mUsage = HardwareBuffer.USAGE_CPU_WRITE_OFTEN;
        private long mUsage = -1;
        private @HardwareBuffer.Format int mHardwareBufferFormat = HardwareBuffer.RGBA_8888;
        private @NamedDataSpace long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
        private boolean mUseSurfaceImageFormatInfo = true;
@@ -885,10 +889,19 @@ public class ImageWriter implements AutoCloseable {
        /**
         * Constructs a new builder for {@link ImageWriter}.
         *
         * <p>Uses {@code surface} input parameter to retrieve image format, hal format
         * and hal dataspace value for default. </p>
         *
         * @param surface The destination Surface this writer produces Image data into.
         *
         * @throws IllegalArgumentException if the surface is already abandoned.
         */
        public Builder(@NonNull Surface surface) {
            mSurface = surface;
            // retrieve format from surface
            mImageFormat = SurfaceUtils.getSurfaceFormat(surface);
            mDataSpace = SurfaceUtils.getSurfaceDataspace(surface);
            mHardwareBufferFormat = PublicFormatUtils.getHalFormat(mImageFormat);
        }

        /**
@@ -926,6 +939,8 @@ public class ImageWriter implements AutoCloseable {
         * @param imageFormat The format of the {@link ImageWriter}. It can be any valid specified
         *                    by {@link ImageFormat} or {@link PixelFormat}.
         * @return the Builder instance with customized image format.
         *
         * @throws IllegalArgumentException if {@code imageFormat} is invalid.
         */
        @SuppressLint("MissingGetterMatchingBuilder")
        public @NonNull Builder setImageFormat(@Format int imageFormat) {
@@ -985,12 +1000,16 @@ public class ImageWriter implements AutoCloseable {

        /**
         * Set the usage flag of this ImageWriter.
         * Default value is {@link HardwareBuffer#USAGE_CPU_WRITE_OFTEN}.
         *
         * <p>If this function is not called, usage bit will be set
         * to {@link HardwareBuffer#USAGE_CPU_WRITE_OFTEN} if the image format is not
         * {@link ImageFormat#PRIVATE PRIVATE}.</p>
         *
         * @param usage The intended usage of the images produced by this ImageWriter.
         * @return the Builder instance with customized usage flag.
         *
         * @see HardwareBuffer
         * @see #getUsage
         */
        public @NonNull Builder setUsage(@Usage long usage) {
            mUsage = usage;
@@ -1022,6 +1041,7 @@ public class ImageWriter implements AutoCloseable {
        private int mHeight = -1;
        private int mWidth = -1;
        private int mFormat = -1;
        private @NamedDataSpace long mDataSpace = DataSpace.DATASPACE_UNKNOWN;
        // When this default timestamp is used, timestamp for the input Image
        // will be generated automatically when queueInputBuffer is called.
        private final long DEFAULT_TIMESTAMP = Long.MIN_VALUE;
@@ -1034,19 +1054,34 @@ public class ImageWriter implements AutoCloseable {
            mOwner = writer;
            mWidth = writer.mWidth;
            mHeight = writer.mHeight;
            mDataSpace = writer.mDataSpace;

            if (!writer.mUseLegacyImageFormat) {
            if (!mOwner.mUseLegacyImageFormat) {
                mFormat = PublicFormatUtils.getPublicFormat(
                        writer.mHardwareBufferFormat, writer.mDataSpace);
                    mOwner.mHardwareBufferFormat, mDataSpace);
            }
        }

        @Override
        public @NamedDataSpace long getDataSpace() {
            throwISEIfImageIsInvalid();

            return mDataSpace;
        }

        @Override
        public void setDataSpace(@NamedDataSpace long dataSpace) {
            throwISEIfImageIsInvalid();

            mDataSpace = dataSpace;
        }

        @Override
        public int getFormat() {
            throwISEIfImageIsInvalid();

            if (mFormat == -1) {
                mFormat = nativeGetFormat();
            if (mOwner.mUseLegacyImageFormat && mFormat == -1) {
                mFormat = nativeGetFormat(mDataSpace);
            }
            return mFormat;
        }
@@ -1114,7 +1149,8 @@ public class ImageWriter implements AutoCloseable {

            if (mPlanes == null) {
                int numPlanes = ImageUtils.getNumPlanesForFormat(getFormat());
                mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat());
                mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat(),
                        getOwner().getDataSpace());
            }

            return mPlanes.clone();
@@ -1222,13 +1258,14 @@ public class ImageWriter implements AutoCloseable {
        }

        // Create the SurfacePlane object and fill the information
        private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt);
        private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt,
                long dataSpace);

        private synchronized native int nativeGetWidth();

        private synchronized native int nativeGetHeight();

        private synchronized native int nativeGetFormat();
        private synchronized native int nativeGetFormat(long dataSpace);

        private synchronized native HardwareBuffer nativeGetHardwareBuffer();
    }
+24 −17
Original line number Diff line number Diff line
@@ -460,8 +460,6 @@ static jlong ImageWriter_init(JNIEnv* env, jobject thiz, jobject weakThiz, jobje
    } else {
        // Set consumer buffer format to user specified format
        android_dataspace nativeDataspace = static_cast<android_dataspace>(dataSpace);
        int userFormat = static_cast<int>(mapHalFormatDataspaceToPublicFormat(
            hardwareBufferFormat, nativeDataspace));
        res = native_window_set_buffers_format(anw.get(), hardwareBufferFormat);
        if (res != OK) {
            ALOGE("%s: Unable to configure consumer native buffer format to %#x",
@@ -478,21 +476,30 @@ static jlong ImageWriter_init(JNIEnv* env, jobject thiz, jobject weakThiz, jobje
            return 0;
        }
        ctx->setBufferDataSpace(nativeDataspace);
        surfaceFormat = userFormat;
        surfaceFormat = static_cast<int32_t>(mapHalFormatDataspaceToPublicFormat(
            hardwareBufferFormat, nativeDataspace));
    }

    ctx->setBufferFormat(surfaceFormat);
    env->SetIntField(thiz,
            gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(surfaceFormat));

    // ndkUsage == -1 means setUsage in ImageWriter class is not called.
    // skip usage setting if setUsage in ImageWriter is not called and imageformat is opaque.
    if (!(ndkUsage == -1 && isFormatOpaque(surfaceFormat))) {
        if (ndkUsage == -1) {
            ndkUsage = GRALLOC_USAGE_SW_WRITE_OFTEN;
        }
        res = native_window_set_usage(anw.get(), ndkUsage);
        if (res != OK) {
            ALOGE("%s: Configure usage %08x for format %08x failed: %s (%d)",
                  __FUNCTION__, static_cast<unsigned int>(ndkUsage),
                  surfaceFormat, strerror(-res), res);
        jniThrowRuntimeException(env, "Failed to SW_WRITE_OFTEN configure usage");
            jniThrowRuntimeException(env,
                                     "Failed to SW_WRITE_OFTEN configure usage");
            return 0;
        }
    }

    int minUndequeuedBufferCount = 0;
    res = anw->query(anw.get(),
@@ -952,7 +959,7 @@ static jint Image_getHeight(JNIEnv* env, jobject thiz) {
    return buffer->getHeight();
}

static jint Image_getFormat(JNIEnv* env, jobject thiz) {
static jint Image_getFormat(JNIEnv* env, jobject thiz, jlong dataSpace) {
    ALOGV("%s", __FUNCTION__);
    GraphicBuffer* buffer;
    Image_getNativeContext(env, thiz, &buffer, NULL);
@@ -962,9 +969,9 @@ static jint Image_getFormat(JNIEnv* env, jobject thiz) {
        return 0;
    }

    // ImageWriter doesn't support data space yet, assuming it is unknown.
    PublicFormat publicFmt = mapHalFormatDataspaceToPublicFormat(buffer->getPixelFormat(),
                                                                 HAL_DATASPACE_UNKNOWN);
        static_cast<android_dataspace>(dataSpace));

    return static_cast<jint>(publicFmt);
}

@@ -1031,14 +1038,14 @@ static bool Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx,
}

static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz,
        int numPlanes, int writerFormat) {
        int numPlanes, int writerFormat, long dataSpace) {
    ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes);
    int rowStride, pixelStride;
    uint8_t *pData;
    uint32_t dataSize;
    jobject byteBuffer;

    int format = Image_getFormat(env, thiz);
    int format = Image_getFormat(env, thiz, dataSpace);
    if (isFormatOpaque(format) && numPlanes > 0) {
        String8 msg;
        msg.appendFormat("Format 0x%x is opaque, thus not writable, the number of planes (%d)"
@@ -1108,11 +1115,11 @@ static JNINativeMethod gImageWriterMethods[] = {
};

static JNINativeMethod gImageMethods[] = {
    {"nativeCreatePlanes",      "(II)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
    {"nativeCreatePlanes",      "(IIJ)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;",
                                                               (void*)Image_createSurfacePlanes },
    {"nativeGetWidth",          "()I",                         (void*)Image_getWidth },
    {"nativeGetHeight",         "()I",                         (void*)Image_getHeight },
    {"nativeGetFormat",         "()I",                         (void*)Image_getFormat },
    {"nativeGetFormat",         "(J)I",                        (void*)Image_getFormat },
    {"nativeGetHardwareBuffer", "()Landroid/hardware/HardwareBuffer;",
                                                               (void*)Image_getHardwareBuffer },
};