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