android_media_MediaCodec.cpp revision 5e02ba977ede1e38c9f206057ec3f0f1e89ba943
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
2485e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnarstatus_t JMediaCodec::setSurface(
2495e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        const sp<IGraphicBufferProducer> &bufferProducer) {
2505e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<Surface> client;
2515e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (bufferProducer != NULL) {
2525e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        client = new Surface(bufferProducer, true /* controlledByApp */);
2535e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
2545e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    status_t err = mCodec->setSurface(client);
2555e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (err == OK) {
2565e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        mSurfaceTextureClient = client;
2575e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
2585e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    return err;
2595e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar}
2605e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
2612621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
2622621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
2632621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
2642621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
2652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
2678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->start();
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
271b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
272b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
2738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->stop();
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
27788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2801e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatus_t JMediaCodec::reset() {
2811e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    return mCodec->reset();
2821e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
2831e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
286bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
287bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
288bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
289bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
2939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
2949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
2959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
2969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
2979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
2989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
2999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
3009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
301bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
302bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
3039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
3049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
305bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
3069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
3079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
3098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->dequeueInputBuffer(index, timeoutUs);
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
317aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    status_t err = mCodec->dequeueOutputBuffer(
318aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            index, &offset, &size, &timeUs, &flags, timeoutUs);
319aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
320aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    if (err != OK) {
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3248d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
3258d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3278d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
328fef85ef152ab176fd96dbe3047c8025136fa8560Ashok Bhat    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3337c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnarstatus_t JMediaCodec::releaseOutputBuffer(
3347c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
3357c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    if (updatePTS) {
3367c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
3377c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    }
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3432621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
3442621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
3452621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3462621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
347d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
350d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
351d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
352d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
353d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
354d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
355d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return ConvertMessageToMap(env, msg, format);
356d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
357d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
358d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
359d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<AMessage> msg;
360d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err;
361d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
3827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            buffers.size(), mByteBufferClass, NULL);
383cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
384cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
385cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3907de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject byteBuffer = NULL;
3917de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        err = createByteBufferFromABuffer(
3927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, !input /* readOnly */, true /* clearBuffer */, buffer, &byteBuffer);
3937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (err != OK) {
3947de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            return err;
395cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
3967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (byteBuffer != NULL) {
3977de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env->SetObjectArrayElement(
3987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                    *bufArray, i, byteBuffer);
3997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
400d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env->DeleteLocalRef(byteBuffer);
4017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer = NULL;
402d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        }
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar// static
4097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::createByteBufferFromABuffer(
4107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<ABuffer> &buffer,
4117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject *buf) const {
412d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
413d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
4147de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = NULL;
415d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
416d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
417d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
418d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
419d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject byteBuffer =
4207de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->NewDirectByteBuffer(buffer->base(), buffer->capacity());
4217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (readOnly && byteBuffer != NULL) {
422d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jobject readOnlyBuffer = env->CallObjectMethod(
4237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                byteBuffer, mByteBufferAsReadOnlyBufferMethodID);
424d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(byteBuffer);
425d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        byteBuffer = readOnlyBuffer;
426d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
427d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (byteBuffer == NULL) {
428d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NO_MEMORY;
429d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
430d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject me = env->CallObjectMethod(
4317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferOrderMethodID, mNativeByteOrderObj);
432d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
433d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
4347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferLimitMethodID,
4357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? buffer->capacity() : (buffer->offset() + buffer->size()));
436d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
4377be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = env->CallObjectMethod(
4387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferPositionMethodID,
4397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? 0 : buffer->offset());
4407be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
441d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = NULL;
442d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
443d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = byteBuffer;
444d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
445d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
446d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
4477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::getBuffer(
4487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
4497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> buffer;
4507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    status_t err =
4527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        input
4537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
4547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
4557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4567de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4577de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return err;
4587de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4607de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    return createByteBufferFromABuffer(
4617de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, buf);
4627de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
4637de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
464d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getImage(
465d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
466d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<ABuffer> buffer;
467d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
468d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
469d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
470d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
471d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
472d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
473d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
474d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
475d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
476d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
477d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
478d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
479d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = NULL;
480d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
481d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
482d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
483d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
484d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // check if buffer is an image
4857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> imageData;
4867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!buffer->meta()->findBuffer("image-data", &imageData)) {
4877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
4887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4897de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4907de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int64_t timestamp = 0;
4917de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!input && buffer->meta()->findInt64("timeUs", &timestamp)) {
4927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        timestamp *= 1000; // adjust to ns
4937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
4947de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4957de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject byteBuffer = NULL;
4967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
4977de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, &byteBuffer);
4987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
4997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
5007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject infoBuffer = NULL;
5037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
5047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, true /* readOnly */, true /* clearBuffer */, imageData, &infoBuffer);
5057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(byteBuffer);
5077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        byteBuffer = NULL;
508d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
509d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
510d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
5117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject cropRect = NULL;
5127de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int32_t left, top, right, bottom;
5137de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (buffer->meta()->findRect("crop-rect", &left, &top, &right, &bottom)) {
5147de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        ScopedLocalRef<jclass> rectClazz(
5157de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, env->FindClass("android/graphics/Rect"));
5167de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        CHECK(rectClazz.get() != NULL);
5177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5187de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jmethodID rectConstructID = env->GetMethodID(
5197de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), "<init>", "(IIII)V");
5207de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5217de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = env->NewObject(
5227de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), rectConstructID, left, top, right + 1, bottom + 1);
5237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5247de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5257de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> imageClazz(
5267de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("android/media/MediaCodec$MediaImage"));
5277de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(imageClazz.get() != NULL);
5287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID imageConstructID = env->GetMethodID(imageClazz.get(), "<init>",
5307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;ZJIILandroid/graphics/Rect;)V");
5317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = env->NewObject(imageClazz.get(), imageConstructID,
5337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, infoBuffer,
5347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jboolean)!input /* readOnly */,
5357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jlong)timestamp,
5367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jint)0 /* xOffset */, (jint)0 /* yOffset */, cropRect);
5377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    // if MediaImage creation fails, return null
5397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (env->ExceptionCheck()) {
5407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionDescribe();
5417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionClear();
5427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        *buf = NULL;
5437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (cropRect != NULL) {
5467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(cropRect);
5477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = NULL;
5487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(byteBuffer);
5517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    byteBuffer = NULL;
5527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(infoBuffer);
5547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    infoBuffer = NULL;
5557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
556d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
557d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
558d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
559056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
560056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
561056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
562056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
563056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
564056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
565056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
566056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
567056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
568056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
569056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
570056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
571056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
572056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
573226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
574226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
575226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
576226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
577b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
578b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
579b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
580b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
581b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
582b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
5835f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic jthrowable createCodecException(
5845f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
5855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jclass> clazz(
5865f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->FindClass("android/media/MediaCodec$CodecException"));
5875f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
5885f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5899e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;I)V");
5905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(ctor != NULL);
5915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5925f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jstring> msgObj(
5935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err)));
5945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
5955f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    // translate action code to Java equivalent
5965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    switch (actionCode) {
5975f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_TRANSIENT:
5985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionTransient;
5995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_RECOVERABLE:
6015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionRecoverable;
6025f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6035f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    default:
6045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = 0;  // everything else is fatal
6055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6065f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    }
6075f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
608fb621e8737392ef10acbba083b46aedf6583c9a4Ronghua Wu    int reason =
609fb621e8737392ef10acbba083b46aedf6583c9a4Ronghua Wu        (err == DEAD_OBJECT) ? gExceptionReason.reasonReclaimed : gExceptionReason.reasonHardware;
6109e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get(), reason);
6115f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
6125f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::handleCallback(const sp<AMessage> &msg) {
6148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    int32_t arg1, arg2 = 0;
6158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    jobject obj = NULL;
6168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    CHECK(msg->findInt32("callbackID", &arg1));
6178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    JNIEnv *env = AndroidRuntime::getJNIEnv();
6188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (arg1) {
6208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_INPUT_AVAILABLE:
621aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_AVAILABLE:
6278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            size_t size, offset;
6318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            int64_t timeUs;
6328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            uint32_t flags;
6338d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("size", &size));
6348d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("offset", &offset));
6358d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt64("timeUs", &timeUs));
6368d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
6378d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6388d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
6398d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
6408d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
6418d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
6428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6438d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj = env->NewObject(clazz.get(), ctor);
6448d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6458d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
6468d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
6478d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    ALOGE("Could not create MediaCodec.BufferInfo.");
6488d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
6498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
6508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
652aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            }
653aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
655aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
656aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
657aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_ERROR:
659aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
66094686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            int32_t err, actionCode;
66194686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            CHECK(msg->findInt32("err", &err));
6628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("actionCode", &actionCode));
663aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6645f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            // note that DRM errors could conceivably alias into a CodecException
6655f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            obj = (jobject)createCodecException(env, err, actionCode);
666aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
6688d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
66994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    ALOGE("Could not create CodecException object.");
6708d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
6718d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
6728d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6748d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
675aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
676aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
677aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
678aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6798d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
680aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6818d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            sp<AMessage> format;
6828d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findMessage("format", &format));
683aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6848d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (OK != ConvertMessageToMap(env, format, &obj)) {
6858d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6868d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
688aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
689aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
690aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
691aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
692aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        default:
693aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            TRESPASS();
694aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    }
6958d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->CallVoidMethod(
6978d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mObject,
6988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            gFields.postEventFromNativeID,
6998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            EVENT_CALLBACK,
7008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg1,
7018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg2,
7028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj);
7038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->DeleteLocalRef(obj);
705aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
706aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
7088d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (msg->what()) {
7098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case kWhatCallbackNotify:
7108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
7118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            handleCallback(msg);
7128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
7138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
7148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        default:
7158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            TRESPASS();
7168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
717aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
718aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
71988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
72088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
72288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
72488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
72688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
727075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
732128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* release MediaCodec and stop the looper now before decStrong.
733128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * otherwise JMediaCodec::~JMediaCodec() could be called from within
734128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * its message handler, doing release() from there will deadlock
735128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * (as MediaCodec::release() post synchronous message to the same looper)
736128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
737128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        old->release();
73888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
73988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
740075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
74188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
74388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
74488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
746075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
74788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
74888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
75088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
75188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
75288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) {
7545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jthrowable exception = createCodecException(env, err, actionCode, msg);
7555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->Throw(exception);
7565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
7575f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
758bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
7598d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
7608d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
7618d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
762bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
763bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
7648d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
765bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
766bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
767bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
768bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
7695f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    /* translate OS errors to Java API CryptoException errorCodes (which are positive) */
7703ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
7713ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
7723ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
7733ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7743ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
7753ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
7763ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7773ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
7783ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
7793ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
780336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
781336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
782336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            break;
7835f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        default:  /* Other negative DRM error codes go out as is. */
7843ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7853ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
7863ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
787bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
7888d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
789bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
790bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
791bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
792bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
793bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
7945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
7955f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        const char *msg = NULL) {
79688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
79788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
79988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
80188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
80488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
80588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        case INVALID_OPERATION:
8105f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            jniThrowException(env, "java/lang/IllegalStateException", msg);
8115f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
8123ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8135e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        case BAD_VALUE:
8145e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            jniThrowException(env, "java/lang/IllegalArgumentException", msg);
8155e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            return 0;
8165e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
81788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
8185f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            if (isCryptoError(err)) {
8195f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                throwCryptoException(env, err, msg);
8205f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                return 0;
8215f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            }
8225f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            throwCodecException(env, err, actionCode, msg);
8235f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
82488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
82588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatic void android_media_MediaCodec_native_setCallback(
8288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        JNIEnv *env,
8298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject thiz,
8308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject cb) {
8318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8338d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (codec == NULL) {
8345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
8358d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        return;
8368d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
8378d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8388d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    status_t err = codec->setCallback(cb);
8398d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
8408d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    throwExceptionAsNecessary(env, err);
8418d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
8428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
84388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
84488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
84588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
84688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
84788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
8488240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
84988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
85088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
85188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
85288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
8535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
85488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
85588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
85688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
85788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
85888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
85988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
86188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
86288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
86388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
86488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
865d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
86688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
86764a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
86888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
86952800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
87088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
87188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
87288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
87388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
87488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
87588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
87688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
87788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
87888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8798240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
8808240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
8818240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
8828240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
8838240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
884d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
88588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
88688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
88788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
88888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8895e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnarstatic void android_media_MediaCodec_native_setSurface(
8905e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        JNIEnv *env,
8915e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        jobject thiz,
8925e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        jobject jsurface) {
8935e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8945e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
8955e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (codec == NULL) {
8965e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        throwExceptionAsNecessary(env, INVALID_OPERATION);
8975e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        return;
8985e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
8995e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
9005e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<IGraphicBufferProducer> bufferProducer;
9015e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (jsurface != NULL) {
9025e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
9035e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        if (surface != NULL) {
9045e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            bufferProducer = surface->getIGraphicBufferProducer();
9055e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        } else {
9065e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            jniThrowException(
9075e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    env,
9085e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    "java/lang/IllegalArgumentException",
9095e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    "The surface has been released");
9105e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            return;
9115e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        }
9125e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
9135e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
9145e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    status_t err = codec->setSurface(bufferProducer);
9155e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    throwExceptionAsNecessary(env, err);
9165e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar}
9175e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
9182621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
9192621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
9202621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
9212621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
9222621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9232621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
9245f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9252621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
9262621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
9272621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
9282621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
9292621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
9302621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
9312621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
9322621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
9332621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
9342621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
9352621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
9362621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
9372621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
9382621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
9392621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
9402621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
94188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
94288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
94388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
94588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
94888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
94988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
95088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
95288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
95488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
95588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
95788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
95888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
96088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9625f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
96388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
96488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
96588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
96788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
96988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9711e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatic void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
9721e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    ALOGV("android_media_MediaCodec_reset");
9731e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9741e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9751e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9761e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (codec == NULL) {
9775f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9781e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        return;
9791e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
9801e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
9811e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    status_t err = codec->reset();
9821e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (err != OK) {
9831e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // treat all errors as fatal for now, though resource not available
9841e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // errors could be treated as transient.
9855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // we also should avoid sending INVALID_OPERATION here due to
9865f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // the transitory nature of reset(), it should not inadvertently
9875f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // trigger an IllegalStateException.
9885f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        err = UNKNOWN_ERROR;
9891e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
9901e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    throwExceptionAsNecessary(env, err);
9911e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
9921e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
99388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
99488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
99588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
99688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
99788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
99888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
100088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
100188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
100288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
100388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
100488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
100588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
100688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
100788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
100888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
100988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
101088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
101188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
101288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
101388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
101488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
101588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
101688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
101788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
101888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
101988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
102088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
10215f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
102288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
102388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
102488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1025bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1026bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
102788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
1028bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
102988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1030bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
10315f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
103288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
103388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
10359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
10369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
10379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
10389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
103991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
10409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
10419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
10429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
10439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
10459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
10475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
10489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
10499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
105191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
105291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
105391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
105491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
105591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
105691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
105791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
105891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
105991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
106091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
106191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
106291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
106391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
106491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
106591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
106691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
106791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
106891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
106991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
10709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
10719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
10739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
10749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
10759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
10779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
10789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
10799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
10809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
10819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
10829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
10839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
10849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
10859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
10869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
10877ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // subSamples array may silently overflow if number of samples are too large.  Use
10887ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
10895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
10907ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar        err = -EINVAL;
10919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
10929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
10939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
10959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
10969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
10979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
10989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
11009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
11019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
11029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
11039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
11059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
11079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
11089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
11099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
11119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
11129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
11139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
11149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
11169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
11179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
11189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
11199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
11209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
11229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
11239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
11249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
11259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
11269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
11299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
11309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
11319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
11329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
11339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
11349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
11359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
11389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
11399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
11409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
11419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
11429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
11439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
11449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1146bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1147bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
11489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
11499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
11509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
11519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
11529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
11539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
1154bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
1155bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
1156bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
11579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
11609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
11619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
11629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
11659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
11669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
11679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
11689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
11699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
11709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
11719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1172bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
11735f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
11749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
11759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
117688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
117788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
117888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
117988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
118188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11835f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
118488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
118588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
118688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
118888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
118988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1191075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
119288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
119388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
119588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
119688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
119888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
119988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
120088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
120188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
120288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
120388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
12050e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
120688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
120788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
120888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
120988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
121088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
121188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
121288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1213075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
121488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
121588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
121688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
121788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
121888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
121988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
12207c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        JNIEnv *env, jobject thiz,
12217c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
122288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
122388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
122488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
122588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
122688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12275f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
122888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
122988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
123088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12317c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
123288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
123488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
123588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12362621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
12372621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
12382621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
12392621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
12402621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
12412621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
12425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
12432621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
12442621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
12452621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
12462621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
12472621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
12482621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
12492621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
12502621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1251d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getFormatNative(
1252d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input) {
1253d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getFormatNative");
1254d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1255d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1256d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1257d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
12585f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1259d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1260d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1261d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1262d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject format;
1263d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getFormat(env, input, &format);
1264d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1265d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1266d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return format;
1267d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1268d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1269d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    throwExceptionAsNecessary(env, err);
1270d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1271d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1272d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1273d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1274d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getOutputFormatForIndexNative(
1275d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jint index) {
1276d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
127788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
127888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
127988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
128088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
128288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
128388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
128488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
128588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
1286d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getOutputFormat(env, index, &format);
128788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
128888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
128988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
129088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
129188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
129288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
129388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
129488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
129588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
129688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
129788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
129888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
129988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
130088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
130188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
130288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
130388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
13045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
130588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
130688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
130788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
130888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
130988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
131088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
131188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
131288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
131388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
131488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1315cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
1316cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
1317cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
1318cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
131988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
132088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
132188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
132288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1323d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getBuffer(
1324d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1325d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getBuffer");
1326d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1327d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1328d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1329d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
13305f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1331d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1332d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1333d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1334d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject buffer;
1335d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getBuffer(env, input, index, &buffer);
1336d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1337d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1338d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return buffer;
1339d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1340d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1341d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1342d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1343d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1344d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1345d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1346d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1347d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1348d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1349d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getImage(
1350d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1351d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getImage");
1352d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1353d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1354d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1355d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
13565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1357d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1358d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1359d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1360d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject image;
1361d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getImage(env, input, index, &image);
1362d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1363d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1364d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return image;
1365d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1366d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1367d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1368d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1369d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1370d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1371d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1372d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1373d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1374d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1375056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
1376056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
1377056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
1378056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1379056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1380056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1381056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
13825f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1383056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
1384056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1385056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1386056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
1387056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
1388056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1389056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
1390056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
1391056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1392056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1393056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
1394056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1395056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
1396056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
1397056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1398226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
1399226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
1400226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
1401226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1402226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1403226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1404226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
14055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1406226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
1407226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1408226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1409226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
1410226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
1411226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1412226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
1413226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
1414226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1415226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1416226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
1417226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
1418226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1419b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
1420b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
1421b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1422b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1423b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
14245f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1425b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1426b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1427b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1428b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
1429b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
1430b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
1431b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1432b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1433b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1434b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
1435b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
1436b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
143788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
14388d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
14398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
14408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
144188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1442075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
144388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
144491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1445aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    gFields.postEventFromNativeID =
1446aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        env->GetMethodID(
1447aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber                clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
1448aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1449aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    CHECK(gFields.postEventFromNativeID != NULL);
1450aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
14518d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
14528d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
145391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
145491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
14558d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
145691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
145791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
145891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
14598d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
146091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
146191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
146291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
14638d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
146491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
146591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14668d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
146791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
146891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14698d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
147091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
147191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
14728d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
147391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
14743ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14758d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
14768d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
14773ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14783ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jfieldID field;
14798d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
14803ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14818d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
14828d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14833ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14848d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
14853ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14868d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
14878d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14883ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
14898d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
14903ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
14918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
14928d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
14935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1494336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
1495336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    CHECK(field != NULL);
1496336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
1497336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1498336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker
14995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
15005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
15015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
15025f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
15035f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionTransient =
15045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
15055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
15065f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_RECOVERABLE", "I");
15075f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
15085f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionRecoverable =
15095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
15109e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
15119e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "REASON_HARDWARE", "I");
15129e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
15139e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    gExceptionReason.reasonHardware =
15149e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
15159e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
15169e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "REASON_RECLAIMED", "I");
15179e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
15189e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    gExceptionReason.reasonReclaimed =
15199e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
152088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
152188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
152288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
152388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
152488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
152588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
15265f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/NullPointerException", NULL);
152788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
152888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
152988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
153088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
153188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
153288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
153388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
153488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
153588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
153688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
153788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15385f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    const status_t err = codec->initCheck();
15395f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    if (err == NAME_NOT_FOUND) {
15405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // fail and do not try again.
15415f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/IllegalArgumentException",
15425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to initialize %s, error %#x", tmp, err));
15435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
15445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        return;
15455f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if (err != OK) {
15465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // believed possible to try again
15475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/io/IOException",
15485f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to find matching codec %s, error %#x", tmp, err));
15495f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
155088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
155188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
155288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->ReleaseStringUTFChars(name, tmp);
15545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1555aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    codec->registerSelf();
1556aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
155788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
155888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
155988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
156188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
156288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
156388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
156488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
1566d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_release", "()V", (void *)android_media_MediaCodec_release },
156788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15681e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
15691e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
15708d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    { "native_setCallback",
15718d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      "(Landroid/media/MediaCodec$Callback;)V",
15728d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      (void *)android_media_MediaCodec_native_setCallback },
15738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
157488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
15758240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
157607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
157788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
157888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15795e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    { "native_setSurface",
15805e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar      "(Landroid/view/Surface;)V",
15815e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar      (void *)android_media_MediaCodec_native_setSurface },
15825e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
15832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
15842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
15852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1586d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_start", "()V", (void *)android_media_MediaCodec_start },
1587aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    { "native_stop", "()V", (void *)android_media_MediaCodec_stop },
1588d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
158988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1590d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueInputBuffer", "(IIIJI)V",
159188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
159288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1593d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
15949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
15959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1596d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueInputBuffer", "(J)I",
159788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
159888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1599d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
160088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
160188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16027c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    { "releaseOutputBuffer", "(IZZJ)V",
160388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
160488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
16052621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
16062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
16072621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1608d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getFormatNative", "(Z)Ljava/util/Map;",
1609d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getFormatNative },
1610d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1611d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getOutputFormatNative", "(I)Ljava/util/Map;",
1612d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
161388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
161488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
161588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
161688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1617d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
1618d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getBuffer },
1619d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1620d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getImage", "(ZI)Landroid/media/Image;",
1621d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getImage },
1622d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1623056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
1624056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
1625056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1626226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
1627226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
1628226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1629b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
1630b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
1631b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
163288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
163388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
163488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
163588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
163688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
163788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
163888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
163988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
164088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
164188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
164288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
164388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
164488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
1645