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