android_media_MediaCodec.cpp revision 63834f4d23a97b27d830a301328329c7ef682bd5
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
307ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar#include <cutils/compiler.h>
317ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar
328335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
338335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
340e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
40bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h>
4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
448d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
45b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
46b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
56aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huberenum {
578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_CALLBACK = 1,
588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_SET_CALLBACK = 2,
59aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber};
60aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
615f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic struct CryptoErrorCodes {
623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorNoKey;
633ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorKeyExpired;
643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorResourceBusy;
65336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    jint cryptoErrorInsufficientOutputProtection;
663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker} gCryptoErrorCodes;
673ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
685f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic struct CodecActionCodes {
695f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jint codecActionTransient;
705f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jint codecActionRecoverable;
715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung} gCodecActionCodes;
725f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
75aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    jmethodID postEventFromNativeID;
7691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
7791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
7891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
7991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
8091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
8191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
928d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      mObject(NULL) {
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    cacheJavaObjects(env);
1007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
106aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            true,       // canCallJava
1078d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            PRIORITY_FOREGROUND);
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
1105f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus);
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
1125f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByComponentName(mLooper, name, &mInitStatus);
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
1145f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK((mCodec != NULL) != (mInitStatus != OK));
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::cacheJavaObjects(JNIEnv *env) {
1187de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jclass clazz = (jclass)env->FindClass("java/nio/ByteBuffer");
1197de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = (jclass)env->NewGlobalRef(clazz);
1207de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferClass != NULL);
1217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1227de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> byteOrderClass(
1237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("java/nio/ByteOrder"));
1247de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(byteOrderClass.get() != NULL);
1257de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1267de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID nativeOrderID = env->GetStaticMethodID(
1277de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
1287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(nativeOrderID != NULL);
1297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject nativeByteOrderObj =
1317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
1327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = env->NewGlobalRef(nativeByteOrderObj);
1337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mNativeByteOrderObj != NULL);
1347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(nativeByteOrderObj);
1357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    nativeByteOrderObj = NULL;
1367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = env->GetMethodID(
1387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass,
1397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "order",
1407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
1417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferOrderMethodID != NULL);
1427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = env->GetMethodID(
1447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
1457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferAsReadOnlyBufferMethodID != NULL);
1467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = env->GetMethodID(
1487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "position", "(I)Ljava/nio/Buffer;");
1497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferPositionMethodID != NULL);
1507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = env->GetMethodID(
1527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "limit", "(I)Ljava/nio/Buffer;");
1537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferLimitMethodID != NULL);
1547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
1557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
1575f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    return mInitStatus;
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
160aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Hubervoid JMediaCodec::registerSelf() {
161aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    mLooper->registerHandler(this);
162aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
163aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
164128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhangvoid JMediaCodec::release() {
165d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
166d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
167d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
1685f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mInitStatus = NO_INIT;
169d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
171128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mLooper != NULL) {
172128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->unregisterHandler(id());
173128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->stop();
174128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper.clear();
175128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
176128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang}
177128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
178128b012cc8c2369136bb8450bc91c81aebe18506Chong ZhangJMediaCodec::~JMediaCodec() {
179128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mCodec != NULL || mLooper != NULL) {
180128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* MediaCodec and looper should have been released explicitly already
181128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * in setMediaCodec() (see comments in setMediaCodec()).
182128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
183128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
184128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * message handler, doing release() there risks deadlock as MediaCodec::
185128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * release() post synchronous message to the same looper.
186128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
187128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Print a warning and try to proceed with releasing.
188128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
189128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
190128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        release();
191128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
192128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
193128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
2007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    deleteJavaObjects(env);
2017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
2027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::deleteJavaObjects(JNIEnv *env) {
2047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mByteBufferClass);
2057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = NULL;
2067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mNativeByteOrderObj);
2077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = NULL;
2087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = NULL;
2107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = NULL;
2117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = NULL;
2127de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = NULL;
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatus_t JMediaCodec::setCallback(jobject cb) {
2168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (cb != NULL) {
2178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        if (mCallbackNotification == NULL) {
21863834f4d23a97b27d830a301328329c7ef682bd5Lajos Molnar            mCallbackNotification = new AMessage(kWhatCallbackNotify, this);
2198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
2208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    } else {
2218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        mCallbackNotification.clear();
2228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
2238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
2248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->setCallback(mCallbackNotification);
2258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
2268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
229d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
2308240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
23252800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
233d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
234aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        mSurfaceTextureClient =
235aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            new Surface(bufferProducer, true /* controlledByApp */);
236b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
237b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
239b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
240b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2432621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
2442621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
2452621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
2462621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
2472621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
2498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->start();
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
253b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
254b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
2558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->stop();
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2621e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatus_t JMediaCodec::reset() {
2631e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    return mCodec->reset();
2641e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
2651e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
268bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
269bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
270bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
271bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
2759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
2769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
2779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
2789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
2799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
2809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
2819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
2829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
283bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
284bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
2859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
2869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
287bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
2889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
2899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
2918d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->dequeueInputBuffer(index, timeoutUs);
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
299aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    status_t err = mCodec->dequeueOutputBuffer(
300aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            index, &offset, &size, &timeUs, &flags, timeoutUs);
301aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
302aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    if (err != OK) {
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3068d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
3078d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3098d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
310fef85ef152ab176fd96dbe3047c8025136fa8560Ashok Bhat    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3157c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnarstatus_t JMediaCodec::releaseOutputBuffer(
3167c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
3177c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    if (updatePTS) {
3187c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
3197c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    }
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3252621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
3262621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
3272621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3282621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
329d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
332d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
333d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
334d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
335d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
336d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
337d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return ConvertMessageToMap(env, msg, format);
338d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
339d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
340d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
341d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<AMessage> msg;
342d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err;
343d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
3647de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            buffers.size(), mByteBufferClass, NULL);
365cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
366cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
367cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject byteBuffer = NULL;
3737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        err = createByteBufferFromABuffer(
3747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, !input /* readOnly */, true /* clearBuffer */, buffer, &byteBuffer);
3757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (err != OK) {
3767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            return err;
377cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
3787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (byteBuffer != NULL) {
3797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env->SetObjectArrayElement(
3807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                    *bufArray, i, byteBuffer);
3817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
382d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env->DeleteLocalRef(byteBuffer);
3837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer = NULL;
384d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        }
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3907de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar// static
3917de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::createByteBufferFromABuffer(
3927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<ABuffer> &buffer,
3937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject *buf) const {
394d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
395d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
3967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = NULL;
397d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
398d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
399d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
400d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
401d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject byteBuffer =
4027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->NewDirectByteBuffer(buffer->base(), buffer->capacity());
4037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (readOnly && byteBuffer != NULL) {
404d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jobject readOnlyBuffer = env->CallObjectMethod(
4057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                byteBuffer, mByteBufferAsReadOnlyBufferMethodID);
406d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(byteBuffer);
407d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        byteBuffer = readOnlyBuffer;
408d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
409d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (byteBuffer == NULL) {
410d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NO_MEMORY;
411d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
412d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject me = env->CallObjectMethod(
4137de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferOrderMethodID, mNativeByteOrderObj);
414d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
415d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
4167de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferLimitMethodID,
4177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? buffer->capacity() : (buffer->offset() + buffer->size()));
418d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
4197be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = env->CallObjectMethod(
4207de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferPositionMethodID,
4217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? 0 : buffer->offset());
4227be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
423d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = NULL;
424d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
425d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = byteBuffer;
426d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
427d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
428d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
4297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::getBuffer(
4307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
4317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> buffer;
4327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    status_t err =
4347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        input
4357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
4367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
4377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return err;
4407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    return createByteBufferFromABuffer(
4437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, buf);
4447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
4457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
446d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getImage(
447d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
448d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<ABuffer> buffer;
449d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
450d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
451d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
452d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
453d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
454d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
455d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
456d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
457d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
458d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
459d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
460d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
461d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = NULL;
462d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
463d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
464d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
465d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
466d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // check if buffer is an image
4677de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> imageData;
4687de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!buffer->meta()->findBuffer("image-data", &imageData)) {
4697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
4707de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4717de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int64_t timestamp = 0;
4737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!input && buffer->meta()->findInt64("timeUs", &timestamp)) {
4747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        timestamp *= 1000; // adjust to ns
4757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject byteBuffer = NULL;
4787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
4797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, &byteBuffer);
4807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
4827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4847de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject infoBuffer = NULL;
4857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
4867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, true /* readOnly */, true /* clearBuffer */, imageData, &infoBuffer);
4877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(byteBuffer);
4897de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        byteBuffer = NULL;
490d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
491d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
492d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
4937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject cropRect = NULL;
4947de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int32_t left, top, right, bottom;
4957de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (buffer->meta()->findRect("crop-rect", &left, &top, &right, &bottom)) {
4967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        ScopedLocalRef<jclass> rectClazz(
4977de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, env->FindClass("android/graphics/Rect"));
4987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        CHECK(rectClazz.get() != NULL);
4997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jmethodID rectConstructID = env->GetMethodID(
5017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), "<init>", "(IIII)V");
5027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = env->NewObject(
5047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), rectConstructID, left, top, right + 1, bottom + 1);
5057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> imageClazz(
5087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("android/media/MediaCodec$MediaImage"));
5097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(imageClazz.get() != NULL);
5107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID imageConstructID = env->GetMethodID(imageClazz.get(), "<init>",
5127de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;ZJIILandroid/graphics/Rect;)V");
5137de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5147de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = env->NewObject(imageClazz.get(), imageConstructID,
5157de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, infoBuffer,
5167de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jboolean)!input /* readOnly */,
5177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jlong)timestamp,
5187de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jint)0 /* xOffset */, (jint)0 /* yOffset */, cropRect);
5197de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5207de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    // if MediaImage creation fails, return null
5217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (env->ExceptionCheck()) {
5227de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionDescribe();
5237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionClear();
5247de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        *buf = NULL;
5257de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5267de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5277de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (cropRect != NULL) {
5287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(cropRect);
5297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = NULL;
5307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(byteBuffer);
5337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    byteBuffer = NULL;
5347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(infoBuffer);
5367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    infoBuffer = NULL;
5377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
538d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
539d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
540d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
541056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
542056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
543056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
544056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
545056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
546056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
547056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
548056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
549056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
550056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
551056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
552056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
553056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
554056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
555226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
556226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
557226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
558226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
559b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
560b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
561b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
562b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
563b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
564b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
5655f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic jthrowable createCodecException(
5665f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
5675f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jclass> clazz(
5685f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->FindClass("android/media/MediaCodec$CodecException"));
5695f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
5705f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;)V");
5725f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(ctor != NULL);
5735f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jstring> msgObj(
5755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err)));
5765f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5775f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    // translate action code to Java equivalent
5785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    switch (actionCode) {
5795f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_TRANSIENT:
5805f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionTransient;
5815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
5825f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_RECOVERABLE:
5835f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionRecoverable;
5845f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
5855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    default:
5865f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = 0;  // everything else is fatal
5875f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
5885f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    }
5895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get());
5915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
5925f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5938d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::handleCallback(const sp<AMessage> &msg) {
5948d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    int32_t arg1, arg2 = 0;
5958d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    jobject obj = NULL;
5968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    CHECK(msg->findInt32("callbackID", &arg1));
5978d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    JNIEnv *env = AndroidRuntime::getJNIEnv();
5988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (arg1) {
6008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_INPUT_AVAILABLE:
601aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6058d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6068d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_AVAILABLE:
6078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6088d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            size_t size, offset;
6118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            int64_t timeUs;
6128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            uint32_t flags;
6138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("size", &size));
6148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("offset", &offset));
6158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt64("timeUs", &timeUs));
6168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
6178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
6198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
6208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
6218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
6228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj = env->NewObject(clazz.get(), ctor);
6248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
6268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
6278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    ALOGE("Could not create MediaCodec.BufferInfo.");
6288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
6298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
6308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
632aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            }
633aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6348d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
635aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
636aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
637aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6388d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_ERROR:
639aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
64094686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            int32_t err, actionCode;
64194686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            CHECK(msg->findInt32("err", &err));
6428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("actionCode", &actionCode));
643aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            // note that DRM errors could conceivably alias into a CodecException
6455f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            obj = (jobject)createCodecException(env, err, actionCode);
646aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6478d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
6488d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
64994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    ALOGE("Could not create CodecException object.");
6508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
6518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
6528d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
655aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
656aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
657aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
658aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
660aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            sp<AMessage> format;
6628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findMessage("format", &format));
663aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6648d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (OK != ConvertMessageToMap(env, format, &obj)) {
6658d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6668d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
668aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
669aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
670aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
671aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
672aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        default:
673aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            TRESPASS();
674aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    }
6758d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6768d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->CallVoidMethod(
6778d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mObject,
6788d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            gFields.postEventFromNativeID,
6798d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            EVENT_CALLBACK,
6808d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg1,
6818d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg2,
6828d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj);
6838d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6848d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->DeleteLocalRef(obj);
685aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
686aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
6888d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (msg->what()) {
6898d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case kWhatCallbackNotify:
6908d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6918d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            handleCallback(msg);
6928d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6938d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6948d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        default:
6958d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            TRESPASS();
6968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
697aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
698aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
69988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
70088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
70288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
70488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
70688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
707075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
70888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
70988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
71088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
71188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
712128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* release MediaCodec and stop the looper now before decStrong.
713128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * otherwise JMediaCodec::~JMediaCodec() could be called from within
714128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * its message handler, doing release() from there will deadlock
715128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * (as MediaCodec::release() post synchronous message to the same looper)
716128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
717128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        old->release();
71888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
71988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
720075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
72188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
72388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
72488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
726075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
72788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7335f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) {
7345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jthrowable exception = createCodecException(env, err, actionCode, msg);
7355f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->Throw(exception);
7365f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
7375f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
738bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
7398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
7408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
7418d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
742bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
743bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
7448d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
745bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
746bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
747bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
748bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
7495f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    /* translate OS errors to Java API CryptoException errorCodes (which are positive) */
7503ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
7513ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
7523ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
7533ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7543ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
7553ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
7563ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7573ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
7583ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
7593ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
760336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
761336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
762336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            break;
7635f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        default:  /* Other negative DRM error codes go out as is. */
7643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7653ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
7663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
767bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
7688d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
769bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
770bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
771bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
772bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
773bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
7745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
7755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        const char *msg = NULL) {
77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
77788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
77888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
77988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
78188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
78288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        case INVALID_OPERATION:
7905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            jniThrowException(env, "java/lang/IllegalStateException", msg);
7915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
7923ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
7945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            if (isCryptoError(err)) {
7955f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                throwCryptoException(env, err, msg);
7965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                return 0;
7975f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            }
7985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            throwCodecException(env, err, actionCode, msg);
7995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
80188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatic void android_media_MediaCodec_native_setCallback(
8048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        JNIEnv *env,
8058d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject thiz,
8068d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject cb) {
8078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8088d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (codec == NULL) {
8105f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
8118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        return;
8128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
8138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    status_t err = codec->setCallback(cb);
8158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    throwExceptionAsNecessary(env, err);
8178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
8188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
81988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
82088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
82188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
82288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
82388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
8248240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
82588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
82788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
8295f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
83088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
83188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
83288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
83788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
83888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
83988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
84088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
841d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
84288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
84364a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
84488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
84552800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
84688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
84788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
84888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
84988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
85088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
85188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
85288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
85388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
85488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8558240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
8568240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
8578240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
8588240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
8598240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
860d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
86188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
86388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
86488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
8662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
8672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
8682621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8692621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8702621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
8715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
8722621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
8732621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
8742621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8752621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
8762621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
8772621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
8782621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
8792621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
8802621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
8812621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
8822621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
8842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
8852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
8862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
8872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
88888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
88988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
89088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
89188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
89288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
89388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
8945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
89588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
89688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
89788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
89888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
89988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
90188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
90288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
90488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
90588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
90788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
91088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
91188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
91288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
91488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
91688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
91788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9181e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatic void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
9191e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    ALOGV("android_media_MediaCodec_reset");
9201e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9211e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9221e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9231e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (codec == NULL) {
9245f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9251e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        return;
9261e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
9271e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9281e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    status_t err = codec->reset();
9291e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (err != OK) {
9301e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // treat all errors as fatal for now, though resource not available
9311e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // errors could be treated as transient.
9325f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // we also should avoid sending INVALID_OPERATION here due to
9335f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // the transitory nature of reset(), it should not inadvertently
9345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // trigger an IllegalStateException.
9355f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        err = UNKNOWN_ERROR;
9361e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
9371e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    throwExceptionAsNecessary(env, err);
9381e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
9391e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
94088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
94188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
94288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
94488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
94788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
94888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
94988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
95188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
95388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
95488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
95688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
95788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
95888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
95988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
96088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
96188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
96288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
96388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
96488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
96688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9685f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
96988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
97188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
972bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
973bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
97488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
975bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
97688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
977bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
9785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
97988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
98088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
9829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
9839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
9849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
9859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
98691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
9879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
9889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
9899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
9909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
9945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
9969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
9979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
99891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
99991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
100091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
100191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
100291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
100391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
100491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
100591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
100691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
100791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
100891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
100991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
101091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
101191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
101291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
101391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
101491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
101591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
101691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
10179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
10189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
10209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
10219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
10229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
10249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
10259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
10269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
10279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
10289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
10299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
10309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
10319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
10329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
10339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
10347ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // subSamples array may silently overflow if number of samples are too large.  Use
10357ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
10365f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
10377ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar        err = -EINVAL;
10389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
10399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
10409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
10429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
10439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
10449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
10459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
10479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
10489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
10499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
10509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
10529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
10549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
10559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
10569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
10589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
10599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
10609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
10639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
10649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
10659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
10669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
10699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
10709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
10719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
10729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
10769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
10779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
10789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
10799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
10809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
10819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
10859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
10869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
10879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
10889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
10899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
10909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1093bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1094bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
10959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
10969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
10979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
10989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
10999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
11009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
1101bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
1102bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
1103bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
11049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
11079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
11089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
11099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
11129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
11139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
11149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
11179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
11189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1119bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
11205f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
11219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
11229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
112388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
112488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
112588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
112688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
112788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
112888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
112988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11305f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
113188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
113288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
113388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
113488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
113588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
113688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
113788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1138075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
113988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
114088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
114288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
114388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
114588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
114688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
114788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
114988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
11520e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
115388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
115488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
115688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
115788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
115888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1160075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
116188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
116288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
116488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
116588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
11677c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        JNIEnv *env, jobject thiz,
11687c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
116988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
117088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
117288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
117588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
117688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
117788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11787c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
117988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
118188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
118288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
11842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
11852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
11862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11882621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
11895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
11902621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
11912621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11922621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11932621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
11942621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11952621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
11962621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
11972621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1198d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getFormatNative(
1199d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input) {
1200d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getFormatNative");
1201d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1202d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1203d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1204d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
12055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1206d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1207d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1208d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1209d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject format;
1210d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getFormat(env, input, &format);
1211d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1212d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1213d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return format;
1214d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1215d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1216d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    throwExceptionAsNecessary(env, err);
1217d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1218d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1219d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1220d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1221d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getOutputFormatForIndexNative(
1222d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jint index) {
1223d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
122488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
122588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
122688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
122788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12285f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
122988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
123088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
123188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
1233d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getOutputFormat(env, index, &format);
123488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
123688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
123788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
123888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
124088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
124288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
124388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
124588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
124688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
124788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
124988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
125288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
125388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
125488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
125688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
125788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
125988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
126088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
126188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1262cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
1263cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
1264cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
1265cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
126688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
126788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
126888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
126988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1270d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getBuffer(
1271d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1272d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getBuffer");
1273d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1274d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1275d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1276d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
12775f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1278d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1279d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1280d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1281d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject buffer;
1282d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getBuffer(env, input, index, &buffer);
1283d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1284d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1285d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return buffer;
1286d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1287d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1288d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1289d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1290d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1291d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1292d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1293d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1294d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1295d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1296d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getImage(
1297d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1298d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getImage");
1299d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1300d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1301d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1302d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
13035f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1304d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1305d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1306d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1307d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject image;
1308d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getImage(env, input, index, &image);
1309d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1310d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1311d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return image;
1312d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1313d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1314d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1315d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1316d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1317d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1318d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1319d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1320d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1321d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1322056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
1323056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
1324056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
1325056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1326056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1327056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1328056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
13295f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1330056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
1331056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1332056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1333056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
1334056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
1335056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1336056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
1337056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
1338056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1339056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1340056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
1341056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1342056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
1343056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
1344056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1345226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
1346226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
1347226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
1348226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1349226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1350226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1351226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
13525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1353226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
1354226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1355226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1356226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
1357226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
1358226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1359226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
1360226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
1361226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1362226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1363226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
1364226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
1365226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1366b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
1367b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
1368b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1369b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1370b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
13715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1372b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1373b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1374b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1375b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
1376b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
1377b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
1378b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1379b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1380b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1381b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
1382b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
1383b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
138488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
13858d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
13868d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
13878d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
138888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1389075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
139088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
139191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1392aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    gFields.postEventFromNativeID =
1393aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        env->GetMethodID(
1394aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber                clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
1395aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1396aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    CHECK(gFields.postEventFromNativeID != NULL);
1397aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
13988d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
13998d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
140091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
140191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
14028d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
140391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
140491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
140591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
14068d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
140791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
140891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
140991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
14108d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
141191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
141291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14138d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
141491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
141591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14168d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
141791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
141891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14198d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
142091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
14213ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14228d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
14238d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
14243ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14253ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jfieldID field;
14268d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
14273ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
14298d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14303ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14318d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
14323ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
14348d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14353ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14368d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
14373ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14388d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
14398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1441336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
1442336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    CHECK(field != NULL);
1443336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
1444336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1445336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker
14465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
14475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
14485f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
14495f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
14505f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionTransient =
14515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
14525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
14535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_RECOVERABLE", "I");
14545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
14555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionRecoverable =
14565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
145788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
145888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
146088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
146188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
146288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
14635f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/NullPointerException", NULL);
146488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
146588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
146688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
146888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
147088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
147188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
147288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
147488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    const status_t err = codec->initCheck();
14765f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    if (err == NAME_NOT_FOUND) {
14775f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // fail and do not try again.
14785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/IllegalArgumentException",
14795f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to initialize %s, error %#x", tmp, err));
14805f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
14815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        return;
14825f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if (err != OK) {
14835f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // believed possible to try again
14845f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/io/IOException",
14855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to find matching codec %s, error %#x", tmp, err));
14865f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
148788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
148888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
148988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->ReleaseStringUTFChars(name, tmp);
14915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1492aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    codec->registerSelf();
1493aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
149488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
149588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
149688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
149788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
149888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
149988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
150088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
150188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
150288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
1503d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_release", "()V", (void *)android_media_MediaCodec_release },
150488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15051e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
15061e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
15078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    { "native_setCallback",
15088d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      "(Landroid/media/MediaCodec$Callback;)V",
15098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      (void *)android_media_MediaCodec_native_setCallback },
15108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
151188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
15128240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
151307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
151488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
151588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15162621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
15172621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
15182621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1519d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_start", "()V", (void *)android_media_MediaCodec_start },
1520aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    { "native_stop", "()V", (void *)android_media_MediaCodec_stop },
1521d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
152288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1523d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueInputBuffer", "(IIIJI)V",
152488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
152588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1526d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
15279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
15289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1529d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueInputBuffer", "(J)I",
153088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
153188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1532d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
153388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
153488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15357c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    { "releaseOutputBuffer", "(IZZJ)V",
153688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
153788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15382621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
15392621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
15402621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1541d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getFormatNative", "(Z)Ljava/util/Map;",
1542d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getFormatNative },
1543d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1544d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getOutputFormatNative", "(I)Ljava/util/Map;",
1545d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
154688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
154788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
154888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
154988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1550d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
1551d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getBuffer },
1552d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1553d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getImage", "(ZI)Landroid/media/Image;",
1554d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getImage },
1555d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1556056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
1557056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
1558056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1559226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
1560226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
1561226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1562b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
1563b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
1564b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
156588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
156688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
156888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
156988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
157088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
157188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
157288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
157388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
157488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
157588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
157688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
157788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
1578