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

Commit 53ebc72f authored by James Dong's avatar James Dong
Browse files

Support extracting thumbnail from rotated video tracks

Change-Id: Ife0a2536aaac5ff1efdf1035b9d2c892773ee16c
parent 17ae3597
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -120,6 +120,7 @@ public:
    uint32_t mDisplayHeight;
    uint32_t mSize;            // Number of bytes in mData
    uint8_t* mData;            // Actual binary data
    int32_t  mRotationAngle;   // rotation angle, clockwise
};

}; // namespace android
+58 −1
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ struct fields_t {
    jfieldID context;
    jclass bitmapClazz;
    jmethodID bitmapConstructor;
    jmethodID createBitmapMethod;
};

static fields_t fields;
@@ -174,6 +175,41 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo
        return NULL;
    }

    jobject matrix = NULL;
    if (videoFrame->mRotationAngle != 0) {
        LOGD("Create a rotation matrix: %d degrees", videoFrame->mRotationAngle);
        jclass matrixClazz = env->FindClass("android/graphics/Matrix");
        if (matrixClazz == NULL) {
            jniThrowException(env, "java/lang/RuntimeException",
                "Can't find android/graphics/Matrix");
            return NULL;
        }
        jmethodID matrixConstructor =
            env->GetMethodID(matrixClazz, "<init>", "()V");
        if (matrixConstructor == NULL) {
            jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Matrix constructor");
            return NULL;
        }
        matrix =
            env->NewObject(matrixClazz, matrixConstructor);
        if (matrix == NULL) {
            LOGE("Could not create a Matrix object");
            return NULL;
        }

        LOGV("Rotate the matrix: %d degrees", videoFrame->mRotationAngle);
        jmethodID setRotateMethod =
                env->GetMethodID(matrixClazz, "setRotate", "(F)V");
        if (setRotateMethod == NULL) {
            jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Matrix setRotate method");
            return NULL;
        }
        env->CallVoidMethod(matrix, setRotateMethod, 1.0 * videoFrame->mRotationAngle);
        env->DeleteLocalRef(matrixClazz);
    }

    // Create a SkBitmap to hold the pixels
    SkBitmap *bitmap = new SkBitmap();
    if (bitmap == NULL) {
@@ -191,7 +227,19 @@ static jobject android_media_MediaMetadataRetriever_captureFrame(JNIEnv *env, jo
    // Since internally SkBitmap uses reference count to manage the reference to
    // its pixels, it is important that the pixels (along with SkBitmap) be
    // available after creating the Bitmap is returned to Java app.
    return env->NewObject(fields.bitmapClazz, fields.bitmapConstructor, (int) bitmap, true, NULL, -1);
    jobject jSrcBitmap = env->NewObject(fields.bitmapClazz,
            fields.bitmapConstructor, (int) bitmap, true, NULL, -1);

    LOGV("Return a new bitmap constructed with the rotation matrix");
    return env->CallStaticObjectMethod(
                fields.bitmapClazz, fields.createBitmapMethod,
                jSrcBitmap,                     // source Bitmap
                0,                              // x
                0,                              // y
                videoFrame->mDisplayWidth,      // width
                videoFrame->mDisplayHeight,     // height
                matrix,                         // transform matrix
                false);                         // filter
}

static jbyteArray android_media_MediaMetadataRetriever_extractAlbumArt(JNIEnv *env, jobject thiz)
@@ -291,6 +339,15 @@ static void android_media_MediaMetadataRetriever_native_init(JNIEnv *env)
        jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
        return;
    }
    fields.createBitmapMethod =
            env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
                    "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)"
                    "Landroid/graphics/Bitmap;");
    if (fields.createBitmapMethod == NULL) {
        jniThrowException(env, "java/lang/RuntimeException",
                "Can't find Bitmap.createBitmap method");
        return;
    }
}

static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
+2 −0
Original line number Diff line number Diff line
@@ -253,6 +253,8 @@ sp<IMemory> MetadataRetrieverClient::captureFrame()
    frameCopy->mDisplayWidth = frame->mDisplayWidth;
    frameCopy->mDisplayHeight = frame->mDisplayHeight;
    frameCopy->mSize = frame->mSize;
    frameCopy->mRotationAngle = frame->mRotationAngle;
    LOGV("rotation: %d", frameCopy->mRotationAngle);
    frameCopy->mData = (uint8_t *)frameCopy + sizeof(VideoFrame);
    memcpy(frameCopy->mData, frame->mData, frame->mSize);
    delete frame;  // Fix memory leakage
+6 −0
Original line number Diff line number Diff line
@@ -191,6 +191,11 @@ static VideoFrame *extractVideoFrameWithCodecFlags(
    CHECK(meta->findInt32(kKeyWidth, &width));
    CHECK(meta->findInt32(kKeyHeight, &height));

    int32_t rotationAngle;
    if (!trackMeta->findInt32(kKeyRotation, &rotationAngle)) {
        rotationAngle = 0;  // By default, no rotation
    }

    VideoFrame *frame = new VideoFrame;
    frame->mWidth = width;
    frame->mHeight = height;
@@ -198,6 +203,7 @@ static VideoFrame *extractVideoFrameWithCodecFlags(
    frame->mDisplayHeight = height;
    frame->mSize = width * height * 2;
    frame->mData = new uint8_t[frame->mSize];
    frame->mRotationAngle = rotationAngle;

    int32_t srcFormat;
    CHECK(meta->findInt32(kKeyColorFormat, &srcFormat));