android_media_MediaCodec.cpp revision 0e97fc248eaea7b4c95053618ddedf0af638110e
188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber/*
288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Copyright 2012, The Android Open Source Project
388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * you may not use this file except in compliance with the License.
688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * You may obtain a copy of the License at
788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
1088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Unless required by applicable law or agreed to in writing, software
1188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * See the License for the specific language governing permissions and
1488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * limitations under the License.
1588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber */
1688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber//#define LOG_NDEBUG 0
1888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#define LOG_TAG "MediaCodec-JNI"
1988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <utils/Log.h>
2088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_MediaCodec.h"
2288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_Utils.h"
2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/AndroidRuntime.h"
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/android_view_Surface.h"
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h"
2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h"
2888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
298335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
308335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceTextureClient.h>
318335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
320e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h>
3388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
3488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
4388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
5688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
5888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
5988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
6088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
6188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
6288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
6388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
6488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
6688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,       // canCallJava
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            PRIORITY_DEFAULT);
7588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByType(mLooper, name, encoder);
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByComponentName(mLooper, name);
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec != NULL ? OK : NO_INIT;
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::~JMediaCodec() {
884484bdd2f99a753b0801f0c13ca8a2b7bc38695aAndreas Huber    mCodec->release();
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ISurfaceTexture> &surfaceTexture,
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<SurfaceTextureClient> client;
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (surfaceTexture != NULL) {
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        client = new SurfaceTextureClient(surfaceTexture);
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
1060e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber    return mCodec->configure(format, client, NULL /* crypto */, flags);
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->start();
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->stop();
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags) {
12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->queueInputBuffer(index, offset, size, timeUs, flags);
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->dequeueInputBuffer(index, timeoutUs);
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->dequeueOutputBuffer(
138c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber                    index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) {
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec$BufferInfo");
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID method = env->GetMethodID(clazz, "set", "(IIJI)V");
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) {
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
15388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
15488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const {
15788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->getOutputFormat(&msg)) != OK) {
16088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
16188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
16288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
17388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass byteBufferClass = env->FindClass("java/nio/ByteBuffer");
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            buffers.size(), byteBufferClass, NULL);
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuffer =
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->NewDirectByteBuffer(
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->base(),
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->capacity());
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->SetObjectArrayElement(
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                *bufArray, i, byteBuffer);
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->DeleteLocalRef(byteBuffer);
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        byteBuffer = NULL;
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> old = (JMediaCodec *)env->GetIntField(thiz, gFields.context);
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetIntField(thiz, gFields.context, (int)codec.get());
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return (JMediaCodec *)env->GetIntField(thiz, gFields.context);
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint throwExceptionAsNecessary(JNIEnv *env, status_t err) {
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
23388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
23488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
24088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        {
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(env, "java/lang/IllegalStateException", NULL);
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            break;
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
24988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return 0;
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<ISurfaceTexture> surfaceTexture;
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        sp<Surface> surface(Surface_getSurface(env, jsurface));
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            surfaceTexture = surface->getSurfaceTexture();
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    err = codec->configure(format, surfaceTexture, flags);
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            index, offset, size, timestampUs, flags);
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return index;
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
3910e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return index;
40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index, jboolean render) {
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->releaseOutputBuffer(index, render);
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject android_media_MediaCodec_getOutputFormat(
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getOutputFormat");
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
43088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getOutputFormat(env, &format);
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
44288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
44688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
45688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
45788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
46088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
46188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
46388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
46688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
46888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec");
46988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
47088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
47188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
47288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
47388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
47488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
47588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
47688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
47788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
47888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
47988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
48088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
48188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
48288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
48488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
48688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
48788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
48888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
49088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->initCheck();
49288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->ReleaseStringUTFChars(name, tmp);
49488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    tmp = NULL;
49588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
49788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
49888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
49988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
50088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to allocate component instance");
50188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
50288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
50388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
50588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
50688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
50888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
50988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
51088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
51188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
51388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaCodec_release },
51488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
51688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;I)V",
51788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
51888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "start", "()V", (void *)android_media_MediaCodec_start },
52088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "stop", "()V", (void *)android_media_MediaCodec_stop },
52188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "flush", "()V", (void *)android_media_MediaCodec_flush },
52288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "queueInputBuffer", "(IIIJI)V",
52488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
52588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueInputBuffer", "(J)I",
52788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
52888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
53088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
53188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "releaseOutputBuffer", "(IZ)V",
53388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
53488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getOutputFormat", "()Ljava/util/Map;",
53688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getOutputFormat },
53788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
53988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
54088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
54288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
54488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
54588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
54788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
54888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
54988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
55088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
55188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
55288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
55388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
554