15a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber/* 25a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * Copyright 2012, The Android Open Source Project 35a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * 45a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License"); 55a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * you may not use this file except in compliance with the License. 65a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * You may obtain a copy of the License at 75a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * 85a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * http://www.apache.org/licenses/LICENSE-2.0 95a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * 105a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * Unless required by applicable law or agreed to in writing, software 115a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS, 125a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 135a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * See the License for the specific language governing permissions and 145a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber * limitations under the License. 155a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber */ 165a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 175a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber//#define LOG_NDEBUG 0 185a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#define LOG_TAG "MediaCodec-JNI" 195a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include <utils/Log.h> 205a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 215a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include <media/stagefright/foundation/ADebug.h> 225a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include <media/stagefright/MediaCodecList.h> 235a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 245a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include "android_runtime/AndroidRuntime.h" 255a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include "jni.h" 265a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include "JNIHelp.h" 275a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 285a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberusing namespace android; 295a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 3060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jint android_media_MediaCodecList_getCodecCount( 315a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber JNIEnv *env, jobject thiz) { 325a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return MediaCodecList::getInstance()->countCodecs(); 335a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 345a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 355a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jstring android_media_MediaCodecList_getCodecName( 365a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber JNIEnv *env, jobject thiz, jint index) { 375a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber const char *name = MediaCodecList::getInstance()->getCodecName(index); 385a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 395a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber if (name == NULL) { 405a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 415a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return NULL; 425a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 435a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 445a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return env->NewStringUTF(name); 455a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 465a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 475a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jboolean android_media_MediaCodecList_isEncoder( 485a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber JNIEnv *env, jobject thiz, jint index) { 495a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return MediaCodecList::getInstance()->isEncoder(index); 505a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 515a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 525a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jarray android_media_MediaCodecList_getSupportedTypes( 535a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber JNIEnv *env, jobject thiz, jint index) { 545a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber Vector<AString> types; 555a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber status_t err = 565a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber MediaCodecList::getInstance()->getSupportedTypes(index, &types); 575a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 585a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber if (err != OK) { 595a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 605a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return NULL; 615a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 625a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 635a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jclass clazz = env->FindClass("java/lang/String"); 645a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber CHECK(clazz != NULL); 655a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 665a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jobjectArray array = env->NewObjectArray(types.size(), clazz, NULL); 675a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 685a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber for (size_t i = 0; i < types.size(); ++i) { 695a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jstring obj = env->NewStringUTF(types.itemAt(i).c_str()); 705a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetObjectArrayElement(array, i, obj); 715a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->DeleteLocalRef(obj); 725a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber obj = NULL; 735a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 745a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 755a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return array; 765a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 775a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 785a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jobject android_media_MediaCodecList_getCodecCapabilities( 795a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber JNIEnv *env, jobject thiz, jint index, jstring type) { 805a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber if (type == NULL) { 815a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 825a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return NULL; 835a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 845a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 855a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber const char *typeStr = env->GetStringUTFChars(type, NULL); 865a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 875a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber if (typeStr == NULL) { 885a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber // Out of memory exception already pending. 895a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return NULL; 905a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 915a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 925a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber Vector<MediaCodecList::ProfileLevel> profileLevels; 935a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber Vector<uint32_t> colorFormats; 945a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 955a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber status_t err = 965a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber MediaCodecList::getInstance()->getCodecCapabilities( 975a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber index, typeStr, &profileLevels, &colorFormats); 985a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 995a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->ReleaseStringUTFChars(type, typeStr); 1005a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber typeStr = NULL; 1015a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1025a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber if (err != OK) { 1035a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 1045a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return NULL; 1055a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 1065a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1075a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jclass capsClazz = 10860d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber env->FindClass("android/media/MediaCodecInfo$CodecCapabilities"); 1095a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber CHECK(capsClazz != NULL); 1105a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1115a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jobject caps = env->AllocObject(capsClazz); 1125a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1135a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jclass profileLevelClazz = 11460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel"); 1155a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber CHECK(profileLevelClazz != NULL); 1165a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1175a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jobjectArray profileLevelArray = 1185a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL); 1195a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1205a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jfieldID profileField = 12107ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber env->GetFieldID(profileLevelClazz, "profile", "I"); 1225a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1235a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jfieldID levelField = 12407ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber env->GetFieldID(profileLevelClazz, "level", "I"); 1255a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1265a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber for (size_t i = 0; i < profileLevels.size(); ++i) { 1275a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber const MediaCodecList::ProfileLevel &src = profileLevels.itemAt(i); 1285a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1295a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jobject profileLevelObj = env->AllocObject(profileLevelClazz); 1305a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1315a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetIntField(profileLevelObj, profileField, src.mProfile); 1325a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetIntField(profileLevelObj, levelField, src.mLevel); 1335a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1345a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetObjectArrayElement(profileLevelArray, i, profileLevelObj); 1355a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1365a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->DeleteLocalRef(profileLevelObj); 1375a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber profileLevelObj = NULL; 1385a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 1395a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1405a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jfieldID profileLevelsField = env->GetFieldID( 1415a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber capsClazz, 14207ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber "profileLevels", 14360d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber "[Landroid/media/MediaCodecInfo$CodecProfileLevel;"); 1445a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1455a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetObjectField(caps, profileLevelsField, profileLevelArray); 1465a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1475a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->DeleteLocalRef(profileLevelArray); 1485a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber profileLevelArray = NULL; 1495a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1505a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jintArray colorFormatsArray = env->NewIntArray(colorFormats.size()); 1515a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1525a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber for (size_t i = 0; i < colorFormats.size(); ++i) { 1535a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jint val = colorFormats.itemAt(i); 1545a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetIntArrayRegion(colorFormatsArray, i, 1, &val); 1555a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber } 1565a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1575a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber jfieldID colorFormatsField = env->GetFieldID( 15807ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber capsClazz, "colorFormats", "[I"); 1595a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1605a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->SetObjectField(caps, colorFormatsField, colorFormatsArray); 1615a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1625a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber env->DeleteLocalRef(colorFormatsArray); 1635a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber colorFormatsArray = NULL; 1645a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1655a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return caps; 1665a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 1675a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1685a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic void android_media_MediaCodecList_native_init(JNIEnv *env) { 1695a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 1705a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1715a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic JNINativeMethod gMethods[] = { 17260d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber { "getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount }, 1735a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber { "getCodecName", "(I)Ljava/lang/String;", 1745a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber (void *)android_media_MediaCodecList_getCodecName }, 1755a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder }, 1765a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber { "getSupportedTypes", "(I)[Ljava/lang/String;", 1775a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber (void *)android_media_MediaCodecList_getSupportedTypes }, 1785a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1795a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber { "getCodecCapabilities", 18060d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", 1815a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber (void *)android_media_MediaCodecList_getCodecCapabilities }, 1825a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1835a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber { "native_init", "()V", (void *)android_media_MediaCodecList_native_init }, 1845a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}; 1855a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 1865a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberint register_android_media_MediaCodecList(JNIEnv *env) { 1875a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber return AndroidRuntime::registerNativeMethods(env, 1885a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber "android/media/MediaCodecList", gMethods, NELEM(gMethods)); 1895a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber} 1905a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber 191