android_media_MediaCodec.cpp revision 4273dd03a83fd5f9ba25f3b7c3a4add7bce7206c
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>
354273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim#include <media/MediaCodecBuffer.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
41bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h>
4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
438034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang#include <media/stagefright/PersistentSurface.h>
448d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
458d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
46b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
47b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
57aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huberenum {
588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_CALLBACK = 1,
598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_SET_CALLBACK = 2,
60d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    EVENT_FRAME_RENDERED = 3,
61aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber};
62aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
635f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic struct CryptoErrorCodes {
643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorNoKey;
653ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorKeyExpired;
663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorResourceBusy;
67336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    jint cryptoErrorInsufficientOutputProtection;
6896a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    jint cryptoErrorSessionNotOpened;
69d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    jint cryptoErrorUnsupportedOperation;
703ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker} gCryptoErrorCodes;
713ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
725f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic struct CodecActionCodes {
735f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jint codecActionTransient;
745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jint codecActionRecoverable;
755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung} gCodecActionCodes;
765f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
77c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wustatic struct CodecErrorCodes {
78c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    jint errorInsufficientResource;
79c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    jint errorReclaimed;
80c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu} gCodecErrorCodes;
819e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
828034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic struct {
838034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jclass clazz;
848034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jfieldID mLock;
858034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jfieldID mPersistentObject;
868034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jmethodID ctor;
878034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jmethodID setNativeObjectLocked;
888034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang} gPersistentSurfaceClassInfo;
898034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
90d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinkerstatic struct {
91d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint Unencrypted;
92d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint AesCtr;
93d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint AesCbc;
94d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker} gCryptoModes;
95d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
96d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
99aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    jmethodID postEventFromNativeID;
10091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
10191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
10291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
10391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
10491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
10591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
106d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID cryptoInfoPatternID;
107d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID patternEncryptBlocksID;
108d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID patternSkipBlocksID;
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
1128034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic const void *sRefBaseOwner;
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
1208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      mObject(NULL) {
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1277de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    cacheJavaObjects(env);
1287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
134aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            true,       // canCallJava
1358d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            PRIORITY_FOREGROUND);
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
1385f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus);
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
1405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByComponentName(mLooper, name, &mInitStatus);
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
1425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK((mCodec != NULL) != (mInitStatus != OK));
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::cacheJavaObjects(JNIEnv *env) {
1467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jclass clazz = (jclass)env->FindClass("java/nio/ByteBuffer");
1477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = (jclass)env->NewGlobalRef(clazz);
1487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferClass != NULL);
1497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> byteOrderClass(
1517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("java/nio/ByteOrder"));
1527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(byteOrderClass.get() != NULL);
1537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID nativeOrderID = env->GetStaticMethodID(
1557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
1567de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(nativeOrderID != NULL);
1577de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1587de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject nativeByteOrderObj =
1597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
1607de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = env->NewGlobalRef(nativeByteOrderObj);
1617de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mNativeByteOrderObj != NULL);
1627de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(nativeByteOrderObj);
1637de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    nativeByteOrderObj = NULL;
1647de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1657de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = env->GetMethodID(
1667de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass,
1677de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "order",
1687de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
1697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferOrderMethodID != NULL);
1707de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1717de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = env->GetMethodID(
1727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
1737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferAsReadOnlyBufferMethodID != NULL);
1747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = env->GetMethodID(
1767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "position", "(I)Ljava/nio/Buffer;");
1777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferPositionMethodID != NULL);
1787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = env->GetMethodID(
1807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "limit", "(I)Ljava/nio/Buffer;");
1817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferLimitMethodID != NULL);
1827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
1837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
1855f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    return mInitStatus;
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
188aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Hubervoid JMediaCodec::registerSelf() {
189aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    mLooper->registerHandler(this);
190aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
191aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
192128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhangvoid JMediaCodec::release() {
193d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
194d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
195d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
1965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mInitStatus = NO_INIT;
197d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
199128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mLooper != NULL) {
200128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->unregisterHandler(id());
201128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->stop();
202128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper.clear();
203128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
204128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang}
205128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
206128b012cc8c2369136bb8450bc91c81aebe18506Chong ZhangJMediaCodec::~JMediaCodec() {
207128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mCodec != NULL || mLooper != NULL) {
208128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* MediaCodec and looper should have been released explicitly already
209128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * in setMediaCodec() (see comments in setMediaCodec()).
210128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
211128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
212128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * message handler, doing release() there risks deadlock as MediaCodec::
213128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * release() post synchronous message to the same looper.
214128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
215128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Print a warning and try to proceed with releasing.
216128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
217128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
218128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        release();
219128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
220128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
221128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
2287de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    deleteJavaObjects(env);
2297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
2307de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::deleteJavaObjects(JNIEnv *env) {
2327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mByteBufferClass);
2337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = NULL;
2347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mNativeByteOrderObj);
2357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = NULL;
2367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = NULL;
2387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = NULL;
2397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = NULL;
2407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = NULL;
24188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
243d8578577b02cf6360402eb8726e964d18b46434dLajos Molnarstatus_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
244d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    if (enable) {
245d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        if (mOnFrameRenderedNotification == NULL) {
246d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            mOnFrameRenderedNotification = new AMessage(kWhatFrameRendered, this);
247d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        }
248d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    } else {
249d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        mOnFrameRenderedNotification.clear();
250d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    }
251d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
252d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    return mCodec->setOnFrameRenderedNotification(mOnFrameRenderedNotification);
253d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar}
254d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
2558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatus_t JMediaCodec::setCallback(jobject cb) {
2568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (cb != NULL) {
2578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        if (mCallbackNotification == NULL) {
25863834f4d23a97b27d830a301328329c7ef682bd5Lajos Molnar            mCallbackNotification = new AMessage(kWhatCallbackNotify, this);
2598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
2608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    } else {
2618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        mCallbackNotification.clear();
2628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
2638d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
2648d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->setCallback(mCallbackNotification);
2658d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
2668d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
269d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
2708240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
27252800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
273d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
274aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        mSurfaceTextureClient =
275aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            new Surface(bufferProducer, true /* controlledByApp */);
276b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
277b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
279b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
280b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2835e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnarstatus_t JMediaCodec::setSurface(
2845e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        const sp<IGraphicBufferProducer> &bufferProducer) {
2855e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<Surface> client;
2865e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (bufferProducer != NULL) {
2875e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        client = new Surface(bufferProducer, true /* controlledByApp */);
2885e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
2895e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    status_t err = mCodec->setSurface(client);
2905e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (err == OK) {
2915e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        mSurfaceTextureClient = client;
2925e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
2935e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    return err;
2945e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar}
2955e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
2962621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
2972621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
2982621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
2992621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3002621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
3019560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhangstatus_t JMediaCodec::setInputSurface(
3028034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        const sp<PersistentSurface> &surface) {
3039560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    return mCodec->setInputSurface(surface);
3048034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
3058034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
3078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->start();
30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
311b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
312b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
3138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->stop();
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3201e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatus_t JMediaCodec::reset() {
3211e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    return mCodec->reset();
3221e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
3231e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
326bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
327bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
328bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
329bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
3339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
3349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
3359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
3369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
3379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
3389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
3399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
340d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        const CryptoPlugin::Pattern &pattern,
3419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
342bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
343bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
3449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
345d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker            index, offset, subSamples, numSubSamples, key, iv, mode, pattern,
346bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
3479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
3489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
3508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->dequeueInputBuffer(index, timeoutUs);
35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
35688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
358aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    status_t err = mCodec->dequeueOutputBuffer(
359aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            index, &offset, &size, &timeUs, &flags, timeoutUs);
360aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
361aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    if (err != OK) {
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3658d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
3668d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3688d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
369fef85ef152ab176fd96dbe3047c8025136fa8560Ashok Bhat    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3747c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnarstatus_t JMediaCodec::releaseOutputBuffer(
3757c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
3767c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    if (updatePTS) {
3777c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
3787c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    }
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
3852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
3862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
388d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
391d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
392d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
393d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
394d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
395d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
396d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return ConvertMessageToMap(env, msg, format);
397d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
398d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
399d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
400d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<AMessage> msg;
401d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err;
402d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
4114273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim    Vector<sp<MediaCodecBuffer> > buffers;
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
4237de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            buffers.size(), mByteBufferClass, NULL);
424cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
425cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
426cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
4294273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim        const sp<MediaCodecBuffer> &buffer = buffers.itemAt(i);
43088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject byteBuffer = NULL;
4327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        err = createByteBufferFromABuffer(
4337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, !input /* readOnly */, true /* clearBuffer */, buffer, &byteBuffer);
4347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (err != OK) {
4357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            return err;
436cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
4377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (byteBuffer != NULL) {
4387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env->SetObjectArrayElement(
4397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                    *bufArray, i, byteBuffer);
4407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
441d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env->DeleteLocalRef(byteBuffer);
4427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer = NULL;
443d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        }
44488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
44688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar// static
4504273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kimtemplate <typename T>
4517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::createByteBufferFromABuffer(
4524273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<T> &buffer,
4537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject *buf) const {
454d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
455d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
4567de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = NULL;
457e5b641e6effda54945577e9348df86213b38baebAaron Vaage
458e5b641e6effda54945577e9348df86213b38baebAaron Vaage    if (buffer == NULL) {
459e5b641e6effda54945577e9348df86213b38baebAaron Vaage        ALOGV("createByteBufferFromABuffer - given NULL, returning NULL");
460e5b641e6effda54945577e9348df86213b38baebAaron Vaage        return OK;
461e5b641e6effda54945577e9348df86213b38baebAaron Vaage    }
462e5b641e6effda54945577e9348df86213b38baebAaron Vaage
463d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
464d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
465d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
466d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
467d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject byteBuffer =
4687de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->NewDirectByteBuffer(buffer->base(), buffer->capacity());
4697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (readOnly && byteBuffer != NULL) {
470d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jobject readOnlyBuffer = env->CallObjectMethod(
4717de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                byteBuffer, mByteBufferAsReadOnlyBufferMethodID);
472d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(byteBuffer);
473d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        byteBuffer = readOnlyBuffer;
474d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
475d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (byteBuffer == NULL) {
476d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NO_MEMORY;
477d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
478d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject me = env->CallObjectMethod(
4797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferOrderMethodID, mNativeByteOrderObj);
480d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
481d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
4827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferLimitMethodID,
4837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? buffer->capacity() : (buffer->offset() + buffer->size()));
484d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
4857be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = env->CallObjectMethod(
4867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferPositionMethodID,
4877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? 0 : buffer->offset());
4887be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
489d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = NULL;
490d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
491d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = byteBuffer;
492d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
493d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
494d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
4957de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::getBuffer(
4967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
4974273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim    sp<MediaCodecBuffer> buffer;
4987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
4997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    status_t err =
5007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        input
5017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
5027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
5037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return err;
5067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    return createByteBufferFromABuffer(
5097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, buf);
5107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
5117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
512d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getImage(
513d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
5144273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim    sp<MediaCodecBuffer> buffer;
515d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
516d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
517d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
518d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
519d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
520d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
521d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
522d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
523d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
524d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
525d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
526d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
527d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = NULL;
528d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
529d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
530d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
531d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
532d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // check if buffer is an image
5337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> imageData;
5347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!buffer->meta()->findBuffer("image-data", &imageData)) {
5357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
5367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int64_t timestamp = 0;
5397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!input && buffer->meta()->findInt64("timeUs", &timestamp)) {
5407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        timestamp *= 1000; // adjust to ns
5417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject byteBuffer = NULL;
5447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
5457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, &byteBuffer);
5467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
5487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject infoBuffer = NULL;
5517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
5527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, true /* readOnly */, true /* clearBuffer */, imageData, &infoBuffer);
5537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(byteBuffer);
5557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        byteBuffer = NULL;
556d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
557d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
558d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
5597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject cropRect = NULL;
5607de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int32_t left, top, right, bottom;
5617de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (buffer->meta()->findRect("crop-rect", &left, &top, &right, &bottom)) {
5627de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        ScopedLocalRef<jclass> rectClazz(
5637de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, env->FindClass("android/graphics/Rect"));
5647de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        CHECK(rectClazz.get() != NULL);
5657de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5667de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jmethodID rectConstructID = env->GetMethodID(
5677de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), "<init>", "(IIII)V");
5687de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = env->NewObject(
5707de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), rectConstructID, left, top, right + 1, bottom + 1);
5717de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> imageClazz(
5747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("android/media/MediaCodec$MediaImage"));
5757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(imageClazz.get() != NULL);
5767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID imageConstructID = env->GetMethodID(imageClazz.get(), "<init>",
5787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;ZJIILandroid/graphics/Rect;)V");
5797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = env->NewObject(imageClazz.get(), imageConstructID,
5817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, infoBuffer,
5827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jboolean)!input /* readOnly */,
5837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jlong)timestamp,
5847de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jint)0 /* xOffset */, (jint)0 /* yOffset */, cropRect);
5857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    // if MediaImage creation fails, return null
5877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (env->ExceptionCheck()) {
5887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionDescribe();
5897de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionClear();
5907de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        *buf = NULL;
5917de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (cropRect != NULL) {
5947de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(cropRect);
5957de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = NULL;
5967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5977de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(byteBuffer);
5997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    byteBuffer = NULL;
6007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
6017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(infoBuffer);
6027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    infoBuffer = NULL;
6037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
604d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
605d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
606d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
607056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
608056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
609056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
610056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
611056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
612056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
613056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
614056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
615056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
616056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
617056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
618056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
619056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
620056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
621226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
622226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
623226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
624226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
625b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
626b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
627b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
628b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
629b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
630b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
6315f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic jthrowable createCodecException(
6325f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
6335f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jclass> clazz(
6345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->FindClass("android/media/MediaCodec$CodecException"));
6355f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
6365f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
637c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;)V");
6385f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(ctor != NULL);
6395f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jstring> msgObj(
6415f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err)));
6425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    // translate action code to Java equivalent
6445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    switch (actionCode) {
6455f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_TRANSIENT:
6465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionTransient;
6475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6485f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_RECOVERABLE:
6495f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionRecoverable;
6505f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    default:
6525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = 0;  // everything else is fatal
6535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    }
6555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
656c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    /* translate OS errors to Java API CodecException errorCodes */
657c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    switch (err) {
658c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        case NO_MEMORY:
659c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            err = gCodecErrorCodes.errorInsufficientResource;
660c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            break;
661c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        case DEAD_OBJECT:
662c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            err = gCodecErrorCodes.errorReclaimed;
663c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            break;
664c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        default:  /* Other error codes go out as is. */
665c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            break;
666c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    }
667c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu
668c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get());
6695f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
6705f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6718d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::handleCallback(const sp<AMessage> &msg) {
6728d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    int32_t arg1, arg2 = 0;
6738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    jobject obj = NULL;
6748d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    CHECK(msg->findInt32("callbackID", &arg1));
6758d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    JNIEnv *env = AndroidRuntime::getJNIEnv();
6768d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6778d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (arg1) {
6788d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_INPUT_AVAILABLE:
679aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6808d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6818d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6828d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6838d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6848d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_AVAILABLE:
6858d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6868d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6888d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            size_t size, offset;
6898d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            int64_t timeUs;
6908d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            uint32_t flags;
6918d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("size", &size));
6928d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("offset", &offset));
6938d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt64("timeUs", &timeUs));
6948d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
6958d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
6978d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
6988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
6998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
7008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj = env->NewObject(clazz.get(), ctor);
7028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
7048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
7058d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    ALOGE("Could not create MediaCodec.BufferInfo.");
7068d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
7078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
7088d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
7098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
710aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            }
711aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
713aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
714aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
715aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_ERROR:
717aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
71894686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            int32_t err, actionCode;
71994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            CHECK(msg->findInt32("err", &err));
7208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("actionCode", &actionCode));
721aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7225f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            // note that DRM errors could conceivably alias into a CodecException
7235f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            obj = (jobject)createCodecException(env, err, actionCode);
724aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
7268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
72794686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    ALOGE("Could not create CodecException object.");
7288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
7298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
7308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
7318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
7328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
733aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
734aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
735aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
736aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7378d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
738aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
7398d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            sp<AMessage> format;
7408d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findMessage("format", &format));
741aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (OK != ConvertMessageToMap(env, format, &obj)) {
7438d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
7448d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
7458d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
746aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
747aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
748aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
749aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
750aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        default:
751aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            TRESPASS();
752aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    }
7538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->CallVoidMethod(
7558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mObject,
7568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            gFields.postEventFromNativeID,
7578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            EVENT_CALLBACK,
7588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg1,
7598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg2,
7608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj);
7618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->DeleteLocalRef(obj);
763aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
764aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
765d8578577b02cf6360402eb8726e964d18b46434dLajos Molnarvoid JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
766d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    int32_t arg1 = 0, arg2 = 0;
767d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    jobject obj = NULL;
768d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    JNIEnv *env = AndroidRuntime::getJNIEnv();
769d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
770d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    sp<AMessage> data;
771d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    CHECK(msg->findMessage("data", &data));
772d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
773d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    status_t err = ConvertMessageToMap(env, data, &obj);
774d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    if (err != OK) {
775d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        jniThrowException(env, "java/lang/IllegalStateException", NULL);
776d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        return;
777d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    }
778d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
779d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    env->CallVoidMethod(
780d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            mObject, gFields.postEventFromNativeID,
781d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            EVENT_FRAME_RENDERED, arg1, arg2, obj);
782d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
783d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    env->DeleteLocalRef(obj);
784d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar}
785d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
7868d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
7878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (msg->what()) {
7888d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case kWhatCallbackNotify:
7898d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
7908d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            handleCallback(msg);
7918d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
7928d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
793d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        case kWhatFrameRendered:
794d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        {
795d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            handleFrameRenderedNotification(msg);
796d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            break;
797d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        }
7988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        default:
7998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            TRESPASS();
8008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
801aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
802aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
80488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
80688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
81088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
811075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
81288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
81388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
81488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
81588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
816128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* release MediaCodec and stop the looper now before decStrong.
817128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * otherwise JMediaCodec::~JMediaCodec() could be called from within
818128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * its message handler, doing release() from there will deadlock
819128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * (as MediaCodec::release() post synchronous message to the same looper)
820128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
821128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        old->release();
82288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
82388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
824075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
82588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
82788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
82888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
830075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
83188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
83288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
83688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8375f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) {
8385f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jthrowable exception = createCodecException(env, err, actionCode, msg);
8395f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->Throw(exception);
8405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
8415f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
842bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
8438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
8448d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
8458d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
846bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
847bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
8488d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
849bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
850bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
8513ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker    const char *defaultMsg = "Unknown Error";
852bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
8535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    /* translate OS errors to Java API CryptoException errorCodes (which are positive) */
8543ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
8553ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
8563ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
8573ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Crypto key not available";
8583ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
8593ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
8603ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
8613ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "License expired";
8623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
8633ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
8643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
8653ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Resource busy or unavailable";
8663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
867336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
868336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
8693ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Required output protections are not active";
870336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            break;
87196a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker        case ERROR_DRM_SESSION_NOT_OPENED:
87296a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker            err = gCryptoErrorCodes.cryptoErrorSessionNotOpened;
8733ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Attempted to use a closed session";
87496a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker            break;
875d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker        case ERROR_DRM_CANNOT_HANDLE:
876d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker            err = gCryptoErrorCodes.cryptoErrorUnsupportedOperation;
877d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker            defaultMsg = "Operation not supported in this configuration";
878d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker            break;
8795f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        default:  /* Other negative DRM error codes go out as is. */
8803ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
8813ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
8823ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8833ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : defaultMsg);
8843ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker
885bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
8868d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
887bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
888bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
889bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
890bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
891bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
8925f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
8935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        const char *msg = NULL) {
89488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
89588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
89688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
89788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
89888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
89988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
90088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
90288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
90388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
90588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
90688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9075f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        case INVALID_OPERATION:
9085f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            jniThrowException(env, "java/lang/IllegalStateException", msg);
9095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
9103ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
9115e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        case BAD_VALUE:
9125e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            jniThrowException(env, "java/lang/IllegalArgumentException", msg);
9135e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            return 0;
9145e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
91588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
9165f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            if (isCryptoError(err)) {
9175f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                throwCryptoException(env, err, msg);
9185f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                return 0;
9195f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            }
9205f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            throwCodecException(env, err, actionCode, msg);
9215f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
92288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
92388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
92488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
925d8578577b02cf6360402eb8726e964d18b46434dLajos Molnarstatic void android_media_MediaCodec_native_enableOnFrameRenderedListener(
926d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        JNIEnv *env,
927d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        jobject thiz,
928d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        jboolean enabled) {
929d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
930d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
931d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    if (codec == NULL) {
932d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        throwExceptionAsNecessary(env, INVALID_OPERATION);
933d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        return;
934d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    }
935d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
936d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    status_t err = codec->enableOnFrameRenderedListener(enabled);
937d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
938d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    throwExceptionAsNecessary(env, err);
939d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar}
940d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
9418d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatic void android_media_MediaCodec_native_setCallback(
9428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        JNIEnv *env,
9438d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject thiz,
9448d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject cb) {
9458d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9468d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
9478d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (codec == NULL) {
9485f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        return;
9508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
9518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
9528d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    status_t err = codec->setCallback(cb);
9538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
9548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    throwExceptionAsNecessary(env, err);
9558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
9568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
95788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
95888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
95988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
96088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
96188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
9628240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
96388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
96488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
96588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9675f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
96888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
96988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
97288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
97388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
97588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
97688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
97788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
97888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
979d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
98088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
98164a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
98288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
98352800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
98488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
98588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
98688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
98788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
98888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
98988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
99088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
99188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
99288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9938240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
9948240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
9958240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
9968240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
9978240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
998d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
99988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
100088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
100188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
100288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10035e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnarstatic void android_media_MediaCodec_native_setSurface(
10045e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        JNIEnv *env,
10055e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        jobject thiz,
10065e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        jobject jsurface) {
10075e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
10085e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10095e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (codec == NULL) {
10105e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        throwExceptionAsNecessary(env, INVALID_OPERATION);
10115e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        return;
10125e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
10135e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10145e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<IGraphicBufferProducer> bufferProducer;
10155e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (jsurface != NULL) {
10165e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
10175e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        if (surface != NULL) {
10185e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            bufferProducer = surface->getIGraphicBufferProducer();
10195e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        } else {
10205e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            jniThrowException(
10215e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    env,
10225e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    "java/lang/IllegalArgumentException",
10235e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    "The surface has been released");
10245e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            return;
10255e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        }
10265e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
10275e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10285e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    status_t err = codec->setSurface(bufferProducer);
10295e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    throwExceptionAsNecessary(env, err);
10305e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar}
10315e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10328034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangsp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface(
10338034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jobject object) {
10348034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface;
10358034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10368034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject lock = env->GetObjectField(
10378034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            object, gPersistentSurfaceClassInfo.mLock);
10388034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (env->MonitorEnter(lock) == JNI_OK) {
10398034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface = reinterpret_cast<PersistentSurface *>(
10408034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                env->GetLongField(object,
10418034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                        gPersistentSurfaceClassInfo.mPersistentObject));
10428034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->MonitorExit(lock);
10438034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10448034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    env->DeleteLocalRef(lock);
10458034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10468034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    return persistentSurface;
10478034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
10488034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10498034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic jobject android_media_MediaCodec_createPersistentInputSurface(
10508034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jclass /* clazz */) {
10518034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    ALOGV("android_media_MediaCodec_createPersistentInputSurface");
10528034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface =
10538034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        MediaCodec::CreatePersistentInputSurface();
10548034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10558034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (persistentSurface == NULL) {
10568034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return NULL;
10578034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10588034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10598034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<Surface> surface = new Surface(
10608034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            persistentSurface->getBufferProducer(), true);
10618034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (surface == NULL) {
10628034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return NULL;
10638034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10648034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10658034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject object = env->NewObject(
10668034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            gPersistentSurfaceClassInfo.clazz,
10678034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            gPersistentSurfaceClassInfo.ctor);
10688034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10698034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (object == NULL) {
10708034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        if (env->ExceptionCheck()) {
10718034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            ALOGE("Could not create PersistentSurface.");
10728034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            env->ExceptionClear();
10738034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        }
10748034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return NULL;
10758034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10768034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10778034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject lock = env->GetObjectField(
10788034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            object, gPersistentSurfaceClassInfo.mLock);
10798034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (env->MonitorEnter(lock) == JNI_OK) {
10808034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->CallVoidMethod(
10818034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                object,
10828034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                gPersistentSurfaceClassInfo.setNativeObjectLocked,
10838034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                (jlong)surface.get());
10848034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->SetLongField(
10858034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                object,
10868034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                gPersistentSurfaceClassInfo.mPersistentObject,
10878034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                (jlong)persistentSurface.get());
10888034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->MonitorExit(lock);
10898034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    } else {
10908034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->DeleteLocalRef(object);
10918034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        object = NULL;
10928034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10938034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    env->DeleteLocalRef(lock);
10948034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10958034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (object != NULL) {
10968034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        surface->incStrong(&sRefBaseOwner);
10978034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface->incStrong(&sRefBaseOwner);
10988034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10998034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11008034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    return object;
11018034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
11028034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11038034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic void android_media_MediaCodec_releasePersistentInputSurface(
11048034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jclass /* clazz */, jobject object) {
11058034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface;
11068034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11078034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject lock = env->GetObjectField(
11088034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            object, gPersistentSurfaceClassInfo.mLock);
11098034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (env->MonitorEnter(lock) == JNI_OK) {
11108034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface = reinterpret_cast<PersistentSurface *>(
11118034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            env->GetLongField(
11128034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                    object, gPersistentSurfaceClassInfo.mPersistentObject));
11138034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->SetLongField(
11148034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                object,
11158034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                gPersistentSurfaceClassInfo.mPersistentObject,
11168034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                (jlong)0);
11178034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->MonitorExit(lock);
11188034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11198034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    env->DeleteLocalRef(lock);
11208034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11218034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (persistentSurface != NULL) {
11228034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface->decStrong(&sRefBaseOwner);
11238034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11248034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    // no need to release surface as it will be released by Surface's jni
11258034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
11268034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11279560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhangstatic void android_media_MediaCodec_setInputSurface(
11288034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jobject thiz, jobject object) {
11299560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    ALOGV("android_media_MediaCodec_setInputSurface");
11308034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11318034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11328034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (codec == NULL) {
11338034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        throwExceptionAsNecessary(env, INVALID_OPERATION);
11348034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return;
11358034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11368034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11378034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface =
11388034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        android_media_MediaCodec_getPersistentInputSurface(env, object);
11398034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11409560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    status_t err = codec->setInputSurface(persistentSurface);
11418034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (err != NO_ERROR) {
11428034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        throwExceptionAsNecessary(env, err);
11438034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11448034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
11458034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11462621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
11472621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
11482621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
11492621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11502621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11512621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
11525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
11532621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
11542621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11552621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11562621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
11572621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
11582621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
11592621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
11602621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
11612621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
11622621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11632621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11642621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
11652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
11662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
11672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
11682621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
116988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
117088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
117188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
117388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
117688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
117788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
117888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
118088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
118288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
118388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
118588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
118688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
118888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
119188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
119288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
119388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
119588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
119788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
119888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11991e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatic void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
12001e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    ALOGV("android_media_MediaCodec_reset");
12011e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
12021e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
12031e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
12041e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (codec == NULL) {
12055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
12061e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        return;
12071e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
12081e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
12091e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    status_t err = codec->reset();
12101e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (err != OK) {
12111e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // treat all errors as fatal for now, though resource not available
12121e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // errors could be treated as transient.
12135f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // we also should avoid sending INVALID_OPERATION here due to
12145f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // the transitory nature of reset(), it should not inadvertently
12155f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // trigger an IllegalStateException.
12165f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        err = UNKNOWN_ERROR;
12171e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
12181e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    throwExceptionAsNecessary(env, err);
12191e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
12201e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
122188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
122288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
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
123188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
123288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
123488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
123588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
123688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
123788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
123888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
123988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
124088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
124188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
124288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
124388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
124488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
124588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
124788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12495f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
125088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
125188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
125288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1253bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1254bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
125588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
1256bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
125788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1258bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
12595f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
126088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
126188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
12639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
12649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
12659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
12669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
126791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
12689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
12699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
12709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
12719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
12729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
12739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
12749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
12755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
12769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
12779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
12789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
127991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
128091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
128191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
128291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
128391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
128491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
128591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
128691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
128791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
128891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
128991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
129091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
129191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
129291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
129391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
129491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
129591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1296d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint jmode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
1297d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    enum CryptoPlugin::Mode mode;
1298d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    if (jmode == gCryptoModes.Unencrypted) {
1299d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        mode = CryptoPlugin::kMode_Unencrypted;
1300d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    } else if (jmode == gCryptoModes.AesCtr) {
1301d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        mode = CryptoPlugin::kMode_AES_CTR;
1302d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    } else if (jmode == gCryptoModes.AesCbc) {
1303d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        mode = CryptoPlugin::kMode_AES_CBC;
1304d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    }  else {
1305d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        throwExceptionAsNecessary(env, INVALID_OPERATION);
1306d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        return;
1307d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    }
1308d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1309d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
1310d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1311d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CryptoPlugin::Pattern pattern;
1312e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker    if (patternObj == NULL) {
1313e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker        pattern.mEncryptBlocks = 0;
1314e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker        pattern.mSkipBlocks = 0;
1315e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker    } else {
1316d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
1317d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
1318d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    }
131991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
13209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
13219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
13239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
13249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
13259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
13279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
13289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
13299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
13309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
13319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
13329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
13339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
13349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
13359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
13369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
13377ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // subSamples array may silently overflow if number of samples are too large.  Use
13387ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
13395f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
13407ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar        err = -EINVAL;
13419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
13429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
13439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
13459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
13469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
13479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
13489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
13509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
13519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
13529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
13539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
13559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
13579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
13589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
13599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
13619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
13629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
13639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
13669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
13679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
13689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
13699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
13729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
13739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
13749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
13759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
13779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
13799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
13809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
13819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
13829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
13839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
13849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
13869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
13889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
13899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
13909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
13919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
13929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
13939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
13959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1396bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1397bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
13989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
13999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
14009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
14019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
14029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
1403d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker                mode,
1404d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker                pattern,
1405bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
1406bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
1407bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
14089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
14119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
14129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
14139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
14169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
14179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
14189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
14219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
14229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1423bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
14245f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
14259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
14269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
142788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
142888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
142988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
143088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
143188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
143288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
143388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
14345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
143588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
143688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
143788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
143888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
143988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
144088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
144188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1442075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
144388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
144488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
144588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
144688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
144788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
144888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
144988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
145088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
145188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
145388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
14555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
14560e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
145788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
145888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
146088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
146188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
146288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1464075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
146588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
146688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
146888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
146988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
14717c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        JNIEnv *env, jobject thiz,
14727c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
147388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
147488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
147688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
14785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
147988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
148088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
148188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14827c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
148388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
148488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
148588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
148688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
14882621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
14892621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
14902621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
14912621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
14922621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
14935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
14942621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
14952621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
14962621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
14972621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
14982621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
14992621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
15002621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
15012621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1502d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getFormatNative(
1503d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input) {
1504d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getFormatNative");
1505d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1506d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1507d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1508d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
15095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1510d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1511d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1512d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1513d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject format;
1514d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getFormat(env, input, &format);
1515d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1516d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1517d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return format;
1518d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1519d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1520d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    throwExceptionAsNecessary(env, err);
1521d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1522d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1523d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1524d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1525d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getOutputFormatForIndexNative(
1526d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jint index) {
1527d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
152888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
152988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
153088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
153188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
15325f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
153388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
153488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
153588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
153688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
1537d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getOutputFormat(env, index, &format);
153888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
153988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
154088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
154188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
154288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
154388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
154488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
154588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
154688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
154788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
154888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
154988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
155088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
155188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
155288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
155388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
155488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
15555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
155688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
155788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
155888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
155988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
156088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
156188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
156388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
156488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
156588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1566cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
1567cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
1568cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
1569cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
157088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
157188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
157288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
157388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1574d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getBuffer(
1575d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1576d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getBuffer");
1577d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1578d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1579d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1580d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
15815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1582d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1583d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1584d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1585d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject buffer;
1586d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getBuffer(env, input, index, &buffer);
1587d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1588d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1589d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return buffer;
1590d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1591d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1592d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1593d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1594d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1595d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1596d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1597d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1598d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1599d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1600d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getImage(
1601d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1602d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getImage");
1603d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1604d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1605d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1606d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
16075f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1608d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1609d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1610d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1611d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject image;
1612d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getImage(env, input, index, &image);
1613d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1614d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1615d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return image;
1616d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1617d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1618d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1619d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1620d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1621d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1622d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1623d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1624d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1625d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1626056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
1627056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
1628056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
1629056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1630056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1631056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1632056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
16335f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1634056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
1635056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1636056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1637056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
1638056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
1639056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1640056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
1641056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
1642056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1643056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1644056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
1645056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1646056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
1647056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
1648056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1649226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
1650226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
1651226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
1652226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1653226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1654226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1655226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
16565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1657226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
1658226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1659226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1660226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
1661226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
1662226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1663226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
1664226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
1665226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1666226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1667226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
1668226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
1669226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1670b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
1671b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
1672b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1673b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1674b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
16755f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1676b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1677b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1678b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1679b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
1680b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
1681b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
1682b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1683b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1684b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1685b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
1686b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
1687b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
168888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
16898d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
16908d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
16918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
169288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1693075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
169488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
169591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1696aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    gFields.postEventFromNativeID =
1697aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        env->GetMethodID(
1698aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber                clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
1699aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1700aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    CHECK(gFields.postEventFromNativeID != NULL);
1701aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1702d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID field;
1703d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_UNENCRYPTED", "I");
1704d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(field != NULL);
1705d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gCryptoModes.Unencrypted =
1706d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
1707d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1708d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CTR", "I");
1709d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(field != NULL);
1710d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gCryptoModes.AesCtr =
1711d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
1712d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1713d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CBC", "I");
1714d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(field != NULL);
1715d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gCryptoModes.AesCbc =
1716d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
1717d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
17188d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
17198d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
172091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
172191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
17228d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
172391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
172491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
172591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
17268d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
172791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
172891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
172991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
17308d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
173191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
173291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
17338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
173491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
173591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
17368d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
173791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
173891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
17398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
174091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
17413ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
1742d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gFields.cryptoInfoPatternID = env->GetFieldID(clazz.get(), "pattern",
1743d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        "Landroid/media/MediaCodec$CryptoInfo$Pattern;");
1744d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(gFields.cryptoInfoPatternID != NULL);
1745d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1746d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo$Pattern"));
1747d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(clazz.get() != NULL);
1748d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1749d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gFields.patternEncryptBlocksID = env->GetFieldID(clazz.get(), "mEncryptBlocks", "I");
1750d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(gFields.patternEncryptBlocksID != NULL);
1751d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1752d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gFields.patternSkipBlocksID = env->GetFieldID(clazz.get(), "mSkipBlocks", "I");
1753d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(gFields.patternSkipBlocksID != NULL);
1754d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
17558d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
17568d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
17573ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
17588d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
17593ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
17608d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
17618d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
17623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
17638d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
17643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
17658d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
17668d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
17673ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
17688d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
17693ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
17708d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
17718d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
17725f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1773336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
1774336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    CHECK(field != NULL);
1775336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
1776336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1777336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker
177896a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_SESSION_NOT_OPENED", "I");
177996a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    CHECK(field != NULL);
178096a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    gCryptoErrorCodes.cryptoErrorSessionNotOpened =
178196a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
178296a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker
1783d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_UNSUPPORTED_OPERATION", "I");
1784d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    CHECK(field != NULL);
1785d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    gCryptoErrorCodes.cryptoErrorUnsupportedOperation =
1786d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1787d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker
17885f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
17895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
17905f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
17915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
17925f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionTransient =
17935f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
17945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
17955f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_RECOVERABLE", "I");
17965f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
17975f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionRecoverable =
17985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
17999e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
1800c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_RESOURCE", "I");
18019e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
1802c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    gCodecErrorCodes.errorInsufficientResource =
18039e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
18049e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
1805c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "ERROR_RECLAIMED", "I");
18069e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
1807c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    gCodecErrorCodes.errorReclaimed =
18089e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
18098034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18108034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    clazz.reset(env->FindClass("android/view/Surface"));
18118034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(clazz.get() != NULL);
18128034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18138034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    field = env->GetFieldID(clazz.get(), "mLock", "Ljava/lang/Object;");
18148034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(field != NULL);
18158034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.mLock = field;
18168034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18178034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jmethodID method = env->GetMethodID(clazz.get(), "setNativeObjectLocked", "(J)V");
18188034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(method != NULL);
18198034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.setNativeObjectLocked = method;
18208034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18218034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    clazz.reset(env->FindClass("android/media/MediaCodec$PersistentSurface"));
18228034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(clazz.get() != NULL);
18238034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
18248034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18258034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    method = env->GetMethodID(clazz.get(), "<init>", "()V");
18268034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(method != NULL);
18278034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.ctor = method;
18288034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18298034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    field = env->GetFieldID(clazz.get(), "mPersistentObject", "J");
18308034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(field != NULL);
18318034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.mPersistentObject = field;
183288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
183388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
183488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
183588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
183688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
183788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
18385f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/NullPointerException", NULL);
183988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
184088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
184188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
184288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
184388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
184488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
184588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
184688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
184788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
184888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
184988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18505f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    const status_t err = codec->initCheck();
18515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    if (err == NAME_NOT_FOUND) {
18525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // fail and do not try again.
18535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/IllegalArgumentException",
18545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to initialize %s, error %#x", tmp, err));
1855c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        env->ReleaseStringUTFChars(name, tmp);
1856c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        return;
1857c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    } if (err == NO_MEMORY) {
1858c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        throwCodecException(env, err, ACTION_CODE_TRANSIENT,
1859c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu                String8::format("Failed to initialize %s, error %#x", tmp, err));
18605f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
18615f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        return;
18625f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if (err != OK) {
18635f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // believed possible to try again
18645f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/io/IOException",
18655f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to find matching codec %s, error %#x", tmp, err));
18665f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
186788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
186888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
186988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18705f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->ReleaseStringUTFChars(name, tmp);
18715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1872aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    codec->registerSelf();
1873aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
187488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
187588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
187688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
187788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
187888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
187988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
188088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
188188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
188276f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
1883d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_release", "()V", (void *)android_media_MediaCodec_release },
188488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18851e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
18861e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
18878034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    { "native_releasePersistentInputSurface",
18888034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang      "(Landroid/view/Surface;)V",
18898034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang       (void *)android_media_MediaCodec_releasePersistentInputSurface},
18908034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18918034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    { "native_createPersistentInputSurface",
18928034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang      "()Landroid/media/MediaCodec$PersistentSurface;",
18938034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang      (void *)android_media_MediaCodec_createPersistentInputSurface },
18948034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18959560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    { "native_setInputSurface", "(Landroid/view/Surface;)V",
18969560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang      (void *)android_media_MediaCodec_setInputSurface },
18978034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
1898d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    { "native_enableOnFrameRenderedListener", "(Z)V",
1899d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar      (void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
1900d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
19018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    { "native_setCallback",
19028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      "(Landroid/media/MediaCodec$Callback;)V",
19038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      (void *)android_media_MediaCodec_native_setCallback },
19048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
190588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
19068240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
190707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
190888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
190988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19105e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    { "native_setSurface",
19115e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar      "(Landroid/view/Surface;)V",
19125e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar      (void *)android_media_MediaCodec_native_setSurface },
19135e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
19142621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
19152621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
19162621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1917d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_start", "()V", (void *)android_media_MediaCodec_start },
1918aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    { "native_stop", "()V", (void *)android_media_MediaCodec_stop },
1919d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
192088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1921d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueInputBuffer", "(IIIJI)V",
192288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
192388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1924d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
19259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
19269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1927d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueInputBuffer", "(J)I",
192888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
192988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1930d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
193188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
193288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19337c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    { "releaseOutputBuffer", "(IZZJ)V",
193488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
193588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19362621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
19372621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
19382621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1939d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getFormatNative", "(Z)Ljava/util/Map;",
1940d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getFormatNative },
1941d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1942d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getOutputFormatNative", "(I)Ljava/util/Map;",
1943d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
194488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
194588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
194688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
194788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1948d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
1949d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getBuffer },
1950d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1951d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getImage", "(ZI)Landroid/media/Image;",
1952d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getImage },
1953d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1954056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
1955056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
1956056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1957226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
1958226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
1959226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1960b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
1961b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
1962b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
196388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
196488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
196588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
196688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
196788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
196888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
196988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
197088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
197188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
197288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
197388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
197488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
197588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
1976