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

Commit 6cba61ee authored by James Dong's avatar James Dong Committed by Android (Google) Code Review
Browse files

Merge "Avoid using private Bitmap constructor to generate bitmaps"

parents 33808c6d 0e4b535b
Loading
Loading
Loading
Loading
+97 −7
Original line number Diff line number Diff line
@@ -22,6 +22,20 @@
#include <utils/Log.h>
#include <utils/threads.h>
#include <core/SkBitmap.h>

// Please do not enable "USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR"
// This mode will be removed and it is kept here for
// convenient comparsion just in case. Will be removed soon.
// Tests show that this mode is also ~30ms slower,
// when rotation is involved.
#define USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR 0

#if (!USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR)
#include <core/SkCanvas.h>
#include <core/SkDevice.h>
#include <core/SkScalar.h>
#endif

#include <media/mediametadataretriever.h>
#include <private/media/VideoFrame.h>

@@ -35,8 +49,15 @@ using namespace android;
struct fields_t {
    jfieldID context;
    jclass bitmapClazz;
#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR
    jmethodID bitmapConstructor;
    jmethodID createBitmapRotationMethod;
#else
    jfieldID nativeBitmap;
    jmethodID createBitmapMethod;
    jclass configClazz;
    jmethodID createConfigMethod;
#endif
};

static fields_t fields;
@@ -162,6 +183,12 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env,
        return NULL;
    }

    LOGV("Dimension = %dx%d and bytes = %d",
            videoFrame->mDisplayWidth,
            videoFrame->mDisplayHeight,
            videoFrame->mSize);

#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR
    jobject matrix = NULL;
    if (videoFrame->mRotationAngle != 0) {
        LOGD("Create a rotation matrix: %d degrees", videoFrame->mRotationAngle);
@@ -217,9 +244,9 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env,
    jobject jSrcBitmap = env->NewObject(fields.bitmapClazz,
            fields.bitmapConstructor, (int) bitmap, NULL, true, NULL, -1);

    LOGV("Return a new bitmap constructed with the rotation matrix");
    return env->CallStaticObjectMethod(
                fields.bitmapClazz, fields.createBitmapMethod,
    jobject jBitmap = env->CallStaticObjectMethod(
                fields.bitmapClazz,
                fields.createBitmapRotationMethod,
                jSrcBitmap,                     // source Bitmap
                0,                              // x
                0,                              // y
@@ -227,6 +254,39 @@ static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env,
                videoFrame->mDisplayHeight,     // height
                matrix,                         // transform matrix
                false);                         // filter

#else

    jobject config = env->CallStaticObjectMethod(
                        fields.configClazz,
                        fields.createConfigMethod,
                        SkBitmap::kRGB_565_Config);

    jobject jBitmap = env->CallStaticObjectMethod(
                            fields.bitmapClazz,
                            fields.createBitmapMethod,
                            videoFrame->mDisplayWidth,
                            videoFrame->mDisplayHeight,
                            config);
    SkBitmap *bitmap =
            (SkBitmap *) env->GetIntField(jBitmap, fields.nativeBitmap);

    bitmap->lockPixels();

    memcpy((uint8_t*)bitmap->getPixels(),
            (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize);

    bitmap->unlockPixels();

    if (videoFrame->mRotationAngle != 0) {
        SkDevice device(*bitmap);
        SkCanvas canvas(&device);
        canvas.rotate((SkScalar) (videoFrame->mRotationAngle * 1.0));
        canvas.drawBitmap(*bitmap, 0, 0);
    }
#endif
    LOGV("Return a new bitmap constructed with the rotation matrix");
    return jBitmap;
}

static jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *env, jobject thiz)
@@ -293,7 +353,6 @@ static void android_media_MediaMetadataRetriever_release(JNIEnv *env, jobject th
static void android_media_MediaMetadataRetriever_native_finalize(JNIEnv *env, jobject thiz)
{
    LOGV("native_finalize");
    
    // No lock is needed, since android_media_MediaMetadataRetriever_release() is protected
    android_media_MediaMetadataRetriever_release(env, thiz);
}
@@ -320,21 +379,52 @@ static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env)
        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap");
        return;
    }

#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR
    fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(I[BZ[BI)V");
    if (fields.bitmapConstructor == NULL) {
        jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
        return;
    }
    fields.createBitmapMethod =
    fields.createBitmapRotationMethod =
            env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
                    "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)"
                    "Landroid/graphics/Bitmap;");
    if (fields.createBitmapMethod == NULL) {
    if (fields.createBitmapRotationMethod == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Bitmap.createBitmap method");
        return;
    }
#else
    fields.createBitmapMethod =
            env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
                    "(IILandroid/graphics/Bitmap$Config;)"
                    "Landroid/graphics/Bitmap;");
    if (fields.createBitmapMethod == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Bitmap.createBitmap(int, int, Config)  method");
        return;
    }
    fields.nativeBitmap = env->GetFieldID(fields.bitmapClazz, "mNativeBitmap", "I");
    if (fields.nativeBitmap == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Bitmap.mNativeBitmap field");
    }

    fields.configClazz = env->FindClass("android/graphics/Bitmap$Config");
    if (fields.configClazz == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                               "Can't find Bitmap$Config class");
        return;
    }
    fields.createConfigMethod =
            env->GetStaticMethodID(fields.configClazz, "nativeToConfig",
                    "(I)Landroid/graphics/Bitmap$Config;");
    if (fields.createConfigMethod == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Bitmap$Config.nativeToConfig(int)  method");
        return;
    }
#endif
}

static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)