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 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