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