summaryrefslogtreecommitdiffstats
path: root/media/jni/android_media_MediaCodec.cpp
diff options
context:
space:
mode:
authorLajos Molnar <lajos@google.com>2014-07-11 15:12:59 -0700
committerLajos Molnar <lajos@google.com>2014-07-12 01:43:56 +0000
commitd4023114e8cf7ec7db4d07958a303699b658f2c0 (patch)
treeb9108d6fcc2f948f7eeca94a9727316e77e1e614 /media/jni/android_media_MediaCodec.cpp
parent06b6cdaed5c68816faac9d2354c6caf61e65e19d (diff)
downloadframeworks_base-d4023114e8cf7ec7db4d07958a303699b658f2c0.zip
frameworks_base-d4023114e8cf7ec7db4d07958a303699b658f2c0.tar.gz
frameworks_base-d4023114e8cf7ec7db4d07958a303699b658f2c0.tar.bz2
MediaCodec: add new buffer and format APIs
Bug: 14562236 Bug: 14297827 Bug: 13008204 Bug: 10706245 Bug: 10672559 Bug: 9175531 Change-Id: Ia94d34f625e532619a9ed344eb27e0d26647982f
Diffstat (limited to 'media/jni/android_media_MediaCodec.cpp')
-rw-r--r--media/jni/android_media_MediaCodec.cpp260
1 files changed, 245 insertions, 15 deletions
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index f9e4566..efdacfb 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -260,10 +260,21 @@ status_t JMediaCodec::signalEndOfInputStream() {
return mCodec->signalEndOfInputStream();
}
-status_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const {
+status_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
sp<AMessage> msg;
status_t err;
- if ((err = mCodec->getOutputFormat(&msg)) != OK) {
+ err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
+ if (err != OK) {
+ return err;
+ }
+
+ return ConvertMessageToMap(env, msg, format);
+}
+
+status_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
+ sp<AMessage> msg;
+ status_t err;
+ if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
return err;
}
@@ -295,6 +306,11 @@ status_t JMediaCodec::getBuffers(
CHECK(orderID != NULL);
+ jmethodID asReadOnlyBufferID = env->GetMethodID(
+ byteBufferClass.get(), "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
+
+ CHECK(asReadOnlyBufferID != NULL);
+
ScopedLocalRef<jclass> byteOrderClass(
env, env->FindClass("java/nio/ByteOrder"));
@@ -327,6 +343,12 @@ status_t JMediaCodec::getBuffers(
env->NewDirectByteBuffer(
buffer->base(),
buffer->capacity());
+ if (!input && byteBuffer != NULL) {
+ jobject readOnlyBuffer = env->CallObjectMethod(
+ byteBuffer, asReadOnlyBufferID);
+ env->DeleteLocalRef(byteBuffer);
+ byteBuffer = readOnlyBuffer;
+ }
if (byteBuffer == NULL) {
env->DeleteLocalRef(nativeByteOrderObj);
return NO_MEMORY;
@@ -349,6 +371,130 @@ status_t JMediaCodec::getBuffers(
return OK;
}
+status_t JMediaCodec::getBuffer(
+ JNIEnv *env, bool input, size_t index, jobject *buf) const {
+ sp<ABuffer> buffer;
+
+ status_t err =
+ input
+ ? mCodec->getInputBuffer(index, &buffer)
+ : mCodec->getOutputBuffer(index, &buffer);
+
+ if (err != OK) {
+ return err;
+ }
+
+ ScopedLocalRef<jclass> byteBufferClass(
+ env, env->FindClass("java/nio/ByteBuffer"));
+
+ CHECK(byteBufferClass.get() != NULL);
+
+ jmethodID orderID = env->GetMethodID(
+ byteBufferClass.get(),
+ "order",
+ "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
+
+ CHECK(orderID != NULL);
+
+ jmethodID asReadOnlyBufferID = env->GetMethodID(
+ byteBufferClass.get(), "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
+
+ CHECK(asReadOnlyBufferID != NULL);
+
+ jmethodID positionID = env->GetMethodID(
+ byteBufferClass.get(), "position", "(I)Ljava/nio/Buffer;");
+
+ CHECK(positionID != NULL);
+
+ jmethodID limitID = env->GetMethodID(
+ byteBufferClass.get(), "limit", "(I)Ljava/nio/Buffer;");
+
+ CHECK(limitID != NULL);
+
+ ScopedLocalRef<jclass> byteOrderClass(
+ env, env->FindClass("java/nio/ByteOrder"));
+
+ CHECK(byteOrderClass.get() != NULL);
+
+ jmethodID nativeOrderID = env->GetStaticMethodID(
+ byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
+ CHECK(nativeOrderID != NULL);
+
+ jobject nativeByteOrderObj =
+ env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
+ CHECK(nativeByteOrderObj != NULL);
+
+ // if this is an ABuffer that doesn't actually hold any accessible memory,
+ // use a null ByteBuffer
+ if (buffer->base() == NULL) {
+ *buf = NULL;
+ return OK;
+ }
+
+ jobject byteBuffer =
+ env->NewDirectByteBuffer(
+ buffer->base(),
+ buffer->capacity());
+ if (!input && byteBuffer != NULL) {
+ jobject readOnlyBuffer = env->CallObjectMethod(
+ byteBuffer, asReadOnlyBufferID);
+ env->DeleteLocalRef(byteBuffer);
+ byteBuffer = readOnlyBuffer;
+ }
+ if (byteBuffer == NULL) {
+ env->DeleteLocalRef(nativeByteOrderObj);
+ return NO_MEMORY;
+ }
+ jobject me = env->CallObjectMethod(
+ byteBuffer, orderID, nativeByteOrderObj);
+ env->DeleteLocalRef(me);
+ me = env->CallObjectMethod(
+ byteBuffer, positionID,
+ input ? 0 : buffer->offset());
+ env->DeleteLocalRef(me);
+ me = env->CallObjectMethod(
+ byteBuffer, limitID,
+ input ? buffer->capacity() : (buffer->offset() + buffer->size()));
+ env->DeleteLocalRef(me);
+ me = NULL;
+
+ env->DeleteLocalRef(nativeByteOrderObj);
+ nativeByteOrderObj = NULL;
+
+ *buf = byteBuffer;
+ return OK;
+}
+
+status_t JMediaCodec::getImage(
+ JNIEnv *env, bool input, size_t index, jobject *buf) const {
+ sp<ABuffer> buffer;
+
+ status_t err =
+ input
+ ? mCodec->getInputBuffer(index, &buffer)
+ : mCodec->getOutputBuffer(index, &buffer);
+
+ if (err != OK) {
+ return err;
+ }
+
+ // if this is an ABuffer that doesn't actually hold any accessible memory,
+ // use a null ByteBuffer
+ *buf = NULL;
+ if (buffer->base() == NULL) {
+ return OK;
+ }
+
+ // check if buffer is an image
+ AString imageData;
+ if (!buffer->meta()->findString("image-data", &imageData)) {
+ return OK;
+ }
+
+ return OK;
+}
+
+
status_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
AString name;
@@ -959,9 +1105,32 @@ static void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
throwExceptionAsNecessary(env, err);
}
-static jobject android_media_MediaCodec_getOutputFormatNative(
- JNIEnv *env, jobject thiz) {
- ALOGV("android_media_MediaCodec_getOutputFormatNative");
+static jobject android_media_MediaCodec_getFormatNative(
+ JNIEnv *env, jobject thiz, jboolean input) {
+ ALOGV("android_media_MediaCodec_getFormatNative");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+
+ jobject format;
+ status_t err = codec->getFormat(env, input, &format);
+
+ if (err == OK) {
+ return format;
+ }
+
+ throwExceptionAsNecessary(env, err);
+
+ return NULL;
+}
+
+static jobject android_media_MediaCodec_getOutputFormatForIndexNative(
+ JNIEnv *env, jobject thiz, jint index) {
+ ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
sp<JMediaCodec> codec = getMediaCodec(env, thiz);
@@ -971,7 +1140,7 @@ static jobject android_media_MediaCodec_getOutputFormatNative(
}
jobject format;
- status_t err = codec->getOutputFormat(env, &format);
+ status_t err = codec->getOutputFormat(env, index, &format);
if (err == OK) {
return format;
@@ -1008,6 +1177,58 @@ static jobjectArray android_media_MediaCodec_getBuffers(
return NULL;
}
+static jobject android_media_MediaCodec_getBuffer(
+ JNIEnv *env, jobject thiz, jboolean input, jint index) {
+ ALOGV("android_media_MediaCodec_getBuffer");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+
+ jobject buffer;
+ status_t err = codec->getBuffer(env, input, index, &buffer);
+
+ if (err == OK) {
+ return buffer;
+ }
+
+ // if we're out of memory, an exception was already thrown
+ if (err != NO_MEMORY) {
+ throwExceptionAsNecessary(env, err);
+ }
+
+ return NULL;
+}
+
+static jobject android_media_MediaCodec_getImage(
+ JNIEnv *env, jobject thiz, jboolean input, jint index) {
+ ALOGV("android_media_MediaCodec_getImage");
+
+ sp<JMediaCodec> codec = getMediaCodec(env, thiz);
+
+ if (codec == NULL) {
+ jniThrowException(env, "java/lang/IllegalStateException", NULL);
+ return NULL;
+ }
+
+ jobject image;
+ status_t err = codec->getImage(env, input, index, &image);
+
+ if (err == OK) {
+ return image;
+ }
+
+ // if we're out of memory, an exception was already thrown
+ if (err != NO_MEMORY) {
+ throwExceptionAsNecessary(env, err);
+ }
+
+ return NULL;
+}
+
static jobject android_media_MediaCodec_getName(
JNIEnv *env, jobject thiz) {
ALOGV("android_media_MediaCodec_getName");
@@ -1168,7 +1389,7 @@ static void android_media_MediaCodec_native_finalize(
}
static JNINativeMethod gMethods[] = {
- { "release", "()V", (void *)android_media_MediaCodec_release },
+ { "native_release", "()V", (void *)android_media_MediaCodec_release },
{ "native_setCallback",
"(Landroid/media/MediaCodec$Callback;)V",
@@ -1182,20 +1403,20 @@ static JNINativeMethod gMethods[] = {
{ "createInputSurface", "()Landroid/view/Surface;",
(void *)android_media_MediaCodec_createInputSurface },
- { "start", "()V", (void *)android_media_MediaCodec_start },
+ { "native_start", "()V", (void *)android_media_MediaCodec_start },
{ "native_stop", "()V", (void *)android_media_MediaCodec_stop },
- { "flush", "()V", (void *)android_media_MediaCodec_flush },
+ { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
- { "queueInputBuffer", "(IIIJI)V",
+ { "native_queueInputBuffer", "(IIIJI)V",
(void *)android_media_MediaCodec_queueInputBuffer },
- { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
+ { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
(void *)android_media_MediaCodec_queueSecureInputBuffer },
- { "dequeueInputBuffer", "(J)I",
+ { "native_dequeueInputBuffer", "(J)I",
(void *)android_media_MediaCodec_dequeueInputBuffer },
- { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
+ { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
(void *)android_media_MediaCodec_dequeueOutputBuffer },
{ "releaseOutputBuffer", "(IZZJ)V",
@@ -1204,12 +1425,21 @@ static JNINativeMethod gMethods[] = {
{ "signalEndOfInputStream", "()V",
(void *)android_media_MediaCodec_signalEndOfInputStream },
- { "getOutputFormatNative", "()Ljava/util/Map;",
- (void *)android_media_MediaCodec_getOutputFormatNative },
+ { "getFormatNative", "(Z)Ljava/util/Map;",
+ (void *)android_media_MediaCodec_getFormatNative },
+
+ { "getOutputFormatNative", "(I)Ljava/util/Map;",
+ (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
{ "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
(void *)android_media_MediaCodec_getBuffers },
+ { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
+ (void *)android_media_MediaCodec_getBuffer },
+
+ { "getImage", "(ZI)Landroid/media/Image;",
+ (void *)android_media_MediaCodec_getImage },
+
{ "getName", "()Ljava/lang/String;",
(void *)android_media_MediaCodec_getName },