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/Surface.h> 28 #include <camera3.h> 29 30 #include <android_runtime/AndroidRuntime.h> 31 #include <android_runtime/android_view_Surface.h> 32 33 #include <jni.h> 34 #include <JNIHelp.h> 35 36 #include <stdint.h> 37 #include <inttypes.h> 38 39 #define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 40 41 #define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext" 42 #define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mLockedBuffer" 43 #define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp" 44 45 // ---------------------------------------------------------------------------- 46 47 using namespace android; 48 49 enum { 50 IMAGE_READER_MAX_NUM_PLANES = 3, 51 }; 52 53 enum { 54 ACQUIRE_SUCCESS = 0, 55 ACQUIRE_NO_BUFFERS = 1, 56 ACQUIRE_MAX_IMAGES = 2, 57 }; 58 59 static struct { 60 jfieldID mNativeContext; 61 jmethodID postEventFromNative; 62 } gImageReaderClassInfo; 63 64 static struct { 65 jfieldID mLockedBuffer; 66 jfieldID mTimestamp; 67 } gSurfaceImageClassInfo; 68 69 static struct { 70 jclass clazz; 71 jmethodID ctor; 72 } gSurfacePlaneClassInfo; 73 74 // ---------------------------------------------------------------------------- 75 76 class JNIImageReaderContext : public CpuConsumer::FrameAvailableListener 77 { 78 public: 79 JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages); 80 81 virtual ~JNIImageReaderContext(); 82 83 virtual void onFrameAvailable(const BufferItem& item); 84 85 CpuConsumer::LockedBuffer* getLockedBuffer(); 86 87 void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer); 88 89 void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; } 90 CpuConsumer* getCpuConsumer() { return mConsumer.get(); } 91 92 void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; } 93 IGraphicBufferProducer* getProducer() { return mProducer.get(); } 94 95 void setBufferFormat(int format) { mFormat = format; } 96 int getBufferFormat() { return mFormat; } 97 98 void setBufferWidth(int width) { mWidth = width; } 99 int getBufferWidth() { return mWidth; } 100 101 void setBufferHeight(int height) { mHeight = height; } 102 int getBufferHeight() { return mHeight; } 103 104 private: 105 static JNIEnv* getJNIEnv(bool* needsDetach); 106 static void detachJNI(); 107 108 List<CpuConsumer::LockedBuffer*> mBuffers; 109 sp<CpuConsumer> mConsumer; 110 sp<IGraphicBufferProducer> mProducer; 111 jobject mWeakThiz; 112 jclass mClazz; 113 int mFormat; 114 int mWidth; 115 int mHeight; 116 }; 117 118 JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env, 119 jobject weakThiz, jclass clazz, int maxImages) : 120 mWeakThiz(env->NewGlobalRef(weakThiz)), 121 mClazz((jclass)env->NewGlobalRef(clazz)) { 122 for (int i = 0; i < maxImages; i++) { 123 CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer; 124 mBuffers.push_back(buffer); 125 } 126 } 127 128 JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) { 129 LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!"); 130 *needsDetach = false; 131 JNIEnv* env = AndroidRuntime::getJNIEnv(); 132 if (env == NULL) { 133 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 134 JavaVM* vm = AndroidRuntime::getJavaVM(); 135 int result = vm->AttachCurrentThread(&env, (void*) &args); 136 if (result != JNI_OK) { 137 ALOGE("thread attach failed: %#x", result); 138 return NULL; 139 } 140 *needsDetach = true; 141 } 142 return env; 143 } 144 145 void JNIImageReaderContext::detachJNI() { 146 JavaVM* vm = AndroidRuntime::getJavaVM(); 147 int result = vm->DetachCurrentThread(); 148 if (result != JNI_OK) { 149 ALOGE("thread detach failed: %#x", result); 150 } 151 } 152 153 CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() { 154 if (mBuffers.empty()) { 155 return NULL; 156 } 157 // Return a LockedBuffer pointer and remove it from the list 158 List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin(); 159 CpuConsumer::LockedBuffer* buffer = *it; 160 mBuffers.erase(it); 161 return buffer; 162 } 163 164 void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) { 165 mBuffers.push_back(buffer); 166 } 167 168 JNIImageReaderContext::~JNIImageReaderContext() { 169 bool needsDetach = false; 170 JNIEnv* env = getJNIEnv(&needsDetach); 171 if (env != NULL) { 172 env->DeleteGlobalRef(mWeakThiz); 173 env->DeleteGlobalRef(mClazz); 174 } else { 175 ALOGW("leaking JNI object references"); 176 } 177 if (needsDetach) { 178 detachJNI(); 179 } 180 181 // Delete LockedBuffers 182 for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin(); 183 it != mBuffers.end(); it++) { 184 delete *it; 185 } 186 mBuffers.clear(); 187 mConsumer.clear(); 188 } 189 190 void JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/) 191 { 192 ALOGV("%s: frame available", __FUNCTION__); 193 bool needsDetach = false; 194 JNIEnv* env = getJNIEnv(&needsDetach); 195 if (env != NULL) { 196 env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz); 197 } else { 198 ALOGW("onFrameAvailable event will not posted"); 199 } 200 if (needsDetach) { 201 detachJNI(); 202 } 203 } 204 205 // ---------------------------------------------------------------------------- 206 207 extern "C" { 208 209 static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz) 210 { 211 JNIImageReaderContext *ctx; 212 ctx = reinterpret_cast<JNIImageReaderContext *> 213 (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext)); 214 return ctx; 215 } 216 217 static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz) 218 { 219 ALOGV("%s:", __FUNCTION__); 220 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 221 if (ctx == NULL) { 222 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 223 return NULL; 224 } 225 return ctx->getCpuConsumer(); 226 } 227 228 static IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz) 229 { 230 ALOGV("%s:", __FUNCTION__); 231 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 232 if (ctx == NULL) { 233 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 234 return NULL; 235 } 236 return ctx->getProducer(); 237 } 238 239 static void ImageReader_setNativeContext(JNIEnv* env, 240 jobject thiz, sp<JNIImageReaderContext> ctx) 241 { 242 ALOGV("%s:", __FUNCTION__); 243 JNIImageReaderContext* const p = ImageReader_getContext(env, thiz); 244 if (ctx != 0) { 245 ctx->incStrong((void*)ImageReader_setNativeContext); 246 } 247 if (p) { 248 p->decStrong((void*)ImageReader_setNativeContext); 249 } 250 env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext, 251 reinterpret_cast<jlong>(ctx.get())); 252 } 253 254 static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image) 255 { 256 return reinterpret_cast<CpuConsumer::LockedBuffer*>( 257 env->GetLongField(image, gSurfaceImageClassInfo.mLockedBuffer)); 258 } 259 260 static void Image_setBuffer(JNIEnv* env, jobject thiz, 261 const CpuConsumer::LockedBuffer* buffer) 262 { 263 env->SetLongField(thiz, gSurfaceImageClassInfo.mLockedBuffer, reinterpret_cast<jlong>(buffer)); 264 } 265 266 // Some formats like JPEG defined with different values between android.graphics.ImageFormat and 267 // graphics.h, need convert to the one defined in graphics.h here. 268 static int Image_getPixelFormat(JNIEnv* env, int format) 269 { 270 int jpegFormat; 271 jfieldID fid; 272 273 ALOGV("%s: format = 0x%x", __FUNCTION__, format); 274 275 jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat"); 276 ALOG_ASSERT(imageFormatClazz != NULL); 277 278 fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I"); 279 jpegFormat = env->GetStaticIntField(imageFormatClazz, fid); 280 281 // Translate the JPEG to BLOB for camera purpose. 282 if (format == jpegFormat) { 283 format = HAL_PIXEL_FORMAT_BLOB; 284 } 285 286 return format; 287 } 288 289 static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride) 290 { 291 ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 292 uint32_t size = 0; 293 uint32_t width = buffer->width; 294 uint8_t* jpegBuffer = buffer->data; 295 296 if (usingRGBAOverride) { 297 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4; 298 } 299 300 // First check for JPEG transport header at the end of the buffer 301 uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); 302 struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header); 303 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { 304 size = blob->jpeg_size; 305 ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); 306 } 307 308 // failed to find size, default to whole buffer 309 if (size == 0) { 310 /* 311 * This is a problem because not including the JPEG header 312 * means that in certain rare situations a regular JPEG blob 313 * will be misidentified as having a header, in which case 314 * we will get a garbage size value. 315 */ 316 ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", 317 __FUNCTION__, width); 318 size = width; 319 } 320 321 return size; 322 } 323 324 static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) { 325 return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888; 326 } 327 328 static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t readerCtxFormat) 329 { 330 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW 331 // write limitations for some platforms (b/17379185). 332 if (usingRGBAToJpegOverride(bufferFormat, readerCtxFormat)) { 333 return HAL_PIXEL_FORMAT_BLOB; 334 } 335 return bufferFormat; 336 } 337 338 static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 339 uint8_t **base, uint32_t *size, int32_t readerFormat) 340 { 341 ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 342 ALOG_ASSERT(base != NULL, "base is NULL!!!"); 343 ALOG_ASSERT(size != NULL, "size is NULL!!!"); 344 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); 345 346 ALOGV("%s: buffer: %p", __FUNCTION__, buffer); 347 348 uint32_t dataSize, ySize, cSize, cStride; 349 uint8_t *cb, *cr; 350 uint8_t *pData = NULL; 351 int bytesPerPixel = 0; 352 353 dataSize = ySize = cSize = cStride = 0; 354 int32_t fmt = buffer->flexFormat; 355 356 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat); 357 fmt = applyFormatOverrides(fmt, readerFormat); 358 switch (fmt) { 359 case HAL_PIXEL_FORMAT_YCbCr_420_888: 360 pData = 361 (idx == 0) ? 362 buffer->data : 363 (idx == 1) ? 364 buffer->dataCb : 365 buffer->dataCr; 366 // only map until last pixel 367 if (idx == 0) { 368 dataSize = buffer->stride * (buffer->height - 1) + buffer->width; 369 } else { 370 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) + 371 buffer->chromaStep * (buffer->width / 2 - 1) + 1; 372 } 373 break; 374 // NV21 375 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 376 cr = buffer->data + (buffer->stride * buffer->height); 377 cb = cr + 1; 378 // only map until last pixel 379 ySize = buffer->width * (buffer->height - 1) + buffer->width; 380 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1; 381 382 pData = 383 (idx == 0) ? 384 buffer->data : 385 (idx == 1) ? 386 cb: 387 cr; 388 389 dataSize = (idx == 0) ? ySize : cSize; 390 break; 391 case HAL_PIXEL_FORMAT_YV12: 392 // Y and C stride need to be 16 pixel aligned. 393 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 394 "Stride is not 16 pixel aligned %d", buffer->stride); 395 396 ySize = buffer->stride * buffer->height; 397 cStride = ALIGN(buffer->stride / 2, 16); 398 cr = buffer->data + ySize; 399 cSize = cStride * buffer->height / 2; 400 cb = cr + cSize; 401 402 pData = 403 (idx == 0) ? 404 buffer->data : 405 (idx == 1) ? 406 cb : 407 cr; 408 dataSize = (idx == 0) ? ySize : cSize; 409 break; 410 case HAL_PIXEL_FORMAT_Y8: 411 // Single plane, 8bpp. 412 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 413 414 pData = buffer->data; 415 dataSize = buffer->stride * buffer->height; 416 break; 417 case HAL_PIXEL_FORMAT_Y16: 418 bytesPerPixel = 2; 419 // Single plane, 16bpp, strides are specified in pixels, not in bytes 420 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 421 422 pData = buffer->data; 423 dataSize = buffer->stride * buffer->height * bytesPerPixel; 424 break; 425 case HAL_PIXEL_FORMAT_BLOB: 426 // Used for JPEG data, height must be 1, width == size, single plane. 427 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 428 ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height); 429 430 pData = buffer->data; 431 dataSize = Image_getJpegSize(buffer, usingRGBAOverride); 432 break; 433 case HAL_PIXEL_FORMAT_RAW_SENSOR: 434 // Single plane 16bpp bayer data. 435 bytesPerPixel = 2; 436 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 437 pData = buffer->data; 438 dataSize = buffer->stride * buffer->height * bytesPerPixel; 439 break; 440 case HAL_PIXEL_FORMAT_RAW10: 441 // Single plane 10bpp bayer data. 442 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 443 LOG_ALWAYS_FATAL_IF(buffer->width % 4, 444 "Width is not multiple of 4 %d", buffer->width); 445 LOG_ALWAYS_FATAL_IF(buffer->height % 2, 446 "Height is not even %d", buffer->height); 447 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8), 448 "stride (%d) should be at least %d", 449 buffer->stride, buffer->width * 10 / 8); 450 pData = buffer->data; 451 dataSize = buffer->stride * buffer->height; 452 break; 453 case HAL_PIXEL_FORMAT_RGBA_8888: 454 case HAL_PIXEL_FORMAT_RGBX_8888: 455 // Single plane, 32bpp. 456 bytesPerPixel = 4; 457 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 458 pData = buffer->data; 459 dataSize = buffer->stride * buffer->height * bytesPerPixel; 460 break; 461 case HAL_PIXEL_FORMAT_RGB_565: 462 // Single plane, 16bpp. 463 bytesPerPixel = 2; 464 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 465 pData = buffer->data; 466 dataSize = buffer->stride * buffer->height * bytesPerPixel; 467 break; 468 case HAL_PIXEL_FORMAT_RGB_888: 469 // Single plane, 24bpp. 470 bytesPerPixel = 3; 471 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 472 pData = buffer->data; 473 dataSize = buffer->stride * buffer->height * bytesPerPixel; 474 break; 475 default: 476 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 477 "Pixel format: 0x%x is unsupported", fmt); 478 break; 479 } 480 481 *base = pData; 482 *size = dataSize; 483 } 484 485 static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 486 int32_t readerFormat) 487 { 488 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 489 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx); 490 491 int pixelStride = 0; 492 ALOG_ASSERT(buffer != NULL, "buffer is NULL"); 493 494 int32_t fmt = buffer->flexFormat; 495 496 fmt = applyFormatOverrides(fmt, readerFormat); 497 498 switch (fmt) { 499 case HAL_PIXEL_FORMAT_YCbCr_420_888: 500 pixelStride = (idx == 0) ? 1 : buffer->chromaStep; 501 break; 502 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 503 pixelStride = (idx == 0) ? 1 : 2; 504 break; 505 case HAL_PIXEL_FORMAT_Y8: 506 // Single plane 8bpp data. 507 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 508 pixelStride; 509 break; 510 case HAL_PIXEL_FORMAT_YV12: 511 pixelStride = 1; 512 break; 513 case HAL_PIXEL_FORMAT_BLOB: 514 case HAL_PIXEL_FORMAT_RAW10: 515 // Blob is used for JPEG data, RAW10 is used for 10-bit raw data, they are 516 // single plane, row and pixel strides are 0. 517 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 518 pixelStride = 0; 519 break; 520 case HAL_PIXEL_FORMAT_Y16: 521 case HAL_PIXEL_FORMAT_RAW_SENSOR: 522 case HAL_PIXEL_FORMAT_RGB_565: 523 // Single plane 16bpp data. 524 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 525 pixelStride = 2; 526 break; 527 case HAL_PIXEL_FORMAT_RGBA_8888: 528 case HAL_PIXEL_FORMAT_RGBX_8888: 529 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 530 pixelStride = 4; 531 break; 532 case HAL_PIXEL_FORMAT_RGB_888: 533 // Single plane, 24bpp. 534 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 535 pixelStride = 3; 536 break; 537 default: 538 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 539 "Pixel format: 0x%x is unsupported", fmt); 540 break; 541 } 542 543 return pixelStride; 544 } 545 546 static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 547 int32_t readerFormat) 548 { 549 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 550 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); 551 552 int rowStride = 0; 553 ALOG_ASSERT(buffer != NULL, "buffer is NULL"); 554 555 int32_t fmt = buffer->flexFormat; 556 557 fmt = applyFormatOverrides(fmt, readerFormat); 558 559 switch (fmt) { 560 case HAL_PIXEL_FORMAT_YCbCr_420_888: 561 rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride; 562 break; 563 case HAL_PIXEL_FORMAT_YCrCb_420_SP: 564 rowStride = buffer->width; 565 break; 566 case HAL_PIXEL_FORMAT_YV12: 567 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 568 "Stride is not 16 pixel aligned %d", buffer->stride); 569 rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); 570 break; 571 case HAL_PIXEL_FORMAT_BLOB: 572 // Blob is used for JPEG data, RAW10 is used for 10-bit raw data, they are 573 // single plane, row and pixel strides are 0. 574 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 575 rowStride = 0; 576 break; 577 case HAL_PIXEL_FORMAT_RAW10: 578 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 579 rowStride = buffer->stride; 580 break; 581 case HAL_PIXEL_FORMAT_Y8: 582 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 583 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 584 "Stride is not 16 pixel aligned %d", buffer->stride); 585 rowStride = buffer->stride; 586 break; 587 case HAL_PIXEL_FORMAT_Y16: 588 case HAL_PIXEL_FORMAT_RAW_SENSOR: 589 // In native side, strides are specified in pixels, not in bytes. 590 // Single plane 16bpp bayer data. even width/height, 591 // row stride multiple of 16 pixels (32 bytes) 592 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 593 LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 594 "Stride is not 16 pixel aligned %d", buffer->stride); 595 rowStride = buffer->stride * 2; 596 break; 597 case HAL_PIXEL_FORMAT_RGB_565: 598 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 599 rowStride = buffer->stride * 2; 600 break; 601 case HAL_PIXEL_FORMAT_RGBA_8888: 602 case HAL_PIXEL_FORMAT_RGBX_8888: 603 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 604 rowStride = buffer->stride * 4; 605 break; 606 case HAL_PIXEL_FORMAT_RGB_888: 607 // Single plane, 24bpp. 608 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 609 rowStride = buffer->stride * 3; 610 break; 611 default: 612 ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt); 613 jniThrowException(env, "java/lang/UnsupportedOperationException", 614 "unsupported buffer format"); 615 break; 616 } 617 618 return rowStride; 619 } 620 621 static int Image_getBufferWidth(CpuConsumer::LockedBuffer* buffer) { 622 if (buffer == NULL) return -1; 623 624 if (!buffer->crop.isEmpty()) { 625 return buffer->crop.getWidth(); 626 } 627 return buffer->width; 628 } 629 630 static int Image_getBufferHeight(CpuConsumer::LockedBuffer* buffer) { 631 if (buffer == NULL) return -1; 632 633 if (!buffer->crop.isEmpty()) { 634 return buffer->crop.getHeight(); 635 } 636 return buffer->height; 637 } 638 639 // ---------------------------------------------------------------------------- 640 641 static void ImageReader_classInit(JNIEnv* env, jclass clazz) 642 { 643 ALOGV("%s:", __FUNCTION__); 644 645 jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage"); 646 LOG_ALWAYS_FATAL_IF(imageClazz == NULL, 647 "can't find android/graphics/ImageReader$SurfaceImage"); 648 gSurfaceImageClassInfo.mLockedBuffer = env->GetFieldID( 649 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J"); 650 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mLockedBuffer == NULL, 651 "can't find android/graphics/ImageReader.%s", 652 ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID); 653 654 gSurfaceImageClassInfo.mTimestamp = env->GetFieldID( 655 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J"); 656 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL, 657 "can't find android/graphics/ImageReader.%s", 658 ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID); 659 660 gImageReaderClassInfo.mNativeContext = env->GetFieldID( 661 clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J"); 662 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL, 663 "can't find android/graphics/ImageReader.%s", 664 ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID); 665 666 gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID( 667 clazz, "postEventFromNative", "(Ljava/lang/Object;)V"); 668 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL, 669 "can't find android/graphics/ImageReader.postEventFromNative"); 670 671 jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane"); 672 LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class"); 673 // FindClass only gives a local reference of jclass object. 674 gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz); 675 gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>", 676 "(Landroid/media/ImageReader$SurfaceImage;III)V"); 677 LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL, 678 "Can not find SurfacePlane constructor"); 679 } 680 681 static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, 682 jint width, jint height, jint format, jint maxImages) 683 { 684 status_t res; 685 int nativeFormat; 686 687 ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d", 688 __FUNCTION__, width, height, format, maxImages); 689 690 nativeFormat = Image_getPixelFormat(env, format); 691 692 sp<IGraphicBufferProducer> gbProducer; 693 sp<IGraphicBufferConsumer> gbConsumer; 694 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer); 695 sp<CpuConsumer> consumer = new CpuConsumer(gbConsumer, maxImages, 696 /*controlledByApp*/true); 697 // TODO: throw dvm exOutOfMemoryError? 698 if (consumer == NULL) { 699 jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer"); 700 return; 701 } 702 703 jclass clazz = env->GetObjectClass(thiz); 704 if (clazz == NULL) { 705 jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader"); 706 return; 707 } 708 sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages)); 709 ctx->setCpuConsumer(consumer); 710 ctx->setProducer(gbProducer); 711 consumer->setFrameAvailableListener(ctx); 712 ImageReader_setNativeContext(env, thiz, ctx); 713 ctx->setBufferFormat(nativeFormat); 714 ctx->setBufferWidth(width); 715 ctx->setBufferHeight(height); 716 717 // Set the width/height/format to the CpuConsumer 718 res = consumer->setDefaultBufferSize(width, height); 719 if (res != OK) { 720 jniThrowException(env, "java/lang/IllegalStateException", 721 "Failed to set CpuConsumer buffer size"); 722 return; 723 } 724 res = consumer->setDefaultBufferFormat(nativeFormat); 725 if (res != OK) { 726 jniThrowException(env, "java/lang/IllegalStateException", 727 "Failed to set CpuConsumer buffer format"); 728 } 729 } 730 731 static void ImageReader_close(JNIEnv* env, jobject thiz) 732 { 733 ALOGV("%s:", __FUNCTION__); 734 735 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 736 if (ctx == NULL) { 737 // ImageReader is already closed. 738 return; 739 } 740 741 CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz); 742 if (consumer != NULL) { 743 consumer->abandon(); 744 consumer->setFrameAvailableListener(NULL); 745 } 746 ImageReader_setNativeContext(env, thiz, NULL); 747 } 748 749 static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image) 750 { 751 ALOGV("%s:", __FUNCTION__); 752 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 753 if (ctx == NULL) { 754 ALOGW("ImageReader#close called before Image#close, consider calling Image#close first"); 755 return; 756 } 757 758 CpuConsumer* consumer = ctx->getCpuConsumer(); 759 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image); 760 if (!buffer) { 761 ALOGW("Image already released!!!"); 762 return; 763 } 764 consumer->unlockBuffer(*buffer); 765 Image_setBuffer(env, image, NULL); 766 ctx->returnLockedBuffer(buffer); 767 } 768 769 static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, 770 jobject image) 771 { 772 ALOGV("%s:", __FUNCTION__); 773 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 774 if (ctx == NULL) { 775 jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 776 return -1; 777 } 778 779 CpuConsumer* consumer = ctx->getCpuConsumer(); 780 CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer(); 781 if (buffer == NULL) { 782 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than" 783 " maxImages buffers"); 784 return ACQUIRE_MAX_IMAGES; 785 } 786 status_t res = consumer->lockNextBuffer(buffer); 787 if (res != NO_ERROR) { 788 ctx->returnLockedBuffer(buffer); 789 if (res != BAD_VALUE /*no buffers*/) { 790 if (res == NOT_ENOUGH_DATA) { 791 return ACQUIRE_MAX_IMAGES; 792 } else { 793 ALOGE("%s Fail to lockNextBuffer with error: %d ", 794 __FUNCTION__, res); 795 jniThrowExceptionFmt(env, "java/lang/AssertionError", 796 "Unknown error (%d) when we tried to lock buffer.", 797 res); 798 } 799 } 800 return ACQUIRE_NO_BUFFERS; 801 } 802 803 if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) { 804 jniThrowException(env, "java/lang/UnsupportedOperationException", 805 "NV21 format is not supported by ImageReader"); 806 return -1; 807 } 808 809 // Check if the left-top corner of the crop rect is origin, we currently assume this point is 810 // zero, will revist this once this assumption turns out problematic. 811 Point lt = buffer->crop.leftTop(); 812 if (lt.x != 0 || lt.y != 0) { 813 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 814 "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y); 815 return -1; 816 } 817 818 // Check if the producer buffer configurations match what ImageReader configured. 819 int outputWidth = Image_getBufferWidth(buffer); 820 int outputHeight = Image_getBufferHeight(buffer); 821 822 int imgReaderFmt = ctx->getBufferFormat(); 823 int imageReaderWidth = ctx->getBufferWidth(); 824 int imageReaderHeight = ctx->getBufferHeight(); 825 if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) && 826 (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) { 827 ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d", 828 __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight); 829 } 830 831 int bufFmt = buffer->format; 832 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) { 833 bufFmt = buffer->flexFormat; 834 } 835 if (imgReaderFmt != bufFmt) { 836 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt == 837 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) { 838 // Special casing for when producer switches to a format compatible with flexible YUV 839 // (HAL_PIXEL_FORMAT_YCbCr_420_888). 840 ctx->setBufferFormat(bufFmt); 841 ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt); 842 } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufFmt == HAL_PIXEL_FORMAT_RGBA_8888) { 843 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW 844 // write limitations for (b/17379185). 845 ALOGD("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__); 846 } else { 847 // Return the buffer to the queue. 848 consumer->unlockBuffer(*buffer); 849 ctx->returnLockedBuffer(buffer); 850 851 // Throw exception 852 ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x", 853 buffer->format, ctx->getBufferFormat()); 854 String8 msg; 855 msg.appendFormat("The producer output buffer format 0x%x doesn't " 856 "match the ImageReader's configured buffer format 0x%x.", 857 bufFmt, ctx->getBufferFormat()); 858 jniThrowException(env, "java/lang/UnsupportedOperationException", 859 msg.string()); 860 return -1; 861 } 862 } 863 // Set SurfaceImage instance member variables 864 Image_setBuffer(env, image, buffer); 865 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp, 866 static_cast<jlong>(buffer->timestamp)); 867 868 return ACQUIRE_SUCCESS; 869 } 870 871 static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz) 872 { 873 ALOGV("%s: ", __FUNCTION__); 874 875 IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz); 876 if (gbp == NULL) { 877 jniThrowRuntimeException(env, "CpuConsumer is uninitialized"); 878 return NULL; 879 } 880 881 // Wrap the IGBP in a Java-language Surface. 882 return android_view_Surface_createFromIGraphicBufferProducer(env, gbp); 883 } 884 885 static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat) 886 { 887 int rowStride, pixelStride; 888 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 889 890 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 891 892 ALOG_ASSERT(buffer != NULL); 893 if (buffer == NULL) { 894 jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); 895 } 896 897 readerFormat = Image_getPixelFormat(env, readerFormat); 898 899 rowStride = Image_imageGetRowStride(env, buffer, idx, readerFormat); 900 pixelStride = Image_imageGetPixelStride(env, buffer, idx, readerFormat); 901 902 jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz, 903 gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride); 904 905 return surfPlaneObj; 906 } 907 908 static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat) 909 { 910 uint8_t *base = NULL; 911 uint32_t size = 0; 912 jobject byteBuffer; 913 914 ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 915 916 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 917 918 if (buffer == NULL) { 919 jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); 920 } 921 922 readerFormat = Image_getPixelFormat(env, readerFormat); 923 924 // Create byteBuffer from native buffer 925 Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerFormat); 926 927 if (size > static_cast<uint32_t>(INT32_MAX)) { 928 // Byte buffer have 'int capacity', so check the range 929 jniThrowExceptionFmt(env, "java/lang/IllegalStateException", 930 "Size too large for bytebuffer capacity %" PRIu32, size); 931 return NULL; 932 } 933 934 byteBuffer = env->NewDirectByteBuffer(base, size); 935 // TODO: throw dvm exOutOfMemoryError? 936 if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) { 937 jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer"); 938 } 939 940 return byteBuffer; 941 } 942 943 static jint Image_getWidth(JNIEnv* env, jobject thiz) 944 { 945 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 946 return Image_getBufferWidth(buffer); 947 } 948 949 static jint Image_getHeight(JNIEnv* env, jobject thiz) 950 { 951 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 952 return Image_getBufferHeight(buffer); 953 } 954 955 956 } // extern "C" 957 958 // ---------------------------------------------------------------------------- 959 960 static JNINativeMethod gImageReaderMethods[] = { 961 {"nativeClassInit", "()V", (void*)ImageReader_classInit }, 962 {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init }, 963 {"nativeClose", "()V", (void*)ImageReader_close }, 964 {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, 965 {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup }, 966 {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, 967 }; 968 969 static JNINativeMethod gImageMethods[] = { 970 {"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer }, 971 {"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;", 972 (void*)Image_createSurfacePlane }, 973 {"nativeGetWidth", "()I", (void*)Image_getWidth }, 974 {"nativeGetHeight", "()I", (void*)Image_getHeight }, 975 }; 976 977 int register_android_media_ImageReader(JNIEnv *env) { 978 979 int ret1 = AndroidRuntime::registerNativeMethods(env, 980 "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods)); 981 982 int ret2 = AndroidRuntime::registerNativeMethods(env, 983 "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods)); 984 985 return (ret1 || ret2); 986 } 987