• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
48 using namespace android;
49 
50 enum {
51     IMAGE_READER_MAX_NUM_PLANES = 3,
52 };
53 
54 enum {
55     ACQUIRE_SUCCESS = 0,
56     ACQUIRE_NO_BUFFERS = 1,
57     ACQUIRE_MAX_IMAGES = 2,
58 };
59 
60 static struct {
61     jfieldID mNativeContext;
62     jmethodID postEventFromNative;
63 } gImageReaderClassInfo;
64 
65 static struct {
66     jfieldID mNativeBuffer;
67     jfieldID mTimestamp;
68 } gSurfaceImageClassInfo;
69 
70 static struct {
71     jclass clazz;
72     jmethodID ctor;
73 } gSurfacePlaneClassInfo;
74 
75 // Get an ID that's unique within this process.
createProcessUniqueId()76 static int32_t createProcessUniqueId() {
77     static volatile int32_t globalCounter = 0;
78     return android_atomic_inc(&globalCounter);
79 }
80 
81 // ----------------------------------------------------------------------------
82 
83 class JNIImageReaderContext : public ConsumerBase::FrameAvailableListener
84 {
85 public:
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 
setCpuConsumer(const sp<CpuConsumer> & consumer)98     void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; }
getCpuConsumer()99     CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
100 
setOpaqueConsumer(const sp<BufferItemConsumer> & consumer)101     void setOpaqueConsumer(const sp<BufferItemConsumer>& consumer) { mOpaqueConsumer = consumer; }
getOpaqueConsumer()102     BufferItemConsumer* getOpaqueConsumer() { return mOpaqueConsumer.get(); }
103     // This is the only opaque format exposed in the ImageFormat public API.
isOpaque()104     bool isOpaque() { return mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; }
105 
setProducer(const sp<IGraphicBufferProducer> & producer)106     void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; }
getProducer()107     IGraphicBufferProducer* getProducer() { return mProducer.get(); }
108 
setBufferFormat(int format)109     void setBufferFormat(int format) { mFormat = format; }
getBufferFormat()110     int getBufferFormat() { return mFormat; }
111 
setBufferDataspace(android_dataspace dataSpace)112     void setBufferDataspace(android_dataspace dataSpace) { mDataSpace = dataSpace; }
getBufferDataspace()113     android_dataspace getBufferDataspace() { return mDataSpace; }
114 
setBufferWidth(int width)115     void setBufferWidth(int width) { mWidth = width; }
getBufferWidth()116     int getBufferWidth() { return mWidth; }
117 
setBufferHeight(int height)118     void setBufferHeight(int height) { mHeight = height; }
getBufferHeight()119     int getBufferHeight() { return mHeight; }
120 
121 private:
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 
JNIImageReaderContext(JNIEnv * env,jobject weakThiz,jclass clazz,int maxImages)138 JNIImageReaderContext::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 
getJNIEnv(bool * needsDetach)150 JNIEnv* 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 
detachJNI()167 void 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 
getLockedBuffer()175 CpuConsumer::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 
returnLockedBuffer(CpuConsumer::LockedBuffer * buffer)186 void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) {
187     mBuffers.push_back(buffer);
188 }
189 
getOpaqueBuffer()190 BufferItem* 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 
returnOpaqueBuffer(BufferItem * buffer)201 void JNIImageReaderContext::returnOpaqueBuffer(BufferItem* buffer) {
202     mOpaqueBuffers.push_back(buffer);
203 }
204 
~JNIImageReaderContext()205 JNIImageReaderContext::~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 
onFrameAvailable(const BufferItem &)239 void 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 
256 extern "C" {
257 
isFormatOpaque(int format)258 static 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 
ImageReader_getContext(JNIEnv * env,jobject thiz)263 static 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 
ImageReader_getCpuConsumer(JNIEnv * env,jobject thiz)271 static 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 
ImageReader_getProducer(JNIEnv * env,jobject thiz)289 static 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 
ImageReader_setNativeContext(JNIEnv * env,jobject thiz,sp<JNIImageReaderContext> ctx)301 static 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 
Image_getLockedBuffer(JNIEnv * env,jobject image)316 static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
317 {
318     return reinterpret_cast<CpuConsumer::LockedBuffer*>(
319             env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
320 }
321 
Image_setBuffer(JNIEnv * env,jobject thiz,const CpuConsumer::LockedBuffer * buffer)322 static 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 
Image_setOpaqueBuffer(JNIEnv * env,jobject thiz,const BufferItem * buffer)328 static void Image_setOpaqueBuffer(JNIEnv* env, jobject thiz,
329         const BufferItem* buffer)
330 {
331     env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
332 }
333 
Image_getJpegSize(CpuConsumer::LockedBuffer * buffer,bool usingRGBAOverride)334 static 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 
usingRGBAToJpegOverride(int32_t bufferFormat,int32_t readerCtxFormat)369 static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) {
370     return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888;
371 }
372 
applyFormatOverrides(int32_t bufferFormat,int32_t readerCtxFormat)373 static 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 
Image_getLockedBufferInfo(JNIEnv * env,CpuConsumer::LockedBuffer * buffer,int idx,uint8_t ** base,uint32_t * size,int32_t readerFormat)383 static 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 
Image_imageGetPixelStride(JNIEnv * env,CpuConsumer::LockedBuffer * buffer,int idx,int32_t halReaderFormat)543 static 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 
Image_imageGetRowStride(JNIEnv * env,CpuConsumer::LockedBuffer * buffer,int idx,int32_t halReaderFormat)605 static 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 
Image_getBufferWidth(CpuConsumer::LockedBuffer * buffer)682 static 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 
Image_getBufferHeight(CpuConsumer::LockedBuffer * buffer)691 static 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 
ImageReader_getOpaqueConsumer(JNIEnv * env,jobject thiz)702 static 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 
Image_getOpaqueBuffer(JNIEnv * env,jobject image)719 static BufferItem* Image_getOpaqueBuffer(JNIEnv* env, jobject image)
720 {
721     return reinterpret_cast<BufferItem*>(
722             env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
723 }
724 
Image_getOpaqueBufferWidth(BufferItem * buffer)725 static 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 
Image_getOpaqueBufferHeight(BufferItem * buffer)734 static 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 
ImageReader_classInit(JNIEnv * env,jclass clazz)748 static 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 
ImageReader_init(JNIEnv * env,jobject thiz,jobject weakThiz,jint width,jint height,jint format,jint maxImages)788 static 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 
ImageReader_close(JNIEnv * env,jobject thiz)892 static 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 
ImageReader_imageRelease(JNIEnv * env,jobject thiz,jobject image)916 static 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             ALOGW("Image already released!!!");
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 
ImageReader_opaqueImageSetup(JNIEnv * env,JNIImageReaderContext * ctx,jobject image)946 static 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 
ImageReader_lockedImageSetup(JNIEnv * env,JNIImageReaderContext * ctx,jobject image)984 static 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 
ImageReader_imageSetup(JNIEnv * env,jobject thiz,jobject image)1077 static 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         jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
1082         return -1;
1083     }
1084 
1085     if (ctx->isOpaque()) {
1086         return ImageReader_opaqueImageSetup(env, ctx, image);
1087     } else {
1088         return ImageReader_lockedImageSetup(env, ctx, image);
1089     }
1090 }
1091 
ImageReader_detachImage(JNIEnv * env,jobject thiz,jobject image)1092 static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) {
1093     ALOGV("%s:", __FUNCTION__);
1094     JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
1095     if (ctx == NULL) {
1096         jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed");
1097         return -1;
1098     }
1099 
1100     status_t res = OK;
1101     if (!ctx->isOpaque()) {
1102         // TODO: Non-Opaque format detach is not implemented yet.
1103         jniThrowRuntimeException(env,
1104                 "nativeDetachImage is not implemented yet for non-opaque format !!!");
1105         return -1;
1106     }
1107 
1108     BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
1109     BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
1110     if (!opaqueBuffer) {
1111         ALOGE(
1112                 "Opaque Image already released and can not be detached from ImageReader!!!");
1113         jniThrowException(env, "java/lang/IllegalStateException",
1114                 "Opaque Image detach from ImageReader failed: buffer was already released");
1115         return -1;
1116     }
1117 
1118     res = opaqueConsumer->detachBuffer(opaqueBuffer->mSlot);
1119     if (res != OK) {
1120         ALOGE("Opaque Image detach failed: %s (%d)!!!", strerror(-res), res);
1121         jniThrowRuntimeException(env,
1122                 "nativeDetachImage failed for opaque image!!!");
1123         return res;
1124     }
1125     return OK;
1126 }
1127 
ImageReader_getSurface(JNIEnv * env,jobject thiz)1128 static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
1129 {
1130     ALOGV("%s: ", __FUNCTION__);
1131 
1132     IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
1133     if (gbp == NULL) {
1134         jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
1135         return NULL;
1136     }
1137 
1138     // Wrap the IGBP in a Java-language Surface.
1139     return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
1140 }
1141 
Image_createSurfacePlane(JNIEnv * env,jobject thiz,int idx,int readerFormat)1142 static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat)
1143 {
1144     int rowStride, pixelStride;
1145     PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat);
1146     int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat(
1147         publicReaderFormat);
1148 
1149     ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
1150     if (isFormatOpaque(halReaderFormat)) {
1151         jniThrowException(env, "java/lang/IllegalStateException",
1152                 "Opaque images from Opaque ImageReader do not have any planes");
1153         return NULL;
1154     }
1155 
1156     CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1157 
1158     ALOG_ASSERT(buffer != NULL);
1159     if (buffer == NULL) {
1160         jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
1161     }
1162 
1163     rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat);
1164     pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat);
1165 
1166     jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
1167             gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
1168 
1169     return surfPlaneObj;
1170 }
1171 
Image_getByteBuffer(JNIEnv * env,jobject thiz,int idx,int readerFormat)1172 static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat)
1173 {
1174     uint8_t *base = NULL;
1175     uint32_t size = 0;
1176     jobject byteBuffer;
1177     PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat);
1178     int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1179             readerPublicFormat);
1180 
1181     ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
1182 
1183     if (isFormatOpaque(readerHalFormat)) {
1184         jniThrowException(env, "java/lang/IllegalStateException",
1185                 "Opaque images from Opaque ImageReader do not have any plane");
1186         return NULL;
1187     }
1188 
1189     CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1190 
1191     if (buffer == NULL) {
1192         jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
1193     }
1194 
1195     // Create byteBuffer from native buffer
1196     Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat);
1197 
1198     if (size > static_cast<uint32_t>(INT32_MAX)) {
1199         // Byte buffer have 'int capacity', so check the range
1200         jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
1201                 "Size too large for bytebuffer capacity %" PRIu32, size);
1202         return NULL;
1203     }
1204 
1205     byteBuffer = env->NewDirectByteBuffer(base, size);
1206     // TODO: throw dvm exOutOfMemoryError?
1207     if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
1208         jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
1209     }
1210 
1211     return byteBuffer;
1212 }
1213 
Image_getWidth(JNIEnv * env,jobject thiz,jint format)1214 static jint Image_getWidth(JNIEnv* env, jobject thiz, jint format)
1215 {
1216     if (isFormatOpaque(format)) {
1217         BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
1218         return Image_getOpaqueBufferWidth(opaqueBuffer);
1219     } else {
1220         CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1221         return Image_getBufferWidth(buffer);
1222     }
1223 }
1224 
Image_getHeight(JNIEnv * env,jobject thiz,jint format)1225 static jint Image_getHeight(JNIEnv* env, jobject thiz, jint format)
1226 {
1227     if (isFormatOpaque(format)) {
1228         BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
1229         return Image_getOpaqueBufferHeight(opaqueBuffer);
1230     } else {
1231         CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1232         return Image_getBufferHeight(buffer);
1233     }
1234 }
1235 
Image_getFormat(JNIEnv * env,jobject thiz,jint readerFormat)1236 static jint Image_getFormat(JNIEnv* env, jobject thiz, jint readerFormat)
1237 {
1238     if (isFormatOpaque(readerFormat)) {
1239         // Assuming opaque reader produce opaque images.
1240         return static_cast<jint>(PublicFormat::PRIVATE);
1241     } else {
1242         CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1243         int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1244                 static_cast<PublicFormat>(readerFormat));
1245         int32_t fmt = applyFormatOverrides(buffer->flexFormat, readerHalFormat);
1246         PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
1247                 fmt, buffer->dataSpace);
1248         return static_cast<jint>(publicFmt);
1249     }
1250 }
1251 
1252 } // extern "C"
1253 
1254 // ----------------------------------------------------------------------------
1255 
1256 static JNINativeMethod gImageReaderMethods[] = {
1257     {"nativeClassInit",        "()V",                        (void*)ImageReader_classInit },
1258     {"nativeInit",             "(Ljava/lang/Object;IIII)V",  (void*)ImageReader_init },
1259     {"nativeClose",            "()V",                        (void*)ImageReader_close },
1260     {"nativeReleaseImage",     "(Landroid/media/Image;)V",   (void*)ImageReader_imageRelease },
1261     {"nativeImageSetup",       "(Landroid/media/Image;)I",   (void*)ImageReader_imageSetup },
1262     {"nativeGetSurface",       "()Landroid/view/Surface;",   (void*)ImageReader_getSurface },
1263     {"nativeDetachImage",      "(Landroid/media/Image;)I",   (void*)ImageReader_detachImage },
1264 };
1265 
1266 static JNINativeMethod gImageMethods[] = {
1267     {"nativeImageGetBuffer",   "(II)Ljava/nio/ByteBuffer;",   (void*)Image_getByteBuffer },
1268     {"nativeCreatePlane",      "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
1269                                                               (void*)Image_createSurfacePlane },
1270     {"nativeGetWidth",         "(I)I",                        (void*)Image_getWidth },
1271     {"nativeGetHeight",        "(I)I",                        (void*)Image_getHeight },
1272     {"nativeGetFormat",        "(I)I",                        (void*)Image_getFormat },
1273 };
1274 
register_android_media_ImageReader(JNIEnv * env)1275 int register_android_media_ImageReader(JNIEnv *env) {
1276 
1277     int ret1 = AndroidRuntime::registerNativeMethods(env,
1278                    "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
1279 
1280     int ret2 = AndroidRuntime::registerNativeMethods(env,
1281                    "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
1282 
1283     return (ret1 || ret2);
1284 }
1285