am 45e3d123: Merge "Overlay java files Issue 3370836" into honeycomb

* commit '45e3d123bce32a8b1f469d366ebb1d3f9ccb2bfc':
  Overlay java files Issue 3370836
This commit is contained in:
Dharmaray Kundargi
2011-01-26 12:48:32 -08:00
committed by Android Git Automerger
4 changed files with 245 additions and 27 deletions

View File

@@ -24,15 +24,16 @@ import java.util.ArrayList;
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 @@ class MediaArtistNativeHelper {
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 @@ class MediaArtistNativeHelper {
}
@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 @@ class MediaArtistNativeHelper {
maxHeight = populateMediaItemProperties(lMediaItem,
previewIndex,
maxHeight);
/* Get the clip properties of the media item. */
if (lMediaItem instanceof MediaImageItem)
{
int tmpCnt = 0;
@@ -3014,11 +3045,11 @@ class MediaArtistNativeHelper {
* @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 @@ class MediaArtistNativeHelper {
Log.e("MediaArtistNativeHelper", "Runtime exception in nativeStartPreview");
throw ex;
}
} else {
return;
}
}
@@ -3064,22 +3092,37 @@ class MediaArtistNativeHelper {
* @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 @@ class MediaArtistNativeHelper {
}
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 @@ class MediaArtistNativeHelper {
int outBitrate = 0;
mExportFilename = filePath;
previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
mExportProgressListener = listener;
mProgressToApp = 0;
@@ -3678,7 +3725,6 @@ class MediaArtistNativeHelper {
int outBitrate = 0;
mExportFilename = filePath;
previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
mExportProgressListener = listener;
mProgressToApp = 0;
@@ -4003,6 +4049,7 @@ class MediaArtistNativeHelper {
public void clearPreviewSurface(Surface surface) {
nativeClearSurface(surface);
}
/** Native Methods */
native Properties getMediaProperties(String file) throws IllegalArgumentException,
IllegalStateException, RuntimeException, Exception;

View File

@@ -332,8 +332,6 @@ public abstract class Transition {
List<EffectSettings> effectSettings_clip2;
String output = null;
String effectClip1 = null;
String effectClip2 = null;
if (mNativeHelper == null) {
if (m1 != null)

View File

@@ -20,7 +20,10 @@ package android.media.videoeditor;
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 @@ public interface VideoEditor {
* @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);
}
/**
@@ -125,6 +145,158 @@ public interface VideoEditor {
public void onProgress(Object item, int action, int progress);
}
/**
* 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 @@ public interface VideoEditor {
*
* @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 @@ public interface VideoEditor {
* @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 interface VideoEditor {
*/
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 @@ public interface VideoEditor {
* and needs to be cleared.
*/
public void clearSurface(SurfaceHolder surfaceHolder);
}

View File

@@ -899,7 +899,8 @@ public class VideoEditorImpl implements VideoEditor {
/*
* {@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 @@ public class VideoEditorImpl implements VideoEditor {
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 @@ public class VideoEditorImpl implements VideoEditor {
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 @@ public class VideoEditorImpl implements VideoEditor {
}
}
/**
/*
* Remove transitions associated with the specified media item
*
* @param mediaItem The media item