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>
22b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar#include <media/stagefright/foundation/AMessage.h>
235a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include <media/stagefright/MediaCodecList.h>
24cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar#include <media/IMediaCodecList.h>
25cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar#include <media/MediaCodecInfo.h>
265a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
275a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include "android_runtime/AndroidRuntime.h"
285a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include "jni.h"
295a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber#include "JNIHelp.h"
30b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar#include "android_media_Utils.h"
315a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
325a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberusing namespace android;
335a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
34cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnarstatic sp<IMediaCodecList> getCodecList(JNIEnv *env) {
35cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = MediaCodecList::getInstance();
36cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
37cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // This should never happen unless something is really wrong
38cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        jniThrowException(
39cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar                    env, "java/lang/RuntimeException", "cannot get MediaCodecList");
40cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
41cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    return mcl;
42cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar}
43cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
4460d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huberstatic jint android_media_MediaCodecList_getCodecCount(
455a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        JNIEnv *env, jobject thiz) {
46cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = getCodecList(env);
47cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
48cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // Runtime exception already pending.
49cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return 0;
50cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
51cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    return mcl->countCodecs();
525a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
535a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
545a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jstring android_media_MediaCodecList_getCodecName(
555a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
56cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = getCodecList(env);
57cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
58cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // Runtime exception already pending.
59cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return NULL;
60cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
615a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
62cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
63cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (info == NULL) {
645a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
655a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        return NULL;
665a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
675a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
68cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    const char *name = info->getCodecName();
695a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    return env->NewStringUTF(name);
705a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
715a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
7293077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjostatic jint android_media_MediaCodecList_findCodecByName(
7393077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo        JNIEnv *env, jobject thiz, jstring name) {
7493077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    if (name == NULL) {
7593077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
7693077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo        return -ENOENT;
7793077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    }
7893077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo
7993077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    const char *nameStr = env->GetStringUTFChars(name, NULL);
8093077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    if (nameStr == NULL) {
8193077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo        // Out of memory exception already pending.
8293077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo        return -ENOENT;
8393077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    }
8493077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo
85cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = getCodecList(env);
86cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
87cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // Runtime exception already pending.
88018b70f5de79e614fff3297c617e2416dbf34d77Lajos Molnar        env->ReleaseStringUTFChars(name, nameStr);
89cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return -ENOENT;
90cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
91cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
92cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    jint ret = mcl->findCodecByName(nameStr);
9393077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    env->ReleaseStringUTFChars(name, nameStr);
9493077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    return ret;
9593077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo}
9693077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo
975a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jboolean android_media_MediaCodecList_isEncoder(
985a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
99cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = getCodecList(env);
100cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
101cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // Runtime exception already pending.
102cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return false;
103cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
104cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
105cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
106cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (info == NULL) {
107cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
108cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return false;
109cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
110cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
111cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    return info->isEncoder();
1125a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
1135a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
1145a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jarray android_media_MediaCodecList_getSupportedTypes(
1155a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        JNIEnv *env, jobject thiz, jint index) {
116cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = getCodecList(env);
117cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
118cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // Runtime exception already pending.
119cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return NULL;
120cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
1215a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
122cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
123cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (info == NULL) {
1245a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1255a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        return NULL;
1265a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
1275a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
128cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    Vector<AString> types;
129cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    info->getSupportedMimes(&types);
130cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
1315a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jclass clazz = env->FindClass("java/lang/String");
1325a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    CHECK(clazz != NULL);
1335a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
1345a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jobjectArray array = env->NewObjectArray(types.size(), clazz, NULL);
1355a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
1365a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    for (size_t i = 0; i < types.size(); ++i) {
1375a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        jstring obj = env->NewStringUTF(types.itemAt(i).c_str());
1385a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->SetObjectArrayElement(array, i, obj);
1395a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->DeleteLocalRef(obj);
1405a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        obj = NULL;
1415a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
1425a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
1435a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    return array;
1445a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
1455a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
1465a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic jobject android_media_MediaCodecList_getCodecCapabilities(
1475a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        JNIEnv *env, jobject thiz, jint index, jstring type) {
1485a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    if (type == NULL) {
1495a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1505a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        return NULL;
1515a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
1525a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
153cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<IMediaCodecList> mcl = getCodecList(env);
154cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (mcl == NULL) {
155cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        // Runtime exception already pending.
156cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return NULL;
157cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
158cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
159cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    const sp<MediaCodecInfo> &info = mcl->getCodecInfo(index);
160cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (info == NULL) {
161cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
162cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        return NULL;
163cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    }
164cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
1655a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    const char *typeStr = env->GetStringUTFChars(type, NULL);
1665a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    if (typeStr == NULL) {
1675a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        // Out of memory exception already pending.
1685a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        return NULL;
1695a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
1705a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
171cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
1725a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    Vector<uint32_t> colorFormats;
173b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
174b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    sp<AMessage> defaultFormat = new AMessage();
175b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    defaultFormat->setString("mime", typeStr);
176b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
177b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    // TODO query default-format also from codec/codec list
178cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    const sp<MediaCodecInfo::Capabilities> &capabilities =
179cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        info->getCapabilitiesFor(typeStr);
180018b70f5de79e614fff3297c617e2416dbf34d77Lajos Molnar    env->ReleaseStringUTFChars(type, typeStr);
181018b70f5de79e614fff3297c617e2416dbf34d77Lajos Molnar    typeStr = NULL;
182cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (capabilities == NULL) {
1835a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
1845a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        return NULL;
1855a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
186cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar
187cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    capabilities->getSupportedColorFormats(&colorFormats);
188cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    capabilities->getSupportedProfileLevels(&profileLevels);
189cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    uint32_t flags = capabilities->getFlags();
190cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    sp<AMessage> details = capabilities->getDetails();
191cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    bool isEncoder = info->isEncoder();
1925a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
193b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    jobject defaultFormatObj = NULL;
194b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) {
195b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return NULL;
196b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
197b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
198b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    jobject infoObj = NULL;
199cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar    if (ConvertMessageToMap(env, details, &infoObj)) {
200b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        env->DeleteLocalRef(defaultFormatObj);
201b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        return NULL;
202b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
203b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2045a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jclass capsClazz =
20560d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        env->FindClass("android/media/MediaCodecInfo$CodecCapabilities");
2065a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    CHECK(capsClazz != NULL);
2075a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2085a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jclass profileLevelClazz =
20960d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber        env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel");
2105a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    CHECK(profileLevelClazz != NULL);
2115a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2125a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jobjectArray profileLevelArray =
2135a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->NewObjectArray(profileLevels.size(), profileLevelClazz, NULL);
2145a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2155a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jfieldID profileField =
21607ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        env->GetFieldID(profileLevelClazz, "profile", "I");
2175a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2185a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    jfieldID levelField =
21907ea426e3ae8915ca6bf67135f523f42cd920af0Andreas Huber        env->GetFieldID(profileLevelClazz, "level", "I");
2205a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2215a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    for (size_t i = 0; i < profileLevels.size(); ++i) {
222cd5e3f95bfcc6039aa048b7f3141f265de02d114Lajos Molnar        const MediaCodecInfo::ProfileLevel &src = profileLevels.itemAt(i);
2235a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2245a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        jobject profileLevelObj = env->AllocObject(profileLevelClazz);
2255a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2265a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->SetIntField(profileLevelObj, profileField, src.mProfile);
2275a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->SetIntField(profileLevelObj, levelField, src.mLevel);
2285a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2295a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->SetObjectArrayElement(profileLevelArray, i, profileLevelObj);
2305a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2315a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        env->DeleteLocalRef(profileLevelObj);
2325a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber        profileLevelObj = NULL;
2335a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    }
2345a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
235b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    jintArray colorFormatsArray = env->NewIntArray(colorFormats.size());
236b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
237b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    for (size_t i = 0; i < colorFormats.size(); ++i) {
238b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        jint val = colorFormats.itemAt(i);
239b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar        env->SetIntArrayRegion(colorFormatsArray, i, 1, &val);
240b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    }
241b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
242b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    jmethodID capsConstructID = env->GetMethodID(capsClazz, "<init>",
243b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
244b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            "Ljava/util/Map;Ljava/util/Map;)V");
245b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
246b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    jobject caps = env->NewObject(capsClazz, capsConstructID,
247b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            profileLevelArray, colorFormatsArray, isEncoder, flags,
248b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar            defaultFormatObj, infoObj);
249b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
250b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    env->DeleteLocalRef(profileLevelArray);
251b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    profileLevelArray = NULL;
252b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2535a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    env->DeleteLocalRef(colorFormatsArray);
2545a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    colorFormatsArray = NULL;
2555a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
256b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    env->DeleteLocalRef(defaultFormatObj);
257b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    defaultFormatObj = NULL;
258b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
259b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    env->DeleteLocalRef(infoObj);
260b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    infoObj = NULL;
261b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar
2625a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    return caps;
2635a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
2645a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2655a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic void android_media_MediaCodecList_native_init(JNIEnv *env) {
2665a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
2675a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2685a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberstatic JNINativeMethod gMethods[] = {
269b58dc3132272a5ec1ad4792c3c9d48b4198bd57fLajos Molnar    { "native_getCodecCount", "()I", (void *)android_media_MediaCodecList_getCodecCount },
2705a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    { "getCodecName", "(I)Ljava/lang/String;",
2715a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber      (void *)android_media_MediaCodecList_getCodecName },
2725a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    { "isEncoder", "(I)Z", (void *)android_media_MediaCodecList_isEncoder },
2735a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    { "getSupportedTypes", "(I)[Ljava/lang/String;",
2745a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber      (void *)android_media_MediaCodecList_getSupportedTypes },
2755a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2765a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    { "getCodecCapabilities",
27760d610bf103379277a4b29a7ead4f013f6128e4eAndreas Huber      "(ILjava/lang/String;)Landroid/media/MediaCodecInfo$CodecCapabilities;",
2785a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber      (void *)android_media_MediaCodecList_getCodecCapabilities },
2795a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
28093077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo    { "findCodecByName", "(Ljava/lang/String;)I",
28193077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo      (void *)android_media_MediaCodecList_findCodecByName },
28293077a2902a74256b7eb4795e1ef92bbc5c50f10Martin Storsjo
2835a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    { "native_init", "()V", (void *)android_media_MediaCodecList_native_init },
2845a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber};
2855a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
2865a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huberint register_android_media_MediaCodecList(JNIEnv *env) {
2875a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber    return AndroidRuntime::registerNativeMethods(env,
2885a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber                "android/media/MediaCodecList", gMethods, NELEM(gMethods));
2895a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber}
2905a04bf395514a9342dd26af519b88f4b3e309eb9Andreas Huber
291