blob: 9e90a19f00cc6dcec14f5e435bdfd0c4ca9ae232 [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);
Yin-Chia Yehb99a7f12016-01-22 18:02:58 -0800577 pixelStride = 1;
Zhijun He212e78d2013-06-07 11:36:23 -0700578 break;
579 case HAL_PIXEL_FORMAT_YV12:
580 pixelStride = 1;
581 break;
582 case HAL_PIXEL_FORMAT_BLOB:
Zhijun Hed1988a92014-07-01 04:15:09 -0700583 case HAL_PIXEL_FORMAT_RAW10:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700584 case HAL_PIXEL_FORMAT_RAW12:
585 // Blob is used for JPEG data, RAW10 and RAW12 is used for 10-bit and 12-bit raw data,
586 // those are single plane data with pixel stride 0 since they don't really have a
587 // well defined pixel stride
Zhijun He212e78d2013-06-07 11:36:23 -0700588 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
589 pixelStride = 0;
590 break;
591 case HAL_PIXEL_FORMAT_Y16:
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800592 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He708e3592013-08-05 14:56:11 -0700593 case HAL_PIXEL_FORMAT_RGB_565:
Zhijun He212e78d2013-06-07 11:36:23 -0700594 // Single plane 16bpp data.
595 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
596 pixelStride = 2;
597 break;
Zhijun He708e3592013-08-05 14:56:11 -0700598 case HAL_PIXEL_FORMAT_RGBA_8888:
599 case HAL_PIXEL_FORMAT_RGBX_8888:
600 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
601 pixelStride = 4;
602 break;
603 case HAL_PIXEL_FORMAT_RGB_888:
604 // Single plane, 24bpp.
605 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
606 pixelStride = 3;
607 break;
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800608 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
609 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
610 pixelStride = 0; // RAW OPAQUE doesn't have pixel stride
611 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700612 default:
613 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
614 "Pixel format: 0x%x is unsupported", fmt);
615 break;
616 }
617
618 return pixelStride;
619}
620
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700621static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800622 int32_t halReaderFormat)
Zhijun He212e78d2013-06-07 11:36:23 -0700623{
624 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
625 ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
626
627 int rowStride = 0;
628 ALOG_ASSERT(buffer != NULL, "buffer is NULL");
629
Lajos Molnar4fb44262015-01-22 19:03:31 -0800630 int32_t fmt = buffer->flexFormat;
Zhijun He212e78d2013-06-07 11:36:23 -0700631
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800632 fmt = applyFormatOverrides(fmt, halReaderFormat);
Ruben Brunk0fd198a2014-09-23 23:35:43 -0700633
Zhijun He212e78d2013-06-07 11:36:23 -0700634 switch (fmt) {
635 case HAL_PIXEL_FORMAT_YCbCr_420_888:
636 rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
637 break;
638 case HAL_PIXEL_FORMAT_YCrCb_420_SP:
639 rowStride = buffer->width;
640 break;
641 case HAL_PIXEL_FORMAT_YV12:
642 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
643 "Stride is not 16 pixel aligned %d", buffer->stride);
644 rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
645 break;
646 case HAL_PIXEL_FORMAT_BLOB:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700647 // Blob is used for JPEG data. It is single plane and has 0 row stride and
648 // 0 pixel stride
Zhijun He212e78d2013-06-07 11:36:23 -0700649 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
650 rowStride = 0;
651 break;
Zhijun He4c4064f2014-07-25 09:06:11 -0700652 case HAL_PIXEL_FORMAT_RAW10:
Yin-Chia Yeh11d444f2015-03-20 16:47:02 -0700653 case HAL_PIXEL_FORMAT_RAW12:
654 // RAW10 and RAW12 are used for 10-bit and 12-bit raw data, they are single plane
Zhijun He4c4064f2014-07-25 09:06:11 -0700655 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
656 rowStride = buffer->stride;
657 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700658 case HAL_PIXEL_FORMAT_Y8:
659 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
660 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
661 "Stride is not 16 pixel aligned %d", buffer->stride);
662 rowStride = buffer->stride;
663 break;
664 case HAL_PIXEL_FORMAT_Y16:
Eino-Ville Talvala64cc1d02015-02-19 16:28:08 -0800665 case HAL_PIXEL_FORMAT_RAW16:
Zhijun He212e78d2013-06-07 11:36:23 -0700666 // In native side, strides are specified in pixels, not in bytes.
667 // Single plane 16bpp bayer data. even width/height,
668 // row stride multiple of 16 pixels (32 bytes)
669 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
670 LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
671 "Stride is not 16 pixel aligned %d", buffer->stride);
672 rowStride = buffer->stride * 2;
673 break;
Zhijun He708e3592013-08-05 14:56:11 -0700674 case HAL_PIXEL_FORMAT_RGB_565:
675 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
676 rowStride = buffer->stride * 2;
677 break;
678 case HAL_PIXEL_FORMAT_RGBA_8888:
679 case HAL_PIXEL_FORMAT_RGBX_8888:
680 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
681 rowStride = buffer->stride * 4;
682 break;
683 case HAL_PIXEL_FORMAT_RGB_888:
684 // Single plane, 24bpp.
685 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
686 rowStride = buffer->stride * 3;
687 break;
Yin-Chia Yeh44581ff2015-12-07 17:15:24 -0800688 case HAL_PIXEL_FORMAT_RAW_OPAQUE:
689 ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
690 rowStride = 0; // RAW OPAQUE doesn't have row stride
691 break;
Zhijun He212e78d2013-06-07 11:36:23 -0700692 default:
693 ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
694 jniThrowException(env, "java/lang/UnsupportedOperationException",
695 "unsupported buffer format");
696 break;
697 }
698
699 return rowStride;
700}
701
Ruben Brunkf4a637d2014-11-20 18:01:36 -0800702static int Image_getBufferWidth(CpuConsumer::LockedBuffer* buffer) {
703 if (buffer == NULL) return -1;
704
705 if (!buffer->crop.isEmpty()) {
706 return buffer->crop.getWidth();
707 }
708 return buffer->width;
709}
710
711static int Image_getBufferHeight(CpuConsumer::LockedBuffer* buffer) {
712 if (buffer == NULL) return -1;
713
714 if (!buffer->crop.isEmpty()) {
715 return buffer->crop.getHeight();
716 }
717 return buffer->height;
718}
719
Zhijun Hece9d6f92015-03-29 16:33:59 -0700720// --------------------------Methods for opaque Image and ImageReader----------
721
722static BufferItemConsumer* ImageReader_getOpaqueConsumer(JNIEnv* env, jobject thiz)
723{
724 ALOGV("%s:", __FUNCTION__);
725 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
726 if (ctx == NULL) {
727 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
728 return NULL;
729 }
730
731 if (!ctx->isOpaque()) {
732 jniThrowException(env, "java/lang/IllegalStateException",
733 "Non-opaque ImageReader doesn't support this method");
734 }
735
736 return ctx->getOpaqueConsumer();
737}
738
739static BufferItem* Image_getOpaqueBuffer(JNIEnv* env, jobject image)
740{
741 return reinterpret_cast<BufferItem*>(
742 env->GetLongField(image, gSurfaceImageClassInfo.mNativeBuffer));
743}
744
745static int Image_getOpaqueBufferWidth(BufferItem* buffer) {
746 if (buffer == NULL) return -1;
747
748 if (!buffer->mCrop.isEmpty()) {
749 return buffer->mCrop.getWidth();
750 }
751 return buffer->mGraphicBuffer->getWidth();
752}
753
754static int Image_getOpaqueBufferHeight(BufferItem* buffer) {
755 if (buffer == NULL) return -1;
756
757 if (!buffer->mCrop.isEmpty()) {
758 return buffer->mCrop.getHeight();
759 }
760
761 return buffer->mGraphicBuffer->getHeight();
762}
763
764
765
Zhijun He212e78d2013-06-07 11:36:23 -0700766// ----------------------------------------------------------------------------
767
768static void ImageReader_classInit(JNIEnv* env, jclass clazz)
769{
770 ALOGV("%s:", __FUNCTION__);
771
772 jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
773 LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
774 "can't find android/graphics/ImageReader$SurfaceImage");
Zhijun Hece9d6f92015-03-29 16:33:59 -0700775 gSurfaceImageClassInfo.mNativeBuffer = env->GetFieldID(
Jeff Brownef961212013-08-05 20:39:29 -0700776 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
Zhijun Hece9d6f92015-03-29 16:33:59 -0700777 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeBuffer == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700778 "can't find android/graphics/ImageReader.%s",
779 ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
780
Jeff Brownef961212013-08-05 20:39:29 -0700781 gSurfaceImageClassInfo.mTimestamp = env->GetFieldID(
782 imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
783 LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700784 "can't find android/graphics/ImageReader.%s",
785 ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
786
Jeff Brownef961212013-08-05 20:39:29 -0700787 gImageReaderClassInfo.mNativeContext = env->GetFieldID(
788 clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
789 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700790 "can't find android/graphics/ImageReader.%s",
791 ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
792
Jeff Brownef961212013-08-05 20:39:29 -0700793 gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(
794 clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
795 LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL,
Zhijun He212e78d2013-06-07 11:36:23 -0700796 "can't find android/graphics/ImageReader.postEventFromNative");
797
798 jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
799 LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
800 // FindClass only gives a local reference of jclass object.
Jeff Brownef961212013-08-05 20:39:29 -0700801 gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
802 gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>",
803 "(Landroid/media/ImageReader$SurfaceImage;III)V");
804 LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
805 "Can not find SurfacePlane constructor");
Zhijun He212e78d2013-06-07 11:36:23 -0700806}
807
808static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
809 jint width, jint height, jint format, jint maxImages)
810{
811 status_t res;
812 int nativeFormat;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800813 android_dataspace nativeDataspace;
Zhijun He212e78d2013-06-07 11:36:23 -0700814
815 ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
816 __FUNCTION__, width, height, format, maxImages);
817
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800818 PublicFormat publicFormat = static_cast<PublicFormat>(format);
819 nativeFormat = android_view_Surface_mapPublicFormatToHalFormat(
820 publicFormat);
821 nativeDataspace = android_view_Surface_mapPublicFormatToHalDataspace(
822 publicFormat);
Zhijun He212e78d2013-06-07 11:36:23 -0700823
Zhijun He212e78d2013-06-07 11:36:23 -0700824 jclass clazz = env->GetObjectClass(thiz);
825 if (clazz == NULL) {
826 jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
827 return;
828 }
829 sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
Zhijun Hece9d6f92015-03-29 16:33:59 -0700830
831 sp<IGraphicBufferProducer> gbProducer;
832 sp<IGraphicBufferConsumer> gbConsumer;
833 BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
834 sp<ConsumerBase> consumer;
835 sp<CpuConsumer> cpuConsumer;
836 sp<BufferItemConsumer> opaqueConsumer;
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700837 String8 consumerName = String8::format("ImageReader-%dx%df%xm%d-%d-%d",
838 width, height, format, maxImages, getpid(),
839 createProcessUniqueId());
Zhijun Hece9d6f92015-03-29 16:33:59 -0700840 if (isFormatOpaque(nativeFormat)) {
841 // Use the SW_READ_NEVER usage to tell producer that this format is not for preview or video
842 // encoding. The only possibility will be ZSL output.
843 opaqueConsumer =
844 new BufferItemConsumer(gbConsumer, GRALLOC_USAGE_SW_READ_NEVER, maxImages,
845 /*controlledByApp*/true);
846 if (opaqueConsumer == NULL) {
847 jniThrowRuntimeException(env, "Failed to allocate native opaque consumer");
848 return;
849 }
850 ctx->setOpaqueConsumer(opaqueConsumer);
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700851 opaqueConsumer->setName(consumerName);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700852 consumer = opaqueConsumer;
853 } else {
854 cpuConsumer = new CpuConsumer(gbConsumer, maxImages, /*controlledByApp*/true);
855 // TODO: throw dvm exOutOfMemoryError?
856 if (cpuConsumer == NULL) {
857 jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
858 return;
859 }
860 ctx->setCpuConsumer(cpuConsumer);
Eino-Ville Talvalaef9db7d2015-06-09 14:15:15 -0700861 cpuConsumer->setName(consumerName);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700862 consumer = cpuConsumer;
863 }
864
Dan Stoza5b3c7c12014-03-12 16:44:45 -0700865 ctx->setProducer(gbProducer);
Zhijun He212e78d2013-06-07 11:36:23 -0700866 consumer->setFrameAvailableListener(ctx);
867 ImageReader_setNativeContext(env, thiz, ctx);
868 ctx->setBufferFormat(nativeFormat);
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800869 ctx->setBufferDataspace(nativeDataspace);
Zhijun He212e78d2013-06-07 11:36:23 -0700870 ctx->setBufferWidth(width);
871 ctx->setBufferHeight(height);
872
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -0800873 // Set the width/height/format/dataspace to the CpuConsumer
Zhijun Hece9d6f92015-03-29 16:33:59 -0700874 // TODO: below code can be simplified once b/19977701 is fixed.
875 if (isFormatOpaque(nativeFormat)) {
876 res = opaqueConsumer->setDefaultBufferSize(width, height);
877 if (res != OK) {
878 jniThrowException(env, "java/lang/IllegalStateException",
879 "Failed to set opaque consumer buffer size");
880 return;
881 }
882 res = opaqueConsumer->setDefaultBufferFormat(nativeFormat);
883 if (res != OK) {
884 jniThrowException(env, "java/lang/IllegalStateException",
885 "Failed to set opaque consumer buffer format");
886 }
887 res = opaqueConsumer->setDefaultBufferDataSpace(nativeDataspace);
888 if (res != OK) {
889 jniThrowException(env, "java/lang/IllegalStateException",
890 "Failed to set opaque consumer buffer dataSpace");
891 }
892 } else {
893 res = cpuConsumer->setDefaultBufferSize(width, height);
894 if (res != OK) {
895 jniThrowException(env, "java/lang/IllegalStateException",
896 "Failed to set CpuConsumer buffer size");
897 return;
898 }
899 res = cpuConsumer->setDefaultBufferFormat(nativeFormat);
900 if (res != OK) {
901 jniThrowException(env, "java/lang/IllegalStateException",
902 "Failed to set CpuConsumer buffer format");
903 }
904 res = cpuConsumer->setDefaultBufferDataSpace(nativeDataspace);
905 if (res != OK) {
906 jniThrowException(env, "java/lang/IllegalStateException",
907 "Failed to set CpuConsumer buffer dataSpace");
908 }
Zhijun He212e78d2013-06-07 11:36:23 -0700909 }
Zhijun He212e78d2013-06-07 11:36:23 -0700910}
911
912static void ImageReader_close(JNIEnv* env, jobject thiz)
913{
914 ALOGV("%s:", __FUNCTION__);
915
916 JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
917 if (ctx == NULL) {
918 // ImageReader is already closed.
919 return;
920 }
921
Zhijun Hece9d6f92015-03-29 16:33:59 -0700922 ConsumerBase* consumer = NULL;
923 if (ctx->isOpaque()) {
924 consumer = ImageReader_getOpaqueConsumer(env, thiz);
925 } else {
926 consumer = ImageReader_getCpuConsumer(env, thiz);
927 }
928
Zhijun He212e78d2013-06-07 11:36:23 -0700929 if (consumer != NULL) {
930 consumer->abandon();
931 consumer->setFrameAvailableListener(NULL);
932 }
933 ImageReader_setNativeContext(env, thiz, NULL);
934}
935
936static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
937{
938 ALOGV("%s:", __FUNCTION__);
939 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
940 if (ctx == NULL) {
941 ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
942 return;
943 }
944
Zhijun Hece9d6f92015-03-29 16:33:59 -0700945 if (ctx->isOpaque()) {
946 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
947 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
948 opaqueConsumer->releaseBuffer(*opaqueBuffer); // Not using fence for now.
949 Image_setOpaqueBuffer(env, image, NULL);
950 ctx->returnOpaqueBuffer(opaqueBuffer);
951 ALOGV("%s: Opaque Image has been released", __FUNCTION__);
952 } else {
953 CpuConsumer* consumer = ctx->getCpuConsumer();
954 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
955 if (!buffer) {
Zhijun Hedc6bb242015-12-03 15:34:34 -0800956 // Release an already closed image is harmless.
Zhijun Hece9d6f92015-03-29 16:33:59 -0700957 return;
958 }
959 consumer->unlockBuffer(*buffer);
960 Image_setBuffer(env, image, NULL);
961 ctx->returnLockedBuffer(buffer);
962 ALOGV("%s: Image (format: 0x%x) has been released", __FUNCTION__, ctx->getBufferFormat());
Zhijun He212e78d2013-06-07 11:36:23 -0700963 }
Zhijun He212e78d2013-06-07 11:36:23 -0700964}
965
Zhijun Hece9d6f92015-03-29 16:33:59 -0700966static jint ImageReader_opaqueImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
Zhijun He212e78d2013-06-07 11:36:23 -0700967 ALOGV("%s:", __FUNCTION__);
Zhijun Hece9d6f92015-03-29 16:33:59 -0700968 if (ctx == NULL || !ctx->isOpaque()) {
Zhijun He212e78d2013-06-07 11:36:23 -0700969 jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
Igor Murashkine3351f12013-09-13 13:08:04 -0700970 return -1;
Zhijun He212e78d2013-06-07 11:36:23 -0700971 }
972
Zhijun Hece9d6f92015-03-29 16:33:59 -0700973 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
974 BufferItem* buffer = ctx->getOpaqueBuffer();
975 if (buffer == NULL) {
976 ALOGW("Unable to acquire a buffer item, very likely client tried to acquire more than"
977 " maxImages buffers");
978 return ACQUIRE_MAX_IMAGES;
979 }
980
981 status_t res = opaqueConsumer->acquireBuffer(buffer, 0);
982 if (res != OK) {
983 ctx->returnOpaqueBuffer(buffer);
984 if (res == INVALID_OPERATION) {
985 // Max number of images were already acquired.
986 ALOGE("%s: Max number of buffers allowed are already acquired : %s (%d)",
987 __FUNCTION__, strerror(-res), res);
988 return ACQUIRE_MAX_IMAGES;
989 } else {
990 ALOGE("%s: Acquire image failed with error: %s (%d)",
991 __FUNCTION__, strerror(-res), res);
992 return ACQUIRE_NO_BUFFERS;
993 }
994 }
995
996 // Set SurfaceImage instance member variables
997 Image_setOpaqueBuffer(env, image, buffer);
998 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
999 static_cast<jlong>(buffer->mTimestamp));
1000
1001 return ACQUIRE_SUCCESS;
1002}
1003
1004static jint ImageReader_lockedImageSetup(JNIEnv* env, JNIImageReaderContext* ctx, jobject image) {
Zhijun He212e78d2013-06-07 11:36:23 -07001005 CpuConsumer* consumer = ctx->getCpuConsumer();
1006 CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
1007 if (buffer == NULL) {
Igor Murashkind901c032013-08-27 15:19:55 -07001008 ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
1009 " maxImages buffers");
Igor Murashkine3351f12013-09-13 13:08:04 -07001010 return ACQUIRE_MAX_IMAGES;
Zhijun He212e78d2013-06-07 11:36:23 -07001011 }
1012 status_t res = consumer->lockNextBuffer(buffer);
1013 if (res != NO_ERROR) {
lina.x.pi33477892014-01-27 10:31:44 +08001014 ctx->returnLockedBuffer(buffer);
Jeff Brownf724c272013-08-07 14:17:04 -07001015 if (res != BAD_VALUE /*no buffers*/) {
Igor Murashkindd064322013-08-14 19:05:17 -07001016 if (res == NOT_ENOUGH_DATA) {
Igor Murashkine3351f12013-09-13 13:08:04 -07001017 return ACQUIRE_MAX_IMAGES;
Igor Murashkindd064322013-08-14 19:05:17 -07001018 } else {
1019 ALOGE("%s Fail to lockNextBuffer with error: %d ",
1020 __FUNCTION__, res);
Igor Murashkine3351f12013-09-13 13:08:04 -07001021 jniThrowExceptionFmt(env, "java/lang/AssertionError",
Igor Murashkindd064322013-08-14 19:05:17 -07001022 "Unknown error (%d) when we tried to lock buffer.",
1023 res);
1024 }
Jeff Brownf724c272013-08-07 14:17:04 -07001025 }
Igor Murashkine3351f12013-09-13 13:08:04 -07001026 return ACQUIRE_NO_BUFFERS;
Zhijun He212e78d2013-06-07 11:36:23 -07001027 }
1028
Lajos Molnar4fb44262015-01-22 19:03:31 -08001029 if (buffer->flexFormat == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
Zhijun He4eda9f52013-09-18 08:00:02 -07001030 jniThrowException(env, "java/lang/UnsupportedOperationException",
1031 "NV21 format is not supported by ImageReader");
1032 return -1;
1033 }
1034
Zhijun He212e78d2013-06-07 11:36:23 -07001035 // Check if the left-top corner of the crop rect is origin, we currently assume this point is
1036 // zero, will revist this once this assumption turns out problematic.
1037 Point lt = buffer->crop.leftTop();
1038 if (lt.x != 0 || lt.y != 0) {
Zhijun He4eda9f52013-09-18 08:00:02 -07001039 jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
1040 "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
Igor Murashkine3351f12013-09-13 13:08:04 -07001041 return -1;
Zhijun He212e78d2013-06-07 11:36:23 -07001042 }
1043
1044 // Check if the producer buffer configurations match what ImageReader configured.
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001045 int outputWidth = Image_getBufferWidth(buffer);
1046 int outputHeight = Image_getBufferHeight(buffer);
Zhijun He534046d2013-07-01 11:03:41 -07001047
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001048 int imgReaderFmt = ctx->getBufferFormat();
Zhijun He212e78d2013-06-07 11:36:23 -07001049 int imageReaderWidth = ctx->getBufferWidth();
1050 int imageReaderHeight = ctx->getBufferHeight();
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001051 if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) && (imgReaderFmt != HAL_PIXEL_FORMAT_BLOB) &&
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001052 (imageReaderWidth != outputWidth || imageReaderHeight != outputHeight)) {
1053 ALOGV("%s: Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
1054 __FUNCTION__, outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
Zhijun He212e78d2013-06-07 11:36:23 -07001055 }
1056
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001057 int bufFmt = buffer->format;
Lajos Molnar4fb44262015-01-22 19:03:31 -08001058 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888) {
1059 bufFmt = buffer->flexFormat;
1060 }
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001061 if (imgReaderFmt != bufFmt) {
Ruben Brunk91b9aab2014-06-20 00:24:56 -07001062 if (imgReaderFmt == HAL_PIXEL_FORMAT_YCbCr_420_888 && (bufFmt ==
1063 HAL_PIXEL_FORMAT_YCrCb_420_SP || bufFmt == HAL_PIXEL_FORMAT_YV12)) {
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001064 // Special casing for when producer switches to a format compatible with flexible YUV
1065 // (HAL_PIXEL_FORMAT_YCbCr_420_888).
Ruben Brunk91b9aab2014-06-20 00:24:56 -07001066 ctx->setBufferFormat(bufFmt);
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001067 ALOGD("%s: Overriding buffer format YUV_420_888 to %x.", __FUNCTION__, bufFmt);
1068 } else if (imgReaderFmt == HAL_PIXEL_FORMAT_BLOB && bufFmt == HAL_PIXEL_FORMAT_RGBA_8888) {
1069 // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW
1070 // write limitations for (b/17379185).
1071 ALOGD("%s: Receiving JPEG in HAL_PIXEL_FORMAT_RGBA_8888 buffer.", __FUNCTION__);
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001072 } else {
1073 // Return the buffer to the queue.
1074 consumer->unlockBuffer(*buffer);
1075 ctx->returnLockedBuffer(buffer);
Zhijun He212e78d2013-06-07 11:36:23 -07001076
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001077 // Throw exception
1078 ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
1079 buffer->format, ctx->getBufferFormat());
1080 String8 msg;
1081 msg.appendFormat("The producer output buffer format 0x%x doesn't "
1082 "match the ImageReader's configured buffer format 0x%x.",
Lajos Molnar4fb44262015-01-22 19:03:31 -08001083 bufFmt, ctx->getBufferFormat());
Ruben Brunkfeb50af2014-05-09 19:58:49 -07001084 jniThrowException(env, "java/lang/UnsupportedOperationException",
1085 msg.string());
1086 return -1;
1087 }
Zhijun He212e78d2013-06-07 11:36:23 -07001088 }
1089 // Set SurfaceImage instance member variables
1090 Image_setBuffer(env, image, buffer);
Jeff Brownef961212013-08-05 20:39:29 -07001091 env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
1092 static_cast<jlong>(buffer->timestamp));
Zhijun He212e78d2013-06-07 11:36:23 -07001093
Igor Murashkine3351f12013-09-13 13:08:04 -07001094 return ACQUIRE_SUCCESS;
Zhijun He212e78d2013-06-07 11:36:23 -07001095}
1096
Zhijun Hece9d6f92015-03-29 16:33:59 -07001097static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz, jobject image) {
1098 ALOGV("%s:", __FUNCTION__);
1099 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
1100 if (ctx == NULL) {
Zhijun Hedc6bb242015-12-03 15:34:34 -08001101 jniThrowException(env, "java/lang/IllegalStateException",
1102 "ImageReader is not initialized or was already closed");
Zhijun Hece9d6f92015-03-29 16:33:59 -07001103 return -1;
1104 }
1105
1106 if (ctx->isOpaque()) {
1107 return ImageReader_opaqueImageSetup(env, ctx, image);
1108 } else {
1109 return ImageReader_lockedImageSetup(env, ctx, image);
1110 }
1111}
1112
1113static jint ImageReader_detachImage(JNIEnv* env, jobject thiz, jobject image) {
Zhijun Hef6a09e52015-02-24 18:12:23 -08001114 ALOGV("%s:", __FUNCTION__);
1115 JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
1116 if (ctx == NULL) {
1117 jniThrowException(env, "java/lang/IllegalStateException", "ImageReader was already closed");
Zhijun Hece9d6f92015-03-29 16:33:59 -07001118 return -1;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001119 }
1120
Zhijun Hece9d6f92015-03-29 16:33:59 -07001121 status_t res = OK;
1122 if (!ctx->isOpaque()) {
1123 // TODO: Non-Opaque format detach is not implemented yet.
1124 jniThrowRuntimeException(env,
1125 "nativeDetachImage is not implemented yet for non-opaque format !!!");
1126 return -1;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001127 }
1128
Zhijun Hece9d6f92015-03-29 16:33:59 -07001129 BufferItemConsumer* opaqueConsumer = ctx->getOpaqueConsumer();
1130 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, image);
1131 if (!opaqueBuffer) {
1132 ALOGE(
1133 "Opaque Image already released and can not be detached from ImageReader!!!");
1134 jniThrowException(env, "java/lang/IllegalStateException",
1135 "Opaque Image detach from ImageReader failed: buffer was already released");
1136 return -1;
1137 }
1138
1139 res = opaqueConsumer->detachBuffer(opaqueBuffer->mSlot);
1140 if (res != OK) {
1141 ALOGE("Opaque Image detach failed: %s (%d)!!!", strerror(-res), res);
1142 jniThrowRuntimeException(env,
1143 "nativeDetachImage failed for opaque image!!!");
1144 return res;
1145 }
1146 return OK;
Zhijun Hef6a09e52015-02-24 18:12:23 -08001147}
1148
Zhijun He212e78d2013-06-07 11:36:23 -07001149static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
1150{
1151 ALOGV("%s: ", __FUNCTION__);
1152
Dan Stoza5b3c7c12014-03-12 16:44:45 -07001153 IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
1154 if (gbp == NULL) {
Zhijun He212e78d2013-06-07 11:36:23 -07001155 jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
1156 return NULL;
1157 }
1158
1159 // Wrap the IGBP in a Java-language Surface.
Dan Stoza5b3c7c12014-03-12 16:44:45 -07001160 return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
Zhijun He212e78d2013-06-07 11:36:23 -07001161}
1162
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001163static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx, int readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -07001164{
1165 int rowStride, pixelStride;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001166 PublicFormat publicReaderFormat = static_cast<PublicFormat>(readerFormat);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001167 int halReaderFormat = android_view_Surface_mapPublicFormatToHalFormat(
1168 publicReaderFormat);
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001169
Zhijun He212e78d2013-06-07 11:36:23 -07001170 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001171 if (isFormatOpaque(halReaderFormat)) {
1172 jniThrowException(env, "java/lang/IllegalStateException",
1173 "Opaque images from Opaque ImageReader do not have any planes");
1174 return NULL;
1175 }
Zhijun He212e78d2013-06-07 11:36:23 -07001176
1177 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1178
1179 ALOG_ASSERT(buffer != NULL);
1180 if (buffer == NULL) {
1181 jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
1182 }
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001183
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001184 rowStride = Image_imageGetRowStride(env, buffer, idx, halReaderFormat);
1185 pixelStride = Image_imageGetPixelStride(env, buffer, idx, halReaderFormat);
Zhijun He212e78d2013-06-07 11:36:23 -07001186
Jeff Brownef961212013-08-05 20:39:29 -07001187 jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
1188 gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
Zhijun He212e78d2013-06-07 11:36:23 -07001189
1190 return surfPlaneObj;
1191}
1192
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001193static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx, int readerFormat)
Zhijun He212e78d2013-06-07 11:36:23 -07001194{
1195 uint8_t *base = NULL;
1196 uint32_t size = 0;
1197 jobject byteBuffer;
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001198 PublicFormat readerPublicFormat = static_cast<PublicFormat>(readerFormat);
Zhijun Hece9d6f92015-03-29 16:33:59 -07001199 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1200 readerPublicFormat);
Zhijun He212e78d2013-06-07 11:36:23 -07001201
1202 ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
1203
Zhijun Hece9d6f92015-03-29 16:33:59 -07001204 if (isFormatOpaque(readerHalFormat)) {
1205 jniThrowException(env, "java/lang/IllegalStateException",
1206 "Opaque images from Opaque ImageReader do not have any plane");
1207 return NULL;
1208 }
1209
Zhijun He212e78d2013-06-07 11:36:23 -07001210 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1211
1212 if (buffer == NULL) {
1213 jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
1214 }
1215
1216 // Create byteBuffer from native buffer
Eino-Ville Talvala805f3c92015-02-26 10:57:55 -08001217 Image_getLockedBufferInfo(env, buffer, idx, &base, &size, readerHalFormat);
Igor Murashkin5096def2014-06-24 10:49:11 -07001218
1219 if (size > static_cast<uint32_t>(INT32_MAX)) {
1220 // Byte buffer have 'int capacity', so check the range
1221 jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
Ruben Brunk31798f32014-09-25 19:56:54 -07001222 "Size too large for bytebuffer capacity %" PRIu32, size);
Igor Murashkin5096def2014-06-24 10:49:11 -07001223 return NULL;
1224 }
1225
Zhijun He212e78d2013-06-07 11:36:23 -07001226 byteBuffer = env->NewDirectByteBuffer(base, size);
1227 // TODO: throw dvm exOutOfMemoryError?
1228 if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
1229 jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
1230 }
1231
1232 return byteBuffer;
1233}
1234
Zhijun Hece9d6f92015-03-29 16:33:59 -07001235static jint Image_getWidth(JNIEnv* env, jobject thiz, jint format)
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001236{
Zhijun Hece9d6f92015-03-29 16:33:59 -07001237 if (isFormatOpaque(format)) {
1238 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
1239 return Image_getOpaqueBufferWidth(opaqueBuffer);
1240 } else {
1241 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1242 return Image_getBufferWidth(buffer);
1243 }
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001244}
1245
Zhijun Hece9d6f92015-03-29 16:33:59 -07001246static jint Image_getHeight(JNIEnv* env, jobject thiz, jint format)
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001247{
Zhijun Hece9d6f92015-03-29 16:33:59 -07001248 if (isFormatOpaque(format)) {
1249 BufferItem* opaqueBuffer = Image_getOpaqueBuffer(env, thiz);
1250 return Image_getOpaqueBufferHeight(opaqueBuffer);
1251 } else {
1252 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
1253 return Image_getBufferHeight(buffer);
1254 }
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001255}
1256
Zhijun He7c3997d2015-05-06 10:08:37 -07001257static jint Image_getFormat(JNIEnv* env, jobject thiz, jint readerFormat)
1258{
1259 if (isFormatOpaque(readerFormat)) {
1260 // Assuming opaque reader produce opaque images.
1261 return static_cast<jint>(PublicFormat::PRIVATE);
1262 } else {
1263 CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
Chien-Yu Chen0782aab2015-06-11 16:48:13 -07001264 int readerHalFormat = android_view_Surface_mapPublicFormatToHalFormat(
1265 static_cast<PublicFormat>(readerFormat));
1266 int32_t fmt = applyFormatOverrides(buffer->flexFormat, readerHalFormat);
Zhijun He9cc3f882016-02-17 17:24:04 -08001267 // Override the image format to HAL_PIXEL_FORMAT_YCbCr_420_888 if the actual format is
1268 // NV21 or YV12. This could only happen when the Gralloc HAL version is v0.1 thus doesn't
1269 // support lockycbcr(), the CpuConsumer need to use the lock() method in the
1270 // lockNextBuffer() call. For Gralloc HAL v0.2 or newer, this format should already be
1271 // overridden to HAL_PIXEL_FORMAT_YCbCr_420_888 for the flexible YUV compatible formats.
1272 if (fmt == HAL_PIXEL_FORMAT_YCrCb_420_SP || fmt == HAL_PIXEL_FORMAT_YV12) {
1273 fmt = HAL_PIXEL_FORMAT_YCbCr_420_888;
1274 }
Zhijun He7c3997d2015-05-06 10:08:37 -07001275 PublicFormat publicFmt = android_view_Surface_mapHalFormatDataspaceToPublicFormat(
Chien-Yu Chen0782aab2015-06-11 16:48:13 -07001276 fmt, buffer->dataSpace);
Zhijun He7c3997d2015-05-06 10:08:37 -07001277 return static_cast<jint>(publicFmt);
1278 }
1279}
1280
Zhijun He212e78d2013-06-07 11:36:23 -07001281} // extern "C"
1282
1283// ----------------------------------------------------------------------------
1284
Daniel Micay76f6a862015-09-19 17:31:01 -04001285static const JNINativeMethod gImageReaderMethods[] = {
Zhijun He212e78d2013-06-07 11:36:23 -07001286 {"nativeClassInit", "()V", (void*)ImageReader_classInit },
1287 {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
1288 {"nativeClose", "()V", (void*)ImageReader_close },
1289 {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001290 {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
Zhijun He212e78d2013-06-07 11:36:23 -07001291 {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
Zhijun Hece9d6f92015-03-29 16:33:59 -07001292 {"nativeDetachImage", "(Landroid/media/Image;)I", (void*)ImageReader_detachImage },
Zhijun He212e78d2013-06-07 11:36:23 -07001293};
1294
Daniel Micay76f6a862015-09-19 17:31:01 -04001295static const JNINativeMethod gImageMethods[] = {
Ruben Brunk0fd198a2014-09-23 23:35:43 -07001296 {"nativeImageGetBuffer", "(II)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
1297 {"nativeCreatePlane", "(II)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
Ruben Brunkf4a637d2014-11-20 18:01:36 -08001298 (void*)Image_createSurfacePlane },
Zhijun He7c3997d2015-05-06 10:08:37 -07001299 {"nativeGetWidth", "(I)I", (void*)Image_getWidth },
1300 {"nativeGetHeight", "(I)I", (void*)Image_getHeight },
1301 {"nativeGetFormat", "(I)I", (void*)Image_getFormat },
Zhijun He212e78d2013-06-07 11:36:23 -07001302};
1303
1304int register_android_media_ImageReader(JNIEnv *env) {
1305
1306 int ret1 = AndroidRuntime::registerNativeMethods(env,
1307 "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
1308
1309 int ret2 = AndroidRuntime::registerNativeMethods(env,
1310 "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
1311
1312 return (ret1 || ret2);
1313}