• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
android_media_MediaCodecList_getCodecCount(JNIEnv * env,jobject thiz)30 static jint android_media_MediaCodecList_getCodecCount(
31         JNIEnv *env, jobject thiz) {
32     return MediaCodecList::getInstance()->countCodecs();
33 }
34 
android_media_MediaCodecList_getCodecName(JNIEnv * env,jobject thiz,jint index)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 
android_media_MediaCodecList_findCodecByName(JNIEnv * env,jobject thiz,jstring name)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 
android_media_MediaCodecList_isEncoder(JNIEnv * env,jobject thiz,jint index)66 static jboolean android_media_MediaCodecList_isEncoder(
67         JNIEnv *env, jobject thiz, jint index) {
68     return MediaCodecList::getInstance()->isEncoder(index);
69 }
70 
android_media_MediaCodecList_getSupportedTypes(JNIEnv * env,jobject thiz,jint index)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 
android_media_MediaCodecList_getCodecCapabilities(JNIEnv * env,jobject thiz,jint index,jstring type)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     uint32_t flags;
114 
115     status_t err =
116         MediaCodecList::getInstance()->getCodecCapabilities(
117                 index, typeStr, &profileLevels, &colorFormats, &flags);
118 
119     env->ReleaseStringUTFChars(type, typeStr);
120     typeStr = NULL;
121 
122     if (err != OK) {
123         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
124         return NULL;
125     }
126 
127     jclass capsClazz =
128         env->FindClass("android/media/MediaCodecInfo$CodecCapabilities");
129     CHECK(capsClazz != NULL);
130 
131     jfieldID flagsField =
132         env->GetFieldID(capsClazz, "flags", "I");
133 
134     jobject caps = env->AllocObject(capsClazz);
135 
136     jclass profileLevelClazz =
137         env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel");
138     CHECK(profileLevelClazz != NULL);
139 
140     jobjectArray profileLevelArray =
141         env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL);
142 
143     jfieldID profileField =
144         env->GetFieldID(profileLevelClazz, "profile", "I");
145 
146     jfieldID levelField =
147         env->GetFieldID(profileLevelClazz, "level", "I");
148 
149     for (size_t i = 0; i < profileLevels.size(); ++i) {
150         const MediaCodecList::ProfileLevel &src = profileLevels.itemAt(i);
151 
152         jobject profileLevelObj = env->AllocObject(profileLevelClazz);
153 
154         env->SetIntField(profileLevelObj, profileField, src.mProfile);
155         env->SetIntField(profileLevelObj, levelField, src.mLevel);
156 
157         env->SetObjectArrayElement(profileLevelArray, i, profileLevelObj);
158 
159         env->DeleteLocalRef(profileLevelObj);
160         profileLevelObj = NULL;
161     }
162 
163     jfieldID profileLevelsField = env->GetFieldID(
164             capsClazz,
165             "profileLevels",
166             "[Landroid/media/MediaCodecInfo$CodecProfileLevel;");
167 
168     env->SetObjectField(caps, profileLevelsField, profileLevelArray);
169 
170     env->SetIntField(caps, flagsField, flags);
171 
172     env->DeleteLocalRef(profileLevelArray);
173     profileLevelArray = NULL;
174 
175     jintArray colorFormatsArray = env->NewIntArray(colorFormats.size());
176 
177     for (size_t i = 0; i < colorFormats.size(); ++i) {
178         jint val = colorFormats.itemAt(i);
179         env->SetIntArrayRegion(colorFormatsArray, i, 1, &val);
180     }
181 
182     jfieldID colorFormatsField = env->GetFieldID(
183             capsClazz, "colorFormats", "[I");
184 
185     env->SetObjectField(caps, colorFormatsField, colorFormatsArray);
186 
187     env->DeleteLocalRef(colorFormatsArray);
188     colorFormatsArray = NULL;
189 
190     return caps;
191 }
192 
android_media_MediaCodecList_native_init(JNIEnv * env)193 static void android_media_MediaCodecList_native_init(JNIEnv *env) {
194 }
195 
196 static JNINativeMethod gMethods[] = {
197     { "getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
198     { "getCodecName", "(I)Ljava/lang/String;",
199       (void *)android_media_MediaCodecList_getCodecName },
200     { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder },
201     { "getSupportedTypes", "(I)[Ljava/lang/String;",
202       (void *)android_media_MediaCodecList_getSupportedTypes },
203 
204     { "getCodecCapabilities",
205       "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;",
206       (void *)android_media_MediaCodecList_getCodecCapabilities },
207 
208     { "findCodecByName", "(Ljava/lang/String;)I",
209       (void *)android_media_MediaCodecList_findCodecByName },
210 
211     { "native_init", "()V", (void *)android_media_MediaCodecList_native_init },
212 };
213 
register_android_media_MediaCodecList(JNIEnv * env)214 int register_android_media_MediaCodecList(JNIEnv *env) {
215     return AndroidRuntime::registerNativeMethods(env,
216                 "android/media/MediaCodecList", gMethods, NELEM(gMethods));
217 }
218 
219