android_media_MediaCodec.cpp revision 9e9ec943ce7620bbfcadc2f8986a80ac58003e47
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
739e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wustatic struct ExceptionReason {
749e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    jint reasonHardware;
759e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    jint reasonReclaimed;
769e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu} gExceptionReason;
779e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
80aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    jmethodID postEventFromNativeID;
8191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
8291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
8391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
8491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
8591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
8691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
978d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      mObject(NULL) {
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    cacheJavaObjects(env);
1057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
111aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            true,       // canCallJava
1128d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            PRIORITY_FOREGROUND);
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
1155f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus);
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
1175f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByComponentName(mLooper, name, &mInitStatus);
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
1195f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK((mCodec != NULL) != (mInitStatus != OK));
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1227de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::cacheJavaObjects(JNIEnv *env) {
1237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jclass clazz = (jclass)env->FindClass("java/nio/ByteBuffer");
1247de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = (jclass)env->NewGlobalRef(clazz);
1257de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferClass != NULL);
1267de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1277de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> byteOrderClass(
1287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("java/nio/ByteOrder"));
1297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(byteOrderClass.get() != NULL);
1307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID nativeOrderID = env->GetStaticMethodID(
1327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
1337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(nativeOrderID != NULL);
1347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject nativeByteOrderObj =
1367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
1377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = env->NewGlobalRef(nativeByteOrderObj);
1387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mNativeByteOrderObj != NULL);
1397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(nativeByteOrderObj);
1407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    nativeByteOrderObj = NULL;
1417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = env->GetMethodID(
1437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass,
1447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "order",
1457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
1467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferOrderMethodID != NULL);
1477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = env->GetMethodID(
1497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
1507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferAsReadOnlyBufferMethodID != NULL);
1517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = env->GetMethodID(
1537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "position", "(I)Ljava/nio/Buffer;");
1547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferPositionMethodID != NULL);
1557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1567de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = env->GetMethodID(
1577de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "limit", "(I)Ljava/nio/Buffer;");
1587de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferLimitMethodID != NULL);
1597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
1607de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
16188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
1625f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    return mInitStatus;
16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
165aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Hubervoid JMediaCodec::registerSelf() {
166aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    mLooper->registerHandler(this);
167aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
168aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
169128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhangvoid JMediaCodec::release() {
170d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
171d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
172d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
1735f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mInitStatus = NO_INIT;
174d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
176128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mLooper != NULL) {
177128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->unregisterHandler(id());
178128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->stop();
179128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper.clear();
180128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
181128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang}
182128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
183128b012cc8c2369136bb8450bc91c81aebe18506Chong ZhangJMediaCodec::~JMediaCodec() {
184128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mCodec != NULL || mLooper != NULL) {
185128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* MediaCodec and looper should have been released explicitly already
186128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * in setMediaCodec() (see comments in setMediaCodec()).
187128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
188128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
189128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * message handler, doing release() there risks deadlock as MediaCodec::
190128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * release() post synchronous message to the same looper.
191128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
192128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Print a warning and try to proceed with releasing.
193128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
194128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
195128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        release();
196128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
197128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
198128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
2057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    deleteJavaObjects(env);
2067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
2077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::deleteJavaObjects(JNIEnv *env) {
2097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mByteBufferClass);
2107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = NULL;
2117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mNativeByteOrderObj);
2127de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = NULL;
2137de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2147de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = NULL;
2157de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = NULL;
2167de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = NULL;
2177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = NULL;
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatus_t JMediaCodec::setCallback(jobject cb) {
2218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (cb != NULL) {
2228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        if (mCallbackNotification == NULL) {
22363834f4d23a97b27d830a301328329c7ef682bd5Lajos Molnar            mCallbackNotification = new AMessage(kWhatCallbackNotify, this);
2248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
2258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    } else {
2268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        mCallbackNotification.clear();
2278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
2288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
2298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->setCallback(mCallbackNotification);
2308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
2318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
23388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
234d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
2358240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
23752800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
238d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
239aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        mSurfaceTextureClient =
240aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            new Surface(bufferProducer, true /* controlledByApp */);
241b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
242b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
244b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
245b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2482621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
2492621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
2502621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
2512621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
2522621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
2548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->start();
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
258b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
259b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
2608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->stop();
26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2671e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatus_t JMediaCodec::reset() {
2681e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    return mCodec->reset();
2691e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
2701e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
273bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
274bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
275bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
276bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
2809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
2819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
2829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
2839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
2849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
2859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
2869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
2879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
288bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
289bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
2909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
2919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
292bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
2939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
2949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
2968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->dequeueInputBuffer(index, timeoutUs);
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
304aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    status_t err = mCodec->dequeueOutputBuffer(
305aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            index, &offset, &size, &timeUs, &flags, timeoutUs);
306aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
307aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    if (err != OK) {
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3118d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
3128d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3148d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
315fef85ef152ab176fd96dbe3047c8025136fa8560Ashok Bhat    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3207c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnarstatus_t JMediaCodec::releaseOutputBuffer(
3217c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
3227c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    if (updatePTS) {
3237c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
3247c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    }
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3302621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
3312621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
3322621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3332621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
334d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
337d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
338d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
339d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
340d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
341d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
342d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return ConvertMessageToMap(env, msg, format);
343d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
344d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
345d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
346d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<AMessage> msg;
347d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err;
348d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
3697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            buffers.size(), mByteBufferClass, NULL);
370cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
371cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
372cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject byteBuffer = NULL;
3787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        err = createByteBufferFromABuffer(
3797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, !input /* readOnly */, true /* clearBuffer */, buffer, &byteBuffer);
3807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (err != OK) {
3817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            return err;
382cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
3837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (byteBuffer != NULL) {
3847de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env->SetObjectArrayElement(
3857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                    *bufArray, i, byteBuffer);
3867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
387d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env->DeleteLocalRef(byteBuffer);
3887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer = NULL;
389d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        }
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3957de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar// static
3967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::createByteBufferFromABuffer(
3977de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<ABuffer> &buffer,
3987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject *buf) const {
399d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
400d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
4017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = NULL;
402d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
403d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
404d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
405d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
406d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject byteBuffer =
4077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->NewDirectByteBuffer(buffer->base(), buffer->capacity());
4087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (readOnly && byteBuffer != NULL) {
409d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jobject readOnlyBuffer = env->CallObjectMethod(
4107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                byteBuffer, mByteBufferAsReadOnlyBufferMethodID);
411d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(byteBuffer);
412d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        byteBuffer = readOnlyBuffer;
413d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
414d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (byteBuffer == NULL) {
415d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NO_MEMORY;
416d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
417d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject me = env->CallObjectMethod(
4187de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferOrderMethodID, mNativeByteOrderObj);
419d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
420d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
4217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferLimitMethodID,
4227de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? buffer->capacity() : (buffer->offset() + buffer->size()));
423d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
4247be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = env->CallObjectMethod(
4257de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferPositionMethodID,
4267de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? 0 : buffer->offset());
4277be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
428d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = NULL;
429d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
430d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = byteBuffer;
431d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
432d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
433d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
4347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::getBuffer(
4357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
4367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> buffer;
4377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    status_t err =
4397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        input
4407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
4417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
4427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return err;
4457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    return createByteBufferFromABuffer(
4487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, buf);
4497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
4507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
451d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getImage(
452d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
453d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<ABuffer> buffer;
454d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
455d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
456d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
457d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
458d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
459d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
460d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
461d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
462d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
463d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
464d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
465d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
466d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = NULL;
467d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
468d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
469d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
470d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
471d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // check if buffer is an image
4727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> imageData;
4737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!buffer->meta()->findBuffer("image-data", &imageData)) {
4747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
4757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int64_t timestamp = 0;
4787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!input && buffer->meta()->findInt64("timeUs", &timestamp)) {
4797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        timestamp *= 1000; // adjust to ns
4807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject byteBuffer = NULL;
4837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
4847de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, &byteBuffer);
4857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
4877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4897de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject infoBuffer = NULL;
4907de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
4917de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, true /* readOnly */, true /* clearBuffer */, imageData, &infoBuffer);
4927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(byteBuffer);
4947de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        byteBuffer = NULL;
495d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
496d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
497d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
4987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject cropRect = NULL;
4997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int32_t left, top, right, bottom;
5007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (buffer->meta()->findRect("crop-rect", &left, &top, &right, &bottom)) {
5017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        ScopedLocalRef<jclass> rectClazz(
5027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, env->FindClass("android/graphics/Rect"));
5037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        CHECK(rectClazz.get() != NULL);
5047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jmethodID rectConstructID = env->GetMethodID(
5067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), "<init>", "(IIII)V");
5077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = env->NewObject(
5097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), rectConstructID, left, top, right + 1, bottom + 1);
5107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5127de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> imageClazz(
5137de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("android/media/MediaCodec$MediaImage"));
5147de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(imageClazz.get() != NULL);
5157de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5167de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID imageConstructID = env->GetMethodID(imageClazz.get(), "<init>",
5177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;ZJIILandroid/graphics/Rect;)V");
5187de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5197de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = env->NewObject(imageClazz.get(), imageConstructID,
5207de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, infoBuffer,
5217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jboolean)!input /* readOnly */,
5227de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jlong)timestamp,
5237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jint)0 /* xOffset */, (jint)0 /* yOffset */, cropRect);
5247de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5257de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    // if MediaImage creation fails, return null
5267de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (env->ExceptionCheck()) {
5277de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionDescribe();
5287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionClear();
5297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        *buf = NULL;
5307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (cropRect != NULL) {
5337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(cropRect);
5347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = NULL;
5357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(byteBuffer);
5387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    byteBuffer = NULL;
5397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(infoBuffer);
5417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    infoBuffer = NULL;
5427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
543d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
544d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
545d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
546056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
547056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
548056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
549056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
550056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
551056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
552056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
553056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
554056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
555056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
556056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
557056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
558056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
559056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
560226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
561226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
562226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
563226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
564b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
565b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
566b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
567b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
568b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
569b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
5705f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic jthrowable createCodecException(
5715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
5725f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jclass> clazz(
5735f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->FindClass("android/media/MediaCodec$CodecException"));
5745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
5755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5769e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;I)V");
5775f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(ctor != NULL);
5785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5795f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jstring> msgObj(
5805f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err)));
5815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5825f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    // translate action code to Java equivalent
5835f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    switch (actionCode) {
5845f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_TRANSIENT:
5855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionTransient;
5865f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
5875f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_RECOVERABLE:
5885f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionRecoverable;
5895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
5905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    default:
5915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = 0;  // everything else is fatal
5925f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
5935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    }
5945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5959e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    // TODO: propagate reason from MediaCodec.
5969e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    int reason = gExceptionReason.reasonHardware;
5979e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get(), reason);
5985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
5995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::handleCallback(const sp<AMessage> &msg) {
6018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    int32_t arg1, arg2 = 0;
6028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    jobject obj = NULL;
6038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    CHECK(msg->findInt32("callbackID", &arg1));
6048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    JNIEnv *env = AndroidRuntime::getJNIEnv();
6058d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6068d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (arg1) {
6078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_INPUT_AVAILABLE:
608aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_AVAILABLE:
6148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            size_t size, offset;
6188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            int64_t timeUs;
6198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            uint32_t flags;
6208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("size", &size));
6218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("offset", &offset));
6228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt64("timeUs", &timeUs));
6238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
6248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
6268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
6278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
6288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
6298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj = env->NewObject(clazz.get(), ctor);
6318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
6338d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
6348d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    ALOGE("Could not create MediaCodec.BufferInfo.");
6358d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
6368d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
6378d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6388d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
639aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            }
640aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6418d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
642aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
643aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
644aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6458d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_ERROR:
646aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
64794686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            int32_t err, actionCode;
64894686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            CHECK(msg->findInt32("err", &err));
6498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("actionCode", &actionCode));
650aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            // note that DRM errors could conceivably alias into a CodecException
6525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            obj = (jobject)createCodecException(env, err, actionCode);
653aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
6558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
65694686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    ALOGE("Could not create CodecException object.");
6578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
6588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
6598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
662aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
663aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
664aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
665aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6668d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
667aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6688d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            sp<AMessage> format;
6698d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findMessage("format", &format));
670aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6718d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (OK != ConvertMessageToMap(env, format, &obj)) {
6728d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6748d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
675aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
676aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
677aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
678aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
679aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        default:
680aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            TRESPASS();
681aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    }
6828d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6838d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->CallVoidMethod(
6848d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mObject,
6858d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            gFields.postEventFromNativeID,
6868d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            EVENT_CALLBACK,
6878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg1,
6888d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg2,
6898d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj);
6908d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6918d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->DeleteLocalRef(obj);
692aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
693aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6948d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
6958d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (msg->what()) {
6968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case kWhatCallbackNotify:
6978d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            handleCallback(msg);
6998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
7008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
7018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        default:
7028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            TRESPASS();
7038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
704aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
705aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
70688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
70788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
70988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
71188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
71388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
714075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
71588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
71688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
71788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
71888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
719128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* release MediaCodec and stop the looper now before decStrong.
720128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * otherwise JMediaCodec::~JMediaCodec() could be called from within
721128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * its message handler, doing release() from there will deadlock
722128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * (as MediaCodec::release() post synchronous message to the same looper)
723128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
724128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        old->release();
72588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
72688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
727075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
733075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
73488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
73588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
73788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
73888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
73988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) {
7415f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jthrowable exception = createCodecException(env, err, actionCode, msg);
7425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->Throw(exception);
7435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
7445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
745bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
7468d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
7478d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
7488d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
749bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
750bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
7518d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
752bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
753bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
754bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
755bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
7565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    /* translate OS errors to Java API CryptoException errorCodes (which are positive) */
7573ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
7583ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
7593ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
7603ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7613ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
7623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
7633ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
7653ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
7663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
767336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
768336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
769336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            break;
7705f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        default:  /* Other negative DRM error codes go out as is. */
7713ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7723ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
7733ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
774bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
7758d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
776bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
777bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
778bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
779bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
780bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
7815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
7825f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        const char *msg = NULL) {
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
79488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
79588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        case INVALID_OPERATION:
7975f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            jniThrowException(env, "java/lang/IllegalStateException", msg);
7985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
7993ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
8015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            if (isCryptoError(err)) {
8025f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                throwCryptoException(env, err, msg);
8035f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                return 0;
8045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            }
8055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            throwCodecException(env, err, actionCode, msg);
8065f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
80988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatic void android_media_MediaCodec_native_setCallback(
8118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        JNIEnv *env,
8128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject thiz,
8138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject cb) {
8148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (codec == NULL) {
8175f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
8188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        return;
8198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
8208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    status_t err = codec->setCallback(cb);
8228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    throwExceptionAsNecessary(env, err);
8248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
8258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
82788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
82888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
82988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
83088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
8318240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
83288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
83388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
8365f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
83788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
83888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
83988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
84188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
84288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
84488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
84588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
84688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
84788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
848d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
84988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
85064a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
85188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
85252800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
85388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
85488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
85588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
85688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
85788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
85888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
85988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
86088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
86188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8628240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
8638240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
8648240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
8658240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
8668240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
867d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
86888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
87088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
87188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8722621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
8732621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
8742621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
8752621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8762621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8772621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
8785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
8792621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
8802621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
8812621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8822621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
8832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
8842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
8852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
8862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
8872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
8882621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
8892621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8902621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
8912621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
8922621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
8932621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
8942621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
89588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
89688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
89788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
89888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
89988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
90288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
90388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
90488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
90688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9075f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
90888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
90988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
91188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
91288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
91488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9165f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
91788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
91888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
91988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
92088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
92188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
92288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
92388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
92488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9251e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatic void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
9261e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    ALOGV("android_media_MediaCodec_reset");
9271e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9281e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9291e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9301e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (codec == NULL) {
9315f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9321e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        return;
9331e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
9341e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9351e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    status_t err = codec->reset();
9361e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (err != OK) {
9371e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // treat all errors as fatal for now, though resource not available
9381e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // errors could be treated as transient.
9395f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // we also should avoid sending INVALID_OPERATION here due to
9405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // the transitory nature of reset(), it should not inadvertently
9415f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // trigger an IllegalStateException.
9425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        err = UNKNOWN_ERROR;
9431e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
9441e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    throwExceptionAsNecessary(env, err);
9451e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
9461e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
94788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
94888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
94988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
95188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
95488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
95588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
95688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
95888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
96088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
96188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
96388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
96488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
96588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
96688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
96788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
96888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
96988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
97188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
97388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
97688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
97788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
97888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
979bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
980bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
98188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
982bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
98388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
984bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
9855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
98688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
98788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
9899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
9909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
9919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
9929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
99391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
9949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
9959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
9969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
9979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
10015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
10029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
10039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
100591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
100691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
100791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
100891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
100991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
101091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
101191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
101291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
101391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
101491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
101591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
101691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
101791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
101891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
101991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
102091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
102191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
102291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
102391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
10249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
10259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
10279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
10289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
10299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
10319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
10329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
10339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
10349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
10359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
10369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
10379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
10389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
10399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
10409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
10417ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // subSamples array may silently overflow if number of samples are too large.  Use
10427ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
10435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
10447ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar        err = -EINVAL;
10459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
10469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
10479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
10499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
10509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
10519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
10529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
10549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
10559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
10569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
10579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
10599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
10619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
10629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
10639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
10659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
10669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
10679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
10709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
10719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
10729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
10739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
10769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
10779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
10789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
10799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
10839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
10849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
10859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
10869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
10879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
10889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
10929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
10939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
10949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
10959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
10969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
10979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1100bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1101bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
11029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
11039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
11049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
11059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
11069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
11079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
1108bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
1109bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
1110bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
11119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
11149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
11159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
11169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
11199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
11209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
11219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
11249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
11259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1126bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
11275f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
11289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
11299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
113088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
113188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
113288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
113388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
113488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
113588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
113688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11375f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
113888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
113988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
114088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
114288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
114388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1145075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
114688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
114788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
114988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
115088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
115288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
115388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
115488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
115688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11585f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
11590e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
116088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
116188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
116388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
116488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
116588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1167075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
116888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
116988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
117188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
117288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
11747c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        JNIEnv *env, jobject thiz,
11757c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
117688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
117788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
117988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
118288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
118388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
118488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11857c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
118688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
118888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
118988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11902621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
11912621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
11922621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
11932621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11942621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11952621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
11965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
11972621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
11982621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11992621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
12002621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
12012621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
12022621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
12032621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
12042621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1205d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getFormatNative(
1206d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input) {
1207d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getFormatNative");
1208d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1209d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1210d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1211d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
12125f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1213d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1214d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1215d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1216d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject format;
1217d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getFormat(env, input, &format);
1218d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1219d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1220d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return format;
1221d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1222d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1223d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    throwExceptionAsNecessary(env, err);
1224d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1225d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1226d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1227d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1228d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getOutputFormatForIndexNative(
1229d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jint index) {
1230d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
123188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
123388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12355f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
123688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
123788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
123888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
1240d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getOutputFormat(env, index, &format);
124188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
124388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
124488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
124588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
124788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
124988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
125088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
125288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
125388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
125488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
125688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12585f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
125988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
126088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
126188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
126288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
126388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
126488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
126588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
126688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
126788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
126888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1269cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
1270cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
1271cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
1272cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
127388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
127488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
127588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
127688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1277d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getBuffer(
1278d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1279d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getBuffer");
1280d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1281d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1282d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1283d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
12845f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1285d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1286d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1287d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1288d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject buffer;
1289d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getBuffer(env, input, index, &buffer);
1290d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1291d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1292d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return buffer;
1293d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1294d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1295d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1296d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1297d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1298d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1299d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1300d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1301d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1302d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1303d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getImage(
1304d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1305d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getImage");
1306d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1307d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1308d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1309d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
13105f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1311d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1312d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1313d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1314d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject image;
1315d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getImage(env, input, index, &image);
1316d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1317d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1318d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return image;
1319d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1320d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1321d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1322d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1323d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1324d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1325d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1326d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1327d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1328d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1329056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
1330056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
1331056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
1332056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1333056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1334056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1335056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
13365f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1337056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
1338056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1339056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1340056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
1341056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
1342056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1343056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
1344056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
1345056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1346056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1347056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
1348056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1349056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
1350056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
1351056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1352226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
1353226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
1354226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
1355226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1356226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1357226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1358226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
13595f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1360226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
1361226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1362226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1363226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
1364226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
1365226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1366226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
1367226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
1368226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1369226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1370226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
1371226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
1372226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1373b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
1374b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
1375b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1376b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1377b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
13785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1379b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1380b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1381b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1382b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
1383b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
1384b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
1385b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1386b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1387b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1388b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
1389b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
1390b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
139188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
13928d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
13938d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
13948d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
139588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1396075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
139788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
139891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1399aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    gFields.postEventFromNativeID =
1400aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        env->GetMethodID(
1401aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber                clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
1402aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1403aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    CHECK(gFields.postEventFromNativeID != NULL);
1404aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
14058d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
14068d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
140791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
140891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
14098d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
141091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
141191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
141291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
14138d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
141491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
141591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
141691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
14178d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
141891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
141991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14208d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
142191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
142291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14238d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
142491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
142591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14268d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
142791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
14283ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14298d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
14308d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
14313ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14323ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jfieldID field;
14338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
14343ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14358d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
14368d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14373ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14388d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
14393ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
14418d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14423ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
14443ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14458d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
14468d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1448336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
1449336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    CHECK(field != NULL);
1450336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
1451336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1452336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker
14535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
14545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
14555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
14565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
14575f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionTransient =
14585f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
14595f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
14605f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_RECOVERABLE", "I");
14615f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
14625f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionRecoverable =
14635f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
14649e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
14659e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "REASON_HARDWARE", "I");
14669e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
14679e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    gExceptionReason.reasonHardware =
14689e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
14699e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
14709e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "REASON_RECLAIMED", "I");
14719e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
14729e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    gExceptionReason.reasonReclaimed =
14739e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
147488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
147588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
147788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
147888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
147988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
14805f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/NullPointerException", NULL);
148188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
148288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
148388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
148488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
148588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
148688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
148788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
148888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
148988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
149088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
149188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14925f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    const status_t err = codec->initCheck();
14935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    if (err == NAME_NOT_FOUND) {
14945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // fail and do not try again.
14955f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/IllegalArgumentException",
14965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to initialize %s, error %#x", tmp, err));
14975f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
14985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        return;
14995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if (err != OK) {
15005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // believed possible to try again
15015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/io/IOException",
15025f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to find matching codec %s, error %#x", tmp, err));
15035f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
150488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
150588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
150688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15075f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->ReleaseStringUTFChars(name, tmp);
15085f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1509aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    codec->registerSelf();
1510aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
151188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
151288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
151388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
151488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
151588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
151688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
151788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
151888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
151988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
1520d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_release", "()V", (void *)android_media_MediaCodec_release },
152188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15221e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
15231e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
15248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    { "native_setCallback",
15258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      "(Landroid/media/MediaCodec$Callback;)V",
15268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      (void *)android_media_MediaCodec_native_setCallback },
15278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
152888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
15298240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
153007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
153188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
153288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15332621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
15342621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
15352621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1536d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_start", "()V", (void *)android_media_MediaCodec_start },
1537aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    { "native_stop", "()V", (void *)android_media_MediaCodec_stop },
1538d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
153988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1540d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueInputBuffer", "(IIIJI)V",
154188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
154288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1543d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
15449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
15459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1546d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueInputBuffer", "(J)I",
154788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
154888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1549d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
155088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
155188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15527c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    { "releaseOutputBuffer", "(IZZJ)V",
155388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
155488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15552621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
15562621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
15572621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1558d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getFormatNative", "(Z)Ljava/util/Map;",
1559d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getFormatNative },
1560d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1561d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getOutputFormatNative", "(I)Ljava/util/Map;",
1562d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
156388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
156588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
156688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1567d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
1568d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getBuffer },
1569d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1570d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getImage", "(ZI)Landroid/media/Image;",
1571d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getImage },
1572d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1573056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
1574056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
1575056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1576226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
1577226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
1578226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1579b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
1580b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
1581b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
158288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
158388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
158488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
158588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
158688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
158788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
158888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
158988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
159088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
159188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
159288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
159388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
159488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
1595