android_media_ImageWriter.cpp revision f6a09e510649ae4701bb5ad4c40d102d59a5608c
1f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He/* 2f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Copyright 2015 The Android Open Source Project 3f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * 4f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Licensed under the Apache License, Version 2.0 (the "License"); 5f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * you may not use this file except in compliance with the License. 6f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * You may obtain a copy of the License at 7f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * 8f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * http://www.apache.org/licenses/LICENSE-2.0 9f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * 10f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * Unless required by applicable law or agreed to in writing, software 11f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * distributed under the License is distributed on an "AS IS" BASIS, 12f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * See the License for the specific language governing permissions and 14f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * limitations under the License. 15f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 16f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 17f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He//#define LOG_NDEBUG 0 18f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#define LOG_TAG "ImageWriter_JNI" 19f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <utils/Log.h> 20f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <utils/String8.h> 21f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 22f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <gui/IProducerListener.h> 23f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <gui/Surface.h> 24f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <gui/CpuConsumer.h> 25f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <android_runtime/AndroidRuntime.h> 26f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <android_runtime/android_view_Surface.h> 27f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <camera3.h> 28f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 29f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <jni.h> 30f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <JNIHelp.h> 31f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 32f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <stdint.h> 33f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#include <inttypes.h> 34f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 35f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) ) 36f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 37f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He#define IMAGE_BUFFER_JNI_ID "mNativeBuffer" 38f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 39f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// ---------------------------------------------------------------------------- 40f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 41f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heusing namespace android; 42f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 43f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heenum { 44f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He IMAGE_WRITER_MAX_NUM_PLANES = 3, 45f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He}; 46f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 47f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic struct { 48f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jmethodID postEventFromNative; 49f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jfieldID mWriterFormat; 50f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} gImageWriterClassInfo; 51f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 52f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic struct { 53f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jfieldID mNativeBuffer; 54f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jfieldID mNativeFenceFd; 55f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jfieldID mPlanes; 56f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} gSurfaceImageClassInfo; 57f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 58f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic struct { 59f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jclass clazz; 60f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jmethodID ctor; 61f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} gSurfacePlaneClassInfo; 62f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 63f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hetypedef CpuConsumer::LockedBuffer LockedImage; 64f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 65f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// ---------------------------------------------------------------------------- 66f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 67f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heclass JNIImageWriterContext : public BnProducerListener { 68f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hepublic: 69f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIImageWriterContext(JNIEnv* env, jobject weakThiz, jclass clazz); 70f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 71f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He virtual ~JNIImageWriterContext(); 72f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 73f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Implementation of IProducerListener, used to notify the ImageWriter that the consumer 74f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // has returned a buffer and it is ready for ImageWriter to dequeue. 75f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He virtual void onBufferReleased(); 76f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 77f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He void setProducer(const sp<ANativeWindow>& producer) { mProducer = producer; } 78f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ANativeWindow* getProducer() { return mProducer.get(); } 79f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 80f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He void setBufferFormat(int format) { mFormat = format; } 81f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int getBufferFormat() { return mFormat; } 82f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 83f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He void setBufferWidth(int width) { mWidth = width; } 84f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int getBufferWidth() { return mWidth; } 85f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 86f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He void setBufferHeight(int height) { mHeight = height; } 87f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int getBufferHeight() { return mHeight; } 88f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 89f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heprivate: 90f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He static JNIEnv* getJNIEnv(bool* needsDetach); 91f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He static void detachJNI(); 92f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 93f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<ANativeWindow> mProducer; 94f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jobject mWeakThiz; 95f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jclass mClazz; 96f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int mFormat; 97f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int mWidth; 98f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int mHeight; 99f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He}; 100f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 101f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun HeJNIImageWriterContext::JNIImageWriterContext(JNIEnv* env, jobject weakThiz, jclass clazz) : 102f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mWeakThiz(env->NewGlobalRef(weakThiz)), 103f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mClazz((jclass)env->NewGlobalRef(clazz)), 104f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mFormat(0), 105f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mWidth(-1), 106f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mHeight(-1) { 107f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 108f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 109f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun HeJNIImageWriterContext::~JNIImageWriterContext() { 110f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 111f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bool needsDetach = false; 112f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIEnv* env = getJNIEnv(&needsDetach); 113f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (env != NULL) { 114f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->DeleteGlobalRef(mWeakThiz); 115f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->DeleteGlobalRef(mClazz); 116f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } else { 117f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGW("leaking JNI object references"); 118f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 119f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (needsDetach) { 120f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He detachJNI(); 121f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 122f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 123f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He mProducer.clear(); 124f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 125f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 126f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun HeJNIEnv* JNIImageWriterContext::getJNIEnv(bool* needsDetach) { 127f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 128f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!"); 129f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *needsDetach = false; 130f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIEnv* env = AndroidRuntime::getJNIEnv(); 131f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (env == NULL) { 132f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL}; 133f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JavaVM* vm = AndroidRuntime::getJavaVM(); 134f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int result = vm->AttachCurrentThread(&env, (void*) &args); 135f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (result != JNI_OK) { 136f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("thread attach failed: %#x", result); 137f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return NULL; 138f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 139f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *needsDetach = true; 140f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 141f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return env; 142f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 143f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 144f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hevoid JNIImageWriterContext::detachJNI() { 145f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 146f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JavaVM* vm = AndroidRuntime::getJavaVM(); 147f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int result = vm->DetachCurrentThread(); 148f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (result != JNI_OK) { 149f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("thread detach failed: %#x", result); 150f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 151f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 152f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 153f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hevoid JNIImageWriterContext::onBufferReleased() { 154f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s: buffer released", __FUNCTION__); 155f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bool needsDetach = false; 156f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIEnv* env = getJNIEnv(&needsDetach); 157f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (env != NULL) { 158f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->CallStaticVoidMethod(mClazz, gImageWriterClassInfo.postEventFromNative, mWeakThiz); 159f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } else { 160f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGW("onBufferReleased event will not posted"); 161f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 162f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (needsDetach) { 163f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He detachJNI(); 164f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 165f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 166f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 167f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// ---------------------------------------------------------------------------- 168f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 169f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heextern "C" { 170f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 171f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// -------------------------------Private method declarations-------------- 172f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 173f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic bool isWritable(int format); 174f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic bool isPossiblyYUV(PixelFormat format); 175f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_setNativeContext(JNIEnv* env, jobject thiz, 176f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<GraphicBuffer> buffer, int fenceFd); 177f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_getNativeContext(JNIEnv* env, jobject thiz, 178f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer** buffer, int* fenceFd); 179f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_unlockIfLocked(JNIEnv* env, jobject thiz); 180f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 181f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// --------------------------ImageWriter methods--------------------------------------- 182f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 183f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void ImageWriter_classInit(JNIEnv* env, jclass clazz) { 184f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s:", __FUNCTION__); 185f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jclass imageClazz = env->FindClass("android/media/ImageWriter$WriterSurfaceImage"); 186f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(imageClazz == NULL, 187f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "can't find android/media/ImageWriter$WriterSurfaceImage"); 188f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gSurfaceImageClassInfo.mNativeBuffer = env->GetFieldID( 189f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He imageClazz, IMAGE_BUFFER_JNI_ID, "J"); 190f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeBuffer == NULL, 191f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "can't find android/media/ImageWriter$WriterSurfaceImage.%s", IMAGE_BUFFER_JNI_ID); 192f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 193f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gSurfaceImageClassInfo.mNativeFenceFd = env->GetFieldID( 194f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He imageClazz, "mNativeFenceFd", "I"); 195f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mNativeFenceFd == NULL, 196f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "can't find android/media/ImageWriter$WriterSurfaceImage.mNativeFenceFd"); 197f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 198f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gSurfaceImageClassInfo.mPlanes = env->GetFieldID( 199f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He imageClazz, "mPlanes", "[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;"); 200f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mPlanes == NULL, 201f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "can't find android/media/ImageWriter$WriterSurfaceImage.mPlanes"); 202f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 203f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gImageWriterClassInfo.postEventFromNative = env->GetStaticMethodID( 204f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He clazz, "postEventFromNative", "(Ljava/lang/Object;)V"); 205f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(gImageWriterClassInfo.postEventFromNative == NULL, 206f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "can't find android/media/ImageWriter.postEventFromNative"); 207f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 208f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gImageWriterClassInfo.mWriterFormat = env->GetFieldID( 209f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He clazz, "mWriterFormat", "I"); 210f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(gImageWriterClassInfo.mWriterFormat == NULL, 211f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "can't find android/media/ImageWriter.mWriterFormat"); 212f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 213f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jclass planeClazz = env->FindClass("android/media/ImageWriter$WriterSurfaceImage$SurfacePlane"); 214f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class"); 215f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // FindClass only gives a local reference of jclass object. 216f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz); 217f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>", 218f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "(Landroid/media/ImageWriter$WriterSurfaceImage;IILjava/nio/ByteBuffer;)V"); 219f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL, 220f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Can not find SurfacePlane constructor"); 221f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 222f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 223f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic jlong ImageWriter_init(JNIEnv* env, jobject thiz, jobject weakThiz, jobject jsurface, 224f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jint maxImages) { 225f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He status_t res; 226f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 227f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s: maxImages:%d", __FUNCTION__, maxImages); 228f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 229f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<Surface> surface(android_view_Surface_getSurface(env, jsurface)); 230f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (surface == NULL) { 231f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, 232f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "java/lang/IllegalArgumentException", 233f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "The surface has been released"); 234f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 235f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 236f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<IGraphicBufferProducer> bufferProducer = surface->getIGraphicBufferProducer(); 237f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 238f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jclass clazz = env->GetObjectClass(thiz); 239f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (clazz == NULL) { 240f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Can't find android/graphics/ImageWriter"); 241f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 242f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 243f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<JNIImageWriterContext> ctx(new JNIImageWriterContext(env, weakThiz, clazz)); 244f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 245f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<Surface> producer = new Surface(bufferProducer, /*controlledByApp*/false); 246f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ctx->setProducer(producer); 247f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /** 248f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * NATIVE_WINDOW_API_CPU isn't a good choice here, as it makes the bufferQueue not connectable 249f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * after disconnect. MEDIA or CAMERA are treated the same internally. The producer listener 250f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * will be cleared after disconnect call. 251f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 252f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He producer->connect(/*api*/NATIVE_WINDOW_API_CAMERA, /*listener*/ctx); 253f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jlong nativeCtx = reinterpret_cast<jlong>(ctx.get()); 254f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 255f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Get the dimension and format of the producer. 256f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<ANativeWindow> anw = producer; 257f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int32_t width, height, format; 258f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if ((res = anw->query(anw.get(), NATIVE_WINDOW_WIDTH, &width)) != OK) { 259f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Query Surface width failed: %s (%d)", __FUNCTION__, strerror(-res), res); 260f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Failed to query Surface width"); 261f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 262f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 263f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ctx->setBufferWidth(width); 264f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 265f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if ((res = anw->query(anw.get(), NATIVE_WINDOW_HEIGHT, &height)) != OK) { 266f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Query Surface height failed: %s (%d)", __FUNCTION__, strerror(-res), res); 267f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Failed to query Surface height"); 268f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 269f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 270f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ctx->setBufferHeight(height); 271f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 272f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if ((res = anw->query(anw.get(), NATIVE_WINDOW_FORMAT, &format)) != OK) { 273f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Query Surface format failed: %s (%d)", __FUNCTION__, strerror(-res), res); 274f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Failed to query Surface format"); 275f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 276f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 277f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ctx->setBufferFormat(format); 278f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->SetIntField(thiz, gImageWriterClassInfo.mWriterFormat, reinterpret_cast<jint>(format)); 279f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 280f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 281f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (isWritable(format)) { 282f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = native_window_set_usage(anw.get(), GRALLOC_USAGE_SW_WRITE_OFTEN); 283f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 284f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Configure usage %08x for format %08x failed: %s (%d)", 285f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He __FUNCTION__, GRALLOC_USAGE_SW_WRITE_OFTEN, format, strerror(-res), res); 286f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Failed to SW_WRITE_OFTEN configure usage"); 287f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 288f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 289f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 290f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 291f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int minUndequeuedBufferCount = 0; 292f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = anw->query(anw.get(), 293f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &minUndequeuedBufferCount); 294f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 295f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Query producer undequeued buffer count failed: %s (%d)", 296f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He __FUNCTION__, strerror(-res), res); 297f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Query producer undequeued buffer count failed"); 298f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 299f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 300f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 301f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He size_t totalBufferCount = maxImages + minUndequeuedBufferCount; 302f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = native_window_set_buffer_count(anw.get(), totalBufferCount); 303f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 304f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Set buffer count failed: %s (%d)", __FUNCTION__, strerror(-res), res); 305f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Set buffer count failed"); 306f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 307f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 308f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 309f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (ctx != 0) { 310f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ctx->incStrong((void*)ImageWriter_init); 311f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 312f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return nativeCtx; 313f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 314f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 315f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void ImageWriter_dequeueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image) { 316f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 317f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); 318f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (ctx == NULL || thiz == NULL) { 319f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 320f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "ImageWriterContext is not initialized"); 321f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 322f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 323f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 324f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<ANativeWindow> anw = ctx->getProducer(); 325f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He android_native_buffer_t *anb = NULL; 326f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int fenceFd = -1; 327f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He status_t res = anw->dequeueBuffer(anw.get(), &anb, &fenceFd); 328f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 329f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // TODO: handle different error cases here. 330f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: Set buffer count failed: %s (%d)", __FUNCTION__, strerror(-res), res); 331f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "dequeue buffer failed"); 332f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 333f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 334f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // New GraphicBuffer object doesn't own the handle, thus the native buffer 335f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // won't be freed when this object is destroyed. 336f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<GraphicBuffer> buffer(new GraphicBuffer(anb, /*keepOwnership*/false)); 337f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 338f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Note that: 339f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // 1. No need to lock buffer now, will only lock it when the first getPlanes() is called. 340f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // 2. Fence will be saved to mNativeFenceFd, and will consumed by lock/queue/cancel buffer 341f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // later. 342f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // 3. need use lockAsync here, as it will handle the dequeued fence for us automatically. 343f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 344f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Finally, set the native info into image object. 345f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_setNativeContext(env, image, buffer, fenceFd); 346f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 347f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 348f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void ImageWriter_close(JNIEnv* env, jobject thiz, jlong nativeCtx) { 349f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s:", __FUNCTION__); 350f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); 351f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (ctx == NULL || thiz == NULL) { 352f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 353f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "ImageWriterContext is not initialized"); 354f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 355f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 356f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 357f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ANativeWindow* producer = ctx->getProducer(); 358f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (producer != NULL) { 359f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /** 360f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * NATIVE_WINDOW_API_CPU isn't a good choice here, as it makes the bufferQueue not 361f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * connectable after disconnect. MEDIA or CAMERA are treated the same internally. 362f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * The producer listener will be cleared after disconnect call. 363f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 364f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He status_t res = native_window_api_disconnect(producer, /*api*/NATIVE_WINDOW_API_CAMERA); 365f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /** 366f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * This is not an error. if client calling process dies, the window will 367f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * also die and all calls to it will return DEAD_OBJECT, thus it's already 368f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * "disconnected" 369f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 370f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res == DEAD_OBJECT) { 371f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGW("%s: While disconnecting ImageWriter from native window, the" 372f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He " native window died already", __FUNCTION__); 373f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } else if (res != OK) { 374f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGE("%s: native window disconnect failed: %s (%d)", 375f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He __FUNCTION__, strerror(-res), res); 376f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Native window disconnect failed"); 377f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 378f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 379f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 380f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 381f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ctx->decStrong((void*)ImageWriter_init); 382f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 383f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 384f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void ImageWriter_cancelImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image) { 385f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 386f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); 387f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (ctx == NULL || thiz == NULL) { 388f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 389f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "ImageWriterContext is not initialized"); 390f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 391f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 392f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 393f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<ANativeWindow> anw = ctx->getProducer(); 394f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 395f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer *buffer = NULL; 396f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int fenceFd = -1; 397f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, image, &buffer, &fenceFd); 398f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 399f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 400f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 401f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 402f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 403f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 404f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Unlock the image if it was locked 405f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_unlockIfLocked(env, image); 406f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 407f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He anw->cancelBuffer(anw.get(), buffer, fenceFd); 408f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 409f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_setNativeContext(env, image, NULL, -1); 410f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 411f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 412f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void ImageWriter_queueImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image, 413f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jlong timestampNs, jint left, jint top, jint right, jint bottom) { 414f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 415f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); 416f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (ctx == NULL || thiz == NULL) { 417f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 418f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "ImageWriterContext is not initialized"); 419f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 420f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 421f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 422f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He status_t res = OK; 423f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<ANativeWindow> anw = ctx->getProducer(); 424f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 425f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer *buffer = NULL; 426f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int fenceFd = -1; 427f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, image, &buffer, &fenceFd); 428f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 429f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 430f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 431f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 432f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 433f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 434f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Unlock image if it was locked. 435f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_unlockIfLocked(env, image); 436f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 437f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Set timestamp 438f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("timestamp to be queued: %lld", timestampNs); 439f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = native_window_set_buffers_timestamp(anw.get(), timestampNs); 440f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 441f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Set timestamp failed"); 442f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 443f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 444f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 445f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Set crop 446f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He android_native_rect_t cropRect; 447f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cropRect.left = left; 448f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cropRect.top = top; 449f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cropRect.right = right; 450f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cropRect.bottom = bottom; 451f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = native_window_set_crop(anw.get(), &cropRect); 452f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 453f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Set crop rect failed"); 454f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 455f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 456f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 457f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Finally, queue input buffer 458f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = anw->queueBuffer(anw.get(), buffer, fenceFd); 459f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 460f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Queue input buffer failed"); 461f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 462f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 463f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 464f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_setNativeContext(env, image, NULL, -1); 465f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 466f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 467f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void ImageWriter_attachImage(JNIEnv* env, jobject thiz, jlong nativeCtx, jobject image) { 468f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 469f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He JNIImageWriterContext* const ctx = reinterpret_cast<JNIImageWriterContext *>(nativeCtx); 470f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (ctx == NULL || thiz == NULL) { 471f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 472f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "ImageWriterContext is not initialized"); 473f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 474f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 475f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 476f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<ANativeWindow> anw = ctx->getProducer(); 477f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 478f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer *buffer = NULL; 479f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int fenceFd = -1; 480f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, image, &buffer, &fenceFd); 481f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 482f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 483f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 484f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 485f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 486f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 487f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // TODO: need implement 488f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "nativeAttachImage is not implement yet!!!"); 489f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 490f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 491f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// --------------------------Image methods--------------------------------------- 492f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 493f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_getNativeContext(JNIEnv* env, jobject thiz, 494f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer** buffer, int* fenceFd) { 495f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 496f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer != NULL) { 497f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer *gb = reinterpret_cast<GraphicBuffer *> 498f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (env->GetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer)); 499f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *buffer = gb; 500f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 501f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 502f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (fenceFd != NULL) { 503f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *fenceFd = reinterpret_cast<jint>(env->GetIntField( 504f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He thiz, gSurfaceImageClassInfo.mNativeFenceFd)); 505f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 506f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 507f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 508f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_setNativeContext(JNIEnv* env, jobject thiz, 509f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He sp<GraphicBuffer> buffer, int fenceFd) { 510f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s:", __FUNCTION__); 511f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer* p = NULL; 512f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, thiz, &p, /*fenceFd*/NULL); 513f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer != 0) { 514f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->incStrong((void*)Image_setNativeContext); 515f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 516f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (p) { 517f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He p->decStrong((void*)Image_setNativeContext); 518f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 519f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->SetLongField(thiz, gSurfaceImageClassInfo.mNativeBuffer, 520f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He reinterpret_cast<jlong>(buffer.get())); 521f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 522f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->SetIntField(thiz, gSurfaceImageClassInfo.mNativeFenceFd, reinterpret_cast<jint>(fenceFd)); 523f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 524f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 525f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_unlockIfLocked(JNIEnv* env, jobject thiz) { 526f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 527f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer* buffer; 528f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, thiz, &buffer, NULL); 529f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 530f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 531f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 532f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 533f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 534f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 535f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Is locked? 536f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bool isLocked = false; 537f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jobject planes = env->GetObjectField(thiz, gSurfaceImageClassInfo.mPlanes); 538f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He isLocked = (planes != NULL); 539f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (isLocked) { 540f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // no need to use fence here, as we it will be consumed by either concel or queue buffer. 541f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He status_t res = buffer->unlock(); 542f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 543f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "unlock buffer failed"); 544f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 545f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("Successfully unlocked the image"); 546f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 547f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 548f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 549f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic jint Image_getWidth(JNIEnv* env, jobject thiz) { 550f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 551f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer* buffer; 552f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, thiz, &buffer, NULL); 553f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 554f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 555f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 556f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return -1; 557f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 558f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 559f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return buffer->getWidth(); 560f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 561f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 562f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic jint Image_getHeight(JNIEnv* env, jobject thiz) { 563f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 564f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer* buffer; 565f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, thiz, &buffer, NULL); 566f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 567f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 568f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 569f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return -1; 570f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 571f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 572f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return buffer->getHeight(); 573f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 574f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 575f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// Some formats like JPEG defined with different values between android.graphics.ImageFormat and 576f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// graphics.h, need convert to the one defined in graphics.h here. 577f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic int Image_getPixelFormat(JNIEnv* env, int format) { 578f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int jpegFormat; 579f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jfieldID fid; 580f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 581f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s: format = 0x%x", __FUNCTION__, format); 582f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 583f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat"); 584f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(imageFormatClazz != NULL); 585f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 586f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I"); 587f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jpegFormat = env->GetStaticIntField(imageFormatClazz, fid); 588f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 589f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Translate the JPEG to BLOB for camera purpose. 590f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (format == jpegFormat) { 591f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He format = HAL_PIXEL_FORMAT_BLOB; 592f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 593f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 594f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return format; 595f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 596f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 597f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic jint Image_getFormat(JNIEnv* env, jobject thiz) { 598f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 599f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer* buffer; 600f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, thiz, &buffer, NULL); 601f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 602f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 603f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 604f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return 0; 605f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 606f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 607f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return Image_getPixelFormat(env, buffer->getPixelFormat()); 608f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 609f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 610f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_setFenceFd(JNIEnv* env, jobject thiz, int fenceFd) { 611f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s:", __FUNCTION__); 612f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->SetIntField(thiz, gSurfaceImageClassInfo.mNativeFenceFd, reinterpret_cast<jint>(fenceFd)); 613f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 614f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 615f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_getLockedImage(JNIEnv* env, jobject thiz, LockedImage *image) { 616f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 617f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He GraphicBuffer* buffer; 618f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int fenceFd = -1; 619f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getNativeContext(env, thiz, &buffer, &fenceFd); 620f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (buffer == NULL) { 621f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 622f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Image is not initialized"); 623f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 624f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 625f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 626f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He void* pData = NULL; 627f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He android_ycbcr ycbcr = android_ycbcr(); 628f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He status_t res; 629f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int format = Image_getFormat(env, thiz); 630f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int flexFormat = format; 631f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (isPossiblyYUV(format)) { 632f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // ImageWriter doesn't use crop by itself, app sets it, use the no crop version. 633f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = buffer->lockAsyncYCbCr(GRALLOC_USAGE_SW_WRITE_OFTEN, &ycbcr, fenceFd); 634f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Clear the fenceFd as it is already consumed by lock call. 635f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_setFenceFd(env, thiz, /*fenceFd*/-1); 636f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 637f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "lockAsyncYCbCr failed for YUV buffer"); 638f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 639f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 640f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = ycbcr.y; 641f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He flexFormat = HAL_PIXEL_FORMAT_YCbCr_420_888; 642f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 643f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 644f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // lockAsyncYCbCr for YUV is unsuccessful. 645f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (pData == NULL) { 646f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He res = buffer->lockAsync(GRALLOC_USAGE_SW_WRITE_OFTEN, &pData, fenceFd); 647f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (res != OK) { 648f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "lockAsync failed"); 649f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return; 650f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 651f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 652f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 653f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->data = reinterpret_cast<uint8_t*>(pData); 654f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->width = buffer->getWidth(); 655f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->height = buffer->getHeight(); 656f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->format = format; 657f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->flexFormat = flexFormat; 658f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->stride = (ycbcr.y != NULL) ? static_cast<uint32_t>(ycbcr.ystride) : buffer->getStride(); 659f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 660f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->dataCb = reinterpret_cast<uint8_t*>(ycbcr.cb); 661f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->dataCr = reinterpret_cast<uint8_t*>(ycbcr.cr); 662f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->chromaStride = static_cast<uint32_t>(ycbcr.cstride); 663f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He image->chromaStep = static_cast<uint32_t>(ycbcr.chroma_step); 664f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("Successfully locked the image"); 665f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // crop, transform, scalingMode, timestamp, and frameNumber should be set by producer, 666f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // and we don't set them here. 667f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 668f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 669f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic bool usingRGBAToJpegOverride(int32_t bufferFormat, int32_t writerCtxFormat) { 670f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return writerCtxFormat == HAL_PIXEL_FORMAT_BLOB && bufferFormat == HAL_PIXEL_FORMAT_RGBA_8888; 671f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 672f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 673f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic int32_t applyFormatOverrides(int32_t bufferFormat, int32_t writerCtxFormat) 674f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He{ 675f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Using HAL_PIXEL_FORMAT_RGBA_8888 gralloc buffers containing JPEGs to get around SW 676f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // write limitations for some platforms (b/17379185). 677f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (usingRGBAToJpegOverride(bufferFormat, writerCtxFormat)) { 678f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return HAL_PIXEL_FORMAT_BLOB; 679f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 680f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return bufferFormat; 681f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 682f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 683f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic uint32_t Image_getJpegSize(LockedImage* buffer, bool usingRGBAOverride) { 684f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 685f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 686f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint32_t size = 0; 687f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint32_t width = buffer->width; 688f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint8_t* jpegBuffer = buffer->data; 689f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 690f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (usingRGBAOverride) { 691f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He width = (buffer->width + buffer->stride * (buffer->height - 1)) * 4; 692f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 693f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 694f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // First check for JPEG transport header at the end of the buffer 695f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob)); 696f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header); 697f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) { 698f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He size = blob->jpeg_size; 699f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s: Jpeg size = %d", __FUNCTION__, size); 700f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 701f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 702f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // failed to find size, default to whole buffer 703f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (size == 0) { 704f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /* 705f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * This is a problem because not including the JPEG header 706f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * means that in certain rare situations a regular JPEG blob 707f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * will be misidentified as having a header, in which case 708f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He * we will get a garbage size value. 709f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He */ 710f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGW("%s: No JPEG header detected, defaulting to size=width=%d", 711f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He __FUNCTION__, width); 712f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He size = width; 713f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 714f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 715f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return size; 716f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 717f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 718f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic void Image_getLockedImageInfo(JNIEnv* env, LockedImage* buffer, int idx, 719f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int32_t writerFormat, uint8_t **base, uint32_t *size, int *pixelStride, int *rowStride) { 720f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s", __FUNCTION__); 721f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!"); 722f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(base != NULL, "base is NULL!!!"); 723f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(size != NULL, "size is NULL!!!"); 724f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(pixelStride != NULL, "pixelStride is NULL!!!"); 725f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(rowStride != NULL, "rowStride is NULL!!!"); 726f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT((idx < IMAGE_WRITER_MAX_NUM_PLANES) && (idx >= 0)); 727f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 728f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s: buffer: %p", __FUNCTION__, buffer); 729f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 730f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint32_t dataSize, ySize, cSize, cStride; 731f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint32_t pStride = 0, rStride = 0; 732f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint8_t *cb, *cr; 733f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint8_t *pData = NULL; 734f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int bytesPerPixel = 0; 735f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 736f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = ySize = cSize = cStride = 0; 737f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int32_t fmt = buffer->flexFormat; 738f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 739f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bool usingRGBAOverride = usingRGBAToJpegOverride(fmt, writerFormat); 740f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He fmt = applyFormatOverrides(fmt, writerFormat); 741f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He switch (fmt) { 742f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YCbCr_420_888: 743f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = 744f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (idx == 0) ? 745f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->data : 746f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (idx == 1) ? 747f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->dataCb : 748f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->dataCr; 749f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // only map until last pixel 750f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (idx == 0) { 751f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = 1; 752f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride; 753f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * (buffer->height - 1) + buffer->width; 754f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } else { 755f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = buffer->chromaStep; 756f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->chromaStride; 757f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->chromaStride * (buffer->height / 2 - 1) + 758f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->chromaStep * (buffer->width / 2 - 1) + 1; 759f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 760f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 761f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // NV21 762f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YCrCb_420_SP: 763f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cr = buffer->data + (buffer->stride * buffer->height); 764f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cb = cr + 1; 765f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // only map until last pixel 766f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ySize = buffer->width * (buffer->height - 1) + buffer->width; 767f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cSize = buffer->width * (buffer->height / 2 - 1) + buffer->width - 1; 768f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 769f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = 770f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (idx == 0) ? 771f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->data : 772f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (idx == 1) ? 773f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cb: 774f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cr; 775f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 776f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = (idx == 0) ? ySize : cSize; 777f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = (idx == 0) ? 1 : 2; 778f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->width; 779f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 780f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YV12: 781f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Y and C stride need to be 16 pixel aligned. 782f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(buffer->stride % 16, 783f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Stride is not 16 pixel aligned %d", buffer->stride); 784f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 785f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ySize = buffer->stride * buffer->height; 786f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cStride = ALIGN(buffer->stride / 2, 16); 787f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cr = buffer->data + ySize; 788f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cSize = cStride * buffer->height / 2; 789f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cb = cr + cSize; 790f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 791f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = 792f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (idx == 0) ? 793f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->data : 794f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (idx == 1) ? 795f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cb : 796f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He cr; 797f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = (idx == 0) ? ySize : cSize; 798f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = 1; 799f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16); 800f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 801f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_Y8: 802f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane, 8bpp. 803f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 804f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 805f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 806f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height; 807f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = 1; 808f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride; 809f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 810f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_Y16: 811f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bytesPerPixel = 2; 812f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane, 16bpp, strides are specified in pixels, not in bytes 813f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 814f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 815f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 816f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height * bytesPerPixel; 817f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = bytesPerPixel; 818f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride * 2; 819f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 820f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_BLOB: 821f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Used for JPEG data, height must be 1, width == size, single plane. 822f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 823f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height); 824f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 825f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 826f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = Image_getJpegSize(buffer, usingRGBAOverride); 827f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = bytesPerPixel; 828f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rowStride = 0; 829f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 830f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RAW16: 831f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane 16bpp bayer data. 832f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bytesPerPixel = 2; 833f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 834f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 835f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height * bytesPerPixel; 836f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = bytesPerPixel; 837f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride * 2; 838f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 839f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RAW10: 840f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane 10bpp bayer data. 841f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 842f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(buffer->width % 4, 843f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Width is not multiple of 4 %d", buffer->width); 844f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(buffer->height % 2, 845f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Height is not even %d", buffer->height); 846f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LOG_ALWAYS_FATAL_IF(buffer->stride < (buffer->width * 10 / 8), 847f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "stride (%d) should be at least %d", 848f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He buffer->stride, buffer->width * 10 / 8); 849f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 850f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height; 851f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = 0; 852f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride; 853f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 854f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGBA_8888: 855f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGBX_8888: 856f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane, 32bpp. 857f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bytesPerPixel = 4; 858f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 859f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 860f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height * bytesPerPixel; 861f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = bytesPerPixel; 862f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride * 4; 863f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 864f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGB_565: 865f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane, 16bpp. 866f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bytesPerPixel = 2; 867f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 868f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 869f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height * bytesPerPixel; 870f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = bytesPerPixel; 871f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride * 2; 872f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 873f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGB_888: 874f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Single plane, 24bpp. 875f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He bytesPerPixel = 3; 876f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOG_ASSERT(idx == 0, "Wrong index: %d", idx); 877f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pData = buffer->data; 878f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He dataSize = buffer->stride * buffer->height * bytesPerPixel; 879f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He pStride = bytesPerPixel; 880f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He rStride = buffer->stride * 3; 881f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 882f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He default: 883f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException", 884f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Pixel format: 0x%x is unsupported", fmt); 885f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He break; 886f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 887f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 888f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *base = pData; 889f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *size = dataSize; 890f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *pixelStride = pStride; 891f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He *rowStride = rStride; 892f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 893f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 894f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic jobjectArray Image_createSurfacePlanes(JNIEnv* env, jobject thiz, 895f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int numPlanes, int writerFormat) { 896f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He ALOGV("%s: create SurfacePlane array with size %d", __FUNCTION__, numPlanes); 897f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int rowStride, pixelStride; 898f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint8_t *pData; 899f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He uint32_t dataSize; 900f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jobject byteBuffer; 901f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 902f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int format = Image_getFormat(env, thiz); 903f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (!isWritable(format) && numPlanes > 0) { 904f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He String8 msg; 905f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He msg.appendFormat("Format 0x%x is opaque, thus not writable, the number of planes (%d)" 906f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He " must be 0", format, numPlanes); 907f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalArgumentException", msg.string()); 908f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return NULL; 909f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 910f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 911f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jobjectArray surfacePlanes = env->NewObjectArray(numPlanes, gSurfacePlaneClassInfo.clazz, 912f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He /*initial_element*/NULL); 913f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if (surfacePlanes == NULL) { 914f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowRuntimeException(env, "Failed to create SurfacePlane arrays," 915f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He " probably out of memory"); 916f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return NULL; 917f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 918f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 919f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Buildup buffer info: rowStride, pixelStride and byteBuffers. 920f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He LockedImage lockedImg = LockedImage(); 921f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getLockedImage(env, thiz, &lockedImg); 922f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 923f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Create all SurfacePlanes 924f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He writerFormat = Image_getPixelFormat(env, writerFormat); 925f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He for (int i = 0; i < numPlanes; i++) { 926f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He Image_getLockedImageInfo(env, &lockedImg, i, writerFormat, 927f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He &pData, &dataSize, &pixelStride, &rowStride); 928f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He byteBuffer = env->NewDirectByteBuffer(pData, dataSize); 929f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) { 930f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jniThrowException(env, "java/lang/IllegalStateException", 931f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "Failed to allocate ByteBuffer"); 932f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return NULL; 933f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 934f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 935f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Finally, create this SurfacePlane. 936f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He jobject surfacePlane = env->NewObject(gSurfacePlaneClassInfo.clazz, 937f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He gSurfacePlaneClassInfo.ctor, thiz, rowStride, pixelStride, byteBuffer); 938f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He env->SetObjectArrayElement(surfacePlanes, i, surfacePlane); 939f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 940f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 941f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return surfacePlanes; 942f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 943f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 944f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// -------------------------------Private convenience methods-------------------- 945f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 946f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// Check if buffer with this format is writable. Generally speaking, the opaque formats 947f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// like IMPLEMENTATION_DEFINED is not writable, as the actual buffer formats and layouts 948f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// are unknown to frameworks. 949f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic bool isWritable(int format) { 950f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He // Assume all other formats are writable. 951f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return !(format == HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED || 952f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He format == HAL_PIXEL_FORMAT_RAW_OPAQUE); 953f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 954f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 955f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic bool isPossiblyYUV(PixelFormat format) { 956f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He switch (static_cast<int>(format)) { 957f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGBA_8888: 958f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGBX_8888: 959f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGB_888: 960f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RGB_565: 961f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_BGRA_8888: 962f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_Y8: 963f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_Y16: 964f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RAW16: 965f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RAW10: 966f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_RAW_OPAQUE: 967f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_BLOB: 968f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED: 969f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return false; 970f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 971f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YV12: 972f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YCbCr_420_888: 973f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YCbCr_422_SP: 974f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YCrCb_420_SP: 975f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He case HAL_PIXEL_FORMAT_YCbCr_422_I: 976f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He default: 977f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return true; 978f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He } 979f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 980f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 981f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} // extern "C" 982f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 983f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He// ---------------------------------------------------------------------------- 984f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 985f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic JNINativeMethod gImageWriterMethods[] = { 986f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeClassInit", "()V", (void*)ImageWriter_classInit }, 987f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeInit", "(Ljava/lang/Object;Landroid/view/Surface;I)J", 988f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (void*)ImageWriter_init }, 989f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeClose", "(J)V", (void*)ImageWriter_close }, 990f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeAttachImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_attachImage }, 991f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeDequeueInputImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_dequeueImage }, 992f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeQueueInputImage", "(JLandroid/media/Image;JIIII)V", (void*)ImageWriter_queueImage }, 993f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"cancelImage", "(JLandroid/media/Image;)V", (void*)ImageWriter_cancelImage }, 994f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He}; 995f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 996f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Hestatic JNINativeMethod gImageMethods[] = { 997f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeCreatePlanes", "(II)[Landroid/media/ImageWriter$WriterSurfaceImage$SurfacePlane;", 998f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He (void*)Image_createSurfacePlanes }, 999f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeGetWidth", "()I", (void*)Image_getWidth }, 1000f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeGetHeight", "()I", (void*)Image_getHeight }, 1001f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He {"nativeGetFormat", "()I", (void*)Image_getFormat }, 1002f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He}; 1003f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 1004f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun Heint register_android_media_ImageWriter(JNIEnv *env) { 1005f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 1006f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int ret1 = AndroidRuntime::registerNativeMethods(env, 1007f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "android/media/ImageWriter", gImageWriterMethods, NELEM(gImageWriterMethods)); 1008f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 1009f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He int ret2 = AndroidRuntime::registerNativeMethods(env, 1010f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He "android/media/ImageWriter$WriterSurfaceImage", gImageMethods, NELEM(gImageMethods)); 1011f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 1012f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He return (ret1 || ret2); 1013f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He} 1014f6a09e510649ae4701bb5ad4c40d102d59a5608cZhijun He 1015