Loading include/private/media/VideoFrame.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading media/jni/android_media_MediaMetadataRetriever.cpp +58 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct fields_t { jfieldID context; jclass bitmapClazz; jmethodID bitmapConstructor; jmethodID createBitmapMethod; }; static fields_t fields; Loading Loading @@ -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) { Loading @@ -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) Loading Loading @@ -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) Loading media/libmediaplayerservice/MetadataRetrieverClient.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading media/libstagefright/StagefrightMetadataRetriever.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); Loading Loading
include/private/media/VideoFrame.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
media/jni/android_media_MediaMetadataRetriever.cpp +58 −1 Original line number Diff line number Diff line Loading @@ -36,6 +36,7 @@ struct fields_t { jfieldID context; jclass bitmapClazz; jmethodID bitmapConstructor; jmethodID createBitmapMethod; }; static fields_t fields; Loading Loading @@ -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) { Loading @@ -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) Loading Loading @@ -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) Loading
media/libmediaplayerservice/MetadataRetrieverClient.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
media/libstagefright/StagefrightMetadataRetriever.cpp +6 −0 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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)); Loading