blob: 1c043e0706814a2b51ba2fb4898c3c51664dd655 [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.
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800104 // Note that we do support CPU access for HAL_PIXEL_FORMAT_RAW_OPAQUE
105 // (ImageFormat#RAW_PRIVATE) so it doesn't count as opaque here.
Zhijun Hece9d6f92015-03-29 16:33:59 -0700106 bool isOpaque() { return mFormat == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED; }
107
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700108 void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; }
109 IGraphicBufferProducer* getProducer() { return mProducer.get(); }
Zhijun He212e78d2013-06-07 11:36:23 -0700110
111 void setBufferFormat(int format) { mFormat = format; }
112 int getBufferFormat() { return mFormat; }
113
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800114 void setBufferDataspace(android_dataspace dataSpace) { mDataSpace = dataSpace; }
115 android_dataspace getBufferDataspace() { return mDataSpace; }
116
Zhijun He212e78d2013-06-07 11:36:23 -0700117 void setBufferWidth(int width) { mWidth = width; }
118 int getBufferWidth() { return mWidth; }
119
120 void setBufferHeight(int height) { mHeight = height; }
121 int getBufferHeight() { return mHeight; }
122
123private:
124 static JNIEnv* getJNIEnv(bool* needsDetach);
125 static void detachJNI();
126
127 List<CpuConsumer::LockedBuffer*> mBuffers;
Zhijun Hece9d6f92015-03-29 16:33:59 -0700128 List<BufferItem*> mOpaqueBuffers;
Zhijun He212e78d2013-06-07 11:36:23 -0700129 sp<CpuConsumer> mConsumer;
Zhijun Hece9d6f92015-03-29 16:33:59 -0700130 sp<BufferItemConsumer> mOpaqueConsumer;
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700131 sp<IGraphicBufferProducer> mProducer;
Zhijun He212e78d2013-06-07 11:36:23 -0700132 jobject mWeakThiz;
133 jclass mClazz;
134 int mFormat;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800135 android_dataspace mDataSpace;
Zhijun He212e78d2013-06-07 11:36:23 -0700136 int mWidth;
137 int mHeight;
138};
139
140JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
141 jobject weakThiz, jclass clazz, int maxImages) :
142 mWeakThiz(env->NewGlobalRef(weakThiz)),
143 mClazz((jclass)env->NewGlobalRef(clazz)) {
144 for (int i = 0; i < maxImages; i++) {
145 CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
Zhijun Hece9d6f92015-03-29 16:33:59 -0700146 BufferItem* opaqueBuffer = new BufferItem;
Zhijun He212e78d2013-06-07 11:36:23 -0700147 mBuffers.push_back(buffer);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700148 mOpaqueBuffers.push_back(opaqueBuffer);
Zhijun He212e78d2013-06-07 11:36:23 -0700149 }
150}
151
152JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
153 LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
154 *needsDetach = false;
155 JNIEnv* env = AndroidRuntime::getJNIEnv();
156 if (env == NULL) {
157 JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
158 JavaVM* vm = AndroidRuntime::getJavaVM();
159 int result = vm->AttachCurrentThread(&env, (void*) &args);
160 if (result != JNI_OK) {
161 ALOGE("thread attach failed: %#x", result);
162 return NULL;
163 }
164 *needsDetach = true;
165 }
166 return env;
167}
168
169void JNIImageReaderContext::detachJNI() {
170 JavaVM* vm = AndroidRuntime::getJavaVM();
171 int result = vm->DetachCurrentThread();
172 if (result != JNI_OK) {
173 ALOGE("thread detach failed: %#x", result);
174 }
175}
176
177CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
178 if (mBuffers.empty()) {
179 return NULL;
180 }
181 // Return a LockedBuffer pointer and remove it from the list
182 List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
183 CpuConsumer::LockedBuffer* buffer = *it;
184 mBuffers.erase(it);
185 return buffer;
186}
187
Igor Murashkind901c032013-08-27 15:19:55 -0700188void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) {
Zhijun He212e78d2013-06-07 11:36:23 -0700189 mBuffers.push_back(buffer);
190}
191
Zhijun Hece9d6f92015-03-29 16:33:59 -0700192BufferItem* JNIImageReaderContext::getOpaqueBuffer() {
193 if (mOpaqueBuffers.empty()) {
194 return NULL;
195 }
196 // Return an opaque buffer pointer and remove it from the list
197 List<BufferItem*>::iterator it = mOpaqueBuffers.begin();
198 BufferItem* buffer = *it;
199 mOpaqueBuffers.erase(it);
200 return buffer;
201}
202
203void JNIImageReaderContext::returnOpaqueBuffer(BufferItem* buffer) {
204 mOpaqueBuffers.push_back(buffer);
205}
206
Zhijun He212e78d2013-06-07 11:36:23 -0700207JNIImageReaderContext::~JNIImageReaderContext() {
208 bool needsDetach = false;
209 JNIEnv* env = getJNIEnv(&needsDetach);
210 if (env != NULL) {
211 env->DeleteGlobalRef(mWeakThiz);
212 env->DeleteGlobalRef(mClazz);
213 } else {
214 ALOGW("leaking JNI object references");
215 }
216 if (needsDetach) {
217 detachJNI();
218 }
219
220 // Delete LockedBuffers
221 for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin();
222 it != mBuffers.end(); it++) {
223 delete *it;
224 }
Zhijun Hece9d6f92015-03-29 16:33:59 -0700225
226 // Delete opaque buffers
227 for (List<BufferItem *>::iterator it = mOpaqueBuffers.begin();
228 it != mOpaqueBuffers.end(); it++) {
229 delete *it;
230 }
231
Zhijun He212e78d2013-06-07 11:36:23 -0700232 mBuffers.clear();
Zhijun Hece9d6f92015-03-29 16:33:59 -0700233 if (mConsumer != 0) {
234 mConsumer.clear();
235 }
236 if (mOpaqueConsumer != 0) {
237 mOpaqueConsumer.clear();
238 }
Zhijun He212e78d2013-06-07 11:36:23 -0700239}
240
Dan Stoza2c34b5e2014-11-04 11:36:33 -0800241void JNIImageReaderContext::onFrameAvailable(const BufferItem& /*item*/)
Zhijun He212e78d2013-06-07 11:36:23 -0700242{
243 ALOGV("%s: frame available", __FUNCTION__);
244 bool needsDetach = false;
245 JNIEnv* env = getJNIEnv(&needsDetach);
246 if (env != NULL) {
Jeff Brownef961212013-08-05 20:39:29 -0700247 env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz);
Zhijun He212e78d2013-06-07 11:36:23 -0700248 } else {
249 ALOGW("onFrameAvailable event will not posted");
250 }
251 if (needsDetach) {
252 detachJNI();
253 }
254}
255
256// ----------------------------------------------------------------------------
257
258extern "C" {
259
Zhijun Hece9d6f92015-03-29 16:33:59 -0700260static bool isFormatOpaque(int format) {
261 // Only treat IMPLEMENTATION_DEFINED as an opaque format for now.
262 return format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED;
263}
264
Zhijun He212e78d2013-06-07 11:36:23 -0700265static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
266{
267 JNIImageReaderContext *ctx;
268 ctx = reinterpret_cast<JNIImageReaderContext *>
Jeff Brownef961212013-08-05 20:39:29 -0700269 (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext));
Zhijun He212e78d2013-06-07 11:36:23 -0700270 return ctx;
271}
272
273static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
274{
275 ALOGV("%s:", __FUNCTION__);
276 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
277 if (ctx == NULL) {
278 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
279 return NULL;
280 }
Zhijun Hece9d6f92015-03-29 16:33:59 -0700281
282 if (ctx->isOpaque()) {
283 jniThrowException(env, "java/lang/IllegalStateException",
284 "Opaque ImageReader doesn't support this method");
285 return NULL;
286 }
287
Zhijun He212e78d2013-06-07 11:36:23 -0700288 return ctx->getCpuConsumer();
289}
290
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700291static IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz)
Mathias Agopian52a9a102013-08-02 01:38:38 -0700292{
293 ALOGV("%s:", __FUNCTION__);
294 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
295 if (ctx == NULL) {
296 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
297 return NULL;
298 }
Zhijun Hece9d6f92015-03-29 16:33:59 -0700299
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700300 return ctx->getProducer();
Mathias Agopian52a9a102013-08-02 01:38:38 -0700301}
302
Zhijun He212e78d2013-06-07 11:36:23 -0700303static void ImageReader_setNativeContext(JNIEnv* env,
304 jobject thiz, sp<JNIImageReaderContext> ctx)
305{
306 ALOGV("%s:", __FUNCTION__);
307 JNIImageReaderContext* const p = ImageReader_getContext(env, thiz);
308 if (ctx != 0) {
309 ctx->incStrong((void*)ImageReader_setNativeContext);
310 }
311 if (p) {
312 p->decStrong((void*)ImageReader_setNativeContext);
313 }
Jeff Brownef961212013-08-05 20:39:29 -0700314 env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext,
315 reinterpret_cast<jlong>(ctx.get()));
Zhijun He212e78d2013-06-07 11:36:23 -0700316}
317
318static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
319{
Jeff Brownef961212013-08-05 20:39:29 -0700320 return reinterpret_cast<CpuConsumer::LockedBuffer*>(
Zhijun Hece9d6f92015-03-29 16:33:59 -0700321 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
Zhijun He212e78d2013-06-07 11:36:23 -0700322}
323
324static void Image_setBuffer(JNIEnv* env, jobject thiz,
325 const CpuConsumer::LockedBuffer* buffer)
326{
Zhijun Hece9d6f92015-03-29 16:33:59 -0700327 env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
328}
329
330static void Image_setOpaqueBuffer(JNIEnv* env, jobject thiz,
331 const BufferItem* buffer)
332{
333 env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, reinterpret_cast<jlong>(buffer));
Zhijun He212e78d2013-06-07 11:36:23 -0700334}
335
Ruben Brunk31798f32014-09-25 19:56:54 -0700336static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer, bool usingRGBAOverride)
Zhijun He534046d2013-07-01 11:03:41 -0700337{
338 ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
339 uint32_t size = 0;
340 uint32_t width = buffer->width;
341 uint8_t* jpegBuffer = buffer->data;
342
Ruben Brunk31798f32014-09-25 19:56:54 -0700343 if (usingRGBAOverride) {
Ruben Brunk0c798842014-09-30 03:42:13 -0700344 width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4;
Ruben Brunk31798f32014-09-25 19:56:54 -0700345 }
346
Zhijun He534046d2013-07-01 11:03:41 -0700347 // First check for JPEG transport header at the end of the buffer
348 uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
349 struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
350 if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
351 size = blob->jpeg_size;
352 ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
353 }
354
355 // failed to find size, default to whole buffer
356 if (size == 0) {
Igor Murashkin5096def2014-06-24 10:49:11 -0700357 /*
358 * This is a problem because not including the JPEG header
359 * means that in certain rare situations a regular JPEG blob
360 * will be misidentified as having a header, in which case
361 * we will get a garbage size value.
362 */
363 ALOGW("%s: No JPEG header detected, defaulting to size=width=%d",
364 __FUNCTION__, width);
Zhijun He534046d2013-07-01 11:03:41 -0700365 size = width;
366 }
367
368 return size;
369}
370
Ruben Brunk31798f32014-09-25 19:56:54 -0700371static bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t readerCtxFormat) {
372 return readerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888;
373}
374
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700375static int32_t applyFormatOverrides(int32_t bufferFormat, int32_t readerCtxFormat)
376{
377 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
378 // write limitations for some platforms (b/17379185).
Ruben Brunk31798f32014-09-25 19:56:54 -0700379 if (usingRGBAToJpegOverride(bufferFormat, readerCtxFormat)) {
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700380 return HAL_PIXEL_FORMAT_BLOB;
381 }
382 return bufferFormat;
383}
384
Zhijun He212e78d2013-06-07 11:36:23 -0700385static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700386 uint8_t **base, uint32_t *size, int32_t readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700387{
388 ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
389 ALOG_ASSERT(base != NULL, "base is NULL!!!");
390 ALOG_ASSERT(size != NULL, "size is NULL!!!");
391 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
392
Zhijun He7f4d3142013-07-23 07:54:38 -0700393 ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
Zhijun He212e78d2013-06-07 11:36:23 -0700394
395 uint32_t dataSize, ySize, cSize, cStride;
396 uint8_t *cb, *cr;
397 uint8_t *pData = NULL;
Zhijun He708e3592013-08-05 14:56:11 -0700398 int bytesPerPixel = 0;
Zhijun He212e78d2013-06-07 11:36:23 -0700399
400 dataSize = ySize = cSize = cStride = 0;
Lajos Molnar4fb44262015-01-22 19:03:31 -0800401 int32_t fmt = buffer->flexFormat;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700402
Ruben Brunk31798f32014-09-25 19:56:54 -0700403 bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, readerFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700404 fmt = applyFormatOverrides(fmt, readerFormat);
Zhijun He212e78d2013-06-07 11:36:23 -0700405 switch (fmt) {
406 case HAL_PIXEL_FORMAT_YCbCr_420_888:
407 pData =
408 (idx == 0) ?
409 buffer->data :
410 (idx == 1) ?
411 buffer->dataCb :
412 buffer->dataCr;
Lajos Molnar4fb44262015-01-22 19:03:31 -0800413 // only map until last pixel
Zhijun He212e78d2013-06-07 11:36:23 -0700414 if (idx == 0) {
Lajos Molnar4fb44262015-01-22 19:03:31 -0800415 dataSize = buffer->stride * (buffer->height - 1) + buffer->width;
Zhijun He212e78d2013-06-07 11:36:23 -0700416 } else {
Lajos Molnar4fb44262015-01-22 19:03:31 -0800417 dataSize = buffer->chromaStride * (buffer->height / 2 - 1) +
418 buffer->chromaStep * (buffer->width / 2 - 1) + 1;
Zhijun He212e78d2013-06-07 11:36:23 -0700419 }
420 break;
421 // NV21
422 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
423 cr = buffer->data + (buffer->stride * buffer->height);
424 cb = cr + 1;
Lajos Molnar4fb44262015-01-22 19:03:31 -0800425 // only map until last pixel
426 ySize = buffer->width * (buffer->height - 1) + buffer->width;
427 cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1;
Zhijun He212e78d2013-06-07 11:36:23 -0700428
429 pData =
430 (idx == 0) ?
431 buffer->data :
432 (idx == 1) ?
433 cb:
434 cr;
435
436 dataSize = (idx == 0) ? ySize : cSize;
437 break;
438 case HAL_PIXEL_FORMAT_YV12:
439 // Y and C stride need to be 16 pixel aligned.
440 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
441 "Stride is not 16 pixel aligned %d", buffer->stride);
442
443 ySize = buffer->stride * buffer->height;
444 cStride = ALIGN(buffer->stride / 2, 16);
445 cr = buffer->data + ySize;
446 cSize = cStride * buffer->height / 2;
447 cb = cr + cSize;
448
449 pData =
450 (idx == 0) ?
451 buffer->data :
452 (idx == 1) ?
453 cb :
454 cr;
455 dataSize = (idx == 0) ? ySize : cSize;
456 break;
457 case HAL_PIXEL_FORMAT_Y8:
458 // Single plane, 8bpp.
459 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
460
461 pData = buffer->data;
462 dataSize = buffer->stride * buffer->height;
463 break;
464 case HAL_PIXEL_FORMAT_Y16:
Zhijun He977ad8d2014-04-08 16:59:29 -0700465 bytesPerPixel = 2;
Zhijun He212e78d2013-06-07 11:36:23 -0700466 // Single plane, 16bpp, strides are specified in pixels, not in bytes
467 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
468
469 pData = buffer->data;
Zhijun He977ad8d2014-04-08 16:59:29 -0700470 dataSize = buffer->stride * buffer->height * bytesPerPixel;
Zhijun He212e78d2013-06-07 11:36:23 -0700471 break;
472 case HAL_PIXEL_FORMAT_BLOB:
473 // Used for JPEG data, height must be 1, width == size, single plane.
474 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800475 ALOG_ASSERT(buffer->height == 1,
476 "JPEG should has height value one but got %d", buffer->height);
Zhijun He212e78d2013-06-07 11:36:23 -0700477
478 pData = buffer->data;
Ruben Brunk31798f32014-09-25 19:56:54 -0700479 dataSize = Image_getJpegSize(buffer, usingRGBAOverride);
Zhijun He212e78d2013-06-07 11:36:23 -0700480 break;
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800481 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He212e78d2013-06-07 11:36:23 -0700482 // Single plane 16bpp bayer data.
Zhijun He977ad8d2014-04-08 16:59:29 -0700483 bytesPerPixel = 2;
Zhijun He212e78d2013-06-07 11:36:23 -0700484 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
485 pData = buffer->data;
Zhijun He977ad8d2014-04-08 16:59:29 -0700486 dataSize = buffer->stride * buffer->height * bytesPerPixel;
Zhijun He212e78d2013-06-07 11:36:23 -0700487 break;
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800488 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
489 // Used for RAW_OPAQUE data, height must be 1, width == size, single plane.
490 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
491 ALOG_ASSERT(buffer->height == 1,
492 "RAW_PRIVATE should has height value one but got %d", buffer->height);
493 pData = buffer->data;
494 dataSize = buffer->width;
495 break;
Zhijun Hed1988a92014-07-01 04:15:09 -0700496 case HAL_PIXEL_FORMAT_RAW10:
497 // Single plane 10bpp bayer data.
498 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
499 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
500 "Width is not multiple of 4 %d", buffer->width);
501 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
502 "Height is not even %d", buffer->height);
Zhijun He4c4064f2014-07-25 09:06:11 -0700503 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8),
504 "stride (%d) should be at least %d",
505 buffer->stride, buffer->width * 10 / 8);
Zhijun Hed1988a92014-07-01 04:15:09 -0700506 pData = buffer->data;
Zhijun He4c4064f2014-07-25 09:06:11 -0700507 dataSize = buffer->stride * buffer->height;
Zhijun Hed1988a92014-07-01 04:15:09 -0700508 break;
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700509 case HAL_PIXEL_FORMAT_RAW12:
510 // Single plane 10bpp bayer data.
511 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
512 LOG_ALWAYS_FATAL_IF(buffer->width % 4,
513 "Width is not multiple of 4 %d", buffer->width);
514 LOG_ALWAYS_FATAL_IF(buffer->height % 2,
515 "Height is not even %d", buffer->height);
516 LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 12 / 8),
517 "stride (%d) should be at least %d",
518 buffer->stride, buffer->width * 12 / 8);
519 pData = buffer->data;
520 dataSize = buffer->stride * buffer->height;
521 break;
Zhijun He708e3592013-08-05 14:56:11 -0700522 case HAL_PIXEL_FORMAT_RGBA_8888:
523 case HAL_PIXEL_FORMAT_RGBX_8888:
524 // Single plane, 32bpp.
525 bytesPerPixel = 4;
526 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
527 pData = buffer->data;
528 dataSize = buffer->stride * buffer->height * bytesPerPixel;
529 break;
530 case HAL_PIXEL_FORMAT_RGB_565:
531 // Single plane, 16bpp.
532 bytesPerPixel = 2;
533 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
534 pData = buffer->data;
535 dataSize = buffer->stride * buffer->height * bytesPerPixel;
536 break;
537 case HAL_PIXEL_FORMAT_RGB_888:
538 // Single plane, 24bpp.
539 bytesPerPixel = 3;
540 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
541 pData = buffer->data;
542 dataSize = buffer->stride * buffer->height * bytesPerPixel;
543 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700544 default:
545 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
546 "Pixel format: 0x%x is unsupported", fmt);
547 break;
548 }
549
550 *base = pData;
551 *size = dataSize;
552}
553
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700554static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800555 int32_t halReaderFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700556{
557 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
558 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
559
560 int pixelStride = 0;
561 ALOG_ASSERT(buffer != NULL, "buffer is NULL");
562
Lajos Molnar4fb44262015-01-22 19:03:31 -0800563 int32_t fmt = buffer->flexFormat;
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700564
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800565 fmt = applyFormatOverrides(fmt, halReaderFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700566
Zhijun He212e78d2013-06-07 11:36:23 -0700567 switch (fmt) {
568 case HAL_PIXEL_FORMAT_YCbCr_420_888:
569 pixelStride = (idx == 0) ? 1 : buffer->chromaStep;
570 break;
571 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
572 pixelStride = (idx == 0) ? 1 : 2;
573 break;
574 case HAL_PIXEL_FORMAT_Y8:
575 // Single plane 8bpp data.
576 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
Zhijun He212e78d2013-06-07 11:36:23 -0700577 break;
578 case HAL_PIXEL_FORMAT_YV12:
579 pixelStride = 1;
580 break;
581 case HAL_PIXEL_FORMAT_BLOB:
Zhijun Hed1988a92014-07-01 04:15:09 -0700582 case HAL_PIXEL_FORMAT_RAW10:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700583 case HAL_PIXEL_FORMAT_RAW12:
584 // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data,
585 // those are single plane data with pixel stride 0 since they don't really have a
586 // well defined pixel stride
Zhijun He212e78d2013-06-07 11:36:23 -0700587 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
588 pixelStride = 0;
589 break;
590 case HAL_PIXEL_FORMAT_Y16:
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800591 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He708e3592013-08-05 14:56:11 -0700592 case HAL_PIXEL_FORMAT_RGB_565:
Zhijun He212e78d2013-06-07 11:36:23 -0700593 // Single plane 16bpp data.
594 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
595 pixelStride = 2;
596 break;
Zhijun He708e3592013-08-05 14:56:11 -0700597 case HAL_PIXEL_FORMAT_RGBA_8888:
598 case HAL_PIXEL_FORMAT_RGBX_8888:
599 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
600 pixelStride = 4;
601 break;
602 case HAL_PIXEL_FORMAT_RGB_888:
603 // Single plane, 24bpp.
604 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
605 pixelStride = 3;
606 break;
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800607 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
608 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
609 pixelStride = 0; // RAW OPAQUE doesn't have pixel stride
610 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700611 default:
612 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
613 "Pixel format: 0x%x is unsupported", fmt);
614 break;
615 }
616
617 return pixelStride;
618}
619
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700620static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800621 int32_t halReaderFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700622{
623 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
624 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
625
626 int rowStride = 0;
627 ALOG_ASSERT(buffer != NULL, "buffer is NULL");
628
Lajos Molnar4fb44262015-01-22 19:03:31 -0800629 int32_t fmt = buffer->flexFormat;
Zhijun He212e78d2013-06-07 11:36:23 -0700630
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800631 fmt = applyFormatOverrides(fmt, halReaderFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700632
Zhijun He212e78d2013-06-07 11:36:23 -0700633 switch (fmt) {
634 case HAL_PIXEL_FORMAT_YCbCr_420_888:
635 rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
636 break;
637 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
638 rowStride = buffer->width;
639 break;
640 case HAL_PIXEL_FORMAT_YV12:
641 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
642 "Stride is not 16 pixel aligned %d", buffer->stride);
643 rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
644 break;
645 case HAL_PIXEL_FORMAT_BLOB:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700646 // Blob is used for JPEG data. It is single plane and has 0 row stride and
647 // 0 pixel stride
Zhijun He212e78d2013-06-07 11:36:23 -0700648 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
649 rowStride = 0;
650 break;
Zhijun He4c4064f2014-07-25 09:06:11 -0700651 case HAL_PIXEL_FORMAT_RAW10:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700652 case HAL_PIXEL_FORMAT_RAW12:
653 // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
Zhijun He4c4064f2014-07-25 09:06:11 -0700654 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
655 rowStride = buffer->stride;
656 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700657 case HAL_PIXEL_FORMAT_Y8:
658 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
659 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
660 "Stride is not 16 pixel aligned %d", buffer->stride);
661 rowStride = buffer->stride;
662 break;
663 case HAL_PIXEL_FORMAT_Y16:
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800664 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He212e78d2013-06-07 11:36:23 -0700665 // In native side, strides are specified in pixels, not in bytes.
666 // Single plane 16bpp bayer data. even width/height,
667 // row stride multiple of 16 pixels (32 bytes)
668 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
669 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
670 "Stride is not 16 pixel aligned %d", buffer->stride);
671 rowStride = buffer->stride * 2;
672 break;
Zhijun He708e3592013-08-05 14:56:11 -0700673 case HAL_PIXEL_FORMAT_RGB_565:
674 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
675 rowStride = buffer->stride * 2;
676 break;
677 case HAL_PIXEL_FORMAT_RGBA_8888:
678 case HAL_PIXEL_FORMAT_RGBX_8888:
679 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
680 rowStride = buffer->stride * 4;
681 break;
682 case HAL_PIXEL_FORMAT_RGB_888:
683 // Single plane, 24bpp.
684 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
685 rowStride = buffer->stride * 3;
686 break;
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800687 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
688 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
689 rowStride = 0; // RAW OPAQUE doesn't have row stride
690 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700691 default:
692 ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
693 jniThrowException(env, "java/lang/UnsupportedOperationException",
694 "unsupported buffer format");
695 break;
696 }
697
698 return rowStride;
699}
700
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800701static int Image_getBufferWidth(CpuConsumer::LockedBuffer* buffer) {
702 if (buffer == NULL) return -1;
703
704 if (!buffer->crop.isEmpty()) {
705 return buffer->crop.getWidth();
706 }
707 return buffer->width;
708}
709
710static int Image_getBufferHeight(CpuConsumer::LockedBuffer* buffer) {
711 if (buffer == NULL) return -1;
712
713 if (!buffer->crop.isEmpty()) {
714 return buffer->crop.getHeight();
715 }
716 return buffer->height;
717}
718
Zhijun Hece9d6f92015-03-29 16:33:59 -0700719// --------------------------Methods for opaque Image and ImageReader----------
720
721static BufferItemConsumer* ImageReader_getOpaqueConsumer(JNIEnv* env, jobject thiz)
722{
723 ALOGV("%s:", __FUNCTION__);
724 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
725 if (ctx == NULL) {
726 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
727 return NULL;
728 }
729
730 if (!ctx->isOpaque()) {
731 jniThrowException(env, "java/lang/IllegalStateException",
732 "Non-opaque ImageReader doesn't support this method");
733 }
734
735 return ctx->getOpaqueConsumer();
736}
737
738static BufferItem* Image_getOpaqueBuffer(JNIEnv* env, jobject image)
739{
740 return reinterpret_cast<BufferItem*>(
741 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
742}
743
744static int Image_getOpaqueBufferWidth(BufferItem* buffer) {
745 if (buffer == NULL) return -1;
746
747 if (!buffer->mCrop.isEmpty()) {
748 return buffer->mCrop.getWidth();
749 }
750 return buffer->mGraphicBuffer->getWidth();
751}
752
753static int Image_getOpaqueBufferHeight(BufferItem* buffer) {
754 if (buffer == NULL) return -1;
755
756 if (!buffer->mCrop.isEmpty()) {
757 return buffer->mCrop.getHeight();
758 }
759
760 return buffer->mGraphicBuffer->getHeight();
761}
762
763
764
Zhijun He212e78d2013-06-07 11:36:23 -0700765// ----------------------------------------------------------------------------
766
767static void ImageReader_classInit(JNIEnv* env, jclass clazz)
768{
769 ALOGV("%s:", __FUNCTION__);
770
771 jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
772 LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
773 "can't find android/graphics/ImageReader$SurfaceImage");
Zhijun Hece9d6f92015-03-29 16:33:59 -0700774 gSurfaceImageClassInfo.mNativeBuffer = env->GetFieldID(
Jeff Brownef961212013-08-05 20:39:29 -0700775 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
Zhijun Hece9d6f92015-03-29 16:33:59 -0700776 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeBuffer == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700777 "can't find android/graphics/ImageReader.%s",
778 ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
779
Jeff Brownef961212013-08-05 20:39:29 -0700780 gSurfaceImageClassInfo.mTimestamp = env->GetFieldID(
781 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
782 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700783 "can't find android/graphics/ImageReader.%s",
784 ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
785
Jeff Brownef961212013-08-05 20:39:29 -0700786 gImageReaderClassInfo.mNativeContext = env->GetFieldID(
787 clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
788 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700789 "can't find android/graphics/ImageReader.%s",
790 ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
791
Jeff Brownef961212013-08-05 20:39:29 -0700792 gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(
793 clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
794 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700795 "can't find android/graphics/ImageReader.postEventFromNative");
796
797 jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
798 LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
799 // FindClass only gives a local reference of jclass object.
Jeff Brownef961212013-08-05 20:39:29 -0700800 gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
801 gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>",
802 "(Landroid/media/ImageReader$SurfaceImage;III)V");
803 LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
804 "Can not find SurfacePlane constructor");
Zhijun He212e78d2013-06-07 11:36:23 -0700805}
806
807static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
808 jint width, jint height, jint format, jint maxImages)
809{
810 status_t res;
811 int nativeFormat;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800812 android_dataspace nativeDataspace;
Zhijun He212e78d2013-06-07 11:36:23 -0700813
814 ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
815 __FUNCTION__, width, height, format, maxImages);
816
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800817 PublicFormat publicFormat = static_cast<PublicFormat>(format);
818 nativeFormat = android_view_Surface_mapPublicFormatToHalFormat(
819 publicFormat);
820 nativeDataspace = android_view_Surface_mapPublicFormatToHalDataspace(
821 publicFormat);
Zhijun He212e78d2013-06-07 11:36:23 -0700822
Zhijun He212e78d2013-06-07 11:36:23 -0700823 jclass clazz = env->GetObjectClass(thiz);
824 if (clazz == NULL) {
825 jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
826 return;
827 }
828 sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
Zhijun Hece9d6f92015-03-29 16:33:59 -0700829
830 sp<IGraphicBufferProducer> gbProducer;
831 sp<IGraphicBufferConsumer> gbConsumer;
832 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
833 sp<ConsumerBase> consumer;
834 sp<CpuConsumer> cpuConsumer;
835 sp<BufferItemConsumer> opaqueConsumer;
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700836 String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
837 width, height, format, maxImages, getpid(),
838 createProcessUniqueId());
Zhijun Hece9d6f92015-03-29 16:33:59 -0700839 if (isFormatOpaque(nativeFormat)) {
840 // Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
841 // encoding. The only possibility will be ZSL output.
842 opaqueConsumer =
843 new BufferItemConsumer(gbConsumer, GRALLOC_USAGE_SW_READ_NEVER, maxImages,
844 /*controlledByApp*/true);
845 if (opaqueConsumer == NULL) {
846 jniThrowRuntimeException(env, "Failed to allocate native opaque consumer");
847 return;
848 }
849 ctx->setOpaqueConsumer(opaqueConsumer);
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700850 opaqueConsumer->setName(consumerName);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700851 consumer = opaqueConsumer;
852 } else {
853 cpuConsumer = new CpuConsumer(gbConsumer, maxImages, /*controlledByApp*/true);
854 // TODO: throw dvm exOutOfMemoryError?
855 if (cpuConsumer == NULL) {
856 jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
857 return;
858 }
859 ctx->setCpuConsumer(cpuConsumer);
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700860 cpuConsumer->setName(consumerName);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700861 consumer = cpuConsumer;
862 }
863
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700864 ctx->setProducer(gbProducer);
Zhijun He212e78d2013-06-07 11:36:23 -0700865 consumer->setFrameAvailableListener(ctx);
866 ImageReader_setNativeContext(env, thiz, ctx);
867 ctx->setBufferFormat(nativeFormat);
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800868 ctx->setBufferDataspace(nativeDataspace);
Zhijun He212e78d2013-06-07 11:36:23 -0700869 ctx->setBufferWidth(width);
870 ctx->setBufferHeight(height);
871
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800872 // Set the width/height/format/dataspace to the CpuConsumer
Zhijun Hece9d6f92015-03-29 16:33:59 -0700873 // TODO: below code can be simplified once b/19977701 is fixed.
874 if (isFormatOpaque(nativeFormat)) {
875 res = opaqueConsumer->setDefaultBufferSize(width, height);
876 if (res != OK) {
877 jniThrowException(env, "java/lang/IllegalStateException",
878 "Failed to set opaque consumer buffer size");
879 return;
880 }
881 res = opaqueConsumer->setDefaultBufferFormat(nativeFormat);
882 if (res != OK) {
883 jniThrowException(env, "java/lang/IllegalStateException",
884 "Failed to set opaque consumer buffer format");
885 }
886 res = opaqueConsumer->setDefaultBufferDataSpace(nativeDataspace);
887 if (res != OK) {
888 jniThrowException(env, "java/lang/IllegalStateException",
889 "Failed to set opaque consumer buffer dataSpace");
890 }
891 } else {
892 res = cpuConsumer->setDefaultBufferSize(width, height);
893 if (res != OK) {
894 jniThrowException(env, "java/lang/IllegalStateException",
895 "Failed to set CpuConsumer buffer size");
896 return;
897 }
898 res = cpuConsumer->setDefaultBufferFormat(nativeFormat);
899 if (res != OK) {
900 jniThrowException(env, "java/lang/IllegalStateException",
901 "Failed to set CpuConsumer buffer format");
902 }
903 res = cpuConsumer->setDefaultBufferDataSpace(nativeDataspace);
904 if (res != OK) {
905 jniThrowException(env, "java/lang/IllegalStateException",
906 "Failed to set CpuConsumer buffer dataSpace");
907 }
Zhijun He212e78d2013-06-07 11:36:23 -0700908 }
Zhijun He212e78d2013-06-07 11:36:23 -0700909}
910
911static void ImageReader_close(JNIEnv* env, jobject thiz)
912{
913 ALOGV("%s:", __FUNCTION__);
914
915 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
916 if (ctx == NULL) {
917 // ImageReader is already closed.
918 return;
919 }
920
Zhijun Hece9d6f92015-03-29 16:33:59 -0700921 ConsumerBase* consumer = NULL;
922 if (ctx->isOpaque()) {
923 consumer = ImageReader_getOpaqueConsumer(env, thiz);
924 } else {
925 consumer = ImageReader_getCpuConsumer(env, thiz);
926 }
927
Zhijun He212e78d2013-06-07 11:36:23 -0700928 if (consumer != NULL) {
929 consumer->abandon();
930 consumer->setFrameAvailableListener(NULL);
931 }
932 ImageReader_setNativeContext(env, thiz, NULL);
933}
934
935static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
936{
937 ALOGV("%s:", __FUNCTION__);
938 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
939 if (ctx == NULL) {
940 ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
941 return;
942 }
943
Zhijun Hece9d6f92015-03-29 16:33:59 -0700944 if (ctx->isOpaque()) {
945 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
946 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
947 opaqueConsumer->releaseBuffer(*opaqueBuffer); // Not using fence for now.
948 Image_setOpaqueBuffer(env, image, NULL);
949 ctx->returnOpaqueBuffer(opaqueBuffer);
950 ALOGV("%s: Opaque Image has been released", __FUNCTION__);
951 } else {
952 CpuConsumer* consumer = ctx->getCpuConsumer();
953 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
954 if (!buffer) {
Zhijun Hedc6bb242015-12-03 15:34:34 -0800955 // Release an already closed image is harmless.
Zhijun Hece9d6f92015-03-29 16:33:59 -0700956 return;
957 }
958 consumer->unlockBuffer(*buffer);
959 Image_setBuffer(env, image, NULL);
960 ctx->returnLockedBuffer(buffer);
961 ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());
Zhijun He212e78d2013-06-07 11:36:23 -0700962 }
Zhijun He212e78d2013-06-07 11:36:23 -0700963}
964
Zhijun Hece9d6f92015-03-29 16:33:59 -0700965static jint ImageReader_opaqueImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
Zhijun He212e78d2013-06-07 11:36:23 -0700966 ALOGV("%s:", __FUNCTION__);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700967 if (ctx == NULL || !ctx->isOpaque()) {
Zhijun He212e78d2013-06-07 11:36:23 -0700968 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
Igor Murashkine3351f12013-09-13 13:08:04 -0700969 return -1;
Zhijun He212e78d2013-06-07 11:36:23 -0700970 }
971
Zhijun Hece9d6f92015-03-29 16:33:59 -0700972 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
973 BufferItem* buffer = ctx->getOpaqueBuffer();
974 if (buffer == NULL) {
975 ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than"
976 " maxImages buffers");
977 return ACQUIRE_MAX_IMAGES;
978 }
979
980 status_t res = opaqueConsumer->acquireBuffer(buffer, 0);
981 if (res != OK) {
982 ctx->returnOpaqueBuffer(buffer);
983 if (res == INVALID_OPERATION) {
984 // Max number of images were already acquired.
985 ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)",
986 __FUNCTION__, strerror(-res), res);
987 return ACQUIRE_MAX_IMAGES;
988 } else {
989 ALOGE("%s: Acquire image failed with error: %s (%d)",
990 __FUNCTION__, strerror(-res), res);
991 return ACQUIRE_NO_BUFFERS;
992 }
993 }
994
995 // Set SurfaceImage instance member variables
996 Image_setOpaqueBuffer(env, image, buffer);
997 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
998 static_cast<jlong>(buffer->mTimestamp));
999
1000 return ACQUIRE_SUCCESS;
1001}
1002
1003static jint ImageReader_lockedImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
Zhijun He212e78d2013-06-07 11:36:23 -07001004 CpuConsumer* consumer = ctx->getCpuConsumer();
1005 CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
1006 if (buffer == NULL) {
Igor Murashkind901c032013-08-27 15:19:55 -07001007 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
1008 " maxImages buffers");
Igor Murashkine3351f12013-09-13 13:08:04 -07001009 return ACQUIRE_MAX_IMAGES;
Zhijun He212e78d2013-06-07 11:36:23 -07001010 }
1011 status_t res = consumer->lockNextBuffer(buffer);
1012 if (res != NO_ERROR) {
lina.x.pi33477892014-01-27 10:31:44 +08001013 ctx->returnLockedBuffer(buffer);
Jeff Brownf724c272013-08-07 14:17:04 -07001014 if (res != BAD_VALUE /*no buffers*/) {
Igor Murashkindd064322013-08-14 19:05:17 -07001015 if (res == NOT_ENOUGH_DATA) {
Igor Murashkine3351f12013-09-13 13:08:04 -07001016 return ACQUIRE_MAX_IMAGES;
Igor Murashkindd064322013-08-14 19:05:17 -07001017 } else {
1018 ALOGE("%s Fail to lockNextBuffer with error: %d ",
1019 __FUNCTION__, res);
Igor Murashkine3351f12013-09-13 13:08:04 -07001020 jniThrowExceptionFmt(env, "java/lang/AssertionError",
Igor Murashkindd064322013-08-14 19:05:17 -07001021 "Unknown error (%d) when we tried to lock buffer.",
1022 res);
1023 }
Jeff Brownf724c272013-08-07 14:17:04 -07001024 }
Igor Murashkine3351f12013-09-13 13:08:04 -07001025 return ACQUIRE_NO_BUFFERS;
Zhijun He212e78d2013-06-07 11:36:23 -07001026 }
1027
Lajos Molnar4fb44262015-01-22 19:03:31 -08001028 if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
Zhijun He4eda9f52013-09-18 08:00:02 -07001029 jniThrowException(env, "java/lang/UnsupportedOperationException",
1030 "NV21 format is not supported by ImageReader");
1031 return -1;
1032 }
1033
Zhijun He212e78d2013-06-07 11:36:23 -07001034 // Check if the left-top corner of the crop rect is origin, we currently assume this point is
1035 // zero, will revist this once this assumption turns out problematic.
1036 Point lt = buffer->crop.leftTop();
1037 if (lt.x != 0 || lt.y != 0) {
Zhijun He4eda9f52013-09-18 08:00:02 -07001038 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
1039 "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
Igor Murashkine3351f12013-09-13 13:08:04 -07001040 return -1;
Zhijun He212e78d2013-06-07 11:36:23 -07001041 }
1042
1043 // Check if the producer buffer configurations match what ImageReader configured.
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001044 int outputWidth = Image_getBufferWidth(buffer);
1045 int outputHeight = Image_getBufferHeight(buffer);
Zhijun He534046d2013-07-01 11:03:41 -07001046
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001047 int imgReaderFmt = ctx->getBufferFormat();
Zhijun He212e78d2013-06-07 11:36:23 -07001048 int imageReaderWidth = ctx->getBufferWidth();
1049 int imageReaderHeight = ctx->getBufferHeight();
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001050 if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) &&
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001051 (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) {
1052 ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
1053 __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
Zhijun He212e78d2013-06-07 11:36:23 -07001054 }
1055
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001056 int bufFmt = buffer->format;
Lajos Molnar4fb44262015-01-22 19:03:31 -08001057 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
1058 bufFmt = buffer->flexFormat;
1059 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001060 if (imgReaderFmt != bufFmt) {
Ruben Brunk91b9aab2014-06-20 00:24:56 -07001061 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
1062 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001063 // Special casing for when producer switches to a format compatible with flexible YUV
1064 // (HAL_PIXEL_FORMAT_YCbCr_420_888).
Ruben Brunk91b9aab2014-06-20 00:24:56 -07001065 ctx->setBufferFormat(bufFmt);
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001066 ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt);
1067 } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufFmt == HAL_PIXEL_FORMAT_RGBA_8888) {
1068 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
1069 // write limitations for (b/17379185).
1070 ALOGD("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__);
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001071 } else {
1072 // Return the buffer to the queue.
1073 consumer->unlockBuffer(*buffer);
1074 ctx->returnLockedBuffer(buffer);
Zhijun He212e78d2013-06-07 11:36:23 -07001075
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001076 // Throw exception
1077 ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
1078 buffer->format, ctx->getBufferFormat());
1079 String8 msg;
1080 msg.appendFormat("The producer output buffer format 0x%x doesn't "
1081 "match the ImageReader's configured buffer format 0x%x.",
Lajos Molnar4fb44262015-01-22 19:03:31 -08001082 bufFmt, ctx->getBufferFormat());
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001083 jniThrowException(env, "java/lang/UnsupportedOperationException",
1084 msg.string());
1085 return -1;
1086 }
Zhijun He212e78d2013-06-07 11:36:23 -07001087 }
1088 // Set SurfaceImage instance member variables
1089 Image_setBuffer(env, image, buffer);
Jeff Brownef961212013-08-05 20:39:29 -07001090 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
1091 static_cast<jlong>(buffer->timestamp));
Zhijun He212e78d2013-06-07 11:36:23 -07001092
Igor Murashkine3351f12013-09-13 13:08:04 -07001093 return ACQUIRE_SUCCESS;
Zhijun He212e78d2013-06-07 11:36:23 -07001094}
1095
Zhijun Hece9d6f92015-03-29 16:33:59 -07001096static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
1097 ALOGV("%s:", __FUNCTION__);
1098 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
1099 if (ctx == NULL) {
Zhijun Hedc6bb242015-12-03 15:34:34 -08001100 jniThrowException(env, "java/lang/IllegalStateException",
1101 "ImageReader is not initialized or was already closed");
Zhijun Hece9d6f92015-03-29 16:33:59 -07001102 return -1;
1103 }
1104
1105 if (ctx->isOpaque()) {
1106 return ImageReader_opaqueImageSetup(env, ctx, image);
1107 } else {
1108 return ImageReader_lockedImageSetup(env, ctx, image);
1109 }
1110}
1111
1112static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) {
Zhijun Hef6a09e52015-02-24 18:12:23 -08001113 ALOGV("%s:", __FUNCTION__);
1114 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
1115 if (ctx == NULL) {
1116 jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed");
Zhijun Hece9d6f92015-03-29 16:33:59 -07001117 return -1;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001118 }
1119
Zhijun Hece9d6f92015-03-29 16:33:59 -07001120 status_t res = OK;
1121 if (!ctx->isOpaque()) {
1122 // TODO: Non-Opaque format detach is not implemented yet.
1123 jniThrowRuntimeException(env,
1124 "nativeDetachImage is not implemented yet for non-opaque format !!!");
1125 return -1;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001126 }
1127
Zhijun Hece9d6f92015-03-29 16:33:59 -07001128 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
1129 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
1130 if (!opaqueBuffer) {
1131 ALOGE(
1132 "Opaque Image already released and can not be detached from ImageReader!!!");
1133 jniThrowException(env, "java/lang/IllegalStateException",
1134 "Opaque Image detach from ImageReader failed: buffer was already released");
1135 return -1;
1136 }
1137
1138 res = opaqueConsumer->detachBuffer(opaqueBuffer->mSlot);
1139 if (res != OK) {
1140 ALOGE("Opaque Image detach failed: %s (%d)!!!", strerror(-res), res);
1141 jniThrowRuntimeException(env,
1142 "nativeDetachImage failed for opaque image!!!");
1143 return res;
1144 }
1145 return OK;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001146}
1147
Zhijun He212e78d2013-06-07 11:36:23 -07001148static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
1149{
1150 ALOGV("%s: ", __FUNCTION__);
1151
Dan Stoza5b3c7c12014-03-12 16:44:45 -07001152 IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
1153 if (gbp == NULL) {
Zhijun He212e78d2013-06-07 11:36:23 -07001154 jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
1155 return NULL;
1156 }
1157
1158 // Wrap the IGBP in a Java-language Surface.
Dan Stoza5b3c7c12014-03-12 16:44:45 -07001159 return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
Zhijun He212e78d2013-06-07 11:36:23 -07001160}
1161
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001162static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -07001163{
1164 int rowStride, pixelStride;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001165 PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001166 int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat(
1167 publicReaderFormat);
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001168
Zhijun He212e78d2013-06-07 11:36:23 -07001169 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001170 if (isFormatOpaque(halReaderFormat)) {
1171 jniThrowException(env, "java/lang/IllegalStateException",
1172 "Opaque images from Opaque ImageReader do not have any planes");
1173 return NULL;
1174 }
Zhijun He212e78d2013-06-07 11:36:23 -07001175
1176 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1177
1178 ALOG_ASSERT(buffer != NULL);
1179 if (buffer == NULL) {
1180 jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
1181 }
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001182
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001183 rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat);
1184 pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat);
Zhijun He212e78d2013-06-07 11:36:23 -07001185
Jeff Brownef961212013-08-05 20:39:29 -07001186 jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
1187 gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
Zhijun He212e78d2013-06-07 11:36:23 -07001188
1189 return surfPlaneObj;
1190}
1191
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001192static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -07001193{
1194 uint8_t *base = NULL;
1195 uint32_t size = 0;
1196 jobject byteBuffer;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001197 PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001198 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1199 readerPublicFormat);
Zhijun He212e78d2013-06-07 11:36:23 -07001200
1201 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
1202
Zhijun Hece9d6f92015-03-29 16:33:59 -07001203 if (isFormatOpaque(readerHalFormat)) {
1204 jniThrowException(env, "java/lang/IllegalStateException",
1205 "Opaque images from Opaque ImageReader do not have any plane");
1206 return NULL;
1207 }
1208
Zhijun He212e78d2013-06-07 11:36:23 -07001209 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1210
1211 if (buffer == NULL) {
1212 jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
1213 }
1214
1215 // Create byteBuffer from native buffer
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001216 Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat);
Igor Murashkin5096def2014-06-24 10:49:11 -07001217
1218 if (size > static_cast<uint32_t>(INT32_MAX)) {
1219 // Byte buffer have 'int capacity', so check the range
1220 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
Ruben Brunk31798f32014-09-25 19:56:54 -07001221 "Size too large for bytebuffer capacity %" PRIu32, size);
Igor Murashkin5096def2014-06-24 10:49:11 -07001222 return NULL;
1223 }
1224
Zhijun He212e78d2013-06-07 11:36:23 -07001225 byteBuffer = env->NewDirectByteBuffer(base, size);
1226 // TODO: throw dvm exOutOfMemoryError?
1227 if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
1228 jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
1229 }
1230
1231 return byteBuffer;
1232}
1233
Zhijun Hece9d6f92015-03-29 16:33:59 -07001234static jint Image_getWidth(JNIEnv* env, jobject thiz, jint format)
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001235{
Zhijun Hece9d6f92015-03-29 16:33:59 -07001236 if (isFormatOpaque(format)) {
1237 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
1238 return Image_getOpaqueBufferWidth(opaqueBuffer);
1239 } else {
1240 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1241 return Image_getBufferWidth(buffer);
1242 }
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001243}
1244
Zhijun Hece9d6f92015-03-29 16:33:59 -07001245static jint Image_getHeight(JNIEnv* env, jobject thiz, jint format)
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001246{
Zhijun Hece9d6f92015-03-29 16:33:59 -07001247 if (isFormatOpaque(format)) {
1248 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
1249 return Image_getOpaqueBufferHeight(opaqueBuffer);
1250 } else {
1251 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1252 return Image_getBufferHeight(buffer);
1253 }
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001254}
1255
Zhijun He7c3997d2015-05-06 10:08:37 -07001256static jint Image_getFormat(JNIEnv* env, jobject thiz, jint readerFormat)
1257{
1258 if (isFormatOpaque(readerFormat)) {
1259 // Assuming opaque reader produce opaque images.
1260 return static_cast<jint>(PublicFormat::PRIVATE);
1261 } else {
1262 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
Chien-Yu Chen0782aab2015-06-11 16:48:13 -07001263 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1264 static_cast<PublicFormat>(readerFormat));
1265 int32_t fmt = applyFormatOverrides(buffer->flexFormat, readerHalFormat);
Zhijun He7c3997d2015-05-06 10:08:37 -07001266 PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
Chien-Yu Chen0782aab2015-06-11 16:48:13 -07001267 fmt, buffer->dataSpace);
Zhijun He7c3997d2015-05-06 10:08:37 -07001268 return static_cast<jint>(publicFmt);
1269 }
1270}
1271
Zhijun He212e78d2013-06-07 11:36:23 -07001272} // extern "C"
1273
1274// ----------------------------------------------------------------------------
1275
Daniel Micay76f6a862015-09-19 17:31:01 -04001276static const JNINativeMethod gImageReaderMethods[] = {
Zhijun He212e78d2013-06-07 11:36:23 -07001277 {"nativeClassInit", "()V", (void*)ImageReader_classInit },
1278 {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
1279 {"nativeClose", "()V", (void*)ImageReader_close },
1280 {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001281 {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
Zhijun He212e78d2013-06-07 11:36:23 -07001282 {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
Zhijun Hece9d6f92015-03-29 16:33:59 -07001283 {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage },
Zhijun He212e78d2013-06-07 11:36:23 -07001284};
1285
Daniel Micay76f6a862015-09-19 17:31:01 -04001286static const JNINativeMethod gImageMethods[] = {
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001287 {"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
1288 {"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001289 (void*)Image_createSurfacePlane },
Zhijun He7c3997d2015-05-06 10:08:37 -07001290 {"nativeGetWidth", "(I)I", (void*)Image_getWidth },
1291 {"nativeGetHeight", "(I)I", (void*)Image_getHeight },
1292 {"nativeGetFormat", "(I)I", (void*)Image_getFormat },
Zhijun He212e78d2013-06-07 11:36:23 -07001293};
1294
1295int register_android_media_ImageReader(JNIEnv *env) {
1296
1297 int ret1 = AndroidRuntime::registerNativeMethods(env,
1298 "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
1299
1300 int ret2 = AndroidRuntime::registerNativeMethods(env,
1301 "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
1302
1303 return (ret1 || ret2);
1304}