android_media_MediaCodec.cpp revision 075e9a19ce645752f8282bc19c91b25978a7dc52
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
308335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
318335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
320e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h>
3388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
3488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
38bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h>
3988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
418d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
428d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
43b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
44b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
543ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinkerstruct CryptoErrorCodes {
553ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorNoKey;
563ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorKeyExpired;
573ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorResourceBusy;
583ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker} gCryptoErrorCodes;
593ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
6088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
6188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
6291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
6391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
6491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
6591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
6691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
6791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
7588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,       // canCallJava
918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            PRIORITY_FOREGROUND);
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByType(mLooper, name, encoder);
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByComponentName(mLooper, name);
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec != NULL ? OK : NO_INIT;
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::~JMediaCodec() {
105d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
106d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
107d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
108d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
120d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
1218240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
12352800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
124d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
125fd2e50086c4f4e2bb064c76a1de73e10c172f387Marco Nelissen        mSurfaceTextureClient = new Surface(bufferProducer, true /* controlledByApp */);
126b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
127b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
129b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
130b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1332621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
1342621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
1352621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
1362621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
1372621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->start();
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
143b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
144b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->stop();
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
15388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
154bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
155bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
156bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
157bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
15888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
1619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
1629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
1639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
1649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
1659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
1669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
1679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
1689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
169bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
170bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
1719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
1729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
173bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
1749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
1759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->dequeueInputBuffer(index, timeoutUs);
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->dequeueOutputBuffer(
187c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber                    index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) {
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
1928d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1948d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) {
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
2072621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
2082621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
2092621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const {
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->getOutputFormat(&msg)) != OK) {
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2338d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> byteBufferClass(
2348d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("java/nio/ByteBuffer"));
2358d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
2368d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(byteBufferClass.get() != NULL);
2373dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2383dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID orderID = env->GetMethodID(
2398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            byteBufferClass.get(),
2403dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "order",
2413dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
2423dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2433dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(orderID != NULL);
2443dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2458d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> byteOrderClass(
2468d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("java/nio/ByteOrder"));
2478d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
2488d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(byteOrderClass.get() != NULL);
2493dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2503dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID nativeOrderID = env->GetStaticMethodID(
2518d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
2523dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeOrderID != NULL);
2533dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2543dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jobject nativeByteOrderObj =
2558d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
2563dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeByteOrderObj != NULL);
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
2598d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            buffers.size(), byteBufferClass.get(), NULL);
260cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
261cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        env->DeleteLocalRef(nativeByteOrderObj);
262cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
263cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
268cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        // if this is an ABuffer that doesn't actually hold any accessible memory,
269cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        // use a null ByteBuffer
270cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        if (buffer->base() == NULL) {
271cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            continue;
272cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
27388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuffer =
27488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->NewDirectByteBuffer(
27588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->base(),
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->capacity());
277cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        if (byteBuffer == NULL) {
278cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            env->DeleteLocalRef(nativeByteOrderObj);
279cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            return NO_MEMORY;
280cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
2813dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        jobject me = env->CallObjectMethod(
2823dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber                byteBuffer, orderID, nativeByteOrderObj);
2833dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        env->DeleteLocalRef(me);
2843dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        me = NULL;
2853dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
28688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->SetObjectArrayElement(
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                *bufArray, i, byteBuffer);
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->DeleteLocalRef(byteBuffer);
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        byteBuffer = NULL;
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
29288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2933dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    env->DeleteLocalRef(nativeByteOrderObj);
2943dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    nativeByteOrderObj = NULL;
2953dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
299056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
300056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
301056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
302056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
303056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
304056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
305056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
306056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
307056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
308056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
309056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
310056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
311056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
312056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
313226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
314226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
315226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
316226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
317b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
318b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
319b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
320b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
321b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
322b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
331075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
338075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
344075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
351bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
3528d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
3538d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
3548d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
355bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
356bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
3578d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
358bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
359bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
360bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
361bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
3623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    /* translate OS errors to Java API CryptoException errorCodes */
3633ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
3643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
3653ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
3663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3673ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
3683ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
3693ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3703ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
3713ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
3723ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3733ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        default:
3743ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3753ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
3763ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
377bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
3788d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
379bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
380bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
381bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
382bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
383bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
384bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        JNIEnv *env, status_t err, const char *msg = NULL) {
3853ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
386bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        // We'll throw our custom MediaCodec.CryptoException
387bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        throwCryptoException(env, err, msg);
388bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        return 0;
389bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    }
390bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4043ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
4053ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
4063ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
4073ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            throwCryptoException(env, err, msg);
4083ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
4093ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        {
412e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen            jniThrowException(env, "java/lang/IllegalStateException", msg);
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            break;
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return 0;
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
4258240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
43088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
43288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
442d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
44464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
44588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
44652800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
44788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
44888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
44988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4568240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
4578240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
4588240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
4598240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
4608240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
461d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
46288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
46388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
46488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
46588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
4672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
4682621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
4692621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
4702621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
4712621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
4722621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jniThrowException(env, "java/lang/IllegalStateException", NULL);
4732621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
4742621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
4752621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
4762621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
4772621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
4782621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
4792621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
4802621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
4812621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
4822621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
4832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
4842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
4852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
4862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
4872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
4882621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
48988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
49088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
49188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
49388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
495e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        jniThrowException(env, "java/lang/IllegalStateException", "no codec found");
49688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
49788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
49888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
50088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
501e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    throwExceptionAsNecessary(env, err, "start failed");
50288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
50388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
50588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
50688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
50888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
51088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
51188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
51288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
51388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
51588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
51788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
51888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
52088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
52188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
52388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
52588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
52688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
52788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
52888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
53088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
53288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
53388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
53588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
53688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
53788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
53888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
53988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
54088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
54188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
54288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
54388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
54588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
54688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
54788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
54888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
54988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
55088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
551bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
552bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
55388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
554bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
55588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
556bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
557bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
55888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
55988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
5619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
5629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
5639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
5649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
56591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
5669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
5679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
5689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
5699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
5719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
5739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
5749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
5759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
57791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
57891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
57991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
58191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
58291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
58391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
58591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
58691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
58791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
58991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
59091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
59191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
59291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
59391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
59491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
59591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
5969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
5979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
5999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
6009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
6019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
6039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
6049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
6059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
6069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
6079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
6089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
6099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
6109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
6119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
6129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
6139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
6149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
6159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
6179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
6189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
6199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
6209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
6229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
6239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
6249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
6259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
6279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
6299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
6309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
6319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
6339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
6349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
6359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
6389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
6399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
6409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
6419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
6449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
6459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
6469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
6479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
6519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
6529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
6539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
6549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
6559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
6569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
6609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
6619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
6629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
6639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
6649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
6659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
668bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
669bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
6709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
6719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
6729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
6739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
6749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
6759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
676bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
677bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
678bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
6799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
6829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
6839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
6849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
6879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
6889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
6899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
6929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
6939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
694bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
695bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
6969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
6979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
69888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
69988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
70088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
70188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
70388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
70588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
70688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
70788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
70888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
71088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
71188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
713075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
71488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
71588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
71788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
71888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
72088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
72188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
72288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
72488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
72688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
7270e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
73388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
735075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
73688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
73788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
73988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
74088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
74288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index, jboolean render) {
74388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
74488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
74688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
74888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
74988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
75088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
75188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
75288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->releaseOutputBuffer(index, render);
75388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
75488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
75588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
75688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7572621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
7582621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
7592621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
7602621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
7612621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
7622621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
7632621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jniThrowException(env, "java/lang/IllegalStateException", NULL);
7642621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
7652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
7662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
7672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
7682621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
7692621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
7702621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
7712621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
77260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jobject android_media_MediaCodec_getOutputFormatNative(
77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
77460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    ALOGV("android_media_MediaCodec_getOutputFormatNative");
77588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
77788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
77988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
78088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
78188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
78288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getOutputFormat(env, &format);
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
79488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
79688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
79788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
80488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
80588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
81088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
81188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
81288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
813cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
814cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
815cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
816cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
81788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
81888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
81988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
82088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
821056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
822056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
823056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
824056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
825056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
826056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
827056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
828056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        jniThrowException(env, "java/lang/IllegalStateException", NULL);
829056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
830056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
831056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
832056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
833056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
834056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
835056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
836056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
837056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
838056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
839056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
840056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
841056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
842056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
843056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
844226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
845226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
846226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
847226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
848226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
849226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
850226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
851226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
852226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
853226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
854226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
855226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
856226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
857226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
858226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
859226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
860226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
861226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
862226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
863226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
864226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
865b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
866b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
867b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
868b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
869b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
870b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
871b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
872b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
873b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
874b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
875b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
876b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
877b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
878b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
879b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
880b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
881b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
882b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
88388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
8848d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
8858d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
8868d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
88788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
888075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
88988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
89091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
8918d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
8928d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
89391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
89491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
8958d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
89691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
89791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
89891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
8998d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
90091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
90191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
90291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
9038d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
90491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
90591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
9068d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
90791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
90891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
9098d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
91091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
91191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
9128d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
91391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
9143ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
9158d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
9168d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
9173ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
9183ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jfieldID field;
9198d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
9203ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
9218d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
9228d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
9233ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
9248d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
9253ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
9268d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
9278d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
9283ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
9298d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
9303ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
9318d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
9328d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
93388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
93488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
93588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
93688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
93788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
93888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
93988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
94088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
94188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
94288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
94488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
94688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
94788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
94888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
94988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
95088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->initCheck();
95288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->ReleaseStringUTFChars(name, tmp);
95488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    tmp = NULL;
95588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
95788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
95888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
95988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
96088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to allocate component instance");
96188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
96288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
96388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
96588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
96688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
96888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
96988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
97188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
97388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaCodec_release },
97488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
9768240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
97707ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
97888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
97988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9802621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
9812621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
9822621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
98388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "start", "()V", (void *)android_media_MediaCodec_start },
98488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "stop", "()V", (void *)android_media_MediaCodec_stop },
98588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "flush", "()V", (void *)android_media_MediaCodec_flush },
98688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
98788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "queueInputBuffer", "(IIIJI)V",
98888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
98988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
99091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
9919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
9929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
99388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueInputBuffer", "(J)I",
99488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
99588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
99688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
99788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
99888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
99988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "releaseOutputBuffer", "(IZ)V",
100088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
100188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10022621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
10032621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
10042621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
100560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getOutputFormatNative", "()Ljava/util/Map;",
100660d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber      (void *)android_media_MediaCodec_getOutputFormatNative },
100788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
100888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
100988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
101088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1011056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
1012056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
1013056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1014226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
1015226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
1016226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1017b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
1018b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
1019b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
102088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
102188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
102288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
102388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
102488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
102588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
102688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
102788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
102888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
102988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
103088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
103188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
103288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
1033