android_media_MediaCodec.cpp revision b12a5390694e8525ac61d7377e266e31d124c815
188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber/* 288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Copyright 2012, The Android Open Source Project 388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * 488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * you may not use this file except in compliance with the License. 688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * You may obtain a copy of the License at 788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * 888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * 1088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * Unless required by applicable law or agreed to in writing, software 1188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 1288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * See the License for the specific language governing permissions and 1488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber * limitations under the License. 1588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber */ 1688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 1788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber//#define LOG_NDEBUG 0 1888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#define LOG_TAG "MediaCodec-JNI" 1988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <utils/Log.h> 2088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 2188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_MediaCodec.h" 2288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 2307ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber#include "android_media_MediaCrypto.h" 2488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_media_Utils.h" 2588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/AndroidRuntime.h" 2688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "android_runtime/android_view_Surface.h" 2788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "jni.h" 2888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include "JNIHelp.h" 2988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 308335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/Surface.h> 318335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian#include <gui/SurfaceTextureClient.h> 328335f1ccccedb6655d96d9d5b697a7f0938235ddMathias Agopian 330e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber#include <media/ICrypto.h> 3488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaCodec.h> 3588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ABuffer.h> 3688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ADebug.h> 3788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/ALooper.h> 3888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/foundation/AMessage.h> 39bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber#include <media/stagefright/foundation/AString.h> 4088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber#include <media/stagefright/MediaErrors.h> 4188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 42b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber#include <system/window.h> 43b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 4488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Hubernamespace android { 4588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 4688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber// Keep these in sync with their equivalents in MediaCodec.java !!! 4788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberenum { 4888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber DEQUEUE_INFO_TRY_AGAIN_LATER = -1, 4988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED = -2, 5088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED = -3, 5188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}; 5288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 5388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstruct fields_t { 5488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jfieldID context; 5591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 5691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jfieldID cryptoInfoNumSubSamplesID; 5791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jfieldID cryptoInfoNumBytesOfClearDataID; 5891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jfieldID cryptoInfoNumBytesOfEncryptedDataID; 5991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jfieldID cryptoInfoKeyID; 6091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jfieldID cryptoInfoIVID; 6191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jfieldID cryptoInfoModeID; 6288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}; 6388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 6488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic fields_t gFields; 6588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 6688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber//////////////////////////////////////////////////////////////////////////////// 6788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 6888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::JMediaCodec( 6988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, 7088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber const char *name, bool nameIsType, bool encoder) 7188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber : mClass(NULL), 7288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mObject(NULL) { 7388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jclass clazz = env->GetObjectClass(thiz); 7488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber CHECK(clazz != NULL); 7588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 7688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mClass = (jclass)env->NewGlobalRef(clazz); 7788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mObject = env->NewWeakGlobalRef(thiz); 7888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 7988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mLooper = new ALooper; 8088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mLooper->setName("MediaCodec_looper"); 8188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 8288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mLooper->start( 8388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber false, // runOnCallingThread 8488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber false, // canCallJava 8588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber PRIORITY_DEFAULT); 8688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 8788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (nameIsType) { 8888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mCodec = MediaCodec::CreateByType(mLooper, name, encoder); 8988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } else { 9088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mCodec = MediaCodec::CreateByComponentName(mLooper, name); 9188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 9288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 9388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 9488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::initCheck() const { 9588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return mCodec != NULL ? OK : NO_INIT; 9688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 9788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 9888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas HuberJMediaCodec::~JMediaCodec() { 994484bdd2f99a753b0801f0c13ca8a2b7bc38695aAndreas Huber mCodec->release(); 10088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 10188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env = AndroidRuntime::getJNIEnv(); 10288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 10388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->DeleteWeakGlobalRef(mObject); 10488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mObject = NULL; 10588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->DeleteGlobalRef(mClass); 10688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber mClass = NULL; 10788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 10888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 10988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::configure( 11088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber const sp<AMessage> &format, 11188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber const sp<ISurfaceTexture> &surfaceTexture, 1128240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber const sp<ICrypto> &crypto, 11388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber int flags) { 11488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<SurfaceTextureClient> client; 11588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (surfaceTexture != NULL) { 116b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber mSurfaceTextureClient = new SurfaceTextureClient(surfaceTexture); 117b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber } else { 118b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber mSurfaceTextureClient.clear(); 11988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 120b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 121b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber return mCodec->configure(format, mSurfaceTextureClient, crypto, flags); 12288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 12388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 12488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::start() { 12588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return mCodec->start(); 12688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 12788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 12888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::stop() { 129b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber mSurfaceTextureClient.clear(); 130b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 13188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return mCodec->stop(); 13288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 13388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 13488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::flush() { 13588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return mCodec->flush(); 13688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 13788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 13888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::queueInputBuffer( 13988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber size_t index, 140bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber size_t offset, size_t size, int64_t timeUs, uint32_t flags, 141bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber AString *errorDetailMsg) { 142bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber return mCodec->queueInputBuffer( 143bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber index, offset, size, timeUs, flags, errorDetailMsg); 14488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 14588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 1469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatus_t JMediaCodec::queueSecureInputBuffer( 1479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber size_t index, 1489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber size_t offset, 1499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber const CryptoPlugin::SubSample *subSamples, 1509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber size_t numSubSamples, 1519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber const uint8_t key[16], 1529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber const uint8_t iv[16], 1539e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber CryptoPlugin::Mode mode, 1549e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber int64_t presentationTimeUs, 155bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber uint32_t flags, 156bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber AString *errorDetailMsg) { 1579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber return mCodec->queueSecureInputBuffer( 1589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber index, offset, subSamples, numSubSamples, key, iv, mode, 159bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber presentationTimeUs, flags, errorDetailMsg); 1609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber} 1619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 16288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueInputBuffer(size_t *index, int64_t timeoutUs) { 16388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return mCodec->dequeueInputBuffer(index, timeoutUs); 16488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 16588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 16688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::dequeueOutputBuffer( 16788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject bufferInfo, size_t *index, int64_t timeoutUs) { 16888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber size_t size, offset; 16988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber int64_t timeUs; 17088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber uint32_t flags; 17188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err; 17288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if ((err = mCodec->dequeueOutputBuffer( 173c52b980277f08aee7981b1fdbca7a89464cf66d9Andreas Huber index, &offset, &size, &timeUs, &flags, timeoutUs)) != OK) { 17488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return err; 17588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 17688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 17788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jclass clazz = env->FindClass("android/media/MediaCodec$BufferInfo"); 17888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 17988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jmethodID method = env->GetMethodID(clazz, "set", "(IIJI)V"); 18088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags); 18188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 18288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return OK; 18388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 18488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 18588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::releaseOutputBuffer(size_t index, bool render) { 18688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return render 18788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ? mCodec->renderOutputBufferAndRelease(index) 18888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber : mCodec->releaseOutputBuffer(index); 18988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 19088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 19188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getOutputFormat(JNIEnv *env, jobject *format) const { 19288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<AMessage> msg; 19388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err; 19488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if ((err = mCodec->getOutputFormat(&msg)) != OK) { 19588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return err; 19688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 19788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 19888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return ConvertMessageToMap(env, msg, format); 19988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 20088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 20188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatus_t JMediaCodec::getBuffers( 20288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, bool input, jobjectArray *bufArray) const { 20388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber Vector<sp<ABuffer> > buffers; 20488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 20588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = 20688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber input 20788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ? mCodec->getInputBuffers(&buffers) 20888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber : mCodec->getOutputBuffers(&buffers); 20988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 21088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err != OK) { 21188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return err; 21288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 21388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 21488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jclass byteBufferClass = env->FindClass("java/nio/ByteBuffer"); 21588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 21688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *bufArray = (jobjectArray)env->NewObjectArray( 21788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber buffers.size(), byteBufferClass, NULL); 21888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 21988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber for (size_t i = 0; i < buffers.size(); ++i) { 22088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber const sp<ABuffer> &buffer = buffers.itemAt(i); 22188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 22288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobject byteBuffer = 22388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->NewDirectByteBuffer( 22488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber buffer->base(), 22588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber buffer->capacity()); 22688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 22788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->SetObjectArrayElement( 22888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber *bufArray, i, byteBuffer); 22988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 23088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->DeleteLocalRef(byteBuffer); 23188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber byteBuffer = NULL; 23288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 23388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 23488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return OK; 23588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 23688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 237b12a5390694e8525ac61d7377e266e31d124c815Andreas Hubervoid JMediaCodec::setVideoScalingMode(int mode) { 238b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber if (mSurfaceTextureClient != NULL) { 239b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber native_window_set_scaling_mode(mSurfaceTextureClient.get(), mode); 240b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber } 241b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber} 242b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 24388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} // namespace android 24488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 24588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber//////////////////////////////////////////////////////////////////////////////// 24688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 24788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberusing namespace android; 24888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 24988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> setMediaCodec( 25088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, const sp<JMediaCodec> &codec) { 25188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> old = (JMediaCodec *)env->GetIntField(thiz, gFields.context); 25288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec != NULL) { 25388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber codec->incStrong(thiz); 25488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 25588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (old != NULL) { 25688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber old->decStrong(thiz); 25788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 25888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->SetIntField(thiz, gFields.context, (int)codec.get()); 25988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 26088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return old; 26188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 26288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 26388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic sp<JMediaCodec> getMediaCodec(JNIEnv *env, jobject thiz) { 26488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return (JMediaCodec *)env->GetIntField(thiz, gFields.context); 26588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 26688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 26788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_release(JNIEnv *env, jobject thiz) { 26888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber setMediaCodec(env, thiz, NULL); 26988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 27088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 271bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic void throwCryptoException(JNIEnv *env, status_t err, const char *msg) { 272bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber jclass clazz = env->FindClass("android/media/MediaCodec$CryptoException"); 273bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber CHECK(clazz != NULL); 274bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 275bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber jmethodID constructID = 276bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber env->GetMethodID(clazz, "<init>", "(ILjava/lang/String;)V"); 277bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber CHECK(constructID != NULL); 278bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 279bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber jstring msgObj = env->NewStringUTF(msg != NULL ? msg : "Unknown Error"); 280bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 281bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber jthrowable exception = 282bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber (jthrowable)env->NewObject(clazz, constructID, err, msgObj); 283bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 284bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber env->Throw(exception); 285bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber} 286bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 287bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huberstatic jint throwExceptionAsNecessary( 288bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber JNIEnv *env, status_t err, const char *msg = NULL) { 289bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber if (err >= ERROR_DRM_WV_VENDOR_MIN && err <= ERROR_DRM_WV_VENDOR_MAX) { 290bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber // We'll throw our custom MediaCodec.CryptoException 291bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 292bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber throwCryptoException(env, err, msg); 293bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber return 0; 294bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber } 295bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 29688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber switch (err) { 29788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber case OK: 29888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return 0; 29988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 30088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber case -EAGAIN: 30188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return DEQUEUE_INFO_TRY_AGAIN_LATER; 30288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 30388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber case INFO_FORMAT_CHANGED: 30488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return DEQUEUE_INFO_OUTPUT_FORMAT_CHANGED; 30588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 30688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber case INFO_OUTPUT_BUFFERS_CHANGED: 30788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return DEQUEUE_INFO_OUTPUT_BUFFERS_CHANGED; 30888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 30988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber default: 31088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { 31188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 31288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber break; 31388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 31488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 31588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 31688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return 0; 31788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 31888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 31988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_configure( 32088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, 32188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobject thiz, 32288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobjectArray keys, jobjectArray values, 32388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobject jsurface, 3248240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber jobject jcrypto, 32588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jint flags) { 32688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 32788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 32888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 32988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 33088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 33188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 33288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 33388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<AMessage> format; 33488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = ConvertKeyValueArraysToMessage(env, keys, values, &format); 33588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 33688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err != OK) { 33788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 33888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 33988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 34088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 34188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<ISurfaceTexture> surfaceTexture; 34288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (jsurface != NULL) { 34388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<Surface> surface(Surface_getSurface(env, jsurface)); 34488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (surface != NULL) { 34588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber surfaceTexture = surface->getSurfaceTexture(); 34688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } else { 34788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException( 34888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env, 34988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber "java/lang/IllegalArgumentException", 35088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber "The surface has been released"); 35188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 35288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 35388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 35488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 3558240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber sp<ICrypto> crypto; 3568240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber if (jcrypto != NULL) { 3578240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber crypto = JCrypto::GetCrypto(env, jcrypto); 3588240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber } 3598240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber 3608240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber err = codec->configure(format, surfaceTexture, crypto, flags); 36188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 36288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 36388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 36488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 36588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_start(JNIEnv *env, jobject thiz) { 36688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_start"); 36788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 36888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 36988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 37088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 37188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 37288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 37388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 37488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 37588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->start(); 37688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 37788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 37888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 37988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 38088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_stop(JNIEnv *env, jobject thiz) { 38188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_stop"); 38288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 38388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 38488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 38588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 38688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 38788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 38888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 38988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 39088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->stop(); 39188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 39288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 39388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 39488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 39588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_flush(JNIEnv *env, jobject thiz) { 39688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_flush"); 39788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 39888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 39988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 40088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 40188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 40288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 40388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 40488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 40588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->flush(); 40688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 40788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 40888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 40988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 41088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_queueInputBuffer( 41188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, 41288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobject thiz, 41388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jint index, 41488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jint offset, 41588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jint size, 41688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jlong timestampUs, 41788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jint flags) { 41888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_queueInputBuffer"); 41988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 42088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 42188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 42288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 42388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 42488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 42588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 42688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 427bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber AString errorDetailMsg; 428bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 42988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->queueInputBuffer( 430bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber index, offset, size, timestampUs, flags, &errorDetailMsg); 43188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 432bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber throwExceptionAsNecessary( 433bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str()); 43488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 43588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 4369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huberstatic void android_media_MediaCodec_queueSecureInputBuffer( 4379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber JNIEnv *env, 4389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jobject thiz, 4399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jint index, 4409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jint offset, 44191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jobject cryptoInfoObj, 4429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jlong timestampUs, 4439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jint flags) { 4449e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber ALOGV("android_media_MediaCodec_queueSecureInputBuffer"); 4459e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 4469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 4479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 4489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (codec == NULL) { 4499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 4509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber return; 4519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 4529e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 45391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jint numSubSamples = 45491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber env->GetIntField(cryptoInfoObj, gFields.cryptoInfoNumSubSamplesID); 45591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 45691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jintArray numBytesOfClearDataObj = 45791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber (jintArray)env->GetObjectField( 45891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber cryptoInfoObj, gFields.cryptoInfoNumBytesOfClearDataID); 45991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 46091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jintArray numBytesOfEncryptedDataObj = 46191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber (jintArray)env->GetObjectField( 46291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber cryptoInfoObj, gFields.cryptoInfoNumBytesOfEncryptedDataID); 46391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 46491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jbyteArray keyObj = 46591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoKeyID); 46691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 46791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jbyteArray ivObj = 46891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber (jbyteArray)env->GetObjectField(cryptoInfoObj, gFields.cryptoInfoIVID); 46991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 47091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber jint mode = env->GetIntField(cryptoInfoObj, gFields.cryptoInfoModeID); 47191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 4729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber status_t err = OK; 4739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 4749e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber CryptoPlugin::SubSample *subSamples = NULL; 4759e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jbyte *key = NULL; 4769e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jbyte *iv = NULL; 4779e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 4789e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (numSubSamples <= 0) { 4799e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = -EINVAL; 4809e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } else if (numBytesOfClearDataObj == NULL 4819e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber && numBytesOfEncryptedDataObj == NULL) { 4829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = -EINVAL; 4839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } else if (numBytesOfEncryptedDataObj != NULL 4849e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber && env->GetArrayLength(numBytesOfEncryptedDataObj) < numSubSamples) { 4859e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = -ERANGE; 4869e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } else if (numBytesOfClearDataObj != NULL 4879e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber && env->GetArrayLength(numBytesOfClearDataObj) < numSubSamples) { 4889e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = -ERANGE; 4899e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } else { 4909e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jboolean isCopy; 4919e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 4929e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jint *numBytesOfClearData = 4939e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (numBytesOfClearDataObj == NULL) 4949e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber ? NULL 4959e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber : env->GetIntArrayElements(numBytesOfClearDataObj, &isCopy); 4969e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 4979e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jint *numBytesOfEncryptedData = 4989e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (numBytesOfEncryptedDataObj == NULL) 4999e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber ? NULL 5009e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber : env->GetIntArrayElements(numBytesOfEncryptedDataObj, &isCopy); 5019e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5029e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber subSamples = new CryptoPlugin::SubSample[numSubSamples]; 5039e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5049e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber for (jint i = 0; i < numSubSamples; ++i) { 5059e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber subSamples[i].mNumBytesOfClearData = 5069e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (numBytesOfClearData == NULL) ? 0 : numBytesOfClearData[i]; 5079e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5089e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber subSamples[i].mNumBytesOfEncryptedData = 5099e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (numBytesOfEncryptedData == NULL) 5109e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber ? 0 : numBytesOfEncryptedData[i]; 5119e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5129e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5139e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (numBytesOfEncryptedData != NULL) { 5149e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber env->ReleaseIntArrayElements( 5159e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber numBytesOfEncryptedDataObj, numBytesOfEncryptedData, 0); 5169e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber numBytesOfEncryptedData = NULL; 5179e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5189e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5199e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (numBytesOfClearData != NULL) { 5209e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber env->ReleaseIntArrayElements( 5219e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber numBytesOfClearDataObj, numBytesOfClearData, 0); 5229e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber numBytesOfClearData = NULL; 5239e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5249e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5259e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5269e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (err == OK && keyObj != NULL) { 5279e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (env->GetArrayLength(keyObj) != 16) { 5289e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = -EINVAL; 5299e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } else { 5309e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jboolean isCopy; 5319e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber key = env->GetByteArrayElements(keyObj, &isCopy); 5329e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5339e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5349e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5359e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (err == OK && ivObj != NULL) { 5369e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (env->GetArrayLength(ivObj) != 16) { 5379e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = -EINVAL; 5389e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } else { 5399e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber jboolean isCopy; 5409e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber iv = env->GetByteArrayElements(ivObj, &isCopy); 5419e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5429e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5439e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 544bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber AString errorDetailMsg; 545bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber 5469e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (err == OK) { 5479e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber err = codec->queueSecureInputBuffer( 5489e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber index, offset, 5499e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber subSamples, numSubSamples, 5509e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (const uint8_t *)key, (const uint8_t *)iv, 5519e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (CryptoPlugin::Mode)mode, 552bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber timestampUs, 553bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber flags, 554bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber &errorDetailMsg); 5559e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5569e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5579e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (iv != NULL) { 5589e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber env->ReleaseByteArrayElements(ivObj, iv, 0); 5599e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber iv = NULL; 5609e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5619e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5629e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber if (key != NULL) { 5639e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber env->ReleaseByteArrayElements(keyObj, key, 0); 5649e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber key = NULL; 5659e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber } 5669e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 5679e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber delete[] subSamples; 5689e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber subSamples = NULL; 5699e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 570bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber throwExceptionAsNecessary( 571bfc56f497de0d18125366a02a93e61cdc0891be4Andreas Huber env, err, errorDetailMsg.empty() ? NULL : errorDetailMsg.c_str()); 5729e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber} 5739e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 57488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueInputBuffer( 57588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, jlong timeoutUs) { 57688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_dequeueInputBuffer"); 57788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 57888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 57988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 58088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 58188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 58288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return -1; 58388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 58488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 58588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber size_t index; 58688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->dequeueInputBuffer(&index, timeoutUs); 58788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 58888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err == OK) { 58988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return index; 59088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 59188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 59288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return throwExceptionAsNecessary(env, err); 59388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 59488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 59588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jint android_media_MediaCodec_dequeueOutputBuffer( 59688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, jobject bufferInfo, jlong timeoutUs) { 59788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_dequeueOutputBuffer"); 59888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 59988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 60088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 60188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 60288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 6030e97fc248eaea7b4c95053618ddedf0af638110eAndreas Huber return 0; 60488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 60588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 60688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber size_t index; 60788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->dequeueOutputBuffer( 60888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env, bufferInfo, &index, timeoutUs); 60988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 61088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err == OK) { 61188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return index; 61288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 61388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 61488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return throwExceptionAsNecessary(env, err); 61588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 61688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 61788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_releaseOutputBuffer( 61888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, jint index, jboolean render) { 61988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_renderOutputBufferAndRelease"); 62088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 62188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 62288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 62388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 62488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 62588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 62688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 62788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 62888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->releaseOutputBuffer(index, render); 62988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 63088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 63188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 63288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 63388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobject android_media_MediaCodec_getOutputFormat( 63488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz) { 63588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_getOutputFormat"); 63688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 63788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 63888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 63988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 64088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 64188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return NULL; 64288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 64388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 64488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobject format; 64588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->getOutputFormat(env, &format); 64688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 64788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err == OK) { 64888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return format; 64988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 65088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 65188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 65288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 65388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return NULL; 65488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 65588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 65688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic jobjectArray android_media_MediaCodec_getBuffers( 65788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, jboolean input) { 65888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber ALOGV("android_media_MediaCodec_getBuffers"); 65988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 66088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 66188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 66288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (codec == NULL) { 66388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 66488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return NULL; 66588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 66688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 66788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jobjectArray buffers; 66888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->getBuffers(env, input, &buffers); 66988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 67088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err == OK) { 67188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return buffers; 67288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 67388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 67488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber throwExceptionAsNecessary(env, err); 67588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 67688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return NULL; 67788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 67888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 679b12a5390694e8525ac61d7377e266e31d124c815Andreas Huberstatic void android_media_MediaCodec_setVideoScalingMode( 680b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber JNIEnv *env, jobject thiz, jint mode) { 681b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber sp<JMediaCodec> codec = getMediaCodec(env, thiz); 682b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 683b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber if (codec == NULL) { 684b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber jniThrowException(env, "java/lang/IllegalStateException", NULL); 685b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber return; 686b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber } 687b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 688b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber if (mode != NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW 689b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber && mode != NATIVE_WINDOW_SCALING_MODE_SCALE_CROP) { 690b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber jniThrowException(env, "java/lang/InvalidArgumentException", NULL); 691b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber return; 692b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber } 693b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 694b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber codec->setVideoScalingMode(mode); 695b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber} 696b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 69788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_init(JNIEnv *env) { 69888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jclass clazz = env->FindClass("android/media/MediaCodec"); 69988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber CHECK(clazz != NULL); 70088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 70188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber gFields.context = env->GetFieldID(clazz, "mNativeContext", "I"); 70288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber CHECK(gFields.context != NULL); 70391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 70491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber clazz = env->FindClass("android/media/MediaCodec$CryptoInfo"); 70591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(clazz != NULL); 70691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 70791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber gFields.cryptoInfoNumSubSamplesID = 70891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber env->GetFieldID(clazz, "numSubSamples", "I"); 70991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(gFields.cryptoInfoNumSubSamplesID != NULL); 71091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 71191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber gFields.cryptoInfoNumBytesOfClearDataID = 71291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber env->GetFieldID(clazz, "numBytesOfClearData", "[I"); 71391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(gFields.cryptoInfoNumBytesOfClearDataID != NULL); 71491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 71591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber gFields.cryptoInfoNumBytesOfEncryptedDataID = 71691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber env->GetFieldID(clazz, "numBytesOfEncryptedData", "[I"); 71791befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(gFields.cryptoInfoNumBytesOfEncryptedDataID != NULL); 71891befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 71991befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber gFields.cryptoInfoKeyID = env->GetFieldID(clazz, "key", "[B"); 72091befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(gFields.cryptoInfoKeyID != NULL); 72191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 72291befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber gFields.cryptoInfoIVID = env->GetFieldID(clazz, "iv", "[B"); 72391befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(gFields.cryptoInfoIVID != NULL); 72491befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber 72591befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber gFields.cryptoInfoModeID = env->GetFieldID(clazz, "mode", "I"); 72691befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber CHECK(gFields.cryptoInfoModeID != NULL); 72788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 72888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 72988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_setup( 73088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz, 73188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jstring name, jboolean nameIsType, jboolean encoder) { 73288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (name == NULL) { 73388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 73488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 73588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 73688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 73788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber const char *tmp = env->GetStringUTFChars(name, NULL); 73888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 73988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (tmp == NULL) { 74088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 74188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 74288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 74388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber sp<JMediaCodec> codec = new JMediaCodec(env, thiz, tmp, nameIsType, encoder); 74488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 74588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber status_t err = codec->initCheck(); 74688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 74788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env->ReleaseStringUTFChars(name, tmp); 74888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber tmp = NULL; 74988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 75088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber if (err != OK) { 75188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber jniThrowException( 75288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber env, 75388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber "java/io/IOException", 75488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber "Failed to allocate component instance"); 75588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return; 75688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber } 75788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 75888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber setMediaCodec(env,thiz, codec); 75988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 76088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 76188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic void android_media_MediaCodec_native_finalize( 76288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber JNIEnv *env, jobject thiz) { 76388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber android_media_MediaCodec_release(env, thiz); 76488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 76588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 76688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberstatic JNINativeMethod gMethods[] = { 76788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "release", "()V", (void *)android_media_MediaCodec_release }, 76888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 76988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "native_configure", 7708240d9239d9aabed75c49f9d4d69fd8a5fe4c899Andreas Huber "([Ljava/lang/String;[Ljava/lang/Object;Landroid/view/Surface;" 77107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber "Landroid/media/MediaCrypto;I)V", 77288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_native_configure }, 77388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 77488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "start", "()V", (void *)android_media_MediaCodec_start }, 77588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "stop", "()V", (void *)android_media_MediaCodec_stop }, 77688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "flush", "()V", (void *)android_media_MediaCodec_flush }, 77788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 77888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "queueInputBuffer", "(IIIJI)V", 77988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_queueInputBuffer }, 78088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 78191befdc0c4710234840cdfd853e7d30e8f9de62cAndreas Huber { "queueSecureInputBuffer", "(IILandroid/media/MediaCodec$CryptoInfo;JI)V", 7829e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber (void *)android_media_MediaCodec_queueSecureInputBuffer }, 7839e6bcce17d13bd4f7bba5f8fbcc2e6a0d695274bAndreas Huber 78488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "dequeueInputBuffer", "(J)I", 78588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_dequeueInputBuffer }, 78688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 78788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "dequeueOutputBuffer", "(Landroid/media/MediaCodec$BufferInfo;J)I", 78888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_dequeueOutputBuffer }, 78988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 79088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "releaseOutputBuffer", "(IZ)V", 79188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_releaseOutputBuffer }, 79288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 79388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "getOutputFormat", "()Ljava/util/Map;", 79488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_getOutputFormat }, 79588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 79688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "getBuffers", "(Z)[Ljava/nio/ByteBuffer;", 79788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_getBuffers }, 79888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 799b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber { "setVideoScalingMode", "(I)V", 800b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber (void *)android_media_MediaCodec_setVideoScalingMode }, 801b12a5390694e8525ac61d7377e266e31d124c815Andreas Huber 80288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "native_init", "()V", (void *)android_media_MediaCodec_native_init }, 80388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 80488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "native_setup", "(Ljava/lang/String;ZZ)V", 80588572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_native_setup }, 80688572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 80788572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber { "native_finalize", "()V", 80888572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber (void *)android_media_MediaCodec_native_finalize }, 80988572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber}; 81088572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber 81188572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huberint register_android_media_MediaCodec(JNIEnv *env) { 81288572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber return AndroidRuntime::registerNativeMethods(env, 81388572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber "android/media/MediaCodec", gMethods, NELEM(gMethods)); 81488572f7a3e9d7ef85c26865a0150f3c2041561c2Andreas Huber} 815