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

Commit 15045b10 authored by Songyue Han's avatar Songyue Han
Browse files

Java and JNI support for native PerformancePoint.

Bug: b/306023029
Test: MediaCodecCapabilitiesTest
Change-Id: Ie0864e21923fee4a4d72cfb8251ca78c37bca363
parent b279f15f
Loading
Loading
Loading
Loading
+84 −14
Original line number Diff line number Diff line
@@ -2387,6 +2387,24 @@ public final class MediaCodecInfo {
                return saturateLongToInt(mWidth * (long)mHeight);
            }

            /**
             * Width in macroblocks.
             *
             * @hide
             */
            /** package private */ int getWidth() {
                return mWidth;
            }

            /**
             * Height in macroblocks.
             *
             * @hide
             */
            /** package private */ int getHeight() {
                return mHeight;
            }

            /**
             * Maximum frame rate in frames per second.
             *
@@ -2407,6 +2425,24 @@ public final class MediaCodecInfo {
                return mMaxMacroBlockRate;
            }

            /**
             * Codec block width in macroblocks.
             *
             * @hide
             */
            /** package private */ int getBlockWidth() {
                return mBlockSize.getWidth();
            }

            /**
             * Codec block height in macroblocks.
             *
             * @hide
             */
            /** package private */ int getBlockHeight() {
                return mBlockSize.getHeight();
            }

            /** Convert to a debug string */
            public String toString() {
                int blockWidth = 16 * mBlockSize.getWidth();
@@ -2494,6 +2530,20 @@ public final class MediaCodecInfo {
                this(width, height, frameRate, frameRate /* maxFrameRate */, new Size(16, 16));
            }

            /* package private */ PerformancePoint(int width, int height, int maxFrameRate,
                    long maxMacroBlockRate, int blockSizeWidth, int blockSizeHeight) {
                mWidth = width;
                mHeight = height;
                mMaxFrameRate = maxFrameRate;
                mMaxMacroBlockRate = maxMacroBlockRate;
                mBlockSize = new Size(blockSizeWidth, blockSizeHeight);
            }

            private PerformancePoint(PerformancePoint pp) {
                this(pp.mWidth, pp.mHeight, pp.mMaxFrameRate, pp.mMaxMacroBlockRate,
                        pp.mBlockSize.getWidth(), pp.mBlockSize.getHeight());
            }

            /** Saturates a long value to int */
            private int saturateLongToInt(long value) {
                if (value < Integer.MIN_VALUE) {
@@ -2547,6 +2597,9 @@ public final class MediaCodecInfo {
             * @return {@code true} if the performance point covers the other.
             */
            public boolean covers(@NonNull PerformancePoint other) {
                if (GetFlag(() -> android.media.codec.Flags.nativeCapabilites())) {
                    return native_covers(other);
                } else {
                    // convert performance points to common block size
                    Size commonSize = getCommonBlockSize(other);
                    PerformancePoint aligned = new PerformancePoint(this, commonSize);
@@ -2556,6 +2609,7 @@ public final class MediaCodecInfo {
                            && aligned.mMaxFrameRate >= otherAligned.mMaxFrameRate
                            && aligned.mMaxMacroBlockRate >= otherAligned.mMaxMacroBlockRate);
                }
            }

            private @NonNull Size getCommonBlockSize(@NonNull PerformancePoint other) {
                return new Size(
@@ -2568,6 +2622,9 @@ public final class MediaCodecInfo {
                if (o instanceof PerformancePoint) {
                    // convert performance points to common block size
                    PerformancePoint other = (PerformancePoint)o;
                    if (GetFlag(() -> android.media.codec.Flags.nativeCapabilites())) {
                        return native_equals(other);
                    } else {
                        Size commonSize = getCommonBlockSize(other);
                        PerformancePoint aligned = new PerformancePoint(this, commonSize);
                        PerformancePoint otherAligned = new PerformancePoint(other, commonSize);
@@ -2576,9 +2633,17 @@ public final class MediaCodecInfo {
                                && aligned.mMaxFrameRate == otherAligned.mMaxFrameRate
                                && aligned.mMaxMacroBlockRate == otherAligned.mMaxMacroBlockRate);
                    }
                }
                return false;
            }

            private native boolean native_covers(PerformancePoint other);
            private native boolean native_equals(PerformancePoint other);

            static {
                System.loadLibrary("media_jni");
            }

            /** 480p 24fps */
            @NonNull
            public static final PerformancePoint SD_24 = new PerformancePoint(720, 480, 24);
@@ -4995,5 +5060,10 @@ public final class MediaCodecInfo {
        private static Range<Integer> constructIntegerRange(int lower, int upper) {
            return Range.create(Integer.valueOf(lower), Integer.valueOf(upper));
        }

        private static List<VideoCapabilities.PerformancePoint>
                constructPerformancePointList(VideoCapabilities.PerformancePoint[] array) {
            return Arrays.asList(array);
        }
    }
}
+74 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include "jni.h"

#include <media/AudioCapabilities.h>
#include <media/VideoCapabilities.h>
#include <media/stagefright/foundation/ADebug.h>
#include <nativehelper/JNIHelp.h>

@@ -39,6 +40,47 @@ static AudioCapabilities* getAudioCapabilities(JNIEnv *env, jobject thiz) {
    return p;
}

// Converters between Java objects and native instances

static VideoCapabilities::PerformancePoint convertToNativePerformancePoint(
        JNIEnv *env, jobject pp) {
    if (pp == NULL) {
        jniThrowException(env, "java/lang/NullPointerException", NULL);
    }

    jclass clazz = env->FindClass(
            "android/media/MediaCodecInfo$VideoCapabilities$PerformancePoint");
    CHECK(clazz != NULL);
    CHECK(env->IsInstanceOf(pp, clazz));

    jmethodID getWidthID = env->GetMethodID(clazz, "getWidth", "()I");
    CHECK(getWidthID != NULL);
    jint width = env->CallIntMethod(pp, getWidthID);

    jmethodID getHeightID = env->GetMethodID(clazz, "getHeight", "()I");
    CHECK(getHeightID != NULL);
    jint height = env->CallIntMethod(pp, getHeightID);

    jmethodID getMaxFrameRateID = env->GetMethodID(clazz, "getMaxFrameRate", "()I");
    CHECK(getMaxFrameRateID != NULL);
    jint maxFrameRate = env->CallIntMethod(pp, getMaxFrameRateID);

    jmethodID getMaxMacroBlockRateID = env->GetMethodID(clazz, "getMaxMacroBlockRate", "()J");
    CHECK(getMaxMacroBlockRateID != NULL);
    jlong maxMacroBlockRate = env->CallLongMethod(pp, getMaxMacroBlockRateID);

    jmethodID getBlockWidthID = env->GetMethodID(clazz, "getBlockWidth", "()I");
    CHECK(getBlockWidthID != NULL);
    jint blockWidth = env->CallIntMethod(pp, getBlockWidthID);

    jmethodID getBlockHeightID = env->GetMethodID(clazz, "getBlockHeight", "()I");
    CHECK(getBlockHeightID != NULL);
    jint blockHeight = env->CallIntMethod(pp, getBlockHeightID);

    return VideoCapabilities::PerformancePoint(VideoSize(blockWidth, blockHeight),
            width, height, maxFrameRate, maxMacroBlockRate);
}

}  // namespace android

// ----------------------------------------------------------------------------
@@ -96,6 +138,26 @@ static jboolean android_media_AudioCapabilities_isSampleRateSupported(JNIEnv *en
    return res;
}

// PerformancePoint

static jboolean android_media_VideoCapabilities_PerformancePoint_covers(JNIEnv *env, jobject thiz,
        jobject other) {
    VideoCapabilities::PerformancePoint pp0 = convertToNativePerformancePoint(env, thiz);
    VideoCapabilities::PerformancePoint pp1 = convertToNativePerformancePoint(env, other);

    bool res = pp0.covers(pp1);
    return res;
}

static jboolean android_media_VideoCapabilities_PerformancePoint_equals(JNIEnv *env, jobject thiz,
        jobject other) {
    VideoCapabilities::PerformancePoint pp0 = convertToNativePerformancePoint(env, thiz);
    VideoCapabilities::PerformancePoint pp1 = convertToNativePerformancePoint(env, other);

    bool res = pp0.equals(pp1);
    return res;
}

// ----------------------------------------------------------------------------

static const JNINativeMethod gAudioCapsMethods[] = {
@@ -105,6 +167,11 @@ static const JNINativeMethod gAudioCapsMethods[] = {
    {"native_isSampleRateSupported", "(I)Z", (void *)android_media_AudioCapabilities_isSampleRateSupported}
};

static const JNINativeMethod gPerformancePointMethods[] = {
    {"native_covers", "(Landroid/media/MediaCodecInfo$VideoCapabilities$PerformancePoint;)Z", (void *)android_media_VideoCapabilities_PerformancePoint_covers},
    {"native_equals", "(Landroid/media/MediaCodecInfo$VideoCapabilities$PerformancePoint;)Z", (void *)android_media_VideoCapabilities_PerformancePoint_equals},
};

int register_android_media_CodecCapabilities(JNIEnv *env) {
    int result = AndroidRuntime::registerNativeMethods(env,
            "android/media/MediaCodecInfo$AudioCapabilities$AudioCapsNativeImpl",
@@ -113,5 +180,12 @@ int register_android_media_CodecCapabilities(JNIEnv *env) {
        return result;
    }

    result = AndroidRuntime::registerNativeMethods(env,
            "android/media/MediaCodecInfo$VideoCapabilities$PerformancePoint",
            gPerformancePointMethods, NELEM(gPerformancePointMethods));
    if (result != JNI_OK) {
        return result;
    }

    return result;
}
 No newline at end of file