diff options
| author | 2021-12-06 16:37:50 -0800 | |
|---|---|---|
| committer | 2022-01-11 20:43:23 -0800 | |
| commit | aba398d87d91afcdbc8a8ff766af86c3b6dc9c25 (patch) | |
| tree | d19cdda46fed05173940ee50d99b03d6285f6338 | |
| parent | 943415466f1cfeabc4c86e9c7bf913bffda28d39 (diff) | |
Introduce Builder in ImageReader class for setup and construct an
ImageReader instance.
- Builder pattern allows the app to provide HardwareBuffer.Format
constant which is 1:1 mapping with the HAL PixelFormat
- create an JNI binding for PublicFormat.cpp functions and directly map
imageFormat to the pairings of hardwareBufferformat and dataspace
in the ImageReader class.
- involve dataspace setting option into ImageReader
Bug: 205734633
Test: android.hardware.camera2.cts.ImageReaderTest pass
Change-Id: Idd4c610a710d123615449af76763f1c04afb2bda
| -rw-r--r-- | core/api/current.txt | 13 | ||||
| -rw-r--r-- | media/java/android/media/ImageReader.java | 314 | ||||
| -rw-r--r-- | media/java/android/media/ImageUtils.java | 29 | ||||
| -rw-r--r-- | media/java/android/media/PublicFormatUtils.java | 34 | ||||
| -rw-r--r-- | media/jni/Android.bp | 1 | ||||
| -rw-r--r-- | media/jni/android_media_ImageReader.cpp | 24 | ||||
| -rw-r--r-- | media/jni/android_media_MediaPlayer.cpp | 6 | ||||
| -rw-r--r-- | media/jni/android_media_PublicFormatUtils.cpp | 59 | 
8 files changed, 430 insertions, 50 deletions
diff --git a/core/api/current.txt b/core/api/current.txt index 020c8ff1d464..bdedc5803659 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -21681,16 +21681,29 @@ package android.media {      method public android.media.Image acquireNextImage();      method public void close();      method public void discardFreeBuffers(); +    method public long getDataSpace(); +    method public int getHardwareBufferFormat();      method public int getHeight();      method public int getImageFormat();      method public int getMaxImages();      method public android.view.Surface getSurface(); +    method public long getUsage();      method public int getWidth();      method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int);      method @NonNull public static android.media.ImageReader newInstance(@IntRange(from=1) int, @IntRange(from=1) int, int, @IntRange(from=1) int, long);      method public void setOnImageAvailableListener(android.media.ImageReader.OnImageAvailableListener, android.os.Handler);    } +  public static final class ImageReader.Builder { +    ctor public ImageReader.Builder(@IntRange(from=1) int, @IntRange(from=1) int); +    method @NonNull public android.media.ImageReader build(); +    method @NonNull public android.media.ImageReader.Builder setDefaultDataSpace(long); +    method @NonNull public android.media.ImageReader.Builder setDefaultHardwareBufferFormat(int); +    method @NonNull public android.media.ImageReader.Builder setImageFormat(int); +    method @NonNull public android.media.ImageReader.Builder setMaxImages(int); +    method @NonNull public android.media.ImageReader.Builder setUsage(long); +  } +    public static interface ImageReader.OnImageAvailableListener {      method public void onImageAvailable(android.media.ImageReader);    } diff --git a/media/java/android/media/ImageReader.java b/media/java/android/media/ImageReader.java index bd0f32e6ffee..69ce8d2a3d93 100644 --- a/media/java/android/media/ImageReader.java +++ b/media/java/android/media/ImageReader.java @@ -18,10 +18,13 @@ package android.media;  import android.annotation.IntRange;  import android.annotation.NonNull; +import android.annotation.SuppressLint;  import android.graphics.GraphicBuffer;  import android.graphics.ImageFormat;  import android.graphics.ImageFormat.Format;  import android.graphics.Rect; +import android.hardware.DataSpace; +import android.hardware.DataSpace.NamedDataSpace;  import android.hardware.HardwareBuffer;  import android.hardware.HardwareBuffer.Usage;  import android.hardware.camera2.MultiResolutionImageReader; @@ -136,8 +139,7 @@ public class ImageReader implements AutoCloseable {          // If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not          // work, and is inscrutable anyway          return new ImageReader(width, height, format, maxImages, -                format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN, -                /*parent*/ null); +                format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN, null);      }      /** @@ -268,44 +270,32 @@ public class ImageReader implements AutoCloseable {          // If the format is private don't default to USAGE_CPU_READ_OFTEN since it may not          // work, and is inscrutable anyway          return new ImageReader(width, height, format, maxImages, -                format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN, -                parent); +                format == ImageFormat.PRIVATE ? 0 : HardwareBuffer.USAGE_CPU_READ_OFTEN, parent);      } - -    /** -     * @hide -     */ -    protected ImageReader(int width, int height, int format, int maxImages, long usage, -            MultiResolutionImageReader parent) { -        mWidth = width; -        mHeight = height; -        mFormat = format; -        mUsage = usage; -        mMaxImages = maxImages; -        mParent = parent; - +    private void initializeImageReader(int width, int height, int imageFormat, int maxImages, +            long usage, int hardwareBufferFormat, long dataSpace, boolean useLegacyImageFormat) {          if (width < 1 || height < 1) {              throw new IllegalArgumentException(                  "The image dimensions must be positive");          } -        if (mMaxImages < 1) { + +        if (maxImages < 1) {              throw new IllegalArgumentException(                  "Maximum outstanding image count must be at least 1");          } -        if (format == ImageFormat.NV21) { +        if (imageFormat == ImageFormat.NV21) {              throw new IllegalArgumentException( -                    "NV21 format is not supported"); +                "NV21 format is not supported");          } -        mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat); +        nativeInit(new WeakReference<>(this), width, height, maxImages, usage, +                hardwareBufferFormat, dataSpace); -        nativeInit(new WeakReference<>(this), width, height, format, maxImages, usage); +        mIsReaderValid = true;          mSurface = nativeGetSurface(); - -        mIsReaderValid = true;          // Estimate the native buffer allocation size and register it so it gets accounted for          // during GC. Note that this doesn't include the buffers required by the buffer queue          // itself and the buffers requested by the producer. @@ -313,10 +303,46 @@ public class ImageReader implements AutoCloseable {          // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some          // size.          mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( -                width, height, format, /*buffer count*/ 1); +            width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat, +            /*buffer count*/ 1);          VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes);      } +    private ImageReader(int width, int height, int imageFormat, int maxImages, long usage, +            MultiResolutionImageReader parent) { +        mWidth = width; +        mHeight = height; +        mFormat = imageFormat; +        mUsage = usage; +        mMaxImages = maxImages; +        mParent = parent; +        // retrieve hal Format and hal dataspace from imageFormat +        mHardwareBufferFormat = PublicFormatUtils.getHalFormat(mFormat); +        mDataSpace = PublicFormatUtils.getHalDataspace(mFormat); +        mUseLegacyImageFormat = true; +        mNumPlanes = ImageUtils.getNumPlanesForFormat(mFormat); + +        initializeImageReader(width, height, imageFormat, maxImages, usage, mHardwareBufferFormat, +                mDataSpace, mUseLegacyImageFormat); +    } + +    private ImageReader(int width, int height, int maxImages, long usage, +            MultiResolutionImageReader parent, int hardwareBufferFormat, long dataSpace) { +        mWidth = width; +        mHeight = height; +        mFormat = ImageFormat.UNKNOWN; // set default image format value as UNKNOWN +        mUsage = usage; +        mMaxImages = maxImages; +        mParent = parent; +        mHardwareBufferFormat = hardwareBufferFormat; +        mDataSpace = dataSpace; +        mUseLegacyImageFormat = false; +        mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat); + +        initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat, +                dataSpace, mUseLegacyImageFormat); +    } +      /**       * The default width of {@link Image Images}, in pixels.       * @@ -354,6 +380,10 @@ public class ImageReader implements AutoCloseable {       * As of now, each format is only compatible to itself.       * The actual format of the images can be found using {@link Image#getFormat}.</p>       * +     * <p>Use this function if the ImageReader instance is created by factory method +     * {@code newInstance} function or by builder pattern {@code ImageReader.Builder} and using +     * {@link Builder#setImageFormat}.</p> +     *       * @return the expected format of an Image       *       * @see ImageFormat @@ -363,6 +393,32 @@ public class ImageReader implements AutoCloseable {      }      /** +     * The default {@link HardwareBuffer} format of {@link Image Images}. +     * +     * <p>Use this function if the ImageReader instance is created by builder pattern +     * {@code ImageReader.Builder} and using {@link Builder#setDefaultHardwareBufferFormat} and +     * {@link Builder#setDefaultDataSpace}.</p> +     * +     * @return the expected {@link HardwareBuffer} format of an Image. +     */ +    public @HardwareBuffer.Format int getHardwareBufferFormat() { +        return mHardwareBufferFormat; +    } + +    /** +     * The default dataspace of {@link Image Images}. +     * +     * <p>Use this function if the ImageReader instance is created by builder pattern +     * {@code ImageReader.Builder} and {@link Builder#setDefaultDataSpace}.</p> +     * +     * @return the expected dataspace of an Image. +     */ +    @SuppressLint("MethodNameUnits") +    public @NamedDataSpace long getDataSpace() { +        return mDataSpace; +    } + +    /**       * Maximum number of images that can be acquired from the ImageReader by any time (for example,       * with {@link #acquireNextImage}).       * @@ -384,6 +440,15 @@ public class ImageReader implements AutoCloseable {      }      /** +     * The usage flag of images that can be produced by the ImageReader. +     * +     * @return The usage flag of the images for this ImageReader. +     */ +    public @Usage long getUsage() { +        return mUsage; +    } + +    /**       * <p>Get a {@link Surface} that can be used to produce {@link Image Images} for this       * {@code ImageReader}.</p>       * @@ -469,7 +534,12 @@ public class ImageReader implements AutoCloseable {       * @hide       */      public Image acquireNextImageNoThrowISE() { -        SurfaceImage si = new SurfaceImage(mFormat); +        SurfaceImage si; +        if (mUseLegacyImageFormat) { +            si = new SurfaceImage(mFormat); +        } else { +            si = new SurfaceImage(mHardwareBufferFormat, mDataSpace); +        }          return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null;      } @@ -492,7 +562,7 @@ public class ImageReader implements AutoCloseable {              // A null image will eventually be returned if ImageReader is already closed.              int status = ACQUIRE_NO_BUFS;              if (mIsReaderValid) { -                status = nativeImageSetup(si); +                status = nativeImageSetup(si, mUseLegacyImageFormat);              }              switch (status) { @@ -545,7 +615,12 @@ public class ImageReader implements AutoCloseable {      public Image acquireNextImage() {          // Initialize with reader format, but can be overwritten by native if the image          // format is different from the reader format. -        SurfaceImage si = new SurfaceImage(mFormat); +        SurfaceImage si; +        if (mUseLegacyImageFormat) { +            si = new SurfaceImage(mFormat); +        } else { +            si = new SurfaceImage(mHardwareBufferFormat, mDataSpace); +        }          int status = acquireNextSurfaceImage(si);          switch (status) { @@ -838,13 +913,161 @@ public class ImageReader implements AutoCloseable {          }      } +    /** +     * Builder class for {@link ImageReader} objects. +     */ +    public static final class Builder { +        private int mWidth; +        private int mHeight; +        private int mMaxImages = 1; +        private int mImageFormat = ImageFormat.UNKNOWN; +        private int mHardwareBufferFormat = HardwareBuffer.RGBA_8888; +        private long mDataSpace = DataSpace.DATASPACE_UNKNOWN; +        private long mUsage = HardwareBuffer.USAGE_CPU_READ_OFTEN; +        private boolean mUseLegacyImageFormat = false; + +        /** +         * Constructs a new builder for {@link ImageReader}. +         * +         * @param width The default width in pixels that will be passed to the producer. +         *              May be overridden by the producer. +         * @param height The default height in pixels that will be passed to the producer. +         *              May be overridden by the producer. +         * @see Image +         */ +        public Builder(@IntRange(from = 1) int width, @IntRange(from = 1) int height) { +            mWidth = width; +            mHeight = height; +        } + +        /** +         * Set the maximal number of images. +         * +         * @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. Default value is 1. +         * @return the Builder instance with customized usage value. +         */ +        public @NonNull Builder setMaxImages(int maxImages) { +            mMaxImages = maxImages; +            return this; +        } + +        /** +         * Set the consumer usage flag. +         * +         * @param usage The intended usage of the images consumed by this ImageReader. +         *              See the usages on {@link HardwareBuffer} for a list of valid usage bits. +         *              Default value is {@link HardwareBuffer#USAGE_CPU_READ_OFTEN}. +         * @return the Builder instance with customized usage value. +         * +         * @see HardwareBuffer +         */ +        public @NonNull Builder setUsage(long usage) { +            mUsage = usage; +            return this; +        } + +        /** +         * Set the default image format passed by the producer. May be overridden by the producer. +         * +         * <p>{@link #setImageFormat} function replaces the combination of +         * {@link #setDefaultHardwareBufferFormat} and {@link #setDefaultDataSpace} functions. +         * Either this or these two functions must be called to initialize an {@code ImageReader} +         * instance.</p> +         * +         * @param imageFormat The format of the image that this reader will produce. This +         *                    must be one of the {@link android.graphics.ImageFormat} or +         *                   {@link android.graphics.PixelFormat} constants. Note that not +         *                   all formats are supported, like ImageFormat.NV21. The default value is +         *                   {@link ImageFormat#UNKNOWN}. +         * @return the builder instance with customized image format value. +         * +         * @see #setDefaultHardwareBufferFormat +         * @see #setDefaultDataSpace +         */ +        public @NonNull Builder setImageFormat(@Format int imageFormat) { +            mImageFormat = imageFormat; +            mUseLegacyImageFormat = true; +            mHardwareBufferFormat = HardwareBuffer.RGBA_8888; +            mDataSpace = DataSpace.DATASPACE_UNKNOWN; +            return this; +        } + +        /** +         * Set the default hardwareBuffer format passed by the producer. +         * May be overridden by the producer. +         * +         * <p>This function works together with {@link #setDefaultDataSpace} for an +         * {@link ImageReader} instance. Setting at least one of these two replaces +         * {@link #setImageFormat} function.</p> +         * +         * <p>The format of the Image can be overridden after {@link #setImageFormat} by calling +         * this function and then {@link #setDefaultDataSpace} functions. +         * <i>Warning:</i> Missing one of callings for initializing or overriding the format may +         * involve undefined behaviors.</p> +         * +         * @param hardwareBufferFormat The HardwareBuffer format of the image that this reader +         *                             will produce. The default value is +         *                             {@link HardwareBuffer#RGBA_8888 HardwareBuffer.RGBA_8888}. +         * @return the builder instance with customized hardwareBuffer value. +         * +         * @see #setDefaultDataSpace +         * @see #setImageFormat +         */ +        @SuppressLint("MissingGetterMatchingBuilder") +        public @NonNull Builder setDefaultHardwareBufferFormat( +                @HardwareBuffer.Format int hardwareBufferFormat) { +            mHardwareBufferFormat = hardwareBufferFormat; +            mUseLegacyImageFormat = false; +            mImageFormat = ImageFormat.UNKNOWN; +            return this; +        } + +        /** +         * Set the default dataspace passed by the producer. +         * May be overridden by the producer. +         * +         * <p>This function works together with {@link #setDefaultHardwareBufferFormat} for an +         * {@link ImageReader} instance. Setting at least one of these two replaces +         * {@link #setImageFormat} function.</p> +         * +         * @param dataSpace The dataspace of the image that this reader will produce. +         *                  The default value is {@link DataSpace#DATASPACE_UNKNOWN}. +         * @return the builder instance with customized dataspace value. +         * +         * @see #setDefaultHardwareBufferFormat +         */ +        @SuppressLint("MissingGetterMatchingBuilder") +        public @NonNull Builder setDefaultDataSpace(@NamedDataSpace long dataSpace) { +            mDataSpace = dataSpace; +            mUseLegacyImageFormat = false; +            mImageFormat = ImageFormat.UNKNOWN; +            return this; +        } + +        /** +         * Builds a new ImageReader object. +         * +         * @return The new ImageReader object. +         */ +        public @NonNull ImageReader build() { +            if (mUseLegacyImageFormat) { +                return new ImageReader(mWidth, mHeight, mImageFormat, mMaxImages, mUsage, null); +            } else { +                return new ImageReader(mWidth, mHeight, mMaxImages, mUsage, null, +                    mHardwareBufferFormat, mDataSpace); +            } +        } +    } +      private final int mWidth;      private final int mHeight;      private final int mFormat;      private final long mUsage;      private final int mMaxImages;      private final int mNumPlanes; -    private final Surface mSurface; +    private Surface mSurface;      private int mEstimatedNativeAllocBytes;      private final Object mListenerLock = new Object(); @@ -861,6 +1084,12 @@ public class ImageReader implements AutoCloseable {      // MultiResolutionImageReader.      private final MultiResolutionImageReader mParent; +    private final int mHardwareBufferFormat; + +    private final long mDataSpace; + +    private final boolean mUseLegacyImageFormat; +      /**       * This field is used by native code, do not access or modify.       */ @@ -897,6 +1126,12 @@ public class ImageReader implements AutoCloseable {              mFormat = format;          } +        SurfaceImage(int hardwareBufferFormat, long dataSpace) { +            mHardwareBufferFormat = hardwareBufferFormat; +            mDataSpace = dataSpace; +            mFormat = PublicFormatUtils.getPublicFormat(mHardwareBufferFormat, mDataSpace); +        } +          @Override          public void close() {              ImageReader.this.releaseImage(this); @@ -909,10 +1144,15 @@ public class ImageReader implements AutoCloseable {          @Override          public int getFormat() {              throwISEIfImageIsInvalid(); -            int readerFormat = ImageReader.this.getImageFormat(); -            // Assume opaque reader always produce opaque images. -            mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat : -                nativeGetFormat(readerFormat); +            // update mFormat only if ImageReader is initialized by factory pattern. +            // if using builder pattern, mFormat has been updated upon initialization. +            // no need update here. +            if (ImageReader.this.mUseLegacyImageFormat) { +                int readerFormat = ImageReader.this.getImageFormat(); +                // Assume opaque reader always produce opaque images. +                mFormat = (readerFormat == ImageFormat.PRIVATE) ? readerFormat : +                    nativeGetFormat(readerFormat); +            }              return mFormat;          } @@ -1125,6 +1365,8 @@ public class ImageReader implements AutoCloseable {          private SurfacePlane[] mPlanes;          private int mFormat = ImageFormat.UNKNOWN; +        private int mHardwareBufferFormat = HardwareBuffer.RGBA_8888; +        private long mDataSpace = DataSpace.DATASPACE_UNKNOWN;          // If this image is detached from the ImageReader.          private AtomicBoolean mIsDetached = new AtomicBoolean(false); @@ -1137,8 +1379,8 @@ public class ImageReader implements AutoCloseable {          private synchronized native HardwareBuffer nativeGetHardwareBuffer();      } -    private synchronized native void nativeInit(Object weakSelf, int w, int h, -                                                    int fmt, int maxImgs, long consumerUsage); +    private synchronized native void nativeInit(Object weakSelf, int w, int h, int maxImgs, +            long consumerUsage, int hardwareBufferFormat, long dataSpace);      private synchronized native void nativeClose();      private synchronized native void nativeReleaseImage(Image i);      private synchronized native Surface nativeGetSurface(); @@ -1152,7 +1394,7 @@ public class ImageReader implements AutoCloseable {       * @see #ACQUIRE_NO_BUFS       * @see #ACQUIRE_MAX_IMAGES       */ -    private synchronized native int nativeImageSetup(Image i); +    private synchronized native int nativeImageSetup(Image i, boolean legacyValidateImageFormat);      /**       * @hide diff --git a/media/java/android/media/ImageUtils.java b/media/java/android/media/ImageUtils.java index 7837d7e39599..2f1a36cba9d0 100644 --- a/media/java/android/media/ImageUtils.java +++ b/media/java/android/media/ImageUtils.java @@ -18,6 +18,7 @@ package android.media;  import android.graphics.ImageFormat;  import android.graphics.PixelFormat; +import android.hardware.HardwareBuffer;  import android.media.Image.Plane;  import android.util.Size; @@ -77,6 +78,34 @@ class ImageUtils {      }      /** +     * Only a subset of the formats defined in +     * {@link android.graphics.HardwareBuffer.Format} constants are supported by ImageReader. +     */ +    public static int getNumPlanesForHardwareBufferFormat(int hardwareBufferFormat) { +        switch(hardwareBufferFormat) { +            case HardwareBuffer.YCBCR_420_888: +                return 3; +            case HardwareBuffer.RGBA_8888: +            case HardwareBuffer.RGBX_8888: +            case HardwareBuffer.RGB_888: +            case HardwareBuffer.RGB_565: +            case HardwareBuffer.RGBA_FP16: +            case HardwareBuffer.RGBA_1010102: +            case HardwareBuffer.BLOB: +            case HardwareBuffer.D_16: +            case HardwareBuffer.D_24: +            case HardwareBuffer.DS_24UI8: +            case HardwareBuffer.D_FP32: +            case HardwareBuffer.DS_FP32UI8: +            case HardwareBuffer.S_UI8: +                return 1; +            default: +                throw new UnsupportedOperationException( +                    String.format("Invalid hardwareBuffer format specified %d", +                            hardwareBufferFormat)); +        } +    } +    /**       * <p>       * Copy source image data to destination Image.       * </p> diff --git a/media/java/android/media/PublicFormatUtils.java b/media/java/android/media/PublicFormatUtils.java new file mode 100644 index 000000000000..6268804128c6 --- /dev/null +++ b/media/java/android/media/PublicFormatUtils.java @@ -0,0 +1,34 @@ +/* + * Copyright 2022 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. + */ +package android.media; + +/** + * Package private utility class for PublicFormat related methods. + */ +class PublicFormatUtils { +    public static int getHalFormat(int imageFormat) { +        return nativeGetHalFormat(imageFormat); +    } +    public static long getHalDataspace(int imageFormat) { +        return nativeGetHalDataspace(imageFormat); +    } +    public static int getPublicFormat(int imageFormat, long dataspace) { +        return nativeGetPublicFormat(imageFormat, dataspace); +    } +    private static native int nativeGetHalFormat(int imageFormat); +    private static native long nativeGetHalDataspace(int imageFormat); +    private static native int nativeGetPublicFormat(int imageFormat, long dataspace); +} diff --git a/media/jni/Android.bp b/media/jni/Android.bp index e817f2dc9e1d..feae6065c680 100644 --- a/media/jni/Android.bp +++ b/media/jni/Android.bp @@ -39,6 +39,7 @@ cc_library_shared {          "android_media_MediaProfiles.cpp",          "android_media_MediaRecorder.cpp",          "android_media_MediaSync.cpp", +        "android_media_PublicFormatUtils.cpp",          "android_media_ResampleInputStream.cpp",          "android_media_Streams.cpp",          "android_media_SyncParams.cpp", diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp index 021507c8631c..6002e2884db8 100644 --- a/media/jni/android_media_ImageReader.cpp +++ b/media/jni/android_media_ImageReader.cpp @@ -375,18 +375,13 @@ static void ImageReader_classInit(JNIEnv* env, jclass clazz)  }  static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height, -                             jint format, jint maxImages, jlong ndkUsage) -{ +                             jint maxImages, jlong ndkUsage, jint nativeFormat, jlong dataSpace) {      status_t res; -    int nativeFormat; -    android_dataspace nativeDataspace; -    ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d", -          __FUNCTION__, width, height, format, maxImages); +    ALOGV("%s: width:%d, height: %d, nativeFormat: %d, maxImages:%d", +          __FUNCTION__, width, height, nativeFormat, maxImages); -    PublicFormat publicFormat = static_cast<PublicFormat>(format); -    nativeFormat = mapPublicFormatToHalFormat(publicFormat); -    nativeDataspace = mapPublicFormatToHalDataspace(publicFormat); +    android_dataspace nativeDataspace = static_cast<android_dataspace>(dataSpace);      jclass clazz = env->GetObjectClass(thiz);      if (clazz == NULL) { @@ -400,7 +395,7 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w      BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);      sp<BufferItemConsumer> bufferConsumer;      String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d", -            width, height, format, maxImages, getpid(), +            width, height, nativeFormat, maxImages, getpid(),              createProcessUniqueId());      uint64_t consumerUsage =              android_hardware_HardwareBuffer_convertToGrallocUsageBits(ndkUsage); @@ -527,7 +522,8 @@ static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)      ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());  } -static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) { +static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image, +                                   jboolean legacyValidateImageFormat) {      ALOGV("%s:", __FUNCTION__);      JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);      if (ctx == NULL) { @@ -590,7 +586,7 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {              ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",                      __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);          } -        if (imgReaderFmt != bufferFormat) { +        if (legacyValidateImageFormat && imgReaderFmt != bufferFormat) {              if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 &&                      isPossiblyYUV(bufferFormat)) {                  // Treat formats that are compatible with flexible YUV @@ -958,10 +954,10 @@ static jobject Image_getHardwareBuffer(JNIEnv* env, jobject thiz) {  static const JNINativeMethod gImageReaderMethods[] = {      {"nativeClassInit",        "()V",                        (void*)ImageReader_classInit }, -    {"nativeInit",             "(Ljava/lang/Object;IIIIJ)V",  (void*)ImageReader_init }, +    {"nativeInit",             "(Ljava/lang/Object;IIIJIJ)V",   (void*)ImageReader_init },      {"nativeClose",            "()V",                        (void*)ImageReader_close },      {"nativeReleaseImage",     "(Landroid/media/Image;)V",   (void*)ImageReader_imageRelease }, -    {"nativeImageSetup",       "(Landroid/media/Image;)I",   (void*)ImageReader_imageSetup }, +    {"nativeImageSetup",       "(Landroid/media/Image;Z)I",   (void*)ImageReader_imageSetup },      {"nativeGetSurface",       "()Landroid/view/Surface;",   (void*)ImageReader_getSurface },      {"nativeDetachImage",      "(Landroid/media/Image;)I",   (void*)ImageReader_detachImage },      {"nativeCreateImagePlanes", diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 8dcdc989ec8f..a548a472fc3a 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -1454,6 +1454,7 @@ extern int register_android_media_MediaMetadataRetriever(JNIEnv *env);  extern int register_android_media_MediaMuxer(JNIEnv *env);  extern int register_android_media_MediaRecorder(JNIEnv *env);  extern int register_android_media_MediaSync(JNIEnv *env); +extern int register_android_media_PublicFormatUtils(JNIEnv *env);  extern int register_android_media_ResampleInputStream(JNIEnv *env);  extern int register_android_media_MediaProfiles(JNIEnv *env);  extern int register_android_mtp_MtpDatabase(JNIEnv *env); @@ -1501,6 +1502,11 @@ jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)          goto bail;      } +    if (register_android_media_PublicFormatUtils(env) < 0) { +        ALOGE("ERROR: PublicFormatUtils native registration failed\n"); +        goto bail; +    } +      if (register_android_media_ResampleInputStream(env) < 0) {          ALOGE("ERROR: ResampleInputStream native registration failed\n");          goto bail; diff --git a/media/jni/android_media_PublicFormatUtils.cpp b/media/jni/android_media_PublicFormatUtils.cpp new file mode 100644 index 000000000000..09ebdeeff06f --- /dev/null +++ b/media/jni/android_media_PublicFormatUtils.cpp @@ -0,0 +1,59 @@ +/* + * Copyright 2022 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. + */ + +#define LOG_TAG "PublicFormatUtils_JNI" + +#include <utils/misc.h> +#include <ui/PublicFormat.h> +#include <android_runtime/AndroidRuntime.h> +#include <jni.h> + +using namespace android; + +static jint android_media_PublicFormatUtils_getHalFormat(JNIEnv* /*env*/, jobject /*thiz*/, +                                                         jint imageFormat) { +    PublicFormat publicFormat = static_cast<PublicFormat>(imageFormat); +    int nativeFormat = mapPublicFormatToHalFormat(publicFormat); +    return static_cast<jint>(nativeFormat); +} + +static jlong android_media_PublicFormatUtils_getHalDataspace(JNIEnv* /*env*/, jobject /*thiz*/, +                                                             jint imageFormat) { +    PublicFormat publicFormat = static_cast<PublicFormat>(imageFormat); +    android_dataspace +        nativeDataspace = mapPublicFormatToHalDataspace(publicFormat); +    return static_cast<jlong>(nativeDataspace); +} + +static jint android_media_PublicFormatUtils_getPublicFormat(JNIEnv* /*env*/, jobject /*thiz*/, +                                                            jint hardwareBufferFormat, +                                                            jlong dataspace) { +    PublicFormat nativeFormat = mapHalFormatDataspaceToPublicFormat( +            hardwareBufferFormat, static_cast<android_dataspace>(dataspace)); +    return static_cast<jint>(nativeFormat); +} + +static const JNINativeMethod gMethods[] = { +    {"nativeGetHalFormat",    "(I)I", (void*)android_media_PublicFormatUtils_getHalFormat}, +    {"nativeGetHalDataspace", "(I)J", (void*)android_media_PublicFormatUtils_getHalDataspace}, +    {"nativeGetPublicFormat", "(IJ)I",(void*)android_media_PublicFormatUtils_getPublicFormat} +}; + +int register_android_media_PublicFormatUtils(JNIEnv *env) { +    return AndroidRuntime::registerNativeMethods(env, +             "android/media/PublicFormatUtils", gMethods, NELEM(gMethods)); +} +  |