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"
240e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick#include "android_media_MediaMetricsJNI.h"
2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_Utils.h"
2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/AndroidRuntime.h"
2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/android_view_Surface.h"
28d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang#include "android_util_Binder.h"
2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h"
3088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h"
3188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang#include <android/media/IDescrambler.h>
33d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang
347ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar#include <cutils/compiler.h>
357ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar
368335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h>
378335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian
380e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h>
394273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim#include <media/MediaCodecBuffer.h>
4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h>
4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h>
4288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h>
4388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h>
4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h>
45bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h>
4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h>
478034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang#include <media/stagefright/PersistentSurface.h>
488d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber#include <nativehelper/ScopedLocalRef.h>
498d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber
50b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h>
51b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android {
5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!!
5588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum {
5688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_TRY_AGAIN_LATER            = -1,
5788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED      = -2,
5888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED     = -3,
5988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
6088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
61aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huberenum {
628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_CALLBACK = 1,
638d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    EVENT_SET_CALLBACK = 2,
64d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    EVENT_FRAME_RENDERED = 3,
65aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber};
66aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
675f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic struct CryptoErrorCodes {
683ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorNoKey;
693ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorKeyExpired;
703ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    jint cryptoErrorResourceBusy;
71336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    jint cryptoErrorInsufficientOutputProtection;
7296a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    jint cryptoErrorSessionNotOpened;
73d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    jint cryptoErrorUnsupportedOperation;
743ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker} gCryptoErrorCodes;
753ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
765f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic struct CodecActionCodes {
775f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jint codecActionTransient;
785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jint codecActionRecoverable;
795f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung} gCodecActionCodes;
805f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
81c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wustatic struct CodecErrorCodes {
82c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    jint errorInsufficientResource;
83c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    jint errorReclaimed;
84c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu} gCodecErrorCodes;
859e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
868034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic struct {
878034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jclass clazz;
888034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jfieldID mLock;
898034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jfieldID mPersistentObject;
908034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jmethodID ctor;
918034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jmethodID setNativeObjectLocked;
928034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang} gPersistentSurfaceClassInfo;
938034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
94d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinkerstatic struct {
95d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint Unencrypted;
96d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint AesCtr;
97d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint AesCbc;
98d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker} gCryptoModes;
99d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
100d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t {
10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jfieldID context;
103aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    jmethodID postEventFromNativeID;
10491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumSubSamplesID;
10591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfClearDataID;
10691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoNumBytesOfEncryptedDataID;
10791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoKeyID;
10891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoIVID;
10991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jfieldID cryptoInfoModeID;
110d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID cryptoInfoPatternID;
111d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID patternEncryptBlocksID;
112d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID patternSkipBlocksID;
11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields;
1168034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic const void *sRefBaseOwner;
11788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
11888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec(
12188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const char *name, bool nameIsType, bool encoder)
12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    : mClass(NULL),
1248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      mObject(NULL) {
12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jclass clazz = env->GetObjectClass(thiz);
12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(clazz != NULL);
12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = (jclass)env->NewGlobalRef(clazz);
12988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = env->NewWeakGlobalRef(thiz);
13088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1317de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    cacheJavaObjects(env);
1327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper = new ALooper;
13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->setName("MediaCodec_looper");
13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mLooper->start(
13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            false,      // runOnCallingThread
138aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            true,       // canCallJava
1398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            PRIORITY_FOREGROUND);
14088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
14188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (nameIsType) {
1425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByType(mLooper, name, encoder, &mInitStatus);
14388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    } else {
1445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mCodec = MediaCodec::CreateByComponentName(mLooper, name, &mInitStatus);
14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
1465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK((mCodec != NULL) != (mInitStatus != OK));
14788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
14888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::cacheJavaObjects(JNIEnv *env) {
1507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jclass clazz = (jclass)env->FindClass("java/nio/ByteBuffer");
1517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = (jclass)env->NewGlobalRef(clazz);
1527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferClass != NULL);
1537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> byteOrderClass(
1557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("java/nio/ByteOrder"));
1567de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(byteOrderClass.get() != NULL);
1577de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1587de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID nativeOrderID = env->GetStaticMethodID(
1597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteOrderClass.get(), "nativeOrder", "()Ljava/nio/ByteOrder;");
1607de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(nativeOrderID != NULL);
1617de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1627de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject nativeByteOrderObj =
1637de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->CallStaticObjectMethod(byteOrderClass.get(), nativeOrderID);
1647de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = env->NewGlobalRef(nativeByteOrderObj);
1657de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mNativeByteOrderObj != NULL);
1667de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(nativeByteOrderObj);
1677de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    nativeByteOrderObj = NULL;
1687de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = env->GetMethodID(
1707de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass,
1717de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "order",
1727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteOrder;)Ljava/nio/ByteBuffer;");
1737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferOrderMethodID != NULL);
1747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = env->GetMethodID(
1767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "asReadOnlyBuffer", "()Ljava/nio/ByteBuffer;");
1777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferAsReadOnlyBufferMethodID != NULL);
1787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = env->GetMethodID(
1807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "position", "(I)Ljava/nio/Buffer;");
1817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferPositionMethodID != NULL);
1827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
1837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = env->GetMethodID(
1847de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            mByteBufferClass, "limit", "(I)Ljava/nio/Buffer;");
1857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(mByteBufferLimitMethodID != NULL);
1867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
1877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const {
1895f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    return mInitStatus;
19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
192aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Hubervoid JMediaCodec::registerSelf() {
193aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    mLooper->registerHandler(this);
194aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
195aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
196128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhangvoid JMediaCodec::release() {
197d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    if (mCodec != NULL) {
198d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec->release();
199d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo        mCodec.clear();
2005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        mInitStatus = NO_INIT;
201d932de9aff49d1d9f752ad479b42854d2557c881Martin Storsjo    }
20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
203128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mLooper != NULL) {
204128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->unregisterHandler(id());
205128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper->stop();
206128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        mLooper.clear();
207128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
208128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang}
209128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
210128b012cc8c2369136bb8450bc91c81aebe18506Chong ZhangJMediaCodec::~JMediaCodec() {
211128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    if (mCodec != NULL || mLooper != NULL) {
212128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* MediaCodec and looper should have been released explicitly already
213128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * in setMediaCodec() (see comments in setMediaCodec()).
214128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
215128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Otherwise JMediaCodec::~JMediaCodec() might be called from within the
216128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * message handler, doing release() there risks deadlock as MediaCodec::
217128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * release() post synchronous message to the same looper.
218128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         *
219128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * Print a warning and try to proceed with releasing.
220128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
221128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("try to release MediaCodec from JMediaCodec::~JMediaCodec()...");
222128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        release();
223128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        ALOGW("done releasing MediaCodec from JMediaCodec::~JMediaCodec().");
224128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang    }
225128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang
22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    JNIEnv *env = AndroidRuntime::getJNIEnv();
22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteWeakGlobalRef(mObject);
22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mObject = NULL;
23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    env->DeleteGlobalRef(mClass);
23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    mClass = NULL;
2327de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    deleteJavaObjects(env);
2337de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
2347de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2357de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarvoid JMediaCodec::deleteJavaObjects(JNIEnv *env) {
2367de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mByteBufferClass);
2377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferClass = NULL;
2387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteGlobalRef(mNativeByteOrderObj);
2397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mNativeByteOrderObj = NULL;
2407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
2417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferOrderMethodID = NULL;
2427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferAsReadOnlyBufferMethodID = NULL;
2437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferPositionMethodID = NULL;
2447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    mByteBufferLimitMethodID = NULL;
24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
247d8578577b02cf6360402eb8726e964d18b46434dLajos Molnarstatus_t JMediaCodec::enableOnFrameRenderedListener(jboolean enable) {
248d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    if (enable) {
249d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        if (mOnFrameRenderedNotification == NULL) {
250d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            mOnFrameRenderedNotification = new AMessage(kWhatFrameRendered, this);
251d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        }
252d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    } else {
253d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        mOnFrameRenderedNotification.clear();
254d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    }
255d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
256d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    return mCodec->setOnFrameRenderedNotification(mOnFrameRenderedNotification);
257d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar}
258d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
2598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatus_t JMediaCodec::setCallback(jobject cb) {
2608d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (cb != NULL) {
2618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        if (mCallbackNotification == NULL) {
26263834f4d23a97b27d830a301328329c7ef682bd5Lajos Molnar            mCallbackNotification = new AMessage(kWhatCallbackNotify, this);
2638d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
2648d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    } else {
2658d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        mCallbackNotification.clear();
2668d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
2678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
2688d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->setCallback(mCallbackNotification);
2698d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
2708d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
27188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure(
27288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        const sp<AMessage> &format,
273d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden        const sp<IGraphicBufferProducer> &bufferProducer,
2748240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        const sp<ICrypto> &crypto,
275d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang        const sp<IDescrambler> &descrambler,
27688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        int flags) {
27752800617946c456e78ed010c82d0ec4358368164Mathias Agopian    sp<Surface> client;
278d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    if (bufferProducer != NULL) {
279aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        mSurfaceTextureClient =
280aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            new Surface(bufferProducer, true /* controlledByApp */);
281b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    } else {
282b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        mSurfaceTextureClient.clear();
28388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
284b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
285d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang    return mCodec->configure(
286d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang            format, mSurfaceTextureClient, crypto, descrambler, flags);
28788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
28888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
2895e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnarstatus_t JMediaCodec::setSurface(
2905e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        const sp<IGraphicBufferProducer> &bufferProducer) {
2915e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<Surface> client;
2925e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (bufferProducer != NULL) {
2935e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        client = new Surface(bufferProducer, true /* controlledByApp */);
2945e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
2955e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    status_t err = mCodec->setSurface(client);
2965e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (err == OK) {
2975e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        mSurfaceTextureClient = client;
2985e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
2995e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    return err;
3005e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar}
3015e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
3022621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::createInputSurface(
3032621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        sp<IGraphicBufferProducer>* bufferProducer) {
3042621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->createInputSurface(bufferProducer);
3052621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
3079560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhangstatus_t JMediaCodec::setInputSurface(
3088034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        const sp<PersistentSurface> &surface) {
3099560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    return mCodec->setInputSurface(surface);
3108034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
3118034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() {
3138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->start();
31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() {
317b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    mSurfaceTextureClient.clear();
318b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
3198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->stop();
32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() {
32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return mCodec->flush();
32488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3261e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatus_t JMediaCodec::reset() {
3271e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    return mCodec->reset();
3281e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
3291e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer(
33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        size_t index,
332bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        size_t offset, size_t size, int64_t timeUs, uint32_t flags,
333bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
334bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    return mCodec->queueInputBuffer(
335bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timeUs, flags, errorDetailMsg);
33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer(
3399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t index,
3409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t offset,
3419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const CryptoPlugin::SubSample *subSamples,
3429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        size_t numSubSamples,
3439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t key[16],
3449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        const uint8_t iv[16],
3459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        CryptoPlugin::Mode mode,
346d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        const CryptoPlugin::Pattern &pattern,
3479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        int64_t presentationTimeUs,
348bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        uint32_t flags,
349bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber        AString *errorDetailMsg) {
3509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    return mCodec->queueSecureInputBuffer(
351d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker            index, offset, subSamples, numSubSamples, key, iv, mode, pattern,
352bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            presentationTimeUs, flags, errorDetailMsg);
3539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
3549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
35588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) {
3568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    return mCodec->dequeueInputBuffer(index, timeoutUs);
35788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
35888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
35988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer(
36088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) {
36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t size, offset;
36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    int64_t timeUs;
36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    uint32_t flags;
364aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    status_t err = mCodec->dequeueOutputBuffer(
365aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            index, &offset, &size, &timeUs, &flags, timeoutUs);
366aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
367aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    if (err != OK) {
36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3718d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
3728d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$BufferInfo"));
37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3748d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
375fef85ef152ab176fd96dbe3047c8025136fa8560Ashok Bhat    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3807c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnarstatus_t JMediaCodec::releaseOutputBuffer(
3817c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        size_t index, bool render, bool updatePTS, int64_t timestampNs) {
3827c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    if (updatePTS) {
3837c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        return mCodec->renderOutputBufferAndRelease(index, timestampNs);
3847c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    }
38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return render
38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        ? mCodec->renderOutputBufferAndRelease(index)
38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        : mCodec->releaseOutputBuffer(index);
38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
3902621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatus_t JMediaCodec::signalEndOfInputStream() {
3912621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return mCodec->signalEndOfInputStream();
3922621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
3932621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
394d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getFormat(JNIEnv *env, bool input, jobject *format) const {
39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> msg;
39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err;
397d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    err = input ? mCodec->getInputFormat(&msg) : mCodec->getOutputFormat(&msg);
398d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
399d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
400d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
401d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
402d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return ConvertMessageToMap(env, msg, format);
403d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
404d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
405d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, size_t index, jobject *format) const {
406d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<AMessage> msg;
407d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err;
408d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if ((err = mCodec->getOutputFormat(index, &msg)) != OK) {
40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return ConvertMessageToMap(env, msg, format);
41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers(
41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, bool input, jobjectArray *bufArray) const {
4174273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim    Vector<sp<MediaCodecBuffer> > buffers;
41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err =
42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        input
42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            ? mCodec->getInputBuffers(&buffers)
42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            : mCodec->getOutputBuffers(&buffers);
42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return err;
42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
42788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
42888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    *bufArray = (jobjectArray)env->NewObjectArray(
4297de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            buffers.size(), mByteBufferClass, NULL);
430cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (*bufArray == NULL) {
431cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        return NO_MEMORY;
432cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
43388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    for (size_t i = 0; i < buffers.size(); ++i) {
4354273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim        const sp<MediaCodecBuffer> &buffer = buffers.itemAt(i);
43688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4377de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject byteBuffer = NULL;
4387de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        err = createByteBufferFromABuffer(
4397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, !input /* readOnly */, true /* clearBuffer */, buffer, &byteBuffer);
4407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (err != OK) {
4417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            return err;
442cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        }
4437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        if (byteBuffer != NULL) {
4447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env->SetObjectArrayElement(
4457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                    *bufArray, i, byteBuffer);
4467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
447d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            env->DeleteLocalRef(byteBuffer);
4487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer = NULL;
449d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        }
45088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
45188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
45288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return OK;
45388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
45488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
4557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar// static
4564273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kimtemplate <typename T>
4577de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::createByteBufferFromABuffer(
4584273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim        JNIEnv *env, bool readOnly, bool clearBuffer, const sp<T> &buffer,
4597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jobject *buf) const {
460d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
461d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
4627de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = NULL;
463e5b641e6effda54945577e9348df86213b38baebAaron Vaage
464e5b641e6effda54945577e9348df86213b38baebAaron Vaage    if (buffer == NULL) {
465e5b641e6effda54945577e9348df86213b38baebAaron Vaage        ALOGV("createByteBufferFromABuffer - given NULL, returning NULL");
466e5b641e6effda54945577e9348df86213b38baebAaron Vaage        return OK;
467e5b641e6effda54945577e9348df86213b38baebAaron Vaage    }
468e5b641e6effda54945577e9348df86213b38baebAaron Vaage
469d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
470d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
471d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
472d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
473d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject byteBuffer =
4747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->NewDirectByteBuffer(buffer->base(), buffer->capacity());
4757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (readOnly && byteBuffer != NULL) {
476d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        jobject readOnlyBuffer = env->CallObjectMethod(
4777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                byteBuffer, mByteBufferAsReadOnlyBufferMethodID);
478d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        env->DeleteLocalRef(byteBuffer);
479d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        byteBuffer = readOnlyBuffer;
480d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
481d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (byteBuffer == NULL) {
482d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NO_MEMORY;
483d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
484d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject me = env->CallObjectMethod(
4857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferOrderMethodID, mNativeByteOrderObj);
486d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
487d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = env->CallObjectMethod(
4887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferLimitMethodID,
4897de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? buffer->capacity() : (buffer->offset() + buffer->size()));
490d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    env->DeleteLocalRef(me);
4917be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    me = env->CallObjectMethod(
4927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, mByteBufferPositionMethodID,
4937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            clearBuffer ? 0 : buffer->offset());
4947be24522ce2e1821ad45e7ada7c3f91e6814889aLajos Molnar    env->DeleteLocalRef(me);
495d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    me = NULL;
496d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
497d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = byteBuffer;
498d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
499d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
500d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
5017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnarstatus_t JMediaCodec::getBuffer(
5027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
5034273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim    sp<MediaCodecBuffer> buffer;
5047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    status_t err =
5067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        input
5077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
5087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
5097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5107de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5117de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return err;
5127de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5137de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5147de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    return createByteBufferFromABuffer(
5157de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, buf);
5167de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar}
5177de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
518d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatus_t JMediaCodec::getImage(
519d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, bool input, size_t index, jobject *buf) const {
5204273dd03a83fd5f9ba25f3b7c3a4add7bce7206cWonsik Kim    sp<MediaCodecBuffer> buffer;
521d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
522d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err =
523d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        input
524d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            ? mCodec->getInputBuffer(index, &buffer)
525d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar            : mCodec->getOutputBuffer(index, &buffer);
526d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
527d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != OK) {
528d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return err;
529d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
530d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
531d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if this is an ABuffer that doesn't actually hold any accessible memory,
532d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // use a null ByteBuffer
533d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    *buf = NULL;
534d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (buffer->base() == NULL) {
535d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
536d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
537d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
538d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // check if buffer is an image
5397de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    sp<ABuffer> imageData;
5407de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!buffer->meta()->findBuffer("image-data", &imageData)) {
5417de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
5427de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5437de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5447de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int64_t timestamp = 0;
5457de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (!input && buffer->meta()->findInt64("timeUs", &timestamp)) {
5467de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        timestamp *= 1000; // adjust to ns
5477de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5487de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5497de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject byteBuffer = NULL;
5507de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
5517de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, !input /* readOnly */, input /* clearBuffer */, buffer, &byteBuffer);
5527de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5537de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        return OK;
5547de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5557de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5567de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject infoBuffer = NULL;
5577de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    err = createByteBufferFromABuffer(
5587de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, true /* readOnly */, true /* clearBuffer */, imageData, &infoBuffer);
5597de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (err != OK) {
5607de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(byteBuffer);
5617de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        byteBuffer = NULL;
562d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return OK;
563d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
564d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
5657de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jobject cropRect = NULL;
5667de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    int32_t left, top, right, bottom;
5677de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (buffer->meta()->findRect("crop-rect", &left, &top, &right, &bottom)) {
5687de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        ScopedLocalRef<jclass> rectClazz(
5697de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                env, env->FindClass("android/graphics/Rect"));
5707de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        CHECK(rectClazz.get() != NULL);
5717de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5727de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        jmethodID rectConstructID = env->GetMethodID(
5737de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), "<init>", "(IIII)V");
5747de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5757de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = env->NewObject(
5767de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar                rectClazz.get(), rectConstructID, left, top, right + 1, bottom + 1);
5777de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5787de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5797de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    ScopedLocalRef<jclass> imageClazz(
5807de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            env, env->FindClass("android/media/MediaCodec$MediaImage"));
5817de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    CHECK(imageClazz.get() != NULL);
5827de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5837de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    jmethodID imageConstructID = env->GetMethodID(imageClazz.get(), "<init>",
5847de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            "(Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;ZJIILandroid/graphics/Rect;)V");
5857de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5867de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    *buf = env->NewObject(imageClazz.get(), imageConstructID,
5877de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            byteBuffer, infoBuffer,
5887de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jboolean)!input /* readOnly */,
5897de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jlong)timestamp,
5907de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar            (jint)0 /* xOffset */, (jint)0 /* yOffset */, cropRect);
5917de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5927de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    // if MediaImage creation fails, return null
5937de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (env->ExceptionCheck()) {
5947de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionDescribe();
5957de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->ExceptionClear();
5967de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        *buf = NULL;
5977de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
5987de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
5997de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    if (cropRect != NULL) {
6007de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        env->DeleteLocalRef(cropRect);
6017de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar        cropRect = NULL;
6027de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    }
6037de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
6047de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(byteBuffer);
6057de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    byteBuffer = NULL;
6067de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
6077de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    env->DeleteLocalRef(infoBuffer);
6087de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar    infoBuffer = NULL;
6097de28d34f1ca3a727a8325cf3304f2fe03d2ac59Lajos Molnar
610d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return OK;
611d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
612d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
613056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatus_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
614056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    AString name;
615056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
616056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = mCodec->getName(&name);
617056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
618056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err != OK) {
619056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return err;
620056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
621056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
622056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    *nameStr = env->NewStringUTF(name.c_str());
623056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
624056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return OK;
625056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
626056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
627f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essickstatus_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {
6280e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
6290e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    status_t status = mCodec->getMetrics(reply);
6300e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    return status;
6310e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick}
6320e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
633226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatus_t JMediaCodec::setParameters(const sp<AMessage> &msg) {
634226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    return mCodec->setParameters(msg);
635226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
636226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
637b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) {
638b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mSurfaceTextureClient != NULL) {
639b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode);
640b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
641b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
642b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
6435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic jthrowable createCodecException(
6445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode, const char *msg = NULL) {
6455f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jclass> clazz(
6465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->FindClass("android/media/MediaCodec$CodecException"));
6475f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
6485f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
649c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    const jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "(IILjava/lang/String;)V");
6505f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(ctor != NULL);
6515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    ScopedLocalRef<jstring> msgObj(
6535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, env->NewStringUTF(msg != NULL ? msg : String8::format("Error %#x", err)));
6545f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6555f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    // translate action code to Java equivalent
6565f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    switch (actionCode) {
6575f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_TRANSIENT:
6585f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionTransient;
6595f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6605f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    case ACTION_CODE_RECOVERABLE:
6615f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = gCodecActionCodes.codecActionRecoverable;
6625f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6635f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    default:
6645f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        actionCode = 0;  // everything else is fatal
6655f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        break;
6665f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    }
6675f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
668c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    /* translate OS errors to Java API CodecException errorCodes */
669c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    switch (err) {
670c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        case NO_MEMORY:
671c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            err = gCodecErrorCodes.errorInsufficientResource;
672c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            break;
673c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        case DEAD_OBJECT:
674c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            err = gCodecErrorCodes.errorReclaimed;
675c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            break;
676c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        default:  /* Other error codes go out as is. */
677c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu            break;
678c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    }
679c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu
680c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    return (jthrowable)env->NewObject(clazz.get(), ctor, err, actionCode, msgObj.get());
6815f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
6825f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
6838d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::handleCallback(const sp<AMessage> &msg) {
6848d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    int32_t arg1, arg2 = 0;
6858d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    jobject obj = NULL;
6868d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    CHECK(msg->findInt32("callbackID", &arg1));
6878d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    JNIEnv *env = AndroidRuntime::getJNIEnv();
6888d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6898d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (arg1) {
6908d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_INPUT_AVAILABLE:
691aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
6928d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6938d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
6948d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
6958d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
6968d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_AVAILABLE:
6978d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
6988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("index", &arg2));
6998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            size_t size, offset;
7018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            int64_t timeUs;
7028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            uint32_t flags;
7038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("size", &size));
7048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findSize("offset", &offset));
7058d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt64("timeUs", &timeUs));
7068d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("flags", (int32_t *)&flags));
7078d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7088d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            ScopedLocalRef<jclass> clazz(
7098d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env, env->FindClass("android/media/MediaCodec$BufferInfo"));
7108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID ctor = env->GetMethodID(clazz.get(), "<init>", "()V");
7118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
7128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7138d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj = env->NewObject(clazz.get(), ctor);
7148d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7158d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
7168d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
7178d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    ALOGE("Could not create MediaCodec.BufferInfo.");
7188d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
7198d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
7208d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
7218d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
722aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            }
723aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7248d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            env->CallVoidMethod(obj, method, (jint)offset, (jint)size, timeUs, flags);
725aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
726aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
727aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7288d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_ERROR:
729aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
73094686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            int32_t err, actionCode;
73194686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang            CHECK(msg->findInt32("err", &err));
7328d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findInt32("actionCode", &actionCode));
733aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            // note that DRM errors could conceivably alias into a CodecException
7355f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            obj = (jobject)createCodecException(env, err, actionCode);
736aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7378d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (obj == NULL) {
7388d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                if (env->ExceptionCheck()) {
73994686d13cacbec1ce7cf5fd0178fffb037d03cc1Chong Zhang                    ALOGE("Could not create CodecException object.");
7408d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                    env->ExceptionClear();
7418d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                }
7428d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
7438d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
7448d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
745aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
746aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
747aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
748aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case MediaCodec::CB_OUTPUT_FORMAT_CHANGED:
750aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        {
7518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            sp<AMessage> format;
7528d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            CHECK(msg->findMessage("format", &format));
753aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
7548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            if (OK != ConvertMessageToMap(env, format, &obj)) {
7558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                jniThrowException(env, "java/lang/IllegalStateException", NULL);
7568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang                return;
7578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            }
758aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
759aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            break;
760aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        }
761aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
762aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        default:
763aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber            TRESPASS();
764aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    }
7658d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7668d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->CallVoidMethod(
7678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            mObject,
7688d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            gFields.postEventFromNativeID,
7698d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            EVENT_CALLBACK,
7708d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg1,
7718d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            arg2,
7728d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            obj);
7738d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
7748d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    env->DeleteLocalRef(obj);
775aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
776aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
777d8578577b02cf6360402eb8726e964d18b46434dLajos Molnarvoid JMediaCodec::handleFrameRenderedNotification(const sp<AMessage> &msg) {
778d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    int32_t arg1 = 0, arg2 = 0;
779d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    jobject obj = NULL;
780d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    JNIEnv *env = AndroidRuntime::getJNIEnv();
781d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
782d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    sp<AMessage> data;
783d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    CHECK(msg->findMessage("data", &data));
784d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
785d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    status_t err = ConvertMessageToMap(env, data, &obj);
786d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    if (err != OK) {
787d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        jniThrowException(env, "java/lang/IllegalStateException", NULL);
788d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        return;
789d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    }
790d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
791d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    env->CallVoidMethod(
792d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            mObject, gFields.postEventFromNativeID,
793d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            EVENT_FRAME_RENDERED, arg1, arg2, obj);
794d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
795d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    env->DeleteLocalRef(obj);
796d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar}
797d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
7988d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangvoid JMediaCodec::onMessageReceived(const sp<AMessage> &msg) {
7998d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    switch (msg->what()) {
8008d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        case kWhatCallbackNotify:
8018d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        {
8028d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            handleCallback(msg);
8038d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            break;
8048d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        }
805d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        case kWhatFrameRendered:
806d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        {
807d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            handleFrameRenderedNotification(msg);
808d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar            break;
809d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        }
8108d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        default:
8118d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang            TRESPASS();
8128d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
813aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber}
814aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
81588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}  // namespace android
81688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
81788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber////////////////////////////////////////////////////////////////////////////////
81888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
81988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android;
82088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
82188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec(
82288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) {
823075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    sp<JMediaCodec> old = (JMediaCodec *)env->GetLongField(thiz, gFields.context);
82488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec != NULL) {
82588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        codec->incStrong(thiz);
82688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
82788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (old != NULL) {
828128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        /* release MediaCodec and stop the looper now before decStrong.
829128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * otherwise JMediaCodec::~JMediaCodec() could be called from within
830128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * its message handler, doing release() from there will deadlock
831128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         * (as MediaCodec::release() post synchronous message to the same looper)
832128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang         */
833128b012cc8c2369136bb8450bc91c81aebe18506Chong Zhang        old->release();
83488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        old->decStrong(thiz);
83588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
836075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    env->SetLongField(thiz, gFields.context, (jlong)codec.get());
83788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
83888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return old;
83988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
84088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) {
842075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    return (JMediaCodec *)env->GetLongField(thiz, gFields.context);
84388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
84488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
84588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) {
84688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env, thiz, NULL);
84788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
84888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
8495f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hungstatic void throwCodecException(JNIEnv *env, status_t err, int32_t actionCode, const char *msg) {
8505f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    jthrowable exception = createCodecException(env, err, actionCode, msg);
8515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->Throw(exception);
8525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung}
8535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
854bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) {
8558d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
8568d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec$CryptoException"));
8578d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
858bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
859bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jmethodID constructID =
8608d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetMethodID(clazz.get(), "<init>", "(ILjava/lang/String;)V");
861bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    CHECK(constructID != NULL);
862bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
8633ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker    const char *defaultMsg = "Unknown Error";
864bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
8655f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    /* translate OS errors to Java API CryptoException errorCodes (which are positive) */
8663ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    switch (err) {
8673ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_NO_LICENSE:
8683ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorNoKey;
8693ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Crypto key not available";
8703ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
8713ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_LICENSE_EXPIRED:
8723ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorKeyExpired;
8733ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "License expired";
8743ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
8753ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker        case ERROR_DRM_RESOURCE_BUSY:
8763ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            err = gCryptoErrorCodes.cryptoErrorResourceBusy;
8773ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Resource busy or unavailable";
8783ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
879336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        case ERROR_DRM_INSUFFICIENT_OUTPUT_PROTECTION:
880336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            err = gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection;
8813ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Required output protections are not active";
882336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker            break;
88396a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker        case ERROR_DRM_SESSION_NOT_OPENED:
88496a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker            err = gCryptoErrorCodes.cryptoErrorSessionNotOpened;
8853ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker            defaultMsg = "Attempted to use a closed session";
88696a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker            break;
887d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker        case ERROR_DRM_CANNOT_HANDLE:
888d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker            err = gCryptoErrorCodes.cryptoErrorUnsupportedOperation;
889d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker            defaultMsg = "Operation not supported in this configuration";
890d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker            break;
8915f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        default:  /* Other negative DRM error codes go out as is. */
8923ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker            break;
8933ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    }
8943ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
8953ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker    jstring msgObj = env->NewStringUTF(msg != NULL ? msg : defaultMsg);
8963ccb34d7070d73ba6c7842801b070b41de32b842Jeff Tinker
897bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    jthrowable exception =
8988d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        (jthrowable)env->NewObject(clazz.get(), constructID, err, msgObj);
899bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
900bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    env->Throw(exception);
901bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber}
902bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
903bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary(
9045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        JNIEnv *env, status_t err, int32_t actionCode = ACTION_CODE_FATAL,
9055f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        const char *msg = NULL) {
90688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    switch (err) {
90788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case OK:
90888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return 0;
90988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case -EAGAIN:
91188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_TRY_AGAIN_LATER;
91288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_FORMAT_CHANGED:
91488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED;
91588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
91688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        case INFO_OUTPUT_BUFFERS_CHANGED:
91788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED;
91888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
9195f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        case INVALID_OPERATION:
9205f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            jniThrowException(env, "java/lang/IllegalStateException", msg);
9215f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
9223ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
9235e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        case BAD_VALUE:
9245e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            jniThrowException(env, "java/lang/IllegalArgumentException", msg);
9255e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            return 0;
9265e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
92788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        default:
9285f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            if (isCryptoError(err)) {
9295f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                throwCryptoException(env, err, msg);
9305f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                return 0;
9315f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            }
9325f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            throwCodecException(env, err, actionCode, msg);
9335f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            return 0;
93488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
93588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
93688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
937d8578577b02cf6360402eb8726e964d18b46434dLajos Molnarstatic void android_media_MediaCodec_native_enableOnFrameRenderedListener(
938d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        JNIEnv *env,
939d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        jobject thiz,
940d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        jboolean enabled) {
941d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
942d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
943d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    if (codec == NULL) {
944d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        throwExceptionAsNecessary(env, INVALID_OPERATION);
945d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar        return;
946d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    }
947d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
948d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    status_t err = codec->enableOnFrameRenderedListener(enabled);
949d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
950d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    throwExceptionAsNecessary(env, err);
951d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar}
952d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
9538d5e556b2b76278000a506382fdf594c071e1fbdChong Zhangstatic void android_media_MediaCodec_native_setCallback(
9548d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        JNIEnv *env,
9558d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject thiz,
9568d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        jobject cb) {
9578d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
9588d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
9598d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    if (codec == NULL) {
9605f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
9618d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang        return;
9628d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    }
9638d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
9648d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    status_t err = codec->setCallback(cb);
9658d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
9668d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    throwExceptionAsNecessary(env, err);
9678d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang}
9688d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
96988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure(
97088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
97188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
97288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobjectArray keys, jobjectArray values,
97388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject jsurface,
9748240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        jobject jcrypto,
975d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang        jobject descramblerBinderObj,
97688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
97788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
97888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
97988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
9805f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
98188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
98288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
98388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
98488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<AMessage> format;
98588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format);
98688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
98788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err != OK) {
98888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
98988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
99088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
99188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
992d47f7d8b5fe3a3861d7cbdc5f912235407823c8eAndy McFadden    sp<IGraphicBufferProducer> bufferProducer;
99388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (jsurface != NULL) {
99464a55af0ac700baecb0877235eb42caac59a3560Jeff Brown        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
99588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        if (surface != NULL) {
99652800617946c456e78ed010c82d0ec4358368164Mathias Agopian            bufferProducer = surface->getIGraphicBufferProducer();
99788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        } else {
99888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            jniThrowException(
99988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    env,
100088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "java/lang/IllegalArgumentException",
100188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                    "The surface has been released");
100288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            return;
100388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        }
100488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
100588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10068240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    sp<ICrypto> crypto;
10078240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    if (jcrypto != NULL) {
10088240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber        crypto = JCrypto::GetCrypto(env, jcrypto);
10098240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber    }
10108240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber
1011d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang    sp<IDescrambler> descrambler;
1012d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang    if (descramblerBinderObj != NULL) {
1013d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang        sp<IBinder> binder = ibinderForJavaObject(env, descramblerBinderObj);
1014d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang        descrambler = interface_cast<IDescrambler>(binder);
1015d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang    }
1016d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang
1017d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang    err = codec->configure(format, bufferProducer, crypto, descrambler, flags);
101888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
101988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
102088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
102188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
10225e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnarstatic void android_media_MediaCodec_native_setSurface(
10235e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        JNIEnv *env,
10245e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        jobject thiz,
10255e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        jobject jsurface) {
10265e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
10275e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10285e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (codec == NULL) {
10295e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        throwExceptionAsNecessary(env, INVALID_OPERATION);
10305e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        return;
10315e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
10325e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10335e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    sp<IGraphicBufferProducer> bufferProducer;
10345e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    if (jsurface != NULL) {
10355e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        sp<Surface> surface(android_view_Surface_getSurface(env, jsurface));
10365e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        if (surface != NULL) {
10375e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            bufferProducer = surface->getIGraphicBufferProducer();
10385e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        } else {
10395e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            jniThrowException(
10405e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    env,
10415e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    "java/lang/IllegalArgumentException",
10425e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar                    "The surface has been released");
10435e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar            return;
10445e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar        }
10455e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    }
10465e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10475e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    status_t err = codec->setSurface(bufferProducer);
10485e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    throwExceptionAsNecessary(env, err);
10495e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar}
10505e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
10518034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangsp<PersistentSurface> android_media_MediaCodec_getPersistentInputSurface(
10528034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jobject object) {
10538034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface;
10548034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10558034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject lock = env->GetObjectField(
10568034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            object, gPersistentSurfaceClassInfo.mLock);
10578034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (env->MonitorEnter(lock) == JNI_OK) {
10588034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface = reinterpret_cast<PersistentSurface *>(
10598034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                env->GetLongField(object,
10608034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                        gPersistentSurfaceClassInfo.mPersistentObject));
10618034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->MonitorExit(lock);
10628034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10638034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    env->DeleteLocalRef(lock);
10648034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10658034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    return persistentSurface;
10668034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
10678034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10688034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic jobject android_media_MediaCodec_createPersistentInputSurface(
10698034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jclass /* clazz */) {
10708034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    ALOGV("android_media_MediaCodec_createPersistentInputSurface");
10718034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface =
10728034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        MediaCodec::CreatePersistentInputSurface();
10738034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10748034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (persistentSurface == NULL) {
10758034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return NULL;
10768034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10778034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10788034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<Surface> surface = new Surface(
10798034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            persistentSurface->getBufferProducer(), true);
10808034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (surface == NULL) {
10818034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return NULL;
10828034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10838034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10848034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject object = env->NewObject(
10858034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            gPersistentSurfaceClassInfo.clazz,
10868034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            gPersistentSurfaceClassInfo.ctor);
10878034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10888034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (object == NULL) {
10898034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        if (env->ExceptionCheck()) {
10908034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            ALOGE("Could not create PersistentSurface.");
10918034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            env->ExceptionClear();
10928034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        }
10938034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return NULL;
10948034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
10958034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
10968034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject lock = env->GetObjectField(
10978034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            object, gPersistentSurfaceClassInfo.mLock);
10988034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (env->MonitorEnter(lock) == JNI_OK) {
10998034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->CallVoidMethod(
11008034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                object,
11018034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                gPersistentSurfaceClassInfo.setNativeObjectLocked,
11028034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                (jlong)surface.get());
11038034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->SetLongField(
11048034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                object,
11058034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                gPersistentSurfaceClassInfo.mPersistentObject,
11068034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                (jlong)persistentSurface.get());
11078034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->MonitorExit(lock);
11088034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    } else {
11098034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->DeleteLocalRef(object);
11108034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        object = NULL;
11118034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11128034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    env->DeleteLocalRef(lock);
11138034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11148034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (object != NULL) {
11158034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        surface->incStrong(&sRefBaseOwner);
11168034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface->incStrong(&sRefBaseOwner);
11178034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11188034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11198034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    return object;
11208034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
11218034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11228034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhangstatic void android_media_MediaCodec_releasePersistentInputSurface(
11238034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jclass /* clazz */, jobject object) {
11248034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface;
11258034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11268034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jobject lock = env->GetObjectField(
11278034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            object, gPersistentSurfaceClassInfo.mLock);
11288034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (env->MonitorEnter(lock) == JNI_OK) {
11298034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface = reinterpret_cast<PersistentSurface *>(
11308034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang            env->GetLongField(
11318034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                    object, gPersistentSurfaceClassInfo.mPersistentObject));
11328034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->SetLongField(
11338034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                object,
11348034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                gPersistentSurfaceClassInfo.mPersistentObject,
11358034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang                (jlong)0);
11368034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        env->MonitorExit(lock);
11378034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11388034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    env->DeleteLocalRef(lock);
11398034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11408034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (persistentSurface != NULL) {
11418034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        persistentSurface->decStrong(&sRefBaseOwner);
11428034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11438034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    // no need to release surface as it will be released by Surface's jni
11448034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
11458034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11469560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhangstatic void android_media_MediaCodec_setInputSurface(
11478034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        JNIEnv* env, jobject thiz, jobject object) {
11489560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    ALOGV("android_media_MediaCodec_setInputSurface");
11498034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11508034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11518034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (codec == NULL) {
11528034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        throwExceptionAsNecessary(env, INVALID_OPERATION);
11538034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        return;
11548034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11558034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11568034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    sp<PersistentSurface> persistentSurface =
11578034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        android_media_MediaCodec_getPersistentInputSurface(env, object);
11588034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11599560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    status_t err = codec->setInputSurface(persistentSurface);
11608034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    if (err != NO_ERROR) {
11618034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang        throwExceptionAsNecessary(env, err);
11628034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    }
11638034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang}
11648034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
11652621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic jobject android_media_MediaCodec_createInputSurface(JNIEnv* env,
11662621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
11672621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_createInputSurface");
11682621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11692621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
11702621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
11715f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
11722621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
11732621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11742621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11752621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Tell the MediaCodec that we want to use a Surface as input.
11762621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<IGraphicBufferProducer> bufferProducer;
11772621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->createInputSurface(&bufferProducer);
11782621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (err != NO_ERROR) {
11792621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        throwExceptionAsNecessary(env, err);
11802621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return NULL;
11812621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
11822621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
11832621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    // Wrap the IGBP in a Java-language Surface.
11842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    return android_view_Surface_createFromIGraphicBufferProducer(env,
11852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden            bufferProducer);
11862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
11872621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
118888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) {
118988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_start");
119088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
119288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
11945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
119588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
119688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
119788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
119888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->start();
119988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    throwExceptionAsNecessary(env, err, ACTION_CODE_FATAL, "start failed");
120188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
120288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
120388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) {
120488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_stop");
120588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
120688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
120788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
120888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
121088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
121188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
121288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
121388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->stop();
121488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
121588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
121688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
121788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12181e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnarstatic void android_media_MediaCodec_reset(JNIEnv *env, jobject thiz) {
12191e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    ALOGV("android_media_MediaCodec_reset");
12201e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
12211e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
12221e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
12231e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (codec == NULL) {
12245f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
12251e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        return;
12261e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
12271e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
12281e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    status_t err = codec->reset();
12291e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    if (err != OK) {
12301e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // treat all errors as fatal for now, though resource not available
12311e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar        // errors could be treated as transient.
12325f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // we also should avoid sending INVALID_OPERATION here due to
12335f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // the transitory nature of reset(), it should not inadvertently
12345f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // trigger an IllegalStateException.
12355f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        err = UNKNOWN_ERROR;
12361e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    }
12371e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    throwExceptionAsNecessary(env, err);
12381e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar}
12391e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
124088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) {
124188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_flush");
124288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
124488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
124588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
124788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
124888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
124988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->flush();
125188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
125388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
125488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
125588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer(
125688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env,
125788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jobject thiz,
125888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint index,
125988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint offset,
126088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint size,
126188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jlong timestampUs,
126288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jint flags) {
126388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_queueInputBuffer");
126488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
126588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
126688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
126788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
12685f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
126988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
127088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
127188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1272bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1273bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
127488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->queueInputBuffer(
1275bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber            index, offset, size, timestampUs, flags, &errorDetailMsg);
127688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1277bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
12785f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
127988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
128088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
12819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer(
12829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        JNIEnv *env,
12839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jobject thiz,
12849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint index,
12859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint offset,
128691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        jobject cryptoInfoObj,
12879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jlong timestampUs,
12889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint flags) {
12899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    ALOGV("android_media_MediaCodec_queueSecureInputBuffer");
12909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
12919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
12929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
12939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (codec == NULL) {
12945f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
12959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        return;
12969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
12979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
129891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jint numSubSamples =
129991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID);
130091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
130191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfClearDataObj =
130291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
130391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID);
130491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
130591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jintArray numBytesOfEncryptedDataObj =
130691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jintArray)env->GetObjectField(
130791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber                cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID);
130891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
130991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray keyObj =
131091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID);
131191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
131291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    jbyteArray ivObj =
131391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber        (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID);
131491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1315d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jint jmode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID);
1316d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    enum CryptoPlugin::Mode mode;
1317d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    if (jmode == gCryptoModes.Unencrypted) {
1318d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        mode = CryptoPlugin::kMode_Unencrypted;
1319d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    } else if (jmode == gCryptoModes.AesCtr) {
1320d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        mode = CryptoPlugin::kMode_AES_CTR;
1321d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    } else if (jmode == gCryptoModes.AesCbc) {
1322d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        mode = CryptoPlugin::kMode_AES_CBC;
1323d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    }  else {
1324d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        throwExceptionAsNecessary(env, INVALID_OPERATION);
1325d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        return;
1326d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    }
1327d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1328d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jobject patternObj = env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoPatternID);
1329d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1330d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CryptoPlugin::Pattern pattern;
1331e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker    if (patternObj == NULL) {
1332e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker        pattern.mEncryptBlocks = 0;
1333e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker        pattern.mSkipBlocks = 0;
1334e872ac45f79ca2c0b538df891d983e3d5e037574Jeff Tinker    } else {
1335d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        pattern.mEncryptBlocks = env->GetIntField(patternObj, gFields.patternEncryptBlocksID);
1336d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        pattern.mSkipBlocks = env->GetIntField(patternObj, gFields.patternSkipBlocksID);
1337d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    }
133891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
13399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    status_t err = OK;
13409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    CryptoPlugin::SubSample *subSamples = NULL;
13429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *key = NULL;
13439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    jbyte *iv = NULL;
13449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (numSubSamples <= 0) {
13469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
13479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj == NULL
13489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && numBytesOfEncryptedDataObj == NULL) {
13499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -EINVAL;
13509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfEncryptedDataObj != NULL
13519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) {
13529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
13539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else if (numBytesOfClearDataObj != NULL
13549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) {
13559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = -ERANGE;
13567ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // subSamples array may silently overflow if number of samples are too large.  Use
13577ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar    // INT32_MAX as maximum allocation size may be less than SIZE_MAX on some platforms
13585f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if ( CC_UNLIKELY(numSubSamples >= (signed)(INT32_MAX / sizeof(*subSamples))) ) {
13597ac4f560dfe754eb4fe0d279fa03c1d9b3a7a5afLajos Molnar        err = -EINVAL;
13609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    } else {
13619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jboolean isCopy;
13629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfClearData =
13649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfClearDataObj == NULL)
13659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
13669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy);
13679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        jint *numBytesOfEncryptedData =
13699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            (numBytesOfEncryptedDataObj == NULL)
13709e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                ? NULL
13719e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy);
13729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        subSamples = new CryptoPlugin::SubSample[numSubSamples];
13749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        for (jint i = 0; i < numSubSamples; ++i) {
13769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfClearData =
13779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i];
13789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            subSamples[i].mNumBytesOfEncryptedData =
13809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (numBytesOfEncryptedData == NULL)
13819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    ? 0 : numBytesOfEncryptedData[i];
13829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfEncryptedData != NULL) {
13859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
13869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0);
13879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfEncryptedData = NULL;
13889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (numBytesOfClearData != NULL) {
13919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            env->ReleaseIntArrayElements(
13929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                    numBytesOfClearDataObj, numBytesOfClearData, 0);
13939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            numBytesOfClearData = NULL;
13949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
13959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
13969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
13979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && keyObj != NULL) {
13989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(keyObj) != 16) {
13999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
14009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
14019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
14029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            key = env->GetByteArrayElements(keyObj, &isCopy);
14039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
14049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK && ivObj != NULL) {
14079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        if (env->GetArrayLength(ivObj) != 16) {
14089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            err = -EINVAL;
14099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        } else {
14109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            jboolean isCopy;
14119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber            iv = env->GetByteArrayElements(ivObj, &isCopy);
14129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        }
14139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1415bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    AString errorDetailMsg;
1416bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber
14179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (err == OK) {
14189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        err = codec->queueSecureInputBuffer(
14199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                index, offset,
14209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                subSamples, numSubSamples,
14219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber                (const uint8_t *)key, (const uint8_t *)iv,
1422d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker                mode,
1423d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker                pattern,
1424bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                timestampUs,
1425bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                flags,
1426bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber                &errorDetailMsg);
14279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (iv != NULL) {
14309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(ivObj, iv, 0);
14319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        iv = NULL;
14329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    if (key != NULL) {
14359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        env->ReleaseByteArrayElements(keyObj, key, 0);
14369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber        key = NULL;
14379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    }
14389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
14399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    delete[] subSamples;
14409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber    subSamples = NULL;
14419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1442bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber    throwExceptionAsNecessary(
14435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung            env, err, ACTION_CODE_FATAL, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str());
14449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber}
14459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
144688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer(
144788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jlong timeoutUs) {
144888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueInputBuffer");
144988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
145188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
14535f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
145488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return -1;
145588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
145688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
145788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
145888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueInputBuffer(&index, timeoutUs);
145988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1461075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
146288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
146388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
146588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
146688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
146788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer(
146888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) {
146988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_dequeueOutputBuffer");
147088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
147288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
14745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
14750e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber        return 0;
147688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
147788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
147888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    size_t index;
147988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->dequeueOutputBuffer(
148088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber            env, bufferInfo, &index, timeoutUs);
148188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
148288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
1483075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat        return (jint) index;
148488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
148588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
148688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return throwExceptionAsNecessary(env, err);
148788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
148888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
148988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer(
14907c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        JNIEnv *env, jobject thiz,
14917c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar        jint index, jboolean render, jboolean updatePTS, jlong timestampNs) {
149288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease");
149388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
149488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
149588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
149688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
14975f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
149888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
149988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
150088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15017c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    status_t err = codec->releaseOutputBuffer(index, render, updatePTS, timestampNs);
150288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
150388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
150488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
150588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
15062621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFaddenstatic void android_media_MediaCodec_signalEndOfInputStream(JNIEnv* env,
15072621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        jobject thiz) {
15082621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    ALOGV("android_media_MediaCodec_signalEndOfInputStream");
15092621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
15102621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
15112621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    if (codec == NULL) {
15125f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
15132621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden        return;
15142621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    }
15152621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
15162621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    status_t err = codec->signalEndOfInputStream();
15172621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
15182621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    throwExceptionAsNecessary(env, err);
15192621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden}
15202621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1521d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getFormatNative(
1522d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input) {
1523d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getFormatNative");
1524d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1525d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1526d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1527d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
15285f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1529d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1530d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1531d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1532d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject format;
1533d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getFormat(env, input, &format);
1534d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1535d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1536d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return format;
1537d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1538d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1539d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    throwExceptionAsNecessary(env, err);
1540d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1541d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1542d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1543d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1544d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getOutputFormatForIndexNative(
1545d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jint index) {
1546d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getOutputFormatForIndexNative");
154788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
154888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
154988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
155088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
15515f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
155288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
155388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
155488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
155588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobject format;
1556d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getOutputFormat(env, index, &format);
155788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
155888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
155988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return format;
156088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
156188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    throwExceptionAsNecessary(env, err);
156388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
156588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
156688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
156788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers(
156888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz, jboolean input) {
156988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    ALOGV("android_media_MediaCodec_getBuffers");
157088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
157188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
157288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
157388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (codec == NULL) {
15745f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
157588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return NULL;
157688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
157788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
157888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    jobjectArray buffers;
157988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    status_t err = codec->getBuffers(env, input, &buffers);
158088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
158188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (err == OK) {
158288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return buffers;
158388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
158488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1585cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    // if we're out of memory, an exception was already thrown
1586cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    if (err != NO_MEMORY) {
1587cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen        throwExceptionAsNecessary(env, err);
1588cbbea8e651feb580f439e28359d72589709fb120Marco Nelissen    }
158988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
159088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return NULL;
159188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
159288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1593d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getBuffer(
1594d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1595d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getBuffer");
1596d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1597d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1598d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1599d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
16005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1601d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1602d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1603d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1604d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject buffer;
1605d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getBuffer(env, input, index, &buffer);
1606d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1607d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1608d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return buffer;
1609d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1610d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1611d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1612d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1613d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1614d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1615d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1616d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1617d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1618d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1619d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnarstatic jobject android_media_MediaCodec_getImage(
1620d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        JNIEnv *env, jobject thiz, jboolean input, jint index) {
1621d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    ALOGV("android_media_MediaCodec_getImage");
1622d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1623d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1624d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1625d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (codec == NULL) {
16265f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1627d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return NULL;
1628d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1629d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1630d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    jobject image;
1631d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    status_t err = codec->getImage(env, input, index, &image);
1632d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1633d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err == OK) {
1634d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        return image;
1635d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1636d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1637d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    // if we're out of memory, an exception was already thrown
1638d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    if (err != NO_MEMORY) {
1639d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar        throwExceptionAsNecessary(env, err);
1640d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    }
1641d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1642d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    return NULL;
1643d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar}
1644d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1645056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjostatic jobject android_media_MediaCodec_getName(
1646056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        JNIEnv *env, jobject thiz) {
1647056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    ALOGV("android_media_MediaCodec_getName");
1648056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1649056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1650056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1651056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (codec == NULL) {
16525f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1653056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return NULL;
1654056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1655056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1656056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    jstring name;
1657056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    status_t err = codec->getName(env, &name);
1658056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1659056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    if (err == OK) {
1660056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo        return name;
1661056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    }
1662056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1663056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    throwExceptionAsNecessary(env, err);
1664056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
1665056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    return NULL;
1666056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo}
1667056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
16680e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essickstatic jobject
1669f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essickandroid_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
16700e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick{
1671f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essick    ALOGV("android_media_MediaCodec_native_getMetrics");
16720e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
16730e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
16740e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    if (codec == NULL ) {
16750e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick        jniThrowException(env, "java/lang/IllegalStateException", NULL);
16760e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick        return 0;
16770e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    }
16780e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
16790e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    // get what we have for the metrics from the codec
1680f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essick    MediaAnalyticsItem *item = NULL;
1681f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essick
1682f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essick    status_t err = codec->getMetrics(env, item);
16830e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    if (err != OK) {
16840e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick        ALOGE("getMetrics failed");
16850e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick        return (jobject) NULL;
16860e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    }
16870e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
16880e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    jobject mybundle = MediaMetricsJNI::writeMetricsToBundle(env, item, NULL);
16890e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
16900e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    // housekeeping
16910e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    delete item;
16920e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    item = NULL;
16930e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
16940e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick    return mybundle;
16950e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick}
16960e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
1697226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huberstatic void android_media_MediaCodec_setParameters(
1698226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        JNIEnv *env, jobject thiz, jobjectArray keys, jobjectArray vals) {
1699226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    ALOGV("android_media_MediaCodec_setParameters");
1700226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1701226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1702226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1703226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (codec == NULL) {
17045f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1705226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        return;
1706226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1707226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1708226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    sp<AMessage> params;
1709226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    status_t err = ConvertKeyValueArraysToMessage(env, keys, vals, &params);
1710226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1711226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    if (err == OK) {
1712226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber        err = codec->setParameters(params);
1713226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    }
1714226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1715226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    throwExceptionAsNecessary(env, err);
1716226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber}
1717226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
1718b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode(
1719b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        JNIEnv *env, jobject thiz, jint mode) {
1720b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    sp<JMediaCodec> codec = getMediaCodec(env, thiz);
1721b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1722b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (codec == NULL) {
17235f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        throwExceptionAsNecessary(env, INVALID_OPERATION);
1724b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1725b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1726b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1727b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW
1728b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber            && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) {
1729b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        jniThrowException(env, "java/lang/InvalidArgumentException", NULL);
1730b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber        return;
1731b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    }
1732b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
1733b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    codec->setVideoScalingMode(mode);
1734b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber}
1735b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
173688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) {
17378d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    ScopedLocalRef<jclass> clazz(
17388d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber            env, env->FindClass("android/media/MediaCodec"));
17398d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
174088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1741075e9a19ce645752f8282bc19c91b25978a7dc52Ashok Bhat    gFields.context = env->GetFieldID(clazz.get(), "mNativeContext", "J");
174288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    CHECK(gFields.context != NULL);
174391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
1744aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    gFields.postEventFromNativeID =
1745aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber        env->GetMethodID(
1746aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber                clazz.get(), "postEventFromNative", "(IIILjava/lang/Object;)V");
1747aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1748aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    CHECK(gFields.postEventFromNativeID != NULL);
1749aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
1750d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    jfieldID field;
1751d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_UNENCRYPTED", "I");
1752d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(field != NULL);
1753d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gCryptoModes.Unencrypted =
1754d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
1755d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1756d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CTR", "I");
1757d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(field != NULL);
1758d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gCryptoModes.AesCtr =
1759d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
1760d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1761d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "CRYPTO_MODE_AES_CBC", "I");
1762d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(field != NULL);
1763d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gCryptoModes.AesCbc =
1764d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
1765d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
17668d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo"));
17678d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
176891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
176991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumSubSamplesID =
17708d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numSubSamples", "I");
177191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumSubSamplesID != NULL);
177291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
177391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfClearDataID =
17748d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfClearData", "[I");
177591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL);
177691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
177791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    gFields.cryptoInfoNumBytesOfEncryptedDataID =
17788d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetFieldID(clazz.get(), "numBytesOfEncryptedData", "[I");
177991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL);
178091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
17818d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoKeyID = env->GetFieldID(clazz.get(), "key", "[B");
178291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoKeyID != NULL);
178391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
17848d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoIVID = env->GetFieldID(clazz.get(), "iv", "[B");
178591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoIVID != NULL);
178691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber
17878d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gFields.cryptoInfoModeID = env->GetFieldID(clazz.get(), "mode", "I");
178891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber    CHECK(gFields.cryptoInfoModeID != NULL);
17893ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
1790d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gFields.cryptoInfoPatternID = env->GetFieldID(clazz.get(), "pattern",
1791d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker        "Landroid/media/MediaCodec$CryptoInfo$Pattern;");
1792d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(gFields.cryptoInfoPatternID != NULL);
1793d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1794d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoInfo$Pattern"));
1795d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(clazz.get() != NULL);
1796d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1797d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gFields.patternEncryptBlocksID = env->GetFieldID(clazz.get(), "mEncryptBlocks", "I");
1798d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(gFields.patternEncryptBlocksID != NULL);
1799d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
1800d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    gFields.patternSkipBlocksID = env->GetFieldID(clazz.get(), "mSkipBlocks", "I");
1801d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker    CHECK(gFields.patternSkipBlocksID != NULL);
1802d4ea5d3eb630476a43da2adb4ac518360bd64758Jeff Tinker
18038d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    clazz.reset(env->FindClass("android/media/MediaCodec$CryptoException"));
18048d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    CHECK(clazz.get() != NULL);
18053ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
18068d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_NO_KEY", "I");
18073ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
18088d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorNoKey =
18098d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
18103ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
18118d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_KEY_EXPIRED", "I");
18123ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
18138d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorKeyExpired =
18148d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
18153ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker
18168d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    field = env->GetStaticFieldID(clazz.get(), "ERROR_RESOURCE_BUSY", "I");
18173ed38266c1647c6219ae5ad89cb3f867cf66caaaJeff Tinker    CHECK(field != NULL);
18188d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber    gCryptoErrorCodes.cryptoErrorResourceBusy =
18198d5f3e31c914e29129f50fe9830d71adf52ab5cfAndreas Huber        env->GetStaticIntField(clazz.get(), field);
18205f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1821336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_OUTPUT_PROTECTION", "I");
1822336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    CHECK(field != NULL);
1823336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker    gCryptoErrorCodes.cryptoErrorInsufficientOutputProtection =
1824336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1825336d3eabc0d57fd2d1b8a9aa4ade7a0450cf183eJeff Tinker
182696a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_SESSION_NOT_OPENED", "I");
182796a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    CHECK(field != NULL);
182896a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker    gCryptoErrorCodes.cryptoErrorSessionNotOpened =
182996a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker        env->GetStaticIntField(clazz.get(), field);
183096a2a957e42e04be817b60bb27199f3846f00fc9Jeff Tinker
1831d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    field = env->GetStaticFieldID(clazz.get(), "ERROR_UNSUPPORTED_OPERATION", "I");
1832d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    CHECK(field != NULL);
1833d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker    gCryptoErrorCodes.cryptoErrorUnsupportedOperation =
1834d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker        env->GetStaticIntField(clazz.get(), field);
1835d393216f8a2186eebdb8615c61787ae599c1432fJeff Tinker
18365f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    clazz.reset(env->FindClass("android/media/MediaCodec$CodecException"));
18375f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(clazz.get() != NULL);
18385f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_TRANSIENT", "I");
18395f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
18405f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionTransient =
18415f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
18425f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
18435f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    field = env->GetStaticFieldID(clazz.get(), "ACTION_RECOVERABLE", "I");
18445f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    CHECK(field != NULL);
18455f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    gCodecActionCodes.codecActionRecoverable =
18465f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->GetStaticIntField(clazz.get(), field);
18479e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
1848c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "ERROR_INSUFFICIENT_RESOURCE", "I");
18499e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
1850c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    gCodecErrorCodes.errorInsufficientResource =
18519e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
18529e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu
1853c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    field = env->GetStaticFieldID(clazz.get(), "ERROR_RECLAIMED", "I");
18549e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu    CHECK(field != NULL);
1855c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    gCodecErrorCodes.errorReclaimed =
18569e9ec943ce7620bbfcadc2f8986a80ac58003e47Ronghua Wu        env->GetStaticIntField(clazz.get(), field);
18578034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18588034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    clazz.reset(env->FindClass("android/view/Surface"));
18598034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(clazz.get() != NULL);
18608034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18618034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    field = env->GetFieldID(clazz.get(), "mLock", "Ljava/lang/Object;");
18628034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(field != NULL);
18638034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.mLock = field;
18648034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18658034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    jmethodID method = env->GetMethodID(clazz.get(), "setNativeObjectLocked", "(J)V");
18668034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(method != NULL);
18678034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.setNativeObjectLocked = method;
18688034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18698034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    clazz.reset(env->FindClass("android/media/MediaCodec$PersistentSurface"));
18708034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(clazz.get() != NULL);
18718034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.clazz = (jclass)env->NewGlobalRef(clazz.get());
18728034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18738034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    method = env->GetMethodID(clazz.get(), "<init>", "()V");
18748034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(method != NULL);
18758034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.ctor = method;
18768034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
18778034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    field = env->GetFieldID(clazz.get(), "mPersistentObject", "J");
18788034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    CHECK(field != NULL);
18798034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    gPersistentSurfaceClassInfo.mPersistentObject = field;
188088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
188188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
188288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup(
188388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz,
188488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        jstring name, jboolean nameIsType, jboolean encoder) {
188588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (name == NULL) {
18865f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/NullPointerException", NULL);
188788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
188888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
188988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
189088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    const char *tmp = env->GetStringUTFChars(name, NULL);
189188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
189288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    if (tmp == NULL) {
189388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
189488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
189588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
189688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder);
189788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
18985f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    const status_t err = codec->initCheck();
18995f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    if (err == NAME_NOT_FOUND) {
19005f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // fail and do not try again.
19015f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/lang/IllegalArgumentException",
19025f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to initialize %s, error %#x", tmp, err));
1903c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        env->ReleaseStringUTFChars(name, tmp);
1904c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        return;
1905c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu    } if (err == NO_MEMORY) {
1906c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu        throwCodecException(env, err, ACTION_CODE_TRANSIENT,
1907c53ad69bcc920cdbdb15685ddad1d864631bb4f7Ronghua Wu                String8::format("Failed to initialize %s, error %#x", tmp, err));
19085f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
19095f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        return;
19105f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    } else if (err != OK) {
19115f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        // believed possible to try again
19125f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        jniThrowException(env, "java/io/IOException",
19135f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung                String8::format("Failed to find matching codec %s, error %#x", tmp, err));
19145f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung        env->ReleaseStringUTFChars(name, tmp);
191588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        return;
191688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    }
191788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19185f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung    env->ReleaseStringUTFChars(name, tmp);
19195f9aa0bcea8be860fdf5a35476435616cb5f44f3Andy Hung
1920aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    codec->registerSelf();
1921aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber
192288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    setMediaCodec(env,thiz, codec);
192388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
192488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
192588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize(
192688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber        JNIEnv *env, jobject thiz) {
192788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    android_media_MediaCodec_release(env, thiz);
192888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
192988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
193076f6a86de25e1bf74717e047e55fd44b089673f3Daniel Micaystatic const JNINativeMethod gMethods[] = {
1931d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_release", "()V", (void *)android_media_MediaCodec_release },
193288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19331e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar    { "native_reset", "()V", (void *)android_media_MediaCodec_reset },
19341e6e8018a4f914210b615bfca0f818fd13574228Lajos Molnar
19358034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    { "native_releasePersistentInputSurface",
19368034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang      "(Landroid/view/Surface;)V",
19378034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang       (void *)android_media_MediaCodec_releasePersistentInputSurface},
19388034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
19398034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang    { "native_createPersistentInputSurface",
19408034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang      "()Landroid/media/MediaCodec$PersistentSurface;",
19418034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang      (void *)android_media_MediaCodec_createPersistentInputSurface },
19428034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
19439560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang    { "native_setInputSurface", "(Landroid/view/Surface;)V",
19449560ddb48af0e2da7743452f8d9d6d9cd34d8438Chong Zhang      (void *)android_media_MediaCodec_setInputSurface },
19458034d60f6e044deafe48501dfbfe17c31284bc17Chong Zhang
1946d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar    { "native_enableOnFrameRenderedListener", "(Z)V",
1947d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar      (void *)android_media_MediaCodec_native_enableOnFrameRenderedListener },
1948d8578577b02cf6360402eb8726e964d18b46434dLajos Molnar
19498d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang    { "native_setCallback",
19508d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      "(Landroid/media/MediaCodec$Callback;)V",
19518d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang      (void *)android_media_MediaCodec_native_setCallback },
19528d5e556b2b76278000a506382fdf594c071e1fbdChong Zhang
195388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_configure",
19548240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber      "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;"
1955d5927ae8833780395f8fc5070d0a0a4f8f668292Chong Zhang      "Landroid/media/MediaCrypto;Landroid/os/IBinder;I)V",
195688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_configure },
195788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19585e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar    { "native_setSurface",
19595e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar      "(Landroid/view/Surface;)V",
19605e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar      (void *)android_media_MediaCodec_native_setSurface },
19615e02ba977ede1e38c9f206057ec3f0f1e89ba943Lajos Molnar
19622621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "createInputSurface", "()Landroid/view/Surface;",
19632621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_createInputSurface },
19642621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1965d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_start", "()V", (void *)android_media_MediaCodec_start },
1966aba671392d6606e35726c350a28d0c9b36ebfe16Andreas Huber    { "native_stop", "()V", (void *)android_media_MediaCodec_stop },
1967d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_flush", "()V", (void *)android_media_MediaCodec_flush },
196888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1969d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueInputBuffer", "(IIIJI)V",
197088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_queueInputBuffer },
197188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1972d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V",
19739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber      (void *)android_media_MediaCodec_queueSecureInputBuffer },
19749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber
1975d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueInputBuffer", "(J)I",
197688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueInputBuffer },
197788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1978d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "native_dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I",
197988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_dequeueOutputBuffer },
198088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19817c513b6bef8ed4dfc28e0af6c8594563fdb9f436Lajos Molnar    { "releaseOutputBuffer", "(IZZJ)V",
198288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_releaseOutputBuffer },
198388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
19842621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden    { "signalEndOfInputStream", "()V",
19852621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden      (void *)android_media_MediaCodec_signalEndOfInputStream },
19862621e40d0e0a496a96575768b7e2b70e3b3be640Andy McFadden
1987d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getFormatNative", "(Z)Ljava/util/Map;",
1988d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getFormatNative },
1989d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1990d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getOutputFormatNative", "(I)Ljava/util/Map;",
1991d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getOutputFormatForIndexNative },
199288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
199388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;",
199488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_getBuffers },
199588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
1996d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getBuffer", "(ZI)Ljava/nio/ByteBuffer;",
1997d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getBuffer },
1998d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
1999d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar    { "getImage", "(ZI)Landroid/media/Image;",
2000d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar      (void *)android_media_MediaCodec_getImage },
2001d4023114e8cf7ec7db4d07958a303699b658f2c0Lajos Molnar
2002056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo    { "getName", "()Ljava/lang/String;",
2003056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo      (void *)android_media_MediaCodec_getName },
2004056ef2ed5ff92b742fe53f2498c596ec1f6bed3cMartin Storsjo
200510353e36018224b86ef2918d1d68107459d445cfRay Essick    { "native_getMetrics", "()Landroid/os/PersistableBundle;",
2006f2d0e40bf01fa133dd6b36f3716005d53fa9776cRay Essick      (void *)android_media_MediaCodec_native_getMetrics},
20070e0fee1e3a04023c9ec122d3bd7da54e9565c3e7Ray Essick
2008226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber    { "setParameters", "([Ljava/lang/String;[Ljava/lang/Object;)V",
2009226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber      (void *)android_media_MediaCodec_setParameters },
2010226065bbe60cf32b33a5f86d27e2db88138e4486Andreas Huber
2011b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber    { "setVideoScalingMode", "(I)V",
2012b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber      (void *)android_media_MediaCodec_setVideoScalingMode },
2013b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber
201488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodec_native_init },
201588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
201688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_setup", "(Ljava/lang/String;ZZ)V",
201788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_setup },
201888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
201988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    { "native_finalize", "()V",
202088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber      (void *)android_media_MediaCodec_native_finalize },
202188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber};
202288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber
202388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) {
202488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
202588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber                "android/media/MediaCodec", gMethods, NELEM(gMethods));
202688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}
2027