Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f834155e authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "fix slow get caps"

parents b247dbdf 90d7304a
Loading
Loading
Loading
Loading
+20 −2
Original line number Diff line number Diff line
@@ -1602,7 +1602,9 @@ final public class MediaCodec {
    private EventHandler mCallbackHandler;
    private Callback mCallback;
    private OnFrameRenderedListener mOnFrameRenderedListener;
    private Object mListenerLock = new Object();
    private final Object mListenerLock = new Object();
    private MediaCodecInfo mCodecInfo;
    private final Object mCodecInfoLock = new Object();

    private static final int EVENT_CALLBACK = 1;
    private static final int EVENT_SET_CALLBACK = 2;
@@ -3469,8 +3471,24 @@ final public class MediaCodec {
     */
    @NonNull
    public MediaCodecInfo getCodecInfo() {
        return MediaCodecList.getInfoFor(getName());
        // Get the codec name first. If the codec is already released,
        // IllegalStateException will be thrown here.
        String name = getName();
        synchronized (mCodecInfoLock) {
            if (mCodecInfo == null) {
                // Get the codec info for this codec itself first. Only initialize
                // the full codec list if this somehow fails because it can be slow.
                mCodecInfo = getOwnCodecInfo();
                if (mCodecInfo == null) {
                    mCodecInfo = MediaCodecList.getInfoFor(name);
                }
            }
            return mCodecInfo;
        }
    }

    @NonNull
    private native final MediaCodecInfo getOwnCodecInfo();

    @NonNull
    private native final ByteBuffer[] getBuffers(boolean input);
+25 −18
Original line number Diff line number Diff line
@@ -829,14 +829,24 @@ public final class MediaCodecInfo {

        /** @hide */
        public CodecCapabilities dup() {
            return new CodecCapabilities(
                // clone writable arrays
                Arrays.copyOf(profileLevels, profileLevels.length),
                Arrays.copyOf(colorFormats, colorFormats.length),
                isEncoder(),
                mFlagsVerified,
                mDefaultFormat,
                mCapabilitiesInfo);
            CodecCapabilities caps = new CodecCapabilities();

            // profileLevels and colorFormats may be modified by client.
            caps.profileLevels = Arrays.copyOf(profileLevels, profileLevels.length);
            caps.colorFormats = Arrays.copyOf(colorFormats, colorFormats.length);

            caps.mMime = mMime;
            caps.mMaxSupportedInstances = mMaxSupportedInstances;
            caps.mFlagsRequired = mFlagsRequired;
            caps.mFlagsSupported = mFlagsSupported;
            caps.mFlagsVerified = mFlagsVerified;
            caps.mAudioCaps = mAudioCaps;
            caps.mVideoCaps = mVideoCaps;
            caps.mEncoderCaps = mEncoderCaps;
            caps.mDefaultFormat = mDefaultFormat;
            caps.mCapabilitiesInfo = mCapabilitiesInfo;

            return caps;
        }

        /**
@@ -898,13 +908,13 @@ public final class MediaCodecInfo {

            if (mMime.toLowerCase().startsWith("audio/")) {
                mAudioCaps = AudioCapabilities.create(info, this);
                mAudioCaps.setDefaultFormat(mDefaultFormat);
                mAudioCaps.getDefaultFormat(mDefaultFormat);
            } else if (mMime.toLowerCase().startsWith("video/")) {
                mVideoCaps = VideoCapabilities.create(info, this);
            }
            if (encoder) {
                mEncoderCaps = EncoderCapabilities.create(info, this);
                mEncoderCaps.setDefaultFormat(mDefaultFormat);
                mEncoderCaps.getDefaultFormat(mDefaultFormat);
            }

            final Map<String, Object> global = MediaCodecList.getGlobalSettings();
@@ -990,8 +1000,7 @@ public final class MediaCodecInfo {
            return caps;
        }

        /** @hide */
        public void init(MediaFormat info, CodecCapabilities parent) {
        private void init(MediaFormat info, CodecCapabilities parent) {
            mParent = parent;
            initWithPlatformLimits();
            applyLevelLimits();
@@ -1171,7 +1180,7 @@ public final class MediaCodecInfo {
        }

        /** @hide */
        public void setDefaultFormat(MediaFormat format) {
        public void getDefaultFormat(MediaFormat format) {
            // report settings that have only a single choice
            if (mBitrateRange.getLower().equals(mBitrateRange.getUpper())) {
                format.setInteger(MediaFormat.KEY_BIT_RATE, mBitrateRange.getLower());
@@ -1585,8 +1594,7 @@ public final class MediaCodecInfo {
            return caps;
        }

        /** @hide */
        public void init(MediaFormat info, CodecCapabilities parent) {
        private void init(MediaFormat info, CodecCapabilities parent) {
            mParent = parent;
            initWithPlatformLimits();
            applyLevelLimits();
@@ -2707,8 +2715,7 @@ public final class MediaCodecInfo {
            return caps;
        }

        /** @hide */
        public void init(MediaFormat info, CodecCapabilities parent) {
        private void init(MediaFormat info, CodecCapabilities parent) {
            // no support for complexity or quality yet
            mParent = parent;
            mComplexityRange = Range.create(0, 0);
@@ -2789,7 +2796,7 @@ public final class MediaCodecInfo {
        }

        /** @hide */
        public void setDefaultFormat(MediaFormat format) {
        public void getDefaultFormat(MediaFormat format) {
            // don't list trivial quality/complexity as default for now
            if (!mQualityRange.getUpper().equals(mQualityRange.getLower())
                    && mDefaultQuality != null) {
+153 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
#include "android_util_Binder.h"
#include "jni.h"
#include <nativehelper/JNIHelp.h>
#include <nativehelper/ScopedLocalRef.h>

#include <android/hardware/cas/native/1.0/IDescrambler.h>

@@ -98,6 +99,13 @@ static struct {
    jint AesCbc;
} gCryptoModes;

static struct {
    jclass capsClazz;
    jmethodID capsCtorId;
    jclass profileLevelClazz;
    jfieldID profileField;
    jfieldID levelField;
} gCodecInfo;

struct fields_t {
    jfieldID context;
@@ -625,6 +633,103 @@ status_t JMediaCodec::getName(JNIEnv *env, jstring *nameStr) const {
    return OK;
}

static jobject getCodecCapabilitiesObject(
        JNIEnv *env, const char *mime, bool isEncoder,
        const sp<MediaCodecInfo::Capabilities> &capabilities) {
    Vector<MediaCodecInfo::ProfileLevel> profileLevels;
    Vector<uint32_t> colorFormats;

    sp<AMessage> defaultFormat = new AMessage();
    defaultFormat->setString("mime", mime);

    capabilities->getSupportedColorFormats(&colorFormats);
    capabilities->getSupportedProfileLevels(&profileLevels);
    uint32_t flags = capabilities->getFlags();
    sp<AMessage> details = capabilities->getDetails();

    jobject defaultFormatObj = NULL;
    if (ConvertMessageToMap(env, defaultFormat, &defaultFormatObj)) {
        return NULL;
    }
    ScopedLocalRef<jobject> defaultFormatRef(env, defaultFormatObj);

    jobject detailsObj = NULL;
    if (ConvertMessageToMap(env, details, &detailsObj)) {
        return NULL;
    }
    ScopedLocalRef<jobject> detailsRef(env, detailsObj);

    ScopedLocalRef<jobjectArray> profileLevelArray(env, env->NewObjectArray(
            profileLevels.size(), gCodecInfo.profileLevelClazz, NULL));

    for (size_t i = 0; i < profileLevels.size(); ++i) {
        const MediaCodecInfo::ProfileLevel &src = profileLevels.itemAt(i);

        ScopedLocalRef<jobject> srcRef(env, env->AllocObject(
                gCodecInfo.profileLevelClazz));

        env->SetIntField(srcRef.get(), gCodecInfo.profileField, src.mProfile);
        env->SetIntField(srcRef.get(), gCodecInfo.levelField, src.mLevel);

        env->SetObjectArrayElement(profileLevelArray.get(), i, srcRef.get());
    }

    ScopedLocalRef<jintArray> colorFormatsArray(
            env, env->NewIntArray(colorFormats.size()));
    for (size_t i = 0; i < colorFormats.size(); ++i) {
        jint val = colorFormats.itemAt(i);
        env->SetIntArrayRegion(colorFormatsArray.get(), i, 1, &val);
    }

    return env->NewObject(
            gCodecInfo.capsClazz, gCodecInfo.capsCtorId,
            profileLevelArray.get(), colorFormatsArray.get(), isEncoder, flags,
            defaultFormatRef.get(), detailsRef.get());
}

status_t JMediaCodec::getCodecInfo(JNIEnv *env, jobject *codecInfoObject) const {
    sp<MediaCodecInfo> codecInfo;

    status_t err = mCodec->getCodecInfo(&codecInfo);

    if (err != OK) {
        return err;
    }

    ScopedLocalRef<jstring> nameObject(env,
            env->NewStringUTF(codecInfo->getCodecName()));

    bool isEncoder = codecInfo->isEncoder();

    Vector<AString> mimes;
    codecInfo->getSupportedMimes(&mimes);

    ScopedLocalRef<jobjectArray> capsArrayObj(env,
        env->NewObjectArray(mimes.size(), gCodecInfo.capsClazz, NULL));

    for (size_t i = 0; i < mimes.size(); i++) {
        const sp<MediaCodecInfo::Capabilities> caps =
                codecInfo->getCapabilitiesFor(mimes[i].c_str());

        ScopedLocalRef<jobject> capsObj(env, getCodecCapabilitiesObject(
                env, mimes[i].c_str(), isEncoder, caps));

        env->SetObjectArrayElement(capsArrayObj.get(), i, capsObj.get());
    }

    ScopedLocalRef<jclass> codecInfoClazz(env,
            env->FindClass("android/media/MediaCodecInfo"));
    CHECK(codecInfoClazz.get() != NULL);

    jmethodID codecInfoCtorID = env->GetMethodID(codecInfoClazz.get(), "<init>",
            "(Ljava/lang/String;Z[Landroid/media/MediaCodecInfo$CodecCapabilities;)V");

    *codecInfoObject = env->NewObject(codecInfoClazz.get(), codecInfoCtorID,
            nameObject.get(), isEncoder, capsArrayObj.get());

    return OK;
}

status_t JMediaCodec::getMetrics(JNIEnv *, MediaAnalyticsItem * &reply) const {

    status_t status = mCodec->getMetrics(reply);
@@ -1665,6 +1770,29 @@ static jobject android_media_MediaCodec_getName(
    return NULL;
}

static jobject android_media_MediaCodec_getOwnCodecInfo(
        JNIEnv *env, jobject thiz) {
    ALOGV("android_media_MediaCodec_getOwnCodecInfo");

    sp<JMediaCodec> codec = getMediaCodec(env, thiz);

    if (codec == NULL) {
        throwExceptionAsNecessary(env, INVALID_OPERATION);
        return NULL;
    }

    jobject codecInfoObj;
    status_t err = codec->getCodecInfo(env, &codecInfoObj);

    if (err == OK) {
        return codecInfoObj;
    }

    throwExceptionAsNecessary(env, err);

    return NULL;
}

static jobject
android_media_MediaCodec_native_getMetrics(JNIEnv *env, jobject thiz)
{
@@ -1877,6 +2005,28 @@ static void android_media_MediaCodec_native_init(JNIEnv *env) {
    field = env->GetFieldID(clazz.get(), "mPersistentObject", "J");
    CHECK(field != NULL);
    gPersistentSurfaceClassInfo.mPersistentObject = field;

    clazz.reset(env->FindClass("android/media/MediaCodecInfo$CodecCapabilities"));
    CHECK(clazz.get() != NULL);
    gCodecInfo.capsClazz = (jclass)env->NewGlobalRef(clazz.get());

    method = env->GetMethodID(clazz.get(), "<init>",
            "([Landroid/media/MediaCodecInfo$CodecProfileLevel;[IZI"
            "Ljava/util/Map;Ljava/util/Map;)V");
    CHECK(method != NULL);
    gCodecInfo.capsCtorId = method;

    clazz.reset(env->FindClass("android/media/MediaCodecInfo$CodecProfileLevel"));
    CHECK(clazz.get() != NULL);
    gCodecInfo.profileLevelClazz = (jclass)env->NewGlobalRef(clazz.get());

    field = env->GetFieldID(clazz.get(), "profile", "I");
    CHECK(field != NULL);
    gCodecInfo.profileField = field;

    field = env->GetFieldID(clazz.get(), "level", "I");
    CHECK(field != NULL);
    gCodecInfo.levelField = field;
}

static void android_media_MediaCodec_native_setup(
@@ -2002,6 +2152,9 @@ static const JNINativeMethod gMethods[] = {
    { "getName", "()Ljava/lang/String;",
      (void *)android_media_MediaCodec_getName },

    { "getOwnCodecInfo", "()Landroid/media/MediaCodecInfo;",
        (void *)android_media_MediaCodec_getOwnCodecInfo },

    { "native_getMetrics", "()Landroid/os/PersistableBundle;",
      (void *)android_media_MediaCodec_native_getMetrics},

+2 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ struct JMediaCodec : public AHandler {

    status_t getName(JNIEnv *env, jstring *name) const;

    status_t getCodecInfo(JNIEnv *env, jobject *codecInfo) const;

    status_t getMetrics(JNIEnv *env, MediaAnalyticsItem * &reply) const;

    status_t setParameters(const sp<AMessage> &params);