android_media_MediaCodec.cpp revision 94686d13cacbec1ce7cf5fd0178fffb037d03cc1
188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber/*
288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Copyright 2012, The Android Open Source Project
388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * you may not use this file except in compliance with the License.
688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * You may obtain a copy of the License at
788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *     http://www.apache.org/licenses/LICENSE-2.0
988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *
1088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Unless required by applicable law or agreed to in writing, software
1188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
1288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * See the License for the specific language governing permissions and
1488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * limitations under the License.
1588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber */
1688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber//#define LOG_NDEBUG 0
1888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#define LOG_TAG "MediaCodec-JNI"
1988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <utils/Log.h>
2088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_MediaCodec.h"
2288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber#include "android_media_MediaCrypto.h"
2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_Utils.h"
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/AndroidRuntime.h"
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/android_view_Surface.h"
2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h"
2888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h"
2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
307ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar#include <cutils/compiler.h>
317ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar
328335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
338335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
340e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
40bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h>
4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
448d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
45b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
46b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
56aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huberenum {
578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_CALLBACK = 1,
588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_SET_CALLBACK = 2,
59aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber};
60aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
613ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinkerstruct CryptoErrorCodes {
623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorNoKey;
633ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorKeyExpired;
643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorResourceBusy;
653ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker} gCryptoErrorCodes;
663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
69aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    jmethodID postEventFromNativeID;
7091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
7191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
7291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
7391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
7491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
7591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
868d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      mObject(NULL) {
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
98aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            true,       // canCallJava
998d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            PRIORITY_FOREGROUND);
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByType(mLooper, name, encoder);
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByComponentName(mLooper, name);
10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec != NULL ? OK : NO_INIT;
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
112aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Hubervoid JMediaCodec::registerSelf() {
113aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    mLooper->registerHandler(this);
114aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
115aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
116128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhangvoid JMediaCodec::release() {
117d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
118d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
119d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
120d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
122128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mLooper != NULL) {
123128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->unregisterHandler(id());
124128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->stop();
125128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper.clear();
126128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
127128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang}
128128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
129128b012cc8c2369136bb8450bc91c81aebe18506Chong ZhangJMediaCodec::~JMediaCodec() {
130128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mCodec != NULL || mLooper != NULL) {
131128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* MediaCodec and looper should have been released explicitly already
132128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * in setMediaCodec() (see comments in setMediaCodec()).
133128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
134128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
135128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * message handler, doing release() there risks deadlock as MediaCodec::
136128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * release() post synchronous message to the same looper.
137128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
138128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Print a warning and try to proceed with releasing.
139128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
140128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
141128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        release();
142128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
143128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
144128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatus_t JMediaCodec::setCallback(jobject cb) {
1548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (cb != NULL) {
1558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        if (mCallbackNotification == NULL) {
1568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mCallbackNotification = new AMessage(kWhatCallbackNotify, id());
1578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
1588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    } else {
1598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        mCallbackNotification.clear();
1608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
1618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
1628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->setCallback(mCallbackNotification);
1638d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
1648d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
167d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
1688240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
17052800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
171d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
172aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        mSurfaceTextureClient =
173aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            new Surface(bufferProducer, true /* controlledByApp */);
174b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
175b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
177b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
178b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1812621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
1822621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
1832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
1842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
1852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
1878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->start();
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
191b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
192b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1938d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->stop();
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
202bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
203bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
204bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
205bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
2099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
2109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
2119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
2129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
2139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
2149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
2159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
2169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
217bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
218bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
2199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
2209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
221bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
2229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
2239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
2258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->dequeueInputBuffer(index, timeoutUs);
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
233aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    status_t err = mCodec->dequeueOutputBuffer(
234aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            index, &offset, &size, &timeUs, &flags, timeoutUs);
235aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
236aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    if (err != OK) {
23788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
23888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
23988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
2418d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
24288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
244fef85ef152ab176fd96dbe3047c8025136fa8560Ashok Bhat    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2497c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnarstatus_t JMediaCodec::releaseOutputBuffer(
2507c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
2517c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    if (updatePTS) {
2527c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
2537c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    }
25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2592621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
2602621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
2612621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
2622621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
263d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
266d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
267d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
268d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
269d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
270d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
271d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return ConvertMessageToMap(env, msg, format);
272d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
273d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
274d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
275d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<AMessage> msg;
276d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err;
277d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
27888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
29388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
29488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
29588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2978d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> byteBufferClass(
2988d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("java/nio/ByteBuffer"));
2998d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
3008d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(byteBufferClass.get() != NULL);
3013dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
3023dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID orderID = env->GetMethodID(
3038d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            byteBufferClass.get(),
3043dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "order",
3053dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
3063dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
3073dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(orderID != NULL);
3083dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
309d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jmethodID asReadOnlyBufferID = env->GetMethodID(
310d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBufferClass.get(), "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
311d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
312d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(asReadOnlyBufferID != NULL);
313d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
3148d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> byteOrderClass(
3158d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("java/nio/ByteOrder"));
3168d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
3178d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(byteOrderClass.get() != NULL);
3183dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
3193dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID nativeOrderID = env->GetStaticMethodID(
3208d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
3213dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeOrderID != NULL);
3223dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
3233dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jobject nativeByteOrderObj =
3248d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
3253dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeByteOrderObj != NULL);
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
3288d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            buffers.size(), byteBufferClass.get(), NULL);
329cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
330cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        env->DeleteLocalRef(nativeByteOrderObj);
331cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
332cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
337cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        // if this is an ABuffer that doesn't actually hold any accessible memory,
338cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        // use a null ByteBuffer
339cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        if (buffer->base() == NULL) {
340cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            continue;
341cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuffer =
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->NewDirectByteBuffer(
34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->base(),
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->capacity());
346d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        if (!input && byteBuffer != NULL) {
347d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            jobject readOnlyBuffer = env->CallObjectMethod(
348d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar                    byteBuffer, asReadOnlyBufferID);
349d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env->DeleteLocalRef(byteBuffer);
350d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBuffer = readOnlyBuffer;
351d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        }
352cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        if (byteBuffer == NULL) {
353cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            env->DeleteLocalRef(nativeByteOrderObj);
354cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            return NO_MEMORY;
355cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
3563dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        jobject me = env->CallObjectMethod(
3573dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber                byteBuffer, orderID, nativeByteOrderObj);
3583dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        env->DeleteLocalRef(me);
3593dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        me = NULL;
3603dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->SetObjectArrayElement(
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                *bufArray, i, byteBuffer);
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->DeleteLocalRef(byteBuffer);
36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        byteBuffer = NULL;
36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3683dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    env->DeleteLocalRef(nativeByteOrderObj);
3693dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    nativeByteOrderObj = NULL;
3703dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
374d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getBuffer(
375d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
376d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<ABuffer> buffer;
377d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
378d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
379d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
380d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
381d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
382d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
383d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
384d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
385d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
386d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
387d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ScopedLocalRef<jclass> byteBufferClass(
388d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env, env->FindClass("java/nio/ByteBuffer"));
389d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
390d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(byteBufferClass.get() != NULL);
391d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
392d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jmethodID orderID = env->GetMethodID(
393d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBufferClass.get(),
394d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            "order",
395d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
396d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
397d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(orderID != NULL);
398d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
399d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jmethodID asReadOnlyBufferID = env->GetMethodID(
400d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBufferClass.get(), "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
401d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
402d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(asReadOnlyBufferID != NULL);
403d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
404d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jmethodID positionID = env->GetMethodID(
405d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBufferClass.get(), "position", "(I)Ljava/nio/Buffer;");
406d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
407d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(positionID != NULL);
408d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
409d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jmethodID limitID = env->GetMethodID(
410d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBufferClass.get(), "limit", "(I)Ljava/nio/Buffer;");
411d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
412d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(limitID != NULL);
413d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
414d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ScopedLocalRef<jclass> byteOrderClass(
415d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env, env->FindClass("java/nio/ByteOrder"));
416d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
417d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(byteOrderClass.get() != NULL);
418d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
419d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jmethodID nativeOrderID = env->GetStaticMethodID(
420d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
421d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(nativeOrderID != NULL);
422d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
423d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject nativeByteOrderObj =
424d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
425d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    CHECK(nativeByteOrderObj != NULL);
426d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
427d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
428d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
429d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
430d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        *buf = NULL;
431d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
432d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
433d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
434d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject byteBuffer =
435d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->NewDirectByteBuffer(
436d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            buffer->base(),
437d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            buffer->capacity());
438d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (!input && byteBuffer != NULL) {
439d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jobject readOnlyBuffer = env->CallObjectMethod(
440d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar                byteBuffer, asReadOnlyBufferID);
441d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(byteBuffer);
442d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        byteBuffer = readOnlyBuffer;
443d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
444d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (byteBuffer == NULL) {
445d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(nativeByteOrderObj);
446d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NO_MEMORY;
447d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
448d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject me = env->CallObjectMethod(
449d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBuffer, orderID, nativeByteOrderObj);
450d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
451d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
452d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBuffer, positionID,
453d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            input ? 0 : buffer->offset());
454d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
455d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
456d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            byteBuffer, limitID,
457d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            input ? buffer->capacity() : (buffer->offset() + buffer->size()));
458d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
459d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = NULL;
460d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
461d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(nativeByteOrderObj);
462d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    nativeByteOrderObj = NULL;
463d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
464d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = byteBuffer;
465d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
466d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
467d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
468d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getImage(
469d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
470d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<ABuffer> buffer;
471d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
472d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
473d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
474d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
475d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
476d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
477d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
478d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
479d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
480d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
481d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
482d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
483d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = NULL;
484d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
485d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
486d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
487d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
488d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // check if buffer is an image
489d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    AString imageData;
490d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (!buffer->meta()->findString("image-data", &imageData)) {
491d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
492d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
493d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
494d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
495d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
496d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
497d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
498056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
499056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
500056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
501056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
502056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
503056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
504056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
505056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
506056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
507056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
508056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
509056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
510056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
511056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
512226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
513226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
514226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
515226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
516b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
517b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
518b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
519b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
520b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
521b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
5228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::handleCallback(const sp<AMessage> &msg) {
5238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    int32_t arg1, arg2 = 0;
5248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    jobject obj = NULL;
5258d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    CHECK(msg->findInt32("callbackID", &arg1));
5268d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    JNIEnv *env = AndroidRuntime::getJNIEnv();
5278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (arg1) {
5298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_INPUT_AVAILABLE:
530aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
5318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
5328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
5338d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
5348d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5358d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_AVAILABLE:
5368d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
5378d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
5388d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5398d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            size_t size, offset;
5408d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            int64_t timeUs;
5418d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            uint32_t flags;
5428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("size", &size));
5438d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("offset", &offset));
5448d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt64("timeUs", &timeUs));
5458d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
5468d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5478d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
5488d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
5498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
5508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
5518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5528d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj = env->NewObject(clazz.get(), ctor);
5538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
5548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
5558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
5568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    ALOGE("Could not create MediaCodec.BufferInfo.");
5578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
5588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
5598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
5608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
561aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            }
562aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
5638d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
564aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
565aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
566aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
5678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_ERROR:
568aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
56994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            int32_t err, actionCode;
57094686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            CHECK(msg->findInt32("err", &err));
5718d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("actionCode", &actionCode));
572aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
5738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            // use Integer object to pass the action code
5748d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
57594686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    env, env->FindClass("android/media/MediaCodec$CodecException"));
57694686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;)V");
57794686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang
57894686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            AString str;
57994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            const char *detail = "Unknown error";
58094686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            if (msg->findString("detail", &str)) {
58194686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                detail = str.c_str();
58294686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            }
58394686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            jstring msgObj = env->NewStringUTF(detail);
58494686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang
58594686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            obj = env->NewObject(clazz.get(), ctor, err, actionCode, msgObj);
586aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
5878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
5888d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
58994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    ALOGE("Could not create CodecException object.");
5908d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
5918d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
5928d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
5938d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
5948d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
595aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
596aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
597aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
598aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
5998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
600aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            sp<AMessage> format;
6028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findMessage("format", &format));
603aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (OK != ConvertMessageToMap(env, format, &obj)) {
6058d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
6068d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
6078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
608aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
609aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
610aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
611aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
612aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        default:
613aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            TRESPASS();
614aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    }
6158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->CallVoidMethod(
6178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mObject,
6188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            gFields.postEventFromNativeID,
6198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            EVENT_CALLBACK,
6208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg1,
6218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg2,
6228d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj);
6238d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->DeleteLocalRef(obj);
625aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
626aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
6278d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
6288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (msg->what()) {
6298d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case kWhatCallbackNotify:
6308d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6318d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            handleCallback(msg);
6328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6338d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6348d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        default:
6358d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            TRESPASS();
6368d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
637aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
638aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
63988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
64088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
64288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
64488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
64588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
64688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
647075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
64888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
64988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
65088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
65188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
652128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* release MediaCodec and stop the looper now before decStrong.
653128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * otherwise JMediaCodec::~JMediaCodec() could be called from within
654128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * its message handler, doing release() from there will deadlock
655128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * (as MediaCodec::release() post synchronous message to the same looper)
656128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
657128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        old->release();
65888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
65988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
660075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
66188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
66388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
66488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
666075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
66788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
66888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
66988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
67088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
67188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
67288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
673bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
6748d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
6758d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
6768d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
677bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
678bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
6798d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
680bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
681bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
682bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
683bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
6843ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    /* translate OS errors to Java API CryptoException errorCodes */
6853ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
6863ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
6873ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
6883ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
6893ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
6903ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
6913ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
6923ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
6933ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
6943ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
6953ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        default:
6963ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
6973ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
6983ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
699bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
7008d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
701bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
702bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
703bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
704bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
705bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
706bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        JNIEnv *env, status_t err, const char *msg = NULL) {
7073ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
708bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        // We'll throw our custom MediaCodec.CryptoException
709bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        throwCryptoException(env, err, msg);
710bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        return 0;
711bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    }
712bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
71388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
71488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
71588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
71688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
71888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
71988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
72188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
72288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
72488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
72588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7263ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
7273ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
7283ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
7293ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            throwCryptoException(env, err, msg);
7303ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
7313ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
73388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        {
734e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen            jniThrowException(env, "java/lang/IllegalStateException", msg);
73588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            break;
73688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
73788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
73888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return 0;
74088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
74188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatic void android_media_MediaCodec_native_setCallback(
7438d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        JNIEnv *env,
7448d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject thiz,
7458d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject cb) {
7468d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
7478d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7488d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (codec == NULL) {
7498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jniThrowException(env, "java/lang/IllegalStateException", NULL);
7508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        return;
7518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
7528d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    status_t err = codec->setCallback(cb);
7548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    throwExceptionAsNecessary(env, err);
7568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
7578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
75888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
75988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
76088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
76188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
76288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
7638240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
76488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
76588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
76688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
76888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
76988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
77088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
77188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
77488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
77788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
77888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
77988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
780d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
78188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
78264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
78452800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7948240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
7958240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
7968240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
7978240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
7988240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
799d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8042621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
8052621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
8062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
8072621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8082621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
8092621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
8102621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jniThrowException(env, "java/lang/IllegalStateException", NULL);
8112621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
8122621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
8132621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8142621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
8152621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
8162621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
8172621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
8182621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
8192621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
8202621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
8212621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
8222621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
8232621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
8242621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
8252621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
8262621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
82788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
82888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
82988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
83188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
833e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        jniThrowException(env, "java/lang/IllegalStateException", "no codec found");
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
83688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
83888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
839e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    throwExceptionAsNecessary(env, err, "start failed");
84088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
84188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
84388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
84488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
84688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
84888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
84988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
85088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
85188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
85288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
85388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
85488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
85588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
85688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
85788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
85888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
85988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
86188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
86388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
86488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
86588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
86688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
86888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
86988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
87088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
87188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
87288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
87388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
87488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
87588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
87688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
87788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
87888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
87988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
88088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
88188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
88288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
88388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
88488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
88588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
88688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
88788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
88888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
889bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
890bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
89188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
892bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
89388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
894bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
895bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
89688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
89788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
8999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
9009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
9019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
9029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
90391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
9049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
9059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
9069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
9079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
9119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
9129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
9139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
9149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
91591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
91691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
91791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
91891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
91991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
92091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
92191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
92291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
92391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
92491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
92591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
92691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
92791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
92891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
92991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
93091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
93191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
93291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
93391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
9349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
9359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
9379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
9389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
9399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
9419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
9429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
9439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
9449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
9459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
9469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
9479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
9489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
9499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
9509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
9517ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // subSamples array may silently overflow if number of samples are too large.  Use
9527ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
9537ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    } else if ( CC_UNLIKELY(numSubSamples >= INT32_MAX / sizeof(*subSamples)) ) {
9547ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar        err = -EINVAL;
9559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
9569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
9579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
9599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
9609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
9619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
9629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
9649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
9659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
9669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
9679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
9699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
9719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
9729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
9739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
9759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
9769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
9779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
9789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
9809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
9819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
9829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
9839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
9849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
9869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
9879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
9889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
9899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
9909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
9919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
9929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
9939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
9949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
9959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
9969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
9979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
9989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
9999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
10029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
10039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
10049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
10059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
10069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
10079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
10089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1010bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1011bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
10129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
10139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
10149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
10159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
10169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
10179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
1018bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
1019bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
1020bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
10219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
10249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
10259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
10269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
10299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
10309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
10319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
10329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
10339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
10349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
10359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1036bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
1037bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
10389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
10399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
104088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
104188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
104288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
104388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
104488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
104588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
104688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
104788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
104888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
104988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
105088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
105188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
105288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
105388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
105488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1055075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
105688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
105788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
105888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
105988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
106088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
106188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
106288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
106388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
106488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
106588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
106688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
106788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
106888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
10690e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
107088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
107188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
107288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
107388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
107488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
107588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
107688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1077075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
107888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
107988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
108088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
108188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
108288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
108388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
10847c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        JNIEnv *env, jobject thiz,
10857c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
108688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
108788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
108888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
108988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
109088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
109188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
109288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
109388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
109488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10957c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
109688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
109788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
109888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
109988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11002621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
11012621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
11022621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
11032621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11042621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11052621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
11062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jniThrowException(env, "java/lang/IllegalStateException", NULL);
11072621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
11082621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11092621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11102621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
11112621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11122621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
11132621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
11142621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1115d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getFormatNative(
1116d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input) {
1117d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getFormatNative");
1118d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1119d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1120d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1121d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
1122d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1123d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1124d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1125d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1126d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject format;
1127d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getFormat(env, input, &format);
1128d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1129d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1130d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return format;
1131d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1132d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1133d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    throwExceptionAsNecessary(env, err);
1134d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1135d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1136d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1137d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1138d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getOutputFormatForIndexNative(
1139d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jint index) {
1140d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
114188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
114388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
114588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
114688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
114788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
114888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
114988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
1150d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getOutputFormat(env, index, &format);
115188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
115388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
115488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
115588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
115788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
115888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
115988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
116088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
116288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
116388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
116488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
116688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
116788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
116888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
116988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
117088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
117188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
117388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
117488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
117588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
117688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
117788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
117888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1179cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
1180cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
1181cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
1182cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
118388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
118488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
118588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
118688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1187d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getBuffer(
1188d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1189d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getBuffer");
1190d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1191d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1192d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1193d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
1194d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1195d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1196d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1197d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1198d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject buffer;
1199d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getBuffer(env, input, index, &buffer);
1200d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1201d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1202d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return buffer;
1203d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1204d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1205d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1206d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1207d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1208d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1209d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1210d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1211d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1212d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1213d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getImage(
1214d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1215d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getImage");
1216d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1217d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1218d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1219d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
1220d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1221d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1222d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1223d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1224d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject image;
1225d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getImage(env, input, index, &image);
1226d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1227d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1228d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return image;
1229d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1230d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1231d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1232d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1233d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1234d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1235d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1236d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1237d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1238d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1239056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
1240056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
1241056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
1242056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1243056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1244056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1245056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
1246056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1247056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
1248056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1249056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1250056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
1251056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
1252056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1253056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
1254056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
1255056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1256056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1257056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
1258056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1259056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
1260056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
1261056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1262226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
1263226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
1264226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
1265226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1266226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1267226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1268226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
1269226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1270226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
1271226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1272226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1273226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
1274226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
1275226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1276226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
1277226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
1278226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1279226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1280226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
1281226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
1282226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1283b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
1284b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
1285b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1286b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1287b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
1288b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
1289b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1290b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1291b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1292b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
1293b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
1294b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
1295b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1296b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1297b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1298b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
1299b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
1300b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
130188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
13028d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
13038d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
13048d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
130588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1306075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
130788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
130891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1309aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    gFields.postEventFromNativeID =
1310aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        env->GetMethodID(
1311aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber                clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
1312aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1313aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    CHECK(gFields.postEventFromNativeID != NULL);
1314aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
13158d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
13168d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
131791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
131891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
13198d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
132091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
132191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
132291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
13238d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
132491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
132591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
132691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
13278d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
132891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
132991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
13308d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
133191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
133291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
13338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
133491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
133591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
13368d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
133791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
13383ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
13398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
13408d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
13413ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
13423ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jfieldID field;
13438d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
13443ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
13458d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
13468d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
13473ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
13488d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
13493ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
13508d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
13518d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
13523ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
13538d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
13543ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
13558d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
13568d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
135788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
135888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
135988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
136088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
136188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
136288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
136388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
136488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
136588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
136688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
136788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
136888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
136988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
137088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
137188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
137288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
137388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
137488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
137588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->initCheck();
137688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
137788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->ReleaseStringUTFChars(name, tmp);
137888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    tmp = NULL;
137988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
138088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
138188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
138288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
138388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
138488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to allocate component instance");
138588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
138688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
138788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1388aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    codec->registerSelf();
1389aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
139088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
139188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
139288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
139388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
139488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
139588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
139688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
139788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
139888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
1399d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_release", "()V", (void *)android_media_MediaCodec_release },
140088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    { "native_setCallback",
14028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      "(Landroid/media/MediaCodec$Callback;)V",
14038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      (void *)android_media_MediaCodec_native_setCallback },
14048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
140588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
14068240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
140707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
140888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
140988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14102621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
14112621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
14122621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1413d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_start", "()V", (void *)android_media_MediaCodec_start },
1414aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    { "native_stop", "()V", (void *)android_media_MediaCodec_stop },
1415d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
141688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1417d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueInputBuffer", "(IIIJI)V",
141888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
141988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1420d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
14219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
14229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1423d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueInputBuffer", "(J)I",
142488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
142588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1426d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
142788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
142888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14297c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    { "releaseOutputBuffer", "(IZZJ)V",
143088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
143188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14322621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
14332621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
14342621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1435d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getFormatNative", "(Z)Ljava/util/Map;",
1436d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getFormatNative },
1437d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1438d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getOutputFormatNative", "(I)Ljava/util/Map;",
1439d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
144088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
144188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
144288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
144388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1444d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
1445d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getBuffer },
1446d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1447d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getImage", "(ZI)Landroid/media/Image;",
1448d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getImage },
1449d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1450056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
1451056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
1452056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1453226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
1454226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
1455226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1456b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
1457b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
1458b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
145988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
146088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
146288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
146388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
146588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
146688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
146788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
146988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
147088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
147188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
1472