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
2307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber#include "android_media_MediaCrypto.h"
2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_Utils.h"
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/AndroidRuntime.h"
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/android_view_Surface.h"
2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h"
2888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h"
2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
308335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
318335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceTextureClient.h>
328335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
330e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h>
3488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
39bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h>
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
43b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
5591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
5691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
5791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
5891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
5991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
6091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
6191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
6288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
6388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
6588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
7588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,       // canCallJava
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            PRIORITY_DEFAULT);
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByType(mLooper, name, encoder);
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByComponentName(mLooper, name);
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec != NULL ? OK : NO_INIT;
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::~JMediaCodec() {
99d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
100d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
101d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
102d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ISurfaceTexture> &surfaceTexture,
1158240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<SurfaceTextureClient> client;
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (surfaceTexture != NULL) {
119b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture);
120b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
121b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
123b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
124b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->start();
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
132b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
133b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->stop();
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
14288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
143bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
144bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
145bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
146bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
1509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
1519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
1529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
1539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
1549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
1559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
1569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
1579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
158bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
159bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
1609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
1619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
162bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
1639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
1649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->dequeueInputBuffer(index, timeoutUs);
16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
17388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->dequeueOutputBuffer(
176c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber                    index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) {
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec$BufferInfo");
18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID method = env->GetMethodID(clazz, "set", "(IIJI)V");
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) {
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const {
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->getOutputFormat(&msg)) != OK) {
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass byteBufferClass = env->FindClass("java/nio/ByteBuffer");
2183dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(byteBufferClass != NULL);
2193dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2203dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID orderID = env->GetMethodID(
2213dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            byteBufferClass,
2223dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "order",
2233dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
2243dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2253dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(orderID != NULL);
2263dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2273dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jclass byteOrderClass = env->FindClass("java/nio/ByteOrder");
2283dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(byteOrderClass != NULL);
2293dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2303dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID nativeOrderID = env->GetStaticMethodID(
2313dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            byteOrderClass, "nativeOrder", "()Ljava/nio/ByteOrder;");
2323dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeOrderID != NULL);
2333dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2343dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jobject nativeByteOrderObj =
2353dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        env->CallStaticObjectMethod(byteOrderClass, nativeOrderID);
2363dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeByteOrderObj != NULL);
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            buffers.size(), byteBufferClass, NULL);
24088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuffer =
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->NewDirectByteBuffer(
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->base(),
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->capacity());
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2493dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        jobject me = env->CallObjectMethod(
2503dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber                byteBuffer, orderID, nativeByteOrderObj);
2513dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        env->DeleteLocalRef(me);
2523dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        me = NULL;
2533dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->SetObjectArrayElement(
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                *bufArray, i, byteBuffer);
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->DeleteLocalRef(byteBuffer);
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        byteBuffer = NULL;
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2613dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    env->DeleteLocalRef(nativeByteOrderObj);
2623dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    nativeByteOrderObj = NULL;
2633dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
267b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
268b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
269b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
270b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
271b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
272b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> old = (JMediaCodec *)env->GetIntField(thiz, gFields.context);
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetIntField(thiz, gFields.context, (int)codec.get());
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return (JMediaCodec *)env->GetIntField(thiz, gFields.context);
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
301bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
302bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec$CryptoException");
303bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(clazz != NULL);
304bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
305bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
306bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V");
307bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
308bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
309bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
310bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
311bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
312bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        (jthrowable)env->NewObject(clazz, constructID, err, msgObj);
313bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
314bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
315bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
316bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
317bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
318bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        JNIEnv *env, status_t err, const char *msg = NULL) {
319bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    if (err >= ERROR_DRM_WV_VENDOR_MIN && err <= ERROR_DRM_WV_VENDOR_MAX) {
320bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        // We'll throw our custom MediaCodec.CryptoException
321bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
322bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        throwCryptoException(env, err, msg);
323bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        return 0;
324bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    }
325bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        {
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(env, "java/lang/IllegalStateException", NULL);
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            break;
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return 0;
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
3548240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<ISurfaceTexture> surfaceTexture;
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
37364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            surfaceTexture = surface->getSurfaceTexture();
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3858240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
3868240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
3878240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
3888240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
3898240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
3908240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    err = codec->configure(format, surfaceTexture, crypto, flags);
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
43288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
44288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
44488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
44688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
457bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
458bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
45988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
460bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
46188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
462bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
463bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
4679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
4689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
4699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
4709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
47191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
4729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
4739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
4749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
4759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
4769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
4779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
4789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
4799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
4809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
4819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
4829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
48391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
48491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
48591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
48691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
48791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
48891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
48991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
49091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
49191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
49291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
49391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
49491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
49591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
49691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
49791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
49891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
49991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
50091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
50191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
5029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
5039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
5059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
5069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
5079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
5099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
5109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
5119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
5129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
5139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
5149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
5159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
5169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
5179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
5189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
5199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
5209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
5219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
5239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
5249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
5259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
5269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
5289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
5299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
5309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
5319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
5339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
5359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
5369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
5379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
5399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
5409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
5419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
5429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
5449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
5459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
5469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
5479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
5489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
5509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
5519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
5529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
5539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
5549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
5579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
5589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
5599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
5609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
5619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
5629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
5639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
5669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
5679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
5689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
5699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
5709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
5719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
5729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
574bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
575bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
5769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
5779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
5789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
5799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
5809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
5819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
582bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
583bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
584bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
5859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
5889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
5899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
5909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
5939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
5949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
5959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
5989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
5999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
600bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
601bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
6029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
6039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
60488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
60588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
60688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
60788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
60888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
60988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
61188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
61288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
61388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
61488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
61688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
61788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
61988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return index;
62088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
62188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
62288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
62388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
62488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
62588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
62688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
62788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
62888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
62988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
63088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
63188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
63288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
6330e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
63488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
63588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
63688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
63788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
63888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
63988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
64188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return index;
64288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
64388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
64588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
64688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
64888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index, jboolean render) {
64988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
65088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
65188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
65288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
65388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
65488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
65588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
65688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
65788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
65888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->releaseOutputBuffer(index, render);
65988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
66188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
66288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jobject android_media_MediaCodec_getOutputFormatNative(
66488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
66560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    ALOGV("android_media_MediaCodec_getOutputFormatNative");
66688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
66888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
67088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
67188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
67288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
67388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
67488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
67588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getOutputFormat(env, &format);
67688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
67788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
67888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
67988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
68088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
68188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
68288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
68388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
68488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
68588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
68688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
68788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
68888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
68988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
69088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
69188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
69288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
69388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
69488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
69588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
69688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
69788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
69888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
69988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
70188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
70288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
70388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
70588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
70788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
70888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
709b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
710b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
711b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
712b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
713b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
714b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
715b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
716b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
717b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
718b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
719b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
720b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
721b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
722b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
723b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
724b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
725b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
726b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
72788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec");
72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
73391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
73491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    clazz = env->FindClass("android/media/MediaCodec$CryptoInfo");
73591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(clazz != NULL);
73691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
73791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
73891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetFieldID(clazz, "numSubSamples", "I");
73991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
74091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
74191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
74291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetFieldID(clazz, "numBytesOfClearData", "[I");
74391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
74491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
74591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
74691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I");
74791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
74891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
74991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B");
75091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
75191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
75291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B");
75391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
75491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
75591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I");
75691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
75788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
75888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
75988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
76088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
76188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
76288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
76388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
76488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
76588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
76688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
76888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
77088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
77188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
77288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
77488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->initCheck();
77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->ReleaseStringUTFChars(name, tmp);
77888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    tmp = NULL;
77988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
78188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
78288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to allocate component instance");
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
79488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
79588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
79788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaCodec_release },
79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
8008240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
80107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "start", "()V", (void *)android_media_MediaCodec_start },
80588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "stop", "()V", (void *)android_media_MediaCodec_stop },
80688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "flush", "()V", (void *)android_media_MediaCodec_flush },
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "queueInputBuffer", "(IIIJI)V",
80988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
81088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
81191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
8129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
8139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
81488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueInputBuffer", "(J)I",
81588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
81688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
81788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
81888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
81988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "releaseOutputBuffer", "(IZ)V",
82188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
82288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getOutputFormatNative", "()Ljava/util/Map;",
82460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber      (void *)android_media_MediaCodec_getOutputFormatNative },
82588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
82788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
82888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
829b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
830b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
831b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
83288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
83388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
83688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
83888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
83988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
84088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
84288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
84388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
84488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
845