static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed"); return -1; } BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer(); BufferItem* buffer = Image_getBufferItem(env, image); if (!buffer) { ALOGE( "Image already released and can not be detached from ImageReader!!!"); jniThrowException(env, "java/lang/IllegalStateException", "Image detach from ImageReader failed: buffer was already released"); return -1; } status_t res = OK; Image_unlockIfLocked(env, image); res = bufferConsumer->detachBuffer(buffer->mSlot); if (res != OK) { ALOGE("Image detach failed: %s (%d)!!!", strerror(-res), res); jniThrowRuntimeException(env, "nativeDetachImage failed for image!!!"); return res; } return OK; }
static void ImageReader_discardFreeBuffers(JNIEnv* env, jobject thiz) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed"); return; } BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer(); status_t res = bufferConsumer->discardFreeBuffers(); if (res != OK) { ALOGE("Buffer discard failed: %s (%d)", strerror(-res), res); jniThrowRuntimeException(env, "nativeDicardFreebuffers failed"); } }
static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { ALOGW("ImageReader#close called before Image#close, consider calling Image#close first"); return; } BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer(); BufferItem* buffer = Image_getBufferItem(env, image); if (buffer == nullptr) { // Release an already closed image is harmless. return; } sp<Fence> releaseFence = Image_unlockIfLocked(env, image); bufferConsumer->releaseBuffer(*buffer, releaseFence); Image_setBufferItem(env, image, NULL); ctx->returnBufferItem(buffer); ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat()); }
static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) { ALOGV("%s:", __FUNCTION__); JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); if (ctx == NULL) { jniThrowException(env, "java/lang/IllegalStateException", "ImageReader is not initialized or was already closed"); return -1; } BufferItemConsumer* bufferConsumer = ctx->getBufferConsumer(); BufferItem* buffer = ctx->getBufferItem(); if (buffer == NULL) { ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than" " maxImages buffers"); return ACQUIRE_MAX_IMAGES; } status_t res = bufferConsumer->acquireBuffer(buffer, 0); if (res != OK) { ctx->returnBufferItem(buffer); if (res != BufferQueue::NO_BUFFER_AVAILABLE) { if (res == INVALID_OPERATION) { // Max number of images were already acquired. ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)", __FUNCTION__, strerror(-res), res); return ACQUIRE_MAX_IMAGES; } else { ALOGE("%s: Acquire image failed with some unknown error: %s (%d)", __FUNCTION__, strerror(-res), res); jniThrowExceptionFmt(env, "java/lang/IllegalStateException", "Unknown error (%d) when we tried to acquire an image.", res); return ACQUIRE_NO_BUFFERS; } } // This isn't really an error case, as the application may acquire buffer at any time. return ACQUIRE_NO_BUFFERS; } // Add some extra checks for non-opaque formats. if (!isFormatOpaque(ctx->getBufferFormat())) { // Check if the left-top corner of the crop rect is origin, we currently assume this point is // zero, will revisit this once this assumption turns out problematic. Point lt = buffer->mCrop.leftTop(); if (lt.x != 0 || lt.y != 0) { jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y); return -1; } // Check if the producer buffer configurations match what ImageReader configured. int outputWidth = getBufferWidth(buffer); int outputHeight = getBufferHeight(buffer); int imgReaderFmt = 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) && (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 (imgReaderFmt != bufferFormat) { if (imgReaderFmt == 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_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). ALOGV("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__); } else { // Return the buffer to the queue. No need to provide fence, as this buffer wasn't // used anywhere yet. bufferConsumer->releaseBuffer(*buffer); ctx->returnBufferItem(buffer); // Throw exception ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x", bufferFormat, ctx->getBufferFormat()); String8 msg; msg.appendFormat("The producer output buffer format 0x%x doesn't " "match the ImageReader's configured buffer format 0x%x.", bufferFormat, ctx->getBufferFormat()); jniThrowException(env, "java/lang/UnsupportedOperationException", msg.string()); return -1; } } } // Set SurfaceImage instance member variables Image_setBufferItem(env, image, buffer); env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp, static_cast<jlong>(buffer->mTimestamp)); return ACQUIRE_SUCCESS; }