Home | History | Annotate | Download | only in jni
      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 jint android_media_MediaCodecList_findCodecByName(
     48         JNIEnv *env, jobject thiz, jstring name) {
     49     if (name == NULL) {
     50         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
     51         return -ENOENT;
     52     }
     53 
     54     const char *nameStr = env->GetStringUTFChars(name, NULL);
     55 
     56     if (nameStr == NULL) {
     57         // Out of memory exception already pending.
     58         return -ENOENT;
     59     }
     60 
     61     jint ret = MediaCodecList::getInstance()->findCodecByName(nameStr);
     62     env->ReleaseStringUTFChars(name, nameStr);
     63     return ret;
     64 }
     65 
     66 static jboolean android_media_MediaCodecList_isEncoder(
     67         JNIEnv *env, jobject thiz, jint index) {
     68     return MediaCodecList::getInstance()->isEncoder(index);
     69 }
     70 
     71 static jarray android_media_MediaCodecList_getSupportedTypes(
     72         JNIEnv *env, jobject thiz, jint index) {
     73     Vector<AString> types;
     74     status_t err =
     75         MediaCodecList::getInstance()->getSupportedTypes(index, &types);
     76 
     77     if (err != OK) {
     78         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
     79         return NULL;
     80     }
     81 
     82     jclass clazz = env->FindClass("java/lang/String");
     83     CHECK(clazz != NULL);
     84 
     85     jobjectArray array = env->NewObjectArray(types.size(), clazz, NULL);
     86 
     87     for (size_t i = 0; i < types.size(); ++i) {
     88         jstring obj = env->NewStringUTF(types.itemAt(i).c_str());
     89         env->SetObjectArrayElement(array, i, obj);
     90         env->DeleteLocalRef(obj);
     91         obj = NULL;
     92     }
     93 
     94     return array;
     95 }
     96 
     97 static jobject android_media_MediaCodecList_getCodecCapabilities(
     98         JNIEnv *env, jobject thiz, jint index, jstring type) {
     99     if (type == NULL) {
    100         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    101         return NULL;
    102     }
    103 
    104     const char *typeStr = env->GetStringUTFChars(type, NULL);
    105 
    106     if (typeStr == NULL) {
    107         // Out of memory exception already pending.
    108         return NULL;
    109     }
    110 
    111     Vector<MediaCodecList::ProfileLevel> profileLevels;
    112     Vector<uint32_t> colorFormats;
    113 
    114     status_t err =
    115         MediaCodecList::getInstance()->getCodecCapabilities(
    116                 index, typeStr, &profileLevels, &colorFormats);
    117 
    118     env->ReleaseStringUTFChars(type, typeStr);
    119     typeStr = NULL;
    120 
    121     if (err != OK) {
    122         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
    123         return NULL;
    124     }
    125 
    126     jclass capsClazz =
    127         env->FindClass("android/media/MediaCodecInfo$CodecCapabilities");
    128     CHECK(capsClazz != NULL);
    129 
    130     jobject caps = env->AllocObject(capsClazz);
    131 
    132     jclass profileLevelClazz =
    133         env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel");
    134     CHECK(profileLevelClazz != NULL);
    135 
    136     jobjectArray profileLevelArray =
    137         env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL);
    138 
    139     jfieldID profileField =
    140         env->GetFieldID(profileLevelClazz, "profile", "I");
    141 
    142     jfieldID levelField =
    143         env->GetFieldID(profileLevelClazz, "level", "I");
    144 
    145     for (size_t i = 0; i < profileLevels.size(); ++i) {
    146         const MediaCodecList::ProfileLevel &src = profileLevels.itemAt(i);
    147 
    148         jobject profileLevelObj = env->AllocObject(profileLevelClazz);
    149 
    150         env->SetIntField(profileLevelObj, profileField, src.mProfile);
    151         env->SetIntField(profileLevelObj, levelField, src.mLevel);
    152 
    153         env->SetObjectArrayElement(profileLevelArray, i, profileLevelObj);
    154 
    155         env->DeleteLocalRef(profileLevelObj);
    156         profileLevelObj = NULL;
    157     }
    158 
    159     jfieldID profileLevelsField = env->GetFieldID(
    160             capsClazz,
    161             "profileLevels",
    162             "[Landroid/media/MediaCodecInfo$CodecProfileLevel;");
    163 
    164     env->SetObjectField(caps, profileLevelsField, profileLevelArray);
    165 
    166     env->DeleteLocalRef(profileLevelArray);
    167     profileLevelArray = NULL;
    168 
    169     jintArray colorFormatsArray = env->NewIntArray(colorFormats.size());
    170 
    171     for (size_t i = 0; i < colorFormats.size(); ++i) {
    172         jint val = colorFormats.itemAt(i);
    173         env->SetIntArrayRegion(colorFormatsArray, i, 1, &val);
    174     }
    175 
    176     jfieldID colorFormatsField = env->GetFieldID(
    177             capsClazz, "colorFormats", "[I");
    178 
    179     env->SetObjectField(caps, colorFormatsField, colorFormatsArray);
    180 
    181     env->DeleteLocalRef(colorFormatsArray);
    182     colorFormatsArray = NULL;
    183 
    184     return caps;
    185 }
    186 
    187 static void android_media_MediaCodecList_native_init(JNIEnv *env) {
    188 }
    189 
    190 static JNINativeMethod gMethods[] = {
    191     { "getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
    192     { "getCodecName", "(I)Ljava/lang/String;",
    193       (void *)android_media_MediaCodecList_getCodecName },
    194     { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder },
    195     { "getSupportedTypes", "(I)[Ljava/lang/String;",
    196       (void *)android_media_MediaCodecList_getSupportedTypes },
    197 
    198     { "getCodecCapabilities",
    199       "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;",
    200       (void *)android_media_MediaCodecList_getCodecCapabilities },
    201 
    202     { "findCodecByName", "(Ljava/lang/String;)I",
    203       (void *)android_media_MediaCodecList_findCodecByName },
    204 
    205     { "native_init", "()V", (void *)android_media_MediaCodecList_native_init },
    206 };
    207 
    208 int register_android_media_MediaCodecList(JNIEnv *env) {
    209     return AndroidRuntime::registerNativeMethods(env,
    210                 "android/media/MediaCodecList", gMethods, NELEM(gMethods));
    211 }
    212 
    213