android_media_MediaCodec.cpp revision 3ed38266c1647c6219ae5ad89cb3f867cf66caaa
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
41b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
42b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
4388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
523ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinkerstruct CryptoErrorCodes {
533ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorNoKey;
543ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorKeyExpired;
553ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorResourceBusy;
563ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker} gCryptoErrorCodes;
573ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
5888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
5988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
6091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
6191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
6291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
6391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
6491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
6591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
6688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
7588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      mObject(NULL) {
7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,       // canCallJava
8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            PRIORITY_DEFAULT);
9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByType(mLooper, name, encoder);
9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        mCodec = MediaCodec::CreateByComponentName(mLooper, name);
9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
9988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec != NULL ? OK : NO_INIT;
10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::~JMediaCodec() {
103d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
104d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
105d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
106d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
11288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
118d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
1198240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
12152800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
122d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
12352800617946c456e78ed010c82d0ec4358368164Mathias Agopian        mSurfaceTextureClient = new Surface(bufferProducer);
124b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
125b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
127b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
128b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    return mCodec->configure(format, mSurfaceTextureClient, crypto, flags);
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1312621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
1322621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
1332621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
1342621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
1352621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->start();
13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
141b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
142b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->stop();
14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
15188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
152bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
153bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
154bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
155bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
15688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
15788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
1599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
1609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
1619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
1629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
1639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
1649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
1659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
1669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
167bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
168bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
1699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
1709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            index, offset, subSamples, numSubSamples, key, iv, mode,
171bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
1729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
1739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->dequeueInputBuffer(index, timeoutUs);
17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->dequeueOutputBuffer(
185c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber                    index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) {
18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec$BufferInfo");
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jmethodID method = env->GetMethodID(clazz, "set", "(IIJI)V");
19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) {
19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2032621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
2042621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
2052621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
2062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const {
20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if ((err = mCodec->getOutputFormat(&msg)) != OK) {
21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    Vector<sp<ABuffer> > buffers;
22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass byteBufferClass = env->FindClass("java/nio/ByteBuffer");
2313dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(byteBufferClass != NULL);
2323dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2333dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID orderID = env->GetMethodID(
2343dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            byteBufferClass,
2353dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "order",
2363dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
2373dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2383dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(orderID != NULL);
2393dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2403dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jclass byteOrderClass = env->FindClass("java/nio/ByteOrder");
2413dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(byteOrderClass != NULL);
2423dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2433dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jmethodID nativeOrderID = env->GetStaticMethodID(
2443dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber            byteOrderClass, "nativeOrder", "()Ljava/nio/ByteOrder;");
2453dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeOrderID != NULL);
2463dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
2473dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    jobject nativeByteOrderObj =
2483dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        env->CallStaticObjectMethod(byteOrderClass, nativeOrderID);
2493dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    CHECK(nativeByteOrderObj != NULL);
25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            buffers.size(), byteBufferClass, NULL);
253cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
254cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        env->DeleteLocalRef(nativeByteOrderObj);
255cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
256cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<ABuffer> &buffer = buffers.itemAt(i);
26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
261cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        // if this is an ABuffer that doesn't actually hold any accessible memory,
262cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        // use a null ByteBuffer
263cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        if (buffer->base() == NULL) {
264cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            continue;
265cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject byteBuffer =
26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env->NewDirectByteBuffer(
26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->base(),
26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                buffer->capacity());
270cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        if (byteBuffer == NULL) {
271cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            env->DeleteLocalRef(nativeByteOrderObj);
272cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen            return NO_MEMORY;
273cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
2743dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        jobject me = env->CallObjectMethod(
2753dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber                byteBuffer, orderID, nativeByteOrderObj);
2763dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        env->DeleteLocalRef(me);
2773dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber        me = NULL;
2783dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
27988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->SetObjectArrayElement(
28088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                *bufArray, i, byteBuffer);
28188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
28288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        env->DeleteLocalRef(byteBuffer);
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        byteBuffer = NULL;
28488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
28588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2863dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    env->DeleteLocalRef(nativeByteOrderObj);
2873dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber    nativeByteOrderObj = NULL;
2883dd7fd08a8a1d658b0aac8590f1fd922e056f689Andreas Huber
28988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
29088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
29188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
292056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
293056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
294056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
295056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
296056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
297056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
298056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
299056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
300056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
301056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
302056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
303056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
304056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
305056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
306b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
307b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
308b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
309b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
310b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
311b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> old = (JMediaCodec *)env->GetIntField(thiz, gFields.context);
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->SetIntField(thiz, gFields.context, (int)codec.get());
32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return (JMediaCodec *)env->GetIntField(thiz, gFields.context);
33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
340bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
341bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec$CryptoException");
342bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(clazz != NULL);
343bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
344bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
345bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V");
346bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
347bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
348bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error");
349bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
3503ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    /* translate OS errors to Java API CryptoException errorCodes */
3513ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
3523ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
3533ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
3543ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3553ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
3563ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
3573ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3583ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
3593ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
3603ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3613ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        default:
3623ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3633ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
3643ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
365bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
366bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        (jthrowable)env->NewObject(clazz, constructID, err, msgObj);
367bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
368bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
369bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
370bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
371bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
372bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        JNIEnv *env, status_t err, const char *msg = NULL) {
3733ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    if (err >= ERROR_DRM_VENDOR_MIN && err <= ERROR_DRM_VENDOR_MAX) {
374bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        // We'll throw our custom MediaCodec.CryptoException
375bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        throwCryptoException(env, err, msg);
376bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        return 0;
377bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    }
378bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3923ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
3933ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
3943ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
3953ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            throwCryptoException(env, err, msg);
3963ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
3973ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        {
400e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen            jniThrowException(env, "java/lang/IllegalStateException", msg);
40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            break;
40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return 0;
40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
4138240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
430d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
43264a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
43452800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
43788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
43888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
43988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
44088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
44188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
44288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
44388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4448240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
4458240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
4468240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
4478240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
4488240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
449d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    err = codec->configure(format, bufferProducer, crypto, flags);
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4542621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
4552621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
4562621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
4572621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
4582621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
4592621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
4602621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jniThrowException(env, "java/lang/IllegalStateException", NULL);
4612621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
4622621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
4632621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
4642621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
4652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
4662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
4672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
4682621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
4692621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
4702621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
4712621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
4722621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
4732621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
4742621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
4752621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
4762621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
47788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
47888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
47988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
48188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
483e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen        jniThrowException(env, "java/lang/IllegalStateException", "no codec found");
48488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
48588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
48688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
48788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
48888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
489e20a6d5c479909f37af748a81a6e5a5deb7b6e2cMarco Nelissen    throwExceptionAsNecessary(env, err, "start failed");
49088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
49188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
49388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
49488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
49688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
49788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
49888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
49988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
50088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
50188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
50388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
50588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
50688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
50788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
50888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
50988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
51188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
51388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
51488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
51588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
51688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
51888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
51988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
52088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
52188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
52288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
52388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
52488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
52588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
52688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
52788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
52888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
52988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
53088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
53188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
53388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
53488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
53588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
53688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
53788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
53888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
539bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
540bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
54188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
542bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
54388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
544bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
545bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
54688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
54788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
5499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
5509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
5519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
5529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
55391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
5549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
5559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
5569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
5579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
5599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
5619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
5629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
5639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
5649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
56591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
56691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
56791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
56891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
56991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
57091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
57191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
57291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
57391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
57491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
57591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
57691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
57791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
57891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
57991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
58091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
58191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
58291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
58391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
5849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
5859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
5879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
5889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
5899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
5909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
5919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
5929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
5939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
5949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
5959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
5969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
5979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
5989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
5999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
6009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
6019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
6029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
6039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
6059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
6069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
6079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
6089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
6109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
6119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
6129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
6139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
6159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
6179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
6189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
6199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
6219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
6229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
6239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
6269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
6279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
6289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
6299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
6329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
6339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
6349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
6359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
6399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
6409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
6419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
6429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
6439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
6449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
6489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
6499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
6509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
6519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
6529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
6539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
6549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
656bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
657bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
6589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
6599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
6609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
6619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
6629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
6639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (CryptoPlugin::Mode)mode,
664bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
665bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
666bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
6679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
6709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
6719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
6729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
6759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
6769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
6779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
6789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
6799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
6809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
6819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
682bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
683bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
6849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
6859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
68688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
68788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
68888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
68988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
69088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
69188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
69288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
69388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
69488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
69588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
69688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
69788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
69888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
69988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
70188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return index;
70288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
70388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
70588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
70688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
70788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
70888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
70988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
71088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
71288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
71488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
7150e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
71688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
71788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
71888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
71988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
72088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
72188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
72388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return index;
72488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
72588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
72788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jint index, jboolean render) {
73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
73488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
73588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
73688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
73788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
73888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
73988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->releaseOutputBuffer(index, render);
74188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
74288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
74388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
74488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
7452621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
7462621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
7472621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
7482621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
7492621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
7502621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
7512621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jniThrowException(env, "java/lang/IllegalStateException", NULL);
7522621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
7532621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
7542621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
7552621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
7562621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
7572621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
7582621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
7592621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
76060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jobject android_media_MediaCodec_getOutputFormatNative(
76188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
76260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    ALOGV("android_media_MediaCodec_getOutputFormatNative");
76388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
76588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
76688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
76788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
76888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
76988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
77088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
77288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getOutputFormat(env, &format);
77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
77588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
77788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
77888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
77988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
78188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
78288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
79588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
79688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
79788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
79988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
80088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
801cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
802cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
803cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
804cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
80588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
80688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
809056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
810056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
811056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
812056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
813056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
814056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
815056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
816056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        jniThrowException(env, "java/lang/IllegalStateException", NULL);
817056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
818056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
819056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
820056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
821056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
822056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
823056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
824056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
825056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
826056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
827056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
828056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
829056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
830056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
831056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
832b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
833b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
834b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
835b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
836b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
837b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/IllegalStateException", NULL);
838b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
839b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
840b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
841b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
842b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
843b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
844b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
845b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
846b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
847b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
848b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
849b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
85088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
85188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->FindClass("android/media/MediaCodec");
85288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
85388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
85488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    gFields.context = env->GetFieldID(clazz, "mNativeContext", "I");
85588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
85691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
85791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    clazz = env->FindClass("android/media/MediaCodec$CryptoInfo");
85891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(clazz != NULL);
85991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
86091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
86191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetFieldID(clazz, "numSubSamples", "I");
86291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
86391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
86491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
86591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetFieldID(clazz, "numBytesOfClearData", "[I");
86691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
86791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
86891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
86991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I");
87091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
87191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
87291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B");
87391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
87491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
87591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B");
87691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
87791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
87891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I");
87991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
8803ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8813ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    clazz = env->FindClass("android/media/MediaCodec$CryptoException");
8823ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(clazz != NULL);
8833ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8843ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jfieldID field;
8853ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    field = env->GetStaticFieldID(clazz, "ERROR_NO_KEY", "I");
8863ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
8873ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    gCryptoErrorCodes.cryptoErrorNoKey = env->GetStaticIntField(clazz, field);
8883ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8893ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    field = env->GetStaticFieldID(clazz, "ERROR_KEY_EXPIRED", "I");
8903ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
8913ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    gCryptoErrorCodes.cryptoErrorKeyExpired = env->GetStaticIntField(clazz, field);
8923ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8933ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    field = env->GetStaticFieldID(clazz, "ERROR_RESOURCE_BUSY", "I");
8943ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
8953ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    gCryptoErrorCodes.cryptoErrorResourceBusy = env->GetStaticIntField(clazz, field);
89688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
89788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
89888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
89988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
90088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
90188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
90288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
90388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
90488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
90588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
90788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
90888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
90988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
91088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
91188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
91388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->initCheck();
91588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->ReleaseStringUTFChars(name, tmp);
91788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    tmp = NULL;
91888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
92088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(
92188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                env,
92288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "java/io/IOException",
92388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "Failed to allocate component instance");
92488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
92588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
92688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
92788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
92888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
92988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
93088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
93188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
93288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
93388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
93488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
93588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = {
93688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "release", "()V", (void *)android_media_MediaCodec_release },
93788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
93888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
9398240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
94007ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber      "Landroid/media/MediaCrypto;I)V",
94188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
94288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9432621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
9442621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
9452621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
94688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "start", "()V", (void *)android_media_MediaCodec_start },
94788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "stop", "()V", (void *)android_media_MediaCodec_stop },
94888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "flush", "()V", (void *)android_media_MediaCodec_flush },
94988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "queueInputBuffer", "(IIIJI)V",
95188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
95288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
9549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
9559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
95688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueInputBuffer", "(J)I",
95788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
95888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
95988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
96088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
96188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
96288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "releaseOutputBuffer", "(IZ)V",
96388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
96488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
9662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
9672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
96860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber    { "getOutputFormatNative", "()Ljava/util/Map;",
96960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber      (void *)android_media_MediaCodec_getOutputFormatNative },
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
97288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
97388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
974056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
975056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
976056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
977b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
978b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
979b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
98088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
98188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
98288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
98388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
98488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
98588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
98688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
98788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
98888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
98988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
99088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
99188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
99288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
993