diff options
author | Chih-Chung Chang <chihchung@google.com> | 2011-08-15 20:15:14 +0800 |
---|---|---|
committer | Chih-Chung Chang <chihchung@google.com> | 2011-08-16 16:48:43 +0800 |
commit | 1f5de3833daddfa1d0ebc7dee1f9e007d4ed36a0 (patch) | |
tree | 77c4ad2ab7fce3ab6efff68bf0887631b54f2f01 /media | |
parent | 0a2f9664737f112e7a15d8b28e053469845a5a80 (diff) | |
download | frameworks_base-1f5de3833daddfa1d0ebc7dee1f9e007d4ed36a0.zip frameworks_base-1f5de3833daddfa1d0ebc7dee1f9e007d4ed36a0.tar.gz frameworks_base-1f5de3833daddfa1d0ebc7dee1f9e007d4ed36a0.tar.bz2 |
Display thumbnails one by one and cache them.
Change-Id: I10808f5bca475aea924817bf532dc5916438563a
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/videoeditor/MediaArtistNativeHelper.java | 93 | ||||
-rwxr-xr-x | media/java/android/media/videoeditor/MediaImageItem.java | 26 | ||||
-rwxr-xr-x | media/java/android/media/videoeditor/MediaItem.java | 38 | ||||
-rwxr-xr-x | media/java/android/media/videoeditor/MediaVideoItem.java | 18 | ||||
-rwxr-xr-x | media/jni/mediaeditor/VideoBrowserInternal.h | 3 | ||||
-rwxr-xr-x | media/jni/mediaeditor/VideoBrowserMain.c | 19 | ||||
-rwxr-xr-x | media/jni/mediaeditor/VideoEditorMain.cpp | 86 |
7 files changed, 139 insertions, 144 deletions
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java index 5bfdcdb..8caa04c 100644 --- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java +++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java @@ -3781,72 +3781,62 @@ class MediaArtistNativeHelper { * @param startMs The starting time in ms * @param endMs The end time in ms * @param thumbnailCount The number of frames to be extracted + * @param indices The indices of thumbnails wanted + * @param callback The callback used to pass back the bitmaps * from startMs to endMs * * @return The frames as bitmaps in bitmap array **/ - Bitmap[] getPixelsList(String filename, int width, int height, long startMs, long endMs, - int thumbnailCount) { - int[] rgb888 = null; - int thumbnailSize = 0; - Bitmap tempBitmap = null; - + void getPixelsList(String filename, final int width, final int height, + long startMs, long endMs, int thumbnailCount, int[] indices, + final MediaItem.GetThumbnailListCallback callback) { /* Make width and height as even */ final int newWidth = (width + 1) & 0xFFFFFFFE; final int newHeight = (height + 1) & 0xFFFFFFFE; - thumbnailSize = newWidth * newHeight * 4; + final int thumbnailSize = newWidth * newHeight; /* Create a temp bitmap for resized thumbnails */ - if ((newWidth != width) || (newHeight != height)) { - tempBitmap = Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888); - } - int i = 0; - int deltaTime = (int)(endMs - startMs) / thumbnailCount; - Bitmap[] bitmaps = null; - - try { - // This may result in out of Memory Error - rgb888 = new int[thumbnailSize * thumbnailCount]; - bitmaps = new Bitmap[thumbnailCount]; - } catch (Throwable e) { - // Allocating to new size with Fixed count - try { - rgb888 = new int[thumbnailSize * MAX_THUMBNAIL_PERMITTED]; - bitmaps = new Bitmap[MAX_THUMBNAIL_PERMITTED]; - thumbnailCount = MAX_THUMBNAIL_PERMITTED; - } catch (Throwable ex) { - throw new RuntimeException("Memory allocation fails, thumbnail count too large: " - + thumbnailCount); - } - } - IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize); - nativeGetPixelsList(filename, rgb888, newWidth, newHeight, deltaTime, thumbnailCount, - startMs, endMs); + final Bitmap tempBitmap = + (newWidth != width || newHeight != height) + ? Bitmap.createBitmap(newWidth, newHeight, Bitmap.Config.ARGB_8888) + : null; + + final int[] rgb888 = new int[thumbnailSize]; + final IntBuffer tmpBuffer = IntBuffer.allocate(thumbnailSize); + nativeGetPixelsList(filename, rgb888, newWidth, newHeight, + thumbnailCount, startMs, endMs, indices, + new NativeGetPixelsListCallback() { + public void onThumbnail(int index) { + Bitmap bitmap = Bitmap.createBitmap( + width, height, Bitmap.Config.ARGB_8888); + tmpBuffer.put(rgb888, 0, thumbnailSize); + tmpBuffer.rewind(); + + if ((newWidth == width) && (newHeight == height)) { + bitmap.copyPixelsFromBuffer(tmpBuffer); + } else { + /* Copy the out rgb buffer to temp bitmap */ + tempBitmap.copyPixelsFromBuffer(tmpBuffer); - for (; i < thumbnailCount; i++) { - bitmaps[i] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - tmpBuffer.put(rgb888, (i * thumbnailSize), thumbnailSize); - tmpBuffer.rewind(); + /* Create a canvas to resize */ + final Canvas canvas = new Canvas(bitmap); + canvas.drawBitmap(tempBitmap, + new Rect(0, 0, newWidth, newHeight), + new Rect(0, 0, width, height), sResizePaint); - if ((newWidth == width) && (newHeight == height)) { - bitmaps[i].copyPixelsFromBuffer(tmpBuffer); - } else { - /* Copy the out rgb buffer to temp bitmap */ - tempBitmap.copyPixelsFromBuffer(tmpBuffer); - - /* Create a canvas to resize */ - final Canvas canvas = new Canvas(bitmaps[i]); - canvas.drawBitmap(tempBitmap, new Rect(0, 0, newWidth, newHeight), - new Rect(0, 0, width, height), sResizePaint); - canvas.setBitmap(null); + canvas.setBitmap(null); + } + callback.onThumbnail(bitmap, index); } - } + }); if (tempBitmap != null) { tempBitmap.recycle(); } + } - return bitmaps; + interface NativeGetPixelsListCallback { + public void onThumbnail(int index); } /** @@ -3957,8 +3947,9 @@ class MediaArtistNativeHelper { private native int nativeGetPixels(String fileName, int[] pixelArray, int width, int height, long timeMS); - private native int nativeGetPixelsList(String fileName, int[] pixelArray, int width, int height, - int timeMS, int nosofTN, long startTimeMs, long endTimeMs); + private native int nativeGetPixelsList(String fileName, int[] pixelArray, + int width, int height, int nosofTN, long startTimeMs, long endTimeMs, + int[] indices, NativeGetPixelsListCallback callback); /** * Releases the JNI and cleans up the core native module.. Should be called diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java index f0cc1fe..4ca6fad 100755 --- a/media/java/android/media/videoeditor/MediaImageItem.java +++ b/media/java/android/media/videoeditor/MediaImageItem.java @@ -616,17 +616,18 @@ public class MediaImageItem extends MediaItem { * {@inheritDoc} */ @Override - public Bitmap[] getThumbnailList(int width, int height, long startMs, long endMs, - int thumbnailCount) throws IOException { + public void getThumbnailList(int width, int height, + long startMs, long endMs, + int thumbnailCount, + int[] indices, + GetThumbnailListCallback callback) + throws IOException { //KenBurns was not applied on this. if (getGeneratedImageClip() == null) { final Bitmap thumbnail = scaleImage(mFilename, width, height); - final Bitmap[] thumbnailArray = new Bitmap[thumbnailCount]; - for (int i = 0; i < thumbnailCount; i++) { - thumbnailArray[i] = thumbnail; + for (int i = 0; i < indices.length; i++) { + callback.onThumbnail(thumbnail, i); } - - return thumbnailArray; } else { if (startMs > endMs) { throw new IllegalArgumentException("Start time is greater than end time"); @@ -636,15 +637,8 @@ public class MediaImageItem extends MediaItem { throw new IllegalArgumentException("End time is greater than file duration"); } - if (startMs == endMs) { - Bitmap[] bitmap = new Bitmap[1]; - bitmap[0] = mMANativeHelper.getPixels(getGeneratedImageClip(), - width, height,startMs); - return bitmap; - } - - return mMANativeHelper.getPixelsList(getGeneratedImageClip(), width, - height,startMs,endMs,thumbnailCount); + mMANativeHelper.getPixelsList(getGeneratedImageClip(), width, + height, startMs, endMs, thumbnailCount, indices, callback); } } diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java index 8c4841f..4e9ea75 100755 --- a/media/java/android/media/videoeditor/MediaItem.java +++ b/media/java/android/media/videoeditor/MediaItem.java @@ -564,15 +564,41 @@ public abstract class MediaItem { * @param startMs The start of time range in milliseconds * @param endMs The end of the time range in milliseconds * @param thumbnailCount The thumbnail count - * - * @return The array of Bitmaps + * @param indices The indices of the thumbnails wanted + * @param callback The callback used to pass back the bitmaps * * @throws IOException if a file error occurs */ - public abstract Bitmap[] getThumbnailList(int width, int height, - long startMs, long endMs, - int thumbnailCount) - throws IOException; + public abstract void getThumbnailList(int width, int height, + long startMs, long endMs, + int thumbnailCount, + int[] indices, + GetThumbnailListCallback callback) + throws IOException; + + public interface GetThumbnailListCallback { + public void onThumbnail(Bitmap bitmap, int index); + } + + // This is for compatibility, only used in tests. + public Bitmap[] getThumbnailList(int width, int height, + long startMs, long endMs, + int thumbnailCount) + throws IOException { + final Bitmap[] bitmaps = new Bitmap[thumbnailCount]; + int[] indices = new int[thumbnailCount]; + for (int i = 0; i < thumbnailCount; i++) { + indices[i] = i; + } + getThumbnailList(width, height, startMs, endMs, + thumbnailCount, indices, new GetThumbnailListCallback() { + public void onThumbnail(Bitmap bitmap, int index) { + bitmaps[index] = bitmap; + } + }); + + return bitmaps; + } /* * {@inheritDoc} diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java index 6248651..0ac354b 100755 --- a/media/java/android/media/videoeditor/MediaVideoItem.java +++ b/media/java/android/media/videoeditor/MediaVideoItem.java @@ -293,8 +293,12 @@ public class MediaVideoItem extends MediaItem { * {@inheritDoc} */ @Override - public Bitmap[] getThumbnailList(int width, int height, long startMs, - long endMs, int thumbnailCount) throws IOException { + public void getThumbnailList(int width, int height, + long startMs, long endMs, + int thumbnailCount, + int[] indices, + GetThumbnailListCallback callback) + throws IOException { if (startMs > endMs) { throw new IllegalArgumentException("Start time is greater than end time"); } @@ -307,14 +311,8 @@ public class MediaVideoItem extends MediaItem { throw new IllegalArgumentException("Invalid dimension"); } - if (startMs == endMs) { - final Bitmap[] bitmap = new Bitmap[1]; - bitmap[0] = mMANativeHelper.getPixels(super.getFilename(), width, height,startMs); - return bitmap; - } - - return mMANativeHelper.getPixelsList(super.getFilename(), width, - height,startMs,endMs,thumbnailCount); + mMANativeHelper.getPixelsList(super.getFilename(), width, + height, startMs, endMs, thumbnailCount, indices, callback); } /* diff --git a/media/jni/mediaeditor/VideoBrowserInternal.h b/media/jni/mediaeditor/VideoBrowserInternal.h index 3cfb6b9..f4eaab8 100755 --- a/media/jni/mediaeditor/VideoBrowserInternal.h +++ b/media/jni/mediaeditor/VideoBrowserInternal.h @@ -26,9 +26,6 @@ #define VIDEO_BROWSER_BGR565 - -#define VIDEO_BROWSER_PREDECODE_TIME 2000 /* In miliseconds */ - /*---------------------------- MACROS ----------------------------*/ #define CHECK_PTR(fct, p, err, errValue) \ { \ diff --git a/media/jni/mediaeditor/VideoBrowserMain.c b/media/jni/mediaeditor/VideoBrowserMain.c index 2de55e3..c6c6000 100755 --- a/media/jni/mediaeditor/VideoBrowserMain.c +++ b/media/jni/mediaeditor/VideoBrowserMain.c @@ -447,13 +447,9 @@ M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime, VideoBrowserContext* pC = (VideoBrowserContext*)pContext; M4OSA_ERR err = M4NO_ERROR; M4OSA_UInt32 targetTime = 0; - M4OSA_UInt32 jumpTime = 0; M4_MediaTime timeMS = 0; - M4OSA_Int32 rapTime = 0; - M4OSA_Bool isBackward = M4OSA_FALSE; M4OSA_Bool bJumpNeeded = M4OSA_FALSE; - /*--- Sanity checks ---*/ CHECK_PTR(videoBrowserPrepareFrame, pContext, err, M4ERR_PARAMETER); CHECK_PTR(videoBrowserPrepareFrame, pTime, err, M4ERR_PARAMETER); @@ -472,16 +468,11 @@ M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime, goto videoBrowserPrepareFrame_cleanUp; } - /*--- Check the duration ---*/ - /*--- If we jump backward, we need to jump ---*/ - if (targetTime < pC->m_currentCTS) - { - isBackward = M4OSA_TRUE; - bJumpNeeded = M4OSA_TRUE; - } - /*--- If we jumpt to a time greater than "currentTime" + "predecodeTime" - we need to jump ---*/ - else if (targetTime > (pC->m_currentCTS + VIDEO_BROWSER_PREDECODE_TIME)) + // If we jump backward or forward to a time greater than current position by + // 85ms (~ 2 frames), we want to jump. + if (pC->m_currentCTS == 0 || + targetTime < pC->m_currentCTS || + targetTime > (pC->m_currentCTS + 85)) { bJumpNeeded = M4OSA_TRUE; } diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp index 14972a2..7d0f56f 100755 --- a/media/jni/mediaeditor/VideoEditorMain.cpp +++ b/media/jni/mediaeditor/VideoEditorMain.cpp @@ -182,10 +182,11 @@ static int videoEditor_getPixelsList( jintArray pixelArray, M4OSA_UInt32 width, M4OSA_UInt32 height, - M4OSA_UInt32 deltatimeMS, M4OSA_UInt32 noOfThumbnails, - M4OSA_UInt32 startTime, - M4OSA_UInt32 endTime); + jlong startTime, + jlong endTime, + jintArray indexArray, + jobject callback); static void videoEditor_startPreview( @@ -288,7 +289,7 @@ static JNINativeMethod gManualEditMethods[] = { (void *)videoEditor_release }, {"nativeGetPixels", "(Ljava/lang/String;[IIIJ)I", (void*)videoEditor_getPixels }, - {"nativeGetPixelsList", "(Ljava/lang/String;[IIIIIJJ)I", + {"nativeGetPixelsList", "(Ljava/lang/String;[IIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I", (void*)videoEditor_getPixelsList }, {"getMediaProperties", "(Ljava/lang/String;)Landroid/media/videoeditor/MediaArtistNativeHelper$Properties;", @@ -2150,75 +2151,72 @@ static int videoEditor_getPixels( } static int videoEditor_getPixelsList( - JNIEnv* env, - jobject thiz, - jstring path, - jintArray pixelArray, - M4OSA_UInt32 width, - M4OSA_UInt32 height, - M4OSA_UInt32 deltatimeMS, + JNIEnv* env, + jobject thiz, + jstring path, + jintArray pixelArray, + M4OSA_UInt32 width, + M4OSA_UInt32 height, M4OSA_UInt32 noOfThumbnails, - M4OSA_UInt32 startTime, - M4OSA_UInt32 endTime) + jlong startTime, + jlong endTime, + jintArray indexArray, + jobject callback) { - M4OSA_ERR err; + M4OSA_ERR err = M4NO_ERROR; M4OSA_Context mContext = M4OSA_NULL; - jint* m_dst32; - M4OSA_UInt32 timeMS = startTime; - int arrayOffset = 0; - - - - // Add a text marker (the condition must always be true). - ADD_TEXT_MARKER_FUN(NULL != env) const char *pString = env->GetStringUTFChars(path, NULL); if (pString == M4OSA_NULL) { - if (env != NULL) { - jniThrowException(env, "java/lang/RuntimeException", "Input string null"); - } + jniThrowException(env, "java/lang/RuntimeException", "Input string null"); return M4ERR_ALLOC; } err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE); if (err != M4NO_ERROR || mContext == M4OSA_NULL) { - if (env != NULL) { - jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed"); - } + jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed"); if (pString != NULL) { env->ReleaseStringUTFChars(path, pString); } return err; } - m_dst32 = env->GetIntArrayElements(pixelArray, NULL); + jlong duration = (endTime - startTime); + M4OSA_UInt32 tolerance = duration / (2 * noOfThumbnails); + jint* m_dst32 = env->GetIntArrayElements(pixelArray, NULL); + jint* indices = env->GetIntArrayElements(indexArray, NULL); + jsize len = env->GetArrayLength(indexArray); - M4OSA_UInt32 tolerance = deltatimeMS / 2; - do { - err = ThumbnailGetPixels32(mContext, ((M4OSA_Int32 *)m_dst32 + arrayOffset), - width,height,&timeMS, tolerance); - if (err != M4NO_ERROR ) { - if (env != NULL) { - jniThrowException(env, "java/lang/RuntimeException",\ - "ThumbnailGetPixels32 failed"); - } - return err; + jclass cls = env->GetObjectClass(callback); + jmethodID mid = env->GetMethodID(cls, "onThumbnail", "(I)V"); + + for (int i = 0; i < len; i++) { + int k = indices[i]; + M4OSA_UInt32 timeMS = startTime; + timeMS += (2 * k + 1) * duration / (2 * noOfThumbnails); + err = ThumbnailGetPixels32(mContext, ((M4OSA_Int32 *)m_dst32), + width, height, &timeMS, tolerance); + if (err != M4NO_ERROR) { + break; } - timeMS += deltatimeMS; - arrayOffset += (width * height * 4); - noOfThumbnails--; - } while(noOfThumbnails > 0); + env->CallVoidMethod(callback, mid, (jint)k); + } env->ReleaseIntArrayElements(pixelArray, m_dst32, 0); + env->ReleaseIntArrayElements(indexArray, indices, 0); ThumbnailClose(mContext); if (pString != NULL) { env->ReleaseStringUTFChars(path, pString); } - return err; + if (err != M4NO_ERROR) { + jniThrowException(env, "java/lang/RuntimeException",\ + "ThumbnailGetPixels32 failed"); + } + return err; } static M4OSA_ERR |