Merge "Overlay java files Issue 3370836" into honeycomb
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
old mode 100755
new mode 100644
index f10f5e8..1244b8e
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
@@ -24,15 +24,16 @@
import java.util.Iterator;
import java.util.List;
import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
import android.media.videoeditor.VideoEditor.ExportProgressListener;
import android.media.videoeditor.VideoEditor.PreviewProgressListener;
import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
import android.util.Log;
import android.util.Pair;
import android.view.Surface;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
/**
*This class provide Native methods to be used by MediaArtist {@hide}
@@ -70,11 +71,17 @@
private boolean mExportDone = false;
private int mProgressToApp;
+
/**
* The resize paint
*/
private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
+ private String mRenderPreviewOverlayFile;
+ private int mRenderPreviewRenderingMode;
+
+ private boolean mIsFirstProgress;
+
public static final int TASK_LOADING_SETTINGS = 1;
public static final int TASK_ENCODING = 2;
@@ -1899,12 +1906,35 @@
}
@SuppressWarnings("unused")
- private void onPreviewProgressUpdate(int progress, boolean isFinished) {
+ private void onPreviewProgressUpdate(int progress, boolean isFinished,
+ boolean updateOverlay, String filename, int renderingMode) {
if (mPreviewProgressListener != null) {
- mPreviewProgressListener.onProgress(mVideoEditor, progress, isFinished);
+ if (mIsFirstProgress) {
+ mPreviewProgressListener.onStart(mVideoEditor);
+ mIsFirstProgress = false;
+ }
+
+ final VideoEditor.OverlayData overlayData;
+ if (updateOverlay) {
+ overlayData = new VideoEditor.OverlayData();
+ if (filename != null) {
+ overlayData.set(BitmapFactory.decodeFile(filename), renderingMode);
+ } else {
+ overlayData.setClear();
+ }
+ } else {
+ overlayData = null;
+ }
+
+ mPreviewProgressListener.onProgress(mVideoEditor, progress, overlayData);
+
if (progress != 0) {
mPreviewProgress = progress;
}
+
+ if (isFinished) {
+ mPreviewProgressListener.onStop(mVideoEditor);
+ }
}
}
@@ -2894,6 +2924,7 @@
maxHeight = populateMediaItemProperties(lMediaItem,
previewIndex,
maxHeight);
+ /* Get the clip properties of the media item. */
if (lMediaItem instanceof MediaImageItem)
{
int tmpCnt = 0;
@@ -3014,11 +3045,11 @@
* @param callbackAfterFrameCount INdicated after how many frames
* the callback is needed
* @param listener The PreviewProgressListener
- *
*/
public void doPreview(Surface surface, long fromMs, long toMs, boolean loop,
int callbackAfterFrameCount, PreviewProgressListener listener) {
mPreviewProgress = fromMs;
+ mIsFirstProgress = true;
mPreviewProgressListener = listener;
if (!mInvalidatePreviewArray) {
@@ -3042,9 +3073,6 @@
Log.e("MediaArtistNativeHelper", "Runtime exception in nativeStartPreview");
throw ex;
}
-
- } else {
- return;
}
}
@@ -3064,22 +3092,37 @@
* @param time The time in ms at which the frame has to be rendered
* @param surfaceWidth The surface width
* @param surfaceHeight The surface height
+ * @param overlayData The overlay data
*
* @return The actual time from the story board at which the frame was extracted
* and rendered
*/
public long renderPreviewFrame(Surface surface, long time, int surfaceWidth,
- int surfaceHeight) {
+ int surfaceHeight, VideoEditor.OverlayData overlayData) {
long timeMs = 0;
if (!mInvalidatePreviewArray) {
try {
- for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length; clipCnt++) {
+ for (int clipCnt = 0;
+ clipCnt < mPreviewEditSettings.clipSettingsArray.length;
+ clipCnt++) {
+
if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
- mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath = mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
+ mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
+ mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
}
}
+
+ // Reset the render preview frame params that shall be set by native.
+ mRenderPreviewOverlayFile = null;
+ mRenderPreviewRenderingMode = MediaRendering.RESIZING;
nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
timeMs = (long)nativeRenderPreviewFrame(surface, time, surfaceWidth, surfaceHeight);
+
+ if (mRenderPreviewOverlayFile != null) {
+ overlayData.set(BitmapFactory.decodeFile(mRenderPreviewOverlayFile), mRenderPreviewRenderingMode);
+ } else {
+ overlayData.setClear();
+ }
} catch (IllegalArgumentException ex) {
Log.e("MediaArtistNativeHelper",
"Illegal Argument exception in nativeRenderPreviewFrame");
@@ -3094,11 +3137,16 @@
}
return timeMs;
} else {
-
throw new RuntimeException("Call generate preview first");
}
}
+ private void previewFrameEditInfo(String filename, int renderingMode) {
+ mRenderPreviewOverlayFile = filename;
+ mRenderPreviewRenderingMode = renderingMode;
+ }
+
+
/**
* This function is responsible for rendering a single frame
* from a single media item on the surface
@@ -3551,7 +3599,6 @@
int outBitrate = 0;
mExportFilename = filePath;
previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
-
mExportProgressListener = listener;
mProgressToApp = 0;
@@ -3678,7 +3725,6 @@
int outBitrate = 0;
mExportFilename = filePath;
previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
-
mExportProgressListener = listener;
mProgressToApp = 0;
@@ -4003,6 +4049,7 @@
public void clearPreviewSurface(Surface surface) {
nativeClearSurface(surface);
}
+
/** Native Methods */
native Properties getMediaProperties(String file) throws IllegalArgumentException,
IllegalStateException, RuntimeException, Exception;
diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java
index feec284..4d1bafb 100755
--- a/media/java/android/media/videoeditor/Transition.java
+++ b/media/java/android/media/videoeditor/Transition.java
@@ -332,8 +332,6 @@
List<EffectSettings> effectSettings_clip2;
String output = null;
- String effectClip1 = null;
- String effectClip2 = null;
if (mNativeHelper == null) {
if (m1 != null)
diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java
index f1ad921..9006613 100755
--- a/media/java/android/media/videoeditor/VideoEditor.java
+++ b/media/java/android/media/videoeditor/VideoEditor.java
@@ -20,7 +20,10 @@
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CancellationException;
-
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.Canvas;
+import android.graphics.Rect;
import android.view.SurfaceHolder;
/**
@@ -78,9 +81,26 @@
* @param videoEditor The VideoEditor instance
* @param timeMs The current preview position (expressed in milliseconds
* since the beginning of the storyboard timeline).
- * @param end true if the end of the timeline was reached
+ * @param overlayData The overlay data (null if the overlay data
+ * is unchanged)
*/
- public void onProgress(VideoEditor videoEditor, long timeMs, boolean end);
+ public void onProgress(VideoEditor videoEditor, long timeMs,
+ OverlayData overlayData);
+ /**
+ * This method notifies the listener when the preview is started
+ * previewing a project.
+ *
+ * @param videoEditor The VideoEditor instance
+ */
+ public void onStart(VideoEditor videoEditor);
+
+ /**
+ * This method notifies the listener when the preview is stopped
+ * previewing a project.
+ *
+ * @param videoEditor The VideoEditor instance
+ */
+ public void onStop(VideoEditor videoEditor);
}
/**
@@ -126,6 +146,158 @@
}
/**
+ * The overlay data
+ */
+ public static final class OverlayData {
+ // Instance variables
+ private Bitmap mOverlayBitmap;
+ private int mRenderingMode;
+ private boolean mClear;
+
+ /**
+ * Default constructor
+ */
+ public OverlayData() {
+ mOverlayBitmap = null;
+ mRenderingMode = MediaArtistNativeHelper.MediaRendering.BLACK_BORDERS;
+ mClear = false;
+ }
+
+ /**
+ * Releases the bitmap
+ */
+ public void release() {
+ if (mOverlayBitmap != null) {
+ mOverlayBitmap.recycle();
+ mOverlayBitmap = null;
+ }
+ }
+
+ /**
+ * Check if the overlay needs to be rendered
+ *
+ * @return true if rendering is needed
+ */
+ public boolean needsRendering() {
+ return (mClear || mOverlayBitmap != null);
+ }
+
+ /**
+ * Store the overlay data
+ *
+ * @param overlayBitmap The overlay bitmap
+ * @param renderingMode The rendering mode
+ */
+ void set(Bitmap overlayBitmap, int renderingMode) {
+ mOverlayBitmap = overlayBitmap;
+ mRenderingMode = renderingMode;
+ mClear = false;
+ }
+
+ /**
+ * Clear the overlay
+ */
+ void setClear() {
+ mClear = true;
+ }
+
+ /**
+ * Render the overlay by either clearing it or by
+ * rendering the overlay bitmap with the specified
+ * rendering mode
+ *
+ * @param destBitmap The destination bitmap
+ */
+ public void renderOverlay(Bitmap destBitmap) {
+ if (mClear) {
+ destBitmap.eraseColor(Color.TRANSPARENT);
+ } else if (mOverlayBitmap != null) {
+ final Canvas overlayCanvas = new Canvas(destBitmap);
+ final Rect destRect;
+ final Rect srcRect;
+ switch (mRenderingMode) {
+ case MediaArtistNativeHelper.MediaRendering.RESIZING: {
+ destRect = new Rect(0, 0, overlayCanvas.getWidth(),
+ overlayCanvas.getHeight());
+ srcRect = new Rect(0, 0, mOverlayBitmap.getWidth(),
+ mOverlayBitmap.getHeight());
+ break;
+ }
+
+ case MediaArtistNativeHelper.MediaRendering.BLACK_BORDERS: {
+ int left, right, top, bottom;
+ float aROverlayImage, aRCanvas;
+ aROverlayImage = (float)(mOverlayBitmap.getWidth()) /
+ (float)(mOverlayBitmap.getHeight());
+
+ aRCanvas = (float)(overlayCanvas.getWidth()) /
+ (float)(overlayCanvas.getHeight());
+
+ if (aROverlayImage > aRCanvas) {
+ int newHeight = ((overlayCanvas.getWidth() * mOverlayBitmap.getHeight())
+ / mOverlayBitmap.getWidth());
+ left = 0;
+ top = (overlayCanvas.getHeight() - newHeight) / 2;
+ right = overlayCanvas.getWidth();
+ bottom = top + newHeight;
+ } else {
+ int newWidth = ((overlayCanvas.getHeight() * mOverlayBitmap.getWidth())
+ / mOverlayBitmap.getHeight());
+ left = (overlayCanvas.getWidth() - newWidth) / 2;
+ top = 0;
+ right = left + newWidth;
+ bottom = overlayCanvas.getHeight();
+ }
+
+ destRect = new Rect(left, top, right, bottom);
+ srcRect = new Rect(0, 0, mOverlayBitmap.getWidth(), mOverlayBitmap.getHeight());
+ break;
+ }
+
+ case MediaArtistNativeHelper.MediaRendering.CROPPING: {
+ // Calculate the source rect
+ int left, right, top, bottom;
+ float aROverlayImage, aRCanvas;
+ aROverlayImage = (float)(mOverlayBitmap.getWidth()) /
+ (float)(mOverlayBitmap.getHeight());
+ aRCanvas = (float)(overlayCanvas.getWidth()) /
+ (float)(overlayCanvas.getHeight());
+ if (aROverlayImage < aRCanvas) {
+ int newHeight = ((mOverlayBitmap.getWidth() * overlayCanvas.getHeight())
+ / overlayCanvas.getWidth());
+
+ left = 0;
+ top = (mOverlayBitmap.getHeight() - newHeight) / 2;
+ right = mOverlayBitmap.getWidth();
+ bottom = top + newHeight;
+ } else {
+ int newWidth = ((mOverlayBitmap.getHeight() * overlayCanvas.getWidth())
+ / overlayCanvas.getHeight());
+ left = (mOverlayBitmap.getWidth() - newWidth) / 2;
+ top = 0;
+ right = left + newWidth;
+ bottom = mOverlayBitmap.getHeight();
+ }
+
+ srcRect = new Rect(left, top, right, bottom);
+ destRect = new Rect(0, 0, overlayCanvas.getWidth(), overlayCanvas.getHeight());
+ break;
+ }
+
+ default: {
+ throw new IllegalStateException("Rendering mode: " + mRenderingMode);
+ }
+ }
+
+ destBitmap.eraseColor(Color.TRANSPARENT);
+ overlayCanvas.drawBitmap(mOverlayBitmap, srcRect, destRect, null);
+
+ mOverlayBitmap.recycle();
+ }
+ }
+ }
+
+ /**
* @return The path where the VideoEditor stores all files related to the
* project
*/
@@ -518,6 +690,7 @@
*
* @param surfaceHolder SurfaceHolder used by the application
* @param timeMs time corresponding to the frame to display
+ * @param overlayData The overlay data
*
* @return The accurate time stamp of the frame that is rendered.
*
@@ -526,7 +699,8 @@
* @throws IllegalArgumentException if time is negative or beyond the
* preview duration
*/
- public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs);
+ public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs,
+ OverlayData overlayData);
/**
* This method must be called after any changes made to the storyboard
@@ -535,7 +709,6 @@
*/
public void generatePreview(MediaProcessingProgressListener listener);
-
/**
* Start the preview of all the storyboard items applied on all MediaItems
* This method does not block (does not wait for the preview to complete).
@@ -580,5 +753,4 @@
* and needs to be cleared.
*/
public void clearSurface(SurfaceHolder surfaceHolder);
-
}
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
index 672ce19..d2dfe82bf 100755
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ b/media/java/android/media/videoeditor/VideoEditorImpl.java
@@ -899,7 +899,8 @@
/*
* {@inheritDoc}
*/
- public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs) {
+ public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs,
+ OverlayData overlayData) {
long result = 0;
int surfaceWidth = 0;
int surfaceHeight = 0;
@@ -939,7 +940,7 @@
if (!mMANativeHelper.mInvalidatePreviewArray) {
if (mMediaItems.size() > 0) {
result = mMANativeHelper.renderPreviewFrame(surface,
- timeMs,surfaceWidth,surfaceHeight);
+ timeMs,surfaceWidth,surfaceHeight, overlayData);
}
else {
result = 0;
@@ -1643,7 +1644,7 @@
mMANativeHelper.previewStoryBoard(mMediaItems, mTransitions,
mAudioTracks, null);
mMANativeHelper.doPreview(mSurface, fromMs, toMs, loop,
- callbackAfterFrameCount, listener);
+ callbackAfterFrameCount, listener);
mPreviewInProgress = true;
} catch (IllegalArgumentException ex) {
mPreviewSemaphore.release();
@@ -1683,7 +1684,7 @@
}
}
- /**
+ /*
* Remove transitions associated with the specified media item
*
* @param mediaItem The media item