summaryrefslogtreecommitdiffstats
path: root/media/jni
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2013-11-22 11:18:57 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2013-11-22 11:18:57 -0800
commitdbccd44a638ae8705a5b14bff8b2dd74abc26045 (patch)
tree14bfabaf3f3c7be86dfc064e919e00433a0cf2bb /media/jni
parentecfae4f899873f224e1aeed076dc8a41f8884487 (diff)
parentb873a17ce7be0a9771c24999adca6964431728f6 (diff)
downloadframeworks_base-dbccd44a638ae8705a5b14bff8b2dd74abc26045.zip
frameworks_base-dbccd44a638ae8705a5b14bff8b2dd74abc26045.tar.gz
frameworks_base-dbccd44a638ae8705a5b14bff8b2dd74abc26045.tar.bz2
Merge commit 'b873a17ce7be0a9771c24999adca6964431728f6' into HEAD
Change-Id: I938755073e70602cc8f51ce9bd420fdcf870cecd
Diffstat (limited to 'media/jni')
-rw-r--r--media/jni/Android.mk3
-rw-r--r--media/jni/android_media_ImageReader.cpp879
-rw-r--r--media/jni/android_media_MediaCodec.cpp141
-rw-r--r--media/jni/android_media_MediaCodec.h2
-rw-r--r--media/jni/android_media_MediaCodecList.cpp8
-rw-r--r--media/jni/android_media_MediaDrm.cpp35
-rw-r--r--media/jni/android_media_MediaDrm.h2
-rw-r--r--media/jni/android_media_MediaExtractor.cpp1
-rw-r--r--media/jni/android_media_MediaMuxer.cpp15
-rw-r--r--media/jni/android_media_MediaPlayer.cpp51
-rw-r--r--media/jni/android_media_MediaScanner.cpp1
-rw-r--r--media/jni/android_media_Utils.cpp97
-rw-r--r--media/jni/android_mtp_MtpDatabase.cpp1
-rw-r--r--media/jni/android_mtp_MtpDevice.cpp1
-rw-r--r--media/jni/audioeffect/android_media_Visualizer.cpp72
-rw-r--r--media/jni/mediaeditor/VideoEditorClasses.cpp1
-rw-r--r--media/jni/mediaeditor/VideoEditorJava.cpp2
-rw-r--r--media/jni/mediaeditor/VideoEditorLogging.h10
-rw-r--r--media/jni/mediaeditor/VideoEditorOsal.cpp2
-rw-r--r--media/jni/mediaeditor/VideoEditorPropertiesMain.cpp2
-rw-r--r--media/jni/soundpool/Android.mk2
-rw-r--r--media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp (renamed from media/jni/soundpool/android_media_SoundPool.cpp)96
22 files changed, 1248 insertions, 176 deletions
diff --git a/media/jni/Android.mk b/media/jni/Android.mk
index 416a2a1..63a61e2 100644
--- a/media/jni/Android.mk
+++ b/media/jni/Android.mk
@@ -2,6 +2,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ android_media_ImageReader.cpp \
android_media_MediaCrypto.cpp \
android_media_MediaCodec.cpp \
android_media_MediaCodecList.cpp \
@@ -56,6 +57,8 @@ LOCAL_C_INCLUDES += \
frameworks/av/media/libstagefright/codecs/amrnb/common/include \
frameworks/av/media/mtp \
frameworks/native/include/media/openmax \
+ $(call include-path-for, libhardware)/hardware \
+ system/media/camera/include \
$(PV_INCLUDES) \
$(JNI_H_INCLUDE) \
$(call include-path-for, corecg graphics)
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
new file mode 100644
index 0000000..0030dbd
--- /dev/null
+++ b/media/jni/android_media_ImageReader.cpp
@@ -0,0 +1,879 @@
+/*
+ * Copyright 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "ImageReader_JNI"
+#include <utils/Log.h>
+#include <utils/misc.h>
+#include <utils/List.h>
+#include <utils/String8.h>
+
+#include <cstdio>
+
+#include <gui/CpuConsumer.h>
+#include <gui/Surface.h>
+#include <camera3.h>
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+
+#include <jni.h>
+#include <JNIHelp.h>
+
+#define ALIGN(x, mask) ( ((x) + (mask) - 1) & ~((mask) - 1) )
+
+#define ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID "mNativeContext"
+#define ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID "mLockedBuffer"
+#define ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID "mTimestamp"
+
+// ----------------------------------------------------------------------------
+
+using namespace android;
+
+enum {
+ IMAGE_READER_MAX_NUM_PLANES = 3,
+};
+
+enum {
+ ACQUIRE_SUCCESS = 0,
+ ACQUIRE_NO_BUFFERS = 1,
+ ACQUIRE_MAX_IMAGES = 2,
+};
+
+static struct {
+ jfieldID mNativeContext;
+ jmethodID postEventFromNative;
+} gImageReaderClassInfo;
+
+static struct {
+ jfieldID mLockedBuffer;
+ jfieldID mTimestamp;
+} gSurfaceImageClassInfo;
+
+static struct {
+ jclass clazz;
+ jmethodID ctor;
+} gSurfacePlaneClassInfo;
+
+// ----------------------------------------------------------------------------
+
+class JNIImageReaderContext : public CpuConsumer::FrameAvailableListener
+{
+public:
+ JNIImageReaderContext(JNIEnv* env, jobject weakThiz, jclass clazz, int maxImages);
+
+ virtual ~JNIImageReaderContext();
+
+ virtual void onFrameAvailable();
+
+ CpuConsumer::LockedBuffer* getLockedBuffer();
+
+ void returnLockedBuffer(CpuConsumer::LockedBuffer* buffer);
+
+ void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; }
+ CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
+
+ void setBufferQueue(const sp<BufferQueue>& bq) { mBufferQueue = bq; }
+ BufferQueue* getBufferQueue() { return mBufferQueue.get(); }
+
+ void setBufferFormat(int format) { mFormat = format; }
+ int getBufferFormat() { return mFormat; }
+
+ void setBufferWidth(int width) { mWidth = width; }
+ int getBufferWidth() { return mWidth; }
+
+ void setBufferHeight(int height) { mHeight = height; }
+ int getBufferHeight() { return mHeight; }
+
+private:
+ static JNIEnv* getJNIEnv(bool* needsDetach);
+ static void detachJNI();
+
+ List<CpuConsumer::LockedBuffer*> mBuffers;
+ sp<CpuConsumer> mConsumer;
+ sp<BufferQueue> mBufferQueue;
+ jobject mWeakThiz;
+ jclass mClazz;
+ int mFormat;
+ int mWidth;
+ int mHeight;
+};
+
+JNIImageReaderContext::JNIImageReaderContext(JNIEnv* env,
+ jobject weakThiz, jclass clazz, int maxImages) :
+ mWeakThiz(env->NewGlobalRef(weakThiz)),
+ mClazz((jclass)env->NewGlobalRef(clazz)) {
+ for (int i = 0; i < maxImages; i++) {
+ CpuConsumer::LockedBuffer *buffer = new CpuConsumer::LockedBuffer;
+ mBuffers.push_back(buffer);
+ }
+}
+
+JNIEnv* JNIImageReaderContext::getJNIEnv(bool* needsDetach) {
+ LOG_ALWAYS_FATAL_IF(needsDetach == NULL, "needsDetach is null!!!");
+ *needsDetach = false;
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+ if (env == NULL) {
+ JavaVMAttachArgs args = {JNI_VERSION_1_4, NULL, NULL};
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->AttachCurrentThread(&env, (void*) &args);
+ if (result != JNI_OK) {
+ ALOGE("thread attach failed: %#x", result);
+ return NULL;
+ }
+ *needsDetach = true;
+ }
+ return env;
+}
+
+void JNIImageReaderContext::detachJNI() {
+ JavaVM* vm = AndroidRuntime::getJavaVM();
+ int result = vm->DetachCurrentThread();
+ if (result != JNI_OK) {
+ ALOGE("thread detach failed: %#x", result);
+ }
+}
+
+CpuConsumer::LockedBuffer* JNIImageReaderContext::getLockedBuffer() {
+ if (mBuffers.empty()) {
+ return NULL;
+ }
+ // Return a LockedBuffer pointer and remove it from the list
+ List<CpuConsumer::LockedBuffer*>::iterator it = mBuffers.begin();
+ CpuConsumer::LockedBuffer* buffer = *it;
+ mBuffers.erase(it);
+ return buffer;
+}
+
+void JNIImageReaderContext::returnLockedBuffer(CpuConsumer::LockedBuffer* buffer) {
+ mBuffers.push_back(buffer);
+}
+
+JNIImageReaderContext::~JNIImageReaderContext() {
+ bool needsDetach = false;
+ JNIEnv* env = getJNIEnv(&needsDetach);
+ if (env != NULL) {
+ env->DeleteGlobalRef(mWeakThiz);
+ env->DeleteGlobalRef(mClazz);
+ } else {
+ ALOGW("leaking JNI object references");
+ }
+ if (needsDetach) {
+ detachJNI();
+ }
+
+ // Delete LockedBuffers
+ for (List<CpuConsumer::LockedBuffer *>::iterator it = mBuffers.begin();
+ it != mBuffers.end(); it++) {
+ delete *it;
+ }
+ mBuffers.clear();
+ mConsumer.clear();
+}
+
+void JNIImageReaderContext::onFrameAvailable()
+{
+ ALOGV("%s: frame available", __FUNCTION__);
+ bool needsDetach = false;
+ JNIEnv* env = getJNIEnv(&needsDetach);
+ if (env != NULL) {
+ env->CallStaticVoidMethod(mClazz, gImageReaderClassInfo.postEventFromNative, mWeakThiz);
+ } else {
+ ALOGW("onFrameAvailable event will not posted");
+ }
+ if (needsDetach) {
+ detachJNI();
+ }
+}
+
+// ----------------------------------------------------------------------------
+
+extern "C" {
+
+static JNIImageReaderContext* ImageReader_getContext(JNIEnv* env, jobject thiz)
+{
+ JNIImageReaderContext *ctx;
+ ctx = reinterpret_cast<JNIImageReaderContext *>
+ (env->GetLongField(thiz, gImageReaderClassInfo.mNativeContext));
+ return ctx;
+}
+
+static CpuConsumer* ImageReader_getCpuConsumer(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+ return NULL;
+ }
+ return ctx->getCpuConsumer();
+}
+
+static BufferQueue* ImageReader_getBufferQueue(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+ return NULL;
+ }
+ return ctx->getBufferQueue();
+}
+
+static void ImageReader_setNativeContext(JNIEnv* env,
+ jobject thiz, sp<JNIImageReaderContext> ctx)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* const p = ImageReader_getContext(env, thiz);
+ if (ctx != 0) {
+ ctx->incStrong((void*)ImageReader_setNativeContext);
+ }
+ if (p) {
+ p->decStrong((void*)ImageReader_setNativeContext);
+ }
+ env->SetLongField(thiz, gImageReaderClassInfo.mNativeContext,
+ reinterpret_cast<jlong>(ctx.get()));
+}
+
+static CpuConsumer::LockedBuffer* Image_getLockedBuffer(JNIEnv* env, jobject image)
+{
+ return reinterpret_cast<CpuConsumer::LockedBuffer*>(
+ env->GetLongField(image, gSurfaceImageClassInfo.mLockedBuffer));
+}
+
+static void Image_setBuffer(JNIEnv* env, jobject thiz,
+ const CpuConsumer::LockedBuffer* buffer)
+{
+ env->SetLongField(thiz, gSurfaceImageClassInfo.mLockedBuffer, reinterpret_cast<jlong>(buffer));
+}
+
+// Some formats like JPEG defined with different values between android.graphics.ImageFormat and
+// graphics.h, need convert to the one defined in graphics.h here.
+static int Image_getPixelFormat(JNIEnv* env, int format)
+{
+ int jpegFormat, rawSensorFormat;
+ jfieldID fid;
+
+ ALOGV("%s: format = 0x%x", __FUNCTION__, format);
+
+ jclass imageFormatClazz = env->FindClass("android/graphics/ImageFormat");
+ ALOG_ASSERT(imageFormatClazz != NULL);
+
+ fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
+ jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
+ fid = env->GetStaticFieldID(imageFormatClazz, "RAW_SENSOR", "I");
+ rawSensorFormat = env->GetStaticIntField(imageFormatClazz, fid);
+
+ // Translate the JPEG to BLOB for camera purpose, an add more if more mismatch is found.
+ if (format == jpegFormat) {
+ format = HAL_PIXEL_FORMAT_BLOB;
+ }
+ // Same thing for RAW_SENSOR format
+ if (format == rawSensorFormat) {
+ format = HAL_PIXEL_FORMAT_RAW_SENSOR;
+ }
+
+ return format;
+}
+
+static uint32_t Image_getJpegSize(CpuConsumer::LockedBuffer* buffer)
+{
+ ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
+ uint32_t size = 0;
+ uint32_t width = buffer->width;
+ uint8_t* jpegBuffer = buffer->data;
+
+ // First check for JPEG transport header at the end of the buffer
+ uint8_t* header = jpegBuffer + (width - sizeof(struct camera3_jpeg_blob));
+ struct camera3_jpeg_blob *blob = (struct camera3_jpeg_blob*)(header);
+ if (blob->jpeg_blob_id == CAMERA3_JPEG_BLOB_ID) {
+ size = blob->jpeg_size;
+ ALOGV("%s: Jpeg size = %d", __FUNCTION__, size);
+ }
+
+ // failed to find size, default to whole buffer
+ if (size == 0) {
+ size = width;
+ }
+
+ return size;
+}
+
+static void Image_getLockedBufferInfo(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx,
+ uint8_t **base, uint32_t *size)
+{
+ ALOG_ASSERT(buffer != NULL, "Input buffer is NULL!!!");
+ ALOG_ASSERT(base != NULL, "base is NULL!!!");
+ ALOG_ASSERT(size != NULL, "size is NULL!!!");
+ ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
+
+ ALOGV("%s: buffer: %p", __FUNCTION__, buffer);
+
+ uint32_t dataSize, ySize, cSize, cStride;
+ uint8_t *cb, *cr;
+ uint8_t *pData = NULL;
+ int bytesPerPixel = 0;
+
+ dataSize = ySize = cSize = cStride = 0;
+ int32_t fmt = buffer->format;
+ switch (fmt) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ pData =
+ (idx == 0) ?
+ buffer->data :
+ (idx == 1) ?
+ buffer->dataCb :
+ buffer->dataCr;
+ if (idx == 0) {
+ dataSize = buffer->stride * buffer->height;
+ } else {
+ dataSize = buffer->chromaStride * buffer->height / 2;
+ }
+ break;
+ // NV21
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ cr = buffer->data + (buffer->stride * buffer->height);
+ cb = cr + 1;
+ ySize = buffer->width * buffer->height;
+ cSize = buffer->width * buffer->height / 2;
+
+ pData =
+ (idx == 0) ?
+ buffer->data :
+ (idx == 1) ?
+ cb:
+ cr;
+
+ dataSize = (idx == 0) ? ySize : cSize;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ // Y and C stride need to be 16 pixel aligned.
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+
+ ySize = buffer->stride * buffer->height;
+ cStride = ALIGN(buffer->stride / 2, 16);
+ cr = buffer->data + ySize;
+ cSize = cStride * buffer->height / 2;
+ cb = cr + cSize;
+
+ pData =
+ (idx == 0) ?
+ buffer->data :
+ (idx == 1) ?
+ cb :
+ cr;
+ dataSize = (idx == 0) ? ySize : cSize;
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ // Single plane, 8bpp.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height;
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ // Single plane, 16bpp, strides are specified in pixels, not in bytes
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height * 2;
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Used for JPEG data, height must be 1, width == size, single plane.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ ALOG_ASSERT(buffer->height == 1, "JPEG should has height value %d", buffer->height);
+
+ pData = buffer->data;
+ dataSize = Image_getJpegSize(buffer);
+ break;
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ // Single plane 16bpp bayer data.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pData = buffer->data;
+ dataSize = buffer->width * 2 * buffer->height;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ // Single plane, 32bpp.
+ bytesPerPixel = 4;
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height * bytesPerPixel;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ // Single plane, 16bpp.
+ bytesPerPixel = 2;
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height * bytesPerPixel;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ // Single plane, 24bpp.
+ bytesPerPixel = 3;
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pData = buffer->data;
+ dataSize = buffer->stride * buffer->height * bytesPerPixel;
+ break;
+ default:
+ jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+ "Pixel format: 0x%x is unsupported", fmt);
+ break;
+ }
+
+ *base = pData;
+ *size = dataSize;
+}
+
+static jint Image_imageGetPixelStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
+{
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+ ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0), "Index is out of range:%d", idx);
+
+ int pixelStride = 0;
+ ALOG_ASSERT(buffer != NULL, "buffer is NULL");
+
+ int32_t fmt = buffer->format;
+ switch (fmt) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ pixelStride = (idx == 0) ? 1 : buffer->chromaStep;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ pixelStride = (idx == 0) ? 1 : 2;
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ // Single plane 8bpp data.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ pixelStride = 1;
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Used for JPEG data, single plane, row and pixel strides are 0
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride = 0;
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ case HAL_PIXEL_FORMAT_RGB_565:
+ // Single plane 16bpp data.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride = 2;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride = 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ // Single plane, 24bpp.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ pixelStride = 3;
+ break;
+ default:
+ jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+ "Pixel format: 0x%x is unsupported", fmt);
+ break;
+ }
+
+ return pixelStride;
+}
+
+static jint Image_imageGetRowStride(JNIEnv* env, CpuConsumer::LockedBuffer* buffer, int idx)
+{
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+ ALOG_ASSERT((idx < IMAGE_READER_MAX_NUM_PLANES) && (idx >= 0));
+
+ int rowStride = 0;
+ ALOG_ASSERT(buffer != NULL, "buffer is NULL");
+
+ int32_t fmt = buffer->format;
+
+ switch (fmt) {
+ case HAL_PIXEL_FORMAT_YCbCr_420_888:
+ rowStride = (idx == 0) ? buffer->stride : buffer->chromaStride;
+ break;
+ case HAL_PIXEL_FORMAT_YCrCb_420_SP:
+ rowStride = buffer->width;
+ break;
+ case HAL_PIXEL_FORMAT_YV12:
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+ rowStride = (idx == 0) ? buffer->stride : ALIGN(buffer->stride / 2, 16);
+ break;
+ case HAL_PIXEL_FORMAT_BLOB:
+ // Used for JPEG data, single plane, row and pixel strides are 0
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ rowStride = 0;
+ break;
+ case HAL_PIXEL_FORMAT_Y8:
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+ rowStride = buffer->stride;
+ break;
+ case HAL_PIXEL_FORMAT_Y16:
+ case HAL_PIXEL_FORMAT_RAW_SENSOR:
+ // In native side, strides are specified in pixels, not in bytes.
+ // Single plane 16bpp bayer data. even width/height,
+ // row stride multiple of 16 pixels (32 bytes)
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ LOG_ALWAYS_FATAL_IF(buffer->stride % 16,
+ "Stride is not 16 pixel aligned %d", buffer->stride);
+ rowStride = buffer->stride * 2;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_565:
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ rowStride = buffer->stride * 2;
+ break;
+ case HAL_PIXEL_FORMAT_RGBA_8888:
+ case HAL_PIXEL_FORMAT_RGBX_8888:
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ rowStride = buffer->stride * 4;
+ break;
+ case HAL_PIXEL_FORMAT_RGB_888:
+ // Single plane, 24bpp.
+ ALOG_ASSERT(idx == 0, "Wrong index: %d", idx);
+ rowStride = buffer->stride * 3;
+ break;
+ default:
+ ALOGE("%s Pixel format: 0x%x is unsupported", __FUNCTION__, fmt);
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ "unsupported buffer format");
+ break;
+ }
+
+ return rowStride;
+}
+
+// ----------------------------------------------------------------------------
+
+static void ImageReader_classInit(JNIEnv* env, jclass clazz)
+{
+ ALOGV("%s:", __FUNCTION__);
+
+ jclass imageClazz = env->FindClass("android/media/ImageReader$SurfaceImage");
+ LOG_ALWAYS_FATAL_IF(imageClazz == NULL,
+ "can't find android/graphics/ImageReader$SurfaceImage");
+ gSurfaceImageClassInfo.mLockedBuffer = env->GetFieldID(
+ imageClazz, ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mLockedBuffer == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_SURFACEIMAGE_BUFFER_JNI_ID);
+
+ gSurfaceImageClassInfo.mTimestamp = env->GetFieldID(
+ imageClazz, ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(gSurfaceImageClassInfo.mTimestamp == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_SURFACEIMAGE_TS_JNI_ID);
+
+ gImageReaderClassInfo.mNativeContext = env->GetFieldID(
+ clazz, ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID, "J");
+ LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.mNativeContext == NULL,
+ "can't find android/graphics/ImageReader.%s",
+ ANDROID_MEDIA_IMAGEREADER_CTX_JNI_ID);
+
+ gImageReaderClassInfo.postEventFromNative = env->GetStaticMethodID(
+ clazz, "postEventFromNative", "(Ljava/lang/Object;)V");
+ LOG_ALWAYS_FATAL_IF(gImageReaderClassInfo.postEventFromNative == NULL,
+ "can't find android/graphics/ImageReader.postEventFromNative");
+
+ jclass planeClazz = env->FindClass("android/media/ImageReader$SurfaceImage$SurfacePlane");
+ LOG_ALWAYS_FATAL_IF(planeClazz == NULL, "Can not find SurfacePlane class");
+ // FindClass only gives a local reference of jclass object.
+ gSurfacePlaneClassInfo.clazz = (jclass) env->NewGlobalRef(planeClazz);
+ gSurfacePlaneClassInfo.ctor = env->GetMethodID(gSurfacePlaneClassInfo.clazz, "<init>",
+ "(Landroid/media/ImageReader$SurfaceImage;III)V");
+ LOG_ALWAYS_FATAL_IF(gSurfacePlaneClassInfo.ctor == NULL,
+ "Can not find SurfacePlane constructor");
+}
+
+static void ImageReader_init(JNIEnv* env, jobject thiz, jobject weakThiz,
+ jint width, jint height, jint format, jint maxImages)
+{
+ status_t res;
+ int nativeFormat;
+
+ ALOGV("%s: width:%d, height: %d, format: 0x%x, maxImages:%d",
+ __FUNCTION__, width, height, format, maxImages);
+
+ nativeFormat = Image_getPixelFormat(env, format);
+
+ sp<BufferQueue> bq = new BufferQueue();
+ sp<CpuConsumer> consumer = new CpuConsumer(bq, maxImages,
+ /*controlledByApp*/true);
+ // TODO: throw dvm exOutOfMemoryError?
+ if (consumer == NULL) {
+ jniThrowRuntimeException(env, "Failed to allocate native CpuConsumer");
+ return;
+ }
+
+ jclass clazz = env->GetObjectClass(thiz);
+ if (clazz == NULL) {
+ jniThrowRuntimeException(env, "Can't find android/graphics/ImageReader");
+ return;
+ }
+ sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
+ ctx->setCpuConsumer(consumer);
+ ctx->setBufferQueue(bq);
+ consumer->setFrameAvailableListener(ctx);
+ ImageReader_setNativeContext(env, thiz, ctx);
+ ctx->setBufferFormat(nativeFormat);
+ ctx->setBufferWidth(width);
+ ctx->setBufferHeight(height);
+
+ // Set the width/height/format to the CpuConsumer
+ res = consumer->setDefaultBufferSize(width, height);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set CpuConsumer buffer size");
+ return;
+ }
+ res = consumer->setDefaultBufferFormat(nativeFormat);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set CpuConsumer buffer format");
+ }
+}
+
+static void ImageReader_close(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s:", __FUNCTION__);
+
+ JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ // ImageReader is already closed.
+ return;
+ }
+
+ CpuConsumer* consumer = ImageReader_getCpuConsumer(env, thiz);
+ if (consumer != NULL) {
+ consumer->abandon();
+ consumer->setFrameAvailableListener(NULL);
+ }
+ ImageReader_setNativeContext(env, thiz, NULL);
+}
+
+static void ImageReader_imageRelease(JNIEnv* env, jobject thiz, jobject image)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ ALOGW("ImageReader#close called before Image#close, consider calling Image#close first");
+ return;
+ }
+
+ CpuConsumer* consumer = ctx->getCpuConsumer();
+ CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, image);
+ if (!buffer) {
+ ALOGW("Image already released!!!");
+ return;
+ }
+ consumer->unlockBuffer(*buffer);
+ Image_setBuffer(env, image, NULL);
+ ctx->returnLockedBuffer(buffer);
+}
+
+static jint ImageReader_imageSetup(JNIEnv* env, jobject thiz,
+ jobject image)
+{
+ ALOGV("%s:", __FUNCTION__);
+ JNIImageReaderContext* ctx = ImageReader_getContext(env, thiz);
+ if (ctx == NULL) {
+ jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
+ return -1;
+ }
+
+ CpuConsumer* consumer = ctx->getCpuConsumer();
+ CpuConsumer::LockedBuffer* buffer = ctx->getLockedBuffer();
+ if (buffer == NULL) {
+ ALOGW("Unable to acquire a lockedBuffer, very likely client tries to lock more than"
+ " maxImages buffers");
+ return ACQUIRE_MAX_IMAGES;
+ }
+ status_t res = consumer->lockNextBuffer(buffer);
+ if (res != NO_ERROR) {
+ if (res != BAD_VALUE /*no buffers*/) {
+ if (res == NOT_ENOUGH_DATA) {
+ return ACQUIRE_MAX_IMAGES;
+ } else {
+ ALOGE("%s Fail to lockNextBuffer with error: %d ",
+ __FUNCTION__, res);
+ jniThrowExceptionFmt(env, "java/lang/AssertionError",
+ "Unknown error (%d) when we tried to lock buffer.",
+ res);
+ }
+ }
+ return ACQUIRE_NO_BUFFERS;
+ }
+
+ if (buffer->format == HAL_PIXEL_FORMAT_YCrCb_420_SP) {
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ "NV21 format is not supported by ImageReader");
+ return -1;
+ }
+
+ // Check if the left-top corner of the crop rect is origin, we currently assume this point is
+ // zero, will revist this once this assumption turns out problematic.
+ Point lt = buffer->crop.leftTop();
+ if (lt.x != 0 || lt.y != 0) {
+ jniThrowExceptionFmt(env, "java/lang/UnsupportedOperationException",
+ "crop left top corner [%d, %d] need to be at origin", lt.x, lt.y);
+ return -1;
+ }
+
+ // Check if the producer buffer configurations match what ImageReader configured.
+ // We want to fail for the very first image because this case is too bad.
+ int outputWidth = buffer->width;
+ int outputHeight = buffer->height;
+
+ // Correct width/height when crop is set.
+ if (!buffer->crop.isEmpty()) {
+ outputWidth = buffer->crop.getWidth();
+ outputHeight = buffer->crop.getHeight();
+ }
+
+ int imageReaderWidth = ctx->getBufferWidth();
+ int imageReaderHeight = ctx->getBufferHeight();
+ if ((buffer->format != HAL_PIXEL_FORMAT_BLOB) &&
+ (imageReaderWidth != outputWidth || imageReaderHeight > outputHeight)) {
+ /**
+ * For video decoder, the buffer height is actually the vertical stride,
+ * which is always >= actual image height. For future, decoder need provide
+ * right crop rectangle to CpuConsumer to indicate the actual image height,
+ * see bug 9563986. After this bug is fixed, we can enforce the height equal
+ * check. Right now, only make sure buffer height is no less than ImageReader
+ * height.
+ */
+ jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
+ "Producer buffer size: %dx%d, doesn't match ImageReader configured size: %dx%d",
+ outputWidth, outputHeight, imageReaderWidth, imageReaderHeight);
+ return -1;
+ }
+
+ if (ctx->getBufferFormat() != buffer->format) {
+ // Return the buffer to the queue.
+ consumer->unlockBuffer(*buffer);
+ ctx->returnLockedBuffer(buffer);
+
+ // Throw exception
+ ALOGE("Producer output buffer format: 0x%x, ImageReader configured format: 0x%x",
+ buffer->format, ctx->getBufferFormat());
+ String8 msg;
+ msg.appendFormat("The producer output buffer format 0x%x doesn't "
+ "match the ImageReader's configured buffer format 0x%x.",
+ buffer->format, ctx->getBufferFormat());
+ jniThrowException(env, "java/lang/UnsupportedOperationException",
+ msg.string());
+ return -1;
+ }
+ // Set SurfaceImage instance member variables
+ Image_setBuffer(env, image, buffer);
+ env->SetLongField(image, gSurfaceImageClassInfo.mTimestamp,
+ static_cast<jlong>(buffer->timestamp));
+
+ return ACQUIRE_SUCCESS;
+}
+
+static jobject ImageReader_getSurface(JNIEnv* env, jobject thiz)
+{
+ ALOGV("%s: ", __FUNCTION__);
+
+ BufferQueue* bq = ImageReader_getBufferQueue(env, thiz);
+ if (bq == NULL) {
+ jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
+ return NULL;
+ }
+
+ // Wrap the IGBP in a Java-language Surface.
+ return android_view_Surface_createFromIGraphicBufferProducer(env, bq);
+}
+
+static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx)
+{
+ int rowStride, pixelStride;
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+
+ CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+
+ ALOG_ASSERT(buffer != NULL);
+ if (buffer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+ }
+ rowStride = Image_imageGetRowStride(env, buffer, idx);
+ pixelStride = Image_imageGetPixelStride(env, buffer, idx);
+
+ jobject surfPlaneObj = env->NewObject(gSurfacePlaneClassInfo.clazz,
+ gSurfacePlaneClassInfo.ctor, thiz, idx, rowStride, pixelStride);
+
+ return surfPlaneObj;
+}
+
+static jobject Image_getByteBuffer(JNIEnv* env, jobject thiz, int idx)
+{
+ uint8_t *base = NULL;
+ uint32_t size = 0;
+ jobject byteBuffer;
+
+ ALOGV("%s: buffer index: %d", __FUNCTION__, idx);
+
+ CpuConsumer::LockedBuffer* buffer = Image_getLockedBuffer(env, thiz);
+
+ if (buffer == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Image was released");
+ }
+
+ // Create byteBuffer from native buffer
+ Image_getLockedBufferInfo(env, buffer, idx, &base, &size);
+ byteBuffer = env->NewDirectByteBuffer(base, size);
+ // TODO: throw dvm exOutOfMemoryError?
+ if ((byteBuffer == NULL) && (env->ExceptionCheck() == false)) {
+ jniThrowException(env, "java/lang/IllegalStateException", "Failed to allocate ByteBuffer");
+ }
+
+ return byteBuffer;
+}
+
+} // extern "C"
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod gImageReaderMethods[] = {
+ {"nativeClassInit", "()V", (void*)ImageReader_classInit },
+ {"nativeInit", "(Ljava/lang/Object;IIII)V", (void*)ImageReader_init },
+ {"nativeClose", "()V", (void*)ImageReader_close },
+ {"nativeReleaseImage", "(Landroid/media/Image;)V", (void*)ImageReader_imageRelease },
+ {"nativeImageSetup", "(Landroid/media/Image;)I", (void*)ImageReader_imageSetup },
+ {"nativeGetSurface", "()Landroid/view/Surface;", (void*)ImageReader_getSurface },
+};
+
+static JNINativeMethod gImageMethods[] = {
+ {"nativeImageGetBuffer", "(I)Ljava/nio/ByteBuffer;", (void*)Image_getByteBuffer },
+ {"nativeCreatePlane", "(I)Landroid/media/ImageReader$SurfaceImage$SurfacePlane;",
+ (void*)Image_createSurfacePlane },
+};
+
+int register_android_media_ImageReader(JNIEnv *env) {
+
+ int ret1 = AndroidRuntime::registerNativeMethods(env,
+ "android/media/ImageReader", gImageReaderMethods, NELEM(gImageReaderMethods));
+
+ int ret2 = AndroidRuntime::registerNativeMethods(env,
+ "android/media/ImageReader$SurfaceImage", gImageMethods, NELEM(gImageMethods));
+
+ return (ret1 || ret2);
+}
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index cd1d9ce..b8d437c 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -38,6 +38,8 @@
#include <media/stagefright/foundation/AString.h>
#include <media/stagefright/MediaErrors.h>
+#include <nativehelper/ScopedLocalRef.h>
+
#include <system/window.h>
namespace android {
@@ -49,9 +51,14 @@ enum {
DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED = -3,
};
+struct CryptoErrorCodes {
+ jint cryptoErrorNoKey;
+ jint cryptoErrorKeyExpired;
+ jint cryptoErrorResourceBusy;
+} gCryptoErrorCodes;
+
struct fields_t {
jfieldID context;
-
jfieldID cryptoInfoNumSubSamplesID;
jfieldID cryptoInfoNumBytesOfClearDataID;
jfieldID cryptoInfoNumBytesOfEncryptedDataID;
@@ -81,7 +88,7 @@ JMediaCodec::JMediaCodec(
mLooper->start(
false, // runOnCallingThread
false, // canCallJava
- PRIORITY_DEFAULT);
+ PRIORITY_FOREGROUND);
if (nameIsType) {
mCodec = MediaCodec::CreateByType(mLooper, name, encoder);
@@ -115,7 +122,7 @@ status_t JMediaCodec::configure(
int flags) {
sp<Surface> client;
if (bufferProducer != NULL) {
- mSurfaceTextureClient = new Surface(bufferProducer);
+ mSurfaceTextureClient = new Surface(bufferProducer, true /* controlledByApp */);
} else {
mSurfaceTextureClient.clear();
}
@@ -181,9 +188,10 @@ status_t JMediaCodec::dequeueOutputBuffer(
return err;
}
- jclass clazz = env->FindClass("android/media/MediaCodec$BufferInfo");
+ ScopedLocalRef<jclass> clazz(
+ env, env->FindClass("android/media/MediaCodec$BufferInfo"));
- jmethodID method = env->GetMethodID(clazz, "set", "(IIJI)V");
+ jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
return OK;
@@ -222,29 +230,33 @@ status_t JMediaCodec::getBuffers(
return err;
}
- jclass byteBufferClass = env->FindClass("java/nio/ByteBuffer");
- CHECK(byteBufferClass != NULL);
+ ScopedLocalRef<jclass> byteBufferClass(
+ env, env->FindClass("java/nio/ByteBuffer"));
+
+ CHECK(byteBufferClass.get() != NULL);
jmethodID orderID = env->GetMethodID(
- byteBufferClass,
+ byteBufferClass.get(),
"order",
"(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
CHECK(orderID != NULL);
- jclass byteOrderClass = env->FindClass("java/nio/ByteOrder");
- CHECK(byteOrderClass != NULL);
+ ScopedLocalRef<jclass> byteOrderClass(
+ env, env->FindClass("java/nio/ByteOrder"));
+
+ CHECK(byteOrderClass.get() != NULL);
jmethodID nativeOrderID = env->GetStaticMethodID(
- byteOrderClass, "nativeOrder", "()Ljava/nio/ByteOrder;");
+ byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
CHECK(nativeOrderID != NULL);
jobject nativeByteOrderObj =
- env->CallStaticObjectMethod(byteOrderClass, nativeOrderID);
+ env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
CHECK(nativeByteOrderObj != NULL);
*bufArray = (jobjectArray)env->NewObjectArray(
- buffers.size(), byteBufferClass, NULL);
+ buffers.size(), byteBufferClass.get(), NULL);
if (*bufArray == NULL) {
env->DeleteLocalRef(nativeByteOrderObj);
return NO_MEMORY;
@@ -298,6 +310,10 @@ status_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
return OK;
}
+status_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
+ return mCodec->setParameters(msg);
+}
+
void JMediaCodec::setVideoScalingMode(int mode) {
if (mSurfaceTextureClient != NULL) {
native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
@@ -333,26 +349,41 @@ static void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
}
static void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
- jclass clazz = env->FindClass("android/media/MediaCodec$CryptoException");
- CHECK(clazz != NULL);
+ ScopedLocalRef<jclass> clazz(
+ env, env->FindClass("android/media/MediaCodec$CryptoException"));
+ CHECK(clazz.get() != NULL);
jmethodID constructID =
- env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V");
+ env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
CHECK(constructID != NULL);
jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
+ /* translate OS errors to Java API CryptoException errorCodes */
+ switch (err) {
+ case ERROR_DRM_NO_LICENSE:
+ err = gCryptoErrorCodes.cryptoErrorNoKey;
+ break;
+ case ERROR_DRM_LICENSE_EXPIRED:
+ err = gCryptoErrorCodes.cryptoErrorKeyExpired;
+ break;
+ case ERROR_DRM_RESOURCE_BUSY:
+ err = gCryptoErrorCodes.cryptoErrorResourceBusy;
+ break;
+ default:
+ break;
+ }
+
jthrowable exception =
- (jthrowable)env->NewObject(clazz, constructID, err, msgObj);
+ (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
env->Throw(exception);
}
static jint throwExceptionAsNecessary(
JNIEnv *env, status_t err, const char *msg = NULL) {
- if (err >= ERROR_DRM_WV_VENDOR_MIN && err <= ERROR_DRM_WV_VENDOR_MAX) {
+ if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
// We'll throw our custom MediaCodec.CryptoException
-
throwCryptoException(env, err, msg);
return 0;
}
@@ -370,6 +401,12 @@ static jint throwExceptionAsNecessary(
case INFO_OUTPUT_BUFFERS_CHANGED:
return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
+ case ERROR_DRM_NO_LICENSE:
+ case ERROR_DRM_LICENSE_EXPIRED:
+ case ERROR_DRM_RESOURCE_BUSY:
+ throwCryptoException(env, err, msg);
+ break;
+
default:
{
jniThrowException(env, "java/lang/IllegalStateException", msg);
@@ -804,6 +841,27 @@ static jobject android_media_MediaCodec_getName(
return NULL;
}
+static void android_media_MediaCodec_setParameters(
+ JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
+ ALOGV("android_media_MediaCodec_setParameters");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return;
+ }
+
+ sp<AMessage> params;
+ status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
+
+ if (err == OK) {
+ err = codec->setParameters(params);
+ }
+
+ throwExceptionAsNecessary(env, err);
+}
+
static void android_media_MediaCodec_setVideoScalingMode(
JNIEnv *env, jobject thiz, jint mode) {
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
@@ -823,35 +881,55 @@ static void android_media_MediaCodec_setVideoScalingMode(
}
static void android_media_MediaCodec_native_init(JNIEnv *env) {
- jclass clazz = env->FindClass("android/media/MediaCodec");
- CHECK(clazz != NULL);
+ ScopedLocalRef<jclass> clazz(
+ env, env->FindClass("android/media/MediaCodec"));
+ CHECK(clazz.get() != NULL);
- gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
+ gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "I");
CHECK(gFields.context != NULL);
- clazz = env->FindClass("android/media/MediaCodec$CryptoInfo");
- CHECK(clazz != NULL);
+ clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
+ CHECK(clazz.get() != NULL);
gFields.cryptoInfoNumSubSamplesID =
- env->GetFieldID(clazz, "numSubSamples", "I");
+ env->GetFieldID(clazz.get(), "numSubSamples", "I");
CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
gFields.cryptoInfoNumBytesOfClearDataID =
- env->GetFieldID(clazz, "numBytesOfClearData", "[I");
+ env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
gFields.cryptoInfoNumBytesOfEncryptedDataID =
- env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I");
+ env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
- gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B");
+ gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
CHECK(gFields.cryptoInfoKeyID != NULL);
- gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B");
+ gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
CHECK(gFields.cryptoInfoIVID != NULL);
- gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I");
+ gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
CHECK(gFields.cryptoInfoModeID != NULL);
+
+ clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
+ CHECK(clazz.get() != NULL);
+
+ jfieldID field;
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
+ CHECK(field != NULL);
+ gCryptoErrorCodes.cryptoErrorNoKey =
+ env->GetStaticIntField(clazz.get(), field);
+
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
+ CHECK(field != NULL);
+ gCryptoErrorCodes.cryptoErrorKeyExpired =
+ env->GetStaticIntField(clazz.get(), field);
+
+ field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
+ CHECK(field != NULL);
+ gCryptoErrorCodes.cryptoErrorResourceBusy =
+ env->GetStaticIntField(clazz.get(), field);
}
static void android_media_MediaCodec_native_setup(
@@ -933,6 +1011,9 @@ static JNINativeMethod gMethods[] = {
{ "getName", "()Ljava/lang/String;",
(void *)android_media_MediaCodec_getName },
+ { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
+ (void *)android_media_MediaCodec_setParameters },
+
{ "setVideoScalingMode", "(I)V",
(void *)android_media_MediaCodec_setVideoScalingMode },
diff --git a/media/jni/android_media_MediaCodec.h b/media/jni/android_media_MediaCodec.h
index 282d2c5..2fbbd72 100644
--- a/media/jni/android_media_MediaCodec.h
+++ b/media/jni/android_media_MediaCodec.h
@@ -87,6 +87,8 @@ struct JMediaCodec : public RefBase {
status_t getName(JNIEnv *env, jstring *name) const;
+ status_t setParameters(const sp<AMessage> &params);
+
void setVideoScalingMode(int mode);
protected:
diff --git a/media/jni/android_media_MediaCodecList.cpp b/media/jni/android_media_MediaCodecList.cpp
index 04430ec..caa594e 100644
--- a/media/jni/android_media_MediaCodecList.cpp
+++ b/media/jni/android_media_MediaCodecList.cpp
@@ -110,10 +110,11 @@ static jobject android_media_MediaCodecList_getCodecCapabilities(
Vector<MediaCodecList::ProfileLevel> profileLevels;
Vector<uint32_t> colorFormats;
+ uint32_t flags;
status_t err =
MediaCodecList::getInstance()->getCodecCapabilities(
- index, typeStr, &profileLevels, &colorFormats);
+ index, typeStr, &profileLevels, &colorFormats, &flags);
env->ReleaseStringUTFChars(type, typeStr);
typeStr = NULL;
@@ -127,6 +128,9 @@ static jobject android_media_MediaCodecList_getCodecCapabilities(
env->FindClass("android/media/MediaCodecInfo$CodecCapabilities");
CHECK(capsClazz != NULL);
+ jfieldID flagsField =
+ env->GetFieldID(capsClazz, "flags", "I");
+
jobject caps = env->AllocObject(capsClazz);
jclass profileLevelClazz =
@@ -163,6 +167,8 @@ static jobject android_media_MediaCodecList_getCodecCapabilities(
env->SetObjectField(caps, profileLevelsField, profileLevelArray);
+ env->SetIntField(caps, flagsField, flags);
+
env->DeleteLocalRef(profileLevelArray);
profileLevelArray = NULL;
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 7799ca4..bbb74d2 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -21,6 +21,7 @@
#include "android_media_MediaDrm.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
#include "android_os_Parcel.h"
#include "jni.h"
#include "JNIHelp.h"
@@ -242,6 +243,9 @@ static bool throwExceptionAsNecessary(
} else if (err == ERROR_DRM_NOT_PROVISIONED) {
jniThrowException(env, "android/media/NotProvisionedException", msg);
return true;
+ } else if (err == ERROR_DRM_RESOURCE_BUSY) {
+ jniThrowException(env, "android/media/ResourceBusyException", msg);
+ return true;
} else if (err == ERROR_DRM_DEVICE_REVOKED) {
jniThrowException(env, "android/media/DeniedByServerException", msg);
return true;
@@ -345,14 +349,14 @@ void JDrm::notify(DrmPlugin::EventType eventType, int extra, const Parcel *obj)
// static
-bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16]) {
+bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
sp<IDrm> drm = MakeDrm();
if (drm == NULL) {
return false;
}
- return drm->isCryptoSchemeSupported(uuid);
+ return drm->isCryptoSchemeSupported(uuid, mimeType);
}
status_t JDrm::initCheck() const {
@@ -608,7 +612,7 @@ static void android_media_MediaDrm_native_finalize(
}
static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
- JNIEnv *env, jobject thiz, jbyteArray uuidObj) {
+ JNIEnv *env, jobject thiz, jbyteArray uuidObj, jstring jmimeType) {
if (uuidObj == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
@@ -625,7 +629,12 @@ static jboolean android_media_MediaDrm_isCryptoSchemeSupportedNative(
return false;
}
- return JDrm::IsCryptoSchemeSupported(uuid.array());
+ String8 mimeType;
+ if (jmimeType != NULL) {
+ mimeType = JStringToString8(env, jmimeType);
+ }
+
+ return JDrm::IsCryptoSchemeSupported(uuid.array(), mimeType);
}
static jbyteArray android_media_MediaDrm_openSession(
@@ -750,7 +759,9 @@ static jbyteArray android_media_MediaDrm_provideKeyResponse(
status_t err = drm->provideKeyResponse(sessionId, response, keySetId);
- throwExceptionAsNecessary(env, err, "Failed to handle key response");
+ if (throwExceptionAsNecessary(env, err, "Failed to handle key response")) {
+ return NULL;
+ }
return VectorToJByteArray(env, keySetId);
}
@@ -1101,7 +1112,9 @@ static jbyteArray android_media_MediaDrm_encryptNative(
status_t err = drm->encrypt(sessionId, keyId, input, iv, output);
- throwExceptionAsNecessary(env, err, "Failed to encrypt");
+ if (throwExceptionAsNecessary(env, err, "Failed to encrypt")) {
+ return NULL;
+ }
return VectorToJByteArray(env, output);
}
@@ -1129,7 +1142,9 @@ static jbyteArray android_media_MediaDrm_decryptNative(
Vector<uint8_t> output;
status_t err = drm->decrypt(sessionId, keyId, input, iv, output);
- throwExceptionAsNecessary(env, err, "Failed to decrypt");
+ if (throwExceptionAsNecessary(env, err, "Failed to decrypt")) {
+ return NULL;
+ }
return VectorToJByteArray(env, output);
}
@@ -1157,7 +1172,9 @@ static jbyteArray android_media_MediaDrm_signNative(
status_t err = drm->sign(sessionId, keyId, message, signature);
- throwExceptionAsNecessary(env, err, "Failed to sign");
+ if (throwExceptionAsNecessary(env, err, "Failed to sign")) {
+ return NULL;
+ }
return VectorToJByteArray(env, signature);
}
@@ -1201,7 +1218,7 @@ static JNINativeMethod gMethods[] = {
{ "native_finalize", "()V",
(void *)android_media_MediaDrm_native_finalize },
- { "isCryptoSchemeSupportedNative", "([B)Z",
+ { "isCryptoSchemeSupportedNative", "([BLjava/lang/String;)Z",
(void *)android_media_MediaDrm_isCryptoSchemeSupportedNative },
{ "openSession", "()[B",
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 9b3917f..620ad28 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -37,7 +37,7 @@ public:
};
struct JDrm : public BnDrmClient {
- static bool IsCryptoSchemeSupported(const uint8_t uuid[16]);
+ static bool IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType);
JDrm(JNIEnv *env, jobject thiz, const uint8_t uuid[16]);
diff --git a/media/jni/android_media_MediaExtractor.cpp b/media/jni/android_media_MediaExtractor.cpp
index 1704d5c..1ac45d4 100644
--- a/media/jni/android_media_MediaExtractor.cpp
+++ b/media/jni/android_media_MediaExtractor.cpp
@@ -22,6 +22,7 @@
#include "android_media_Utils.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
#include "jni.h"
#include "JNIHelp.h"
diff --git a/media/jni/android_media_MediaMuxer.cpp b/media/jni/android_media_MediaMuxer.cpp
index 7517e85..457b956 100644
--- a/media/jni/android_media_MediaMuxer.cpp
+++ b/media/jni/android_media_MediaMuxer.cpp
@@ -164,6 +164,18 @@ static void android_media_MediaMuxer_setOrientationHint(
}
+static void android_media_MediaMuxer_setLocation(
+ JNIEnv *env, jclass clazz, jint nativeObject, jint latitude, jint longitude) {
+ MediaMuxer* muxer = reinterpret_cast<MediaMuxer *>(nativeObject);
+
+ status_t res = muxer->setLocation(latitude, longitude);
+ if (res != OK) {
+ jniThrowException(env, "java/lang/IllegalStateException",
+ "Failed to set location");
+ return;
+ }
+}
+
static void android_media_MediaMuxer_start(JNIEnv *env, jclass clazz,
jint nativeObject) {
sp<MediaMuxer> muxer(reinterpret_cast<MediaMuxer *>(nativeObject));
@@ -216,6 +228,9 @@ static JNINativeMethod gMethods[] = {
{ "nativeSetOrientationHint", "(II)V",
(void *)android_media_MediaMuxer_setOrientationHint},
+ { "nativeSetLocation", "(III)V",
+ (void *)android_media_MediaMuxer_setLocation},
+
{ "nativeStart", "(I)V", (void *)android_media_MediaMuxer_start},
{ "nativeWriteSampleData", "(IILjava/nio/ByteBuffer;IIJI)V",
diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp
index d06380d..4be9cd6 100644
--- a/media/jni/android_media_MediaPlayer.cpp
+++ b/media/jni/android_media_MediaPlayer.cpp
@@ -31,6 +31,7 @@
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include "android_runtime/android_view_Surface.h"
+#include "android_runtime/Log.h"
#include "utils/Errors.h" // for status_t
#include "utils/KeyedVector.h"
#include "utils/String8.h"
@@ -526,14 +527,6 @@ android_media_MediaPlayer_setVolume(JNIEnv *env, jobject thiz, float leftVolume,
process_media_player_call( env, thiz, mp->setVolume(leftVolume, rightVolume), NULL, NULL );
}
-// FIXME: deprecated
-static jobject
-android_media_MediaPlayer_getFrameAt(JNIEnv *env, jobject thiz, jint msec)
-{
- return NULL;
-}
-
-
// Sends the request and reply parcels to the media player via the
// binder interface.
static jint
@@ -782,39 +775,6 @@ android_media_MediaPlayer_setRetransmitEndpoint(JNIEnv *env, jobject thiz,
return ret;
}
-static jboolean
-android_media_MediaPlayer_setParameter(JNIEnv *env, jobject thiz, jint key, jobject java_request)
-{
- ALOGV("setParameter: key %d", key);
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return false;
- }
-
- Parcel *request = parcelForJavaObject(env, java_request);
- status_t err = mp->setParameter(key, *request);
- if (err == OK) {
- return true;
- } else {
- return false;
- }
-}
-
-static void
-android_media_MediaPlayer_getParameter(JNIEnv *env, jobject thiz, jint key, jobject java_reply)
-{
- ALOGV("getParameter: key %d", key);
- sp<MediaPlayer> mp = getMediaPlayer(env, thiz);
- if (mp == NULL ) {
- jniThrowException(env, "java/lang/IllegalStateException", NULL);
- return;
- }
-
- Parcel *reply = parcelForJavaObject(env, java_reply);
- process_media_player_call(env, thiz, mp->getParameter(key, reply), NULL, NULL );
-}
-
static void
android_media_MediaPlayer_setNextMediaPlayer(JNIEnv *env, jobject thiz, jobject java_player)
{
@@ -913,7 +873,6 @@ static JNINativeMethod gMethods[] = {
{"setLooping", "(Z)V", (void *)android_media_MediaPlayer_setLooping},
{"isLooping", "()Z", (void *)android_media_MediaPlayer_isLooping},
{"setVolume", "(FF)V", (void *)android_media_MediaPlayer_setVolume},
- {"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt},
{"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
@@ -925,8 +884,6 @@ static JNINativeMethod gMethods[] = {
{"setAuxEffectSendLevel", "(F)V", (void *)android_media_MediaPlayer_setAuxEffectSendLevel},
{"attachAuxEffect", "(I)V", (void *)android_media_MediaPlayer_attachAuxEffect},
{"native_pullBatteryData", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_pullBatteryData},
- {"setParameter", "(ILandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_setParameter},
- {"getParameter", "(ILandroid/os/Parcel;)V", (void *)android_media_MediaPlayer_getParameter},
{"native_setRetransmitEndpoint", "(Ljava/lang/String;I)I", (void *)android_media_MediaPlayer_setRetransmitEndpoint},
{"setNextMediaPlayer", "(Landroid/media/MediaPlayer;)V", (void *)android_media_MediaPlayer_setNextMediaPlayer},
{"updateProxyConfig", "(Landroid/net/ProxyProperties;)V", (void *)android_media_MediaPlayer_updateProxyConfig},
@@ -941,6 +898,7 @@ static int register_android_media_MediaPlayer(JNIEnv *env)
"android/media/MediaPlayer", gMethods, NELEM(gMethods));
}
+extern int register_android_media_ImageReader(JNIEnv *env);
extern int register_android_media_Crypto(JNIEnv *env);
extern int register_android_media_Drm(JNIEnv *env);
extern int register_android_media_MediaCodec(JNIEnv *env);
@@ -968,6 +926,11 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
}
assert(env != NULL);
+ if (register_android_media_ImageReader(env) < 0) {
+ ALOGE("ERROR: ImageReader native registration failed");
+ goto bail;
+ }
+
if (register_android_media_MediaPlayer(env) < 0) {
ALOGE("ERROR: MediaPlayer native registration failed\n");
goto bail;
diff --git a/media/jni/android_media_MediaScanner.cpp b/media/jni/android_media_MediaScanner.cpp
index 5d27966..4e3d14e 100644
--- a/media/jni/android_media_MediaScanner.cpp
+++ b/media/jni/android_media_MediaScanner.cpp
@@ -25,6 +25,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
using namespace android;
diff --git a/media/jni/android_media_Utils.cpp b/media/jni/android_media_Utils.cpp
index e35ace3..54c5e9b 100644
--- a/media/jni/android_media_Utils.cpp
+++ b/media/jni/android_media_Utils.cpp
@@ -24,6 +24,8 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/AMessage.h>
+#include <nativehelper/ScopedLocalRef.h>
+
namespace android {
bool ConvertKeyValueArraysToKeyedVector(
@@ -76,33 +78,35 @@ bool ConvertKeyValueArraysToKeyedVector(
}
static jobject makeIntegerObject(JNIEnv *env, int32_t value) {
- jclass clazz = env->FindClass("java/lang/Integer");
- CHECK(clazz != NULL);
+ ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Integer"));
+ CHECK(clazz.get() != NULL);
- jmethodID integerConstructID = env->GetMethodID(clazz, "<init>", "(I)V");
+ jmethodID integerConstructID =
+ env->GetMethodID(clazz.get(), "<init>", "(I)V");
CHECK(integerConstructID != NULL);
- return env->NewObject(clazz, integerConstructID, value);
+ return env->NewObject(clazz.get(), integerConstructID, value);
}
static jobject makeLongObject(JNIEnv *env, int64_t value) {
- jclass clazz = env->FindClass("java/lang/Long");
- CHECK(clazz != NULL);
+ ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Long"));
+ CHECK(clazz.get() != NULL);
- jmethodID longConstructID = env->GetMethodID(clazz, "<init>", "(J)V");
+ jmethodID longConstructID = env->GetMethodID(clazz.get(), "<init>", "(J)V");
CHECK(longConstructID != NULL);
- return env->NewObject(clazz, longConstructID, value);
+ return env->NewObject(clazz.get(), longConstructID, value);
}
static jobject makeFloatObject(JNIEnv *env, float value) {
- jclass clazz = env->FindClass("java/lang/Float");
- CHECK(clazz != NULL);
+ ScopedLocalRef<jclass> clazz(env, env->FindClass("java/lang/Float"));
+ CHECK(clazz.get() != NULL);
- jmethodID floatConstructID = env->GetMethodID(clazz, "<init>", "(F)V");
+ jmethodID floatConstructID =
+ env->GetMethodID(clazz.get(), "<init>", "(F)V");
CHECK(floatConstructID != NULL);
- return env->NewObject(clazz, floatConstructID, value);
+ return env->NewObject(clazz.get(), floatConstructID, value);
}
static jobject makeByteBufferObject(
@@ -110,15 +114,16 @@ static jobject makeByteBufferObject(
jbyteArray byteArrayObj = env->NewByteArray(size);
env->SetByteArrayRegion(byteArrayObj, 0, size, (const jbyte *)data);
- jclass clazz = env->FindClass("java/nio/ByteBuffer");
- CHECK(clazz != NULL);
+ ScopedLocalRef<jclass> clazz(env, env->FindClass("java/nio/ByteBuffer"));
+ CHECK(clazz.get() != NULL);
jmethodID byteBufWrapID =
- env->GetStaticMethodID(clazz, "wrap", "([B)Ljava/nio/ByteBuffer;");
+ env->GetStaticMethodID(
+ clazz.get(), "wrap", "([B)Ljava/nio/ByteBuffer;");
CHECK(byteBufWrapID != NULL);
jobject byteBufObj = env->CallStaticObjectMethod(
- clazz, byteBufWrapID, byteArrayObj);
+ clazz.get(), byteBufWrapID, byteArrayObj);
env->DeleteLocalRef(byteArrayObj); byteArrayObj = NULL;
@@ -140,14 +145,15 @@ static void SetMapInt32(
status_t ConvertMessageToMap(
JNIEnv *env, const sp<AMessage> &msg, jobject *map) {
- jclass hashMapClazz = env->FindClass("java/util/HashMap");
+ ScopedLocalRef<jclass> hashMapClazz(
+ env, env->FindClass("java/util/HashMap"));
- if (hashMapClazz == NULL) {
+ if (hashMapClazz.get() == NULL) {
return -EINVAL;
}
jmethodID hashMapConstructID =
- env->GetMethodID(hashMapClazz, "<init>", "()V");
+ env->GetMethodID(hashMapClazz.get(), "<init>", "()V");
if (hashMapConstructID == NULL) {
return -EINVAL;
@@ -155,7 +161,7 @@ status_t ConvertMessageToMap(
jmethodID hashMapPutID =
env->GetMethodID(
- hashMapClazz,
+ hashMapClazz.get(),
"put",
"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
@@ -163,7 +169,7 @@ status_t ConvertMessageToMap(
return -EINVAL;
}
- jobject hashMap = env->NewObject(hashMapClazz, hashMapConstructID);
+ jobject hashMap = env->NewObject(hashMapClazz.get(), hashMapConstructID);
for (size_t i = 0; i < msg->countEntries(); ++i) {
AMessage::Type valueType;
@@ -276,17 +282,16 @@ status_t ConvertMessageToMap(
status_t ConvertKeyValueArraysToMessage(
JNIEnv *env, jobjectArray keys, jobjectArray values,
sp<AMessage> *out) {
- jclass stringClass = env->FindClass("java/lang/String");
- CHECK(stringClass != NULL);
-
- jclass integerClass = env->FindClass("java/lang/Integer");
- CHECK(integerClass != NULL);
-
- jclass floatClass = env->FindClass("java/lang/Float");
- CHECK(floatClass != NULL);
-
- jclass byteBufClass = env->FindClass("java/nio/ByteBuffer");
- CHECK(byteBufClass != NULL);
+ ScopedLocalRef<jclass> stringClass(env, env->FindClass("java/lang/String"));
+ CHECK(stringClass.get() != NULL);
+ ScopedLocalRef<jclass> integerClass(env, env->FindClass("java/lang/Integer"));
+ CHECK(integerClass.get() != NULL);
+ ScopedLocalRef<jclass> longClass(env, env->FindClass("java/lang/Long"));
+ CHECK(longClass.get() != NULL);
+ ScopedLocalRef<jclass> floatClass(env, env->FindClass("java/lang/Float"));
+ CHECK(floatClass.get() != NULL);
+ ScopedLocalRef<jclass> byteBufClass(env, env->FindClass("java/nio/ByteBuffer"));
+ CHECK(byteBufClass.get() != NULL);
sp<AMessage> msg = new AMessage;
@@ -309,7 +314,7 @@ status_t ConvertKeyValueArraysToMessage(
for (jsize i = 0; i < numEntries; ++i) {
jobject keyObj = env->GetObjectArrayElement(keys, i);
- if (!env->IsInstanceOf(keyObj, stringClass)) {
+ if (!env->IsInstanceOf(keyObj, stringClass.get())) {
return -EINVAL;
}
@@ -326,7 +331,7 @@ status_t ConvertKeyValueArraysToMessage(
jobject valueObj = env->GetObjectArrayElement(values, i);
- if (env->IsInstanceOf(valueObj, stringClass)) {
+ if (env->IsInstanceOf(valueObj, stringClass.get())) {
const char *value = env->GetStringUTFChars((jstring)valueObj, NULL);
if (value == NULL) {
@@ -337,29 +342,37 @@ status_t ConvertKeyValueArraysToMessage(
env->ReleaseStringUTFChars((jstring)valueObj, value);
value = NULL;
- } else if (env->IsInstanceOf(valueObj, integerClass)) {
+ } else if (env->IsInstanceOf(valueObj, integerClass.get())) {
jmethodID intValueID =
- env->GetMethodID(integerClass, "intValue", "()I");
+ env->GetMethodID(integerClass.get(), "intValue", "()I");
CHECK(intValueID != NULL);
jint value = env->CallIntMethod(valueObj, intValueID);
msg->setInt32(key.c_str(), value);
- } else if (env->IsInstanceOf(valueObj, floatClass)) {
+ } else if (env->IsInstanceOf(valueObj, longClass.get())) {
+ jmethodID longValueID =
+ env->GetMethodID(longClass.get(), "longValue", "()J");
+ CHECK(longValueID != NULL);
+
+ jlong value = env->CallLongMethod(valueObj, longValueID);
+
+ msg->setInt64(key.c_str(), value);
+ } else if (env->IsInstanceOf(valueObj, floatClass.get())) {
jmethodID floatValueID =
- env->GetMethodID(floatClass, "floatValue", "()F");
+ env->GetMethodID(floatClass.get(), "floatValue", "()F");
CHECK(floatValueID != NULL);
jfloat value = env->CallFloatMethod(valueObj, floatValueID);
msg->setFloat(key.c_str(), value);
- } else if (env->IsInstanceOf(valueObj, byteBufClass)) {
+ } else if (env->IsInstanceOf(valueObj, byteBufClass.get())) {
jmethodID positionID =
- env->GetMethodID(byteBufClass, "position", "()I");
+ env->GetMethodID(byteBufClass.get(), "position", "()I");
CHECK(positionID != NULL);
jmethodID limitID =
- env->GetMethodID(byteBufClass, "limit", "()I");
+ env->GetMethodID(byteBufClass.get(), "limit", "()I");
CHECK(limitID != NULL);
jint position = env->CallIntMethod(valueObj, positionID);
@@ -375,7 +388,7 @@ status_t ConvertKeyValueArraysToMessage(
buffer->size());
} else {
jmethodID arrayID =
- env->GetMethodID(byteBufClass, "array", "()[B");
+ env->GetMethodID(byteBufClass.get(), "array", "()[B");
CHECK(arrayID != NULL);
jbyteArray byteArray =
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index fbd5d21..77c7966 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -26,6 +26,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
#include "MtpDatabase.h"
#include "MtpDataPacket.h"
diff --git a/media/jni/android_mtp_MtpDevice.cpp b/media/jni/android_mtp_MtpDevice.cpp
index 113784e..b61b66c 100644
--- a/media/jni/android_mtp_MtpDevice.cpp
+++ b/media/jni/android_mtp_MtpDevice.cpp
@@ -28,6 +28,7 @@
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
+#include "android_runtime/Log.h"
#include "private/android_filesystem_config.h"
#include "MtpTypes.h"
diff --git a/media/jni/audioeffect/android_media_Visualizer.cpp b/media/jni/audioeffect/android_media_Visualizer.cpp
index 4d77cfd..40cd06b 100644
--- a/media/jni/audioeffect/android_media_Visualizer.cpp
+++ b/media/jni/audioeffect/android_media_Visualizer.cpp
@@ -43,6 +43,8 @@ using namespace android;
// ----------------------------------------------------------------------------
static const char* const kClassPathName = "android/media/audiofx/Visualizer";
+static const char* const kClassPeakRmsPathName =
+ "android/media/audiofx/Visualizer$MeasurementPeakRms";
struct fields_t {
// these fields provide access from C++ to the...
@@ -50,6 +52,8 @@ struct fields_t {
jmethodID midPostNativeEvent; // event post callback method
jfieldID fidNativeVisualizer; // stores in Java the native Visualizer object
jfieldID fidJniData; // stores in Java additional resources used by the native Visualizer
+ jfieldID fidPeak; // to access Visualizer.MeasurementPeakRms.mPeak
+ jfieldID fidRms; // to access Visualizer.MeasurementPeakRms.mRms
};
static fields_t fields;
@@ -257,6 +261,14 @@ android_media_visualizer_native_init(JNIEnv *env)
fields.clazzEffect = (jclass)env->NewGlobalRef(clazz);
+ // Get the Visualizer.MeasurementPeakRms class
+ clazz = env->FindClass(kClassPeakRmsPathName);
+ if (clazz == NULL) {
+ ALOGE("Can't find %s", kClassPeakRmsPathName);
+ return;
+ }
+ jclass clazzMeasurementPeakRms = (jclass)env->NewGlobalRef(clazz);
+
// Get the postEvent method
fields.midPostNativeEvent = env->GetStaticMethodID(
fields.clazzEffect,
@@ -283,7 +295,24 @@ android_media_visualizer_native_init(JNIEnv *env)
ALOGE("Can't find Visualizer.%s", "mJniData");
return;
}
+ // fidPeak
+ fields.fidPeak = env->GetFieldID(
+ clazzMeasurementPeakRms,
+ "mPeak", "I");
+ if (fields.fidPeak == NULL) {
+ ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
+ return;
+ }
+ // fidRms
+ fields.fidRms = env->GetFieldID(
+ clazzMeasurementPeakRms,
+ "mRms", "I");
+ if (fields.fidRms == NULL) {
+ ALOGE("Can't find Visualizer.MeasurementPeakRms.%s", "mPeak");
+ return;
+ }
+ env->DeleteGlobalRef(clazzMeasurementPeakRms);
}
static void android_media_visualizer_effect_callback(int32_t event,
@@ -513,6 +542,26 @@ android_media_visualizer_native_getScalingMode(JNIEnv *env, jobject thiz)
}
static jint
+android_media_visualizer_native_setMeasurementMode(JNIEnv *env, jobject thiz, jint mode)
+{
+ Visualizer* lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == NULL) {
+ return VISUALIZER_ERROR_NO_INIT;
+ }
+ return translateError(lpVisualizer->setMeasurementMode(mode));
+}
+
+static jint
+android_media_visualizer_native_getMeasurementMode(JNIEnv *env, jobject thiz)
+{
+ Visualizer* lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == NULL) {
+ return MEASUREMENT_MODE_NONE;
+ }
+ return lpVisualizer->getMeasurementMode();
+}
+
+static jint
android_media_visualizer_native_getSamplingRate(JNIEnv *env, jobject thiz)
{
Visualizer* lpVisualizer = getVisualizer(env, thiz);
@@ -560,6 +609,25 @@ android_media_visualizer_native_getFft(JNIEnv *env, jobject thiz, jbyteArray jFf
}
static jint
+android_media_visualizer_native_getPeakRms(JNIEnv *env, jobject thiz, jobject jPeakRmsObj)
+{
+ Visualizer* lpVisualizer = getVisualizer(env, thiz);
+ if (lpVisualizer == NULL) {
+ return VISUALIZER_ERROR_NO_INIT;
+ }
+ int32_t measurements[2];
+ jint status = translateError(
+ lpVisualizer->getIntMeasurements(MEASUREMENT_MODE_PEAK_RMS,
+ 2, measurements));
+ if (status == VISUALIZER_SUCCESS) {
+ // measurement worked, write the values to the java object
+ env->SetIntField(jPeakRmsObj, fields.fidPeak, measurements[MEASUREMENT_IDX_PEAK]);
+ env->SetIntField(jPeakRmsObj, fields.fidRms, measurements[MEASUREMENT_IDX_RMS]);
+ }
+ return status;
+}
+
+static jint
android_media_setPeriodicCapture(JNIEnv *env, jobject thiz, jint rate, jboolean jWaveform, jboolean jFft)
{
Visualizer* lpVisualizer = getVisualizer(env, thiz);
@@ -606,9 +674,13 @@ static JNINativeMethod gMethods[] = {
{"native_getCaptureSize", "()I", (void *)android_media_visualizer_native_getCaptureSize},
{"native_setScalingMode", "(I)I", (void *)android_media_visualizer_native_setScalingMode},
{"native_getScalingMode", "()I", (void *)android_media_visualizer_native_getScalingMode},
+ {"native_setMeasurementMode","(I)I", (void *)android_media_visualizer_native_setMeasurementMode},
+ {"native_getMeasurementMode","()I", (void *)android_media_visualizer_native_getMeasurementMode},
{"native_getSamplingRate", "()I", (void *)android_media_visualizer_native_getSamplingRate},
{"native_getWaveForm", "([B)I", (void *)android_media_visualizer_native_getWaveForm},
{"native_getFft", "([B)I", (void *)android_media_visualizer_native_getFft},
+ {"native_getPeakRms", "(Landroid/media/audiofx/Visualizer$MeasurementPeakRms;)I",
+ (void *)android_media_visualizer_native_getPeakRms},
{"native_setPeriodicCapture","(IZZ)I",(void *)android_media_setPeriodicCapture},
};
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
index 4982a47..d8099dd 100644
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ b/media/jni/mediaeditor/VideoEditorClasses.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#define LOG_TAG "VideoEditorClasses"
#include <VideoEditorClasses.h>
#include <VideoEditorJava.h>
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
index bcf9099..fde0fb5 100644
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ b/media/jni/mediaeditor/VideoEditorJava.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "VideoEditorJava"
+
#include <VideoEditorClasses.h>
#include <VideoEditorJava.h>
#include <VideoEditorLogging.h>
diff --git a/media/jni/mediaeditor/VideoEditorLogging.h b/media/jni/mediaeditor/VideoEditorLogging.h
index 479d8b6..1f1228a 100644
--- a/media/jni/mediaeditor/VideoEditorLogging.h
+++ b/media/jni/mediaeditor/VideoEditorLogging.h
@@ -17,6 +17,16 @@
#ifndef VIDEO_EDITOR_LOGGING_H
#define VIDEO_EDITOR_LOGGING_H
+#ifndef LOG_TAG
+#error "No LOG_TAG defined!"
+#endif
+
+/*
+ * This file is used as a proxy for cutils/log.h. Include cutils/log.h here to
+ * avoid relying on import ordering.
+ */
+#include <cutils/log.h>
+
//#define VIDEOEDIT_LOGGING_ENABLED
#define VIDEOEDIT_LOG_INDENTATION (3)
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
index a8c08ac..c12b1f5 100644
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ b/media/jni/mediaeditor/VideoEditorOsal.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "VideoEditorOsal"
+
#include <VideoEditorJava.h>
#include <VideoEditorLogging.h>
#include <VideoEditorOsal.h>
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
index c8fb263..2f8e357 100644
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
@@ -14,6 +14,8 @@
* limitations under the License.
*/
+#define LOG_TAG "VideoEditorPropertiesMain"
+
#include <dlfcn.h>
#include <stdio.h>
#include <unistd.h>
diff --git a/media/jni/soundpool/Android.mk b/media/jni/soundpool/Android.mk
index 5835b9f..ed8d7c1 100644
--- a/media/jni/soundpool/Android.mk
+++ b/media/jni/soundpool/Android.mk
@@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
- android_media_SoundPool.cpp
+ android_media_SoundPool_SoundPoolImpl.cpp
LOCAL_SHARED_LIBRARIES := \
liblog \
diff --git a/media/jni/soundpool/android_media_SoundPool.cpp b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
index 9658856..2604850 100644
--- a/media/jni/soundpool/android_media_SoundPool.cpp
+++ b/media/jni/soundpool/android_media_SoundPool_SoundPoolImpl.cpp
@@ -39,9 +39,9 @@ static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) {
// ----------------------------------------------------------------------------
static int
-android_media_SoundPool_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
+android_media_SoundPool_SoundPoolImpl_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
{
- ALOGV("android_media_SoundPool_load_URL");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_load_URL");
SoundPool *ap = MusterSoundPool(env, thiz);
if (path == NULL) {
jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
@@ -54,10 +54,10 @@ android_media_SoundPool_load_URL(JNIEnv *env, jobject thiz, jstring path, jint p
}
static int
-android_media_SoundPool_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
+android_media_SoundPool_SoundPoolImpl_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
jlong offset, jlong length, jint priority)
{
- ALOGV("android_media_SoundPool_load_FD");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_load_FD");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return 0;
return ap->load(jniGetFDFromFileDescriptor(env, fileDescriptor),
@@ -65,104 +65,104 @@ android_media_SoundPool_load_FD(JNIEnv *env, jobject thiz, jobject fileDescripto
}
static bool
-android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
- ALOGV("android_media_SoundPool_unload\n");
+android_media_SoundPool_SoundPoolImpl_unload(JNIEnv *env, jobject thiz, jint sampleID) {
+ ALOGV("android_media_SoundPool_SoundPoolImpl_unload\n");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return 0;
return ap->unload(sampleID);
}
static int
-android_media_SoundPool_play(JNIEnv *env, jobject thiz, jint sampleID,
+android_media_SoundPool_SoundPoolImpl_play(JNIEnv *env, jobject thiz, jint sampleID,
jfloat leftVolume, jfloat rightVolume, jint priority, jint loop,
jfloat rate)
{
- ALOGV("android_media_SoundPool_play\n");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_play\n");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return 0;
return ap->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
}
static void
-android_media_SoundPool_pause(JNIEnv *env, jobject thiz, jint channelID)
+android_media_SoundPool_SoundPoolImpl_pause(JNIEnv *env, jobject thiz, jint channelID)
{
- ALOGV("android_media_SoundPool_pause");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_pause");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->pause(channelID);
}
static void
-android_media_SoundPool_resume(JNIEnv *env, jobject thiz, jint channelID)
+android_media_SoundPool_SoundPoolImpl_resume(JNIEnv *env, jobject thiz, jint channelID)
{
- ALOGV("android_media_SoundPool_resume");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_resume");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->resume(channelID);
}
static void
-android_media_SoundPool_autoPause(JNIEnv *env, jobject thiz)
+android_media_SoundPool_SoundPoolImpl_autoPause(JNIEnv *env, jobject thiz)
{
- ALOGV("android_media_SoundPool_autoPause");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_autoPause");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->autoPause();
}
static void
-android_media_SoundPool_autoResume(JNIEnv *env, jobject thiz)
+android_media_SoundPool_SoundPoolImpl_autoResume(JNIEnv *env, jobject thiz)
{
- ALOGV("android_media_SoundPool_autoResume");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_autoResume");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->autoResume();
}
static void
-android_media_SoundPool_stop(JNIEnv *env, jobject thiz, jint channelID)
+android_media_SoundPool_SoundPoolImpl_stop(JNIEnv *env, jobject thiz, jint channelID)
{
- ALOGV("android_media_SoundPool_stop");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_stop");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->stop(channelID);
}
static void
-android_media_SoundPool_setVolume(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_SoundPoolImpl_setVolume(JNIEnv *env, jobject thiz, jint channelID,
float leftVolume, float rightVolume)
{
- ALOGV("android_media_SoundPool_setVolume");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_setVolume");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->setVolume(channelID, leftVolume, rightVolume);
}
static void
-android_media_SoundPool_setPriority(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_SoundPoolImpl_setPriority(JNIEnv *env, jobject thiz, jint channelID,
int priority)
{
- ALOGV("android_media_SoundPool_setPriority");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_setPriority");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->setPriority(channelID, priority);
}
static void
-android_media_SoundPool_setLoop(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_SoundPoolImpl_setLoop(JNIEnv *env, jobject thiz, jint channelID,
int loop)
{
- ALOGV("android_media_SoundPool_setLoop");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_setLoop");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->setLoop(channelID, loop);
}
static void
-android_media_SoundPool_setRate(JNIEnv *env, jobject thiz, jint channelID,
+android_media_SoundPool_SoundPoolImpl_setRate(JNIEnv *env, jobject thiz, jint channelID,
float rate)
{
- ALOGV("android_media_SoundPool_setRate");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_setRate");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap == NULL) return;
ap->setRate(channelID, rate);
@@ -176,9 +176,9 @@ static void android_media_callback(SoundPoolEvent event, SoundPool* soundPool, v
}
static jint
-android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef, jint maxChannels, jint streamType, jint srcQuality)
+android_media_SoundPool_SoundPoolImpl_native_setup(JNIEnv *env, jobject thiz, jobject weakRef, jint maxChannels, jint streamType, jint srcQuality)
{
- ALOGV("android_media_SoundPool_native_setup");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_native_setup");
SoundPool *ap = new SoundPool(maxChannels, (audio_stream_type_t) streamType, srcQuality);
if (ap == NULL) {
return -1;
@@ -194,9 +194,9 @@ android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
}
static void
-android_media_SoundPool_release(JNIEnv *env, jobject thiz)
+android_media_SoundPool_SoundPoolImpl_release(JNIEnv *env, jobject thiz)
{
- ALOGV("android_media_SoundPool_release");
+ ALOGV("android_media_SoundPool_SoundPoolImpl_release");
SoundPool *ap = MusterSoundPool(env, thiz);
if (ap != NULL) {
@@ -219,67 +219,67 @@ android_media_SoundPool_release(JNIEnv *env, jobject thiz)
static JNINativeMethod gMethods[] = {
{ "_load",
"(Ljava/lang/String;I)I",
- (void *)android_media_SoundPool_load_URL
+ (void *)android_media_SoundPool_SoundPoolImpl_load_URL
},
{ "_load",
"(Ljava/io/FileDescriptor;JJI)I",
- (void *)android_media_SoundPool_load_FD
+ (void *)android_media_SoundPool_SoundPoolImpl_load_FD
},
{ "unload",
"(I)Z",
- (void *)android_media_SoundPool_unload
+ (void *)android_media_SoundPool_SoundPoolImpl_unload
},
{ "play",
"(IFFIIF)I",
- (void *)android_media_SoundPool_play
+ (void *)android_media_SoundPool_SoundPoolImpl_play
},
{ "pause",
"(I)V",
- (void *)android_media_SoundPool_pause
+ (void *)android_media_SoundPool_SoundPoolImpl_pause
},
{ "resume",
"(I)V",
- (void *)android_media_SoundPool_resume
+ (void *)android_media_SoundPool_SoundPoolImpl_resume
},
{ "autoPause",
"()V",
- (void *)android_media_SoundPool_autoPause
+ (void *)android_media_SoundPool_SoundPoolImpl_autoPause
},
{ "autoResume",
"()V",
- (void *)android_media_SoundPool_autoResume
+ (void *)android_media_SoundPool_SoundPoolImpl_autoResume
},
{ "stop",
"(I)V",
- (void *)android_media_SoundPool_stop
+ (void *)android_media_SoundPool_SoundPoolImpl_stop
},
{ "setVolume",
"(IFF)V",
- (void *)android_media_SoundPool_setVolume
+ (void *)android_media_SoundPool_SoundPoolImpl_setVolume
},
{ "setPriority",
"(II)V",
- (void *)android_media_SoundPool_setPriority
+ (void *)android_media_SoundPool_SoundPoolImpl_setPriority
},
{ "setLoop",
"(II)V",
- (void *)android_media_SoundPool_setLoop
+ (void *)android_media_SoundPool_SoundPoolImpl_setLoop
},
{ "setRate",
"(IF)V",
- (void *)android_media_SoundPool_setRate
+ (void *)android_media_SoundPool_SoundPoolImpl_setRate
},
{ "native_setup",
"(Ljava/lang/Object;III)I",
- (void*)android_media_SoundPool_native_setup
+ (void*)android_media_SoundPool_SoundPoolImpl_native_setup
},
{ "release",
"()V",
- (void*)android_media_SoundPool_release
+ (void*)android_media_SoundPool_SoundPoolImpl_release
}
};
-static const char* const kClassPathName = "android/media/SoundPool";
+static const char* const kClassPathName = "android/media/SoundPool$SoundPoolImpl";
jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
@@ -301,14 +301,14 @@ jint JNI_OnLoad(JavaVM* vm, void* reserved)
fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
if (fields.mNativeContext == NULL) {
- ALOGE("Can't find SoundPool.mNativeContext");
+ ALOGE("Can't find SoundPoolImpl.mNativeContext");
goto bail;
}
fields.mPostEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;IIILjava/lang/Object;)V");
if (fields.mPostEvent == NULL) {
- ALOGE("Can't find android/media/SoundPool.postEventFromNative");
+ ALOGE("Can't find android/media/SoundPoolImpl.postEventFromNative");
goto bail;
}