android_media_ImageReader.cpp revision f724c277d3362dbc8099fcbf8674609a424cd2ee
13399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi/*
23399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * Copyright 2013 The Android Open Source Project
33399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi *
43399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * Licensed under the Apache License, Version 2.0 (the "License");
53399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * you may not use this file except in compliance with the License.
63399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * You may obtain a copy of the License at
73399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi *
83399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi *      http://www.apache.org/licenses/LICENSE-2.0
93399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi *
103399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * Unless required by applicable law or agreed to in writing, software
113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * distributed under the License is distributed on an "AS IS" BASIS,
123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * See the License for the specific language governing permissions and
143399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi * limitations under the License.
153399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi */
163399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
17bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam//#define LOG_NDEBUG 0
180c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi#define LOG_TAG "ImageReader_JNI"
193399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <utils/Log.h>
203399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <utils/misc.h>
213399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <utils/List.h>
223399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <utils/String8.h>
230c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi#include <cstdio>
253399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
261a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi#include <gui/CpuConsumer.h>
270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi#include <gui/Surface.h>
283399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <camera3.h>
293399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
30df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <android_runtime/AndroidRuntime.h>
31df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <android_runtime/android_view_Surface.h>
32df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian
33df712ea86e6350f7005a02ab0e1c60c28a343ed0Mathias Agopian#include <jni.h>
343399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#include <JNIHelp.h>
353399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
363399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
373399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
38f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong#define ANDROID_MEDIA_IMAGEREADER_JNI_ID           "mCpuConsumer"
390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID       "mNativeContext"
403399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID   "mLockedBuffer"
413399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID       "mTimestamp"
423399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
433399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi// ----------------------------------------------------------------------------
443399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
453399b7267185646c69b04352211fca4fad9d7547Pannag Sanketiusing namespace android;
463399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
473399b7267185646c69b04352211fca4fad9d7547Pannag Sanketienum {
480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    IMAGE_READER_MAX_NUM_PLANES = 3,
493399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi};
503399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic struct {
520c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jfieldID mNativeContext;
530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jmethodID postEventFromNative;
540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi} gImageReaderClassInfo;
550c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
560c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic struct {
570c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jfieldID mLockedBuffer;
580c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jfieldID mTimestamp;
590c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi} gSurfaceImageClassInfo;
600c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
613856b090cd04ba5dd4a59a12430ed724d5995909Steve Blockstatic struct {
620c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jclass clazz;
630c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jmethodID ctor;
640c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi} gSurfacePlaneClassInfo;
650c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
660c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi// ----------------------------------------------------------------------------
670c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
680c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketiclass JNIImageReaderContext : public CpuConsumer::FrameAvailableListener
690c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
700c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketipublic:
710c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages);
720c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
730c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    virtual ~JNIImageReaderContext();
740c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
750c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    virtual void onFrameAvailable();
760c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
770c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    CpuConsumer::LockedBuffer* getLockedBuffer();
780c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
790c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer);
800c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
810c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; }
820c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
830c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
840c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    void setBufferQueue(const sp<BufferQueue>& bq) { mBufferQueue = bq; }
850c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    BufferQueue* getBufferQueue() { return mBufferQueue.get(); }
860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    void setBufferFormat(int format) { mFormat = format; }
880c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int getBufferFormat() { return mFormat; }
890c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
900c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    void setBufferWidth(int width) { mWidth = width; }
910c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int getBufferWidth() { return mWidth; }
920c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
930c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    void setBufferHeight(int height) { mHeight = height; }
940c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int getBufferHeight() { return mHeight; }
950c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
960c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketiprivate:
970c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    static JNIEnv* getJNIEnv(bool* needsDetach);
980c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    static void detachJNI();
990c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1000c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    List<CpuConsumer::LockedBuffer*> mBuffers;
1010c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    sp<CpuConsumer> mConsumer;
1020c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    sp<BufferQueue> mBufferQueue;
1030c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jobject mWeakThiz;
1040c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jclass mClazz;
1050c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int mFormat;
1060c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int mWidth;
1070c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int mHeight;
1080c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi};
1093856b090cd04ba5dd4a59a12430ed724d5995909Steve Block
110bdddc659a941afdb7f4958f582c6901c07246097Daniel LamJNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
111bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam        jobject weakThiz, jclass clazz, int maxImages) :
11221fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi    mWeakThiz(env->NewGlobalRef(weakThiz)),
11321fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi    mClazz((jclass)env->NewGlobalRef(clazz)) {
1140c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    for (int i = 0; i < maxImages; i++) {
11521fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi        CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
11621fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi        mBuffers.push_back(buffer);
1170c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1180c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1190c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1200c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag SanketiJNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
1210c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
1220c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    *needsDetach = false;
1230c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIEnv* env = AndroidRuntime::getJNIEnv();
1240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (env == NULL) {
1250c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
1260c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        JavaVM* vm = AndroidRuntime::getJavaVM();
1270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        int result = vm->AttachCurrentThread(&env, (void*) &args);
1280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        if (result != JNI_OK) {
1290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOGE("thread attach failed: %#x", result);
1300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            return NULL;
1310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        }
1320c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        *needsDetach = true;
1330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return env;
1350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1370c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketivoid JNIImageReaderContext::detachJNI() {
1380c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JavaVM* vm = AndroidRuntime::getJavaVM();
1390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int result = vm->DetachCurrentThread();
1400c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (result != JNI_OK) {
1410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ALOGE("thread detach failed: %#x", result);
1420c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1430c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1440c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1450c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag SanketiCpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
1460c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (mBuffers.empty()) {
1470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return NULL;
1480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // Return a LockedBuffer pointer and remove it from the list
1500c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
1510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    CpuConsumer::LockedBuffer* buffer = *it;
1520c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    mBuffers.erase(it);
1530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return buffer;
1540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1550c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1560c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketivoid JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer * buffer) {
1570c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    mBuffers.push_back(buffer);
1580c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1590c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1600c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag SanketiJNIImageReaderContext::~JNIImageReaderContext() {
1610c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    bool needsDetach = false;
1620c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIEnv* env = getJNIEnv(&needsDetach);
1630c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (env != NULL) {
1640c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        env->DeleteGlobalRef(mWeakThiz);
1653856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        env->DeleteGlobalRef(mClazz);
1660c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    } else {
1670c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ALOGW("leaking JNI object references");
1680c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1690c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (needsDetach) {
1700c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        detachJNI();
1710c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1720c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1730c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // Delete LockedBuffers
1740c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin();
1750c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            it != mBuffers.end(); it++) {
1760c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        delete *it;
1770c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1780c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    mBuffers.clear();
1790c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    mConsumer.clear();
1800c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1810c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1820c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketivoid JNIImageReaderContext::onFrameAvailable()
1830c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
1840c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s: frame available", __FUNCTION__);
1850c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    bool needsDetach = false;
1860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIEnv* env = getJNIEnv(&needsDetach);
1870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (env != NULL) {
1880c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz);
1890c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    } else {
1900c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ALOGW("onFrameAvailable event will not posted");
1910c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1920c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (needsDetach) {
1930c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        detachJNI();
1940c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
1950c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
1960c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1970c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi// ----------------------------------------------------------------------------
1980c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
1990c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketiextern "C" {
2000c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2010c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
2020c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2030c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIImageReaderContext *ctx;
2040c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ctx = reinterpret_cast<JNIImageReaderContext *>
2050c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi              (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext));
2060c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return ctx;
2070c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
2080c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2090c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
2100c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2110c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
2120c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
2130c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (ctx == NULL) {
2140c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
2150c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return NULL;
2160c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
2170c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return ctx->getCpuConsumer();
2180c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
2190c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2200c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic BufferQueue* ImageReader_getBufferQueue(JNIEnv* env, jobject thiz)
2210c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2220c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
2230c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
2240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (ctx == NULL) {
2250c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
2260c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return NULL;
2270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
2280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return ctx->getBufferQueue();
2290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
2300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic void ImageReader_setNativeContext(JNIEnv* env,
2320c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jobject thiz, sp<JNIImageReaderContext> ctx)
2330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
2350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    JNIImageReaderContext* const p = ImageReader_getContext(env, thiz);
2360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (ctx != 0) {
2370c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ctx->incStrong((void*)ImageReader_setNativeContext);
2380c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
2390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (p) {
2400c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        p->decStrong((void*)ImageReader_setNativeContext);
2410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
2420c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext,
2430c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            reinterpret_cast<jlong>(ctx.get()));
2440c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
2450c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2460c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
2470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return reinterpret_cast<CpuConsumer::LockedBuffer*>(
2490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            env->GetLongField(image, gSurfaceImageClassInfo.mLockedBuffer));
2500c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
2510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2520c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic void Image_setBuffer(JNIEnv* env, jobject thiz,
2530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        const CpuConsumer::LockedBuffer* buffer)
2540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2550c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    env->SetLongField(thiz, gSurfaceImageClassInfo.mLockedBuffer, reinterpret_cast<jlong>(buffer));
2560c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
2570c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2580c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi// Some formats like JPEG defined with different values between android.graphics.ImageFormat and
2590c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi// graphics.h, need convert to the one defined in graphics.h here.
2600c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic int Image_getPixelFormat(JNIEnv* env, int format)
2610c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2620c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int jpegFormat, rawSensorFormat;
2630c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jfieldID fid;
2640c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2650c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s: format = 0x%x", __FUNCTION__, format);
2660c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2670c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat");
2680c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(imageFormatClazz != NULL);
2690c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2700c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
2710c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
2720c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    fid = env->GetStaticFieldID(imageFormatClazz, "RAW_SENSOR", "I");
2730c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    rawSensorFormat = env->GetStaticIntField(imageFormatClazz, fid);
2740c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2750c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // Translate the JPEG to BLOB for camera purpose, an add more if more mismatch is found.
2760c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (format == jpegFormat) {
2770c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        format = HAL_PIXEL_FORMAT_BLOB;
2780c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
2790c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // Same thing for RAW_SENSOR format
2800c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (format == rawSensorFormat) {
2810c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        format = HAL_PIXEL_FORMAT_RAW_SENSOR;
2820c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
2830c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2840c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return format;
2853399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi}
2860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer)
2880c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
2890c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
2900c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint32_t size = 0;
2910c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint32_t width = buffer->width;
2920c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint8_t* jpegBuffer = buffer->data;
2930c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
2940c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // First check for JPEG transport header at the end of the buffer
2950c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
2960c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
2970c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
2980c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        size = blob->jpeg_size;
2990c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
3000c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
3010c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3020c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // failed to find size, default to whole buffer
3030c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (size == 0) {
3040c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        size = width;
3050c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
3060c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3070c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return size;
3080c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
3090c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3100c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
3110c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                                uint8_t **base, uint32_t *size)
3120c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
3130c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
3140c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(base != NULL, "base is NULL!!!");
3150c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(size != NULL, "size is NULL!!!");
3160c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
3170c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3180c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
3190c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3200c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint32_t dataSize, ySize, cSize, cStride;
3210c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint8_t *cb, *cr;
3220c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint8_t *pData = NULL;
3230c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int bytesPerPixel = 0;
3240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3250c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    dataSize = ySize = cSize = cStride = 0;
3260c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int32_t fmt = buffer->format;
3270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    switch (fmt) {
3280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YCbCr_420_888:
3290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData =
3300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                (idx == 0) ?
3310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                    buffer->data :
3320c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                (idx == 1) ?
3330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                    buffer->dataCb :
3340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                buffer->dataCr;
3350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            if (idx == 0) {
3360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                dataSize = buffer->stride * buffer->height;
3370c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            } else {
3380c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                dataSize = buffer->chromaStride * buffer->height / 2;
3390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            }
3400c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
3410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        // NV21
3420c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
3430c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            cr = buffer->data + (buffer->stride * buffer->height);
3440c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            cb = cr + 1;
3450c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ySize = buffer->width * buffer->height;
3460c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            cSize = buffer->width * buffer->height / 2;
3470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3481a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi            pData =
3493399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                (idx == 0) ?
3503399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                    buffer->data :
3510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                (idx == 1) ?
3523399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                    cb:
3530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                cr;
3543399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
3553399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            dataSize = (idx == 0) ? ySize : cSize;
3563399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
3573399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_YV12:
3583399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            // Y and C stride need to be 16 pixel aligned.
3593399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
360b6f2fced47866a5d095b2b18d2e28d7c4321e3a6James Dong                                "Stride is not 16 pixel aligned %d", buffer->stride);
3611a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi
362bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam            ySize = buffer->stride * buffer->height;
363abf0610a8cea021548f2909e1d47d656206f641cDaniel Lam            cStride = ALIGN(buffer->stride / 2, 16);
364bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam            cr = buffer->data + ySize;
3653399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            cSize = cStride * buffer->height / 2;
3660c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            cb = cr + cSize;
3673399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
3680c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData =
3690c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                (idx == 0) ?
3700c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                    buffer->data :
3710c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                (idx == 1) ?
3723399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                    cb :
3733399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                cr;
3740c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            dataSize = (idx == 0) ? ySize : cSize;
3750c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
3760c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_Y8:
3770c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Single plane, 8bpp.
3780c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
3790c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3800c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData = buffer->data;
3810c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            dataSize = buffer->stride * buffer->height;
3820c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
3830c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_Y16:
3840c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Single plane, 16bpp, strides are specified in pixels, not in bytes
3850c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
3860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData = buffer->data;
3880c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            dataSize = buffer->stride * buffer->height * 2;
3890c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
3900c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_BLOB:
3910c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Used for JPEG data, height must be 1, width == size, single plane.
3920c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
3930c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height);
3940c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
3950c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData = buffer->data;
3963856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            dataSize = Image_getJpegSize(buffer);
3970c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
3980c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RAW_SENSOR:
399bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam            // Single plane 16bpp bayer data.
4000c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4010c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData = buffer->data;
4020c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            dataSize = buffer->width * 2 * buffer->height;
4030c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4040c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RGBA_8888:
4053399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RGBX_8888:
4063399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            // Single plane, 32bpp.
4071a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi            bytesPerPixel = 4;
4083399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4093399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            pData = buffer->data;
4100c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            dataSize = buffer->stride * buffer->height * bytesPerPixel;
4113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
4123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RGB_565:
4130c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Single plane, 16bpp.
4140c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            bytesPerPixel = 2;
415a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
416a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi            pData = buffer->data;
4173399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            dataSize = buffer->stride * buffer->height * bytesPerPixel;
4181a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi            break;
4193399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RGB_888:
4203399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            // Single plane, 24bpp.
4213399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            bytesPerPixel = 3;
4223399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4230c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pData = buffer->data;
4240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            dataSize = buffer->stride * buffer->height * bytesPerPixel;
4250c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4260c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        default:
4273856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
4280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                                 "Pixel format: 0x%x is unsupported", fmt);
4290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
4310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
4320c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    *base = pData;
4330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    *size = dataSize;
4340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
4350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
4360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
4370c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
4380c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
4390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
4400c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
4410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int pixelStride = 0;
4420c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(buffer != NULL, "buffer is NULL");
4430c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
4440c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int32_t fmt = buffer->format;
4450c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    switch (fmt) {
4460c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YCbCr_420_888:
4470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride = (idx == 0) ? 1 : buffer->chromaStep;
4480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
4500c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride = (idx == 0) ? 1 : 2;
4510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4520c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_Y8:
4530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Single plane 8bpp data.
4540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4550c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride;
4560c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4570c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YV12:
4580c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride = 1;
4590c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4600c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_BLOB:
4610c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Used for JPEG data, single plane, row and pixel strides are 0
46221fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
46331292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi            pixelStride = 0;
4640c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4650c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_Y16:
4660c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RAW_SENSOR:
4670c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RGB_565:
4680c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Single plane 16bpp data.
4690c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4700c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride = 2;
4710c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4720c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RGBA_8888:
4730c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RGBX_8888:
4740c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4750c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride = 4;
4760c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4770c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RGB_888:
4783856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            // Single plane, 24bpp.
479f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
4800c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            pixelStride = 3;
4810c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4820c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        default:
4830c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
4840c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                                 "Pixel format: 0x%x is unsupported", fmt);
4850c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
4860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
4870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
4880c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return pixelStride;
4899d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam}
4909d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam
4919d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lamstatic jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
4929d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam{
49321fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
4940c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
4950c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
49621fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi    int rowStride = 0;
4970c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(buffer != NULL, "buffer is NULL");
49821fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi
4990c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int32_t fmt = buffer->format;
5000c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
5010c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    switch (fmt) {
5020c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YCbCr_420_888:
5030c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
5040c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
5050c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YCrCb_420_SP:
5060c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            rowStride = buffer->width;
5070c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
5080c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_YV12:
5090c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
5101a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi                                "Stride is not 16 pixel aligned %d", buffer->stride);
5113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
5123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
5133399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_BLOB:
5143399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            // Used for JPEG data, single plane, row and pixel strides are 0
5153399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
5163399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            rowStride = 0;
5173399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
5183399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_Y8:
5193399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
5203399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
5211a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi                                "Stride is not 16 pixel aligned %d", buffer->stride);
5223399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            rowStride = buffer->stride;
5233399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
5243399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_Y16:
5253399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RAW_SENSOR:
5263399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            // In native side, strides are specified in pixels, not in bytes.
5270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // Single plane 16bpp bayer data. even width/height,
5280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            // row stride multiple of 16 pixels (32 bytes)
5290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
5300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
5310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                                "Stride is not 16 pixel aligned %d", buffer->stride);
5323399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            rowStride = buffer->stride * 2;
5330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            break;
5340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        case HAL_PIXEL_FORMAT_RGB_565:
5350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
5360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            rowStride = buffer->stride * 2;
5373399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
5383399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RGBA_8888:
5393399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RGBX_8888:
5401a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
5413399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            rowStride = buffer->stride * 4;
5423399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
5433399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        case HAL_PIXEL_FORMAT_RGB_888:
5443399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            // Single plane, 24bpp.
5453399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
5463399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            rowStride = buffer->stride * 3;
5473399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            break;
5483399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        default:
5493399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
5503399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            jniThrowException(env, "java/lang/UnsupportedOperationException",
5513399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                              "unsupported buffer format");
5523399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi          break;
5533399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
5543399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5553399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    return rowStride;
5563399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi}
5573399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5583399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi// ----------------------------------------------------------------------------
5593399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5603399b7267185646c69b04352211fca4fad9d7547Pannag Sanketistatic void ImageReader_classInit(JNIEnv* env, jclass clazz)
5613399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{
5623399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
5633399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5643399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
5653399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
5663399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                        "can't find android/graphics/ImageReader$SurfaceImage");
5673399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    gSurfaceImageClassInfo.mLockedBuffer = env->GetFieldID(
5683399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
5693399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mLockedBuffer == NULL,
5701a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi                        "can't find android/graphics/ImageReader.%s",
5713399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                        ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
5723399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5733399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    gSurfaceImageClassInfo.mTimestamp = env->GetFieldID(
5743399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
5753399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL,
5763399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                        "can't find android/graphics/ImageReader.%s",
5773399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                        ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
5783399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5793399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    gImageReaderClassInfo.mNativeContext = env->GetFieldID(
5803399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
5813399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
5823399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                        "can't find android/graphics/ImageReader.%s",
5833399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                          ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
5843399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5853399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(
5863399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
5873399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL,
5883399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                        "can't find android/graphics/ImageReader.postEventFromNative");
5893399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
5903399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
5913399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
5921a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi    // FindClass only gives a local reference of jclass object.
5933399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
5943399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>",
5953399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            "(Landroid/media/ImageReader$SurfaceImage;III)V");
5963399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
5973399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            "Can not find SurfacePlane constructor");
5983399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi}
5993399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6003399b7267185646c69b04352211fca4fad9d7547Pannag Sanketistatic void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
6013399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                             jint width, jint height, jint format, jint maxImages)
6023399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi{
6033399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    status_t res;
6043399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    int nativeFormat;
6053399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6063399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
6073399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi          __FUNCTION__, width, height, format, maxImages);
6083399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6093399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    nativeFormat = Image_getPixelFormat(env, format);
6103399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6113399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    sp<BufferQueue> bq = new BufferQueue();
6123399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    sp<CpuConsumer> consumer = new CpuConsumer(bq, true, maxImages);
6133399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    // TODO: throw dvm exOutOfMemoryError?
6143399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (consumer == NULL) {
6153399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
6163399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        return;
6173399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
6183399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6193399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    jclass clazz = env->GetObjectClass(thiz);
6200c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (clazz == NULL) {
6210c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
6220c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return;
6230c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
6240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
6250c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ctx->setCpuConsumer(consumer);
6260c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ctx->setBufferQueue(bq);
6270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    consumer->setFrameAvailableListener(ctx);
6281a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi    ImageReader_setNativeContext(env, thiz, ctx);
6290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ctx->setBufferFormat(nativeFormat);
6300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ctx->setBufferWidth(width);
6310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ctx->setBufferHeight(height);
6323856b090cd04ba5dd4a59a12430ed724d5995909Steve Block
6333856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    // Set the width/height/format to the CpuConsumer
6343399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    res = consumer->setDefaultBufferSize(width, height);
6350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (res != OK) {
6360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowException(env, "java/lang/IllegalStateException",
6373399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                          "Failed to set CpuConsumer buffer size");
6383399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        return;
6393399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
6403399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    res = consumer->setDefaultBufferFormat(nativeFormat);
6410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (res != OK) {
6420c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowException(env, "java/lang/IllegalStateException",
6433856b090cd04ba5dd4a59a12430ed724d5995909Steve Block                          "Failed to set CpuConsumer buffer format");
6443856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    }
6453399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi}
6463399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic void ImageReader_close(JNIEnv* env, jobject thiz)
6480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
6490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
6500c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
6513399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
6523399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (ctx == NULL) {
6533399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        // ImageReader is already closed.
6540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return;
6553399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
6563399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6573399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz);
6581a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi    if (consumer != NULL) {
6590c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        consumer->abandon();
6600c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        consumer->setFrameAvailableListener(NULL);
6613856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    }
6623856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    ImageReader_setNativeContext(env, thiz, NULL);
6630c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
6640c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
665a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketistatic void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
6661a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi{
6673399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
6683399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
6693399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (ctx == NULL) {
6703399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
6713399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        return;
6723399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
6733399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
6743399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    CpuConsumer* consumer = ctx->getCpuConsumer();
6753399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
6763399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (!buffer) {
6773399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        ALOGW("Image already released!!!");
6783399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        return;
6793399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
6801a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi    consumer->unlockBuffer(*buffer);
6810c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    Image_setBuffer(env, image, NULL);
682bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam    ctx->returnLockedBuffer(buffer);
6833856b090cd04ba5dd4a59a12430ed724d5995909Steve Block}
6843856b090cd04ba5dd4a59a12430ed724d5995909Steve Block
685a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketistatic jboolean ImageReader_imageSetup(JNIEnv* env, jobject thiz,
6860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                                             jobject image)
6870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
688a361483bb5dbd3bbf132c5b99b2df7d197c3fc50Pannag Sanketi    ALOGV("%s:", __FUNCTION__);
6891a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi    JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
6903399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (ctx == NULL) {
6913399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
6923399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        return false;
693bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam    }
694bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam
6953399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    CpuConsumer* consumer = ctx->getCpuConsumer();
696bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam    CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
6973399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (buffer == NULL) {
6983399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        ALOGE("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
6993399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            "maxImages buffers");
7003399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        return false;
7013399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
7023399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    status_t res = consumer->lockNextBuffer(buffer);
7033399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (res != NO_ERROR) {
7043399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        if (res != BAD_VALUE /*no buffers*/) {
7053399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi            ALOGE("%s Fail to lockNextBuffer with error: %d ", __FUNCTION__, res);
7063399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        }
7071a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi        return false;
7083399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
709bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam
7103856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    // Check if the left-top corner of the crop rect is origin, we currently assume this point is
7113856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    // zero, will revist this once this assumption turns out problematic.
7120c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    Point lt = buffer->crop.leftTop();
7130c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (lt.x != 0 || lt.y != 0) {
7143399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        ALOGE("crop left: %d, top = %d", lt.x, lt.y);
7151a2fafbaa36390a06cc9a066fcbe147c8c47ea77Pannag Sanketi        jniThrowException(env, "java/lang/UnsupportedOperationException",
7163399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi                          "crop left top corner need to at origin");
7173399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
7183399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
7193399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    // Check if the producer buffer configurations match what ImageReader configured.
720bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam    // We want to fail for the very first image because this case is too bad.
7213399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    int outputWidth = buffer->width;
7223399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    int outputHeight = buffer->height;
7233399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
7243399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    // Correct with/height when crop is set.
7253399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (buffer->crop.getWidth() > 0) {
7263399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        outputWidth = buffer->crop.getWidth() + 1;
7273399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    }
7280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (buffer->crop.getHeight() > 0) {
7290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        outputHeight = buffer->crop.getHeight() + 1;
7300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
7310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
7320c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int imageReaderWidth = ctx->getBufferWidth();
7330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int imageReaderHeight = ctx->getBufferHeight();
7340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (imageReaderWidth != outputWidth
7353856b090cd04ba5dd4a59a12430ed724d5995909Steve Block            || imageReaderHeight != outputHeight) {
7363856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        // Spew warning for now, since MediaCodec decoder has a bug to setup the right crop
7373856b090cd04ba5dd4a59a12430ed724d5995909Steve Block        // TODO: make it throw exception once the decoder bug is fixed.
7380c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ALOGW("Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
7390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi              outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
7400c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
7410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
74229357bc2c0dd7c43ad3bd0c8e3efa4e6fd9bfd47Steve Block    if (ctx->getBufferFormat() != buffer->format) {
7430c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        // Return the buffer to the queue.
7440c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        consumer->unlockBuffer(*buffer);
7450c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ctx->returnLockedBuffer(buffer);
7460c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
7470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        // Throw exception
7480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
7490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi              buffer->format, ctx->getBufferFormat());
7500c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        String8 msg;
7510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        msg.appendFormat("The producer output buffer format 0x%x doesn't "
7520c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                "match the ImageReader's configured buffer format 0x%x.",
7530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                buffer->format, ctx->getBufferFormat());
7540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowException(env, "java/lang/UnsupportedOperationException",
7550c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                msg.string());
7560c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return false;
7570c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
7583399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    // Set SurfaceImage instance member variables
7593399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    Image_setBuffer(env, image, buffer);
7603399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
7610c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi            static_cast<jlong>(buffer->timestamp));
7623399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
7633856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    return true;
7643399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi}
7653399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi
7660c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
7673856b090cd04ba5dd4a59a12430ed724d5995909Steve Block{
768f1d5aa162c02a16b7195a43a9bcea4d592600ac4James Dong    ALOGV("%s: ", __FUNCTION__);
7690c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
7700c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    BufferQueue* bq = ImageReader_getBufferQueue(env, thiz);
7713399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    if (bq == NULL) {
7723399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi        jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
7730c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        return NULL;
7740c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
7750c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
7760c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // Wrap the IGBP in a Java-language Surface.
7770c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return android_view_Surface_createFromIGraphicBufferProducer(env, bq);
7780c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
77921fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi
7803856b090cd04ba5dd4a59a12430ed724d5995909Steve Blockstatic jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx)
7813856b090cd04ba5dd4a59a12430ed724d5995909Steve Block{
7820c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int rowStride, pixelStride;
7830c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
784bdddc659a941afdb7f4958f582c6901c07246097Daniel Lam
7850c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
7860c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
7870c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOG_ASSERT(buffer != NULL);
7880c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (buffer == NULL) {
7890c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
7909d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam    }
7919d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam    rowStride = Image_imageGetRowStride(env, buffer, idx);
7929d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam    pixelStride = Image_imageGetPixelStride(env, buffer, idx);
7939d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam
7949d06df4ecfe39e7e46873f7cd75a71e32a01d4f7Daniel Lam    jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
79521fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi            gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
7960c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
7970c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return surfPlaneObj;
79821fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketi}
7990c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
80021fcf0830c8b4fb544a09467bc96a8d0463ad966Pannag Sanketistatic jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx)
8010c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi{
8020c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    uint8_t *base = NULL;
8033399b7267185646c69b04352211fca4fad9d7547Pannag Sanketi    uint32_t size = 0;
8040c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    jobject byteBuffer;
8050c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8060c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
8070c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8083856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
8090c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8100c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if (buffer == NULL) {
81131292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi        jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
81231292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi    }
81331292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi
81431292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi    // Create byteBuffer from native buffer
81531292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi    Image_getLockedBufferInfo(env, buffer, idx, &base, &size);
81631292d99f62a812af691e67e8e732c6ae582ee08Pannag Sanketi    byteBuffer = env->NewDirectByteBuffer(base, size);
8170c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    // TODO: throw dvm exOutOfMemoryError?
8180c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
8190c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi        jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
8200c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    }
8210c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8223856b090cd04ba5dd4a59a12430ed724d5995909Steve Block    return byteBuffer;
8233856b090cd04ba5dd4a59a12430ed724d5995909Steve Block}
8240c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8250c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi} // extern "C"
8260c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8270c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi// ----------------------------------------------------------------------------
8280c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8290c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic JNINativeMethod gImageReaderMethods[] = {
8300c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeClassInit",        "()V",                        (void*)ImageReader_classInit },
8310c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeInit",             "(Ljava/lang/Object;IIII)V",  (void*)ImageReader_init },
8320c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeClose",            "()V",                        (void*)ImageReader_close },
8330c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeReleaseImage",     "(Landroid/media/Image;)V",   (void*)ImageReader_imageRelease },
8340c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeImageSetup",       "(Landroid/media/Image;)Z",    (void*)ImageReader_imageSetup },
8350c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeGetSurface",       "()Landroid/view/Surface;",   (void*)ImageReader_getSurface },
8360c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi};
8370c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8380c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketistatic JNINativeMethod gImageMethods[] = {
8390c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeImageGetBuffer",   "(I)Ljava/nio/ByteBuffer;",   (void*)Image_getByteBuffer },
8400c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    {"nativeCreatePlane",      "(I)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
8410c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                                                             (void*)Image_createSurfacePlane },
8420c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi};
8430c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8440c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketiint register_android_media_ImageReader(JNIEnv *env) {
8450c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8460c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int ret1 = AndroidRuntime::registerNativeMethods(env,
8470c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                   "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
8480c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8490c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    int ret2 = AndroidRuntime::registerNativeMethods(env,
8500c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi                   "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
8510c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi
8520c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi    return (ret1 || ret2);
8530c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi}
8540c5c7d2b119d2350c186ae9902919bcf28c3e277Pannag Sanketi