android_media_ImageReader.cpp revision 9cc3f881df13583c93ca08668281413be6412414
1/* 2 * Copyright 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "ImageReader_JNI" 19#include <utils/Log.h> 20#include <utils/misc.h> 21#include <utils/List.h> 22#include <utils/String8.h> 23 24#include <cstdio> 25 26#include <gui/CpuConsumer.h> 27#include <gui/BufferItemConsumer.h> 28#include <gui/Surface.h> 29#include <camera3.h> 30 31#include <android_runtime/AndroidRuntime.h> 32#include <android_runtime/android_view_Surface.h> 33 34#include <jni.h> 35#include <JNIHelp.h> 36 37#include <stdint.h> 38#include <inttypes.h> 39 40#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 41 42#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext" 43#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mNativeBuffer" 44#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp" 45 46// ---------------------------------------------------------------------------- 47 48using namespace android; 49 50enum { 51 IMAGE_READER_MAX_NUM_PLANES = 3, 52}; 53 54enum { 55 ACQUIRE_SUCCESS = 0, 56 ACQUIRE_NO_BUFFERS = 1, 57 ACQUIRE_MAX_IMAGES = 2, 58}; 59 60static struct { 61 jfieldID mNativeContext; 62 jmethodID postEventFromNative; 63} gImageReaderClassInfo; 64 65static struct { 66 jfieldID mNativeBuffer; 67 jfieldID mTimestamp; 68} gSurfaceImageClassInfo; 69 70static struct { 71 jclass clazz; 72 jmethodID ctor; 73} gSurfacePlaneClassInfo; 74 75// Get an ID that's unique within this process. 76static int32_t createProcessUniqueId() { 77 static volatile int32_t globalCounter = 0; 78 return android_atomic_inc(&globalCounter); 79} 80 81// ---------------------------------------------------------------------------- 82 83class JNIImageReaderContext : public ConsumerBase::FrameAvailableListener 84{ 85public: 86 JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages); 87 88 virtual ~JNIImageReaderContext(); 89 90 virtual void onFrameAvailable(const BufferItem& item); 91 92 CpuConsumer::LockedBuffer* getLockedBuffer(); 93 void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer); 94 95 BufferItem* getOpaqueBuffer(); 96 void returnOpaqueBuffer(BufferItem* buffer); 97 98 void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; } 99 CpuConsumer* getCpuConsumer() { return mConsumer.get(); } 100 101 void setOpaqueConsumer(const sp<BufferItemConsumer>& consumer) { mOpaqueConsumer = consumer; } 102 BufferItemConsumer* getOpaqueConsumer() { return mOpaqueConsumer.get(); } 103 // This is the only opaque format exposed in the ImageFormat public API. 104 // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE 105 // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here. 106 bool isOpaque() { return mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; } 107 108 void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; } 109 IGraphicBufferProducer* getProducer() { return mProducer.get(); } 110 111 void setBufferFormat(int format) { mFormat = format; } 112 int getBufferFormat() { return mFormat; } 113 114 void setBufferDataspace(android_dataspace dataSpace) { mDataSpace = dataSpace; } 115 android_dataspace getBufferDataspace() { return mDataSpace; } 116 117 void setBufferWidth(int width) { mWidth = width; } 118 int getBufferWidth() { return mWidth; } 119 120 void setBufferHeight(int height) { mHeight = height; } 121 int getBufferHeight() { return mHeight; } 122 123private: 124 static JNIEnv* getJNIEnv(bool* needsDetach); 125 static void detachJNI(); 126 127 List<CpuConsumer::LockedBuffer*> mBuffers; 128 List<BufferItem*> mOpaqueBuffers; 129 sp<CpuConsumer> mConsumer; 130 sp<BufferItemConsumer> mOpaqueConsumer; 131 sp<IGraphicBufferProducer> mProducer; 132 jobject mWeakThiz; 133 jclass mClazz; 134 int mFormat; 135 android_dataspace mDataSpace; 136 int mWidth; 137 int mHeight; 138}; 139 140JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env, 141 jobject weakThiz, jclass clazz, int maxImages) : 142 mWeakThiz(env->NewGlobalRef(weakThiz)), 143 mClazz((jclass)env->NewGlobalRef(clazz)) { 144 for (int i = 0; i < maxImages; i++) { 145 CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer; 146 BufferItem* opaqueBuffer = new BufferItem; 147 mBuffers.push_back(buffer); 148 mOpaqueBuffers.push_back(opaqueBuffer); 149 } 150} 151 152JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) { 153 LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!"); 154 *needsDetach = false; 155 JNIEnv* env = AndroidRuntime::getJNIEnv(); 156 if (env == NULL) { 157 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 158 JavaVM* vm = AndroidRuntime::getJavaVM(); 159 int result = vm->AttachCurrentThread(&env, (void*) &args); 160 if (result != JNI_OK) { 161 ALOGE("thread attach failed: %#x", result); 162 return NULL; 163 } 164 *needsDetach = true; 165 } 166 return env; 167} 168 169void JNIImageReaderContext::detachJNI() { 170 JavaVM* vm = AndroidRuntime::getJavaVM(); 171 int result = vm->DetachCurrentThread(); 172 if (result != JNI_OK) { 173 ALOGE("thread detach failed: %#x", result); 174 } 175} 176 177CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() { 178 if (mBuffers.empty()) { 179 return NULL; 180 } 181 // Return a LockedBuffer pointer and remove it from the list 182 List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin(); 183 CpuConsumer::LockedBuffer* buffer = *it; 184 mBuffers.erase(it); 185 return buffer; 186} 187 188void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) { 189 mBuffers.push_back(buffer); 190} 191 192BufferItem* JNIImageReaderContext::getOpaqueBuffer() { 193 if (mOpaqueBuffers.empty()) { 194 return NULL; 195 } 196 // Return an opaque buffer pointer and remove it from the list 197 List<BufferItem*>::iterator it = mOpaqueBuffers.begin(); 198 BufferItem* buffer = *it; 199 mOpaqueBuffers.erase(it); 200 return buffer; 201} 202 203void JNIImageReaderContext::returnOpaqueBuffer(BufferItem* buffer) { 204 mOpaqueBuffers.push_back(buffer); 205} 206 207JNIImageReaderContext::~JNIImageReaderContext() { 208 bool needsDetach = false; 209 JNIEnv* env = getJNIEnv(&needsDetach); 210 if (env != NULL) { 211 env->DeleteGlobalRef(mWeakThiz); 212 env->DeleteGlobalRef(mClazz); 213 } else { 214 ALOGW("leaking JNI object references"); 215 } 216 if (needsDetach) { 217 detachJNI(); 218 } 219 220 // Delete LockedBuffers 221 for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin(); 222 it != mBuffers.end(); it++) { 223 delete *it; 224 } 225 226 // Delete opaque buffers 227 for (List<BufferItem *>::iterator it = mOpaqueBuffers.begin(); 228 it != mOpaqueBuffers.end(); it++) { 229 delete *it; 230 } 231 232 mBuffers.clear(); 233 if (mConsumer != 0) { 234 mConsumer.clear(); 235 } 236 if (mOpaqueConsumer != 0) { 237 mOpaqueConsumer.clear(); 238 } 239} 240 241void JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/) 242{ 243 ALOGV("%s: frame available", __FUNCTION__); 244 bool needsDetach = false; 245 JNIEnv* env = getJNIEnv(&needsDetach); 246 if (env != NULL) { 247 env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz); 248 } else { 249 ALOGW("onFrameAvailable event will not posted"); 250 } 251 if (needsDetach) { 252 detachJNI(); 253 } 254} 255 256// ---------------------------------------------------------------------------- 257 258extern "C" { 259 260static bool isFormatOpaque(int format) { 261 // Only treat IMPLEMENTATION_DEFINED as an opaque format for now. 262 return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; 263} 264 265static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz) 266{ 267 JNIImageReaderContext *ctx; 268 ctx = reinterpret_cast<JNIImageReaderContext *> 269 (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext)); 270 return ctx; 271} 272 273static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz) 274{ 275 ALOGV("%s:", __FUNCTION__); 276 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 277 if (ctx == NULL) { 278 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 279 return NULL; 280 } 281 282 if (ctx->isOpaque()) { 283 jniThrowException(env, "java/lang/IllegalStateException", 284 "Opaque ImageReader doesn't support this method"); 285 return NULL; 286 } 287 288 return ctx->getCpuConsumer(); 289} 290 291static IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz) 292{ 293 ALOGV("%s:", __FUNCTION__); 294 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 295 if (ctx == NULL) { 296 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 297 return NULL; 298 } 299 300 return ctx->getProducer(); 301} 302 303static void ImageReader_setNativeContext(JNIEnv* env, 304 jobject thiz, sp<JNIImageReaderContext> ctx) 305{ 306 ALOGV("%s:", __FUNCTION__); 307 JNIImageReaderContext* const p = ImageReader_getContext(env, thiz); 308 if (ctx != 0) { 309 ctx->incStrong((void*)ImageReader_setNativeContext); 310 } 311 if (p) { 312 p->decStrong((void*)ImageReader_setNativeContext); 313 } 314 env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext, 315 reinterpret_cast<jlong>(ctx.get())); 316} 317 318static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image) 319{ 320 return reinterpret_cast<CpuConsumer::LockedBuffer*>( 321 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer)); 322} 323 324static void Image_setBuffer(JNIEnv* env, jobject thiz, 325 const CpuConsumer::LockedBuffer* buffer) 326{ 327 env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer)); 328} 329 330static void Image_setOpaqueBuffer(JNIEnv* env, jobject thiz, 331 const BufferItem* buffer) 332{ 333 env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer)); 334} 335 336static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride) 337{ 338 ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 339 uint32_t size = 0; 340 uint32_t width = buffer->width; 341 uint8_t* jpegBuffer = buffer->data; 342 343 if (usingRGBAOverride) { 344 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4; 345 } 346 347 // First check for JPEG transport header at the end of the buffer 348 uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); 349 struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header); 350 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { 351 size = blob->jpeg_size; 352 ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); 353 } 354 355 // failed to find size, default to whole buffer 356 if (size == 0) { 357 /* 358 * This is a problem because not including the JPEG header 359 * means that in certain rare situations a regular JPEG blob 360 * will be misidentified as having a header, in which case 361 * we will get a garbage size value. 362 */ 363 ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", 364 __FUNCTION__, width); 365 size = width; 366 } 367 368 return size; 369} 370 371static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) { 372 return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888; 373} 374 375static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t readerCtxFormat) 376{ 377 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW 378 // write limitations for some platforms (b/17379185). 379 if (usingRGBAToJpegOverride(bufferFormat, readerCtxFormat)) { 380 return HAL_PIXEL_FORMAT_BLOB; 381 } 382 return bufferFormat; 383} 384 385static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 386 uint8_t **base, uint32_t *size, int32_t readerFormat) 387{ 388 ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 389 ALOG_ASSERT(base != NULL, "base is NULL!!!"); 390 ALOG_ASSERT(size != NULL, "size is NULL!!!"); 391 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); 392 393 ALOGV("%s: buffer: %p", __FUNCTION__, buffer); 394 395 uint32_t dataSize, ySize, cSize, cStride; 396 uint8_t *cb, *cr; 397 uint8_t *pData = NULL; 398 int bytesPerPixel = 0; 399 400 dataSize = ySize = cSize = cStride = 0; 401 int32_t fmt = buffer->flexFormat; 402 403 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat); 404 fmt = applyFormatOverrides(fmt, readerFormat); 405 switch (fmt) { 406 case HAL_PIXEL_FORMAT_YCbCr_420_888: 407 pData = 408 (idx == 0) ? 409 buffer->data : 410 (idx == 1) ? 411 buffer->dataCb : 412 buffer->dataCr; 413 // only map until last pixel 414 if (idx == 0) { 415 dataSize = buffer->stride * (buffer->height - 1) + buffer->width; 416 } else { 417 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) + 418 buffer->chromaStep * (buffer->width / 2 - 1) + 1; 419 } 420 break; 421 // NV21 422 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 423 cr = buffer->data + (buffer->stride * buffer->height); 424 cb = cr + 1; 425 // only map until last pixel 426 ySize = buffer->width * (buffer->height - 1) + buffer->width; 427 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1; 428 429 pData = 430 (idx == 0) ? 431 buffer->data : 432 (idx == 1) ? 433 cb: 434 cr; 435 436 dataSize = (idx == 0) ? ySize : cSize; 437 break; 438 case HAL_PIXEL_FORMAT_YV12: 439 // Y and C stride need to be 16 pixel aligned. 440 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 441 "Stride is not 16 pixel aligned %d", buffer->stride); 442 443 ySize = buffer->stride * buffer->height; 444 cStride = ALIGN(buffer->stride / 2, 16); 445 cr = buffer->data + ySize; 446 cSize = cStride * buffer->height / 2; 447 cb = cr + cSize; 448 449 pData = 450 (idx == 0) ? 451 buffer->data : 452 (idx == 1) ? 453 cb : 454 cr; 455 dataSize = (idx == 0) ? ySize : cSize; 456 break; 457 case HAL_PIXEL_FORMAT_Y8: 458 // Single plane, 8bpp. 459 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 460 461 pData = buffer->data; 462 dataSize = buffer->stride * buffer->height; 463 break; 464 case HAL_PIXEL_FORMAT_Y16: 465 bytesPerPixel = 2; 466 // Single plane, 16bpp, strides are specified in pixels, not in bytes 467 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 468 469 pData = buffer->data; 470 dataSize = buffer->stride * buffer->height * bytesPerPixel; 471 break; 472 case HAL_PIXEL_FORMAT_BLOB: 473 // Used for JPEG data, height must be 1, width == size, single plane. 474 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 475 ALOG_ASSERT(buffer->height == 1, 476 "JPEG should has height value one but got %d", buffer->height); 477 478 pData = buffer->data; 479 dataSize = Image_getJpegSize(buffer, usingRGBAOverride); 480 break; 481 case HAL_PIXEL_FORMAT_RAW16: 482 // Single plane 16bpp bayer data. 483 bytesPerPixel = 2; 484 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 485 pData = buffer->data; 486 dataSize = buffer->stride * buffer->height * bytesPerPixel; 487 break; 488 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 489 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane. 490 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 491 ALOG_ASSERT(buffer->height == 1, 492 "RAW_PRIVATE should has height value one but got %d", buffer->height); 493 pData = buffer->data; 494 dataSize = buffer->width; 495 break; 496 case HAL_PIXEL_FORMAT_RAW10: 497 // Single plane 10bpp bayer data. 498 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 499 LOG_ALWAYS_FATAL_IF(buffer->width % 4, 500 "Width is not multiple of 4 %d", buffer->width); 501 LOG_ALWAYS_FATAL_IF(buffer->height % 2, 502 "Height is not even %d", buffer->height); 503 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8), 504 "stride (%d) should be at least %d", 505 buffer->stride, buffer->width * 10 / 8); 506 pData = buffer->data; 507 dataSize = buffer->stride * buffer->height; 508 break; 509 case HAL_PIXEL_FORMAT_RAW12: 510 // Single plane 10bpp bayer data. 511 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 512 LOG_ALWAYS_FATAL_IF(buffer->width % 4, 513 "Width is not multiple of 4 %d", buffer->width); 514 LOG_ALWAYS_FATAL_IF(buffer->height % 2, 515 "Height is not even %d", buffer->height); 516 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8), 517 "stride (%d) should be at least %d", 518 buffer->stride, buffer->width * 12 / 8); 519 pData = buffer->data; 520 dataSize = buffer->stride * buffer->height; 521 break; 522 case HAL_PIXEL_FORMAT_RGBA_8888: 523 case HAL_PIXEL_FORMAT_RGBX_8888: 524 // Single plane, 32bpp. 525 bytesPerPixel = 4; 526 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 527 pData = buffer->data; 528 dataSize = buffer->stride * buffer->height * bytesPerPixel; 529 break; 530 case HAL_PIXEL_FORMAT_RGB_565: 531 // Single plane, 16bpp. 532 bytesPerPixel = 2; 533 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 534 pData = buffer->data; 535 dataSize = buffer->stride * buffer->height * bytesPerPixel; 536 break; 537 case HAL_PIXEL_FORMAT_RGB_888: 538 // Single plane, 24bpp. 539 bytesPerPixel = 3; 540 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 541 pData = buffer->data; 542 dataSize = buffer->stride * buffer->height * bytesPerPixel; 543 break; 544 default: 545 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 546 "Pixel format: 0x%x is unsupported", fmt); 547 break; 548 } 549 550 *base = pData; 551 *size = dataSize; 552} 553 554static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 555 int32_t halReaderFormat) 556{ 557 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 558 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx); 559 560 int pixelStride = 0; 561 ALOG_ASSERT(buffer != NULL, "buffer is NULL"); 562 563 int32_t fmt = buffer->flexFormat; 564 565 fmt = applyFormatOverrides(fmt, halReaderFormat); 566 567 switch (fmt) { 568 case HAL_PIXEL_FORMAT_YCbCr_420_888: 569 pixelStride = (idx == 0) ? 1 : buffer->chromaStep; 570 break; 571 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 572 pixelStride = (idx == 0) ? 1 : 2; 573 break; 574 case HAL_PIXEL_FORMAT_Y8: 575 // Single plane 8bpp data. 576 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 577 pixelStride = 1; 578 break; 579 case HAL_PIXEL_FORMAT_YV12: 580 pixelStride = 1; 581 break; 582 case HAL_PIXEL_FORMAT_BLOB: 583 case HAL_PIXEL_FORMAT_RAW10: 584 case HAL_PIXEL_FORMAT_RAW12: 585 // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data, 586 // those are single plane data with pixel stride 0 since they don't really have a 587 // well defined pixel stride 588 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 589 pixelStride = 0; 590 break; 591 case HAL_PIXEL_FORMAT_Y16: 592 case HAL_PIXEL_FORMAT_RAW16: 593 case HAL_PIXEL_FORMAT_RGB_565: 594 // Single plane 16bpp data. 595 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 596 pixelStride = 2; 597 break; 598 case HAL_PIXEL_FORMAT_RGBA_8888: 599 case HAL_PIXEL_FORMAT_RGBX_8888: 600 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 601 pixelStride = 4; 602 break; 603 case HAL_PIXEL_FORMAT_RGB_888: 604 // Single plane, 24bpp. 605 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 606 pixelStride = 3; 607 break; 608 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 609 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 610 pixelStride = 0; // RAW OPAQUE doesn't have pixel stride 611 break; 612 default: 613 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 614 "Pixel format: 0x%x is unsupported", fmt); 615 break; 616 } 617 618 return pixelStride; 619} 620 621static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 622 int32_t halReaderFormat) 623{ 624 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 625 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); 626 627 int rowStride = 0; 628 ALOG_ASSERT(buffer != NULL, "buffer is NULL"); 629 630 int32_t fmt = buffer->flexFormat; 631 632 fmt = applyFormatOverrides(fmt, halReaderFormat); 633 634 switch (fmt) { 635 case HAL_PIXEL_FORMAT_YCbCr_420_888: 636 rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride; 637 break; 638 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 639 rowStride = buffer->width; 640 break; 641 case HAL_PIXEL_FORMAT_YV12: 642 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 643 "Stride is not 16 pixel aligned %d", buffer->stride); 644 rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); 645 break; 646 case HAL_PIXEL_FORMAT_BLOB: 647 // Blob is used for JPEG data. It is single plane and has 0 row stride and 648 // 0 pixel stride 649 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 650 rowStride = 0; 651 break; 652 case HAL_PIXEL_FORMAT_RAW10: 653 case HAL_PIXEL_FORMAT_RAW12: 654 // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane 655 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 656 rowStride = buffer->stride; 657 break; 658 case HAL_PIXEL_FORMAT_Y8: 659 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 660 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 661 "Stride is not 16 pixel aligned %d", buffer->stride); 662 rowStride = buffer->stride; 663 break; 664 case HAL_PIXEL_FORMAT_Y16: 665 case HAL_PIXEL_FORMAT_RAW16: 666 // In native side, strides are specified in pixels, not in bytes. 667 // Single plane 16bpp bayer data. even width/height, 668 // row stride multiple of 16 pixels (32 bytes) 669 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 670 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 671 "Stride is not 16 pixel aligned %d", buffer->stride); 672 rowStride = buffer->stride * 2; 673 break; 674 case HAL_PIXEL_FORMAT_RGB_565: 675 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 676 rowStride = buffer->stride * 2; 677 break; 678 case HAL_PIXEL_FORMAT_RGBA_8888: 679 case HAL_PIXEL_FORMAT_RGBX_8888: 680 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 681 rowStride = buffer->stride * 4; 682 break; 683 case HAL_PIXEL_FORMAT_RGB_888: 684 // Single plane, 24bpp. 685 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 686 rowStride = buffer->stride * 3; 687 break; 688 case HAL_PIXEL_FORMAT_RAW_OPAQUE: 689 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 690 rowStride = 0; // RAW OPAQUE doesn't have row stride 691 break; 692 default: 693 ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt); 694 jniThrowException(env, "java/lang/UnsupportedOperationException", 695 "unsupported buffer format"); 696 break; 697 } 698 699 return rowStride; 700} 701 702static int Image_getBufferWidth(CpuConsumer::LockedBuffer* buffer) { 703 if (buffer == NULL) return -1; 704 705 if (!buffer->crop.isEmpty()) { 706 return buffer->crop.getWidth(); 707 } 708 return buffer->width; 709} 710 711static int Image_getBufferHeight(CpuConsumer::LockedBuffer* buffer) { 712 if (buffer == NULL) return -1; 713 714 if (!buffer->crop.isEmpty()) { 715 return buffer->crop.getHeight(); 716 } 717 return buffer->height; 718} 719 720// --------------------------Methods for opaque Image and ImageReader---------- 721 722static BufferItemConsumer* ImageReader_getOpaqueConsumer(JNIEnv* env, jobject thiz) 723{ 724 ALOGV("%s:", __FUNCTION__); 725 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 726 if (ctx == NULL) { 727 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 728 return NULL; 729 } 730 731 if (!ctx->isOpaque()) { 732 jniThrowException(env, "java/lang/IllegalStateException", 733 "Non-opaque ImageReader doesn't support this method"); 734 } 735 736 return ctx->getOpaqueConsumer(); 737} 738 739static BufferItem* Image_getOpaqueBuffer(JNIEnv* env, jobject image) 740{ 741 return reinterpret_cast<BufferItem*>( 742 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer)); 743} 744 745static int Image_getOpaqueBufferWidth(BufferItem* buffer) { 746 if (buffer == NULL) return -1; 747 748 if (!buffer->mCrop.isEmpty()) { 749 return buffer->mCrop.getWidth(); 750 } 751 return buffer->mGraphicBuffer->getWidth(); 752} 753 754static int Image_getOpaqueBufferHeight(BufferItem* buffer) { 755 if (buffer == NULL) return -1; 756 757 if (!buffer->mCrop.isEmpty()) { 758 return buffer->mCrop.getHeight(); 759 } 760 761 return buffer->mGraphicBuffer->getHeight(); 762} 763 764 765 766// ---------------------------------------------------------------------------- 767 768static void ImageReader_classInit(JNIEnv* env, jclass clazz) 769{ 770 ALOGV("%s:", __FUNCTION__); 771 772 jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage"); 773 LOG_ALWAYS_FATAL_IF(imageClazz == NULL, 774 "can't find android/graphics/ImageReader$SurfaceImage"); 775 gSurfaceImageClassInfo.mNativeBuffer = env->GetFieldID( 776 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J"); 777 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeBuffer == NULL, 778 "can't find android/graphics/ImageReader.%s", 779 ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID); 780 781 gSurfaceImageClassInfo.mTimestamp = env->GetFieldID( 782 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J"); 783 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL, 784 "can't find android/graphics/ImageReader.%s", 785 ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID); 786 787 gImageReaderClassInfo.mNativeContext = env->GetFieldID( 788 clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J"); 789 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL, 790 "can't find android/graphics/ImageReader.%s", 791 ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID); 792 793 gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID( 794 clazz, "postEventFromNative", "(Ljava/lang/Object;)V"); 795 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL, 796 "can't find android/graphics/ImageReader.postEventFromNative"); 797 798 jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane"); 799 LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class"); 800 // FindClass only gives a local reference of jclass object. 801 gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz); 802 gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>", 803 "(Landroid/media/ImageReader$SurfaceImage;III)V"); 804 LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL, 805 "Can not find SurfacePlane constructor"); 806} 807 808static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, 809 jint width, jint height, jint format, jint maxImages) 810{ 811 status_t res; 812 int nativeFormat; 813 android_dataspace nativeDataspace; 814 815 ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d", 816 __FUNCTION__, width, height, format, maxImages); 817 818 PublicFormat publicFormat = static_cast<PublicFormat>(format); 819 nativeFormat = android_view_Surface_mapPublicFormatToHalFormat( 820 publicFormat); 821 nativeDataspace = android_view_Surface_mapPublicFormatToHalDataspace( 822 publicFormat); 823 824 jclass clazz = env->GetObjectClass(thiz); 825 if (clazz == NULL) { 826 jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader"); 827 return; 828 } 829 sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages)); 830 831 sp<IGraphicBufferProducer> gbProducer; 832 sp<IGraphicBufferConsumer> gbConsumer; 833 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer); 834 sp<ConsumerBase> consumer; 835 sp<CpuConsumer> cpuConsumer; 836 sp<BufferItemConsumer> opaqueConsumer; 837 String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d", 838 width, height, format, maxImages, getpid(), 839 createProcessUniqueId()); 840 if (isFormatOpaque(nativeFormat)) { 841 // Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video 842 // encoding. The only possibility will be ZSL output. 843 opaqueConsumer = 844 new BufferItemConsumer(gbConsumer, GRALLOC_USAGE_SW_READ_NEVER, maxImages, 845 /*controlledByApp*/true); 846 if (opaqueConsumer == NULL) { 847 jniThrowRuntimeException(env, "Failed to allocate native opaque consumer"); 848 return; 849 } 850 ctx->setOpaqueConsumer(opaqueConsumer); 851 opaqueConsumer->setName(consumerName); 852 consumer = opaqueConsumer; 853 } else { 854 cpuConsumer = new CpuConsumer(gbConsumer, maxImages, /*controlledByApp*/true); 855 // TODO: throw dvm exOutOfMemoryError? 856 if (cpuConsumer == NULL) { 857 jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer"); 858 return; 859 } 860 ctx->setCpuConsumer(cpuConsumer); 861 cpuConsumer->setName(consumerName); 862 consumer = cpuConsumer; 863 } 864 865 ctx->setProducer(gbProducer); 866 consumer->setFrameAvailableListener(ctx); 867 ImageReader_setNativeContext(env, thiz, ctx); 868 ctx->setBufferFormat(nativeFormat); 869 ctx->setBufferDataspace(nativeDataspace); 870 ctx->setBufferWidth(width); 871 ctx->setBufferHeight(height); 872 873 // Set the width/height/format/dataspace to the CpuConsumer 874 // TODO: below code can be simplified once b/19977701 is fixed. 875 if (isFormatOpaque(nativeFormat)) { 876 res = opaqueConsumer->setDefaultBufferSize(width, height); 877 if (res != OK) { 878 jniThrowException(env, "java/lang/IllegalStateException", 879 "Failed to set opaque consumer buffer size"); 880 return; 881 } 882 res = opaqueConsumer->setDefaultBufferFormat(nativeFormat); 883 if (res != OK) { 884 jniThrowException(env, "java/lang/IllegalStateException", 885 "Failed to set opaque consumer buffer format"); 886 } 887 res = opaqueConsumer->setDefaultBufferDataSpace(nativeDataspace); 888 if (res != OK) { 889 jniThrowException(env, "java/lang/IllegalStateException", 890 "Failed to set opaque consumer buffer dataSpace"); 891 } 892 } else { 893 res = cpuConsumer->setDefaultBufferSize(width, height); 894 if (res != OK) { 895 jniThrowException(env, "java/lang/IllegalStateException", 896 "Failed to set CpuConsumer buffer size"); 897 return; 898 } 899 res = cpuConsumer->setDefaultBufferFormat(nativeFormat); 900 if (res != OK) { 901 jniThrowException(env, "java/lang/IllegalStateException", 902 "Failed to set CpuConsumer buffer format"); 903 } 904 res = cpuConsumer->setDefaultBufferDataSpace(nativeDataspace); 905 if (res != OK) { 906 jniThrowException(env, "java/lang/IllegalStateException", 907 "Failed to set CpuConsumer buffer dataSpace"); 908 } 909 } 910} 911 912static void ImageReader_close(JNIEnv* env, jobject thiz) 913{ 914 ALOGV("%s:", __FUNCTION__); 915 916 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 917 if (ctx == NULL) { 918 // ImageReader is already closed. 919 return; 920 } 921 922 ConsumerBase* consumer = NULL; 923 if (ctx->isOpaque()) { 924 consumer = ImageReader_getOpaqueConsumer(env, thiz); 925 } else { 926 consumer = ImageReader_getCpuConsumer(env, thiz); 927 } 928 929 if (consumer != NULL) { 930 consumer->abandon(); 931 consumer->setFrameAvailableListener(NULL); 932 } 933 ImageReader_setNativeContext(env, thiz, NULL); 934} 935 936static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image) 937{ 938 ALOGV("%s:", __FUNCTION__); 939 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 940 if (ctx == NULL) { 941 ALOGW("ImageReader#close called before Image#close, consider calling Image#close first"); 942 return; 943 } 944 945 if (ctx->isOpaque()) { 946 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer(); 947 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image); 948 opaqueConsumer->releaseBuffer(*opaqueBuffer); // Not using fence for now. 949 Image_setOpaqueBuffer(env, image, NULL); 950 ctx->returnOpaqueBuffer(opaqueBuffer); 951 ALOGV("%s: Opaque Image has been released", __FUNCTION__); 952 } else { 953 CpuConsumer* consumer = ctx->getCpuConsumer(); 954 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image); 955 if (!buffer) { 956 // Release an already closed image is harmless. 957 return; 958 } 959 consumer->unlockBuffer(*buffer); 960 Image_setBuffer(env, image, NULL); 961 ctx->returnLockedBuffer(buffer); 962 ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat()); 963 } 964} 965 966static jint ImageReader_opaqueImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) { 967 ALOGV("%s:", __FUNCTION__); 968 if (ctx == NULL || !ctx->isOpaque()) { 969 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 970 return -1; 971 } 972 973 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer(); 974 BufferItem* buffer = ctx->getOpaqueBuffer(); 975 if (buffer == NULL) { 976 ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than" 977 " maxImages buffers"); 978 return ACQUIRE_MAX_IMAGES; 979 } 980 981 status_t res = opaqueConsumer->acquireBuffer(buffer, 0); 982 if (res != OK) { 983 ctx->returnOpaqueBuffer(buffer); 984 if (res == INVALID_OPERATION) { 985 // Max number of images were already acquired. 986 ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)", 987 __FUNCTION__, strerror(-res), res); 988 return ACQUIRE_MAX_IMAGES; 989 } else { 990 ALOGE("%s: Acquire image failed with error: %s (%d)", 991 __FUNCTION__, strerror(-res), res); 992 return ACQUIRE_NO_BUFFERS; 993 } 994 } 995 996 // Set SurfaceImage instance member variables 997 Image_setOpaqueBuffer(env, image, buffer); 998 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp, 999 static_cast<jlong>(buffer->mTimestamp)); 1000 1001 return ACQUIRE_SUCCESS; 1002} 1003 1004static jint ImageReader_lockedImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) { 1005 CpuConsumer* consumer = ctx->getCpuConsumer(); 1006 CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer(); 1007 if (buffer == NULL) { 1008 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than" 1009 " maxImages buffers"); 1010 return ACQUIRE_MAX_IMAGES; 1011 } 1012 status_t res = consumer->lockNextBuffer(buffer); 1013 if (res != NO_ERROR) { 1014 ctx->returnLockedBuffer(buffer); 1015 if (res != BAD_VALUE /*no buffers*/) { 1016 if (res == NOT_ENOUGH_DATA) { 1017 return ACQUIRE_MAX_IMAGES; 1018 } else { 1019 ALOGE("%s Fail to lockNextBuffer with error: %d ", 1020 __FUNCTION__, res); 1021 jniThrowExceptionFmt(env, "java/lang/AssertionError", 1022 "Unknown error (%d) when we tried to lock buffer.", 1023 res); 1024 } 1025 } 1026 return ACQUIRE_NO_BUFFERS; 1027 } 1028 1029 if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) { 1030 jniThrowException(env, "java/lang/UnsupportedOperationException", 1031 "NV21 format is not supported by ImageReader"); 1032 return -1; 1033 } 1034 1035 // Check if the left-top corner of the crop rect is origin, we currently assume this point is 1036 // zero, will revist this once this assumption turns out problematic. 1037 Point lt = buffer->crop.leftTop(); 1038 if (lt.x != 0 || lt.y != 0) { 1039 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 1040 "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y); 1041 return -1; 1042 } 1043 1044 // Check if the producer buffer configurations match what ImageReader configured. 1045 int outputWidth = Image_getBufferWidth(buffer); 1046 int outputHeight = Image_getBufferHeight(buffer); 1047 1048 int imgReaderFmt = ctx->getBufferFormat(); 1049 int imageReaderWidth = ctx->getBufferWidth(); 1050 int imageReaderHeight = ctx->getBufferHeight(); 1051 if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) && 1052 (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) { 1053 ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d", 1054 __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight); 1055 } 1056 1057 int bufFmt = buffer->format; 1058 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) { 1059 bufFmt = buffer->flexFormat; 1060 } 1061 if (imgReaderFmt != bufFmt) { 1062 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt == 1063 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) { 1064 // Special casing for when producer switches to a format compatible with flexible YUV 1065 // (HAL_PIXEL_FORMAT_YCbCr_420_888). 1066 ctx->setBufferFormat(bufFmt); 1067 ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt); 1068 } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufFmt == HAL_PIXEL_FORMAT_RGBA_8888) { 1069 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW 1070 // write limitations for (b/17379185). 1071 ALOGD("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__); 1072 } else { 1073 // Return the buffer to the queue. 1074 consumer->unlockBuffer(*buffer); 1075 ctx->returnLockedBuffer(buffer); 1076 1077 // Throw exception 1078 ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x", 1079 buffer->format, ctx->getBufferFormat()); 1080 String8 msg; 1081 msg.appendFormat("The producer output buffer format 0x%x doesn't " 1082 "match the ImageReader's configured buffer format 0x%x.", 1083 bufFmt, ctx->getBufferFormat()); 1084 jniThrowException(env, "java/lang/UnsupportedOperationException", 1085 msg.string()); 1086 return -1; 1087 } 1088 } 1089 // Set SurfaceImage instance member variables 1090 Image_setBuffer(env, image, buffer); 1091 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp, 1092 static_cast<jlong>(buffer->timestamp)); 1093 1094 return ACQUIRE_SUCCESS; 1095} 1096 1097static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) { 1098 ALOGV("%s:", __FUNCTION__); 1099 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 1100 if (ctx == NULL) { 1101 jniThrowException(env, "java/lang/IllegalStateException", 1102 "ImageReader is not initialized or was already closed"); 1103 return -1; 1104 } 1105 1106 if (ctx->isOpaque()) { 1107 return ImageReader_opaqueImageSetup(env, ctx, image); 1108 } else { 1109 return ImageReader_lockedImageSetup(env, ctx, image); 1110 } 1111} 1112 1113static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) { 1114 ALOGV("%s:", __FUNCTION__); 1115 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 1116 if (ctx == NULL) { 1117 jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed"); 1118 return -1; 1119 } 1120 1121 status_t res = OK; 1122 if (!ctx->isOpaque()) { 1123 // TODO: Non-Opaque format detach is not implemented yet. 1124 jniThrowRuntimeException(env, 1125 "nativeDetachImage is not implemented yet for non-opaque format !!!"); 1126 return -1; 1127 } 1128 1129 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer(); 1130 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image); 1131 if (!opaqueBuffer) { 1132 ALOGE( 1133 "Opaque Image already released and can not be detached from ImageReader!!!"); 1134 jniThrowException(env, "java/lang/IllegalStateException", 1135 "Opaque Image detach from ImageReader failed: buffer was already released"); 1136 return -1; 1137 } 1138 1139 res = opaqueConsumer->detachBuffer(opaqueBuffer->mSlot); 1140 if (res != OK) { 1141 ALOGE("Opaque Image detach failed: %s (%d)!!!", strerror(-res), res); 1142 jniThrowRuntimeException(env, 1143 "nativeDetachImage failed for opaque image!!!"); 1144 return res; 1145 } 1146 return OK; 1147} 1148 1149static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz) 1150{ 1151 ALOGV("%s: ", __FUNCTION__); 1152 1153 IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz); 1154 if (gbp == NULL) { 1155 jniThrowRuntimeException(env, "CpuConsumer is uninitialized"); 1156 return NULL; 1157 } 1158 1159 // Wrap the IGBP in a Java-language Surface. 1160 return android_view_Surface_createFromIGraphicBufferProducer(env, gbp); 1161} 1162 1163static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat) 1164{ 1165 int rowStride, pixelStride; 1166 PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat); 1167 int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat( 1168 publicReaderFormat); 1169 1170 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 1171 if (isFormatOpaque(halReaderFormat)) { 1172 jniThrowException(env, "java/lang/IllegalStateException", 1173 "Opaque images from Opaque ImageReader do not have any planes"); 1174 return NULL; 1175 } 1176 1177 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 1178 1179 ALOG_ASSERT(buffer != NULL); 1180 if (buffer == NULL) { 1181 jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); 1182 } 1183 1184 rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat); 1185 pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat); 1186 1187 jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz, 1188 gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride); 1189 1190 return surfPlaneObj; 1191} 1192 1193static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat) 1194{ 1195 uint8_t *base = NULL; 1196 uint32_t size = 0; 1197 jobject byteBuffer; 1198 PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat); 1199 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat( 1200 readerPublicFormat); 1201 1202 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 1203 1204 if (isFormatOpaque(readerHalFormat)) { 1205 jniThrowException(env, "java/lang/IllegalStateException", 1206 "Opaque images from Opaque ImageReader do not have any plane"); 1207 return NULL; 1208 } 1209 1210 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 1211 1212 if (buffer == NULL) { 1213 jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); 1214 } 1215 1216 // Create byteBuffer from native buffer 1217 Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat); 1218 1219 if (size > static_cast<uint32_t>(INT32_MAX)) { 1220 // Byte buffer have 'int capacity', so check the range 1221 jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 1222 "Size too large for bytebuffer capacity %" PRIu32, size); 1223 return NULL; 1224 } 1225 1226 byteBuffer = env->NewDirectByteBuffer(base, size); 1227 // TODO: throw dvm exOutOfMemoryError? 1228 if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) { 1229 jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer"); 1230 } 1231 1232 return byteBuffer; 1233} 1234 1235static jint Image_getWidth(JNIEnv* env, jobject thiz, jint format) 1236{ 1237 if (isFormatOpaque(format)) { 1238 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz); 1239 return Image_getOpaqueBufferWidth(opaqueBuffer); 1240 } else { 1241 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 1242 return Image_getBufferWidth(buffer); 1243 } 1244} 1245 1246static jint Image_getHeight(JNIEnv* env, jobject thiz, jint format) 1247{ 1248 if (isFormatOpaque(format)) { 1249 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz); 1250 return Image_getOpaqueBufferHeight(opaqueBuffer); 1251 } else { 1252 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 1253 return Image_getBufferHeight(buffer); 1254 } 1255} 1256 1257static jint Image_getFormat(JNIEnv* env, jobject thiz, jint readerFormat) 1258{ 1259 if (isFormatOpaque(readerFormat)) { 1260 // Assuming opaque reader produce opaque images. 1261 return static_cast<jint>(PublicFormat::PRIVATE); 1262 } else { 1263 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 1264 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat( 1265 static_cast<PublicFormat>(readerFormat)); 1266 int32_t fmt = applyFormatOverrides(buffer->flexFormat, readerHalFormat); 1267 // Override the image format to HAL_PIXEL_FORMAT_YCbCr_420_888 if the actual format is 1268 // NV21 or YV12. This could only happen when the Gralloc HAL version is v0.1 thus doesn't 1269 // support lockycbcr(), the CpuConsumer need to use the lock() method in the 1270 // lockNextBuffer() call. For Gralloc HAL v0.2 or newer, this format should already be 1271 // overridden to HAL_PIXEL_FORMAT_YCbCr_420_888 for the flexible YUV compatible formats. 1272 if (fmt == HAL_PIXEL_FORMAT_YCrCb_420_SP || fmt == HAL_PIXEL_FORMAT_YV12) { 1273 fmt = HAL_PIXEL_FORMAT_YCbCr_420_888; 1274 } 1275 PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat( 1276 fmt, buffer->dataSpace); 1277 return static_cast<jint>(publicFmt); 1278 } 1279} 1280 1281} // extern "C" 1282 1283// ---------------------------------------------------------------------------- 1284 1285static const JNINativeMethod gImageReaderMethods[] = { 1286 {"nativeClassInit", "()V", (void*)ImageReader_classInit }, 1287 {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init }, 1288 {"nativeClose", "()V", (void*)ImageReader_close }, 1289 {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, 1290 {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup }, 1291 {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, 1292 {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage }, 1293}; 1294 1295static const JNINativeMethod gImageMethods[] = { 1296 {"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer }, 1297 {"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;", 1298 (void*)Image_createSurfacePlane }, 1299 {"nativeGetWidth", "(I)I", (void*)Image_getWidth }, 1300 {"nativeGetHeight", "(I)I", (void*)Image_getHeight }, 1301 {"nativeGetFormat", "(I)I", (void*)Image_getFormat }, 1302}; 1303 1304int register_android_media_ImageReader(JNIEnv *env) { 1305 1306 int ret1 = AndroidRuntime::registerNativeMethods(env, 1307 "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods)); 1308 1309 int ret2 = AndroidRuntime::registerNativeMethods(env, 1310 "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods)); 1311 1312 return (ret1 || ret2); 1313} 1314