Merge "Overlay java files Issue 3370836" into honeycomb
This commit is contained in:
committed by
Android (Google) Code Review
commit
45e3d123bc
77
media/java/android/media/videoeditor/MediaArtistNativeHelper.java
Executable file → Normal file
77
media/java/android/media/videoeditor/MediaArtistNativeHelper.java
Executable file → Normal 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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user