android_media_ImageReader.cpp revision 212e78df9eb3bfff069de01aa7820cf4201c5f82
1212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He/* 2212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Copyright 2013 The Android Open Source Project 3212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * 4212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Licensed under the Apache License, Version 2.0 (the "License"); 5212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * you may not use this file except in compliance with the License. 6212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * You may obtain a copy of the License at 7212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * 8212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * http://www.apache.org/licenses/LICENSE-2.0 9212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * 10212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * Unless required by applicable law or agreed to in writing, software 11212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * distributed under the License is distributed on an "AS IS" BASIS, 12212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * See the License for the specific language governing permissions and 14212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He * limitations under the License. 15212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He */ 16212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 17212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He//#define LOG_NDEBUG 0 18212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define LOG_TAG "ImageReader_JNI" 19212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <utils/Log.h> 20212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <utils/misc.h> 21212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <utils/List.h> 22212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 23212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <cstdio> 24212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 25212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <gui/CpuConsumer.h> 26212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <gui/Surface.h> 27212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 28212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <android_runtime/AndroidRuntime.h> 29212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <android_runtime/android_view_Surface.h> 30212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 31212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <jni.h> 32212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#include <JNIHelp.h> 33212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 34212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 35212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 36212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ANDROID_MEDIA_IMAGEREADER_JNI_ID "mCpuConsumer" 37212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext" 38212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mLockedBuffer" 39212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp" 40212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 41212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ---------------------------------------------------------------------------- 42212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 43212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heusing namespace android; 44212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 45212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heenum { 46212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He IMAGE_READER_MAX_NUM_PLANES = 3, 47212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}; 48212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 49212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestruct fields_t { 50212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // For ImageReader class 51212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jfieldID imageReaderContext; 52212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jmethodID postEvent; 53212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // For SurfaceImage class 54212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jfieldID buffer; 55212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jfieldID timeStamp; 56212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}; 57212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 58212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestruct classInfo_t { 59212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jclass clazz; 60212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jmethodID ctor; 61212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}; 62212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 63212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic fields_t fields; 64212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic classInfo_t surfPlaneClassInfo; 65212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 66212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ---------------------------------------------------------------------------- 67212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 68212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heclass JNIImageReaderContext : public CpuConsumer::FrameAvailableListener 69212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 70212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hepublic: 71212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages); 72212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 73212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He virtual ~JNIImageReaderContext(); 74212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 75212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He virtual void onFrameAvailable(); 76212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 77212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer* getLockedBuffer(); 78212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 79212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer); 80212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 81212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer* getCpuConsumer() { return mConsumer.get(); } 82212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 83212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He void setCpuConsumer(sp<CpuConsumer> consumer) { mConsumer = consumer; } 84212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 85212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He void setBufferFormat(int format) { mFormat = format; } 86212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int getBufferFormat() { return mFormat; } 87212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 88212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He void setBufferWidth(int width) { mWidth = width; } 89212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int getBufferWidth() { return mWidth; } 90212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 91212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He void setBufferHeight(int height) { mHeight = height; } 92212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int getBufferHeight() { return mHeight; } 93212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 94212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heprivate: 95212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He static JNIEnv* getJNIEnv(bool* needsDetach); 96212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He static void detachJNI(); 97212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 98212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He List<CpuConsumer::LockedBuffer*> mBuffers; 99212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He sp<CpuConsumer> mConsumer; 100212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jobject mWeakThiz; 101212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jclass mClazz; 102212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int mFormat; 103212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int mWidth; 104212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int mHeight; 105212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}; 106212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 107212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeJNIImageReaderContext::JNIImageReaderContext(JNIEnv* env, 108212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jobject weakThiz, jclass clazz, int maxImages) : 109212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mWeakThiz(env->NewGlobalRef(weakThiz)), 110212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mClazz((jclass)env->NewGlobalRef(clazz)) { 111212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He for (int i = 0; i < maxImages; i++) { 112212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer; 113212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mBuffers.push_back(buffer); 114212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 115212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 116212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 117212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeJNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) { 118212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!"); 119212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *needsDetach = false; 120212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIEnv* env = AndroidRuntime::getJNIEnv(); 121212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (env == NULL) { 122212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 123212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JavaVM* vm = AndroidRuntime::getJavaVM(); 124212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int result = vm->AttachCurrentThread(&env, (void*) &args); 125212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (result != JNI_OK) { 126212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("thread attach failed: %#x", result); 127212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return NULL; 128212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 129212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *needsDetach = true; 130212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 131212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return env; 132212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 133212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 134212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hevoid JNIImageReaderContext::detachJNI() { 135212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JavaVM* vm = AndroidRuntime::getJavaVM(); 136212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int result = vm->DetachCurrentThread(); 137212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (result != JNI_OK) { 138212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("thread detach failed: %#x", result); 139212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 140212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 141212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 142212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeCpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() { 143212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (mBuffers.empty()) { 144212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return NULL; 145212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 146212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Return a LockedBuffer pointer and remove it from the list 147212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin(); 148212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer* buffer = *it; 149212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mBuffers.erase(it); 150212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return buffer; 151212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 152212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 153212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hevoid JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer * buffer) { 154212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mBuffers.push_back(buffer); 155212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 156212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 157212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun HeJNIImageReaderContext::~JNIImageReaderContext() { 158212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He bool needsDetach = false; 159212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIEnv* env = getJNIEnv(&needsDetach); 160212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (env != NULL) { 161212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He env->DeleteGlobalRef(mWeakThiz); 162212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He env->DeleteGlobalRef(mClazz); 163212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } else { 164212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGW("leaking JNI object references"); 165212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 166212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (needsDetach) { 167212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He detachJNI(); 168212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 169212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 170212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Delete LockedBuffers 171212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin(); 172212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He it != mBuffers.end(); it++) { 173212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He delete *it; 174212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 175212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mBuffers.clear(); 176212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He mConsumer.clear(); 177212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 178212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 179212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hevoid JNIImageReaderContext::onFrameAvailable() 180212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 181212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: frame available", __FUNCTION__); 182212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He bool needsDetach = false; 183212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIEnv* env = getJNIEnv(&needsDetach); 184212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (env != NULL) { 185212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He env->CallStaticVoidMethod(mClazz, fields.postEvent, mWeakThiz); 186212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } else { 187212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGW("onFrameAvailable event will not posted"); 188212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 189212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (needsDetach) { 190212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He detachJNI(); 191212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 192212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 193212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 194212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ---------------------------------------------------------------------------- 195212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 196212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heextern "C" { 197212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 198212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz) 199212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 200212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext *ctx; 201212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx = reinterpret_cast<JNIImageReaderContext *> 202212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (env->GetLongField(thiz, fields.imageReaderContext)); 203212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return ctx; 204212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 205212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 206212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz) 207212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 208212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s:", __FUNCTION__); 209212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 210212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ctx == NULL) { 211212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 212212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return NULL; 213212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 214212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return ctx->getCpuConsumer(); 215212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 216212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 217212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_setNativeContext(JNIEnv* env, 218212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jobject thiz, sp<JNIImageReaderContext> ctx) 219212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 220212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s:", __FUNCTION__); 221212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext* const p = ImageReader_getContext(env, thiz); 222212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ctx != 0) { 223212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->incStrong((void*)ImageReader_setNativeContext); 224212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 225212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (p) { 226212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He p->decStrong((void*)ImageReader_setNativeContext); 227212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 228212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He env->SetLongField(thiz, fields.imageReaderContext, reinterpret_cast<jlong>(ctx.get())); 229212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 230212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 231212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image) 232212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 233212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return reinterpret_cast<CpuConsumer::LockedBuffer*>(env->GetLongField(image, fields.buffer)); 234212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 235212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 236212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void Image_setBuffer(JNIEnv* env, jobject thiz, 237212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He const CpuConsumer::LockedBuffer* buffer) 238212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 239212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He env->SetLongField(thiz, fields.buffer, reinterpret_cast<jlong>(buffer)); 240212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 241212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 242212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// Some formats like JPEG defined with different values between android.graphics.ImageFormat and 243212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// graphics.h, need convert to the one defined in graphics.h here. 244212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic int Image_getPixelFormat(JNIEnv* env, int format) 245212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 246212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int jpegFormat, rawSensorFormat; 247212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jfieldID fid; 248212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 249212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: format = 0x%x", __FUNCTION__, format); 250212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 251212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat"); 252212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(imageFormatClazz != NULL); 253212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 254212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I"); 255212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jpegFormat = env->GetStaticIntField(imageFormatClazz, fid); 256212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He fid = env->GetStaticFieldID(imageFormatClazz, "RAW_SENSOR", "I"); 257212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rawSensorFormat = env->GetStaticIntField(imageFormatClazz, fid); 258212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 259212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Translate the JPEG to BLOB for camera purpose, an add more if more mismatch is found. 260212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (format == jpegFormat) { 261212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He format = HAL_PIXEL_FORMAT_BLOB; 262212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 263212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Same thing for RAW_SENSOR format 264212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (format == rawSensorFormat) { 265212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He format = HAL_PIXEL_FORMAT_RAW_SENSOR; 266212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 267212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 268212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return format; 269212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 270212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 271212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx, 272212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He uint8_t **base, uint32_t *size) 273212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 274212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 275212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(base != NULL, "base is NULL!!!"); 276212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(size != NULL, "size is NULL!!!"); 277212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); 278212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 279212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: buffer: 0x%p", __FUNCTION__, buffer); 280212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 281212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He uint32_t dataSize, ySize, cSize, cStride; 282212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He uint8_t *cb, *cr; 283212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He uint8_t *pData = NULL; 284212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 285212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = ySize = cSize = cStride = 0; 286212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int32_t fmt = buffer->format; 287212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He switch (fmt) { 288212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YCbCr_420_888: 289212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = 290212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (idx == 0) ? 291212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He buffer->data : 292212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (idx == 1) ? 293212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He buffer->dataCb : 294212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He buffer->dataCr; 295212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (idx == 0) { 296212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = buffer->stride * buffer->height; 297212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } else { 298212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = buffer->chromaStride * buffer->height / 2; 299212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 300212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 301212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // NV21 302212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YCrCb_420_SP: 303212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cr = buffer->data + (buffer->stride * buffer->height); 304212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cb = cr + 1; 305212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ySize = buffer->width * buffer->height; 306212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cSize = buffer->width * buffer->height / 2; 307212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 308212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = 309212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (idx == 0) ? 310212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He buffer->data : 311212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (idx == 1) ? 312212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cb: 313212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cr; 314212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 315212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = (idx == 0) ? ySize : cSize; 316212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 317212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YV12: 318212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Y and C stride need to be 16 pixel aligned. 319212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 320212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Stride is not 16 pixel aligned %d", buffer->stride); 321212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 322212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ySize = buffer->stride * buffer->height; 323212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cStride = ALIGN(buffer->stride / 2, 16); 324212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cr = buffer->data + ySize; 325212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cSize = cStride * buffer->height / 2; 326212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cb = cr + cSize; 327212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 328212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = 329212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (idx == 0) ? 330212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He buffer->data : 331212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (idx == 1) ? 332212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cb : 333212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He cr; 334212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = (idx == 0) ? ySize : cSize; 335212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 336212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_Y8: 337212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Single plane, 8bpp. 338212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 339212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 340212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = buffer->data; 341212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = buffer->stride * buffer->height; 342212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 343212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_Y16: 344212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Single plane, 16bpp, strides are specified in pixels, not in bytes 345212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 346212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 347212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = buffer->data; 348212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = buffer->stride * buffer->height * 2; 349212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 350212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_BLOB: 351212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Used for JPEG data, height must be 1, width == size, single plane. 352212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 353212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height); 354212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 355212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = buffer->data; 356212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = buffer->width; 357212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 358212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_RAW_SENSOR: 359212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Single plane 16bpp bayer data. 360212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 361212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pData = buffer->data; 362212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He dataSize = buffer->width * 2 * buffer->height; 363212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 364212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He default: 365212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 366212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Pixel format: 0x%x is unsupported", fmt); 367212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 368212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 369212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 370212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *base = pData; 371212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He *size = dataSize; 372212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 373212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 374212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx) 375212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 376212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 377212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx); 378212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 379212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int pixelStride = 0; 380212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(buffer != NULL, "buffer is NULL"); 381212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 382212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int32_t fmt = buffer->format; 383212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He switch (fmt) { 384212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YCbCr_420_888: 385212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride = (idx == 0) ? 1 : buffer->chromaStep; 386212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 387212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YCrCb_420_SP: 388212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride = (idx == 0) ? 1 : 2; 389212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 390212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_Y8: 391212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Single plane 8bpp data. 392212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 393212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride; 394212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 395212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YV12: 396212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride = 1; 397212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 398212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_BLOB: 399212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Used for JPEG data, single plane, row and pixel strides are 0 400212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 401212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride = 0; 402212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 403212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_Y16: 404212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_RAW_SENSOR: 405212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Single plane 16bpp data. 406212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 407212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride = 2; 408212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 409212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He default: 410212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 411212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Pixel format: 0x%x is unsupported", fmt); 412212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 413212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 414212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 415212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return pixelStride; 416212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 417212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 418212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx) 419212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 420212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 421212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0)); 422212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 423212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int rowStride = 0; 424212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(buffer != NULL, "buffer is NULL"); 425212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 426212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int32_t fmt = buffer->format; 427212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 428212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He switch (fmt) { 429212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YCbCr_420_888: 430212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride; 431212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 432212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YCrCb_420_SP: 433212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = buffer->width; 434212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 435212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_YV12: 436212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 437212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Stride is not 16 pixel aligned %d", buffer->stride); 438212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); 439212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 440212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_BLOB: 441212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Used for JPEG data, single plane, row and pixel strides are 0 442212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 443212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = 0; 444212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 445212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_Y8: 446212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 447212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 448212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Stride is not 16 pixel aligned %d", buffer->stride); 449212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = buffer->stride; 450212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 451212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_Y16: 452212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He case HAL_PIXEL_FORMAT_RAW_SENSOR: 453212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // In native side, strides are specified in pixels, not in bytes. 454212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Single plane 16bpp bayer data. even width/height, 455212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // row stride multiple of 16 pixels (32 bytes) 456212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 457212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 458212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Stride is not 16 pixel aligned %d", buffer->stride); 459212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = buffer->stride * 2; 460212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 461212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He default: 462212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt); 463212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/UnsupportedOperationException", 464212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "unsupported buffer format"); 465212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He break; 466212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 467212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 468212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return rowStride; 469212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 470212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 471212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ---------------------------------------------------------------------------- 472212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 473212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_classInit(JNIEnv* env, jclass clazz) 474212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 475212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s:", __FUNCTION__); 476212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 477212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage"); 478212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(imageClazz == NULL, 479212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "can't find android/graphics/ImageReader$SurfaceImage"); 480212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He fields.buffer = env->GetFieldID(imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J"); 481212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(fields.buffer == NULL, 482212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "can't find android/graphics/ImageReader.%s", 483212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID); 484212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 485212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He fields.timeStamp = env->GetFieldID(imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J"); 486212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(fields.timeStamp == NULL, 487212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "can't find android/graphics/ImageReader.%s", 488212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID); 489212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 490212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He fields.imageReaderContext = env->GetFieldID(clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J"); 491212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(fields.imageReaderContext == NULL, 492212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "can't find android/graphics/ImageReader.%s", 493212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID); 494212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 495212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He fields.postEvent = env->GetStaticMethodID(clazz, "postEventFromNative", 496212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "(Ljava/lang/Object;)V"); 497212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(fields.postEvent == NULL, 498212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "can't find android/graphics/ImageReader.postEventFromNative"); 499212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 500212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane"); 501212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class"); 502212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // FindClass only gives a local reference of jclass object. 503212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He surfPlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz); 504212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He surfPlaneClassInfo.ctor = env->GetMethodID(surfPlaneClassInfo.clazz, "<init>", 505212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "(Landroid/media/ImageReader$SurfaceImage;III)V"); 506212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He LOG_ALWAYS_FATAL_IF(surfPlaneClassInfo.ctor == NULL, "Can not find SurfacePlane constructor"); 507212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 508212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 509212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz, 510212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jint width, jint height, jint format, jint maxImages) 511212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 512212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He status_t res; 513212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int nativeFormat; 514212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 515212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d", 516212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He __FUNCTION__, width, height, format, maxImages); 517212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 518212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He nativeFormat = Image_getPixelFormat(env, format); 519212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 520212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He sp<CpuConsumer> consumer = new CpuConsumer(maxImages); 521212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // TODO: throw dvm exOutOfMemoryError? 522212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (consumer == NULL) { 523212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer"); 524212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 525212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 526212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 527212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jclass clazz = env->GetObjectClass(thiz); 528212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (clazz == NULL) { 529212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader"); 530212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 531212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 532212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages)); 533212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->setCpuConsumer(consumer); 534212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He consumer->setFrameAvailableListener(ctx); 535212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ImageReader_setNativeContext(env, thiz, ctx); 536212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->setBufferFormat(nativeFormat); 537212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->setBufferWidth(width); 538212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->setBufferHeight(height); 539212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 540212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Set the width/height/format to the CpuConsumer 541212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He res = consumer->setDefaultBufferSize(width, height); 542212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (res != OK) { 543212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/IllegalStateException", 544212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Failed to set CpuConsumer buffer size"); 545212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 546212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 547212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He res = consumer->setDefaultBufferFormat(nativeFormat); 548212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (res != OK) { 549212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/IllegalStateException", 550212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "Failed to set CpuConsumer buffer format"); 551212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 552212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 553212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 554212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_close(JNIEnv* env, jobject thiz) 555212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 556212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s:", __FUNCTION__); 557212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 558212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz); 559212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ctx == NULL) { 560212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // ImageReader is already closed. 561212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 562212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 563212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 564212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz); 565212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (consumer != NULL) { 566212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He consumer->abandon(); 567212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He consumer->setFrameAvailableListener(NULL); 568212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 569212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ImageReader_setNativeContext(env, thiz, NULL); 570212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 571212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 572212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image) 573212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 574212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s:", __FUNCTION__); 575212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 576212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ctx == NULL) { 577212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGW("ImageReader#close called before Image#close, consider calling Image#close first"); 578212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 579212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 580212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 581212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer* consumer = ctx->getCpuConsumer(); 582212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image); 583212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (!buffer) { 584212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGW("Image already released!!!"); 585212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return; 586212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 587212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He consumer->unlockBuffer(*buffer); 588212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He Image_setBuffer(env, image, NULL); 589212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->returnLockedBuffer(buffer); 590212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 591212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 592212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz, 593212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jobject image) 594212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 595212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s:", __FUNCTION__); 596212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz); 597212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ctx == NULL) { 598212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowRuntimeException(env, "ImageReaderContext is not initialized"); 599212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return false; 600212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 601212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 602212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer* consumer = ctx->getCpuConsumer(); 603212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer(); 604212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (buffer == NULL) { 605212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("Unable to acquire a lockedBuffer, very likely client tries to lock more than" 606212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "maxImages buffers"); 607212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return false; 608212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 609212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He status_t res = consumer->lockNextBuffer(buffer); 610212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (res != NO_ERROR) { 611212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("%s Fail to lockNextBuffer with error: 0x%x ", __FUNCTION__, res); 612212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return false; 613212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 614212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 615212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 616212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Check if the left-top corner of the crop rect is origin, we currently assume this point is 617212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // zero, will revist this once this assumption turns out problematic. 618212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He Point lt = buffer->crop.leftTop(); 619212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (lt.x != 0 || lt.y != 0) { 620212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("crop left: %d, top = %d", lt.x, lt.y); 621212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/UnsupportedOperationException", 622212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "crop left top corner need to at origin"); 623212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 624212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 625212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Check if the producer buffer configurations match what ImageReader configured. 626212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // We want to fail for the very first image because this case is too bad. 627212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int outputWidth = buffer->crop.getWidth() + 1; 628212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int outputHeight = buffer->crop.getHeight() + 1; 629212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int imageReaderWidth = ctx->getBufferWidth(); 630212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int imageReaderHeight = ctx->getBufferHeight(); 631212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if ((imageReaderWidth != outputWidth) || 632212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (imageReaderHeight != outputHeight)) { 633212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Spew warning for now, since MediaCodec decoder has a bug to setup the right crop 634212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // TODO: make it throw exception once the decoder bug is fixed. 635212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGW("Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d", 636212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He outputWidth, outputHeight, imageReaderWidth, imageReaderHeight); 637212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 638212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 639212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (ctx->getBufferFormat() != buffer->format) { 640212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Return the buffer to the queue. 641212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He consumer->unlockBuffer(*buffer); 642212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ctx->returnLockedBuffer(buffer); 643212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 644212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Throw exception 645212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x", 646212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He buffer->format, ctx->getBufferFormat()); 647212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/UnsupportedOperationException", 648212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "The producer output buffer configuration doesn't match the ImageReader" 649212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "configured"); 650212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return false; 651212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 652212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Set SurfaceImage instance member variables 653212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He Image_setBuffer(env, image, buffer); 654212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He env->SetLongField(image, fields.timeStamp, static_cast<jlong>(buffer->timestamp)); 655212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 656212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return true; 657212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 658212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 659212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jobject ImageReader_getSurface(JNIEnv* env, jobject thiz) 660212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 661212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: ", __FUNCTION__); 662212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 663212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz); 664212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (consumer == NULL) { 665212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowRuntimeException(env, "CpuConsumer is uninitialized"); 666212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return NULL; 667212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 668212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 669212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Wrap the IGBP in a Java-language Surface. 670212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return android_view_Surface_createFromIGraphicBufferProducer(env, 671212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He consumer->getProducerInterface()); 672212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 673212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 674212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx) 675212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 676212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int rowStride, pixelStride; 677212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 678212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 679212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 680212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 681212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOG_ASSERT(buffer != NULL); 682212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (buffer == NULL) { 683212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); 684212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 685212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He rowStride = Image_imageGetRowStride(env, buffer, idx); 686212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He pixelStride = Image_imageGetPixelStride(env, buffer, idx); 687212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 688212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jobject surfPlaneObj = env->NewObject(surfPlaneClassInfo.clazz, surfPlaneClassInfo.ctor, 689212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He thiz, idx, rowStride, pixelStride); 690212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 691212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return surfPlaneObj; 692212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 693212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 694212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx) 695212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He{ 696212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He uint8_t *base = NULL; 697212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He uint32_t size = 0; 698212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jobject byteBuffer; 699212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 700212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He ALOGV("%s: buffer index: %d", __FUNCTION__, idx); 701212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 702212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz); 703212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 704212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if (buffer == NULL) { 705212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/IllegalStateException", "Image was released"); 706212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 707212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 708212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // Create byteBuffer from native buffer 709212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He Image_getLockedBufferInfo(env, buffer, idx, &base, &size); 710212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He byteBuffer = env->NewDirectByteBuffer(base, size); 711212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He // TODO: throw dvm exOutOfMemoryError? 712212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) { 713212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer"); 714212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He } 715212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 716212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return byteBuffer; 717212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 718212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 719212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} // extern "C" 720212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 721212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He// ---------------------------------------------------------------------------- 722212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 723212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic JNINativeMethod gImageReaderMethods[] = { 724212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeClassInit", "()V", (void*)ImageReader_classInit }, 725212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init }, 726212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeClose", "()V", (void*)ImageReader_close }, 727212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease }, 728212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeImageSetup", "(Landroid/media/Image;)Z", (void*)ImageReader_imageSetup }, 729212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface }, 730212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}; 731212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 732212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Hestatic JNINativeMethod gImageMethods[] = { 733212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeImageGetBuffer", "(I)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer }, 734212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He {"nativeCreatePlane", "(I)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;", 735212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He (void*)Image_createSurfacePlane }, 736212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He}; 737212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 738212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun Heint register_android_media_ImageReader(JNIEnv *env) { 739212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 740212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int ret1 = AndroidRuntime::registerNativeMethods(env, 741212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods)); 742212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 743212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He int ret2 = AndroidRuntime::registerNativeMethods(env, 744212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods)); 745212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He 746212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He return (ret1 || ret2); 747212e78df9eb3bfff069de01aa7820cf4201c5f82Zhijun He} 748