1 /* 2 * Copyright 2012, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 //#define LOG_NDEBUG 0 18 #define LOG_TAG "MediaCodec-JNI" 19 #include <utils/Log.h> 20 21 #include <media/stagefright/foundation/ADebug.h> 22 #include <media/stagefright/MediaCodecList.h> 23 24 #include "android_runtime/AndroidRuntime.h" 25 #include "jni.h" 26 #include "JNIHelp.h" 27 28 using namespace android; 29 30 static jint android_media_MediaCodecList_getCodecCount( 31 JNIEnv *env, jobject thiz) { 32 return MediaCodecList::getInstance()->countCodecs(); 33 } 34 35 static jstring android_media_MediaCodecList_getCodecName( 36 JNIEnv *env, jobject thiz, jint index) { 37 const char *name = MediaCodecList::getInstance()->getCodecName(index); 38 39 if (name == NULL) { 40 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 41 return NULL; 42 } 43 44 return env->NewStringUTF(name); 45 } 46 47 static jboolean android_media_MediaCodecList_isEncoder( 48 JNIEnv *env, jobject thiz, jint index) { 49 return MediaCodecList::getInstance()->isEncoder(index); 50 } 51 52 static jarray android_media_MediaCodecList_getSupportedTypes( 53 JNIEnv *env, jobject thiz, jint index) { 54 Vector<AString> types; 55 status_t err = 56 MediaCodecList::getInstance()->getSupportedTypes(index, &types); 57 58 if (err != OK) { 59 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 60 return NULL; 61 } 62 63 jclass clazz = env->FindClass("java/lang/String"); 64 CHECK(clazz != NULL); 65 66 jobjectArray array = env->NewObjectArray(types.size(), clazz, NULL); 67 68 for (size_t i = 0; i < types.size(); ++i) { 69 jstring obj = env->NewStringUTF(types.itemAt(i).c_str()); 70 env->SetObjectArrayElement(array, i, obj); 71 env->DeleteLocalRef(obj); 72 obj = NULL; 73 } 74 75 return array; 76 } 77 78 static jobject android_media_MediaCodecList_getCodecCapabilities( 79 JNIEnv *env, jobject thiz, jint index, jstring type) { 80 if (type == NULL) { 81 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 82 return NULL; 83 } 84 85 const char *typeStr = env->GetStringUTFChars(type, NULL); 86 87 if (typeStr == NULL) { 88 // Out of memory exception already pending. 89 return NULL; 90 } 91 92 Vector<MediaCodecList::ProfileLevel> profileLevels; 93 Vector<uint32_t> colorFormats; 94 95 status_t err = 96 MediaCodecList::getInstance()->getCodecCapabilities( 97 index, typeStr, &profileLevels, &colorFormats); 98 99 env->ReleaseStringUTFChars(type, typeStr); 100 typeStr = NULL; 101 102 if (err != OK) { 103 jniThrowException(env, "java/lang/IllegalArgumentException", NULL); 104 return NULL; 105 } 106 107 jclass capsClazz = 108 env->FindClass("android/media/MediaCodecInfo$CodecCapabilities"); 109 CHECK(capsClazz != NULL); 110 111 jobject caps = env->AllocObject(capsClazz); 112 113 jclass profileLevelClazz = 114 env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel"); 115 CHECK(profileLevelClazz != NULL); 116 117 jobjectArray profileLevelArray = 118 env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL); 119 120 jfieldID profileField = 121 env->GetFieldID(profileLevelClazz, "profile", "I"); 122 123 jfieldID levelField = 124 env->GetFieldID(profileLevelClazz, "level", "I"); 125 126 for (size_t i = 0; i < profileLevels.size(); ++i) { 127 const MediaCodecList::ProfileLevel &src = profileLevels.itemAt(i); 128 129 jobject profileLevelObj = env->AllocObject(profileLevelClazz); 130 131 env->SetIntField(profileLevelObj, profileField, src.mProfile); 132 env->SetIntField(profileLevelObj, levelField, src.mLevel); 133 134 env->SetObjectArrayElement(profileLevelArray, i, profileLevelObj); 135 136 env->DeleteLocalRef(profileLevelObj); 137 profileLevelObj = NULL; 138 } 139 140 jfieldID profileLevelsField = env->GetFieldID( 141 capsClazz, 142 "profileLevels", 143 "[Landroid/media/MediaCodecInfo$CodecProfileLevel;"); 144 145 env->SetObjectField(caps, profileLevelsField, profileLevelArray); 146 147 env->DeleteLocalRef(profileLevelArray); 148 profileLevelArray = NULL; 149 150 jintArray colorFormatsArray = env->NewIntArray(colorFormats.size()); 151 152 for (size_t i = 0; i < colorFormats.size(); ++i) { 153 jint val = colorFormats.itemAt(i); 154 env->SetIntArrayRegion(colorFormatsArray, i, 1, &val); 155 } 156 157 jfieldID colorFormatsField = env->GetFieldID( 158 capsClazz, "colorFormats", "[I"); 159 160 env->SetObjectField(caps, colorFormatsField, colorFormatsArray); 161 162 env->DeleteLocalRef(colorFormatsArray); 163 colorFormatsArray = NULL; 164 165 return caps; 166 } 167 168 static void android_media_MediaCodecList_native_init(JNIEnv *env) { 169 } 170 171 static JNINativeMethod gMethods[] = { 172 { "getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount }, 173 { "getCodecName", "(I)Ljava/lang/String;", 174 (void *)android_media_MediaCodecList_getCodecName }, 175 { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder }, 176 { "getSupportedTypes", "(I)[Ljava/lang/String;", 177 (void *)android_media_MediaCodecList_getSupportedTypes }, 178 179 { "getCodecCapabilities", 180 "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;", 181 (void *)android_media_MediaCodecList_getCodecCapabilities }, 182 183 { "native_init", "()V", (void *)android_media_MediaCodecList_native_init }, 184 }; 185 186 int register_android_media_MediaCodecList(JNIEnv *env) { 187 return AndroidRuntime::registerNativeMethods(env, 188 "android/media/MediaCodecList", gMethods, NELEM(gMethods)); 189 } 190 191