Loading core/jni/android_hardware_camera2_utils_SurfaceUtils.cpp +14 −11 Original line number Diff line number Diff line Loading @@ -89,39 +89,42 @@ static sp<Surface> getSurface(JNIEnv* env, jobject surface) { extern "C" { static jint SurfaceUtils_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceType"); static jint SurfaceUtils_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceDataspace"); sp<ANativeWindow> anw; if ((anw = getNativeWindow(env, surface)) == NULL) { ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); return BAD_VALUE; } int32_t fmt = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt); status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt); if (err != NO_ERROR) { ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), err); ALOGE("%s: Error while querying surface dataspace %s (%d).", __FUNCTION__, strerror(-err), err); OVERRIDE_SURFACE_ERROR(err); return err; } return fmt; } static jint SurfaceUtils_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceDataspace"); static jint SurfaceUtils_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceType"); sp<ANativeWindow> anw; if ((anw = getNativeWindow(env, surface)) == NULL) { ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); return BAD_VALUE; } int32_t fmt = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt); int32_t halFmt = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &halFmt); if (err != NO_ERROR) { ALOGE("%s: Error while querying surface dataspace %s (%d).", __FUNCTION__, strerror(-err), err); ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), err); OVERRIDE_SURFACE_ERROR(err); return err; } int32_t dataspace = SurfaceUtils_nativeDetectSurfaceDataspace(env, thiz, surface); int32_t fmt = static_cast<int32_t>( mapHalFormatDataspaceToPublicFormat(halFmt, static_cast<android_dataspace>(dataspace))); return fmt; } Loading media/java/android/media/ImageReader.java +15 −42 Original line number Diff line number Diff line Loading @@ -314,7 +314,7 @@ public class ImageReader implements AutoCloseable { } private void initializeImageReader(int width, int height, int imageFormat, int maxImages, long usage, int hardwareBufferFormat, int dataSpace, boolean useLegacyImageFormat) { long usage, int hardwareBufferFormat, int dataSpace) { if (width < 1 || height < 1) { throw new IllegalArgumentException( "The image dimensions must be positive"); Loading Loading @@ -342,14 +342,8 @@ public class ImageReader implements AutoCloseable { // Only include memory for 1 buffer, since actually accounting for the memory used is // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some // size. if (hardwareBufferFormat == HardwareBuffer.BLOB) { mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( width, height, imageFormat, /*buffer count*/ 1); } else { mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1); } VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); } Loading @@ -364,11 +358,10 @@ public class ImageReader implements AutoCloseable { // 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); mDataSpace); } private ImageReader(int width, int height, int maxImages, long usage, Loading @@ -380,12 +373,11 @@ public class ImageReader implements AutoCloseable { mParent = parent; mHardwareBufferFormat = hardwareBufferFormat; mDataSpace = dataSpace; mUseLegacyImageFormat = false; mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat); mFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace); initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat, dataSpace, mUseLegacyImageFormat); dataSpace); } /** Loading Loading @@ -579,12 +571,7 @@ public class ImageReader implements AutoCloseable { * @hide */ public Image acquireNextImageNoThrowISE() { SurfaceImage si; if (mUseLegacyImageFormat) { si = new SurfaceImage(mFormat); } else { si = new SurfaceImage(mHardwareBufferFormat, mDataSpace); } SurfaceImage si = new SurfaceImage(mFormat); return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null; } Loading @@ -607,7 +594,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, mUseLegacyImageFormat); status = nativeImageSetup(si); } switch (status) { Loading Loading @@ -661,11 +648,7 @@ public class ImageReader implements AutoCloseable { // Initialize with reader format, but can be overwritten by native if the image // format is different from the reader format. SurfaceImage si; if (mUseLegacyImageFormat) { si = new SurfaceImage(mFormat); } else { si = new SurfaceImage(mHardwareBufferFormat, mDataSpace); } int status = acquireNextSurfaceImage(si); switch (status) { Loading Loading @@ -1142,8 +1125,6 @@ public class ImageReader implements AutoCloseable { private final @NamedDataSpace int mDataSpace; private final boolean mUseLegacyImageFormat; /** * This field is used by native code, do not access or modify. */ Loading Loading @@ -1184,12 +1165,6 @@ public class ImageReader implements AutoCloseable { mDataSpace = ImageReader.this.mDataSpace; } SurfaceImage(int hardwareBufferFormat, int dataSpace) { mHardwareBufferFormat = hardwareBufferFormat; mDataSpace = dataSpace; mFormat = PublicFormatUtils.getPublicFormat(mHardwareBufferFormat, mDataSpace); } @Override public void close() { synchronized (this.mCloseLock) { Loading @@ -1207,12 +1182,10 @@ public class ImageReader implements AutoCloseable { // 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; } Loading Loading @@ -1311,8 +1284,8 @@ public class ImageReader implements AutoCloseable { throwISEIfImageIsInvalid(); if (mPlanes == null) { mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat, ImageReader.this.mUsage); mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mHardwareBufferFormat, ImageReader.this.mUsage); } // Shallow copy is fine. return mPlanes.clone(); Loading Loading @@ -1443,7 +1416,7 @@ public class ImageReader implements AutoCloseable { private AtomicBoolean mIsDetached = new AtomicBoolean(false); private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int readerFormat, long readerUsage); int hardwareBufferFormat, long readerUsage); private synchronized native int nativeGetWidth(); private synchronized native int nativeGetHeight(); private synchronized native int nativeGetFormat(int readerFormat); Loading @@ -1466,7 +1439,7 @@ public class ImageReader implements AutoCloseable { * @see #ACQUIRE_NO_BUFS * @see #ACQUIRE_MAX_IMAGES */ private synchronized native int nativeImageSetup(Image i, boolean legacyValidateImageFormat); private synchronized native int nativeImageSetup(Image i); /** * @hide Loading media/java/android/media/ImageWriter.java +16 −42 Original line number Diff line number Diff line Loading @@ -248,7 +248,7 @@ public class ImageWriter implements AutoCloseable { } private void initializeImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo, boolean useLegacyImageFormat, int imageFormat, boolean useSurfaceImageFormatInfo, int imageFormat, int hardwareBufferFormat, int dataSpace, int width, int height, long usage) { if (surface == null || maxImages < 1) { throw new IllegalArgumentException("Illegal input argument: surface " + surface Loading @@ -265,7 +265,7 @@ public class ImageWriter implements AutoCloseable { // nativeInit internally overrides UNKNOWN format. So does surface format query after // nativeInit and before getEstimatedNativeAllocBytes(). imageFormat = SurfaceUtils.getSurfaceFormat(surface); mDataSpace = dataSpace = PublicFormatUtils.getHalDataspace(dataSpace); mDataSpace = dataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mHardwareBufferFormat = hardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat); } Loading @@ -280,37 +280,11 @@ public class ImageWriter implements AutoCloseable { mWidth = width == -1 ? surfSize.getWidth() : width; mHeight = height == -1 ? surfSize.getHeight() : height; if (hardwareBufferFormat == HardwareBuffer.BLOB) { // TODO(b/246344817): remove mWriterFormat and mDataSpace re-set here after fixing. mWriterFormat = imageFormat = getImageFormatByBLOB(dataSpace); mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight, imageFormat, /*buffer count*/ 1); } else { mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight, useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1); } VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); } // 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. private int getImageFormatByBLOB(int dataspace) { switch (dataspace) { case DataSpace.DATASPACE_DEPTH: return ImageFormat.DEPTH_POINT_CLOUD; case DataSpace.DATASPACE_DYNAMIC_DEPTH: return ImageFormat.DEPTH_JPEG; case DataSpace.DATASPACE_HEIF: return ImageFormat.HEIC; default: return ImageFormat.JPEG; } } private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo, int imageFormat, int width, int height) { mMaxImages = maxImages; Loading @@ -319,7 +293,7 @@ public class ImageWriter implements AutoCloseable { mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); } initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, imageFormat, mHardwareBufferFormat, mDataSpace, width, height, mUsage); } Loading @@ -332,7 +306,7 @@ public class ImageWriter implements AutoCloseable { mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); } initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, imageFormat, mHardwareBufferFormat, mDataSpace, width, height, usage); } Loading @@ -351,7 +325,7 @@ public class ImageWriter implements AutoCloseable { mDataSpace = dataSpace; } initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, false, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, imageFormat, hardwareBufferFormat, dataSpace, width, height, usage); } Loading Loading @@ -770,13 +744,15 @@ public class ImageWriter implements AutoCloseable { // need do some cleanup to make sure no orphaned // buffer caused leak. Rect crop = image.getCropRect(); int hardwareBufferFormat = PublicFormatUtils.getHalFormat(image.getFormat()); if (image.getNativeContext() != 0) { nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), image.getFormat(), image.getTimestamp(), image.getDataSpace(), crop.left, crop.top, crop.right, crop.bottom, image.getTransform(), image.getScalingMode()); nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), hardwareBufferFormat, image.getTimestamp(), image.getDataSpace(), crop.left, crop.top, crop.right, crop.bottom, image.getTransform(), image.getScalingMode()); } else { GraphicBuffer gb = GraphicBuffer.createFromHardwareBuffer(image.getHardwareBuffer()); nativeAttachAndQueueGraphicBuffer(mNativeContext, gb, image.getFormat(), nativeAttachAndQueueGraphicBuffer(mNativeContext, gb, hardwareBufferFormat, image.getTimestamp(), image.getDataSpace(), crop.left, crop.top, crop.right, crop.bottom, image.getTransform(), image.getScalingMode()); gb.destroy(); Loading Loading @@ -1167,8 +1143,7 @@ public class ImageWriter implements AutoCloseable { if (mPlanes == null) { int numPlanes = ImageUtils.getNumPlanesForFormat(getFormat()); mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat(), getOwner().getDataSpace()); mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat()); } return mPlanes.clone(); Loading Loading @@ -1276,8 +1251,7 @@ public class ImageWriter implements AutoCloseable { } // Create the SurfacePlane object and fill the information private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt, int dataSpace); private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt); private synchronized native int nativeGetWidth(); Loading @@ -1304,10 +1278,10 @@ public class ImageWriter implements AutoCloseable { int transform, int scalingMode); private synchronized native int nativeAttachAndQueueImage(long nativeCtx, long imageNativeBuffer, int imageFormat, long timestampNs, int dataSpace, long imageNativeBuffer, int hardwareBufferFormat, long timestampNs, int dataSpace, int left, int top, int right, int bottom, int transform, int scalingMode); private synchronized native int nativeAttachAndQueueGraphicBuffer(long nativeCtx, GraphicBuffer graphicBuffer, int imageFormat, long timestampNs, int dataSpace, GraphicBuffer graphicBuffer, int hardwareBufferFormat, long timestampNs, int dataSpace, int left, int top, int right, int bottom, int transform, int scalingMode); private synchronized native void cancelImage(long nativeCtx, Image image); Loading media/jni/android_media_ImageReader.cpp +20 −24 Original line number Diff line number Diff line Loading @@ -375,11 +375,11 @@ static void ImageReader_classInit(JNIEnv* env, jclass clazz) } static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height, jint maxImages, jlong ndkUsage, jint nativeFormat, jint dataSpace) { jint maxImages, jlong ndkUsage, jint nativeHalFormat, jint dataSpace) { status_t res; ALOGV("%s: width:%d, height: %d, nativeFormat: %d, maxImages:%d", __FUNCTION__, width, height, nativeFormat, maxImages); ALOGV("%s: width:%d, height: %d, nativeHalFormat: %d, maxImages:%d", __FUNCTION__, width, height, nativeHalFormat, maxImages); android_dataspace nativeDataspace = static_cast<android_dataspace>(dataSpace); Loading @@ -395,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, nativeFormat, maxImages, getpid(), width, height, nativeHalFormat, maxImages, getpid(), createProcessUniqueId()); uint64_t consumerUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(ndkUsage); Loading @@ -404,8 +404,8 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w /*controlledByApp*/true); if (bufferConsumer == nullptr) { jniThrowExceptionFmt(env, "java/lang/RuntimeException", "Failed to allocate native buffer consumer for format 0x%x and usage 0x%x", nativeFormat, consumerUsage); "Failed to allocate native buffer consumer for hal format 0x%x and usage 0x%x", nativeHalFormat, consumerUsage); return; } Loading @@ -419,7 +419,7 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w ctx->setProducer(gbProducer); bufferConsumer->setFrameAvailableListener(ctx); ImageReader_setNativeContext(env, thiz, ctx); ctx->setBufferFormat(nativeFormat); ctx->setBufferFormat(nativeHalFormat); ctx->setBufferDataspace(nativeDataspace); ctx->setBufferWidth(width); ctx->setBufferHeight(height); Loading @@ -428,14 +428,14 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w res = bufferConsumer->setDefaultBufferSize(width, height); if (res != OK) { jniThrowExceptionFmt(env, "java/lang/IllegalStateException", "Failed to set buffer consumer default size (%dx%d) for format 0x%x", width, height, nativeFormat); "Failed to set buffer consumer default size (%dx%d) for Hal format 0x%x", width, height, nativeHalFormat); return; } res = bufferConsumer->setDefaultBufferFormat(nativeFormat); res = bufferConsumer->setDefaultBufferFormat(nativeHalFormat); if (res != OK) { jniThrowExceptionFmt(env, "java/lang/IllegalStateException", "Failed to set buffer consumer default format 0x%x", nativeFormat); "Failed to set buffer consumer default Halformat 0x%x", nativeHalFormat); return; } res = bufferConsumer->setDefaultBufferDataSpace(nativeDataspace); Loading Loading @@ -522,8 +522,7 @@ 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, jboolean legacyValidateImageFormat) { static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { Loading Loading @@ -577,29 +576,29 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image, int outputWidth = getBufferWidth(buffer); int outputHeight = getBufferHeight(buffer); int imgReaderFmt = ctx->getBufferFormat(); int imgReaderHalFmt = ctx->getBufferFormat(); int imageReaderWidth = ctx->getBufferWidth(); int imageReaderHeight = ctx->getBufferHeight(); int bufferFormat = buffer->mGraphicBuffer->getPixelFormat(); if ((bufferFormat != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) && if ((bufferFormat != HAL_PIXEL_FORMAT_BLOB) && (imgReaderHalFmt != HAL_PIXEL_FORMAT_BLOB) && (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) { ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d", __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight); } if (legacyValidateImageFormat && imgReaderFmt != bufferFormat) { if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && if (imgReaderHalFmt != bufferFormat) { if (imgReaderHalFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFormat)) { // Treat formats that are compatible with flexible YUV // (HAL_PIXEL_FORMAT_YCbCr_420_888) as HAL_PIXEL_FORMAT_YCbCr_420_888. ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCbCr_420_888", __FUNCTION__, bufferFormat); } else if (imgReaderFmt == HAL_PIXEL_FORMAT_YCBCR_P010 && } else if (imgReaderHalFmt == HAL_PIXEL_FORMAT_YCBCR_P010 && isPossibly10BitYUV(bufferFormat)) { // Treat formats that are compatible with flexible 10-bit YUV // (HAL_PIXEL_FORMAT_YCBCR_P010) as HAL_PIXEL_FORMAT_YCBCR_P010. ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCBCR_P010", __FUNCTION__, bufferFormat); } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && } else if (imgReaderHalFmt == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) { // Using HAL_PIXEL_FORMAT_RGBA_8888 Gralloc buffers containing JPEGs to get around // SW write limitations for (b/17379185). Loading Loading @@ -847,7 +846,7 @@ static jobjectArray ImageReader_createImagePlanes(JNIEnv* env, jobject /*thiz*/, } static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz, int numPlanes, int readerFormat, uint64_t ndkReaderUsage) int numPlanes, int halReaderFormat, uint64_t ndkReaderUsage) { ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes); int rowStride = 0; Loading @@ -856,9 +855,6 @@ static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz, uint32_t dataSize = 0; jobject byteBuffer = NULL; PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat); int halReaderFormat = mapPublicFormatToHalFormat(publicReaderFormat); if (isFormatOpaque(halReaderFormat) && numPlanes > 0) { String8 msg; msg.appendFormat("Format 0x%x is opaque, thus not writable, the number of planes (%d)" Loading Loading @@ -968,7 +964,7 @@ static const JNINativeMethod gImageReaderMethods[] = { {"nativeInit", "(Ljava/lang/Object;IIIJII)V", (void*)ImageReader_init }, {"nativeClose", "()V", (void*)ImageReader_close }, {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, {"nativeImageSetup", "(Landroid/media/Image;Z)I", (void*)ImageReader_imageSetup }, {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup }, {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, {"nativeDetachImage", "(Landroid/media/Image;Z)I", (void*)ImageReader_detachImage }, {"nativeCreateImagePlanes", Loading media/jni/android_media_ImageWriter.cpp +36 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
core/jni/android_hardware_camera2_utils_SurfaceUtils.cpp +14 −11 Original line number Diff line number Diff line Loading @@ -89,39 +89,42 @@ static sp<Surface> getSurface(JNIEnv* env, jobject surface) { extern "C" { static jint SurfaceUtils_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceType"); static jint SurfaceUtils_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceDataspace"); sp<ANativeWindow> anw; if ((anw = getNativeWindow(env, surface)) == NULL) { ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); return BAD_VALUE; } int32_t fmt = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &fmt); status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt); if (err != NO_ERROR) { ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), err); ALOGE("%s: Error while querying surface dataspace %s (%d).", __FUNCTION__, strerror(-err), err); OVERRIDE_SURFACE_ERROR(err); return err; } return fmt; } static jint SurfaceUtils_nativeDetectSurfaceDataspace(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceDataspace"); static jint SurfaceUtils_nativeDetectSurfaceType(JNIEnv* env, jobject thiz, jobject surface) { ALOGV("nativeDetectSurfaceType"); sp<ANativeWindow> anw; if ((anw = getNativeWindow(env, surface)) == NULL) { ALOGE("%s: Could not retrieve native window from surface.", __FUNCTION__); return BAD_VALUE; } int32_t fmt = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_DEFAULT_DATASPACE, &fmt); int32_t halFmt = 0; status_t err = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &halFmt); if (err != NO_ERROR) { ALOGE("%s: Error while querying surface dataspace %s (%d).", __FUNCTION__, strerror(-err), err); ALOGE("%s: Error while querying surface pixel format %s (%d).", __FUNCTION__, strerror(-err), err); OVERRIDE_SURFACE_ERROR(err); return err; } int32_t dataspace = SurfaceUtils_nativeDetectSurfaceDataspace(env, thiz, surface); int32_t fmt = static_cast<int32_t>( mapHalFormatDataspaceToPublicFormat(halFmt, static_cast<android_dataspace>(dataspace))); return fmt; } Loading
media/java/android/media/ImageReader.java +15 −42 Original line number Diff line number Diff line Loading @@ -314,7 +314,7 @@ public class ImageReader implements AutoCloseable { } private void initializeImageReader(int width, int height, int imageFormat, int maxImages, long usage, int hardwareBufferFormat, int dataSpace, boolean useLegacyImageFormat) { long usage, int hardwareBufferFormat, int dataSpace) { if (width < 1 || height < 1) { throw new IllegalArgumentException( "The image dimensions must be positive"); Loading Loading @@ -342,14 +342,8 @@ public class ImageReader implements AutoCloseable { // Only include memory for 1 buffer, since actually accounting for the memory used is // complex, and 1 buffer is enough for the VM to treat the ImageReader as being of some // size. if (hardwareBufferFormat == HardwareBuffer.BLOB) { mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( width, height, imageFormat, /*buffer count*/ 1); } else { mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes( width, height, useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1); } VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); } Loading @@ -364,11 +358,10 @@ public class ImageReader implements AutoCloseable { // 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); mDataSpace); } private ImageReader(int width, int height, int maxImages, long usage, Loading @@ -380,12 +373,11 @@ public class ImageReader implements AutoCloseable { mParent = parent; mHardwareBufferFormat = hardwareBufferFormat; mDataSpace = dataSpace; mUseLegacyImageFormat = false; mNumPlanes = ImageUtils.getNumPlanesForHardwareBufferFormat(mHardwareBufferFormat); mFormat = PublicFormatUtils.getPublicFormat(hardwareBufferFormat, dataSpace); initializeImageReader(width, height, mFormat, maxImages, usage, hardwareBufferFormat, dataSpace, mUseLegacyImageFormat); dataSpace); } /** Loading Loading @@ -579,12 +571,7 @@ public class ImageReader implements AutoCloseable { * @hide */ public Image acquireNextImageNoThrowISE() { SurfaceImage si; if (mUseLegacyImageFormat) { si = new SurfaceImage(mFormat); } else { si = new SurfaceImage(mHardwareBufferFormat, mDataSpace); } SurfaceImage si = new SurfaceImage(mFormat); return acquireNextSurfaceImage(si) == ACQUIRE_SUCCESS ? si : null; } Loading @@ -607,7 +594,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, mUseLegacyImageFormat); status = nativeImageSetup(si); } switch (status) { Loading Loading @@ -661,11 +648,7 @@ public class ImageReader implements AutoCloseable { // Initialize with reader format, but can be overwritten by native if the image // format is different from the reader format. SurfaceImage si; if (mUseLegacyImageFormat) { si = new SurfaceImage(mFormat); } else { si = new SurfaceImage(mHardwareBufferFormat, mDataSpace); } int status = acquireNextSurfaceImage(si); switch (status) { Loading Loading @@ -1142,8 +1125,6 @@ public class ImageReader implements AutoCloseable { private final @NamedDataSpace int mDataSpace; private final boolean mUseLegacyImageFormat; /** * This field is used by native code, do not access or modify. */ Loading Loading @@ -1184,12 +1165,6 @@ public class ImageReader implements AutoCloseable { mDataSpace = ImageReader.this.mDataSpace; } SurfaceImage(int hardwareBufferFormat, int dataSpace) { mHardwareBufferFormat = hardwareBufferFormat; mDataSpace = dataSpace; mFormat = PublicFormatUtils.getPublicFormat(mHardwareBufferFormat, mDataSpace); } @Override public void close() { synchronized (this.mCloseLock) { Loading @@ -1207,12 +1182,10 @@ public class ImageReader implements AutoCloseable { // 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; } Loading Loading @@ -1311,8 +1284,8 @@ public class ImageReader implements AutoCloseable { throwISEIfImageIsInvalid(); if (mPlanes == null) { mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mFormat, ImageReader.this.mUsage); mPlanes = nativeCreatePlanes(ImageReader.this.mNumPlanes, ImageReader.this.mHardwareBufferFormat, ImageReader.this.mUsage); } // Shallow copy is fine. return mPlanes.clone(); Loading Loading @@ -1443,7 +1416,7 @@ public class ImageReader implements AutoCloseable { private AtomicBoolean mIsDetached = new AtomicBoolean(false); private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int readerFormat, long readerUsage); int hardwareBufferFormat, long readerUsage); private synchronized native int nativeGetWidth(); private synchronized native int nativeGetHeight(); private synchronized native int nativeGetFormat(int readerFormat); Loading @@ -1466,7 +1439,7 @@ public class ImageReader implements AutoCloseable { * @see #ACQUIRE_NO_BUFS * @see #ACQUIRE_MAX_IMAGES */ private synchronized native int nativeImageSetup(Image i, boolean legacyValidateImageFormat); private synchronized native int nativeImageSetup(Image i); /** * @hide Loading
media/java/android/media/ImageWriter.java +16 −42 Original line number Diff line number Diff line Loading @@ -248,7 +248,7 @@ public class ImageWriter implements AutoCloseable { } private void initializeImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo, boolean useLegacyImageFormat, int imageFormat, boolean useSurfaceImageFormatInfo, int imageFormat, int hardwareBufferFormat, int dataSpace, int width, int height, long usage) { if (surface == null || maxImages < 1) { throw new IllegalArgumentException("Illegal input argument: surface " + surface Loading @@ -265,7 +265,7 @@ public class ImageWriter implements AutoCloseable { // nativeInit internally overrides UNKNOWN format. So does surface format query after // nativeInit and before getEstimatedNativeAllocBytes(). imageFormat = SurfaceUtils.getSurfaceFormat(surface); mDataSpace = dataSpace = PublicFormatUtils.getHalDataspace(dataSpace); mDataSpace = dataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mHardwareBufferFormat = hardwareBufferFormat = PublicFormatUtils.getHalFormat(imageFormat); } Loading @@ -280,37 +280,11 @@ public class ImageWriter implements AutoCloseable { mWidth = width == -1 ? surfSize.getWidth() : width; mHeight = height == -1 ? surfSize.getHeight() : height; if (hardwareBufferFormat == HardwareBuffer.BLOB) { // TODO(b/246344817): remove mWriterFormat and mDataSpace re-set here after fixing. mWriterFormat = imageFormat = getImageFormatByBLOB(dataSpace); mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight, imageFormat, /*buffer count*/ 1); } else { mEstimatedNativeAllocBytes = ImageUtils.getEstimatedNativeAllocBytes(mWidth, mHeight, useLegacyImageFormat ? imageFormat : hardwareBufferFormat, /*buffer count*/ 1); } VMRuntime.getRuntime().registerNativeAllocation(mEstimatedNativeAllocBytes); } // 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. private int getImageFormatByBLOB(int dataspace) { switch (dataspace) { case DataSpace.DATASPACE_DEPTH: return ImageFormat.DEPTH_POINT_CLOUD; case DataSpace.DATASPACE_DYNAMIC_DEPTH: return ImageFormat.DEPTH_JPEG; case DataSpace.DATASPACE_HEIF: return ImageFormat.HEIC; default: return ImageFormat.JPEG; } } private ImageWriter(Surface surface, int maxImages, boolean useSurfaceImageFormatInfo, int imageFormat, int width, int height) { mMaxImages = maxImages; Loading @@ -319,7 +293,7 @@ public class ImageWriter implements AutoCloseable { mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); } initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, imageFormat, mHardwareBufferFormat, mDataSpace, width, height, mUsage); } Loading @@ -332,7 +306,7 @@ public class ImageWriter implements AutoCloseable { mDataSpace = PublicFormatUtils.getHalDataspace(imageFormat); } initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, true, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, imageFormat, mHardwareBufferFormat, mDataSpace, width, height, usage); } Loading @@ -351,7 +325,7 @@ public class ImageWriter implements AutoCloseable { mDataSpace = dataSpace; } initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, false, initializeImageWriter(surface, maxImages, useSurfaceImageFormatInfo, imageFormat, hardwareBufferFormat, dataSpace, width, height, usage); } Loading Loading @@ -770,13 +744,15 @@ public class ImageWriter implements AutoCloseable { // need do some cleanup to make sure no orphaned // buffer caused leak. Rect crop = image.getCropRect(); int hardwareBufferFormat = PublicFormatUtils.getHalFormat(image.getFormat()); if (image.getNativeContext() != 0) { nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), image.getFormat(), image.getTimestamp(), image.getDataSpace(), crop.left, crop.top, crop.right, crop.bottom, image.getTransform(), image.getScalingMode()); nativeAttachAndQueueImage(mNativeContext, image.getNativeContext(), hardwareBufferFormat, image.getTimestamp(), image.getDataSpace(), crop.left, crop.top, crop.right, crop.bottom, image.getTransform(), image.getScalingMode()); } else { GraphicBuffer gb = GraphicBuffer.createFromHardwareBuffer(image.getHardwareBuffer()); nativeAttachAndQueueGraphicBuffer(mNativeContext, gb, image.getFormat(), nativeAttachAndQueueGraphicBuffer(mNativeContext, gb, hardwareBufferFormat, image.getTimestamp(), image.getDataSpace(), crop.left, crop.top, crop.right, crop.bottom, image.getTransform(), image.getScalingMode()); gb.destroy(); Loading Loading @@ -1167,8 +1143,7 @@ public class ImageWriter implements AutoCloseable { if (mPlanes == null) { int numPlanes = ImageUtils.getNumPlanesForFormat(getFormat()); mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat(), getOwner().getDataSpace()); mPlanes = nativeCreatePlanes(numPlanes, getOwner().getFormat()); } return mPlanes.clone(); Loading Loading @@ -1276,8 +1251,7 @@ public class ImageWriter implements AutoCloseable { } // Create the SurfacePlane object and fill the information private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt, int dataSpace); private synchronized native SurfacePlane[] nativeCreatePlanes(int numPlanes, int writerFmt); private synchronized native int nativeGetWidth(); Loading @@ -1304,10 +1278,10 @@ public class ImageWriter implements AutoCloseable { int transform, int scalingMode); private synchronized native int nativeAttachAndQueueImage(long nativeCtx, long imageNativeBuffer, int imageFormat, long timestampNs, int dataSpace, long imageNativeBuffer, int hardwareBufferFormat, long timestampNs, int dataSpace, int left, int top, int right, int bottom, int transform, int scalingMode); private synchronized native int nativeAttachAndQueueGraphicBuffer(long nativeCtx, GraphicBuffer graphicBuffer, int imageFormat, long timestampNs, int dataSpace, GraphicBuffer graphicBuffer, int hardwareBufferFormat, long timestampNs, int dataSpace, int left, int top, int right, int bottom, int transform, int scalingMode); private synchronized native void cancelImage(long nativeCtx, Image image); Loading
media/jni/android_media_ImageReader.cpp +20 −24 Original line number Diff line number Diff line Loading @@ -375,11 +375,11 @@ static void ImageReader_classInit(JNIEnv* env, jclass clazz) } static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint width, jint height, jint maxImages, jlong ndkUsage, jint nativeFormat, jint dataSpace) { jint maxImages, jlong ndkUsage, jint nativeHalFormat, jint dataSpace) { status_t res; ALOGV("%s: width:%d, height: %d, nativeFormat: %d, maxImages:%d", __FUNCTION__, width, height, nativeFormat, maxImages); ALOGV("%s: width:%d, height: %d, nativeHalFormat: %d, maxImages:%d", __FUNCTION__, width, height, nativeHalFormat, maxImages); android_dataspace nativeDataspace = static_cast<android_dataspace>(dataSpace); Loading @@ -395,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, nativeFormat, maxImages, getpid(), width, height, nativeHalFormat, maxImages, getpid(), createProcessUniqueId()); uint64_t consumerUsage = android_hardware_HardwareBuffer_convertToGrallocUsageBits(ndkUsage); Loading @@ -404,8 +404,8 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w /*controlledByApp*/true); if (bufferConsumer == nullptr) { jniThrowExceptionFmt(env, "java/lang/RuntimeException", "Failed to allocate native buffer consumer for format 0x%x and usage 0x%x", nativeFormat, consumerUsage); "Failed to allocate native buffer consumer for hal format 0x%x and usage 0x%x", nativeHalFormat, consumerUsage); return; } Loading @@ -419,7 +419,7 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w ctx->setProducer(gbProducer); bufferConsumer->setFrameAvailableListener(ctx); ImageReader_setNativeContext(env, thiz, ctx); ctx->setBufferFormat(nativeFormat); ctx->setBufferFormat(nativeHalFormat); ctx->setBufferDataspace(nativeDataspace); ctx->setBufferWidth(width); ctx->setBufferHeight(height); Loading @@ -428,14 +428,14 @@ static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, jint w res = bufferConsumer->setDefaultBufferSize(width, height); if (res != OK) { jniThrowExceptionFmt(env, "java/lang/IllegalStateException", "Failed to set buffer consumer default size (%dx%d) for format 0x%x", width, height, nativeFormat); "Failed to set buffer consumer default size (%dx%d) for Hal format 0x%x", width, height, nativeHalFormat); return; } res = bufferConsumer->setDefaultBufferFormat(nativeFormat); res = bufferConsumer->setDefaultBufferFormat(nativeHalFormat); if (res != OK) { jniThrowExceptionFmt(env, "java/lang/IllegalStateException", "Failed to set buffer consumer default format 0x%x", nativeFormat); "Failed to set buffer consumer default Halformat 0x%x", nativeHalFormat); return; } res = bufferConsumer->setDefaultBufferDataSpace(nativeDataspace); Loading Loading @@ -522,8 +522,7 @@ 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, jboolean legacyValidateImageFormat) { static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { Loading Loading @@ -577,29 +576,29 @@ static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image, int outputWidth = getBufferWidth(buffer); int outputHeight = getBufferHeight(buffer); int imgReaderFmt = ctx->getBufferFormat(); int imgReaderHalFmt = ctx->getBufferFormat(); int imageReaderWidth = ctx->getBufferWidth(); int imageReaderHeight = ctx->getBufferHeight(); int bufferFormat = buffer->mGraphicBuffer->getPixelFormat(); if ((bufferFormat != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) && if ((bufferFormat != HAL_PIXEL_FORMAT_BLOB) && (imgReaderHalFmt != HAL_PIXEL_FORMAT_BLOB) && (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) { ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d", __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight); } if (legacyValidateImageFormat && imgReaderFmt != bufferFormat) { if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && if (imgReaderHalFmt != bufferFormat) { if (imgReaderHalFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && isPossiblyYUV(bufferFormat)) { // Treat formats that are compatible with flexible YUV // (HAL_PIXEL_FORMAT_YCbCr_420_888) as HAL_PIXEL_FORMAT_YCbCr_420_888. ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCbCr_420_888", __FUNCTION__, bufferFormat); } else if (imgReaderFmt == HAL_PIXEL_FORMAT_YCBCR_P010 && } else if (imgReaderHalFmt == HAL_PIXEL_FORMAT_YCBCR_P010 && isPossibly10BitYUV(bufferFormat)) { // Treat formats that are compatible with flexible 10-bit YUV // (HAL_PIXEL_FORMAT_YCBCR_P010) as HAL_PIXEL_FORMAT_YCBCR_P010. ALOGV("%s: Treat buffer format to 0x%x as HAL_PIXEL_FORMAT_YCBCR_P010", __FUNCTION__, bufferFormat); } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && } else if (imgReaderHalFmt == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888) { // Using HAL_PIXEL_FORMAT_RGBA_8888 Gralloc buffers containing JPEGs to get around // SW write limitations for (b/17379185). Loading Loading @@ -847,7 +846,7 @@ static jobjectArray ImageReader_createImagePlanes(JNIEnv* env, jobject /*thiz*/, } static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz, int numPlanes, int readerFormat, uint64_t ndkReaderUsage) int numPlanes, int halReaderFormat, uint64_t ndkReaderUsage) { ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes); int rowStride = 0; Loading @@ -856,9 +855,6 @@ static jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz, uint32_t dataSize = 0; jobject byteBuffer = NULL; PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat); int halReaderFormat = mapPublicFormatToHalFormat(publicReaderFormat); if (isFormatOpaque(halReaderFormat) && numPlanes > 0) { String8 msg; msg.appendFormat("Format 0x%x is opaque, thus not writable, the number of planes (%d)" Loading Loading @@ -968,7 +964,7 @@ static const JNINativeMethod gImageReaderMethods[] = { {"nativeInit", "(Ljava/lang/Object;IIIJII)V", (void*)ImageReader_init }, {"nativeClose", "()V", (void*)ImageReader_close }, {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, {"nativeImageSetup", "(Landroid/media/Image;Z)I", (void*)ImageReader_imageSetup }, {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup }, {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, {"nativeDetachImage", "(Landroid/media/Image;Z)I", (void*)ImageReader_detachImage }, {"nativeCreateImagePlanes", Loading
media/jni/android_media_ImageWriter.cpp +36 −23 File changed.Preview size limit exceeded, changes collapsed. Show changes