blob: 635fa11c6b443045490cb869b0e9b3f38b8a353b [file] [log] [blame]
Zhijun He212e78d2013-06-07 11:36:23 -07001/*
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>
Jeff Brownef961212013-08-05 20:39:29 -070022#include <utils/String8.h>
Zhijun He212e78d2013-06-07 11:36:23 -070023
24#include <cstdio>
25
26#include <gui/CpuConsumer.h>
Zhijun Hece9d6f92015-03-29 16:33:59 -070027#include <gui/BufferItemConsumer.h>
Zhijun He212e78d2013-06-07 11:36:23 -070028#include <gui/Surface.h>
Zhijun He534046d2013-07-01 11:03:41 -070029#include <camera3.h>
Zhijun He212e78d2013-06-07 11:36:23 -070030
31#include <android_runtime/AndroidRuntime.h>
32#include <android_runtime/android_view_Surface.h>
33
34#include <jni.h>
35#include <JNIHelp.h>
36
Igor Murashkin5096def2014-06-24 10:49:11 -070037#include <stdint.h>
38#include <inttypes.h>
39
Zhijun He212e78d2013-06-07 11:36:23 -070040#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
41
Zhijun He212e78d2013-06-07 11:36:23 -070042#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext"
Zhijun Hece9d6f92015-03-29 16:33:59 -070043#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mNativeBuffer"
Zhijun He212e78d2013-06-07 11:36:23 -070044#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp"
45
46// ----------------------------------------------------------------------------
47
48using namespace android;
49
50enum {
51 IMAGE_READER_MAX_NUM_PLANES = 3,
52};
53
Igor Murashkine3351f12013-09-13 13:08:04 -070054enum {
55 ACQUIRE_SUCCESS = 0,
56 ACQUIRE_NO_BUFFERS = 1,
57 ACQUIRE_MAX_IMAGES = 2,
58};
59
Jeff Brownef961212013-08-05 20:39:29 -070060static struct {
61 jfieldID mNativeContext;
62 jmethodID postEventFromNative;
63} gImageReaderClassInfo;
Zhijun He212e78d2013-06-07 11:36:23 -070064
Jeff Brownef961212013-08-05 20:39:29 -070065static struct {
Zhijun Hece9d6f92015-03-29 16:33:59 -070066 jfieldID mNativeBuffer;
Jeff Brownef961212013-08-05 20:39:29 -070067 jfieldID mTimestamp;
68} gSurfaceImageClassInfo;
69
70static struct {
Zhijun He212e78d2013-06-07 11:36:23 -070071 jclass clazz;
72 jmethodID ctor;
Jeff Brownef961212013-08-05 20:39:29 -070073} gSurfacePlaneClassInfo;
Zhijun He212e78d2013-06-07 11:36:23 -070074
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -070075// Get an ID that's unique within this process.
76static int32_t createProcessUniqueId() {
77 static volatile int32_t globalCounter = 0;
78 return android_atomic_inc(&globalCounter);
79}
80
Zhijun He212e78d2013-06-07 11:36:23 -070081// ----------------------------------------------------------------------------
82
Zhijun Hece9d6f92015-03-29 16:33:59 -070083class JNIImageReaderContext : public ConsumerBase::FrameAvailableListener
Zhijun He212e78d2013-06-07 11:36:23 -070084{
85public:
86 JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages);
87
88 virtual ~JNIImageReaderContext();
89
Dan Stoza2c34b5e2014-11-04 11:36:33 -080090 virtual void onFrameAvailable(const BufferItem& item);
Zhijun He212e78d2013-06-07 11:36:23 -070091
92 CpuConsumer::LockedBuffer* getLockedBuffer();
Zhijun He212e78d2013-06-07 11:36:23 -070093 void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer);
94
Zhijun Hece9d6f92015-03-29 16:33:59 -070095 BufferItem* getOpaqueBuffer();
96 void returnOpaqueBuffer(BufferItem* buffer);
97
Mathias Agopian52a9a102013-08-02 01:38:38 -070098 void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; }
Zhijun He212e78d2013-06-07 11:36:23 -070099 CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
100
Zhijun Hece9d6f92015-03-29 16:33:59 -0700101 void setOpaqueConsumer(const sp<BufferItemConsumer>& consumer) { mOpaqueConsumer = consumer; }
102 BufferItemConsumer* getOpaqueConsumer() { return mOpaqueConsumer.get(); }
103 // This is the only opaque format exposed in the ImageFormat public API.
104 bool isOpaque() { return mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; }
105
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700106 void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; }
107 IGraphicBufferProducer* getProducer() { return mProducer.get(); }
Zhijun He212e78d2013-06-07 11:36:23 -0700108
109 void setBufferFormat(int format) { mFormat = format; }
110 int getBufferFormat() { return mFormat; }
111
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800112 void setBufferDataspace(android_dataspace dataSpace) { mDataSpace = dataSpace; }
113 android_dataspace getBufferDataspace() { return mDataSpace; }
114
Zhijun He212e78d2013-06-07 11:36:23 -0700115 void setBufferWidth(int width) { mWidth = width; }
116 int getBufferWidth() { return mWidth; }
117
118 void setBufferHeight(int height) { mHeight = height; }
119 int getBufferHeight() { return mHeight; }
120
121private:
122 static JNIEnv* getJNIEnv(bool* needsDetach);
123 static void detachJNI();
124
125 List<CpuConsumer::LockedBuffer*> mBuffers;
Zhijun Hece9d6f92015-03-29 16:33:59 -0700126 List<BufferItem*> mOpaqueBuffers;
Zhijun He212e78d2013-06-07 11:36:23 -0700127 sp<CpuConsumer> mConsumer;
Zhijun Hece9d6f92015-03-29 16:33:59 -0700128 sp<BufferItemConsumer> mOpaqueConsumer;
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700129 sp<IGraphicBufferProducer> mProducer;
Zhijun He212e78d2013-06-07 11:36:23 -0700130 jobject mWeakThiz;
131 jclass mClazz;
132 int mFormat;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800133 android_dataspace mDataSpace;
Zhijun He212e78d2013-06-07 11:36:23 -0700134 int mWidth;
135 int mHeight;
136};
137
138JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
139 jobject weakThiz, jclass clazz, int maxImages) :
140 mWeakThiz(env->NewGlobalRef(weakThiz)),
141 mClazz((jclass)env->NewGlobalRef(clazz)) {
142 for (int i = 0; i < maxImages; i++) {
143 CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
Zhijun Hece9d6f92015-03-29 16:33:59 -0700144 BufferItem* opaqueBuffer = new BufferItem;
Zhijun He212e78d2013-06-07 11:36:23 -0700145 mBuffers.push_back(buffer);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700146 mOpaqueBuffers.push_back(opaqueBuffer);
Zhijun He212e78d2013-06-07 11:36:23 -0700147 }
148}
149
150JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
151 LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
152 *needsDetach = false;
153 JNIEnv* env = AndroidRuntime::getJNIEnv();
154 if (env == NULL) {
155 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
156 JavaVM* vm = AndroidRuntime::getJavaVM();
157 int result = vm->AttachCurrentThread(&env, (void*) &args);
158 if (result != JNI_OK) {
159 ALOGE("thread attach failed: %#x", result);
160 return NULL;
161 }
162 *needsDetach = true;
163 }
164 return env;
165}
166
167void JNIImageReaderContext::detachJNI() {
168 JavaVM* vm = AndroidRuntime::getJavaVM();
169 int result = vm->DetachCurrentThread();
170 if (result != JNI_OK) {
171 ALOGE("thread detach failed: %#x", result);
172 }
173}
174
175CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
176 if (mBuffers.empty()) {
177 return NULL;
178 }
179 // Return a LockedBuffer pointer and remove it from the list
180 List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
181 CpuConsumer::LockedBuffer* buffer = *it;
182 mBuffers.erase(it);
183 return buffer;
184}
185
Igor Murashkind901c032013-08-27 15:19:55 -0700186void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) {
Zhijun He212e78d2013-06-07 11:36:23 -0700187 mBuffers.push_back(buffer);
188}
189
Zhijun Hece9d6f92015-03-29 16:33:59 -0700190BufferItem* JNIImageReaderContext::getOpaqueBuffer() {
191 if (mOpaqueBuffers.empty()) {
192 return NULL;
193 }
194 // Return an opaque buffer pointer and remove it from the list
195 List<BufferItem*>::iterator it = mOpaqueBuffers.begin();
196 BufferItem* buffer = *it;
197 mOpaqueBuffers.erase(it);
198 return buffer;
199}
200
201void JNIImageReaderContext::returnOpaqueBuffer(BufferItem* buffer) {
202 mOpaqueBuffers.push_back(buffer);
203}
204
Zhijun He212e78d2013-06-07 11:36:23 -0700205JNIImageReaderContext::~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 }
Zhijun Hece9d6f92015-03-29 16:33:59 -0700223
224 // Delete opaque buffers
225 for (List<BufferItem *>::iterator it = mOpaqueBuffers.begin();
226 it != mOpaqueBuffers.end(); it++) {
227 delete *it;
228 }
229
Zhijun He212e78d2013-06-07 11:36:23 -0700230 mBuffers.clear();
Zhijun Hece9d6f92015-03-29 16:33:59 -0700231 if (mConsumer != 0) {
232 mConsumer.clear();
233 }
234 if (mOpaqueConsumer != 0) {
235 mOpaqueConsumer.clear();
236 }
Zhijun He212e78d2013-06-07 11:36:23 -0700237}
238
Dan Stoza2c34b5e2014-11-04 11:36:33 -0800239void JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/)
Zhijun He212e78d2013-06-07 11:36:23 -0700240{
241 ALOGV("%s: frame available", __FUNCTION__);
242 bool needsDetach = false;
243 JNIEnv* env = getJNIEnv(&needsDetach);
244 if (env != NULL) {
Jeff Brownef961212013-08-05 20:39:29 -0700245 env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz);
Zhijun He212e78d2013-06-07 11:36:23 -0700246 } else {
247 ALOGW("onFrameAvailable event will not posted");
248 }
249 if (needsDetach) {
250 detachJNI();
251 }
252}
253
254// ----------------------------------------------------------------------------
255
256extern "C" {
257
Zhijun Hece9d6f92015-03-29 16:33:59 -0700258static 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
Zhijun He212e78d2013-06-07 11:36:23 -0700263static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
264{
265 JNIImageReaderContext *ctx;
266 ctx = reinterpret_cast<JNIImageReaderContext *>
Jeff Brownef961212013-08-05 20:39:29 -0700267 (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext));
Zhijun He212e78d2013-06-07 11:36:23 -0700268 return ctx;
269}
270
271static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
272{
273 ALOGV("%s:", __FUNCTION__);
274 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
275 if (ctx == NULL) {
276 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
277 return NULL;
278 }
Zhijun Hece9d6f92015-03-29 16:33:59 -0700279
280 if (ctx->isOpaque()) {
281 jniThrowException(env, "java/lang/IllegalStateException",
282 "Opaque ImageReader doesn't support this method");
283 return NULL;
284 }
285
Zhijun He212e78d2013-06-07 11:36:23 -0700286 return ctx->getCpuConsumer();
287}
288
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700289static IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz)
Mathias Agopian52a9a102013-08-02 01:38:38 -0700290{
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 }
Zhijun Hece9d6f92015-03-29 16:33:59 -0700297
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700298 return ctx->getProducer();
Mathias Agopian52a9a102013-08-02 01:38:38 -0700299}
300
Zhijun He212e78d2013-06-07 11:36:23 -0700301static 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 }
Jeff Brownef961212013-08-05 20:39:29 -0700312 env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext,
313 reinterpret_cast<jlong>(ctx.get()));
Zhijun He212e78d2013-06-07 11:36:23 -0700314}
315
316static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
317{
Jeff Brownef961212013-08-05 20:39:29 -0700318 return reinterpret_cast<CpuConsumer::LockedBuffer*>(
Zhijun Hece9d6f92015-03-29 16:33:59 -0700319 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
Zhijun He212e78d2013-06-07 11:36:23 -0700320}
321
322static void Image_setBuffer(JNIEnv* env, jobject thiz,
323 const CpuConsumer::LockedBuffer* buffer)
324{
Zhijun Hece9d6f92015-03-29 16:33:59 -0700325 env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
326}
327
328static void Image_setOpaqueBuffer(JNIEnv* env, jobject thiz,
329 const BufferItem* buffer)
330{
331 env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
Zhijun He212e78d2013-06-07 11:36:23 -0700332}
333
Ruben Brunk31798f32014-09-25 19:56:54 -0700334static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride)
Zhijun He534046d2013-07-01 11:03:41 -0700335{
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
Ruben Brunk31798f32014-09-25 19:56:54 -0700341 if (usingRGBAOverride) {
Ruben Brunk0c798842014-09-30 03:42:13 -0700342 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
Ruben Brunk31798f32014-09-25 19:56:54 -0700343 }
344
Zhijun He534046d2013-07-01 11:03:41 -0700345 // 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) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700355 /*
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);
Zhijun He534046d2013-07-01 11:03:41 -0700363 size = width;
364 }
365
366 return size;
367}
368
Ruben Brunk31798f32014-09-25 19:56:54 -0700369static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) {
370 return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888;
371}
372
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700373static 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).
Ruben Brunk31798f32014-09-25 19:56:54 -0700377 if (usingRGBAToJpegOverride(bufferFormat, readerCtxFormat)) {
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700378 return HAL_PIXEL_FORMAT_BLOB;
379 }
380 return bufferFormat;
381}
382
Zhijun He212e78d2013-06-07 11:36:23 -0700383static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700384 uint8_t **base, uint32_t *size, int32_t readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700385{
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
Zhijun He7f4d3142013-07-23 07:54:38 -0700391 ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
Zhijun He212e78d2013-06-07 11:36:23 -0700392
393 uint32_t dataSize, ySize, cSize, cStride;
394 uint8_t *cb, *cr;
395 uint8_t *pData = NULL;
Zhijun He708e3592013-08-05 14:56:11 -0700396 int bytesPerPixel = 0;
Zhijun He212e78d2013-06-07 11:36:23 -0700397
398 dataSize = ySize = cSize = cStride = 0;
Lajos Molnar4fb44262015-01-22 19:03:31 -0800399 int32_t fmt = buffer->flexFormat;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700400
Ruben Brunk31798f32014-09-25 19:56:54 -0700401 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700402 fmt = applyFormatOverrides(fmt, readerFormat);
Zhijun He212e78d2013-06-07 11:36:23 -0700403 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;
Lajos Molnar4fb44262015-01-22 19:03:31 -0800411 // only map until last pixel
Zhijun He212e78d2013-06-07 11:36:23 -0700412 if (idx == 0) {
Lajos Molnar4fb44262015-01-22 19:03:31 -0800413 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
Zhijun He212e78d2013-06-07 11:36:23 -0700414 } else {
Lajos Molnar4fb44262015-01-22 19:03:31 -0800415 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
416 buffer->chromaStep * (buffer->width / 2 - 1) + 1;
Zhijun He212e78d2013-06-07 11:36:23 -0700417 }
418 break;
419 // NV21
420 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
421 cr = buffer->data + (buffer->stride * buffer->height);
422 cb = cr + 1;
Lajos Molnar4fb44262015-01-22 19:03:31 -0800423 // 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;
Zhijun He212e78d2013-06-07 11:36:23 -0700426
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:
Zhijun He977ad8d2014-04-08 16:59:29 -0700463 bytesPerPixel = 2;
Zhijun He212e78d2013-06-07 11:36:23 -0700464 // 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;
Zhijun He977ad8d2014-04-08 16:59:29 -0700468 dataSize = buffer->stride * buffer->height * bytesPerPixel;
Zhijun He212e78d2013-06-07 11:36:23 -0700469 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;
Ruben Brunk31798f32014-09-25 19:56:54 -0700476 dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
Zhijun He212e78d2013-06-07 11:36:23 -0700477 break;
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800478 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He212e78d2013-06-07 11:36:23 -0700479 // Single plane 16bpp bayer data.
Zhijun He977ad8d2014-04-08 16:59:29 -0700480 bytesPerPixel = 2;
Zhijun He212e78d2013-06-07 11:36:23 -0700481 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
482 pData = buffer->data;
Zhijun He977ad8d2014-04-08 16:59:29 -0700483 dataSize = buffer->stride * buffer->height * bytesPerPixel;
Zhijun He212e78d2013-06-07 11:36:23 -0700484 break;
Zhijun Hed1988a92014-07-01 04:15:09 -0700485 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);
Zhijun He4c4064f2014-07-25 09:06:11 -0700492 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);
Zhijun Hed1988a92014-07-01 04:15:09 -0700495 pData = buffer->data;
Zhijun He4c4064f2014-07-25 09:06:11 -0700496 dataSize = buffer->stride * buffer->height;
Zhijun Hed1988a92014-07-01 04:15:09 -0700497 break;
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700498 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;
Zhijun He708e3592013-08-05 14:56:11 -0700511 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;
Zhijun He212e78d2013-06-07 11:36:23 -0700533 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
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700543static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800544 int32_t halReaderFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700545{
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
Lajos Molnar4fb44262015-01-22 19:03:31 -0800552 int32_t fmt = buffer->flexFormat;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700553
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800554 fmt = applyFormatOverrides(fmt, halReaderFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700555
Zhijun He212e78d2013-06-07 11:36:23 -0700556 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);
Zhijun He212e78d2013-06-07 11:36:23 -0700566 break;
567 case HAL_PIXEL_FORMAT_YV12:
568 pixelStride = 1;
569 break;
570 case HAL_PIXEL_FORMAT_BLOB:
Zhijun Hed1988a92014-07-01 04:15:09 -0700571 case HAL_PIXEL_FORMAT_RAW10:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700572 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
Zhijun He212e78d2013-06-07 11:36:23 -0700576 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
577 pixelStride = 0;
578 break;
579 case HAL_PIXEL_FORMAT_Y16:
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800580 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He708e3592013-08-05 14:56:11 -0700581 case HAL_PIXEL_FORMAT_RGB_565:
Zhijun He212e78d2013-06-07 11:36:23 -0700582 // Single plane 16bpp data.
583 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
584 pixelStride = 2;
585 break;
Zhijun He708e3592013-08-05 14:56:11 -0700586 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;
Zhijun He212e78d2013-06-07 11:36:23 -0700596 default:
597 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
598 "Pixel format: 0x%x is unsupported", fmt);
599 break;
600 }
601
602 return pixelStride;
603}
604
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700605static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800606 int32_t halReaderFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700607{
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
Lajos Molnar4fb44262015-01-22 19:03:31 -0800614 int32_t fmt = buffer->flexFormat;
Zhijun He212e78d2013-06-07 11:36:23 -0700615
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800616 fmt = applyFormatOverrides(fmt, halReaderFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700617
Zhijun He212e78d2013-06-07 11:36:23 -0700618 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:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700631 // Blob is used for JPEG data. It is single plane and has 0 row stride and
632 // 0 pixel stride
Zhijun He212e78d2013-06-07 11:36:23 -0700633 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
634 rowStride = 0;
635 break;
Zhijun He4c4064f2014-07-25 09:06:11 -0700636 case HAL_PIXEL_FORMAT_RAW10:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700637 case HAL_PIXEL_FORMAT_RAW12:
638 // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
Zhijun He4c4064f2014-07-25 09:06:11 -0700639 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
640 rowStride = buffer->stride;
641 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700642 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:
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800649 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He212e78d2013-06-07 11:36:23 -0700650 // 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;
Zhijun He708e3592013-08-05 14:56:11 -0700658 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;
Zhijun He212e78d2013-06-07 11:36:23 -0700672 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
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800682static int Image_getBufferWidth(CpuConsumer::LockedBuffer* buffer) {
683 if (buffer == NULL) return -1;
684
685 if (!buffer->crop.isEmpty()) {
686 return buffer->crop.getWidth();
687 }
688 return buffer->width;
689}
690
691static int Image_getBufferHeight(CpuConsumer::LockedBuffer* buffer) {
692 if (buffer == NULL) return -1;
693
694 if (!buffer->crop.isEmpty()) {
695 return buffer->crop.getHeight();
696 }
697 return buffer->height;
698}
699
Zhijun Hece9d6f92015-03-29 16:33:59 -0700700// --------------------------Methods for opaque Image and ImageReader----------
701
702static BufferItemConsumer* ImageReader_getOpaqueConsumer(JNIEnv* env, jobject thiz)
703{
704 ALOGV("%s:", __FUNCTION__);
705 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
706 if (ctx == NULL) {
707 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
708 return NULL;
709 }
710
711 if (!ctx->isOpaque()) {
712 jniThrowException(env, "java/lang/IllegalStateException",
713 "Non-opaque ImageReader doesn't support this method");
714 }
715
716 return ctx->getOpaqueConsumer();
717}
718
719static BufferItem* Image_getOpaqueBuffer(JNIEnv* env, jobject image)
720{
721 return reinterpret_cast<BufferItem*>(
722 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
723}
724
725static int Image_getOpaqueBufferWidth(BufferItem* buffer) {
726 if (buffer == NULL) return -1;
727
728 if (!buffer->mCrop.isEmpty()) {
729 return buffer->mCrop.getWidth();
730 }
731 return buffer->mGraphicBuffer->getWidth();
732}
733
734static int Image_getOpaqueBufferHeight(BufferItem* buffer) {
735 if (buffer == NULL) return -1;
736
737 if (!buffer->mCrop.isEmpty()) {
738 return buffer->mCrop.getHeight();
739 }
740
741 return buffer->mGraphicBuffer->getHeight();
742}
743
744
745
Zhijun He212e78d2013-06-07 11:36:23 -0700746// ----------------------------------------------------------------------------
747
748static void ImageReader_classInit(JNIEnv* env, jclass clazz)
749{
750 ALOGV("%s:", __FUNCTION__);
751
752 jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
753 LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
754 "can't find android/graphics/ImageReader$SurfaceImage");
Zhijun Hece9d6f92015-03-29 16:33:59 -0700755 gSurfaceImageClassInfo.mNativeBuffer = env->GetFieldID(
Jeff Brownef961212013-08-05 20:39:29 -0700756 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
Zhijun Hece9d6f92015-03-29 16:33:59 -0700757 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeBuffer == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700758 "can't find android/graphics/ImageReader.%s",
759 ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
760
Jeff Brownef961212013-08-05 20:39:29 -0700761 gSurfaceImageClassInfo.mTimestamp = env->GetFieldID(
762 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
763 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700764 "can't find android/graphics/ImageReader.%s",
765 ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
766
Jeff Brownef961212013-08-05 20:39:29 -0700767 gImageReaderClassInfo.mNativeContext = env->GetFieldID(
768 clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
769 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700770 "can't find android/graphics/ImageReader.%s",
771 ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
772
Jeff Brownef961212013-08-05 20:39:29 -0700773 gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(
774 clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
775 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700776 "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.
Jeff Brownef961212013-08-05 20:39:29 -0700781 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");
Zhijun He212e78d2013-06-07 11:36:23 -0700786}
787
788static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
789 jint width, jint height, jint format, jint maxImages)
790{
791 status_t res;
792 int nativeFormat;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800793 android_dataspace nativeDataspace;
Zhijun He212e78d2013-06-07 11:36:23 -0700794
795 ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
796 __FUNCTION__, width, height, format, maxImages);
797
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800798 PublicFormat publicFormat = static_cast<PublicFormat>(format);
799 nativeFormat = android_view_Surface_mapPublicFormatToHalFormat(
800 publicFormat);
801 nativeDataspace = android_view_Surface_mapPublicFormatToHalDataspace(
802 publicFormat);
Zhijun He212e78d2013-06-07 11:36:23 -0700803
Zhijun He212e78d2013-06-07 11:36:23 -0700804 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));
Zhijun Hece9d6f92015-03-29 16:33:59 -0700810
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;
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700817 String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
818 width, height, format, maxImages, getpid(),
819 createProcessUniqueId());
Zhijun Hece9d6f92015-03-29 16:33:59 -0700820 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);
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700831 opaqueConsumer->setName(consumerName);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700832 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);
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700841 cpuConsumer->setName(consumerName);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700842 consumer = cpuConsumer;
843 }
844
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700845 ctx->setProducer(gbProducer);
Zhijun He212e78d2013-06-07 11:36:23 -0700846 consumer->setFrameAvailableListener(ctx);
847 ImageReader_setNativeContext(env, thiz, ctx);
848 ctx->setBufferFormat(nativeFormat);
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800849 ctx->setBufferDataspace(nativeDataspace);
Zhijun He212e78d2013-06-07 11:36:23 -0700850 ctx->setBufferWidth(width);
851 ctx->setBufferHeight(height);
852
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800853 // Set the width/height/format/dataspace to the CpuConsumer
Zhijun Hece9d6f92015-03-29 16:33:59 -0700854 // 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 }
Zhijun He212e78d2013-06-07 11:36:23 -0700889 }
Zhijun He212e78d2013-06-07 11:36:23 -0700890}
891
892static void ImageReader_close(JNIEnv* env, jobject thiz)
893{
894 ALOGV("%s:", __FUNCTION__);
895
896 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
897 if (ctx == NULL) {
898 // ImageReader is already closed.
899 return;
900 }
901
Zhijun Hece9d6f92015-03-29 16:33:59 -0700902 ConsumerBase* consumer = NULL;
903 if (ctx->isOpaque()) {
904 consumer = ImageReader_getOpaqueConsumer(env, thiz);
905 } else {
906 consumer = ImageReader_getCpuConsumer(env, thiz);
907 }
908
Zhijun He212e78d2013-06-07 11:36:23 -0700909 if (consumer != NULL) {
910 consumer->abandon();
911 consumer->setFrameAvailableListener(NULL);
912 }
913 ImageReader_setNativeContext(env, thiz, NULL);
914}
915
916static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
917{
918 ALOGV("%s:", __FUNCTION__);
919 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
920 if (ctx == NULL) {
921 ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
922 return;
923 }
924
Zhijun Hece9d6f92015-03-29 16:33:59 -0700925 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());
Zhijun He212e78d2013-06-07 11:36:23 -0700943 }
Zhijun He212e78d2013-06-07 11:36:23 -0700944}
945
Zhijun Hece9d6f92015-03-29 16:33:59 -0700946static jint ImageReader_opaqueImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
Zhijun He212e78d2013-06-07 11:36:23 -0700947 ALOGV("%s:", __FUNCTION__);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700948 if (ctx == NULL || !ctx->isOpaque()) {
Zhijun He212e78d2013-06-07 11:36:23 -0700949 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
Igor Murashkine3351f12013-09-13 13:08:04 -0700950 return -1;
Zhijun He212e78d2013-06-07 11:36:23 -0700951 }
952
Zhijun Hece9d6f92015-03-29 16:33:59 -0700953 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
954 BufferItem* buffer = ctx->getOpaqueBuffer();
955 if (buffer == NULL) {
956 ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than"
957 " maxImages buffers");
958 return ACQUIRE_MAX_IMAGES;
959 }
960
961 status_t res = opaqueConsumer->acquireBuffer(buffer, 0);
962 if (res != OK) {
963 ctx->returnOpaqueBuffer(buffer);
964 if (res == INVALID_OPERATION) {
965 // Max number of images were already acquired.
966 ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)",
967 __FUNCTION__, strerror(-res), res);
968 return ACQUIRE_MAX_IMAGES;
969 } else {
970 ALOGE("%s: Acquire image failed with error: %s (%d)",
971 __FUNCTION__, strerror(-res), res);
972 return ACQUIRE_NO_BUFFERS;
973 }
974 }
975
976 // Set SurfaceImage instance member variables
977 Image_setOpaqueBuffer(env, image, buffer);
978 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
979 static_cast<jlong>(buffer->mTimestamp));
980
981 return ACQUIRE_SUCCESS;
982}
983
984static jint ImageReader_lockedImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
Zhijun He212e78d2013-06-07 11:36:23 -0700985 CpuConsumer* consumer = ctx->getCpuConsumer();
986 CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
987 if (buffer == NULL) {
Igor Murashkind901c032013-08-27 15:19:55 -0700988 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
989 " maxImages buffers");
Igor Murashkine3351f12013-09-13 13:08:04 -0700990 return ACQUIRE_MAX_IMAGES;
Zhijun He212e78d2013-06-07 11:36:23 -0700991 }
992 status_t res = consumer->lockNextBuffer(buffer);
993 if (res != NO_ERROR) {
lina.x.pi33477892014-01-27 10:31:44 +0800994 ctx->returnLockedBuffer(buffer);
Jeff Brownf724c272013-08-07 14:17:04 -0700995 if (res != BAD_VALUE /*no buffers*/) {
Igor Murashkindd064322013-08-14 19:05:17 -0700996 if (res == NOT_ENOUGH_DATA) {
Igor Murashkine3351f12013-09-13 13:08:04 -0700997 return ACQUIRE_MAX_IMAGES;
Igor Murashkindd064322013-08-14 19:05:17 -0700998 } else {
999 ALOGE("%s Fail to lockNextBuffer with error: %d ",
1000 __FUNCTION__, res);
Igor Murashkine3351f12013-09-13 13:08:04 -07001001 jniThrowExceptionFmt(env, "java/lang/AssertionError",
Igor Murashkindd064322013-08-14 19:05:17 -07001002 "Unknown error (%d) when we tried to lock buffer.",
1003 res);
1004 }
Jeff Brownf724c272013-08-07 14:17:04 -07001005 }
Igor Murashkine3351f12013-09-13 13:08:04 -07001006 return ACQUIRE_NO_BUFFERS;
Zhijun He212e78d2013-06-07 11:36:23 -07001007 }
1008
Lajos Molnar4fb44262015-01-22 19:03:31 -08001009 if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
Zhijun He4eda9f52013-09-18 08:00:02 -07001010 jniThrowException(env, "java/lang/UnsupportedOperationException",
1011 "NV21 format is not supported by ImageReader");
1012 return -1;
1013 }
1014
Zhijun He212e78d2013-06-07 11:36:23 -07001015 // 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) {
Zhijun He4eda9f52013-09-18 08:00:02 -07001019 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
1020 "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
Igor Murashkine3351f12013-09-13 13:08:04 -07001021 return -1;
Zhijun He212e78d2013-06-07 11:36:23 -07001022 }
1023
1024 // Check if the producer buffer configurations match what ImageReader configured.
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001025 int outputWidth = Image_getBufferWidth(buffer);
1026 int outputHeight = Image_getBufferHeight(buffer);
Zhijun He534046d2013-07-01 11:03:41 -07001027
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001028 int imgReaderFmt = ctx->getBufferFormat();
Zhijun He212e78d2013-06-07 11:36:23 -07001029 int imageReaderWidth = ctx->getBufferWidth();
1030 int imageReaderHeight = ctx->getBufferHeight();
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001031 if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) &&
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001032 (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);
Zhijun He212e78d2013-06-07 11:36:23 -07001035 }
1036
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001037 int bufFmt = buffer->format;
Lajos Molnar4fb44262015-01-22 19:03:31 -08001038 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
1039 bufFmt = buffer->flexFormat;
1040 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001041 if (imgReaderFmt != bufFmt) {
Ruben Brunk91b9aab2014-06-20 00:24:56 -07001042 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
1043 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001044 // Special casing for when producer switches to a format compatible with flexible YUV
1045 // (HAL_PIXEL_FORMAT_YCbCr_420_888).
Ruben Brunk91b9aab2014-06-20 00:24:56 -07001046 ctx->setBufferFormat(bufFmt);
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001047 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__);
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001052 } else {
1053 // Return the buffer to the queue.
1054 consumer->unlockBuffer(*buffer);
1055 ctx->returnLockedBuffer(buffer);
Zhijun He212e78d2013-06-07 11:36:23 -07001056
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001057 // 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.",
Lajos Molnar4fb44262015-01-22 19:03:31 -08001063 bufFmt, ctx->getBufferFormat());
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001064 jniThrowException(env, "java/lang/UnsupportedOperationException",
1065 msg.string());
1066 return -1;
1067 }
Zhijun He212e78d2013-06-07 11:36:23 -07001068 }
1069 // Set SurfaceImage instance member variables
1070 Image_setBuffer(env, image, buffer);
Jeff Brownef961212013-08-05 20:39:29 -07001071 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
1072 static_cast<jlong>(buffer->timestamp));
Zhijun He212e78d2013-06-07 11:36:23 -07001073
Igor Murashkine3351f12013-09-13 13:08:04 -07001074 return ACQUIRE_SUCCESS;
Zhijun He212e78d2013-06-07 11:36:23 -07001075}
1076
Zhijun Hece9d6f92015-03-29 16:33:59 -07001077static 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
1092static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) {
Zhijun Hef6a09e52015-02-24 18:12:23 -08001093 ALOGV("%s:", __FUNCTION__);
1094 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
1095 if (ctx == NULL) {
1096 jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed");
Zhijun Hece9d6f92015-03-29 16:33:59 -07001097 return -1;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001098 }
1099
Zhijun Hece9d6f92015-03-29 16:33:59 -07001100 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;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001106 }
1107
Zhijun Hece9d6f92015-03-29 16:33:59 -07001108 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;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001126}
1127
Zhijun He212e78d2013-06-07 11:36:23 -07001128static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
1129{
1130 ALOGV("%s: ", __FUNCTION__);
1131
Dan Stoza5b3c7c12014-03-12 16:44:45 -07001132 IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
1133 if (gbp == NULL) {
Zhijun He212e78d2013-06-07 11:36:23 -07001134 jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
1135 return NULL;
1136 }
1137
1138 // Wrap the IGBP in a Java-language Surface.
Dan Stoza5b3c7c12014-03-12 16:44:45 -07001139 return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
Zhijun He212e78d2013-06-07 11:36:23 -07001140}
1141
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001142static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -07001143{
1144 int rowStride, pixelStride;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001145 PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001146 int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat(
1147 publicReaderFormat);
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001148
Zhijun He212e78d2013-06-07 11:36:23 -07001149 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001150 if (isFormatOpaque(halReaderFormat)) {
1151 jniThrowException(env, "java/lang/IllegalStateException",
1152 "Opaque images from Opaque ImageReader do not have any planes");
1153 return NULL;
1154 }
Zhijun He212e78d2013-06-07 11:36:23 -07001155
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 }
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001162
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001163 rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat);
1164 pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat);
Zhijun He212e78d2013-06-07 11:36:23 -07001165
Jeff Brownef961212013-08-05 20:39:29 -07001166 jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
1167 gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
Zhijun He212e78d2013-06-07 11:36:23 -07001168
1169 return surfPlaneObj;
1170}
1171
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001172static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -07001173{
1174 uint8_t *base = NULL;
1175 uint32_t size = 0;
1176 jobject byteBuffer;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001177 PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001178 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1179 readerPublicFormat);
Zhijun He212e78d2013-06-07 11:36:23 -07001180
1181 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
1182
Zhijun Hece9d6f92015-03-29 16:33:59 -07001183 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
Zhijun He212e78d2013-06-07 11:36:23 -07001189 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
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001196 Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat);
Igor Murashkin5096def2014-06-24 10:49:11 -07001197
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",
Ruben Brunk31798f32014-09-25 19:56:54 -07001201 "Size too large for bytebuffer capacity %" PRIu32, size);
Igor Murashkin5096def2014-06-24 10:49:11 -07001202 return NULL;
1203 }
1204
Zhijun He212e78d2013-06-07 11:36:23 -07001205 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
Zhijun Hece9d6f92015-03-29 16:33:59 -07001214static jint Image_getWidth(JNIEnv* env, jobject thiz, jint format)
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001215{
Zhijun Hece9d6f92015-03-29 16:33:59 -07001216 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 }
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001223}
1224
Zhijun Hece9d6f92015-03-29 16:33:59 -07001225static jint Image_getHeight(JNIEnv* env, jobject thiz, jint format)
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001226{
Zhijun Hece9d6f92015-03-29 16:33:59 -07001227 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 }
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001234}
1235
Zhijun He7c3997d2015-05-06 10:08:37 -07001236static 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 PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
1244 buffer->flexFormat, buffer->dataSpace);
1245 return static_cast<jint>(publicFmt);
1246 }
1247}
1248
Zhijun He212e78d2013-06-07 11:36:23 -07001249} // extern "C"
1250
1251// ----------------------------------------------------------------------------
1252
1253static JNINativeMethod gImageReaderMethods[] = {
1254 {"nativeClassInit", "()V", (void*)ImageReader_classInit },
1255 {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
1256 {"nativeClose", "()V", (void*)ImageReader_close },
1257 {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001258 {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
Zhijun He212e78d2013-06-07 11:36:23 -07001259 {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
Zhijun Hece9d6f92015-03-29 16:33:59 -07001260 {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage },
Zhijun He212e78d2013-06-07 11:36:23 -07001261};
1262
1263static JNINativeMethod gImageMethods[] = {
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001264 {"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
1265 {"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001266 (void*)Image_createSurfacePlane },
Zhijun He7c3997d2015-05-06 10:08:37 -07001267 {"nativeGetWidth", "(I)I", (void*)Image_getWidth },
1268 {"nativeGetHeight", "(I)I", (void*)Image_getHeight },
1269 {"nativeGetFormat", "(I)I", (void*)Image_getFormat },
Zhijun He212e78d2013-06-07 11:36:23 -07001270};
1271
1272int register_android_media_ImageReader(JNIEnv *env) {
1273
1274 int ret1 = AndroidRuntime::registerNativeMethods(env,
1275 "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
1276
1277 int ret2 = AndroidRuntime::registerNativeMethods(env,
1278 "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
1279
1280 return (ret1 || ret2);
1281}